summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--LICENSE2
-rw-r--r--SConscript421
-rw-r--r--SConstruct438
-rw-r--r--arch/SConscript146
-rw-r--r--arch/alpha/SConscript91
-rw-r--r--arch/alpha/arguments.cc66
-rw-r--r--arch/alpha/arguments.hh143
-rw-r--r--arch/alpha/ev5.cc593
-rw-r--r--arch/alpha/freebsd/system.cc167
-rw-r--r--arch/alpha/isa/branch.isa259
-rw-r--r--arch/alpha/isa/decoder.isa819
-rw-r--r--arch/alpha/isa/fp.isa301
-rw-r--r--arch/alpha/isa/int.isa128
-rw-r--r--arch/alpha/isa/main.isa448
-rw-r--r--arch/alpha/isa/mem.isa702
-rw-r--r--arch/alpha/isa/opcdec.isa72
-rw-r--r--arch/alpha/isa/pal.isa273
-rw-r--r--arch/alpha/isa/unimp.isa165
-rw-r--r--arch/alpha/isa/unknown.isa52
-rw-r--r--arch/alpha/isa/util.isa112
-rw-r--r--arch/alpha/isa_traits.hh384
-rw-r--r--arch/alpha/linux/process.cc589
-rw-r--r--arch/alpha/linux/process.hh58
-rw-r--r--arch/alpha/linux/system.cc289
-rw-r--r--arch/alpha/linux/system.hh146
-rw-r--r--arch/alpha/process.cc61
-rw-r--r--arch/alpha/process.hh48
-rw-r--r--arch/alpha/stacktrace.cc348
-rw-r--r--arch/alpha/system.cc299
-rw-r--r--arch/alpha/system.hh109
-rw-r--r--arch/alpha/tlb.cc643
-rw-r--r--arch/alpha/tlb.hh121
-rw-r--r--arch/alpha/tru64/process.cc542
-rw-r--r--arch/alpha/tru64/process.hh58
-rw-r--r--arch/alpha/tru64/system.cc159
-rw-r--r--arch/alpha/vtophys.cc268
-rw-r--r--arch/alpha/vtophys.hh50
-rwxr-xr-xarch/isa_parser.py1772
-rw-r--r--arch/isa_specific.hh62
-rw-r--r--arch/mips/SConscript83
-rw-r--r--arch/mips/faults.cc80
-rw-r--r--arch/mips/faults.hh160
-rw-r--r--arch/mips/isa/base.isa96
-rw-r--r--arch/mips/isa/bitfields.isa67
-rw-r--r--arch/mips/isa/decoder.isa930
-rw-r--r--arch/mips/isa/formats.isa35
-rw-r--r--arch/mips/isa/formats/branch.isa322
-rw-r--r--arch/mips/isa/formats/fp.isa49
-rw-r--r--arch/mips/isa/formats/int.isa130
-rw-r--r--arch/mips/isa/formats/mem.isa469
-rw-r--r--arch/mips/isa/formats/noop.isa90
-rw-r--r--arch/mips/isa/formats/unimp.isa165
-rw-r--r--arch/mips/isa/formats/unknown.isa52
-rw-r--r--arch/mips/isa/formats/util.isa148
-rw-r--r--arch/mips/isa/includes.isa39
-rw-r--r--arch/mips/isa/main.isa52
-rw-r--r--arch/mips/isa/operands.isa33
-rw-r--r--arch/mips/isa_traits.cc403
-rw-r--r--arch/mips/isa_traits.hh546
-rw-r--r--arch/mips/linux_process.cc588
-rw-r--r--arch/mips/linux_process.hh58
-rw-r--r--arch/mips/process.cc56
-rw-r--r--arch/mips/process.hh45
-rw-r--r--arch/sparc/SConscript82
-rw-r--r--arch/sparc/faults.cc248
-rw-r--r--arch/sparc/faults.hh587
-rw-r--r--arch/sparc/isa/base.isa129
-rw-r--r--arch/sparc/isa/bitfields.isa50
-rw-r--r--arch/sparc/isa/decoder.isa662
-rw-r--r--arch/sparc/isa/formats.isa19
-rw-r--r--arch/sparc/isa/formats/basic.isa68
-rw-r--r--arch/sparc/isa/formats/branch.isa62
-rw-r--r--arch/sparc/isa/formats/integerop.isa112
-rw-r--r--arch/sparc/isa/formats/mem.isa73
-rw-r--r--arch/sparc/isa/formats/noop.isa50
-rw-r--r--arch/sparc/isa/formats/trap.isa51
-rw-r--r--arch/sparc/isa/includes.isa43
-rw-r--r--arch/sparc/isa/main.isa52
-rw-r--r--arch/sparc/isa/operands.isa31
-rw-r--r--arch/sparc/isa_traits.hh527
-rw-r--r--arch/sparc/linux/process.cc374
-rw-r--r--arch/sparc/linux/process.hh58
-rw-r--r--arch/sparc/process.cc56
-rw-r--r--arch/sparc/process.hh45
-rw-r--r--base/cprintf.hh198
-rw-r--r--base/cprintf_formats.hh346
-rw-r--r--base/crc.cc115
-rw-r--r--base/hostinfo.cc86
-rw-r--r--base/inet.cc208
-rw-r--r--base/inet.hh407
-rw-r--r--base/intmath.hh230
-rw-r--r--base/loader/aout_object.cc114
-rw-r--r--base/loader/aout_object.hh58
-rw-r--r--base/loader/coff_sym.h489
-rw-r--r--base/loader/coff_symconst.h170
-rw-r--r--base/loader/ecoff_object.cc171
-rw-r--r--base/loader/ecoff_object.hh62
-rw-r--r--base/loader/elf_object.cc331
-rw-r--r--base/loader/elf_object.hh60
-rw-r--r--base/loader/object_file.cc117
-rw-r--r--base/loader/object_file.hh113
-rw-r--r--base/loader/symtab.hh173
-rw-r--r--base/remote_gdb.cc1232
-rw-r--r--base/statistics.cc357
-rw-r--r--base/statistics.hh2897
-rw-r--r--base/stats/text.cc735
-rw-r--r--base/traceflags.py325
-rw-r--r--build/SConstruct421
-rw-r--r--build_opts/ALPHA_FS (renamed from build/default_options/ALPHA_FS)0
-rw-r--r--build_opts/ALPHA_FS_TL (renamed from build/default_options/ALPHA_FS_TL)0
-rw-r--r--build_opts/ALPHA_SE (renamed from build/default_options/ALPHA_SE)0
-rw-r--r--build_opts/MIPS_SE (renamed from build/default_options/MIPS_SE)0
-rw-r--r--build_opts/SPARC_FS2
-rw-r--r--build_opts/SPARC_SE (renamed from build/default_options/SPARC_SE)0
-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/SConscript167
-rw-r--r--cpu/base.cc378
-rw-r--r--cpu/base.hh238
-rw-r--r--cpu/cpu_exec_context.cc315
-rw-r--r--cpu/cpu_exec_context.hh524
-rw-r--r--cpu/cpu_models.py80
-rw-r--r--cpu/exec_context.hh382
-rw-r--r--cpu/exetrace.cc231
-rw-r--r--cpu/exetrace.hh189
-rw-r--r--cpu/memtest/memtest.cc441
-rw-r--r--cpu/o3/alpha_cpu.hh430
-rw-r--r--cpu/o3/alpha_cpu_impl.hh776
-rw-r--r--cpu/o3/alpha_dyn_inst.hh268
-rw-r--r--cpu/o3/cpu.cc1183
-rw-r--r--cpu/o3/cpu.hh521
-rw-r--r--cpu/o3/regfile.hh266
-rw-r--r--cpu/pc_event.hh143
-rw-r--r--cpu/simple/cpu.cc955
-rw-r--r--cpu/simple/cpu.hh363
-rw-r--r--cpu/static_inst.hh475
-rw-r--r--dev/alpha_console.cc356
-rw-r--r--dev/alpha_console.hh127
-rw-r--r--dev/baddev.cc116
-rw-r--r--dev/baddev.hh95
-rw-r--r--dev/disk_image.cc471
-rw-r--r--dev/etherbus.cc125
-rw-r--r--dev/etherbus.hh79
-rw-r--r--dev/etherdump.cc136
-rw-r--r--dev/etherdump.hh59
-rw-r--r--dev/etherint.hh66
-rw-r--r--dev/etherlink.cc300
-rw-r--r--dev/etherlink.hh130
-rw-r--r--dev/etherpkt.cc53
-rw-r--r--dev/etherpkt.hh84
-rw-r--r--dev/ethertap.cc345
-rw-r--r--dev/ethertap.hh107
-rw-r--r--dev/ide_ctrl.cc813
-rw-r--r--dev/ide_ctrl.hh246
-rw-r--r--dev/ide_disk.cc1286
-rw-r--r--dev/ide_disk.hh373
-rw-r--r--dev/io_device.cc57
-rw-r--r--dev/io_device.hh62
-rw-r--r--dev/isa_fake.cc140
-rw-r--r--dev/isa_fake.hh87
-rw-r--r--dev/ns_gige.cc3105
-rw-r--r--dev/ns_gige.hh487
-rw-r--r--dev/pciconfigall.cc229
-rw-r--r--dev/pciconfigall.hh147
-rw-r--r--dev/pcidev.cc427
-rw-r--r--dev/pcidev.hh298
-rw-r--r--dev/pktfifo.cc99
-rw-r--r--dev/pktfifo.hh168
-rw-r--r--dev/platform.cc64
-rw-r--r--dev/platform.hh68
-rw-r--r--dev/simconsole.cc415
-rw-r--r--dev/simconsole.hh165
-rw-r--r--dev/simple_disk.cc109
-rw-r--r--dev/simple_disk.hh62
-rw-r--r--dev/sinic.cc1905
-rw-r--r--dev/sinic.hh401
-rw-r--r--dev/tsunami.cc132
-rw-r--r--dev/tsunami.hh134
-rw-r--r--dev/tsunami_cchip.cc580
-rw-r--r--dev/tsunami_cchip.hh176
-rw-r--r--dev/tsunami_io.cc719
-rw-r--r--dev/tsunami_io.hh371
-rw-r--r--dev/tsunami_pchip.cc388
-rw-r--r--dev/tsunami_pchip.hh133
-rw-r--r--dev/uart.cc78
-rw-r--r--dev/uart.hh85
-rw-r--r--dev/uart8250.cc349
-rw-r--r--dev/uart8250.hh107
-rw-r--r--encumbered/cpu/full/op_class.hh64
-rw-r--r--ext/dnet/LICENSE28
-rw-r--r--ext/dnet/dnet/addr.h67
-rw-r--r--ext/dnet/dnet/arp.h103
-rw-r--r--ext/dnet/dnet/blob.h56
-rw-r--r--ext/dnet/dnet/eth.h77
-rw-r--r--ext/dnet/dnet/fw.h54
-rw-r--r--ext/dnet/dnet/icmp.h265
-rw-r--r--ext/dnet/dnet/intf.h68
-rw-r--r--ext/dnet/dnet/ip.h487
-rw-r--r--ext/dnet/dnet/ip6.h183
-rw-r--r--ext/dnet/dnet/os.h117
-rw-r--r--ext/dnet/dnet/rand.h33
-rw-r--r--ext/dnet/dnet/route.h35
-rw-r--r--ext/dnet/dnet/tcp.h158
-rw-r--r--ext/dnet/dnet/udp.h32
-rw-r--r--ext/ply/CHANGES158
-rw-r--r--ext/ply/COPYING504
-rw-r--r--ext/ply/README249
-rw-r--r--ext/ply/TODO22
-rw-r--r--ext/ply/doc/ply.html1642
-rw-r--r--ext/ply/example/ansic/README2
-rw-r--r--ext/ply/example/ansic/clex.py161
-rw-r--r--ext/ply/example/ansic/cparse.py859
-rw-r--r--ext/ply/example/calc/calc.py108
-rw-r--r--ext/ply/example/hedit/hedit.py44
-rw-r--r--ext/ply/example/optcalc/README9
-rw-r--r--ext/ply/example/optcalc/calc.py110
-rw-r--r--ext/ply/lex.py681
-rw-r--r--ext/ply/test/README9
-rw-r--r--ext/ply/test/calclex.py46
-rw-r--r--ext/ply/test/lex_doc1.exp1
-rw-r--r--ext/ply/test/lex_doc1.py27
-rw-r--r--ext/ply/test/lex_dup1.exp2
-rw-r--r--ext/ply/test/lex_dup1.py27
-rw-r--r--ext/ply/test/lex_dup2.exp2
-rw-r--r--ext/ply/test/lex_dup2.py31
-rw-r--r--ext/ply/test/lex_dup3.exp2
-rw-r--r--ext/ply/test/lex_dup3.py29
-rw-r--r--ext/ply/test/lex_empty.exp1
-rw-r--r--ext/ply/test/lex_empty.py18
-rw-r--r--ext/ply/test/lex_error1.exp1
-rw-r--r--ext/ply/test/lex_error1.py22
-rw-r--r--ext/ply/test/lex_error2.exp1
-rw-r--r--ext/ply/test/lex_error2.py24
-rw-r--r--ext/ply/test/lex_error3.exp2
-rw-r--r--ext/ply/test/lex_error3.py25
-rw-r--r--ext/ply/test/lex_error4.exp2
-rw-r--r--ext/ply/test/lex_error4.py25
-rw-r--r--ext/ply/test/lex_hedit.exp3
-rw-r--r--ext/ply/test/lex_hedit.py44
-rw-r--r--ext/ply/test/lex_ignore.exp2
-rw-r--r--ext/ply/test/lex_ignore.py29
-rw-r--r--ext/ply/test/lex_re1.exp2
-rw-r--r--ext/ply/test/lex_re1.py25
-rw-r--r--ext/ply/test/lex_rule1.exp2
-rw-r--r--ext/ply/test/lex_rule1.py25
-rw-r--r--ext/ply/test/lex_token1.exp1
-rw-r--r--ext/ply/test/lex_token1.py19
-rw-r--r--ext/ply/test/lex_token2.exp1
-rw-r--r--ext/ply/test/lex_token2.py21
-rw-r--r--ext/ply/test/lex_token3.exp2
-rw-r--r--ext/ply/test/lex_token3.py24
-rw-r--r--ext/ply/test/lex_token4.exp2
-rw-r--r--ext/ply/test/lex_token4.py26
-rw-r--r--ext/ply/test/lex_token5.exp1
-rw-r--r--ext/ply/test/lex_token5.py31
-rwxr-xr-xext/ply/test/testlex.py57
-rw-r--r--ext/ply/test/testyacc.py58
-rw-r--r--ext/ply/test/yacc_badargs.exp3
-rw-r--r--ext/ply/test/yacc_badargs.py67
-rw-r--r--ext/ply/test/yacc_badprec.exp1
-rw-r--r--ext/ply/test/yacc_badprec.py63
-rw-r--r--ext/ply/test/yacc_badprec2.exp3
-rw-r--r--ext/ply/test/yacc_badprec2.py67
-rw-r--r--ext/ply/test/yacc_badrule.exp5
-rw-r--r--ext/ply/test/yacc_badrule.py67
-rw-r--r--ext/ply/test/yacc_badtok.exp1
-rw-r--r--ext/ply/test/yacc_badtok.py68
-rw-r--r--ext/ply/test/yacc_dup.exp4
-rw-r--r--ext/ply/test/yacc_dup.py67
-rw-r--r--ext/ply/test/yacc_error1.exp1
-rw-r--r--ext/ply/test/yacc_error1.py67
-rw-r--r--ext/ply/test/yacc_error2.exp1
-rw-r--r--ext/ply/test/yacc_error2.py67
-rw-r--r--ext/ply/test/yacc_error3.exp1
-rw-r--r--ext/ply/test/yacc_error3.py66
-rw-r--r--ext/ply/test/yacc_inf.exp5
-rw-r--r--ext/ply/test/yacc_inf.py55
-rw-r--r--ext/ply/test/yacc_missing1.exp2
-rw-r--r--ext/ply/test/yacc_missing1.py67
-rw-r--r--ext/ply/test/yacc_nodoc.exp2
-rw-r--r--ext/ply/test/yacc_nodoc.py66
-rw-r--r--ext/ply/test/yacc_noerror.exp2
-rw-r--r--ext/ply/test/yacc_noerror.py64
-rw-r--r--ext/ply/test/yacc_nop.exp2
-rw-r--r--ext/ply/test/yacc_nop.py67
-rw-r--r--ext/ply/test/yacc_notfunc.exp4
-rw-r--r--ext/ply/test/yacc_notfunc.py65
-rw-r--r--ext/ply/test/yacc_notok.exp1
-rw-r--r--ext/ply/test/yacc_notok.py66
-rw-r--r--ext/ply/test/yacc_rr.exp2
-rw-r--r--ext/ply/test/yacc_rr.py71
-rw-r--r--ext/ply/test/yacc_simple.exp1
-rw-r--r--ext/ply/test/yacc_simple.py67
-rw-r--r--ext/ply/test/yacc_sr.exp2
-rw-r--r--ext/ply/test/yacc_sr.py62
-rw-r--r--ext/ply/test/yacc_term1.exp2
-rw-r--r--ext/ply/test/yacc_term1.py67
-rw-r--r--ext/ply/test/yacc_unused.exp4
-rw-r--r--ext/ply/test/yacc_unused.py76
-rw-r--r--ext/ply/test/yacc_uprec.exp2
-rw-r--r--ext/ply/test/yacc_uprec.py62
-rw-r--r--ext/ply/yacc.py1846
-rw-r--r--kern/linux/events.cc55
-rw-r--r--kern/linux/linux.hh341
-rw-r--r--kern/linux/printk.cc261
-rw-r--r--kern/linux/printk.hh36
-rw-r--r--kern/system_events.cc90
-rw-r--r--kern/tru64/dump_mbuf.hh38
-rw-r--r--kern/tru64/printf.cc266
-rw-r--r--kern/tru64/printf.hh38
-rw-r--r--kern/tru64/tru64.hh1324
-rw-r--r--kern/tru64/tru64_events.cc95
-rw-r--r--python/SConscript207
-rw-r--r--python/m5/objects/AlphaConsole.py9
-rw-r--r--python/m5/objects/BadDevice.py6
-rw-r--r--python/m5/objects/BaseCPU.py29
-rw-r--r--python/m5/objects/Bus.py7
-rw-r--r--python/m5/objects/Device.py35
-rw-r--r--python/m5/objects/Ethernet.py119
-rw-r--r--python/m5/objects/Ide.py15
-rw-r--r--python/m5/objects/Pci.py55
-rw-r--r--python/m5/objects/PhysicalMemory.py8
-rw-r--r--python/m5/objects/Process.py17
-rw-r--r--python/m5/objects/Root.py25
-rw-r--r--python/m5/objects/SimpleDisk.py5
-rw-r--r--python/m5/objects/System.py21
-rw-r--r--python/m5/objects/Tsunami.py27
-rw-r--r--python/m5/objects/Uart.py16
-rw-r--r--sim/byteswap.hh146
-rw-r--r--sim/eventq.cc259
-rw-r--r--sim/faults.cc46
-rw-r--r--sim/faults.hh67
-rw-r--r--sim/host.hh65
-rw-r--r--sim/main.cc429
-rw-r--r--sim/param.cc794
-rw-r--r--sim/process.cc446
-rw-r--r--sim/process.hh219
-rw-r--r--sim/pseudo_inst.cc291
-rw-r--r--sim/sim_object.cc231
-rw-r--r--sim/sim_object.hh108
-rw-r--r--sim/syscall_emul.cc441
-rw-r--r--sim/syscall_emul.hh832
-rw-r--r--sim/system.cc185
-rw-r--r--sim/system.hh194
-rw-r--r--sim/vptr.hh116
-rw-r--r--src/Doxyfile (renamed from Doxyfile)0
-rw-r--r--src/SConscript400
-rw-r--r--src/arch/SConscript150
-rw-r--r--src/arch/alpha/SConscript93
-rw-r--r--src/arch/alpha/aout_machdep.h (renamed from arch/alpha/aout_machdep.h)0
-rw-r--r--src/arch/alpha/arguments.cc68
-rw-r--r--src/arch/alpha/arguments.hh147
-rw-r--r--src/arch/alpha/ecoff_machdep.h (renamed from arch/alpha/ecoff_machdep.h)0
-rw-r--r--src/arch/alpha/ev5.cc584
-rw-r--r--src/arch/alpha/ev5.hh (renamed from arch/alpha/ev5.hh)0
-rw-r--r--src/arch/alpha/faults.cc (renamed from arch/alpha/faults.cc)0
-rw-r--r--src/arch/alpha/faults.hh (renamed from arch/alpha/faults.hh)0
-rw-r--r--src/arch/alpha/freebsd/system.cc156
-rw-r--r--src/arch/alpha/freebsd/system.hh (renamed from arch/alpha/freebsd/system.hh)0
-rw-r--r--src/arch/alpha/isa/branch.isa264
-rw-r--r--src/arch/alpha/isa/decoder.isa824
-rw-r--r--src/arch/alpha/isa/fp.isa310
-rw-r--r--src/arch/alpha/isa/int.isa133
-rw-r--r--src/arch/alpha/isa/main.isa461
-rw-r--r--src/arch/alpha/isa/mem.isa734
-rw-r--r--src/arch/alpha/isa/opcdec.isa77
-rw-r--r--src/arch/alpha/isa/pal.isa278
-rw-r--r--src/arch/alpha/isa/unimp.isa170
-rw-r--r--src/arch/alpha/isa/unknown.isa57
-rw-r--r--src/arch/alpha/isa/util.isa117
-rw-r--r--src/arch/alpha/isa_traits.hh112
-rw-r--r--src/arch/alpha/linux/aligned.hh (renamed from arch/alpha/linux/aligned.hh)0
-rw-r--r--src/arch/alpha/linux/hwrpb.hh (renamed from arch/alpha/linux/hwrpb.hh)0
-rw-r--r--src/arch/alpha/linux/linux.cc70
-rw-r--r--src/arch/alpha/linux/linux.hh128
-rw-r--r--src/arch/alpha/linux/process.cc591
-rw-r--r--src/arch/alpha/linux/process.hh60
-rw-r--r--src/arch/alpha/linux/system.cc265
-rw-r--r--src/arch/alpha/linux/system.hh145
-rw-r--r--src/arch/alpha/linux/thread_info.hh (renamed from arch/alpha/linux/thread_info.hh)0
-rw-r--r--src/arch/alpha/linux/threadinfo.hh (renamed from arch/alpha/linux/threadinfo.hh)0
-rw-r--r--src/arch/alpha/osfpal.cc (renamed from arch/alpha/osfpal.cc)0
-rw-r--r--src/arch/alpha/osfpal.hh (renamed from arch/alpha/osfpal.hh)0
-rw-r--r--src/arch/alpha/process.cc167
-rw-r--r--src/arch/alpha/process.hh64
-rw-r--r--src/arch/alpha/regfile.hh278
-rw-r--r--src/arch/alpha/stacktrace.cc344
-rw-r--r--src/arch/alpha/stacktrace.hh (renamed from arch/alpha/stacktrace.hh)0
-rw-r--r--src/arch/alpha/system.cc280
-rw-r--r--src/arch/alpha/system.hh108
-rw-r--r--src/arch/alpha/tlb.cc628
-rw-r--r--src/arch/alpha/tlb.hh121
-rw-r--r--src/arch/alpha/tru64/process.cc586
-rw-r--r--src/arch/alpha/tru64/process.hh61
-rw-r--r--src/arch/alpha/tru64/system.cc151
-rw-r--r--src/arch/alpha/tru64/system.hh (renamed from arch/alpha/tru64/system.hh)0
-rw-r--r--src/arch/alpha/tru64/tru64.cc70
-rw-r--r--src/arch/alpha/tru64/tru64.hh127
-rw-r--r--src/arch/alpha/types.hh64
-rw-r--r--src/arch/alpha/utility.hh156
-rw-r--r--src/arch/alpha/vtophys.cc162
-rw-r--r--src/arch/alpha/vtophys.hh52
-rwxr-xr-xsrc/arch/isa_parser.py1810
-rw-r--r--src/arch/isa_specific.hh62
-rw-r--r--src/arch/mips/SConscript83
-rw-r--r--src/arch/mips/faults.cc131
-rw-r--r--src/arch/mips/faults.hh269
-rw-r--r--src/arch/mips/isa/base.isa88
-rw-r--r--src/arch/mips/isa/bitfields.isa71
-rw-r--r--src/arch/mips/isa/decoder.isa1688
-rw-r--r--src/arch/mips/isa/formats/basic.isa (renamed from arch/mips/isa/formats/basic.isa)0
-rw-r--r--src/arch/mips/isa/formats/branch.isa324
-rw-r--r--src/arch/mips/isa/formats/formats.isa35
-rw-r--r--src/arch/mips/isa/formats/fp.isa109
-rw-r--r--src/arch/mips/isa/formats/int.isa131
-rw-r--r--src/arch/mips/isa/formats/mem.isa478
-rw-r--r--src/arch/mips/isa/formats/noop.isa94
-rw-r--r--src/arch/mips/isa/formats/tlbop.isa (renamed from arch/mips/isa/formats/tlbop.isa)0
-rw-r--r--src/arch/mips/isa/formats/trap.isa (renamed from arch/mips/isa/formats/trap.isa)0
-rw-r--r--src/arch/mips/isa/formats/unimp.isa171
-rw-r--r--src/arch/mips/isa/formats/unknown.isa79
-rw-r--r--src/arch/mips/isa/formats/util.isa129
-rw-r--r--src/arch/mips/isa/includes.isa48
-rw-r--r--src/arch/mips/isa/main.isa59
-rw-r--r--src/arch/mips/isa/operands.isa61
-rw-r--r--src/arch/mips/isa_traits.cc229
-rw-r--r--src/arch/mips/isa_traits.hh199
-rw-r--r--src/arch/mips/linux/linux.cc72
-rw-r--r--src/arch/mips/linux/linux.hh126
-rw-r--r--src/arch/mips/linux/process.cc429
-rw-r--r--src/arch/mips/linux/process.hh59
-rw-r--r--src/arch/mips/process.cc161
-rw-r--r--src/arch/mips/process.hh64
-rw-r--r--src/arch/mips/regfile/float_regfile.hh159
-rw-r--r--src/arch/mips/regfile/int_regfile.hh73
-rw-r--r--src/arch/mips/regfile/misc_regfile.hh96
-rw-r--r--src/arch/mips/regfile/regfile.hh199
-rw-r--r--src/arch/mips/stacktrace.hh (renamed from arch/mips/stacktrace.hh)0
-rw-r--r--src/arch/mips/types.hh92
-rw-r--r--src/arch/mips/utility.hh44
-rw-r--r--src/arch/sparc/SConscript80
-rw-r--r--src/arch/sparc/faults.cc255
-rw-r--r--src/arch/sparc/faults.hh591
-rw-r--r--src/arch/sparc/isa/base.isa252
-rw-r--r--src/arch/sparc/isa/bitfields.isa78
-rw-r--r--src/arch/sparc/isa/decoder.isa669
-rw-r--r--src/arch/sparc/isa/formats.isa28
-rw-r--r--src/arch/sparc/isa/formats/basic.isa97
-rw-r--r--src/arch/sparc/isa/formats/branch.isa337
-rw-r--r--src/arch/sparc/isa/formats/integerop.isa395
-rw-r--r--src/arch/sparc/isa/formats/mem.isa171
-rw-r--r--src/arch/sparc/isa/formats/nop.isa98
-rw-r--r--src/arch/sparc/isa/formats/priv.isa125
-rw-r--r--src/arch/sparc/isa/formats/trap.isa93
-rw-r--r--src/arch/sparc/isa/formats/unknown.isa75
-rw-r--r--src/arch/sparc/isa/includes.isa76
-rw-r--r--src/arch/sparc/isa/main.isa59
-rw-r--r--src/arch/sparc/isa/operands.isa88
-rw-r--r--src/arch/sparc/isa_traits.hh190
-rw-r--r--src/arch/sparc/linux/linux.cc68
-rw-r--r--src/arch/sparc/linux/linux.hh61
-rw-r--r--src/arch/sparc/linux/process.cc407
-rw-r--r--src/arch/sparc/linux/process.hh65
-rw-r--r--src/arch/sparc/process.cc379
-rw-r--r--src/arch/sparc/process.hh79
-rw-r--r--src/arch/sparc/regfile.hh861
-rw-r--r--src/arch/sparc/solaris/process.cc347
-rw-r--r--src/arch/sparc/solaris/process.hh63
-rw-r--r--src/arch/sparc/solaris/solaris.cc74
-rw-r--r--src/arch/sparc/solaris/solaris.hh62
-rw-r--r--src/arch/sparc/stacktrace.hh (renamed from arch/sparc/stacktrace.hh)0
-rw-r--r--src/arch/sparc/system.cc201
-rw-r--r--src/arch/sparc/system.hh117
-rw-r--r--src/arch/sparc/tlb.hh35
-rw-r--r--src/arch/sparc/ua2005.cc222
-rw-r--r--src/arch/sparc/utility.hh89
-rw-r--r--src/arch/sparc/vtophys.cc162
-rw-r--r--src/arch/sparc/vtophys.hh52
-rw-r--r--src/base/bitfield.hh (renamed from base/bitfield.hh)0
-rw-r--r--src/base/callback.hh (renamed from base/callback.hh)0
-rw-r--r--src/base/chunk_generator.hh141
-rw-r--r--src/base/circlebuf.cc (renamed from base/circlebuf.cc)0
-rw-r--r--src/base/circlebuf.hh (renamed from base/circlebuf.hh)0
-rw-r--r--src/base/compression/lzss_compression.cc (renamed from base/compression/lzss_compression.cc)0
-rw-r--r--src/base/compression/lzss_compression.hh (renamed from base/compression/lzss_compression.hh)0
-rw-r--r--src/base/compression/null_compression.hh (renamed from base/compression/null_compression.hh)0
-rw-r--r--src/base/cprintf.cc (renamed from base/cprintf.cc)0
-rw-r--r--src/base/cprintf.hh197
-rw-r--r--src/base/cprintf_formats.hh353
-rw-r--r--src/base/crc.cc114
-rw-r--r--src/base/crc.hh (renamed from base/crc.hh)0
-rw-r--r--src/base/date.cc (renamed from base/date.cc)0
-rw-r--r--src/base/dbl_list.hh (renamed from base/dbl_list.hh)0
-rw-r--r--src/base/endian.hh (renamed from base/endian.hh)0
-rw-r--r--src/base/fast_alloc.cc (renamed from base/fast_alloc.cc)0
-rw-r--r--src/base/fast_alloc.hh (renamed from base/fast_alloc.hh)0
-rw-r--r--src/base/fenv.hh (renamed from base/fenv.hh)0
-rw-r--r--src/base/fifo_buffer.cc (renamed from base/fifo_buffer.cc)0
-rw-r--r--src/base/fifo_buffer.hh (renamed from base/fifo_buffer.hh)0
-rw-r--r--src/base/hashmap.hh (renamed from base/hashmap.hh)0
-rw-r--r--src/base/hostinfo.cc85
-rw-r--r--src/base/hostinfo.hh (renamed from base/hostinfo.hh)0
-rw-r--r--src/base/hybrid_pred.cc (renamed from base/hybrid_pred.cc)0
-rw-r--r--src/base/hybrid_pred.hh (renamed from base/hybrid_pred.hh)0
-rw-r--r--src/base/inet.cc207
-rw-r--r--src/base/inet.hh407
-rw-r--r--src/base/inifile.cc (renamed from base/inifile.cc)0
-rw-r--r--src/base/inifile.hh (renamed from base/inifile.hh)0
-rw-r--r--src/base/intmath.cc (renamed from base/intmath.cc)0
-rw-r--r--src/base/intmath.hh230
-rw-r--r--src/base/kgdb.h (renamed from base/kgdb.h)0
-rw-r--r--src/base/loader/aout_object.cc94
-rw-r--r--src/base/loader/aout_object.hh56
-rw-r--r--src/base/loader/coff_sym.h519
-rw-r--r--src/base/loader/coff_symconst.h200
-rw-r--r--src/base/loader/ecoff_object.cc153
-rw-r--r--src/base/loader/ecoff_object.hh60
-rw-r--r--src/base/loader/elf_object.cc309
-rw-r--r--src/base/loader/elf_object.hh55
-rw-r--r--src/base/loader/exec_aout.h (renamed from base/loader/exec_aout.h)0
-rw-r--r--src/base/loader/exec_ecoff.h (renamed from base/loader/exec_ecoff.h)0
-rw-r--r--src/base/loader/object_file.cc145
-rw-r--r--src/base/loader/object_file.hh119
-rw-r--r--src/base/loader/symtab.cc (renamed from base/loader/symtab.cc)0
-rw-r--r--src/base/loader/symtab.hh173
-rw-r--r--src/base/match.cc (renamed from base/match.cc)0
-rw-r--r--src/base/match.hh (renamed from base/match.hh)0
-rw-r--r--src/base/misc.cc (renamed from base/misc.cc)0
-rw-r--r--src/base/misc.hh (renamed from base/misc.hh)0
-rw-r--r--src/base/mod_num.hh (renamed from base/mod_num.hh)0
-rw-r--r--src/base/mysql.cc (renamed from base/mysql.cc)0
-rw-r--r--src/base/mysql.hh (renamed from base/mysql.hh)0
-rw-r--r--src/base/output.cc (renamed from base/output.cc)0
-rw-r--r--src/base/output.hh (renamed from base/output.hh)0
-rw-r--r--src/base/pollevent.cc (renamed from base/pollevent.cc)0
-rw-r--r--src/base/pollevent.hh (renamed from base/pollevent.hh)0
-rw-r--r--src/base/predictor.hh (renamed from base/predictor.hh)0
-rw-r--r--src/base/random.cc (renamed from base/random.cc)0
-rw-r--r--src/base/random.hh (renamed from base/random.hh)0
-rw-r--r--src/base/range.cc (renamed from base/range.cc)0
-rw-r--r--src/base/range.hh (renamed from base/range.hh)0
-rw-r--r--src/base/refcnt.hh (renamed from base/refcnt.hh)0
-rw-r--r--src/base/remote_gdb.cc1175
-rw-r--r--src/base/remote_gdb.hh (renamed from base/remote_gdb.hh)0
-rw-r--r--src/base/res_list.hh (renamed from base/res_list.hh)0
-rw-r--r--src/base/sat_counter.cc (renamed from base/sat_counter.cc)0
-rw-r--r--src/base/sat_counter.hh (renamed from base/sat_counter.hh)0
-rw-r--r--src/base/sched_list.hh (renamed from base/sched_list.hh)0
-rw-r--r--src/base/socket.cc (renamed from base/socket.cc)0
-rw-r--r--src/base/socket.hh (renamed from base/socket.hh)0
-rw-r--r--src/base/statistics.cc356
-rw-r--r--src/base/statistics.hh2896
-rw-r--r--src/base/stats/events.cc (renamed from base/stats/events.cc)0
-rw-r--r--src/base/stats/events.hh (renamed from base/stats/events.hh)0
-rw-r--r--src/base/stats/flags.hh (renamed from base/stats/flags.hh)0
-rw-r--r--src/base/stats/mysql.cc (renamed from base/stats/mysql.cc)0
-rw-r--r--src/base/stats/mysql.hh (renamed from base/stats/mysql.hh)0
-rw-r--r--src/base/stats/mysql_run.hh (renamed from base/stats/mysql_run.hh)0
-rw-r--r--src/base/stats/output.hh (renamed from base/stats/output.hh)0
-rw-r--r--src/base/stats/statdb.cc (renamed from base/stats/statdb.cc)0
-rw-r--r--src/base/stats/statdb.hh (renamed from base/stats/statdb.hh)0
-rw-r--r--src/base/stats/text.cc736
-rw-r--r--src/base/stats/text.hh (renamed from base/stats/text.hh)0
-rw-r--r--src/base/stats/types.hh (renamed from base/stats/types.hh)0
-rw-r--r--src/base/stats/visit.cc (renamed from base/stats/visit.cc)0
-rw-r--r--src/base/stats/visit.hh (renamed from base/stats/visit.hh)0
-rw-r--r--src/base/str.cc (renamed from base/str.cc)0
-rw-r--r--src/base/str.hh (renamed from base/str.hh)0
-rw-r--r--src/base/time.cc (renamed from base/time.cc)0
-rw-r--r--src/base/time.hh (renamed from base/time.hh)0
-rw-r--r--src/base/timebuf.hh (renamed from base/timebuf.hh)0
-rw-r--r--src/base/trace.cc (renamed from base/trace.cc)0
-rw-r--r--src/base/trace.hh (renamed from base/trace.hh)0
-rw-r--r--src/base/traceflags.py289
-rw-r--r--src/base/userinfo.cc (renamed from base/userinfo.cc)0
-rw-r--r--src/base/userinfo.hh (renamed from base/userinfo.hh)0
-rw-r--r--src/cpu/SConscript179
-rw-r--r--src/cpu/base.cc381
-rw-r--r--src/cpu/base.hh238
-rw-r--r--src/cpu/base_dyn_inst.cc (renamed from cpu/base_dyn_inst.cc)0
-rw-r--r--src/cpu/base_dyn_inst.hh (renamed from cpu/base_dyn_inst.hh)0
-rw-r--r--src/cpu/cpu_exec_context.cc340
-rw-r--r--src/cpu/cpu_exec_context.hh540
-rw-r--r--src/cpu/cpu_models.py80
-rw-r--r--src/cpu/cpuevent.cc61
-rw-r--r--src/cpu/cpuevent.hh88
-rw-r--r--src/cpu/exec_context.hh417
-rw-r--r--src/cpu/exetrace.cc230
-rw-r--r--src/cpu/exetrace.hh189
-rw-r--r--src/cpu/inst_seq.hh (renamed from cpu/inst_seq.hh)0
-rw-r--r--src/cpu/intr_control.cc (renamed from cpu/intr_control.cc)0
-rw-r--r--src/cpu/intr_control.hh (renamed from cpu/intr_control.hh)0
-rw-r--r--src/cpu/memtest/memtest.cc440
-rw-r--r--src/cpu/memtest/memtest.hh (renamed from cpu/memtest/memtest.hh)0
-rw-r--r--src/cpu/o3/2bit_local_pred.cc (renamed from cpu/o3/2bit_local_pred.cc)0
-rw-r--r--src/cpu/o3/2bit_local_pred.hh (renamed from cpu/o3/2bit_local_pred.hh)0
-rw-r--r--src/cpu/o3/alpha_cpu.cc (renamed from cpu/o3/alpha_cpu.cc)0
-rw-r--r--src/cpu/o3/alpha_cpu.hh430
-rw-r--r--src/cpu/o3/alpha_cpu_builder.cc (renamed from cpu/o3/alpha_cpu_builder.cc)0
-rw-r--r--src/cpu/o3/alpha_cpu_impl.hh775
-rw-r--r--src/cpu/o3/alpha_dyn_inst.cc (renamed from cpu/o3/alpha_dyn_inst.cc)0
-rw-r--r--src/cpu/o3/alpha_dyn_inst.hh280
-rw-r--r--src/cpu/o3/alpha_dyn_inst_impl.hh (renamed from cpu/o3/alpha_dyn_inst_impl.hh)0
-rw-r--r--src/cpu/o3/alpha_impl.hh (renamed from cpu/o3/alpha_impl.hh)0
-rw-r--r--src/cpu/o3/alpha_params.hh (renamed from cpu/o3/alpha_params.hh)0
-rw-r--r--src/cpu/o3/bpred_unit.cc (renamed from cpu/o3/bpred_unit.cc)0
-rw-r--r--src/cpu/o3/bpred_unit.hh (renamed from cpu/o3/bpred_unit.hh)0
-rw-r--r--src/cpu/o3/bpred_unit_impl.hh (renamed from cpu/o3/bpred_unit_impl.hh)0
-rw-r--r--src/cpu/o3/btb.cc (renamed from cpu/o3/btb.cc)0
-rw-r--r--src/cpu/o3/btb.hh (renamed from cpu/o3/btb.hh)0
-rw-r--r--src/cpu/o3/comm.hh (renamed from cpu/o3/comm.hh)0
-rw-r--r--src/cpu/o3/commit.cc (renamed from cpu/o3/commit.cc)0
-rw-r--r--src/cpu/o3/commit.hh (renamed from cpu/o3/commit.hh)0
-rw-r--r--src/cpu/o3/commit_impl.hh (renamed from cpu/o3/commit_impl.hh)0
-rw-r--r--src/cpu/o3/cpu.cc1196
-rw-r--r--src/cpu/o3/cpu.hh525
-rw-r--r--src/cpu/o3/cpu_policy.hh (renamed from cpu/o3/cpu_policy.hh)0
-rw-r--r--src/cpu/o3/decode.cc (renamed from cpu/o3/decode.cc)0
-rw-r--r--src/cpu/o3/decode.hh (renamed from cpu/o3/decode.hh)0
-rw-r--r--src/cpu/o3/decode_impl.hh (renamed from cpu/o3/decode_impl.hh)0
-rw-r--r--src/cpu/o3/fetch.cc (renamed from cpu/o3/fetch.cc)0
-rw-r--r--src/cpu/o3/fetch.hh (renamed from cpu/o3/fetch.hh)0
-rw-r--r--src/cpu/o3/fetch_impl.hh (renamed from cpu/o3/fetch_impl.hh)0
-rw-r--r--src/cpu/o3/free_list.cc (renamed from cpu/o3/free_list.cc)0
-rw-r--r--src/cpu/o3/free_list.hh (renamed from cpu/o3/free_list.hh)0
-rw-r--r--src/cpu/o3/iew.cc (renamed from cpu/o3/iew.cc)0
-rw-r--r--src/cpu/o3/iew.hh (renamed from cpu/o3/iew.hh)0
-rw-r--r--src/cpu/o3/iew_impl.hh (renamed from cpu/o3/iew_impl.hh)0
-rw-r--r--src/cpu/o3/inst_queue.cc (renamed from cpu/o3/inst_queue.cc)0
-rw-r--r--src/cpu/o3/inst_queue.hh (renamed from cpu/o3/inst_queue.hh)0
-rw-r--r--src/cpu/o3/inst_queue_impl.hh (renamed from cpu/o3/inst_queue_impl.hh)0
-rw-r--r--src/cpu/o3/mem_dep_unit.cc (renamed from cpu/o3/mem_dep_unit.cc)0
-rw-r--r--src/cpu/o3/mem_dep_unit.hh (renamed from cpu/o3/mem_dep_unit.hh)0
-rw-r--r--src/cpu/o3/mem_dep_unit_impl.hh (renamed from cpu/o3/mem_dep_unit_impl.hh)0
-rw-r--r--src/cpu/o3/ras.cc (renamed from cpu/o3/ras.cc)0
-rw-r--r--src/cpu/o3/ras.hh (renamed from cpu/o3/ras.hh)0
-rw-r--r--src/cpu/o3/regfile.hh289
-rw-r--r--src/cpu/o3/rename.cc (renamed from cpu/o3/rename.cc)0
-rw-r--r--src/cpu/o3/rename.hh (renamed from cpu/o3/rename.hh)0
-rw-r--r--src/cpu/o3/rename_impl.hh (renamed from cpu/o3/rename_impl.hh)0
-rw-r--r--src/cpu/o3/rename_map.cc (renamed from cpu/o3/rename_map.cc)0
-rw-r--r--src/cpu/o3/rename_map.hh (renamed from cpu/o3/rename_map.hh)0
-rw-r--r--src/cpu/o3/rob.cc (renamed from cpu/o3/rob.cc)0
-rw-r--r--src/cpu/o3/rob.hh (renamed from cpu/o3/rob.hh)0
-rw-r--r--src/cpu/o3/rob_impl.hh (renamed from cpu/o3/rob_impl.hh)0
-rw-r--r--src/cpu/o3/sat_counter.cc55
-rw-r--r--src/cpu/o3/sat_counter.hh (renamed from cpu/o3/sat_counter.hh)0
-rw-r--r--src/cpu/o3/store_set.cc (renamed from cpu/o3/store_set.cc)0
-rw-r--r--src/cpu/o3/store_set.hh (renamed from cpu/o3/store_set.hh)0
-rw-r--r--src/cpu/o3/tournament_pred.cc (renamed from cpu/o3/tournament_pred.cc)0
-rw-r--r--src/cpu/o3/tournament_pred.hh (renamed from cpu/o3/tournament_pred.hh)0
-rw-r--r--src/cpu/op_class.cc50
-rw-r--r--src/cpu/op_class.hh64
-rw-r--r--src/cpu/ozone/cpu.cc (renamed from cpu/ozone/cpu.cc)0
-rw-r--r--src/cpu/ozone/cpu.hh (renamed from cpu/ozone/cpu.hh)0
-rw-r--r--src/cpu/ozone/cpu_impl.hh (renamed from cpu/ozone/cpu_impl.hh)0
-rw-r--r--src/cpu/ozone/ea_list.cc (renamed from cpu/ozone/ea_list.cc)0
-rw-r--r--src/cpu/ozone/ea_list.hh (renamed from cpu/ozone/ea_list.hh)0
-rw-r--r--src/cpu/pc_event.cc (renamed from cpu/pc_event.cc)0
-rw-r--r--src/cpu/pc_event.hh140
-rw-r--r--src/cpu/profile.cc (renamed from cpu/profile.cc)0
-rw-r--r--src/cpu/profile.hh (renamed from cpu/profile.hh)0
-rw-r--r--src/cpu/simple/atomic.cc546
-rw-r--r--src/cpu/simple/atomic.hh139
-rw-r--r--src/cpu/simple/base.cc482
-rw-r--r--src/cpu/simple/base.hh316
-rw-r--r--src/cpu/simple/timing.cc570
-rw-r--r--src/cpu/simple/timing.hh150
-rw-r--r--src/cpu/smt.hh (renamed from cpu/smt.hh)0
-rw-r--r--src/cpu/static_inst.cc (renamed from cpu/static_inst.cc)0
-rw-r--r--src/cpu/static_inst.hh490
-rw-r--r--src/cpu/trace/opt_cpu.cc (renamed from cpu/trace/opt_cpu.cc)0
-rw-r--r--src/cpu/trace/opt_cpu.hh (renamed from cpu/trace/opt_cpu.hh)0
-rw-r--r--src/cpu/trace/reader/ibm_reader.cc (renamed from cpu/trace/reader/ibm_reader.cc)0
-rw-r--r--src/cpu/trace/reader/ibm_reader.hh (renamed from cpu/trace/reader/ibm_reader.hh)0
-rw-r--r--src/cpu/trace/reader/itx_reader.cc (renamed from cpu/trace/reader/itx_reader.cc)0
-rw-r--r--src/cpu/trace/reader/itx_reader.hh (renamed from cpu/trace/reader/itx_reader.hh)0
-rw-r--r--src/cpu/trace/reader/m5_reader.cc (renamed from cpu/trace/reader/m5_reader.cc)0
-rw-r--r--src/cpu/trace/reader/m5_reader.hh (renamed from cpu/trace/reader/m5_reader.hh)0
-rw-r--r--src/cpu/trace/reader/mem_trace_reader.cc (renamed from cpu/trace/reader/mem_trace_reader.cc)0
-rw-r--r--src/cpu/trace/reader/mem_trace_reader.hh (renamed from cpu/trace/reader/mem_trace_reader.hh)0
-rw-r--r--src/cpu/trace/trace_cpu.cc (renamed from cpu/trace/trace_cpu.cc)0
-rw-r--r--src/cpu/trace/trace_cpu.hh (renamed from cpu/trace/trace_cpu.hh)0
-rw-r--r--src/dev/alpha_access.h (renamed from dev/alpha_access.h)0
-rw-r--r--src/dev/alpha_console.cc344
-rw-r--r--src/dev/alpha_console.hh129
-rw-r--r--src/dev/baddev.cc97
-rw-r--r--src/dev/baddev.hh72
-rw-r--r--src/dev/disk_image.cc470
-rw-r--r--src/dev/disk_image.hh (renamed from dev/disk_image.hh)0
-rw-r--r--src/dev/etherbus.cc125
-rw-r--r--src/dev/etherbus.hh79
-rw-r--r--src/dev/etherdump.cc136
-rw-r--r--src/dev/etherdump.hh59
-rw-r--r--src/dev/etherint.cc (renamed from dev/etherint.cc)0
-rw-r--r--src/dev/etherint.hh66
-rw-r--r--src/dev/etherlink.cc300
-rw-r--r--src/dev/etherlink.hh130
-rw-r--r--src/dev/etherpkt.cc53
-rw-r--r--src/dev/etherpkt.hh84
-rw-r--r--src/dev/ethertap.cc345
-rw-r--r--src/dev/ethertap.hh107
-rw-r--r--src/dev/ide_atareg.h (renamed from dev/ide_atareg.h)0
-rw-r--r--src/dev/ide_ctrl.cc814
-rw-r--r--src/dev/ide_ctrl.hh241
-rw-r--r--src/dev/ide_disk.cc1146
-rw-r--r--src/dev/ide_disk.hh367
-rw-r--r--src/dev/ide_wdcreg.h (renamed from dev/ide_wdcreg.h)0
-rw-r--r--src/dev/io_device.cc225
-rw-r--r--src/dev/io_device.hh335
-rw-r--r--src/dev/isa_fake.cc121
-rw-r--r--src/dev/isa_fake.hh78
-rw-r--r--src/dev/ns_gige.cc2914
-rw-r--r--src/dev/ns_gige.hh463
-rw-r--r--src/dev/ns_gige_reg.h (renamed from dev/ns_gige_reg.h)0
-rw-r--r--src/dev/pciconfigall.cc224
-rw-r--r--src/dev/pciconfigall.hh128
-rw-r--r--src/dev/pcidev.cc386
-rw-r--r--src/dev/pcidev.hh230
-rw-r--r--src/dev/pcireg.h (renamed from dev/pcireg.h)0
-rw-r--r--src/dev/pitreg.h (renamed from dev/pitreg.h)0
-rw-r--r--src/dev/pktfifo.cc99
-rw-r--r--src/dev/pktfifo.hh168
-rw-r--r--src/dev/platform.cc64
-rw-r--r--src/dev/platform.hh73
-rw-r--r--src/dev/rtcreg.h (renamed from dev/rtcreg.h)0
-rw-r--r--src/dev/simconsole.cc413
-rw-r--r--src/dev/simconsole.hh165
-rw-r--r--src/dev/simple_disk.cc111
-rw-r--r--src/dev/simple_disk.hh62
-rw-r--r--src/dev/sinic.cc1756
-rw-r--r--src/dev/sinic.hh371
-rw-r--r--src/dev/sinicreg.hh (renamed from dev/sinicreg.hh)0
-rw-r--r--src/dev/tsunami.cc127
-rw-r--r--src/dev/tsunami.hh130
-rw-r--r--src/dev/tsunami_cchip.cc554
-rw-r--r--src/dev/tsunami_cchip.hh150
-rw-r--r--src/dev/tsunami_io.cc685
-rw-r--r--src/dev/tsunami_io.hh351
-rw-r--r--src/dev/tsunami_pchip.cc358
-rw-r--r--src/dev/tsunami_pchip.hh98
-rw-r--r--src/dev/tsunamireg.h (renamed from dev/tsunamireg.h)0
-rw-r--r--src/dev/uart.cc52
-rw-r--r--src/dev/uart.hh79
-rw-r--r--src/dev/uart8250.cc366
-rw-r--r--src/dev/uart8250.hh105
-rw-r--r--src/kern/kernel_stats.cc (renamed from kern/kernel_stats.cc)0
-rw-r--r--src/kern/kernel_stats.hh (renamed from kern/kernel_stats.hh)0
-rw-r--r--src/kern/linux/events.cc55
-rw-r--r--src/kern/linux/events.hh (renamed from kern/linux/events.hh)0
-rw-r--r--src/kern/linux/linux.hh283
-rw-r--r--src/kern/linux/linux_syscalls.cc (renamed from kern/linux/linux_syscalls.cc)0
-rw-r--r--src/kern/linux/linux_syscalls.hh (renamed from kern/linux/linux_syscalls.hh)0
-rw-r--r--src/kern/linux/printk.cc261
-rw-r--r--src/kern/linux/printk.hh36
-rw-r--r--src/kern/linux/sched.hh (renamed from kern/linux/sched.hh)0
-rw-r--r--src/kern/solaris/solaris.hh304
-rw-r--r--src/kern/system_events.cc94
-rw-r--r--src/kern/system_events.hh (renamed from kern/system_events.hh)0
-rw-r--r--src/kern/tru64/dump_mbuf.cc (renamed from kern/tru64/dump_mbuf.cc)0
-rw-r--r--src/kern/tru64/dump_mbuf.hh38
-rw-r--r--src/kern/tru64/mbuf.hh (renamed from kern/tru64/mbuf.hh)0
-rw-r--r--src/kern/tru64/printf.cc266
-rw-r--r--src/kern/tru64/printf.hh38
-rw-r--r--src/kern/tru64/tru64.hh1240
-rw-r--r--src/kern/tru64/tru64_events.cc105
-rw-r--r--src/kern/tru64/tru64_events.hh (renamed from kern/tru64/tru64_events.hh)0
-rw-r--r--src/kern/tru64/tru64_syscalls.cc (renamed from kern/tru64/tru64_syscalls.cc)0
-rw-r--r--src/kern/tru64/tru64_syscalls.hh (renamed from kern/tru64/tru64_syscalls.hh)0
-rw-r--r--src/mem/bridge.cc263
-rw-r--r--src/mem/bridge.hh184
-rw-r--r--src/mem/bus.cc206
-rw-r--r--src/mem/bus.hh158
-rw-r--r--src/mem/cache/prefetch/tagged_prefetcher_impl.hh (renamed from mem/cache/prefetch/tagged_prefetcher_impl.hh)0
-rw-r--r--src/mem/config/prefetch.hh (renamed from mem/config/prefetch.hh)0
-rw-r--r--src/mem/mem_object.cc37
-rw-r--r--src/mem/mem_object.hh54
-rw-r--r--src/mem/packet.cc118
-rw-r--r--src/mem/packet.hh256
-rw-r--r--src/mem/page_table.cc134
-rw-r--r--src/mem/page_table.hh90
-rw-r--r--src/mem/physical.cc377
-rw-r--r--src/mem/physical.hh127
-rw-r--r--src/mem/port.cc84
-rw-r--r--src/mem/port.hh270
-rw-r--r--src/mem/request.hh201
-rw-r--r--src/mem/translating_port.cc187
-rw-r--r--src/mem/translating_port.hh61
-rw-r--r--src/mem/vport.cc69
-rw-r--r--src/mem/vport.hh76
-rw-r--r--src/python/SConscript207
-rw-r--r--src/python/m5/__init__.py (renamed from python/m5/__init__.py)0
-rw-r--r--src/python/m5/config.py (renamed from python/m5/config.py)0
-rw-r--r--src/python/m5/convert.py (renamed from python/m5/convert.py)0
-rw-r--r--src/python/m5/multidict.py (renamed from python/m5/multidict.py)0
-rw-r--r--src/python/m5/objects/AlphaConsole.py9
-rw-r--r--src/python/m5/objects/AlphaFullCPU.py (renamed from python/m5/objects/AlphaFullCPU.py)0
-rw-r--r--src/python/m5/objects/AlphaTLB.py (renamed from python/m5/objects/AlphaTLB.py)0
-rw-r--r--src/python/m5/objects/BadDevice.py6
-rw-r--r--src/python/m5/objects/BaseCPU.py27
-rw-r--r--src/python/m5/objects/BaseCache.py (renamed from python/m5/objects/BaseCache.py)0
-rw-r--r--src/python/m5/objects/Bridge.py9
-rw-r--r--src/python/m5/objects/Bus.py6
-rw-r--r--src/python/m5/objects/CoherenceProtocol.py (renamed from python/m5/objects/CoherenceProtocol.py)0
-rw-r--r--src/python/m5/objects/Device.py18
-rw-r--r--src/python/m5/objects/DiskImage.py (renamed from python/m5/objects/DiskImage.py)0
-rw-r--r--src/python/m5/objects/Ethernet.py115
-rw-r--r--src/python/m5/objects/Ide.py14
-rw-r--r--src/python/m5/objects/IntrControl.py (renamed from python/m5/objects/IntrControl.py)0
-rw-r--r--src/python/m5/objects/MemObject.py5
-rw-r--r--src/python/m5/objects/MemTest.py (renamed from python/m5/objects/MemTest.py)0
-rw-r--r--src/python/m5/objects/Pci.py55
-rw-r--r--src/python/m5/objects/PhysicalMemory.py8
-rw-r--r--src/python/m5/objects/Platform.py (renamed from python/m5/objects/Platform.py)0
-rw-r--r--src/python/m5/objects/Process.py27
-rw-r--r--src/python/m5/objects/Repl.py (renamed from python/m5/objects/Repl.py)0
-rw-r--r--src/python/m5/objects/Root.py23
-rw-r--r--src/python/m5/objects/SimConsole.py (renamed from python/m5/objects/SimConsole.py)0
-rw-r--r--src/python/m5/objects/SimpleDisk.py5
-rw-r--r--src/python/m5/objects/System.py21
-rw-r--r--src/python/m5/objects/Tsunami.py27
-rw-r--r--src/python/m5/objects/Uart.py15
-rw-r--r--src/python/m5/smartdict.py (renamed from python/m5/smartdict.py)0
-rw-r--r--src/sim/async.hh (renamed from sim/async.hh)0
-rw-r--r--src/sim/builder.cc (renamed from sim/builder.cc)0
-rw-r--r--src/sim/builder.hh (renamed from sim/builder.hh)0
-rw-r--r--src/sim/byteswap.hh163
-rw-r--r--src/sim/debug.cc (renamed from sim/debug.cc)0
-rw-r--r--src/sim/debug.hh (renamed from sim/debug.hh)0
-rw-r--r--src/sim/eventq.cc258
-rw-r--r--src/sim/eventq.hh (renamed from sim/eventq.hh)0
-rw-r--r--src/sim/faults.cc52
-rw-r--r--src/sim/faults.hh80
-rw-r--r--src/sim/host.hh67
-rw-r--r--src/sim/main.cc433
-rw-r--r--src/sim/param.cc793
-rw-r--r--src/sim/param.hh (renamed from sim/param.hh)0
-rw-r--r--src/sim/process.cc361
-rw-r--r--src/sim/process.hh192
-rw-r--r--src/sim/pseudo_inst.cc290
-rw-r--r--src/sim/pseudo_inst.hh (renamed from sim/pseudo_inst.hh)0
-rw-r--r--src/sim/root.cc (renamed from sim/root.cc)0
-rw-r--r--src/sim/serialize.cc (renamed from sim/serialize.cc)0
-rw-r--r--src/sim/serialize.hh (renamed from sim/serialize.hh)0
-rw-r--r--src/sim/sim_events.cc (renamed from sim/sim_events.cc)0
-rw-r--r--src/sim/sim_events.hh (renamed from sim/sim_events.hh)0
-rw-r--r--src/sim/sim_exit.hh (renamed from sim/sim_exit.hh)0
-rw-r--r--src/sim/sim_object.cc258
-rw-r--r--src/sim/sim_object.hh119
-rw-r--r--src/sim/startup.cc (renamed from sim/startup.cc)0
-rw-r--r--src/sim/startup.hh (renamed from sim/startup.hh)0
-rw-r--r--src/sim/stat_control.cc (renamed from sim/stat_control.cc)0
-rw-r--r--src/sim/stat_control.hh (renamed from sim/stat_control.hh)0
-rw-r--r--src/sim/stats.hh (renamed from sim/stats.hh)0
-rw-r--r--src/sim/syscall_emul.cc454
-rw-r--r--src/sim/syscall_emul.hh849
-rw-r--r--src/sim/system.cc267
-rw-r--r--src/sim/system.hh229
-rw-r--r--src/sim/vptr.hh122
-rw-r--r--src/unittest/Makefile98
-rw-r--r--src/unittest/bitvectest.cc (renamed from test/bitvectest.cc)0
-rw-r--r--src/unittest/circletest.cc (renamed from test/circletest.cc)0
-rw-r--r--src/unittest/cprintftest.cc163
-rw-r--r--src/unittest/foo.ini (renamed from test/foo.ini)0
-rwxr-xr-xsrc/unittest/genini.py (renamed from test/genini.py)0
-rw-r--r--src/unittest/initest.cc (renamed from test/initest.cc)0
-rw-r--r--src/unittest/initest.ini (renamed from test/initest.ini)0
-rw-r--r--src/unittest/lru_test.cc (renamed from test/lru_test.cc)0
-rw-r--r--src/unittest/nmtest.cc (renamed from test/nmtest.cc)0
-rw-r--r--src/unittest/offtest.cc (renamed from test/offtest.cc)0
-rw-r--r--src/unittest/paramtest.cc (renamed from test/paramtest.cc)0
-rw-r--r--src/unittest/rangetest.cc (renamed from test/rangetest.cc)0
-rw-r--r--src/unittest/sized_test.cc (renamed from test/sized_test.cc)0
-rw-r--r--src/unittest/stattest.cc (renamed from test/stattest.cc)0
-rw-r--r--src/unittest/strnumtest.cc (renamed from test/strnumtest.cc)0
-rw-r--r--src/unittest/symtest.cc (renamed from test/symtest.cc)0
-rw-r--r--src/unittest/tokentest.cc (renamed from test/tokentest.cc)0
-rw-r--r--src/unittest/tracetest.cc (renamed from test/tracetest.cc)0
-rw-r--r--test/Makefile69
-rw-r--r--test/cprintftest.cc164
-rwxr-xr-xutil/qdo4
885 files changed, 82744 insertions, 62207 deletions
diff --git a/LICENSE b/LICENSE
index 05aa2d1b0..a08009439 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2000-2005 The Regents of The University of Michigan
+Copyright (c) 2000-2006 The Regents of The University of Michigan
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/SConscript b/SConscript
deleted file mode 100644
index e5ca7c380..000000000
--- a/SConscript
+++ /dev/null
@@ -1,421 +0,0 @@
-# -*- mode:python -*-
-
-# Copyright (c) 2004-2005 The Regents of The University of Michigan
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met: redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer;
-# redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution;
-# neither the name of the copyright holders nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-import os
-import sys
-from os.path import isdir
-
-# This file defines how to build a particular configuration of M5
-# based on variable settings in the 'env' build environment.
-
-# Import build environment variable from SConstruct.
-Import('env')
-
-###################################################
-#
-# Define needed sources.
-#
-###################################################
-
-# Base sources used by all configurations.
-
-base_sources = Split('''
- base/circlebuf.cc
- base/copyright.cc
- base/cprintf.cc
- base/embedfile.cc
- base/fast_alloc.cc
- base/fifo_buffer.cc
- base/hostinfo.cc
- base/hybrid_pred.cc
- base/inifile.cc
- base/intmath.cc
- base/match.cc
- base/misc.cc
- base/output.cc
- base/pollevent.cc
- base/range.cc
- base/random.cc
- base/sat_counter.cc
- base/socket.cc
- base/statistics.cc
- base/str.cc
- base/time.cc
- base/trace.cc
- base/traceflags.cc
- base/userinfo.cc
- base/compression/lzss_compression.cc
- base/loader/aout_object.cc
- base/loader/ecoff_object.cc
- base/loader/elf_object.cc
- base/loader/object_file.cc
- base/loader/symtab.cc
- base/stats/events.cc
- base/stats/statdb.cc
- base/stats/visit.cc
- base/stats/text.cc
-
- cpu/activity.cc
- cpu/base.cc
- cpu/base_dyn_inst.cc
- cpu/cpu_exec_context.cc
- cpu/exetrace.cc
- cpu/pc_event.cc
- cpu/quiesce_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
-
- python/pyconfig.cc
- python/embedded_py.cc
-
- sim/builder.cc
- sim/configfile.cc
- sim/debug.cc
- sim/eventq.cc
- sim/faults.cc
- sim/main.cc
- sim/param.cc
- sim/profile.cc
- sim/root.cc
- sim/serialize.cc
- sim/sim_events.cc
- sim/sim_exit.cc
- sim/sim_object.cc
- sim/startup.cc
- sim/stat_context.cc
- sim/stat_control.cc
- sim/trace_context.cc
- ''')
-
-# Old FullCPU sources
-full_cpu_sources = Split('''
- encumbered/cpu/full/bpred.cc
- encumbered/cpu/full/commit.cc
- encumbered/cpu/full/cpu.cc
- encumbered/cpu/full/create_vector.cc
- encumbered/cpu/full/cv_spec_state.cc
- encumbered/cpu/full/dd_queue.cc
- encumbered/cpu/full/dep_link.cc
- encumbered/cpu/full/dispatch.cc
- encumbered/cpu/full/dyn_inst.cc
- encumbered/cpu/full/execute.cc
- encumbered/cpu/full/fetch.cc
- encumbered/cpu/full/floss_reasons.cc
- encumbered/cpu/full/fu_pool.cc
- encumbered/cpu/full/inst_fifo.cc
- encumbered/cpu/full/instpipe.cc
- encumbered/cpu/full/issue.cc
- encumbered/cpu/full/ls_queue.cc
- encumbered/cpu/full/machine_queue.cc
- encumbered/cpu/full/pipetrace.cc
- encumbered/cpu/full/readyq.cc
- encumbered/cpu/full/reg_info.cc
- encumbered/cpu/full/rob_station.cc
- encumbered/cpu/full/spec_memory.cc
- encumbered/cpu/full/spec_state.cc
- encumbered/cpu/full/storebuffer.cc
- encumbered/cpu/full/writeback.cc
- encumbered/cpu/full/iq/iq_station.cc
- encumbered/cpu/full/iq/iqueue.cc
- encumbered/cpu/full/iq/segmented/chain_info.cc
- encumbered/cpu/full/iq/segmented/chain_wire.cc
- encumbered/cpu/full/iq/segmented/iq_seg.cc
- encumbered/cpu/full/iq/segmented/iq_segmented.cc
- encumbered/cpu/full/iq/segmented/seg_chain.cc
- encumbered/cpu/full/iq/seznec/iq_seznec.cc
- encumbered/cpu/full/iq/standard/iq_standard.cc
- ''')
-
-# MySql sources
-mysql_sources = Split('''
- base/mysql.cc
- base/stats/mysql.cc
- ''')
-
-# Full-system sources
-full_system_sources = Split('''
- base/crc.cc
- base/inet.cc
- base/remote_gdb.cc
-
- cpu/intr_control.cc
- cpu/profile.cc
-
- dev/alpha_console.cc
- dev/baddev.cc
- dev/simconsole.cc
- dev/disk_image.cc
- dev/etherbus.cc
- dev/etherdump.cc
- dev/etherint.cc
- dev/etherlink.cc
- dev/etherpkt.cc
- dev/ethertap.cc
- dev/ide_ctrl.cc
- dev/ide_disk.cc
- dev/io_device.cc
- dev/ns_gige.cc
- dev/pciconfigall.cc
- dev/pcidev.cc
- dev/pcifake.cc
- dev/pktfifo.cc
- dev/platform.cc
- dev/sinic.cc
- dev/simple_disk.cc
- dev/tsunami.cc
- dev/tsunami_cchip.cc
- dev/isa_fake.cc
- dev/tsunami_io.cc
- dev/tsunami_pchip.cc
- dev/uart.cc
- dev/uart8250.cc
-
- kern/kernel_binning.cc
- kern/kernel_stats.cc
- kern/system_events.cc
- kern/linux/events.cc
- kern/linux/linux_syscalls.cc
- kern/linux/printk.cc
- 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
-turbolaser_sources = Split('''
- encumbered/dev/dma.cc
- encumbered/dev/etherdev.cc
- encumbered/dev/scsi.cc
- encumbered/dev/scsi_ctrl.cc
- encumbered/dev/scsi_disk.cc
- encumbered/dev/scsi_none.cc
- encumbered/dev/tlaser_clock.cc
- encumbered/dev/tlaser_ipi.cc
- encumbered/dev/tlaser_mbox.cc
- encumbered/dev/tlaser_mc146818.cc
- encumbered/dev/tlaser_node.cc
- encumbered/dev/tlaser_pcia.cc
- encumbered/dev/tlaser_pcidev.cc
- encumbered/dev/tlaser_serial.cc
- encumbered/dev/turbolaser.cc
- encumbered/dev/uart8530.cc
- ''')
-
-# Syscall emulation (non-full-system) sources
-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
- sim/process.cc
- sim/syscall_emul.cc
- ''')
-
-# Add a flag defining what THE_ISA should be for all compilation
-env.Append(CPPDEFINES=[('THE_ISA','%s_ISA' % env['TARGET_ISA'].upper())])
-
-arch_sources = SConscript('arch/SConscript',
- exports = 'env', duplicate = False)
-
-cpu_sources = SConscript('cpu/SConscript',
- exports = 'env', duplicate = False)
-
-# This is outside of cpu/SConscript since the source directory isn't
-# underneath 'cpu'.
-if 'FullCPU' in env['CPU_MODELS']:
- cpu_sources += full_cpu_sources
-
-# Set up complete list of sources based on configuration.
-sources = base_sources + arch_sources + cpu_sources
-
-if env['FULL_SYSTEM']:
- sources += full_system_sources
- if env['ALPHA_TLASER']:
- sources += turbolaser_sources
-else:
- sources += syscall_emulation_sources
-
-if env['USE_MYSQL']:
- sources += mysql_sources
-
-for opt in env.ExportOptions:
- env.ConfigFile(opt)
-
-###################################################
-#
-# Special build rules.
-#
-###################################################
-
-# base/traceflags.{cc,hh} are generated from base/traceflags.py.
-# $TARGET.base will expand to "<build-dir>/base/traceflags".
-env.Command(Split('base/traceflags.hh base/traceflags.cc'),
- 'base/traceflags.py',
- 'python $SOURCE $TARGET.base')
-
-# libelf build is described in its own SConscript file.
-# SConscript-local is the per-config build, which just copies some
-# header files into a place where they can be found.
-SConscript('libelf/SConscript-local', exports = 'env', duplicate=0)
-SConscript('python/SConscript', exports = ['env'], duplicate=0)
-
-# This function adds the specified sources to the given build
-# environment, and returns a list of all the corresponding SCons
-# Object nodes (including an extra one for date.cc). We explicitly
-# add the Object nodes so we can set up special dependencies for
-# date.cc.
-def make_objs(sources, env):
- objs = [env.Object(s) for s in sources]
- # make date.cc depend on all other objects so it always gets
- # recompiled whenever anything else does
- date_obj = env.Object('base/date.cc')
- env.Depends(date_obj, objs)
- objs.append(date_obj)
- return objs
-
-###################################################
-#
-# Define binaries. Each different build type (debug, opt, etc.) gets
-# a slightly different build environment.
-#
-###################################################
-
-# Include file paths are rooted in this directory. SCons will
-# automatically expand '.' to refer to both the source directory and
-# the corresponding build directory to pick up generated include
-# files.
-env.Append(CPPPATH='.')
-env.Append(CPPPATH='./libelf')
-
-# Debug binary
-debugEnv = env.Copy(OBJSUFFIX='.do')
-debugEnv.Label = 'debug'
-debugEnv.Append(CCFLAGS=Split('-g -gdwarf-2 -O0'))
-debugEnv.Append(CPPDEFINES='DEBUG')
-tlist = debugEnv.Program(target = 'm5.debug',
- source = make_objs(sources, debugEnv))
-debugEnv.M5Binary = tlist[0]
-
-# Optimized binary
-optEnv = env.Copy()
-optEnv.Label = 'opt'
-optEnv.Append(CCFLAGS=Split('-g -O5'))
-tlist = optEnv.Program(target = 'm5.opt',
- source = make_objs(sources, optEnv))
-optEnv.M5Binary = tlist[0]
-
-# "Fast" binary
-fastEnv = env.Copy(OBJSUFFIX='.fo')
-fastEnv.Label = 'fast'
-fastEnv.Append(CCFLAGS=Split('-O5'))
-fastEnv.Append(CPPDEFINES='NDEBUG')
-fastEnv.Program(target = 'm5.fast.unstripped',
- source = make_objs(sources, fastEnv))
-tlist = fastEnv.Command(target = 'm5.fast',
- source = 'm5.fast.unstripped',
- action = 'strip $SOURCE -o $TARGET')
-fastEnv.M5Binary = tlist[0]
-
-# Profiled binary
-profEnv = env.Copy(OBJSUFFIX='.po')
-profEnv.Label = 'prof'
-profEnv.Append(CCFLAGS=Split('-O5 -g -pg'), LINKFLAGS='-pg')
-tlist = profEnv.Program(target = 'm5.prof',
- source = make_objs(sources, profEnv))
-profEnv.M5Binary = tlist[0]
-
-envList = [debugEnv, optEnv, fastEnv, profEnv]
-
-Return('envList')
diff --git a/SConstruct b/SConstruct
new file mode 100644
index 000000000..f2a41400c
--- /dev/null
+++ b/SConstruct
@@ -0,0 +1,438 @@
+# -*- mode:python -*-
+
+# Copyright (c) 2004-2005 The Regents of The University of Michigan
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met: redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer;
+# redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution;
+# neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+###################################################
+#
+# SCons top-level build description (SConstruct) file.
+#
+# While in this directory ('m5'), just type 'scons' to build the default
+# configuration (see below), or type 'scons build/<CONFIG>/<binary>'
+# to build some other configuration (e.g., 'build/ALPHA_FS/m5.opt' for
+# the optimized full-system version).
+#
+# You can build M5 in a different directory as long as there is a
+# 'build/<CONFIG>' somewhere along the target path. The build system
+# expdects that all configs under the same build directory are being
+# built for the same host system.
+#
+# Examples:
+# These two commands are equivalent. The '-u' option tells scons to
+# search up the directory tree for this SConstruct file.
+# % cd <path-to-src>/m5 ; scons build/ALPHA_FS/m5.debug
+# % cd <path-to-src>/m5/build/ALPHA_FS; scons -u m5.debug
+# These two commands are equivalent and demonstrate building in a
+# directory outside of the source tree. The '-C' option tells scons
+# to chdir to the specified directory to find this SConstruct file.
+# % cd <path-to-src>/m5 ; scons /local/foo/build/ALPHA_FS/m5.debug
+# % cd /local/foo/build/ALPHA_FS; scons -C <path-to-src>/m5 m5.debug
+#
+# You can use 'scons -H' to print scons options. If you're in this
+# 'm5' directory (or use -u or -C to tell scons where to find this
+# file), you can use 'scons -h' to print all the M5-specific build
+# options as well.
+#
+###################################################
+
+# Python library imports
+import sys
+import os
+
+# Check for recent-enough Python and SCons versions
+EnsurePythonVersion(2,3)
+
+# Ironically, SCons 0.96 dies if you give EnsureSconsVersion a
+# 3-element version number.
+min_scons_version = (0,96,91)
+try:
+ EnsureSConsVersion(*min_scons_version)
+except:
+ print "Error checking current SCons version."
+ print "SCons", ".".join(map(str,min_scons_version)), "or greater required."
+ Exit(2)
+
+
+# The absolute path to the current directory (where this file lives).
+ROOT = Dir('.').abspath
+
+# Paths to the M5 and external source trees.
+SRCDIR = os.path.join(ROOT, 'src')
+
+# tell python where to find m5 python code
+sys.path.append(os.path.join(ROOT, 'src/python'))
+
+###################################################
+#
+# Figure out which configurations to set up based on the path(s) of
+# the target(s).
+#
+###################################################
+
+# Find default configuration & binary.
+Default(os.environ.get('M5_DEFAULT_BINARY', 'build/ALPHA_SE/m5.debug'))
+
+# Ask SCons which directory it was invoked from.
+launch_dir = GetLaunchDir()
+
+# Make targets relative to invocation directory
+abs_targets = map(lambda x: os.path.normpath(os.path.join(launch_dir, str(x))),
+ BUILD_TARGETS)
+
+# helper function: find last occurrence of element in list
+def rfind(l, elt, offs = -1):
+ for i in range(len(l)+offs, 0, -1):
+ if l[i] == elt:
+ return i
+ raise ValueError, "element not found"
+
+# Each target must have 'build' in the interior of the path; the
+# directory below this will determine the build parameters. For
+# example, for target 'foo/bar/build/ALPHA_SE/arch/alpha/blah.do' we
+# recognize that ALPHA_SE specifies the configuration because it
+# follow 'build' in the bulid path.
+
+# Generate a list of the unique build roots and configs that the
+# collected targets reference.
+build_paths = []
+build_root = None
+for t in abs_targets:
+ path_dirs = t.split('/')
+ try:
+ build_top = rfind(path_dirs, 'build', -2)
+ except:
+ print "Error: no non-leaf 'build' dir found on target path", t
+ Exit(1)
+ this_build_root = os.path.join('/',*path_dirs[:build_top+1])
+ if not build_root:
+ build_root = this_build_root
+ else:
+ if this_build_root != build_root:
+ print "Error: build targets not under same build root\n"\
+ " %s\n %s" % (build_root, this_build_root)
+ Exit(1)
+ build_path = os.path.join('/',*path_dirs[:build_top+2])
+ if build_path not in build_paths:
+ build_paths.append(build_path)
+
+###################################################
+#
+# Set up the default build environment. This environment is copied
+# and modified according to each selected configuration.
+#
+###################################################
+
+env = Environment(ENV = os.environ, # inherit user's environment vars
+ ROOT = ROOT,
+ SRCDIR = SRCDIR)
+
+env.SConsignFile("sconsign")
+
+# I waffle on this setting... it does avoid a few painful but
+# unnecessary builds, but it also seems to make trivial builds take
+# noticeably longer.
+if False:
+ env.TargetSignatures('content')
+
+# M5_PLY is used by isa_parser.py to find the PLY package.
+env.Append(ENV = { 'M5_PLY' : Dir('ext/ply') })
+
+# Set up default C++ compiler flags
+env.Append(CCFLAGS='-pipe')
+env.Append(CCFLAGS='-fno-strict-aliasing')
+env.Append(CCFLAGS=Split('-Wall -Wno-sign-compare -Werror -Wundef'))
+if sys.platform == 'cygwin':
+ # cygwin has some header file issues...
+ env.Append(CCFLAGS=Split("-Wno-uninitialized"))
+env.Append(CPPPATH=[Dir('ext/dnet')])
+
+# Default libraries
+env.Append(LIBS=['z'])
+
+# Platform-specific configuration. Note again that we assume that all
+# builds under a given build root run on the same host platform.
+conf = Configure(env,
+ conf_dir = os.path.join(build_root, '.scons_config'),
+ log_file = os.path.join(build_root, 'scons_config.log'))
+
+# Check for <fenv.h> (C99 FP environment control)
+have_fenv = conf.CheckHeader('fenv.h', '<>')
+if not have_fenv:
+ print "Warning: Header file <fenv.h> not found."
+ print " This host has no IEEE FP rounding mode control."
+
+# Check for mysql.
+mysql_config = WhereIs('mysql_config')
+have_mysql = mysql_config != None
+
+# Check MySQL version.
+if have_mysql:
+ mysql_version = os.popen(mysql_config + ' --version').read()
+ mysql_version = mysql_version.split('.')
+ mysql_major = int(mysql_version[0])
+ mysql_minor = int(mysql_version[1])
+ # This version check is probably overly conservative, but it deals
+ # with the versions we have installed.
+ if mysql_major < 4 or (mysql_major == 4 and mysql_minor < 1):
+ print "Warning: MySQL v4.1 or newer required."
+ have_mysql = False
+
+# Set up mysql_config commands.
+if have_mysql:
+ mysql_config_include = mysql_config + ' --include'
+ if os.system(mysql_config_include + ' > /dev/null') != 0:
+ # older mysql_config versions don't support --include, use
+ # --cflags instead
+ mysql_config_include = mysql_config + ' --cflags | sed s/\\\'//g'
+ # This seems to work in all versions
+ mysql_config_libs = mysql_config + ' --libs'
+
+env = conf.Finish()
+
+# Define the universe of supported ISAs
+env['ALL_ISA_LIST'] = ['alpha', 'sparc', 'mips']
+
+# Define the universe of supported CPU models
+env['ALL_CPU_LIST'] = ['AtomicSimpleCPU', 'TimingSimpleCPU',
+ 'FullCPU', 'AlphaFullCPU',
+ 'OzoneSimpleCPU', 'OzoneCPU', 'CheckerCPU']
+
+# Sticky options get saved in the options file so they persist from
+# one invocation to the next (unless overridden, in which case the new
+# value becomes sticky).
+sticky_opts = Options(args=ARGUMENTS)
+sticky_opts.AddOptions(
+ EnumOption('TARGET_ISA', 'Target ISA', 'alpha', 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', 'AtomicSimpleCPU,TimingSimpleCPU',
+ env['ALL_CPU_LIST']),
+ BoolOption('ALPHA_TLASER',
+ 'Model Alpha TurboLaser platform (vs. Tsunami)', False),
+ BoolOption('NO_FAST_ALLOC', 'Disable fast object allocator', False),
+ BoolOption('EFENCE', 'Link with Electric Fence malloc debugger',
+ False),
+ BoolOption('SS_COMPATIBLE_FP',
+ 'Make floating-point results compatible with SimpleScalar',
+ False),
+ BoolOption('USE_SSE2',
+ 'Compile for SSE2 (-msse2) to get IEEE FP on x86 hosts',
+ False),
+ BoolOption('STATS_BINNING', 'Bin statistics by CPU mode', have_mysql),
+ BoolOption('USE_MYSQL', 'Use MySQL for stats output', have_mysql),
+ BoolOption('USE_FENV', 'Use <fenv.h> IEEE mode control', have_fenv),
+ ('CC', 'C compiler', os.environ.get('CC', env['CC'])),
+ ('CXX', 'C++ compiler', os.environ.get('CXX', env['CXX'])),
+ BoolOption('BATCH', 'Use batch pool for build and tests', False),
+ ('BATCH_CMD', 'Batch pool submission command name', 'qdo')
+ )
+
+# Non-sticky options only apply to the current build.
+nonsticky_opts = Options(args=ARGUMENTS)
+nonsticky_opts.AddOptions(
+ BoolOption('update_ref', 'Update test reference outputs', False)
+ )
+
+# These options get exported to #defines in config/*.hh (see m5/SConscript).
+env.ExportOptions = ['FULL_SYSTEM', 'ALPHA_TLASER', 'USE_FENV', \
+ 'USE_MYSQL', 'NO_FAST_ALLOC', 'SS_COMPATIBLE_FP', \
+ 'STATS_BINNING']
+
+# Define a handy 'no-op' action
+def no_action(target, source, env):
+ return 0
+
+env.NoAction = Action(no_action, None)
+
+###################################################
+#
+# Define a SCons builder for configuration flag headers.
+#
+###################################################
+
+# This function generates a config header file that #defines the
+# option symbol to the current option setting (0 or 1). The source
+# operands are the name of the option and a Value node containing the
+# value of the option.
+def build_config_file(target, source, env):
+ (option, value) = [s.get_contents() for s in source]
+ f = file(str(target[0]), 'w')
+ print >> f, '#define', option, value
+ f.close()
+ return None
+
+# Generate the message to be printed when building the config file.
+def build_config_file_string(target, source, env):
+ (option, value) = [s.get_contents() for s in source]
+ return "Defining %s as %s in %s." % (option, value, target[0])
+
+# Combine the two functions into a scons Action object.
+config_action = Action(build_config_file, build_config_file_string)
+
+# The emitter munges the source & target node lists to reflect what
+# we're really doing.
+def config_emitter(target, source, env):
+ # extract option name from Builder arg
+ option = str(target[0])
+ # True target is config header file
+ target = os.path.join('config', option.lower() + '.hh')
+ # Force value to 0/1 even if it's a Python bool
+ val = int(eval(str(env[option])))
+ # Sources are option name & value (packaged in SCons Value nodes)
+ return ([target], [Value(option), Value(val)])
+
+config_builder = Builder(emitter = config_emitter, action = config_action)
+
+env.Append(BUILDERS = { 'ConfigFile' : config_builder })
+
+# base help text
+help_text = '''
+Usage: scons [scons options] [build options] [target(s)]
+
+'''
+
+# libelf build is shared across all configs in the build root.
+env.SConscript('ext/libelf/SConscript',
+ build_dir = os.path.join(build_root, 'libelf'),
+ exports = 'env')
+
+###################################################
+#
+# Define build environments for selected configurations.
+#
+###################################################
+
+# rename base env
+base_env = env
+
+for build_path in build_paths:
+ print "Building in", build_path
+ # build_dir is the tail component of build path, and is used to
+ # determine the build parameters (e.g., 'ALPHA_SE')
+ (build_root, build_dir) = os.path.split(build_path)
+ # Make a copy of the build-root environment to use for this config.
+ env = base_env.Copy()
+
+ # Set env options according to the build directory config.
+ sticky_opts.files = []
+ # Options for $BUILD_ROOT/$BUILD_DIR are stored in
+ # $BUILD_ROOT/options/$BUILD_DIR so you can nuke
+ # $BUILD_ROOT/$BUILD_DIR without losing your options settings.
+ current_opts_file = os.path.join(build_root, 'options', build_dir)
+ if os.path.isfile(current_opts_file):
+ sticky_opts.files.append(current_opts_file)
+ print "Using saved options file %s" % current_opts_file
+ else:
+ # Build dir-specific options file doesn't exist.
+
+ # Make sure the directory is there so we can create it later
+ opt_dir = os.path.dirname(current_opts_file)
+ if not os.path.isdir(opt_dir):
+ os.mkdir(opt_dir)
+
+ # Get default build options from source tree. Options are
+ # normally determined by name of $BUILD_DIR, but can be
+ # overriden by 'default=' arg on command line.
+ default_opts_file = os.path.join('build_opts',
+ ARGUMENTS.get('default', build_dir))
+ if os.path.isfile(default_opts_file):
+ sticky_opts.files.append(default_opts_file)
+ print "Options file %s not found,\n using defaults in %s" \
+ % (current_opts_file, default_opts_file)
+ else:
+ print "Error: cannot find options file %s or %s" \
+ % (current_opts_file, default_opts_file)
+ Exit(1)
+
+ # Apply current option settings to env
+ 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']:
+ print "Warning: <fenv.h> not available; " \
+ "forcing USE_FENV to False in", build_dir + "."
+ env['USE_FENV'] = False
+
+ if not env['USE_FENV']:
+ print "Warning: No IEEE FP rounding mode control in", build_dir + "."
+ print " FP results may deviate slightly from other platforms."
+
+ if env['EFENCE']:
+ env.Append(LIBS=['efence'])
+
+ if env['USE_MYSQL']:
+ if not have_mysql:
+ print "Warning: MySQL not available; " \
+ "forcing USE_MYSQL to False in", build_dir + "."
+ env['USE_MYSQL'] = False
+ else:
+ print "Compiling in", build_dir, "with MySQL support."
+ env.ParseConfig(mysql_config_libs)
+ env.ParseConfig(mysql_config_include)
+
+ # Save sticky option settings back to current options file
+ sticky_opts.Save(current_opts_file, env)
+
+ # Do this after we save setting back, or else we'll tack on an
+ # extra 'qdo' every time we run scons.
+ if env['BATCH']:
+ env['CC'] = env['BATCH_CMD'] + ' ' + env['CC']
+ env['CXX'] = env['BATCH_CMD'] + ' ' + env['CXX']
+
+ if env['USE_SSE2']:
+ env.Append(CCFLAGS='-msse2')
+
+ # The m5/SConscript file sets up the build rules in 'env' according
+ # to the configured options. It returns a list of environments,
+ # one for each variant build (debug, opt, etc.)
+ envList = SConscript('src/SConscript', build_dir = build_path,
+ exports = 'env', duplicate = False)
+
+ # Set up the regression tests for each build.
+# for e in envList:
+# SConscript('m5-test/SConscript',
+# 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
+# build environments to build the requested targets.
+#
+###################################################
+
diff --git a/arch/SConscript b/arch/SConscript
deleted file mode 100644
index 92547c0ae..000000000
--- a/arch/SConscript
+++ /dev/null
@@ -1,146 +0,0 @@
-# -*- mode:python -*-
-
-# Copyright (c) 2006 The Regents of The University of Michigan
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met: redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer;
-# redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution;
-# neither the name of the copyright holders nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-import os.path
-
-# Import build environment variable from SConstruct.
-Import('env')
-
-# Right now there are no source files immediately in this directory
-sources = []
-
-#################################################################
-#
-# ISA "switch header" generation.
-#
-# Auto-generate arch headers that include the right ISA-specific
-# header based on the setting of THE_ISA preprocessor variable.
-#
-#################################################################
-
-# List of headers to generate
-isa_switch_hdrs = Split('''
- isa_traits.hh
- tlb.hh
- process.hh
- arguments.hh
- stacktrace.hh
- vtophys.hh
- faults.hh
- ''')
-
-# Generate the header. target[0] is the full path of the output
-# header to generate. 'source' is a dummy variable, since we get the
-# list of ISAs from env['ALL_ISA_LIST'].
-def gen_switch_hdr(target, source, env):
- fname = str(target[0])
- basename = os.path.basename(fname)
- f = open(fname, 'w')
- f.write('#include "arch/isa_specific.hh"\n')
- cond = '#if'
- for isa in env['ALL_ISA_LIST']:
- f.write('%s THE_ISA == %s_ISA\n#include "arch/%s/%s"\n'
- % (cond, isa.upper(), isa, basename))
- cond = '#elif'
- f.write('#else\n#error "THE_ISA not set"\n#endif\n')
- f.close()
- return 0
-
-# String to print when generating header
-def gen_switch_hdr_string(target, source, env):
- return "Generating ISA switch header " + str(target[0])
-
-# Build SCons Action object. 'varlist' specifies env vars that this
-# action depends on; when env['ALL_ISA_LIST'] changes these actions
-# should get re-executed.
-switch_hdr_action = Action(gen_switch_hdr, gen_switch_hdr_string,
- varlist=['ALL_ISA_LIST'])
-
-# Instantiate actions for each header
-for hdr in isa_switch_hdrs:
- env.Command(hdr, [], switch_hdr_action)
-
-#################################################################
-#
-# Include architecture-specific files.
-#
-#################################################################
-
-#
-# Build a SCons scanner for ISA files
-#
-import SCons.Scanner
-
-isa_scanner = SCons.Scanner.Classic("ISAScan",
- [".isa", ".ISA"],
- "SRCDIR",
- r'^\s*##include\s+"([\w/.-]*)"')
-
-env.Append(SCANNERS = isa_scanner)
-
-#
-# Now create a Builder object that uses isa_parser.py to generate C++
-# output from the ISA description (*.isa) files.
-#
-
-# Convert to File node to fix path
-isa_parser = File('isa_parser.py')
-cpu_models_file = File('#m5/cpu/cpu_models.py')
-
-# This sucks in the defintions of the CpuModel objects.
-execfile(cpu_models_file.srcnode().abspath)
-
-# Several files are generated from the ISA description.
-# We always get the basic decoder and header file.
-isa_desc_gen_files = Split('decoder.cc decoder.hh')
-# We also get an execute file for each selected CPU model.
-isa_desc_gen_files += [CpuModel.dict[cpu].filename
- for cpu in env['CPU_MODELS']]
-
-# The emitter patches up the sources & targets to include the
-# autogenerated files as targets and isa parser itself as a source.
-def isa_desc_emitter(target, source, env):
- return (isa_desc_gen_files, [isa_parser, cpu_models_file] + source)
-
-# Pieces are in place, so create the builder.
-isa_desc_builder = Builder(action='python $SOURCES $TARGET.dir $CPU_MODELS',
- emitter = isa_desc_emitter)
-
-env.Append(BUILDERS = { 'ISADesc' : isa_desc_builder })
-
-#
-# Now include other ISA-specific sources from the ISA subdirectories.
-#
-
-isa = env['TARGET_ISA'] # someday this may be a list of ISAs
-
-# Let the target architecture define what additional sources it needs
-sources += SConscript(os.path.join(isa, 'SConscript'),
- exports = 'env', duplicate = False)
-
-Return('sources')
diff --git a/arch/alpha/SConscript b/arch/alpha/SConscript
deleted file mode 100644
index ed7fd3404..000000000
--- a/arch/alpha/SConscript
+++ /dev/null
@@ -1,91 +0,0 @@
-# -*- mode:python -*-
-
-# Copyright (c) 2004-2005 The Regents of The University of Michigan
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met: redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer;
-# redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution;
-# neither the name of the copyright holders nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-import os
-import sys
-from os.path import isdir
-
-# This file defines how to build a particular configuration of M5
-# based on variable settings in the 'env' build environment.
-
-# Import build environment variable from SConstruct.
-Import('env')
-
-###################################################
-#
-# Define needed sources.
-#
-###################################################
-
-# Base sources used by all configurations.
-base_sources = Split('''
- faults.cc
- isa_traits.cc
- ''')
-
-# Full-system sources
-full_system_sources = Split('''
- tlb.cc
- arguments.cc
- ev5.cc
- osfpal.cc
- stacktrace.cc
- vtophys.cc
- system.cc
- freebsd/system.cc
- linux/system.cc
- tru64/system.cc
- ''')
-
-
-# Syscall emulation (non-full-system) sources
-syscall_emulation_sources = Split('''
- linux/process.cc
- tru64/process.cc
- process.cc
- ''')
-
-# Set up complete list of sources based on configuration.
-sources = base_sources
-
-if env['FULL_SYSTEM']:
- sources += full_system_sources
-else:
- sources += syscall_emulation_sources
-
-# Convert file names to SCons File objects. This takes care of the
-# path relative to the top of the directory tree.
-sources = [File(s) for s in sources]
-
-# Add in files generated by the ISA description.
-isa_desc_files = env.ISADesc('isa/main.isa')
-# Only non-header files need to be compiled.
-isa_desc_sources = [f for f in isa_desc_files if not f.path.endswith('.hh')]
-sources += isa_desc_sources
-
-Return('sources')
diff --git a/arch/alpha/arguments.cc b/arch/alpha/arguments.cc
deleted file mode 100644
index 019390aeb..000000000
--- a/arch/alpha/arguments.cc
+++ /dev/null
@@ -1,66 +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/alpha/arguments.hh"
-#include "arch/alpha/vtophys.hh"
-#include "cpu/exec_context.hh"
-#include "mem/functional/physical.hh"
-
-using namespace AlphaISA;
-
-AlphaArguments::Data::~Data()
-{
- while (!data.empty()) {
- delete [] data.front();
- data.pop_front();
- }
-}
-
-char *
-AlphaArguments::Data::alloc(size_t size)
-{
- char *buf = new char[size];
- data.push_back(buf);
- return buf;
-}
-
-uint64_t
-AlphaArguments::getArg(bool fp)
-{
- if (number < 6) {
- if (fp)
- return xc->readFloatRegInt(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);
- }
-}
-
diff --git a/arch/alpha/arguments.hh b/arch/alpha/arguments.hh
deleted file mode 100644
index 75346bf58..000000000
--- a/arch/alpha/arguments.hh
+++ /dev/null
@@ -1,143 +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.
- */
-
-#ifndef __ARGUMENTS_HH__
-#define __ARGUMENTS_HH__
-
-#include <assert.h>
-
-#include "arch/alpha/vtophys.hh"
-#include "base/refcnt.hh"
-#include "sim/host.hh"
-
-class ExecContext;
-
-class AlphaArguments
-{
- protected:
- ExecContext *xc;
- int number;
- uint64_t getArg(bool fp = false);
-
- protected:
- class Data : public RefCounted
- {
- public:
- Data(){}
- ~Data();
-
- private:
- std::list<char *> data;
-
- public:
- char *alloc(size_t size);
- };
-
- RefCountingPtr<Data> data;
-
- public:
- AlphaArguments(ExecContext *ctx, int n = 0)
- : xc(ctx), number(n), data(NULL)
- { assert(number >= 0); data = new Data;}
- AlphaArguments(const AlphaArguments &args)
- : xc(args.xc), number(args.number), data(args.data) {}
- ~AlphaArguments() {}
-
- ExecContext *getExecContext() const { return xc; }
-
- const AlphaArguments &operator=(const AlphaArguments &args) {
- xc = args.xc;
- number = args.number;
- data = args.data;
- return *this;
- }
-
- AlphaArguments &operator++() {
- ++number;
- assert(number >= 0);
- return *this;
- }
-
- AlphaArguments operator++(int) {
- AlphaArguments args = *this;
- ++number;
- assert(number >= 0);
- return args;
- }
-
- AlphaArguments &operator--() {
- --number;
- assert(number >= 0);
- return *this;
- }
-
- AlphaArguments operator--(int) {
- AlphaArguments args = *this;
- --number;
- assert(number >= 0);
- return args;
- }
-
- const AlphaArguments &operator+=(int index) {
- number += index;
- assert(number >= 0);
- return *this;
- }
-
- const AlphaArguments &operator-=(int index) {
- number -= index;
- assert(number >= 0);
- return *this;
- }
-
- AlphaArguments operator[](int index) {
- return AlphaArguments(xc, index);
- }
-
- template <class T>
- operator T() {
- assert(sizeof(T) <= sizeof(uint64_t));
- T data = static_cast<T>(getArg());
- return data;
- }
-
- template <class T>
- operator T *() {
- T *buf = (T *)data->alloc(sizeof(T));
- CopyData(xc, buf, getArg(), sizeof(T));
- return buf;
- }
-
- operator char *() {
- char *buf = data->alloc(2048);
- CopyString(xc, buf, getArg(), 2048);
- return buf;
- }
-};
-
-#endif // __ARGUMENTS_HH__
diff --git a/arch/alpha/ev5.cc b/arch/alpha/ev5.cc
deleted file mode 100644
index f113a2767..000000000
--- a/arch/alpha/ev5.cc
+++ /dev/null
@@ -1,593 +0,0 @@
-/*
- * Copyright (c) 2002-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "arch/alpha/tlb.hh"
-#include "arch/alpha/isa_traits.hh"
-#include "arch/alpha/osfpal.hh"
-#include "base/kgdb.h"
-#include "base/remote_gdb.hh"
-#include "base/stats/events.hh"
-#include "config/full_system.hh"
-#include "cpu/base.hh"
-#include "cpu/cpu_exec_context.hh"
-#include "cpu/exec_context.hh"
-#include "cpu/fast/cpu.hh"
-#include "kern/kernel_stats.hh"
-#include "sim/debug.hh"
-#include "sim/sim_events.hh"
-
-#if FULL_SYSTEM
-
-using namespace EV5;
-
-////////////////////////////////////////////////////////////////////////
-//
-// Machine dependent functions
-//
-void
-AlphaISA::initCPU(ExecContext *xc, int cpuId)
-{
- initIPRs(xc, cpuId);
-
- xc->setIntReg(16, cpuId);
- xc->setIntReg(0, cpuId);
-
- xc->setPC(xc->readMiscReg(IPR_PAL_BASE) + (new ResetFault)->vect());
- xc->setNextPC(xc->readPC() + sizeof(MachInst));
-}
-
-////////////////////////////////////////////////////////////////////////
-//
-//
-//
-void
-AlphaISA::initIPRs(ExecContext *xc, int cpuId)
-{
- for (int i = 0; i < NumInternalProcRegs; ++i) {
- xc->setMiscReg(i, 0);
- }
-
- xc->setMiscReg(IPR_PAL_BASE, PalBase);
- xc->setMiscReg(IPR_MCSR, 0x6);
- xc->setMiscReg(IPR_PALtemp16, cpuId);
-}
-
-
-template <class CPU>
-void
-AlphaISA::processInterrupts(CPU *cpu)
-{
- //Check if there are any outstanding interrupts
- //Handle the interrupts
- int ipl = 0;
- int summary = 0;
-
- cpu->checkInterrupts = false;
-
- if (cpu->readMiscReg(IPR_ASTRR))
- panic("asynchronous traps not implemented\n");
-
- if (cpu->readMiscReg(IPR_SIRR)) {
- for (int i = INTLEVEL_SOFTWARE_MIN;
- i < INTLEVEL_SOFTWARE_MAX; i++) {
- if (cpu->readMiscReg(IPR_SIRR) & (ULL(1) << i)) {
- // See table 4-19 of the 21164 hardware reference
- ipl = (i - INTLEVEL_SOFTWARE_MIN) + 1;
- summary |= (ULL(1) << i);
- }
- }
- }
-
- uint64_t interrupts = cpu->intr_status();
-
- if (interrupts) {
- for (int i = INTLEVEL_EXTERNAL_MIN;
- i < INTLEVEL_EXTERNAL_MAX; i++) {
- if (interrupts & (ULL(1) << i)) {
- // See table 4-19 of the 21164 hardware reference
- ipl = i;
- summary |= (ULL(1) << i);
- }
- }
- }
-
- if (ipl && ipl > cpu->readMiscReg(IPR_IPLR)) {
- cpu->setMiscReg(IPR_ISR, summary);
- cpu->setMiscReg(IPR_INTID, ipl);
- cpu->trap(new InterruptFault);
- DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n",
- cpu->readMiscReg(IPR_IPLR), ipl, summary);
- }
-
-}
-
-template <class CPU>
-void
-AlphaISA::zeroRegisters(CPU *cpu)
-{
- // Insure ISA semantics
- // (no longer very clean due to the change in setIntReg() in the
- // cpu model. Consider changing later.)
- cpu->cpuXC->setIntReg(ZeroReg, 0);
- cpu->cpuXC->setFloatRegDouble(ZeroReg, 0.0);
-}
-
-Fault
-CPUExecContext::hwrei()
-{
- if (!inPalMode())
- return new UnimplementedOpcodeFault;
-
- setNextPC(readMiscReg(AlphaISA::IPR_EXC_ADDR));
-
- if (!misspeculating()) {
- if (kernelStats)
- kernelStats->hwrei();
-
- cpu->checkInterrupts = true;
- }
-
- // FIXME: XXX check for interrupts? XXX
- return NoFault;
-}
-
-int
-AlphaISA::MiscRegFile::getInstAsid()
-{
- return EV5::ITB_ASN_ASN(ipr[IPR_ITB_ASN]);
-}
-
-int
-AlphaISA::MiscRegFile::getDataAsid()
-{
- return EV5::DTB_ASN_ASN(ipr[IPR_DTB_ASN]);
-}
-
-AlphaISA::MiscReg
-AlphaISA::MiscRegFile::readIpr(int idx, Fault &fault, ExecContext *xc)
-{
- uint64_t retval = 0; // return value, default 0
-
- switch (idx) {
- case AlphaISA::IPR_PALtemp0:
- case AlphaISA::IPR_PALtemp1:
- case AlphaISA::IPR_PALtemp2:
- case AlphaISA::IPR_PALtemp3:
- case AlphaISA::IPR_PALtemp4:
- case AlphaISA::IPR_PALtemp5:
- case AlphaISA::IPR_PALtemp6:
- case AlphaISA::IPR_PALtemp7:
- case AlphaISA::IPR_PALtemp8:
- case AlphaISA::IPR_PALtemp9:
- case AlphaISA::IPR_PALtemp10:
- case AlphaISA::IPR_PALtemp11:
- case AlphaISA::IPR_PALtemp12:
- case AlphaISA::IPR_PALtemp13:
- case AlphaISA::IPR_PALtemp14:
- case AlphaISA::IPR_PALtemp15:
- case AlphaISA::IPR_PALtemp16:
- case AlphaISA::IPR_PALtemp17:
- case AlphaISA::IPR_PALtemp18:
- case AlphaISA::IPR_PALtemp19:
- case AlphaISA::IPR_PALtemp20:
- case AlphaISA::IPR_PALtemp21:
- case AlphaISA::IPR_PALtemp22:
- case AlphaISA::IPR_PALtemp23:
- case AlphaISA::IPR_PAL_BASE:
-
- case AlphaISA::IPR_IVPTBR:
- case AlphaISA::IPR_DC_MODE:
- case AlphaISA::IPR_MAF_MODE:
- case AlphaISA::IPR_ISR:
- case AlphaISA::IPR_EXC_ADDR:
- case AlphaISA::IPR_IC_PERR_STAT:
- case AlphaISA::IPR_DC_PERR_STAT:
- case AlphaISA::IPR_MCSR:
- case AlphaISA::IPR_ASTRR:
- case AlphaISA::IPR_ASTER:
- case AlphaISA::IPR_SIRR:
- case AlphaISA::IPR_ICSR:
- case AlphaISA::IPR_ICM:
- case AlphaISA::IPR_DTB_CM:
- case AlphaISA::IPR_IPLR:
- case AlphaISA::IPR_INTID:
- case AlphaISA::IPR_PMCTR:
- // no side-effect
- retval = ipr[idx];
- break;
-
- case AlphaISA::IPR_CC:
- retval |= ipr[idx] & ULL(0xffffffff00000000);
- retval |= xc->getCpuPtr()->curCycle() & ULL(0x00000000ffffffff);
- break;
-
- case AlphaISA::IPR_VA:
- retval = ipr[idx];
- break;
-
- case AlphaISA::IPR_VA_FORM:
- case AlphaISA::IPR_MM_STAT:
- case AlphaISA::IPR_IFAULT_VA_FORM:
- case AlphaISA::IPR_EXC_MASK:
- case AlphaISA::IPR_EXC_SUM:
- retval = ipr[idx];
- break;
-
- case AlphaISA::IPR_DTB_PTE:
- {
- AlphaISA::PTE &pte = xc->getDTBPtr()->index(!xc->misspeculating());
-
- retval |= ((u_int64_t)pte.ppn & ULL(0x7ffffff)) << 32;
- retval |= ((u_int64_t)pte.xre & ULL(0xf)) << 8;
- retval |= ((u_int64_t)pte.xwe & ULL(0xf)) << 12;
- retval |= ((u_int64_t)pte.fonr & ULL(0x1)) << 1;
- retval |= ((u_int64_t)pte.fonw & ULL(0x1))<< 2;
- retval |= ((u_int64_t)pte.asma & ULL(0x1)) << 4;
- retval |= ((u_int64_t)pte.asn & ULL(0x7f)) << 57;
- }
- break;
-
- // write only registers
- case AlphaISA::IPR_HWINT_CLR:
- case AlphaISA::IPR_SL_XMIT:
- case AlphaISA::IPR_DC_FLUSH:
- case AlphaISA::IPR_IC_FLUSH:
- case AlphaISA::IPR_ALT_MODE:
- case AlphaISA::IPR_DTB_IA:
- case AlphaISA::IPR_DTB_IAP:
- case AlphaISA::IPR_ITB_IA:
- case AlphaISA::IPR_ITB_IAP:
- fault = new UnimplementedOpcodeFault;
- break;
-
- default:
- // invalid IPR
- fault = new UnimplementedOpcodeFault;
- break;
- }
-
- return retval;
-}
-
-#ifdef DEBUG
-// Cause the simulator to break when changing to the following IPL
-int break_ipl = -1;
-#endif
-
-Fault
-AlphaISA::MiscRegFile::setIpr(int idx, uint64_t val, ExecContext *xc)
-{
- uint64_t old;
-
- if (xc->misspeculating())
- return NoFault;
-
- switch (idx) {
- case AlphaISA::IPR_PALtemp0:
- case AlphaISA::IPR_PALtemp1:
- case AlphaISA::IPR_PALtemp2:
- case AlphaISA::IPR_PALtemp3:
- case AlphaISA::IPR_PALtemp4:
- case AlphaISA::IPR_PALtemp5:
- case AlphaISA::IPR_PALtemp6:
- case AlphaISA::IPR_PALtemp7:
- case AlphaISA::IPR_PALtemp8:
- case AlphaISA::IPR_PALtemp9:
- case AlphaISA::IPR_PALtemp10:
- case AlphaISA::IPR_PALtemp11:
- case AlphaISA::IPR_PALtemp12:
- case AlphaISA::IPR_PALtemp13:
- case AlphaISA::IPR_PALtemp14:
- case AlphaISA::IPR_PALtemp15:
- case AlphaISA::IPR_PALtemp16:
- case AlphaISA::IPR_PALtemp17:
- case AlphaISA::IPR_PALtemp18:
- case AlphaISA::IPR_PALtemp19:
- case AlphaISA::IPR_PALtemp20:
- case AlphaISA::IPR_PALtemp21:
- case AlphaISA::IPR_PALtemp22:
- case AlphaISA::IPR_PAL_BASE:
- case AlphaISA::IPR_IC_PERR_STAT:
- case AlphaISA::IPR_DC_PERR_STAT:
- case AlphaISA::IPR_PMCTR:
- // write entire quad w/ no side-effect
- ipr[idx] = val;
- break;
-
- case AlphaISA::IPR_CC_CTL:
- // This IPR resets the cycle counter. We assume this only
- // happens once... let's verify that.
- assert(ipr[idx] == 0);
- ipr[idx] = 1;
- break;
-
- case AlphaISA::IPR_CC:
- // This IPR only writes the upper 64 bits. It's ok to write
- // all 64 here since we mask out the lower 32 in rpcc (see
- // isa_desc).
- ipr[idx] = val;
- break;
-
- case AlphaISA::IPR_PALtemp23:
- // write entire quad w/ no side-effect
- old = ipr[idx];
- ipr[idx] = val;
- if (xc->getKernelStats())
- xc->getKernelStats()->context(old, val, xc);
- break;
-
- case AlphaISA::IPR_DTB_PTE:
- // write entire quad w/ no side-effect, tag is forthcoming
- ipr[idx] = val;
- break;
-
- case AlphaISA::IPR_EXC_ADDR:
- // second least significant bit in PC is always zero
- ipr[idx] = val & ~2;
- break;
-
- case AlphaISA::IPR_ASTRR:
- case AlphaISA::IPR_ASTER:
- // only write least significant four bits - privilege mask
- ipr[idx] = val & 0xf;
- break;
-
- case AlphaISA::IPR_IPLR:
-#ifdef DEBUG
- if (break_ipl != -1 && break_ipl == (val & 0x1f))
- debug_break();
-#endif
-
- // only write least significant five bits - interrupt level
- ipr[idx] = val & 0x1f;
- if (xc->getKernelStats())
- xc->getKernelStats()->swpipl(ipr[idx]);
- break;
-
- case AlphaISA::IPR_DTB_CM:
- if (val & 0x18) {
- if (xc->getKernelStats())
- xc->getKernelStats()->mode(Kernel::user, xc);
- } else {
- if (xc->getKernelStats())
- xc->getKernelStats()->mode(Kernel::kernel, xc);
- }
-
- case AlphaISA::IPR_ICM:
- // only write two mode bits - processor mode
- ipr[idx] = val & 0x18;
- break;
-
- case AlphaISA::IPR_ALT_MODE:
- // only write two mode bits - processor mode
- ipr[idx] = val & 0x18;
- break;
-
- case AlphaISA::IPR_MCSR:
- // more here after optimization...
- ipr[idx] = val;
- break;
-
- case AlphaISA::IPR_SIRR:
- // only write software interrupt mask
- ipr[idx] = val & 0x7fff0;
- break;
-
- case AlphaISA::IPR_ICSR:
- ipr[idx] = val & ULL(0xffffff0300);
- break;
-
- case AlphaISA::IPR_IVPTBR:
- case AlphaISA::IPR_MVPTBR:
- ipr[idx] = val & ULL(0xffffffffc0000000);
- break;
-
- case AlphaISA::IPR_DC_TEST_CTL:
- ipr[idx] = val & 0x1ffb;
- break;
-
- case AlphaISA::IPR_DC_MODE:
- case AlphaISA::IPR_MAF_MODE:
- ipr[idx] = val & 0x3f;
- break;
-
- case AlphaISA::IPR_ITB_ASN:
- ipr[idx] = val & 0x7f0;
- break;
-
- case AlphaISA::IPR_DTB_ASN:
- ipr[idx] = val & ULL(0xfe00000000000000);
- break;
-
- case AlphaISA::IPR_EXC_SUM:
- case AlphaISA::IPR_EXC_MASK:
- // any write to this register clears it
- ipr[idx] = 0;
- break;
-
- case AlphaISA::IPR_INTID:
- case AlphaISA::IPR_SL_RCV:
- case AlphaISA::IPR_MM_STAT:
- case AlphaISA::IPR_ITB_PTE_TEMP:
- case AlphaISA::IPR_DTB_PTE_TEMP:
- // read-only registers
- return new UnimplementedOpcodeFault;
-
- case AlphaISA::IPR_HWINT_CLR:
- case AlphaISA::IPR_SL_XMIT:
- case AlphaISA::IPR_DC_FLUSH:
- case AlphaISA::IPR_IC_FLUSH:
- // the following are write only
- ipr[idx] = val;
- break;
-
- case AlphaISA::IPR_DTB_IA:
- // really a control write
- ipr[idx] = 0;
-
- xc->getDTBPtr()->flushAll();
- break;
-
- case AlphaISA::IPR_DTB_IAP:
- // really a control write
- ipr[idx] = 0;
-
- xc->getDTBPtr()->flushProcesses();
- break;
-
- case AlphaISA::IPR_DTB_IS:
- // really a control write
- ipr[idx] = val;
-
- xc->getDTBPtr()->flushAddr(val,
- DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN]));
- break;
-
- case AlphaISA::IPR_DTB_TAG: {
- struct AlphaISA::PTE pte;
-
- // FIXME: granularity hints NYI...
- if (DTB_PTE_GH(ipr[AlphaISA::IPR_DTB_PTE]) != 0)
- panic("PTE GH field != 0");
-
- // write entire quad
- ipr[idx] = val;
-
- // construct PTE for new entry
- pte.ppn = DTB_PTE_PPN(ipr[AlphaISA::IPR_DTB_PTE]);
- pte.xre = DTB_PTE_XRE(ipr[AlphaISA::IPR_DTB_PTE]);
- pte.xwe = DTB_PTE_XWE(ipr[AlphaISA::IPR_DTB_PTE]);
- pte.fonr = DTB_PTE_FONR(ipr[AlphaISA::IPR_DTB_PTE]);
- pte.fonw = DTB_PTE_FONW(ipr[AlphaISA::IPR_DTB_PTE]);
- pte.asma = DTB_PTE_ASMA(ipr[AlphaISA::IPR_DTB_PTE]);
- pte.asn = DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN]);
-
- // insert new TAG/PTE value into data TLB
- xc->getDTBPtr()->insert(val, pte);
- }
- break;
-
- case AlphaISA::IPR_ITB_PTE: {
- struct AlphaISA::PTE pte;
-
- // FIXME: granularity hints NYI...
- if (ITB_PTE_GH(val) != 0)
- panic("PTE GH field != 0");
-
- // write entire quad
- ipr[idx] = val;
-
- // construct PTE for new entry
- pte.ppn = ITB_PTE_PPN(val);
- pte.xre = ITB_PTE_XRE(val);
- pte.xwe = 0;
- pte.fonr = ITB_PTE_FONR(val);
- pte.fonw = ITB_PTE_FONW(val);
- pte.asma = ITB_PTE_ASMA(val);
- pte.asn = ITB_ASN_ASN(ipr[AlphaISA::IPR_ITB_ASN]);
-
- // insert new TAG/PTE value into data TLB
- xc->getITBPtr()->insert(ipr[AlphaISA::IPR_ITB_TAG], pte);
- }
- break;
-
- case AlphaISA::IPR_ITB_IA:
- // really a control write
- ipr[idx] = 0;
-
- xc->getITBPtr()->flushAll();
- break;
-
- case AlphaISA::IPR_ITB_IAP:
- // really a control write
- ipr[idx] = 0;
-
- xc->getITBPtr()->flushProcesses();
- break;
-
- case AlphaISA::IPR_ITB_IS:
- // really a control write
- ipr[idx] = val;
-
- xc->getITBPtr()->flushAddr(val,
- ITB_ASN_ASN(ipr[AlphaISA::IPR_ITB_ASN]));
- break;
-
- default:
- // invalid IPR
- return new UnimplementedOpcodeFault;
- }
-
- // no error...
- return NoFault;
-}
-
-void
-AlphaISA::MiscRegFile::copyIprs(ExecContext *xc)
-{
- for (int i = IPR_Base_DepTag; i < NumInternalProcRegs; ++i) {
- ipr[i] = xc->readMiscReg(i);
- }
-}
-
-/**
- * Check for special simulator handling of specific PAL calls.
- * If return value is false, actual PAL call will be suppressed.
- */
-bool
-CPUExecContext::simPalCheck(int palFunc)
-{
- if (kernelStats)
- kernelStats->callpal(palFunc, proxy);
-
- switch (palFunc) {
- case PAL::halt:
- halt();
- if (--System::numSystemsRunning == 0)
- new SimExitEvent("all cpus halted");
- break;
-
- case PAL::bpt:
- case PAL::bugchk:
- if (system->breakpoint())
- return false;
- break;
- }
-
- 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/freebsd/system.cc b/arch/alpha/freebsd/system.cc
deleted file mode 100644
index e32053afd..000000000
--- a/arch/alpha/freebsd/system.cc
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * @file
- * Modifications for the FreeBSD kernel.
- * Based on kern/linux/linux_system.cc.
- *
- */
-
-#include "arch/alpha/system.hh"
-#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 "arch/isa_traits.hh"
-#include "sim/builder.hh"
-#include "sim/byteswap.hh"
-#include "arch/vtophys.hh"
-
-#define TIMER_FREQUENCY 1193180
-
-using namespace std;
-using namespace AlphaISA;
-
-FreebsdAlphaSystem::FreebsdAlphaSystem(Params *p)
- : AlphaSystem(p)
-{
- /**
- * Any time DELAY is called just skip the function.
- * Shouldn't we actually emulate the delay?
- */
- skipDelayEvent = addKernelFuncEvent<SkipFuncEvent>("DELAY");
- skipCalibrateClocks =
- addKernelFuncEvent<SkipCalibrateClocksEvent>("calibrate_clocks");
-}
-
-
-FreebsdAlphaSystem::~FreebsdAlphaSystem()
-{
- delete skipDelayEvent;
- delete skipCalibrateClocks;
-}
-
-
-void
-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);
-}
-
-
-void
-FreebsdAlphaSystem::SkipCalibrateClocksEvent::process(ExecContext *xc)
-{
- SkipFuncEvent::process(xc);
- ((FreebsdAlphaSystem *)xc->getSystemPtr())->doCalibrateClocks(xc);
-}
-
-
-BEGIN_DECLARE_SIM_OBJECT_PARAMS(FreebsdAlphaSystem)
-
- Param<Tick> boot_cpu_frequency;
- SimObjectParam<MemoryController *> memctrl;
- SimObjectParam<PhysicalMemory *> physmem;
-
- Param<string> kernel;
- Param<string> console;
- Param<string> pal;
-
- Param<string> boot_osflags;
- Param<string> readfile;
- Param<unsigned int> init_param;
-
- Param<uint64_t> system_type;
- Param<uint64_t> system_rev;
-
- Param<bool> bin;
- VectorParam<string> binned_fns;
- Param<bool> bin_int;
-
-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"),
- INIT_PARAM(pal, "file that contains palcode"),
- INIT_PARAM_DFLT(boot_osflags, "flags to pass to the kernel during boot",
- "a"),
- INIT_PARAM_DFLT(readfile, "file to read startup script from", ""),
- INIT_PARAM_DFLT(init_param, "numerical value to pass into simulator", 0),
- INIT_PARAM_DFLT(system_type, "Type of system we are emulating", 34),
- INIT_PARAM_DFLT(system_rev, "Revision of system we are emulating", 1<<10),
- INIT_PARAM_DFLT(bin, "is this system to be binned", false),
- INIT_PARAM(binned_fns, "functions to be broken down and binned"),
- INIT_PARAM_DFLT(bin_int, "is interrupt code binned seperately?", true)
-
-END_INIT_SIM_OBJECT_PARAMS(FreebsdAlphaSystem)
-
-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;
- p->palcode = pal;
- p->boot_osflags = boot_osflags;
- p->init_param = init_param;
- p->readfile = readfile;
- p->system_type = system_type;
- p->system_rev = system_rev;
- p->bin = bin;
- p->binned_fns = binned_fns;
- p->bin_int = bin_int;
- return new FreebsdAlphaSystem(p);
-}
-
-REGISTER_SIM_OBJECT("FreebsdAlphaSystem", FreebsdAlphaSystem)
-
diff --git a/arch/alpha/isa/branch.isa b/arch/alpha/isa/branch.isa
deleted file mode 100644
index b528df938..000000000
--- a/arch/alpha/isa/branch.isa
+++ /dev/null
@@ -1,259 +0,0 @@
-// -*- mode:c++ -*-
-
-// Copyright (c) 2003-2005 The Regents of The University of Michigan
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met: redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer;
-// redistributions in binary form must reproduce the above copyright
-// notice, this list of conditions and the following disclaimer in the
-// documentation and/or other materials provided with the distribution;
-// neither the name of the copyright holders nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-output header {{
-
- /**
- * Base class for instructions whose disassembly is not purely a
- * function of the machine instruction (i.e., it depends on the
- * PC). This class overrides the disassemble() method to check
- * the PC and symbol table values before re-using a cached
- * disassembly string. This is necessary for branches and jumps,
- * where the disassembly string includes the target address (which
- * may depend on the PC and/or symbol table).
- */
- class PCDependentDisassembly : public AlphaStaticInst
- {
- protected:
- /// Cached program counter from last disassembly
- mutable Addr cachedPC;
- /// Cached symbol table pointer from last disassembly
- mutable const SymbolTable *cachedSymtab;
-
- /// Constructor
- PCDependentDisassembly(const char *mnem, ExtMachInst _machInst,
- OpClass __opClass)
- : AlphaStaticInst(mnem, _machInst, __opClass),
- cachedPC(0), cachedSymtab(0)
- {
- }
-
- const std::string &
- disassemble(Addr pc, const SymbolTable *symtab) const;
- };
-
- /**
- * Base class for branches (PC-relative control transfers),
- * conditional or unconditional.
- */
- class Branch : public PCDependentDisassembly
- {
- protected:
- /// Displacement to target address (signed).
- int32_t disp;
-
- /// Constructor.
- Branch(const char *mnem, ExtMachInst _machInst, OpClass __opClass)
- : PCDependentDisassembly(mnem, _machInst, __opClass),
- disp(BRDISP << 2)
- {
- }
-
- Addr branchTarget(Addr branchPC) const;
-
- std::string
- generateDisassembly(Addr pc, const SymbolTable *symtab) const;
- };
-
- /**
- * Base class for jumps (register-indirect control transfers). In
- * the Alpha ISA, these are always unconditional.
- */
- class Jump : public PCDependentDisassembly
- {
- protected:
-
- /// Displacement to target address (signed).
- int32_t disp;
-
- public:
- /// Constructor
- Jump(const char *mnem, ExtMachInst _machInst, OpClass __opClass)
- : PCDependentDisassembly(mnem, _machInst, __opClass),
- disp(BRDISP)
- {
- }
-
- Addr branchTarget(ExecContext *xc) const;
-
- std::string
- generateDisassembly(Addr pc, const SymbolTable *symtab) const;
- };
-}};
-
-output decoder {{
- Addr
- Branch::branchTarget(Addr branchPC) const
- {
- return branchPC + 4 + disp;
- }
-
- Addr
- Jump::branchTarget(ExecContext *xc) const
- {
- Addr NPC = xc->readPC() + 4;
- uint64_t Rb = xc->readIntReg(_srcRegIdx[0]);
- return (Rb & ~3) | (NPC & 1);
- }
-
- const std::string &
- PCDependentDisassembly::disassemble(Addr pc,
- const SymbolTable *symtab) const
- {
- if (!cachedDisassembly ||
- pc != cachedPC || symtab != cachedSymtab)
- {
- if (cachedDisassembly)
- delete cachedDisassembly;
-
- cachedDisassembly =
- new std::string(generateDisassembly(pc, symtab));
- cachedPC = pc;
- cachedSymtab = symtab;
- }
-
- return *cachedDisassembly;
- }
-
- std::string
- Branch::generateDisassembly(Addr pc, const SymbolTable *symtab) const
- {
- std::stringstream ss;
-
- ccprintf(ss, "%-10s ", mnemonic);
-
- // There's only one register arg (RA), but it could be
- // either a source (the condition for conditional
- // branches) or a destination (the link reg for
- // unconditional branches)
- if (_numSrcRegs > 0) {
- printReg(ss, _srcRegIdx[0]);
- ss << ",";
- }
- else if (_numDestRegs > 0) {
- printReg(ss, _destRegIdx[0]);
- ss << ",";
- }
-
-#ifdef SS_COMPATIBLE_DISASSEMBLY
- if (_numSrcRegs == 0 && _numDestRegs == 0) {
- printReg(ss, 31);
- ss << ",";
- }
-#endif
-
- Addr target = pc + 4 + disp;
-
- std::string str;
- if (symtab && symtab->findSymbol(target, str))
- ss << str;
- else
- ccprintf(ss, "0x%x", target);
-
- return ss.str();
- }
-
- std::string
- Jump::generateDisassembly(Addr pc, const SymbolTable *symtab) const
- {
- std::stringstream ss;
-
- ccprintf(ss, "%-10s ", mnemonic);
-
-#ifdef SS_COMPATIBLE_DISASSEMBLY
- if (_numDestRegs == 0) {
- printReg(ss, 31);
- ss << ",";
- }
-#endif
-
- if (_numDestRegs > 0) {
- printReg(ss, _destRegIdx[0]);
- ss << ",";
- }
-
- ccprintf(ss, "(r%d)", RB);
-
- return ss.str();
- }
-}};
-
-def template JumpOrBranchDecode {{
- return (RA == 31)
- ? (StaticInst *)new %(class_name)s(machInst)
- : (StaticInst *)new %(class_name)sAndLink(machInst);
-}};
-
-def format CondBranch(code) {{
- code = 'bool cond;\n' + code + '\nif (cond) NPC = NPC + disp;\n';
- iop = InstObjParams(name, Name, 'Branch', CodeBlock(code),
- ('IsDirectControl', 'IsCondControl'))
- header_output = BasicDeclare.subst(iop)
- decoder_output = BasicConstructor.subst(iop)
- decode_block = BasicDecode.subst(iop)
- exec_output = BasicExecute.subst(iop)
-}};
-
-let {{
-def UncondCtrlBase(name, Name, base_class, npc_expr, flags):
- # Declare basic control transfer w/o link (i.e. link reg is R31)
- nolink_code = 'NPC = %s;\n' % npc_expr
- nolink_iop = InstObjParams(name, Name, base_class,
- CodeBlock(nolink_code), flags)
- header_output = BasicDeclare.subst(nolink_iop)
- decoder_output = BasicConstructor.subst(nolink_iop)
- exec_output = BasicExecute.subst(nolink_iop)
-
- # Generate declaration of '*AndLink' version, append to decls
- link_code = 'Ra = NPC & ~3;\n' + nolink_code
- link_iop = InstObjParams(name, Name + 'AndLink', base_class,
- CodeBlock(link_code), flags)
- header_output += BasicDeclare.subst(link_iop)
- decoder_output += BasicConstructor.subst(link_iop)
- exec_output += BasicExecute.subst(link_iop)
-
- # need to use link_iop for the decode template since it is expecting
- # the shorter version of class_name (w/o "AndLink")
-
- return (header_output, decoder_output,
- JumpOrBranchDecode.subst(nolink_iop), exec_output)
-}};
-
-def format UncondBranch(*flags) {{
- flags += ('IsUncondControl', 'IsDirectControl')
- (header_output, decoder_output, decode_block, exec_output) = \
- UncondCtrlBase(name, Name, 'Branch', 'NPC + disp', flags)
-}};
-
-def format Jump(*flags) {{
- flags += ('IsUncondControl', 'IsIndirectControl')
- (header_output, decoder_output, decode_block, exec_output) = \
- UncondCtrlBase(name, Name, 'Jump', '(Rb & ~3) | (NPC & 1)', flags)
-}};
-
-
diff --git a/arch/alpha/isa/decoder.isa b/arch/alpha/isa/decoder.isa
deleted file mode 100644
index b3744a43d..000000000
--- a/arch/alpha/isa/decoder.isa
+++ /dev/null
@@ -1,819 +0,0 @@
-// -*- mode:c++ -*-
-
-// Copyright (c) 2003-2006 The Regents of The University of Michigan
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met: redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer;
-// redistributions in binary form must reproduce the above copyright
-// notice, this list of conditions and the following disclaimer in the
-// documentation and/or other materials provided with the distribution;
-// neither the name of the copyright holders nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-decode OPCODE default Unknown::unknown() {
-
- format LoadAddress {
- 0x08: lda({{ Ra = Rb + disp; }});
- 0x09: ldah({{ Ra = Rb + (disp << 16); }});
- }
-
- format LoadOrNop {
- 0x0a: ldbu({{ Ra.uq = Mem.ub; }});
- 0x0c: ldwu({{ Ra.uq = Mem.uw; }});
- 0x0b: ldq_u({{ Ra = Mem.uq; }}, ea_code = {{ EA = (Rb + disp) & ~7; }});
- 0x23: ldt({{ Fa = Mem.df; }});
- 0x2a: ldl_l({{ Ra.sl = Mem.sl; }}, mem_flags = LOCKED);
- 0x2b: ldq_l({{ Ra.uq = Mem.uq; }}, mem_flags = LOCKED);
- 0x20: MiscPrefetch::copy_load({{ EA = Ra; }},
- {{ fault = xc->copySrcTranslate(EA); }},
- inst_flags = [IsMemRef, IsLoad, IsCopy]);
- }
-
- format LoadOrPrefetch {
- 0x28: ldl({{ Ra.sl = Mem.sl; }});
- 0x29: ldq({{ Ra.uq = Mem.uq; }}, pf_flags = EVICT_NEXT);
- // IsFloating flag on lds gets the prefetch to disassemble
- // using f31 instead of r31... funcitonally it's unnecessary
- 0x22: lds({{ Fa.uq = s_to_t(Mem.ul); }},
- pf_flags = PF_EXCLUSIVE, inst_flags = IsFloating);
- }
-
- format Store {
- 0x0e: stb({{ Mem.ub = Ra<7:0>; }});
- 0x0d: stw({{ Mem.uw = Ra<15:0>; }});
- 0x2c: stl({{ Mem.ul = Ra<31:0>; }});
- 0x2d: stq({{ Mem.uq = Ra.uq; }});
- 0x0f: stq_u({{ Mem.uq = Ra.uq; }}, {{ EA = (Rb + disp) & ~7; }});
- 0x26: sts({{ Mem.ul = t_to_s(Fa.uq); }});
- 0x27: stt({{ Mem.df = Fa; }});
- 0x24: MiscPrefetch::copy_store({{ EA = Rb; }},
- {{ fault = xc->copy(EA); }},
- inst_flags = [IsMemRef, IsStore, IsCopy]);
- }
-
- format StoreCond {
- 0x2e: stl_c({{ Mem.ul = Ra<31:0>; }},
- {{
- uint64_t tmp = write_result;
- // see stq_c
- Ra = (tmp == 0 || tmp == 1) ? tmp : Ra;
- }}, mem_flags = LOCKED, inst_flags = IsStoreConditional);
- 0x2f: stq_c({{ Mem.uq = Ra; }},
- {{
- uint64_t tmp = write_result;
- // If the write operation returns 0 or 1, then
- // this was a conventional store conditional,
- // and the value indicates the success/failure
- // of the operation. If another value is
- // returned, then this was a Turbolaser
- // mailbox access, and we don't update the
- // result register at all.
- Ra = (tmp == 0 || tmp == 1) ? tmp : Ra;
- }}, mem_flags = LOCKED, inst_flags = IsStoreConditional);
- }
-
- format IntegerOperate {
-
- 0x10: decode INTFUNC { // integer arithmetic operations
-
- 0x00: addl({{ Rc.sl = Ra.sl + Rb_or_imm.sl; }});
- 0x40: addlv({{
- uint32_t tmp = Ra.sl + Rb_or_imm.sl;
- // signed overflow occurs when operands have same sign
- // and sign of result does not match.
- if (Ra.sl<31:> == Rb_or_imm.sl<31:> && tmp<31:> != Ra.sl<31:>)
- fault = new IntegerOverflowFault;
- Rc.sl = tmp;
- }});
- 0x02: s4addl({{ Rc.sl = (Ra.sl << 2) + Rb_or_imm.sl; }});
- 0x12: s8addl({{ Rc.sl = (Ra.sl << 3) + Rb_or_imm.sl; }});
-
- 0x20: addq({{ Rc = Ra + Rb_or_imm; }});
- 0x60: addqv({{
- uint64_t tmp = Ra + Rb_or_imm;
- // signed overflow occurs when operands have same sign
- // and sign of result does not match.
- if (Ra<63:> == Rb_or_imm<63:> && tmp<63:> != Ra<63:>)
- fault = new IntegerOverflowFault;
- Rc = tmp;
- }});
- 0x22: s4addq({{ Rc = (Ra << 2) + Rb_or_imm; }});
- 0x32: s8addq({{ Rc = (Ra << 3) + Rb_or_imm; }});
-
- 0x09: subl({{ Rc.sl = Ra.sl - Rb_or_imm.sl; }});
- 0x49: sublv({{
- uint32_t tmp = Ra.sl - Rb_or_imm.sl;
- // signed overflow detection is same as for add,
- // except we need to look at the *complemented*
- // sign bit of the subtrahend (Rb), i.e., if the initial
- // signs are the *same* then no overflow can occur
- if (Ra.sl<31:> != Rb_or_imm.sl<31:> && tmp<31:> != Ra.sl<31:>)
- fault = new IntegerOverflowFault;
- Rc.sl = tmp;
- }});
- 0x0b: s4subl({{ Rc.sl = (Ra.sl << 2) - Rb_or_imm.sl; }});
- 0x1b: s8subl({{ Rc.sl = (Ra.sl << 3) - Rb_or_imm.sl; }});
-
- 0x29: subq({{ Rc = Ra - Rb_or_imm; }});
- 0x69: subqv({{
- uint64_t tmp = Ra - Rb_or_imm;
- // signed overflow detection is same as for add,
- // except we need to look at the *complemented*
- // sign bit of the subtrahend (Rb), i.e., if the initial
- // signs are the *same* then no overflow can occur
- if (Ra<63:> != Rb_or_imm<63:> && tmp<63:> != Ra<63:>)
- fault = new IntegerOverflowFault;
- Rc = tmp;
- }});
- 0x2b: s4subq({{ Rc = (Ra << 2) - Rb_or_imm; }});
- 0x3b: s8subq({{ Rc = (Ra << 3) - Rb_or_imm; }});
-
- 0x2d: cmpeq({{ Rc = (Ra == Rb_or_imm); }});
- 0x6d: cmple({{ Rc = (Ra.sq <= Rb_or_imm.sq); }});
- 0x4d: cmplt({{ Rc = (Ra.sq < Rb_or_imm.sq); }});
- 0x3d: cmpule({{ Rc = (Ra.uq <= Rb_or_imm.uq); }});
- 0x1d: cmpult({{ Rc = (Ra.uq < Rb_or_imm.uq); }});
-
- 0x0f: cmpbge({{
- int hi = 7;
- int lo = 0;
- uint64_t tmp = 0;
- for (int i = 0; i < 8; ++i) {
- tmp |= (Ra.uq<hi:lo> >= Rb_or_imm.uq<hi:lo>) << i;
- hi += 8;
- lo += 8;
- }
- Rc = tmp;
- }});
- }
-
- 0x11: decode INTFUNC { // integer logical operations
-
- 0x00: and({{ Rc = Ra & Rb_or_imm; }});
- 0x08: bic({{ Rc = Ra & ~Rb_or_imm; }});
- 0x20: bis({{ Rc = Ra | Rb_or_imm; }});
- 0x28: ornot({{ Rc = Ra | ~Rb_or_imm; }});
- 0x40: xor({{ Rc = Ra ^ Rb_or_imm; }});
- 0x48: eqv({{ Rc = Ra ^ ~Rb_or_imm; }});
-
- // conditional moves
- 0x14: cmovlbs({{ Rc = ((Ra & 1) == 1) ? Rb_or_imm : Rc; }});
- 0x16: cmovlbc({{ Rc = ((Ra & 1) == 0) ? Rb_or_imm : Rc; }});
- 0x24: cmoveq({{ Rc = (Ra == 0) ? Rb_or_imm : Rc; }});
- 0x26: cmovne({{ Rc = (Ra != 0) ? Rb_or_imm : Rc; }});
- 0x44: cmovlt({{ Rc = (Ra.sq < 0) ? Rb_or_imm : Rc; }});
- 0x46: cmovge({{ Rc = (Ra.sq >= 0) ? Rb_or_imm : Rc; }});
- 0x64: cmovle({{ Rc = (Ra.sq <= 0) ? Rb_or_imm : Rc; }});
- 0x66: cmovgt({{ Rc = (Ra.sq > 0) ? Rb_or_imm : Rc; }});
-
- // For AMASK, RA must be R31.
- 0x61: decode RA {
- 31: amask({{ Rc = Rb_or_imm & ~ULL(0x17); }});
- }
-
- // For IMPLVER, RA must be R31 and the B operand
- // must be the immediate value 1.
- 0x6c: decode RA {
- 31: decode IMM {
- 1: decode INTIMM {
- // return EV5 for FULL_SYSTEM and EV6 otherwise
- 1: implver({{
-#if FULL_SYSTEM
- Rc = 1;
-#else
- Rc = 2;
-#endif
- }});
- }
- }
- }
-
-#if FULL_SYSTEM
- // The mysterious 11.25...
- 0x25: WarnUnimpl::eleven25();
-#endif
- }
-
- 0x12: decode INTFUNC {
- 0x39: sll({{ Rc = Ra << Rb_or_imm<5:0>; }});
- 0x34: srl({{ Rc = Ra.uq >> Rb_or_imm<5:0>; }});
- 0x3c: sra({{ Rc = Ra.sq >> Rb_or_imm<5:0>; }});
-
- 0x02: mskbl({{ Rc = Ra & ~(mask( 8) << (Rb_or_imm<2:0> * 8)); }});
- 0x12: mskwl({{ Rc = Ra & ~(mask(16) << (Rb_or_imm<2:0> * 8)); }});
- 0x22: mskll({{ Rc = Ra & ~(mask(32) << (Rb_or_imm<2:0> * 8)); }});
- 0x32: mskql({{ Rc = Ra & ~(mask(64) << (Rb_or_imm<2:0> * 8)); }});
-
- 0x52: mskwh({{
- int bv = Rb_or_imm<2:0>;
- Rc = bv ? (Ra & ~(mask(16) >> (64 - 8 * bv))) : Ra;
- }});
- 0x62: msklh({{
- int bv = Rb_or_imm<2:0>;
- Rc = bv ? (Ra & ~(mask(32) >> (64 - 8 * bv))) : Ra;
- }});
- 0x72: mskqh({{
- int bv = Rb_or_imm<2:0>;
- Rc = bv ? (Ra & ~(mask(64) >> (64 - 8 * bv))) : Ra;
- }});
-
- 0x06: extbl({{ Rc = (Ra.uq >> (Rb_or_imm<2:0> * 8))< 7:0>; }});
- 0x16: extwl({{ Rc = (Ra.uq >> (Rb_or_imm<2:0> * 8))<15:0>; }});
- 0x26: extll({{ Rc = (Ra.uq >> (Rb_or_imm<2:0> * 8))<31:0>; }});
- 0x36: extql({{ Rc = (Ra.uq >> (Rb_or_imm<2:0> * 8)); }});
-
- 0x5a: extwh({{
- Rc = (Ra << (64 - (Rb_or_imm<2:0> * 8))<5:0>)<15:0>; }});
- 0x6a: extlh({{
- Rc = (Ra << (64 - (Rb_or_imm<2:0> * 8))<5:0>)<31:0>; }});
- 0x7a: extqh({{
- Rc = (Ra << (64 - (Rb_or_imm<2:0> * 8))<5:0>); }});
-
- 0x0b: insbl({{ Rc = Ra< 7:0> << (Rb_or_imm<2:0> * 8); }});
- 0x1b: inswl({{ Rc = Ra<15:0> << (Rb_or_imm<2:0> * 8); }});
- 0x2b: insll({{ Rc = Ra<31:0> << (Rb_or_imm<2:0> * 8); }});
- 0x3b: insql({{ Rc = Ra << (Rb_or_imm<2:0> * 8); }});
-
- 0x57: inswh({{
- int bv = Rb_or_imm<2:0>;
- Rc = bv ? (Ra.uq<15:0> >> (64 - 8 * bv)) : 0;
- }});
- 0x67: inslh({{
- int bv = Rb_or_imm<2:0>;
- Rc = bv ? (Ra.uq<31:0> >> (64 - 8 * bv)) : 0;
- }});
- 0x77: insqh({{
- int bv = Rb_or_imm<2:0>;
- Rc = bv ? (Ra.uq >> (64 - 8 * bv)) : 0;
- }});
-
- 0x30: zap({{
- uint64_t zapmask = 0;
- for (int i = 0; i < 8; ++i) {
- if (Rb_or_imm<i:>)
- zapmask |= (mask(8) << (i * 8));
- }
- Rc = Ra & ~zapmask;
- }});
- 0x31: zapnot({{
- uint64_t zapmask = 0;
- for (int i = 0; i < 8; ++i) {
- if (!Rb_or_imm<i:>)
- zapmask |= (mask(8) << (i * 8));
- }
- Rc = Ra & ~zapmask;
- }});
- }
-
- 0x13: decode INTFUNC { // integer multiplies
- 0x00: mull({{ Rc.sl = Ra.sl * Rb_or_imm.sl; }}, IntMultOp);
- 0x20: mulq({{ Rc = Ra * Rb_or_imm; }}, IntMultOp);
- 0x30: umulh({{
- uint64_t hi, lo;
- mul128(Ra, Rb_or_imm, hi, lo);
- Rc = hi;
- }}, IntMultOp);
- 0x40: mullv({{
- // 32-bit multiply with trap on overflow
- int64_t Rax = Ra.sl; // sign extended version of Ra.sl
- int64_t Rbx = Rb_or_imm.sl;
- int64_t tmp = Rax * Rbx;
- // To avoid overflow, all the upper 32 bits must match
- // the sign bit of the lower 32. We code this as
- // checking the upper 33 bits for all 0s or all 1s.
- uint64_t sign_bits = tmp<63:31>;
- if (sign_bits != 0 && sign_bits != mask(33))
- fault = new IntegerOverflowFault;
- Rc.sl = tmp<31:0>;
- }}, IntMultOp);
- 0x60: mulqv({{
- // 64-bit multiply with trap on overflow
- uint64_t hi, lo;
- mul128(Ra, Rb_or_imm, hi, lo);
- // all the upper 64 bits must match the sign bit of
- // the lower 64
- if (!((hi == 0 && lo<63:> == 0) ||
- (hi == mask(64) && lo<63:> == 1)))
- fault = new IntegerOverflowFault;
- Rc = lo;
- }}, IntMultOp);
- }
-
- 0x1c: decode INTFUNC {
- 0x00: decode RA { 31: sextb({{ Rc.sb = Rb_or_imm< 7:0>; }}); }
- 0x01: decode RA { 31: sextw({{ Rc.sw = Rb_or_imm<15:0>; }}); }
- 0x32: ctlz({{
- uint64_t count = 0;
- uint64_t temp = Rb;
- if (temp<63:32>) temp >>= 32; else count += 32;
- if (temp<31:16>) temp >>= 16; else count += 16;
- if (temp<15:8>) temp >>= 8; else count += 8;
- if (temp<7:4>) temp >>= 4; else count += 4;
- if (temp<3:2>) temp >>= 2; else count += 2;
- if (temp<1:1>) temp >>= 1; else count += 1;
- if ((temp<0:0>) != 0x1) count += 1;
- Rc = count;
- }}, IntAluOp);
-
- 0x33: cttz({{
- uint64_t count = 0;
- uint64_t temp = Rb;
- if (!(temp<31:0>)) { temp >>= 32; count += 32; }
- if (!(temp<15:0>)) { temp >>= 16; count += 16; }
- if (!(temp<7:0>)) { temp >>= 8; count += 8; }
- if (!(temp<3:0>)) { temp >>= 4; count += 4; }
- if (!(temp<1:0>)) { temp >>= 2; count += 2; }
- if (!(temp<0:0> & ULL(0x1))) count += 1;
- Rc = count;
- }}, IntAluOp);
-
- format FailUnimpl {
- 0x30: ctpop();
- 0x31: perr();
- 0x34: unpkbw();
- 0x35: unpkbl();
- 0x36: pkwb();
- 0x37: pklb();
- 0x38: minsb8();
- 0x39: minsw4();
- 0x3a: minub8();
- 0x3b: minuw4();
- 0x3c: maxub8();
- 0x3d: maxuw4();
- 0x3e: maxsb8();
- 0x3f: maxsw4();
- }
-
- format BasicOperateWithNopCheck {
- 0x70: decode RB {
- 31: ftoit({{ Rc = Fa.uq; }}, FloatCvtOp);
- }
- 0x78: decode RB {
- 31: ftois({{ Rc.sl = t_to_s(Fa.uq); }},
- FloatCvtOp);
- }
- }
- }
- }
-
- // Conditional branches.
- format CondBranch {
- 0x39: beq({{ cond = (Ra == 0); }});
- 0x3d: bne({{ cond = (Ra != 0); }});
- 0x3e: bge({{ cond = (Ra.sq >= 0); }});
- 0x3f: bgt({{ cond = (Ra.sq > 0); }});
- 0x3b: ble({{ cond = (Ra.sq <= 0); }});
- 0x3a: blt({{ cond = (Ra.sq < 0); }});
- 0x38: blbc({{ cond = ((Ra & 1) == 0); }});
- 0x3c: blbs({{ cond = ((Ra & 1) == 1); }});
-
- 0x31: fbeq({{ cond = (Fa == 0); }});
- 0x35: fbne({{ cond = (Fa != 0); }});
- 0x36: fbge({{ cond = (Fa >= 0); }});
- 0x37: fbgt({{ cond = (Fa > 0); }});
- 0x33: fble({{ cond = (Fa <= 0); }});
- 0x32: fblt({{ cond = (Fa < 0); }});
- }
-
- // unconditional branches
- format UncondBranch {
- 0x30: br();
- 0x34: bsr(IsCall);
- }
-
- // indirect branches
- 0x1a: decode JMPFUNC {
- format Jump {
- 0: jmp();
- 1: jsr(IsCall);
- 2: ret(IsReturn);
- 3: jsr_coroutine(IsCall, IsReturn);
- }
- }
-
- // Square root and integer-to-FP moves
- 0x14: decode FP_SHORTFUNC {
- // Integer to FP register moves must have RB == 31
- 0x4: decode RB {
- 31: decode FP_FULLFUNC {
- format BasicOperateWithNopCheck {
- 0x004: itofs({{ Fc.uq = s_to_t(Ra.ul); }}, FloatCvtOp);
- 0x024: itoft({{ Fc.uq = Ra.uq; }}, FloatCvtOp);
- 0x014: FailUnimpl::itoff(); // VAX-format conversion
- }
- }
- }
-
- // Square root instructions must have FA == 31
- 0xb: decode FA {
- 31: decode FP_TYPEFUNC {
- format FloatingPointOperate {
-#if SS_COMPATIBLE_FP
- 0x0b: sqrts({{
- if (Fb < 0.0)
- fault = new ArithmeticFault;
- Fc = sqrt(Fb);
- }}, FloatSqrtOp);
-#else
- 0x0b: sqrts({{
- if (Fb.sf < 0.0)
- fault = new ArithmeticFault;
- Fc.sf = sqrt(Fb.sf);
- }}, FloatSqrtOp);
-#endif
- 0x2b: sqrtt({{
- if (Fb < 0.0)
- fault = new ArithmeticFault;
- Fc = sqrt(Fb);
- }}, FloatSqrtOp);
- }
- }
- }
-
- // VAX-format sqrtf and sqrtg are not implemented
- 0xa: FailUnimpl::sqrtfg();
- }
-
- // IEEE floating point
- 0x16: decode FP_SHORTFUNC_TOP2 {
- // The top two bits of the short function code break this
- // space into four groups: binary ops, compares, reserved, and
- // conversions. See Table 4-12 of AHB. There are different
- // special cases in these different groups, so we decode on
- // these top two bits first just to select a decode strategy.
- // Most of these instructions may have various trapping and
- // rounding mode flags set; these are decoded in the
- // FloatingPointDecode template used by the
- // FloatingPointOperate format.
-
- // add/sub/mul/div: just decode on the short function code
- // and source type. All valid trapping and rounding modes apply.
- 0: decode FP_TRAPMODE {
- // check for valid trapping modes here
- 0,1,5,7: decode FP_TYPEFUNC {
- format FloatingPointOperate {
-#if SS_COMPATIBLE_FP
- 0x00: adds({{ Fc = Fa + Fb; }});
- 0x01: subs({{ Fc = Fa - Fb; }});
- 0x02: muls({{ Fc = Fa * Fb; }}, FloatMultOp);
- 0x03: divs({{ Fc = Fa / Fb; }}, FloatDivOp);
-#else
- 0x00: adds({{ Fc.sf = Fa.sf + Fb.sf; }});
- 0x01: subs({{ Fc.sf = Fa.sf - Fb.sf; }});
- 0x02: muls({{ Fc.sf = Fa.sf * Fb.sf; }}, FloatMultOp);
- 0x03: divs({{ Fc.sf = Fa.sf / Fb.sf; }}, FloatDivOp);
-#endif
-
- 0x20: addt({{ Fc = Fa + Fb; }});
- 0x21: subt({{ Fc = Fa - Fb; }});
- 0x22: mult({{ Fc = Fa * Fb; }}, FloatMultOp);
- 0x23: divt({{ Fc = Fa / Fb; }}, FloatDivOp);
- }
- }
- }
-
- // Floating-point compare instructions must have the default
- // rounding mode, and may use the default trapping mode or
- // /SU. Both trapping modes are treated the same by M5; the
- // only difference on the real hardware (as far a I can tell)
- // is that without /SU you'd get an imprecise trap if you
- // tried to compare a NaN with something else (instead of an
- // "unordered" result).
- 1: decode FP_FULLFUNC {
- format BasicOperateWithNopCheck {
- 0x0a5, 0x5a5: cmpteq({{ Fc = (Fa == Fb) ? 2.0 : 0.0; }},
- FloatCmpOp);
- 0x0a7, 0x5a7: cmptle({{ Fc = (Fa <= Fb) ? 2.0 : 0.0; }},
- FloatCmpOp);
- 0x0a6, 0x5a6: cmptlt({{ Fc = (Fa < Fb) ? 2.0 : 0.0; }},
- FloatCmpOp);
- 0x0a4, 0x5a4: cmptun({{ // unordered
- Fc = (!(Fa < Fb) && !(Fa == Fb) && !(Fa > Fb)) ? 2.0 : 0.0;
- }}, FloatCmpOp);
- }
- }
-
- // The FP-to-integer and integer-to-FP conversion insts
- // require that FA be 31.
- 3: decode FA {
- 31: decode FP_TYPEFUNC {
- format FloatingPointOperate {
- 0x2f: decode FP_ROUNDMODE {
- format FPFixedRounding {
- // "chopped" i.e. round toward zero
- 0: cvttq({{ Fc.sq = (int64_t)trunc(Fb); }},
- Chopped);
- // round to minus infinity
- 1: cvttq({{ Fc.sq = (int64_t)floor(Fb); }},
- MinusInfinity);
- }
- default: cvttq({{ Fc.sq = (int64_t)nearbyint(Fb); }});
- }
-
- // The cvtts opcode is overloaded to be cvtst if the trap
- // mode is 2 or 6 (which are not valid otherwise)
- 0x2c: decode FP_FULLFUNC {
- format BasicOperateWithNopCheck {
- // trap on denorm version "cvtst/s" is
- // simulated same as cvtst
- 0x2ac, 0x6ac: cvtst({{ Fc = Fb.sf; }});
- }
- default: cvtts({{ Fc.sf = Fb; }});
- }
-
- // The trapping mode for integer-to-FP conversions
- // must be /SUI or nothing; /U and /SU are not
- // allowed. The full set of rounding modes are
- // supported though.
- 0x3c: decode FP_TRAPMODE {
- 0,7: cvtqs({{ Fc.sf = Fb.sq; }});
- }
- 0x3e: decode FP_TRAPMODE {
- 0,7: cvtqt({{ Fc = Fb.sq; }});
- }
- }
- }
- }
- }
-
- // misc FP operate
- 0x17: decode FP_FULLFUNC {
- format BasicOperateWithNopCheck {
- 0x010: cvtlq({{
- Fc.sl = (Fb.uq<63:62> << 30) | Fb.uq<58:29>;
- }});
- 0x030: cvtql({{
- Fc.uq = (Fb.uq<31:30> << 62) | (Fb.uq<29:0> << 29);
- }});
-
- // We treat the precise & imprecise trapping versions of
- // cvtql identically.
- 0x130, 0x530: cvtqlv({{
- // To avoid overflow, all the upper 32 bits must match
- // the sign bit of the lower 32. We code this as
- // checking the upper 33 bits for all 0s or all 1s.
- uint64_t sign_bits = Fb.uq<63:31>;
- if (sign_bits != 0 && sign_bits != mask(33))
- fault = new IntegerOverflowFault;
- Fc.uq = (Fb.uq<31:30> << 62) | (Fb.uq<29:0> << 29);
- }});
-
- 0x020: cpys({{ // copy sign
- Fc.uq = (Fa.uq<63:> << 63) | Fb.uq<62:0>;
- }});
- 0x021: cpysn({{ // copy sign negated
- Fc.uq = (~Fa.uq<63:> << 63) | Fb.uq<62:0>;
- }});
- 0x022: cpyse({{ // copy sign and exponent
- Fc.uq = (Fa.uq<63:52> << 52) | Fb.uq<51:0>;
- }});
-
- 0x02a: fcmoveq({{ Fc = (Fa == 0) ? Fb : Fc; }});
- 0x02b: fcmovne({{ Fc = (Fa != 0) ? Fb : Fc; }});
- 0x02c: fcmovlt({{ Fc = (Fa < 0) ? Fb : Fc; }});
- 0x02d: fcmovge({{ Fc = (Fa >= 0) ? Fb : Fc; }});
- 0x02e: fcmovle({{ Fc = (Fa <= 0) ? Fb : Fc; }});
- 0x02f: fcmovgt({{ Fc = (Fa > 0) ? Fb : Fc; }});
-
- 0x024: mt_fpcr({{ FPCR = Fa.uq; }}, IsIprAccess);
- 0x025: mf_fpcr({{ Fa.uq = FPCR; }}, IsIprAccess);
- }
- }
-
- // miscellaneous mem-format ops
- 0x18: decode MEMFUNC {
- format WarnUnimpl {
- 0x8000: fetch();
- 0xa000: fetch_m();
- 0xe800: ecb();
- }
-
- format MiscPrefetch {
- 0xf800: wh64({{ EA = Rb & ~ULL(63); }},
- {{ xc->writeHint(EA, 64, memAccessFlags); }},
- mem_flags = NO_FAULT,
- inst_flags = [IsMemRef, IsDataPrefetch,
- IsStore, MemWriteOp]);
- }
-
- format BasicOperate {
- 0xc000: rpcc({{
-#if FULL_SYSTEM
- /* Rb is a fake dependency so here is a fun way to get
- * the parser to understand that.
- */
- Ra = xc->readMiscRegWithEffect(AlphaISA::IPR_CC, fault) + (Rb & 0);
-
-#else
- Ra = curTick;
-#endif
- }}, IsUnverifiable);
-
- // All of the barrier instructions below do nothing in
- // their execute() methods (hence the empty code blocks).
- // All of their functionality is hard-coded in the
- // pipeline based on the flags IsSerializing,
- // IsMemBarrier, and IsWriteBarrier. In the current
- // detailed CPU model, the execute() function only gets
- // called at fetch, so there's no way to generate pipeline
- // behavior at any other stage. Once we go to an
- // exec-in-exec CPU model we should be able to get rid of
- // these flags and implement this behavior via the
- // execute() methods.
-
- // trapb is just a barrier on integer traps, where excb is
- // a barrier on integer and FP traps. "EXCB is thus a
- // superset of TRAPB." (Alpha ARM, Sec 4.11.4) We treat
- // them the same though.
- 0x0000: trapb({{ }}, IsSerializing, IsSerializeBefore, No_OpClass);
- 0x0400: excb({{ }}, IsSerializing, IsSerializeBefore, No_OpClass);
- 0x4000: mb({{ }}, IsMemBarrier, MemReadOp);
- 0x4400: wmb({{ }}, IsWriteBarrier, MemWriteOp);
- }
-
-#if FULL_SYSTEM
- format BasicOperate {
- 0xe000: rc({{
- Ra = xc->readIntrFlag();
- xc->setIntrFlag(0);
- }}, IsNonSpeculative);
- 0xf000: rs({{
- Ra = xc->readIntrFlag();
- xc->setIntrFlag(1);
- }}, IsNonSpeculative);
- }
-#else
- format FailUnimpl {
- 0xe000: rc();
- 0xf000: rs();
- }
-#endif
- }
-
-#if FULL_SYSTEM
- 0x00: CallPal::call_pal({{
- if (!palValid ||
- (palPriv
- && xc->readMiscRegWithEffect(AlphaISA::IPR_ICM, fault) != AlphaISA::mode_kernel)) {
- // invalid pal function code, or attempt to do privileged
- // PAL call in non-kernel mode
- fault = new UnimplementedOpcodeFault;
- }
- else {
- // check to see if simulator wants to do something special
- // on this PAL call (including maybe suppress it)
- bool dopal = xc->simPalCheck(palFunc);
-
- if (dopal) {
- xc->setMiscRegWithEffect(AlphaISA::IPR_EXC_ADDR, NPC);
- NPC = xc->readMiscRegWithEffect(AlphaISA::IPR_PAL_BASE, fault) + palOffset;
- }
- }
- }}, IsNonSpeculative);
-#else
- 0x00: decode PALFUNC {
- format EmulatedCallPal {
- 0x00: halt ({{
- SimExit(curTick, "halt instruction encountered");
- }}, IsNonSpeculative);
- 0x83: callsys({{
- xc->syscall();
- }}, IsNonSpeculative);
- // Read uniq reg into ABI return value register (r0)
- 0x9e: rduniq({{ R0 = Runiq; }}, IsIprAccess);
- // Write uniq reg with value from ABI arg register (r16)
- 0x9f: wruniq({{ Runiq = R16; }}, IsIprAccess);
- }
- }
-#endif
-
-#if FULL_SYSTEM
- 0x1b: decode PALMODE {
- 0: OpcdecFault::hw_st_quad();
- 1: decode HW_LDST_QUAD {
- format HwLoad {
- 0: hw_ld({{ EA = (Rb + disp) & ~3; }}, {{ Ra = Mem.ul; }}, L);
- 1: hw_ld({{ EA = (Rb + disp) & ~7; }}, {{ Ra = Mem.uq; }}, Q);
- }
- }
- }
-
- 0x1f: decode PALMODE {
- 0: OpcdecFault::hw_st_cond();
- format HwStore {
- 1: decode HW_LDST_COND {
- 0: decode HW_LDST_QUAD {
- 0: hw_st({{ EA = (Rb + disp) & ~3; }},
- {{ Mem.ul = Ra<31:0>; }}, L);
- 1: hw_st({{ EA = (Rb + disp) & ~7; }},
- {{ Mem.uq = Ra.uq; }}, Q);
- }
-
- 1: FailUnimpl::hw_st_cond();
- }
- }
- }
-
- 0x19: decode PALMODE {
- 0: OpcdecFault::hw_mfpr();
- format HwMoveIPR {
- 1: hw_mfpr({{
- Ra = xc->readMiscRegWithEffect(ipr_index, fault);
- }}, IsIprAccess);
- }
- }
-
- 0x1d: decode PALMODE {
- 0: OpcdecFault::hw_mtpr();
- format HwMoveIPR {
- 1: hw_mtpr({{
- xc->setMiscRegWithEffect(ipr_index, Ra);
- if (traceData) { traceData->setData(Ra); }
- }}, IsIprAccess);
- }
- }
-
- format BasicOperate {
- 0x1e: decode PALMODE {
- 0: OpcdecFault::hw_rei();
- 1:hw_rei({{ xc->hwrei(); }}, IsSerializing, IsSerializeBefore);
- }
-
- // M5 special opcodes use the reserved 0x01 opcode space
- 0x01: decode M5FUNC {
- 0x00: arm({{
- AlphaPseudo::arm(xc->xcBase());
- }}, IsNonSpeculative);
- 0x01: quiesce({{
- AlphaPseudo::quiesce(xc->xcBase());
- }}, IsNonSpeculative, IsQuiesce);
- 0x02: quiesceNs({{
- AlphaPseudo::quiesceNs(xc->xcBase(), R16);
- }}, IsNonSpeculative, IsQuiesce);
- 0x03: quiesceCycles({{
- AlphaPseudo::quiesceCycles(xc->xcBase(), R16);
- }}, IsNonSpeculative, IsQuiesce);
- 0x04: quiesceTime({{
- R0 = AlphaPseudo::quiesceTime(xc->xcBase());
- }}, IsNonSpeculative);
- 0x10: ivlb({{
- AlphaPseudo::ivlb(xc->xcBase());
- }}, No_OpClass, IsNonSpeculative);
- 0x11: ivle({{
- AlphaPseudo::ivle(xc->xcBase());
- }}, No_OpClass, IsNonSpeculative);
- 0x20: m5exit_old({{
- AlphaPseudo::m5exit_old(xc->xcBase());
- }}, No_OpClass, IsNonSpeculative);
- 0x21: m5exit({{
- AlphaPseudo::m5exit(xc->xcBase(), R16);
- }}, No_OpClass, IsNonSpeculative);
- 0x30: initparam({{ Ra = xc->xcBase()->getCpuPtr()->system->init_param; }});
- 0x40: resetstats({{
- AlphaPseudo::resetstats(xc->xcBase(), R16, R17);
- }}, IsNonSpeculative);
- 0x41: dumpstats({{
- AlphaPseudo::dumpstats(xc->xcBase(), R16, R17);
- }}, IsNonSpeculative);
- 0x42: dumpresetstats({{
- AlphaPseudo::dumpresetstats(xc->xcBase(), R16, R17);
- }}, IsNonSpeculative);
- 0x43: m5checkpoint({{
- AlphaPseudo::m5checkpoint(xc->xcBase(), R16, R17);
- }}, IsNonSpeculative);
- 0x50: m5readfile({{
- R0 = AlphaPseudo::readfile(xc->xcBase(), R16, R17, R18);
- }}, IsNonSpeculative);
- 0x51: m5break({{
- AlphaPseudo::debugbreak(xc->xcBase());
- }}, IsNonSpeculative);
- 0x52: m5switchcpu({{
- AlphaPseudo::switchcpu(xc->xcBase());
- }}, IsNonSpeculative);
- 0x53: m5addsymbol({{
- AlphaPseudo::addsymbol(xc->xcBase(), R16, R17);
- }}, IsNonSpeculative);
- 0x54: m5panic({{
- panic("M5 panic instruction called at pc=%#x.", xc->readPC());
- }}, IsNonSpeculative);
-
- }
- }
-#endif
-}
diff --git a/arch/alpha/isa/fp.isa b/arch/alpha/isa/fp.isa
deleted file mode 100644
index f34c13c42..000000000
--- a/arch/alpha/isa/fp.isa
+++ /dev/null
@@ -1,301 +0,0 @@
-// -*- mode:c++ -*-
-
-// Copyright (c) 2003-2005 The Regents of The University of Michigan
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met: redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer;
-// redistributions in binary form must reproduce the above copyright
-// notice, this list of conditions and the following disclaimer in the
-// documentation and/or other materials provided with the distribution;
-// neither the name of the copyright holders nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-output exec {{
- /// Check "FP enabled" machine status bit. Called when executing any FP
- /// instruction in full-system mode.
- /// @retval Full-system mode: NoFault if FP is enabled, FenFault
- /// if not. Non-full-system mode: always returns NoFault.
-#if FULL_SYSTEM
- inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc)
- {
- Fault fault = NoFault; // dummy... this ipr access should not fault
- if (!EV5::ICSR_FPE(xc->readMiscRegWithEffect(AlphaISA::IPR_ICSR, fault))) {
- fault = new FloatEnableFault;
- }
- return fault;
- }
-#else
- inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc)
- {
- return NoFault;
- }
-#endif
-}};
-
-output header {{
- /**
- * Base class for general floating-point instructions. Includes
- * support for various Alpha rounding and trapping modes. Only FP
- * instructions that require this support are derived from this
- * class; the rest derive directly from AlphaStaticInst.
- */
- class AlphaFP : public AlphaStaticInst
- {
- public:
- /// Alpha FP rounding modes.
- enum RoundingMode {
- Chopped = 0, ///< round toward zero
- Minus_Infinity = 1, ///< round toward minus infinity
- Normal = 2, ///< round to nearest (default)
- Dynamic = 3, ///< use FPCR setting (in instruction)
- Plus_Infinity = 3 ///< round to plus inifinity (in FPCR)
- };
-
- /// Alpha FP trapping modes.
- /// For instructions that produce integer results, the
- /// "Underflow Enable" modes really mean "Overflow Enable", and
- /// the assembly modifier is V rather than U.
- enum TrappingMode {
- /// default: nothing enabled
- Imprecise = 0, ///< no modifier
- /// underflow/overflow traps enabled, inexact disabled
- Underflow_Imprecise = 1, ///< /U or /V
- Underflow_Precise = 5, ///< /SU or /SV
- /// underflow/overflow and inexact traps enabled
- Underflow_Inexact_Precise = 7 ///< /SUI or /SVI
- };
-
- protected:
- /// Map Alpha rounding mode to C99 constants from <fenv.h>.
- static const int alphaToC99RoundingMode[];
-
- /// Map enum RoundingMode values to disassembly suffixes.
- static const char *roundingModeSuffix[];
- /// Map enum TrappingMode values to FP disassembly suffixes.
- static const char *fpTrappingModeSuffix[];
- /// Map enum TrappingMode values to integer disassembly suffixes.
- static const char *intTrappingModeSuffix[];
-
- /// This instruction's rounding mode.
- RoundingMode roundingMode;
- /// This instruction's trapping mode.
- TrappingMode trappingMode;
-
- /// Have we warned about this instruction's unsupported
- /// rounding mode (if applicable)?
- mutable bool warnedOnRounding;
-
- /// Have we warned about this instruction's unsupported
- /// trapping mode (if applicable)?
- mutable bool warnedOnTrapping;
-
- /// Constructor
- AlphaFP(const char *mnem, ExtMachInst _machInst, OpClass __opClass)
- : AlphaStaticInst(mnem, _machInst, __opClass),
- roundingMode((enum RoundingMode)FP_ROUNDMODE),
- trappingMode((enum TrappingMode)FP_TRAPMODE),
- warnedOnRounding(false),
- warnedOnTrapping(false)
- {
- }
-
- int getC99RoundingMode(uint64_t fpcr_val) const;
-
- // This differs from the AlphaStaticInst version only in
- // printing suffixes for non-default rounding & trapping modes.
- std::string
- generateDisassembly(Addr pc, const SymbolTable *symtab) const;
- };
-
-}};
-
-
-output decoder {{
- int
- AlphaFP::getC99RoundingMode(uint64_t fpcr_val) const
- {
- if (roundingMode == Dynamic) {
- return alphaToC99RoundingMode[bits(fpcr_val, 59, 58)];
- }
- else {
- return alphaToC99RoundingMode[roundingMode];
- }
- }
-
- std::string
- AlphaFP::generateDisassembly(Addr pc, const SymbolTable *symtab) const
- {
- std::string mnem_str(mnemonic);
-
-#ifndef SS_COMPATIBLE_DISASSEMBLY
- std::string suffix("");
- suffix += ((_destRegIdx[0] >= FP_Base_DepTag)
- ? fpTrappingModeSuffix[trappingMode]
- : intTrappingModeSuffix[trappingMode]);
- suffix += roundingModeSuffix[roundingMode];
-
- if (suffix != "") {
- mnem_str = csprintf("%s/%s", mnemonic, suffix);
- }
-#endif
-
- std::stringstream ss;
- ccprintf(ss, "%-10s ", mnem_str.c_str());
-
- // just print the first two source regs... if there's
- // a third one, it's a read-modify-write dest (Rc),
- // e.g. for CMOVxx
- if (_numSrcRegs > 0) {
- printReg(ss, _srcRegIdx[0]);
- }
- if (_numSrcRegs > 1) {
- ss << ",";
- printReg(ss, _srcRegIdx[1]);
- }
-
- // just print the first dest... if there's a second one,
- // it's generally implicit
- if (_numDestRegs > 0) {
- if (_numSrcRegs > 0)
- ss << ",";
- printReg(ss, _destRegIdx[0]);
- }
-
- return ss.str();
- }
-
- const int AlphaFP::alphaToC99RoundingMode[] = {
- FE_TOWARDZERO, // Chopped
- FE_DOWNWARD, // Minus_Infinity
- FE_TONEAREST, // Normal
- FE_UPWARD // Dynamic in inst, Plus_Infinity in FPCR
- };
-
- const char *AlphaFP::roundingModeSuffix[] = { "c", "m", "", "d" };
- // mark invalid trapping modes, but don't fail on them, because
- // you could decode anything on a misspeculated path
- const char *AlphaFP::fpTrappingModeSuffix[] =
- { "", "u", "INVTM2", "INVTM3", "INVTM4", "su", "INVTM6", "sui" };
- const char *AlphaFP::intTrappingModeSuffix[] =
- { "", "v", "INVTM2", "INVTM3", "INVTM4", "sv", "INVTM6", "svi" };
-}};
-
-// FP instruction class execute method template. Handles non-standard
-// rounding modes.
-def template FloatingPointExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
- Trace::InstRecord *traceData) const
- {
- if (trappingMode != Imprecise && !warnedOnTrapping) {
- warn("%s: non-standard trapping mode not supported",
- generateDisassembly(0, NULL));
- warnedOnTrapping = true;
- }
-
- Fault fault = NoFault;
-
- %(fp_enable_check)s;
- %(op_decl)s;
- %(op_rd)s;
-#if USE_FENV
- if (roundingMode == Normal) {
- %(code)s;
- } else {
- fesetround(getC99RoundingMode(
- xc->readMiscReg(AlphaISA::Fpcr_DepTag)));
- %(code)s;
- fesetround(FE_TONEAREST);
- }
-#else
- if (roundingMode != Normal && !warnedOnRounding) {
- warn("%s: non-standard rounding mode not supported",
- generateDisassembly(0, NULL));
- warnedOnRounding = true;
- }
- %(code)s;
-#endif
-
- if (fault == NoFault) {
- %(op_wb)s;
- }
-
- return fault;
- }
-}};
-
-// FP instruction class execute method template where no dynamic
-// rounding mode control is needed. Like BasicExecute, but includes
-// check & warning for non-standard trapping mode.
-def template FPFixedRoundingExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
- Trace::InstRecord *traceData) const
- {
- if (trappingMode != Imprecise && !warnedOnTrapping) {
- warn("%s: non-standard trapping mode not supported",
- generateDisassembly(0, NULL));
- warnedOnTrapping = true;
- }
-
- Fault fault = NoFault;
-
- %(fp_enable_check)s;
- %(op_decl)s;
- %(op_rd)s;
- %(code)s;
-
- if (fault == NoFault) {
- %(op_wb)s;
- }
-
- return fault;
- }
-}};
-
-def template FloatingPointDecode {{
- {
- AlphaStaticInst *i = new %(class_name)s(machInst);
- if (FC == 31) {
- i = makeNop(i);
- }
- return i;
- }
-}};
-
-// General format for floating-point operate instructions:
-// - Checks trapping and rounding mode flags. Trapping modes
-// currently unimplemented (will fail).
-// - Generates NOP if FC == 31.
-def format FloatingPointOperate(code, *opt_args) {{
- iop = InstObjParams(name, Name, 'AlphaFP', CodeBlock(code), opt_args)
- decode_block = FloatingPointDecode.subst(iop)
- header_output = BasicDeclare.subst(iop)
- decoder_output = BasicConstructor.subst(iop)
- exec_output = FloatingPointExecute.subst(iop)
-}};
-
-// Special format for cvttq where rounding mode is pre-decoded
-def format FPFixedRounding(code, class_suffix, *opt_args) {{
- Name += class_suffix
- iop = InstObjParams(name, Name, 'AlphaFP', CodeBlock(code), opt_args)
- decode_block = FloatingPointDecode.subst(iop)
- header_output = BasicDeclare.subst(iop)
- decoder_output = BasicConstructor.subst(iop)
- exec_output = FPFixedRoundingExecute.subst(iop)
-}};
-
diff --git a/arch/alpha/isa/int.isa b/arch/alpha/isa/int.isa
deleted file mode 100644
index 17ecc1a51..000000000
--- a/arch/alpha/isa/int.isa
+++ /dev/null
@@ -1,128 +0,0 @@
-// -*- mode:c++ -*-
-
-// Copyright (c) 2003-2005 The Regents of The University of Michigan
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met: redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer;
-// redistributions in binary form must reproduce the above copyright
-// notice, this list of conditions and the following disclaimer in the
-// documentation and/or other materials provided with the distribution;
-// neither the name of the copyright holders nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-output header {{
- /**
- * Base class for integer immediate instructions.
- */
- class IntegerImm : public AlphaStaticInst
- {
- protected:
- /// Immediate operand value (unsigned 8-bit int).
- uint8_t imm;
-
- /// Constructor
- IntegerImm(const char *mnem, ExtMachInst _machInst, OpClass __opClass)
- : AlphaStaticInst(mnem, _machInst, __opClass), imm(INTIMM)
- {
- }
-
- std::string
- generateDisassembly(Addr pc, const SymbolTable *symtab) const;
- };
-}};
-
-output decoder {{
- std::string
- IntegerImm::generateDisassembly(Addr pc, const SymbolTable *symtab) const
- {
- std::stringstream ss;
-
- ccprintf(ss, "%-10s ", mnemonic);
-
- // just print the first source reg... if there's
- // a second one, it's a read-modify-write dest (Rc),
- // e.g. for CMOVxx
- if (_numSrcRegs > 0) {
- printReg(ss, _srcRegIdx[0]);
- ss << ",";
- }
-
- ss << (int)imm;
-
- if (_numDestRegs > 0) {
- ss << ",";
- printReg(ss, _destRegIdx[0]);
- }
-
- return ss.str();
- }
-}};
-
-
-def template RegOrImmDecode {{
- {
- AlphaStaticInst *i =
- (IMM) ? (AlphaStaticInst *)new %(class_name)sImm(machInst)
- : (AlphaStaticInst *)new %(class_name)s(machInst);
- if (RC == 31) {
- i = makeNop(i);
- }
- return i;
- }
-}};
-
-// Primary format for integer operate instructions:
-// - Generates both reg-reg and reg-imm versions if Rb_or_imm is used.
-// - Generates NOP if RC == 31.
-def format IntegerOperate(code, *opt_flags) {{
- # If the code block contains 'Rb_or_imm', we define two instructions,
- # one using 'Rb' and one using 'imm', and have the decoder select
- # the right one.
- uses_imm = (code.find('Rb_or_imm') != -1)
- if uses_imm:
- orig_code = code
- # base code is reg version:
- # rewrite by substituting 'Rb' for 'Rb_or_imm'
- code = re.sub(r'Rb_or_imm', 'Rb', orig_code)
- # generate immediate version by substituting 'imm'
- # note that imm takes no extenstion, so we extend
- # the regexp to replace any extension as well
- imm_code = re.sub(r'Rb_or_imm(\.\w+)?', 'imm', orig_code)
-
- # generate declaration for register version
- cblk = CodeBlock(code)
- iop = InstObjParams(name, Name, 'AlphaStaticInst', cblk, opt_flags)
- header_output = BasicDeclare.subst(iop)
- decoder_output = BasicConstructor.subst(iop)
- exec_output = BasicExecute.subst(iop)
-
- if uses_imm:
- # append declaration for imm version
- imm_cblk = CodeBlock(imm_code)
- imm_iop = InstObjParams(name, Name + 'Imm', 'IntegerImm', imm_cblk,
- opt_flags)
- header_output += BasicDeclare.subst(imm_iop)
- decoder_output += BasicConstructor.subst(imm_iop)
- exec_output += BasicExecute.subst(imm_iop)
- # decode checks IMM bit to pick correct version
- decode_block = RegOrImmDecode.subst(iop)
- else:
- # no imm version: just check for nop
- decode_block = OperateNopCheckDecode.subst(iop)
-}};
diff --git a/arch/alpha/isa/main.isa b/arch/alpha/isa/main.isa
deleted file mode 100644
index 80a5e9ca1..000000000
--- a/arch/alpha/isa/main.isa
+++ /dev/null
@@ -1,448 +0,0 @@
-// -*- mode:c++ -*-
-
-// Copyright (c) 2003-2005 The Regents of The University of Michigan
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met: redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer;
-// redistributions in binary form must reproduce the above copyright
-// notice, this list of conditions and the following disclaimer in the
-// documentation and/or other materials provided with the distribution;
-// neither the name of the copyright holders nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-output header {{
-#include <sstream>
-#include <iostream>
-#include <iomanip>
-
-#include "config/ss_compatible_fp.hh"
-#include "cpu/static_inst.hh"
-#include "arch/alpha/faults.hh"
-#include "mem/mem_req.hh" // some constructors use MemReq flags
-}};
-
-output decoder {{
-#include "base/cprintf.hh"
-#include "base/fenv.hh"
-#include "base/loader/symtab.hh"
-#include "config/ss_compatible_fp.hh"
-#include "cpu/exec_context.hh" // for Jump::branchTarget()
-
-#include <math.h>
-
-using namespace AlphaISA;
-}};
-
-output exec {{
-#include <math.h>
-
-#if FULL_SYSTEM
-#include "sim/pseudo_inst.hh"
-#endif
-#include "base/fenv.hh"
-#include "config/ss_compatible_fp.hh"
-#include "cpu/base.hh"
-#include "cpu/exetrace.hh"
-#include "sim/sim_exit.hh"
-
-using namespace AlphaISA;
-}};
-
-////////////////////////////////////////////////////////////////////
-//
-// Namespace statement. Everything below this line will be in the
-// AlphaISAInst namespace.
-//
-
-
-namespace AlphaISA;
-
-////////////////////////////////////////////////////////////////////
-//
-// Bitfield definitions.
-//
-
-// Universal (format-independent) fields
-def bitfield PALMODE <32:32>;
-def bitfield OPCODE <31:26>;
-def bitfield RA <25:21>;
-def bitfield RB <20:16>;
-
-// Memory format
-def signed bitfield MEMDISP <15: 0>; // displacement
-def bitfield MEMFUNC <15: 0>; // function code (same field, unsigned)
-
-// Memory-format jumps
-def bitfield JMPFUNC <15:14>; // function code (disp<15:14>)
-def bitfield JMPHINT <13: 0>; // tgt Icache idx hint (disp<13:0>)
-
-// Branch format
-def signed bitfield BRDISP <20: 0>; // displacement
-
-// Integer operate format(s>;
-def bitfield INTIMM <20:13>; // integer immediate (literal)
-def bitfield IMM <12:12>; // immediate flag
-def bitfield INTFUNC <11: 5>; // function code
-def bitfield RC < 4: 0>; // dest reg
-
-// Floating-point operate format
-def bitfield FA <25:21>;
-def bitfield FB <20:16>;
-def bitfield FP_FULLFUNC <15: 5>; // complete function code
- def bitfield FP_TRAPMODE <15:13>; // trapping mode
- def bitfield FP_ROUNDMODE <12:11>; // rounding mode
- def bitfield FP_TYPEFUNC <10: 5>; // type+func: handiest for decoding
- def bitfield FP_SRCTYPE <10: 9>; // source reg type
- def bitfield FP_SHORTFUNC < 8: 5>; // short function code
- def bitfield FP_SHORTFUNC_TOP2 <8:7>; // top 2 bits of short func code
-def bitfield FC < 4: 0>; // dest reg
-
-// PALcode format
-def bitfield PALFUNC <25: 0>; // function code
-
-// EV5 PAL instructions:
-// HW_LD/HW_ST
-def bitfield HW_LDST_PHYS <15>; // address is physical
-def bitfield HW_LDST_ALT <14>; // use ALT_MODE IPR
-def bitfield HW_LDST_WRTCK <13>; // HW_LD only: fault if no write acc
-def bitfield HW_LDST_QUAD <12>; // size: 0=32b, 1=64b
-def bitfield HW_LDST_VPTE <11>; // HW_LD only: is PTE fetch
-def bitfield HW_LDST_LOCK <10>; // HW_LD only: is load locked
-def bitfield HW_LDST_COND <10>; // HW_ST only: is store conditional
-def signed bitfield HW_LDST_DISP <9:0>; // signed displacement
-
-// HW_REI
-def bitfield HW_REI_TYP <15:14>; // type: stalling vs. non-stallingk
-def bitfield HW_REI_MBZ <13: 0>; // must be zero
-
-// HW_MTPR/MW_MFPR
-def bitfield HW_IPR_IDX <15:0>; // IPR index
-
-// M5 instructions
-def bitfield M5FUNC <7:0>;
-
-def operand_types {{
- 'sb' : ('signed int', 8),
- 'ub' : ('unsigned int', 8),
- 'sw' : ('signed int', 16),
- 'uw' : ('unsigned int', 16),
- 'sl' : ('signed int', 32),
- 'ul' : ('unsigned int', 32),
- 'sq' : ('signed int', 64),
- 'uq' : ('unsigned int', 64),
- 'sf' : ('float', 32),
- 'df' : ('float', 64)
-}};
-
-def operands {{
- # Int regs default to unsigned, but code should not count on this.
- # For clarity, descriptions that depend on unsigned behavior should
- # explicitly specify '.uq'.
- 'Ra': ('IntReg', 'uq', 'PALMODE ? AlphaISA::reg_redir[RA] : RA',
- 'IsInteger', 1),
- 'Rb': ('IntReg', 'uq', 'PALMODE ? AlphaISA::reg_redir[RB] : RB',
- 'IsInteger', 2),
- 'Rc': ('IntReg', 'uq', 'PALMODE ? AlphaISA::reg_redir[RC] : RC',
- 'IsInteger', 3),
- 'Fa': ('FloatReg', 'df', 'FA', 'IsFloating', 1),
- 'Fb': ('FloatReg', 'df', 'FB', 'IsFloating', 2),
- 'Fc': ('FloatReg', 'df', 'FC', 'IsFloating', 3),
- 'Mem': ('Mem', 'uq', None, ('IsMemRef', 'IsLoad', 'IsStore'), 4),
- 'NPC': ('NPC', 'uq', None, ( None, None, 'IsControl' ), 4),
- 'Runiq': ('ControlReg', 'uq', 'TheISA::Uniq_DepTag', None, 1),
- 'FPCR': (' ControlReg', 'uq', 'TheISA::Fpcr_DepTag', None, 1),
- # The next two are hacks for non-full-system call-pal emulation
- 'R0': ('IntReg', 'uq', '0', None, 1),
- 'R16': ('IntReg', 'uq', '16', None, 1),
- 'R17': ('IntReg', 'uq', '17', None, 1),
- 'R18': ('IntReg', 'uq', '18', None, 1)
-}};
-
-////////////////////////////////////////////////////////////////////
-//
-// Basic instruction classes/templates/formats etc.
-//
-
-output header {{
-// uncomment the following to get SimpleScalar-compatible disassembly
-// (useful for diffing output traces).
-// #define SS_COMPATIBLE_DISASSEMBLY
-
- /**
- * Base class for all Alpha static instructions.
- */
- class AlphaStaticInst : public StaticInst
- {
- protected:
-
- /// Make AlphaISA register dependence tags directly visible in
- /// this class and derived classes. Maybe these should really
- /// live here and not in the AlphaISA namespace.
- enum DependenceTags {
- FP_Base_DepTag = AlphaISA::FP_Base_DepTag,
- Fpcr_DepTag = AlphaISA::Fpcr_DepTag,
- Uniq_DepTag = AlphaISA::Uniq_DepTag,
- Lock_Flag_DepTag = AlphaISA::Lock_Flag_DepTag,
- Lock_Addr_DepTag = AlphaISA::Lock_Addr_DepTag,
- IPR_Base_DepTag = AlphaISA::IPR_Base_DepTag
- };
-
- /// Constructor.
- AlphaStaticInst(const char *mnem, ExtMachInst _machInst,
- OpClass __opClass)
- : StaticInst(mnem, _machInst, __opClass)
- {
- }
-
- /// Print a register name for disassembly given the unique
- /// dependence tag number (FP or int).
- void printReg(std::ostream &os, int reg) const;
-
- std::string
- generateDisassembly(Addr pc, const SymbolTable *symtab) const;
- };
-}};
-
-output decoder {{
- void
- AlphaStaticInst::printReg(std::ostream &os, int reg) const
- {
- if (reg < FP_Base_DepTag) {
- ccprintf(os, "r%d", reg);
- }
- else {
- ccprintf(os, "f%d", reg - FP_Base_DepTag);
- }
- }
-
- std::string
- AlphaStaticInst::generateDisassembly(Addr pc,
- const SymbolTable *symtab) const
- {
- std::stringstream ss;
-
- ccprintf(ss, "%-10s ", mnemonic);
-
- // just print the first two source regs... if there's
- // a third one, it's a read-modify-write dest (Rc),
- // e.g. for CMOVxx
- if (_numSrcRegs > 0) {
- printReg(ss, _srcRegIdx[0]);
- }
- if (_numSrcRegs > 1) {
- ss << ",";
- printReg(ss, _srcRegIdx[1]);
- }
-
- // just print the first dest... if there's a second one,
- // it's generally implicit
- if (_numDestRegs > 0) {
- if (_numSrcRegs > 0)
- ss << ",";
- printReg(ss, _destRegIdx[0]);
- }
-
- return ss.str();
- }
-}};
-
-// Declarations for execute() methods.
-def template BasicExecDeclare {{
- Fault execute(%(CPU_exec_context)s *, Trace::InstRecord *) const;
-}};
-
-// Basic instruction class declaration template.
-def template BasicDeclare {{
- /**
- * Static instruction class for "%(mnemonic)s".
- */
- class %(class_name)s : public %(base_class)s
- {
- public:
- /// Constructor.
- %(class_name)s(ExtMachInst machInst);
-
- %(BasicExecDeclare)s
- };
-}};
-
-// Basic instruction class constructor template.
-def template BasicConstructor {{
- inline %(class_name)s::%(class_name)s(ExtMachInst machInst)
- : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
- {
- %(constructor)s;
- }
-}};
-
-// Basic instruction class execute method template.
-def template BasicExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
- Trace::InstRecord *traceData) const
- {
- Fault fault = NoFault;
-
- %(fp_enable_check)s;
- %(op_decl)s;
- %(op_rd)s;
- %(code)s;
-
- if (fault == NoFault) {
- %(op_wb)s;
- }
-
- return fault;
- }
-}};
-
-// Basic decode template.
-def template BasicDecode {{
- return new %(class_name)s(machInst);
-}};
-
-// Basic decode template, passing mnemonic in as string arg to constructor.
-def template BasicDecodeWithMnemonic {{
- return new %(class_name)s("%(mnemonic)s", machInst);
-}};
-
-// The most basic instruction format... used only for a few misc. insts
-def format BasicOperate(code, *flags) {{
- iop = InstObjParams(name, Name, 'AlphaStaticInst', CodeBlock(code), flags)
- header_output = BasicDeclare.subst(iop)
- decoder_output = BasicConstructor.subst(iop)
- decode_block = BasicDecode.subst(iop)
- exec_output = BasicExecute.subst(iop)
-}};
-
-
-
-////////////////////////////////////////////////////////////////////
-//
-// Nop
-//
-
-output header {{
- /**
- * Static instruction class for no-ops. This is a leaf class.
- */
- class Nop : public AlphaStaticInst
- {
- /// Disassembly of original instruction.
- const std::string originalDisassembly;
-
- public:
- /// Constructor
- Nop(const std::string _originalDisassembly, ExtMachInst _machInst)
- : AlphaStaticInst("nop", _machInst, No_OpClass),
- originalDisassembly(_originalDisassembly)
- {
- flags[IsNop] = true;
- }
-
- ~Nop() { }
-
- std::string
- generateDisassembly(Addr pc, const SymbolTable *symtab) const;
-
- %(BasicExecDeclare)s
- };
-
- /// Helper function for decoding nops. Substitute Nop object
- /// for original inst passed in as arg (and delete latter).
- static inline
- AlphaStaticInst *
- makeNop(AlphaStaticInst *inst)
- {
- AlphaStaticInst *nop = new Nop(inst->disassemble(0), inst->machInst);
- delete inst;
- return nop;
- }
-}};
-
-output decoder {{
- std::string Nop::generateDisassembly(Addr pc,
- const SymbolTable *symtab) const
- {
-#ifdef SS_COMPATIBLE_DISASSEMBLY
- return originalDisassembly;
-#else
- return csprintf("%-10s (%s)", "nop", originalDisassembly);
-#endif
- }
-}};
-
-output exec {{
- Fault
- Nop::execute(%(CPU_exec_context)s *, Trace::InstRecord *) const
- {
- return NoFault;
- }
-}};
-
-// integer & FP operate instructions use Rc as dest, so check for
-// Rc == 31 to detect nops
-def template OperateNopCheckDecode {{
- {
- AlphaStaticInst *i = new %(class_name)s(machInst);
- if (RC == 31) {
- i = makeNop(i);
- }
- return i;
- }
-}};
-
-// Like BasicOperate format, but generates NOP if RC/FC == 31
-def format BasicOperateWithNopCheck(code, *opt_args) {{
- iop = InstObjParams(name, Name, 'AlphaStaticInst', CodeBlock(code),
- opt_args)
- header_output = BasicDeclare.subst(iop)
- decoder_output = BasicConstructor.subst(iop)
- decode_block = OperateNopCheckDecode.subst(iop)
- exec_output = BasicExecute.subst(iop)
-}};
-
-// Integer instruction templates, formats, etc.
-##include "int.isa"
-
-// Floating-point instruction templates, formats, etc.
-##include "fp.isa"
-
-// Memory instruction templates, formats, etc.
-##include "mem.isa"
-
-// Branch/jump instruction templates, formats, etc.
-##include "branch.isa"
-
-// PAL instruction templates, formats, etc.
-##include "pal.isa"
-
-// Opcdec fault instruction templates, formats, etc.
-##include "opcdec.isa"
-
-// Unimplemented instruction templates, formats, etc.
-##include "unimp.isa"
-
-// Unknown instruction templates, formats, etc.
-##include "unknown.isa"
-
-// Execution utility functions
-##include "util.isa"
-
-// The actual decoder
-##include "decoder.isa"
diff --git a/arch/alpha/isa/mem.isa b/arch/alpha/isa/mem.isa
deleted file mode 100644
index 3c8b4f755..000000000
--- a/arch/alpha/isa/mem.isa
+++ /dev/null
@@ -1,702 +0,0 @@
-// -*- mode:c++ -*-
-
-// Copyright (c) 2003-2005 The Regents of The University of Michigan
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met: redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer;
-// redistributions in binary form must reproduce the above copyright
-// notice, this list of conditions and the following disclaimer in the
-// documentation and/or other materials provided with the distribution;
-// neither the name of the copyright holders nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-output header {{
- /**
- * Base class for general Alpha memory-format instructions.
- */
- class Memory : public AlphaStaticInst
- {
- protected:
-
- /// Memory request flags. See mem_req_base.hh.
- unsigned memAccessFlags;
- /// Pointer to EAComp object.
- const StaticInstPtr eaCompPtr;
- /// Pointer to MemAcc object.
- const StaticInstPtr memAccPtr;
-
- /// Constructor
- Memory(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
- StaticInstPtr _eaCompPtr = nullStaticInstPtr,
- StaticInstPtr _memAccPtr = nullStaticInstPtr)
- : AlphaStaticInst(mnem, _machInst, __opClass),
- memAccessFlags(0), eaCompPtr(_eaCompPtr), memAccPtr(_memAccPtr)
- {
- }
-
- std::string
- generateDisassembly(Addr pc, const SymbolTable *symtab) const;
-
- public:
-
- const StaticInstPtr &eaCompInst() const { return eaCompPtr; }
- const StaticInstPtr &memAccInst() const { return memAccPtr; }
- };
-
- /**
- * Base class for memory-format instructions using a 32-bit
- * displacement (i.e. most of them).
- */
- class MemoryDisp32 : public Memory
- {
- protected:
- /// Displacement for EA calculation (signed).
- int32_t disp;
-
- /// Constructor.
- MemoryDisp32(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
- StaticInstPtr _eaCompPtr = nullStaticInstPtr,
- StaticInstPtr _memAccPtr = nullStaticInstPtr)
- : Memory(mnem, _machInst, __opClass, _eaCompPtr, _memAccPtr),
- disp(MEMDISP)
- {
- }
- };
-
-
- /**
- * Base class for a few miscellaneous memory-format insts
- * that don't interpret the disp field: wh64, fetch, fetch_m, ecb.
- * None of these instructions has a destination register either.
- */
- class MemoryNoDisp : public Memory
- {
- protected:
- /// Constructor
- MemoryNoDisp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
- StaticInstPtr _eaCompPtr = nullStaticInstPtr,
- StaticInstPtr _memAccPtr = nullStaticInstPtr)
- : Memory(mnem, _machInst, __opClass, _eaCompPtr, _memAccPtr)
- {
- }
-
- std::string
- generateDisassembly(Addr pc, const SymbolTable *symtab) const;
- };
-}};
-
-
-output decoder {{
- std::string
- Memory::generateDisassembly(Addr pc, const SymbolTable *symtab) const
- {
- return csprintf("%-10s %c%d,%d(r%d)", mnemonic,
- flags[IsFloating] ? 'f' : 'r', RA, MEMDISP, RB);
- }
-
- std::string
- MemoryNoDisp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
- {
- return csprintf("%-10s (r%d)", mnemonic, RB);
- }
-}};
-
-def format LoadAddress(code) {{
- iop = InstObjParams(name, Name, 'MemoryDisp32', CodeBlock(code))
- header_output = BasicDeclare.subst(iop)
- decoder_output = BasicConstructor.subst(iop)
- decode_block = BasicDecode.subst(iop)
- exec_output = BasicExecute.subst(iop)
-}};
-
-
-def template LoadStoreDeclare {{
- /**
- * Static instruction class for "%(mnemonic)s".
- */
- class %(class_name)s : public %(base_class)s
- {
- protected:
-
- /**
- * "Fake" effective address computation class for "%(mnemonic)s".
- */
- class EAComp : public %(base_class)s
- {
- public:
- /// Constructor
- EAComp(ExtMachInst machInst);
-
- %(BasicExecDeclare)s
- };
-
- /**
- * "Fake" memory access instruction class for "%(mnemonic)s".
- */
- class MemAcc : public %(base_class)s
- {
- public:
- /// Constructor
- MemAcc(ExtMachInst machInst);
-
- %(BasicExecDeclare)s
- };
-
- public:
-
- /// Constructor.
- %(class_name)s(ExtMachInst machInst);
-
- %(BasicExecDeclare)s
-
- %(InitiateAccDeclare)s
-
- %(CompleteAccDeclare)s
- };
-}};
-
-
-def template InitiateAccDeclare {{
- Fault initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const;
-}};
-
-
-def template CompleteAccDeclare {{
- Fault completeAcc(uint8_t *, %(CPU_exec_context)s *, Trace::InstRecord *) const;
-}};
-
-
-def template LoadStoreConstructor {{
- /** TODO: change op_class to AddrGenOp or something (requires
- * creating new member of OpClass enum in op_class.hh, updating
- * config files, etc.). */
- inline %(class_name)s::EAComp::EAComp(ExtMachInst machInst)
- : %(base_class)s("%(mnemonic)s (EAComp)", machInst, IntAluOp)
- {
- %(ea_constructor)s;
- }
-
- inline %(class_name)s::MemAcc::MemAcc(ExtMachInst machInst)
- : %(base_class)s("%(mnemonic)s (MemAcc)", machInst, %(op_class)s)
- {
- %(memacc_constructor)s;
- }
-
- inline %(class_name)s::%(class_name)s(ExtMachInst machInst)
- : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
- new EAComp(machInst), new MemAcc(machInst))
- {
- %(constructor)s;
- }
-}};
-
-
-def template EACompExecute {{
- Fault
- %(class_name)s::EAComp::execute(%(CPU_exec_context)s *xc,
- Trace::InstRecord *traceData) const
- {
- Addr EA;
- Fault fault = NoFault;
-
- %(fp_enable_check)s;
- %(op_decl)s;
- %(op_rd)s;
- %(code)s;
-
- if (fault == NoFault) {
- %(op_wb)s;
- xc->setEA(EA);
- }
-
- return fault;
- }
-}};
-
-def template LoadMemAccExecute {{
- Fault
- %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
- Trace::InstRecord *traceData) const
- {
- Addr EA;
- Fault fault = NoFault;
-
- %(fp_enable_check)s;
- %(op_decl)s;
- %(op_rd)s;
- EA = xc->getEA();
-
- if (fault == NoFault) {
- fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags);
- %(code)s;
- }
-
- if (fault == NoFault) {
- %(op_wb)s;
- }
-
- return fault;
- }
-}};
-
-
-def template LoadExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
- Trace::InstRecord *traceData) const
- {
- Addr EA;
- Fault fault = NoFault;
-
- %(fp_enable_check)s;
- %(op_decl)s;
- %(op_rd)s;
- %(ea_code)s;
-
- if (fault == NoFault) {
- fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags);
- %(memacc_code)s;
- }
-
- if (fault == NoFault) {
- %(op_wb)s;
- }
-
- return fault;
- }
-}};
-
-
-def template LoadInitiateAcc {{
- Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
- Trace::InstRecord *traceData) const
- {
- Addr EA;
- Fault fault = NoFault;
-
- %(fp_enable_check)s;
- %(op_src_decl)s;
- %(op_rd)s;
- %(ea_code)s;
-
- if (fault == NoFault) {
- fault = xc->read(EA, (uint%(mem_acc_size)d_t &)Mem, memAccessFlags);
- }
-
- return fault;
- }
-}};
-
-
-def template LoadCompleteAcc {{
- Fault %(class_name)s::completeAcc(uint8_t *data,
- %(CPU_exec_context)s *xc,
- Trace::InstRecord *traceData) const
- {
- Fault fault = NoFault;
-
- %(fp_enable_check)s;
- %(op_src_decl)s;
- %(op_dest_decl)s;
-
- memcpy(&Mem, data, sizeof(Mem));
-
- if (fault == NoFault) {
- %(memacc_code)s;
- }
-
- if (fault == NoFault) {
- %(op_wb)s;
- }
-
- return fault;
- }
-}};
-
-
-def template StoreMemAccExecute {{
- Fault
- %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
- Trace::InstRecord *traceData) const
- {
- Addr EA;
- Fault fault = NoFault;
- uint64_t write_result = 0;
-
- %(fp_enable_check)s;
- %(op_decl)s;
- %(op_rd)s;
- EA = xc->getEA();
-
- if (fault == NoFault) {
- %(code)s;
- }
-
- if (fault == NoFault) {
- fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
- memAccessFlags, &write_result);
- if (traceData) { traceData->setData(Mem); }
- }
-
- if (fault == NoFault) {
- %(postacc_code)s;
- }
-
- if (fault == NoFault) {
- %(op_wb)s;
- }
-
- return fault;
- }
-}};
-
-
-def template StoreExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
- Trace::InstRecord *traceData) const
- {
- Addr EA;
- Fault fault = NoFault;
- uint64_t write_result = 0;
-
- %(fp_enable_check)s;
- %(op_decl)s;
- %(op_rd)s;
- %(ea_code)s;
-
- if (fault == NoFault) {
- %(memacc_code)s;
- }
-
- if (fault == NoFault) {
- fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
- memAccessFlags, &write_result);
- if (traceData) { traceData->setData(Mem); }
- }
-
- if (fault == NoFault) {
- %(postacc_code)s;
- }
-
- if (fault == NoFault) {
- %(op_wb)s;
- }
-
- return fault;
- }
-}};
-
-def template StoreInitiateAcc {{
- Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
- Trace::InstRecord *traceData) const
- {
- Addr EA;
- Fault fault = NoFault;
- uint64_t write_result = 0;
-
- %(fp_enable_check)s;
- %(op_src_decl)s;
- %(op_dest_decl)s;
- %(op_rd)s;
- %(ea_code)s;
-
- if (fault == NoFault) {
- %(memacc_code)s;
- }
-
- if (fault == NoFault) {
- fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
- memAccessFlags, &write_result);
- if (traceData) { traceData->setData(Mem); }
- }
-
- return fault;
- }
-}};
-
-
-def template StoreCompleteAcc {{
- Fault %(class_name)s::completeAcc(uint8_t *data,
- %(CPU_exec_context)s *xc,
- Trace::InstRecord *traceData) const
- {
- Fault fault = NoFault;
- uint64_t write_result = 0;
-
- %(fp_enable_check)s;
- %(op_dest_decl)s;
-
- memcpy(&write_result, data, sizeof(write_result));
-
- if (fault == NoFault) {
- %(postacc_code)s;
- }
-
- if (fault == NoFault) {
- %(op_wb)s;
- }
-
- return fault;
- }
-}};
-
-
-def template MiscMemAccExecute {{
- Fault %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
- Trace::InstRecord *traceData) const
- {
- Addr EA;
- Fault fault = NoFault;
-
- %(fp_enable_check)s;
- %(op_decl)s;
- %(op_rd)s;
- EA = xc->getEA();
-
- if (fault == NoFault) {
- %(code)s;
- }
-
- return NoFault;
- }
-}};
-
-def template MiscExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
- Trace::InstRecord *traceData) const
- {
- Addr EA;
- Fault fault = NoFault;
-
- %(fp_enable_check)s;
- %(op_decl)s;
- %(op_rd)s;
- %(ea_code)s;
-
- if (fault == NoFault) {
- %(memacc_code)s;
- }
-
- return NoFault;
- }
-}};
-
-def template MiscInitiateAcc {{
- Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
- Trace::InstRecord *traceData) const
- {
- panic("Misc instruction does not support split access method!");
- return NoFault;
- }
-}};
-
-
-def template MiscCompleteAcc {{
- Fault %(class_name)s::completeAcc(uint8_t *data,
- %(CPU_exec_context)s *xc,
- Trace::InstRecord *traceData) const
- {
- panic("Misc instruction does not support split access method!");
-
- return NoFault;
- }
-}};
-
-// load instructions use Ra as dest, so check for
-// Ra == 31 to detect nops
-def template LoadNopCheckDecode {{
- {
- AlphaStaticInst *i = new %(class_name)s(machInst);
- if (RA == 31) {
- i = makeNop(i);
- }
- return i;
- }
-}};
-
-
-// for some load instructions, Ra == 31 indicates a prefetch (not a nop)
-def template LoadPrefetchCheckDecode {{
- {
- if (RA != 31) {
- return new %(class_name)s(machInst);
- }
- else {
- return new %(class_name)sPrefetch(machInst);
- }
- }
-}};
-
-
-let {{
-def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
- postacc_code = '', base_class = 'MemoryDisp32',
- decode_template = BasicDecode, exec_template_base = ''):
- # Make sure flags are in lists (convert to lists if not).
- mem_flags = makeList(mem_flags)
- inst_flags = makeList(inst_flags)
-
- # add hook to get effective addresses into execution trace output.
- ea_code += '\nif (traceData) { traceData->setAddr(EA); }\n'
-
- # generate code block objects
- ea_cblk = CodeBlock(ea_code)
- memacc_cblk = CodeBlock(memacc_code)
- postacc_cblk = CodeBlock(postacc_code)
-
- # Some CPU models execute the memory operation as an atomic unit,
- # while others want to separate them into an effective address
- # computation and a memory access operation. As a result, we need
- # to generate three StaticInst objects. Note that the latter two
- # are nested inside the larger "atomic" one.
-
- # generate InstObjParams for EAComp object
- ea_iop = InstObjParams(name, Name, base_class, ea_cblk, inst_flags)
-
- # generate InstObjParams for MemAcc object
- memacc_iop = InstObjParams(name, Name, base_class, memacc_cblk, inst_flags)
- # in the split execution model, the MemAcc portion is responsible
- # for the post-access code.
- memacc_iop.postacc_code = postacc_cblk.code
-
- # generate InstObjParams for InitiateAcc, CompleteAcc object
- # The code used depends on the template being used
- if (exec_template_base == 'Load'):
- initiateacc_cblk = CodeBlock(ea_code + memacc_code)
- completeacc_cblk = CodeBlock(memacc_code + postacc_code)
- elif (exec_template_base == 'Store'):
- initiateacc_cblk = CodeBlock(ea_code + memacc_code)
- completeacc_cblk = CodeBlock(postacc_code)
- else:
- initiateacc_cblk = ''
- completeacc_cblk = ''
-
- initiateacc_iop = InstObjParams(name, Name, base_class, initiateacc_cblk,
- inst_flags)
-
- completeacc_iop = InstObjParams(name, Name, base_class, completeacc_cblk,
- inst_flags)
-
- if (exec_template_base == 'Load'):
- initiateacc_iop.ea_code = ea_cblk.code
- initiateacc_iop.memacc_code = memacc_cblk.code
- completeacc_iop.memacc_code = memacc_cblk.code
- completeacc_iop.postacc_code = postacc_cblk.code
- elif (exec_template_base == 'Store'):
- initiateacc_iop.ea_code = ea_cblk.code
- initiateacc_iop.memacc_code = memacc_cblk.code
- completeacc_iop.postacc_code = postacc_cblk.code
-
- # generate InstObjParams for unified execution
- cblk = CodeBlock(ea_code + memacc_code + postacc_code)
- iop = InstObjParams(name, Name, base_class, cblk, inst_flags)
-
- iop.ea_constructor = ea_cblk.constructor
- iop.ea_code = ea_cblk.code
- iop.memacc_constructor = memacc_cblk.constructor
- iop.memacc_code = memacc_cblk.code
- iop.postacc_code = postacc_cblk.code
-
- if mem_flags:
- s = '\n\tmemAccessFlags = ' + string.join(mem_flags, '|') + ';'
- iop.constructor += s
- memacc_iop.constructor += s
-
- # select templates
- memAccExecTemplate = eval(exec_template_base + 'MemAccExecute')
- fullExecTemplate = eval(exec_template_base + 'Execute')
- initiateAccTemplate = eval(exec_template_base + 'InitiateAcc')
- completeAccTemplate = eval(exec_template_base + 'CompleteAcc')
-
- # (header_output, decoder_output, decode_block, exec_output)
- return (LoadStoreDeclare.subst(iop), LoadStoreConstructor.subst(iop),
- decode_template.subst(iop),
- EACompExecute.subst(ea_iop)
- + memAccExecTemplate.subst(memacc_iop)
- + fullExecTemplate.subst(iop)
- + initiateAccTemplate.subst(initiateacc_iop)
- + completeAccTemplate.subst(completeacc_iop))
-}};
-
-
-def format LoadOrNop(memacc_code, ea_code = {{ EA = Rb + disp; }},
- mem_flags = [], inst_flags = []) {{
- (header_output, decoder_output, decode_block, exec_output) = \
- LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
- decode_template = LoadNopCheckDecode,
- exec_template_base = 'Load')
-}};
-
-
-// Note that the flags passed in apply only to the prefetch version
-def format LoadOrPrefetch(memacc_code, ea_code = {{ EA = Rb + disp; }},
- mem_flags = [], pf_flags = [], inst_flags = []) {{
- # declare the load instruction object and generate the decode block
- (header_output, decoder_output, decode_block, exec_output) = \
- LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
- decode_template = LoadPrefetchCheckDecode,
- exec_template_base = 'Load')
-
- # Declare the prefetch instruction object.
-
- # Make sure flag args are lists so we can mess with them.
- mem_flags = makeList(mem_flags)
- pf_flags = makeList(pf_flags)
- inst_flags = makeList(inst_flags)
-
- pf_mem_flags = mem_flags + pf_flags + ['NO_FAULT']
- pf_inst_flags = inst_flags + ['IsMemRef', 'IsLoad',
- 'IsDataPrefetch', 'MemReadOp']
-
- (pf_header_output, pf_decoder_output, _, pf_exec_output) = \
- LoadStoreBase(name, Name + 'Prefetch', ea_code,
- 'xc->prefetch(EA, memAccessFlags);',
- pf_mem_flags, pf_inst_flags, exec_template_base = 'Misc')
-
- header_output += pf_header_output
- decoder_output += pf_decoder_output
- exec_output += pf_exec_output
-}};
-
-
-def format Store(memacc_code, ea_code = {{ EA = Rb + disp; }},
- mem_flags = [], inst_flags = []) {{
- (header_output, decoder_output, decode_block, exec_output) = \
- LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
- exec_template_base = 'Store')
-}};
-
-
-def format StoreCond(memacc_code, postacc_code,
- ea_code = {{ EA = Rb + disp; }},
- mem_flags = [], inst_flags = []) {{
- (header_output, decoder_output, decode_block, exec_output) = \
- LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
- postacc_code, exec_template_base = 'Store')
-}};
-
-
-// Use 'MemoryNoDisp' as base: for wh64, fetch, ecb
-def format MiscPrefetch(ea_code, memacc_code,
- mem_flags = [], inst_flags = []) {{
- (header_output, decoder_output, decode_block, exec_output) = \
- LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
- base_class = 'MemoryNoDisp', exec_template_base = 'Misc')
-}};
-
-
diff --git a/arch/alpha/isa/opcdec.isa b/arch/alpha/isa/opcdec.isa
deleted file mode 100644
index bb2f91e5c..000000000
--- a/arch/alpha/isa/opcdec.isa
+++ /dev/null
@@ -1,72 +0,0 @@
-// -*- mode:c++ -*-
-
-// Copyright (c) 2003-2005 The Regents of The University of Michigan
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met: redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer;
-// redistributions in binary form must reproduce the above copyright
-// notice, this list of conditions and the following disclaimer in the
-// documentation and/or other materials provided with the distribution;
-// neither the name of the copyright holders nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-output header {{
- /**
- * Static instruction class for instructions that cause an OPCDEC fault
- * when executed. This is currently only for PAL mode instructions
- * executed in non-PAL mode.
- */
- class OpcdecFault : public AlphaStaticInst
- {
- public:
- /// Constructor
- OpcdecFault(ExtMachInst _machInst)
- : AlphaStaticInst("opcdec fault", _machInst, No_OpClass)
- {
- }
-
- %(BasicExecDeclare)s
-
- std::string
- generateDisassembly(Addr pc, const SymbolTable *symtab) const;
- };
-}};
-
-output decoder {{
- std::string
- OpcdecFault::generateDisassembly(Addr pc, const SymbolTable *symtab) const
- {
- return csprintf("%-10s (inst 0x%x, opcode 0x%x)",
- " OPCDEC fault", machInst, OPCODE);
- }
-}};
-
-output exec {{
- Fault
- OpcdecFault::execute(%(CPU_exec_context)s *xc,
- Trace::InstRecord *traceData) const
- {
- return new UnimplementedOpcodeFault;
- }
-}};
-
-def format OpcdecFault() {{
- decode_block = 'return new OpcdecFault(machInst);\n'
-}};
-
diff --git a/arch/alpha/isa/pal.isa b/arch/alpha/isa/pal.isa
deleted file mode 100644
index 63af56359..000000000
--- a/arch/alpha/isa/pal.isa
+++ /dev/null
@@ -1,273 +0,0 @@
-// -*- mode:c++ -*-
-
-// Copyright (c) 2003-2005 The Regents of The University of Michigan
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met: redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer;
-// redistributions in binary form must reproduce the above copyright
-// notice, this list of conditions and the following disclaimer in the
-// documentation and/or other materials provided with the distribution;
-// neither the name of the copyright holders nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-output header {{
- /**
- * Base class for emulated call_pal calls (used only in
- * non-full-system mode).
- */
- class EmulatedCallPal : public AlphaStaticInst
- {
- protected:
-
- /// Constructor.
- EmulatedCallPal(const char *mnem, ExtMachInst _machInst,
- OpClass __opClass)
- : AlphaStaticInst(mnem, _machInst, __opClass)
- {
- }
-
- std::string
- generateDisassembly(Addr pc, const SymbolTable *symtab) const;
- };
-}};
-
-output decoder {{
- std::string
- EmulatedCallPal::generateDisassembly(Addr pc,
- const SymbolTable *symtab) const
- {
-#ifdef SS_COMPATIBLE_DISASSEMBLY
- return csprintf("%s %s", "call_pal", mnemonic);
-#else
- return csprintf("%-10s %s", "call_pal", mnemonic);
-#endif
- }
-}};
-
-def format EmulatedCallPal(code, *flags) {{
- iop = InstObjParams(name, Name, 'EmulatedCallPal', CodeBlock(code), flags)
- header_output = BasicDeclare.subst(iop)
- decoder_output = BasicConstructor.subst(iop)
- decode_block = BasicDecode.subst(iop)
- exec_output = BasicExecute.subst(iop)
-}};
-
-output header {{
- /**
- * Base class for full-system-mode call_pal instructions.
- * Probably could turn this into a leaf class and get rid of the
- * parser template.
- */
- class CallPalBase : public AlphaStaticInst
- {
- protected:
- int palFunc; ///< Function code part of instruction
- int palOffset; ///< Target PC, offset from IPR_PAL_BASE
- bool palValid; ///< is the function code valid?
- bool palPriv; ///< is this call privileged?
-
- /// Constructor.
- CallPalBase(const char *mnem, ExtMachInst _machInst,
- OpClass __opClass);
-
- std::string
- generateDisassembly(Addr pc, const SymbolTable *symtab) const;
- };
-}};
-
-output decoder {{
- inline
- CallPalBase::CallPalBase(const char *mnem, ExtMachInst _machInst,
- OpClass __opClass)
- : AlphaStaticInst(mnem, _machInst, __opClass),
- palFunc(PALFUNC)
- {
- // From the 21164 HRM (paraphrased):
- // Bit 7 of the function code (mask 0x80) indicates
- // whether the call is privileged (bit 7 == 0) or
- // unprivileged (bit 7 == 1). The privileged call table
- // starts at 0x2000, the unprivielged call table starts at
- // 0x3000. Bits 5-0 (mask 0x3f) are used to calculate the
- // offset.
- const int palPrivMask = 0x80;
- const int palOffsetMask = 0x3f;
-
- // Pal call is invalid unless all other bits are 0
- palValid = ((machInst & ~(palPrivMask | palOffsetMask)) == 0);
- palPriv = ((machInst & palPrivMask) == 0);
- int shortPalFunc = (machInst & palOffsetMask);
- // Add 1 to base to set pal-mode bit
- palOffset = (palPriv ? 0x2001 : 0x3001) + (shortPalFunc << 6);
- }
-
- std::string
- CallPalBase::generateDisassembly(Addr pc, const SymbolTable *symtab) const
- {
- return csprintf("%-10s %#x", "call_pal", palFunc);
- }
-}};
-
-def format CallPal(code, *flags) {{
- iop = InstObjParams(name, Name, 'CallPalBase', CodeBlock(code), flags)
- header_output = BasicDeclare.subst(iop)
- decoder_output = BasicConstructor.subst(iop)
- decode_block = BasicDecode.subst(iop)
- exec_output = BasicExecute.subst(iop)
-}};
-
-////////////////////////////////////////////////////////////////////
-//
-// hw_ld, hw_st
-//
-
-output header {{
- /**
- * Base class for hw_ld and hw_st.
- */
- class HwLoadStore : public Memory
- {
- protected:
-
- /// Displacement for EA calculation (signed).
- int16_t disp;
-
- /// Constructor
- HwLoadStore(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
- StaticInstPtr _eaCompPtr = nullStaticInstPtr,
- StaticInstPtr _memAccPtr = nullStaticInstPtr);
-
- std::string
- generateDisassembly(Addr pc, const SymbolTable *symtab) const;
- };
-}};
-
-
-output decoder {{
- inline
- HwLoadStore::HwLoadStore(const char *mnem, ExtMachInst _machInst,
- OpClass __opClass,
- StaticInstPtr _eaCompPtr,
- StaticInstPtr _memAccPtr)
- : Memory(mnem, _machInst, __opClass, _eaCompPtr, _memAccPtr),
- disp(HW_LDST_DISP)
- {
- memAccessFlags = 0;
- if (HW_LDST_PHYS) memAccessFlags |= PHYSICAL;
- if (HW_LDST_ALT) memAccessFlags |= ALTMODE;
- if (HW_LDST_VPTE) memAccessFlags |= VPTE;
- if (HW_LDST_LOCK) memAccessFlags |= LOCKED;
- }
-
- std::string
- HwLoadStore::generateDisassembly(Addr pc, const SymbolTable *symtab) const
- {
-#ifdef SS_COMPATIBLE_DISASSEMBLY
- return csprintf("%-10s r%d,%d(r%d)", mnemonic, RA, disp, RB);
-#else
- // HW_LDST_LOCK and HW_LDST_COND are the same bit.
- const char *lock_str =
- (HW_LDST_LOCK) ? (flags[IsLoad] ? ",LOCK" : ",COND") : "";
-
- return csprintf("%-10s r%d,%d(r%d)%s%s%s%s%s",
- mnemonic, RA, disp, RB,
- HW_LDST_PHYS ? ",PHYS" : "",
- HW_LDST_ALT ? ",ALT" : "",
- HW_LDST_QUAD ? ",QUAD" : "",
- HW_LDST_VPTE ? ",VPTE" : "",
- lock_str);
-#endif
- }
-}};
-
-def format HwLoad(ea_code, memacc_code, class_ext, *flags) {{
- (header_output, decoder_output, decode_block, exec_output) = \
- LoadStoreBase(name, Name + class_ext, ea_code, memacc_code,
- mem_flags = [], inst_flags = flags,
- base_class = 'HwLoadStore', exec_template_base = 'Load')
-}};
-
-
-def format HwStore(ea_code, memacc_code, class_ext, *flags) {{
- (header_output, decoder_output, decode_block, exec_output) = \
- LoadStoreBase(name, Name + class_ext, ea_code, memacc_code,
- mem_flags = [], inst_flags = flags,
- base_class = 'HwLoadStore', exec_template_base = 'Store')
-}};
-
-
-def format HwStoreCond(ea_code, memacc_code, postacc_code, class_ext,
- *flags) {{
- (header_output, decoder_output, decode_block, exec_output) = \
- LoadStoreBase(name, Name + class_ext, ea_code, memacc_code,
- postacc_code, mem_flags = [], inst_flags = flags,
- base_class = 'HwLoadStore')
-}};
-
-
-output header {{
- /**
- * Base class for hw_mfpr and hw_mtpr.
- */
- class HwMoveIPR : public AlphaStaticInst
- {
- protected:
- /// Index of internal processor register.
- int ipr_index;
-
- /// Constructor
- HwMoveIPR(const char *mnem, ExtMachInst _machInst, OpClass __opClass)
- : AlphaStaticInst(mnem, _machInst, __opClass),
- ipr_index(HW_IPR_IDX)
- {
- }
-
- std::string
- generateDisassembly(Addr pc, const SymbolTable *symtab) const;
- };
-}};
-
-output decoder {{
- std::string
- HwMoveIPR::generateDisassembly(Addr pc, const SymbolTable *symtab) const
- {
- if (_numSrcRegs > 0) {
- // must be mtpr
- return csprintf("%-10s r%d,IPR(%#x)",
- mnemonic, RA, ipr_index);
- }
- else {
- // must be mfpr
- return csprintf("%-10s IPR(%#x),r%d",
- mnemonic, ipr_index, RA);
- }
- }
-}};
-
-def format HwMoveIPR(code, *flags) {{
- all_flags = ['IprAccessOp']
- all_flags += flags
- iop = InstObjParams(name, Name, 'HwMoveIPR', CodeBlock(code),
- all_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/alpha/isa/unimp.isa b/arch/alpha/isa/unimp.isa
deleted file mode 100644
index 392522801..000000000
--- a/arch/alpha/isa/unimp.isa
+++ /dev/null
@@ -1,165 +0,0 @@
-// -*- mode:c++ -*-
-
-// Copyright (c) 2003-2005 The Regents of The University of Michigan
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met: redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer;
-// redistributions in binary form must reproduce the above copyright
-// notice, this list of conditions and the following disclaimer in the
-// documentation and/or other materials provided with the distribution;
-// neither the name of the copyright holders nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-output header {{
- /**
- * Static instruction class for unimplemented instructions that
- * cause simulator termination. Note that these are recognized
- * (legal) instructions that the simulator does not support; the
- * 'Unknown' class is used for unrecognized/illegal instructions.
- * This is a leaf class.
- */
- class FailUnimplemented : public AlphaStaticInst
- {
- public:
- /// Constructor
- FailUnimplemented(const char *_mnemonic, ExtMachInst _machInst)
- : AlphaStaticInst(_mnemonic, _machInst, No_OpClass)
- {
- // don't call execute() (which panics) if we're on a
- // speculative path
- flags[IsNonSpeculative] = true;
- }
-
- %(BasicExecDeclare)s
-
- std::string
- generateDisassembly(Addr pc, const SymbolTable *symtab) const;
- };
-
- /**
- * Base class for unimplemented instructions that cause a warning
- * to be printed (but do not terminate simulation). This
- * implementation is a little screwy in that it will print a
- * warning for each instance of a particular unimplemented machine
- * instruction, not just for each unimplemented opcode. Should
- * probably make the 'warned' flag a static member of the derived
- * class.
- */
- class WarnUnimplemented : public AlphaStaticInst
- {
- private:
- /// Have we warned on this instruction yet?
- mutable bool warned;
-
- public:
- /// Constructor
- WarnUnimplemented(const char *_mnemonic, ExtMachInst _machInst)
- : AlphaStaticInst(_mnemonic, _machInst, No_OpClass), warned(false)
- {
- // don't call execute() (which panics) if we're on a
- // speculative path
- flags[IsNonSpeculative] = true;
- }
-
- %(BasicExecDeclare)s
-
- std::string
- generateDisassembly(Addr pc, const SymbolTable *symtab) const;
- };
-}};
-
-output decoder {{
- std::string
- FailUnimplemented::generateDisassembly(Addr pc,
- const SymbolTable *symtab) const
- {
- return csprintf("%-10s (unimplemented)", mnemonic);
- }
-
- std::string
- WarnUnimplemented::generateDisassembly(Addr pc,
- const SymbolTable *symtab) const
- {
-#ifdef SS_COMPATIBLE_DISASSEMBLY
- return csprintf("%-10s", mnemonic);
-#else
- return csprintf("%-10s (unimplemented)", mnemonic);
-#endif
- }
-}};
-
-output exec {{
- Fault
- FailUnimplemented::execute(%(CPU_exec_context)s *xc,
- Trace::InstRecord *traceData) const
- {
- panic("attempt to execute unimplemented instruction '%s' "
- "(inst 0x%08x, opcode 0x%x)", mnemonic, machInst, OPCODE);
- return new UnimplementedOpcodeFault;
- }
-
- Fault
- WarnUnimplemented::execute(%(CPU_exec_context)s *xc,
- Trace::InstRecord *traceData) const
- {
- if (!warned) {
- warn("instruction '%s' unimplemented\n", mnemonic);
- warned = true;
- }
-
- return NoFault;
- }
-}};
-
-
-def format FailUnimpl() {{
- iop = InstObjParams(name, 'FailUnimplemented')
- decode_block = BasicDecodeWithMnemonic.subst(iop)
-}};
-
-def format WarnUnimpl() {{
- iop = InstObjParams(name, 'WarnUnimplemented')
- decode_block = BasicDecodeWithMnemonic.subst(iop)
-}};
-
-output header {{
- /**
- * Static instruction class for unknown (illegal) instructions.
- * These cause simulator termination if they are executed in a
- * non-speculative mode. This is a leaf class.
- */
- class Unknown : public AlphaStaticInst
- {
- public:
- /// Constructor
- Unknown(ExtMachInst _machInst)
- : AlphaStaticInst("unknown", _machInst, No_OpClass)
- {
- // don't call execute() (which panics) if we're on a
- // speculative path
- flags[IsNonSpeculative] = true;
- }
-
- %(BasicExecDeclare)s
-
- std::string
- generateDisassembly(Addr pc, const SymbolTable *symtab) const;
- };
-}};
-
diff --git a/arch/alpha/isa/unknown.isa b/arch/alpha/isa/unknown.isa
deleted file mode 100644
index 47d166255..000000000
--- a/arch/alpha/isa/unknown.isa
+++ /dev/null
@@ -1,52 +0,0 @@
-// -*- mode:c++ -*-
-
-// Copyright (c) 2003-2005 The Regents of The University of Michigan
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met: redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer;
-// redistributions in binary form must reproduce the above copyright
-// notice, this list of conditions and the following disclaimer in the
-// documentation and/or other materials provided with the distribution;
-// neither the name of the copyright holders nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-output decoder {{
- std::string
- Unknown::generateDisassembly(Addr pc, const SymbolTable *symtab) const
- {
- return csprintf("%-10s (inst 0x%x, opcode 0x%x)",
- "unknown", machInst, OPCODE);
- }
-}};
-
-output exec {{
- Fault
- Unknown::execute(%(CPU_exec_context)s *xc,
- Trace::InstRecord *traceData) const
- {
- panic("attempt to execute unknown instruction "
- "(inst 0x%08x, opcode 0x%x)", machInst, OPCODE);
- return new UnimplementedOpcodeFault;
- }
-}};
-
-def format Unknown() {{
- decode_block = 'return new Unknown(machInst);\n'
-}};
-
diff --git a/arch/alpha/isa/util.isa b/arch/alpha/isa/util.isa
deleted file mode 100644
index 9fbbf6636..000000000
--- a/arch/alpha/isa/util.isa
+++ /dev/null
@@ -1,112 +0,0 @@
-// -*- mode:c++ -*-
-
-// Copyright (c) 2003-2005 The Regents of The University of Michigan
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met: redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer;
-// redistributions in binary form must reproduce the above copyright
-// notice, this list of conditions and the following disclaimer in the
-// documentation and/or other materials provided with the distribution;
-// neither the name of the copyright holders nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-output exec {{
-
- /// Return opa + opb, summing carry into third arg.
- inline uint64_t
- addc(uint64_t opa, uint64_t opb, int &carry)
- {
- uint64_t res = opa + opb;
- if (res < opa || res < opb)
- ++carry;
- return res;
- }
-
- /// Multiply two 64-bit values (opa * opb), returning the 128-bit
- /// product in res_hi and res_lo.
- inline void
- mul128(uint64_t opa, uint64_t opb, uint64_t &res_hi, uint64_t &res_lo)
- {
- // do a 64x64 --> 128 multiply using four 32x32 --> 64 multiplies
- uint64_t opa_hi = opa<63:32>;
- uint64_t opa_lo = opa<31:0>;
- uint64_t opb_hi = opb<63:32>;
- uint64_t opb_lo = opb<31:0>;
-
- res_lo = opa_lo * opb_lo;
-
- // The middle partial products logically belong in bit
- // positions 95 to 32. Thus the lower 32 bits of each product
- // sum into the upper 32 bits of the low result, while the
- // upper 32 sum into the low 32 bits of the upper result.
- uint64_t partial1 = opa_hi * opb_lo;
- uint64_t partial2 = opa_lo * opb_hi;
-
- uint64_t partial1_lo = partial1<31:0> << 32;
- uint64_t partial1_hi = partial1<63:32>;
- uint64_t partial2_lo = partial2<31:0> << 32;
- uint64_t partial2_hi = partial2<63:32>;
-
- // Add partial1_lo and partial2_lo to res_lo, keeping track
- // of any carries out
- int carry_out = 0;
- res_lo = addc(partial1_lo, res_lo, carry_out);
- res_lo = addc(partial2_lo, res_lo, carry_out);
-
- // Now calculate the high 64 bits...
- res_hi = (opa_hi * opb_hi) + partial1_hi + partial2_hi + carry_out;
- }
-
- /// Map 8-bit S-floating exponent to 11-bit T-floating exponent.
- /// See Table 2-2 of Alpha AHB.
- inline int
- map_s(int old_exp)
- {
- int hibit = old_exp<7:>;
- int lobits = old_exp<6:0>;
-
- if (hibit == 1) {
- return (lobits == 0x7f) ? 0x7ff : (0x400 | lobits);
- }
- else {
- return (lobits == 0) ? 0 : (0x380 | lobits);
- }
- }
-
- /// Convert a 32-bit S-floating value to the equivalent 64-bit
- /// representation to be stored in an FP reg.
- inline uint64_t
- s_to_t(uint32_t s_val)
- {
- uint64_t tmp = s_val;
- return (tmp<31:> << 63 // sign bit
- | (uint64_t)map_s(tmp<30:23>) << 52 // exponent
- | tmp<22:0> << 29); // fraction
- }
-
- /// Convert a 64-bit T-floating value to the equivalent 32-bit
- /// S-floating representation to be stored in memory.
- inline int32_t
- t_to_s(uint64_t t_val)
- {
- return (t_val<63:62> << 30 // sign bit & hi exp bit
- | t_val<58:29>); // rest of exp & fraction
- }
-}};
-
diff --git a/arch/alpha/isa_traits.hh b/arch/alpha/isa_traits.hh
deleted file mode 100644
index 878193881..000000000
--- a/arch/alpha/isa_traits.hh
+++ /dev/null
@@ -1,384 +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.
- */
-
-#ifndef __ARCH_ALPHA_ISA_TRAITS_HH__
-#define __ARCH_ALPHA_ISA_TRAITS_HH__
-
-namespace LittleEndianGuest {}
-using namespace LittleEndianGuest;
-
-//#include "arch/alpha/faults.hh"
-#include "base/misc.hh"
-#include "config/full_system.hh"
-#include "sim/host.hh"
-#include "sim/faults.hh"
-
-class ExecContext;
-class FastCPU;
-class FullCPU;
-class Checkpoint;
-
-#define TARGET_ALPHA
-
-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:
- template <class T>
- SyscallReturn(T v, bool s)
- {
- retval = (uint64_t)v;
- success = s;
- }
-
- template <class T>
- SyscallReturn(T v)
- {
- success = (v >= 0);
- retval = (uint64_t)v;
- }
-
- ~SyscallReturn() {}
-
- SyscallReturn& operator=(const SyscallReturn& s) {
- retval = s.retval;
- success = s.success;
- return *this;
- }
-
- bool successful() { return success; }
- uint64_t value() { return retval; }
-
-
- private:
- uint64_t retval;
- bool success;
-};
-
-#endif
-
-
-
-namespace AlphaISA
-{
-
- 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;
-
-// 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)
- {
- // check for error condition. Alpha syscall convention is to
- // indicate success/failure in reg a3 (r19) and put the
- // return value itself in the standard return value reg (v0).
- if (return_value.successful()) {
- // no error
- regs->intRegFile[SyscallSuccessReg] = 0;
- regs->intRegFile[ReturnValueReg] = return_value.value();
- } else {
- // got an error, return details
- regs->intRegFile[SyscallSuccessReg] = (IntReg) -1;
- regs->intRegFile[ReturnValueReg] = -return_value.value();
- }
- }
-#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/process.cc b/arch/alpha/linux/process.cc
deleted file mode 100644
index 1c911bc50..000000000
--- a/arch/alpha/linux/process.cc
+++ /dev/null
@@ -1,589 +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/alpha/linux/process.hh"
-#include "arch/alpha/isa_traits.hh"
-
-#include "base/trace.hh"
-#include "cpu/exec_context.hh"
-#include "kern/linux/linux.hh"
-#include "mem/functional/functional.hh"
-
-#include "sim/process.hh"
-#include "sim/syscall_emul.hh"
-
-using namespace std;
-using namespace AlphaISA;
-
-
-
-/// Target uname() handler.
-static SyscallReturn
-unameFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
-{
- TypedBufferArg<Linux::utsname> name(xc->getSyscallArg(0));
-
- strcpy(name->sysname, "Linux");
- strcpy(name->nodename, "m5.eecs.umich.edu");
- strcpy(name->release, "2.4.20");
- strcpy(name->version, "#1 Mon Aug 18 11:32:15 EDT 2003");
- strcpy(name->machine, "alpha");
-
- name.copyOut(xc->getMemPtr());
- return 0;
-}
-
-/// Target osf_getsysyinfo() handler. Even though this call is
-/// borrowed from Tru64, the subcases that get used appear to be
-/// different in practice from those used by Tru64 processes.
-static SyscallReturn
-osf_getsysinfoFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
-{
- unsigned op = xc->getSyscallArg(0);
- // unsigned nbytes = xc->getSyscallArg(2);
-
- switch (op) {
-
- case 45: { // GSI_IEEE_FP_CONTROL
- TypedBufferArg<uint64_t> fpcr(xc->getSyscallArg(1));
- // I don't think this exactly matches the HW FPCR
- *fpcr = 0;
- fpcr.copyOut(xc->getMemPtr());
- return 0;
- }
-
- default:
- cerr << "osf_getsysinfo: unknown op " << op << endl;
- abort();
- break;
- }
-
- return 1;
-}
-
-/// Target osf_setsysinfo() handler.
-static SyscallReturn
-osf_setsysinfoFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
-{
- unsigned op = xc->getSyscallArg(0);
- // unsigned nbytes = xc->getSyscallArg(2);
-
- switch (op) {
-
- case 14: { // SSI_IEEE_FP_CONTROL
- TypedBufferArg<uint64_t> fpcr(xc->getSyscallArg(1));
- // I don't think this exactly matches the HW FPCR
- fpcr.copyIn(xc->getMemPtr());
- DPRINTFR(SyscallVerbose, "osf_setsysinfo(SSI_IEEE_FP_CONTROL): "
- " setting FPCR to 0x%x\n", gtoh(*(uint64_t*)fpcr));
- return 0;
- }
-
- default:
- cerr << "osf_setsysinfo: unknown op " << op << endl;
- abort();
- break;
- }
-
- return 1;
-}
-
-
-SyscallDesc AlphaLinuxProcess::syscallDescs[] = {
- /* 0 */ SyscallDesc("osf_syscall", unimplementedFunc),
- /* 1 */ SyscallDesc("exit", exitFunc),
- /* 2 */ SyscallDesc("fork", unimplementedFunc),
- /* 3 */ SyscallDesc("read", readFunc),
- /* 4 */ SyscallDesc("write", writeFunc),
- /* 5 */ SyscallDesc("osf_old_open", unimplementedFunc),
- /* 6 */ SyscallDesc("close", closeFunc),
- /* 7 */ SyscallDesc("osf_wait4", unimplementedFunc),
- /* 8 */ SyscallDesc("osf_old_creat", unimplementedFunc),
- /* 9 */ SyscallDesc("link", unimplementedFunc),
- /* 10 */ SyscallDesc("unlink", unlinkFunc),
- /* 11 */ SyscallDesc("osf_execve", unimplementedFunc),
- /* 12 */ SyscallDesc("chdir", unimplementedFunc),
- /* 13 */ SyscallDesc("fchdir", unimplementedFunc),
- /* 14 */ SyscallDesc("mknod", unimplementedFunc),
- /* 15 */ SyscallDesc("chmod", chmodFunc<Linux>),
- /* 16 */ SyscallDesc("chown", chownFunc),
- /* 17 */ SyscallDesc("brk", obreakFunc),
- /* 18 */ SyscallDesc("osf_getfsstat", unimplementedFunc),
- /* 19 */ SyscallDesc("lseek", lseekFunc),
- /* 20 */ SyscallDesc("getxpid", getpidPseudoFunc),
- /* 21 */ SyscallDesc("osf_mount", unimplementedFunc),
- /* 22 */ SyscallDesc("umount", unimplementedFunc),
- /* 23 */ SyscallDesc("setuid", setuidFunc),
- /* 24 */ SyscallDesc("getxuid", getuidPseudoFunc),
- /* 25 */ SyscallDesc("exec_with_loader", unimplementedFunc),
- /* 26 */ SyscallDesc("osf_ptrace", unimplementedFunc),
- /* 27 */ SyscallDesc("osf_nrecvmsg", unimplementedFunc),
- /* 28 */ SyscallDesc("osf_nsendmsg", unimplementedFunc),
- /* 29 */ SyscallDesc("osf_nrecvfrom", unimplementedFunc),
- /* 30 */ SyscallDesc("osf_naccept", unimplementedFunc),
- /* 31 */ SyscallDesc("osf_ngetpeername", unimplementedFunc),
- /* 32 */ SyscallDesc("osf_ngetsockname", unimplementedFunc),
- /* 33 */ SyscallDesc("access", unimplementedFunc),
- /* 34 */ SyscallDesc("osf_chflags", unimplementedFunc),
- /* 35 */ SyscallDesc("osf_fchflags", unimplementedFunc),
- /* 36 */ SyscallDesc("sync", unimplementedFunc),
- /* 37 */ SyscallDesc("kill", unimplementedFunc),
- /* 38 */ SyscallDesc("osf_old_stat", unimplementedFunc),
- /* 39 */ SyscallDesc("setpgid", unimplementedFunc),
- /* 40 */ SyscallDesc("osf_old_lstat", unimplementedFunc),
- /* 41 */ SyscallDesc("dup", unimplementedFunc),
- /* 42 */ SyscallDesc("pipe", pipePseudoFunc),
- /* 43 */ SyscallDesc("osf_set_program_attributes", unimplementedFunc),
- /* 44 */ SyscallDesc("osf_profil", unimplementedFunc),
- /* 45 */ SyscallDesc("open", openFunc<Linux>),
- /* 46 */ SyscallDesc("osf_old_sigaction", unimplementedFunc),
- /* 47 */ SyscallDesc("getxgid", getgidPseudoFunc),
- /* 48 */ SyscallDesc("osf_sigprocmask", ignoreFunc),
- /* 49 */ SyscallDesc("osf_getlogin", unimplementedFunc),
- /* 50 */ SyscallDesc("osf_setlogin", unimplementedFunc),
- /* 51 */ SyscallDesc("acct", unimplementedFunc),
- /* 52 */ SyscallDesc("sigpending", unimplementedFunc),
- /* 53 */ SyscallDesc("osf_classcntl", unimplementedFunc),
- /* 54 */ SyscallDesc("ioctl", ioctlFunc<Linux>),
- /* 55 */ SyscallDesc("osf_reboot", unimplementedFunc),
- /* 56 */ SyscallDesc("osf_revoke", unimplementedFunc),
- /* 57 */ SyscallDesc("symlink", unimplementedFunc),
- /* 58 */ SyscallDesc("readlink", unimplementedFunc),
- /* 59 */ SyscallDesc("execve", unimplementedFunc),
- /* 60 */ SyscallDesc("umask", unimplementedFunc),
- /* 61 */ SyscallDesc("chroot", unimplementedFunc),
- /* 62 */ SyscallDesc("osf_old_fstat", unimplementedFunc),
- /* 63 */ SyscallDesc("getpgrp", unimplementedFunc),
- /* 64 */ SyscallDesc("getpagesize", getpagesizeFunc),
- /* 65 */ SyscallDesc("osf_mremap", unimplementedFunc),
- /* 66 */ SyscallDesc("vfork", unimplementedFunc),
- /* 67 */ SyscallDesc("stat", statFunc<Linux>),
- /* 68 */ SyscallDesc("lstat", lstatFunc<Linux>),
- /* 69 */ SyscallDesc("osf_sbrk", unimplementedFunc),
- /* 70 */ SyscallDesc("osf_sstk", unimplementedFunc),
- /* 71 */ SyscallDesc("mmap", mmapFunc<Linux>),
- /* 72 */ SyscallDesc("osf_old_vadvise", unimplementedFunc),
- /* 73 */ SyscallDesc("munmap", munmapFunc),
- /* 74 */ SyscallDesc("mprotect", ignoreFunc),
- /* 75 */ SyscallDesc("madvise", unimplementedFunc),
- /* 76 */ SyscallDesc("vhangup", unimplementedFunc),
- /* 77 */ SyscallDesc("osf_kmodcall", unimplementedFunc),
- /* 78 */ SyscallDesc("osf_mincore", unimplementedFunc),
- /* 79 */ SyscallDesc("getgroups", unimplementedFunc),
- /* 80 */ SyscallDesc("setgroups", unimplementedFunc),
- /* 81 */ SyscallDesc("osf_old_getpgrp", unimplementedFunc),
- /* 82 */ SyscallDesc("setpgrp", unimplementedFunc),
- /* 83 */ SyscallDesc("osf_setitimer", unimplementedFunc),
- /* 84 */ SyscallDesc("osf_old_wait", unimplementedFunc),
- /* 85 */ SyscallDesc("osf_table", unimplementedFunc),
- /* 86 */ SyscallDesc("osf_getitimer", unimplementedFunc),
- /* 87 */ SyscallDesc("gethostname", gethostnameFunc),
- /* 88 */ SyscallDesc("sethostname", unimplementedFunc),
- /* 89 */ SyscallDesc("getdtablesize", unimplementedFunc),
- /* 90 */ SyscallDesc("dup2", unimplementedFunc),
- /* 91 */ SyscallDesc("fstat", fstatFunc<Linux>),
- /* 92 */ SyscallDesc("fcntl", fcntlFunc),
- /* 93 */ SyscallDesc("osf_select", unimplementedFunc),
- /* 94 */ SyscallDesc("poll", unimplementedFunc),
- /* 95 */ SyscallDesc("fsync", unimplementedFunc),
- /* 96 */ SyscallDesc("setpriority", unimplementedFunc),
- /* 97 */ SyscallDesc("socket", unimplementedFunc),
- /* 98 */ SyscallDesc("connect", unimplementedFunc),
- /* 99 */ SyscallDesc("accept", unimplementedFunc),
- /* 100 */ SyscallDesc("getpriority", unimplementedFunc),
- /* 101 */ SyscallDesc("send", unimplementedFunc),
- /* 102 */ SyscallDesc("recv", unimplementedFunc),
- /* 103 */ SyscallDesc("sigreturn", unimplementedFunc),
- /* 104 */ SyscallDesc("bind", unimplementedFunc),
- /* 105 */ SyscallDesc("setsockopt", unimplementedFunc),
- /* 106 */ SyscallDesc("listen", unimplementedFunc),
- /* 107 */ SyscallDesc("osf_plock", unimplementedFunc),
- /* 108 */ SyscallDesc("osf_old_sigvec", unimplementedFunc),
- /* 109 */ SyscallDesc("osf_old_sigblock", unimplementedFunc),
- /* 110 */ SyscallDesc("osf_old_sigsetmask", unimplementedFunc),
- /* 111 */ SyscallDesc("sigsuspend", unimplementedFunc),
- /* 112 */ SyscallDesc("osf_sigstack", ignoreFunc),
- /* 113 */ SyscallDesc("recvmsg", unimplementedFunc),
- /* 114 */ SyscallDesc("sendmsg", unimplementedFunc),
- /* 115 */ SyscallDesc("osf_old_vtrace", unimplementedFunc),
- /* 116 */ SyscallDesc("osf_gettimeofday", unimplementedFunc),
- /* 117 */ SyscallDesc("osf_getrusage", unimplementedFunc),
- /* 118 */ SyscallDesc("getsockopt", unimplementedFunc),
- /* 119 */ SyscallDesc("numa_syscalls", unimplementedFunc),
- /* 120 */ SyscallDesc("readv", unimplementedFunc),
- /* 121 */ SyscallDesc("writev", writevFunc<Linux>),
- /* 122 */ SyscallDesc("osf_settimeofday", unimplementedFunc),
- /* 123 */ SyscallDesc("fchown", fchownFunc),
- /* 124 */ SyscallDesc("fchmod", fchmodFunc<Linux>),
- /* 125 */ SyscallDesc("recvfrom", unimplementedFunc),
- /* 126 */ SyscallDesc("setreuid", unimplementedFunc),
- /* 127 */ SyscallDesc("setregid", unimplementedFunc),
- /* 128 */ SyscallDesc("rename", renameFunc),
- /* 129 */ SyscallDesc("truncate", unimplementedFunc),
- /* 130 */ SyscallDesc("ftruncate", unimplementedFunc),
- /* 131 */ SyscallDesc("flock", unimplementedFunc),
- /* 132 */ SyscallDesc("setgid", unimplementedFunc),
- /* 133 */ SyscallDesc("sendto", unimplementedFunc),
- /* 134 */ SyscallDesc("shutdown", unimplementedFunc),
- /* 135 */ SyscallDesc("socketpair", unimplementedFunc),
- /* 136 */ SyscallDesc("mkdir", unimplementedFunc),
- /* 137 */ SyscallDesc("rmdir", unimplementedFunc),
- /* 138 */ SyscallDesc("osf_utimes", unimplementedFunc),
- /* 139 */ SyscallDesc("osf_old_sigreturn", unimplementedFunc),
- /* 140 */ SyscallDesc("osf_adjtime", unimplementedFunc),
- /* 141 */ SyscallDesc("getpeername", unimplementedFunc),
- /* 142 */ SyscallDesc("osf_gethostid", unimplementedFunc),
- /* 143 */ SyscallDesc("osf_sethostid", unimplementedFunc),
- /* 144 */ SyscallDesc("getrlimit", getrlimitFunc<Linux>),
- /* 145 */ SyscallDesc("setrlimit", ignoreFunc),
- /* 146 */ SyscallDesc("osf_old_killpg", unimplementedFunc),
- /* 147 */ SyscallDesc("setsid", unimplementedFunc),
- /* 148 */ SyscallDesc("quotactl", unimplementedFunc),
- /* 149 */ SyscallDesc("osf_oldquota", unimplementedFunc),
- /* 150 */ SyscallDesc("getsockname", unimplementedFunc),
- /* 151 */ SyscallDesc("osf_pread", unimplementedFunc),
- /* 152 */ SyscallDesc("osf_pwrite", unimplementedFunc),
- /* 153 */ SyscallDesc("osf_pid_block", unimplementedFunc),
- /* 154 */ SyscallDesc("osf_pid_unblock", unimplementedFunc),
- /* 155 */ SyscallDesc("osf_signal_urti", unimplementedFunc),
- /* 156 */ SyscallDesc("sigaction", ignoreFunc),
- /* 157 */ SyscallDesc("osf_sigwaitprim", unimplementedFunc),
- /* 158 */ SyscallDesc("osf_nfssvc", unimplementedFunc),
- /* 159 */ SyscallDesc("osf_getdirentries", unimplementedFunc),
- /* 160 */ SyscallDesc("osf_statfs", unimplementedFunc),
- /* 161 */ SyscallDesc("osf_fstatfs", unimplementedFunc),
- /* 162 */ SyscallDesc("unknown #162", unimplementedFunc),
- /* 163 */ SyscallDesc("osf_async_daemon", unimplementedFunc),
- /* 164 */ SyscallDesc("osf_getfh", unimplementedFunc),
- /* 165 */ SyscallDesc("osf_getdomainname", unimplementedFunc),
- /* 166 */ SyscallDesc("setdomainname", unimplementedFunc),
- /* 167 */ SyscallDesc("unknown #167", unimplementedFunc),
- /* 168 */ SyscallDesc("unknown #168", unimplementedFunc),
- /* 169 */ SyscallDesc("osf_exportfs", unimplementedFunc),
- /* 170 */ SyscallDesc("unknown #170", unimplementedFunc),
- /* 171 */ SyscallDesc("unknown #171", unimplementedFunc),
- /* 172 */ SyscallDesc("unknown #172", unimplementedFunc),
- /* 173 */ SyscallDesc("unknown #173", unimplementedFunc),
- /* 174 */ SyscallDesc("unknown #174", unimplementedFunc),
- /* 175 */ SyscallDesc("unknown #175", unimplementedFunc),
- /* 176 */ SyscallDesc("unknown #176", unimplementedFunc),
- /* 177 */ SyscallDesc("unknown #177", unimplementedFunc),
- /* 178 */ SyscallDesc("unknown #178", unimplementedFunc),
- /* 179 */ SyscallDesc("unknown #179", unimplementedFunc),
- /* 180 */ SyscallDesc("unknown #180", unimplementedFunc),
- /* 181 */ SyscallDesc("osf_alt_plock", unimplementedFunc),
- /* 182 */ SyscallDesc("unknown #182", unimplementedFunc),
- /* 183 */ SyscallDesc("unknown #183", unimplementedFunc),
- /* 184 */ SyscallDesc("osf_getmnt", unimplementedFunc),
- /* 185 */ SyscallDesc("unknown #185", unimplementedFunc),
- /* 186 */ SyscallDesc("unknown #186", unimplementedFunc),
- /* 187 */ SyscallDesc("osf_alt_sigpending", unimplementedFunc),
- /* 188 */ SyscallDesc("osf_alt_setsid", unimplementedFunc),
- /* 189 */ SyscallDesc("unknown #189", unimplementedFunc),
- /* 190 */ SyscallDesc("unknown #190", unimplementedFunc),
- /* 191 */ SyscallDesc("unknown #191", unimplementedFunc),
- /* 192 */ SyscallDesc("unknown #192", unimplementedFunc),
- /* 193 */ SyscallDesc("unknown #193", unimplementedFunc),
- /* 194 */ SyscallDesc("unknown #194", unimplementedFunc),
- /* 195 */ SyscallDesc("unknown #195", unimplementedFunc),
- /* 196 */ SyscallDesc("unknown #196", unimplementedFunc),
- /* 197 */ SyscallDesc("unknown #197", unimplementedFunc),
- /* 198 */ SyscallDesc("unknown #198", unimplementedFunc),
- /* 199 */ SyscallDesc("osf_swapon", unimplementedFunc),
- /* 200 */ SyscallDesc("msgctl", unimplementedFunc),
- /* 201 */ SyscallDesc("msgget", unimplementedFunc),
- /* 202 */ SyscallDesc("msgrcv", unimplementedFunc),
- /* 203 */ SyscallDesc("msgsnd", unimplementedFunc),
- /* 204 */ SyscallDesc("semctl", unimplementedFunc),
- /* 205 */ SyscallDesc("semget", unimplementedFunc),
- /* 206 */ SyscallDesc("semop", unimplementedFunc),
- /* 207 */ SyscallDesc("osf_utsname", unimplementedFunc),
- /* 208 */ SyscallDesc("lchown", unimplementedFunc),
- /* 209 */ SyscallDesc("osf_shmat", unimplementedFunc),
- /* 210 */ SyscallDesc("shmctl", unimplementedFunc),
- /* 211 */ SyscallDesc("shmdt", unimplementedFunc),
- /* 212 */ SyscallDesc("shmget", unimplementedFunc),
- /* 213 */ SyscallDesc("osf_mvalid", unimplementedFunc),
- /* 214 */ SyscallDesc("osf_getaddressconf", unimplementedFunc),
- /* 215 */ SyscallDesc("osf_msleep", unimplementedFunc),
- /* 216 */ SyscallDesc("osf_mwakeup", unimplementedFunc),
- /* 217 */ SyscallDesc("msync", unimplementedFunc),
- /* 218 */ SyscallDesc("osf_signal", unimplementedFunc),
- /* 219 */ SyscallDesc("osf_utc_gettime", unimplementedFunc),
- /* 220 */ SyscallDesc("osf_utc_adjtime", unimplementedFunc),
- /* 221 */ SyscallDesc("unknown #221", unimplementedFunc),
- /* 222 */ SyscallDesc("osf_security", unimplementedFunc),
- /* 223 */ SyscallDesc("osf_kloadcall", unimplementedFunc),
- /* 224 */ SyscallDesc("unknown #224", unimplementedFunc),
- /* 225 */ SyscallDesc("unknown #225", unimplementedFunc),
- /* 226 */ SyscallDesc("unknown #226", unimplementedFunc),
- /* 227 */ SyscallDesc("unknown #227", unimplementedFunc),
- /* 228 */ SyscallDesc("unknown #228", unimplementedFunc),
- /* 229 */ SyscallDesc("unknown #229", unimplementedFunc),
- /* 230 */ SyscallDesc("unknown #230", unimplementedFunc),
- /* 231 */ SyscallDesc("unknown #231", unimplementedFunc),
- /* 232 */ SyscallDesc("unknown #232", unimplementedFunc),
- /* 233 */ SyscallDesc("getpgid", unimplementedFunc),
- /* 234 */ SyscallDesc("getsid", unimplementedFunc),
- /* 235 */ SyscallDesc("sigaltstack", ignoreFunc),
- /* 236 */ SyscallDesc("osf_waitid", unimplementedFunc),
- /* 237 */ SyscallDesc("osf_priocntlset", unimplementedFunc),
- /* 238 */ SyscallDesc("osf_sigsendset", unimplementedFunc),
- /* 239 */ SyscallDesc("osf_set_speculative", unimplementedFunc),
- /* 240 */ SyscallDesc("osf_msfs_syscall", unimplementedFunc),
- /* 241 */ SyscallDesc("osf_sysinfo", unimplementedFunc),
- /* 242 */ SyscallDesc("osf_uadmin", unimplementedFunc),
- /* 243 */ SyscallDesc("osf_fuser", unimplementedFunc),
- /* 244 */ SyscallDesc("osf_proplist_syscall", unimplementedFunc),
- /* 245 */ SyscallDesc("osf_ntp_adjtime", unimplementedFunc),
- /* 246 */ SyscallDesc("osf_ntp_gettime", unimplementedFunc),
- /* 247 */ SyscallDesc("osf_pathconf", unimplementedFunc),
- /* 248 */ SyscallDesc("osf_fpathconf", unimplementedFunc),
- /* 249 */ SyscallDesc("unknown #249", unimplementedFunc),
- /* 250 */ SyscallDesc("osf_uswitch", unimplementedFunc),
- /* 251 */ SyscallDesc("osf_usleep_thread", unimplementedFunc),
- /* 252 */ SyscallDesc("osf_audcntl", unimplementedFunc),
- /* 253 */ SyscallDesc("osf_audgen", unimplementedFunc),
- /* 254 */ SyscallDesc("sysfs", unimplementedFunc),
- /* 255 */ SyscallDesc("osf_subsys_info", unimplementedFunc),
- /* 256 */ SyscallDesc("osf_getsysinfo", osf_getsysinfoFunc),
- /* 257 */ SyscallDesc("osf_setsysinfo", osf_setsysinfoFunc),
- /* 258 */ SyscallDesc("osf_afs_syscall", unimplementedFunc),
- /* 259 */ SyscallDesc("osf_swapctl", unimplementedFunc),
- /* 260 */ SyscallDesc("osf_memcntl", unimplementedFunc),
- /* 261 */ SyscallDesc("osf_fdatasync", unimplementedFunc),
- /* 262 */ SyscallDesc("unknown #262", unimplementedFunc),
- /* 263 */ SyscallDesc("unknown #263", unimplementedFunc),
- /* 264 */ SyscallDesc("unknown #264", unimplementedFunc),
- /* 265 */ SyscallDesc("unknown #265", unimplementedFunc),
- /* 266 */ SyscallDesc("unknown #266", unimplementedFunc),
- /* 267 */ SyscallDesc("unknown #267", unimplementedFunc),
- /* 268 */ SyscallDesc("unknown #268", unimplementedFunc),
- /* 269 */ SyscallDesc("unknown #269", unimplementedFunc),
- /* 270 */ SyscallDesc("unknown #270", unimplementedFunc),
- /* 271 */ SyscallDesc("unknown #271", unimplementedFunc),
- /* 272 */ SyscallDesc("unknown #272", unimplementedFunc),
- /* 273 */ SyscallDesc("unknown #273", unimplementedFunc),
- /* 274 */ SyscallDesc("unknown #274", unimplementedFunc),
- /* 275 */ SyscallDesc("unknown #275", unimplementedFunc),
- /* 276 */ SyscallDesc("unknown #276", unimplementedFunc),
- /* 277 */ SyscallDesc("unknown #277", unimplementedFunc),
- /* 278 */ SyscallDesc("unknown #278", unimplementedFunc),
- /* 279 */ SyscallDesc("unknown #279", unimplementedFunc),
- /* 280 */ SyscallDesc("unknown #280", unimplementedFunc),
- /* 281 */ SyscallDesc("unknown #281", unimplementedFunc),
- /* 282 */ SyscallDesc("unknown #282", unimplementedFunc),
- /* 283 */ SyscallDesc("unknown #283", unimplementedFunc),
- /* 284 */ SyscallDesc("unknown #284", unimplementedFunc),
- /* 285 */ SyscallDesc("unknown #285", unimplementedFunc),
- /* 286 */ SyscallDesc("unknown #286", unimplementedFunc),
- /* 287 */ SyscallDesc("unknown #287", unimplementedFunc),
- /* 288 */ SyscallDesc("unknown #288", unimplementedFunc),
- /* 289 */ SyscallDesc("unknown #289", unimplementedFunc),
- /* 290 */ SyscallDesc("unknown #290", unimplementedFunc),
- /* 291 */ SyscallDesc("unknown #291", unimplementedFunc),
- /* 292 */ SyscallDesc("unknown #292", unimplementedFunc),
- /* 293 */ SyscallDesc("unknown #293", unimplementedFunc),
- /* 294 */ SyscallDesc("unknown #294", unimplementedFunc),
- /* 295 */ SyscallDesc("unknown #295", unimplementedFunc),
- /* 296 */ SyscallDesc("unknown #296", unimplementedFunc),
- /* 297 */ SyscallDesc("unknown #297", unimplementedFunc),
- /* 298 */ SyscallDesc("unknown #298", unimplementedFunc),
- /* 299 */ SyscallDesc("unknown #299", unimplementedFunc),
-/*
- * Linux-specific system calls begin at 300
- */
- /* 300 */ SyscallDesc("bdflush", unimplementedFunc),
- /* 301 */ SyscallDesc("sethae", unimplementedFunc),
- /* 302 */ SyscallDesc("mount", unimplementedFunc),
- /* 303 */ SyscallDesc("old_adjtimex", unimplementedFunc),
- /* 304 */ SyscallDesc("swapoff", unimplementedFunc),
- /* 305 */ SyscallDesc("getdents", unimplementedFunc),
- /* 306 */ SyscallDesc("create_module", unimplementedFunc),
- /* 307 */ SyscallDesc("init_module", unimplementedFunc),
- /* 308 */ SyscallDesc("delete_module", unimplementedFunc),
- /* 309 */ SyscallDesc("get_kernel_syms", unimplementedFunc),
- /* 310 */ SyscallDesc("syslog", unimplementedFunc),
- /* 311 */ SyscallDesc("reboot", unimplementedFunc),
- /* 312 */ SyscallDesc("clone", unimplementedFunc),
- /* 313 */ SyscallDesc("uselib", unimplementedFunc),
- /* 314 */ SyscallDesc("mlock", unimplementedFunc),
- /* 315 */ SyscallDesc("munlock", unimplementedFunc),
- /* 316 */ SyscallDesc("mlockall", unimplementedFunc),
- /* 317 */ SyscallDesc("munlockall", unimplementedFunc),
- /* 318 */ SyscallDesc("sysinfo", unimplementedFunc),
- /* 319 */ SyscallDesc("_sysctl", unimplementedFunc),
- /* 320 */ SyscallDesc("was sys_idle", unimplementedFunc),
- /* 321 */ SyscallDesc("oldumount", unimplementedFunc),
- /* 322 */ SyscallDesc("swapon", unimplementedFunc),
- /* 323 */ SyscallDesc("times", ignoreFunc),
- /* 324 */ SyscallDesc("personality", unimplementedFunc),
- /* 325 */ SyscallDesc("setfsuid", unimplementedFunc),
- /* 326 */ SyscallDesc("setfsgid", unimplementedFunc),
- /* 327 */ SyscallDesc("ustat", unimplementedFunc),
- /* 328 */ SyscallDesc("statfs", unimplementedFunc),
- /* 329 */ SyscallDesc("fstatfs", unimplementedFunc),
- /* 330 */ SyscallDesc("sched_setparam", unimplementedFunc),
- /* 331 */ SyscallDesc("sched_getparam", unimplementedFunc),
- /* 332 */ SyscallDesc("sched_setscheduler", unimplementedFunc),
- /* 333 */ SyscallDesc("sched_getscheduler", unimplementedFunc),
- /* 334 */ SyscallDesc("sched_yield", unimplementedFunc),
- /* 335 */ SyscallDesc("sched_get_priority_max", unimplementedFunc),
- /* 336 */ SyscallDesc("sched_get_priority_min", unimplementedFunc),
- /* 337 */ SyscallDesc("sched_rr_get_interval", unimplementedFunc),
- /* 338 */ SyscallDesc("afs_syscall", unimplementedFunc),
- /* 339 */ SyscallDesc("uname", unameFunc),
- /* 340 */ SyscallDesc("nanosleep", unimplementedFunc),
- /* 341 */ SyscallDesc("mremap", unimplementedFunc),
- /* 342 */ SyscallDesc("nfsservctl", unimplementedFunc),
- /* 343 */ SyscallDesc("setresuid", unimplementedFunc),
- /* 344 */ SyscallDesc("getresuid", unimplementedFunc),
- /* 345 */ SyscallDesc("pciconfig_read", unimplementedFunc),
- /* 346 */ SyscallDesc("pciconfig_write", unimplementedFunc),
- /* 347 */ SyscallDesc("query_module", unimplementedFunc),
- /* 348 */ SyscallDesc("prctl", unimplementedFunc),
- /* 349 */ SyscallDesc("pread", unimplementedFunc),
- /* 350 */ SyscallDesc("pwrite", unimplementedFunc),
- /* 351 */ SyscallDesc("rt_sigreturn", unimplementedFunc),
- /* 352 */ SyscallDesc("rt_sigaction", ignoreFunc),
- /* 353 */ SyscallDesc("rt_sigprocmask", unimplementedFunc),
- /* 354 */ SyscallDesc("rt_sigpending", unimplementedFunc),
- /* 355 */ SyscallDesc("rt_sigtimedwait", unimplementedFunc),
- /* 356 */ SyscallDesc("rt_sigqueueinfo", unimplementedFunc),
- /* 357 */ SyscallDesc("rt_sigsuspend", unimplementedFunc),
- /* 358 */ SyscallDesc("select", unimplementedFunc),
- /* 359 */ SyscallDesc("gettimeofday", gettimeofdayFunc<Linux>),
- /* 360 */ SyscallDesc("settimeofday", unimplementedFunc),
- /* 361 */ SyscallDesc("getitimer", unimplementedFunc),
- /* 362 */ SyscallDesc("setitimer", unimplementedFunc),
- /* 363 */ SyscallDesc("utimes", utimesFunc<Linux>),
- /* 364 */ SyscallDesc("getrusage", getrusageFunc<Linux>),
- /* 365 */ SyscallDesc("wait4", unimplementedFunc),
- /* 366 */ SyscallDesc("adjtimex", unimplementedFunc),
- /* 367 */ SyscallDesc("getcwd", unimplementedFunc),
- /* 368 */ SyscallDesc("capget", unimplementedFunc),
- /* 369 */ SyscallDesc("capset", unimplementedFunc),
- /* 370 */ SyscallDesc("sendfile", unimplementedFunc),
- /* 371 */ SyscallDesc("setresgid", unimplementedFunc),
- /* 372 */ SyscallDesc("getresgid", unimplementedFunc),
- /* 373 */ SyscallDesc("dipc", unimplementedFunc),
- /* 374 */ SyscallDesc("pivot_root", unimplementedFunc),
- /* 375 */ SyscallDesc("mincore", unimplementedFunc),
- /* 376 */ SyscallDesc("pciconfig_iobase", unimplementedFunc),
- /* 377 */ SyscallDesc("getdents64", unimplementedFunc),
- /* 378 */ SyscallDesc("gettid", unimplementedFunc),
- /* 379 */ SyscallDesc("readahead", unimplementedFunc),
- /* 380 */ SyscallDesc("security", unimplementedFunc),
- /* 381 */ SyscallDesc("tkill", unimplementedFunc),
- /* 382 */ SyscallDesc("setxattr", unimplementedFunc),
- /* 383 */ SyscallDesc("lsetxattr", unimplementedFunc),
- /* 384 */ SyscallDesc("fsetxattr", unimplementedFunc),
- /* 385 */ SyscallDesc("getxattr", unimplementedFunc),
- /* 386 */ SyscallDesc("lgetxattr", unimplementedFunc),
- /* 387 */ SyscallDesc("fgetxattr", unimplementedFunc),
- /* 388 */ SyscallDesc("listxattr", unimplementedFunc),
- /* 389 */ SyscallDesc("llistxattr", unimplementedFunc),
- /* 390 */ SyscallDesc("flistxattr", unimplementedFunc),
- /* 391 */ SyscallDesc("removexattr", unimplementedFunc),
- /* 392 */ SyscallDesc("lremovexattr", unimplementedFunc),
- /* 393 */ SyscallDesc("fremovexattr", unimplementedFunc),
- /* 394 */ SyscallDesc("futex", unimplementedFunc),
- /* 395 */ SyscallDesc("sched_setaffinity", unimplementedFunc),
- /* 396 */ SyscallDesc("sched_getaffinity", unimplementedFunc),
- /* 397 */ SyscallDesc("tuxcall", unimplementedFunc),
- /* 398 */ SyscallDesc("io_setup", unimplementedFunc),
- /* 399 */ SyscallDesc("io_destroy", unimplementedFunc),
- /* 400 */ SyscallDesc("io_getevents", unimplementedFunc),
- /* 401 */ SyscallDesc("io_submit", unimplementedFunc),
- /* 402 */ SyscallDesc("io_cancel", unimplementedFunc),
- /* 403 */ SyscallDesc("unknown #403", unimplementedFunc),
- /* 404 */ SyscallDesc("unknown #404", unimplementedFunc),
- /* 405 */ SyscallDesc("exit_group", exitFunc), // exit all threads...
- /* 406 */ SyscallDesc("lookup_dcookie", unimplementedFunc),
- /* 407 */ SyscallDesc("sys_epoll_create", unimplementedFunc),
- /* 408 */ SyscallDesc("sys_epoll_ctl", unimplementedFunc),
- /* 409 */ SyscallDesc("sys_epoll_wait", unimplementedFunc),
- /* 410 */ SyscallDesc("remap_file_pages", unimplementedFunc),
- /* 411 */ SyscallDesc("set_tid_address", unimplementedFunc),
- /* 412 */ SyscallDesc("restart_syscall", unimplementedFunc),
- /* 413 */ SyscallDesc("fadvise64", unimplementedFunc),
- /* 414 */ SyscallDesc("timer_create", unimplementedFunc),
- /* 415 */ SyscallDesc("timer_settime", unimplementedFunc),
- /* 416 */ SyscallDesc("timer_gettime", unimplementedFunc),
- /* 417 */ SyscallDesc("timer_getoverrun", unimplementedFunc),
- /* 418 */ SyscallDesc("timer_delete", unimplementedFunc),
- /* 419 */ SyscallDesc("clock_settime", unimplementedFunc),
- /* 420 */ SyscallDesc("clock_gettime", unimplementedFunc),
- /* 421 */ SyscallDesc("clock_getres", unimplementedFunc),
- /* 422 */ SyscallDesc("clock_nanosleep", unimplementedFunc),
- /* 423 */ SyscallDesc("semtimedop", unimplementedFunc),
- /* 424 */ SyscallDesc("tgkill", unimplementedFunc),
- /* 425 */ SyscallDesc("stat64", unimplementedFunc),
- /* 426 */ SyscallDesc("lstat64", lstat64Func<Linux>),
- /* 427 */ SyscallDesc("fstat64", fstat64Func<Linux>),
- /* 428 */ SyscallDesc("vserver", unimplementedFunc),
- /* 429 */ SyscallDesc("mbind", unimplementedFunc),
- /* 430 */ SyscallDesc("get_mempolicy", unimplementedFunc),
- /* 431 */ SyscallDesc("set_mempolicy", unimplementedFunc),
- /* 432 */ SyscallDesc("mq_open", unimplementedFunc),
- /* 433 */ SyscallDesc("mq_unlink", unimplementedFunc),
- /* 434 */ SyscallDesc("mq_timedsend", unimplementedFunc),
- /* 435 */ SyscallDesc("mq_timedreceive", unimplementedFunc),
- /* 436 */ SyscallDesc("mq_notify", unimplementedFunc),
- /* 437 */ SyscallDesc("mq_getsetattr", unimplementedFunc),
- /* 438 */ SyscallDesc("waitid", unimplementedFunc),
- /* 439 */ SyscallDesc("add_key", unimplementedFunc),
- /* 440 */ SyscallDesc("request_key", unimplementedFunc),
- /* 441 */ SyscallDesc("keyctl", unimplementedFunc)
-};
-
-AlphaLinuxProcess::AlphaLinuxProcess(const std::string &name,
- ObjectFile *objFile,
- int stdin_fd,
- int stdout_fd,
- int stderr_fd,
- std::vector<std::string> &argv,
- std::vector<std::string> &envp)
- : LiveProcess(name, objFile, stdin_fd, stdout_fd, stderr_fd, argv, envp),
- Num_Syscall_Descs(sizeof(syscallDescs) / sizeof(SyscallDesc))
-{
- init_regs->intRegFile[0] = 0;
-}
-
-
-
-SyscallDesc*
-AlphaLinuxProcess::getDesc(int callnum)
-{
- if (callnum < 0 || callnum > Num_Syscall_Descs)
- return NULL;
- return &syscallDescs[callnum];
-}
diff --git a/arch/alpha/linux/process.hh b/arch/alpha/linux/process.hh
deleted file mode 100644
index 7de1b1ac1..000000000
--- a/arch/alpha/linux/process.hh
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (c) 2003-2004 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __ALPHA_LINUX_PROCESS_HH__
-#define __ALPHA_LINUX_PROCESS_HH__
-
-#include "sim/process.hh"
-
-
-/// A process with emulated Alpha/Linux syscalls.
-class AlphaLinuxProcess : public LiveProcess
-{
- public:
- /// Constructor.
- AlphaLinuxProcess(const std::string &name,
- ObjectFile *objFile,
- int stdin_fd, int stdout_fd, int stderr_fd,
- std::vector<std::string> &argv,
- std::vector<std::string> &envp);
-
- virtual SyscallDesc* getDesc(int callnum);
-
- /// The target system's hostname.
- static const char *hostname;
-
- /// Array of syscall descriptors, indexed by call number.
- static SyscallDesc syscallDescs[];
-
- const int Num_Syscall_Descs;
-};
-
-
-#endif // __ALPHA_LINUX_PROCESS_HH__
diff --git a/arch/alpha/linux/system.cc b/arch/alpha/linux/system.cc
deleted file mode 100644
index f9275d15e..000000000
--- a/arch/alpha/linux/system.cc
+++ /dev/null
@@ -1,289 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * @file
- * This code loads the linux kernel, console, pal and patches certain
- * functions. The symbol tables are loaded so that traces can show
- * the executing function and we can skip functions. Various delay
- * loops are skipped and their final values manually computed to speed
- * up boot time.
- */
-
-#include "arch/arguments.hh"
-#include "arch/vtophys.hh"
-#include "arch/alpha/linux/system.hh"
-#include "arch/alpha/linux/threadinfo.hh"
-#include "arch/alpha/system.hh"
-#include "base/loader/symtab.hh"
-#include "cpu/exec_context.hh"
-#include "cpu/base.hh"
-#include "dev/platform.hh"
-#include "kern/linux/printk.hh"
-#include "kern/linux/events.hh"
-#include "mem/functional/memory_control.hh"
-#include "mem/functional/physical.hh"
-#include "sim/builder.hh"
-#include "sim/byteswap.hh"
-
-using namespace std;
-using namespace AlphaISA;
-using namespace Linux;
-
-LinuxAlphaSystem::LinuxAlphaSystem(Params *p)
- : AlphaSystem(p)
-{
- Addr addr = 0;
- Addr paddr = 0;
-
- /**
- * The symbol swapper_pg_dir marks the beginning of the kernel and
- * the location of bootloader passed arguments
- */
- if (!kernelSymtab->findAddress("swapper_pg_dir", KernelStart)) {
- panic("Could not determine start location of kernel");
- }
-
- /**
- * 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);
-
- /**
- * 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;
- }
-
-
- /**
- * EV5 only supports 127 ASNs so we are going to tell the kernel that the
- * paritiuclar EV6 we have only supports 127 asns.
- * @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
- panic("could not find dp264_mv\n");
-
-#ifndef NDEBUG
- kernelPanicEvent = addKernelFuncEvent<BreakPCEvent>("panic");
- if (!kernelPanicEvent)
- panic("could not find kernel symbol \'panic\'");
-
-#if 0
- kernelDieEvent = addKernelFuncEvent<BreakPCEvent>("die_if_kernel");
- if (!kernelDieEvent)
- panic("could not find kernel symbol \'die_if_kernel\'");
-#endif
-
-#endif
-
- /**
- * Any time ide_delay_50ms, calibarte_delay or
- * determine_cpu_caches is called just skip the
- * function. Currently determine_cpu_caches only is used put
- * information in proc, however if that changes in the future we
- * will have to fill in the cache size variables appropriately.
- */
-
- skipIdeDelay50msEvent =
- addKernelFuncEvent<SkipFuncEvent>("ide_delay_50ms");
- skipDelayLoopEvent =
- addKernelFuncEvent<SkipDelayLoopEvent>("calibrate_delay");
- skipCacheProbeEvent =
- addKernelFuncEvent<SkipFuncEvent>("determine_cpu_caches");
- debugPrintkEvent = addKernelFuncEvent<DebugPrintkEvent>("dprintk");
- idleStartEvent = addKernelFuncEvent<IdleStartEvent>("cpu_idle");
-
- if (kernelSymtab->findAddress("alpha_switch_to", addr) && DTRACE(Thread)) {
- printThreadEvent = new PrintThreadInfo(&pcEventQueue, "threadinfo",
- addr + sizeof(MachInst) * 6);
- } else {
- printThreadEvent = NULL;
- }
-
- if (params()->bin_int) {
- intStartEvent = addPalFuncEvent<InterruptStartEvent>("sys_int_21");
- if (!intStartEvent)
- panic("could not find symbol: sys_int_21\n");
-
- intEndEvent = addPalFuncEvent<InterruptEndEvent>("rti_to_kern");
- if (!intEndEvent)
- panic("could not find symbol: rti_to_kern\n");
-
- intEndEvent2 = addPalFuncEvent<InterruptEndEvent>("rti_to_user");
- if (!intEndEvent2)
- panic("could not find symbol: rti_to_user\n");
-
- intEndEvent3 = addKernelFuncEvent<InterruptEndEvent>("do_softirq");
- if (!intEndEvent3)
- panic("could not find symbol: do_softirq\n");
- }
-}
-
-LinuxAlphaSystem::~LinuxAlphaSystem()
-{
-#ifndef NDEBUG
- delete kernelPanicEvent;
-#endif
- delete skipIdeDelay50msEvent;
- delete skipDelayLoopEvent;
- delete skipCacheProbeEvent;
- delete debugPrintkEvent;
- delete idleStartEvent;
- delete printThreadEvent;
- delete intStartEvent;
- delete intEndEvent;
- delete intEndEvent2;
-}
-
-
-void
-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);
- }
-}
-
-
-void
-LinuxAlphaSystem::SkipDelayLoopEvent::process(ExecContext *xc)
-{
- SkipFuncEvent::process(xc);
- // calculate and set loops_per_jiffy
- ((LinuxAlphaSystem *)xc->getSystemPtr())->setDelayLoop(xc);
-}
-
-void
-LinuxAlphaSystem::PrintThreadInfo::process(ExecContext *xc)
-{
- Linux::ThreadInfo ti(xc);
-
- DPRINTF(Thread, "Currently Executing Thread %s, pid %d, started at: %d\n",
- ti.curTaskName(), ti.curTaskPID(), ti.curTaskStart());
-}
-
-
-BEGIN_DECLARE_SIM_OBJECT_PARAMS(LinuxAlphaSystem)
-
- Param<Tick> boot_cpu_frequency;
- SimObjectParam<MemoryController *> memctrl;
- SimObjectParam<PhysicalMemory *> physmem;
-
- Param<string> kernel;
- Param<string> console;
- Param<string> pal;
-
- Param<string> boot_osflags;
- Param<string> readfile;
- Param<unsigned int> init_param;
-
- Param<uint64_t> system_type;
- Param<uint64_t> system_rev;
-
- Param<bool> bin;
- VectorParam<string> binned_fns;
- Param<bool> bin_int;
-
-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"),
- INIT_PARAM(pal, "file that contains palcode"),
- INIT_PARAM_DFLT(boot_osflags, "flags to pass to the kernel during boot",
- "a"),
- INIT_PARAM_DFLT(readfile, "file to read startup script from", ""),
- INIT_PARAM_DFLT(init_param, "numerical value to pass into simulator", 0),
- INIT_PARAM_DFLT(system_type, "Type of system we are emulating", 34),
- INIT_PARAM_DFLT(system_rev, "Revision of system we are emulating", 1<<10),
- INIT_PARAM_DFLT(bin, "is this system to be binned", false),
- INIT_PARAM(binned_fns, "functions to be broken down and binned"),
- INIT_PARAM_DFLT(bin_int, "is interrupt code binned seperately?", true)
-
-END_INIT_SIM_OBJECT_PARAMS(LinuxAlphaSystem)
-
-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;
- p->palcode = pal;
- p->boot_osflags = boot_osflags;
- p->init_param = init_param;
- p->readfile = readfile;
- p->system_type = system_type;
- p->system_rev = system_rev;
- p->bin = bin;
- p->binned_fns = binned_fns;
- p->bin_int = bin_int;
- return new LinuxAlphaSystem(p);
-}
-
-REGISTER_SIM_OBJECT("LinuxAlphaSystem", LinuxAlphaSystem)
-
diff --git a/arch/alpha/linux/system.hh b/arch/alpha/linux/system.hh
deleted file mode 100644
index 035e2a427..000000000
--- a/arch/alpha/linux/system.hh
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * Copyright (c) 2004-2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __ARCH_ALPHA_LINUX_SYSTEM_HH__
-#define __ARCH_ALPHA_LINUX_SYSTEM_HH__
-
-class ExecContext;
-
-class BreakPCEvent;
-class IdleStartEvent;
-
-#include "arch/alpha/system.hh"
-#include "kern/linux/events.hh"
-
-using namespace AlphaISA;
-using namespace Linux;
-using namespace std;
-
-/**
- * This class contains linux specific system code (Loading, Events, Binning).
- * It points to objects that are the system binaries to load and patches them
- * appropriately to work in simulator.
- */
-class LinuxAlphaSystem : public AlphaSystem
-{
- private:
- class SkipDelayLoopEvent : public SkipFuncEvent
- {
- public:
- SkipDelayLoopEvent(PCEventQueue *q, const std::string &desc, Addr addr)
- : SkipFuncEvent(q, desc, addr) {}
- virtual void process(ExecContext *xc);
- };
-
- class PrintThreadInfo : public PCEvent
- {
- public:
- PrintThreadInfo(PCEventQueue *q, const std::string &desc, Addr addr)
- : PCEvent(q, desc, addr) {}
- virtual void process(ExecContext *xc);
- };
-
-
- /**
- * Addresses defining where the kernel bootloader places various
- * elements. Details found in include/asm-alpha/system.h
- */
- Addr KernelStart; // Lookup the symbol swapper_pg_dir
-
- public:
- Addr InitStack() const { return KernelStart + 0x02000; }
- Addr EmptyPGT() const { return KernelStart + 0x04000; }
- Addr EmptyPGE() const { return KernelStart + 0x08000; }
- Addr ZeroPGE() const { return KernelStart + 0x0A000; }
- Addr StartAddr() const { return KernelStart + 0x10000; }
-
- Addr Param() const { return ZeroPGE() + 0x0; }
- Addr CommandLine() const { return Param() + 0x0; }
- Addr InitrdStart() const { return Param() + 0x100; }
- Addr InitrdSize() const { return Param() + 0x108; }
- static const int CommandLineSize = 256;
-
- private:
-#ifndef NDEBUG
- /** Event to halt the simulator if the kernel calls panic() */
- BreakPCEvent *kernelPanicEvent;
-
- /** Event to halt the simulator if the kernel calls die_if_kernel */
- BreakPCEvent *kernelDieEvent;
-#endif
-
- /**
- * Event to skip determine_cpu_caches() because we don't support
- * the IPRs that the code can access to figure out cache sizes
- */
- SkipFuncEvent *skipCacheProbeEvent;
-
- /** PC based event to skip the ide_delay_50ms() call */
- SkipFuncEvent *skipIdeDelay50msEvent;
-
- /**
- * PC based event to skip the dprink() call and emulate its
- * functionality
- */
- DebugPrintkEvent *debugPrintkEvent;
-
- /**
- * Skip calculate_delay_loop() rather than waiting for this to be
- * calculated
- */
- SkipDelayLoopEvent *skipDelayLoopEvent;
-
- /**
- * Event to print information about thread switches if the trace flag
- * Thread is set
- */
- PrintThreadInfo *printThreadEvent;
-
- /**
- * Event to bin Interrupts seperately from kernel code
- */
- InterruptStartEvent *intStartEvent;
-
- /**
- * Event to bin Interrupts seperately from kernel code
- */
- InterruptEndEvent *intEndEvent;
- InterruptEndEvent *intEndEvent2;
- InterruptEndEvent *intEndEvent3;
-
- /** Grab the PCBB of the idle process when it starts */
- IdleStartEvent *idleStartEvent;
-
- public:
- LinuxAlphaSystem(Params *p);
- ~LinuxAlphaSystem();
-
- void setDelayLoop(ExecContext *xc);
-};
-
-#endif // __ARCH_ALPHA_LINUX_SYSTEM_HH__
diff --git a/arch/alpha/process.cc b/arch/alpha/process.cc
deleted file mode 100644
index b2dbe7ad1..000000000
--- a/arch/alpha/process.cc
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (c) 2003-2004 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "arch/alpha/process.hh"
-
-namespace AlphaISA
-{
-
-LiveProcess *
-createProcess(const std::string &nm, ObjectFile * objFile,
- int stdin_fd, int stdout_fd, int stderr_fd,
- std::vector<std::string> &argv, std::vector<std::string> &envp)
-{
- LiveProcess * process = NULL;
- if (objFile->getArch() != ObjectFile::Alpha)
- fatal("Object file does not match architecture.");
- switch (objFile->getOpSys()) {
- case ObjectFile::Tru64:
- process = new AlphaTru64Process(nm, objFile,
- stdin_fd, stdout_fd, stderr_fd,
- argv, envp);
- break;
-
- case ObjectFile::Linux:
- process = new AlphaLinuxProcess(nm, objFile,
- stdin_fd, stdout_fd, stderr_fd,
- argv, envp);
- break;
-
- default:
- fatal("Unknown/unsupported operating system.");
- }
- return process;
-}
-
-} // namespace AlphaISA
diff --git a/arch/alpha/process.hh b/arch/alpha/process.hh
deleted file mode 100644
index 4a2a4212e..000000000
--- a/arch/alpha/process.hh
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2003-2004 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __ALPHA_PROCESS_HH__
-#define __ALPHA_PROCESS_HH__
-
-#include <string>
-
-#include "arch/alpha/linux/process.hh"
-#include "arch/alpha/tru64/process.hh"
-#include "base/loader/object_file.hh"
-
-namespace AlphaISA
-{
-
-LiveProcess *
-createProcess(const std::string &nm, ObjectFile * objFile,
- int stdin_fd, int stdout_fd, int stderr_fd,
- std::vector<std::string> &argv, std::vector<std::string> &envp);
-
-} // namespace AlphaISA
-
-#endif // __ALPHA_PROCESS_HH__
diff --git a/arch/alpha/stacktrace.cc b/arch/alpha/stacktrace.cc
deleted file mode 100644
index 26656ab5c..000000000
--- a/arch/alpha/stacktrace.cc
+++ /dev/null
@@ -1,348 +0,0 @@
-/*
- * Copyright (c) 2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <string>
-
-#include "arch/alpha/isa_traits.hh"
-#include "arch/alpha/stacktrace.hh"
-#include "arch/alpha/vtophys.hh"
-#include "base/bitfield.hh"
-#include "base/trace.hh"
-#include "cpu/base.hh"
-#include "cpu/exec_context.hh"
-#include "sim/system.hh"
-
-using namespace std;
-using namespace AlphaISA;
-
-ProcessInfo::ProcessInfo(ExecContext *_xc)
- : xc(_xc)
-{
- Addr addr = 0;
-
- if (!xc->getSystemPtr()->kernelSymtab->findAddress("thread_info_size", addr))
- panic("thread info not compiled into kernel\n");
- thread_info_size = *(int32_t *)vtomem(xc, addr, sizeof(int32_t));
-
- if (!xc->getSystemPtr()->kernelSymtab->findAddress("task_struct_size", addr))
- panic("thread info not compiled into kernel\n");
- task_struct_size = *(int32_t *)vtomem(xc, addr, sizeof(int32_t));
-
- if (!xc->getSystemPtr()->kernelSymtab->findAddress("thread_info_task", addr))
- panic("thread info not compiled into kernel\n");
- task_off = *(int32_t *)vtomem(xc, addr, sizeof(int32_t));
-
- if (!xc->getSystemPtr()->kernelSymtab->findAddress("task_struct_pid", addr))
- panic("thread info not compiled into kernel\n");
- pid_off = *(int32_t *)vtomem(xc, addr, sizeof(int32_t));
-
- if (!xc->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));
-}
-
-Addr
-ProcessInfo::task(Addr ksp) const
-{
- Addr base = ksp & ~0x3fff;
- if (base == ULL(0xfffffc0000000000))
- return 0;
-
- Addr task;
- CopyOut(xc, &task, base + task_off, sizeof(task));
- return task;
-}
-
-int
-ProcessInfo::pid(Addr ksp) const
-{
- Addr task = this->task(ksp);
- if (!task)
- return -1;
-
- uint16_t pid;
- CopyOut(xc, &pid, task + pid_off, sizeof(pid));
- return pid;
-}
-
-string
-ProcessInfo::name(Addr ksp) const
-{
- Addr task = this->task(ksp);
- if (!task)
- return "console";
-
- char comm[256];
- CopyString(xc, comm, task + name_off, sizeof(comm));
- if (!comm[0])
- return "startup";
-
- return comm;
-}
-
-StackTrace::StackTrace()
- : xc(0), stack(64)
-{
-}
-
-StackTrace::StackTrace(ExecContext *_xc, StaticInstPtr inst)
- : xc(0), stack(64)
-{
- trace(_xc, inst);
-}
-
-StackTrace::~StackTrace()
-{
-}
-
-void
-StackTrace::trace(ExecContext *_xc, bool is_call)
-{
- xc = _xc;
-
- bool usermode = (xc->readMiscReg(AlphaISA::IPR_DTB_CM) & 0x18) != 0;
-
- Addr pc = xc->readNextPC();
- bool kernel = xc->getSystemPtr()->kernelStart <= pc &&
- pc <= xc->getSystemPtr()->kernelEnd;
-
- if (usermode) {
- stack.push_back(user);
- return;
- }
-
- if (!kernel) {
- stack.push_back(console);
- return;
- }
-
- SymbolTable *symtab = xc->getSystemPtr()->kernelSymtab;
- Addr ksp = xc->readIntReg(TheISA::StackPointerReg);
- Addr bottom = ksp & ~0x3fff;
- Addr addr;
-
- if (is_call) {
- if (!symtab->findNearestAddr(pc, addr))
- panic("could not find address %#x", pc);
-
- stack.push_back(addr);
- pc = xc->readPC();
- }
-
- Addr ra;
- int size;
-
- while (ksp > bottom) {
- if (!symtab->findNearestAddr(pc, addr))
- panic("could not find symbol for pc=%#x", pc);
- assert(pc >= addr && "symbol botch: callpc < func");
-
- stack.push_back(addr);
-
- if (isEntry(addr))
- return;
-
- if (decodePrologue(ksp, pc, addr, size, ra)) {
- if (!ra)
- return;
-
- if (size <= 0) {
- stack.push_back(unknown);
- return;
- }
-
- pc = ra;
- ksp += size;
- } else {
- stack.push_back(unknown);
- return;
- }
-
- bool kernel = xc->getSystemPtr()->kernelStart <= pc &&
- pc <= xc->getSystemPtr()->kernelEnd;
- if (!kernel)
- return;
-
- if (stack.size() >= 1000)
- panic("unwinding too far");
- }
-
- panic("unwinding too far");
-}
-
-bool
-StackTrace::isEntry(Addr addr)
-{
- if (addr == xc->readMiscReg(AlphaISA::IPR_PALtemp12))
- return true;
-
- if (addr == xc->readMiscReg(AlphaISA::IPR_PALtemp7))
- return true;
-
- if (addr == xc->readMiscReg(AlphaISA::IPR_PALtemp11))
- return true;
-
- if (addr == xc->readMiscReg(AlphaISA::IPR_PALtemp21))
- return true;
-
- if (addr == xc->readMiscReg(AlphaISA::IPR_PALtemp9))
- return true;
-
- if (addr == xc->readMiscReg(AlphaISA::IPR_PALtemp2))
- return true;
-
- return false;
-}
-
-bool
-StackTrace::decodeStack(MachInst inst, int &disp)
-{
- // lda $sp, -disp($sp)
- //
- // Opcode<31:26> == 0x08
- // RA<25:21> == 30
- // RB<20:16> == 30
- // Disp<15:0>
- const MachInst mem_mask = 0xffff0000;
- const MachInst lda_pattern = 0x23de0000;
- const MachInst lda_disp_mask = 0x0000ffff;
-
- // subq $sp, disp, $sp
- // addq $sp, disp, $sp
- //
- // Opcode<31:26> == 0x10
- // RA<25:21> == 30
- // Lit<20:13>
- // One<12> = 1
- // Func<11:5> == 0x20 (addq)
- // Func<11:5> == 0x29 (subq)
- // RC<4:0> == 30
- const MachInst intop_mask = 0xffe01fff;
- const MachInst addq_pattern = 0x43c0141e;
- const MachInst subq_pattern = 0x43c0153e;
- const MachInst intop_disp_mask = 0x001fe000;
- const int intop_disp_shift = 13;
-
- if ((inst & mem_mask) == lda_pattern)
- disp = -sext<16>(inst & lda_disp_mask);
- else if ((inst & intop_mask) == addq_pattern)
- disp = -int((inst & intop_disp_mask) >> intop_disp_shift);
- else if ((inst & intop_mask) == subq_pattern)
- disp = int((inst & intop_disp_mask) >> intop_disp_shift);
- else
- return false;
-
- return true;
-}
-
-bool
-StackTrace::decodeSave(MachInst inst, int &reg, int &disp)
-{
- // lda $stq, disp($sp)
- //
- // Opcode<31:26> == 0x08
- // RA<25:21> == ?
- // RB<20:16> == 30
- // Disp<15:0>
- const MachInst stq_mask = 0xfc1f0000;
- const MachInst stq_pattern = 0xb41e0000;
- const MachInst stq_disp_mask = 0x0000ffff;
- const MachInst reg_mask = 0x03e00000;
- const int reg_shift = 21;
-
- if ((inst & stq_mask) == stq_pattern) {
- reg = (inst & reg_mask) >> reg_shift;
- disp = sext<16>(inst & stq_disp_mask);
- } else {
- return false;
- }
-
- return true;
-}
-
-/*
- * Decode the function prologue for the function we're in, and note
- * which registers are stored where, and how large the stack frame is.
- */
-bool
-StackTrace::decodePrologue(Addr sp, Addr callpc, Addr func,
- int &size, Addr &ra)
-{
- size = 0;
- ra = 0;
-
- for (Addr pc = func; pc < callpc; pc += sizeof(MachInst)) {
- MachInst inst;
- CopyOut(xc, (uint8_t *)&inst, pc, sizeof(MachInst));
-
- int reg, disp;
- if (decodeStack(inst, disp)) {
- if (size) {
- // panic("decoding frame size again");
- return true;
- }
- size += disp;
- } else if (decodeSave(inst, reg, disp)) {
- if (!ra && reg == ReturnAddressReg) {
- CopyOut(xc, (uint8_t *)&ra, sp + disp, sizeof(Addr));
- if (!ra) {
- // panic("no return address value pc=%#x\n", pc);
- return false;
- }
- }
- }
- }
-
- return true;
-}
-
-#if TRACING_ON
-void
-StackTrace::dump()
-{
- StringWrap name(xc->getCpuPtr()->name());
- SymbolTable *symtab = xc->getSystemPtr()->kernelSymtab;
-
- DPRINTFN("------ Stack ------\n");
-
- string symbol;
- for (int i = 0, size = stack.size(); i < size; ++i) {
- Addr addr = stack[size - i - 1];
- if (addr == user)
- symbol = "user";
- else if (addr == console)
- symbol = "console";
- else if (addr == unknown)
- symbol = "unknown";
- else
- symtab->findSymbol(addr, symbol);
-
- DPRINTFN("%#x: %s\n", addr, symbol);
- }
-}
-#endif
diff --git a/arch/alpha/system.cc b/arch/alpha/system.cc
deleted file mode 100644
index 25543da57..000000000
--- a/arch/alpha/system.cc
+++ /dev/null
@@ -1,299 +0,0 @@
-/*
- * Copyright (c) 2002-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "arch/alpha/system.hh"
-#include "arch/vtophys.hh"
-#include "base/remote_gdb.hh"
-#include "base/loader/object_file.hh"
-#include "base/loader/symtab.hh"
-#include "base/trace.hh"
-#include "mem/functional/memory_control.hh"
-#include "mem/functional/physical.hh"
-#include "sim/byteswap.hh"
-#include "sim/builder.hh"
-
-
-using namespace LittleEndianGuest;
-
-AlphaSystem::AlphaSystem(Params *p)
- : System(p)
-{
- consoleSymtab = new SymbolTable;
- palSymtab = new SymbolTable;
-
-
- /**
- * Load the pal, and console code into memory
- */
- // Load Console Code
- console = createObjectFile(params()->console_path);
- if (console == NULL)
- fatal("Could not load console file %s", params()->console_path);
-
- // Load pal file
- pal = createObjectFile(params()->palcode);
- if (pal == NULL)
- fatal("Could not load PALcode file %s", params()->palcode);
-
-
- // Load program sections into memory
- pal->loadSections(physmem, true);
- console->loadSections(physmem, true);
-
- // load symbols
- if (!console->loadGlobalSymbols(consoleSymtab))
- panic("could not load console symbols\n");
-
- if (!pal->loadGlobalSymbols(palSymtab))
- panic("could not load pal symbols\n");
-
- if (!pal->loadLocalSymbols(palSymtab))
- panic("could not load pal symbols\n");
-
- if (!console->loadGlobalSymbols(debugSymbolTable))
- panic("could not load console symbols\n");
-
- if (!pal->loadGlobalSymbols(debugSymbolTable))
- panic("could not load pal symbols\n");
-
- if (!pal->loadLocalSymbols(debugSymbolTable))
- panic("could not load pal symbols\n");
-
- Addr addr = 0;
-#ifndef NDEBUG
- consolePanicEvent = addConsoleFuncEvent<BreakPCEvent>("panic");
-#endif
-
- /**
- * Copy the osflags (kernel arguments) into the consoles
- * memory. (Presently Linux does not use the console service
- * routine to get these command line arguments, but Tru64 and
- * others do.)
- */
- if (consoleSymtab->findAddress("env_booted_osflags", addr)) {
- Addr paddr = vtophys(physmem, addr);
- char *osflags = (char *)physmem->dma_addr(paddr, sizeof(uint32_t));
-
- if (osflags)
- strcpy(osflags, params()->boot_osflags.c_str());
- }
-
- /**
- * Set the hardware reset parameter block system type and revision
- * information to Tsunami.
- */
- if (consoleSymtab->findAddress("m5_rpb", addr)) {
- Addr paddr = vtophys(physmem, addr);
- char *hwrpb = (char *)physmem->dma_addr(paddr, sizeof(uint64_t));
-
- if (!hwrpb)
- panic("could not translate hwrpb addr\n");
-
- *(uint64_t*)(hwrpb+0x50) = htog(params()->system_type);
- *(uint64_t*)(hwrpb+0x58) = htog(params()->system_rev);
- } else
- panic("could not find hwrpb\n");
-
-}
-
-AlphaSystem::~AlphaSystem()
-{
- delete consoleSymtab;
- delete console;
- delete pal;
-#ifdef DEBUG
- delete consolePanicEvent;
-#endif
-}
-
-/**
- * This function fixes up addresses that are used to match PCs for
- * hooking simulator events on to target function executions.
- *
- * Alpha binaries may have multiple global offset table (GOT)
- * sections. A function that uses the GOT starts with a
- * two-instruction prolog which sets the global pointer (gp == r29) to
- * the appropriate GOT section. The proper gp value is calculated
- * based on the function address, which must be passed by the caller
- * in the procedure value register (pv aka t12 == r27). This sequence
- * looks like the following:
- *
- * opcode Ra Rb offset
- * ldah gp,X(pv) 09 29 27 X
- * lda gp,Y(gp) 08 29 29 Y
- *
- * for some constant offsets X and Y. The catch is that the linker
- * (or maybe even the compiler, I'm not sure) may recognize that the
- * caller and callee are using the same GOT section, making this
- * prolog redundant, and modify the call target to skip these
- * instructions. If we check for execution of the first instruction
- * of a function (the one the symbol points to) to detect when to skip
- * it, we'll miss all these modified calls. It might work to
- * unconditionally check for the third instruction, but not all
- * functions have this prolog, and there's some chance that those
- * first two instructions could have undesired consequences. So we do
- * the Right Thing and pattern-match the first two instructions of the
- * function to decide where to patch.
- *
- * Eventually this code should be moved into an ISA-specific file.
- */
-Addr
-AlphaSystem::fixFuncEventAddr(Addr addr)
-{
- // mask for just the opcode, Ra, and Rb fields (not the offset)
- const uint32_t inst_mask = 0xffff0000;
- // ldah gp,X(pv): opcode 9, Ra = 29, Rb = 27
- const uint32_t gp_ldah_pattern = (9 << 26) | (29 << 21) | (27 << 16);
- // lda gp,Y(gp): opcode 8, Ra = 29, rb = 29
- const uint32_t gp_lda_pattern = (8 << 26) | (29 << 21) | (29 << 16);
- // instruction size
- const int sz = sizeof(uint32_t);
-
- Addr paddr = vtophys(physmem, addr);
- uint32_t i1 = *(uint32_t *)physmem->dma_addr(paddr, sz);
- uint32_t i2 = *(uint32_t *)physmem->dma_addr(paddr+sz, sz);
-
- if ((i1 & inst_mask) == gp_ldah_pattern &&
- (i2 & inst_mask) == gp_lda_pattern) {
- Addr new_addr = addr + 2*sz;
- DPRINTF(Loader, "fixFuncEventAddr: %p -> %p", addr, new_addr);
- return new_addr;
- } else {
- return addr;
- }
-}
-
-
-void
-AlphaSystem::setAlphaAccess(Addr access)
-{
- Addr addr = 0;
- if (consoleSymtab->findAddress("m5AlphaAccess", addr)) {
- Addr paddr = vtophys(physmem, addr);
- uint64_t *m5AlphaAccess =
- (uint64_t *)physmem->dma_addr(paddr, sizeof(uint64_t));
-
- if (!m5AlphaAccess)
- panic("could not translate m5AlphaAccess addr\n");
-
- *m5AlphaAccess = htog(EV5::Phys2K0Seg(access));
- } else
- panic("could not find m5AlphaAccess\n");
-}
-
-bool
-AlphaSystem::breakpoint()
-{
- return remoteGDB[0]->trap(ALPHA_KENTRY_INT);
-}
-
-void
-AlphaSystem::serialize(std::ostream &os)
-{
- System::serialize(os);
- consoleSymtab->serialize("console_symtab", os);
- palSymtab->serialize("pal_symtab", os);
-}
-
-
-void
-AlphaSystem::unserialize(Checkpoint *cp, const std::string &section)
-{
- System::unserialize(cp,section);
- consoleSymtab->unserialize("console_symtab", cp, section);
- palSymtab->unserialize("pal_symtab", cp, section);
-}
-
-
-BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaSystem)
-
- Param<Tick> boot_cpu_frequency;
- SimObjectParam<MemoryController *> memctrl;
- SimObjectParam<PhysicalMemory *> physmem;
-
- Param<std::string> kernel;
- Param<std::string> console;
- Param<std::string> pal;
-
- Param<std::string> boot_osflags;
- Param<std::string> readfile;
- Param<unsigned int> init_param;
-
- Param<uint64_t> system_type;
- Param<uint64_t> system_rev;
-
- Param<bool> bin;
- VectorParam<std::string> binned_fns;
- Param<bool> bin_int;
-
-END_DECLARE_SIM_OBJECT_PARAMS(AlphaSystem)
-
-BEGIN_INIT_SIM_OBJECT_PARAMS(AlphaSystem)
-
- INIT_PARAM(boot_cpu_frequency, "Frequency of the boot CPU"),
- INIT_PARAM(memctrl, "memory controller"),
- INIT_PARAM(physmem, "phsyical memory"),
- INIT_PARAM(kernel, "file that contains the kernel code"),
- INIT_PARAM(console, "file that contains the console code"),
- INIT_PARAM(pal, "file that contains palcode"),
- INIT_PARAM_DFLT(boot_osflags, "flags to pass to the kernel during boot",
- "a"),
- INIT_PARAM_DFLT(readfile, "file to read startup script from", ""),
- INIT_PARAM_DFLT(init_param, "numerical value to pass into simulator", 0),
- INIT_PARAM_DFLT(system_type, "Type of system we are emulating", 34),
- INIT_PARAM_DFLT(system_rev, "Revision of system we are emulating", 1<<10),
- INIT_PARAM_DFLT(bin, "is this system to be binned", false),
- INIT_PARAM(binned_fns, "functions to be broken down and binned"),
- INIT_PARAM_DFLT(bin_int, "is interrupt code binned seperately?", true)
-
-END_INIT_SIM_OBJECT_PARAMS(AlphaSystem)
-
-CREATE_SIM_OBJECT(AlphaSystem)
-{
- AlphaSystem::Params *p = new AlphaSystem::Params;
- p->name = getInstanceName();
- p->boot_cpu_frequency = boot_cpu_frequency;
- p->memctrl = memctrl;
- p->physmem = physmem;
- p->kernel_path = kernel;
- p->console_path = console;
- p->palcode = pal;
- p->boot_osflags = boot_osflags;
- p->init_param = init_param;
- p->readfile = readfile;
- p->system_type = system_type;
- p->system_rev = system_rev;
- p->bin = bin;
- p->binned_fns = binned_fns;
- p->bin_int = bin_int;
- return new AlphaSystem(p);
-}
-
-REGISTER_SIM_OBJECT("AlphaSystem", AlphaSystem)
-
-
diff --git a/arch/alpha/system.hh b/arch/alpha/system.hh
deleted file mode 100644
index fe1307ac3..000000000
--- a/arch/alpha/system.hh
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright (c) 2002-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __ARCH_ALPHA_SYSTEM_HH__
-#define __ARCH_ALPHA_SYSTEM_HH__
-
-#include <string>
-#include <vector>
-
-#include "sim/system.hh"
-#include "base/loader/symtab.hh"
-#include "cpu/pc_event.hh"
-#include "kern/system_events.hh"
-#include "sim/sim_object.hh"
-
-class AlphaSystem : public System
-{
- public:
- struct Params : public System::Params
- {
- std::string console_path;
- std::string palcode;
- std::string boot_osflags;
- uint64_t system_type;
- uint64_t system_rev;
- };
-
- AlphaSystem(Params *p);
-
- ~AlphaSystem();
-
- virtual bool breakpoint();
-
-/**
- * Serialization stuff
- */
- public:
- virtual void serialize(std::ostream &os);
- virtual void unserialize(Checkpoint *cp, const std::string &section);
-
- /**
- * Set the m5AlphaAccess pointer in the console
- */
- void setAlphaAccess(Addr access);
-
- /** console symbol table */
- SymbolTable *consoleSymtab;
-
- /** pal symbol table */
- SymbolTable *palSymtab;
-
- /** Object pointer for the console code */
- ObjectFile *console;
-
- /** Object pointer for the PAL code */
- ObjectFile *pal;
-
-#ifndef NDEBUG
- /** Event to halt the simulator if the console calls panic() */
- BreakPCEvent *consolePanicEvent;
-#endif
- protected:
- const Params *params() const { return (const Params *)_params; }
-
- /** Add a function-based event to PALcode. */
- template <class T>
- T *AlphaSystem::addPalFuncEvent(const char *lbl)
- {
- return addFuncEvent<T>(palSymtab, lbl);
- }
-
- /** Add a function-based event to the console code. */
- template <class T>
- T *AlphaSystem::addConsoleFuncEvent(const char *lbl)
- {
- return addFuncEvent<T>(consoleSymtab, lbl);
- }
-
- virtual Addr fixFuncEventAddr(Addr addr);
-
-};
-
-#endif
-
diff --git a/arch/alpha/tlb.cc b/arch/alpha/tlb.cc
deleted file mode 100644
index 562235ef8..000000000
--- a/arch/alpha/tlb.cc
+++ /dev/null
@@ -1,643 +0,0 @@
-/*
- * Copyright (c) 2001-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <sstream>
-#include <string>
-#include <vector>
-
-#include "arch/alpha/tlb.hh"
-#include "base/inifile.hh"
-#include "base/str.hh"
-#include "base/trace.hh"
-#include "config/alpha_tlaser.hh"
-#include "cpu/exec_context.hh"
-#include "sim/builder.hh"
-
-using namespace std;
-using namespace EV5;
-
-///////////////////////////////////////////////////////////////////////
-//
-// Alpha TLB
-//
-#ifdef DEBUG
-bool uncacheBit39 = false;
-bool uncacheBit40 = false;
-#endif
-
-#define MODE2MASK(X) (1 << (X))
-
-AlphaTLB::AlphaTLB(const string &name, int s)
- : SimObject(name), size(s), nlu(0)
-{
- table = new AlphaISA::PTE[size];
- memset(table, 0, sizeof(AlphaISA::PTE[size]));
-}
-
-AlphaTLB::~AlphaTLB()
-{
- if (table)
- delete [] table;
-}
-
-// look up an entry in the TLB
-AlphaISA::PTE *
-AlphaTLB::lookup(Addr vpn, uint8_t asn) const
-{
- // assume not found...
- AlphaISA::PTE *retval = NULL;
-
- PageTable::const_iterator i = lookupTable.find(vpn);
- if (i != lookupTable.end()) {
- while (i->first == vpn) {
- int index = i->second;
- AlphaISA::PTE *pte = &table[index];
- assert(pte->valid);
- if (vpn == pte->tag && (pte->asma || pte->asn == asn)) {
- retval = pte;
- break;
- }
-
- ++i;
- }
- }
-
- DPRINTF(TLB, "lookup %#x, asn %#x -> %s ppn %#x\n", vpn, (int)asn,
- retval ? "hit" : "miss", retval ? retval->ppn : 0);
- return retval;
-}
-
-
-void
-AlphaTLB::checkCacheability(MemReqPtr &req)
-{
- // in Alpha, cacheability is controlled by upper-level bits of the
- // physical address
-
- /*
- * We support having the uncacheable bit in either bit 39 or bit 40.
- * The Turbolaser platform (and EV5) support having the bit in 39, but
- * Tsunami (which Linux assumes uses an EV6) generates accesses with
- * the bit in 40. So we must check for both, but we have debug flags
- * to catch a weird case where both are used, which shouldn't happen.
- */
-
-
-#if ALPHA_TLASER
- if (req->paddr & PAddrUncachedBit39) {
-#else
- if (req->paddr & 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);
- }
- }
- } else {
- // mark request as uncacheable
- req->flags |= UNCACHEABLE;
-
-#if !ALPHA_TLASER
- // Clear bits 42:35 of the physical address (10-2 in Tsunami manual)
- req->paddr &= PAddrUncachedMask;
-#endif
- }
- }
-}
-
-
-// insert a new TLB entry
-void
-AlphaTLB::insert(Addr addr, AlphaISA::PTE &pte)
-{
- AlphaISA::VAddr vaddr = addr;
- if (table[nlu].valid) {
- Addr oldvpn = table[nlu].tag;
- PageTable::iterator i = lookupTable.find(oldvpn);
-
- if (i == lookupTable.end())
- panic("TLB entry not found in lookupTable");
-
- int index;
- while ((index = i->second) != nlu) {
- if (table[index].tag != oldvpn)
- panic("TLB entry not found in lookupTable");
-
- ++i;
- }
-
- DPRINTF(TLB, "remove @%d: %#x -> %#x\n", nlu, oldvpn, table[nlu].ppn);
-
- lookupTable.erase(i);
- }
-
- DPRINTF(TLB, "insert @%d: %#x -> %#x\n", nlu, vaddr.vpn(), pte.ppn);
-
- table[nlu] = pte;
- table[nlu].tag = vaddr.vpn();
- table[nlu].valid = true;
-
- lookupTable.insert(make_pair(vaddr.vpn(), nlu));
- nextnlu();
-}
-
-void
-AlphaTLB::flushAll()
-{
- DPRINTF(TLB, "flushAll\n");
- memset(table, 0, sizeof(AlphaISA::PTE[size]));
- lookupTable.clear();
- nlu = 0;
-}
-
-void
-AlphaTLB::flushProcesses()
-{
- PageTable::iterator i = lookupTable.begin();
- PageTable::iterator end = lookupTable.end();
- while (i != end) {
- int index = i->second;
- AlphaISA::PTE *pte = &table[index];
- assert(pte->valid);
-
- // we can't increment i after we erase it, so save a copy and
- // increment it to get the next entry now
- PageTable::iterator cur = i;
- ++i;
-
- if (!pte->asma) {
- DPRINTF(TLB, "flush @%d: %#x -> %#x\n", index, pte->tag, pte->ppn);
- pte->valid = false;
- lookupTable.erase(cur);
- }
- }
-}
-
-void
-AlphaTLB::flushAddr(Addr addr, uint8_t asn)
-{
- AlphaISA::VAddr vaddr = addr;
-
- PageTable::iterator i = lookupTable.find(vaddr.vpn());
- if (i == lookupTable.end())
- return;
-
- while (i->first == vaddr.vpn()) {
- int index = i->second;
- AlphaISA::PTE *pte = &table[index];
- assert(pte->valid);
-
- if (vaddr.vpn() == pte->tag && (pte->asma || pte->asn == asn)) {
- DPRINTF(TLB, "flushaddr @%d: %#x -> %#x\n", index, vaddr.vpn(),
- pte->ppn);
-
- // invalidate this entry
- pte->valid = false;
-
- lookupTable.erase(i);
- }
-
- ++i;
- }
-}
-
-
-void
-AlphaTLB::serialize(ostream &os)
-{
- SERIALIZE_SCALAR(size);
- SERIALIZE_SCALAR(nlu);
-
- for (int i = 0; i < size; i++) {
- nameOut(os, csprintf("%s.PTE%d", name(), i));
- table[i].serialize(os);
- }
-}
-
-void
-AlphaTLB::unserialize(Checkpoint *cp, const string &section)
-{
- UNSERIALIZE_SCALAR(size);
- UNSERIALIZE_SCALAR(nlu);
-
- for (int i = 0; i < size; i++) {
- table[i].unserialize(cp, csprintf("%s.PTE%d", section, i));
- if (table[i].valid) {
- lookupTable.insert(make_pair(table[i].tag, i));
- }
- }
-}
-
-
-///////////////////////////////////////////////////////////////////////
-//
-// Alpha ITB
-//
-AlphaITB::AlphaITB(const std::string &name, int size)
- : AlphaTLB(name, size)
-{}
-
-
-void
-AlphaITB::regStats()
-{
- hits
- .name(name() + ".hits")
- .desc("ITB hits");
- misses
- .name(name() + ".misses")
- .desc("ITB misses");
- acv
- .name(name() + ".acv")
- .desc("ITB acv");
- accesses
- .name(name() + ".accesses")
- .desc("ITB accesses");
-
- accesses = hits + misses;
-}
-
-
-Fault
-AlphaITB::translate(MemReqPtr &req) const
-{
- ExecContext *xc = req->xc;
-
- if (AlphaISA::PcPAL(req->vaddr)) {
- // strip off PAL PC marker (lsb is 1)
- req->paddr = (req->vaddr & ~3) & PAddrImplMask;
- hits++;
- return NoFault;
- }
-
- if (req->flags & PHYSICAL) {
- req->paddr = req->vaddr;
- } else {
- // verify that this is a good virtual address
- if (!validVirtualAddress(req->vaddr)) {
- acv++;
- return new ItbAcvFault(req->vaddr);
- }
-
-
- // VA<42:41> == 2, VA<39:13> maps directly to PA<39:13> for EV5
- // VA<47:41> == 0x7e, VA<40:13> maps directly to PA<40:13> for EV6
-#if ALPHA_TLASER
- if ((MCSR_SP(xc->readMiscReg(AlphaISA::IPR_MCSR)) & 2) &&
- VAddrSpaceEV5(req->vaddr) == 2) {
-#else
- if (VAddrSpaceEV6(req->vaddr) == 0x7e) {
-#endif
- // only valid in kernel mode
- if (ICM_CM(xc->readMiscReg(AlphaISA::IPR_ICM)) !=
- AlphaISA::mode_kernel) {
- acv++;
- return new ItbAcvFault(req->vaddr);
- }
-
- req->paddr = req->vaddr & PAddrImplMask;
-
-#if !ALPHA_TLASER
- // sign extend the physical address properly
- if (req->paddr & PAddrUncachedBit40)
- req->paddr |= ULL(0xf0000000000);
- else
- req->paddr &= 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(),
- asn);
-
- if (!pte) {
- misses++;
- return new ItbPageFault(req->vaddr);
- }
-
- req->paddr = (pte->ppn << AlphaISA::PageShift) +
- (AlphaISA::VAddr(req->vaddr).offset() & ~3);
-
- // check permissions for this access
- if (!(pte->xre &
- (1 << ICM_CM(xc->readMiscReg(AlphaISA::IPR_ICM))))) {
- // instruction access fault
- acv++;
- return new ItbAcvFault(req->vaddr);
- }
-
- hits++;
- }
- }
-
- // check that the physical address is ok (catch bad physical addresses)
- if (req->paddr & ~PAddrImplMask)
- return genMachineCheckFault();
-
- checkCacheability(req);
-
- return NoFault;
-}
-
-///////////////////////////////////////////////////////////////////////
-//
-// Alpha DTB
-//
-AlphaDTB::AlphaDTB(const std::string &name, int size)
- : AlphaTLB(name, size)
-{}
-
-void
-AlphaDTB::regStats()
-{
- read_hits
- .name(name() + ".read_hits")
- .desc("DTB read hits")
- ;
-
- read_misses
- .name(name() + ".read_misses")
- .desc("DTB read misses")
- ;
-
- read_acv
- .name(name() + ".read_acv")
- .desc("DTB read access violations")
- ;
-
- read_accesses
- .name(name() + ".read_accesses")
- .desc("DTB read accesses")
- ;
-
- write_hits
- .name(name() + ".write_hits")
- .desc("DTB write hits")
- ;
-
- write_misses
- .name(name() + ".write_misses")
- .desc("DTB write misses")
- ;
-
- write_acv
- .name(name() + ".write_acv")
- .desc("DTB write access violations")
- ;
-
- write_accesses
- .name(name() + ".write_accesses")
- .desc("DTB write accesses")
- ;
-
- hits
- .name(name() + ".hits")
- .desc("DTB hits")
- ;
-
- misses
- .name(name() + ".misses")
- .desc("DTB misses")
- ;
-
- acv
- .name(name() + ".acv")
- .desc("DTB access violations")
- ;
-
- accesses
- .name(name() + ".accesses")
- .desc("DTB accesses")
- ;
-
- hits = read_hits + write_hits;
- misses = read_misses + write_misses;
- acv = read_acv + write_acv;
- accesses = read_accesses + write_accesses;
-}
-
-Fault
-AlphaDTB::translate(MemReqPtr &req, bool write) const
-{
- ExecContext *xc = req->xc;
- Addr pc = xc->readPC();
-
- AlphaISA::mode_type mode =
- (AlphaISA::mode_type)DTB_CM_CM(xc->readMiscReg(AlphaISA::IPR_DTB_CM));
-
-
- /**
- * Check for alignment faults
- */
- if (req->vaddr & (req->size - 1)) {
- DPRINTF(TLB, "Alignment Fault on %#x, size = %d", req->vaddr,
- req->size);
- uint64_t flags = write ? MM_STAT_WR_MASK : 0;
- return new DtbAlignmentFault(req->vaddr, req->flags, flags);
- }
-
- if (pc & 0x1) {
- mode = (req->flags & ALTMODE) ?
- (AlphaISA::mode_type)ALT_MODE_AM(
- xc->readMiscReg(AlphaISA::IPR_ALT_MODE))
- : AlphaISA::mode_kernel;
- }
-
- if (req->flags & PHYSICAL) {
- req->paddr = req->vaddr;
- } else {
- // verify that this is a good virtual address
- if (!validVirtualAddress(req->vaddr)) {
- if (write) { write_acv++; } else { read_acv++; }
- uint64_t flags = (write ? MM_STAT_WR_MASK : 0) |
- MM_STAT_BAD_VA_MASK |
- MM_STAT_ACV_MASK;
- return new DtbPageFault(req->vaddr, req->flags, flags);
- }
-
- // Check for "superpage" mapping
-#if ALPHA_TLASER
- if ((MCSR_SP(xc->readMiscReg(AlphaISA::IPR_MCSR)) & 2) &&
- VAddrSpaceEV5(req->vaddr) == 2) {
-#else
- if (VAddrSpaceEV6(req->vaddr) == 0x7e) {
-#endif
-
- // only valid in kernel mode
- if (DTB_CM_CM(xc->readMiscReg(AlphaISA::IPR_DTB_CM)) !=
- AlphaISA::mode_kernel) {
- if (write) { write_acv++; } else { read_acv++; }
- uint64_t flags = ((write ? MM_STAT_WR_MASK : 0) |
- MM_STAT_ACV_MASK);
- return new DtbAcvFault(req->vaddr, req->flags, flags);
- }
-
- req->paddr = req->vaddr & PAddrImplMask;
-
-#if !ALPHA_TLASER
- // sign extend the physical address properly
- if (req->paddr & PAddrUncachedBit40)
- req->paddr |= ULL(0xf0000000000);
- else
- req->paddr &= ULL(0xffffffffff);
-#endif
-
- } else {
- if (write)
- write_accesses++;
- else
- read_accesses++;
-
- int asn = DTB_ASN_ASN(xc->readMiscReg(AlphaISA::IPR_DTB_ASN));
-
- // not a physical address: need to look up pte
- AlphaISA::PTE *pte = lookup(AlphaISA::VAddr(req->vaddr).vpn(),
- asn);
-
- if (!pte) {
- // page fault
- if (write) { write_misses++; } else { read_misses++; }
- uint64_t flags = (write ? MM_STAT_WR_MASK : 0) |
- MM_STAT_DTB_MISS_MASK;
- return (req->flags & VPTE) ?
- (Fault)(new PDtbMissFault(req->vaddr, req->flags,
- flags)) :
- (Fault)(new NDtbMissFault(req->vaddr, req->flags,
- flags));
- }
-
- req->paddr = (pte->ppn << AlphaISA::PageShift) +
- AlphaISA::VAddr(req->vaddr).offset();
-
- if (write) {
- if (!(pte->xwe & MODE2MASK(mode))) {
- // declare the instruction access fault
- write_acv++;
- uint64_t flags = MM_STAT_WR_MASK |
- MM_STAT_ACV_MASK |
- (pte->fonw ? MM_STAT_FONW_MASK : 0);
- return new DtbPageFault(req->vaddr, req->flags, flags);
- }
- if (pte->fonw) {
- write_acv++;
- uint64_t flags = MM_STAT_WR_MASK |
- MM_STAT_FONW_MASK;
- return new DtbPageFault(req->vaddr, req->flags, flags);
- }
- } else {
- if (!(pte->xre & MODE2MASK(mode))) {
- read_acv++;
- uint64_t flags = MM_STAT_ACV_MASK |
- (pte->fonr ? MM_STAT_FONR_MASK : 0);
- return new DtbAcvFault(req->vaddr, req->flags, flags);
- }
- if (pte->fonr) {
- read_acv++;
- uint64_t flags = MM_STAT_FONR_MASK;
- return new DtbPageFault(req->vaddr, req->flags, flags);
- }
- }
- }
-
- if (write)
- write_hits++;
- else
- read_hits++;
- }
-
- // check that the physical address is ok (catch bad physical addresses)
- if (req->paddr & ~PAddrImplMask)
- return genMachineCheckFault();
-
- checkCacheability(req);
-
- return NoFault;
-}
-
-AlphaISA::PTE &
-AlphaTLB::index(bool advance)
-{
- AlphaISA::PTE *pte = &table[nlu];
-
- if (advance)
- nextnlu();
-
- return *pte;
-}
-
-DEFINE_SIM_OBJECT_CLASS_NAME("AlphaTLB", AlphaTLB)
-
-BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaITB)
-
- Param<int> size;
-
-END_DECLARE_SIM_OBJECT_PARAMS(AlphaITB)
-
-BEGIN_INIT_SIM_OBJECT_PARAMS(AlphaITB)
-
- INIT_PARAM_DFLT(size, "TLB size", 48)
-
-END_INIT_SIM_OBJECT_PARAMS(AlphaITB)
-
-
-CREATE_SIM_OBJECT(AlphaITB)
-{
- return new AlphaITB(getInstanceName(), size);
-}
-
-REGISTER_SIM_OBJECT("AlphaITB", AlphaITB)
-
-BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaDTB)
-
- Param<int> size;
-
-END_DECLARE_SIM_OBJECT_PARAMS(AlphaDTB)
-
-BEGIN_INIT_SIM_OBJECT_PARAMS(AlphaDTB)
-
- INIT_PARAM_DFLT(size, "TLB size", 64)
-
-END_INIT_SIM_OBJECT_PARAMS(AlphaDTB)
-
-
-CREATE_SIM_OBJECT(AlphaDTB)
-{
- return new AlphaDTB(getInstanceName(), size);
-}
-
-REGISTER_SIM_OBJECT("AlphaDTB", AlphaDTB)
-
diff --git a/arch/alpha/tlb.hh b/arch/alpha/tlb.hh
deleted file mode 100644
index 676345f01..000000000
--- a/arch/alpha/tlb.hh
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright (c) 2001-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __ALPHA_MEMORY_HH__
-#define __ALPHA_MEMORY_HH__
-
-#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 "sim/sim_object.hh"
-
-class ExecContext;
-
-class AlphaTLB : public SimObject
-{
- protected:
- typedef std::multimap<Addr, int> PageTable;
- PageTable lookupTable; // Quick lookup into page table
-
- AlphaISA::PTE *table; // the Page Table
- int size; // TLB Size
- int nlu; // not last used entry (for replacement)
-
- void nextnlu() { if (++nlu >= size) nlu = 0; }
- AlphaISA::PTE *lookup(Addr vpn, uint8_t asn) const;
-
- public:
- AlphaTLB(const std::string &name, int size);
- virtual ~AlphaTLB();
-
- int getsize() const { return size; }
-
- AlphaISA::PTE &index(bool advance = true);
- void insert(Addr vaddr, AlphaISA::PTE &pte);
-
- void flushAll();
- void flushProcesses();
- void flushAddr(Addr addr, uint8_t asn);
-
- // static helper functions... really EV5 VM traits
- static bool validVirtualAddress(Addr vaddr) {
- // unimplemented bits must be all 0 or all 1
- Addr unimplBits = vaddr & EV5::VAddrUnImplMask;
- return (unimplBits == 0) || (unimplBits == EV5::VAddrUnImplMask);
- }
-
- static void checkCacheability(MemReqPtr &req);
-
- // Checkpointing
- virtual void serialize(std::ostream &os);
- virtual void unserialize(Checkpoint *cp, const std::string &section);
-};
-
-class AlphaITB : public AlphaTLB
-{
- protected:
- mutable Stats::Scalar<> hits;
- mutable Stats::Scalar<> misses;
- mutable Stats::Scalar<> acv;
- mutable Stats::Formula accesses;
-
- public:
- AlphaITB(const std::string &name, int size);
- virtual void regStats();
-
- Fault translate(MemReqPtr &req) const;
-};
-
-class AlphaDTB : public AlphaTLB
-{
- protected:
- mutable Stats::Scalar<> read_hits;
- mutable Stats::Scalar<> read_misses;
- mutable Stats::Scalar<> read_acv;
- mutable Stats::Scalar<> read_accesses;
- mutable Stats::Scalar<> write_hits;
- mutable Stats::Scalar<> write_misses;
- mutable Stats::Scalar<> write_acv;
- mutable Stats::Scalar<> write_accesses;
- Stats::Formula hits;
- Stats::Formula misses;
- Stats::Formula acv;
- Stats::Formula accesses;
-
- public:
- AlphaDTB(const std::string &name, int size);
- virtual void regStats();
-
- Fault translate(MemReqPtr &req, bool write) const;
-};
-
-#endif // __ALPHA_MEMORY_HH__
diff --git a/arch/alpha/tru64/process.cc b/arch/alpha/tru64/process.cc
deleted file mode 100644
index ae83bb649..000000000
--- a/arch/alpha/tru64/process.cc
+++ /dev/null
@@ -1,542 +0,0 @@
-/*
- * Copyright (c) 2001-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "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"
-
-using namespace std;
-using namespace AlphaISA;
-
-/// Target uname() handler.
-static SyscallReturn
-unameFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
-{
- TypedBufferArg<Tru64::utsname> name(xc->getSyscallArg(0));
-
- strcpy(name->sysname, "OSF1");
- strcpy(name->nodename, "m5.eecs.umich.edu");
- strcpy(name->release, "V5.1");
- strcpy(name->version, "732");
- strcpy(name->machine, "alpha");
-
- name.copyOut(xc->getMemPtr());
- return 0;
-}
-
-/// Target getsysyinfo() handler.
-static SyscallReturn
-getsysinfoFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
-{
- unsigned op = xc->getSyscallArg(0);
- unsigned nbytes = xc->getSyscallArg(2);
-
- switch (op) {
-
- case Tru64::GSI_MAX_CPU: {
- TypedBufferArg<uint32_t> max_cpu(xc->getSyscallArg(1));
- *max_cpu = htog((uint32_t)process->numCpus());
- max_cpu.copyOut(xc->getMemPtr());
- return 1;
- }
-
- case Tru64::GSI_CPUS_IN_BOX: {
- TypedBufferArg<uint32_t> cpus_in_box(xc->getSyscallArg(1));
- *cpus_in_box = htog((uint32_t)process->numCpus());
- cpus_in_box.copyOut(xc->getMemPtr());
- return 1;
- }
-
- case Tru64::GSI_PHYSMEM: {
- TypedBufferArg<uint64_t> physmem(xc->getSyscallArg(1));
- *physmem = htog((uint64_t)1024 * 1024); // physical memory in KB
- physmem.copyOut(xc->getMemPtr());
- return 1;
- }
-
- case Tru64::GSI_CPU_INFO: {
- TypedBufferArg<Tru64::cpu_info> infop(xc->getSyscallArg(1));
-
- infop->current_cpu = htog(0);
- infop->cpus_in_box = htog(process->numCpus());
- infop->cpu_type = htog(57);
- infop->ncpus = htog(process->numCpus());
- uint64_t cpumask = (1 << process->numCpus()) - 1;
- infop->cpus_present = infop->cpus_running = htog(cpumask);
- infop->cpu_binding = htog(0);
- infop->cpu_ex_binding = htog(0);
- infop->mhz = htog(667);
-
- infop.copyOut(xc->getMemPtr());
- return 1;
- }
-
- case Tru64::GSI_PROC_TYPE: {
- TypedBufferArg<uint64_t> proc_type(xc->getSyscallArg(1));
- *proc_type = htog((uint64_t)11);
- proc_type.copyOut(xc->getMemPtr());
- return 1;
- }
-
- case Tru64::GSI_PLATFORM_NAME: {
- BufferArg bufArg(xc->getSyscallArg(1), nbytes);
- strncpy((char *)bufArg.bufferPtr(),
- "COMPAQ Professional Workstation XP1000",
- nbytes);
- bufArg.copyOut(xc->getMemPtr());
- return 1;
- }
-
- case Tru64::GSI_CLK_TCK: {
- TypedBufferArg<uint64_t> clk_hz(xc->getSyscallArg(1));
- *clk_hz = htog((uint64_t)1024);
- clk_hz.copyOut(xc->getMemPtr());
- return 1;
- }
-
- default:
- warn("getsysinfo: unknown op %d\n", op);
- break;
- }
-
- return 0;
-}
-
-/// Target setsysyinfo() handler.
-static SyscallReturn
-setsysinfoFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
-{
- unsigned op = xc->getSyscallArg(0);
-
- switch (op) {
- case Tru64::SSI_IEEE_FP_CONTROL:
- warn("setsysinfo: ignoring ieee_set_fp_control() arg 0x%x\n",
- xc->getSyscallArg(1));
- break;
-
- default:
- warn("setsysinfo: unknown op %d\n", op);
- break;
- }
-
- return 0;
-}
-
-
-SyscallDesc AlphaTru64Process::syscallDescs[] = {
- /* 0 */ SyscallDesc("syscall (#0)", Tru64::indirectSyscallFunc,
- SyscallDesc::SuppressReturnValue),
- /* 1 */ SyscallDesc("exit", exitFunc),
- /* 2 */ SyscallDesc("fork", unimplementedFunc),
- /* 3 */ SyscallDesc("read", readFunc),
- /* 4 */ SyscallDesc("write", writeFunc),
- /* 5 */ SyscallDesc("old_open", unimplementedFunc),
- /* 6 */ SyscallDesc("close", closeFunc),
- /* 7 */ SyscallDesc("wait4", unimplementedFunc),
- /* 8 */ SyscallDesc("old_creat", unimplementedFunc),
- /* 9 */ SyscallDesc("link", unimplementedFunc),
- /* 10 */ SyscallDesc("unlink", unlinkFunc),
- /* 11 */ SyscallDesc("execv", unimplementedFunc),
- /* 12 */ SyscallDesc("chdir", unimplementedFunc),
- /* 13 */ SyscallDesc("fchdir", unimplementedFunc),
- /* 14 */ SyscallDesc("mknod", unimplementedFunc),
- /* 15 */ SyscallDesc("chmod", unimplementedFunc),
- /* 16 */ SyscallDesc("chown", unimplementedFunc),
- /* 17 */ SyscallDesc("obreak", obreakFunc),
- /* 18 */ SyscallDesc("pre_F64_getfsstat", unimplementedFunc),
- /* 19 */ SyscallDesc("lseek", lseekFunc),
- /* 20 */ SyscallDesc("getpid", getpidPseudoFunc),
- /* 21 */ SyscallDesc("mount", unimplementedFunc),
- /* 22 */ SyscallDesc("unmount", unimplementedFunc),
- /* 23 */ SyscallDesc("setuid", setuidFunc),
- /* 24 */ SyscallDesc("getuid", getuidPseudoFunc),
- /* 25 */ SyscallDesc("exec_with_loader", unimplementedFunc),
- /* 26 */ SyscallDesc("ptrace", unimplementedFunc),
- /* 27 */ SyscallDesc("recvmsg", unimplementedFunc),
- /* 28 */ SyscallDesc("sendmsg", unimplementedFunc),
- /* 29 */ SyscallDesc("recvfrom", unimplementedFunc),
- /* 30 */ SyscallDesc("accept", unimplementedFunc),
- /* 31 */ SyscallDesc("getpeername", unimplementedFunc),
- /* 32 */ SyscallDesc("getsockname", unimplementedFunc),
- /* 33 */ SyscallDesc("access", unimplementedFunc),
- /* 34 */ SyscallDesc("chflags", unimplementedFunc),
- /* 35 */ SyscallDesc("fchflags", unimplementedFunc),
- /* 36 */ SyscallDesc("sync", unimplementedFunc),
- /* 37 */ SyscallDesc("kill", unimplementedFunc),
- /* 38 */ SyscallDesc("old_stat", unimplementedFunc),
- /* 39 */ SyscallDesc("setpgid", unimplementedFunc),
- /* 40 */ SyscallDesc("old_lstat", unimplementedFunc),
- /* 41 */ SyscallDesc("dup", unimplementedFunc),
- /* 42 */ SyscallDesc("pipe", unimplementedFunc),
- /* 43 */ SyscallDesc("set_program_attributes", unimplementedFunc),
- /* 44 */ SyscallDesc("profil", unimplementedFunc),
- /* 45 */ SyscallDesc("open", openFunc<Tru64>),
- /* 46 */ SyscallDesc("obsolete osigaction", unimplementedFunc),
- /* 47 */ SyscallDesc("getgid", getgidPseudoFunc),
- /* 48 */ SyscallDesc("sigprocmask", ignoreFunc),
- /* 49 */ SyscallDesc("getlogin", unimplementedFunc),
- /* 50 */ SyscallDesc("setlogin", unimplementedFunc),
- /* 51 */ SyscallDesc("acct", unimplementedFunc),
- /* 52 */ SyscallDesc("sigpending", unimplementedFunc),
- /* 53 */ SyscallDesc("classcntl", unimplementedFunc),
- /* 54 */ SyscallDesc("ioctl", ioctlFunc<Tru64>),
- /* 55 */ SyscallDesc("reboot", unimplementedFunc),
- /* 56 */ SyscallDesc("revoke", unimplementedFunc),
- /* 57 */ SyscallDesc("symlink", unimplementedFunc),
- /* 58 */ SyscallDesc("readlink", unimplementedFunc),
- /* 59 */ SyscallDesc("execve", unimplementedFunc),
- /* 60 */ SyscallDesc("umask", unimplementedFunc),
- /* 61 */ SyscallDesc("chroot", unimplementedFunc),
- /* 62 */ SyscallDesc("old_fstat", unimplementedFunc),
- /* 63 */ SyscallDesc("getpgrp", unimplementedFunc),
- /* 64 */ SyscallDesc("getpagesize", getpagesizeFunc),
- /* 65 */ SyscallDesc("mremap", unimplementedFunc),
- /* 66 */ SyscallDesc("vfork", unimplementedFunc),
- /* 67 */ SyscallDesc("pre_F64_stat", statFunc<Tru64::PreF64>),
- /* 68 */ SyscallDesc("pre_F64_lstat", lstatFunc<Tru64::PreF64>),
- /* 69 */ SyscallDesc("sbrk", unimplementedFunc),
- /* 70 */ SyscallDesc("sstk", unimplementedFunc),
- /* 71 */ SyscallDesc("mmap", mmapFunc<Tru64>),
- /* 72 */ SyscallDesc("ovadvise", unimplementedFunc),
- /* 73 */ SyscallDesc("munmap", munmapFunc),
- /* 74 */ SyscallDesc("mprotect", ignoreFunc),
- /* 75 */ SyscallDesc("madvise", unimplementedFunc),
- /* 76 */ SyscallDesc("old_vhangup", unimplementedFunc),
- /* 77 */ SyscallDesc("kmodcall", unimplementedFunc),
- /* 78 */ SyscallDesc("mincore", unimplementedFunc),
- /* 79 */ SyscallDesc("getgroups", unimplementedFunc),
- /* 80 */ SyscallDesc("setgroups", unimplementedFunc),
- /* 81 */ SyscallDesc("old_getpgrp", unimplementedFunc),
- /* 82 */ SyscallDesc("setpgrp", unimplementedFunc),
- /* 83 */ SyscallDesc("setitimer", unimplementedFunc),
- /* 84 */ SyscallDesc("old_wait", unimplementedFunc),
- /* 85 */ SyscallDesc("table", Tru64::tableFunc),
- /* 86 */ SyscallDesc("getitimer", unimplementedFunc),
- /* 87 */ SyscallDesc("gethostname", gethostnameFunc),
- /* 88 */ SyscallDesc("sethostname", unimplementedFunc),
- /* 89 */ SyscallDesc("getdtablesize", unimplementedFunc),
- /* 90 */ SyscallDesc("dup2", unimplementedFunc),
- /* 91 */ SyscallDesc("pre_F64_fstat", fstatFunc<Tru64::PreF64>),
- /* 92 */ SyscallDesc("fcntl", fcntlFunc),
- /* 93 */ SyscallDesc("select", unimplementedFunc),
- /* 94 */ SyscallDesc("poll", unimplementedFunc),
- /* 95 */ SyscallDesc("fsync", unimplementedFunc),
- /* 96 */ SyscallDesc("setpriority", unimplementedFunc),
- /* 97 */ SyscallDesc("socket", unimplementedFunc),
- /* 98 */ SyscallDesc("connect", unimplementedFunc),
- /* 99 */ SyscallDesc("old_accept", unimplementedFunc),
- /* 100 */ SyscallDesc("getpriority", unimplementedFunc),
- /* 101 */ SyscallDesc("old_send", unimplementedFunc),
- /* 102 */ SyscallDesc("old_recv", unimplementedFunc),
- /* 103 */ SyscallDesc("sigreturn", Tru64::sigreturnFunc,
- SyscallDesc::SuppressReturnValue),
- /* 104 */ SyscallDesc("bind", unimplementedFunc),
- /* 105 */ SyscallDesc("setsockopt", unimplementedFunc),
- /* 106 */ SyscallDesc("listen", unimplementedFunc),
- /* 107 */ SyscallDesc("plock", unimplementedFunc),
- /* 108 */ SyscallDesc("old_sigvec", unimplementedFunc),
- /* 109 */ SyscallDesc("old_sigblock", unimplementedFunc),
- /* 110 */ SyscallDesc("old_sigsetmask", unimplementedFunc),
- /* 111 */ SyscallDesc("sigsuspend", unimplementedFunc),
- /* 112 */ SyscallDesc("sigstack", ignoreFunc),
- /* 113 */ SyscallDesc("old_recvmsg", unimplementedFunc),
- /* 114 */ SyscallDesc("old_sendmsg", unimplementedFunc),
- /* 115 */ SyscallDesc("obsolete vtrace", unimplementedFunc),
- /* 116 */ SyscallDesc("gettimeofday", gettimeofdayFunc<Tru64>),
- /* 117 */ SyscallDesc("getrusage", getrusageFunc<Tru64>),
- /* 118 */ SyscallDesc("getsockopt", unimplementedFunc),
- /* 119 */ SyscallDesc("numa_syscalls", unimplementedFunc),
- /* 120 */ SyscallDesc("readv", unimplementedFunc),
- /* 121 */ SyscallDesc("writev", unimplementedFunc),
- /* 122 */ SyscallDesc("settimeofday", unimplementedFunc),
- /* 123 */ SyscallDesc("fchown", unimplementedFunc),
- /* 124 */ SyscallDesc("fchmod", unimplementedFunc),
- /* 125 */ SyscallDesc("old_recvfrom", unimplementedFunc),
- /* 126 */ SyscallDesc("setreuid", unimplementedFunc),
- /* 127 */ SyscallDesc("setregid", unimplementedFunc),
- /* 128 */ SyscallDesc("rename", renameFunc),
- /* 129 */ SyscallDesc("truncate", truncateFunc),
- /* 130 */ SyscallDesc("ftruncate", ftruncateFunc),
- /* 131 */ SyscallDesc("flock", unimplementedFunc),
- /* 132 */ SyscallDesc("setgid", unimplementedFunc),
- /* 133 */ SyscallDesc("sendto", unimplementedFunc),
- /* 134 */ SyscallDesc("shutdown", unimplementedFunc),
- /* 135 */ SyscallDesc("socketpair", unimplementedFunc),
- /* 136 */ SyscallDesc("mkdir", unimplementedFunc),
- /* 137 */ SyscallDesc("rmdir", unimplementedFunc),
- /* 138 */ SyscallDesc("utimes", unimplementedFunc),
- /* 139 */ SyscallDesc("obsolete 4.2 sigreturn", unimplementedFunc),
- /* 140 */ SyscallDesc("adjtime", unimplementedFunc),
- /* 141 */ SyscallDesc("old_getpeername", unimplementedFunc),
- /* 142 */ SyscallDesc("gethostid", unimplementedFunc),
- /* 143 */ SyscallDesc("sethostid", unimplementedFunc),
- /* 144 */ SyscallDesc("getrlimit", getrlimitFunc<Tru64>),
- /* 145 */ SyscallDesc("setrlimit", ignoreFunc),
- /* 146 */ SyscallDesc("old_killpg", unimplementedFunc),
- /* 147 */ SyscallDesc("setsid", unimplementedFunc),
- /* 148 */ SyscallDesc("quotactl", unimplementedFunc),
- /* 149 */ SyscallDesc("oldquota", unimplementedFunc),
- /* 150 */ SyscallDesc("old_getsockname", unimplementedFunc),
- /* 151 */ SyscallDesc("pread", unimplementedFunc),
- /* 152 */ SyscallDesc("pwrite", unimplementedFunc),
- /* 153 */ SyscallDesc("pid_block", unimplementedFunc),
- /* 154 */ SyscallDesc("pid_unblock", unimplementedFunc),
- /* 155 */ SyscallDesc("signal_urti", unimplementedFunc),
- /* 156 */ SyscallDesc("sigaction", ignoreFunc),
- /* 157 */ SyscallDesc("sigwaitprim", unimplementedFunc),
- /* 158 */ SyscallDesc("nfssvc", unimplementedFunc),
- /* 159 */ SyscallDesc("getdirentries", Tru64::getdirentriesFunc),
- /* 160 */ SyscallDesc("pre_F64_statfs", statfsFunc<Tru64::PreF64>),
- /* 161 */ SyscallDesc("pre_F64_fstatfs", fstatfsFunc<Tru64::PreF64>),
- /* 162 */ SyscallDesc("unknown #162", unimplementedFunc),
- /* 163 */ SyscallDesc("async_daemon", unimplementedFunc),
- /* 164 */ SyscallDesc("getfh", unimplementedFunc),
- /* 165 */ SyscallDesc("getdomainname", unimplementedFunc),
- /* 166 */ SyscallDesc("setdomainname", unimplementedFunc),
- /* 167 */ SyscallDesc("unknown #167", unimplementedFunc),
- /* 168 */ SyscallDesc("unknown #168", unimplementedFunc),
- /* 169 */ SyscallDesc("exportfs", unimplementedFunc),
- /* 170 */ SyscallDesc("unknown #170", unimplementedFunc),
- /* 171 */ SyscallDesc("unknown #171", unimplementedFunc),
- /* 172 */ SyscallDesc("unknown #172", unimplementedFunc),
- /* 173 */ SyscallDesc("unknown #173", unimplementedFunc),
- /* 174 */ SyscallDesc("unknown #174", unimplementedFunc),
- /* 175 */ SyscallDesc("unknown #175", unimplementedFunc),
- /* 176 */ SyscallDesc("unknown #176", unimplementedFunc),
- /* 177 */ SyscallDesc("unknown #177", unimplementedFunc),
- /* 178 */ SyscallDesc("unknown #178", unimplementedFunc),
- /* 179 */ SyscallDesc("unknown #179", unimplementedFunc),
- /* 180 */ SyscallDesc("unknown #180", unimplementedFunc),
- /* 181 */ SyscallDesc("alt_plock", unimplementedFunc),
- /* 182 */ SyscallDesc("unknown #182", unimplementedFunc),
- /* 183 */ SyscallDesc("unknown #183", unimplementedFunc),
- /* 184 */ SyscallDesc("getmnt", unimplementedFunc),
- /* 185 */ SyscallDesc("unknown #185", unimplementedFunc),
- /* 186 */ SyscallDesc("unknown #186", unimplementedFunc),
- /* 187 */ SyscallDesc("alt_sigpending", unimplementedFunc),
- /* 188 */ SyscallDesc("alt_setsid", unimplementedFunc),
- /* 189 */ SyscallDesc("unknown #189", unimplementedFunc),
- /* 190 */ SyscallDesc("unknown #190", unimplementedFunc),
- /* 191 */ SyscallDesc("unknown #191", unimplementedFunc),
- /* 192 */ SyscallDesc("unknown #192", unimplementedFunc),
- /* 193 */ SyscallDesc("unknown #193", unimplementedFunc),
- /* 194 */ SyscallDesc("unknown #194", unimplementedFunc),
- /* 195 */ SyscallDesc("unknown #195", unimplementedFunc),
- /* 196 */ SyscallDesc("unknown #196", unimplementedFunc),
- /* 197 */ SyscallDesc("unknown #197", unimplementedFunc),
- /* 198 */ SyscallDesc("unknown #198", unimplementedFunc),
- /* 199 */ SyscallDesc("swapon", unimplementedFunc),
- /* 200 */ SyscallDesc("msgctl", unimplementedFunc),
- /* 201 */ SyscallDesc("msgget", unimplementedFunc),
- /* 202 */ SyscallDesc("msgrcv", unimplementedFunc),
- /* 203 */ SyscallDesc("msgsnd", unimplementedFunc),
- /* 204 */ SyscallDesc("semctl", unimplementedFunc),
- /* 205 */ SyscallDesc("semget", unimplementedFunc),
- /* 206 */ SyscallDesc("semop", unimplementedFunc),
- /* 207 */ SyscallDesc("uname", unameFunc),
- /* 208 */ SyscallDesc("lchown", unimplementedFunc),
- /* 209 */ SyscallDesc("shmat", unimplementedFunc),
- /* 210 */ SyscallDesc("shmctl", unimplementedFunc),
- /* 211 */ SyscallDesc("shmdt", unimplementedFunc),
- /* 212 */ SyscallDesc("shmget", unimplementedFunc),
- /* 213 */ SyscallDesc("mvalid", unimplementedFunc),
- /* 214 */ SyscallDesc("getaddressconf", unimplementedFunc),
- /* 215 */ SyscallDesc("msleep", unimplementedFunc),
- /* 216 */ SyscallDesc("mwakeup", unimplementedFunc),
- /* 217 */ SyscallDesc("msync", unimplementedFunc),
- /* 218 */ SyscallDesc("signal", unimplementedFunc),
- /* 219 */ SyscallDesc("utc_gettime", unimplementedFunc),
- /* 220 */ SyscallDesc("utc_adjtime", unimplementedFunc),
- /* 221 */ SyscallDesc("unknown #221", unimplementedFunc),
- /* 222 */ SyscallDesc("security", unimplementedFunc),
- /* 223 */ SyscallDesc("kloadcall", unimplementedFunc),
- /* 224 */ SyscallDesc("stat", statFunc<Tru64::F64>),
- /* 225 */ SyscallDesc("lstat", lstatFunc<Tru64::F64>),
- /* 226 */ SyscallDesc("fstat", fstatFunc<Tru64::F64>),
- /* 227 */ SyscallDesc("statfs", statfsFunc<Tru64::F64>),
- /* 228 */ SyscallDesc("fstatfs", fstatfsFunc<Tru64::F64>),
- /* 229 */ SyscallDesc("getfsstat", unimplementedFunc),
- /* 230 */ SyscallDesc("gettimeofday64", unimplementedFunc),
- /* 231 */ SyscallDesc("settimeofday64", unimplementedFunc),
- /* 232 */ SyscallDesc("unknown #232", unimplementedFunc),
- /* 233 */ SyscallDesc("getpgid", unimplementedFunc),
- /* 234 */ SyscallDesc("getsid", unimplementedFunc),
- /* 235 */ SyscallDesc("sigaltstack", ignoreFunc),
- /* 236 */ SyscallDesc("waitid", unimplementedFunc),
- /* 237 */ SyscallDesc("priocntlset", unimplementedFunc),
- /* 238 */ SyscallDesc("sigsendset", unimplementedFunc),
- /* 239 */ SyscallDesc("set_speculative", unimplementedFunc),
- /* 240 */ SyscallDesc("msfs_syscall", unimplementedFunc),
- /* 241 */ SyscallDesc("sysinfo", unimplementedFunc),
- /* 242 */ SyscallDesc("uadmin", unimplementedFunc),
- /* 243 */ SyscallDesc("fuser", unimplementedFunc),
- /* 244 */ SyscallDesc("proplist_syscall", unimplementedFunc),
- /* 245 */ SyscallDesc("ntp_adjtime", unimplementedFunc),
- /* 246 */ SyscallDesc("ntp_gettime", unimplementedFunc),
- /* 247 */ SyscallDesc("pathconf", unimplementedFunc),
- /* 248 */ SyscallDesc("fpathconf", unimplementedFunc),
- /* 249 */ SyscallDesc("sync2", unimplementedFunc),
- /* 250 */ SyscallDesc("uswitch", unimplementedFunc),
- /* 251 */ SyscallDesc("usleep_thread", unimplementedFunc),
- /* 252 */ SyscallDesc("audcntl", unimplementedFunc),
- /* 253 */ SyscallDesc("audgen", unimplementedFunc),
- /* 254 */ SyscallDesc("sysfs", unimplementedFunc),
- /* 255 */ SyscallDesc("subsys_info", unimplementedFunc),
- /* 256 */ SyscallDesc("getsysinfo", getsysinfoFunc),
- /* 257 */ SyscallDesc("setsysinfo", setsysinfoFunc),
- /* 258 */ SyscallDesc("afs_syscall", unimplementedFunc),
- /* 259 */ SyscallDesc("swapctl", unimplementedFunc),
- /* 260 */ SyscallDesc("memcntl", unimplementedFunc),
- /* 261 */ SyscallDesc("fdatasync", unimplementedFunc),
- /* 262 */ SyscallDesc("oflock", unimplementedFunc),
- /* 263 */ SyscallDesc("F64_readv", unimplementedFunc),
- /* 264 */ SyscallDesc("F64_writev", unimplementedFunc),
- /* 265 */ SyscallDesc("cdslxlate", unimplementedFunc),
- /* 266 */ SyscallDesc("sendfile", unimplementedFunc),
-};
-
-
-
-SyscallDesc AlphaTru64Process::machSyscallDescs[] = {
- /* 0 */ SyscallDesc("kern_invalid", unimplementedFunc),
- /* 1 */ SyscallDesc("m5_mutex_lock", Tru64::m5_mutex_lockFunc),
- /* 2 */ SyscallDesc("m5_mutex_trylock", Tru64::m5_mutex_trylockFunc),
- /* 3 */ SyscallDesc("m5_mutex_unlock", Tru64::m5_mutex_unlockFunc),
- /* 4 */ SyscallDesc("m5_cond_signal", Tru64::m5_cond_signalFunc),
- /* 5 */ SyscallDesc("m5_cond_broadcast", Tru64::m5_cond_broadcastFunc),
- /* 6 */ SyscallDesc("m5_cond_wait", Tru64::m5_cond_waitFunc),
- /* 7 */ SyscallDesc("m5_thread_exit", Tru64::m5_thread_exitFunc),
- /* 8 */ SyscallDesc("kern_invalid", unimplementedFunc),
- /* 9 */ SyscallDesc("kern_invalid", unimplementedFunc),
- /* 10 */ SyscallDesc("task_self", unimplementedFunc),
- /* 11 */ SyscallDesc("thread_reply", unimplementedFunc),
- /* 12 */ SyscallDesc("task_notify", unimplementedFunc),
- /* 13 */ SyscallDesc("thread_self", unimplementedFunc),
- /* 14 */ SyscallDesc("kern_invalid", unimplementedFunc),
- /* 15 */ SyscallDesc("kern_invalid", unimplementedFunc),
- /* 16 */ SyscallDesc("kern_invalid", unimplementedFunc),
- /* 17 */ SyscallDesc("kern_invalid", unimplementedFunc),
- /* 18 */ SyscallDesc("kern_invalid", unimplementedFunc),
- /* 19 */ SyscallDesc("kern_invalid", unimplementedFunc),
- /* 20 */ SyscallDesc("msg_send_trap", unimplementedFunc),
- /* 21 */ SyscallDesc("msg_receive_trap", unimplementedFunc),
- /* 22 */ SyscallDesc("msg_rpc_trap", unimplementedFunc),
- /* 23 */ SyscallDesc("kern_invalid", unimplementedFunc),
- /* 24 */ SyscallDesc("nxm_block", Tru64::nxm_blockFunc),
- /* 25 */ SyscallDesc("nxm_unblock", Tru64::nxm_unblockFunc),
- /* 26 */ SyscallDesc("kern_invalid", unimplementedFunc),
- /* 27 */ SyscallDesc("kern_invalid", unimplementedFunc),
- /* 28 */ SyscallDesc("kern_invalid", unimplementedFunc),
- /* 29 */ SyscallDesc("nxm_thread_destroy", unimplementedFunc),
- /* 30 */ SyscallDesc("lw_wire", unimplementedFunc),
- /* 31 */ SyscallDesc("lw_unwire", unimplementedFunc),
- /* 32 */ SyscallDesc("nxm_thread_create", Tru64::nxm_thread_createFunc),
- /* 33 */ SyscallDesc("nxm_task_init", Tru64::nxm_task_initFunc),
- /* 34 */ SyscallDesc("kern_invalid", unimplementedFunc),
- /* 35 */ SyscallDesc("nxm_idle", Tru64::nxm_idleFunc),
- /* 36 */ SyscallDesc("nxm_wakeup_idle", unimplementedFunc),
- /* 37 */ SyscallDesc("nxm_set_pthid", unimplementedFunc),
- /* 38 */ SyscallDesc("nxm_thread_kill", unimplementedFunc),
- /* 39 */ SyscallDesc("nxm_thread_block", Tru64::nxm_thread_blockFunc),
- /* 40 */ SyscallDesc("nxm_thread_wakeup", unimplementedFunc),
- /* 41 */ SyscallDesc("init_process", unimplementedFunc),
- /* 42 */ SyscallDesc("nxm_get_binding", unimplementedFunc),
- /* 43 */ SyscallDesc("map_fd", unimplementedFunc),
- /* 44 */ SyscallDesc("nxm_resched", unimplementedFunc),
- /* 45 */ SyscallDesc("nxm_set_cancel", unimplementedFunc),
- /* 46 */ SyscallDesc("nxm_set_binding", unimplementedFunc),
- /* 47 */ SyscallDesc("stack_create", Tru64::stack_createFunc),
- /* 48 */ SyscallDesc("nxm_get_state", unimplementedFunc),
- /* 49 */ SyscallDesc("nxm_thread_suspend", unimplementedFunc),
- /* 50 */ SyscallDesc("nxm_thread_resume", unimplementedFunc),
- /* 51 */ SyscallDesc("nxm_signal_check", unimplementedFunc),
- /* 52 */ SyscallDesc("htg_unix_syscall", unimplementedFunc),
- /* 53 */ SyscallDesc("kern_invalid", unimplementedFunc),
- /* 54 */ SyscallDesc("kern_invalid", unimplementedFunc),
- /* 55 */ SyscallDesc("host_self", unimplementedFunc),
- /* 56 */ SyscallDesc("host_priv_self", unimplementedFunc),
- /* 57 */ SyscallDesc("kern_invalid", unimplementedFunc),
- /* 58 */ SyscallDesc("kern_invalid", unimplementedFunc),
- /* 59 */ SyscallDesc("swtch_pri", Tru64::swtch_priFunc),
- /* 60 */ SyscallDesc("swtch", unimplementedFunc),
- /* 61 */ SyscallDesc("thread_switch", unimplementedFunc),
- /* 62 */ SyscallDesc("semop_fast", unimplementedFunc),
- /* 63 */ SyscallDesc("nxm_pshared_init", unimplementedFunc),
- /* 64 */ SyscallDesc("nxm_pshared_block", unimplementedFunc),
- /* 65 */ SyscallDesc("nxm_pshared_unblock", unimplementedFunc),
- /* 66 */ SyscallDesc("nxm_pshared_destroy", unimplementedFunc),
- /* 67 */ SyscallDesc("nxm_swtch_pri", Tru64::swtch_priFunc),
- /* 68 */ SyscallDesc("lw_syscall", unimplementedFunc),
- /* 69 */ SyscallDesc("kern_invalid", unimplementedFunc),
- /* 70 */ SyscallDesc("mach_sctimes_0", unimplementedFunc),
- /* 71 */ SyscallDesc("mach_sctimes_1", unimplementedFunc),
- /* 72 */ SyscallDesc("mach_sctimes_2", unimplementedFunc),
- /* 73 */ SyscallDesc("mach_sctimes_3", unimplementedFunc),
- /* 74 */ SyscallDesc("mach_sctimes_4", unimplementedFunc),
- /* 75 */ SyscallDesc("mach_sctimes_5", unimplementedFunc),
- /* 76 */ SyscallDesc("mach_sctimes_6", unimplementedFunc),
- /* 77 */ SyscallDesc("mach_sctimes_7", unimplementedFunc),
- /* 78 */ SyscallDesc("mach_sctimes_8", unimplementedFunc),
- /* 79 */ SyscallDesc("mach_sctimes_9", unimplementedFunc),
- /* 80 */ SyscallDesc("mach_sctimes_10", unimplementedFunc),
- /* 81 */ SyscallDesc("mach_sctimes_11", unimplementedFunc),
- /* 82 */ SyscallDesc("mach_sctimes_port_alloc_dealloc", unimplementedFunc)
-};
-
-SyscallDesc*
-AlphaTru64Process::getDesc(int callnum)
-{
- if (callnum < -Num_Mach_Syscall_Descs || callnum > Num_Syscall_Descs)
- return NULL;
-
- if (callnum < 0)
- return &machSyscallDescs[-callnum];
- else
- return &syscallDescs[callnum];
-}
-
-
-AlphaTru64Process::AlphaTru64Process(const std::string &name,
- ObjectFile *objFile,
- int stdin_fd,
- int stdout_fd,
- int stderr_fd,
- std::vector<std::string> &argv,
- std::vector<std::string> &envp)
- : LiveProcess(name, objFile, stdin_fd, stdout_fd, stderr_fd, argv, envp),
- Num_Syscall_Descs(sizeof(syscallDescs) / sizeof(SyscallDesc)),
- Num_Mach_Syscall_Descs(sizeof(machSyscallDescs) / sizeof(SyscallDesc))
-{
-}
diff --git a/arch/alpha/tru64/process.hh b/arch/alpha/tru64/process.hh
deleted file mode 100644
index 051760702..000000000
--- a/arch/alpha/tru64/process.hh
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (c) 2003-2004 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __ALPHA_TRU64_PROCESS_HH__
-#define __ALPHA_TRU64_PROCESS_HH__
-
-#include "sim/process.hh"
-
-/// A process with emulated Alpha Tru64 syscalls.
-class AlphaTru64Process : public LiveProcess
-{
- public:
- /// Constructor.
- AlphaTru64Process(const std::string &name,
- ObjectFile *objFile,
- int stdin_fd, int stdout_fd, int stderr_fd,
- std::vector<std::string> &argv,
- std::vector<std::string> &envp);
-
- /// Array of syscall descriptors, indexed by call number.
- static SyscallDesc syscallDescs[];
-
- /// Array of mach syscall descriptors, indexed by call number.
- static SyscallDesc machSyscallDescs[];
-
- const int Num_Syscall_Descs;
- const int Num_Mach_Syscall_Descs;
-
- virtual SyscallDesc* getDesc(int callnum);
-};
-
-
-#endif // __ALPHA_TRU64_PROCESS_HH__
diff --git a/arch/alpha/tru64/system.cc b/arch/alpha/tru64/system.cc
deleted file mode 100644
index d09a0c85d..000000000
--- a/arch/alpha/tru64/system.cc
+++ /dev/null
@@ -1,159 +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/alpha/tru64/system.hh"
-#include "arch/isa_traits.hh"
-#include "arch/vtophys.hh"
-#include "base/loader/symtab.hh"
-#include "base/trace.hh"
-#include "cpu/base.hh"
-#include "cpu/exec_context.hh"
-#include "kern/tru64/tru64_events.hh"
-#include "kern/system_events.hh"
-#include "mem/functional/memory_control.hh"
-#include "mem/functional/physical.hh"
-#include "sim/builder.hh"
-
-using namespace std;
-
-Tru64AlphaSystem::Tru64AlphaSystem(Tru64AlphaSystem::Params *p)
- : AlphaSystem(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;
- }
-
-#ifdef DEBUG
- kernelPanicEvent = addKernelFuncEvent<BreakPCEvent>("panic");
- if (!kernelPanicEvent)
- panic("could not find kernel symbol \'panic\'");
-#endif
-
- badaddrEvent = addKernelFuncEvent<BadAddrEvent>("badaddr");
- if (!badaddrEvent)
- panic("could not find kernel symbol \'badaddr\'");
-
- skipPowerStateEvent =
- addKernelFuncEvent<SkipFuncEvent>("tl_v48_capture_power_state");
- skipScavengeBootEvent =
- addKernelFuncEvent<SkipFuncEvent>("pmap_scavenge_boot");
-
-#if TRACING_ON
- printfEvent = addKernelFuncEvent<PrintfEvent>("printf");
- debugPrintfEvent = addKernelFuncEvent<DebugPrintfEvent>("m5printf");
- debugPrintfrEvent = addKernelFuncEvent<DebugPrintfrEvent>("m5printfr");
- dumpMbufEvent = addKernelFuncEvent<DumpMbufEvent>("m5_dump_mbuf");
-#endif
-}
-
-Tru64AlphaSystem::~Tru64AlphaSystem()
-{
-#ifdef DEBUG
- delete kernelPanicEvent;
-#endif
- delete badaddrEvent;
- delete skipPowerStateEvent;
- delete skipScavengeBootEvent;
-#if TRACING_ON
- delete printfEvent;
- delete debugPrintfEvent;
- delete debugPrintfrEvent;
- delete dumpMbufEvent;
-#endif
-}
-
-BEGIN_DECLARE_SIM_OBJECT_PARAMS(Tru64AlphaSystem)
-
- Param<Tick> boot_cpu_frequency;
- SimObjectParam<MemoryController *> memctrl;
- SimObjectParam<PhysicalMemory *> physmem;
-
- Param<string> kernel;
- Param<string> console;
- Param<string> pal;
-
- Param<string> boot_osflags;
- Param<string> readfile;
- Param<unsigned int> init_param;
-
- Param<uint64_t> system_type;
- Param<uint64_t> system_rev;
-
- Param<bool> bin;
- VectorParam<string> binned_fns;
-
-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"),
- INIT_PARAM(pal, "file that contains palcode"),
- INIT_PARAM_DFLT(boot_osflags, "flags to pass to the kernel during boot",
- "a"),
- INIT_PARAM_DFLT(readfile, "file to read startup script from", ""),
- INIT_PARAM_DFLT(init_param, "numerical value to pass into simulator", 0),
- INIT_PARAM_DFLT(system_type, "Type of system we are emulating", 12),
- INIT_PARAM_DFLT(system_rev, "Revision of system we are emulating", 2<<1),
- INIT_PARAM_DFLT(bin, "is this system to be binned", false),
- INIT_PARAM(binned_fns, "functions to be broken down and binned")
-
-END_INIT_SIM_OBJECT_PARAMS(Tru64AlphaSystem)
-
-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;
- p->palcode = pal;
- p->boot_osflags = boot_osflags;
- p->init_param = init_param;
- p->readfile = readfile;
- p->system_type = system_type;
- p->system_rev = system_rev;
- p->bin = bin;
- p->binned_fns = binned_fns;
- p->bin_int = false;
-
- return new Tru64AlphaSystem(p);
-}
-
-REGISTER_SIM_OBJECT("Tru64AlphaSystem", Tru64AlphaSystem)
diff --git a/arch/alpha/vtophys.cc b/arch/alpha/vtophys.cc
deleted file mode 100644
index 40261426d..000000000
--- a/arch/alpha/vtophys.cc
+++ /dev/null
@@ -1,268 +0,0 @@
-/*
- * 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 <string>
-
-#include "arch/alpha/vtophys.hh"
-#include "base/trace.hh"
-#include "cpu/exec_context.hh"
-#include "mem/functional/physical.hh"
-
-using namespace std;
-using namespace AlphaISA;
-
-AlphaISA::PageTableEntry
-kernel_pte_lookup(PhysicalMemory *pmem, Addr ptbr, AlphaISA::VAddr vaddr)
-{
- Addr level1_pte = ptbr + vaddr.level1();
- AlphaISA::PageTableEntry level1 = pmem->phys_read_qword(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);
- 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);
- if (!level3.valid()) {
- DPRINTF(VtoPhys, "level 3 PTE not valid, va = %#x\n", vaddr);
- return 0;
- }
- return level3;
-}
-
-Addr
-vtophys(PhysicalMemory *xc, Addr vaddr)
-{
- Addr paddr = 0;
- if (AlphaISA::IsUSeg(vaddr))
- DPRINTF(VtoPhys, "vtophys: invalid vaddr %#x", vaddr);
- else if (AlphaISA::IsK0Seg(vaddr))
- paddr = AlphaISA::K0Seg2Phys(vaddr);
- else
- panic("vtophys: ptbr is not set on virtual lookup");
-
- DPRINTF(VtoPhys, "vtophys(%#x) -> %#x\n", vaddr, paddr);
-
- return paddr;
-}
-
-Addr
-vtophys(ExecContext *xc, Addr addr)
-{
- AlphaISA::VAddr vaddr = addr;
- Addr ptbr = xc->readMiscReg(AlphaISA::IPR_PALtemp20);
- Addr paddr = 0;
- //@todo Andrew couldn't remember why he commented some of this code
- //so I put it back in. Perhaps something to do with gdb debugging?
- if (AlphaISA::PcPAL(vaddr) && (vaddr < EV5::PalMax)) {
- paddr = vaddr & ~ULL(1);
- } else {
- if (AlphaISA::IsK0Seg(vaddr)) {
- paddr = AlphaISA::K0Seg2Phys(vaddr);
- } else if (!ptbr) {
- paddr = vaddr;
- } else {
- AlphaISA::PageTableEntry pte =
- kernel_pte_lookup(xc->getPhysMemPtr(), ptbr, vaddr);
- if (pte.valid())
- paddr = pte.paddr() | vaddr.offset();
- }
- }
-
-
- DPRINTF(VtoPhys, "vtophys(%#x) -> %#x\n", vaddr, paddr);
-
- 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)
-{
- Addr paddr;
- char *dmaaddr;
- char *dst = (char *)dest;
- int len;
-
- paddr = vtophys(xc, src);
- len = min((int)(AlphaISA::PageBytes - (paddr & AlphaISA::PageOffset)),
- (int)cplen);
- dmaaddr = (char *)xc->getPhysMemPtr()->dma_addr(paddr, len);
- assert(dmaaddr);
-
- 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;
- }
-
- 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)
-{
- 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;
- }
-
- if (cplen > 0) {
- paddr = vtophys(xc, dest);
- dmaaddr = (char *)xc->getPhysMemPtr()->dma_addr(paddr, cplen);
- assert(dmaaddr);
-
- memcpy(dmaaddr, src, cplen);
- }
-}
-
-void
-CopyString(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;
-
- memcpy(dst, dmaaddr, len);
- if (term)
- return;
-
- 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);
-
- maxlen -= len;
- }
-
- if (maxlen == 0)
- dst[maxlen] = '\0';
-}
diff --git a/arch/alpha/vtophys.hh b/arch/alpha/vtophys.hh
deleted file mode 100644
index 95430ce77..000000000
--- a/arch/alpha/vtophys.hh
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (c) 2002-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __ARCH_ALPHA_VTOPHYS_H__
-#define __ARCH_ALPHA_VTOPHYS_H__
-
-#include "arch/alpha/isa_traits.hh"
-
-class ExecContext;
-class PhysicalMemory;
-
-AlphaISA::PageTableEntry
-kernel_pte_lookup(PhysicalMemory *pmem, Addr ptbr, AlphaISA::VAddr vaddr);
-
-Addr vtophys(PhysicalMemory *xc, 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);
-
-#endif // __ARCH_ALPHA_VTOPHYS_H__
-
diff --git a/arch/isa_parser.py b/arch/isa_parser.py
deleted file mode 100755
index b0f10783f..000000000
--- a/arch/isa_parser.py
+++ /dev/null
@@ -1,1772 +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.
-
-import os
-import sys
-import re
-import string
-import traceback
-# get type names
-from types import *
-
-# Prepend the directory where the PLY lex & yacc modules are found
-# to the search path. Assumes we're compiling in a subdirectory
-# of 'build' in the current tree.
-sys.path[0:0] = [os.environ['M5_EXT'] + '/ply']
-
-import lex
-import yacc
-
-#####################################################################
-#
-# Lexer
-#
-# The PLY lexer module takes two things as input:
-# - A list of token names (the string list 'tokens')
-# - A regular expression describing a match for each token. The
-# regexp for token FOO can be provided in two ways:
-# - as a string variable named t_FOO
-# - as the doc string for a function named t_FOO. In this case,
-# the function is also executed, allowing an action to be
-# associated with each token match.
-#
-#####################################################################
-
-# Reserved words. These are listed separately as they are matched
-# using the same regexp as generic IDs, but distinguished in the
-# t_ID() function. The PLY documentation suggests this approach.
-reserved = (
- 'BITFIELD', 'DECODE', 'DECODER', 'DEFAULT', 'DEF', 'EXEC', 'FORMAT',
- 'HEADER', 'LET', 'NAMESPACE', 'OPERAND_TYPES', 'OPERANDS',
- 'OUTPUT', 'SIGNED', 'TEMPLATE'
- )
-
-# List of tokens. The lex module requires this.
-tokens = reserved + (
- # identifier
- 'ID',
-
- # integer literal
- 'INTLIT',
-
- # string literal
- 'STRLIT',
-
- # code literal
- 'CODELIT',
-
- # ( ) [ ] { } < > , ; : :: *
- 'LPAREN', 'RPAREN',
- 'LBRACKET', 'RBRACKET',
- 'LBRACE', 'RBRACE',
- 'LESS', 'GREATER', 'EQUALS',
- 'COMMA', 'SEMI', 'COLON', 'DBLCOLON',
- 'ASTERISK',
-
- # C preprocessor directives
- 'CPPDIRECTIVE'
-
-# The following are matched but never returned. commented out to
-# suppress PLY warning
- # newfile directive
-# 'NEWFILE',
-
- # endfile directive
-# 'ENDFILE'
-)
-
-# Regular expressions for token matching
-t_LPAREN = r'\('
-t_RPAREN = r'\)'
-t_LBRACKET = r'\['
-t_RBRACKET = r'\]'
-t_LBRACE = r'\{'
-t_RBRACE = r'\}'
-t_LESS = r'\<'
-t_GREATER = r'\>'
-t_EQUALS = r'='
-t_COMMA = r','
-t_SEMI = r';'
-t_COLON = r':'
-t_DBLCOLON = r'::'
-t_ASTERISK = r'\*'
-
-# Identifiers and reserved words
-reserved_map = { }
-for r in reserved:
- reserved_map[r.lower()] = r
-
-def t_ID(t):
- r'[A-Za-z_]\w*'
- t.type = reserved_map.get(t.value,'ID')
- return t
-
-# Integer literal
-def t_INTLIT(t):
- r'(0x[\da-fA-F]+)|\d+'
- try:
- t.value = int(t.value,0)
- except ValueError:
- error(t.lineno, 'Integer value "%s" too large' % t.value)
- t.value = 0
- return t
-
-# String literal. Note that these use only single quotes, and
-# can span multiple lines.
-def t_STRLIT(t):
- r"(?m)'([^'])+'"
- # strip off quotes
- t.value = t.value[1:-1]
- t.lineno += t.value.count('\n')
- return t
-
-
-# "Code literal"... like a string literal, but delimiters are
-# '{{' and '}}' so they get formatted nicely under emacs c-mode
-def t_CODELIT(t):
- r"(?m)\{\{([^\}]|}(?!\}))+\}\}"
- # strip off {{ & }}
- t.value = t.value[2:-2]
- t.lineno += t.value.count('\n')
- return t
-
-def t_CPPDIRECTIVE(t):
- r'^\#[^\#].*\n'
- t.lineno += t.value.count('\n')
- return t
-
-def t_NEWFILE(t):
- r'^\#\#newfile\s+"[\w/.-]*"'
- fileNameStack.push((t.value[11:-1], t.lineno))
- t.lineno = 0
-
-def t_ENDFILE(t):
- r'^\#\#endfile'
- (old_filename, t.lineno) = fileNameStack.pop()
-
-#
-# The functions t_NEWLINE, t_ignore, and t_error are
-# special for the lex module.
-#
-
-# Newlines
-def t_NEWLINE(t):
- r'\n+'
- t.lineno += t.value.count('\n')
-
-# Comments
-def t_comment(t):
- r'//.*'
-
-# Completely ignored characters
-t_ignore = ' \t\x0c'
-
-# Error handler
-def t_error(t):
- error(t.lineno, "illegal character '%s'" % t.value[0])
- t.skip(1)
-
-# Build the lexer
-lex.lex()
-
-#####################################################################
-#
-# Parser
-#
-# Every function whose name starts with 'p_' defines a grammar rule.
-# The rule is encoded in the function's doc string, while the
-# function body provides the action taken when the rule is matched.
-# The argument to each function is a list of the values of the
-# rule's symbols: t[0] for the LHS, and t[1..n] for the symbols
-# on the RHS. For tokens, the value is copied from the t.value
-# attribute provided by the lexer. For non-terminals, the value
-# is assigned by the producing rule; i.e., the job of the grammar
-# rule function is to set the value for the non-terminal on the LHS
-# (by assigning to t[0]).
-#####################################################################
-
-# The LHS of the first grammar rule is used as the start symbol
-# (in this case, 'specification'). Note that this rule enforces
-# that there will be exactly one namespace declaration, with 0 or more
-# global defs/decls before and after it. The defs & decls before
-# the namespace decl will be outside the namespace; those after
-# will be inside. The decoder function is always inside the namespace.
-def p_specification(t):
- 'specification : opt_defs_and_outputs name_decl opt_defs_and_outputs decode_block'
- global_code = t[1]
- isa_name = t[2]
- namespace = isa_name + "Inst"
- # wrap the decode block as a function definition
- t[4].wrap_decode_block('''
-StaticInstPtr
-%(isa_name)s::decodeInst(%(isa_name)s::ExtMachInst machInst)
-{
- using namespace %(namespace)s;
-''' % vars(), '}')
- # both the latter output blocks and the decode block are in the namespace
- namespace_code = t[3] + t[4]
- # pass it all back to the caller of yacc.parse()
- t[0] = (isa_name, namespace, global_code, namespace_code)
-
-# ISA name declaration looks like "namespace <foo>;"
-def p_name_decl(t):
- 'name_decl : NAMESPACE ID SEMI'
- t[0] = t[2]
-
-# 'opt_defs_and_outputs' is a possibly empty sequence of
-# def and/or output statements.
-def p_opt_defs_and_outputs_0(t):
- 'opt_defs_and_outputs : empty'
- t[0] = GenCode()
-
-def p_opt_defs_and_outputs_1(t):
- 'opt_defs_and_outputs : defs_and_outputs'
- t[0] = t[1]
-
-def p_defs_and_outputs_0(t):
- 'defs_and_outputs : def_or_output'
- t[0] = t[1]
-
-def p_defs_and_outputs_1(t):
- 'defs_and_outputs : defs_and_outputs def_or_output'
- t[0] = t[1] + t[2]
-
-# The list of possible definition/output statements.
-def p_def_or_output(t):
- '''def_or_output : def_format
- | def_bitfield
- | def_template
- | def_operand_types
- | def_operands
- | output_header
- | output_decoder
- | output_exec
- | global_let'''
- t[0] = t[1]
-
-# Output blocks 'output <foo> {{...}}' (C++ code blocks) are copied
-# directly to the appropriate output section.
-
-
-# Protect any non-dict-substitution '%'s in a format string
-# (i.e. those not followed by '(')
-def protect_non_subst_percents(s):
- return re.sub(r'%(?!\()', '%%', s)
-
-# Massage output block by substituting in template definitions and bit
-# operators. We handle '%'s embedded in the string that don't
-# indicate template substitutions (or CPU-specific symbols, which get
-# handled in GenCode) by doubling them first so that the format
-# operation will reduce them back to single '%'s.
-def process_output(s):
- s = protect_non_subst_percents(s)
- # protects cpu-specific symbols too
- s = protect_cpu_symbols(s)
- return substBitOps(s % templateMap)
-
-def p_output_header(t):
- 'output_header : OUTPUT HEADER CODELIT SEMI'
- t[0] = GenCode(header_output = process_output(t[3]))
-
-def p_output_decoder(t):
- 'output_decoder : OUTPUT DECODER CODELIT SEMI'
- t[0] = GenCode(decoder_output = process_output(t[3]))
-
-def p_output_exec(t):
- 'output_exec : OUTPUT EXEC CODELIT SEMI'
- t[0] = GenCode(exec_output = process_output(t[3]))
-
-# global let blocks 'let {{...}}' (Python code blocks) are executed
-# directly when seen. Note that these execute in a special variable
-# context 'exportContext' to prevent the code from polluting this
-# script's namespace.
-def p_global_let(t):
- 'global_let : LET CODELIT SEMI'
- updateExportContext()
- try:
- exec fixPythonIndentation(t[2]) in exportContext
- except Exception, exc:
- error(t.lineno(1),
- 'error: %s in global let block "%s".' % (exc, t[2]))
- t[0] = GenCode() # contributes nothing to the output C++ file
-
-# Define the mapping from operand type extensions to C++ types and bit
-# widths (stored in operandTypeMap).
-def p_def_operand_types(t):
- 'def_operand_types : DEF OPERAND_TYPES CODELIT SEMI'
- try:
- userDict = eval('{' + t[3] + '}')
- except Exception, exc:
- error(t.lineno(1),
- 'error: %s in def operand_types block "%s".' % (exc, t[3]))
- buildOperandTypeMap(userDict, t.lineno(1))
- t[0] = GenCode() # contributes nothing to the output C++ file
-
-# Define the mapping from operand names to operand classes and other
-# traits. Stored in operandNameMap.
-def p_def_operands(t):
- 'def_operands : DEF OPERANDS CODELIT SEMI'
- if not globals().has_key('operandTypeMap'):
- error(t.lineno(1),
- 'error: operand types must be defined before operands')
- try:
- userDict = eval('{' + t[3] + '}')
- except Exception, exc:
- error(t.lineno(1),
- 'error: %s in def operands block "%s".' % (exc, t[3]))
- buildOperandNameMap(userDict, t.lineno(1))
- t[0] = GenCode() # contributes nothing to the output C++ file
-
-# A bitfield definition looks like:
-# 'def [signed] bitfield <ID> [<first>:<last>]'
-# This generates a preprocessor macro in the output file.
-def p_def_bitfield_0(t):
- 'def_bitfield : DEF opt_signed BITFIELD ID LESS INTLIT COLON INTLIT GREATER SEMI'
- expr = 'bits(machInst, %2d, %2d)' % (t[6], t[8])
- if (t[2] == 'signed'):
- expr = 'sext<%d>(%s)' % (t[6] - t[8] + 1, expr)
- hash_define = '#undef %s\n#define %s\t%s\n' % (t[4], t[4], expr)
- t[0] = GenCode(header_output = hash_define)
-
-# alternate form for single bit: 'def [signed] bitfield <ID> [<bit>]'
-def p_def_bitfield_1(t):
- 'def_bitfield : DEF opt_signed BITFIELD ID LESS INTLIT GREATER SEMI'
- expr = 'bits(machInst, %2d, %2d)' % (t[6], t[6])
- if (t[2] == 'signed'):
- expr = 'sext<%d>(%s)' % (1, expr)
- hash_define = '#undef %s\n#define %s\t%s\n' % (t[4], t[4], expr)
- t[0] = GenCode(header_output = hash_define)
-
-def p_opt_signed_0(t):
- 'opt_signed : SIGNED'
- t[0] = t[1]
-
-def p_opt_signed_1(t):
- 'opt_signed : empty'
- t[0] = ''
-
-# Global map variable to hold templates
-templateMap = {}
-
-def p_def_template(t):
- 'def_template : DEF TEMPLATE ID CODELIT SEMI'
- templateMap[t[3]] = Template(t[4])
- t[0] = GenCode()
-
-# An instruction format definition looks like
-# "def format <fmt>(<params>) {{...}};"
-def p_def_format(t):
- 'def_format : DEF FORMAT ID LPAREN param_list RPAREN CODELIT SEMI'
- (id, params, code) = (t[3], t[5], t[7])
- defFormat(id, params, code, t.lineno(1))
- t[0] = GenCode()
-
-# The formal parameter list for an instruction format is a possibly
-# empty list of comma-separated parameters. Positional (standard,
-# non-keyword) parameters must come first, followed by keyword
-# parameters, followed by a '*foo' parameter that gets excess
-# positional arguments (as in Python). Each of these three parameter
-# categories is optional.
-#
-# Note that we do not support the '**foo' parameter for collecting
-# otherwise undefined keyword args. Otherwise the parameter list is
-# (I believe) identical to what is supported in Python.
-#
-# The param list generates a tuple, where the first element is a list of
-# the positional params and the second element is a dict containing the
-# keyword params.
-def p_param_list_0(t):
- 'param_list : positional_param_list COMMA nonpositional_param_list'
- t[0] = t[1] + t[3]
-
-def p_param_list_1(t):
- '''param_list : positional_param_list
- | nonpositional_param_list'''
- t[0] = t[1]
-
-def p_positional_param_list_0(t):
- 'positional_param_list : empty'
- t[0] = []
-
-def p_positional_param_list_1(t):
- 'positional_param_list : ID'
- t[0] = [t[1]]
-
-def p_positional_param_list_2(t):
- 'positional_param_list : positional_param_list COMMA ID'
- t[0] = t[1] + [t[3]]
-
-def p_nonpositional_param_list_0(t):
- 'nonpositional_param_list : keyword_param_list COMMA excess_args_param'
- t[0] = t[1] + t[3]
-
-def p_nonpositional_param_list_1(t):
- '''nonpositional_param_list : keyword_param_list
- | excess_args_param'''
- t[0] = t[1]
-
-def p_keyword_param_list_0(t):
- 'keyword_param_list : keyword_param'
- t[0] = [t[1]]
-
-def p_keyword_param_list_1(t):
- 'keyword_param_list : keyword_param_list COMMA keyword_param'
- t[0] = t[1] + [t[3]]
-
-def p_keyword_param(t):
- 'keyword_param : ID EQUALS expr'
- t[0] = t[1] + ' = ' + t[3].__repr__()
-
-def p_excess_args_param(t):
- 'excess_args_param : ASTERISK ID'
- # Just concatenate them: '*ID'. Wrap in list to be consistent
- # with positional_param_list and keyword_param_list.
- t[0] = [t[1] + t[2]]
-
-# End of format definition-related rules.
-##############
-
-#
-# A decode block looks like:
-# decode <field1> [, <field2>]* [default <inst>] { ... }
-#
-def p_decode_block(t):
- 'decode_block : DECODE ID opt_default LBRACE decode_stmt_list RBRACE'
- default_defaults = defaultStack.pop()
- codeObj = t[5]
- # use the "default defaults" only if there was no explicit
- # default statement in decode_stmt_list
- if not codeObj.has_decode_default:
- codeObj += default_defaults
- codeObj.wrap_decode_block('switch (%s) {\n' % t[2], '}\n')
- t[0] = codeObj
-
-# The opt_default statement serves only to push the "default defaults"
-# onto defaultStack. This value will be used by nested decode blocks,
-# and used and popped off when the current decode_block is processed
-# (in p_decode_block() above).
-def p_opt_default_0(t):
- 'opt_default : empty'
- # no default specified: reuse the one currently at the top of the stack
- defaultStack.push(defaultStack.top())
- # no meaningful value returned
- t[0] = None
-
-def p_opt_default_1(t):
- 'opt_default : DEFAULT inst'
- # push the new default
- codeObj = t[2]
- codeObj.wrap_decode_block('\ndefault:\n', 'break;\n')
- defaultStack.push(codeObj)
- # no meaningful value returned
- t[0] = None
-
-def p_decode_stmt_list_0(t):
- 'decode_stmt_list : decode_stmt'
- t[0] = t[1]
-
-def p_decode_stmt_list_1(t):
- 'decode_stmt_list : decode_stmt decode_stmt_list'
- if (t[1].has_decode_default and t[2].has_decode_default):
- error(t.lineno(1), 'Two default cases in decode block')
- t[0] = t[1] + t[2]
-
-#
-# Decode statement rules
-#
-# There are four types of statements allowed in a decode block:
-# 1. Format blocks 'format <foo> { ... }'
-# 2. Nested decode blocks
-# 3. Instruction definitions.
-# 4. C preprocessor directives.
-
-
-# Preprocessor directives found in a decode statement list are passed
-# through to the output, replicated to all of the output code
-# streams. This works well for ifdefs, so we can ifdef out both the
-# declarations and the decode cases generated by an instruction
-# definition. Handling them as part of the grammar makes it easy to
-# keep them in the right place with respect to the code generated by
-# the other statements.
-def p_decode_stmt_cpp(t):
- 'decode_stmt : CPPDIRECTIVE'
- t[0] = GenCode(t[1], t[1], t[1], t[1])
-
-# A format block 'format <foo> { ... }' sets the default instruction
-# format used to handle instruction definitions inside the block.
-# This format can be overridden by using an explicit format on the
-# instruction definition or with a nested format block.
-def p_decode_stmt_format(t):
- 'decode_stmt : FORMAT push_format_id LBRACE decode_stmt_list RBRACE'
- # The format will be pushed on the stack when 'push_format_id' is
- # processed (see below). Once the parser has recognized the full
- # production (though the right brace), we're done with the format,
- # so now we can pop it.
- formatStack.pop()
- t[0] = t[4]
-
-# This rule exists so we can set the current format (& push the stack)
-# when we recognize the format name part of the format block.
-def p_push_format_id(t):
- 'push_format_id : ID'
- try:
- formatStack.push(formatMap[t[1]])
- t[0] = ('', '// format %s' % t[1])
- except KeyError:
- error(t.lineno(1), 'instruction format "%s" not defined.' % t[1])
-
-# Nested decode block: if the value of the current field matches the
-# specified constant, do a nested decode on some other field.
-def p_decode_stmt_decode(t):
- 'decode_stmt : case_label COLON decode_block'
- label = t[1]
- codeObj = t[3]
- # just wrap the decoding code from the block as a case in the
- # outer switch statement.
- codeObj.wrap_decode_block('\n%s:\n' % label)
- codeObj.has_decode_default = (label == 'default')
- t[0] = codeObj
-
-# Instruction definition (finally!).
-def p_decode_stmt_inst(t):
- 'decode_stmt : case_label COLON inst SEMI'
- label = t[1]
- codeObj = t[3]
- codeObj.wrap_decode_block('\n%s:' % label, 'break;\n')
- codeObj.has_decode_default = (label == 'default')
- t[0] = codeObj
-
-# The case label is either a list of one or more constants or 'default'
-def p_case_label_0(t):
- 'case_label : intlit_list'
- t[0] = ': '.join(map(lambda a: 'case %#x' % a, t[1]))
-
-def p_case_label_1(t):
- 'case_label : DEFAULT'
- t[0] = 'default'
-
-#
-# The constant list for a decode case label must be non-empty, but may have
-# one or more comma-separated integer literals in it.
-#
-def p_intlit_list_0(t):
- 'intlit_list : INTLIT'
- t[0] = [t[1]]
-
-def p_intlit_list_1(t):
- 'intlit_list : intlit_list COMMA INTLIT'
- t[0] = t[1]
- t[0].append(t[3])
-
-# Define an instruction using the current instruction format (specified
-# by an enclosing format block).
-# "<mnemonic>(<args>)"
-def p_inst_0(t):
- 'inst : ID LPAREN arg_list RPAREN'
- # Pass the ID and arg list to the current format class to deal with.
- currentFormat = formatStack.top()
- codeObj = currentFormat.defineInst(t[1], t[3], t.lineno(1))
- args = ','.join(map(str, t[3]))
- args = re.sub('(?m)^', '//', args)
- args = re.sub('^//', '', args)
- comment = '\n// %s::%s(%s)\n' % (currentFormat.id, t[1], args)
- codeObj.prepend_all(comment)
- t[0] = codeObj
-
-# Define an instruction using an explicitly specified format:
-# "<fmt>::<mnemonic>(<args>)"
-def p_inst_1(t):
- 'inst : ID DBLCOLON ID LPAREN arg_list RPAREN'
- try:
- format = formatMap[t[1]]
- except KeyError:
- error(t.lineno(1), 'instruction format "%s" not defined.' % t[1])
- codeObj = format.defineInst(t[3], t[5], t.lineno(1))
- comment = '\n// %s::%s(%s)\n' % (t[1], t[3], t[5])
- codeObj.prepend_all(comment)
- t[0] = codeObj
-
-# The arg list generates a tuple, where the first element is a list of
-# the positional args and the second element is a dict containing the
-# keyword args.
-def p_arg_list_0(t):
- 'arg_list : positional_arg_list COMMA keyword_arg_list'
- t[0] = ( t[1], t[3] )
-
-def p_arg_list_1(t):
- 'arg_list : positional_arg_list'
- t[0] = ( t[1], {} )
-
-def p_arg_list_2(t):
- 'arg_list : keyword_arg_list'
- t[0] = ( [], t[1] )
-
-def p_positional_arg_list_0(t):
- 'positional_arg_list : empty'
- t[0] = []
-
-def p_positional_arg_list_1(t):
- 'positional_arg_list : expr'
- t[0] = [t[1]]
-
-def p_positional_arg_list_2(t):
- 'positional_arg_list : positional_arg_list COMMA expr'
- t[0] = t[1] + [t[3]]
-
-def p_keyword_arg_list_0(t):
- 'keyword_arg_list : keyword_arg'
- t[0] = t[1]
-
-def p_keyword_arg_list_1(t):
- 'keyword_arg_list : keyword_arg_list COMMA keyword_arg'
- t[0] = t[1]
- t[0].update(t[3])
-
-def p_keyword_arg(t):
- 'keyword_arg : ID EQUALS expr'
- t[0] = { t[1] : t[3] }
-
-#
-# Basic expressions. These constitute the argument values of
-# "function calls" (i.e. instruction definitions in the decode block)
-# and default values for formal parameters of format functions.
-#
-# Right now, these are either strings, integers, or (recursively)
-# lists of exprs (using Python square-bracket list syntax). Note that
-# bare identifiers are trated as string constants here (since there
-# isn't really a variable namespace to refer to).
-#
-def p_expr_0(t):
- '''expr : ID
- | INTLIT
- | STRLIT
- | CODELIT'''
- t[0] = t[1]
-
-def p_expr_1(t):
- '''expr : LBRACKET list_expr RBRACKET'''
- t[0] = t[2]
-
-def p_list_expr_0(t):
- 'list_expr : expr'
- t[0] = [t[1]]
-
-def p_list_expr_1(t):
- 'list_expr : list_expr COMMA expr'
- t[0] = t[1] + [t[3]]
-
-def p_list_expr_2(t):
- 'list_expr : empty'
- t[0] = []
-
-#
-# Empty production... use in other rules for readability.
-#
-def p_empty(t):
- 'empty :'
- pass
-
-# Parse error handler. Note that the argument here is the offending
-# *token*, not a grammar symbol (hence the need to use t.value)
-def p_error(t):
- if t:
- error(t.lineno, "syntax error at '%s'" % t.value)
- else:
- error(0, "unknown syntax error", True)
-
-# END OF GRAMMAR RULES
-#
-# Now build the parser.
-yacc.yacc()
-
-
-#####################################################################
-#
-# Support Classes
-#
-#####################################################################
-
-# Expand template with CPU-specific references into a dictionary with
-# an entry for each CPU model name. The entry key is the model name
-# and the corresponding value is the template with the CPU-specific
-# refs substituted for that model.
-def expand_cpu_symbols_to_dict(template):
- # Protect '%'s that don't go with CPU-specific terms
- t = re.sub(r'%(?!\(CPU_)', '%%', template)
- result = {}
- for cpu in cpu_models:
- result[cpu.name] = t % cpu.strings
- return result
-
-# *If* the template has CPU-specific references, return a single
-# string containing a copy of the template for each CPU model with the
-# corresponding values substituted in. If the template has no
-# CPU-specific references, it is returned unmodified.
-def expand_cpu_symbols_to_string(template):
- if template.find('%(CPU_') != -1:
- return reduce(lambda x,y: x+y,
- expand_cpu_symbols_to_dict(template).values())
- else:
- return template
-
-# Protect CPU-specific references by doubling the corresponding '%'s
-# (in preparation for substituting a different set of references into
-# the template).
-def protect_cpu_symbols(template):
- return re.sub(r'%(?=\(CPU_)', '%%', template)
-
-###############
-# GenCode class
-#
-# The GenCode class encapsulates generated code destined for various
-# output files. The header_output and decoder_output attributes are
-# strings containing code destined for decoder.hh and decoder.cc
-# respectively. The decode_block attribute contains code to be
-# incorporated in the decode function itself (that will also end up in
-# decoder.cc). The exec_output attribute is a dictionary with a key
-# for each CPU model name; the value associated with a particular key
-# is the string of code for that CPU model's exec.cc file. The
-# has_decode_default attribute is used in the decode block to allow
-# explicit default clauses to override default default clauses.
-
-class GenCode:
- # Constructor. At this point we substitute out all CPU-specific
- # symbols. For the exec output, these go into the per-model
- # dictionary. For all other output types they get collapsed into
- # a single string.
- def __init__(self,
- header_output = '', decoder_output = '', exec_output = '',
- decode_block = '', has_decode_default = False):
- self.header_output = expand_cpu_symbols_to_string(header_output)
- self.decoder_output = expand_cpu_symbols_to_string(decoder_output)
- if isinstance(exec_output, dict):
- self.exec_output = exec_output
- elif isinstance(exec_output, str):
- # If the exec_output arg is a single string, we replicate
- # it for each of the CPU models, substituting and
- # %(CPU_foo)s params appropriately.
- self.exec_output = expand_cpu_symbols_to_dict(exec_output)
- self.decode_block = expand_cpu_symbols_to_string(decode_block)
- self.has_decode_default = has_decode_default
-
- # Override '+' operator: generate a new GenCode object that
- # concatenates all the individual strings in the operands.
- def __add__(self, other):
- exec_output = {}
- for cpu in cpu_models:
- n = cpu.name
- exec_output[n] = self.exec_output[n] + other.exec_output[n]
- return GenCode(self.header_output + other.header_output,
- self.decoder_output + other.decoder_output,
- exec_output,
- self.decode_block + other.decode_block,
- self.has_decode_default or other.has_decode_default)
-
- # Prepend a string (typically a comment) to all the strings.
- def prepend_all(self, pre):
- self.header_output = pre + self.header_output
- self.decoder_output = pre + self.decoder_output
- self.decode_block = pre + self.decode_block
- for cpu in cpu_models:
- self.exec_output[cpu.name] = pre + self.exec_output[cpu.name]
-
- # Wrap the decode block in a pair of strings (e.g., 'case foo:'
- # and 'break;'). Used to build the big nested switch statement.
- def wrap_decode_block(self, pre, post = ''):
- self.decode_block = pre + indent(self.decode_block) + post
-
-################
-# Format object.
-#
-# A format object encapsulates an instruction format. It must provide
-# a defineInst() method that generates the code for an instruction
-# definition.
-
-exportContextSymbols = ('InstObjParams', 'CodeBlock',
- 'makeList', 're', 'string')
-
-exportContext = {}
-
-def updateExportContext():
- exportContext.update(exportDict(*exportContextSymbols))
- exportContext.update(templateMap)
-
-def exportDict(*symNames):
- return dict([(s, eval(s)) for s in symNames])
-
-
-class Format:
- def __init__(self, id, params, code):
- # constructor: just save away arguments
- self.id = id
- self.params = params
- label = 'def format ' + id
- self.user_code = compile(fixPythonIndentation(code), label, 'exec')
- param_list = string.join(params, ", ")
- f = '''def defInst(_code, _context, %s):
- my_locals = vars().copy()
- exec _code in _context, my_locals
- return my_locals\n''' % param_list
- c = compile(f, label + ' wrapper', 'exec')
- exec c
- self.func = defInst
-
- def defineInst(self, name, args, lineno):
- context = {}
- updateExportContext()
- context.update(exportContext)
- context.update({ 'name': name, 'Name': string.capitalize(name) })
- try:
- vars = self.func(self.user_code, context, *args[0], **args[1])
- except Exception, exc:
- error(lineno, 'error defining "%s": %s.' % (name, exc))
- for k in vars.keys():
- if k not in ('header_output', 'decoder_output',
- 'exec_output', 'decode_block'):
- del vars[k]
- return GenCode(**vars)
-
-# Special null format to catch an implicit-format instruction
-# definition outside of any format block.
-class NoFormat:
- def __init__(self):
- self.defaultInst = ''
-
- def defineInst(self, name, args, lineno):
- error(lineno,
- 'instruction definition "%s" with no active format!' % name)
-
-# This dictionary maps format name strings to Format objects.
-formatMap = {}
-
-# Define a new format
-def defFormat(id, params, code, lineno):
- # make sure we haven't already defined this one
- if formatMap.get(id, None) != None:
- error(lineno, 'format %s redefined.' % id)
- # create new object and store in global map
- formatMap[id] = Format(id, params, code)
-
-
-##############
-# Stack: a simple stack object. Used for both formats (formatStack)
-# and default cases (defaultStack). Simply wraps a list to give more
-# stack-like syntax and enable initialization with an argument list
-# (as opposed to an argument that's a list).
-
-class Stack(list):
- def __init__(self, *items):
- list.__init__(self, items)
-
- def push(self, item):
- self.append(item);
-
- def top(self):
- return self[-1]
-
-# The global format stack.
-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
-
-#
-# Indent every line in string 's' by two spaces
-# (except preprocessor directives).
-# Used to make nested code blocks look pretty.
-#
-def indent(s):
- return re.sub(r'(?m)^(?!#)', ' ', s)
-
-#
-# Munge a somewhat arbitrarily formatted piece of Python code
-# (e.g. from a format 'let' block) into something whose indentation
-# will get by the Python parser.
-#
-# The two keys here are that Python will give a syntax error if
-# there's any whitespace at the beginning of the first line, and that
-# all lines at the same lexical nesting level must have identical
-# indentation. Unfortunately the way code literals work, an entire
-# let block tends to have some initial indentation. Rather than
-# trying to figure out what that is and strip it off, we prepend 'if
-# 1:' to make the let code the nested block inside the if (and have
-# the parser automatically deal with the indentation for us).
-#
-# We don't want to do this if (1) the code block is empty or (2) the
-# first line of the block doesn't have any whitespace at the front.
-
-def fixPythonIndentation(s):
- # get rid of blank lines first
- s = re.sub(r'(?m)^\s*\n', '', s);
- if (s != '' and re.match(r'[ \t]', s[0])):
- s = 'if 1:\n' + s
- return s
-
-# Error handler. Just call exit. Output formatted to work under
-# 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 + ":"
- spaces += " "
- # 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))
-
-
-#####################################################################
-#
-# Bitfield Operator Support
-#
-#####################################################################
-
-bitOp1ArgRE = re.compile(r'<\s*(\w+)\s*:\s*>')
-
-bitOpWordRE = re.compile(r'(?<![\w\.])([\w\.]+)<\s*(\w+)\s*:\s*(\w+)\s*>')
-bitOpExprRE = re.compile(r'\)<\s*(\w+)\s*:\s*(\w+)\s*>')
-
-def substBitOps(code):
- # first convert single-bit selectors to two-index form
- # i.e., <n> --> <n:n>
- code = bitOp1ArgRE.sub(r'<\1:\1>', code)
- # simple case: selector applied to ID (name)
- # i.e., foo<a:b> --> bits(foo, a, b)
- code = bitOpWordRE.sub(r'bits(\1, \2, \3)', code)
- # if selector is applied to expression (ending in ')'),
- # we need to search backward for matching '('
- match = bitOpExprRE.search(code)
- while match:
- exprEnd = match.start()
- here = exprEnd - 1
- nestLevel = 1
- while nestLevel > 0:
- if code[here] == '(':
- nestLevel -= 1
- elif code[here] == ')':
- nestLevel += 1
- here -= 1
- if here < 0:
- sys.exit("Didn't find '('!")
- exprStart = here+1
- newExpr = r'bits(%s, %s, %s)' % (code[exprStart:exprEnd+1],
- match.group(1), match.group(2))
- code = code[:exprStart] + newExpr + code[match.end():]
- match = bitOpExprRE.search(code)
- return code
-
-
-####################
-# Template objects.
-#
-# Template objects are format strings that allow substitution from
-# the attribute spaces of other objects (e.g. InstObjParams instances).
-
-class Template:
- def __init__(self, t):
- self.template = t
-
- def subst(self, d):
- # Start with the template namespace. Make a copy since we're
- # going to modify it.
- myDict = templateMap.copy()
- # if the argument is a dictionary, we just use it.
- if isinstance(d, dict):
- myDict.update(d)
- # if the argument is an object, we use its attribute map.
- elif hasattr(d, '__dict__'):
- myDict.update(d.__dict__)
- else:
- raise TypeError, "Template.subst() arg must be or have dictionary"
- # Protect non-Python-dict substitutions (e.g. if there's a printf
- # in the templated C++ code)
- template = protect_non_subst_percents(self.template)
- # CPU-model-specific substitutions are handled later (in GenCode).
- template = protect_cpu_symbols(template)
- return template % myDict
-
- # Convert to string. This handles the case when a template with a
- # CPU-specific term gets interpolated into another template or into
- # an output block.
- def __str__(self):
- return expand_cpu_symbols_to_string(self.template)
-
-#####################################################################
-#
-# Code Parser
-#
-# The remaining code is the support for automatically extracting
-# instruction characteristics from pseudocode.
-#
-#####################################################################
-
-# Force the argument to be a list. Useful for flags, where a caller
-# can specify a singleton flag or a list of flags. Also usful for
-# converting tuples to lists so they can be modified.
-def makeList(arg):
- if isinstance(arg, list):
- return arg
- elif isinstance(arg, tuple):
- return list(arg)
- elif not arg:
- return []
- else:
- return [ arg ]
-
-# Generate operandTypeMap from the user's 'def operand_types'
-# statement.
-def buildOperandTypeMap(userDict, lineno):
- global operandTypeMap
- operandTypeMap = {}
- for (ext, (desc, size)) in userDict.iteritems():
- if desc == 'signed int':
- ctype = 'int%d_t' % size
- is_signed = 1
- elif desc == 'unsigned int':
- ctype = 'uint%d_t' % size
- is_signed = 0
- elif desc == 'float':
- is_signed = 1 # shouldn't really matter
- if size == 32:
- ctype = 'float'
- elif size == 64:
- ctype = 'double'
- if ctype == '':
- error(lineno, 'Unrecognized type description "%s" in userDict')
- operandTypeMap[ext] = (size, ctype, is_signed)
-
-#
-#
-#
-# Base class for operand descriptors. An instance of this class (or
-# actually a class derived from this one) represents a specific
-# operand for a code block (e.g, "Rc.sq" as a dest). Intermediate
-# derived classes encapsulates the traits of a particular operand type
-# (e.g., "32-bit integer register").
-#
-class Operand(object):
- def __init__(self, full_name, ext, is_src, is_dest):
- self.full_name = full_name
- self.ext = ext
- self.is_src = is_src
- self.is_dest = is_dest
- # The 'effective extension' (eff_ext) is either the actual
- # extension, if one was explicitly provided, or the default.
- if ext:
- self.eff_ext = ext
- else:
- self.eff_ext = self.dflt_ext
-
- (self.size, self.ctype, self.is_signed) = operandTypeMap[self.eff_ext]
-
- # note that mem_acc_size is undefined for non-mem operands...
- # template must be careful not to use it if it doesn't apply.
- if self.isMem():
- self.mem_acc_size = self.makeAccSize()
- self.mem_acc_type = self.ctype
-
- # Finalize additional fields (primarily code fields). This step
- # is done separately since some of these fields may depend on the
- # register index enumeration that hasn't been performed yet at the
- # time of __init__().
- def finalize(self):
- self.flags = self.getFlags()
- self.constructor = self.makeConstructor()
- self.op_decl = self.makeDecl()
-
- if self.is_src:
- self.op_rd = self.makeRead()
- self.op_src_decl = self.makeDecl()
- else:
- self.op_rd = ''
- self.op_src_decl = ''
-
- if self.is_dest:
- self.op_wb = self.makeWrite()
- self.op_dest_decl = self.makeDecl()
- else:
- self.op_wb = ''
- self.op_dest_decl = ''
-
- def isMem(self):
- return 0
-
- def isReg(self):
- return 0
-
- def isFloatReg(self):
- return 0
-
- def isIntReg(self):
- return 0
-
- def isControlReg(self):
- return 0
-
- def getFlags(self):
- # note the empty slice '[:]' gives us a copy of self.flags[0]
- # instead of a reference to it
- my_flags = self.flags[0][:]
- if self.is_src:
- my_flags += self.flags[1]
- if self.is_dest:
- my_flags += self.flags[2]
- return my_flags
-
- def makeDecl(self):
- # Note that initializations in the declarations are solely
- # to avoid 'uninitialized variable' errors from the compiler.
- return self.ctype + ' ' + self.base_name + ' = 0;\n';
-
-class IntRegOperand(Operand):
- def isReg(self):
- return 1
-
- def isIntReg(self):
- return 1
-
- def makeConstructor(self):
- c = ''
- if self.is_src:
- c += '\n\t_srcRegIdx[%d] = %s;' % \
- (self.src_reg_idx, self.reg_spec)
- if self.is_dest:
- c += '\n\t_destRegIdx[%d] = %s;' % \
- (self.dest_reg_idx, self.reg_spec)
- return c
-
- def makeRead(self):
- if (self.ctype == 'float' or self.ctype == 'double'):
- error(0, 'Attempt to read integer register as FP')
- if (self.size == self.dflt_size):
- return '%s = xc->readIntReg(this, %d);\n' % \
- (self.base_name, self.src_reg_idx)
- else:
- return '%s = bits(xc->readIntReg(this, %d), %d, 0);\n' % \
- (self.base_name, self.src_reg_idx, self.size-1)
-
- def makeWrite(self):
- if (self.ctype == 'float' or self.ctype == 'double'):
- error(0, 'Attempt to write integer register as FP')
- if (self.size != self.dflt_size and self.is_signed):
- final_val = 'sext<%d>(%s)' % (self.size, self.base_name)
- else:
- final_val = self.base_name
- wb = '''
- {
- %s final_val = %s;
- xc->setIntReg(this, %d, final_val);\n
- if (traceData) { traceData->setData(final_val); }
- }''' % (self.dflt_ctype, final_val, self.dest_reg_idx)
- return wb
-
-class FloatRegOperand(Operand):
- def isReg(self):
- return 1
-
- def isFloatReg(self):
- return 1
-
- def makeConstructor(self):
- c = ''
- if self.is_src:
- c += '\n\t_srcRegIdx[%d] = %s + FP_Base_DepTag;' % \
- (self.src_reg_idx, self.reg_spec)
- if self.is_dest:
- c += '\n\t_destRegIdx[%d] = %s + FP_Base_DepTag;' % \
- (self.dest_reg_idx, self.reg_spec)
- return c
-
- def makeRead(self):
- bit_select = 0
- if (self.ctype == 'float'):
- func = 'readFloatRegSingle'
- elif (self.ctype == 'double'):
- func = 'readFloatRegDouble'
- else:
- func = 'readFloatRegInt'
- if (self.size != self.dflt_size):
- bit_select = 1
- 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)
- else:
- return '%s = %s;\n' % (self.base_name, base)
-
- def makeWrite(self):
- final_val = self.base_name
- final_ctype = self.ctype
- if (self.ctype == 'float'):
- func = 'setFloatRegSingle'
- elif (self.ctype == 'double'):
- func = 'setFloatRegDouble'
- else:
- func = 'setFloatRegInt'
- final_ctype = 'uint%d_t' % self.dflt_size
- if (self.size != self.dflt_size and self.is_signed):
- final_val = 'sext<%d>(%s)' % (self.size, self.base_name)
- wb = '''
- {
- %s final_val = %s;
- xc->%s(this, %d, final_val);\n
- if (traceData) { traceData->setData(final_val); }
- }''' % (final_ctype, final_val, func, self.dest_reg_idx)
- return wb
-
-class ControlRegOperand(Operand):
- def isReg(self):
- return 1
-
- def isControlReg(self):
- return 1
-
- def makeConstructor(self):
- c = ''
- if self.is_src:
- c += '\n\t_srcRegIdx[%d] = %s;' % \
- (self.src_reg_idx, self.reg_spec)
- if self.is_dest:
- c += '\n\t_destRegIdx[%d] = %s;' % \
- (self.dest_reg_idx, self.reg_spec)
- return c
-
- def makeRead(self):
- bit_select = 0
- if (self.ctype == 'float' or self.ctype == 'double'):
- error(0, 'Attempt to read control register as FP')
- base = 'xc->readMiscReg(%s)' % self.reg_spec
- if self.size == self.dflt_size:
- return '%s = %s;\n' % (self.base_name, base)
- else:
- return '%s = bits(%s, %d, 0);\n' % \
- (self.base_name, base, self.size-1)
-
- def makeWrite(self):
- if (self.ctype == 'float' or self.ctype == 'double'):
- error(0, 'Attempt to write control register as FP')
- wb = 'xc->setMiscReg(%s, %s);\n' % (self.reg_spec, self.base_name)
- wb += 'if (traceData) { traceData->setData(%s); }' % \
- self.base_name
- return wb
-
-class MemOperand(Operand):
- def isMem(self):
- return 1
-
- def makeConstructor(self):
- return ''
-
- def makeDecl(self):
- # Note that initializations in the declarations are solely
- # to avoid 'uninitialized variable' errors from the compiler.
- # Declare memory data variable.
- c = '%s %s = 0;\n' % (self.ctype, self.base_name)
- return c
-
- def makeRead(self):
- return ''
-
- def makeWrite(self):
- return ''
-
- # Return the memory access size *in bits*, suitable for
- # forming a type via "uint%d_t". Divide by 8 if you want bytes.
- def makeAccSize(self):
- return self.size
-
-
-class NPCOperand(Operand):
- def makeConstructor(self):
- return ''
-
- def makeRead(self):
- return '%s = xc->readPC() + 4;\n' % self.base_name
-
- def makeWrite(self):
- return 'xc->setNextPC(%s);\n' % self.base_name
-
-class NNPCOperand(Operand):
- def makeConstructor(self):
- return ''
-
- def makeRead(self):
- return '%s = xc->readPC() + 8;\n' % self.base_name
-
- def makeWrite(self):
- return 'xc->setNextNPC(%s);\n' % self.base_name
-
-def buildOperandNameMap(userDict, lineno):
- global operandNameMap
- operandNameMap = {}
- for (op_name, val) in userDict.iteritems():
- (base_cls_name, dflt_ext, reg_spec, flags, sort_pri) = val
- (dflt_size, dflt_ctype, dflt_is_signed) = operandTypeMap[dflt_ext]
- # Canonical flag structure is a triple of lists, where each list
- # indicates the set of flags implied by this operand always, when
- # used as a source, and when used as a dest, respectively.
- # For simplicity this can be initialized using a variety of fairly
- # obvious shortcuts; we convert these to canonical form here.
- if not flags:
- # no flags specified (e.g., 'None')
- flags = ( [], [], [] )
- elif isinstance(flags, str):
- # a single flag: assumed to be unconditional
- flags = ( [ flags ], [], [] )
- elif isinstance(flags, list):
- # a list of flags: also assumed to be unconditional
- flags = ( flags, [], [] )
- elif isinstance(flags, tuple):
- # it's a tuple: it should be a triple,
- # but each item could be a single string or a list
- (uncond_flags, src_flags, dest_flags) = flags
- flags = (makeList(uncond_flags),
- makeList(src_flags), makeList(dest_flags))
- # Accumulate attributes of new operand class in tmp_dict
- tmp_dict = {}
- for attr in ('dflt_ext', 'reg_spec', 'flags', 'sort_pri',
- 'dflt_size', 'dflt_ctype', 'dflt_is_signed'):
- tmp_dict[attr] = eval(attr)
- tmp_dict['base_name'] = op_name
- # New class name will be e.g. "IntReg_Ra"
- cls_name = base_cls_name + '_' + op_name
- # Evaluate string arg to get class object. Note that the
- # actual base class for "IntReg" is "IntRegOperand", i.e. we
- # have to append "Operand".
- try:
- base_cls = eval(base_cls_name + 'Operand')
- except NameError:
- error(lineno,
- 'error: unknown operand base class "%s"' % base_cls_name)
- # The following statement creates a new class called
- # <cls_name> as a subclass of <base_cls> with the attributes
- # in tmp_dict, just as if we evaluated a class declaration.
- operandNameMap[op_name] = type(cls_name, (base_cls,), tmp_dict)
-
- # Define operand variables.
- operands = userDict.keys()
-
- operandsREString = (r'''
- (?<![\w\.]) # neg. lookbehind assertion: prevent partial matches
- ((%s)(?:\.(\w+))?) # match: operand with optional '.' then suffix
- (?![\w\.]) # neg. lookahead assertion: prevent partial matches
- '''
- % string.join(operands, '|'))
-
- global operandsRE
- operandsRE = re.compile(operandsREString, re.MULTILINE|re.VERBOSE)
-
- # Same as operandsREString, but extension is mandatory, and only two
- # groups are returned (base and ext, not full name as above).
- # Used for subtituting '_' for '.' to make C++ identifiers.
- operandsWithExtREString = (r'(?<![\w\.])(%s)\.(\w+)(?![\w\.])'
- % string.join(operands, '|'))
-
- global operandsWithExtRE
- operandsWithExtRE = re.compile(operandsWithExtREString, re.MULTILINE)
-
-
-class OperandList:
-
- # Find all the operands in the given code block. Returns an operand
- # descriptor list (instance of class OperandList).
- def __init__(self, code):
- self.items = []
- self.bases = {}
- # delete comments so we don't match on reg specifiers inside
- code = commentRE.sub('', code)
- # search for operands
- next_pos = 0
- while 1:
- match = operandsRE.search(code, next_pos)
- if not match:
- # no more matches: we're done
- break
- op = match.groups()
- # regexp groups are operand full name, base, and extension
- (op_full, op_base, op_ext) = op
- # if the token following the operand is an assignment, this is
- # a destination (LHS), else it's a source (RHS)
- is_dest = (assignRE.match(code, match.end()) != None)
- is_src = not is_dest
- # see if we've already seen this one
- op_desc = self.find_base(op_base)
- if op_desc:
- if op_desc.ext != op_ext:
- error(0, 'Inconsistent extensions for operand %s' % \
- op_base)
- op_desc.is_src = op_desc.is_src or is_src
- op_desc.is_dest = op_desc.is_dest or is_dest
- else:
- # new operand: create new descriptor
- op_desc = operandNameMap[op_base](op_full, op_ext,
- is_src, is_dest)
- self.append(op_desc)
- # start next search after end of current match
- next_pos = match.end()
- self.sort()
- # enumerate source & dest register operands... used in building
- # constructor later
- self.numSrcRegs = 0
- self.numDestRegs = 0
- self.numFPDestRegs = 0
- self.numIntDestRegs = 0
- self.memOperand = None
- for op_desc in self.items:
- if op_desc.isReg():
- if op_desc.is_src:
- op_desc.src_reg_idx = self.numSrcRegs
- self.numSrcRegs += 1
- if op_desc.is_dest:
- op_desc.dest_reg_idx = self.numDestRegs
- self.numDestRegs += 1
- if op_desc.isFloatReg():
- self.numFPDestRegs += 1
- elif op_desc.isIntReg():
- self.numIntDestRegs += 1
- elif op_desc.isMem():
- if self.memOperand:
- error(0, "Code block has more than one memory operand.")
- self.memOperand = op_desc
- # now make a final pass to finalize op_desc fields that may depend
- # on the register enumeration
- for op_desc in self.items:
- op_desc.finalize()
-
- def __len__(self):
- return len(self.items)
-
- def __getitem__(self, index):
- return self.items[index]
-
- def append(self, op_desc):
- self.items.append(op_desc)
- self.bases[op_desc.base_name] = op_desc
-
- def find_base(self, base_name):
- # like self.bases[base_name], but returns None if not found
- # (rather than raising exception)
- return self.bases.get(base_name)
-
- # internal helper function for concat[Some]Attr{Strings|Lists}
- def __internalConcatAttrs(self, attr_name, filter, result):
- for op_desc in self.items:
- if filter(op_desc):
- result += getattr(op_desc, attr_name)
- return result
-
- # return a single string that is the concatenation of the (string)
- # values of the specified attribute for all operands
- def concatAttrStrings(self, attr_name):
- return self.__internalConcatAttrs(attr_name, lambda x: 1, '')
-
- # like concatAttrStrings, but only include the values for the operands
- # for which the provided filter function returns true
- def concatSomeAttrStrings(self, filter, attr_name):
- return self.__internalConcatAttrs(attr_name, filter, '')
-
- # return a single list that is the concatenation of the (list)
- # values of the specified attribute for all operands
- def concatAttrLists(self, attr_name):
- return self.__internalConcatAttrs(attr_name, lambda x: 1, [])
-
- # like concatAttrLists, but only include the values for the operands
- # for which the provided filter function returns true
- def concatSomeAttrLists(self, filter, attr_name):
- return self.__internalConcatAttrs(attr_name, filter, [])
-
- def sort(self):
- self.items.sort(lambda a, b: a.sort_pri - b.sort_pri)
-
-# Regular expression object to match C++ comments
-# (used in findOperands())
-commentRE = re.compile(r'//.*\n')
-
-# Regular expression object to match assignment statements
-# (used in findOperands())
-assignRE = re.compile(r'\s*=(?!=)', re.MULTILINE)
-
-# Munge operand names in code string to make legal C++ variable names.
-# This means getting rid of the type extension if any.
-# (Will match base_name attribute of Operand object.)
-def substMungedOpNames(code):
- return operandsWithExtRE.sub(r'\1', code)
-
-def joinLists(t):
- return map(string.join, t)
-
-def makeFlagConstructor(flag_list):
- if len(flag_list) == 0:
- return ''
- # filter out repeated flags
- flag_list.sort()
- i = 1
- while i < len(flag_list):
- if flag_list[i] == flag_list[i-1]:
- del flag_list[i]
- else:
- i += 1
- pre = '\n\tflags['
- post = '] = true;'
- code = pre + string.join(flag_list, post + pre) + post
- return code
-
-class CodeBlock:
- def __init__(self, code):
- self.orig_code = code
- self.operands = OperandList(code)
- self.code = substMungedOpNames(substBitOps(code))
- self.constructor = self.operands.concatAttrStrings('constructor')
- self.constructor += \
- '\n\t_numSrcRegs = %d;' % self.operands.numSrcRegs
- self.constructor += \
- '\n\t_numDestRegs = %d;' % self.operands.numDestRegs
- self.constructor += \
- '\n\t_numFPDestRegs = %d;' % self.operands.numFPDestRegs
- self.constructor += \
- '\n\t_numIntDestRegs = %d;' % self.operands.numIntDestRegs
-
- self.op_decl = self.operands.concatAttrStrings('op_decl')
-
- is_src = lambda op: op.is_src
- is_dest = lambda op: op.is_dest
-
- self.op_src_decl = \
- self.operands.concatSomeAttrStrings(is_src, 'op_src_decl')
- self.op_dest_decl = \
- self.operands.concatSomeAttrStrings(is_dest, 'op_dest_decl')
-
- self.op_rd = self.operands.concatAttrStrings('op_rd')
- self.op_wb = self.operands.concatAttrStrings('op_wb')
-
- self.flags = self.operands.concatAttrLists('flags')
-
- if self.operands.memOperand:
- self.mem_acc_size = self.operands.memOperand.mem_acc_size
- self.mem_acc_type = self.operands.memOperand.mem_acc_type
-
- # Make a basic guess on the operand class (function unit type).
- # These are good enough for most cases, and will be overridden
- # later otherwise.
- if 'IsStore' in self.flags:
- self.op_class = 'MemWriteOp'
- elif 'IsLoad' in self.flags or 'IsPrefetch' in self.flags:
- self.op_class = 'MemReadOp'
- elif 'IsFloating' in self.flags:
- self.op_class = 'FloatAddOp'
- else:
- self.op_class = 'IntAluOp'
-
-# Assume all instruction flags are of the form 'IsFoo'
-instFlagRE = re.compile(r'Is.*')
-
-# OpClass constants end in 'Op' except No_OpClass
-opClassRE = re.compile(r'.*Op|No_OpClass')
-
-class InstObjParams:
- def __init__(self, mnem, class_name, base_class = '',
- code_block = None, opt_args = []):
- 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))
- else:
- self.constructor = ''
- self.flags = []
- # Optional arguments are assumed to be either StaticInst flags
- # or an OpClass value. To avoid having to import a complete
- # list of these values to match against, we do it ad-hoc
- # with regexps.
- for oa in opt_args:
- if instFlagRE.match(oa):
- self.flags.append(oa)
- elif opClassRE.match(oa):
- self.op_class = oa
- else:
- error(0, 'InstObjParams: optional arg "%s" not recognized '
- 'as StaticInst::Flag or OpClass.' % oa)
-
- # add flag initialization to contructor here to include
- # any flags added via opt_args
- self.constructor += makeFlagConstructor(self.flags)
-
- # if 'IsFloating' is set, add call to the FP enable check
- # function (which should be provided by isa_desc via a declare)
- if 'IsFloating' in self.flags:
- self.fp_enable_check = 'fault = checkFpEnableFault(xc);'
- else:
- self.fp_enable_check = ''
-
-#######################
-#
-# Output file template
-#
-
-file_template = '''
-/*
- * DO NOT EDIT THIS FILE!!!
- *
- * It was automatically generated from the ISA description in %(filename)s
- */
-
-%(includes)s
-
-%(global_output)s
-
-namespace %(namespace)s {
-
-%(namespace_output)s
-
-} // namespace %(namespace)s
-
-%(decode_function)s
-'''
-
-
-# Update the output file only if the new contents are different from
-# the current contents. Minimizes the files that need to be rebuilt
-# after minor changes.
-def update_if_needed(file, contents):
- update = False
- if os.access(file, os.R_OK):
- f = open(file, 'r')
- old_contents = f.read()
- f.close()
- if contents != old_contents:
- print 'Updating', file
- os.remove(file) # in case it's write-protected
- update = True
- else:
- print 'File', file, 'is unchanged'
- else:
- print 'Generating', file
- update = True
- if update:
- f = open(file, 'w')
- f.write(contents)
- f.close()
-
-# This regular expression matches '##include' directives
-includeRE = re.compile(r'^\s*##include\s+"(?P<filename>[\w/.-]*)".*$',
- re.MULTILINE)
-
-# 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
- 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):
- # 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)
-
- # grab the last three path components of isa_desc_file to put in
- # the output
- filename = '/'.join(isa_desc_file.split('/')[-3:])
-
- # generate decoder.hh
- includes = '#include "base/bitfield.hh" // for bitfield support'
- global_output = global_code.header_output
- namespace_output = namespace_code.header_output
- decode_function = ''
- update_if_needed(output_dir + '/decoder.hh', file_template % vars())
-
- # generate decoder.cc
- includes = '#include "decoder.hh"'
- global_output = global_code.decoder_output
- namespace_output = namespace_code.decoder_output
- # namespace_output += namespace_code.decode_block
- decode_function = namespace_code.decode_block
- update_if_needed(output_dir + '/decoder.cc', file_template % vars())
-
- # generate per-cpu exec files
- for cpu in cpu_models:
- includes = '#include "decoder.hh"\n'
- includes += cpu.includes
- global_output = global_code.exec_output[cpu.name]
- namespace_output = namespace_code.exec_output[cpu.name]
- decode_function = ''
- update_if_needed(output_dir + '/' + cpu.filename,
- file_template % vars())
-
-# global list of CpuModel objects (see cpu_models.py)
-cpu_models = []
-
-# Called as script: get args from command line.
-# Args are: <path to cpu_models.py> <isa desc file> <output dir> <cpu models>
-if __name__ == '__main__':
- execfile(sys.argv[1]) # read in CpuModel definitions
- cpu_models = [CpuModel.dict[cpu] for cpu in sys.argv[4:]]
- parse_isa_desc(sys.argv[2], sys.argv[3])
diff --git a/arch/isa_specific.hh b/arch/isa_specific.hh
deleted file mode 100644
index 44f8e9d64..000000000
--- a/arch/isa_specific.hh
+++ /dev/null
@@ -1,62 +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.
- */
-
-#ifndef __ARCH_ISA_SPECIFIC_HH__
-#define __ARCH_ISA_SPECIFIC_HH__
-
-//This file provides a mechanism for other source code to bring in
-//files from the ISA being compiled with
-
-//These are constants so you can selective compile code based on the isa
-//To use them, do something like
-//
-//#if THE_ISA == YOUR_FAVORITE_ISA
-// conditional_code
-//#endif
-//
-//Note that this is how this file sets up the other isa "hooks"
-
-//These macros have numerical values because otherwise the preprocessor
-//would treat them as 0 in comparisons.
-#define ALPHA_ISA 21064
-#define SPARC_ISA 42
-#define MIPS_ISA 1337
-
-//These tell the preprocessor where to find the files of a particular
-//ISA, and set the "TheISA" macro for use elsewhere.
-#if THE_ISA == ALPHA_ISA
- #define TheISA AlphaISA
-#elif THE_ISA == SPARC_ISA
- #define TheISA SparcISA
-#elif THE_ISA == MIPS_ISA
- #define TheISA MipsISA
-#else
- #error "THE_ISA not set"
-#endif
-
-#endif
diff --git a/arch/mips/SConscript b/arch/mips/SConscript
deleted file mode 100644
index b8efa7ef9..000000000
--- a/arch/mips/SConscript
+++ /dev/null
@@ -1,83 +0,0 @@
-# -*- mode:python -*-
-
-# Copyright (c) 2004-2005 The Regents of The University of Michigan
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met: redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer;
-# redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution;
-# neither the name of the copyright holders nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-import os
-import sys
-from os.path import isdir
-
-# Import build environment variable from SConstruct.
-Import('env')
-
-###################################################
-#
-# Define needed sources.
-#
-###################################################
-
-# Base sources used by all configurations.
-base_sources = Split('''
- faults.cc
- isa_traits.cc
- ''')
-
-# Full-system sources
-full_system_sources = Split('''
- memory.cc
- arguments.cc
- mips34k.cc
- osfpal.cc
- stacktrace.cc
- vtophys.cc
- ''')
-
-# Syscall emulation (non-full-system) sources
-syscall_emulation_sources = Split('''
- common_syscall_emul.cc
- linux_process.cc
- tru64_process.cc
- ''')
-
-# Set up complete list of sources based on configuration.
-sources = base_sources
-
-if env['FULL_SYSTEM']:
- sources += full_system_sources
-else:
- sources += syscall_emulation_sources
-
-# Convert file names to SCons File objects. This takes care of the
-# path relative to the top of the directory tree.
-sources = [File(s) for s in sources]
-
-# Add in files generated by the ISA description.
-isa_desc_files = env.ISADesc('isa/main.isa')
-# Only non-header files need to be compiled.
-isa_desc_sources = [f for f in isa_desc_files if not f.path.endswith('.hh')]
-sources += isa_desc_sources
-
-Return('sources')
diff --git a/arch/mips/faults.cc b/arch/mips/faults.cc
deleted file mode 100644
index 142dfe0a4..000000000
--- a/arch/mips/faults.cc
+++ /dev/null
@@ -1,80 +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/faults.hh"
-
-ResetFaultType * const ResetFault =
- new ResetFaultType("reset", 1, 0x0001);
-ArithmeticFaultType * const ArithmeticFault =
- new ArithmeticFaultType("arith", 3, 0x0501);
-InterruptFaultType * const InterruptFault =
- new InterruptFaultType("interrupt", 4, 0x0101);
-NDtbMissFaultType * const NDtbMissFault =
- new NDtbMissFaultType("dtb_miss_single", 5, 0x0201);
-PDtbMissFaultType * const PDtbMissFault =
- new PDtbMissFaultType("dtb_miss_double", 6, 0x0281);
-DtbPageFaultType * const DtbPageFault =
- new DtbPageFaultType("dfault", 8, 0x0381);
-DtbAcvFaultType * const DtbAcvFault =
- new DtbAcvFaultType("dfault", 9, 0x0381);
-ItbMissFaultType * const ItbMissFault =
- new ItbMissFaultType("itbmiss", 10, 0x0181);
-ItbPageFaultType * const ItbPageFault =
- new ItbPageFaultType("itbmiss", 11, 0x0181);
-ItbAcvFaultType * const ItbAcvFault =
- new ItbAcvFaultType("iaccvio", 12, 0x0081);
-UnimplementedOpcodeFaultType * const UnimplementedOpcodeFault =
- new UnimplementedOpcodeFaultType("opdec", 13, 0x0481);
-FloatEnableFaultType * const FloatEnableFault =
- new FloatEnableFaultType("fen", 14, 0x0581);
-PalFaultType * const PalFault =
- new PalFaultType("pal", 15, 0x2001);
-IntegerOverflowFaultType * const IntegerOverflowFault =
- new IntegerOverflowFaultType("intover", 16, 0x0501);
-
-Fault ** ListOfFaults[] = {
- (Fault **)&NoFault,
- (Fault **)&ResetFault,
- (Fault **)&MachineCheckFault,
- (Fault **)&ArithmeticFault,
- (Fault **)&InterruptFault,
- (Fault **)&NDtbMissFault,
- (Fault **)&PDtbMissFault,
- (Fault **)&AlignmentFault,
- (Fault **)&DtbPageFault,
- (Fault **)&DtbAcvFault,
- (Fault **)&ItbMissFault,
- (Fault **)&ItbPageFault,
- (Fault **)&ItbAcvFault,
- (Fault **)&UnimplementedOpcodeFault,
- (Fault **)&FloatEnableFault,
- (Fault **)&PalFault,
- (Fault **)&IntegerOverflowFault,
- };
-
-int NumFaults = sizeof(ListOfFaults) / sizeof(Fault **);
diff --git a/arch/mips/faults.hh b/arch/mips/faults.hh
deleted file mode 100644
index c1cb956b0..000000000
--- a/arch/mips/faults.hh
+++ /dev/null
@@ -1,160 +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.
- */
-
-#ifndef __MIPS_FAULTS_HH__
-#define __MIPS_FAULTS_HH__
-
-#include "sim/faults.hh"
-#include "arch/isa_traits.hh" //For the Addr type
-
-class MipsFault : public FaultBase
-{
- public:
- MipsFault(char * newName, int newId, Addr newVect)
- : FaultBase(newName, newId), vect(newVect)
- {;}
-
- Addr vect;
-};
-
-extern class ResetFaultType : public MipsFault
-{
- public:
- ResetFaultType(char * newName, int newId, Addr newVect)
- : MipsFault(newName, newId, newVect)
- {;}
-} * const ResetFault;
-
-extern class ArithmeticFaultType : public MipsFault
-{
- public:
- ArithmeticFaultType(char * newName, int newId, Addr newVect)
- : MipsFault(newName, newId, newVect)
- {;}
-} * const ArithmeticFault;
-
-extern class InterruptFaultType : public MipsFault
-{
- public:
- InterruptFaultType(char * newName, int newId, Addr newVect)
- : MipsFault(newName, newId, newVect)
- {;}
-} * const InterruptFault;
-
-extern class NDtbMissFaultType : public MipsFault
-{
- public:
- NDtbMissFaultType(char * newName, int newId, Addr newVect)
- : MipsFault(newName, newId, newVect)
- {;}
-} * const NDtbMissFault;
-
-extern class PDtbMissFaultType : public MipsFault
-{
- public:
- PDtbMissFaultType(char * newName, int newId, Addr newVect)
- : MipsFault(newName, newId, newVect)
- {;}
-} * const PDtbMissFault;
-
-extern class DtbPageFaultType : public MipsFault
-{
- public:
- DtbPageFaultType(char * newName, int newId, Addr newVect)
- : MipsFault(newName, newId, newVect)
- {;}
-} * const DtbPageFault;
-
-extern class DtbAcvFaultType : public MipsFault
-{
- public:
- DtbAcvFaultType(char * newName, int newId, Addr newVect)
- : MipsFault(newName, newId, newVect)
- {;}
-} * const DtbAcvFault;
-
-extern class ItbMissFaultType : public MipsFault
-{
- public:
- ItbMissFaultType(char * newName, int newId, Addr newVect)
- : MipsFault(newName, newId, newVect)
- {;}
-} * const ItbMissFault;
-
-extern class ItbPageFaultType : public MipsFault
-{
- public:
- ItbPageFaultType(char * newName, int newId, Addr newVect)
- : MipsFault(newName, newId, newVect)
- {;}
-} * const ItbPageFault;
-
-extern class ItbAcvFaultType : public MipsFault
-{
- public:
- ItbAcvFaultType(char * newName, int newId, Addr newVect)
- : MipsFault(newName, newId, newVect)
- {;}
-} * const ItbAcvFault;
-
-extern class UnimplementedOpcodeFaultType : public MipsFault
-{
- public:
- UnimplementedOpcodeFaultType(char * newName, int newId, Addr newVect)
- : MipsFault(newName, newId, newVect)
- {;}
-} * const UnimplementedOpcodeFault;
-
-extern class FloatEnableFaultType : public MipsFault
-{
- public:
- FloatEnableFaultType(char * newName, int newId, Addr newVect)
- : MipsFault(newName, newId, newVect)
- {;}
-} * const FloatEnableFault;
-
-extern class PalFaultType : public MipsFault
-{
- public:
- PalFaultType(char * newName, int newId, Addr newVect)
- : MipsFault(newName, newId, newVect)
- {;}
-} * const PalFault;
-
-extern class IntegerOverflowFaultType : public MipsFault
-{
- public:
- IntegerOverflowFaultType(char * newName, int newId, Addr newVect)
- : MipsFault(newName, newId, newVect)
- {;}
-} * const IntegerOverflowFault;
-
-extern Fault ** ListOfFaults[];
-extern int NumFaults;
-
-#endif // __FAULTS_HH__
diff --git a/arch/mips/isa/base.isa b/arch/mips/isa/base.isa
deleted file mode 100644
index 4125b5101..000000000
--- a/arch/mips/isa/base.isa
+++ /dev/null
@@ -1,96 +0,0 @@
-// -*- mode:c++ -*-
-
-////////////////////////////////////////////////////////////////////
-//
-// Base class for MIPS instructions, and some support functions
-//
-
-//Outputs to decoder.hh
-output header {{
-
-#define R31 31
-#include "arch/mips/faults.hh"
-#include "arch/mips/isa_traits.hh"
-
- using namespace MipsISA;
-
-
- /**
- * Base class for all MIPS static instructions.
- */
- class MipsStaticInst : public StaticInst
- {
- protected:
-
- /// Make MipsISA register dependence tags directly visible in
- /// this class and derived classes. Maybe these should really
- /// live here and not in the MipsISA namespace.
- /*enum DependenceTags {
- FP_Base_DepTag = MipsISA::FP_Base_DepTag,
- Fpcr_DepTag = MipsISA::Fpcr_DepTag,
- Uniq_DepTag = MipsISA::Uniq_DepTag,
- IPR_Base_DepTag = MipsISA::IPR_Base_DepTag
- };*/
-
- // Constructor
- MipsStaticInst(const char *mnem, MachInst _machInst, OpClass __opClass)
- : StaticInst(mnem, _machInst, __opClass)
- {
- }
-
- /// Print a register name for disassembly given the unique
- /// dependence tag number (FP or int).
- void printReg(std::ostream &os, int reg) const;
-
- std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
- };
-
-}};
-
-//Ouputs to decoder.cc
-output decoder {{
-
- void MipsStaticInst::printReg(std::ostream &os, int reg) const
- {
- if (reg < FP_Base_DepTag) {
- ccprintf(os, "r%d", reg);
- }
- else {
- ccprintf(os, "f%d", reg - FP_Base_DepTag);
- }
- }
-
- std::string MipsStaticInst::generateDisassembly(Addr pc, const SymbolTable *symtab) const
- {
- std::stringstream ss;
-
- ccprintf(ss, "%-10s ", mnemonic);
-
- // just print the first two source regs... if there's
- // a third one, it's a read-modify-write dest (Rc),
- // e.g. for CMOVxx
- if(_numSrcRegs > 0)
- {
- printReg(ss, _srcRegIdx[0]);
- }
-
- if(_numSrcRegs > 1)
- {
- ss << ",";
- printReg(ss, _srcRegIdx[1]);
- }
-
- // just print the first dest... if there's a second one,
- // it's generally implicit
- if(_numDestRegs > 0)
- {
- if(_numSrcRegs > 0)
- ss << ",";
- printReg(ss, _destRegIdx[0]);
- }
-
- return ss.str();
- }
-
-}};
-
diff --git a/arch/mips/isa/bitfields.isa b/arch/mips/isa/bitfields.isa
deleted file mode 100644
index 58d487ad2..000000000
--- a/arch/mips/isa/bitfields.isa
+++ /dev/null
@@ -1,67 +0,0 @@
-// -*- mode:c++ -*-
-
-////////////////////////////////////////////////////////////////////
-//
-// Bitfield definitions.
-//
-
-def bitfield OPCODE <31:26>;
-def bitfield OPCODE_HI <31:29>;
-def bitfield OPCODE_LO <28:26>;
-
-def bitfield REGIMM <20:16>;
-def bitfield REGIMM_HI <20:19>;
-def bitfield REGIMM_LO <18:16>;
-
-def bitfield FUNCTION < 5: 0>;
-def bitfield FUNCTION_HI < 5: 3>;
-def bitfield FUNCTION_LO < 2: 0>;
-
-// Integer operate format
-def bitfield RT <20:16>;
-def bitfield RT_HI <20:19>;
-def bitfield RT_LO <18:16>;
-
-def bitfield RS <25:21>;
-def bitfield RS_MSB <25:25>;
-def bitfield RS_HI <25:24>;
-def bitfield RS_LO <23:21>;
-
-def bitfield RD <15:11>;
-
-def bitfield INTIMM <15: 0>; // integer immediate (literal)
-
-// Floating-point operate format
-def bitfield FMT <25:21>;
-def bitfield FR <25:21>;
-def bitfield FT <20:16>;
-def bitfield FS <15:11>;
-def bitfield FD <10:6>;
-
-def bitfield CC <20:18>;
-def bitfield ND <17:17>;
-def bitfield TF <16:16>;
-def bitfield MOVCI <16:16>;
-def bitfield MOVCF <16:16>;
-def bitfield SRL <21:21>;
-def bitfield SRLV < 6: 6>;
-def bitfield SA <10: 6>;
-
-// CP0 Register Select
-def bitfield SEL < 2: 0>;
-
-// Interrupts
-def bitfield SC < 5: 5>;
-
-// Branch format
-def bitfield OFFSET <15: 0>; // displacement
-
-// Jmp format
-def bitfield JMPTARG <25: 0>;
-def bitfield HINT <10: 6>;
-
-def bitfield SYSCALLCODE <25: 6>;
-def bitfield TRAPCODE <15:13>;
-
-// M5 instructions
-def bitfield M5FUNC <7:0>;
diff --git a/arch/mips/isa/decoder.isa b/arch/mips/isa/decoder.isa
deleted file mode 100644
index 3f054f6a5..000000000
--- a/arch/mips/isa/decoder.isa
+++ /dev/null
@@ -1,930 +0,0 @@
-// -*- mode:c++ -*-
-
-////////////////////////////////////////////////////////////////////
-//
-// The actual MIPS32 ISA decoder
-// -----------------------------
-// The following instructions are specified in the MIPS32 ISA
-// Specification. Decoding closely follows the style specified
-// in the MIPS32 ISAthe specification document starting with Table
-// A-2 (document available @ www.mips.com)
-//
-//@todo: Distinguish "unknown/future" use insts from "reserved"
-// ones
-decode OPCODE_HI default Unknown::unknown() {
-
- // Derived From ... Table A-2 MIPS32 ISA Manual
- 0x0: decode OPCODE_LO {
-
- 0x0: decode FUNCTION_HI {
- 0x0: decode FUNCTION_LO {
- 0x1: decode MOVCI {
- format BasicOp {
- 0: movf({{ if (xc->readMiscReg(FPCR,0) != CC) Rd = Rs}});
- 1: movt({{ if (xc->readMiscReg(FPCR,0) == CC) Rd = Rs}});
- }
- }
-
- format BasicOp {
-
- //Table A-3 Note: "1. Specific encodings of the rt, rd, and sa fields
- //are used to distinguish among the SLL, NOP, SSNOP and EHB functions."
-
- 0x0: decode RS {
- 0x0: decode RT default BasicOp::sll({{ Rd = Rt.uw << SA; }}) {
- 0x0: decode RD{
- 0x0: decode HINT {
- 0x0:nop({{}}); //really sll r0,r0,0
- 0x1:ssnop({{}});//really sll r0,r0,1
- 0x3:ehb({{}}); //really sll r0,r0,3
- }
- }
- }
- }
-
- 0x2: decode SRL {
- 0: srl({{ Rd = Rt.uw >> SA; }});
-
- //Hardcoded assuming 32-bit ISA, probably need parameter here
- 1: rotr({{ Rd = (Rt.uw << (32 - SA)) | (Rt.uw >> SA);}});
- }
-
- 0x3: sra({{ Rd = Rt.sw >> SA; }});
-
- 0x4: sllv({{ Rd = Rt.uw << Rs<4:0>; }});
-
- 0x6: decode SRLV {
- 0: srlv({{ Rd = Rt.uw >> Rs<4:0>; }});
-
- //Hardcoded assuming 32-bit ISA, probably need parameter here
- 1: rotrv({{ Rd = (Rt.uw << (32 - Rs<4:0>)) | (Rt.uw >> Rs<4:0>);}});
- }
-
- 0x7: srav({{ Rd = Rt.sw >> Rs<4:0>; }});
- }
- }
-
- 0x1: decode FUNCTION_LO {
-
- //Table A-3 Note: "Specific encodings of the hint field are used
- //to distinguish JR from JR.HB and JALR from JALR.HB"
- format Jump {
- 0x0: decode HINT {
- 0:jr({{ NNPC = Rs & ~1; }},IsReturn);
-
- 1:jr_hb({{ NNPC = Rs & ~1; clear_exe_inst_hazards(); }},IsReturn);
- }
-
- 0x1: decode HINT {
- 0: jalr({{ NNPC = Rs; }},IsCall,IsReturn);
-
- 1: jalr_hb({{ NNPC = Rs; clear_exe_inst_hazards();}},IsCall,IsReturn);
- }
- }
-
- format BasicOp {
- 0x2: movz({{ if (Rt == 0) Rd = Rs; }});
- 0x3: movn({{ if (Rt != 0) Rd = Rs; }});
- }
-
- format WarnUnimpl {
- 0x4: syscall();//{{ xc->syscall()}},IsNonSpeculative
- 0x5: break();
- 0x7: sync();
- }
- }
-
- 0x2: decode FUNCTION_LO {
- format BasicOp {
- 0x0: mfhi({{ Rd = xc->readMiscReg(Hi); }});
- 0x1: mthi({{ xc->setMiscReg(Hi,Rs); }});
- 0x2: mflo({{ Rd = xc->readMiscReg(Lo); }});
- 0x3: mtlo({{ xc->setMiscReg(Lo,Rs); }});
- }
- }
-
- 0x3: decode FUNCTION_LO {
- format IntOp {
- 0x0: mult({{
- int64_t temp1 = Rs.sw * Rt.sw;
- xc->setMiscReg(Hi,temp1<63:32>);
- xc->setMiscReg(Lo,temp1<31:0>);
- }});
-
- 0x1: multu({{
- int64_t temp1 = Rs.uw * Rt.uw;
- xc->setMiscReg(Hi,temp1<63:32>);
- xc->setMiscReg(Lo,temp1<31:0>);
- }});
-
- 0x2: div({{
- xc->setMiscReg(Hi,Rs.sw % Rt.sw);
- xc->setMiscReg(Lo,Rs.sw / Rt.sw);
- }});
-
- 0x3: divu({{
- xc->setMiscReg(Hi,Rs.uw % Rt.uw);
- xc->setMiscReg(Lo,Rs.uw / Rt.uw);
- }});
- }
- }
-
- 0x4: decode FUNCTION_LO {
- format IntOp {
- 0x0: add({{ Rd.sw = Rs.sw + Rt.sw;/*Trap on Overflow*/}});
- 0x1: addu({{ Rd.sw = Rs.sw + Rt.sw;}});
- 0x2: sub({{ Rd.sw = Rs.sw - Rt.sw; /*Trap on Overflow*/}});
- 0x3: subu({{ Rd.sw = Rs.sw - Rt.uw;}});
- 0x4: and({{ Rd = Rs & Rt;}});
- 0x5: or({{ Rd = Rs | Rt;}});
- 0x6: xor({{ Rd = Rs ^ Rt;}});
- 0x7: nor({{ Rd = ~(Rs | Rt);}});
- }
- }
-
- 0x5: decode FUNCTION_LO {
- format IntOp{
- 0x2: slt({{ Rd.sw = ( Rs.sw < Rt.sw ) ? 1 : 0}});
- 0x3: sltu({{ Rd.uw = ( Rs.uw < Rt.uw ) ? 1 : 0}});
- }
- }
-
- 0x6: decode FUNCTION_LO {
- format Trap {
- 0x0: tge({{ cond = (Rs.sw >= Rt.sw); }});
- 0x1: tgeu({{ cond = (Rs.uw >= Rt.uw); }});
- 0x2: tlt({{ cond = (Rs.sw < Rt.sw); }});
- 0x3: tltu({{ cond = (Rs.uw >= Rt.uw); }});
- 0x4: teq({{ cond = (Rs.sw == Rt.sw); }});
- 0x6: tne({{ cond = (Rs.sw != Rt.sw); }});
- }
- }
- }
-
- 0x1: decode REGIMM_HI {
- 0x0: decode REGIMM_LO {
- format Branch {
- 0x0: bltz({{ cond = (Rs.sw < 0); }});
- 0x1: bgez({{ cond = (Rs.sw >= 0); }});
- }
-
- format BranchLikely {
- //MIPS obsolete instructions
- 0x2: bltzl({{ cond = (Rs.sw < 0); }});
- 0x3: bgezl({{ cond = (Rs.sw >= 0); }});
- }
- }
-
- 0x1: decode REGIMM_LO {
- format Trap {
- 0x0: tgei( {{ cond = (Rs.sw >= INTIMM); }});
- 0x1: tgeiu({{ cond = (Rs.uw >= INTIMM); }});
- 0x2: tlti( {{ cond = (Rs.sw < INTIMM); }});
- 0x3: tltiu({{ cond = (Rs.uw < INTIMM); }});
- 0x4: teqi( {{ cond = (Rs.sw == INTIMM);}});
- 0x6: tnei( {{ cond = (Rs.sw != INTIMM);}});
- }
- }
-
- 0x2: decode REGIMM_LO {
- format Branch {
- 0x0: bltzal({{ cond = (Rs.sw < 0); }}, IsCall,IsReturn);
- 0x1: bgezal({{ cond = (Rs.sw >= 0); }}, IsCall,IsReturn);
- }
-
- format BranchLikely {
- //Will be removed in future MIPS releases
- 0x2: bltzall({{ cond = (Rs.sw < 0); }}, IsCall, IsReturn);
- 0x3: bgezall({{ cond = (Rs.sw >= 0); }}, IsCall, IsReturn);
- }
- }
-
- 0x3: decode REGIMM_LO {
- format WarnUnimpl {
- 0x7: synci();
- }
- }
- }
-
- format Jump {
- 0x2: j({{ NNPC = (NPC & 0xF0000000) | (JMPTARG << 2);}});
-
- 0x3: jal({{ NNPC = (NPC & 0xF0000000) | (JMPTARG << 2); }},IsCall,IsReturn);
- }
-
- format Branch {
- 0x4: beq({{ cond = (Rs.sw == Rt.sw); }});
- 0x5: bne({{ cond = (Rs.sw != Rt.sw); }});
- 0x6: blez({{ cond = (Rs.sw <= 0); }});
- 0x7: bgtz({{ cond = (Rs.sw > 0); }});
- }
- }
-
- 0x1: decode OPCODE_LO {
- format IntOp {
- 0x0: addi({{ Rt.sw = Rs.sw + imm; /*Trap If Overflow*/}});
- 0x1: addiu({{ Rt.sw = Rs.sw + imm;}});
- 0x2: slti({{ Rt.sw = ( Rs.sw < imm) ? 1 : 0 }});
- 0x3: sltiu({{ Rt.sw = ( Rs.sw < imm ) ? 1 : 0 }});
- 0x4: andi({{ Rt.sw = Rs.sw & INTIMM;}});
- 0x5: ori({{ Rt.sw = Rs.sw | INTIMM;}});
- 0x6: xori({{ Rt.sw = Rs.sw ^ INTIMM;}});
- 0x7: lui({{ Rt = INTIMM << 16}});
- }
- }
-
- 0x2: decode OPCODE_LO {
-
- //Table A-11 MIPS32 COP0 Encoding of rs Field
- 0x0: decode RS_MSB {
- 0x0: decode RS {
- format System {
- 0x0: mfc0({{
- //uint64_t reg_num = Rd.uw;
-
- Rt = xc->readMiscReg(RD << 5 | SEL);
- }});
-
- 0x4: mtc0({{
- //uint64_t reg_num = Rd.uw;
-
- xc->setMiscReg(RD << 5 | SEL,Rt);
- }});
-
- 0x8: mftr({{
- //The contents of the coprocessor 0 register specified by the
- //combination of rd and sel are loaded into general register
- //rt. Note that not all coprocessor 0 registers support the
- //sel field. In those instances, the sel field must be zero.
-
- //MT Code Needed Here
- }});
-
- 0xC: mttr({{
- //The contents of the coprocessor 0 register specified by the
- //combination of rd and sel are loaded into general register
- //rt. Note that not all coprocessor 0 registers support the
- //sel field. In those instances, the sel field must be zero.
-
- //MT Code Needed Here
- }});
-
-
- 0xA: rdpgpr({{
- //Accessing Previous Shadow Set Register Number
- //uint64_t prev = xc->readMiscReg(SRSCtl)/*[PSS]*/;
- //uint64_t reg_num = Rt.uw;
-
- //Rd = xc->regs.IntRegFile[prev];
- //Rd = xc->shadowIntRegFile[prev][reg_num];
- }});
-
- 0xB: decode RD {
-
- 0x0: decode SC {
- 0x0: dvpe({{
- int idx;
- int sel;
- getMiscRegIdx(MVPControl,idx,sel);
- Rt.sw = xc->readMiscReg(idx,sel);
- xc->setMiscReg(idx,sel);
- }});
-
- 0x1: evpe({{
- int idx;
- int sel;
- getMiscRegIdx(MVPControl,idx,sel);
- Rt.sw = xc->readMiscReg(idx,sel);
- xc->setMiscReg(idx,sel,1);
- }});
- }
-
- 0x1: decode SC {
- 0x0: dmt({{
- int idx;
- int sel;
- getMiscRegIdx(VPEControl,idx,sel);
- Rt.sw = xc->readMiscReg(idx,sel);
- xc->setMiscReg(idx,sel);
- }});
-
- 0x1: emt({{
- int idx;
- int sel;
- getMiscRegIdx(VPEControl,idx,sel);
- Rt.sw = xc->readMiscReg(idx,sel);
- xc->setMiscReg(idx,sel,1);
- }});
- }
-
- 0xC: decode SC {
- 0x0: di({{
- int idx;
- int sel;
- getMiscRegIdx(Status,idx,sel);
- Rt.sw = xc->readMiscReg(idx,sel);
- xc->setMiscReg(idx,sel);
- }});
-
- 0x1: ei({{
- int idx;
- int sel;
- getMiscRegIdx(Status,idx,sel);
- Rt.sw = xc->readMiscReg(idx,sel);
- xc->setMiscReg(idx,sel,1);
- }});
- }
- }
-
- 0xE: wrpgpr({{
- //Accessing Previous Shadow Set Register Number
- //uint64_t prev = xc->readMiscReg(SRSCtl/*[PSS]*/);
- //uint64_t reg_num = Rd.uw;
-
- //xc->regs.IntRegFile[prev];
- //xc->shadowIntRegFile[prev][reg_num] = Rt;
- }});
- }
- }
-
- //Table A-12 MIPS32 COP0 Encoding of Function Field When rs=CO
- 0x1: decode FUNCTION {
- format System {
- 0x01: tlbr({{ }});
- 0x02: tlbwi({{ }});
- 0x06: tlbwr({{ }});
- 0x08: tlbp({{ }});
- }
-
- format WarnUnimpl {
- 0x18: eret();
- 0x1F: deret();
- 0x20: wait();
- }
- }
- }
-
- //Table A-13 MIPS32 COP1 Encoding of rs Field
- 0x1: decode RS_MSB {
-
- 0x0: decode RS_HI {
- 0x0: decode RS_LO {
- format FloatOp {
- 0x0: mfc1({{ /*Rt.uw = Fs.ud<31:0>;*/ }});
- 0x2: cfc1({{ /*Rt.uw = xc->readMiscReg(FPCR[Fs]);*/}});
- 0x3: mfhc1({{ /*Rt.uw = Fs.ud<63:32>*/;}});
- 0x4: mtc1({{ /*Fs = Rt.uw*/}});
- 0x6: ctc1({{ /*xc->setMiscReg(FPCR[Fs],Rt);*/}});
- 0x7: mthc1({{ /*Fs<63:32> = Rt.uw*/}});
- }
- }
-
- 0x1: decode ND {
- 0x0: decode TF {
- format Branch {
- 0x0: bc1f({{ cond = (xc->readMiscReg(FPCR) == 0); }});
- 0x1: bc1t({{ cond = (xc->readMiscReg(FPCR) == 1); }});
- }
- }
-
- 0x1: decode TF {
- format BranchLikely {
- 0x0: bc1fl({{ cond = (xc->readMiscReg(FPCR) == 0); }});
- 0x1: bc1tl({{ cond = (xc->readMiscReg(FPCR) == 1); }});
- }
- }
- }
- }
-
- 0x1: decode RS_HI {
- 0x2: decode RS_LO {
-
- //Table A-14 MIPS32 COP1 Encoding of Function Field When rs=S
- //(( single-word ))
- 0x0: decode RS_HI {
- 0x0: decode RS_LO {
- format FloatOp {
- 0x0: adds({{ Fd.sf = Fs.sf + Ft.sf;}});
- 0x1: subs({{ Fd.sf = Fs.sf - Ft.sf;}});
- 0x2: muls({{ Fd.sf = Fs.sf * Ft.sf;}});
- 0x3: divs({{ Fd.sf = Fs.sf / Ft.sf;}});
- 0x4: sqrts({{ Fd.sf = sqrt(Fs.sf);}});
- 0x5: abss({{ Fd.sf = fabs(Fs.sf);}});
- 0x6: movs({{ Fd.sf = Fs.sf;}});
- 0x7: negs({{ Fd.sf = -1 * Fs.sf;}});
- }
- }
-
- 0x1: decode RS_LO {
- //only legal for 64 bit-FP
- format Float64Op {
- 0x0: round_l_s({{ Fd = convert_and_round(Fs.sf,RND_NEAREST,FP_LONG,FP_SINGLE);}});
- 0x1: trunc_l_s({{ Fd = convert_and_round(Fs.sf,RND_ZERO,FP_LONG,FP_SINGLE);}});
- 0x2: ceil_l_s({{ Fd = convert_and_round(Fs.sf,RND_UP,FP_LONG,FP_SINGLE);}});
- 0x3: floor_l_s({{ Fd = convert_and_round(Fs.sf,RND_DOWN,FP_LONG,FP_SINGLE);}});
- }
-
- format FloatOp {
- 0x4: round_w_s({{ Fd = convert_and_round(Fs.sf,RND_NEAREST,FP_WORD,FP_SINGLE);}});
- 0x5: trunc_w_s({{ Fd = convert_and_round(Fs.sf,RND_ZERO,FP_WORD,FP_SINGLE);}});
- 0x6: ceil_w_s({{ Fd = convert_and_round(Fs.sf,RND_UP,FP_WORD,FP_SINGLE);}});
- 0x7: floor_w_s({{ Fd = convert_and_round(Fs.sf,RND_DOWN,FP_WORD,FP_SINGLE);}});
- }
- }
-
- 0x2: decode RS_LO {
- 0x1: decode MOVCF {
- format FloatOp {
- 0x0: movfs({{if (xc->readMiscReg(FPCR) != CC) Fd = Fs; }});
- 0x1: movts({{if (xc->readMiscReg(FPCR) == CC) Fd = Fs;}});
- }
- }
-
- format BasicOp {
- 0x2: movzs({{ if (Rt == 0) Fd = Fs; }});
- 0x3: movns({{ if (Rt != 0) Fd = Fs; }});
- }
-
- format Float64Op {
- 0x5: recips({{ Fd = 1 / Fs; }});
- 0x6: rsqrts({{ Fd = 1 / sqrt((double)Fs.ud);}});
- }
- }
-
- 0x4: decode RS_LO {
-
- format FloatOp {
- 0x1: cvt_d_s({{ int rnd_mode = xc->readMiscReg(FCSR);
- Fd = convert_and_round(Fs.sf,rnd_mode,FP_DOUBLE,FP_SINGLE);
- }});
-
- 0x4: cvt_w_s({{ int rnd_mode = xc->readMiscReg(FCSR);
- Fd = convert_and_round(Fs.sf,rnd_mode,FP_WORD,FP_SINGLE);
- }});
- }
-
- //only legal for 64 bit
- format Float64Op {
- 0x5: cvt_l_s({{ int rnd_mode = xc->readMiscReg(FCSR);
- Fd = convert_and_round(Fs.sf,rnd_mode,FP_LONG,FP_SINGLE);
- }});
-
- 0x6: cvt_ps_s({{ /*Fd.df = Fs.df<31:0> | Ft.df<31:0>;*/ }});
- }
- }
- }
-
- //Table A-15 MIPS32 COP1 Encoding of Function Field When rs=D
- 0x1: decode RS_HI {
- 0x0: decode RS_LO {
- format FloatOp {
- 0x0: addd({{ Fd.df = Fs.df + Ft.df;}});
- 0x1: subd({{ Fd.df = Fs.df - Ft.df;}});
- 0x2: muld({{ Fd.df = Fs.df * Ft.df;}});
- 0x3: divd({{ Fd.df = Fs.df / Ft.df;}});
- 0x4: sqrtd({{ Fd.df = sqrt(Fs.df);}});
- 0x5: absd({{ Fd.df = fabs(Fs.df);}});
- 0x6: movd({{ Fd.df = Fs.df;}});
- 0x7: negd({{ Fd.df = -1 * Fs.df;}});
- }
- }
-
- 0x1: decode RS_LO {
- //only legal for 64 bit
- format Float64Op {
- 0x0: round_l_d({{ Fd = convert_and_round(Fs.df,RND_NEAREST,FP_LONG,FP_DOUBLE); }});
- 0x1: trunc_l_d({{ Fd = convert_and_round(Fs.df,RND_ZERO,FP_LONG,FP_DOUBLE);}});
- 0x2: ceil_l_d({{ Fd = convert_and_round(Fs.df,RND_UP,FP_LONG,FP_DOUBLE);}});
- 0x3: floor_l_d({{ Fd = convert_and_round(Fs.df,RND_DOWN,FP_LONG,FP_DOUBLE);}});
- }
-
- format FloatOp {
- 0x4: round_w_d({{ Fd = convert_and_round(Fs.df,RND_NEAREST,FP_LONG,FP_DOUBLE); }});
- 0x5: trunc_w_d({{ Fd = convert_and_round(Fs.df,RND_ZERO,FP_LONG,FP_DOUBLE); }});
- 0x6: ceil_w_d({{ Fd = convert_and_round(Fs.df,RND_UP,FP_LONG,FP_DOUBLE); }});
- 0x7: floor_w_d({{ Fd = convert_and_round(Fs.df,RND_DOWN,FP_LONG,FP_DOUBLE); }});
- }
- }
-
- 0x2: decode RS_LO {
- 0x1: decode MOVCF {
- format FloatOp {
- 0x0: movfd({{if (xc->readMiscReg(FPCR) != CC) Fd.df = Fs.df; }});
- 0x1: movtd({{if (xc->readMiscReg(FPCR) == CC) Fd.df = Fs.df; }});
- }
- }
-
- format BasicOp {
- 0x2: movzd({{ if (Rt == 0) Fd.df = Fs.df; }});
- 0x3: movnd({{ if (Rt != 0) Fd.df = Fs.df; }});
- }
-
- format Float64Op {
- 0x5: recipd({{ Fd.df = 1 / Fs.df}});
- 0x6: rsqrtd({{ Fd.df = 1 / sqrt(Fs.df) }});
- }
- }
-
- 0x4: decode RS_LO {
- format FloatOp {
- 0x0: cvt_s_d({{
- int rnd_mode = xc->readMiscReg(FCSR);
- Fd = convert_and_round(Fs.df,rnd_mode,FP_SINGLE,FP_DOUBLE);
- }});
-
- 0x4: cvt_w_d({{
- int rnd_mode = xc->readMiscReg(FCSR);
- Fd = convert_and_round(Fs.df,rnd_mode,FP_WORD,FP_DOUBLE);
- }});
- }
-
- //only legal for 64 bit
- format Float64Op {
- 0x5: cvt_l_d({{
- int rnd_mode = xc->readMiscReg(FCSR);
- Fd = convert_and_round(Fs.df,rnd_mode,FP_LONG,FP_DOUBLE);
- }});
- }
- }
- }
-
- //Table A-16 MIPS32 COP1 Encoding of Function Field When rs=W
- 0x4: decode FUNCTION {
- format FloatOp {
- 0x20: cvt_s({{
- int rnd_mode = xc->readMiscReg(FCSR);
- Fd = convert_and_round(Fs.df,rnd_mode,FP_SINGLE,FP_WORD);
- }});
-
- 0x21: cvt_d({{
- int rnd_mode = xc->readMiscReg(FCSR);
- Fd = convert_and_round(Fs.df,rnd_mode,FP_DOUBLE,FP_WORD);
- }});
- }
- }
-
- //Table A-16 MIPS32 COP1 Encoding of Function Field When rs=L1
- //Note: "1. Format type L is legal only if 64-bit floating point operations
- //are enabled."
- 0x5: decode FUNCTION_HI {
- format FloatOp {
- 0x10: cvt_s_l({{
- int rnd_mode = xc->readMiscReg(FCSR);
- Fd = convert_and_round(Fs.df,rnd_mode,FP_SINGLE,FP_LONG);
- }});
-
- 0x11: cvt_d_l({{
- int rnd_mode = xc->readMiscReg(FCSR);
- Fd = convert_and_round(Fs.df,rnd_mode,FP_DOUBLE,FP_LONG);
- }});
- }
- }
-
- //Table A-17 MIPS64 COP1 Encoding of Function Field When rs=PS1
- //Note: "1. Format type PS is legal only if 64-bit floating point operations
- //are enabled. "
- 0x6: decode RS_HI {
- 0x0: decode RS_LO {
- format Float64Op {
- 0x0: addps({{ //Must Check for Exception Here... Supposed to Operate on Upper and
- //Lower Halves Independently but we take simulator shortcut
- Fd.df = Fs.df + Ft.df;
- }});
-
- 0x1: subps({{ //Must Check for Exception Here... Supposed to Operate on Upper and
- //Lower Halves Independently but we take simulator shortcut
- Fd.df = Fs.df - Ft.df;
- }});
-
- 0x2: mulps({{ //Must Check for Exception Here... Supposed to Operate on Upper and
- //Lower Halves Independently but we take simulator shortcut
- Fd.df = Fs.df * Ft.df;
- }});
-
- 0x5: absps({{ //Must Check for Exception Here... Supposed to Operate on Upper and
- //Lower Halves Independently but we take simulator shortcut
- Fd.df = fabs(Fs.df);
- }});
-
- 0x6: movps({{ //Must Check for Exception Here... Supposed to Operate on Upper and
- //Lower Halves Independently but we take simulator shortcut
- //Fd.df = Fs<31:0> | Ft<31:0>;
- }});
-
- 0x7: negps({{ //Must Check for Exception Here... Supposed to Operate on Upper and
- //Lower Halves Independently but we take simulator shortcut
- Fd.df = -1 * Fs.df;
- }});
- }
- }
-
- 0x2: decode RS_LO {
- 0x1: decode MOVCF {
- format Float64Op {
- 0x0: movfps({{if (xc->readMiscReg(FPCR) != CC) Fd = Fs;}});
- 0x1: movtps({{if (xc->readMiscReg(FPCR) == CC) Fd = Fs;}});
- }
- }
-
- format BasicOp {
- 0x2: movzps({{if (xc->readMiscReg(FPCR) != CC) Fd = Fs; }});
- 0x3: movnps({{if (xc->readMiscReg(FPCR) == CC) Fd = Fs; }});
- }
-
- }
-
- 0x4: decode RS_LO {
- 0x0: Float64Op::cvt_s_pu({{
- int rnd_mode = xc->readMiscReg(FCSR);
- Fd = convert_and_round(Fs.df,rnd_mode,FP_DOUBLE,FP_PS_HI);
- }});
- }
-
- 0x5: decode RS_LO {
- format Float64Op {
- 0x0: cvt_s_pl({{
- int rnd_mode = xc->readMiscReg(FCSR);
- Fd = convert_and_round(Fs.df,rnd_mode,FP_SINGLE,FP_PS_LO);
- }});
- 0x4: pll({{ /*Fd.df = Fs<31:0> | Ft<31:0>*/}});
- 0x5: plu({{ /*Fd.df = Fs<31:0> | Ft<63:32>*/}});
- 0x6: pul({{ /*Fd.df = Fs<63:32> | Ft<31:0>*/}});
- 0x7: puu({{ /*Fd.df = Fs<63:32 | Ft<63:32>*/}});
- }
- }
- }
- }
- }
- }
-
- //Table A-19 MIPS32 COP2 Encoding of rs Field
- 0x2: decode RS_MSB {
- 0x0: decode RS_HI {
- 0x0: decode RS_LO {
- format WarnUnimpl {
- 0x0: mfc2();
- 0x2: cfc2();
- 0x3: mfhc2();
- 0x4: mtc2();
- 0x6: ctc2();
- 0x7: mftc2();
- }
- }
-
- 0x1: decode ND {
- 0x0: decode TF {
- format WarnUnimpl {
- 0x0: bc2f();
- 0x1: bc2t();
- }
- }
-
- 0x1: decode TF {
- format WarnUnimpl {
- 0x0: bc2fl();
- 0x1: bc2tl();
- }
- }
- }
- }
- }
-
- //Table A-20 MIPS64 COP1X Encoding of Function Field 1
- //Note: "COP1X instructions are legal only if 64-bit floating point
- //operations are enabled."
- 0x3: decode FUNCTION_HI {
- 0x0: decode FUNCTION_LO {
- format LoadMemory2 {
- 0x0: lwxc1({{ EA = Rs + Rt; }},{{ /*F_t<31:0> = Mem.sf; */}});
- 0x1: ldxc1({{ EA = Rs + Rt; }},{{ /*F_t<63:0> = Mem.df;*/ }});
- 0x5: luxc1({{ //Need to make EA<2:0> = 0
- EA = Rs + Rt;
- }},
- {{ /*F_t<31:0> = Mem.df; */}});
- }
- }
-
- 0x1: decode FUNCTION_LO {
- format StoreMemory2 {
- 0x0: swxc1({{ EA = Rs + Rt; }},{{ /*Mem.sf = Ft<31:0>; */}});
- 0x1: sdxc1({{ EA = Rs + Rt; }},{{ /*Mem.df = Ft<63:0> */}});
- 0x5: suxc1({{ //Need to make EA<2:0> = 0
- EA = Rs + Rt;
- }},
- {{ /*Mem.df = F_t<63:0>;*/}});
- }
-
- 0x7: WarnUnimpl::prefx();
- }
-
- format FloatOp {
- 0x3: WarnUnimpl::alnv_ps();
-
- format BasicOp {
- 0x4: decode FUNCTION_LO {
- 0x0: madd_s({{ Fd.sf = (Fs.sf * Fs.sf) + Fr.sf; }});
- 0x1: madd_d({{ Fd.df = (Fs.df * Fs.df) + Fr.df; }});
- 0x6: madd_ps({{
- //Must Check for Exception Here... Supposed to Operate on Upper and
- //Lower Halves Independently but we take simulator shortcut
- Fd.df = (Fs.df * Fs.df) + Fr.df;
- }});
- }
-
- 0x5: decode FUNCTION_LO {
- 0x0: msub_s({{ Fd.sf = (Fs.sf * Fs.sf) - Fr.sf; }});
- 0x1: msub_d({{ Fd.df = (Fs.df * Fs.df) - Fr.df; }});
- 0x6: msub_ps({{
- //Must Check for Exception Here... Supposed to Operate on Upper and
- //Lower Halves Independently but we take simulator shortcut
- Fd.df = (Fs.df * Fs.df) - Fr.df;
- }});
- }
-
- 0x6: decode FUNCTION_LO {
- 0x0: nmadd_s({{ Fd.sf = (-1 * Fs.sf * Fs.sf) - Fr.sf; }});
- 0x1: nmadd_d({{ Fd.df = (-1 * Fs.df * Fs.df) + Fr.df; }});
- 0x6: nmadd_ps({{
- //Must Check for Exception Here... Supposed to Operate on Upper and
- //Lower Halves Independently but we take simulator shortcut
- Fd.df = (-1 * Fs.df * Fs.df) + Fr.df;
- }});
- }
-
- 0x7: decode FUNCTION_LO {
- 0x0: nmsub_s({{ Fd.sf = (-1 * Fs.sf * Fs.sf) - Fr.sf; }});
- 0x1: nmsub_d({{ Fd.df = (-1 * Fs.df * Fs.df) - Fr.df; }});
- 0x6: nmsub_ps({{
- //Must Check for Exception Here... Supposed to Operate on Upper and
- //Lower Halves Independently but we take simulator shortcut
- Fd.df = (-1 * Fs.df * Fs.df) + Fr.df;
- }});
- }
- }
- }
- }
-
- //MIPS obsolete instructions
- format BranchLikely {
- 0x4: beql({{ cond = (Rs.sw == 0); }});
- 0x5: bnel({{ cond = (Rs.sw != 0); }});
- 0x6: blezl({{ cond = (Rs.sw <= 0); }});
- 0x7: bgtzl({{ cond = (Rs.sw > 0); }});
- }
- }
-
- 0x3: decode OPCODE_LO default FailUnimpl::reserved() {
-
- //Table A-5 MIPS32 SPECIAL2 Encoding of Function Field
- 0x4: decode FUNCTION_HI {
-
- 0x0: decode FUNCTION_LO {
- format IntOp {
- 0x0: madd({{
- int64_t temp1 = xc->readMiscReg(Hi) << 32 | xc->readMiscReg(Lo) >> 32;
- temp1 = temp1 + (Rs.sw * Rt.sw);
- xc->setMiscReg(Hi,temp1<63:32>);
- xc->setMiscReg(Lo,temp1<31:0>);
- }});
-
- 0x1: maddu({{
- int64_t temp1 = xc->readMiscReg(Hi) << 32 | xc->readMiscReg(Lo) >> 32;
- temp1 = temp1 + (Rs.uw * Rt.uw);
- xc->setMiscReg(Hi,temp1<63:32>);
- xc->setMiscReg(Lo,temp1<31:0>);
- }});
-
- 0x2: mul({{ Rd.sw = Rs.sw * Rt.sw; }});
-
- 0x4: msub({{
- int64_t temp1 = xc->readMiscReg(Hi) << 32 | xc->readMiscReg(Lo) >> 32;
- temp1 = temp1 - (Rs.sw * Rt.sw);
- xc->setMiscReg(Hi,temp1<63:32>);
- xc->setMiscReg(Lo,temp1<31:0>);
- }});
-
- 0x5: msubu({{
- int64_t temp1 = xc->readMiscReg(Hi) << 32 | xc->readMiscReg(Lo) >> 32;
- temp1 = temp1 - (Rs.uw * Rt.uw);
- xc->setMiscReg(Hi,temp1<63:32>);
- xc->setMiscReg(Lo,temp1<31:0>);
- }});
- }
- }
-
- 0x4: decode FUNCTION_LO {
- format BasicOp {
- 0x0: clz({{
- /*int cnt = 0;
- int idx = 0;
- while ( Rs.uw<idx> != 1) {
- cnt++;
- idx--;
- }
-
- Rd.uw = cnt;*/
- }});
-
- 0x1: clo({{
- /*int cnt = 0;
- int idx = 0;
- while ( Rs.uw<idx> != 0) {
- cnt++;
- idx--;
- }
-
- Rd.uw = cnt;*/
- }});
- }
- }
-
- 0x7: decode FUNCTION_LO {
- 0x7: WarnUnimpl::sdbbp();
- }
- }
-
- //Table A-6 MIPS32 SPECIAL3 Encoding of Function Field for Release 2 of the Architecture
- 0x7: decode FUNCTION_HI {
-
- 0x0: decode FUNCTION_LO {
- format WarnUnimpl {
- 0x1: ext();
- 0x4: ins();
- }
- }
-
- 0x1: decode FUNCTION_LO {
- format WarnUnimpl {
- 0x0: fork();
- 0x1: yield();
- }
- }
-
-
- //Table A-10 MIPS32 BSHFL Encoding of sa Field
- 0x4: decode SA {
-
- 0x02: WarnUnimpl::wsbh();
-
- format BasicOp {
- 0x10: seb({{ Rd.sw = /* sext32(Rt<7>,24) | */ Rt<7:0>}});
- 0x18: seh({{ Rd.sw = /* sext32(Rt<15>,16) | */ Rt<15:0>}});
- }
- }
-
- 0x6: decode FUNCTION_LO {
- 0x7: BasicOp::rdhwr({{ /*Rt = xc->hwRegs[RD];*/ }});
- }
- }
- }
-
- 0x4: decode OPCODE_LO default FailUnimpl::reserved() {
- format LoadMemory {
- 0x0: lb({{ Rt.sw = Mem.sb; }});
- 0x1: lh({{ Rt.sw = Mem.sh; }});
- 0x2: lwl({{ Rt.sw = Mem.sw; }});//, WordAlign);
- 0x3: lw({{ Rt.sw = Mem.sb; }});
- 0x4: lbu({{ Rt.uw = Mem.ub; }});
- 0x5: lhu({{ Rt.uw = Mem.uh; }});
- 0x6: lwr({{ Rt.uw = Mem.uw; }});//, WordAlign);
- }
-
- 0x7: FailUnimpl::reserved();
- }
-
- 0x5: decode OPCODE_LO default FailUnimpl::reserved() {
- format StoreMemory {
- 0x0: sb({{ Mem.ub = Rt<7:0>; }});
- 0x1: sh({{ Mem.uh = Rt<15:0>; }});
- 0x2: swl({{ Mem.ub = Rt<31:0>; }});//,WordAlign);
- 0x3: sw({{ Mem.ub = Rt<31:0>; }});
- 0x6: swr({{ Mem.ub = Rt<31:0>; }});//,WordAlign);
- }
-
- format WarnUnimpl {
- 0x7: cache();
- }
-
- }
-
- 0x6: decode OPCODE_LO default FailUnimpl::reserved() {
- 0x0: WarnUnimpl::ll();
-
- format LoadMemory {
- 0x1: lwc1({{ /*F_t<31:0> = Mem.sf; */}});
- 0x5: ldc1({{ /*F_t<63:0> = Mem.df; */}});
- }
- }
-
-
- 0x7: decode OPCODE_LO default FailUnimpl::reserved() {
- 0x0: WarnUnimpl::sc();
-
- format StoreMemory {
- 0x1: swc1({{ //Mem.sf = Ft<31:0>; }});
- 0x5: sdc1({{ //Mem.df = Ft<63:0>; }});
- }
- }
-}
-
-
diff --git a/arch/mips/isa/formats.isa b/arch/mips/isa/formats.isa
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
deleted file mode 100644
index 0d2ad7855..000000000
--- a/arch/mips/isa/formats/branch.isa
+++ /dev/null
@@ -1,322 +0,0 @@
-// -*- mode:c++ -*-
-
-////////////////////////////////////////////////////////////////////
-//
-// Control transfer instructions
-//
-
-output header {{
-
-#include <iostream>
- using namespace std;
-
- /**
- * Base class for instructions whose disassembly is not purely a
- * function of the machine instruction (i.e., it depends on the
- * PC). This class overrides the disassemble() method to check
- * the PC and symbol table values before re-using a cached
- * disassembly string. This is necessary for branches and jumps,
- * where the disassembly string includes the target address (which
- * may depend on the PC and/or symbol table).
- */
- class PCDependentDisassembly : public MipsStaticInst
- {
- protected:
- /// Cached program counter from last disassembly
- mutable Addr cachedPC;
-
- /// Cached symbol table pointer from last disassembly
- mutable const SymbolTable *cachedSymtab;
-
- /// Constructor
- PCDependentDisassembly(const char *mnem, MachInst _machInst,
- OpClass __opClass)
- : MipsStaticInst(mnem, _machInst, __opClass),
- cachedPC(0), cachedSymtab(0)
- {
- }
-
- const std::string &
- disassemble(Addr pc, const SymbolTable *symtab) const;
- };
-
- /**
- * Base class for branches (PC-relative control transfers),
- * conditional or unconditional.
- */
- class Branch : public PCDependentDisassembly
- {
- protected:
- /// target address (signed) Displacement .
- int32_t disp;
-
- /// Constructor.
- Branch(const char *mnem, MachInst _machInst, OpClass __opClass)
- : PCDependentDisassembly(mnem, _machInst, __opClass),
- disp(OFFSET << 2)
- {
- //If Bit 17 is 1 then Sign Extend
- if ( (disp & 0x00020000) > 0 ) {
- disp |= 0xFFFE0000;
- }
- }
-
- Addr branchTarget(Addr branchPC) const;
-
- std::string
- generateDisassembly(Addr pc, const SymbolTable *symtab) const;
- };
-
- /**
- * Base class for branch likely branches (PC-relative control transfers),
- */
- class BranchLikely : public PCDependentDisassembly
- {
- protected:
- /// target address (signed) Displacement .
- int32_t disp;
-
- /// Constructor.
- BranchLikely(const char *mnem, MachInst _machInst, OpClass __opClass)
- : PCDependentDisassembly(mnem, _machInst, __opClass),
- disp(OFFSET << 2)
- {
-
- }
-
- Addr branchTarget(Addr branchPC) const;
-
- std::string
- generateDisassembly(Addr pc, const SymbolTable *symtab) const;
- };
-
- /**
- * Base class for jumps (register-indirect control transfers). In
- * the Mips ISA, these are always unconditional.
- */
- class Jump : public PCDependentDisassembly
- {
- protected:
-
- /// Displacement to target address (signed).
- int32_t disp;
-
- uint32_t target;
-
- public:
- /// Constructor
- Jump(const char *mnem, MachInst _machInst, OpClass __opClass)
- : PCDependentDisassembly(mnem, _machInst, __opClass),
- disp(JMPTARG << 2)
- {
- }
-
- Addr branchTarget(ExecContext *xc) const;
-
- std::string
- generateDisassembly(Addr pc, const SymbolTable *symtab) const;
- };
-}};
-
-output decoder {{
- Addr
- Branch::branchTarget(Addr branchPC) const
- {
- return branchPC + 4 + disp;
- }
-
- Addr
- BranchLikely::branchTarget(Addr branchPC) const
- {
- return branchPC + 4 + disp;
- }
-
- Addr
- Jump::branchTarget(ExecContext *xc) const
- {
- Addr NPC = xc->readPC() + 4;
- uint64_t Rb = xc->readIntReg(_srcRegIdx[0]);
- return (Rb & ~3) | (NPC & 1);
- }
-
- const std::string &
- PCDependentDisassembly::disassemble(Addr pc,
- const SymbolTable *symtab) const
- {
- if (!cachedDisassembly ||
- pc != cachedPC || symtab != cachedSymtab)
- {
- if (cachedDisassembly)
- delete cachedDisassembly;
-
- cachedDisassembly =
- new std::string(generateDisassembly(pc, symtab));
- cachedPC = pc;
- cachedSymtab = symtab;
- }
-
- return *cachedDisassembly;
- }
-
- std::string
- Branch::generateDisassembly(Addr pc, const SymbolTable *symtab) const
- {
- std::stringstream ss;
-
- ccprintf(ss, "%-10s ", mnemonic);
-
- // There's only one register arg (RA), but it could be
- // either a source (the condition for conditional
- // branches) or a destination (the link reg for
- // unconditional branches)
- if (_numSrcRegs == 1) {
- printReg(ss, _srcRegIdx[0]);
- ss << ",";
- } else if(_numSrcRegs == 2) {
- printReg(ss, _srcRegIdx[0]);
- ss << ",";
- printReg(ss, _srcRegIdx[1]);
- ss << ",";
- }
-
- Addr target = pc + 8 + disp;
-
- std::string str;
- if (symtab && symtab->findSymbol(target, str))
- ss << str;
- else
- ccprintf(ss, "0x%x", target);
-
- return ss.str();
- }
-
- std::string
- BranchLikely::generateDisassembly(Addr pc, const SymbolTable *symtab) const
- {
- std::stringstream ss;
-
- ccprintf(ss, "%-10s ", mnemonic);
-
- // There's only one register arg (RA), but it could be
- // either a source (the condition for conditional
- // branches) or a destination (the link reg for
- // unconditional branches)
- if (_numSrcRegs > 0) {
- printReg(ss, _srcRegIdx[0]);
- ss << ",";
- }
- else if (_numDestRegs > 0) {
- printReg(ss, _destRegIdx[0]);
- ss << ",";
- }
-
- Addr target = pc + 4 + disp;
-
- std::string str;
- if (symtab && symtab->findSymbol(target, str))
- ss << str;
- else
- ccprintf(ss, "0x%x", target);
-
- return ss.str();
- }
-
- std::string
- Jump::generateDisassembly(Addr pc, const SymbolTable *symtab) const
- {
- std::stringstream ss;
-
- ccprintf(ss, "%-10s ", mnemonic);
-
- if ( mnemonic == "jal" ) {
- Addr npc = pc + 4;
- ccprintf(ss,"0x%x",(npc & 0xF0000000) | disp);
- } else if (_numSrcRegs == 0) {
- std::string str;
- if (symtab && symtab->findSymbol(disp, str))
- ss << str;
- else
- ccprintf(ss, "0x%x", disp);
- } else if (_numSrcRegs == 1) {
- printReg(ss, _srcRegIdx[0]);
- } else if(_numSrcRegs == 2) {
- printReg(ss, _srcRegIdx[0]);
- ss << ",";
- printReg(ss, _srcRegIdx[1]);
- } else {
- panic(">= 3 Source Registers!!!");
- }
-
- return ss.str();
- }
-}};
-
-def format Branch(code,*flags) {{
- #Add Link Code if Link instruction
- strlen = len(name)
- if name[strlen-2:] == 'al':
- code += 'r31 = NNPC;\n'
-
- #Condition code
- code = 'bool cond;\n' + code
- code += 'if (cond) {\n'
- code += ' NNPC = NPC + disp;\n'
- code += '} else {\n'
- code += ' NNPC = NNPC;\n'
- code += '} \n'
-
- code += 'cout << hex << "NPC: " << NPC << " + " << disp << " = " << NNPC << endl;'
-
- iop = InstObjParams(name, Name, 'Branch', CodeBlock(code),
- ('IsDirectControl', 'IsCondControl'))
-
- header_output = BasicDeclare.subst(iop)
- decoder_output = BasicConstructor.subst(iop)
- decode_block = BasicDecode.subst(iop)
- exec_output = BasicExecute.subst(iop)
-}};
-
-
-def format BranchLikely(code,*flags) {{
- #Add Link Code if Link instruction
- strlen = len(name)
- if name[strlen-3:] == 'all':
- code += 'r31 = NNPC;\n'
-
- #Condition code
- code = 'bool cond;\n' + code
- code += 'if (cond) {'
- code += 'NNPC = NPC + disp;\n'
- code += '} \n'
-
-
- iop = InstObjParams(name, Name, 'Branch', CodeBlock(code),
- ('IsDirectControl', 'IsCondControl','IsCondDelaySlot'))
-
- header_output = BasicDeclare.subst(iop)
- decoder_output = BasicConstructor.subst(iop)
- decode_block = BasicDecode.subst(iop)
- exec_output = BasicExecute.subst(iop)
-}};
-
-def format Jump(code,*flags) {{
- #Add Link Code if Link instruction
- strlen = len(name)
- if strlen > 1 and name[1:] == 'al':
- code = 'r31 = NNPC;\n' + code
-
- #code += 'if(NNPC == 0x80000638) { NNPC = r31; cout << "SKIPPING JUMP TO SIM_GET_MEM_CONF" << endl;}'
- #code += 'target = NNPC;'
-
- iop = InstObjParams(name, Name, 'Jump', CodeBlock(code),\
- ('IsIndirectControl', 'IsUncondControl'))
-
- header_output = BasicDeclare.subst(iop)
- decoder_output = BasicConstructor.subst(iop)
- decode_block = BasicDecode.subst(iop)
- exec_output = BasicExecute.subst(iop)
-}};
-
-
-
-
diff --git a/arch/mips/isa/formats/fp.isa b/arch/mips/isa/formats/fp.isa
deleted file mode 100644
index 34b71acf7..000000000
--- a/arch/mips/isa/formats/fp.isa
+++ /dev/null
@@ -1,49 +0,0 @@
-// -*- mode:c++ -*-
-
-////////////////////////////////////////////////////////////////////
-//
-// Floating Point operate instructions
-//
-
-output header {{
- /**
- * Base class for FP operations.
- */
- class FPOp : public MipsStaticInst
- {
- protected:
-
- /// Constructor
- FPOp(const char *mnem, MachInst _machInst, OpClass __opClass) : MipsStaticInst(mnem, _machInst, __opClass)
- {
- }
-
- std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
- };
-}};
-
-output decoder {{
- std::string FPOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
- {
- return "Disassembly of integer instruction\n";
- }
-}};
-
-
-// Primary format for integer operate instructions:
-def format FloatOp(code, *flags) {{
- iop = InstObjParams(name, Name, 'MipsStaticInst', CodeBlock(code), flags)
- header_output = BasicDeclare.subst(iop)
- decoder_output = BasicConstructor.subst(iop)
- decode_block = BasicDecode.subst(iop)
- exec_output = BasicExecute.subst(iop)
-}};
-
-// Primary format for integer operate instructions:
-def format Float64Op(code, *flags) {{
- iop = InstObjParams(name, Name, 'MipsStaticInst', CodeBlock(code), flags)
- header_output = BasicDeclare.subst(iop)
- decoder_output = BasicConstructor.subst(iop)
- decode_block = BasicDecode.subst(iop)
- exec_output = BasicExecute.subst(iop)
-}};
diff --git a/arch/mips/isa/formats/int.isa b/arch/mips/isa/formats/int.isa
deleted file mode 100644
index a47844bee..000000000
--- a/arch/mips/isa/formats/int.isa
+++ /dev/null
@@ -1,130 +0,0 @@
-// -*- mode:c++ -*-
-
-////////////////////////////////////////////////////////////////////
-//
-// Integer operate instructions
-//
-
-//Outputs to decoder.hh
-output header {{
-#include <iostream>
- using namespace std;
- /**
- * Base class for integer operations.
- */
- class IntOp : public MipsStaticInst
- {
- protected:
-
- /// Constructor
- IntOp(const char *mnem, MachInst _machInst, OpClass __opClass) :
- MipsStaticInst(mnem, _machInst, __opClass)
- {
- }
-
- std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
- };
-
- class IntImmOp : public MipsStaticInst
- {
- protected:
-
- int32_t imm;
-
- /// Constructor
- IntImmOp(const char *mnem, MachInst _machInst, OpClass __opClass) :
- MipsStaticInst(mnem, _machInst, __opClass),imm(INTIMM)
- {
- //If Bit 15 is 1 then Sign Extend
- int32_t temp = imm & 0x00008000;
-
- if (temp > 0 && mnemonic != "lui") {
- imm |= 0xFFFF0000;
- }
- }
-
- std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
-
-
- };
-
-}};
-
-//Outputs to decoder.cc
-output decoder {{
- std::string IntOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
- {
- std::stringstream ss;
-
- ccprintf(ss, "%-10s ", mnemonic);
-
- // just print the first dest... if there's a second one,
- // it's generally implicit
- if (_numDestRegs > 0) {
- printReg(ss, _destRegIdx[0]);
- }
-
- ss << ",";
-
- // just print the first two source regs... if there's
- // a third one, it's a read-modify-write dest (Rc),
- // e.g. for CMOVxx
- if (_numSrcRegs > 0) {
- printReg(ss, _srcRegIdx[0]);
- }
-
- if (_numSrcRegs > 1) {
- ss << ",";
- printReg(ss, _srcRegIdx[1]);
- }
-
- return ss.str();
- }
-
- std::string IntImmOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
- {
- std::stringstream ss;
-
- ccprintf(ss, "%-10s ", mnemonic);
-
- if (_numDestRegs > 0) {
- printReg(ss, _destRegIdx[0]);
- }
-
- ss << ",";
-
- if (_numSrcRegs > 0) {
- printReg(ss, _srcRegIdx[0]);
- ss << ",";
- }
-
- if( mnemonic == "lui")
- ccprintf(ss, "%08p ", imm);
- else
- ss << (int) imm;
-
- return ss.str();
- }
-
-}};
-
-//Used by decoder.isa
-def format IntOp(code, *opt_flags) {{
- orig_code = code
- cblk = CodeBlock(code)
-
- # Figure out if we are creating a IntImmOp or a IntOp
- # by looking at the instruction name
- iop = InstObjParams(name, Name, 'IntOp', cblk, opt_flags)
- strlen = len(name)
- if name[strlen-1] == 'i' or name[strlen-2:] == 'iu':
- iop = InstObjParams(name, Name, 'IntImmOp', cblk, opt_flags)
-
- header_output = BasicDeclare.subst(iop)
- decoder_output = BasicConstructor.subst(iop)
- decode_block = OperateNopCheckDecode.subst(iop)
- exec_output = BasicExecute.subst(iop)
-}};
-
-
-
diff --git a/arch/mips/isa/formats/mem.isa b/arch/mips/isa/formats/mem.isa
deleted file mode 100644
index 8a07e63d4..000000000
--- a/arch/mips/isa/formats/mem.isa
+++ /dev/null
@@ -1,469 +0,0 @@
-// -*- mode:c++ -*-
-
-// Copyright (c) 2003-2005 The Regents of The University of Michigan
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met: redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer;
-// redistributions in binary form must reproduce the above copyright
-// notice, this list of conditions and the following disclaimer in the
-// documentation and/or other materials provided with the distribution;
-// neither the name of the copyright holders nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-output header {{
- /**
- * Base class for general Mips memory-format instructions.
- */
- class Memory : public MipsStaticInst
- {
- protected:
-
- /// Memory request flags. See mem_req_base.hh.
- unsigned memAccessFlags;
- /// Pointer to EAComp object.
- const StaticInstPtr eaCompPtr;
- /// Pointer to MemAcc object.
- const StaticInstPtr memAccPtr;
-
- /// Displacement for EA calculation (signed).
- int32_t disp;
-
- /// Constructor
- Memory(const char *mnem, MachInst _machInst, OpClass __opClass,
- StaticInstPtr _eaCompPtr = nullStaticInstPtr,
- StaticInstPtr _memAccPtr = nullStaticInstPtr)
- : MipsStaticInst(mnem, _machInst, __opClass),
- memAccessFlags(0), eaCompPtr(_eaCompPtr), memAccPtr(_memAccPtr),
- disp(OFFSET)
- {
- //If Bit 15 is 1 then Sign Extend
- int32_t temp = disp & 0x00008000;
-
- if (temp > 0) {
- disp |= 0xFFFF0000;
- }
- }
-
- std::string
- generateDisassembly(Addr pc, const SymbolTable *symtab) const;
-
- public:
-
- const StaticInstPtr &eaCompInst() const { return eaCompPtr; }
- const StaticInstPtr &memAccInst() const { return memAccPtr; }
- };
-
-}};
-
-
-output decoder {{
- std::string
- Memory::generateDisassembly(Addr pc, const SymbolTable *symtab) const
- {
- return csprintf("%-10s %c%d,%d(r%d)", mnemonic,
- flags[IsFloating] ? 'f' : 'r', RT, disp, RS);
- }
-
-}};
-
-def format LoadAddress(code) {{
- iop = InstObjParams(name, Name, 'MemoryDisp32', CodeBlock(code))
- header_output = BasicDeclare.subst(iop)
- decoder_output = BasicConstructor.subst(iop)
- decode_block = BasicDecode.subst(iop)
- exec_output = BasicExecute.subst(iop)
-}};
-
-
-def template LoadStoreDeclare {{
- /**
- * Static instruction class for "%(mnemonic)s".
- */
- class %(class_name)s : public %(base_class)s
- {
- protected:
-
- /**
- * "Fake" effective address computation class for "%(mnemonic)s".
- */
- class EAComp : public %(base_class)s
- {
- public:
- /// Constructor
- EAComp(MachInst machInst);
-
- %(BasicExecDeclare)s
- };
-
- /**
- * "Fake" memory access instruction class for "%(mnemonic)s".
- */
- class MemAcc : public %(base_class)s
- {
- public:
- /// Constructor
- MemAcc(MachInst machInst);
-
- %(BasicExecDeclare)s
- };
-
- public:
-
- /// Constructor.
- %(class_name)s(MachInst machInst);
-
- %(BasicExecDeclare)s
-
- %(InitiateAccDeclare)s
-
- %(CompleteAccDeclare)s
- };
-}};
-
-
-def template InitiateAccDeclare {{
- Fault initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const;
-}};
-
-
-def template CompleteAccDeclare {{
- Fault completeAcc(uint8_t *, %(CPU_exec_context)s *, Trace::InstRecord *) const;
-}};
-
-
-def template LoadStoreConstructor {{
- /** TODO: change op_class to AddrGenOp or something (requires
- * creating new member of OpClass enum in op_class.hh, updating
- * config files, etc.). */
- inline %(class_name)s::EAComp::EAComp(MachInst machInst)
- : %(base_class)s("%(mnemonic)s (EAComp)", machInst, IntAluOp)
- {
- %(ea_constructor)s;
- }
-
- inline %(class_name)s::MemAcc::MemAcc(MachInst machInst)
- : %(base_class)s("%(mnemonic)s (MemAcc)", machInst, %(op_class)s)
- {
- %(memacc_constructor)s;
- }
-
- inline %(class_name)s::%(class_name)s(MachInst machInst)
- : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
- new EAComp(machInst), new MemAcc(machInst))
- {
- %(constructor)s;
- }
-}};
-
-
-def template EACompExecute {{
- Fault
- %(class_name)s::EAComp::execute(%(CPU_exec_context)s *xc,
- Trace::InstRecord *traceData) const
- {
- Addr EA;
- Fault fault = NoFault;
-
- %(fp_enable_check)s;
- %(op_decl)s;
- %(op_rd)s;
- %(code)s;
-
- if (fault == NoFault) {
- %(op_wb)s;
- xc->setEA(EA);
- }
-
- return fault;
- }
-}};
-
-def template LoadMemAccExecute {{
- Fault
- %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
- Trace::InstRecord *traceData) const
- {
- Addr EA;
- Fault fault = NoFault;
-
- %(fp_enable_check)s;
- %(op_decl)s;
- %(op_rd)s;
- EA = xc->getEA();
-
- if (fault == NoFault) {
- fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags);
- %(code)s;
- }
-
- if (fault == NoFault) {
- %(op_wb)s;
- }
-
- return fault;
- }
-}};
-
-
-def template LoadExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
- Trace::InstRecord *traceData) const
- {
- Addr EA;
- Fault fault = NoFault;
-
- %(fp_enable_check)s;
- %(op_decl)s;
- %(op_rd)s;
- %(ea_code)s;
-
- if (fault == NoFault) {
- fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags);
- %(memacc_code)s;
- }
-
- if (fault == NoFault) {
- %(op_wb)s;
- }
-
- return fault;
- }
-}};
-
-
-def template LoadInitiateAcc {{
- Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
- Trace::InstRecord *traceData) const
- {
- Addr EA;
- Fault fault = NoFault;
-
- %(fp_enable_check)s;
- %(op_src_decl)s;
- %(op_rd)s;
- %(ea_code)s;
-
- if (fault == NoFault) {
- fault = xc->read(EA, (uint%(mem_acc_size)d_t &)Mem, memAccessFlags);
- }
-
- return fault;
- }
-}};
-
-
-def template LoadCompleteAcc {{
- Fault %(class_name)s::completeAcc(uint8_t *data,
- %(CPU_exec_context)s *xc,
- Trace::InstRecord *traceData) const
- {
- Fault fault = NoFault;
-
- %(fp_enable_check)s;
- %(op_src_decl)s;
- %(op_dest_decl)s;
-
- memcpy(&Mem, data, sizeof(Mem));
-
- if (fault == NoFault) {
- %(memacc_code)s;
- }
-
- if (fault == NoFault) {
- %(op_wb)s;
- }
-
- return fault;
- }
-}};
-
-
-def template StoreMemAccExecute {{
- Fault
- %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
- Trace::InstRecord *traceData) const
- {
- Addr EA;
- Fault fault = NoFault;
- uint64_t write_result = 0;
-
- %(fp_enable_check)s;
- %(op_decl)s;
- %(op_rd)s;
- EA = xc->getEA();
-
- if (fault == NoFault) {
- %(code)s;
- }
-
- if (fault == NoFault) {
- fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
- memAccessFlags, &write_result);
- if (traceData) { traceData->setData(Mem); }
- }
-
- if (fault == NoFault) {
- %(postacc_code)s;
- }
-
- if (fault == NoFault) {
- %(op_wb)s;
- }
-
- return fault;
- }
-}};
-
-
-def template StoreExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
- Trace::InstRecord *traceData) const
- {
- Addr EA;
- Fault fault = NoFault;
- uint64_t write_result = 0;
-
- %(fp_enable_check)s;
- %(op_decl)s;
- %(op_rd)s;
- %(ea_code)s;
-
- if (fault == NoFault) {
- %(memacc_code)s;
- }
-
- if (fault == NoFault) {
- fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
- memAccessFlags, &write_result);
- if (traceData) { traceData->setData(Mem); }
- }
-
- if (fault == NoFault) {
- %(postacc_code)s;
- }
-
- if (fault == NoFault) {
- %(op_wb)s;
- }
-
- return fault;
- }
-}};
-
-def template StoreInitiateAcc {{
- Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
- Trace::InstRecord *traceData) const
- {
- Addr EA;
- Fault fault = NoFault;
- uint64_t write_result = 0;
-
- %(fp_enable_check)s;
- %(op_src_decl)s;
- %(op_dest_decl)s;
- %(op_rd)s;
- %(ea_code)s;
-
- if (fault == NoFault) {
- %(memacc_code)s;
- }
-
- if (fault == NoFault) {
- fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
- memAccessFlags, &write_result);
- if (traceData) { traceData->setData(Mem); }
- }
-
- return fault;
- }
-}};
-
-
-def template StoreCompleteAcc {{
- Fault %(class_name)s::completeAcc(uint8_t *data,
- %(CPU_exec_context)s *xc,
- Trace::InstRecord *traceData) const
- {
- Fault fault = NoFault;
- uint64_t write_result = 0;
-
- %(fp_enable_check)s;
- %(op_dest_decl)s;
-
- memcpy(&write_result, data, sizeof(write_result));
-
- if (fault == NoFault) {
- %(postacc_code)s;
- }
-
- if (fault == NoFault) {
- %(op_wb)s;
- }
-
- return fault;
- }
-}};
-
-// load instructions use Rt as dest, so check for
-// Rt == 31 to detect nops
-def template LoadNopCheckDecode {{
- {
- MipsStaticInst *i = new %(class_name)s(machInst);
- if (RT == 0) {
- i = makeNop(i);
- }
- return i;
- }
-}};
-
-def format LoadMemory(memacc_code, ea_code = {{ EA = Rs + disp; }},
- mem_flags = [], inst_flags = []) {{
- (header_output, decoder_output, decode_block, exec_output) = \
- LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
- decode_template = LoadNopCheckDecode,
- exec_template_base = 'Load')
-}};
-
-
-def format StoreMemory(memacc_code, ea_code = {{ EA = Rs + disp; }},
- mem_flags = [], inst_flags = []) {{
- (header_output, decoder_output, decode_block, exec_output) = \
- LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
- exec_template_base = 'Store')
-}};
-
-//FP loads are offloaded to these formats for now ...
-def format LoadMemory2(ea_code = {{ EA = Rs + disp; }}, memacc_code = {{ }},
- mem_flags = [], inst_flags = []) {{
- (header_output, decoder_output, decode_block, exec_output) = \
- LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
- decode_template = LoadNopCheckDecode,
- exec_template_base = 'Load')
-}};
-
-
-//FP stores are offloaded to these formats for now ...
-def format StoreMemory2(ea_code = {{ EA = Rs + disp; }},memacc_code = {{ }},
- mem_flags = [], inst_flags = []) {{
- (header_output, decoder_output, decode_block, exec_output) = \
- LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
- decode_template = LoadNopCheckDecode,
- exec_template_base = 'Store')
-}};
-
diff --git a/arch/mips/isa/formats/noop.isa b/arch/mips/isa/formats/noop.isa
deleted file mode 100644
index d35179005..000000000
--- a/arch/mips/isa/formats/noop.isa
+++ /dev/null
@@ -1,90 +0,0 @@
-// -*- mode:c++ -*-
-
-////////////////////////////////////////////////////////////////////
-//
-// Nop
-//
-
-output header {{
- /**
- * Static instruction class for no-ops. This is a leaf class.
- */
- class Nop : public MipsStaticInst
- {
- /// Disassembly of original instruction.
- const std::string originalDisassembly;
-
- public:
- /// Constructor
- Nop(const std::string _originalDisassembly, MachInst _machInst)
- : MipsStaticInst("nop", _machInst, No_OpClass),
- originalDisassembly(_originalDisassembly)
- {
- flags[IsNop] = true;
- }
-
- ~Nop() { }
-
- std::string
- generateDisassembly(Addr pc, const SymbolTable *symtab) const;
-
- %(BasicExecDeclare)s
- };
-}};
-
-output decoder {{
- std::string Nop::generateDisassembly(Addr pc,
- const SymbolTable *symtab) const
- {
-#ifdef SS_COMPATIBLE_DISASSEMBLY
- return originalDisassembly;
-#else
- return csprintf("%-10s (%s)", "nop", originalDisassembly);
-#endif
- }
-
- /// Helper function for decoding nops. Substitute Nop object
- /// for original inst passed in as arg (and delete latter).
- inline
- MipsStaticInst *
- makeNop(MipsStaticInst *inst)
- {
- MipsStaticInst *nop = new Nop(inst->disassemble(0), inst->machInst);
- delete inst;
- return nop;
- }
-}};
-
-output exec {{
- Fault
- Nop::execute(%(CPU_exec_context)s *, Trace::InstRecord *) const
- {
- return NoFault;
- }
-}};
-
-// integer & FP operate instructions use RT as dest, so check for
-// RT == 0 to detect nops
-def template OperateNopCheckDecode {{
- {
- MipsStaticInst *i = new %(class_name)s(machInst);
-
- //if (RD == 0) {
- // i = makeNop(i);
- //}
-
- return i;
- }
-}};
-
-
-// Like BasicOperate format, but generates NOP if RC/FC == 31
-def format BasicOperateWithNopCheck(code, *opt_args) {{
- iop = InstObjParams(name, Name, 'MipsStaticInst', CodeBlock(code),
- opt_args)
- header_output = BasicDeclare.subst(iop)
- decoder_output = BasicConstructor.subst(iop)
- decode_block = OperateNopCheckDecode.subst(iop)
- exec_output = BasicExecute.subst(iop)
-}};
-
diff --git a/arch/mips/isa/formats/unimp.isa b/arch/mips/isa/formats/unimp.isa
deleted file mode 100644
index adbd5b5b1..000000000
--- a/arch/mips/isa/formats/unimp.isa
+++ /dev/null
@@ -1,165 +0,0 @@
-// -*- mode:c++ -*-
-
-// Copyright (c) 2003-2005 The Regents of The University of Michigan
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met: redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer;
-// redistributions in binary form must reproduce the above copyright
-// notice, this list of conditions and the following disclaimer in the
-// documentation and/or other materials provided with the distribution;
-// neither the name of the copyright holders nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-output header {{
- /**
- * Static instruction class for unimplemented instructions that
- * cause simulator termination. Note that these are recognized
- * (legal) instructions that the simulator does not support; the
- * 'Unknown' class is used for unrecognized/illegal instructions.
- * This is a leaf class.
- */
- class FailUnimplemented : public MipsStaticInst
- {
- public:
- /// Constructor
- FailUnimplemented(const char *_mnemonic, MachInst _machInst)
- : MipsStaticInst(_mnemonic, _machInst, No_OpClass)
- {
- // don't call execute() (which panics) if we're on a
- // speculative path
- flags[IsNonSpeculative] = true;
- }
-
- %(BasicExecDeclare)s
-
- std::string
- generateDisassembly(Addr pc, const SymbolTable *symtab) const;
- };
-
- /**
- * Base class for unimplemented instructions that cause a warning
- * to be printed (but do not terminate simulation). This
- * implementation is a little screwy in that it will print a
- * warning for each instance of a particular unimplemented machine
- * instruction, not just for each unimplemented opcode. Should
- * probably make the 'warned' flag a static member of the derived
- * class.
- */
- class WarnUnimplemented : public MipsStaticInst
- {
- private:
- /// Have we warned on this instruction yet?
- mutable bool warned;
-
- public:
- /// Constructor
- WarnUnimplemented(const char *_mnemonic, MachInst _machInst)
- : MipsStaticInst(_mnemonic, _machInst, No_OpClass), warned(false)
- {
- // don't call execute() (which panics) if we're on a
- // speculative path
- flags[IsNonSpeculative] = true;
- }
-
- %(BasicExecDeclare)s
-
- std::string
- generateDisassembly(Addr pc, const SymbolTable *symtab) const;
- };
-}};
-
-output decoder {{
- std::string
- FailUnimplemented::generateDisassembly(Addr pc,
- const SymbolTable *symtab) const
- {
- return csprintf("%-10s (unimplemented)", mnemonic);
- }
-
- std::string
- WarnUnimplemented::generateDisassembly(Addr pc,
- const SymbolTable *symtab) const
- {
-#ifdef SS_COMPATIBLE_DISASSEMBLY
- return csprintf("%-10s", mnemonic);
-#else
- return csprintf("%-10s (unimplemented)", mnemonic);
-#endif
- }
-}};
-
-output exec {{
- Fault
- FailUnimplemented::execute(%(CPU_exec_context)s *xc,
- Trace::InstRecord *traceData) const
- {
- panic("attempt to execute unimplemented instruction '%s' "
- "(inst 0x%08x, opcode 0x%x)", mnemonic, machInst, OPCODE);
- return UnimplementedOpcodeFault;
- }
-
- Fault
- WarnUnimplemented::execute(%(CPU_exec_context)s *xc,
- Trace::InstRecord *traceData) const
- {
- if (!warned) {
- warn("instruction '%s' unimplemented\n", mnemonic);
- warned = true;
- }
-
- return NoFault;
- }
-}};
-
-
-def format FailUnimpl() {{
- iop = InstObjParams(name, 'FailUnimplemented')
- decode_block = BasicDecodeWithMnemonic.subst(iop)
-}};
-
-def format WarnUnimpl() {{
- iop = InstObjParams(name, 'WarnUnimplemented')
- decode_block = BasicDecodeWithMnemonic.subst(iop)
-}};
-
-output header {{
- /**
- * Static instruction class for unknown (illegal) instructions.
- * These cause simulator termination if they are executed in a
- * non-speculative mode. This is a leaf class.
- */
- class Unknown : public MipsStaticInst
- {
- public:
- /// Constructor
- Unknown(MachInst _machInst)
- : MipsStaticInst("unknown", _machInst, No_OpClass)
- {
- // don't call execute() (which panics) if we're on a
- // speculative path
- flags[IsNonSpeculative] = true;
- }
-
- %(BasicExecDeclare)s
-
- std::string
- generateDisassembly(Addr pc, const SymbolTable *symtab) const;
- };
-}};
-
diff --git a/arch/mips/isa/formats/unknown.isa b/arch/mips/isa/formats/unknown.isa
deleted file mode 100644
index 4601b3684..000000000
--- a/arch/mips/isa/formats/unknown.isa
+++ /dev/null
@@ -1,52 +0,0 @@
-// -*- mode:c++ -*-
-
-// Copyright (c) 2003-2005 The Regents of The University of Michigan
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met: redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer;
-// redistributions in binary form must reproduce the above copyright
-// notice, this list of conditions and the following disclaimer in the
-// documentation and/or other materials provided with the distribution;
-// neither the name of the copyright holders nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-output decoder {{
- std::string
- Unknown::generateDisassembly(Addr pc, const SymbolTable *symtab) const
- {
- return csprintf("%-10s (inst 0x%x, opcode 0x%x)",
- "unknown", machInst, OPCODE);
- }
-}};
-
-output exec {{
- Fault
- Unknown::execute(%(CPU_exec_context)s *xc,
- Trace::InstRecord *traceData) const
- {
- panic("attempt to execute unknown instruction "
- "(inst 0x%08x, opcode 0x%x)", machInst, OPCODE);
- return UnimplementedOpcodeFault;
- }
-}};
-
-def format Unknown() {{
- decode_block = 'return new Unknown(machInst);\n'
-}};
-
diff --git a/arch/mips/isa/formats/util.isa b/arch/mips/isa/formats/util.isa
deleted file mode 100644
index db4bf204a..000000000
--- a/arch/mips/isa/formats/util.isa
+++ /dev/null
@@ -1,148 +0,0 @@
-// -*- mode:c++ -*-
-
-let {{
-def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
- postacc_code = '', base_class = 'Memory',
- decode_template = BasicDecode, exec_template_base = ''):
- # Make sure flags are in lists (convert to lists if not).
- mem_flags = makeList(mem_flags)
- inst_flags = makeList(inst_flags)
-
- # add hook to get effective addresses into execution trace output.
- ea_code += '\nif (traceData) { traceData->setAddr(EA); }\n'
-
- # generate code block objects
- ea_cblk = CodeBlock(ea_code)
- memacc_cblk = CodeBlock(memacc_code)
- postacc_cblk = CodeBlock(postacc_code)
-
- # Some CPU models execute the memory operation as an atomic unit,
- # while others want to separate them into an effective address
- # computation and a memory access operation. As a result, we need
- # to generate three StaticInst objects. Note that the latter two
- # are nested inside the larger "atomic" one.
-
- # generate InstObjParams for EAComp object
- ea_iop = InstObjParams(name, Name, base_class, ea_cblk, inst_flags)
-
- # generate InstObjParams for MemAcc object
- memacc_iop = InstObjParams(name, Name, base_class, memacc_cblk, inst_flags)
- # in the split execution model, the MemAcc portion is responsible
- # for the post-access code.
- memacc_iop.postacc_code = postacc_cblk.code
-
- # generate InstObjParams for InitiateAcc, CompleteAcc object
- # The code used depends on the template being used
- if (exec_template_base == 'Load'):
- initiateacc_cblk = CodeBlock(ea_code + memacc_code)
- completeacc_cblk = CodeBlock(memacc_code + postacc_code)
- elif (exec_template_base == 'Store'):
- initiateacc_cblk = CodeBlock(ea_code + memacc_code)
- completeacc_cblk = CodeBlock(postacc_code)
- else:
- initiateacc_cblk = ''
- completeacc_cblk = ''
-
- initiateacc_iop = InstObjParams(name, Name, base_class, initiateacc_cblk,
- inst_flags)
-
- completeacc_iop = InstObjParams(name, Name, base_class, completeacc_cblk,
- inst_flags)
-
- if (exec_template_base == 'Load'):
- initiateacc_iop.ea_code = ea_cblk.code
- initiateacc_iop.memacc_code = memacc_cblk.code
- completeacc_iop.memacc_code = memacc_cblk.code
- completeacc_iop.postacc_code = postacc_cblk.code
- elif (exec_template_base == 'Store'):
- initiateacc_iop.ea_code = ea_cblk.code
- initiateacc_iop.memacc_code = memacc_cblk.code
- completeacc_iop.postacc_code = postacc_cblk.code
-
- # generate InstObjParams for unified execution
- cblk = CodeBlock(ea_code + memacc_code + postacc_code)
- iop = InstObjParams(name, Name, base_class, cblk, inst_flags)
-
- iop.ea_constructor = ea_cblk.constructor
- iop.ea_code = ea_cblk.code
- iop.memacc_constructor = memacc_cblk.constructor
- iop.memacc_code = memacc_cblk.code
- iop.postacc_code = postacc_cblk.code
-
- if mem_flags:
- s = '\n\tmemAccessFlags = ' + string.join(mem_flags, '|') + ';'
- iop.constructor += s
- memacc_iop.constructor += s
-
- # select templates
- memAccExecTemplate = eval(exec_template_base + 'MemAccExecute')
- fullExecTemplate = eval(exec_template_base + 'Execute')
- initiateAccTemplate = eval(exec_template_base + 'InitiateAcc')
- completeAccTemplate = eval(exec_template_base + 'CompleteAcc')
-
- # (header_output, decoder_output, decode_block, exec_output)
- return (LoadStoreDeclare.subst(iop), LoadStoreConstructor.subst(iop),
- decode_template.subst(iop),
- EACompExecute.subst(ea_iop)
- + memAccExecTemplate.subst(memacc_iop)
- + fullExecTemplate.subst(iop)
- + initiateAccTemplate.subst(initiateacc_iop)
- + completeAccTemplate.subst(completeacc_iop))
-}};
-
-
-output exec {{
-
-using namespace MipsISA;
-
-
- /// CLEAR ALL CPU INST/EXE HAZARDS
- inline void
- clear_exe_inst_hazards()
- {
- //CODE HERE
- }
-
-
- /// Check "FP enabled" machine status bit. Called when executing any FP
- /// instruction in full-system mode.
- /// @retval Full-system mode: NoFault if FP is enabled, FenFault
- /// if not. Non-full-system mode: always returns NoFault.
-#if FULL_SYSTEM
- inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc)
- {
- Fault fault = NoFault; // dummy... this ipr access should not fault
- if (!Mips34k::ICSR_FPE(xc->readIpr(MipsISA::IPR_ICSR, fault))) {
- fault = FloatEnableFault;
- }
- return fault;
- }
-#else
- inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc)
- {
- return NoFault;
- }
-#endif
-
- double convert_and_round(float w, int x, int y, int z)
- {
- double temp = .34000;
-
- return temp;
- }
-
- enum FPTypes{
- FP_SINGLE,
- FP_DOUBLE,
- FP_LONG,
- FP_PS_LO,
- FP_PS_HI,
- FP_WORD,
- RND_NEAREST,
- RND_ZERO,
- RND_UP,
- RND_DOWN
- };
-}};
-
-
diff --git a/arch/mips/isa/includes.isa b/arch/mips/isa/includes.isa
deleted file mode 100644
index da919be00..000000000
--- a/arch/mips/isa/includes.isa
+++ /dev/null
@@ -1,39 +0,0 @@
-////////////////////////////////////////////////////////////////////
-//
-// Output include file directives.
-//
-
-output header {{
-#include <sstream>
-#include <iostream>
-#include <iomanip>
-
-#include "cpu/static_inst.hh"
-#include "mem/mem_req.hh" // some constructors use MemReq flags
-}};
-
-output decoder {{
-#include "base/cprintf.hh"
-#include "base/loader/symtab.hh"
-#include "cpu/exec_context.hh" // for Jump::branchTarget()
-
-#include <math.h>
-#if defined(linux)
-#include <fenv.h>
-#endif
-}};
-
-output exec {{
-#include <math.h>
-#if defined(linux)
-#include <fenv.h>
-#endif
-
-#ifdef FULL_SYSTEM
-//#include "arch/alpha/pseudo_inst.hh"
-#endif
-#include "cpu/base.hh"
-#include "cpu/exetrace.hh"
-#include "sim/sim_exit.hh"
-}};
-
diff --git a/arch/mips/isa/main.isa b/arch/mips/isa/main.isa
deleted file mode 100644
index 411e398b4..000000000
--- a/arch/mips/isa/main.isa
+++ /dev/null
@@ -1,52 +0,0 @@
-// -*- mode:c++ -*-
-
-// Copyright (c) 2003-2005 The Regents of The University of Michigan
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met: redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer;
-// redistributions in binary form must reproduce the above copyright
-// notice, this list of conditions and the following disclaimer in the
-// documentation and/or other materials provided with the distribution;
-// neither the name of the copyright holders nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-##include "m5/arch/mips/isa/includes.isa"
-
-////////////////////////////////////////////////////////////////////
-//
-// Namespace statement. Everything below this line will be in the
-// MipsISAInst namespace.
-//
-
-namespace MipsISA;
-
-//Include the bitfield definitions
-##include "m5/arch/mips/isa/bitfields.isa"
-
-//Include the operand_types and operand definitions
-##include "m5/arch/mips/isa/operands.isa"
-
-//Include the base class for mips instructions, and some support code
-##include "m5/arch/mips/isa/base.isa"
-
-//Include the definitions for the instruction formats
-##include "m5/arch/mips/isa/formats.isa"
-
-//Include the decoder definition
-##include "m5/arch/mips/isa/decoder.isa"
diff --git a/arch/mips/isa/operands.isa b/arch/mips/isa/operands.isa
deleted file mode 100644
index 13870337b..000000000
--- a/arch/mips/isa/operands.isa
+++ /dev/null
@@ -1,33 +0,0 @@
-def operand_types {{
- 'sb' : ('signed int', 8),
- 'ub' : ('unsigned int', 8),
- 'sh' : ('signed int', 16),
- 'uh' : ('unsigned int', 16),
- 'sw' : ('signed int', 32),
- 'uw' : ('unsigned int', 32),
- 'sd' : ('signed int', 64),
- 'ud' : ('unsigned int', 64),
- 'sf' : ('float', 32),
- 'df' : ('float', 64),
- 'qf' : ('float', 128)
-}};
-
-def operands {{
- 'Rd': ('IntReg', 'uw', 'RD', 'IsInteger', 1),
- 'Rs': ('IntReg', 'uw', 'RS', 'IsInteger', 2),
- 'Rt': ('IntReg', 'uw', 'RT', 'IsInteger', 3),
- 'r31': ('IntReg', 'uw','R31','IsInteger', 4),
- 'R0': ('IntReg', 'uw','R0', 'IsInteger', 5),
-
- 'IntImm': ('IntReg', 'uw', 'INTIMM', 'IsInteger', 3),
-
- 'Fd': ('FloatReg', 'sf', 'FD', 'IsFloating', 1),
- 'Fs': ('FloatReg', 'sf', 'FS', 'IsFloating', 2),
- 'Ft': ('FloatReg', 'sf', 'FT', 'IsFloating', 3),
- 'Fr': ('FloatReg', 'sf', 'FR', 'IsFloating', 3),
-
- 'Mem': ('Mem', 'ud', None, ('IsMemRef', 'IsLoad', 'IsStore'), 4),
-
- 'NPC': ('NPC', 'uw', None, ( None, None, 'IsControl' ), 4),
- 'NNPC':('NNPC', 'uw', None, ( None, None, 'IsControl' ), 4)
-}};
diff --git a/arch/mips/isa_traits.cc b/arch/mips/isa_traits.cc
deleted file mode 100644
index d01fa6bd4..000000000
--- a/arch/mips/isa_traits.cc
+++ /dev/null
@@ -1,403 +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/isa_traits.hh"
-#include "config/full_system.hh"
-#include "cpu/static_inst.hh"
-#include "sim/serialize.hh"
-
-using namespace MipsISA;
-
-
-//Function now Obsolete in current state.
-//If anyting this should return the correct miscreg index
-//but that is handled implicitly with enums anyway
-void
-MipsISA::getMiscRegIdx(int reg_name,int &idx, int &sel)
-{
- switch(reg_name)
- {
- case Index: idx = 0; sel = 0; break; //0-0 Index into the TLB array
- case MVPControl: idx = 0; sel = 1; break; //0-1 Per-processor register containing global
- case MVPConf0: idx = 0; sel = 2; break; //0-2 Per-processor register containing global
- case MVPConf1: idx = 0; sel = 3; break; //0-3 Per-processor register containing global
- case Random: idx = 1; sel = 3; break; //1-0 Randomly generated index into the TLB array
- case VPEControl: idx = 1; sel = 1; break; //1-1 Per-VPE register containing relatively volatile
- //thread configuration data
- case VPEConf0: idx = 1; sel = 2; break; //1-2 Per-VPE multi-thread configuration
- //information
- case VPEConf1: idx = 1; sel = 3; break; //1-3 Per-VPE multi-thread configuration
- //information
- case YQMask: idx = 1; sel = 4; break; //Per-VPE register defining which YIELD
- //qualifier bits may be used without generating
- //an exception
- case VPESchedule: idx = 1; sel = 5; break;
- case VPEScheFBack: idx = 1; sel = 6; break;
- case VPEOpt: idx = 1; sel = 7; break;
- case EntryLo0: idx = 1; sel = 5; break;
- case TCStatus: idx = 1; sel = 5; break;
- case TCBind: idx = 1; sel = 5; break;
- case TCRestart: idx = 1; sel = 5; break;
- case TCHalt: idx = 1; sel = 5; break;
- case TCContext: idx = 1; sel = 5; break;
- case TCSchedule: idx = 1; sel = 5; break;
- case TCScheFBack: panic("Accessing Unimplemented CP0 Register"); break;
- case EntryLo1: panic("Accessing Unimplemented CP0 Register"); break;
- case Context: panic("Accessing Unimplemented CP0 Register"); break;
- case ContextConfig: panic("Accessing Unimplemented CP0 Register"); break;
- //case PageMask: panic("Accessing Unimplemented CP0 Register"); break;
- case PageGrain: panic("Accessing Unimplemented CP0 Register"); break;
- case Wired: panic("Accessing Unimplemented CP0 Register"); break;
- case SRSConf0: panic("Accessing Unimplemented CP0 Register"); break;
- case SRSConf1: panic("Accessing Unimplemented CP0 Register"); break;
- case SRSConf2: panic("Accessing Unimplemented CP0 Register"); break;
- case SRSConf3: panic("Accessing Unimplemented CP0 Register"); break;
- case SRSConf4: panic("Accessing Unimplemented CP0 Register"); break;
- case BadVAddr: panic("Accessing Unimplemented CP0 Register"); break;
- case Count: panic("Accessing Unimplemented CP0 Register"); break;
- case EntryHi: panic("Accessing Unimplemented CP0 Register"); break;
- case Compare: panic("Accessing Unimplemented CP0 Register"); break;
- case Status: idx = 12; sel = 0; break; //12-0 Processor status and control
- case IntCtl: idx = 12; sel = 1; break; //12-1 Interrupt system status and control
- case SRSCtl: idx = 12; sel = 2; break; //12-2 Shadow register set status and control
- case SRSMap: idx = 12; sel = 3; break; //12-3 Shadow set IPL mapping
- case Cause: idx = 13; sel = 0; break; //13-0 Cause of last general exception
- case EPC: idx = 14; sel = 0; break; //14-0 Program counter at last exception
- case PrId: idx = 15; sel = 0; break; //15-0 Processor identification and revision
- case EBase: idx = 15; sel = 1; break; //15-1 Exception vector base register
- case Config: panic("Accessing Unimplemented CP0 Register"); break;
- case Config1: panic("Accessing Unimplemented CP0 Register"); break;
- case Config2: panic("Accessing Unimplemented CP0 Register"); break;
- case Config3: panic("Accessing Unimplemented CP0 Register"); break;
- case LLAddr: panic("Accessing Unimplemented CP0 Register"); break;
- case WatchLo: panic("Accessing Unimplemented CP0 Register"); break;
- case WatchHi: panic("Accessing Unimplemented CP0 Register"); break;
- case Debug: panic("Accessing Unimplemented CP0 Register"); break;
- case TraceControl1: panic("Accessing Unimplemented CP0 Register"); break;
- case TraceControl2: panic("Accessing Unimplemented CP0 Register"); break;
- case UserTraceData: panic("Accessing Unimplemented CP0 Register"); break;
- case TraceBPC: panic("Accessing Unimplemented CP0 Register"); break;
- case DEPC: panic("Accessing Unimplemented CP0 Register"); break;
- case PerfCnt: panic("Accessing Unimplemented CP0 Register"); break;
- case ErrCtl: panic("Accessing Unimplemented CP0 Register"); break;
- case CacheErr0: panic("Accessing Unimplemented CP0 Register"); break;
- case CacheErr1: panic("Accessing Unimplemented CP0 Register"); break;
- case CacheErr2: panic("Accessing Unimplemented CP0 Register"); break;
- case CacheErr3: panic("Accessing Unimplemented CP0 Register"); break;
- case TagLo: panic("Accessing Unimplemented CP0 Register"); break;
- case DataLo: panic("Accessing Unimplemented CP0 Register"); break;
- case TagHi: panic("Accessing Unimplemented CP0 Register"); break;
- case DataHi: panic("Accessing Unimplemented CP0 Register"); break;
- case ErrorEPC: panic("Accessing Unimplemented CP0 Register"); break;
-
- default:
- panic("Accessing Unimplemented Misc. Register");
- }
-}
-
-void RegFile::coldReset()
-{
- //CP0 Random Reg:
- //Randomly generated index into the TLB array
- miscRegs[Random] = 0x0000003f;
-
- //CP0 Wired Reg.
- miscRegs[Wired] = 0x0000000;
-
- //CP0 HWRENA
- miscRegs[HWRena] = 0x0000000;
-
- //CP0 Status Reg.
- miscRegs[Status] = 0x0400004;
-
- //CP0 INTCNTL
- miscRegs[IntCtl] = 0xfc00000;
-
- //CP0 SRSCNTL
- miscRegs[SRSCtl] = 0x0c00000;
-
- //CP0 SRSMAP
- miscRegs[SRSMap] = 0x0000000;
-
- //CP0 Cause
- miscRegs[Cause] = 0x0000000;
-
- //CP0 Processor ID
- miscRegs[PrId] = 0x0019300;
-
- //CP0 EBASE
- miscRegs[EBase] = 0x8000000;
-
- //CP0 Config Reg.
- miscRegs[Config] = 0x80040482;
-
- //CP0 Config 1 Reg.
- miscRegs[Config1] = 0xfee3719e;
-
- //CP0 Config 2 Reg.
- miscRegs[Config2] = 0x8000000;
-
- //CP0 Config 3 Reg.
- miscRegs[Config3] = 0x0000020;
-
- //CP0 Config 7 Reg.
- miscRegs[Config7] = 0x0000000;
-
- //CP0 Debug
- miscRegs[Debug] = 0x0201800;
-
- //CP0 PERFCNTL1
- miscRegs[PerfCnt0] = 0x0000000;
-
- //CP0 PERFCNTL2
- miscRegs[PerfCnt1] = 0x0000000;
-
-}
-
-void RegFile::createCP0Regs()
-{
-//Resize Coprocessor Register Banks to
-// the number specified in MIPS32K VOL.III
-// Chapter 8
- /*
- //Cop-0 Regs. Bank 0: Index,
- miscRegs[0].resize(4);
-
- //Cop-0 Regs. Bank 1:
- miscRegs[1].resize(8);
-
- //Cop-0 Regs. Bank 2:
- miscRegs[2].resize(8);
-
- //Cop-0 Regs. Bank 3:
- miscRegs[3].resize(1);
-
- //Cop-0 Regs. Bank 4:
- miscRegs[4].resize(2);
-
- //Cop-0 Regs. Bank 5:
- miscRegs[5].resize(2);
-
- //Cop-0 Regs. Bank 6:
- miscRegs[6].resize(6);
-
- //Cop-0 Regs. Bank 7:
- miscRegs[7].resize(1);
-
- //Cop-0 Regs. Bank 8:
- miscRegs[8].resize(1);
-
- //Cop-0 Regs. Bank 9:
- miscRegs[9].resize(1);
-
- //Cop-0 Regs. Bank 10:
- miscRegs[10].resize(1);
-
- //Cop-0 Regs. Bank 11:
- miscRegs[11].resize(1);
-
- //Cop-0 Regs. Bank 12:
- miscRegs[12].resize(4);
-
- //Cop-0 Regs. Bank 13:
- miscRegs[13].resize(1);
-
- //Cop-0 Regs. Bank 14:
- miscRegs[14].resize(1);
-
- //Cop-0 Regs. Bank 15:
- miscRegs[15].resize(2);
-
- //Cop-0 Regs. Bank 16:
- miscRegs[16].resize(4);
-
- //Cop-0 Regs. Bank 17:
- miscRegs[17].resize(1);
-
- //Cop-0 Regs. Bank 18:
- miscRegs[18].resize(8);
-
- //Cop-0 Regs. Bank 19:
- miscRegs[19].resize(8);
-
- //Cop-0 Regs. Bank 20:
- miscRegs[20].resize(1);
-
- //Cop-0 Regs. Bank 21:
- //miscRegs[21].resize(1);
- //Reserved for future extensions
-
- //Cop-0 Regs. Bank 22:
- //miscRegs[22].resize(4);
- //Available for implementation dependent use
-
- //Cop-0 Regs. Bank 23:
- miscRegs[23].resize(5);
-
- //Cop-0 Regs. Bank 24:
- miscRegs[24].resize(1);
-
- //Cop-0 Regs. Bank 25:
- miscRegs[25].resize(8);
-
- //Cop-0 Regs. Bank 26:
- miscRegs[26].resize(1);
-
- //Cop-0 Regs. Bank 27:
- miscRegs[27].resize(4);
-
- //Cop-0 Regs. Bank 28:
- miscRegs[28].resize(8);
-
- //Cop-0 Regs. Bank 29:
- miscRegs[29].resize(8);
-
- //Cop-0 Regs. Bank 30:
- miscRegs[30].resize(1);
-
- //Cop-0 Regs. Bank 31:
- miscRegs[31].resize(1);*/
-
-}
-
-
-const Addr MipsISA::PageShift = 13;
-const Addr MipsISA::PageBytes = ULL(1) << PageShift;
-const Addr MipsISA::PageMask = ~(PageBytes - 1);
-const Addr MipsISA::PageOffset = PageBytes - 1;
-
-#if FULL_SYSTEM
-
-////////////////////////////////////////////////////////////////////////
-//
-// Translation stuff
-//
-
-const Addr MipsISA::PteShift = 3;
-const Addr MipsISA::NPtePageShift = PageShift - PteShift;
-const Addr MipsISA::NPtePage = ULL(1) << NPtePageShift;
-const Addr MipsISA::PteMask = NPtePage - 1;
-
-// User Virtual
-const Addr MipsISA::USegBase = ULL(0x0);
-const Addr MipsISA::USegEnd = ULL(0x000003ffffffffff);
-
-// Kernel Direct Mapped
-const Addr MipsISA::K0SegBase = ULL(0xfffffc0000000000);
-const Addr MipsISA::K0SegEnd = ULL(0xfffffdffffffffff);
-
-// Kernel Virtual
-const Addr MipsISA::K1SegBase = ULL(0xfffffe0000000000);
-const Addr MipsISA::K1SegEnd = ULL(0xffffffffffffffff);
-
-#endif
-
-// Mips UNOP (sll r0,r0,r0)
-const MachInst MipsISA::NoopMachInst = 0x00000000;
-
-static inline Addr
-TruncPage(Addr addr)
-{ return addr & ~(MipsISA::PageBytes - 1); }
-
-static inline Addr
-RoundPage(Addr addr)
-{ return (addr + MipsISA::PageBytes - 1) & ~(MipsISA::PageBytes - 1); }
-
-void
-RegFile::serialize(std::ostream &os)
-{
- SERIALIZE_ARRAY(intRegFile, NumIntRegs);
- SERIALIZE_ARRAY(floatRegFile.q, NumFloatRegs);
- //SERIALIZE_SCALAR(miscRegs.fpcr);
- //SERIALIZE_SCALAR(miscRegs.uniq);
- //SERIALIZE_SCALAR(miscRegs.lock_flag);
- //SERIALIZE_SCALAR(miscRegs.lock_addr);
- SERIALIZE_SCALAR(pc);
- SERIALIZE_SCALAR(npc);
- SERIALIZE_SCALAR(nnpc);
-#if FULL_SYSTEM
- SERIALIZE_ARRAY(palregs, NumIntRegs);
- SERIALIZE_ARRAY(ipr, NumInternalProcRegs);
- SERIALIZE_SCALAR(intrflag);
- SERIALIZE_SCALAR(pal_shadow);
-#endif
-}
-
-
-void
-RegFile::unserialize(Checkpoint *cp, const std::string &section)
-{
- UNSERIALIZE_ARRAY(intRegFile, NumIntRegs);
- UNSERIALIZE_ARRAY(floatRegFile.q, NumFloatRegs);
- //UNSERIALIZE_SCALAR(miscRegs.fpcr);
- //UNSERIALIZE_SCALAR(miscRegs.uniq);
- //UNSERIALIZE_SCALAR(miscRegs.lock_flag);
- //UNSERIALIZE_SCALAR(miscRegs.lock_addr);
- UNSERIALIZE_SCALAR(pc);
- UNSERIALIZE_SCALAR(npc);
- UNSERIALIZE_SCALAR(nnpc);
-#if FULL_SYSTEM
- UNSERIALIZE_ARRAY(palregs, NumIntRegs);
- UNSERIALIZE_ARRAY(ipr, NumInternalProcRegs);
- UNSERIALIZE_SCALAR(intrflag);
- UNSERIALIZE_SCALAR(pal_shadow);
-#endif
-}
-
-
-#if FULL_SYSTEM
-void
-PTE::serialize(std::ostream &os)
-{
- SERIALIZE_SCALAR(tag);
- SERIALIZE_SCALAR(ppn);
- SERIALIZE_SCALAR(xre);
- SERIALIZE_SCALAR(xwe);
- SERIALIZE_SCALAR(asn);
- SERIALIZE_SCALAR(asma);
- SERIALIZE_SCALAR(fonr);
- SERIALIZE_SCALAR(fonw);
- SERIALIZE_SCALAR(valid);
-}
-
-
-void
-PTE::unserialize(Checkpoint *cp, const std::string &section)
-{
- UNSERIALIZE_SCALAR(tag);
- UNSERIALIZE_SCALAR(ppn);
- UNSERIALIZE_SCALAR(xre);
- UNSERIALIZE_SCALAR(xwe);
- UNSERIALIZE_SCALAR(asn);
- UNSERIALIZE_SCALAR(asma);
- UNSERIALIZE_SCALAR(fonr);
- UNSERIALIZE_SCALAR(fonw);
- UNSERIALIZE_SCALAR(valid);
-}
-
-#endif //FULL_SYSTEM
diff --git a/arch/mips/isa_traits.hh b/arch/mips/isa_traits.hh
deleted file mode 100644
index 1dfa0dc7a..000000000
--- a/arch/mips/isa_traits.hh
+++ /dev/null
@@ -1,546 +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.
- */
-
-#ifndef __ARCH_MIPS_ISA_TRAITS_HH__
-#define __ARCH_MIPS_ISA_TRAITS_HH__
-
-//#include "arch/mips/misc_regfile.hh"
-#include "base/misc.hh"
-#include "config/full_system.hh"
-#include "sim/host.hh"
-#include "sim/faults.hh"
-
-#include <vector>
-
-class FastCPU;
-class FullCPU;
-class Checkpoint;
-
-namespace LittleEndianGuest {};
-using namespace LittleEndianGuest;
-
-#define TARGET_MIPS
-
-class StaticInst;
-class StaticInstPtr;
-
-namespace MIPS34K {
-int DTB_ASN_ASN(uint64_t reg);
-int ITB_ASN_ASN(uint64_t reg);
-};
-
-namespace MipsISA
-{
- typedef uint32_t MachInst;
-// typedef uint64_t Addr;
- typedef uint8_t RegIndex;
-
- enum {
- MemoryEnd = 0xffffffffffffffffULL,
-
- NumIntRegs = 32,
- NumFloatRegs = 32,
- NumMiscRegs = 258, //account for hi,lo regs
-
- MaxRegsOfAnyType = 32,
- // Static instruction parameters
- MaxInstSrcRegs = 3,
- MaxInstDestRegs = 2,
-
- // semantically meaningful register indices
- ZeroReg = 0, // architecturally meaningful
- // the rest of these depend on the ABI
- StackPointerReg = 30,
- GlobalPointerReg = 29,
- ProcedureValueReg = 27,
- ReturnAddressReg = 26,
- ReturnValueReg = 0,
- FramePointerReg = 15,
- ArgumentReg0 = 16,
- ArgumentReg1 = 17,
- ArgumentReg2 = 18,
- ArgumentReg3 = 19,
- ArgumentReg4 = 20,
- ArgumentReg5 = 21,
-
- LogVMPageSize = 13, // 8K bytes
- VMPageSize = (1 << LogVMPageSize),
-
- BranchPredAddrShiftAmt = 2, // instructions are 4-byte aligned
-
- WordBytes = 4,
- HalfwordBytes = 2,
- ByteBytes = 1,
- DepNA = 0,
- };
-
- // These enumerate all the registers for dependence tracking.
- enum DependenceTags {
- // 0..31 are the integer regs 0..31
- // 32..63 are the FP regs 0..31, i.e. use (reg + FP_Base_DepTag)
- FP_Base_DepTag = 32,
- Ctrl_Base_DepTag = 64,
- Fpcr_DepTag = 64, // floating point control register
- Uniq_DepTag = 65,
- IPR_Base_DepTag = 66,
- MiscReg_DepTag = 67
- };
-
- typedef uint64_t IntReg;
- typedef IntReg IntRegFile[NumIntRegs];
-
- // floating point register file entry type
- typedef union {
- uint64_t q;
- double d;
- } FloatReg;
-
- typedef union {
- uint64_t q[NumFloatRegs]; // integer qword view
- double d[NumFloatRegs]; // double-precision floating point view
- } FloatRegFile;
-
- // cop-0/cop-1 system control register file
- typedef uint64_t MiscReg;
-//typedef MiscReg MiscRegFile[NumMiscRegs];
- class MiscRegFile {
- public:
- MiscReg
- protected:
- uint64_t fpcr; // floating point condition codes
- uint64_t uniq; // process-unique register
- bool lock_flag; // lock flag for LL/SC
- Addr lock_addr; // lock address for LL/SC
-
- MiscReg miscRegFile[NumMiscRegs];
-
- public:
- //These functions should be removed once the simplescalar cpu model
- //has been replaced.
- int getInstAsid();
- int getDataAsid();
-
- MiscReg readReg(int misc_reg)
- { return miscRegFile[misc_reg]; }
-
- MiscReg readRegWithEffect(int misc_reg, Fault &fault, ExecContext *xc)
- { return miscRegFile[misc_reg];}
-
- Fault setReg(int misc_reg, const MiscReg &val)
- { miscRegFile[misc_reg] = val; return NoFault; }
-
- Fault setRegWithEffect(int misc_reg, const MiscReg &val,
- ExecContext *xc)
- { miscRegFile[misc_reg] = val; return NoFault; }
-
-#if FULL_SYSTEM
- void clearIprs() { };
-
- protected:
- InternalProcReg ipr[NumInternalProcRegs]; // Internal processor regs
-
- private:
- MiscReg readIpr(int idx, Fault &fault, ExecContext *xc) { }
-
- Fault setIpr(int idx, uint64_t val, ExecContext *xc) { }
-#endif
- friend class RegFile;
- };
-
- enum MiscRegTags {
- //Coprocessor 0 Registers
- //Reference MIPS32 Arch. for Programmers, Vol. III, Ch.8
- //(Register Number-Register Select) Summary of Register
- //------------------------------------------------------
- Index = 0, //0-0 Index into the TLB array
-
- MVPControl = 1, //0-1 Per-processor register containing global
- //MIPS® MT configuration data
-
- MVPConf0 = 2, //0-2 Per-processor register containing global
- //MIPS® MT configuration data
-
- MVPConf1 = 3, //0-3 Per-processor register containing global
- //MIPS® MT configuration data
-
- Random = 8, //1-0 Randomly generated index into the TLB array
-
- VPEControl = 9, //1-1 Per-VPE register containing relatively volatile
- //thread configuration data
-
- VPEConf0 = 10, //1-2 Per-VPE multi-thread configuration
- //information
-
-
- VPEConf1 = 11, //1-2 Per-VPE multi-thread configuration
- //information
-
- YQMask = 12, //Per-VPE register defining which YIELD
- //qualifier bits may be used without generating
- //an exception
-
- VPESchedule = 13,
- VPEScheFBack = 14,
- VPEOpt = 15,
- EntryLo0 = 16, // Bank 3: 16 - 23
- TCStatus = 17,
- TCBind = 18,
- TCRestart = 19,
- TCHalt = 20,
- TCContext = 21,
- TCSchedule = 22,
- TCScheFBack = 23,
-
- EntryLo1 = 24,// Bank 4: 24 - 31
-
- Context = 32, // Bank 5: 32 - 39
- ContextConfig = 33,
-
- //PageMask = 40, //Bank 6: 40 - 47
- PageGrain = 41,
-
- Wired = 48, //Bank 7:48 - 55
- SRSConf0 = 49,
- SRSConf1 = 50,
- SRSConf2 = 51,
- SRSConf3 = 52,
- SRSConf4 = 53,
- BadVAddr = 54,
-
- HWRena = 56,//Bank 8:56 - 63
-
- Count = 64, //Bank 9:64 - 71
-
- EntryHi = 72,//Bank 10:72 - 79
-
- Compare = 80,//Bank 11:80 - 87
-
- Status = 88,//Bank 12:88 - 96 //12-0 Processor status and control
- IntCtl = 89, //12-1 Interrupt system status and control
- SRSCtl = 90, //12-2 Shadow register set status and control
- SRSMap = 91, //12-3 Shadow set IPL mapping
-
- Cause = 97,//97-104 //13-0 Cause of last general exception
-
- EPC = 105,//105-112 //14-0 Program counter at last exception
-
- PRId = 113//113-120, //15-0 Processor identification and revision
- EBase = 114, //15-1 Exception vector base register
-
- Config = 121,//Bank 16: 121-128
- Config1 = 122,
- Config2 = 123,
- Config3 = 124,
- Config6 = 127,
- Config7 = 128,
-
-
- LLAddr = 129,//Bank 17: 129-136
-
- WatchLo0 = 137,//Bank 18: 137-144
- WatchLo1 = 138,
- WatchLo2 = 139,
- WatchLo3 = 140,
- WatchLo4 = 141,
- WatchLo5 = 142,
- WatchLo6 = 143,
- WatchLo7 = 144,
-
- WatchHi0 = 145,//Bank 19: 145-152
- WatchHi1 = 146,
- WatchHi2 = 147,
- WatchHi3 = 148,
- WatchHi4 = 149,
- WatchHi5 = 150,
- WatchHi6 = 151,
- WatchHi7 = 152,
-
- XCContext64 = 153,//Bank 20: 153-160
-
- //Bank 21: 161-168
-
- //Bank 22: 169-176
-
- Debug = 177, //Bank 23: 177-184
- TraceControl1 = 178,
- TraceControl2 = 179,
- UserTraceData = 180,
- TraceBPC = 181,
-
- DEPC = 185,//Bank 24: 185-192
-
- PerfCnt0 = 193,//Bank 25: 193 - 200
- PerfCnt1 = 194,
- PerfCnt2 = 195,
- PerfCnt3 = 196,
- PerfCnt4 = 197,
- PerfCnt5 = 198,
- PerfCnt6 = 199,
- PerfCnt7 = 200,
-
- ErrCtl = 201, //Bank 26: 201 - 208
-
- CacheErr0 = 209, //Bank 27: 209 - 216
- CacheErr1 = 210,
- CacheErr2 = 211,
- CacheErr3 = 212,
-
- TagLo0 = 217,//Bank 28: 217 - 224
- DataLo1 = 218,
- TagLo2 = 219,
- DataLo3 = 220,
- TagLo4 = 221,
- DataLo5 = 222,
- TagLo6 = 223,
- DataLo7 = 234,
-
- TagHi0 = 233,//Bank 29: 233 - 240
- DataHi1 = 234,
- TagHi2 = 235,
- DataHi3 = 236,
- TagHi4 = 237,
- DataHi5 = 238,
- TagHi6 = 239,
- DataHi7 = 240,
-
-
- ErrorEPC = 249,//Bank 30: 241 - 248
-
- DESAVE = 257,//Bank 31: 249-256
-
- //More Misc. Regs
- Hi,
- Lo,
- FCSR,
- FPCR,
-
- //Alpha Regs, but here now, for
- //compiling sake
- UNIQ,
- LockAddr,
- LockFlag
- };
-
-extern const Addr PageShift;
-extern const Addr PageBytes;
-extern const Addr PageMask;
-extern const Addr PageOffset;
-
-#if FULL_SYSTEM
-
- typedef uint64_t InternalProcReg;
-
-#include "arch/mips/isa_fullsys_traits.hh"
-
-#else
- enum {
- NumInternalProcRegs = 0
- };
-#endif
-
- enum {
- TotalNumRegs =
- NumIntRegs + NumFloatRegs + NumMiscRegs + NumInternalProcRegs
- };
-
- enum {
- TotalDataRegs = NumIntRegs + NumFloatRegs
- };
-
- typedef union {
- IntReg intreg;
- FloatReg fpreg;
- MiscReg ctrlreg;
- } AnyReg;
-
- struct RegFile {
- IntRegFile intRegFile; // (signed) integer register file
- FloatRegFile floatRegFile; // floating point register file
- MiscRegFile miscRegs; // control register file
-
-
- Addr pc; // program counter
- Addr npc; // next-cycle program counter
- Addr nnpc; // next-next-cycle program counter
- // used to implement branch delay slot
- // not real register
-
- MiscReg hi; // MIPS HI Register
- MiscReg lo; // MIPS LO Register
-
-
-#if FULL_SYSTEM
- IntReg palregs[NumIntRegs]; // PAL shadow registers
- InternalProcReg ipr[NumInternalProcRegs]; // internal processor regs
- int intrflag; // interrupt flag
- bool pal_shadow; // using pal_shadow registers
- inline int instAsid() { return MIPS34K::ITB_ASN_ASN(ipr[IPR_ITB_ASN]); }
- inline int dataAsid() { return MIPS34K::DTB_ASN_ASN(ipr[IPR_DTB_ASN]); }
-#endif // FULL_SYSTEM
-
- //void initCP0Regs();
- void serialize(std::ostream &os);
- void unserialize(Checkpoint *cp, const std::string &section);
-
- void createCP0Regs();
- void coldReset();
- };
-
- StaticInstPtr decodeInst(MachInst);
-
- // return a no-op instruction... used for instruction fetch faults
- extern const MachInst NoopMachInst;
-
- enum annotes {
- ANNOTE_NONE = 0,
- // An impossible number for instruction annotations
- ITOUCH_ANNOTE = 0xffffffff,
- };
-
- void getMiscRegIdx(int reg_name,int &idx, int &sel);
-
-
- static inline bool isCallerSaveIntegerRegister(unsigned int reg) {
- panic("register classification not implemented");
- return (reg >= 1 && reg <= 8 || reg >= 22 && reg <= 25 || reg == 27);
- }
-
- static inline bool isCalleeSaveIntegerRegister(unsigned int reg) {
- panic("register classification not implemented");
- return (reg >= 9 && reg <= 15);
- }
-
- static inline bool isCallerSaveFloatRegister(unsigned int reg) {
- panic("register classification not implemented");
- return false;
- }
-
- static inline bool isCalleeSaveFloatRegister(unsigned int reg) {
- panic("register classification not implemented");
- return false;
- }
-
- static inline Addr alignAddress(const Addr &addr,
- unsigned int nbytes) {
- return (addr & ~(nbytes - 1));
- }
-
- // Instruction address compression hooks
- static inline Addr realPCToFetchPC(const Addr &addr) {
- return addr;
- }
-
- static inline Addr fetchPCToRealPC(const Addr &addr) {
- return addr;
- }
-
- // the size of "fetched" instructions (not necessarily the size
- // of real instructions for PISA)
- static inline size_t fetchInstSize() {
- return sizeof(MachInst);
- }
-
- static inline MachInst makeRegisterCopy(int dest, int src) {
- panic("makeRegisterCopy not implemented");
- return 0;
- }
-
- // Machine operations
-
- void saveMachineReg(AnyReg &savereg, const RegFile &reg_file,
- int regnum);
-
- void restoreMachineReg(RegFile &regs, const AnyReg &reg,
- int regnum);
-
-#if 0
- static void serializeSpecialRegs(const Serializable::Proxy &proxy,
- const RegFile &regs);
-
- static void unserializeSpecialRegs(const IniFile *db,
- const std::string &category,
- ConfigNode *node,
- RegFile &regs);
-#endif
-
- /**
- * Function to insure ISA semantics about 0 registers.
- * @param xc The execution context.
- */
- template <class XC>
- void zeroRegisters(XC *xc);
-
- const Addr MaxAddr = (Addr)-1;
-};
-
-#if !FULL_SYSTEM
-class SyscallReturn {
- public:
- template <class T>
- SyscallReturn(T v, bool s)
- {
- retval = (uint64_t)v;
- success = s;
- }
-
- template <class T>
- SyscallReturn(T v)
- {
- success = (v >= 0);
- retval = (uint64_t)v;
- }
-
- ~SyscallReturn() {}
-
- SyscallReturn& operator=(const SyscallReturn& s) {
- retval = s.retval;
- success = s.success;
- return *this;
- }
-
- bool successful() { return success; }
- uint64_t value() { return retval; }
-
-
- private:
- uint64_t retval;
- bool success;
-};
-
-#endif
-
-
-#if FULL_SYSTEM
-//typedef TheISA::InternalProcReg InternalProcReg;
-//const int NumInternalProcRegs = TheISA::NumInternalProcRegs;
-//const int NumInterruptLevels = TheISA::NumInterruptLevels;
-
-#include "arch/mips/mips34k.hh"
-#endif
-
-#endif // __ARCH_MIPS_ISA_TRAITS_HH__
diff --git a/arch/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/linux_process.hh b/arch/mips/linux_process.hh
deleted file mode 100644
index 5408a6c44..000000000
--- a/arch/mips/linux_process.hh
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (c) 2003-2004 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __MIPS_LINUX_PROCESS_HH__
-#define __MIPS_LINUX_PROCESS_HH__
-
-#include "sim/process.hh"
-
-
-/// A process with emulated Mips/Linux syscalls.
-class MipsLinuxProcess : public LiveProcess
-{
- public:
- /// Constructor.
- MipsLinuxProcess(const std::string &name,
- ObjectFile *objFile,
- int stdin_fd, int stdout_fd, int stderr_fd,
- std::vector<std::string> &argv,
- std::vector<std::string> &envp);
-
- virtual SyscallDesc* getDesc(int callnum);
-
- /// The target system's hostname.
- static const char *hostname;
-
- /// Array of syscall descriptors, indexed by call number.
- static SyscallDesc syscallDescs[];
-
- const int Num_Syscall_Descs;
-};
-
-
-#endif // __MIPS_LINUX_PROCESS_HH__
diff --git a/arch/mips/process.cc b/arch/mips/process.cc
deleted file mode 100644
index 6de44fe9f..000000000
--- a/arch/mips/process.cc
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2003-2004 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "arch/mips/process.hh"
-
-namespace MipsISA
-{
-
-LiveProcess *
-createProcess(const string &nm, ObjectFile * objFile,
- int stdin_fd, int stdout_fd, int stderr_fd,
- vector<string> &argv, vector<string> &envp)
-{
- LiveProcess * process = NULL;
- if (objFile->getArch() != ObjectFile::MIPS)
- fatal("Object file does not match architecture.");
- switch (objFile->getOpSys()) {
- case ObjectFile::Linux:
- process = new MipsLinuxProcess(nm, objFile,
- stdin_fd, stdout_fd, stderr_fd,
- argv, envp);
- break;
-
- default:
- fatal("Unknown/unsupported operating system.");
- }
- return process;
-}
-
-} // namespace MipsISA
-
diff --git a/arch/mips/process.hh b/arch/mips/process.hh
deleted file mode 100644
index ab4323107..000000000
--- a/arch/mips/process.hh
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2003-2004 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __MIPS_PROCESS_HH__
-#define __MIPS_PROCESS_HH__
-
-#include "arch/mips/linux_process.hh"
-#include "base/loader/object_file.hh"
-
-namespace MipsISA
-{
-
-LiveProcess *
-createProcess(const string &nm, ObjectFile * objFile,
- int stdin_fd, int stdout_fd, int stderr_fd,
- vector<string> &argv, vector<string> &envp);
-
-} // namespace MipsISA
-
-#endif // __MIPS_PROCESS_HH__
diff --git a/arch/sparc/SConscript b/arch/sparc/SConscript
deleted file mode 100644
index edff5821e..000000000
--- a/arch/sparc/SConscript
+++ /dev/null
@@ -1,82 +0,0 @@
-# -*- mode:python -*-
-
-# Copyright (c) 2004-2005 The Regents of The University of Michigan
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met: redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer;
-# redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution;
-# neither the name of the copyright holders nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-import os
-import sys
-from os.path import isdir
-
-# Import build environment variable from SConstruct.
-Import('env')
-
-###################################################
-#
-# Define needed sources.
-#
-###################################################
-
-# Base sources used by all configurations.
-base_sources = Split('''
- faults.cc
- isa_traits.cc
- ''')
-
-# Full-system sources
-full_system_sources = Split('''
- tlb.cc
- arguments.cc
- ev5.cc
- osfpal.cc
- stacktrace.cc
- vtophys.cc
- ''')
-
-# Syscall emulation (non-full-system) sources
-syscall_emulation_sources = Split('''
- common_syscall_emul.cc
- linux_process.cc
- process.cc
- ''')
-
-sources = base_sources
-
-if env['FULL_SYSTEM']:
- sources += full_system_sources
-else:
- sources += syscall_emulation_sources
-
-# Convert file names to SCons File objects. This takes care of the
-# path relative to the top of the directory tree.
-sources = [File(s) for s in sources]
-
-# Add in files generated by the ISA description.
-isa_desc_files = env.ISADesc('isa/main.isa')
-# Only non-header files need to be compiled.
-isa_desc_sources = [f for f in isa_desc_files if not f.path.endswith('.hh')]
-sources += isa_desc_sources
-
-Return('sources')
diff --git a/arch/sparc/faults.cc b/arch/sparc/faults.cc
deleted file mode 100644
index b48fc600b..000000000
--- a/arch/sparc/faults.cc
+++ /dev/null
@@ -1,248 +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/sparc/faults.hh"
-#include "cpu/exec_context.hh"
-#include "cpu/base.hh"
-#include "base/trace.hh"
-
-namespace SparcISA
-{
-
-FaultName InternalProcessorError::_name = "intprocerr";
-TrapType InternalProcessorError::_trapType = 0x029;
-FaultPriority InternalProcessorError::_priority = 4;
-FaultStat InternalProcessorError::_count;
-
-FaultName MemAddressNotAligned::_name = "unalign";
-TrapType MemAddressNotAligned::_trapType = 0x034;
-FaultPriority MemAddressNotAligned::_priority = 10;
-FaultStat MemAddressNotAligned::_count;
-
-FaultName PowerOnReset::_name = "pow_reset";
-TrapType PowerOnReset::_trapType = 0x001;
-FaultPriority PowerOnReset::_priority = 0;
-FaultStat PowerOnReset::_count;
-
-FaultName WatchDogReset::_name = "watch_dog_reset";
-TrapType WatchDogReset::_trapType = 0x002;
-FaultPriority WatchDogReset::_priority = 1;
-FaultStat WatchDogReset::_count;
-
-FaultName ExternallyInitiatedReset::_name = "extern_reset";
-TrapType ExternallyInitiatedReset::_trapType = 0x003;
-FaultPriority ExternallyInitiatedReset::_priority = 1;
-FaultStat ExternallyInitiatedReset::_count;
-
-FaultName SoftwareInitiatedReset::_name = "software_reset";
-TrapType SoftwareInitiatedReset::_trapType = 0x004;
-FaultPriority SoftwareInitiatedReset::_priority = 1;
-FaultStat SoftwareInitiatedReset::_count;
-
-FaultName REDStateException::_name = "red_counte";
-TrapType REDStateException::_trapType = 0x005;
-FaultPriority REDStateException::_priority = 1;
-FaultStat REDStateException::_count;
-
-FaultName InstructionAccessException::_name = "inst_access";
-TrapType InstructionAccessException::_trapType = 0x008;
-FaultPriority InstructionAccessException::_priority = 5;
-FaultStat InstructionAccessException::_count;
-
-FaultName InstructionAccessMMUMiss::_name = "inst_mmu";
-TrapType InstructionAccessMMUMiss::_trapType = 0x009;
-FaultPriority InstructionAccessMMUMiss::_priority = 2;
-FaultStat InstructionAccessMMUMiss::_count;
-
-FaultName InstructionAccessError::_name = "inst_error";
-TrapType InstructionAccessError::_trapType = 0x00A;
-FaultPriority InstructionAccessError::_priority = 3;
-FaultStat InstructionAccessError::_count;
-
-FaultName IllegalInstruction::_name = "illegal_inst";
-TrapType IllegalInstruction::_trapType = 0x010;
-FaultPriority IllegalInstruction::_priority = 7;
-FaultStat IllegalInstruction::_count;
-
-FaultName PrivelegedOpcode::_name = "priv_opcode";
-TrapType PrivelegedOpcode::_trapType = 0x011;
-FaultPriority PrivelegedOpcode::_priority = 6;
-FaultStat PrivelegedOpcode::_count;
-
-FaultName UnimplementedLDD::_name = "unimp_ldd";
-TrapType UnimplementedLDD::_trapType = 0x012;
-FaultPriority UnimplementedLDD::_priority = 6;
-FaultStat UnimplementedLDD::_count;
-
-FaultName UnimplementedSTD::_name = "unimp_std";
-TrapType UnimplementedSTD::_trapType = 0x013;
-FaultPriority UnimplementedSTD::_priority = 6;
-FaultStat UnimplementedSTD::_count;
-
-FaultName FpDisabled::_name = "fp_disabled";
-TrapType FpDisabled::_trapType = 0x020;
-FaultPriority FpDisabled::_priority = 8;
-FaultStat FpDisabled::_count;
-
-FaultName FpExceptionIEEE754::_name = "fp_754";
-TrapType FpExceptionIEEE754::_trapType = 0x021;
-FaultPriority FpExceptionIEEE754::_priority = 11;
-FaultStat FpExceptionIEEE754::_count;
-
-FaultName FpExceptionOther::_name = "fp_other";
-TrapType FpExceptionOther::_trapType = 0x022;
-FaultPriority FpExceptionOther::_priority = 11;
-FaultStat FpExceptionOther::_count;
-
-FaultName TagOverflow::_name = "tag_overflow";
-TrapType TagOverflow::_trapType = 0x023;
-FaultPriority TagOverflow::_priority = 14;
-FaultStat TagOverflow::_count;
-
-FaultName DivisionByZero::_name = "div_by_zero";
-TrapType DivisionByZero::_trapType = 0x028;
-FaultPriority DivisionByZero::_priority = 15;
-FaultStat DivisionByZero::_count;
-
-FaultName DataAccessException::_name = "data_access";
-TrapType DataAccessException::_trapType = 0x030;
-FaultPriority DataAccessException::_priority = 12;
-FaultStat DataAccessException::_count;
-
-FaultName DataAccessMMUMiss::_name = "data_mmu";
-TrapType DataAccessMMUMiss::_trapType = 0x031;
-FaultPriority DataAccessMMUMiss::_priority = 12;
-FaultStat DataAccessMMUMiss::_count;
-
-FaultName DataAccessError::_name = "data_error";
-TrapType DataAccessError::_trapType = 0x032;
-FaultPriority DataAccessError::_priority = 12;
-FaultStat DataAccessError::_count;
-
-FaultName DataAccessProtection::_name = "data_protection";
-TrapType DataAccessProtection::_trapType = 0x033;
-FaultPriority DataAccessProtection::_priority = 12;
-FaultStat DataAccessProtection::_count;
-
-FaultName LDDFMemAddressNotAligned::_name = "unalign_lddf";
-TrapType LDDFMemAddressNotAligned::_trapType = 0x035;
-FaultPriority LDDFMemAddressNotAligned::_priority = 10;
-FaultStat LDDFMemAddressNotAligned::_count;
-
-FaultName STDFMemAddressNotAligned::_name = "unalign_stdf";
-TrapType STDFMemAddressNotAligned::_trapType = 0x036;
-FaultPriority STDFMemAddressNotAligned::_priority = 10;
-FaultStat STDFMemAddressNotAligned::_count;
-
-FaultName PrivelegedAction::_name = "priv_action";
-TrapType PrivelegedAction::_trapType = 0x037;
-FaultPriority PrivelegedAction::_priority = 11;
-FaultStat PrivelegedAction::_count;
-
-FaultName LDQFMemAddressNotAligned::_name = "unalign_ldqf";
-TrapType LDQFMemAddressNotAligned::_trapType = 0x038;
-FaultPriority LDQFMemAddressNotAligned::_priority = 10;
-FaultStat LDQFMemAddressNotAligned::_count;
-
-FaultName STQFMemAddressNotAligned::_name = "unalign_stqf";
-TrapType STQFMemAddressNotAligned::_trapType = 0x039;
-FaultPriority STQFMemAddressNotAligned::_priority = 10;
-FaultStat STQFMemAddressNotAligned::_count;
-
-FaultName AsyncDataError::_name = "async_data";
-TrapType AsyncDataError::_trapType = 0x040;
-FaultPriority AsyncDataError::_priority = 2;
-FaultStat AsyncDataError::_count;
-
-//The enumerated faults
-
-FaultName CleanWindow::_name = "clean_win";
-TrapType CleanWindow::_baseTrapType = 0x024;
-FaultPriority CleanWindow::_priority = 10;
-FaultStat CleanWindow::_count;
-
-FaultName InterruptLevelN::_name = "interrupt_n";
-TrapType InterruptLevelN::_baseTrapType = 0x041;
-FaultStat InterruptLevelN::_count;
-
-FaultName SpillNNormal::_name = "spill_n_normal";
-TrapType SpillNNormal::_baseTrapType = 0x080;
-FaultPriority SpillNNormal::_priority = 9;
-FaultStat SpillNNormal::_count;
-
-FaultName SpillNOther::_name = "spill_n_other";
-TrapType SpillNOther::_baseTrapType = 0x0A0;
-FaultPriority SpillNOther::_priority = 9;
-FaultStat SpillNOther::_count;
-
-FaultName FillNNormal::_name = "fill_n_normal";
-TrapType FillNNormal::_baseTrapType = 0x0C0;
-FaultPriority FillNNormal::_priority = 9;
-FaultStat FillNNormal::_count;
-
-FaultName FillNOther::_name = "fill_n_other";
-TrapType FillNOther::_baseTrapType = 0x0E0;
-FaultPriority FillNOther::_priority = 9;
-FaultStat FillNOther::_count;
-
-FaultName TrapInstruction::_name = "trap_inst_n";
-TrapType TrapInstruction::_baseTrapType = 0x100;
-FaultPriority TrapInstruction::_priority = 16;
-FaultStat TrapInstruction::_count;
-
-
-
-#if FULL_SYSTEM
-
-void SparcFault::invoke(ExecContext * xc)
-{
- FaultBase::invoke(xc);
- countStat()++;
-
- //Use the SPARC trap state machine
- /*// exception restart address
- if (setRestartAddress() || !xc->inPalMode())
- xc->setMiscReg(AlphaISA::IPR_EXC_ADDR, xc->regs.pc);
-
- if (skipFaultingInstruction()) {
- // traps... skip faulting instruction.
- xc->setMiscReg(AlphaISA::IPR_EXC_ADDR,
- xc->readMiscReg(AlphaISA::IPR_EXC_ADDR) + 4);
- }
-
- if (!xc->inPalMode())
- AlphaISA::swap_palshadow(&(xc->regs), true);
-
- xc->regs.pc = xc->readMiscReg(AlphaISA::IPR_PAL_BASE) + vect();
- xc->regs.npc = xc->regs.pc + sizeof(MachInst);*/
-}
-
-#endif
-
-} // namespace SparcISA
-
diff --git a/arch/sparc/faults.hh b/arch/sparc/faults.hh
deleted file mode 100644
index 318b1ad5a..000000000
--- a/arch/sparc/faults.hh
+++ /dev/null
@@ -1,587 +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.
- */
-
-#ifndef __ALPHA_FAULTS_HH__
-#define __ALPHA_FAULTS_HH__
-
-#include "sim/faults.hh"
-
-// The design of the "name" and "vect" functions is in sim/faults.hh
-
-namespace SparcISA
-{
-
-typedef const uint32_t TrapType;
-typedef const uint32_t FaultPriority;
-
-class SparcFault : public FaultBase
-{
- public:
-#if FULL_SYSTEM
- void invoke(ExecContext * xc);
-#endif
- virtual TrapType trapType() = 0;
- virtual FaultPriority priority() = 0;
- virtual FaultStat & countStat() = 0;
-};
-
-class InternalProcessorError : public SparcFault
-{
- private:
- static FaultName _name;
- static TrapType _trapType;
- static FaultPriority _priority;
- static FaultStat _count;
- public:
- FaultName name() {return _name;}
- TrapType trapType() {return _trapType;}
- FaultPriority priority() {return _priority;}
- FaultStat & countStat() {return _count;}
- bool isMachineCheckFault() {return true;}
-};
-
-class MemAddressNotAligned : public SparcFault
-{
- private:
- static FaultName _name;
- static TrapType _trapType;
- static FaultPriority _priority;
- static FaultStat _count;
- public:
- FaultName name() {return _name;}
- TrapType trapType() {return _trapType;}
- FaultPriority priority() {return _priority;}
- FaultStat & countStat() {return _count;}
- bool isAlignmentFault() {return true;}
-};
-
-static inline Fault genMachineCheckFault()
-{
- return new InternalProcessorError;
-}
-
-static inline Fault genAlignmentFault()
-{
- return new MemAddressNotAligned;
-}
-
-class PowerOnReset : public SparcFault
-{
- private:
- static FaultName _name;
- static TrapType _trapType;
- static FaultPriority _priority;
- static FaultStat _count;
- public:
- FaultName name() {return _name;}
- TrapType trapType() {return _trapType;}
- FaultPriority priority() {return _priority;}
- FaultStat & countStat() {return _count;}
-};
-
-class WatchDogReset : public SparcFault
-{
- private:
- static FaultName _name;
- static TrapType _trapType;
- static FaultPriority _priority;
- static FaultStat _count;
- public:
- FaultName name() {return _name;}
- TrapType trapType() {return _trapType;}
- FaultPriority priority() {return _priority;}
- FaultStat & countStat() {return _count;}
-};
-
-class ExternallyInitiatedReset : public SparcFault
-{
- private:
- static FaultName _name;
- static TrapType _trapType;
- static FaultPriority _priority;
- static FaultStat _count;
- public:
- FaultName name() {return _name;}
- TrapType trapType() {return _trapType;}
- FaultPriority priority() {return _priority;}
- FaultStat & countStat() {return _count;}
-};
-
-class SoftwareInitiatedReset : public SparcFault
-{
- private:
- static FaultName _name;
- static TrapType _trapType;
- static FaultPriority _priority;
- static FaultStat _count;
- public:
- FaultName name() {return _name;}
- TrapType trapType() {return _trapType;}
- FaultPriority priority() {return _priority;}
- FaultStat & countStat() {return _count;}
-};
-
-class REDStateException : public SparcFault
-{
- private:
- static FaultName _name;
- static TrapType _trapType;
- static FaultPriority _priority;
- static FaultStat _count;
- public:
- FaultName name() {return _name;}
- TrapType trapType() {return _trapType;}
- FaultPriority priority() {return _priority;}
- FaultStat & countStat() {return _count;}
-};
-
-class InstructionAccessException : public SparcFault
-{
- private:
- static FaultName _name;
- static TrapType _trapType;
- static FaultPriority _priority;
- static FaultStat _count;
- public:
- FaultName name() {return _name;}
- TrapType trapType() {return _trapType;}
- FaultPriority priority() {return _priority;}
- FaultStat & countStat() {return _count;}
-};
-
-class InstructionAccessMMUMiss : public SparcFault
-{
- private:
- static FaultName _name;
- static TrapType _trapType;
- static FaultPriority _priority;
- static FaultStat _count;
- public:
- FaultName name() {return _name;}
- TrapType trapType() {return _trapType;}
- FaultPriority priority() {return _priority;}
- FaultStat & countStat() {return _count;}
-};
-
-class InstructionAccessError : public SparcFault
-{
- private:
- static FaultName _name;
- static TrapType _trapType;
- static FaultPriority _priority;
- static FaultStat _count;
- public:
- FaultName name() {return _name;}
- TrapType trapType() {return _trapType;}
- FaultPriority priority() {return _priority;}
- FaultStat & countStat() {return _count;}
-};
-
-class IllegalInstruction : public SparcFault
-{
- private:
- static FaultName _name;
- static TrapType _trapType;
- static FaultPriority _priority;
- static FaultStat _count;
- public:
- FaultName name() {return _name;}
- TrapType trapType() {return _trapType;}
- FaultPriority priority() {return _priority;}
- FaultStat & countStat() {return _count;}
-};
-
-class PrivelegedOpcode : public SparcFault
-{
- private:
- static FaultName _name;
- static TrapType _trapType;
- static FaultPriority _priority;
- static FaultStat _count;
- public:
- FaultName name() {return _name;}
- TrapType trapType() {return _trapType;}
- FaultPriority priority() {return _priority;}
- FaultStat & countStat() {return _count;}
-};
-
-class UnimplementedLDD : public SparcFault
-{
- private:
- static FaultName _name;
- static TrapType _trapType;
- static FaultPriority _priority;
- static FaultStat _count;
- public:
- FaultName name() {return _name;}
- TrapType trapType() {return _trapType;}
- FaultPriority priority() {return _priority;}
- FaultStat & countStat() {return _count;}
-};
-
-class UnimplementedSTD : public SparcFault
-{
- private:
- static FaultName _name;
- static TrapType _trapType;
- static FaultPriority _priority;
- static FaultStat _count;
- public:
- FaultName name() {return _name;}
- TrapType trapType() {return _trapType;}
- FaultPriority priority() {return _priority;}
- FaultStat & countStat() {return _count;}
-};
-
-class FpDisabled : public SparcFault
-{
- private:
- static FaultName _name;
- static TrapType _trapType;
- static FaultPriority _priority;
- static FaultStat _count;
- public:
- FaultName name() {return _name;}
- TrapType trapType() {return _trapType;}
- FaultPriority priority() {return _priority;}
- FaultStat & countStat() {return _count;}
-};
-
-class FpExceptionIEEE754 : public SparcFault
-{
- private:
- static FaultName _name;
- static TrapType _trapType;
- static FaultPriority _priority;
- static FaultStat _count;
- public:
- FaultName name() {return _name;}
- TrapType trapType() {return _trapType;}
- FaultPriority priority() {return _priority;}
- FaultStat & countStat() {return _count;}
-};
-
-class FpExceptionOther : public SparcFault
-{
- private:
- static FaultName _name;
- static TrapType _trapType;
- static FaultPriority _priority;
- static FaultStat _count;
- public:
- FaultName name() {return _name;}
- TrapType trapType() {return _trapType;}
- FaultPriority priority() {return _priority;}
- FaultStat & countStat() {return _count;}
-};
-
-class TagOverflow : public SparcFault
-{
- private:
- static FaultName _name;
- static TrapType _trapType;
- static FaultPriority _priority;
- static FaultStat _count;
- public:
- FaultName name() {return _name;}
- TrapType trapType() {return _trapType;}
- FaultPriority priority() {return _priority;}
- FaultStat & countStat() {return _count;}
-};
-
-class DivisionByZero : public SparcFault
-{
- private:
- static FaultName _name;
- static TrapType _trapType;
- static FaultPriority _priority;
- static FaultStat _count;
- public:
- FaultName name() {return _name;}
- TrapType trapType() {return _trapType;}
- FaultPriority priority() {return _priority;}
- FaultStat & countStat() {return _count;}
-};
-
-class DataAccessException : public SparcFault
-{
- private:
- static FaultName _name;
- static TrapType _trapType;
- static FaultPriority _priority;
- static FaultStat _count;
- public:
- FaultName name() {return _name;}
- TrapType trapType() {return _trapType;}
- FaultPriority priority() {return _priority;}
- FaultStat & countStat() {return _count;}
-};
-
-class DataAccessMMUMiss : public SparcFault
-{
- private:
- static FaultName _name;
- static TrapType _trapType;
- static FaultPriority _priority;
- static FaultStat _count;
- public:
- FaultName name() {return _name;}
- TrapType trapType() {return _trapType;}
- FaultPriority priority() {return _priority;}
- FaultStat & countStat() {return _count;}
-};
-
-class DataAccessError : public SparcFault
-{
- private:
- static FaultName _name;
- static TrapType _trapType;
- static FaultPriority _priority;
- static FaultStat _count;
- public:
- FaultName name() {return _name;}
- TrapType trapType() {return _trapType;}
- FaultPriority priority() {return _priority;}
- FaultStat & countStat() {return _count;}
-};
-
-class DataAccessProtection : public SparcFault
-{
- private:
- static FaultName _name;
- static TrapType _trapType;
- static FaultPriority _priority;
- static FaultStat _count;
- public:
- FaultName name() {return _name;}
- TrapType trapType() {return _trapType;}
- FaultPriority priority() {return _priority;}
- FaultStat & countStat() {return _count;}
-};
-
-class LDDFMemAddressNotAligned : public SparcFault
-{
- private:
- static FaultName _name;
- static TrapType _trapType;
- static FaultPriority _priority;
- static FaultStat _count;
- public:
- FaultName name() {return _name;}
- TrapType trapType() {return _trapType;}
- FaultPriority priority() {return _priority;}
- FaultStat & countStat() {return _count;}
-};
-
-class STDFMemAddressNotAligned : public SparcFault
-{
- private:
- static FaultName _name;
- static TrapType _trapType;
- static FaultPriority _priority;
- static FaultStat _count;
- public:
- FaultName name() {return _name;}
- TrapType trapType() {return _trapType;}
- FaultPriority priority() {return _priority;}
- FaultStat & countStat() {return _count;}
-};
-
-class PrivelegedAction : public SparcFault
-{
- private:
- static FaultName _name;
- static TrapType _trapType;
- static FaultPriority _priority;
- static FaultStat _count;
- public:
- FaultName name() {return _name;}
- TrapType trapType() {return _trapType;}
- FaultPriority priority() {return _priority;}
- FaultStat & countStat() {return _count;}
-};
-
-class LDQFMemAddressNotAligned : public SparcFault
-{
- private:
- static FaultName _name;
- static TrapType _trapType;
- static FaultPriority _priority;
- static FaultStat _count;
- public:
- FaultName name() {return _name;}
- TrapType trapType() {return _trapType;}
- FaultPriority priority() {return _priority;}
- FaultStat & countStat() {return _count;}
-};
-
-class STQFMemAddressNotAligned : public SparcFault
-{
- private:
- static FaultName _name;
- static TrapType _trapType;
- static FaultPriority _priority;
- static FaultStat _count;
- public:
- FaultName name() {return _name;}
- TrapType trapType() {return _trapType;}
- FaultPriority priority() {return _priority;}
- FaultStat & countStat() {return _count;}
-};
-
-class AsyncDataError : public SparcFault
-{
- private:
- static FaultName _name;
- static TrapType _trapType;
- static FaultPriority _priority;
- static FaultStat _count;
- public:
- FaultName name() {return _name;}
- TrapType trapType() {return _trapType;}
- FaultPriority priority() {return _priority;}
- FaultStat & countStat() {return _count;}
-};
-
-class EnumeratedFault : public SparcFault
-{
- protected:
- uint32_t _n;
- virtual TrapType baseTrapType() = 0;
- public:
- EnumeratedFault(uint32_t n) : SparcFault() {_n = n;}
- TrapType trapType() {return baseTrapType() + _n;}
-};
-
-class CleanWindow : public EnumeratedFault
-{
- private:
- static FaultName _name;
- static TrapType _baseTrapType;
- static FaultPriority _priority;
- static FaultStat _count;
- TrapType baseTrapType() {return _baseTrapType;}
- public:
- CleanWindow(uint32_t n) : EnumeratedFault(n) {;}
- FaultName name() {return _name;}
- FaultPriority priority() {return _priority;}
- FaultStat & countStat() {return _count;}
-};
-
-class InterruptLevelN : public EnumeratedFault
-{
- private:
- static FaultName _name;
- static TrapType _baseTrapType;
- static FaultStat _count;
- TrapType baseTrapType() {return _baseTrapType;}
- public:
- InterruptLevelN(uint32_t n) : EnumeratedFault(n) {;}
- FaultName name() {return _name;}
- FaultPriority priority() {return 32 - _n;}
- FaultStat & countStat() {return _count;}
-};
-
-class SpillNNormal : public EnumeratedFault
-{
- private:
- static FaultName _name;
- static TrapType _baseTrapType;
- static FaultPriority _priority;
- static FaultStat _count;
- TrapType baseTrapType() {return _baseTrapType;}
- public:
- SpillNNormal(uint32_t n) : EnumeratedFault(n) {;}
- FaultName name() {return _name;}
- FaultPriority priority() {return _priority;}
- FaultStat & countStat() {return _count;}
-};
-
-class SpillNOther : public EnumeratedFault
-{
- private:
- static FaultName _name;
- static TrapType _baseTrapType;
- static FaultPriority _priority;
- static FaultStat _count;
- TrapType baseTrapType() {return _baseTrapType;}
- public:
- SpillNOther(uint32_t n) : EnumeratedFault(n) {;}
- FaultName name() {return _name;}
- FaultPriority priority() {return _priority;}
- FaultStat & countStat() {return _count;}
-};
-
-class FillNNormal : public EnumeratedFault
-{
- private:
- static FaultName _name;
- static TrapType _baseTrapType;
- static FaultPriority _priority;
- static FaultStat _count;
- TrapType baseTrapType() {return _baseTrapType;}
- public:
- FillNNormal(uint32_t n) : EnumeratedFault(n) {;}
- FaultName name() {return _name;}
- FaultPriority priority() {return _priority;}
- FaultStat & countStat() {return _count;}
-};
-
-class FillNOther : public EnumeratedFault
-{
- private:
- static FaultName _name;
- static TrapType _baseTrapType;
- static FaultPriority _priority;
- static FaultStat _count;
- TrapType baseTrapType() {return _baseTrapType;}
- public:
- FillNOther(uint32_t n) : EnumeratedFault(n) {;}
- FaultName name() {return _name;}
- FaultPriority priority() {return _priority;}
- FaultStat & countStat() {return _count;}
-};
-
-class TrapInstruction : public EnumeratedFault
-{
- private:
- static FaultName _name;
- static TrapType _baseTrapType;
- static FaultPriority _priority;
- static FaultStat _count;
- TrapType baseTrapType() {return _baseTrapType;}
- public:
- TrapInstruction(uint32_t n) : EnumeratedFault(n) {;}
- FaultName name() {return _name;}
- FaultPriority priority() {return _priority;}
- FaultStat & countStat() {return _count;}
-};
-
-} // SparcISA namespace
-
-#endif // __FAULTS_HH__
diff --git a/arch/sparc/isa/base.isa b/arch/sparc/isa/base.isa
deleted file mode 100644
index 992504369..000000000
--- a/arch/sparc/isa/base.isa
+++ /dev/null
@@ -1,129 +0,0 @@
-////////////////////////////////////////////////////////////////////
-//
-// Base class for sparc instructions, and some support functions
-//
-
-output header {{
-
- struct condCodes
- {
- uint8_t c:1;
- uint8_t v:1;
- uint8_t z:1;
- uint8_t n:1;
- }
-
- enum condTest
- {
- Always=0x8,
- Never=0x0,
- NotEqual=0x9,
- Equal=0x1,
- Greater=0xA,
- LessOrEqual=0x2,
- GreaterOrEqual=0xB,
- Less=0x3,
- GreaterUnsigned=0xC,
- LessOrEqualUnsigned=0x4,
- CarryClear=0xD,
- CarrySet=0x5,
- Positive=0xE,
- Negative=0x6,
- OverflowClear=0xF,
- OverflowSet=0x7
- }
-
- /**
- * Base class for all SPARC static instructions.
- */
- class SparcStaticInst : public StaticInst
- {
- protected:
- // Constructor.
- SparcStaticInst(const char *mnem,
- MachInst _machInst, OpClass __opClass)
- : StaticInst(mnem, _machInst, __opClass)
- {
- }
-
- std::string generateDisassembly(Addr pc,
- const SymbolTable *symtab) const;
- };
-
- bool passesCondition(condCodes codes, condTest condition);
-}};
-
-output decoder {{
-
- std::string SparcStaticInst::generateDisassembly(Addr pc,
- const SymbolTable *symtab) const
- {
- std::stringstream ss;
-
- ccprintf(ss, "%-10s ", mnemonic);
-
- // just print the first two source regs... if there's
- // a third one, it's a read-modify-write dest (Rc),
- // e.g. for CMOVxx
- if(_numSrcRegs > 0)
- {
- printReg(ss, _srcRegIdx[0]);
- }
- if(_numSrcRegs > 1)
- {
- ss << ",";
- printReg(ss, _srcRegIdx[1]);
- }
-
- // just print the first dest... if there's a second one,
- // it's generally implicit
- if(_numDestRegs > 0)
- {
- if(_numSrcRegs > 0)
- ss << ",";
- printReg(ss, _destRegIdx[0]);
- }
-
- return ss.str();
- }
-
- bool passesCondition(condCodes codes, condTest condition)
- {
- switch(condition)
- {
- case Always:
- return true;
- case Never:
- return false;
- case NotEqual:
- return !codes.z;
- case Equal:
- return codes.z;
- case Greater:
- return !(codes.z | (codes.n ^ codes.v));
- case LessOrEqual:
- return codes.z | (codes.n ^ codes.v);
- case GreaterOrEqual:
- return !(codes.n ^ codes.v);
- case Less:
- return (codes.n ^ codes.v);
- case GreaterUnsigned:
- return !(codes.c | codes.z);
- case LessOrEqualUnsigned:
- return (codes.c | codes.z);
- case CarryClear:
- return !codes.c;
- case CarrySet:
- return codes.c;
- case Positive:
- return !codes.n;
- case Negative:
- return codes.n;
- case OverflowClear:
- return !codes.v;
- case OverflowSet:
- return codes.v;
- }
- }
-}};
-
diff --git a/arch/sparc/isa/bitfields.isa b/arch/sparc/isa/bitfields.isa
deleted file mode 100644
index b0ac57575..000000000
--- a/arch/sparc/isa/bitfields.isa
+++ /dev/null
@@ -1,50 +0,0 @@
-////////////////////////////////////////////////////////////////////
-//
-// Bitfield definitions.
-//
-
-// Bitfields are shared liberally between instruction formats, so they are
-// simply defined alphabetically
-
-def bitfield A <29>;
-def bitfield CC02 <20>;
-def bitfield CC03 <25>;
-def bitfield CC04 <11>;
-def bitfield CC12 <21>;
-def bitfield CC13 <26>;
-def bitfield CC14 <12>;
-def bitfield CC2 <18>;
-def bitfield CMASK <6:4>;
-def bitfield COND2 <28:25>;
-def bitfield COND4 <17:14>;
-def bitfield D16HI <21:20>;
-def bitfield D16LO <13:0>;
-def bitfield DISP19 <18:0>;
-def bitfield DISP22 <21:0>;
-def bitfield DISP30 <29:0>;
-def bitfield FCN <29:26>;
-def bitfield I <13>;
-def bitfield IMM_ASI <12:5>;
-def bitfield IMM22 <21:0>;
-def bitfield MMASK <3:0>;
-def bitfield OP <31:30>;
-def bitfield OP2 <24:22>;
-def bitfield OP3 <24:19>;
-def bitfield OPF <13:5>;
-def bitfield OPF_CC <13:11>;
-def bitfield OPF_LOW5 <9:5>;
-def bitfield OPF_LOW6 <10:5>;
-def bitfield P <19>;
-def bitfield RCOND2 <27:25>;
-def bitfield RCOND3 <12:10>;
-def bitfield RCOND4 <12:10>;
-def bitfield RD <29:25>;
-def bitfield RS1 <18:14>;
-def bitfield RS2 <4:0>;
-def bitfield SHCNT32 <4:0>;
-def bitfield SHCNT64 <5:0>;
-def bitfield SIMM10 <9:0>;
-def bitfield SIMM11 <10:0>;
-def bitfield SIMM13 <12:0>;
-def bitfield SW_TRAP <6:0>;
-def bitfield X <12>;
diff --git a/arch/sparc/isa/decoder.isa b/arch/sparc/isa/decoder.isa
deleted file mode 100644
index eb458211b..000000000
--- a/arch/sparc/isa/decoder.isa
+++ /dev/null
@@ -1,662 +0,0 @@
-////////////////////////////////////////////////////////////////////
-//
-// The actual decoder specification
-//
-
-decode OP default Trap::unknown({{IllegalInstruction}}) {
-
- 0x0: decode OP2 {
- 0x0: Trap::illtrap({{illegal_instruction}}); //ILLTRAP
- 0x1: Branch::bpcc({{
- switch((CC12 << 1) | CC02)
- {
- case 1:
- case 3:
- fault = new IllegalInstruction;
- case 0:
- if(passesCondition(xc->regs.MiscRegs.ccrFields.icc, COND2))
- ;//branchHere
- break;
- case 2:
- if(passesCondition(xc->regs.MiscRegs.ccrFields.xcc, COND2))
- ;//branchHere
- break;
- }
- }});//BPcc
- 0x2: Branch::bicc({{
- if(passesCondition(xc->regs.MiscRegs.ccrFields.icc, COND2))
- ;//branchHere
- }});//Bicc
- 0x3: Branch::bpr({{
- switch(RCOND)
- {
- case 0:
- case 4:
- fault = new IllegalInstruction;
- case 1:
- if(Rs1 == 0)
- ;//branchHere
- break;
- case 2:
- if(Rs1 <= 0)
- ;//branchHere
- break;
- case 3:
- if(Rs1 < 0)
- ;//branchHere
- break;
- case 5:
- if(Rs1 != 0)
- ;//branchHere
- break;
- case 6:
- if(Rs1 > 0)
- ;//branchHere
- break;
- case 7:
- if(Rs1 >= 0)
- ;//branchHere
- break;
- }
- }}); //BPr
- //SETHI (or NOP if rd == 0 and imm == 0)
- 0x4: IntegerOp::sethi({{Rd = (IMM22 << 10) & 0xFFFFFC00;}});
- 0x5: Trap::fbpfcc({{throw fp_disabled;}}); //FBPfcc
- 0x6: Trap::fbfcc({{throw fp_disabled;}}); //FBfcc
- }
- 0x1: Branch::call({{
- //branch here
- Rd = xc->pc;
- }});
- 0x2: decode OP3 {
- format IntegerOp {
- 0x00: add({{
- int64_t val2 = (I ? SIMM13.sdw : Rs2.sdw);
- Rd = Rs1.sdw + val2;
- }});//ADD
- 0x01: and({{
- uint64_t val2 = (I ? SIMM13.sdw : Rs2.udw);
- Rd = Rs1.udw & val2;
- }});//AND
- 0x02: or({{
- uint64_t val2 = (I ? SIMM13.sdw : Rs2.udw);
- Rd = Rs1.udw | val2;
- }});//OR
- 0x03: xor({{
- uint64_t val2 = (I ? SIMM13.sdw : Rs2.udw);
- Rd = Rs1.udw ^ val2;
- }});//XOR
- 0x04: sub({{
- int64_t val2 = ~((uint64_t)(I ? SIMM13.sdw : Rs2.udw))+1;
- Rd = Rs1.sdw + val2;
- }});//SUB
- 0x05: andn({{
- uint64_t val2 = (I ? SIMM13.sdw : Rs2.udw);
- Rd = Rs1.udw & ~val2;
- }});//ANDN
- 0x06: orn({{
- uint64_t val2 = (I ? SIMM13.sdw : Rs2.udw);
- Rd = Rs1.udw | ~val2;
- }});//ORN
- 0x07: xnor({{
- uint64_t val2 = (I ? SIMM13.sdw : Rs2.udw);
- Rd = ~(Rs1.udw ^ val2);
- }});//XNOR
- 0x08: addc({{
- int64_t val2 = (I ? SIMM13.sdw : Rs2.sdw);
- int64_t carryin = xc->regs.MiscRegs.ccrfields.iccfields.c;
- Rd = Rs1.sdw + val2 + carryin;
- }});//ADDC
- 0x09: mulx({{
- int64_t val2 = (I ? SIMM13.sdw : Rs2);
- Rd = Rs1 * val2;
- }});//MULX
- 0x0A: umul({{
- uint64_t resTemp, val2 = (I ? SIMM13.sdw : Rs2.udw);
- Rd = resTemp = Rs1.udw<31:0> * val2<31:0>;
- xc->regs.MiscRegs.yFields.value = resTemp<63:32>;
- }});//UMUL
- 0x0B: smul({{
- int64_t resTemp, val2 = (I ? SIMM13.sdw : Rs2.sdw);
- rd.sdw = resTemp = Rs1.sdw<31:0> * val2<31:0>;
- xc->regs.MiscRegs.yFields.value = resTemp<63:32>;
- }});//SMUL
- 0x0C: subc({{
- int64_t val2 = ~((int64_t)(I ? SIMM13.sdw : Rs2.sdw))+1;
- int64_t carryin = xc->regs.MiscRegs.ccrfields.iccfields.c;
- Rd.sdw = Rs1.sdw + val2 + carryin;
- }});//SUBC
- 0x0D: udivx({{
- uint64_t val2 = (I ? SIMM13.sdw : Rs2.udw);
- if(val2 == 0) throw division_by_zero;
- Rd.udw = Rs1.udw / val2;
- }});//UDIVX
- 0x0E: udiv({{
- uint32_t resTemp, val2 = (I ? SIMM13.sw : Rs2.udw<31:0>);
- if(val2 == 0)
- fault = new DivisionByZero;
- resTemp = (uint64_t)((xc->regs.MiscRegs.yFields.value << 32)
- | Rs1.udw<31:0>) / val2;
- int32_t overflow = (resTemp<63:32> != 0);
- if(overflow)
- rd.udw = resTemp = 0xFFFFFFFF;
- else
- rd.udw = resTemp;
- }}); //UDIV
- 0x0F: sdiv({{
- int32_t resTemp, val2 = (I ? SIMM13.sw : Rs2.sdw<31:0>);
- if(val2 == 0)
- fault = new DivisionByZero;
-
- Rd.sdw = (int64_t)((xc->regs.MiscRegs.yFields.value << 32) |
- Rs1.sdw<31:0>) / val2;
- resTemp = Rd.sdw;
- int32_t overflow = (resTemp<63:31> != 0);
- int32_t underflow =
- (resTemp<63:> && resTemp<62:31> != 0xFFFFFFFF);
- if(overflow)
- rd.udw = resTemp = 0x7FFFFFFF;
- else if(underflow)
- rd.udw = resTemp = 0xFFFFFFFF80000000;
- else
- rd.udw = resTemp;
- }});//SDIV
- }
- format IntegerOpCc {
- 0x10: addcc({{
- int64_t resTemp, val2 = (I ? SIMM13.sdw : Rs2);
- Rd = resTemp = Rs1 + val2;}},
- {{((Rs1 & 0xFFFFFFFF + val2 & 0xFFFFFFFF) >> 31)}},
- {{Rs1<31:> == val2<31:> && val2<31:> != resTemp<31:>}},
- {{((Rs1 >> 1) + (val2 >> 1) + (Rs1 & val2 & 0x1))<63:>}},
- {{Rs1<63:> == val2<63:> && val2<63:> != resTemp<63:>}}
- );//ADDcc
- 0x11: andcc({{
- int64_t val2 = (I ? SIMM13.sdw : Rs2);
- Rd = Rs1 & val2;}},
- {{0}},{{0}},{{0}},{{0}});//ANDcc
- 0x12: orcc({{
- int64_t val2 = (I ? SIMM13.sdw : Rs2);
- Rd = Rs1 | val2;}},
- {{0}},{{0}},{{0}},{{0}});//ORcc
- 0x13: xorcc({{
- int64_t val2 = (I ? SIMM13.sdw : Rs2);
- Rd = Rs1 ^ val2;}},
- {{0}},{{0}},{{0}},{{0}});//XORcc
- 0x14: subcc({{
- int64_t resTemp, val2 = (int64_t)(I ? SIMM13.sdw : Rs2);
- Rd = resTemp = Rs1 - val2;}},
- {{((Rs1 & 0xFFFFFFFF + (~val2) & 0xFFFFFFFF + 1) >> 31)}},
- {{Rs1<31:> != val2<31:> && Rs1<31:> != resTemp<31:>}},
- {{((Rs1 >> 1) + (~val2) >> 1) +
- ((Rs1 | ~val2) & 0x1))<63:>}},
- {{Rs1<63:> != val2<63:> && Rs1<63:> != resTemp<63:>}}
- );//SUBcc
- 0x15: andncc({{
- int64_t val2 = (I ? SIMM13.sdw : Rs2);
- Rd = Rs1 & ~val2;}},
- {{0}},{{0}},{{0}},{{0}});//ANDNcc
- 0x16: orncc({{
- int64_t val2 = (I ? SIMM13.sdw : Rs2);
- Rd = Rs1 | ~val2;}},
- {{0}},{{0}},{{0}},{{0}});//ORNcc
- 0x17: xnorcc({{
- int64_t val2 = (I ? SIMM13.sdw : Rs2);
- Rd = ~(Rs1 ^ val2);}},
- {{0}},{{0}},{{0}},{{0}});//XNORcc
- 0x18: addccc({{
- int64_t resTemp, val2 = (I ? SIMM13.sdw : Rs2);
- int64_t carryin = xc->regs.MiscRegs.ccrfields.iccfields.c;
- Rd = resTemp = Rs1 + val2 + carryin;}},
- {{((Rs1 & 0xFFFFFFFF + val2 & 0xFFFFFFFF) >> 31
- + carryin)}},
- {{Rs1<31:> == val2<31:> && val2<31:> != resTemp<31:>}},
- {{((Rs1 >> 1) + (val2 >> 1) +
- ((Rs1 & val2) | (carryin & (Rs1 | val2)) & 0x1))<63:>}},
- {{Rs1<63:> == val2<63:> && val2<63:> != resTemp<63:>}}
- );//ADDCcc
- 0x1A: umulcc({{
- uint64_t resTemp, val2 = (I ? SIMM13.sdw : Rs2);
- Rd = resTemp = Rs1.udw<31:0> * val2<31:0>;
- xc->regs.MiscRegs.yFields.value = resTemp<63:32>;}},
- {{0}},{{0}},{{0}},{{0}});//UMULcc
- 0x1B: smulcc({{
- int64_t resTemp, val2 = (I ? SIMM13.sdw : Rs2);
- Rd = resTemp = Rs1.sdw<31:0> * val2<31:0>;
- xc->regs.MiscRegs.yFields.value = resTemp<63:32>;}}
- ,{{0}},{{0}},{{0}},{{0}});//SMULcc
- 0x1C: subccc({{
- int64_t resTemp, val2 = (int64_t)(I ? SIMM13.sdw : Rs2);
- int64_t carryin = xc->regs.MiscRegs.ccrfields.iccfields.c;
- Rd = resTemp = Rs1 + ~(val2 + carryin) + 1;}},
- {{((Rs1 & 0xFFFFFFFF + (~(val2 + carryin)) & 0xFFFFFFFF + 1) >> 31)}},
- {{Rs1<31:> != val2<31:> && Rs1<31:> != resTemp<31:>}},
- {{((Rs1 >> 1) + (~(val2 + carryin)) >> 1) + ((Rs1 | ~(val2+carryin)) & 0x1))<63:>}},
- {{Rs1<63:> != val2<63:> && Rs1<63:> != resTemp<63:>}}
- );//SUBCcc
- 0x1D: udivxcc({{
- uint64_t val2 = (I ? SIMM13.sdw : Rs2.udw);
- if(val2 == 0) throw division_by_zero;
- Rd.udw = Rs1.udw / val2;}}
- ,{{0}},{{0}},{{0}},{{0}});//UDIVXcc
- 0x1E: udivcc({{
- uint32_t resTemp, val2 = (I ? SIMM13.sw : Rs2.udw<31:0>);
- if(val2 == 0) throw division_by_zero;
- resTemp = (uint64_t)((xc->regs.MiscRegs.yFields.value << 32) | Rs1.udw<31:0>) / val2;
- int32_t overflow = (resTemp<63:32> != 0);
- if(overflow) rd.udw = resTemp = 0xFFFFFFFF;
- else rd.udw = resTemp;}},
- {{0}},
- {{overflow}},
- {{0}},
- {{0}}
- );//UDIVcc
- 0x1F: sdivcc({{
- int32_t resTemp, val2 = (I ? SIMM13.sw : Rs2.sdw<31:0>);
- if(val2 == 0) throw division_by_zero;
- Rd.sdw = resTemp = (int64_t)((xc->regs.MiscRegs.yFields.value << 32) | Rs1.sdw<31:0>) / val2;
- int32_t overflow = (resTemp<63:31> != 0);
- int32_t underflow = (resTemp<63:> && resTemp<62:31> != 0xFFFFFFFF);
- if(overflow) rd.udw = resTemp = 0x7FFFFFFF;
- else if(underflow) rd.udw = resTemp = 0xFFFFFFFF80000000;
- else rd.udw = resTemp;}},
- {{0}},
- {{overflow || underflow}},
- {{0}},
- {{0}}
- );//SDIVcc
- 0x20: taddcc({{
- int64_t resTemp, val2 = (I ? SIMM13.sdw : Rs2);
- Rd = resTemp = Rs1 + val2;
- int32_t overflow = Rs1<1:0> || val2<1:0> || (Rs1<31:> == val2<31:> && val2<31:> != resTemp<31:>);}},
- {{((Rs1 & 0xFFFFFFFF + val2 & 0xFFFFFFFF) >> 31)}},
- {{overflow}},
- {{((Rs1 >> 1) + (val2 >> 1) + (Rs1 & val2 & 0x1))<63:>}},
- {{Rs1<63:> == val2<63:> && val2<63:> != resTemp<63:>}}
- );//TADDcc
- 0x21: tsubcc({{
- int64_t resTemp, val2 = (I ? SIMM13.sdw : Rs2);
- Rd = resTemp = Rs1 + val2;
- int32_t overflow = Rs1<1:0> || val2<1:0> || (Rs1<31:> == val2<31:> && val2<31:> != resTemp<31:>);}},
- {{(Rs1 & 0xFFFFFFFF + val2 & 0xFFFFFFFF) >> 31)}},
- {{overflow}},
- {{((Rs1 >> 1) + (val2 >> 1) + (Rs1 & val2 & 0x1))<63:>}},
- {{Rs1<63:> == val2<63:> && val2<63:> != resTemp<63:>}}
- );//TSUBcc
- 0x22: taddcctv({{
- int64_t resTemp, val2 = (I ? SIMM13.sdw : Rs2);
- Rd = resTemp = Rs1 + val2;
- int32_t overflow = Rs1<1:0> || val2<1:0> || (Rs1<31:> == val2<31:> && val2<31:> != resTemp<31:>);
- if(overflow) throw tag_overflow;}},
- {{((Rs1 & 0xFFFFFFFF + val2 & 0xFFFFFFFF) >> 31)}},
- {{overflow}},
- {{((Rs1 >> 1) + (val2 >> 1) + (Rs1 & val2 & 0x1))<63:>}},
- {{Rs1<63:> == val2<63:> && val2<63:> != resTemp<63:>}}
- );//TADDccTV
- 0x23: tsubcctv({{
- int64_t resTemp, val2 = (I ? SIMM13.sdw : Rs2);
- Rd = resTemp = Rs1 + val2;
- int32_t overflow = Rs1<1:0> || val2<1:0> || (Rs1<31:> == val2<31:> && val2<31:> != resTemp<31:>);
- if(overflow) throw tag_overflow;}},
- {{((Rs1 & 0xFFFFFFFF + val2 & 0xFFFFFFFF) >> 31)}},
- {{overflow}},
- {{((Rs1 >> 1) + (val2 >> 1) + (Rs1 & val2 & 0x1))<63:>}},
- {{Rs1<63:> == val2<63:> && val2<63:> != resTemp<63:>}}
- );//TSUBccTV
- 0x24: mulscc({{
- int64_t resTemp, multiplicand = (I ? SIMM13.sdw : Rs2);
- int32_t multiplier = Rs1<31:0>;
- int32_t savedLSB = Rs1<0:>;
- multiplier = multipler<31:1> |
- ((xc->regs.MiscRegs.ccrFields.iccFields.n
- ^ xc->regs.MiscRegs.ccrFields.iccFields.v) << 32);
- if(!xc->regs.MiscRegs.yFields.value<0:>)
- multiplicand = 0;
- Rd = resTemp = multiplicand + multiplier;
- xc->regs.MiscRegs.yFields.value = xc->regs.MiscRegs.yFields.value<31:1> | (savedLSB << 31);}},
- {{((multiplicand & 0xFFFFFFFF + multiplier & 0xFFFFFFFF) >> 31)}},
- {{multiplicand<31:> == multiplier<31:> && multiplier<31:> != resTemp<31:>}},
- {{((multiplicand >> 1) + (multiplier >> 1) + (multiplicand & multiplier & 0x1))<63:>}},
- {{multiplicand<63:> == multiplier<63:> && multiplier<63:> != resTemp<63:>}}
- );//MULScc
- }
- format IntegerOp
- {
- 0x25: decode X {
- 0x0: sll({{Rd = Rs1 << (I ? SHCNT32 : Rs2<4:0>);}}); //SLL
- 0x1: sllx({{Rd = Rs1 << (I ? SHCNT64 : Rs2<5:0>);}}); //SLLX
- }
- 0x26: decode X {
- 0x0: srl({{Rd = Rs1.udw<31:0> >> (I ? SHCNT32 : Rs2<4:0>);}}); //SRL
- 0x1: srlx({{Rd = Rs1.udw >> (I ? SHCNT64 : Rs2<5:0>);}});//SRLX
- }
- 0x27: decode X {
- 0x0: sra({{Rd = Rs1.sdw<31:0> >> (I ? SHCNT32 : Rs2<4:0>);}}); //SRA
- 0x1: srax({{Rd = Rs1.sdw >> (I ? SHCNT64 : Rs2<5:0>);}});//SRAX
- }
- 0x28: decode RS1 {
- 0x0: rdy({{Rd = xc->regs.MiscRegs.yFields.value;}}); //RDY
- 0x2: rdccr({{Rd = xc->regs.MiscRegs.ccr;}}); //RDCCR
- 0x3: rdasi({{Rd = xc->regs.MiscRegs.asi;}}); //RDASI
- 0x4: rdtick({{
- if(xc->regs.MiscRegs.pstateFields.priv == 0 &&
- xc->regs.MiscRegs.tickFields.npt == 1)
- throw privileged_action;
- Rd = xc->regs.MiscRegs.tick;
- }});//RDTICK
- 0x5: rdpc({{Rd = xc->regs.pc;}}); //RDPC
- 0x6: rdfprs({{Rd = xc->regs.MiscRegs.fprs;}}); //RDFPRS
- 0xF: decode I {
- 0x0: Noop::membar({{//Membar isn't needed yet}}); //MEMBAR
- 0x1: Noop::stbar({{//Stbar isn/'t needed yet}}); //STBAR
- }
- }
-
- 0x2A: decode RS1 {
- 0x0: rdprtpc({{checkPriv Rd = xc->regs.MiscRegs.tpc[xc->regs.MiscRegs.tl];}});
- 0x1: rdprtnpc({{checkPriv Rd = xc->regs.MiscRegs.tnpc[xc->regs.MiscRegs.tl];}});
- 0x2: rdprtstate({{checkPriv Rd = xc->regs.MiscRegs.tstate[xc->regs.MiscRegs.tl];}});
- 0x3: rdprtt({{checkPriv Rd = xc->regs.MiscRegs.tt[xc->regs.MiscRegs.tl];}});
- 0x4: rdprtick({{checkPriv Rd = xc->regs.MiscRegs.tick;}});
- 0x5: rdprtba({{checkPriv Rd = xc->regs.MiscRegs.tba;}});
- 0x6: rdprpstate({{checkPriv Rd = xc->regs.MiscRegs.pstate;}});
- 0x7: rdprtl({{checkPriv Rd = xc->regs.MiscRegs.tl;}});
- 0x8: rdprpil({{checkPriv Rd = xc->regs.MiscRegs.pil;}});
- 0x9: rdprcwp({{checkPriv Rd = xc->regs.MiscRegs.cwp;}});
- 0xA: rdprcansave({{checkPriv Rd = xc->regs.MiscRegs.cansave;}});
- 0xB: rdprcanrestore({{checkPriv Rd = xc->regs.MiscRegs.canrestore;}});
- 0xC: rdprcleanwin({{checkPriv Rd = xc->regs.MiscRegs.cleanwin;}});
- 0xD: rdprotherwin({{checkPriv Rd = xc->regs.MiscRegs.otherwin;}});
- 0xE: rdprwstate({{checkPriv Rd = xc->regs.MiscRegs.wstate;}});
- 0xF: rdprfq({{throw illegal_instruction;}}); //The floating point queue isn't implemented right now.
- }
- 0x2B: BasicOperate::flushw({{\\window toilet}}); //FLUSHW
- 0x2C: movcc({{
- ccBank = (CC24 << 2) | (CC14 << 1) | (CC04 << 0);
- switch(ccBank)
- {
- case 0: case 1: case 2: case 3:
- throw fp_disabled;
- break;
- case 5: case 7:
- throw illegal_instruction;
- break;
- case 4:
- if(passesCondition(xc->regs.MiscRegs.ccrFields.icc, COND4))
- Rd = (I ? SIMM11.sdw : RS2);
- break;
- case 6:
- if(passesCondition(xc->regs.MiscRegs.ccrFields.xcc, COND4))
- Rd = (I ? SIMM11.sdw : RS2);
- break;
- }
- }});//MOVcc
- 0x2D: sdivx({{
- int64_t val2 = (I ? SIMM13.sdw : Rs2.sdw);
- if(val2 == 0) throw division_by_zero;
- Rd.sdw = Rs1.sdw / val2;
- }});//SDIVX
- 0x2E: decode RS1 {
- 0x0: IntegerOp::popc({{
- int64_t count = 0, val2 = (I ? SIMM13.sdw : Rs2.sdw);
- uint8_t oneBits[] = {0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4}
- for(unsigned int x = 0; x < 16; x++)
- {
- count += oneBits[val2 & 0xF];
- val2 >> 4;
- }
- }});//POPC
- }
- 0x2F: movr({{
- uint64_t val2 = (I ? SIMM10.sdw : Rs2.sdw);
- switch(RCOND)
- {
- case 0: case 4:
- throw illegal_instruction;
- break;
- case 1:
- if(Rs1 == 0) Rd = val2;
- break;
- case 2:
- if(Rs1 <= 0) Rd = val2;
- break;
- case 3:
- if(Rs1 = 0) Rd = val2;
- break;
- case 5:
- if(Rs1 != 0) Rd = val2;
- break;
- case 6:
- if(Rs1 > 0) Rd = val2;
- break;
- case 7:
- if(Rs1 >= 0) Rd = val2;
- break;
- }
- }});//MOVR
- 0x30: decode RD {
- 0x0: wry({{
- uint64_t val2 = (I ? SIMM13.sdw : Rs2.sdw);
- xc->regs.MiscRegs.y = Rs1 ^ val2;
- }});//WRY
- 0x2: wrccr({{
- uint64_t val2 = (I ? SIMM13.sdw : Rs2.sdw);
- xc->regs.MiscRegs.ccr = Rs1 ^ val2;
- }});//WRCCR
- 0x3: wrasi({{
- uint64_t val2 = (I ? SIMM13.sdw : Rs2.sdw);
- xc->regs.MiscRegs.asi = Rs1 ^ val2;
- }});//WRASI
- 0x6: wrfprs({{
- uint64_t val2 = (I ? SIMM13.sdw : Rs2.sdw);
- xc->regs.MiscRegs.asi = Rs1 ^ val2;
- }});//WRFPRS
- 0xF: Trap::sir({{software_initiated_reset}}); //SIR
- }
- 0x31: decode FCN {
- 0x0: BasicOperate::saved({{\\Boogy Boogy}}); //SAVED
- 0x1: BasicOperate::restored({{\\Boogy Boogy}}); //RESTORED
- }
- 0x32: decode RD {
- 0x0: wrprtpc({{checkPriv
- uint64_t val2 = (I ? SIMM13.sdw : Rs2.sdw);
- xc->regs.MiscRegs.tpc[xc->regs.MiscRegs.tl] = Rs1 ^ val2;
- }});
- 0x1: wrprtnpc({{checkPriv
- uint64_t val2 = (I ? SIMM13.sdw : Rs2.sdw);
- xc->regs.MiscRegs.tnpc[xc->regs.MiscRegs.tl] = Rs1 ^ val2;
- }});
- 0x2: wrprtstate({{checkPriv
- uint64_t val2 = (I ? SIMM13.sdw : Rs2.sdw);
- xc->regs.MiscRegs.tstate[xc->regs.MiscRegs.tl] = Rs1 ^ val2;
- }});
- 0x3: wrprtt({{checkPriv
- uint64_t val2 = (I ? SIMM13.sdw : Rs2.sdw);
- xc->regs.MiscRegs.tt[xc->regs.MiscRegs.tl] = Rs1 ^ val2;
- }});
- 0x4: wrprtick({{checkPriv
- uint64_t val2 = (I ? SIMM13.sdw : Rs2.sdw);
- xc->regs.MiscRegs.tick = Rs1 ^ val2;
- }});
- 0x5: wrprtba({{checkPriv
- uint64_t val2 = (I ? SIMM13.sdw : Rs2.sdw);
- xc->regs.MiscRegs.tba = Rs1 ^ val2;
- }});
- 0x6: wrprpstate({{checkPriv
- uint64_t val2 = (I ? SIMM13.sdw : Rs2.sdw);
- xc->regs.MiscRegs.pstate = Rs1 ^ val2;
- }});
- 0x7: wrprtl({{checkPriv
- uint64_t val2 = (I ? SIMM13.sdw : Rs2.sdw);
- xc->regs.MiscRegs.tl = Rs1 ^ val2;
- }});
- 0x8: wrprpil({{checkPriv
- uint64_t val2 = (I ? SIMM13.sdw : Rs2.sdw);
- xc->regs.MiscRegs.pil = Rs1 ^ val2;
- }});
- 0x9: wrprcwp({{checkPriv
- uint64_t val2 = (I ? SIMM13.sdw : Rs2.sdw);
- xc->regs.MiscRegs.cwp = Rs1 ^ val2;
- }});
- 0xA: wrprcansave({{checkPriv
- uint64_t val2 = (I ? SIMM13.sdw : Rs2.sdw);
- xc->regs.MiscRegs.cansave = Rs1 ^ val2;
- }});
- 0xB: wrprcanrestore({{checkPriv
- uint64_t val2 = (I ? SIMM13.sdw : Rs2.sdw);
- xc->regs.MiscRegs.canrestore = Rs1 ^ val2;
- }});
- 0xC: wrprcleanwin({{checkPriv
- uint64_t val2 = (I ? SIMM13.sdw : Rs2.sdw);
- xc->regs.MiscRegs.cleanwin = Rs1 ^ val2;
- }});
- 0xD: wrprotherwin({{checkPriv
- uint64_t val2 = (I ? SIMM13.sdw : Rs2.sdw);
- xc->regs.MiscRegs.otherwin = Rs1 ^ val2;
- }});
- 0xE: wrprwstate({{checkPriv
- uint64_t val2 = (I ? SIMM13.sdw : Rs2.sdw);
- xc->regs.MiscRegs.wstate = Rs1 ^ val2;
- }});
- }
-
- 0x34: Trap::fpop1({{Throw fp_disabled;}}); //FPOP1
- 0x35: Trap::fpop2({{Throw fp_disabled;}}); //FPOP2
-
-
- 0x38: Branch::jmpl({{//Stuff}}); //JMPL
- 0x39: Branch::return({{//Other Stuff}}); //RETURN
- 0x3A: Trap::tcc({{
- switch((CC14 << 1) | (CC04 << 0))
- {
- case 1: case 3:
- throw illegal_instruction;
- case 0:
- if(passesCondition(xc->regs.MiscRegs.ccrFields.icc, machInst<25:28>))
- throw trap_instruction;
- break;
- case 2:
- if(passesCondition(xc->regs.MiscRegs.ccrFields.xcc, machInst<25:28>))
- throw trap_instruction;
- break;
- }
- }}); //Tcc
- 0x3B: BasicOperate::flush({{//Lala}}); //FLUSH
- 0x3C: BasicOperate::save({{//leprechauns); //SAVE
- 0x3D: BasicOperate::restore({{//Eat my short int}}); //RESTORE
- 0x3E: decode FCN {
- 0x1: BasicOperate::done({{//Done thing}}); //DONE
- 0x2: BasicOperate::retry({{//Retry thing}}); //RETRY
- }
- }
- }
- 0x3: decode OP3 {
- format Mem {
- 0x00: lduw({{Rd.uw = Mem.uw;}}); //LDUW
- 0x01: ldub({{Rd.ub = Mem.ub;}}); //LDUB
- 0x02: lduh({{Rd.uhw = Mem.uhw;}}); //LDUH
- 0x03: ldd({{
- uint64_t val = Mem.udw;
- setIntReg(RD & (~1), val<31:0>);
- setIntReg(RD | 1, val<63:32>);
- }});//LDD
- 0x04: stw({{Mem.sw = Rd.sw;}}); //STW
- 0x05: stb({{Mem.sb = Rd.sb;}}); //STB
- 0x06: sth({{Mem.shw = Rd.shw;}}); //STH
- 0x07: std({{
- Mem.udw = readIntReg(RD & (~1))<31:0> | (readIntReg(RD | 1)<31:0> << 32);
- }});//STD
- 0x08: ldsw({{Rd.sw = Mem.sw;}}); //LDSW
- 0x09: ldsb({{Rd.sb = Mem.sb;}}); //LDSB
- 0x0A: ldsh({{Rd.shw = Mem.shw;}}); //LDSH
- 0x0B: ldx({{Rd.udw = Mem.udw;}}); //LDX
-
- 0x0D: ldstub({{
- Rd.ub = Mem.ub;
- Mem.ub = 0xFF;
- }}); //LDSTUB
- 0x0E: stx({{Rd.udw = Mem.udw;}}); //STX
- 0x0F: swap({{
- uint32_t temp = Rd.uw;
- Rd.uw = Mem.uw;
- Mem.uw = temp;
- }}); //SWAP
- 0x10: lduwa({{Rd.uw = Mem.uw;}}); //LDUWA
- 0x11: lduba({{Rd.ub = Mem.ub;}}); //LDUBA
- 0x12: lduha({{Rd.uhw = Mem.uhw;}}); //LDUHA
- 0x13: ldda({{
- uint64_t val = Mem.udw;
- setIntReg(RD & (~1), val<31:0>);
- setIntReg(RD | 1, val<63:32>);
- }}); //LDDA
- 0x14: stwa({{Mem.uw = Rd.uw;}}); //STWA
- 0x15: stba({{Mem.ub = Rd.ub;}}); //STBA
- 0x16: stha({{Mem.uhw = Rd.uhw;}}); //STHA
- 0x17: stda({{
- Mem.udw = readIntReg(RD & (~1))<31:0> | (readIntReg(RD | 1)<31:0> << 32);
- }}); //STDA
- 0x18: ldswa({{Rd.sw = Mem.sw;}}); //LDSWA
- 0x19: ldsba({{Rd.sb = Mem.sb;}}); //LDSBA
- 0x1A: ldsha({{Rd.shw = Mem.shw;}}); //LDSHA
- 0x1B: ldxa({{Rd.sdw = Mem.sdw;}}); //LDXA
-
- 0x1D: ldstuba({{
- Rd.ub = Mem.ub;
- Mem.ub = 0xFF;
- }}); //LDSTUBA
- 0x1E: stxa({{Mem.sdw = Rd.sdw}}); //STXA
- 0x1F: swapa({{
- uint32_t temp = Rd.uw;
- Rd.uw = Mem.uw;
- Mem.uw = temp;
- }}); //SWAPA
- 0x20: Trap::ldf({{throw fp_disabled;}}); //LDF
- 0x21: decode X {
- 0x0: Trap::ldfsr({{throw fp_disabled;}}); //LDFSR
- 0x1: Trap::ldxfsr({{throw fp_disabled;}}); //LDXFSR
- }
- 0x22: Trap::ldqf({{throw fp_disabled;}}); //LDQF
- 0x23: Trap::lddf({{throw fp_disabled;}}); //LDDF
- 0x24: Trap::stf({{throw fp_disabled;}}); //STF
- 0x25: decode X {
- 0x0: Trap::stfsr({{throw fp_disabled;}}); //STFSR
- 0x1: Trap::stxfsr({{throw fp_disabled;}}); //STXFSR
- }
- 0x26: Trap::stqf({{throw fp_disabled;}}); //STQF
- 0x27: Trap::stdf({{throw fp_disabled;}}); //STDF
-
-
-
-
-
- 0x2D: Noop::prefetch({{ }}); //PREFETCH
-
-
- 0x30: Trap::ldfa({{throw fp_disabled;}}); //LDFA
-
- 0x32: Trap::ldqfa({{throw fp_disabled;}}); //LDQFA
- 0x33: Trap::lddfa({{throw fp_disabled;}}); //LDDFA
- 0x34: Trap::stfa({{throw fp_disabled;}}); //STFA
- 0x35: Trap::stqfa({{throw fp_disabled;}}); //STQFA
- 0x36: Trap::stdfa({{throw fp_disabled;}}); //STDFA
-
-
-
-
-
- 0x3C: Cas::casa(
- {{uint64_t val = Mem.uw;
- if(Rs2.uw == val)
- Mem.uw = Rd.uw;
- Rd.uw = val;
- }}); //CASA
- 0x3D: Noop::prefetcha({{ }}); //PREFETCHA
- 0x3E: Cas::casxa(
- {{uint64_t val = Mem.udw;
- if(Rs2 == val)
- Mem.udw = Rd;
- Rd = val;
- }}); //CASXA
- }
- }
-}
diff --git a/arch/sparc/isa/formats.isa b/arch/sparc/isa/formats.isa
deleted file mode 100644
index 547f8be48..000000000
--- a/arch/sparc/isa/formats.isa
+++ /dev/null
@@ -1,19 +0,0 @@
-//Include the basic format
-//Templates from this format are used later
-##include "m5/arch/sparc/isa/formats/basic.isa"
-
-//Include the integerOp and integerOpCc format
-##include "m5/arch/sparc/isa/formats/integerop.isa"
-
-//Include the mem format
-##include "m5/arch/sparc/isa/formats/mem.isa"
-
-//Include the trap format
-##include "m5/arch/sparc/isa/formats/trap.isa"
-
-//Include the branch format
-##include "m5/arch/sparc/isa/formats/branch.isa"
-
-//Include the noop format
-##include "m5/arch/sparc/isa/formats/noop.isa"
-
diff --git a/arch/sparc/isa/formats/basic.isa b/arch/sparc/isa/formats/basic.isa
deleted file mode 100644
index 73df7617d..000000000
--- a/arch/sparc/isa/formats/basic.isa
+++ /dev/null
@@ -1,68 +0,0 @@
-
-// Declarations for execute() methods.
-def template BasicExecDeclare {{
- Fault execute(%(CPU_exec_context)s *, Trace::InstRecord *) const;
-}};
-
-// Basic instruction class declaration template.
-def template BasicDeclare {{
- /**
- * Static instruction class for "%(mnemonic)s".
- */
- class %(class_name)s : public %(base_class)s
- {
- public:
- // Constructor.
- %(class_name)s(MachInst machInst);
- %(BasicExecDeclare)s
- };
-}};
-
-// Basic instruction class constructor template.
-def template BasicConstructor {{
- inline %(class_name)s::%(class_name)s(MachInst machInst)
- : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
- {
- %(constructor)s;
- }
-}};
-
-// Basic instruction class execute method template.
-def template BasicExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
- Trace::InstRecord *traceData) const
- {
- Fault fault = NoFault;
-
- %(fp_enable_check)s;
- %(op_decl)s;
- %(op_rd)s;
- %(code)s;
-
- if(fault == NoFault)
- {
- %(op_wb)s;
- }
- return fault;
- }
-}};
-
-// Basic decode template.
-def template BasicDecode {{
- return new %(class_name)s(machInst);
-}};
-
-// Basic decode template, passing mnemonic in as string arg to constructor.
-def template BasicDecodeWithMnemonic {{
- return new %(class_name)s("%(mnemonic)s", machInst);
-}};
-
-// The most basic instruction format... used only for a few misc. insts
-def format BasicOperate(code, *flags) {{
- iop = InstObjParams(name, Name, 'SparcStaticInst',
- CodeBlock(code), flags)
- header_output = BasicDeclare.subst(iop)
- decoder_output = BasicConstructor.subst(iop)
- decode_block = BasicDecode.subst(iop)
- exec_output = BasicExecute.subst(iop)
-}};
diff --git a/arch/sparc/isa/formats/branch.isa b/arch/sparc/isa/formats/branch.isa
deleted file mode 100644
index 80101de1b..000000000
--- a/arch/sparc/isa/formats/branch.isa
+++ /dev/null
@@ -1,62 +0,0 @@
-////////////////////////////////////////////////////////////////////
-//
-// Branch instructions
-//
-
-output header {{
- /**
- * Base class for integer operations.
- */
- class Branch : public SparcStaticInst
- {
- protected:
- // Constructor
- Branch(const char *mnem, MachInst _machInst, OpClass __opClass) :
- SparcStaticInst(mnem, _machInst, __opClass)
- {
- }
-
- std::string generateDisassembly(Addr pc,
- const SymbolTable *symtab) const;
- };
-}};
-
-output decoder {{
- std::string Branch::generateDisassembly(Addr pc, const SymbolTable *symtab) const
- {
- return "Branch instruction\n";
- }
-}};
-
-def template BranchExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
- Trace::InstRecord *traceData) const
- {
- //Attempt to execute the instruction
- Fault fault = NoFault;
- checkPriv;
-
- %(op_decl)s;
- %(op_rd)s;
- %(code)s;
-
- if(fault == NoFault)
- {
- //Write the resulting state to the execution context
- %(op_wb)s;
- }
-
- return fault;
- }
-}};
-
-// Primary format for integer operate instructions:
-def format Branch(code, *opt_flags) {{
- orig_code = code
- cblk = CodeBlock(code)
- iop = InstObjParams(name, Name, 'SparcStaticInst', cblk, opt_flags)
- header_output = BasicDeclare.subst(iop)
- decoder_output = BasicConstructor.subst(iop)
- decode_block = BasicDecodeWithMnemonic.subst(iop)
- exec_output = BranchExecute.subst(iop)
-}};
diff --git a/arch/sparc/isa/formats/integerop.isa b/arch/sparc/isa/formats/integerop.isa
deleted file mode 100644
index 5a9e09896..000000000
--- a/arch/sparc/isa/formats/integerop.isa
+++ /dev/null
@@ -1,112 +0,0 @@
-////////////////////////////////////////////////////////////////////
-//
-// Integer operate instructions
-//
-
-output header {{
- /**
- * Base class for integer operations.
- */
- class IntegerOp : public SparcStaticInst
- {
- protected:
- // Constructor
- IntegerOp(const char *mnem, MachInst _machInst, OpClass __opClass) :
- SparcStaticInst(mnem, _machInst, __opClass)
- {
- }
-
- std::string generateDisassembly(Addr pc,
- const SymbolTable *symtab) const;
- };
-}};
-
-output decoder {{
- std::string IntegerOp::generateDisassembly(Addr pc,
- const SymbolTable *symtab) const
- {
- return "Integer instruction\n";
- }
-}};
-
-def template IntegerExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const
- {
- //These are set to constants when the execute method
- //is generated
- bool useCc = ;
- bool checkPriv = ;
-
- //Attempt to execute the instruction
- try
- {
- checkPriv;
-
- %(op_decl)s;
- %(op_rd)s;
- %(code)s;
- }
- //If we have an exception for some reason,
- //deal with it
- catch(SparcException except)
- {
- //Deal with exception
- return No_Fault;
- }
-
- //Write the resulting state to the execution context
- %(op_wb)s;
- if(useCc)
- {
- xc->regs.miscRegFile.ccrFields.iccFields.n = Rd & (1 << 63);
- xc->regs.miscRegFile.ccrFields.iccFields.z = (Rd == 0);
- xc->regs.miscRegFile.ccrFields.iccFields.v = ivValue;
- xc->regs.miscRegFile.ccrFields.iccFields.c = icValue;
- xc->regs.miscRegFile.ccrFields.xccFields.n = Rd & (1 << 31);
- xc->regs.miscRegFile.ccrFields.xccFields.z = ((Rd & 0xFFFFFFFF) == 0);
- xc->regs.miscRegFile.ccrFields.xccFields.v = xvValue;
- xc->regs.miscRegFile.ccrFields.xccFields.c = xcValue;
- }
- return No_Fault;
- }
-}};
-
-// Primary format for integer operate instructions:
-def format IntegerOp(code, *opt_flags) {{
- orig_code = code
- cblk = CodeBlock(code)
- checkPriv = (code.find('checkPriv') != -1)
- code.replace('checkPriv', '')
- if checkPriv:
- code.replace('checkPriv;', 'if(!xc->regs.miscRegFile.pstateFields.priv) throw privileged_opcode;')
- else:
- code.replace('checkPriv;', '')
- for (marker, value) in (('ivValue', '0'), ('icValue', '0'),
- ('xvValue', '0'), ('xcValue', '0')):
- code.replace(marker, value)
- iop = InstObjParams(name, Name, 'SparcStaticInst', cblk, opt_flags)
- header_output = BasicDeclare.subst(iop)
- decoder_output = BasicConstructor.subst(iop)
- decode_block = BasicDecodeWithMnemonic.subst(iop)
- exec_output = IntegerExecute.subst(iop)
-}};
-
-// Primary format for integer operate instructions:
-def format IntegerOpCc(code, icValue, ivValue, xcValue, xvValue, *opt_flags) {{
- orig_code = code
- cblk = CodeBlock(code)
- checkPriv = (code.find('checkPriv') != -1)
- code.replace('checkPriv', '')
- if checkPriv:
- code.replace('checkPriv;', 'if(!xc->regs.miscRegFile.pstateFields.priv) throw privileged_opcode;')
- else:
- code.replace('checkPriv;', '')
- for (marker, value) in (('ivValue', ivValue), ('icValue', icValue),
- ('xvValue', xvValue), ('xcValue', xcValue)):
- code.replace(marker, value)
- iop = InstObjParams(name, Name, 'SparcStaticInst', cblk, opt_flags)
- header_output = BasicDeclare.subst(iop)
- decoder_output = BasicConstructor.subst(iop)
- decode_block = BasicDecodeWithMnemonic.subst(iop)
- exec_output = IntegerExecute.subst(iop)
-}};
diff --git a/arch/sparc/isa/formats/mem.isa b/arch/sparc/isa/formats/mem.isa
deleted file mode 100644
index d72de47d0..000000000
--- a/arch/sparc/isa/formats/mem.isa
+++ /dev/null
@@ -1,73 +0,0 @@
-////////////////////////////////////////////////////////////////////
-//
-// Mem instructions
-//
-
-output header {{
- /**
- * Base class for integer operations.
- */
- class Mem : public SparcStaticInst
- {
- protected:
-
- // Constructor
- Mem(const char *mnem, MachInst _machInst, OpClass __opClass) :
- SparcStaticInst(mnem, _machInst, __opClass)
- {
- }
-
- std::string generateDisassembly(Addr pc,
- const SymbolTable *symtab) const;
- };
-}};
-
-output decoder {{
- std::string Mem::generateDisassembly(Addr pc, const SymbolTable *symtab) const
- {
- return "Memory instruction\n";
- }
-}};
-
-def template MemExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
- Trace::InstRecord *traceData) const
- {
- Fault fault = NoFault;
- %(op_decl)s;
- %(op_rd)s;
- ea_code
- %(code)s;
-
- if(fault == NoFault)
- {
- //Write the resulting state to the execution context
- %(op_wb)s;
- }
-
- return fault;
- }
-}};
-
-// Primary format for integer operate instructions:
-def format Mem(code, *opt_flags) {{
- orig_code = code
- cblk = CodeBlock(code)
- iop = InstObjParams(name, Name, 'SparcStaticInst', cblk, opt_flags)
- header_output = BasicDeclare.subst(iop)
- decoder_output = BasicConstructor.subst(iop)
- decode_block = BasicDecodeWithMnemonic.subst(iop)
- exec_output = MemExecute.subst(iop)
- exec_output.replace('ea_code', 'EA = I ? (R1 + SIMM13) : R1 + R2;');
-}};
-
-def format Cas(code, *opt_flags) {{
- orig_code = code
- cblk = CodeBlock(code)
- iop = InstObjParams(name, Name, 'SparcStaticInst', cblk, opt_flags)
- header_output = BasicDeclare.subst(iop)
- decoder_output = BasicConstructor.subst(iop)
- decode_block = BasicDecodeWithMnemonic.subst(iop)
- exec_output = MemExecute.subst(iop)
- exec_output.replace('ea_code', 'EA = R1;');
-}};
diff --git a/arch/sparc/isa/formats/noop.isa b/arch/sparc/isa/formats/noop.isa
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/trap.isa b/arch/sparc/isa/formats/trap.isa
deleted file mode 100644
index ff3aadf72..000000000
--- a/arch/sparc/isa/formats/trap.isa
+++ /dev/null
@@ -1,51 +0,0 @@
-////////////////////////////////////////////////////////////////////
-//
-// Trap instructions
-//
-
-output header {{
- /**
- * Base class for integer operations.
- */
- class Trap : public SparcStaticInst
- {
- protected:
-
- // Constructor
- Trap(const char *mnem, MachInst _machInst, OpClass __opClass) :
- SparcStaticInst(mnem, _machInst, __opClass)
- {
- }
-
- std::string generateDisassembly(Addr pc,
- const SymbolTable *symtab) const;
- };
-}};
-
-output decoder {{
- std::string Trap::generateDisassembly(Addr pc,
- const SymbolTable *symtab) const
- {
- return "Trap instruction\n";
- }
-}};
-
-def template TrapExecute {{
- Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
- Trace::InstRecord *traceData) const
- {
- //TODO: set up a software fault and return it.
- return NoFault;
- }
-}};
-
-// Primary format for integer operate instructions:
-def format Trap(code, *opt_flags) {{
- orig_code = code
- cblk = CodeBlock(code)
- iop = InstObjParams(name, Name, 'SparcStaticInst', cblk, opt_flags)
- header_output = BasicDeclare.subst(iop)
- decoder_output = BasicConstructor.subst(iop)
- decode_block = BasicDecodeWithMnemonic.subst(iop)
- exec_output = TrapExecute.subst(iop)
-}};
diff --git a/arch/sparc/isa/includes.isa b/arch/sparc/isa/includes.isa
deleted file mode 100644
index a99018b49..000000000
--- a/arch/sparc/isa/includes.isa
+++ /dev/null
@@ -1,43 +0,0 @@
-////////////////////////////////////////////////////////////////////
-//
-// Output include file directives.
-//
-
-output header {{
-#include <sstream>
-#include <iostream>
-#include <iomanip>
-
-#include "cpu/static_inst.hh"
-#include "arch/sparc/faults.hh"
-#include "mem/mem_req.hh" // some constructors use MemReq flags
-#include "arch/sparc/isa_traits.hh"
-}};
-
-output decoder {{
-#include "base/cprintf.hh"
-#include "base/loader/symtab.hh"
-#include "cpu/exec_context.hh" // for Jump::branchTarget()
-
-#include <math.h>
-#if defined(linux)
-#include <fenv.h>
-#endif
-
-using namespace SparcISA;
-}};
-
-output exec {{
-#include <math.h>
-#if defined(linux)
-#include <fenv.h>
-#endif
-
-#ifdef FULL_SYSTEM
-//#include "arch/alpha/pseudo_inst.hh"
-#endif
-#include "cpu/base.hh"
-#include "cpu/exetrace.hh"
-#include "sim/sim_exit.hh"
-}};
-
diff --git a/arch/sparc/isa/main.isa b/arch/sparc/isa/main.isa
deleted file mode 100644
index ab0290d58..000000000
--- a/arch/sparc/isa/main.isa
+++ /dev/null
@@ -1,52 +0,0 @@
-// -*- mode:c++ -*-
-
-// Copyright (c) 2003-2005 The Regents of The University of Michigan
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met: redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer;
-// redistributions in binary form must reproduce the above copyright
-// notice, this list of conditions and the following disclaimer in the
-// documentation and/or other materials provided with the distribution;
-// neither the name of the copyright holders nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-##include "m5/arch/sparc/isa/includes.isa"
-
-////////////////////////////////////////////////////////////////////
-//
-// Namespace statement. Everything below this line will be in the
-// SparcISAInst namespace.
-//
-
-namespace SparcISA;
-
-//Include the bitfield definitions
-##include "m5/arch/sparc/isa/bitfields.isa"
-
-//Include the operand_types and operand definitions
-##include "m5/arch/sparc/isa/operands.isa"
-
-//Include the base class for sparc instructions, and some support code
-##include "m5/arch/sparc/isa/base.isa"
-
-//Include the definitions for the instruction formats
-##include "m5/arch/sparc/isa/formats.isa"
-
-//Include the decoder definition
-##include "m5/arch/sparc/isa/decoder.isa"
diff --git a/arch/sparc/isa/operands.isa b/arch/sparc/isa/operands.isa
deleted file mode 100644
index 64f5abd08..000000000
--- a/arch/sparc/isa/operands.isa
+++ /dev/null
@@ -1,31 +0,0 @@
-def operand_types {{
- 'sb' : ('signed int', 8),
- 'ub' : ('unsigned int', 8),
- 'shw' : ('signed int', 16),
- 'uhw' : ('unsigned int', 16),
- 'sw' : ('signed int', 32),
- 'uw' : ('unsigned int', 32),
- 'sdw' : ('signed int', 64),
- 'udw' : ('unsigned int', 64),
- 'sf' : ('float', 32),
- 'df' : ('float', 64),
- 'qf' : ('float', 128)
-}};
-
-def operands {{
- # Int regs default to unsigned, but code should not count on this.
- # For clarity, descriptions that depend on unsigned behavior should
- # explicitly specify '.uq'.
- 'Rd': ('IntReg', 'udw', 'RD', 'IsInteger', 1),
- 'Rs1': ('IntReg', 'udw', 'RS1', 'IsInteger', 2),
- 'Rs2': ('IntReg', 'udw', 'RS2', 'IsInteger', 3),
- #'Fa': ('FloatReg', 'df', 'FA', 'IsFloating', 1),
- #'Fb': ('FloatReg', 'df', 'FB', 'IsFloating', 2),
- #'Fc': ('FloatReg', 'df', 'FC', 'IsFloating', 3),
- 'Mem': ('Mem', 'udw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 4),
- #'NPC': ('NPC', 'uq', None, ( None, None, 'IsControl' ), 4),
- #'Runiq': ('ControlReg', 'uq', 'Uniq', None, 1),
- #'FPCR': ('ControlReg', 'uq', 'Fpcr', None, 1),
- 'R0': ('IntReg', 'udw', '0', None, 1),
- 'R16': ('IntReg', 'udw', '16', None, 1)
-}};
diff --git a/arch/sparc/isa_traits.hh b/arch/sparc/isa_traits.hh
deleted file mode 100644
index bd3c35beb..000000000
--- a/arch/sparc/isa_traits.hh
+++ /dev/null
@@ -1,527 +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.
- */
-
-#ifndef __ARCH_SPARC_ISA_TRAITS_HH__
-#define __ARCH_SPARC_ISA_TRAITS_HH__
-
-#include "arch/sparc/faults.hh"
-#include "base/misc.hh"
-#include "config/full_system.hh"
-#include "sim/host.hh"
-
-//This makes sure the big endian versions of certain functions are used.
-namespace BigEndianGuest {}
-using namespace BigEndianGuest;
-
-class ExecContext;
-class FastCPU;
-//class FullCPU;
-class Checkpoint;
-
-#define TARGET_SPARC
-
-class StaticInst;
-class StaticInstPtr;
-
-//namespace EV5
-//{
-// int DTB_ASN_ASN(uint64_t reg);
-// int ITB_ASN_ASN(uint64_t reg);
-//}
-
-namespace SparcISA
-{
- typedef uint32_t MachInst;
- typedef uint64_t ExtMachInst;
- typedef uint8_t RegIndex;
-
- const int NumFloatRegs = 32;
- const int NumMiscRegs = 32;
-
- const int // Maximum trap level
- const int MaxTL = 4;
- const int
- const int // semantically meaningful register indices
- const int ZeroReg = 0; // architecturally meaningful
- const int // the rest of these depend on the ABI
- const int StackPointerReg = 14;
- const int ReturnAddressReg = 31; // post call, precall is 15
- const int ReturnValueReg = 8; // Post return, 24 is pre-return.
- const int FramePointerReg = 30;
- const int ArgumentReg0 = 8;
- const int ArgumentReg1 = 9;
- const int ArgumentReg2 = 10;
- const int ArgumentReg3 = 11;
- const int ArgumentReg4 = 12;
- const int ArgumentReg5 = 13;
- // Some OS syscall sue a second register (o1) to return a second value
- const int SyscallPseudoReturnReg = ArgumentReg1;
-
-
- //8K. This value is implmentation specific; and should probably
- //be somewhere else.
- const int LogVMPageSize = 13;
- const int VMPageSize = (1 << LogVMPageSize);
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- typedef uint64_t IntReg;
-
- class IntRegFile
- {
- private:
- //For right now, let's pretend the register file is static
- IntReg regs[32];
- public:
- IntReg & operator [] (RegIndex index)
- {
- //Don't allow indexes outside of the 32 registers
- index &= 0x1F;
- return regs[index];
- }
- };
-
- void serialize(std::ostream & os);
-
- void unserialize(Checkpoint *cp, const std::string &section);
-
- typedef float float32_t;
- typedef double float64_t;
- //FIXME This actually usually refers to a 10 byte float, rather than a
- //16 byte float as required. This data type may have to be emulated.
- typedef long double float128_t;
-
- class FloatRegFile
- {
- private:
- //By using the largest data type, we ensure everything
- //is aligned correctly in memory
- union
- {
- float128_t rawRegs[16];
- uint64_t regDump[32];
- };
- class QuadRegs
- {
- private:
- FloatRegFile * parent;
- public:
- QuadRegs(FloatRegFile * p) : parent(p) {;}
- float128_t & operator [] (RegIndex index)
- {
- //Quad floats are index by the single
- //precision register the start on,
- //and only 16 should be accessed
- index = (index >> 2) & 0xF;
- return parent->rawRegs[index];
- }
- };
- class DoubleRegs
- {
- private:
- FloatRegFile * parent;
- public:
- DoubleRegs(FloatRegFile * p) : parent(p) {;}
- float64_t & operator [] (RegIndex index)
- {
- //Double floats are index by the single
- //precision register the start on,
- //and only 32 should be accessed
- index = (index >> 1) & 0x1F;
- return ((float64_t *)parent->rawRegs)[index];
- }
- };
- class SingleRegs
- {
- private:
- FloatRegFile * parent;
- public:
- SingleRegs(FloatRegFile * p) : parent(p) {;}
- float32_t & operator [] (RegIndex index)
- {
- //Only 32 single floats should be accessed
- index &= 0x1F;
- return ((float32_t *)parent->rawRegs)[index];
- }
- };
- public:
- void serialize(std::ostream & os);
-
- void unserialize(Checkpoint * cp, std::string & section);
-
- QuadRegs quadRegs;
- DoubleRegs doubleRegs;
- SingleRegs singleRegs;
- FloatRegFile() : quadRegs(this), doubleRegs(this), singleRegs(this)
- {;}
- };
-
- // control register file contents
- typedef uint64_t MiscReg;
- // The control registers, broken out into fields
- class MiscRegFile
- {
- private:
- union
- {
- uint16_t pstate; // Process State Register
- struct
- {
- uint16_t ag:1; // Alternate Globals
- uint16_t ie:1; // Interrupt enable
- uint16_t priv:1; // Privelege mode
- uint16_t am:1; // Address mask
- uint16_t pef:1; // PSTATE enable floating-point
- uint16_t red:1; // RED (reset, error, debug) state
- uint16_t mm:2; // Memory Model
- uint16_t tle:1; // Trap little-endian
- uint16_t cle:1; // Current little-endian
- } pstateFields;
- };
- uint64_t tba; // Trap Base Address
- union
- {
- uint64_t y; // Y (used in obsolete multiplication)
- struct
- {
- uint64_t value:32; // The actual value stored in y
- uint64_t :32; // reserved bits
- } yFields;
- };
- uint8_t pil; // Process Interrupt Register
- uint8_t cwp; // Current Window Pointer
- uint16_t tt[MaxTL]; // Trap Type (Type of trap which occured
- // on the previous level)
- union
- {
- uint8_t ccr; // Condition Code Register
- struct
- {
- union
- {
- uint8_t icc:4; // 32-bit condition codes
- struct
- {
- uint8_t c:1; // Carry
- uint8_t v:1; // Overflow
- uint8_t z:1; // Zero
- uint8_t n:1; // Negative
- } iccFields;
- };
- union
- {
- uint8_t xcc:4; // 64-bit condition codes
- struct
- {
- uint8_t c:1; // Carry
- uint8_t v:1; // Overflow
- uint8_t z:1; // Zero
- uint8_t n:1; // Negative
- } xccFields;
- };
- } ccrFields;
- };
- uint8_t asi; // Address Space Identifier
- uint8_t tl; // Trap Level
- uint64_t tpc[MaxTL]; // Trap Program Counter (value from
- // previous trap level)
- uint64_t tnpc[MaxTL]; // Trap Next Program Counter (value from
- // previous trap level)
- union
- {
- uint64_t tstate[MaxTL]; // Trap State
- struct
- {
- //Values are from previous trap level
- uint64_t cwp:5; // Current Window Pointer
- uint64_t :2; // Reserved bits
- uint64_t pstate:10; // Process State
- uint64_t :6; // Reserved bits
- uint64_t asi:8; // Address Space Identifier
- uint64_t ccr:8; // Condition Code Register
- } tstateFields[MaxTL];
- };
- union
- {
- uint64_t tick; // Hardware clock-tick counter
- struct
- {
- uint64_t counter:63; // Clock-tick count
- uint64_t npt:1; // Non-priveleged trap
- } tickFields;
- };
- uint8_t cansave; // Savable windows
- uint8_t canrestore; // Restorable windows
- uint8_t otherwin; // Other windows
- uint8_t cleanwin; // Clean windows
- union
- {
- uint8_t wstate; // Window State
- struct
- {
- uint8_t normal:3; // Bits TT<4:2> are set to on a normal
- // register window trap
- uint8_t other:3; // Bits TT<4:2> are set to on an "otherwin"
- // register window trap
- } wstateFields;
- };
- union
- {
- uint64_t ver; // Version
- struct
- {
- uint64_t maxwin:5; // Max CWP value
- uint64_t :2; // Reserved bits
- uint64_t maxtl:8; // Maximum trap level
- uint64_t :8; // Reserved bits
- uint64_t mask:8; // Processor mask set revision number
- uint64_t impl:16; // Implementation identification number
- uint64_t manuf:16; // Manufacturer code
- } verFields;
- };
- union
- {
- uint64_t fsr; // Floating-Point State Register
- struct
- {
- union
- {
- uint64_t cexc:5; // Current excpetion
- struct
- {
- uint64_t nxc:1; // Inexact
- uint64_t dzc:1; // Divide by zero
- uint64_t ufc:1; // Underflow
- uint64_t ofc:1; // Overflow
- uint64_t nvc:1; // Invalid operand
- } cexecFields;
- };
- union
- {
- uint64_t aexc:5; // Accrued exception
- struct
- {
- uint64_t nxc:1; // Inexact
- uint64_t dzc:1; // Divide by zero
- uint64_t ufc:1; // Underflow
- uint64_t ofc:1; // Overflow
- uint64_t nvc:1; // Invalid operand
- } aexecFields;
- };
- uint64_t fcc0:2; // Floating-Point condtion codes
- uint64_t :1; // Reserved bits
- uint64_t qne:1; // Deferred trap queue not empty
- // with no queue, it should read 0
- uint64_t ftt:3; // Floating-Point trap type
- uint64_t ver:3; // Version (of the FPU)
- uint64_t :2; // Reserved bits
- uint64_t ns:1; // Nonstandard floating point
- union
- {
- uint64_t tem:5; // Trap Enable Mask
- struct
- {
- uint64_t nxm:1; // Inexact
- uint64_t dzm:1; // Divide by zero
- uint64_t ufm:1; // Underflow
- uint64_t ofm:1; // Overflow
- uint64_t nvm:1; // Invalid operand
- } temFields;
- };
- uint64_t :2; // Reserved bits
- uint64_t rd:2; // Rounding direction
- uint64_t fcc1:2; // Floating-Point condition codes
- uint64_t fcc2:2; // Floating-Point condition codes
- uint64_t fcc3:2; // Floating-Point condition codes
- uint64_t :26; // Reserved bits
- } fsrFields;
- };
- union
- {
- uint8_t fprs; // Floating-Point Register State
- struct
- {
- uint8_t dl:1; // Dirty lower
- uint8_t du:1; // Dirty upper
- uint8_t fef:1; // FPRS enable floating-Point
- } fprsFields;
- };
-
- public:
- MiscReg readReg(int misc_reg);
-
- MiscReg readRegWithEffect(int misc_reg, Fault &fault, ExecContext *xc);
-
- Fault setReg(int misc_reg, const MiscReg &val);
-
- Fault setRegWithEffect(int misc_reg, const MiscReg &val,
- ExecContext *xc);
-
- void serialize(std::ostream & os);
-
- void unserialize(Checkpoint * cp, std::string & section);
- };
-
- typedef union
- {
- float32_t singReg;
- float64_t doubReg;
- float128_t quadReg;
- } FloatReg;
-
- typedef union
- {
- IntReg intreg;
- FloatReg fpreg;
- MiscReg ctrlreg;
- } AnyReg;
-
- struct RegFile
- {
- IntRegFile intRegFile; // (signed) integer register file
- FloatRegFile floatRegFile; // floating point register file
- MiscRegFile miscRegFile; // control register file
-
- Addr pc; // Program Counter
- Addr npc; // Next Program Counter
- Addr nnpc;
-
- void serialize(std::ostream &os);
- void unserialize(Checkpoint *cp, const std::string &section);
- };
-
- StaticInstPtr decodeInst(MachInst);
-
- // return a no-op instruction... used for instruction fetch faults
- extern const MachInst NoopMachInst;
-
- // Instruction address compression hooks
- inline Addr realPCToFetchPC(const Addr &addr)
- {
- return addr;
- }
-
- inline Addr fetchPCToRealPC(const Addr &addr)
- {
- return addr;
- }
-
- // the size of "fetched" instructions (not necessarily the size
- // of real instructions for PISA)
- inline size_t fetchInstSize()
- {
- return sizeof(MachInst);
- }
-
- /**
- * Function to insure ISA semantics about 0 registers.
- * @param xc The execution context.
- */
- template <class XC>
-
- static inline setSyscallReturn(SyscallReturn return_value, RegFile *regs)
- {
- // check for error condition. SPARC syscall convention is to
- // indicate success/failure in reg the carry bit of the ccr
- // and put the return value itself in the standard return value reg ().
- if (return_value.successful()) {
- // no error
- regs->miscRegFile.ccrFields.iccFields.c = 0;
- regs->intRegFile[ReturnValueReg] = return_value.value();
- } else {
- // got an error, return details
- regs->miscRegFile.ccrFields.iccFields.c = 1;
- regs->intRegFile[ReturnValueReg] = -return_value.value();
- }
- }
-};
-
-#if !FULL_SYSTEM
-class SyscallReturn
-{
- public:
- template <class T>
- SyscallReturn(T v, bool s)
- {
- retval = (uint64_t)v;
- success = s;
- }
-
- template <class T>
- SyscallReturn(T v)
- {
- success = (v >= 0);
- retval = (uint64_t)v;
- }
-
- ~SyscallReturn() {}
-
- SyscallReturn& operator=(const SyscallReturn& s)
- {
- retval = s.retval;
- success = s.success;
- return *this;
- }
-
- bool successful() { return success; }
- uint64_t value() { return retval; }
-
- private:
- uint64_t retval;
- bool success;
-};
-
-#endif
-
-
-#if FULL_SYSTEM
-
-#include "arch/alpha/ev5.hh"
-#endif
-
-#endif // __ARCH_SPARC_ISA_TRAITS_HH__
diff --git a/arch/sparc/linux/process.cc b/arch/sparc/linux/process.cc
deleted file mode 100644
index fa2a7b9f5..000000000
--- a/arch/sparc/linux/process.cc
+++ /dev/null
@@ -1,374 +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/sparc/common_syscall_emul.hh"
-#include "arch/sparc/linux/process.hh"
-#include "arch/sparc/isa_traits.hh"
-
-#include "base/trace.hh"
-#include "cpu/exec_context.hh"
-#include "kern/linux/linux.hh"
-#include "mem/functional/functional.hh"
-
-#include "sim/process.hh"
-#include "sim/syscall_emul.hh"
-
-using namespace std;
-using namespace SparcISA;
-
-
-/// Target uname() handler.
-static SyscallReturn
-unameFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
-{
- TypedBufferArg<Linux::utsname> name(xc->getSyscallArg(0));
-
- strcpy(name->sysname, "Linux");
- strcpy(name->nodename, "m5.eecs.umich.edu");
- strcpy(name->release, "2.4.20");
- strcpy(name->version, "#1 Mon Aug 18 11:32:15 EDT 2003");
- strcpy(name->machine, "sparc");
-
- name.copyOut(xc->mem);
- return 0;
-}
-
-SyscallDesc SparcLinuxProcess::syscallDescs[] = {
- /* 0 */ SyscallDesc("restart_syscall", unimplementedFunc);
- /* 1 */ SyscallDesc("exit", exitFunc);
- /* 2 */ SyscallDesc("fork", unimplementedFunc);
- /* 3 */ SyscallDesc("read", readFunc);
- /* 4 */ SyscallDesc("write", writeFunc);
- /* 5 */ SyscallDesc("open", openFunc<Linux>);
- /* 6 */ SyscallDesc("close", closeFinc);
- /* 7 */ SyscallDesc("wait4", unimplementedFunc);
- /* 8 */ SyscallDesc("creat", unimplementedFunc);
- /* 9 */ SyscallDesc("link", unimplementedFunc);
- /* 10 */ SyscallDesc("unlink", unlinkFunc);
- /* 11 */ SyscallDesc("execv", unimplementedFunc);
- /* 12 */ SyscallDesc("chdir", unimplementedFunc);
- /* 13 */ SyscallDesc("chown", chownFunc);
- /* 14 */ SyscallDesc("mknod", unimplementedFunc);
- /* 15 */ SyscallDesc("chmod", chmodFunc<Linux>);
- /* 16 */ SyscallDesc("lchown", unimplementedFunc);
- /* 17 */ SyscallDesc("brk", obreakFunc);
- /* 18 */ SyscallDesc("perfctr", unimplementedFunc);
- /* 19 */ SyscallDesc("lseek", lseekFunc);
- /* 20 */ SyscallDesc("getpid", getpidFunc);
- /* 21 */ SyscallDesc("capget", unimplementedFunc);
- /* 22 */ SyscallDesc("capset", unimplementedFunc);
- /* 23 */ SyscallDesc("setuid", setuidFunc);
- /* 24 */ SyscallDesc("getuid", getuidFunc);
- /* 25 */ SyscallDesc("time", unimplementedFunc);
- /* 26 */ SyscallDesc("ptrace", unimplementedFunc);
- /* 27 */ SyscallDesc("alarm", unimplementedFunc);
- /* 28 */ SyscallDesc("sigaltstack", unimplementedFunc);
- /* 29 */ SyscallDesc("pause", unimplementedFunc);
- /* 30 */ SyscallDesc("utime", unimplementedFunc);
- /* 31 */ SyscallDesc("lchown32", unimplementedFunc);
- /* 32 */ SyscallDesc("fchown32", unimplementedFunc);
- /* 33 */ SyscallDesc("access", unimplementedFunc);
- /* 34 */ SyscallDesc("nice", unimplementedFunc);
- /* 35 */ SyscallDesc("chown32", unimplementedFunc);
- /* 36 */ SyscallDesc("sync", unimplementedFunc);
- /* 37 */ SyscallDesc("kill", unimplementedFunc);
- /* 38 */ SyscallDesc("stat", unimplementedFunc);
- /* 39 */ SyscallDesc("sendfile", unimplementedFunc);
- /* 40 */ SyscallDesc("lstat", unimplementedFunc);
- /* 41 */ SyscallDesc("dup", unimplementedFunc);
- /* 42 */ SyscallDesc("pipe", pipePseudoFunc);
- /* 43 */ SyscallDesc("times", unimplementedFunc);
- /* 44 */ SyscallDesc("getuid32", unimplementedFunc);
- /* 45 */ SyscallDesc("umount2", unimplementedFunc);
- /* 46 */ SyscallDesc("setgid", unimplementedFunc);
- /* 47 */ SyscallDesc("getgid", getgidFunc);
- /* 48 */ SyscallDesc("signal", unimplementedFunc);
- /* 49 */ SyscallDesc("geteuid", geteuidFunc);
- /* 50 */ SyscallDesc("getegid", getegidFunc);
- /* 51 */ SyscallDesc("acct", unimplementedFunc);
- /* 52 */ SyscallDesc("memory_ordering", unimplementedFunc);
- /* 53 */ SyscallDesc("getgid32", unimplementedFunc);
- /* 54 */ SyscallDesc("ioctl", unimplementedFunc);
- /* 55 */ SyscallDesc("reboot", unimplementedFunc);
- /* 56 */ SyscallDesc("mmap2", unimplementedFunc);
- /* 57 */ SyscallDesc("symlink", unimplementedFunc);
- /* 58 */ SyscallDesc("readlink", unimplementedFunc);
- /* 59 */ SyscallDesc("execve", unimplementedFunc);
- /* 60 */ SyscallDesc("umask", unimplementedFunc);
- /* 61 */ SyscallDesc("chroot", unimplementedFunc);
- /* 62 */ SyscallDesc("fstat", unimplementedFunc);
- /* 63 */ SyscallDesc("fstat64", unimplementedFunc);
- /* 64 */ SyscallDesc("getpagesize", unimplementedFunc);
- /* 65 */ SyscallDesc("msync", unimplementedFunc);
- /* 66 */ SyscallDesc("vfork", unimplementedFunc);
- /* 67 */ SyscallDesc("pread64", unimplementedFunc);
- /* 68 */ SyscallDesc("pwrite64", unimplementedFunc);
- /* 69 */ SyscallDesc("geteuid32", unimplementedFunc);
- /* 70 */ SyscallDesc("getdgid32", unimplementedFunc);
- /* 71 */ SyscallDesc("mmap", unimplementedFunc);
- /* 72 */ SyscallDesc("setreuid32", unimplementedFunc);
- /* 73 */ SyscallDesc("munmap", unimplementedFunc);
- /* 74 */ SyscallDesc("mprotect", unimplementedFunc);
- /* 75 */ SyscallDesc("madvise", unimplementedFunc);
- /* 76 */ SyscallDesc("vhangup", unimplementedFunc);
- /* 77 */ SyscallDesc("truncate64", unimplementedFunc);
- /* 78 */ SyscallDesc("mincore", unimplementedFunc);
- /* 79 */ SyscallDesc("getgroups", unimplementedFunc);
- /* 80 */ SyscallDesc("setgroups", unimplementedFunc);
- /* 81 */ SyscallDesc("getpgrp", unimplementedFunc);
- /* 82 */ SyscallDesc("setgroups32", unimplementedFunc);
- /* 83 */ SyscallDesc("setitimer", unimplementedFunc);
- /* 84 */ SyscallDesc("ftruncate64", unimplementedFunc);
- /* 85 */ SyscallDesc("swapon", unimplementedFunc);
- /* 86 */ SyscallDesc("getitimer", unimplementedFunc);
- /* 87 */ SyscallDesc("setuid32", unimplementedFunc);
- /* 88 */ SyscallDesc("sethostname", unimplementedFunc);
- /* 89 */ SyscallDesc("setgid32", unimplementedFunc);
- /* 90 */ SyscallDesc("dup2", unimplementedFunc);
- /* 91 */ SyscallDesc("setfsuid32", unimplementedFunc);
- /* 92 */ SyscallDesc("fcntl", unimplementedFunc);
- /* 93 */ SyscallDesc("select", unimplementedFunc);
- /* 94 */ SyscallDesc("setfsgid32", unimplementedFunc);
- /* 95 */ SyscallDesc("fsync", unimplementedFunc);
- /* 96 */ SyscallDesc("setpriority", unimplementedFunc);
- /* 97 */ SyscallDesc("socket", unimplementedFunc);
- /* 98 */ SyscallDesc("connect", unimplementedFunc);
- /* 99 */ SyscallDesc("accept", unimplementedFunc);
- /* 100 */ SyscallDesc("getpriority", unimplementedFunc);
- /* 101 */ SyscallDesc("rt_sigreturn", unimplementedFunc);
- /* 102 */ SyscallDesc("rt_sigaction", unimplementedFunc);
- /* 103 */ SyscallDesc("rt_sigprocmask", unimplementedFunc);
- /* 104 */ SyscallDesc("rt_sigpending", unimplementedFunc);
- /* 105 */ SyscallDesc("rt_sigtimedwait", unimplementedFunc);
- /* 106 */ SyscallDesc("rt_sigqueueinfo", unimplementedFunc);
- /* 107 */ SyscallDesc("rt_sigsuspend", unimplementedFunc);
- /* 108 */ SyscallDesc("setresuid", unimplementedFunc);
- /* 109 */ SyscallDesc("getresuid", unimplementedFunc);
- /* 110 */ SyscallDesc("setresgid", unimplementedFunc);
- /* 111 */ SyscallDesc("getresgid", unimplementedFunc);
- /* 112 */ SyscallDesc("setregid32", unimplementedFunc);
- /* 113 */ SyscallDesc("recvmsg", unimplementedFunc);
- /* 114 */ SyscallDesc("sendmsg", unimplementedFunc);
- /* 115 */ SyscallDesc("getgroups32", unimplementedFunc);
- /* 116 */ SyscallDesc("gettimeofday", unimplementedFunc);
- /* 117 */ SyscallDesc("getrusage", unimplementedFunc);
- /* 118 */ SyscallDesc("getsockopt", unimplementedFunc);
- /* 119 */ SyscallDesc("getcwd", unimplementedFunc);
- /* 120 */ SyscallDesc("readv", unimplementedFunc);
- /* 121 */ SyscallDesc("writev", unimplementedFunc);
- /* 122 */ SyscallDesc("settimeofday", unimplementedFunc);
- /* 123 */ SyscallDesc("fchown", unimplementedFunc);
- /* 124 */ SyscallDesc("fchmod", unimplementedFunc);
- /* 125 */ SyscallDesc("recvfrom", unimplementedFunc);
- /* 126 */ SyscallDesc("setreuid", unimplementedFunc);
- /* 127 */ SyscallDesc("setregid", unimplementedFunc);
- /* 128 */ SyscallDesc("rename", unimplementedFunc);
- /* 129 */ SyscallDesc("truncate", unimplementedFunc);
- /* 130 */ SyscallDesc("ftruncate", unimplementedFunc);
- /* 131 */ SyscallDesc("flock", unimplementedFunc);
- /* 132 */ SyscallDesc("lstat64", unimplementedFunc);
- /* 133 */ SyscallDesc("sendto", unimplementedFunc);
- /* 134 */ SyscallDesc("shutdown", unimplementedFunc);
- /* 135 */ SyscallDesc("socketpair", unimplementedFunc);
- /* 136 */ SyscallDesc("mkdir", unimplementedFunc);
- /* 137 */ SyscallDesc("rmdir", unimplementedFunc);
- /* 138 */ SyscallDesc("utimes", unimplementedFunc);
- /* 139 */ SyscallDesc("stat64", unimplementedFunc);
- /* 140 */ SyscallDesc("sendfile64", unimplementedFunc);
- /* 141 */ SyscallDesc("getpeername", unimplementedFunc);
- /* 142 */ SyscallDesc("futex", unimplementedFunc);
- /* 143 */ SyscallDesc("gettid", unimplementedFunc);
- /* 144 */ SyscallDesc("getrlimit", unimplementedFunc);
- /* 145 */ SyscallDesc("setrlimit", unimplementedFunc);
- /* 146 */ SyscallDesc("pivot_root", unimplementedFunc);
- /* 147 */ SyscallDesc("prctl", unimplementedFunc);
- /* 148 */ SyscallDesc("pciconfig_read", unimplementedFunc);
- /* 149 */ SyscallDesc("pciconfig_write", unimplementedFunc);
- /* 150 */ SyscallDesc("getsockname", unimplementedFunc);
- /* 151 */ SyscallDesc("inotify_init", unimplementedFunc);
- /* 152 */ SyscallDesc("inotify_add_watch", unimplementedFunc);
- /* 153 */ SyscallDesc("poll", unimplementedFunc);
- /* 154 */ SyscallDesc("getdents64", unimplementedFunc);
- /* 155 */ SyscallDesc("fcntl64", unimplementedFunc);
- /* 156 */ SyscallDesc("inotify_rm_watch", unimplementedFunc);
- /* 157 */ SyscallDesc("statfs", unimplementedFunc);
- /* 158 */ SyscallDesc("fstatfs", unimplementedFunc);
- /* 159 */ SyscallDesc("umount", unimplementedFunc);
- /* 160 */ SyscallDesc("sched_set_affinity", unimplementedFunc);
- /* 161 */ SyscallDesc("sched_get_affinity", unimplementedFunc);
- /* 162 */ SyscallDesc("getdomainname", unimplementedFunc);
- /* 163 */ SyscallDesc("setdomainname", unimplementedFunc);
- /* 164 */ SyscallDesc("utrap_install", unimplementedFunc);
- /* 165 */ SyscallDesc("quotactl", unimplementedFunc);
- /* 166 */ SyscallDesc("set_tid_address", unimplementedFunc);
- /* 167 */ SyscallDesc("mount", unimplementedFunc);
- /* 168 */ SyscallDesc("ustat", unimplementedFunc);
- /* 169 */ SyscallDesc("setxattr", unimplementedFunc);
- /* 170 */ SyscallDesc("lsetxattr", unimplementedFunc);
- /* 171 */ SyscallDesc("fsetxattr", unimplementedFunc);
- /* 172 */ SyscallDesc("getxattr", unimplementedFunc);
- /* 173 */ SyscallDesc("lgetxattr", unimplementedFunc);
- /* 174 */ SyscallDesc("getdents", unimplementedFunc);
- /* 175 */ SyscallDesc("setsid", unimplementedFunc);
- /* 176 */ SyscallDesc("fchdir", unimplementedFunc);
- /* 177 */ SyscallDesc("fgetxattr", unimplementedFunc);
- /* 178 */ SyscallDesc("listxattr", unimplementedFunc);
- /* 179 */ SyscallDesc("llistxattr", unimplementedFunc);
- /* 180 */ SyscallDesc("flistxattr", unimplementedFunc);
- /* 181 */ SyscallDesc("removexattr", unimplementedFunc);
- /* 182 */ SyscallDesc("lremovexattr", unimplementedFunc);
- /* 183 */ SyscallDesc("sigpending", unimplementedFunc);
- /* 184 */ SyscallDesc("query_module", unimplementedFunc);
- /* 185 */ SyscallDesc("setpgid", unimplementedFunc);
- /* 186 */ SyscallDesc("fremovexattr", unimplementedFunc);
- /* 187 */ SyscallDesc("tkill", unimplementedFunc);
- /* 188 */ SyscallDesc("exit_group", unimplementedFunc);
- /* 189 */ SyscallDesc("uname", unameFunc);
- /* 190 */ SyscallDesc("init_module", unimplementedFunc);
- /* 191 */ SyscallDesc("personality", unimplementedFunc);
- /* 192 */ SyscallDesc("remap_file_pages", unimplementedFunc);
- /* 193 */ SyscallDesc("epoll_create", unimplementedFunc);
- /* 194 */ SyscallDesc("epoll_ctl", unimplementedFunc);
- /* 195 */ SyscallDesc("epoll_wait", unimplementedFunc);
- /* 196 */ SyscallDesc("ioprio_set", unimplementedFunc);
- /* 197 */ SyscallDesc("getppid", getppidFunc);
- /* 198 */ SyscallDesc("sigaction", unimplementedFunc);
- /* 199 */ SyscallDesc("sgetmask", unimplementedFunc);
- /* 200 */ SyscallDesc("ssetmask", unimplementedFunc);
- /* 201 */ SyscallDesc("sigsuspend", unimplementedFunc);
- /* 202 */ SyscallDesc("oldlstat", unimplementedFunc);
- /* 203 */ SyscallDesc("uselib", unimplementedFunc);
- /* 204 */ SyscallDesc("readdir", unimplementedFunc);
- /* 205 */ SyscallDesc("readahead", unimplementedFunc);
- /* 206 */ SyscallDesc("socketcall", unimplementedFunc);
- /* 207 */ SyscallDesc("syslog", unimplementedFunc);
- /* 208 */ SyscallDesc("lookup_dcookie", unimplementedFunc);
- /* 209 */ SyscallDesc("fadvise64", unimplementedFunc);
- /* 210 */ SyscallDesc("fadvise64_64", unimplementedFunc);
- /* 211 */ SyscallDesc("tgkill", unimplementedFunc);
- /* 212 */ SyscallDesc("waitpid", unimplementedFunc);
- /* 213 */ SyscallDesc("swapoff", unimplementedFunc);
- /* 214 */ SyscallDesc("sysinfo", unimplementedFunc);
- /* 215 */ SyscallDesc("ipc", unimplementedFunc);
- /* 216 */ SyscallDesc("sigreturn", unimplementedFunc);
- /* 217 */ SyscallDesc("clone", unimplementedFunc);
- /* 218 */ SyscallDesc("ioprio_get", unimplementedFunc);
- /* 219 */ SyscallDesc("adjtimex", unimplementedFunc);
- /* 220 */ SyscallDesc("sigprocmask", unimplementedFunc);
- /* 221 */ SyscallDesc("create_module", unimplementedFunc);
- /* 222 */ SyscallDesc("delete_module", unimplementedFunc);
- /* 223 */ SyscallDesc("get_kernel_syms", unimplementedFunc);
- /* 224 */ SyscallDesc("getpgid", unimplementedFunc);
- /* 225 */ SyscallDesc("bdflush", unimplementedFunc);
- /* 226 */ SyscallDesc("sysfs", unimplementedFunc);
- /* 227 */ SyscallDesc("afs_syscall", unimplementedFunc);
- /* 228 */ SyscallDesc("setfsuid", unimplementedFunc);
- /* 229 */ SyscallDesc("setfsgid", unimplementedFunc);
- /* 230 */ SyscallDesc("_newselect", unimplementedFunc);
- /* 231 */ SyscallDesc("time", unimplementedFunc);
- /* 232 */ SyscallDesc("oldstat", unimplementedFunc);
- /* 233 */ SyscallDesc("stime", unimplementedFunc);
- /* 234 */ SyscallDesc("statfs64", unimplementedFunc);
- /* 235 */ SyscallDesc("fstatfs64", unimplementedFunc);
- /* 236 */ SyscallDesc("_llseek", unimplementedFunc);
- /* 237 */ SyscallDesc("mlock", unimplementedFunc);
- /* 238 */ SyscallDesc("munlock", unimplementedFunc);
- /* 239 */ SyscallDesc("mlockall", unimplementedFunc);
- /* 240 */ SyscallDesc("munlockall", unimplementedFunc);
- /* 241 */ SyscallDesc("sched_setparam", unimplementedFunc);
- /* 242 */ SyscallDesc("sched_getparam", unimplementedFunc);
- /* 243 */ SyscallDesc("sched_setscheduler", unimplementedFunc);
- /* 244 */ SyscallDesc("sched_getscheduler", unimplementedFunc);
- /* 245 */ SyscallDesc("sched_yield", unimplementedFunc);
- /* 246 */ SyscallDesc("sched_get_priority_max", unimplimented);
- /* 247 */ SyscallDesc("sched_get_priority_min", unimplimented);
- /* 248 */ SyscallDesc("sched_rr_get_interval", unimplimented);
- /* 249 */ SyscallDesc("nanosleep", unimplementedFunc);
- /* 250 */ SyscallDesc("mremap", unimplementedFunc);
- /* 251 */ SyscallDesc("_sysctl", unimplementedFunc);
- /* 252 */ SyscallDesc("getsid", unimplementedFunc);
- /* 253 */ SyscallDesc("fdatasync", unimplementedFunc);
- /* 254 */ SyscallDesc("nfsservctl", unimplementedFunc);
- /* 255 */ SyscallDesc("aplib", unimplementedFunc);
- /* 256 */ SyscallDesc("clock_settime", unimplementedFunc);
- /* 257 */ SyscallDesc("clock_gettime", unimplementedFunc);
- /* 258 */ SyscallDesc("clock_getres", unimplementedFunc);
- /* 259 */ SyscallDesc("clock_nanosleep", unimplementedFunc);
- /* 260 */ SyscallDesc("sched_getaffinity", unimplementedFunc);
- /* 261 */ SyscallDesc("sched_setaffinity", unimplementedFunc);
- /* 262 */ SyscallDesc("timer_settime", unimplementedFunc);
- /* 263 */ SyscallDesc("timer_gettime", unimplementedFunc);
- /* 264 */ SyscallDesc("timer_getoverrun", unimplementedFunc);
- /* 265 */ SyscallDesc("timer_delete", unimplementedFunc);
- /* 266 */ SyscallDesc("timer_create", unimplementedFunc);
- /* 267 */ SyscallDesc("vserver", unimplementedFunc);
- /* 268 */ SyscallDesc("io_setup", unimplementedFunc);
- /* 269 */ SyscallDesc("io_destroy", unimplementedFunc);
- /* 270 */ SyscallDesc("io_submit", unimplementedFunc);
- /* 271 */ SyscallDesc("io_cancel", unimplementedFunc);
- /* 272 */ SyscallDesc("io_getevents", unimplementedFunc);
- /* 273 */ SyscallDesc("mq_open", unimplementedFunc);
- /* 274 */ SyscallDesc("mq_unlink", unimplementedFunc);
- /* 275 */ SyscallDesc("mq_timedsend", unimplementedFunc);
- /* 276 */ SyscallDesc("mq_timedreceive", unimplementedFunc);
- /* 277 */ SyscallDesc("mq_notify", unimplementedFunc);
- /* 278 */ SyscallDesc("mq_getsetattr", unimplementedFunc);
- /* 279 */ SyscallDesc("waitid", unimplementedFunc);
- /* 280 */ SyscallDesc("sys_setaltroot", unimplementedFunc);
- /* 281 */ SyscallDesc("add_key", unimplementedFunc);
- /* 282 */ SyscallDesc("request_key", unimplementedFunc);
- /* 283 */ SyscallDesc("keyctl", unimplementedFunc);
-};
-
-SparcLinuxProcess::SparcLinuxProcess(const std::string &name,
- ObjectFile *objFile,
- int stdin_fd,
- int stdout_fd,
- int stderr_fd,
- std::vector<std::string> &argv,
- std::vector<std::string> &envp)
- : LiveProcess(name, objFile, stdin_fd, stdout_fd, stderr_fd, argv, envp),
- Num_Syscall_Descs(sizeof(syscallDescs) / sizeof(SyscallDesc))
-{
- // The sparc syscall table must be <= 283 entries because that is all there
- // is space for.
- assert(Num_Syscall_Descs <= 283);
-
- init_regs->intRegFile[0] = 0;
-}
-
-
-
-SyscallDesc*
-AlphaLinuxProcess::getDesc(int callnum)
-{
- if (callnum < 0 || callnum > Num_Syscall_Descs)
- return NULL;
- return &syscallDescs[callnum];
-}
diff --git a/arch/sparc/linux/process.hh b/arch/sparc/linux/process.hh
deleted file mode 100644
index c41406b4b..000000000
--- a/arch/sparc/linux/process.hh
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (c) 2003-2004 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __SPARC_LINUX_PROCESS_HH__
-#define __SPARC_LINUX_PROCESS_HH__
-
-#include "sim/process.hh"
-
-
-/// A process with emulated SPARC/Linux syscalls.
-class SparcLinuxProcess : public LiveProcess
-{
- public:
- /// Constructor.
- SparcLinuxProcess(const std::string &name,
- ObjectFile *objFile,
- int stdin_fd, int stdout_fd, int stderr_fd,
- std::vector<std::string> &argv,
- std::vector<std::string> &envp);
-
- virtual SyscallDesc* getDesc(int callnum);
-
- /// The target system's hostname.
- static const char *hostname;
-
- /// Array of syscall descriptors, indexed by call number.
- static SyscallDesc syscallDescs[];
-
- const int Num_Syscall_Descs;
-};
-
-
-#endif // __ALPHA_LINUX_PROCESS_HH__
diff --git a/arch/sparc/process.cc b/arch/sparc/process.cc
deleted file mode 100644
index 53a215379..000000000
--- a/arch/sparc/process.cc
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2003-2004 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "arch/sparc/process.hh"
-
-namespace SparcISA
-{
-
-LiveProcess *
-createProcess(const string &nm, ObjectFile * objFile,
- int stdin_fd, int stdout_fd, int stderr_fd,
- vector<string> &argv, vector<string> &envp)
-{
- LiveProcess * process = NULL;
- if (objFile->getArch() != ObjectFile::SPARC)
- fatal("Object file does not match architecture.");
- switch (objFile->getOpSys()) {
- case ObjectFile::Linux:
- process = new SparcLinuxProcess(nm, objFile,
- stdin_fd, stdout_fd, stderr_fd,
- argv, envp);
- break;
-
- case ObjectFile::Solaris:
- default:
- fatal("Unknown/unsupported operating system.");
- }
- return process;
-}
-
-} // namespace SparcISA
diff --git a/arch/sparc/process.hh b/arch/sparc/process.hh
deleted file mode 100644
index 48041a316..000000000
--- a/arch/sparc/process.hh
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2003-2004 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __SPARC_PROCESS_HH__
-#define __SPARC_PROCESS_HH__
-
-#include "arch/sparc/linux/process.hh"
-#include "base/loader/object_file.hh"
-
-namespace SparcISA
-{
-
-LiveProcess *
-createProcess(const string &nm, ObjectFile * objFile,
- int stdin_fd, int stdout_fd, int stderr_fd,
- vector<string> &argv, vector<string> &envp);
-
-} // namespace SparcISA
-
-#endif // __SPARC_PROCESS_HH__
diff --git a/base/cprintf.hh b/base/cprintf.hh
deleted file mode 100644
index dcb292434..000000000
--- a/base/cprintf.hh
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * 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 __CPRINTF_HH__
-#define __CPRINTF_HH__
-
-#include <iostream>
-#include <list>
-#include <sstream>
-#include <string>
-
-namespace cp {
-
-#include "base/cprintf_formats.hh"
-
-class ArgList
-{
- private:
- class Base
- {
- public:
- virtual ~Base() {}
- virtual void process(std::ostream &out, Format &fmt) = 0;
- };
-
- template <typename T>
- class Node : public Base
- {
- public:
- const T &data;
-
- public:
- Node(const T &d) : data(d) {}
- virtual void process(std::ostream &out, Format &fmt) {
- switch (fmt.format) {
- case Format::character:
- format_char(out, data, fmt);
- break;
-
- case Format::integer:
- format_integer(out, data, fmt);
- break;
-
- case Format::floating:
- format_float(out, data, fmt);
- break;
-
- case Format::string:
- format_string(out, data, fmt);
- break;
-
- default:
- out << "<bad format>";
- break;
- }
- }
- };
-
- typedef std::list<Base *> list_t;
-
- protected:
- list_t objects;
- std::ostream *stream;
-
- public:
- ArgList() : stream(&std::cout) {}
- ~ArgList();
-
- template<class T>
- void append(const T &data) {
- Base *obj = new ArgList::Node<T>(data);
- objects.push_back(obj);
- }
-
- template<class T>
- void prepend(const T &data) {
- Base *obj = new ArgList::Node<T>(data);
- objects.push_front(obj);
- }
-
- void dump(const std::string &format);
- void dump(std::ostream &strm, const std::string &fmt)
- { stream = &strm; dump(fmt); }
-
- std::string dumpToString(const std::string &format);
-
- friend ArgList &operator<<(std::ostream &str, ArgList &list);
-};
-
-template<class T>
-inline ArgList &
-operator,(ArgList &alist, const T &data)
-{
- alist.append(data);
- return alist;
-}
-
-class ArgListNull {
-};
-
-inline ArgList &
-operator,(ArgList &alist, ArgListNull)
-{ return alist; }
-
-//
-// cprintf(format, args, ...) prints to cout
-// (analogous to printf())
-//
-inline void
-__cprintf(const std::string &format, ArgList &args)
-{ args.dump(format); delete &args; }
-#define __cprintf__(format, args...) \
- cp::__cprintf(format, (*(new cp::ArgList), args))
-#define cprintf(args...) \
- __cprintf__(args, cp::ArgListNull())
-
-//
-// ccprintf(stream, format, args, ...) prints to the specified stream
-// (analogous to fprintf())
-//
-inline void
-__ccprintf(std::ostream &stream, const std::string &format, ArgList &args)
-{ args.dump(stream, format); delete &args; }
-#define __ccprintf__(stream, format, args...) \
- cp::__ccprintf(stream, format, (*(new cp::ArgList), args))
-#define ccprintf(stream, args...) \
- __ccprintf__(stream, args, cp::ArgListNull())
-
-//
-// csprintf(format, args, ...) returns a string
-// (roughly analogous to sprintf())
-//
-inline std::string
-__csprintf(const std::string &format, ArgList &args)
-{ std::string s = args.dumpToString(format); delete &args; return s; }
-#define __csprintf__(format, args...) \
- cp::__csprintf(format, (*(new cp::ArgList), args))
-#define csprintf(args...) \
- __csprintf__(args, cp::ArgListNull())
-
-template<class T>
-inline ArgList &
-operator<<(ArgList &list, const T &data)
-{
- list.append(data);
- return list;
-}
-
-inline ArgList &
-operator<<(std::ostream &str, ArgList &list)
-{
- list.stream = &str;
- return list;
-}
-
-class ArgListTemp
-{
- private:
- std::string format;
- ArgList *args;
-
- public:
- ArgListTemp(const std::string &f) : format(f) { args = new ArgList; }
- ~ArgListTemp() { args->dump(format); delete args; }
-
- operator ArgList *() { return args; }
-};
-
-#define cformat(format) \
- (*((cp::ArgList *)cp::ArgListTemp(format)))
-}
-
-#endif // __CPRINTF_HH__
diff --git a/base/cprintf_formats.hh b/base/cprintf_formats.hh
deleted file mode 100644
index 11b0238ed..000000000
--- a/base/cprintf_formats.hh
+++ /dev/null
@@ -1,346 +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.
- */
-
-#ifndef __CPRINTF_FORMATS_HH__
-#define __CPRINTF_FORMATS_HH__
-
-struct Format
-{
- bool alternate_form;
- bool flush_left;
- bool print_sign;
- bool blank_space;
- bool fill_zero;
- bool uppercase;
- enum { dec, hex, oct } base;
- enum { none, string, integer, character, floating } format;
- enum { best, fixed, scientific } float_format;
- int precision;
- int width;
-
- Format() { clear(); }
-
- void clear()
- {
- alternate_form = false;
- flush_left = false;
- print_sign = false;
- blank_space = false;
- fill_zero = false;
- uppercase = false;
- base = dec;
- format = none;
- precision = -1;
- width = 0;
- }
-};
-
-template <typename T>
-inline void
-_format_char(std::ostream &out, const T &data, Format &fmt)
-{
- using namespace std;
-
- out << data;
-}
-
-template <typename T>
-inline void
-_format_integer(std::ostream &out, const T &data, Format &fmt)
-{
- using namespace std;
-
- switch (fmt.base) {
- case Format::hex:
- out.setf(ios::hex, ios::basefield);
- break;
-
- case Format::oct:
- out.setf(ios::oct, ios::basefield);
- break;
-
- case Format::dec:
- out.setf(ios::dec, ios::basefield);
- break;
- }
-
- if (fmt.alternate_form) {
- if (!fmt.fill_zero)
- out.setf(ios::showbase);
- else {
- switch (fmt.base) {
- case Format::hex:
- out << "0x";
- fmt.width -= 2;
- break;
- case Format::oct:
- out << "0";
- fmt.width -= 1;
- break;
- case Format::dec:
- break;
- }
- }
- }
-
- if (fmt.fill_zero)
- out.fill('0');
-
- if (fmt.width > 0)
- out.width(fmt.width);
-
- if (fmt.flush_left && !fmt.fill_zero)
- out.setf(ios::left);
-
- if (fmt.print_sign)
- out.setf(ios::showpos);
-
- if (fmt.uppercase)
- out.setf(ios::uppercase);
-
- out << data;
-}
-
-template <typename T>
-inline void
-_format_float(std::ostream &out, const T &data, Format &fmt)
-{
- using namespace std;
-
- switch (fmt.float_format) {
- case Format::scientific:
- if (fmt.precision != -1) {
- if (fmt.width > 0)
- out.width(fmt.width);
-
- if (fmt.precision == 0)
- fmt.precision = 1;
- else
- out.setf(ios::scientific);
-
- out.precision(fmt.precision);
- } else
- if (fmt.width > 0)
- out.width(fmt.width);
-
- if (fmt.uppercase)
- out.setf(ios::uppercase);
- break;
-
- case Format::fixed:
- if (fmt.precision != -1) {
- if (fmt.width > 0)
- out.width(fmt.width);
-
- out.setf(ios::fixed);
- out.precision(fmt.precision);
- } else
- if (fmt.width > 0)
- out.width(fmt.width);
-
- break;
-
- default:
- if (fmt.precision != -1)
- out.precision(fmt.precision);
-
- if (fmt.width > 0)
- out.width(fmt.width);
-
- break;
- }
-
- out << data;
-}
-
-template <typename T>
-inline void
-_format_string(std::ostream &out, const T &data, Format &fmt)
-{
- using namespace std;
-
-#if defined(__GNUC__) && (__GNUC__ < 3) || 1
- if (fmt.width > 0) {
- std::stringstream foo;
- foo << data;
- int flen = foo.str().size();
-
- if (fmt.width > flen) {
- char *spaces = new char[fmt.width - flen + 1];
- memset(spaces, ' ', fmt.width - flen);
- spaces[fmt.width - flen] = 0;
-
- if (fmt.flush_left)
- out << foo.str() << spaces;
- else
- out << spaces << foo.str();
-
- delete [] spaces;
- } else
- out << data;
- } else
- out << data;
-#else
- if (fmt.width > 0)
- out.width(fmt.width);
- if (fmt.flush_left)
- out.setf(ios::left);
-
- out << data;
-#endif
-}
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// The code below controls the actual usage of formats for various types
-//
-
-//
-// character formats
-//
-template <typename T>
-inline void
-format_char(std::ostream &out, const T &data, Format &fmt)
-{ out << "<bad arg type for char format>"; }
-
-inline void
-format_char(std::ostream &out, char data, Format &fmt)
-{ _format_char(out, data, fmt); }
-
-inline void
-format_char(std::ostream &out, unsigned char data, Format &fmt)
-{ _format_char(out, data, fmt); }
-
-inline void
-format_char(std::ostream &out, signed char data, Format &fmt)
-{ _format_char(out, data, fmt); }
-
-inline void
-format_char(std::ostream &out, short data, Format &fmt)
-{ _format_char(out, (char)data, fmt); }
-
-inline void
-format_char(std::ostream &out, unsigned short data, Format &fmt)
-{ _format_char(out, (char)data, fmt); }
-
-inline void
-format_char(std::ostream &out, int data, Format &fmt)
-{ _format_char(out, (char)data, fmt); }
-
-inline void
-format_char(std::ostream &out, unsigned int data, Format &fmt)
-{ _format_char(out, (char)data, fmt); }
-
-inline void
-format_char(std::ostream &out, long data, Format &fmt)
-{ _format_char(out, (char)data, fmt); }
-
-inline void
-format_char(std::ostream &out, unsigned long data, Format &fmt)
-{ _format_char(out, (char)data, fmt); }
-
-inline void
-format_char(std::ostream &out, long long data, Format &fmt)
-{ _format_char(out, (char)data, fmt); }
-
-inline void
-format_char(std::ostream &out, unsigned long long data, Format &fmt)
-{ _format_char(out, (char)data, fmt); }
-
-//
-// integer formats
-//
-template <typename T>
-inline void
-format_integer(std::ostream &out, const T &data, Format &fmt)
-{ _format_integer(out, data, fmt); }
-inline void
-format_integer(std::ostream &out, char data, Format &fmt)
-{ _format_integer(out, data, fmt); }
-inline void
-format_integer(std::ostream &out, unsigned char data, Format &fmt)
-{ _format_integer(out, data, fmt); }
-inline void
-format_integer(std::ostream &out, signed char data, Format &fmt)
-{ _format_integer(out, data, fmt); }
-#if 0
-inline void
-format_integer(std::ostream &out, short data, Format &fmt)
-{ _format_integer(out, data, fmt); }
-inline void
-format_integer(std::ostream &out, unsigned short data, Format &fmt)
-{ _format_integer(out, data, fmt); }
-inline void
-format_integer(std::ostream &out, int data, Format &fmt)
-{ _format_integer(out, data, fmt); }
-inline void
-format_integer(std::ostream &out, unsigned int data, Format &fmt)
-{ _format_integer(out, data, fmt); }
-inline void
-format_integer(std::ostream &out, long data, Format &fmt)
-{ _format_integer(out, data, fmt); }
-inline void
-format_integer(std::ostream &out, unsigned long data, Format &fmt)
-{ _format_integer(out, data, fmt); }
-inline void
-format_integer(std::ostream &out, long long data, Format &fmt)
-{ _format_integer(out, data, fmt); }
-inline void
-format_integer(std::ostream &out, unsigned long long data, Format &fmt)
-{ _format_integer(out, data, fmt); }
-#endif
-
-//
-// floating point formats
-//
-template <typename T>
-inline void
-format_float(std::ostream &out, const T &data, Format &fmt)
-{ out << "<bad arg type for float format>"; }
-
-inline void
-format_float(std::ostream &out, float data, Format &fmt)
-{ _format_float(out, data, fmt); }
-
-inline void
-format_float(std::ostream &out, double data, Format &fmt)
-{ _format_float(out, data, fmt); }
-
-//
-// string formats
-//
-template <typename T>
-inline void
-format_string(std::ostream &out, const T &data, Format &fmt)
-{ _format_string(out, data, fmt); }
-
-inline void
-format_string(std::ostream &out, const std::stringstream &data, Format &fmt)
-{ _format_string(out, data.str(), fmt); }
-
-#endif // __CPRINTF_FORMATS_HH__
diff --git a/base/crc.cc b/base/crc.cc
deleted file mode 100644
index 87963ef14..000000000
--- a/base/crc.cc
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright (c) 1988, 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. 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.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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 <sstream>
-#include <string>
-
-#include "sim/host.hh"
-#include "base/crc.hh"
-
-#define ETHER_CRC_POLY_LE 0xedb88320
-#define ETHER_CRC_POLY_BE 0x04c11db6
-
-#if 0
-/*
- * This is for reference. We have a table-driven version
- * of the little-endian crc32 generator, which is faster
- * than the double-loop.
- */
-uint32_t
-crc32le(const uint8_t *buf, size_t len)
-{
- uint32_t c, crc, carry;
- size_t i, j;
-
- crc = 0xffffffffU; /* initial value */
-
- for (i = 0; i < len; i++) {
- c = buf[i];
- for (j = 0; j < 8; j++) {
- carry = ((crc & 0x01) ? 1 : 0) ^ (c & 0x01);
- crc >>= 1;
- c >>= 1;
- if (carry)
- crc = (crc ^ ETHER_CRC_POLY_LE);
- }
- }
-
- return (crc);
-}
-#else
-uint32_t
-crc32le(const uint8_t *buf, size_t len)
-{
- static const uint32_t crctab[] = {
- 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
- 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
- 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
- 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
- };
- uint32_t crc;
- int i;
-
- crc = 0xffffffffU; /* initial value */
-
- for (i = 0; i < len; i++) {
- crc ^= buf[i];
- crc = (crc >> 4) ^ crctab[crc & 0xf];
- crc = (crc >> 4) ^ crctab[crc & 0xf];
- }
-
- return (crc);
-}
-#endif
-
-uint32_t
-crc32be(const uint8_t *buf, size_t len)
-{
- uint32_t c, crc, carry;
- size_t i, j;
-
- crc = 0xffffffffU; /* initial value */
-
- for (i = 0; i < len; i++) {
- c = buf[i];
- for (j = 0; j < 8; j++) {
- carry = ((crc & 0x80000000U) ? 1 : 0) ^ (c & 0x01);
- crc <<= 1;
- c >>= 1;
- if (carry)
- crc = (crc ^ ETHER_CRC_POLY_BE) | carry;
- }
- }
-
- return (crc);
-}
diff --git a/base/hostinfo.cc b/base/hostinfo.cc
deleted file mode 100644
index d15e3ddc1..000000000
--- a/base/hostinfo.cc
+++ /dev/null
@@ -1,86 +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 <ctype.h>
-#include <errno.h>
-#include <math.h>
-#include <unistd.h>
-
-#include <cstdio>
-#include <cstdlib>
-#include <cstring>
-#include <string>
-
-#include "base/misc.hh"
-#include "sim/host.hh"
-
-using namespace std;
-
-string
-__get_hostname()
-{
- char host[256];
- if (gethostname(host, sizeof host) == -1)
- warn("could not get host name!");
- return host;
-}
-
-string &
-hostname()
-{
- static string hostname = __get_hostname();
- return hostname;
-}
-
-uint64_t
-procInfo(char *filename, char *target)
-{
- int done = 0;
- char line[80];
- char format[80];
- long usage;
-
- FILE *fp = fopen(filename, "r");
-
- while (fp && !feof(fp) && !done) {
- if (fgets(line, 80, fp)) {
- if (strncmp(line, target, strlen(target)) == 0) {
- snprintf(format, sizeof(format), "%s %%ld", target);
- sscanf(line, format, &usage);
-
- fclose(fp);
- return usage ;
- }
- }
- }
-
- if (fp)
- fclose(fp);
-
- return 0;
-}
diff --git a/base/inet.cc b/base/inet.cc
deleted file mode 100644
index 2e1c4c84b..000000000
--- a/base/inet.cc
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * 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 <cstdio>
-#include <sstream>
-#include <string>
-
-#include "base/cprintf.hh"
-#include "sim/host.hh"
-#include "base/inet.hh"
-
-using namespace std;
-namespace Net {
-
-EthAddr::EthAddr()
-{
- memset(data, 0, ETH_ADDR_LEN);
-}
-
-EthAddr::EthAddr(const uint8_t ea[ETH_ADDR_LEN])
-{
- *data = *ea;
-}
-
-EthAddr::EthAddr(const eth_addr &ea)
-{
- *data = *ea.data;
-}
-
-EthAddr::EthAddr(const std::string &addr)
-{
- parse(addr);
-}
-
-const EthAddr &
-EthAddr::operator=(const eth_addr &ea)
-{
- *data = *ea.data;
- return *this;
-}
-
-const EthAddr &
-EthAddr::operator=(const std::string &addr)
-{
- parse(addr);
- return *this;
-}
-
-void
-EthAddr::parse(const std::string &addr)
-{
- // the hack below is to make sure that ETH_ADDR_LEN is 6 otherwise
- // the sscanf function won't work.
- int bytes[ETH_ADDR_LEN == 6 ? ETH_ADDR_LEN : -1];
- if (sscanf(addr.c_str(), "%x:%x:%x:%x:%x:%x", &bytes[0], &bytes[1],
- &bytes[2], &bytes[3], &bytes[4], &bytes[5]) != ETH_ADDR_LEN) {
- memset(data, 0xff, ETH_ADDR_LEN);
- return;
- }
-
- for (int i = 0; i < ETH_ADDR_LEN; ++i) {
- if (bytes[i] & ~0xff) {
- memset(data, 0xff, ETH_ADDR_LEN);
- return;
- }
-
- data[i] = bytes[i];
- }
-}
-
-string
-EthAddr::string() const
-{
- stringstream stream;
- stream << *this;
- return stream.str();
-}
-
-bool
-operator==(const EthAddr &left, const EthAddr &right)
-{
- return memcmp(left.bytes(), right.bytes(), ETH_ADDR_LEN);
-}
-
-ostream &
-operator<<(ostream &stream, const EthAddr &ea)
-{
- const uint8_t *a = ea.addr();
- ccprintf(stream, "%x:%x:%x:%x:%x:%x", a[0], a[1], a[2], a[3], a[4], a[5]);
- return stream;
-}
-
-uint16_t
-cksum(const IpPtr &ptr)
-{
- int sum = ip_cksum_add(ptr->bytes(), ptr->hlen(), 0);
- return ip_cksum_carry(sum);
-}
-
-uint16_t
-__tu_cksum(const IpPtr &ip)
-{
- int tcplen = ip->len() - ip->hlen();
- int sum = ip_cksum_add(ip->payload(), tcplen, 0);
- sum = ip_cksum_add(&ip->ip_src, 8, sum); // source and destination
- sum += htons(ip->ip_p + tcplen);
- return ip_cksum_carry(sum);
-}
-
-uint16_t
-cksum(const TcpPtr &tcp)
-{ return __tu_cksum(IpPtr(tcp.packet())); }
-
-uint16_t
-cksum(const UdpPtr &udp)
-{ return __tu_cksum(IpPtr(udp.packet())); }
-
-bool
-IpHdr::options(vector<const IpOpt *> &vec) const
-{
- vec.clear();
-
- const uint8_t *data = bytes() + sizeof(struct ip_hdr);
- int all = hlen() - sizeof(struct ip_hdr);
- while (all > 0) {
- const IpOpt *opt = (const IpOpt *)data;
- int len = opt->len();
- if (all < len)
- return false;
-
- vec.push_back(opt);
- all -= len;
- data += len;
- }
-
- return true;
-}
-
-bool
-TcpHdr::options(vector<const TcpOpt *> &vec) const
-{
- vec.clear();
-
- const uint8_t *data = bytes() + sizeof(struct tcp_hdr);
- int all = off() - sizeof(struct tcp_hdr);
- while (all > 0) {
- const TcpOpt *opt = (const TcpOpt *)data;
- int len = opt->len();
- if (all < len)
- return false;
-
- vec.push_back(opt);
- all -= len;
- data += len;
- }
-
- return true;
-}
-
-bool
-TcpOpt::sack(vector<SackRange> &vec) const
-{
- vec.clear();
-
- const uint8_t *data = bytes() + sizeof(struct tcp_hdr);
- int all = len() - offsetof(tcp_opt, opt_data.sack);
- while (all > 0) {
- const uint16_t *sack = (const uint16_t *)data;
- int len = sizeof(uint16_t) * 2;
- if (all < len) {
- vec.clear();
- return false;
- }
-
- vec.push_back(RangeIn(ntohs(sack[0]), ntohs(sack[1])));
- all -= len;
- data += len;
- }
-
- return false;
-}
-
-/* namespace Net */ }
diff --git a/base/inet.hh b/base/inet.hh
deleted file mode 100644
index e07e01935..000000000
--- a/base/inet.hh
+++ /dev/null
@@ -1,407 +0,0 @@
-/*
- * 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 __BASE_INET_HH__
-#define __BASE_INET_HH__
-
-#include <iosfwd>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include "base/range.hh"
-#include "dev/etherpkt.hh"
-#include "sim/host.hh"
-
-#include "dnet/os.h"
-#include "dnet/eth.h"
-#include "dnet/ip.h"
-#include "dnet/ip6.h"
-#include "dnet/addr.h"
-#include "dnet/arp.h"
-#include "dnet/icmp.h"
-#include "dnet/tcp.h"
-#include "dnet/udp.h"
-#include "dnet/intf.h"
-#include "dnet/route.h"
-#include "dnet/fw.h"
-#include "dnet/blob.h"
-#include "dnet/rand.h"
-
-namespace Net {
-
-/*
- * Ethernet Stuff
- */
-struct EthAddr : protected eth_addr
-{
- protected:
- void parse(const std::string &addr);
-
- public:
- EthAddr();
- EthAddr(const uint8_t ea[ETH_ADDR_LEN]);
- EthAddr(const eth_addr &ea);
- EthAddr(const std::string &addr);
- const EthAddr &operator=(const eth_addr &ea);
- const EthAddr &operator=(const std::string &addr);
-
- int size() const { return sizeof(eth_addr); }
-
- const uint8_t *bytes() const { return &data[0]; }
- uint8_t *bytes() { return &data[0]; }
-
- const uint8_t *addr() const { return &data[0]; }
- bool unicast() const { return data[0] == 0x00; }
- bool multicast() const { return data[0] == 0x01; }
- bool broadcast() const { return data[0] == 0xff; }
- std::string string() const;
-
- operator uint64_t() const
- {
- uint64_t reg = 0;
- reg |= ((uint64_t)data[0]) << 40;
- reg |= ((uint64_t)data[1]) << 32;
- reg |= ((uint64_t)data[2]) << 24;
- reg |= ((uint64_t)data[3]) << 16;
- reg |= ((uint64_t)data[4]) << 8;
- reg |= ((uint64_t)data[5]) << 0;
- return reg;
- }
-
-};
-
-std::ostream &operator<<(std::ostream &stream, const EthAddr &ea);
-bool operator==(const EthAddr &left, const EthAddr &right);
-
-struct EthHdr : public eth_hdr
-{
- uint16_t type() const { return ntohs(eth_type); }
- const EthAddr &src() const { return *(EthAddr *)&eth_src; }
- const EthAddr &dst() const { return *(EthAddr *)&eth_dst; }
-
- int size() const { return sizeof(eth_hdr); }
-
- const uint8_t *bytes() const { return (const uint8_t *)this; }
- const uint8_t *payload() const { return bytes() + size(); }
- uint8_t *bytes() { return (uint8_t *)this; }
- uint8_t *payload() { return bytes() + size(); }
-};
-
-class EthPtr
-{
- protected:
- friend class IpPtr;
- PacketPtr p;
-
- public:
- EthPtr() {}
- EthPtr(const PacketPtr &ptr) : p(ptr) { }
-
- EthHdr *operator->() { return (EthHdr *)p->data; }
- EthHdr &operator*() { return *(EthHdr *)p->data; }
- operator EthHdr *() { return (EthHdr *)p->data; }
-
- const EthHdr *operator->() const { return (const EthHdr *)p->data; }
- 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 PacketPtr packet() const { return p; }
- PacketPtr packet() { return p; }
- bool operator!() const { return !p; }
- operator bool() const { return p; }
-};
-
-/*
- * IP Stuff
- */
-struct IpOpt;
-struct IpHdr : public ip_hdr
-{
- uint8_t version() const { return ip_v; }
- uint8_t hlen() const { return ip_hl * 4; }
- uint8_t tos() const { return ip_tos; }
- uint16_t len() const { return ntohs(ip_len); }
- uint16_t id() const { return ntohs(ip_id); }
- uint16_t frag_flags() const { return ntohs(ip_off) >> 13; }
- uint16_t frag_off() const { return ntohs(ip_off) & 0x1fff; }
- uint8_t ttl() const { return ip_ttl; }
- uint8_t proto() const { return ip_p; }
- uint16_t sum() const { return ip_sum; }
- uint32_t src() const { return ntohl(ip_src); }
- uint32_t dst() const { return ntohl(ip_dst); }
-
- void sum(uint16_t sum) { ip_sum = sum; }
-
- bool options(std::vector<const IpOpt *> &vec) const;
-
- int size() const { return hlen(); }
- const uint8_t *bytes() const { return (const uint8_t *)this; }
- const uint8_t *payload() const { return bytes() + size(); }
- uint8_t *bytes() { return (uint8_t *)this; }
- uint8_t *payload() { return bytes() + size(); }
-};
-
-class IpPtr
-{
- protected:
- friend class TcpPtr;
- friend class UdpPtr;
- PacketPtr 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)
- {
- EthHdr *eth = (EthHdr *)ptr->data;
- if (eth->type() == ETH_TYPE_IP)
- p = ptr;
- else
- p = 0;
- }
-
- public:
- IpPtr() {}
- IpPtr(const PacketPtr &ptr) { set(ptr); }
- IpPtr(const EthPtr &ptr) { set(ptr.p); }
- IpPtr(const IpPtr &ptr) : p(ptr.p) { }
-
- IpHdr *operator->() { return h(); }
- IpHdr &operator*() { return *h(); }
- operator IpHdr *() { return h(); }
-
- const IpHdr *operator->() const { return h(); }
- 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 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; }
- bool operator!() const { return !p; }
- operator bool() const { return p; }
- operator bool() { return p; }
-};
-
-uint16_t cksum(const IpPtr &ptr);
-
-struct IpOpt : public ip_opt
-{
- uint8_t type() const { return opt_type; }
- uint8_t typeNumber() const { return IP_OPT_NUMBER(opt_type); }
- uint8_t typeClass() const { return IP_OPT_CLASS(opt_type); }
- uint8_t typeCopied() const { return IP_OPT_COPIED(opt_type); }
- uint8_t len() const { return IP_OPT_TYPEONLY(type()) ? 1 : opt_len; }
-
- bool isNumber(int num) const { return typeNumber() == IP_OPT_NUMBER(num); }
- bool isClass(int cls) const { return typeClass() == IP_OPT_CLASS(cls); }
- bool isCopied(int cpy) const { return typeCopied() == IP_OPT_COPIED(cpy); }
-
- const uint8_t *data() const { return opt_data.data8; }
- void sec(ip_opt_data_sec &sec) const;
- void lsrr(ip_opt_data_rr &rr) const;
- void ssrr(ip_opt_data_rr &rr) const;
- void ts(ip_opt_data_ts &ts) const;
- uint16_t satid() const { return ntohs(opt_data.satid); }
- uint16_t mtup() const { return ntohs(opt_data.mtu); }
- uint16_t mtur() const { return ntohs(opt_data.mtu); }
- void tr(ip_opt_data_tr &tr) const;
- const uint32_t *addext() const { return &opt_data.addext[0]; }
- uint16_t rtralt() const { return ntohs(opt_data.rtralt); }
- void sdb(std::vector<uint32_t> &vec) const;
-};
-
-/*
- * TCP Stuff
- */
-struct TcpOpt;
-struct TcpHdr : public tcp_hdr
-{
- uint16_t sport() const { return ntohs(th_sport); }
- uint16_t dport() const { return ntohs(th_dport); }
- uint32_t seq() const { return ntohl(th_seq); }
- uint32_t ack() const { return ntohl(th_ack); }
- uint8_t off() const { return th_off; }
- uint8_t flags() const { return th_flags & 0x3f; }
- uint16_t win() const { return ntohs(th_win); }
- uint16_t sum() const { return th_sum; }
- uint16_t urp() const { return ntohs(th_urp); }
-
- void sum(uint16_t sum) { th_sum = sum; }
-
- bool options(std::vector<const TcpOpt *> &vec) const;
-
- int size() const { return off(); }
- const uint8_t *bytes() const { return (const uint8_t *)this; }
- const uint8_t *payload() const { return bytes() + size(); }
- uint8_t *bytes() { return (uint8_t *)this; }
- uint8_t *payload() { return bytes() + size(); }
-};
-
-class TcpPtr
-{
- protected:
- PacketPtr 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 IpPtr &ptr)
- {
- if (ptr->proto() == IP_PROTO_TCP)
- set(ptr.p, sizeof(eth_hdr) + ptr->hlen());
- else
- set(0, 0);
- }
-
- public:
- TcpPtr() {}
- TcpPtr(const IpPtr &ptr) { set(ptr); }
- TcpPtr(const TcpPtr &ptr) : p(ptr.p), off(ptr.off) {}
-
- TcpHdr *operator->() { return h(); }
- TcpHdr &operator*() { return *h(); }
- operator TcpHdr *() { return h(); }
-
- const TcpHdr *operator->() const { return h(); }
- const TcpHdr &operator*() const { return *h(); }
- operator const TcpHdr *() const { return h(); }
-
- 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; }
- bool operator!() const { return !p; }
- operator bool() const { return p; }
- operator bool() { return p; }
-};
-
-uint16_t cksum(const TcpPtr &ptr);
-
-typedef Range<uint16_t> SackRange;
-
-struct TcpOpt : public tcp_opt
-{
- uint8_t type() const { return opt_type; }
- uint8_t len() const { return TCP_OPT_TYPEONLY(type()) ? 1 : opt_len; }
-
- bool isopt(int opt) const { return type() == opt; }
-
- const uint8_t *data() const { return opt_data.data8; }
-
- uint16_t mss() const { return ntohs(opt_data.mss); }
- uint8_t wscale() const { return opt_data.wscale; }
- bool sack(std::vector<SackRange> &vec) const;
- uint32_t echo() const { return ntohl(opt_data.echo); }
- uint32_t tsval() const { return ntohl(opt_data.timestamp[0]); }
- uint32_t tsecr() const { return ntohl(opt_data.timestamp[1]); }
- uint32_t cc() const { return ntohl(opt_data.cc); }
- uint8_t cksum() const{ return opt_data.cksum; }
- const uint8_t *md5() const { return opt_data.md5; }
-
- int size() const { return len(); }
- const uint8_t *bytes() const { return (const uint8_t *)this; }
- const uint8_t *payload() const { return bytes() + size(); }
- uint8_t *bytes() { return (uint8_t *)this; }
- uint8_t *payload() { return bytes() + size(); }
-};
-
-/*
- * UDP Stuff
- */
-struct UdpHdr : public udp_hdr
-{
- uint16_t sport() const { return ntohs(uh_sport); }
- uint16_t dport() const { return ntohs(uh_dport); }
- uint16_t len() const { return ntohs(uh_ulen); }
- uint16_t sum() const { return uh_sum; }
-
- void sum(uint16_t sum) { uh_sum = sum; }
-
- int size() const { return sizeof(udp_hdr); }
- const uint8_t *bytes() const { return (const uint8_t *)this; }
- const uint8_t *payload() const { return bytes() + size(); }
- uint8_t *bytes() { return (uint8_t *)this; }
- uint8_t *payload() { return bytes() + size(); }
-};
-
-class UdpPtr
-{
- protected:
- PacketPtr 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 IpPtr &ptr)
- {
- if (ptr->proto() == IP_PROTO_UDP)
- set(ptr.p, sizeof(eth_hdr) + ptr->hlen());
- else
- set(0, 0);
- }
-
- public:
- UdpPtr() {}
- UdpPtr(const IpPtr &ptr) { set(ptr); }
- UdpPtr(const UdpPtr &ptr) : p(ptr.p), off(ptr.off) {}
-
- UdpHdr *operator->() { return h(); }
- UdpHdr &operator*() { return *h(); }
- operator UdpHdr *() { return h(); }
-
- const UdpHdr *operator->() const { return h(); }
- const UdpHdr &operator*() const { return *h(); }
- operator const UdpHdr *() const { return h(); }
-
- 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; }
- bool operator!() const { return !p; }
- operator bool() const { return p; }
- operator bool() { return p; }
-};
-
-uint16_t cksum(const UdpPtr &ptr);
-
-/* namespace Net */ }
-
-#endif // __BASE_INET_HH__
diff --git a/base/intmath.hh b/base/intmath.hh
deleted file mode 100644
index df0687c62..000000000
--- a/base/intmath.hh
+++ /dev/null
@@ -1,230 +0,0 @@
-/*
- * Copyright (c) 2001, 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 __INTMATH_HH__
-#define __INTMATH_HH__
-
-#include <assert.h>
-
-#include "sim/host.hh"
-
-// Returns the prime number one less than n.
-int prevPrime(int n);
-
-// Determine if a number is prime
-template <class T>
-inline bool
-isPrime(T n)
-{
- T i;
-
- if (n == 2 || n == 3)
- return true;
-
- // Don't try every odd number to prove if it is a prime.
- // Toggle between every 2nd and 4th number.
- // (This is because every 6th odd number is divisible by 3.)
- for (i = 5; i*i <= n; i += 6) {
- if (((n % i) == 0 ) || ((n % (i + 2)) == 0) ) {
- return false;
- }
- }
-
- return true;
-}
-
-template <class T>
-inline T
-leastSigBit(T n)
-{
- return n & ~(n - 1);
-}
-
-template <class T>
-inline bool
-isPowerOf2(T n)
-{
- return n != 0 && leastSigBit(n) == n;
-}
-
-inline int
-floorLog2(unsigned x)
-{
- assert(x > 0);
-
- int y = 0;
-
- if (x & 0xffff0000) { y += 16; x >>= 16; }
- if (x & 0x0000ff00) { y += 8; x >>= 8; }
- if (x & 0x000000f0) { y += 4; x >>= 4; }
- if (x & 0x0000000c) { y += 2; x >>= 2; }
- if (x & 0x00000002) { y += 1; }
-
- return y;
-}
-
-inline int
-floorLog2(unsigned long x)
-{
- assert(x > 0);
-
- int y = 0;
-
-#if defined(__LP64__)
- if (x & ULL(0xffffffff00000000)) { y += 32; x >>= 32; }
-#endif
- if (x & 0xffff0000) { y += 16; x >>= 16; }
- if (x & 0x0000ff00) { y += 8; x >>= 8; }
- if (x & 0x000000f0) { y += 4; x >>= 4; }
- if (x & 0x0000000c) { y += 2; x >>= 2; }
- if (x & 0x00000002) { y += 1; }
-
- return y;
-}
-
-inline int
-floorLog2(unsigned long long x)
-{
- assert(x > 0);
-
- int y = 0;
-
- if (x & ULL(0xffffffff00000000)) { y += 32; x >>= 32; }
- if (x & ULL(0x00000000ffff0000)) { y += 16; x >>= 16; }
- if (x & ULL(0x000000000000ff00)) { y += 8; x >>= 8; }
- if (x & ULL(0x00000000000000f0)) { y += 4; x >>= 4; }
- if (x & ULL(0x000000000000000c)) { y += 2; x >>= 2; }
- if (x & ULL(0x0000000000000002)) { y += 1; }
-
- return y;
-}
-
-inline int
-floorLog2(int x)
-{
- assert(x > 0);
- return floorLog2((unsigned)x);
-}
-
-inline int
-floorLog2(long x)
-{
- assert(x > 0);
- return floorLog2((unsigned long)x);
-}
-
-inline int
-floorLog2(long long x)
-{
- assert(x > 0);
- return floorLog2((unsigned long long)x);
-}
-
-template <class T>
-inline int
-ceilLog2(T n)
-{
- if (n == 1)
- return 0;
-
- return floorLog2(n - (T)1) + 1;
-}
-
-template <class T>
-inline T
-floorPow2(T n)
-{
- return (T)1 << floorLog2(n);
-}
-
-template <class T>
-inline T
-ceilPow2(T n)
-{
- return (T)1 << ceilLog2(n);
-}
-
-template <class T>
-inline T
-divCeil(T a, T b)
-{
- return (a + b - 1) / b;
-}
-
-template <class T>
-inline T
-roundUp(T val, int align)
-{
- T mask = (T)align - 1;
- return (val + mask) & ~mask;
-}
-
-template <class T>
-inline T
-roundDown(T val, T align)
-{
- T mask = align - 1;
- return val & ~mask;
-}
-
-inline bool
-isHex(char c)
-{
- return c >= '0' && c <= '9' ||
- c >= 'A' && c <= 'F' ||
- c >= 'a' && c <= 'f';
-}
-
-inline bool
-isOct(char c)
-{
- return c >= '0' && c <= '7';
-}
-
-inline bool
-isDec(char c)
-{
- return c >= '0' && c <= '9';
-}
-
-inline int
-hex2Int(char c)
-{
- if (c >= '0' && c <= '9')
- return (c - '0');
-
- if (c >= 'A' && c <= 'F')
- return (c - 'A') + 10;
-
- if (c >= 'a' && c <= 'f')
- return (c - 'a') + 10;
-
- return 0;
-}
-
-#endif // __INTMATH_HH__
diff --git a/base/loader/aout_object.cc b/base/loader/aout_object.cc
deleted file mode 100644
index c81f7123f..000000000
--- a/base/loader/aout_object.cc
+++ /dev/null
@@ -1,114 +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 <string>
-
-#include "base/loader/aout_object.hh"
-
-#include "mem/functional/functional.hh"
-#include "base/loader/symtab.hh"
-
-#include "base/trace.hh" // for DPRINTF
-
-#include "base/loader/exec_aout.h"
-
-using namespace std;
-
-ObjectFile *
-AoutObject::tryFile(const string &fname, int fd, size_t len, uint8_t *data)
-{
- if (!N_BADMAG(*(aout_exechdr *)data)) {
- // right now this is only used for Alpha PAL code
- return new AoutObject(fname, fd, len, data,
- ObjectFile::Alpha, ObjectFile::UnknownOpSys);
- }
- else {
- return NULL;
- }
-}
-
-
-AoutObject::AoutObject(const string &_filename, int _fd,
- size_t _len, uint8_t *_data,
- Arch _arch, OpSys _opSys)
- : ObjectFile(_filename, _fd, _len, _data, _arch, _opSys)
-{
- execHdr = (aout_exechdr *)fileData;
-
- entry = execHdr->entry;
-
- text.baseAddr = N_TXTADDR(*execHdr);
- text.size = execHdr->tsize;
-
- data.baseAddr = N_DATADDR(*execHdr);
- data.size = execHdr->dsize;
-
- bss.baseAddr = N_BSSADDR(*execHdr);
- bss.size = execHdr->bsize;
-
- DPRINTFR(Loader, "text: 0x%x %d\ndata: 0x%x %d\nbss: 0x%x %d\n",
- text.baseAddr, text.size, data.baseAddr, data.size,
- bss.baseAddr, bss.size);
-}
-
-
-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
- return false;
-}
-
-bool
-AoutObject::loadLocalSymbols(SymbolTable *symtab)
-{
- // a.out symbols not supported yet
- return false;
-}
diff --git a/base/loader/aout_object.hh b/base/loader/aout_object.hh
deleted file mode 100644
index 1868192b2..000000000
--- a/base/loader/aout_object.hh
+++ /dev/null
@@ -1,58 +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.
- */
-
-#ifndef __AOUT_OBJECT_HH__
-#define __AOUT_OBJECT_HH__
-
-#include "base/loader/object_file.hh"
-
-// forward decls: avoid including exec_aout.h here
-struct aout_exechdr;
-
-class AoutObject : public ObjectFile
-{
- protected:
- aout_exechdr *execHdr;
-
- AoutObject(const std::string &_filename, int _fd,
- size_t _len, uint8_t *_data,
- Arch _arch, OpSys _opSys);
-
- public:
- virtual ~AoutObject() {}
-
- virtual bool loadSections(FunctionalMemory *mem,
- bool loadPhys = false);
- virtual bool loadGlobalSymbols(SymbolTable *symtab);
- virtual bool loadLocalSymbols(SymbolTable *symtab);
-
- static ObjectFile *tryFile(const std::string &fname, int fd,
- size_t len, uint8_t *data);
-};
-
-#endif // __AOUT_OBJECT_HH__
diff --git a/base/loader/coff_sym.h b/base/loader/coff_sym.h
deleted file mode 100644
index 734d96a98..000000000
--- a/base/loader/coff_sym.h
+++ /dev/null
@@ -1,489 +0,0 @@
-/*
- * Taken from binutils-2.14.90.0.5 include/coff/sym.h
- */
-
-/* Declarations of internal format of MIPS ECOFF symbols.
- Originally contributed by MIPS Computer Systems and Third Eye Software.
- Changes contributed by Cygnus Support are in the public domain.
-
- This file is just aggregated with the files that make up the GNU
- release; it is not considered part of GAS, GDB, or other GNU
- programs. */
-
-/*
- * |-----------------------------------------------------------|
- * | Copyright (c) 1992, 1991, 1990 MIPS Computer Systems, Inc.|
- * | MIPS Computer Systems, Inc. grants reproduction and use |
- * | rights to all parties, PROVIDED that this comment is |
- * | maintained in the copy. |
- * |-----------------------------------------------------------|
- */
-#ifndef _SYM_H
-#define _SYM_H
-
-/* (C) Copyright 1984 by Third Eye Software, Inc.
- *
- * Third Eye Software, Inc. grants reproduction and use rights to
- * all parties, PROVIDED that this comment is maintained in the copy.
- *
- * Third Eye makes no claims about the applicability of this
- * symbol table to a particular use.
- */
-
-/*
- * This file contains the definition of the Third Eye Symbol Table.
- *
- * Symbols are assumed to be in 'encounter order' - i.e. the order that
- * the things they represent were encountered by the compiler/assembler/loader.
- * EXCEPT for globals! These are assumed to be bunched together,
- * probably right after the last 'normal' symbol. Globals ARE sorted
- * in ascending order.
- *
- * -----------------------------------------------------------------------
- * A brief word about Third Eye naming/use conventions:
- *
- * All arrays and index's are 0 based.
- * All "ifooMax" values are the highest legal value PLUS ONE. This makes
- * them good for allocating arrays, etc. All checks are "ifoo < ifooMax".
- *
- * "isym" Index into the SYMbol table.
- * "ipd" Index into the Procedure Descriptor array.
- * "ifd" Index into the File Descriptor array.
- * "iss" Index into String Space.
- * "cb" Count of Bytes.
- * "rgPd" array whose domain is "0..ipdMax-1" and RanGe is PDR.
- * "rgFd" array whose domain is "0..ifdMax-1" and RanGe is FDR.
- */
-
-
-/*
- * Symbolic Header (HDR) structure.
- * As long as all the pointers are set correctly,
- * we don't care WHAT order the various sections come out in!
- *
- * A file produced solely for the use of CDB will probably NOT have
- * any instructions or data areas in it, as these are available
- * in the original.
- */
-
-typedef struct ecoff_symhdr {
- coff_short magic; /* to verify validity of the table */
- coff_short vstamp; /* version stamp */
- coff_int ilineMax; /* number of line number entries */
- coff_int idnMax; /* max index into dense number table */
- coff_int ipdMax; /* number of procedures */
- coff_int isymMax; /* number of local symbols */
- coff_int ioptMax; /* max index into optimization symbol entries */
- coff_int iauxMax; /* number of auxillary symbol entries */
- coff_int issMax; /* max index into local strings */
- coff_int issExtMax; /* max index into external strings */
- coff_int ifdMax; /* number of file descriptor entries */
- coff_int crfd; /* number of relative file descriptor entries */
- coff_int iextMax; /* max index into external symbols */
- coff_addr cbLine; /* number of bytes for line number entries */
- coff_addr cbLineOffset; /* offset to start of line number entries*/
- coff_addr cbDnOffset; /* offset to start dense number table */
- coff_addr cbPdOffset; /* offset to procedure descriptor table */
- coff_addr cbSymOffset; /* offset to start of local symbols*/
- coff_addr cbOptOffset; /* offset to optimization symbol entries */
- coff_addr cbAuxOffset; /* offset to start of auxillary symbol entries*/
- coff_addr cbSsOffset; /* offset to start of local strings */
- coff_addr cbSsExtOffset; /* offset to start of external strings */
- coff_addr cbFdOffset; /* offset to file descriptor table */
- coff_addr cbRfdOffset; /* offset to relative file descriptor table */
- coff_addr cbExtOffset; /* offset to start of external symbol entries*/
- /* If you add machine dependent fields, add them here */
-} HDRR, *pHDRR;
-#define cbHDRR sizeof(HDRR)
-#define hdrNil ((pHDRR)0)
-
-/*
- * The FDR and PDR structures speed mapping of address <-> name.
- * They are sorted in ascending memory order and are kept in
- * memory by CDB at runtime.
- */
-
-/*
- * File Descriptor
- *
- * There is one of these for EVERY FILE, whether compiled with
- * full debugging symbols or not. The name of a file should be
- * the path name given to the compiler. This allows the user
- * to simply specify the names of the directories where the COMPILES
- * were done, and we will be able to find their files.
- * A field whose comment starts with "R - " indicates that it will be
- * setup at runtime.
- */
-typedef struct ecoff_fdr {
- coff_addr adr; /* memory address of beginning of file */
- coff_addr cbLineOffset; /* byte offset from header for this file ln's */
- coff_addr cbLine; /* size of lines for this file */
- coff_addr cbSs; /* number of bytes in the ss */
- coff_int rss; /* file name (of source, if known) */
- coff_int issBase; /* file's string space */
- coff_int isymBase; /* beginning of symbols */
- coff_int csym; /* count file's of symbols */
- coff_int ilineBase; /* file's line symbols */
- coff_int cline; /* count of file's line symbols */
- coff_int ioptBase; /* file's optimization entries */
- coff_int copt; /* count of file's optimization entries */
- coff_int ipdFirst; /* start of procedures for this file */
- coff_int cpd; /* count of procedures for this file */
- coff_int iauxBase; /* file's auxiliary entries */
- coff_int caux; /* count of file's auxiliary entries */
- coff_int rfdBase; /* index into the file indirect table */
- coff_int crfd; /* count file indirect entries */
- unsigned lang: 5; /* language for this file */
- unsigned fMerge : 1; /* whether this file can be merged */
- unsigned fReadin : 1; /* true if it was read in (not just created) */
- unsigned fBigendian : 1;/* if set, was compiled on big endian machine */
- /* aux's will be in compile host's sex */
- unsigned glevel : 2; /* level this file was compiled with */
- unsigned reserved : 22; /* reserved for future use */
- coff_uint reserved2;
-} FDR, *pFDR;
-#define cbFDR sizeof(FDR)
-#define fdNil ((pFDR)0)
-#define ifdNil -1
-#define ifdTemp 0
-#define ilnNil -1
-
-
-/*
- * Procedure Descriptor
- *
- * There is one of these for EVERY TEXT LABEL.
- * If a procedure is in a file with full symbols, then isym
- * will point to the PROC symbols, else it will point to the
- * global symbol for the label.
- */
-
-typedef struct pdr {
- coff_addr adr; /* memory address of start of procedure */
- coff_addr cbLineOffset; /* byte offset for this procedure from the fd base */
- coff_int isym; /* start of local symbol entries */
- coff_int iline; /* start of line number entries*/
- coff_uint regmask; /* save register mask */
- coff_int regoffset; /* save register offset */
- coff_int iopt; /* start of optimization symbol entries*/
- coff_uint fregmask; /* save floating point register mask */
- coff_int fregoffset; /* save floating point register offset */
- coff_int frameoffset; /* frame size */
- coff_int lnLow; /* lowest line in the procedure */
- coff_int lnHigh; /* highest line in the procedure */
- /* These fields are new for 64 bit ECOFF. */
- unsigned gp_prologue : 8; /* byte size of GP prologue */
- unsigned gp_used : 1; /* true if the procedure uses GP */
- unsigned reg_frame : 1; /* true if register frame procedure */
- unsigned prof : 1; /* true if compiled with -pg */
- unsigned reserved : 13; /* reserved: must be zero */
- unsigned localoff : 8; /* offset of local variables from vfp */
- coff_short framereg; /* frame pointer register */
- coff_short pcreg; /* offset or reg of return pc */
-} PDR, *pPDR;
-#define cbPDR sizeof(PDR)
-#define pdNil ((pPDR) 0)
-#define ipdNil -1
-
-/*
- * The structure of the runtime procedure descriptor created by the loader
- * for use by the static exception system.
- */
-/*
- * If 0'd out because exception_info chokes Visual C++ and because there
- * don't seem to be any references to this structure elsewhere in gdb.
- */
-#if 0
-typedef struct runtime_pdr {
- coff_addr adr; /* memory address of start of procedure */
- coff_uint regmask; /* save register mask */
- coff_int regoffset; /* save register offset */
- coff_uint fregmask; /* save floating point register mask */
- coff_int fregoffset; /* save floating point register offset */
- coff_int frameoffset; /* frame size */
- coff_ushort framereg; /* frame pointer register */
- coff_ushort pcreg; /* offset or reg of return pc */
- coff_int irpss; /* index into the runtime string table */
- coff_uint reserved;
- struct exception_info *exception_info;/* pointer to exception array */
-} RPDR, *pRPDR;
-#define cbRPDR sizeof(RPDR)
-#define rpdNil ((pRPDR) 0)
-#endif
-
-/*
- * Line Numbers
- *
- * Line Numbers are segregated from the normal symbols because they
- * are [1] smaller , [2] are of no interest to your
- * average loader, and [3] are never needed in the middle of normal
- * scanning and therefore slow things down.
- *
- * By definition, the first LINER for any given procedure will have
- * the first line of a procedure and represent the first address.
- */
-
-typedef coff_int LINER, *pLINER;
-#define lineNil ((pLINER)0)
-#define cbLINER sizeof(LINER)
-#define ilineNil -1
-
-
-
-/*
- * The Symbol Structure (GFW, to those who Know!)
- */
-
-typedef struct ecoff_sym {
- coff_long value; /* value of symbol */
- coff_int iss; /* index into String Space of name */
- unsigned st : 6; /* symbol type */
- unsigned sc : 5; /* storage class - text, data, etc */
- unsigned reserved : 1; /* reserved */
- unsigned index : 20; /* index into sym/aux table */
-} SYMR, *pSYMR;
-#define symNil ((pSYMR)0)
-#define cbSYMR sizeof(SYMR)
-#define isymNil -1
-#define indexNil 0xfffff
-#define issNil -1
-#define issNull 0
-
-
-/* The following converts a memory resident string to an iss.
- * This hack is recognized in SbFIss, in sym.c of the debugger.
- */
-#define IssFSb(sb) (0x80000000 | ((coff_ulong)(sb)))
-
-/* E X T E R N A L S Y M B O L R E C O R D
- *
- * Same as the SYMR except it contains file context to determine where
- * the index is.
- */
-typedef struct ecoff_extsym {
- SYMR asym; /* symbol for the external */
- unsigned jmptbl:1; /* symbol is a jump table entry for shlibs */
- unsigned cobol_main:1; /* symbol is a cobol main procedure */
- unsigned weakext:1; /* symbol is weak external */
- unsigned reserved:29; /* reserved for future use */
- coff_int ifd; /* where the iss and index fields point into */
-} EXTR, *pEXTR;
-#define extNil ((pEXTR)0)
-#define cbEXTR sizeof(EXTR)
-
-
-/* A U X I L L A R Y T Y P E I N F O R M A T I O N */
-
-/*
- * Type Information Record
- */
-typedef struct {
- unsigned fBitfield : 1; /* set if bit width is specified */
- unsigned continued : 1; /* indicates additional TQ info in next AUX */
- unsigned bt : 6; /* basic type */
- unsigned tq4 : 4;
- unsigned tq5 : 4;
- /* ---- 16 bit boundary ---- */
- unsigned tq0 : 4;
- unsigned tq1 : 4; /* 6 type qualifiers - tqPtr, etc. */
- unsigned tq2 : 4;
- unsigned tq3 : 4;
-} TIR, *pTIR;
-#define cbTIR sizeof(TIR)
-#define tiNil ((pTIR)0)
-#define itqMax 6
-
-/*
- * Relative symbol record
- *
- * If the rfd field is 4095, the index field indexes into the global symbol
- * table.
- */
-
-typedef struct {
- unsigned rfd : 12; /* index into the file indirect table */
- unsigned index : 20; /* index int sym/aux/iss tables */
-} RNDXR, *pRNDXR;
-#define cbRNDXR sizeof(RNDXR)
-#define rndxNil ((pRNDXR)0)
-
-/* dense numbers or sometimes called block numbers are stored in this type,
- * a rfd of 0xffffffff is an index into the global table.
- */
-typedef struct {
- coff_uint rfd; /* index into the file table */
- coff_uint index; /* index int sym/aux/iss tables */
-} DNR, *pDNR;
-#define cbDNR sizeof(DNR)
-#define dnNil ((pDNR)0)
-
-
-
-/*
- * Auxillary information occurs only if needed.
- * It ALWAYS occurs in this order when present.
-
- isymMac used by stProc only
- TIR type info
- TIR additional TQ info (if first TIR was not enough)
- rndx if (bt == btStruct,btUnion,btEnum,btSet,btRange,
- btTypedef):
- rsym.index == iaux for btSet or btRange
- else rsym.index == isym
- dimLow btRange, btSet
- dimMac btRange, btSet
- rndx0 As many as there are tq arrays
- dimLow0
- dimHigh0
- ...
- rndxMax-1
- dimLowMax-1
- dimHighMax-1
- width in bits if (bit field), width in bits.
- */
-#define cAuxMax (6 + (idimMax*3))
-
-/* a union of all possible info in the AUX universe */
-typedef union {
- TIR ti; /* type information record */
- RNDXR rndx; /* relative index into symbol table */
- coff_int dnLow; /* low dimension */
- coff_int dnHigh; /* high dimension */
- coff_int isym; /* symbol table index (end of proc) */
- coff_int iss; /* index into string space (not used) */
- coff_int width; /* width for non-default sized struc fields */
- coff_int count; /* count of ranges for variant arm */
-} AUXU, *pAUXU;
-#define cbAUXU sizeof(AUXU)
-#define auxNil ((pAUXU)0)
-#define iauxNil -1
-
-
-/*
- * Optimization symbols
- *
- * Optimization symbols contain some overlap information with the normal
- * symbol table. In particular, the proc information
- * is somewhat redundant but necessary to easily find the other information
- * present.
- *
- * All of the offsets are relative to the beginning of the last otProc
- */
-
-typedef struct {
- unsigned ot: 8; /* optimization type */
- unsigned value: 24; /* address where we are moving it to */
- RNDXR rndx; /* points to a symbol or opt entry */
- coff_ulong offset; /* relative offset this occured */
-} OPTR, *pOPTR;
-#define optNil ((pOPTR) 0)
-#define cbOPTR sizeof(OPTR)
-#define ioptNil -1
-
-/*
- * File Indirect
- *
- * When a symbol is referenced across files the following procedure is used:
- * 1) use the file index to get the File indirect entry.
- * 2) use the file indirect entry to get the File descriptor.
- * 3) add the sym index to the base of that file's sym table
- *
- */
-
-typedef coff_long RFDT, *pRFDT;
-#define cbRFDT sizeof(RFDT)
-#define rfdNil -1
-
-/*
- * The file indirect table in the mips loader is known as an array of FITs.
- * This is done to keep the code in the loader readable in the area where
- * these tables are merged. Note this is only a name change.
- */
-typedef coff_int FIT, *pFIT;
-#define cbFIT sizeof(FIT)
-#define ifiNil -1
-#define fiNil ((pFIT) 0)
-
-#ifdef _LANGUAGE_PASCAL
-#define ifdNil -1
-#define ilnNil -1
-#define ipdNil -1
-#define ilineNil -1
-#define isymNil -1
-#define indexNil 16#fffff
-#define issNil -1
-#define issNull 0
-#define itqMax 6
-#define iauxNil -1
-#define ioptNil -1
-#define rfdNil -1
-#define ifiNil -1
-#endif /* _LANGUAGE_PASCAL */
-
-
-/* Dense numbers
- *
- * Rather than use file index, symbol index pairs to represent symbols
- * and globals, we use dense number so that they can be easily embeded
- * in intermediate code and the programs that process them can
- * use direct access tabls instead of hash table (which would be
- * necesary otherwise because of the sparse name space caused by
- * file index, symbol index pairs. Dense number are represented
- * by RNDXRs.
- */
-
-/*
- * The following table defines the meaning of each SYM field as
- * a function of the "st". (scD/B == scData OR scBss)
- *
- * Note: the value "isymMac" is used by symbols that have the concept
- * of enclosing a block of related information. This value is the
- * isym of the first symbol AFTER the end associated with the primary
- * symbol. For example if a procedure was at isym==90 and had an
- * isymMac==155, the associated end would be at isym==154, and the
- * symbol at 155 would probably (although not necessarily) be the
- * symbol for the next procedure. This allows rapid skipping over
- * internal information of various sorts. "stEnd"s ALWAYS have the
- * isym of the primary symbol that started the block.
- *
-
-ST SC VALUE INDEX
--------- ------ -------- ------
-stFile scText address isymMac
-stLabel scText address ---
-stGlobal scD/B address iaux
-stStatic scD/B address iaux
-stParam scAbs offset iaux
-stLocal scAbs offset iaux
-stProc scText address iaux (isymMac is first AUX)
-stStaticProc scText address iaux (isymMac is first AUX)
-
-stMember scNil ordinal --- (if member of enum)
- (mipsread thinks the case below has a bit, not byte, offset.)
-stMember scNil byte offset iaux (if member of struct/union)
-stMember scBits bit offset iaux (bit field spec)
-
-stBlock scText address isymMac (text block)
- (the code seems to think that rather than scNil, we see scInfo for
- the two cases below.)
-stBlock scNil cb isymMac (struct/union member define)
-stBlock scNil cMembers isymMac (enum member define)
-
- (New types added by SGI to simplify things:)
-stStruct scInfo cb isymMac (struct type define)
-stUnion scInfo cb isymMac (union type define)
-stEnum scInfo cMembers isymMac (enum type define)
-
-stEnd scText address isymStart
-stEnd scNil ------- isymStart (struct/union/enum)
-
-stTypedef scNil ------- iaux
-stRegReloc sc??? value old register number
-stForward sc??? new address isym to original symbol
-
-stConstant scInfo value --- (scalar)
-stConstant scInfo iss --- (complex, e.g. string)
-
- *
- */
-#endif
diff --git a/base/loader/coff_symconst.h b/base/loader/coff_symconst.h
deleted file mode 100644
index 87bace02d..000000000
--- a/base/loader/coff_symconst.h
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * Taken from binutils-2.14.90.0.5 include/coff/symconst.h
- */
-
-/* Declarations of constants for internal format of MIPS ECOFF symbols.
- Originally contributed by MIPS Computer Systems and Third Eye Software.
- Changes contributed by Cygnus Support are in the public domain.
-
- This file is just aggregated with the files that make up the GNU
- release; it is not considered part of GAS, GDB, or other GNU
- programs. */
-
-/*
- * |-----------------------------------------------------------|
- * | Copyright (c) 1992, 1991, 1990 MIPS Computer Systems, Inc.|
- * | MIPS Computer Systems, Inc. grants reproduction and use |
- * | rights to all parties, PROVIDED that this comment is |
- * | maintained in the copy. |
- * |-----------------------------------------------------------|
- */
-
-/* (C) Copyright 1984 by Third Eye Software, Inc.
- *
- * Third Eye Software, Inc. grants reproduction and use rights to
- * all parties, PROVIDED that this comment is maintained in the copy.
- *
- * Third Eye makes no claims about the applicability of this
- * symbol table to a particular use.
- */
-
-/* glevels for field in FDR */
-#define GLEVEL_0 2
-#define GLEVEL_1 1
-#define GLEVEL_2 0 /* for upward compat reasons. */
-#define GLEVEL_3 3
-
-/* magic number fo symheader */
-#define magicSym 0x7009
-/* The Alpha uses this value instead, for some reason. */
-#define magicSym2 0x1992
-
-/* Language codes */
-#define langC 0
-#define langPascal 1
-#define langFortran 2
-#define langAssembler 3 /* one Assembley inst might map to many mach */
-#define langMachine 4
-#define langNil 5
-#define langAda 6
-#define langPl1 7
-#define langCobol 8
-#define langStdc 9 /* FIXME: Collides with SGI langCplusplus */
-#define langCplusplus 9 /* FIXME: Collides with langStdc */
-#define langCplusplusV2 10 /* SGI addition */
-#define langMax 11 /* maximun allowed 32 -- 5 bits */
-
-/* The following are value definitions for the fields in the SYMR */
-
-/*
- * Storage Classes
- */
-
-#define scNil 0
-#define scText 1 /* text symbol */
-#define scData 2 /* initialized data symbol */
-#define scBss 3 /* un-initialized data symbol */
-#define scRegister 4 /* value of symbol is register number */
-#define scAbs 5 /* value of symbol is absolute */
-#define scUndefined 6 /* who knows? */
-#define scCdbLocal 7 /* variable's value is IN se->va.?? */
-#define scBits 8 /* this is a bit field */
-#define scCdbSystem 9 /* variable's value is IN CDB's address space */
-#define scDbx 9 /* overlap dbx internal use */
-#define scRegImage 10 /* register value saved on stack */
-#define scInfo 11 /* symbol contains debugger information */
-#define scUserStruct 12 /* address in struct user for current process */
-#define scSData 13 /* load time only small data */
-#define scSBss 14 /* load time only small common */
-#define scRData 15 /* load time only read only data */
-#define scVar 16 /* Var parameter (fortran,pascal) */
-#define scCommon 17 /* common variable */
-#define scSCommon 18 /* small common */
-#define scVarRegister 19 /* Var parameter in a register */
-#define scVariant 20 /* Variant record */
-#define scSUndefined 21 /* small undefined(external) data */
-#define scInit 22 /* .init section symbol */
-#define scBasedVar 23 /* Fortran or PL/1 ptr based var */
-#define scXData 24 /* exception handling data */
-#define scPData 25 /* Procedure section */
-#define scFini 26 /* .fini section */
-#define scRConst 27 /* .rconst section */
-#define scMax 32
-
-
-/*
- * Symbol Types
- */
-
-#define stNil 0 /* Nuthin' special */
-#define stGlobal 1 /* external symbol */
-#define stStatic 2 /* static */
-#define stParam 3 /* procedure argument */
-#define stLocal 4 /* local variable */
-#define stLabel 5 /* label */
-#define stProc 6 /* " " Procedure */
-#define stBlock 7 /* beginnning of block */
-#define stEnd 8 /* end (of anything) */
-#define stMember 9 /* member (of anything - struct/union/enum */
-#define stTypedef 10 /* type definition */
-#define stFile 11 /* file name */
-#define stRegReloc 12 /* register relocation */
-#define stForward 13 /* forwarding address */
-#define stStaticProc 14 /* load time only static procs */
-#define stConstant 15 /* const */
-#define stStaParam 16 /* Fortran static parameters */
- /* These new symbol types have been recently added to SGI machines. */
-#define stStruct 26 /* Beginning of block defining a struct type */
-#define stUnion 27 /* Beginning of block defining a union type */
-#define stEnum 28 /* Beginning of block defining an enum type */
-#define stIndirect 34 /* Indirect type specification */
- /* Pseudo-symbols - internal to debugger */
-#define stStr 60 /* string */
-#define stNumber 61 /* pure number (ie. 4 NOR 2+2) */
-#define stExpr 62 /* 2+2 vs. 4 */
-#define stType 63 /* post-coersion SER */
-#define stMax 64
-
-/* definitions for fields in TIR */
-
-/* type qualifiers for ti.tq0 -> ti.(itqMax-1) */
-#define tqNil 0 /* bt is what you see */
-#define tqPtr 1 /* pointer */
-#define tqProc 2 /* procedure */
-#define tqArray 3 /* duh */
-#define tqFar 4 /* longer addressing - 8086/8 land */
-#define tqVol 5 /* volatile */
-#define tqConst 6 /* const */
-#define tqMax 8
-
-/* basic types as seen in ti.bt */
-#define btNil 0 /* undefined (also, enum members) */
-#define btAdr 1 /* address - integer same size as pointer */
-#define btChar 2 /* character */
-#define btUChar 3 /* unsigned character */
-#define btShort 4 /* short */
-#define btUShort 5 /* unsigned short */
-#define btInt 6 /* int */
-#define btUInt 7 /* unsigned int */
-#define btLong 8 /* long */
-#define btULong 9 /* unsigned long */
-#define btFloat 10 /* float (real) */
-#define btDouble 11 /* Double (real) */
-#define btStruct 12 /* Structure (Record) */
-#define btUnion 13 /* Union (variant) */
-#define btEnum 14 /* Enumerated */
-#define btTypedef 15 /* defined via a typedef, isymRef points */
-#define btRange 16 /* subrange of int */
-#define btSet 17 /* pascal sets */
-#define btComplex 18 /* fortran complex */
-#define btDComplex 19 /* fortran double complex */
-#define btIndirect 20 /* forward or unnamed typedef */
-#define btFixedDec 21 /* Fixed Decimal */
-#define btFloatDec 22 /* Float Decimal */
-#define btString 23 /* Varying Length Character String */
-#define btBit 24 /* Aligned Bit String */
-#define btPicture 25 /* Picture */
-#define btVoid 26 /* void */
-#define btLongLong 27 /* long long */
-#define btULongLong 28 /* unsigned long long */
-#define btMax 64
diff --git a/base/loader/ecoff_object.cc b/base/loader/ecoff_object.cc
deleted file mode 100644
index 353a5f333..000000000
--- a/base/loader/ecoff_object.cc
+++ /dev/null
@@ -1,171 +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 <string>
-
-#include "base/loader/ecoff_object.hh"
-
-#include "mem/functional/functional.hh"
-#include "base/loader/symtab.hh"
-
-#include "base/trace.hh" // for DPRINTF
-
-#include "base/loader/exec_ecoff.h"
-#include "base/loader/coff_sym.h"
-#include "base/loader/coff_symconst.h"
-
-using namespace std;
-
-ObjectFile *
-EcoffObject::tryFile(const string &fname, int fd, size_t len, uint8_t *data)
-{
- if (((ecoff_filehdr *)data)->f_magic == ECOFF_MAGIC_ALPHA) {
- // it's Alpha ECOFF
- return new EcoffObject(fname, fd, len, data,
- ObjectFile::Alpha, ObjectFile::Tru64);
- }
- else {
- return NULL;
- }
-}
-
-
-EcoffObject::EcoffObject(const string &_filename, int _fd,
- size_t _len, uint8_t *_data,
- Arch _arch, OpSys _opSys)
- : ObjectFile(_filename, _fd, _len, _data, _arch, _opSys)
-{
- execHdr = (ecoff_exechdr *)fileData;
- fileHdr = &(execHdr->f);
- aoutHdr = &(execHdr->a);
-
- entry = aoutHdr->entry;
-
- text.baseAddr = aoutHdr->text_start;
- text.size = aoutHdr->tsize;
-
- data.baseAddr = aoutHdr->data_start;
- data.size = aoutHdr->dsize;
-
- bss.baseAddr = aoutHdr->bss_start;
- bss.size = aoutHdr->bsize;
-
- DPRINTFR(Loader, "text: 0x%x %d\ndata: 0x%x %d\nbss: 0x%x %d\n",
- text.baseAddr, text.size, data.baseAddr, data.size,
- bss.baseAddr, bss.size);
-}
-
-
-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)
- return false;
-
- if (fileHdr->f_magic != ECOFF_MAGIC_ALPHA) {
- warn("loadGlobalSymbols: wrong magic on %s\n", filename);
- return false;
- }
-
- ecoff_symhdr *syms = (ecoff_symhdr *)(fileData + fileHdr->f_symptr);
- if (syms->magic != magicSym2) {
- warn("loadGlobalSymbols: bad symbol header magic on %s\n", filename);
- return false;
- }
-
- ecoff_extsym *ext_syms = (ecoff_extsym *)(fileData + syms->cbExtOffset);
-
- char *ext_strings = (char *)(fileData + syms->cbSsExtOffset);
- for (int i = 0; i < syms->iextMax; i++) {
- ecoff_sym *entry = &(ext_syms[i].asym);
- if (entry->iss != -1)
- symtab->insert(entry->value, ext_strings + entry->iss);
- }
-
- return true;
-}
-
-bool
-EcoffObject::loadLocalSymbols(SymbolTable *symtab)
-{
- if (!symtab)
- return false;
-
- if (fileHdr->f_magic != ECOFF_MAGIC_ALPHA) {
- warn("loadGlobalSymbols: wrong magic on %s\n", filename);
- return false;
- }
-
- ecoff_symhdr *syms = (ecoff_symhdr *)(fileData + fileHdr->f_symptr);
- if (syms->magic != magicSym2) {
- warn("loadGlobalSymbols: bad symbol header magic on %s\n", filename);
- return false;
- }
-
- ecoff_sym *local_syms = (ecoff_sym *)(fileData + syms->cbSymOffset);
- char *local_strings = (char *)(fileData + syms->cbSsOffset);
- ecoff_fdr *fdesc = (ecoff_fdr *)(fileData + syms->cbFdOffset);
-
- for (int i = 0; i < syms->ifdMax; i++) {
- ecoff_sym *entry = (ecoff_sym *)(local_syms + fdesc[i].isymBase);
- char *strings = (char *)(local_strings + fdesc[i].issBase);
- for (int j = 0; j < fdesc[i].csym; j++) {
- if (entry[j].st == stGlobal || entry[j].st == stProc)
- if (entry[j].iss != -1)
- symtab->insert(entry[j].value, strings + entry[j].iss);
- }
- }
-
- for (int i = 0; i < syms->isymMax; i++) {
- ecoff_sym *entry = &(local_syms[i]);
- if (entry->st == stProc)
- symtab->insert(entry->value, local_strings + entry->iss);
- }
-
- return true;
-}
diff --git a/base/loader/ecoff_object.hh b/base/loader/ecoff_object.hh
deleted file mode 100644
index 78aa7f3f7..000000000
--- a/base/loader/ecoff_object.hh
+++ /dev/null
@@ -1,62 +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.
- */
-
-#ifndef __ECOFF_OBJECT_HH__
-#define __ECOFF_OBJECT_HH__
-
-#include "base/loader/object_file.hh"
-
-// forward decls: avoid including exec_ecoff.h here
-struct ecoff_exechdr;
-struct ecoff_filehdr;
-struct ecoff_aouthdr;
-
-class EcoffObject : public ObjectFile
-{
- protected:
- ecoff_exechdr *execHdr;
- ecoff_filehdr *fileHdr;
- ecoff_aouthdr *aoutHdr;
-
- EcoffObject(const std::string &_filename, int _fd,
- size_t _len, uint8_t *_data,
- Arch _arch, OpSys _opSys);
-
- public:
- virtual ~EcoffObject() {}
-
- virtual bool loadSections(FunctionalMemory *mem,
- bool loadPhys = false);
- virtual bool loadGlobalSymbols(SymbolTable *symtab);
- virtual bool loadLocalSymbols(SymbolTable *symtab);
-
- static ObjectFile *tryFile(const std::string &fname, int fd,
- size_t len, uint8_t *data);
-};
-
-#endif // __ECOFF_OBJECT_HH__
diff --git a/base/loader/elf_object.cc b/base/loader/elf_object.cc
deleted file mode 100644
index 791c6f6de..000000000
--- a/base/loader/elf_object.cc
+++ /dev/null
@@ -1,331 +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 <string>
-
-// Because of the -Wundef flag we have to do this
-#define __LIBELF_INTERNAL__ 0
-// counterintuitive, but the flag below causes libelf to define
-// 64-bit elf types that apparently didn't exist in some older
-// versions of Linux. They seem to be there in 2.4.x, so don't
-// set this now (it causes things to break on 64-bit platforms).
-#define __LIBELF64_LINUX 0
-#define __LIBELF_NEED_LINK_H 0
-#define __LIBELF_SYMBOL_VERSIONS 0
-
-#include "libelf/libelf.h"
-#include "libelf/gelf.h"
-
-#include "base/loader/elf_object.hh"
-
-#include "mem/functional/functional.hh"
-#include "base/loader/symtab.hh"
-
-#include "base/trace.hh" // for DPRINTF
-
-
-using namespace std;
-
-ObjectFile *
-ElfObject::tryFile(const string &fname, int fd, size_t len, uint8_t *data)
-{
- Elf *elf;
- GElf_Ehdr ehdr;
- Arch arch = UnknownArch;
- OpSys opSys = UnknownOpSys;
-
- // check that header matches library version
- if (elf_version(EV_CURRENT) == EV_NONE)
- panic("wrong elf version number!");
-
- // get a pointer to elf structure
- elf = elf_memory((char*)data,len);
- // will only fail if fd is invalid
- assert(elf != NULL);
-
- // Check that we actually have a elf file
- if (gelf_getehdr(elf, &ehdr) ==0) {
- DPRINTFR(Loader, "Not ELF\n");
- elf_end(elf);
- return NULL;
- }
- 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.
- if (ehdr.e_machine == EM_SPARC64 ||
- ehdr.e_machine == EM_SPARC ||
- ehdr.e_machine == EM_SPARCV9) {
- arch = ObjectFile::SPARC;
- } else if (ehdr.e_machine == EM_MIPS
- && ehdr.e_ident[EI_CLASS] == ELFCLASS32) {
- arch = ObjectFile::MIPS;
- } else if (ehdr.e_ident[EI_CLASS] == ELFCLASS64) {
- arch = ObjectFile::Alpha;
- } else {
- arch = ObjectFile::UnknownArch;
- }
-
- //Detect the operating system
- switch (ehdr.e_ident[EI_OSABI])
- {
-
- case ELFOSABI_LINUX:
- opSys = ObjectFile::Linux;
- break;
- case ELFOSABI_SOLARIS:
- opSys = ObjectFile::Solaris;
- break;
- case ELFOSABI_TRU64:
- opSys = ObjectFile::Tru64;
- break;
- default:
- opSys = ObjectFile::UnknownOpSys;
- }
-
- //take a look at the .note.ABI section
- //It can let us know what's what.
- if (opSys == ObjectFile::UnknownOpSys)
- {
- Elf_Scn *section;
- GElf_Shdr shdr;
- Elf_Data *data;
- uint32_t osAbi;;
- int secIdx = 1;
-
- // Get the first section
- section = elf_getscn(elf, secIdx);
-
- // While there are no more sections
- while (section != NULL) {
- gelf_getshdr(section, &shdr);
- if (shdr.sh_type == SHT_NOTE && !strcmp(".note.ABI-tag",
- elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name))) {
- // we have found a ABI note section
- // Check the 5th 32bit word for OS 0 == linux, 1 == hurd,
- // 2 == solaris, 3 == freebsd
- data = elf_rawdata(section, NULL);
- assert(data->d_buf);
- if(ehdr.e_ident[EI_DATA] == ELFDATA2LSB)
- osAbi = htole(((uint32_t*)data->d_buf)[4]);
- else
- osAbi = htobe(((uint32_t*)data->d_buf)[4]);
-
- switch(osAbi) {
- case 0:
- opSys = ObjectFile::Linux;
- break;
- case 2:
- opSys = ObjectFile::Solaris;
- break;
- }
- } // if section found
- section = elf_getscn(elf, ++secIdx);
- } // while sections
- }
- elf_end(elf);
- return new ElfObject(fname, fd, len, data, arch, opSys);
- }
-}
-
-
-ElfObject::ElfObject(const string &_filename, int _fd,
- size_t _len, uint8_t *_data,
- Arch _arch, OpSys _opSys)
- : ObjectFile(_filename, _fd, _len, _data, _arch, _opSys)
-
-{
- Elf *elf;
- GElf_Ehdr ehdr;
-
- // check that header matches library version
- if (elf_version(EV_CURRENT) == EV_NONE)
- panic("wrong elf version number!");
-
- // get a pointer to elf structure
- elf = elf_memory((char*)fileData,len);
- // will only fail if fd is invalid
- assert(elf != NULL);
-
- // Check that we actually have a elf file
- if (gelf_getehdr(elf, &ehdr) ==0) {
- panic("Not ELF, shouldn't be here");
- }
-
- entry = ehdr.e_entry;
-
- // initialize segment sizes to 0 in case they're not present
- text.size = data.size = bss.size = 0;
-
- for (int i = 0; i < ehdr.e_phnum; ++i) {
- GElf_Phdr phdr;
- if (gelf_getphdr(elf, i, &phdr) == 0) {
- panic("gelf_getphdr failed for section %d", i);
- }
-
- // for now we don't care about non-loadable segments
- if (!(phdr.p_type & PT_LOAD))
- continue;
-
- // the headers don't explicitly distinguish text from data,
- // but empirically the text segment comes first.
- 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;
- // 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
- data.baseAddr = phdr.p_vaddr;
- data.size = phdr.p_filesz;
- // remember where the data is for loadSections()
- fileDataBits = 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).
- if (phdr.p_memsz - phdr.p_filesz > 0 && bss.size != 0) {
- warn("Two implied bss segments in file!\n");
- }
- bss.size = phdr.p_memsz - phdr.p_filesz;
- bss.baseAddr = phdr.p_vaddr + phdr.p_filesz;
- }
- }
-
- // should have found at least one loadable segment
- assert(text.size != 0);
-
- DPRINTFR(Loader, "text: 0x%x %d\ndata: 0x%x %d\nbss: 0x%x %d\n",
- text.baseAddr, text.size, data.baseAddr, data.size,
- bss.baseAddr, bss.size);
-
- elf_end(elf);
-
- // We will actually read the sections when we need to load them
-}
-
-
-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;
- int sec_idx = 1; // there is a 0 but it is nothing, go figure
- Elf_Scn *section;
- GElf_Shdr shdr;
- Elf_Data *data;
- int count, ii;
- bool found = false;
- GElf_Sym sym;
-
- if (!symtab)
- return false;
-
- // check that header matches library version
- if (elf_version(EV_CURRENT) == EV_NONE)
- panic("wrong elf version number!");
-
- // get a pointer to elf structure
- elf = elf_memory((char*)fileData,len);
-
- assert(elf != NULL);
-
- // Get the first section
- section = elf_getscn(elf, sec_idx);
-
- // While there are no more sections
- while (section != NULL) {
- gelf_getshdr(section, &shdr);
-
- if (shdr.sh_type == SHT_SYMTAB) {
- found = true;
- data = elf_getdata(section, NULL);
- count = shdr.sh_size / shdr.sh_entsize;
- DPRINTF(Loader, "Found Symbol Table, %d symbols present\n", count);
-
- // loop through all the symbols, only loading global ones
- for (ii = 0; ii < count; ++ii) {
- gelf_getsym(data, ii, &sym);
- if (GELF_ST_BIND(sym.st_info) == binding) {
- symtab->insert(sym.st_value,
- elf_strptr(elf, shdr.sh_link, sym.st_name));
- }
- }
- }
- ++sec_idx;
- section = elf_getscn(elf, sec_idx);
- }
-
- elf_end(elf);
-
- return found;
-}
-
-bool
-ElfObject::loadGlobalSymbols(SymbolTable *symtab)
-{
- return loadSomeSymbols(symtab, STB_GLOBAL);
-}
-
-bool
-ElfObject::loadLocalSymbols(SymbolTable *symtab)
-{
- return loadSomeSymbols(symtab, STB_LOCAL);
-}
diff --git a/base/loader/elf_object.hh b/base/loader/elf_object.hh
deleted file mode 100644
index 66d8b3e63..000000000
--- a/base/loader/elf_object.hh
+++ /dev/null
@@ -1,60 +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.
- */
-
-#ifndef __ELF_OBJECT_HH__
-#define __ELF_OBJECT_HH__
-
-#include "base/loader/object_file.hh"
-
-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);
-
- ElfObject(const std::string &_filename, int _fd,
- size_t _len, uint8_t *_data,
- Arch _arch, OpSys _opSys);
-
- public:
- virtual ~ElfObject() {}
-
- virtual bool loadSections(FunctionalMemory *mem,
- bool loadPhys = false);
- virtual bool loadGlobalSymbols(SymbolTable *symtab);
- virtual bool loadLocalSymbols(SymbolTable *symtab);
-
- static ObjectFile *tryFile(const std::string &fname, int fd,
- size_t len, uint8_t *data);
-};
-
-#endif // __ELF_OBJECT_HH__
diff --git a/base/loader/object_file.cc b/base/loader/object_file.cc
deleted file mode 100644
index 1410d05b8..000000000
--- a/base/loader/object_file.cc
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright (c) 2002-2004 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <list>
-#include <string>
-
-#include <sys/types.h>
-#include <sys/mman.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <unistd.h>
-
-#include "base/cprintf.hh"
-#include "base/loader/object_file.hh"
-#include "base/loader/symtab.hh"
-
-#include "base/loader/ecoff_object.hh"
-#include "base/loader/aout_object.hh"
-#include "base/loader/elf_object.hh"
-
-using namespace std;
-
-ObjectFile::ObjectFile(const string &_filename, int _fd,
- size_t _len, uint8_t *_data,
- Arch _arch, OpSys _opSys)
- : filename(_filename), descriptor(_fd), fileData(_data), len(_len),
- arch(_arch), opSys(_opSys)
-{
-}
-
-
-ObjectFile::~ObjectFile()
-{
- close();
-}
-
-
-void
-ObjectFile::close()
-{
- if (descriptor >= 0) {
- ::close(descriptor);
- descriptor = -1;
- }
-
- if (fileData) {
- ::munmap(fileData, len);
- fileData = NULL;
- }
-}
-
-
-ObjectFile *
-createObjectFile(const string &fname)
-{
- // open the file
- int fd = open(fname.c_str(), O_RDONLY);
- if (fd < 0) {
- return NULL;
- }
-
- // find the length of the file by seeking to the end
- size_t len = (size_t)lseek(fd, 0, SEEK_END);
-
- // mmap the whole shebang
- uint8_t *fileData =
- (uint8_t *)mmap(NULL, len, PROT_READ, MAP_SHARED, fd, 0);
- if (fileData == MAP_FAILED) {
- close(fd);
- return NULL;
- }
-
- ObjectFile *fileObj = NULL;
-
- // figure out what we have here
- if ((fileObj = EcoffObject::tryFile(fname, fd, len, fileData)) != NULL) {
- return fileObj;
- }
-
- if ((fileObj = AoutObject::tryFile(fname, fd, len, fileData)) != NULL) {
- return fileObj;
- }
-
- if ((fileObj = ElfObject::tryFile(fname, fd, len, fileData)) != NULL) {
- return fileObj;
- }
-
- // don't know what it is
- close(fd);
- munmap(fileData, len);
- return NULL;
-}
diff --git a/base/loader/object_file.hh b/base/loader/object_file.hh
deleted file mode 100644
index 1b44ae14f..000000000
--- a/base/loader/object_file.hh
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright (c) 2002-2004 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __OBJECT_FILE_HH__
-#define __OBJECT_FILE_HH__
-
-#include <string>
-
-#include "sim/host.hh" // for Addr
-
-class FunctionalMemory;
-class SymbolTable;
-
-class ObjectFile
-{
- public:
-
- enum Arch {
- UnknownArch,
- Alpha,
- SPARC,
- MIPS
- };
-
- enum OpSys {
- UnknownOpSys,
- Tru64,
- Linux,
- Solaris
- };
-
- protected:
- const std::string filename;
- int descriptor;
- uint8_t *fileData;
- size_t len;
-
- Arch arch;
- OpSys opSys;
-
- ObjectFile(const std::string &_filename, int _fd,
- size_t _len, uint8_t *_data,
- Arch _arch, OpSys _opSys);
-
- public:
- virtual ~ObjectFile();
-
- void close();
-
- virtual bool loadSections(FunctionalMemory *mem,
- bool loadPhys = false) = 0;
- virtual bool loadGlobalSymbols(SymbolTable *symtab) = 0;
- virtual bool loadLocalSymbols(SymbolTable *symtab) = 0;
-
- Arch getArch() const { return arch; }
- OpSys getOpSys() const { return opSys; }
-
- protected:
-
- struct Section {
- Addr baseAddr;
- size_t size;
- };
-
- Addr entry;
- Addr globalPtr;
-
- Section text;
- Section data;
- Section bss;
-
- public:
- Addr entryPoint() const { return entry; }
- Addr globalPointer() const { return globalPtr; }
-
- Addr textBase() const { return text.baseAddr; }
- Addr dataBase() const { return data.baseAddr; }
- Addr bssBase() const { return bss.baseAddr; }
-
- size_t textSize() const { return text.size; }
- size_t dataSize() const { return data.size; }
- size_t bssSize() const { return bss.size; }
-};
-
-ObjectFile *createObjectFile(const std::string &fname);
-
-
-#endif // __OBJECT_FILE_HH__
diff --git a/base/loader/symtab.hh b/base/loader/symtab.hh
deleted file mode 100644
index ebcda1345..000000000
--- a/base/loader/symtab.hh
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * 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 __SYMTAB_HH__
-#define __SYMTAB_HH__
-
-#include <iosfwd>
-#include <map>
-
-#include "arch/isa_traits.hh" // for Addr
-
-class Checkpoint;
-class SymbolTable
-{
- public:
- typedef std::map<Addr, std::string> ATable;
- typedef std::map<std::string, Addr> STable;
-
- private:
- ATable addrTable;
- STable symbolTable;
-
- private:
- bool
- upperBound(Addr addr, ATable::const_iterator &iter) const
- {
- // find first key *larger* than desired address
- iter = addrTable.upper_bound(addr);
-
- // if very first key is larger, we're out of luck
- if (iter == addrTable.begin())
- return false;
-
- return true;
- }
-
- public:
- SymbolTable() {}
- SymbolTable(const std::string &file) { load(file); }
- ~SymbolTable() {}
-
- void clear();
- bool insert(Addr address, std::string symbol);
- bool load(const std::string &file);
-
- const ATable &getAddrTable() const { return addrTable; }
- const STable &getSymbolTable() const { return symbolTable; }
-
- public:
- void serialize(const std::string &base, std::ostream &os);
- void unserialize(const std::string &base, Checkpoint *cp,
- const std::string &section);
-
- public:
- bool
- findSymbol(Addr address, std::string &symbol) const
- {
- ATable::const_iterator i = addrTable.find(address);
- if (i == addrTable.end())
- return false;
-
- symbol = (*i).second;
- return true;
- }
-
- bool
- findAddress(const std::string &symbol, Addr &address) const
- {
- STable::const_iterator i = symbolTable.find(symbol);
- if (i == symbolTable.end())
- return false;
-
- address = (*i).second;
- return true;
- }
-
- /// Find the nearest symbol equal to or less than the supplied
- /// address (e.g., the label for the enclosing function).
- /// @param address The address to look up.
- /// @param symbol Return reference for symbol string.
- /// @param sym_address Return reference for symbol address.
- /// @param next_sym_address Address of following symbol (for
- /// determining valid range of symbol).
- /// @retval True if a symbol was found.
- bool
- findNearestSymbol(Addr addr, std::string &symbol, Addr &symaddr,
- Addr &nextaddr) const
- {
- ATable::const_iterator i;
- if (!upperBound(addr, i))
- return false;
-
- nextaddr = i->first;
- --i;
- symaddr = i->first;
- symbol = i->second;
- return true;
- }
-
- /// Overload for findNearestSymbol() for callers who don't care
- /// about next_sym_address.
- bool
- findNearestSymbol(Addr addr, std::string &symbol, Addr &symaddr) const
- {
- ATable::const_iterator i;
- if (!upperBound(addr, i))
- return false;
-
- --i;
- symaddr = i->first;
- symbol = i->second;
- return true;
- }
-
-
- bool
- findNearestAddr(Addr addr, Addr &symaddr, Addr &nextaddr) const
- {
- ATable::const_iterator i;
- if (!upperBound(addr, i))
- return false;
-
- nextaddr = i->first;
- --i;
- symaddr = i->first;
- return true;
- }
-
- bool
- findNearestAddr(Addr addr, Addr &symaddr) const
- {
- ATable::const_iterator i;
- if (!upperBound(addr, i))
- return false;
-
- --i;
- symaddr = i->first;
- return true;
- }
-};
-
-/// Global unified debugging symbol table (for target). Conceptually
-/// there should be one of these per System object for full system,
-/// and per Process object for non-full-system, but so far one big
-/// global one has worked well enough.
-extern SymbolTable *debugSymbolTable;
-
-#endif // __SYMTAB_HH__
diff --git a/base/remote_gdb.cc b/base/remote_gdb.cc
deleted file mode 100644
index 84093459c..000000000
--- a/base/remote_gdb.cc
+++ /dev/null
@@ -1,1232 +0,0 @@
-/*
- * 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.
- */
-
-/*
- * Copyright (c) 1990, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This software was developed by the Computer Systems Engineering group
- * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
- * contributed to Berkeley.
- *
- * All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Lawrence Berkeley Laboratories.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. 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.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
- *
- * @(#)kgdb_stub.c 8.4 (Berkeley) 1/12/94
- */
-
-/*-
- * Copyright (c) 2001 The NetBSD Foundation, Inc.
- * All rights reserved.
- *
- * This code is derived from software contributed to The NetBSD Foundation
- * by Jason R. Thorpe.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. 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.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the NetBSD
- * Foundation, Inc. and its contributors.
- * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
- */
-
-/*
- * $NetBSD: kgdb_stub.c,v 1.8 2001/07/07 22:58:00 wdk Exp $
- *
- * Taken from NetBSD
- *
- * "Stub" to allow remote cpu to debug over a serial line using gdb.
- */
-
-#include <sys/signal.h>
-
-#include <cstdio>
-#include <string>
-#include <unistd.h>
-
-#include "base/intmath.hh"
-#include "base/kgdb.h"
-#include "base/remote_gdb.hh"
-#include "base/socket.hh"
-#include "base/trace.hh"
-#include "cpu/exec_context.hh"
-#include "cpu/static_inst.hh"
-#include "mem/functional/physical.hh"
-#include "sim/system.hh"
-#include "arch/vtophys.hh"
-
-using namespace std;
-using namespace TheISA;
-
-#ifndef NDEBUG
-vector<RemoteGDB *> debuggers;
-int current_debugger = -1;
-
-void
-debugger()
-{
- if (current_debugger >= 0 && current_debugger < debuggers.size()) {
- RemoteGDB *gdb = debuggers[current_debugger];
- if (!gdb->isattached())
- gdb->listener->accept();
- if (gdb->isattached())
- gdb->trap(ALPHA_KENTRY_IF);
- }
-}
-#endif
-
-///////////////////////////////////////////////////////////
-//
-//
-//
-
-GDBListener::Event::Event(GDBListener *l, int fd, int e)
- : PollEvent(fd, e), listener(l)
-{}
-
-void
-GDBListener::Event::process(int revent)
-{
- listener->accept();
-}
-
-GDBListener::GDBListener(RemoteGDB *g, int p)
- : event(NULL), gdb(g), port(p)
-{
- assert(!gdb->listener);
- gdb->listener = this;
-}
-
-GDBListener::~GDBListener()
-{
- if (event)
- delete event;
-}
-
-string
-GDBListener::name()
-{
- return gdb->name() + ".listener";
-}
-
-void
-GDBListener::listen()
-{
- while (!listener.listen(port, true)) {
- DPRINTF(GDBMisc, "Can't bind port %d\n", port);
- port++;
- }
-
- event = new Event(this, listener.getfd(), POLLIN);
- pollQueue.schedule(event);
-
-#ifndef NDEBUG
- gdb->number = debuggers.size();
- debuggers.push_back(gdb);
-#endif
-
-#ifndef NDEBUG
- ccprintf(cerr, "%d: %s: listening for remote gdb #%d on port %d\n",
- curTick, name(), gdb->number, port);
-#else
- ccprintf(cerr, "%d: %s: listening for remote gdb on port %d\n",
- curTick, name(), port);
-#endif
-}
-
-void
-GDBListener::accept()
-{
- if (!listener.islistening())
- panic("GDBListener::accept(): cannot accept if we're not listening!");
-
- int sfd = listener.accept(true);
-
- if (sfd != -1) {
- if (gdb->isattached())
- close(sfd);
- else
- gdb->attach(sfd);
- }
-}
-
-///////////////////////////////////////////////////////////
-//
-//
-//
-int digit2i(char);
-char i2digit(int);
-void mem2hex(void *, const void *, int);
-const char *hex2mem(void *, const char *, int);
-Addr hex2i(const char **);
-
-RemoteGDB::Event::Event(RemoteGDB *g, int fd, int e)
- : PollEvent(fd, e), gdb(g)
-{}
-
-void
-RemoteGDB::Event::process(int revent)
-{
- if (revent & POLLIN)
- gdb->trap(ALPHA_KENTRY_IF);
- else if (revent & POLLNVAL)
- gdb->detach();
-}
-
-RemoteGDB::RemoteGDB(System *_system, ExecContext *c)
- : event(NULL), listener(NULL), number(-1), fd(-1),
- active(false), attached(false),
- system(_system), pmem(_system->physmem), context(c)
-{
- memset(gdbregs, 0, sizeof(gdbregs));
-}
-
-RemoteGDB::~RemoteGDB()
-{
- if (event)
- delete event;
-}
-
-string
-RemoteGDB::name()
-{
- return system->name() + ".remote_gdb";
-}
-
-bool
-RemoteGDB::isattached()
-{ return attached; }
-
-void
-RemoteGDB::attach(int f)
-{
- fd = f;
-
- event = new Event(this, fd, POLLIN);
- pollQueue.schedule(event);
-
- attached = true;
- DPRINTFN("remote gdb attached\n");
-}
-
-void
-RemoteGDB::detach()
-{
- attached = false;
- close(fd);
- fd = -1;
-
- pollQueue.remove(event);
- DPRINTFN("remote gdb detached\n");
-}
-
-const char *
-gdb_command(char cmd)
-{
- switch (cmd) {
- case KGDB_SIGNAL: return "KGDB_SIGNAL";
- case KGDB_SET_BAUD: return "KGDB_SET_BAUD";
- case KGDB_SET_BREAK: return "KGDB_SET_BREAK";
- case KGDB_CONT: return "KGDB_CONT";
- case KGDB_ASYNC_CONT: return "KGDB_ASYNC_CONT";
- case KGDB_DEBUG: return "KGDB_DEBUG";
- case KGDB_DETACH: return "KGDB_DETACH";
- case KGDB_REG_R: return "KGDB_REG_R";
- case KGDB_REG_W: return "KGDB_REG_W";
- case KGDB_SET_THREAD: return "KGDB_SET_THREAD";
- case KGDB_CYCLE_STEP: return "KGDB_CYCLE_STEP";
- case KGDB_SIG_CYCLE_STEP: return "KGDB_SIG_CYCLE_STEP";
- case KGDB_KILL: return "KGDB_KILL";
- case KGDB_MEM_W: return "KGDB_MEM_W";
- case KGDB_MEM_R: return "KGDB_MEM_R";
- case KGDB_SET_REG: return "KGDB_SET_REG";
- case KGDB_READ_REG: return "KGDB_READ_REG";
- case KGDB_QUERY_VAR: return "KGDB_QUERY_VAR";
- case KGDB_SET_VAR: return "KGDB_SET_VAR";
- case KGDB_RESET: return "KGDB_RESET";
- case KGDB_STEP: return "KGDB_STEP";
- case KGDB_ASYNC_STEP: return "KGDB_ASYNC_STEP";
- case KGDB_THREAD_ALIVE: return "KGDB_THREAD_ALIVE";
- case KGDB_TARGET_EXIT: return "KGDB_TARGET_EXIT";
- case KGDB_BINARY_DLOAD: return "KGDB_BINARY_DLOAD";
- case KGDB_CLR_HW_BKPT: return "KGDB_CLR_HW_BKPT";
- case KGDB_SET_HW_BKPT: return "KGDB_SET_HW_BKPT";
- case KGDB_START: return "KGDB_START";
- case KGDB_END: return "KGDB_END";
- case KGDB_GOODP: return "KGDB_GOODP";
- case KGDB_BADP: return "KGDB_BADP";
- default: return "KGDB_UNKNOWN";
- }
-}
-
-///////////////////////////////////////////////////////////
-// RemoteGDB::acc
-//
-// Determine if the mapping at va..(va+len) is valid.
-//
-bool
-RemoteGDB::acc(Addr va, size_t len)
-{
- Addr last_va;
-
- va = TheISA::TruncPage(va);
- last_va = TheISA::RoundPage(va + len);
-
- do {
- if (TheISA::IsK0Seg(va)) {
- if (va < (TheISA::K0SegBase + pmem->size())) {
- DPRINTF(GDBAcc, "acc: Mapping is valid K0SEG <= "
- "%#x < K0SEG + size\n", va);
- return true;
- } else {
- DPRINTF(GDBAcc, "acc: Mapping invalid %#x > K0SEG + size\n",
- va);
- return false;
- }
- }
-
- /**
- * This code says that all accesses to palcode (instruction and data)
- * are valid since there isn't a va->pa mapping because palcode is
- * accessed physically. At some point this should probably be cleaned up
- * but there is no easy way to do it.
- */
-
- if (AlphaISA::PcPAL(va) || va < 0x10000)
- return true;
-
- Addr ptbr = context->readMiscReg(AlphaISA::IPR_PALtemp20);
- TheISA::PageTableEntry pte = kernel_pte_lookup(pmem, ptbr, va);
- if (!pte.valid()) {
- DPRINTF(GDBAcc, "acc: %#x pte is invalid\n", va);
- return false;
- }
- va += TheISA::PageBytes;
- } while (va < last_va);
-
- DPRINTF(GDBAcc, "acc: %#x mapping is valid\n", va);
- return true;
-}
-
-///////////////////////////////////////////////////////////
-// RemoteGDB::signal
-//
-// Translate a trap number into a Unix-compatible signal number.
-// (GDB only understands Unix signal numbers.)
-//
-int
-RemoteGDB::signal(int type)
-{
- switch (type) {
- case ALPHA_KENTRY_INT:
- return (SIGTRAP);
-
- case ALPHA_KENTRY_UNA:
- return (SIGBUS);
-
- case ALPHA_KENTRY_ARITH:
- return (SIGFPE);
-
- case ALPHA_KENTRY_IF:
- return (SIGILL);
-
- case ALPHA_KENTRY_MM:
- return (SIGSEGV);
-
- default:
- panic("unknown signal type");
- return 0;
- }
-}
-
-///////////////////////////////////////////////////////////
-// RemoteGDB::getregs
-//
-// Translate the kernel debugger register format into
-// the GDB register format.
-void
-RemoteGDB::getregs()
-{
- memset(gdbregs, 0, sizeof(gdbregs));
-
- gdbregs[KGDB_REG_PC] = context->readPC();
-
- // @todo: Currently this is very Alpha specific.
- if (AlphaISA::PcPAL(gdbregs[KGDB_REG_PC])) {
- for (int i = 0; i < TheISA::NumIntArchRegs; ++i) {
- gdbregs[i] = context->readIntReg(AlphaISA::reg_redir[i]);
- }
- } else {
- for (int i = 0; i < TheISA::NumIntArchRegs; ++i) {
- gdbregs[i] = context->readIntReg(i);
- }
- }
-
-#ifdef KGDB_FP_REGS
- for (int i = 0; i < TheISA::NumFloatArchRegs; ++i) {
- gdbregs[i + KGDB_REG_F0] = context->readFloatRegInt(i);
- }
-#endif
-}
-
-///////////////////////////////////////////////////////////
-// RemoteGDB::setregs
-//
-// Translate the GDB register format into the kernel
-// debugger register format.
-//
-void
-RemoteGDB::setregs()
-{
- // @todo: Currently this is very Alpha specific.
- if (AlphaISA::PcPAL(gdbregs[KGDB_REG_PC])) {
- for (int i = 0; i < TheISA::NumIntArchRegs; ++i) {
- context->setIntReg(AlphaISA::reg_redir[i], gdbregs[i]);
- }
- } else {
- for (int i = 0; i < TheISA::NumIntArchRegs; ++i) {
- context->setIntReg(i, gdbregs[i]);
- }
- }
-
-#ifdef KGDB_FP_REGS
- for (int i = 0; i < TheISA::NumFloatArchRegs; ++i) {
- context->setFloatRegInt(i, gdbregs[i + KGDB_REG_F0]);
- }
-#endif
- context->setPC(gdbregs[KGDB_REG_PC]);
-}
-
-void
-RemoteGDB::setTempBreakpoint(TempBreakpoint &bkpt, Addr addr)
-{
- DPRINTF(GDBMisc, "setTempBreakpoint: addr=%#x\n", addr);
-
- bkpt.address = addr;
- insertHardBreak(addr, 4);
-}
-
-void
-RemoteGDB::clearTempBreakpoint(TempBreakpoint &bkpt)
-{
- DPRINTF(GDBMisc, "setTempBreakpoint: addr=%#x\n",
- bkpt.address);
-
-
- removeHardBreak(bkpt.address, 4);
- bkpt.address = 0;
-}
-
-void
-RemoteGDB::clearSingleStep()
-{
- DPRINTF(GDBMisc, "clearSingleStep bt_addr=%#x nt_addr=%#x\n",
- takenBkpt.address, notTakenBkpt.address);
-
- if (takenBkpt.address != 0)
- clearTempBreakpoint(takenBkpt);
-
- if (notTakenBkpt.address != 0)
- clearTempBreakpoint(notTakenBkpt);
-}
-
-void
-RemoteGDB::setSingleStep()
-{
- Addr pc = context->readPC();
- Addr npc, bpc;
- bool set_bt = false;
-
- npc = pc + sizeof(MachInst);
-
- // User was stopped at pc, e.g. the instruction at pc was not
- // executed.
- MachInst inst = read<MachInst>(pc);
- StaticInstPtr si(inst);
- if (si->hasBranchTarget(pc, context, bpc)) {
- // Don't bother setting a breakpoint on the taken branch if it
- // is the same as the next pc
- if (bpc != npc)
- set_bt = true;
- }
-
- DPRINTF(GDBMisc, "setSingleStep bt_addr=%#x nt_addr=%#x\n",
- takenBkpt.address, notTakenBkpt.address);
-
- setTempBreakpoint(notTakenBkpt, npc);
-
- if (set_bt)
- setTempBreakpoint(takenBkpt, bpc);
-}
-
-/////////////////////////
-//
-//
-
-uint8_t
-RemoteGDB::getbyte()
-{
- uint8_t b;
- ::read(fd, &b, 1);
- return b;
-}
-
-void
-RemoteGDB::putbyte(uint8_t b)
-{
- ::write(fd, &b, 1);
-}
-
-// Send a packet to gdb
-void
-RemoteGDB::send(const char *bp)
-{
- const char *p;
- uint8_t csum, c;
-
- DPRINTF(GDBSend, "send: %s\n", bp);
-
- do {
- p = bp;
- putbyte(KGDB_START);
- for (csum = 0; (c = *p); p++) {
- putbyte(c);
- csum += c;
- }
- putbyte(KGDB_END);
- putbyte(i2digit(csum >> 4));
- putbyte(i2digit(csum));
- } while ((c = getbyte() & 0x7f) == KGDB_BADP);
-}
-
-// Receive a packet from gdb
-int
-RemoteGDB::recv(char *bp, int maxlen)
-{
- char *p;
- int c, csum;
- int len;
-
- do {
- p = bp;
- csum = len = 0;
- while ((c = getbyte()) != KGDB_START)
- ;
-
- while ((c = getbyte()) != KGDB_END && len < maxlen) {
- c &= 0x7f;
- csum += c;
- *p++ = c;
- len++;
- }
- csum &= 0xff;
- *p = '\0';
-
- if (len >= maxlen) {
- putbyte(KGDB_BADP);
- continue;
- }
-
- csum -= digit2i(getbyte()) * 16;
- csum -= digit2i(getbyte());
-
- if (csum == 0) {
- putbyte(KGDB_GOODP);
- // Sequence present?
- if (bp[2] == ':') {
- putbyte(bp[0]);
- putbyte(bp[1]);
- len -= 3;
- bcopy(bp + 3, bp, len);
- }
- break;
- }
- putbyte(KGDB_BADP);
- } while (1);
-
- DPRINTF(GDBRecv, "recv: %s: %s\n", gdb_command(*bp), bp);
-
- return (len);
-}
-
-// Read bytes from kernel address space for debugger.
-bool
-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);
- }
-
-#if TRACING_ON
- if (DTRACE(GDBRead)) {
- if (DTRACE(GDBExtra)) {
- char buf[1024];
- mem2hex(buf, d, s);
- DPRINTFNR(": %s\n", buf);
- } else
- DPRINTFNR("\n");
- }
-#endif
-
- return true;
-}
-
-// Write bytes to kernel address space for debugger.
-bool
-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;
- }
-
- if (DTRACE(GDBWrite)) {
- DPRINTFN("write: addr=%#x, size=%d", vaddr, size);
- if (DTRACE(GDBExtra)) {
- char buf[1024];
- mem2hex(buf, data, size);
- DPRINTFNR(": %s\n", buf);
- } else
- 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);
- }
-
-#ifdef IMB
- alpha_pal_imb();
-#endif
-
- return true;
-}
-
-
-PCEventQueue *RemoteGDB::getPcEventQueue()
-{
- return &system->pcEventQueue;
-}
-
-
-RemoteGDB::HardBreakpoint::HardBreakpoint(RemoteGDB *_gdb, Addr pc)
- : PCEvent(_gdb->getPcEventQueue(), "HardBreakpoint Event", pc),
- gdb(_gdb), refcount(0)
-{
- DPRINTF(GDBMisc, "creating hardware breakpoint at %#x\n", evpc);
-}
-
-void
-RemoteGDB::HardBreakpoint::process(ExecContext *xc)
-{
- DPRINTF(GDBMisc, "handling hardware breakpoint at %#x\n", pc());
-
- if (xc == gdb->context)
- gdb->trap(ALPHA_KENTRY_INT);
-}
-
-bool
-RemoteGDB::insertSoftBreak(Addr addr, size_t len)
-{
- if (len != sizeof(MachInst))
- panic("invalid length\n");
-
- return insertHardBreak(addr, len);
-}
-
-bool
-RemoteGDB::removeSoftBreak(Addr addr, size_t len)
-{
- if (len != sizeof(MachInst))
- panic("invalid length\n");
-
- return removeHardBreak(addr, len);
-}
-
-bool
-RemoteGDB::insertHardBreak(Addr addr, size_t len)
-{
- if (len != sizeof(MachInst))
- panic("invalid length\n");
-
- DPRINTF(GDBMisc, "inserting hardware breakpoint at %#x\n", addr);
-
- HardBreakpoint *&bkpt = hardBreakMap[addr];
- if (bkpt == 0)
- bkpt = new HardBreakpoint(this, addr);
-
- bkpt->refcount++;
-
- return true;
-}
-
-bool
-RemoteGDB::removeHardBreak(Addr addr, size_t len)
-{
- if (len != sizeof(MachInst))
- panic("invalid length\n");
-
- DPRINTF(GDBMisc, "removing hardware breakpoint at %#x\n", addr);
-
- break_iter_t i = hardBreakMap.find(addr);
- if (i == hardBreakMap.end())
- return false;
-
- HardBreakpoint *hbp = (*i).second;
- if (--hbp->refcount == 0) {
- delete hbp;
- hardBreakMap.erase(i);
- }
-
- return true;
-}
-
-const char *
-break_type(char c)
-{
- switch(c) {
- case '0': return "software breakpoint";
- case '1': return "hardware breakpoint";
- case '2': return "write watchpoint";
- case '3': return "read watchpoint";
- case '4': return "access watchpoint";
- default: return "unknown breakpoint/watchpoint";
- }
-}
-
-// This function does all command processing for interfacing to a
-// remote gdb. Note that the error codes are ignored by gdb at
-// present, but might eventually become meaningful. (XXX) It might
-// makes sense to use POSIX errno values, because that is what the
-// gdb/remote.c functions want to return.
-bool
-RemoteGDB::trap(int type)
-{
- uint64_t val;
- size_t datalen, len;
- char data[KGDB_BUFLEN + 1];
- char buffer[sizeof(gdbregs) * 2 + 256];
- char temp[KGDB_BUFLEN];
- const char *p;
- char command, subcmd;
- string var;
- bool ret;
-
- if (!attached)
- return false;
-
- DPRINTF(GDBMisc, "trap: PC=%#x NPC=%#x\n",
- context->readPC(), context->readNextPC());
-
- clearSingleStep();
-
- /*
- * The first entry to this function is normally through
- * a breakpoint trap in kgdb_connect(), in which case we
- * must advance past the breakpoint because gdb will not.
- *
- * On the first entry here, we expect that gdb is not yet
- * listening to us, so just enter the interaction loop.
- * After the debugger is "active" (connected) it will be
- * waiting for a "signaled" message from us.
- */
- if (!active)
- active = true;
- else
- // Tell remote host that an exception has occurred.
- snprintf((char *)buffer, sizeof(buffer), "S%02x", signal(type));
- send(buffer);
-
- // Stick frame regs into our reg cache.
- getregs();
-
- for (;;) {
- datalen = recv(data, sizeof(data));
- data[sizeof(data) - 1] = 0; // Sentinel
- command = data[0];
- subcmd = 0;
- p = data + 1;
- switch (command) {
-
- case KGDB_SIGNAL:
- // if this command came from a running gdb, answer it --
- // the other guy has no way of knowing if we're in or out
- // of this loop when he issues a "remote-signal".
- snprintf((char *)buffer, sizeof(buffer), "S%02x", signal(type));
- send(buffer);
- continue;
-
- case KGDB_REG_R:
- if (2 * sizeof(gdbregs) > sizeof(buffer))
- panic("buffer too small");
-
- mem2hex(buffer, gdbregs, sizeof(gdbregs));
- send(buffer);
- continue;
-
- case KGDB_REG_W:
- p = hex2mem(gdbregs, p, sizeof(gdbregs));
- if (p == NULL || *p != '\0')
- send("E01");
- else {
- setregs();
- send("OK");
- }
- continue;
-
-#if 0
- case KGDB_SET_REG:
- val = hex2i(&p);
- if (*p++ != '=') {
- send("E01");
- continue;
- }
- if (val < 0 && val >= KGDB_NUMREGS) {
- send("E01");
- continue;
- }
-
- gdbregs[val] = hex2i(&p);
- setregs();
- send("OK");
-
- continue;
-#endif
-
- case KGDB_MEM_R:
- val = hex2i(&p);
- if (*p++ != ',') {
- send("E02");
- continue;
- }
- len = hex2i(&p);
- if (*p != '\0') {
- send("E03");
- continue;
- }
- if (len > sizeof(buffer)) {
- send("E04");
- continue;
- }
- if (!acc(val, len)) {
- send("E05");
- continue;
- }
-
- if (read(val, (size_t)len, (char *)buffer)) {
- mem2hex(temp, buffer, len);
- send(temp);
- } else {
- send("E05");
- }
- continue;
-
- case KGDB_MEM_W:
- val = hex2i(&p);
- if (*p++ != ',') {
- send("E06");
- continue;
- }
- len = hex2i(&p);
- if (*p++ != ':') {
- send("E07");
- continue;
- }
- if (len > datalen - (p - data)) {
- send("E08");
- continue;
- }
- p = hex2mem(buffer, p, sizeof(buffer));
- if (p == NULL) {
- send("E09");
- continue;
- }
- if (!acc(val, len)) {
- send("E0A");
- continue;
- }
- if (write(val, (size_t)len, (char *)buffer))
- send("OK");
- else
- send("E0B");
- continue;
-
- case KGDB_SET_THREAD:
- subcmd = *p++;
- val = hex2i(&p);
- if (val == 0)
- send("OK");
- else
- send("E01");
- continue;
-
- case KGDB_DETACH:
- case KGDB_KILL:
- active = false;
- clearSingleStep();
- detach();
- goto out;
-
- case KGDB_ASYNC_CONT:
- subcmd = hex2i(&p);
- if (*p++ == ';') {
- val = hex2i(&p);
- context->setPC(val);
- context->setNextPC(val + sizeof(MachInst));
- }
- clearSingleStep();
- goto out;
-
- case KGDB_CONT:
- if (p - data < datalen) {
- val = hex2i(&p);
- context->setPC(val);
- context->setNextPC(val + sizeof(MachInst));
- }
- clearSingleStep();
- goto out;
-
- case KGDB_ASYNC_STEP:
- subcmd = hex2i(&p);
- if (*p++ == ';') {
- val = hex2i(&p);
- context->setPC(val);
- context->setNextPC(val + sizeof(MachInst));
- }
- setSingleStep();
- goto out;
-
- case KGDB_STEP:
- if (p - data < datalen) {
- val = hex2i(&p);
- context->setPC(val);
- context->setNextPC(val + sizeof(MachInst));
- }
- setSingleStep();
- goto out;
-
- case KGDB_CLR_HW_BKPT:
- subcmd = *p++;
- if (*p++ != ',') send("E0D");
- val = hex2i(&p);
- if (*p++ != ',') send("E0D");
- len = hex2i(&p);
-
- DPRINTF(GDBMisc, "clear %s, addr=%#x, len=%d\n",
- break_type(subcmd), val, len);
-
- ret = false;
-
- switch (subcmd) {
- case '0': // software breakpoint
- ret = removeSoftBreak(val, len);
- break;
-
- case '1': // hardware breakpoint
- ret = removeHardBreak(val, len);
- break;
-
- case '2': // write watchpoint
- case '3': // read watchpoint
- case '4': // access watchpoint
- default: // unknown
- send("");
- break;
- }
-
- send(ret ? "OK" : "E0C");
- continue;
-
- case KGDB_SET_HW_BKPT:
- subcmd = *p++;
- if (*p++ != ',') send("E0D");
- val = hex2i(&p);
- if (*p++ != ',') send("E0D");
- len = hex2i(&p);
-
- DPRINTF(GDBMisc, "set %s, addr=%#x, len=%d\n",
- break_type(subcmd), val, len);
-
- ret = false;
-
- switch (subcmd) {
- case '0': // software breakpoint
- ret = insertSoftBreak(val, len);
- break;
-
- case '1': // hardware breakpoint
- ret = insertHardBreak(val, len);
- break;
-
- case '2': // write watchpoint
- case '3': // read watchpoint
- case '4': // access watchpoint
- default: // unknown
- send("");
- break;
- }
-
- send(ret ? "OK" : "E0C");
- continue;
-
- case KGDB_QUERY_VAR:
- var = string(p, datalen - 1);
- if (var == "C")
- send("QC0");
- else
- send("");
- continue;
-
- case KGDB_SET_BAUD:
- case KGDB_SET_BREAK:
- case KGDB_DEBUG:
- case KGDB_CYCLE_STEP:
- case KGDB_SIG_CYCLE_STEP:
- case KGDB_READ_REG:
- case KGDB_SET_VAR:
- case KGDB_RESET:
- case KGDB_THREAD_ALIVE:
- case KGDB_TARGET_EXIT:
- case KGDB_BINARY_DLOAD:
- // Unsupported command
- DPRINTF(GDBMisc, "Unsupported command: %s\n",
- gdb_command(command));
- DDUMP(GDBMisc, (uint8_t *)data, datalen);
- send("");
- continue;
-
- default:
- // Unknown command.
- DPRINTF(GDBMisc, "Unknown command: %c(%#x)\n",
- command, command);
- send("");
- continue;
-
-
- }
- }
-
- out:
- return true;
-}
-
-// Convert a hex digit into an integer.
-// This returns -1 if the argument passed is no valid hex digit.
-int
-digit2i(char c)
-{
- if (c >= '0' && c <= '9')
- return (c - '0');
- else if (c >= 'a' && c <= 'f')
- return (c - 'a' + 10);
- else if (c >= 'A' && c <= 'F')
-
- return (c - 'A' + 10);
- else
- return (-1);
-}
-
-// Convert the low 4 bits of an integer into an hex digit.
-char
-i2digit(int n)
-{
- return ("0123456789abcdef"[n & 0x0f]);
-}
-
-// Convert a byte array into an hex string.
-void
-mem2hex(void *vdst, const void *vsrc, int len)
-{
- char *dst = (char *)vdst;
- const char *src = (const char *)vsrc;
-
- while (len--) {
- *dst++ = i2digit(*src >> 4);
- *dst++ = i2digit(*src++);
- }
- *dst = '\0';
-}
-
-// Convert an hex string into a byte array.
-// This returns a pointer to the character following the last valid
-// hex digit. If the string ends in the middle of a byte, NULL is
-// returned.
-const char *
-hex2mem(void *vdst, const char *src, int maxlen)
-{
- char *dst = (char *)vdst;
- int msb, lsb;
-
- while (*src && maxlen--) {
- msb = digit2i(*src++);
- if (msb < 0)
- return (src - 1);
- lsb = digit2i(*src++);
- if (lsb < 0)
- return (NULL);
- *dst++ = (msb << 4) | lsb;
- }
- return (src);
-}
-
-// Convert an hex string into an integer.
-// This returns a pointer to the character following the last valid
-// hex digit.
-Addr
-hex2i(const char **srcp)
-{
- const char *src = *srcp;
- Addr r = 0;
- int nibble;
-
- while ((nibble = digit2i(*src)) >= 0) {
- r *= 16;
- r += nibble;
- src++;
- }
- *srcp = src;
- return (r);
-}
-
diff --git a/base/statistics.cc b/base/statistics.cc
deleted file mode 100644
index c97564641..000000000
--- a/base/statistics.cc
+++ /dev/null
@@ -1,357 +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 <iomanip>
-#include <fstream>
-#include <list>
-#include <map>
-#include <string>
-#include <sstream>
-
-#include "base/callback.hh"
-#include "base/cprintf.hh"
-#include "base/hostinfo.hh"
-#include "base/misc.hh"
-#include "base/statistics.hh"
-#include "base/str.hh"
-#include "base/time.hh"
-#include "base/trace.hh"
-#include "base/stats/statdb.hh"
-#include "config/stats_binning.hh"
-
-using namespace std;
-
-namespace Stats {
-
-StatData *
-DataAccess::find() const
-{
- return Database::find(const_cast<void *>((const void *)this));
-}
-
-const StatData *
-getStatData(const void *stat)
-{
- return Database::find(const_cast<void *>(stat));
-}
-
-void
-DataAccess::map(StatData *data)
-{
- Database::regStat(this, data);
-}
-
-StatData *
-DataAccess::statData()
-{
- StatData *ptr = find();
- assert(ptr);
- return ptr;
-}
-
-const StatData *
-DataAccess::statData() const
-{
- const StatData *ptr = find();
- assert(ptr);
- return ptr;
-}
-
-void
-DataAccess::setInit()
-{
- statData()->flags |= init;
-}
-
-void
-DataAccess::setPrint()
-{
- Database::regPrint(this);
-}
-
-StatData::StatData()
- : flags(none), precision(-1), prereq(0)
-{
- static int count = 0;
- id = count++;
-}
-
-StatData::~StatData()
-{
-}
-
-bool
-StatData::less(StatData *stat1, StatData *stat2)
-{
- const string &name1 = stat1->name;
- const string &name2 = stat2->name;
-
- vector<string> v1;
- vector<string> v2;
-
- tokenize(v1, name1, '.');
- tokenize(v2, name2, '.');
-
- int last = min(v1.size(), v2.size()) - 1;
- for (int i = 0; i < last; ++i)
- if (v1[i] != v2[i])
- return v1[i] < v2[i];
-
- // Special compare for last element.
- if (v1[last] == v2[last])
- return v1.size() < v2.size();
- else
- return v1[last] < v2[last];
-
- return false;
-}
-
-bool
-StatData::baseCheck() const
-{
- if (!(flags & init)) {
-#ifdef DEBUG
- cprintf("this is stat number %d\n", id);
-#endif
- panic("Not all stats have been initialized");
- return false;
- }
-
- if ((flags & print) && name.empty()) {
- panic("all printable stats must be named");
- return false;
- }
-
- return true;
-}
-
-
-void
-FormulaBase::result(VResult &vec) const
-{
- if (root)
- vec = root->result();
-}
-
-Result
-FormulaBase::total() const
-{
- return root ? root->total() : 0.0;
-}
-
-size_t
-FormulaBase::size() const
-{
- if (!root)
- return 0;
- else
- return root->size();
-}
-
-bool
-FormulaBase::binned() const
-{
- return root && root->binned();
-}
-
-void
-FormulaBase::reset()
-{
-}
-
-bool
-FormulaBase::zero() const
-{
- VResult vec;
- result(vec);
- for (int i = 0; i < vec.size(); ++i)
- if (vec[i] != 0.0)
- return false;
- return true;
-}
-
-void
-FormulaBase::update(StatData *)
-{
-}
-
-string
-FormulaBase::str() const
-{
- return root ? root->str() : "";
-}
-
-Formula::Formula()
-{
- setInit();
-}
-
-Formula::Formula(Temp r)
-{
- root = r;
- assert(size());
-}
-
-const Formula &
-Formula::operator=(Temp r)
-{
- assert(!root && "Can't change formulas");
- root = r;
- assert(size());
- return *this;
-}
-
-const Formula &
-Formula::operator+=(Temp r)
-{
- if (root)
- root = NodePtr(new BinaryNode<std::plus<Result> >(root, r));
- else
- root = r;
- assert(size());
- return *this;
-}
-
-MainBin::MainBin(const string &name)
- : _name(name), mem(NULL), memsize(-1)
-{
- Database::regBin(this, name);
-}
-
-MainBin::~MainBin()
-{
- if (mem)
- delete [] mem;
-}
-
-char *
-MainBin::memory(off_t off)
-{
- if (memsize == -1)
- memsize = ceilPow2((size_t) offset());
-
- if (!mem) {
- mem = new char[memsize];
- memset(mem, 0, memsize);
- }
-
- assert(offset() <= size());
- return mem + off;
-}
-
-void
-check()
-{
- typedef Database::stat_list_t::iterator iter_t;
-
- iter_t i, end = Database::stats().end();
- for (i = Database::stats().begin(); i != end; ++i) {
- StatData *data = *i;
- assert(data);
- if (!data->check() || !data->baseCheck())
- panic("stat check failed for %s\n", data->name);
- }
-
- int j = 0;
- for (i = Database::stats().begin(); i != end; ++i) {
- StatData *data = *i;
- if (!(data->flags & print))
- data->name = "__Stat" + to_string(j++);
- }
-
- Database::stats().sort(StatData::less);
-
-#if STATS_BINNING
- if (MainBin::curBin() == NULL) {
- static MainBin mainBin("main bin");
- mainBin.activate();
- }
-#endif
-
- if (i == end)
- return;
-
- iter_t last = i;
- ++i;
-
- for (i = Database::stats().begin(); i != end; ++i) {
- if ((*i)->name == (*last)->name)
- panic("same name used twice! name=%s\n", (*i)->name);
-
- last = i;
- }
-}
-
-CallbackQueue resetQueue;
-
-void
-reset()
-{
- // reset non-binned stats
- Database::stat_list_t::iterator i = Database::stats().begin();
- Database::stat_list_t::iterator end = Database::stats().end();
- while (i != end) {
- StatData *data = *i;
- if (!data->binned())
- data->reset();
- ++i;
- }
-
- // save the bin so we can go back to where we were
- MainBin *orig = MainBin::curBin();
-
- // reset binned stats
- Database::bin_list_t::iterator bi = Database::bins().begin();
- Database::bin_list_t::iterator be = Database::bins().end();
- while (bi != be) {
- MainBin *bin = *bi;
- bin->activate();
-
- i = Database::stats().begin();
- while (i != end) {
- StatData *data = *i;
- if (data->binned())
- data->reset();
- ++i;
- }
- ++bi;
- }
-
- // restore bin
- MainBin::curBin() = orig;
-
- resetQueue.process();
-}
-
-void
-registerResetCallback(Callback *cb)
-{
- resetQueue.add(cb);
-}
-
-/* namespace Stats */ }
diff --git a/base/statistics.hh b/base/statistics.hh
deleted file mode 100644
index c46744cac..000000000
--- a/base/statistics.hh
+++ /dev/null
@@ -1,2897 +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.
- */
-
-/** @file
- * Declaration of Statistics objects.
- */
-
-/**
-* @todo
-*
-* Generalized N-dimensinal vector
-* documentation
-* key stats
-* interval stats
-* -- these both can use the same function that prints out a
-* specific set of stats
-* VectorStandardDeviation totals
-* Document Namespaces
-*/
-#ifndef __BASE_STATISTICS_HH__
-#define __BASE_STATISTICS_HH__
-
-#include <algorithm>
-#include <cassert>
-#include <cmath>
-#include <functional>
-#include <iosfwd>
-#include <sstream>
-#include <string>
-#include <vector>
-
-#include "base/cprintf.hh"
-#include "base/intmath.hh"
-#include "base/refcnt.hh"
-#include "base/str.hh"
-#include "base/stats/bin.hh"
-#include "base/stats/flags.hh"
-#include "base/stats/visit.hh"
-#include "base/stats/types.hh"
-#include "config/stats_binning.hh"
-#include "sim/host.hh"
-
-class Callback;
-
-/** The current simulated cycle. */
-extern Tick curTick;
-
-/* A namespace for all of the Statistics */
-namespace Stats {
-
-/* Contains the statistic implementation details */
-//////////////////////////////////////////////////////////////////////
-//
-// Statistics Framework Base classes
-//
-//////////////////////////////////////////////////////////////////////
-struct StatData
-{
- /** The name of the stat. */
- std::string name;
- /** The description of the stat. */
- std::string desc;
- /** The formatting flags. */
- StatFlags flags;
- /** The display precision. */
- int precision;
- /** A pointer to a prerequisite Stat. */
- const StatData *prereq;
- /**
- * A unique stat ID for each stat in the simulator.
- * Can be used externally for lookups as well as for debugging.
- */
- int id;
-
- StatData();
- virtual ~StatData();
-
- /**
- * @return true if the stat is binned.
- */
- virtual bool binned() const = 0;
-
- /**
- * Reset the corresponding stat to the default state.
- */
- virtual void reset() = 0;
-
- /**
- * @return true if this stat has a value and satisfies its
- * requirement as a prereq
- */
- virtual bool zero() const = 0;
-
- /**
- * Check that this stat has been set up properly and is ready for
- * use
- * @return true for success
- */
- virtual bool check() const = 0;
- bool baseCheck() const;
-
- /**
- * Visitor entry for outputing statistics data
- */
- virtual void visit(Visit &visitor) = 0;
-
- /**
- * Checks if the first stat's name is alphabetically less than the second.
- * This function breaks names up at periods and considers each subname
- * separately.
- * @param stat1 The first stat.
- * @param stat2 The second stat.
- * @return stat1's name is alphabetically before stat2's
- */
- static bool less(StatData *stat1, StatData *stat2);
-};
-
-class ScalarData : public StatData
-{
- public:
- virtual Counter value() const = 0;
- virtual Result result() const = 0;
- virtual Result total() const = 0;
- virtual void visit(Visit &visitor) { visitor.visit(*this); }
-};
-
-template <class Stat>
-class ScalarStatData : public ScalarData
-{
- protected:
- Stat &s;
-
- public:
- ScalarStatData(Stat &stat) : s(stat) {}
-
- virtual bool binned() const { return s.binned(); }
- virtual bool check() const { return s.check(); }
- virtual Counter value() const { return s.value(); }
- virtual Result result() const { return s.result(); }
- virtual Result total() const { return s.total(); }
- virtual void reset() { s.reset(); }
- virtual bool zero() const { return s.zero(); }
-};
-
-struct VectorData : public StatData
-{
- /** Names and descriptions of subfields. */
- mutable std::vector<std::string> subnames;
- mutable std::vector<std::string> subdescs;
-
- virtual size_t size() const = 0;
- virtual const VCounter &value() const = 0;
- virtual const VResult &result() const = 0;
- virtual Result total() const = 0;
- void update()
- {
- if (!subnames.empty()) {
- int s = size();
- if (subnames.size() < s)
- subnames.resize(s);
-
- if (subdescs.size() < s)
- subdescs.resize(s);
- }
- }
-};
-
-template <class Stat>
-class VectorStatData : public VectorData
-{
- protected:
- Stat &s;
- mutable VCounter cvec;
- mutable VResult rvec;
-
- public:
- VectorStatData(Stat &stat) : s(stat) {}
-
- virtual bool binned() const { return s.binned(); }
- virtual bool check() const { return s.check(); }
- virtual bool zero() const { return s.zero(); }
- virtual void reset() { s.reset(); }
-
- virtual size_t size() const { return s.size(); }
- virtual VCounter &value() const
- {
- s.value(cvec);
- return cvec;
- }
- virtual const VResult &result() const
- {
- s.result(rvec);
- return rvec;
- }
- virtual Result total() const { return s.total(); }
- virtual void visit(Visit &visitor)
- {
- update();
- s.update(this);
- visitor.visit(*this);
- }
-};
-
-struct DistDataData
-{
- Counter min_val;
- Counter max_val;
- Counter underflow;
- Counter overflow;
- VCounter cvec;
- Counter sum;
- Counter squares;
- Counter samples;
-
- Counter min;
- Counter max;
- Counter bucket_size;
- int size;
- bool fancy;
-};
-
-struct DistData : public StatData
-{
- /** Local storage for the entry values, used for printing. */
- DistDataData data;
-};
-
-template <class Stat>
-class DistStatData : public DistData
-{
- protected:
- Stat &s;
-
- public:
- DistStatData(Stat &stat) : s(stat) {}
-
- virtual bool binned() const { return s.binned(); }
- virtual bool check() const { return s.check(); }
- virtual void reset() { s.reset(); }
- virtual bool zero() const { return s.zero(); }
- virtual void visit(Visit &visitor)
- {
- s.update(this);
- visitor.visit(*this);
- }
-};
-
-struct VectorDistData : public StatData
-{
- std::vector<DistDataData> data;
-
- /** Names and descriptions of subfields. */
- mutable std::vector<std::string> subnames;
- mutable std::vector<std::string> subdescs;
-
- /** Local storage for the entry values, used for printing. */
- mutable VResult rvec;
-
- virtual size_t size() const = 0;
- void update()
- {
- int s = size();
- if (subnames.size() < s)
- subnames.resize(s);
-
- if (subdescs.size() < s)
- subdescs.resize(s);
- }
-};
-
-template <class Stat>
-class VectorDistStatData : public VectorDistData
-{
- protected:
- Stat &s;
- typedef typename Stat::bin_t bin_t;
-
- public:
- VectorDistStatData(Stat &stat) : s(stat) {}
-
- virtual bool binned() const { return bin_t::binned; }
- virtual bool check() const { return s.check(); }
- virtual void reset() { s.reset(); }
- virtual size_t size() const { return s.size(); }
- virtual bool zero() const { return s.zero(); }
- virtual void visit(Visit &visitor)
- {
- update();
- s.update(this);
- visitor.visit(*this);
- }
-};
-
-struct Vector2dData : public StatData
-{
- /** Names and descriptions of subfields. */
- std::vector<std::string> subnames;
- std::vector<std::string> subdescs;
- std::vector<std::string> y_subnames;
-
- /** Local storage for the entry values, used for printing. */
- mutable VCounter cvec;
- mutable int x;
- mutable int y;
-
- void update()
- {
- if (subnames.size() < x)
- subnames.resize(x);
- }
-};
-
-template <class Stat>
-class Vector2dStatData : public Vector2dData
-{
- protected:
- Stat &s;
- typedef typename Stat::bin_t bin_t;
-
- public:
- Vector2dStatData(Stat &stat) : s(stat) {}
-
- virtual bool binned() const { return bin_t::binned; }
- virtual bool check() const { return s.check(); }
- virtual void reset() { s.reset(); }
- virtual bool zero() const { return s.zero(); }
- virtual void visit(Visit &visitor)
- {
- update();
- s.update(this);
- visitor.visit(*this);
- }
-};
-
-
-class DataAccess
-{
- protected:
- StatData *find() const;
- void map(StatData *data);
-
- StatData *statData();
- const StatData *statData() const;
-
- void setInit();
- void setPrint();
-};
-
-template <class Parent, class Child, template <class> class Data>
-class Wrap : public Child
-{
- protected:
- Parent &self() { return *reinterpret_cast<Parent *>(this); }
-
- protected:
- Data<Child> *statData()
- {
- StatData *__data = DataAccess::statData();
- Data<Child> *ptr = dynamic_cast<Data<Child> *>(__data);
- assert(ptr);
- return ptr;
- }
-
- public:
- const Data<Child> *statData() const
- {
- const StatData *__data = DataAccess::statData();
- const Data<Child> *ptr = dynamic_cast<const Data<Child> *>(__data);
- assert(ptr);
- return ptr;
- }
-
- protected:
- /**
- * Copy constructor, copies are not allowed.
- */
- Wrap(const Wrap &stat);
- /**
- * Can't copy stats.
- */
- void operator=(const Wrap &);
-
- public:
- Wrap()
- {
- map(new Data<Child>(*this));
- }
-
- /**
- * Set the name and marks this stat to print at the end of simulation.
- * @param name The new name.
- * @return A reference to this stat.
- */
- Parent &name(const std::string &_name)
- {
- Data<Child> *data = this->statData();
- data->name = _name;
- this->setPrint();
- return this->self();
- }
-
- /**
- * Set the description and marks this stat to print at the end of
- * simulation.
- * @param desc The new description.
- * @return A reference to this stat.
- */
- Parent &desc(const std::string &_desc)
- {
- this->statData()->desc = _desc;
- return this->self();
- }
-
- /**
- * Set the precision and marks this stat to print at the end of simulation.
- * @param p The new precision
- * @return A reference to this stat.
- */
- Parent &precision(int _precision)
- {
- this->statData()->precision = _precision;
- return this->self();
- }
-
- /**
- * Set the flags and marks this stat to print at the end of simulation.
- * @param f The new flags.
- * @return A reference to this stat.
- */
- Parent &flags(StatFlags _flags)
- {
- this->statData()->flags |= _flags;
- return this->self();
- }
-
- /**
- * Set the prerequisite stat and marks this stat to print at the end of
- * simulation.
- * @param prereq The prerequisite stat.
- * @return A reference to this stat.
- */
- template <class Stat>
- Parent &prereq(const Stat &prereq)
- {
- this->statData()->prereq = prereq.statData();
- return this->self();
- }
-};
-
-template <class Parent, class Child, template <class Child> class Data>
-class WrapVec : public Wrap<Parent, Child, Data>
-{
- public:
- // The following functions are specific to vectors. If you use them
- // in a non vector context, you will get a nice compiler error!
-
- /**
- * Set the subfield name for the given index, and marks this stat to print
- * at the end of simulation.
- * @param index The subfield index.
- * @param name The new name of the subfield.
- * @return A reference to this stat.
- */
- Parent &subname(int index, const std::string &name)
- {
- std::vector<std::string> &subn = this->statData()->subnames;
- if (subn.size() <= index)
- subn.resize(index + 1);
- subn[index] = name;
- return this->self();
- }
-
- /**
- * Set the subfield description for the given index and marks this stat to
- * print at the end of simulation.
- * @param index The subfield index.
- * @param desc The new description of the subfield
- * @return A reference to this stat.
- */
- Parent &subdesc(int index, const std::string &desc)
- {
- std::vector<std::string> &subd = this->statData()->subdescs;
- if (subd.size() <= index)
- subd.resize(index + 1);
- subd[index] = desc;
-
- return this->self();
- }
-
-};
-
-template <class Parent, class Child, template <class Child> class Data>
-class WrapVec2d : public WrapVec<Parent, Child, Data>
-{
- public:
- /**
- * @warning This makes the assumption that if you're gonna subnames a 2d
- * vector, you're subnaming across all y
- */
- Parent &ysubnames(const char **names)
- {
- Data<Child> *data = this->statData();
- data->y_subnames.resize(this->y);
- for (int i = 0; i < this->y; ++i)
- data->y_subnames[i] = names[i];
- return this->self();
- }
- Parent &ysubname(int index, const std::string subname)
- {
- Data<Child> *data = this->statData();
- assert(index < this->y);
- data->y_subnames.resize(this->y);
- data->y_subnames[index] = subname.c_str();
- return this->self();
- }
-};
-
-//////////////////////////////////////////////////////////////////////
-//
-// Simple Statistics
-//
-//////////////////////////////////////////////////////////////////////
-
-/**
- * Templatized storage and interface for a simple scalar stat.
- */
-struct StatStor
-{
- public:
- /** The paramaters for this storage type, none for a scalar. */
- struct Params { };
-
- private:
- /** The statistic value. */
- Counter data;
-
- public:
- /**
- * Builds this storage element and calls the base constructor of the
- * datatype.
- */
- StatStor(const Params &) : data(Counter()) {}
-
- /**
- * The the stat to the given value.
- * @param val The new value.
- * @param p The paramters of this storage type.
- */
- void set(Counter val, const Params &p) { data = val; }
- /**
- * Increment the stat by the given value.
- * @param val The new value.
- * @param p The paramters of this storage type.
- */
- void inc(Counter val, const Params &p) { data += val; }
- /**
- * Decrement the stat by the given value.
- * @param val The new value.
- * @param p The paramters of this storage type.
- */
- void dec(Counter val, const Params &p) { data -= val; }
- /**
- * Return the value of this stat as its base type.
- * @param p The params of this storage type.
- * @return The value of this stat.
- */
- Counter value(const Params &p) const { return data; }
- /**
- * Return the value of this stat as a result type.
- * @param p The parameters of this storage type.
- * @return The value of this stat.
- */
- Result result(const Params &p) const { return (Result)data; }
- /**
- * Reset stat value to default
- */
- void reset() { data = Counter(); }
-
- /**
- * @return true if zero value
- */
- bool zero() const { return data == Counter(); }
-};
-
-/**
- * Templatized storage and interface to a per-cycle average stat. This keeps
- * a current count and updates a total (count * cycles) when this count
- * changes. This allows the quick calculation of a per cycle count of the item
- * being watched. This is good for keeping track of residencies in structures
- * among other things.
- * @todo add lateny to the stat and fix binning.
- */
-struct AvgStor
-{
- public:
- /** The paramaters for this storage type */
- struct Params
- {
- /**
- * The current count. We stash this here because the current
- * value is not a binned value.
- */
- Counter current;
- };
-
- private:
- /** The total count for all cycles. */
- mutable Result total;
- /** The cycle that current last changed. */
- mutable Tick last;
-
- public:
- /**
- * Build and initializes this stat storage.
- */
- AvgStor(Params &p) : total(0), last(0) { p.current = Counter(); }
-
- /**
- * Set the current count to the one provided, update the total and last
- * set values.
- * @param val The new count.
- * @param p The parameters for this storage.
- */
- void set(Counter val, Params &p) {
- total += p.current * (curTick - last);
- last = curTick;
- p.current = val;
- }
-
- /**
- * Increment the current count by the provided value, calls set.
- * @param val The amount to increment.
- * @param p The parameters for this storage.
- */
- void inc(Counter val, Params &p) { set(p.current + val, p); }
-
- /**
- * Deccrement the current count by the provided value, calls set.
- * @param val The amount to decrement.
- * @param p The parameters for this storage.
- */
- void dec(Counter val, Params &p) { set(p.current - val, p); }
-
- /**
- * Return the current count.
- * @param p The parameters for this storage.
- * @return The current count.
- */
- Counter value(const Params &p) const { return p.current; }
-
- /**
- * Return the current average.
- * @param p The parameters for this storage.
- * @return The current average.
- */
- Result result(const Params &p) const
- {
- total += p.current * (curTick - last);
- last = curTick;
- return (Result)(total + p.current) / (Result)(curTick + 1);
- }
-
- /**
- * Reset stat value to default
- */
- void reset()
- {
- total = 0;
- last = curTick;
- }
-
- /**
- * @return true if zero value
- */
- bool zero() const { return total == 0.0; }
-};
-
-/**
- * Implementation of a scalar stat. The type of stat is determined by the
- * Storage template. The storage for this stat is held within the Bin class.
- * This allows for breaking down statistics across multiple bins easily.
- */
-template <class Storage, class Bin>
-class ScalarBase : public DataAccess
-{
- public:
- /** Define the params of the storage class. */
- typedef typename Storage::Params params_t;
- /** Define the bin type. */
- typedef typename Bin::template Bin<Storage> bin_t;
-
- protected:
- /** The bin of this stat. */
- bin_t bin;
- /** The parameters for this stat. */
- params_t params;
-
- protected:
- /**
- * Retrieve the storage from the bin.
- * @return The storage object for this stat.
- */
- Storage *data() { return bin.data(params); }
- /**
- * Retrieve a const pointer to the storage from the bin.
- * @return A const pointer to the storage object for this stat.
- */
- const Storage *data() const
- {
- bin_t *_bin = const_cast<bin_t *>(&bin);
- params_t *_params = const_cast<params_t *>(&params);
- return _bin->data(*_params);
- }
-
- public:
- /**
- * Return the current value of this stat as its base type.
- * @return The current value.
- */
- Counter value() const { return data()->value(params); }
-
- public:
- /**
- * Create and initialize this stat, register it with the database.
- */
- ScalarBase()
- {
- bin.init(params);
- }
-
- public:
- // Common operators for stats
- /**
- * Increment the stat by 1. This calls the associated storage object inc
- * function.
- */
- void operator++() { data()->inc(1, params); }
- /**
- * Decrement the stat by 1. This calls the associated storage object dec
- * function.
- */
- void operator--() { data()->dec(1, params); }
-
- /** Increment the stat by 1. */
- void operator++(int) { ++*this; }
- /** Decrement the stat by 1. */
- void operator--(int) { --*this; }
-
- /**
- * Set the data value to the given value. This calls the associated storage
- * object set function.
- * @param v The new value.
- */
- template <typename U>
- void operator=(const U &v) { data()->set(v, params); }
-
- /**
- * Increment the stat by the given value. This calls the associated
- * storage object inc function.
- * @param v The value to add.
- */
- template <typename U>
- void operator+=(const U &v) { data()->inc(v, params); }
-
- /**
- * Decrement the stat by the given value. This calls the associated
- * storage object dec function.
- * @param v The value to substract.
- */
- template <typename U>
- void operator-=(const U &v) { data()->dec(v, params); }
-
- /**
- * Return the number of elements, always 1 for a scalar.
- * @return 1.
- */
- size_t size() const { return 1; }
- /**
- * Return true if stat is binned.
- *@return True is stat is binned.
- */
- bool binned() const { return bin_t::binned; }
-
- bool check() const { return bin.initialized(); }
-
- /**
- * Reset stat value to default
- */
- void reset() { bin.reset(); }
-
- Counter value() { return data()->value(params); }
-
- Result result() { return data()->result(params); }
-
- Result total() { return result(); }
-
- bool zero() { return result() == 0.0; }
-
-};
-
-class ProxyData : public ScalarData
-{
- public:
- virtual void visit(Visit &visitor) { visitor.visit(*this); }
- virtual bool binned() const { return false; }
- virtual std::string str() const { return to_string(value()); }
- virtual size_t size() const { return 1; }
- virtual bool zero() const { return value() == 0; }
- virtual bool check() const { return true; }
- virtual void reset() { }
-};
-
-template <class T>
-class ValueProxy : public ProxyData
-{
- private:
- T *scalar;
-
- public:
- ValueProxy(T &val) : scalar(&val) {}
- virtual Counter value() const { return *scalar; }
- virtual Result result() const { return *scalar; }
- virtual Result total() const { return *scalar; }
-};
-
-template <class T>
-class FunctorProxy : public ProxyData
-{
- private:
- T *functor;
-
- public:
- FunctorProxy(T &func) : functor(&func) {}
- virtual Counter value() const { return (*functor)(); }
- virtual Result result() const { return (*functor)(); }
- virtual Result total() const { return (*functor)(); }
-};
-
-class ValueBase : public DataAccess
-{
- private:
- ProxyData *proxy;
-
- public:
- ValueBase() : proxy(NULL) { }
- ~ValueBase() { if (proxy) delete proxy; }
-
- template <class T>
- void scalar(T &value)
- {
- proxy = new ValueProxy<T>(value);
- setInit();
- }
-
- template <class T>
- void functor(T &func)
- {
- proxy = new FunctorProxy<T>(func);
- setInit();
- }
-
- Counter value() { return proxy->value(); }
- Result result() const { return proxy->result(); }
- Result total() const { return proxy->total(); };
- size_t size() const { return proxy->size(); }
-
- bool binned() const { return proxy->binned(); }
- std::string str() const { return proxy->str(); }
- bool zero() const { return proxy->zero(); }
- bool check() const { return proxy != NULL; }
- void reset() { }
-};
-
-//////////////////////////////////////////////////////////////////////
-//
-// Vector Statistics
-//
-//////////////////////////////////////////////////////////////////////
-template <class Storage, class Bin>
-class ScalarProxy;
-
-/**
- * Implementation of a vector of stats. The type of stat is determined by the
- * Storage class. @sa ScalarBase
- */
-template <class Storage, class Bin>
-class VectorBase : public DataAccess
-{
- public:
- /** Define the params of the storage class. */
- typedef typename Storage::Params params_t;
- /** Define the bin type. */
- typedef typename Bin::template VectorBin<Storage> bin_t;
-
- protected:
- /** The bin of this stat. */
- bin_t bin;
- /** The parameters for this stat. */
- params_t params;
-
- protected:
- /**
- * Retrieve the storage from the bin for the given index.
- * @param index The vector index to access.
- * @return The storage object at the given index.
- */
- Storage *data(int index) { return bin.data(index, params); }
- /**
- * Retrieve a const pointer to the storage from the bin
- * for the given index.
- * @param index The vector index to access.
- * @return A const pointer to the storage object at the given index.
- */
- const Storage *data(int index) const
- {
- bin_t *_bin = const_cast<bin_t *>(&bin);
- params_t *_params = const_cast<params_t *>(&params);
- return _bin->data(index, *_params);
- }
-
- public:
- void value(VCounter &vec) const
- {
- vec.resize(size());
- for (int i = 0; i < size(); ++i)
- vec[i] = data(i)->value(params);
- }
-
- /**
- * Copy the values to a local vector and return a reference to it.
- * @return A reference to a vector of the stat values.
- */
- void result(VResult &vec) const
- {
- vec.resize(size());
- for (int i = 0; i < size(); ++i)
- vec[i] = data(i)->result(params);
- }
-
- /**
- * @return True is stat is binned.
- */
- bool binned() const { return bin_t::binned; }
-
- /**
- * Return a total of all entries in this vector.
- * @return The total of all vector entries.
- */
- Result total() const {
- Result total = 0.0;
- for (int i = 0; i < size(); ++i)
- total += data(i)->result(params);
- return total;
- }
-
- /**
- * @return the number of elements in this vector.
- */
- size_t size() const { return bin.size(); }
-
- bool zero() const
- {
- for (int i = 0; i < size(); ++i)
- if (data(i)->zero())
- return true;
- return false;
- }
-
- bool check() const { return bin.initialized(); }
- void reset() { bin.reset(); }
-
- public:
- VectorBase() {}
-
- /** Friend this class with the associated scalar proxy. */
- friend class ScalarProxy<Storage, Bin>;
-
- /**
- * Return a reference (ScalarProxy) to the stat at the given index.
- * @param index The vector index to access.
- * @return A reference of the stat.
- */
- ScalarProxy<Storage, Bin> operator[](int index);
-
- void update(StatData *data) {}
-};
-
-const StatData * getStatData(const void *stat);
-
-/**
- * A proxy class to access the stat at a given index in a VectorBase stat.
- * Behaves like a ScalarBase.
- */
-template <class Storage, class Bin>
-class ScalarProxy
-{
- public:
- /** Define the params of the storage class. */
- typedef typename Storage::Params params_t;
- /** Define the bin type. */
- typedef typename Bin::template VectorBin<Storage> bin_t;
-
- private:
- /** Pointer to the bin in the parent VectorBase. */
- bin_t *bin;
- /** Pointer to the params in the parent VectorBase. */
- params_t *params;
- /** The index to access in the parent VectorBase. */
- int index;
- /** Keep a pointer to the original stat so was can get data */
- void *stat;
-
- protected:
- /**
- * Retrieve the storage from the bin.
- * @return The storage from the bin for this stat.
- */
- Storage *data() { return bin->data(index, *params); }
- /**
- * Retrieve a const pointer to the storage from the bin.
- * @return A const pointer to the storage for this stat.
- */
- const Storage *data() const
- {
- bin_t *_bin = const_cast<bin_t *>(bin);
- params_t *_params = const_cast<params_t *>(params);
- return _bin->data(index, *_params);
- }
-
- public:
- /**
- * Return the current value of this stat as its base type.
- * @return The current value.
- */
- Counter value() const { return data()->value(*params); }
-
- /**
- * Return the current value of this statas a result type.
- * @return The current value.
- */
- Result result() const { return data()->result(*params); }
-
- public:
- /**
- * Create and initialize this proxy, do not register it with the database.
- * @param b The bin to use.
- * @param p The params to use.
- * @param i The index to access.
- */
- ScalarProxy(bin_t &b, params_t &p, int i, void *s)
- : bin(&b), params(&p), index(i), stat(s) {}
- /**
- * Create a copy of the provided ScalarProxy.
- * @param sp The proxy to copy.
- */
- ScalarProxy(const ScalarProxy &sp)
- : bin(sp.bin), params(sp.params), index(sp.index), stat(sp.stat) {}
- /**
- * Set this proxy equal to the provided one.
- * @param sp The proxy to copy.
- * @return A reference to this proxy.
- */
- const ScalarProxy &operator=(const ScalarProxy &sp) {
- bin = sp.bin;
- params = sp.params;
- index = sp.index;
- stat = sp.stat;
- return *this;
- }
-
- public:
- // Common operators for stats
- /**
- * Increment the stat by 1. This calls the associated storage object inc
- * function.
- */
- void operator++() { data()->inc(1, *params); }
- /**
- * Decrement the stat by 1. This calls the associated storage object dec
- * function.
- */
- void operator--() { data()->dec(1, *params); }
-
- /** Increment the stat by 1. */
- void operator++(int) { ++*this; }
- /** Decrement the stat by 1. */
- void operator--(int) { --*this; }
-
- /**
- * Set the data value to the given value. This calls the associated storage
- * object set function.
- * @param v The new value.
- */
- template <typename U>
- void operator=(const U &v) { data()->set(v, *params); }
-
- /**
- * Increment the stat by the given value. This calls the associated
- * storage object inc function.
- * @param v The value to add.
- */
- template <typename U>
- void operator+=(const U &v) { data()->inc(v, *params); }
-
- /**
- * Decrement the stat by the given value. This calls the associated
- * storage object dec function.
- * @param v The value to substract.
- */
- template <typename U>
- void operator-=(const U &v) { data()->dec(v, *params); }
-
- /**
- * Return the number of elements, always 1 for a scalar.
- * @return 1.
- */
- size_t size() const { return 1; }
-
- /**
- * Return true if stat is binned.
- *@return false since Proxies aren't printed/binned
- */
- bool binned() const { return false; }
-
- /**
- * This stat has no state. Nothing to reset
- */
- void reset() { }
-
- public:
- const StatData *statData() const { return getStatData(stat); }
- std::string str() const
- {
- return csprintf("%s[%d]", this->statData()->name, index);
-
- }
-};
-
-template <class Storage, class Bin>
-inline ScalarProxy<Storage, Bin>
-VectorBase<Storage, Bin>::operator[](int index)
-{
- assert (index >= 0 && index < size());
- return ScalarProxy<Storage, Bin>(bin, params, index, this);
-}
-
-template <class Storage, class Bin>
-class VectorProxy;
-
-template <class Storage, class Bin>
-class Vector2dBase : public DataAccess
-{
- public:
- typedef typename Storage::Params params_t;
- typedef typename Bin::template VectorBin<Storage> bin_t;
-
- protected:
- size_t x;
- size_t y;
- bin_t bin;
- params_t params;
-
- protected:
- Storage *data(int index) { return bin.data(index, params); }
- const Storage *data(int index) const
- {
- bin_t *_bin = const_cast<bin_t *>(&bin);
- params_t *_params = const_cast<params_t *>(&params);
- return _bin->data(index, *_params);
- }
-
- public:
- Vector2dBase() {}
-
- void update(Vector2dData *data)
- {
- int size = this->size();
- data->cvec.resize(size);
- for (int i = 0; i < size; ++i)
- data->cvec[i] = this->data(i)->value(params);
- }
-
- std::string ysubname(int i) const { return (*this->y_subnames)[i]; }
-
- friend class VectorProxy<Storage, Bin>;
- VectorProxy<Storage, Bin> operator[](int index);
-
- size_t size() const { return bin.size(); }
- bool zero() const { return data(0)->value(params) == 0.0; }
-
- /**
- * Reset stat value to default
- */
- void reset() { bin.reset(); }
-
- bool check() { return bin.initialized(); }
-};
-
-template <class Storage, class Bin>
-class VectorProxy
-{
- public:
- typedef typename Storage::Params params_t;
- typedef typename Bin::template VectorBin<Storage> bin_t;
-
- private:
- bin_t *bin;
- params_t *params;
- int offset;
- int len;
- void *stat;
-
- private:
- mutable VResult *vec;
-
- Storage *data(int index) {
- assert(index < len);
- return bin->data(offset + index, *params);
- }
-
- const Storage *data(int index) const {
- bin_t *_bin = const_cast<bin_t *>(bin);
- params_t *_params = const_cast<params_t *>(params);
- return _bin->data(offset + index, *_params);
- }
-
- public:
- const VResult &result() const {
- if (vec)
- vec->resize(size());
- else
- vec = new VResult(size());
-
- for (int i = 0; i < size(); ++i)
- (*vec)[i] = data(i)->result(*params);
-
- return *vec;
- }
-
- Result total() const {
- Result total = 0.0;
- for (int i = 0; i < size(); ++i)
- total += data(i)->result(*params);
- return total;
- }
-
- public:
- VectorProxy(bin_t &b, params_t &p, int o, int l, void *s)
- : bin(&b), params(&p), offset(o), len(l), stat(s), vec(NULL)
- {
- }
-
- VectorProxy(const VectorProxy &sp)
- : bin(sp.bin), params(sp.params), offset(sp.offset), len(sp.len),
- stat(sp.stat), vec(NULL)
- {
- }
-
- ~VectorProxy()
- {
- if (vec)
- delete vec;
- }
-
- const VectorProxy &operator=(const VectorProxy &sp)
- {
- bin = sp.bin;
- params = sp.params;
- offset = sp.offset;
- len = sp.len;
- stat = sp.stat;
- if (vec)
- delete vec;
- vec = NULL;
- return *this;
- }
-
- ScalarProxy<Storage, Bin> operator[](int index)
- {
- assert (index >= 0 && index < size());
- return ScalarProxy<Storage, Bin>(*bin, *params, offset + index, stat);
- }
-
- size_t size() const { return len; }
-
- /**
- * Return true if stat is binned.
- *@return false since Proxies aren't printed/binned
- */
- bool binned() const { return false; }
-
- /**
- * This stat has no state. Nothing to reset.
- */
- void reset() { }
-};
-
-template <class Storage, class Bin>
-inline VectorProxy<Storage, Bin>
-Vector2dBase<Storage, Bin>::operator[](int index)
-{
- int offset = index * y;
- assert (index >= 0 && offset < size());
- return VectorProxy<Storage, Bin>(bin, params, offset, y, this);
-}
-
-//////////////////////////////////////////////////////////////////////
-//
-// Non formula statistics
-//
-//////////////////////////////////////////////////////////////////////
-
-/**
- * Templatized storage and interface for a distrbution stat.
- */
-struct DistStor
-{
- public:
- /** The parameters for a distribution stat. */
- struct Params
- {
- /** The minimum value to track. */
- Counter min;
- /** The maximum value to track. */
- Counter max;
- /** The number of entries in each bucket. */
- Counter bucket_size;
- /** The number of buckets. Equal to (max-min)/bucket_size. */
- int size;
- };
- enum { fancy = false };
-
- private:
- /** The smallest value sampled. */
- Counter min_val;
- /** The largest value sampled. */
- Counter max_val;
- /** The number of values sampled less than min. */
- Counter underflow;
- /** The number of values sampled more than max. */
- Counter overflow;
- /** The current sum. */
- Counter sum;
- /** The sum of squares. */
- Counter squares;
- /** The number of samples. */
- Counter samples;
- /** Counter for each bucket. */
- VCounter cvec;
-
- public:
- /**
- * Construct this storage with the supplied params.
- * @param params The parameters.
- */
- DistStor(const Params &params)
- : min_val(INT_MAX), max_val(INT_MIN), underflow(Counter()),
- overflow(Counter()), sum(Counter()), squares(Counter()),
- samples(Counter()), cvec(params.size)
- {
- reset();
- }
-
- /**
- * Add a value to the distribution for the given number of times.
- * @param val The value to add.
- * @param number The number of times to add the value.
- * @param params The paramters of the distribution.
- */
- void sample(Counter val, int number, const Params &params)
- {
- if (val < params.min)
- underflow += number;
- else if (val > params.max)
- overflow += number;
- else {
- int index = (int)floor((val - params.min) / params.bucket_size);
- assert(index < size(params));
- cvec[index] += number;
- }
-
- if (val < min_val)
- min_val = val;
-
- if (val > max_val)
- max_val = val;
-
- Counter sample = val * number;
- sum += sample;
- squares += sample * sample;
- samples += number;
- }
-
- /**
- * Return the number of buckets in this distribution.
- * @return the number of buckets.
- * @todo Is it faster to return the size from the parameters?
- */
- size_t size(const Params &) const { return cvec.size(); }
-
- /**
- * Returns true if any calls to sample have been made.
- * @param params The paramters of the distribution.
- * @return True if any values have been sampled.
- */
- bool zero(const Params &params) const
- {
- return samples == Counter();
- }
-
- void update(DistDataData *data, const Params &params)
- {
- data->min = params.min;
- data->max = params.max;
- data->bucket_size = params.bucket_size;
- data->size = params.size;
-
- data->min_val = (min_val == INT_MAX) ? 0 : min_val;
- data->max_val = (max_val == INT_MIN) ? 0 : max_val;
- data->underflow = underflow;
- data->overflow = overflow;
- data->cvec.resize(params.size);
- for (int i = 0; i < params.size; ++i)
- data->cvec[i] = cvec[i];
-
- data->sum = sum;
- data->squares = squares;
- data->samples = samples;
- }
-
- /**
- * Reset stat value to default
- */
- void reset()
- {
- min_val = INT_MAX;
- max_val = INT_MIN;
- underflow = 0;
- overflow = 0;
-
- int size = cvec.size();
- for (int i = 0; i < size; ++i)
- cvec[i] = Counter();
-
- sum = Counter();
- squares = Counter();
- samples = Counter();
- }
-};
-
-/**
- * Templatized storage and interface for a distribution that calculates mean
- * and variance.
- */
-struct FancyStor
-{
- public:
- /**
- * No paramters for this storage.
- */
- struct Params {};
- enum { fancy = true };
-
- private:
- /** The current sum. */
- Counter sum;
- /** The sum of squares. */
- Counter squares;
- /** The number of samples. */
- Counter samples;
-
- public:
- /**
- * Create and initialize this storage.
- */
- FancyStor(const Params &)
- : sum(Counter()), squares(Counter()), samples(Counter())
- { }
-
- /**
- * Add a value the given number of times to this running average.
- * Update the running sum and sum of squares, increment the number of
- * values seen by the given number.
- * @param val The value to add.
- * @param number The number of times to add the value.
- * @param p The parameters of this stat.
- */
- void sample(Counter val, int number, const Params &p)
- {
- Counter value = val * number;
- sum += value;
- squares += value * value;
- samples += number;
- }
-
- void update(DistDataData *data, const Params &params)
- {
- data->sum = sum;
- data->squares = squares;
- data->samples = samples;
- }
-
- /**
- * Return the number of entries in this stat, 1
- * @return 1.
- */
- size_t size(const Params &) const { return 1; }
-
- /**
- * Return true if no samples have been added.
- * @return True if no samples have been added.
- */
- bool zero(const Params &) const { return samples == Counter(); }
-
- /**
- * Reset stat value to default
- */
- void reset()
- {
- sum = Counter();
- squares = Counter();
- samples = Counter();
- }
-};
-
-/**
- * Templatized storage for distribution that calculates per cycle mean and
- * variance.
- */
-struct AvgFancy
-{
- public:
- /** No parameters for this storage. */
- struct Params {};
- enum { fancy = true };
-
- private:
- /** Current total. */
- Counter sum;
- /** Current sum of squares. */
- Counter squares;
-
- public:
- /**
- * Create and initialize this storage.
- */
- AvgFancy(const Params &) : sum(Counter()), squares(Counter()) {}
-
- /**
- * Add a value to the distribution for the given number of times.
- * Update the running sum and sum of squares.
- * @param val The value to add.
- * @param number The number of times to add the value.
- * @param p The paramters of the distribution.
- */
- void sample(Counter val, int number, const Params &p)
- {
- Counter value = val * number;
- sum += value;
- squares += value * value;
- }
-
- void update(DistDataData *data, const Params &params)
- {
- data->sum = sum;
- data->squares = squares;
- data->samples = curTick;
- }
-
- /**
- * Return the number of entries, in this case 1.
- * @return 1.
- */
- size_t size(const Params &params) const { return 1; }
- /**
- * Return true if no samples have been added.
- * @return True if the sum is zero.
- */
- bool zero(const Params &params) const { return sum == Counter(); }
- /**
- * Reset stat value to default
- */
- void reset()
- {
- sum = Counter();
- squares = Counter();
- }
-};
-
-/**
- * Implementation of a distribution stat. The type of distribution is
- * determined by the Storage template. @sa ScalarBase
- */
-template <class Storage, class Bin>
-class DistBase : public DataAccess
-{
- public:
- /** Define the params of the storage class. */
- typedef typename Storage::Params params_t;
- /** Define the bin type. */
- typedef typename Bin::template Bin<Storage> bin_t;
-
- protected:
- /** The bin of this stat. */
- bin_t bin;
- /** The parameters for this stat. */
- params_t params;
-
- protected:
- /**
- * Retrieve the storage from the bin.
- * @return The storage object for this stat.
- */
- Storage *data() { return bin.data(params); }
- /**
- * Retrieve a const pointer to the storage from the bin.
- * @return A const pointer to the storage object for this stat.
- */
- const Storage *data() const
- {
- bin_t *_bin = const_cast<bin_t *>(&bin);
- params_t *_params = const_cast<params_t *>(&params);
- return _bin->data(*_params);
- }
-
- public:
- DistBase() { }
-
- /**
- * Add a value to the distribtion n times. Calls sample on the storage
- * class.
- * @param v The value to add.
- * @param n The number of times to add it, defaults to 1.
- */
- template <typename U>
- void sample(const U &v, int n = 1) { data()->sample(v, n, params); }
-
- /**
- * Return the number of entries in this stat.
- * @return The number of entries.
- */
- size_t size() const { return data()->size(params); }
- /**
- * Return true if no samples have been added.
- * @return True if there haven't been any samples.
- */
- bool zero() const { return data()->zero(params); }
-
- void update(DistData *base)
- {
- base->data.fancy = Storage::fancy;
- data()->update(&(base->data), params);
- }
- /**
- * @return True is stat is binned.
- */
- bool binned() const { return bin_t::binned; }
- /**
- * Reset stat value to default
- */
- void reset()
- {
- bin.reset();
- }
-
- bool check() { return bin.initialized(); }
-};
-
-template <class Storage, class Bin>
-class DistProxy;
-
-template <class Storage, class Bin>
-class VectorDistBase : public DataAccess
-{
- public:
- typedef typename Storage::Params params_t;
- typedef typename Bin::template VectorBin<Storage> bin_t;
-
- protected:
- bin_t bin;
- params_t params;
-
- protected:
- Storage *data(int index) { return bin.data(index, params); }
- const Storage *data(int index) const
- {
- bin_t *_bin = const_cast<bin_t *>(&bin);
- params_t *_params = const_cast<params_t *>(&params);
- return _bin->data(index, *_params);
- }
-
- public:
- VectorDistBase() {}
-
- friend class DistProxy<Storage, Bin>;
- DistProxy<Storage, Bin> operator[](int index);
- const DistProxy<Storage, Bin> operator[](int index) const;
-
- size_t size() const { return bin.size(); }
- bool zero() const { return false; }
- /**
- * Return true if stat is binned.
- *@return True is stat is binned.
- */
- bool binned() const { return bin_t::binned; }
- /**
- * Reset stat value to default
- */
- void reset() { bin.reset(); }
-
- bool check() { return bin.initialized(); }
- void update(VectorDistData *base)
- {
- int size = this->size();
- base->data.resize(size);
- for (int i = 0; i < size; ++i) {
- base->data[i].fancy = Storage::fancy;
- data(i)->update(&(base->data[i]), params);
- }
- }
-};
-
-template <class Storage, class Bin>
-class DistProxy
-{
- public:
- typedef typename Storage::Params params_t;
- typedef typename Bin::template Bin<Storage> bin_t;
- typedef VectorDistBase<Storage, Bin> base_t;
-
- private:
- union {
- base_t *stat;
- const base_t *cstat;
- };
- int index;
-
- protected:
- Storage *data() { return stat->data(index); }
- const Storage *data() const { return cstat->data(index); }
-
- public:
- DistProxy(const VectorDistBase<Storage, Bin> &s, int i)
- : cstat(&s), index(i) {}
- DistProxy(const DistProxy &sp)
- : cstat(sp.cstat), index(sp.index) {}
- const DistProxy &operator=(const DistProxy &sp) {
- cstat = sp.cstat; index = sp.index; return *this;
- }
-
- public:
- template <typename U>
- void sample(const U &v, int n = 1) { data()->sample(v, n, cstat->params); }
-
- size_t size() const { return 1; }
- bool zero() const { return data()->zero(cstat->params); }
- /**
- * Return true if stat is binned.
- *@return false since Proxies are not binned/printed.
- */
- bool binned() const { return false; }
- /**
- * Proxy has no state. Nothing to reset.
- */
- void reset() { }
-};
-
-template <class Storage, class Bin>
-inline DistProxy<Storage, Bin>
-VectorDistBase<Storage, Bin>::operator[](int index)
-{
- assert (index >= 0 && index < size());
- return DistProxy<Storage, Bin>(*this, index);
-}
-
-template <class Storage, class Bin>
-inline const DistProxy<Storage, Bin>
-VectorDistBase<Storage, Bin>::operator[](int index) const
-{
- assert (index >= 0 && index < size());
- return DistProxy<Storage, Bin>(*this, index);
-}
-
-#if 0
-template <class Storage, class Bin>
-Result
-VectorDistBase<Storage, Bin>::total(int index) const
-{
- int total = 0;
- for (int i=0; i < x_size(); ++i) {
- total += data(i)->result(*params);
- }
-}
-#endif
-
-//////////////////////////////////////////////////////////////////////
-//
-// Formula Details
-//
-//////////////////////////////////////////////////////////////////////
-
-/**
- * Base class for formula statistic node. These nodes are used to build a tree
- * that represents the formula.
- */
-class Node : public RefCounted
-{
- public:
- /**
- * Return the number of nodes in the subtree starting at this node.
- * @return the number of nodes in this subtree.
- */
- virtual size_t size() const = 0;
- /**
- * Return the result vector of this subtree.
- * @return The result vector of this subtree.
- */
- virtual const VResult &result() const = 0;
- /**
- * Return the total of the result vector.
- * @return The total of the result vector.
- */
- virtual Result total() const = 0;
- /**
- * Return true if stat is binned.
- *@return True is stat is binned.
- */
- virtual bool binned() const = 0;
-
- /**
- *
- */
- virtual std::string str() const = 0;
-};
-
-/** Reference counting pointer to a function Node. */
-typedef RefCountingPtr<Node> NodePtr;
-
-class ScalarStatNode : public Node
-{
- private:
- const ScalarData *data;
- mutable VResult vresult;
-
- public:
- ScalarStatNode(const ScalarData *d) : data(d), vresult(1) {}
- virtual const VResult &result() const
- {
- vresult[0] = data->result();
- return vresult;
- }
- virtual Result total() const { return data->result(); };
-
- virtual size_t size() const { return 1; }
- /**
- * Return true if stat is binned.
- *@return True is stat is binned.
- */
- virtual bool binned() const { return data->binned(); }
-
- /**
- *
- */
- virtual std::string str() const { return data->name; }
-};
-
-template <class Storage, class Bin>
-class ScalarProxyNode : public Node
-{
- private:
- const ScalarProxy<Storage, Bin> proxy;
- mutable VResult vresult;
-
- public:
- ScalarProxyNode(const ScalarProxy<Storage, Bin> &p)
- : proxy(p), vresult(1) { }
- virtual const VResult &result() const
- {
- vresult[0] = proxy.result();
- return vresult;
- }
- virtual Result total() const { return proxy.result(); };
-
- virtual size_t size() const { return 1; }
- /**
- * Return true if stat is binned.
- *@return True is stat is binned.
- */
- virtual bool binned() const { return proxy.binned(); }
-
- /**
- *
- */
- virtual std::string str() const { return proxy.str(); }
-};
-
-class VectorStatNode : public Node
-{
- private:
- const VectorData *data;
-
- public:
- VectorStatNode(const VectorData *d) : data(d) { }
- virtual const VResult &result() const { return data->result(); }
- virtual Result total() const { return data->total(); };
-
- virtual size_t size() const { return data->size(); }
- /**
- * Return true if stat is binned.
- *@return True is stat is binned.
- */
- virtual bool binned() const { return data->binned(); }
-
- virtual std::string str() const { return data->name; }
-};
-
-template <class T>
-class ConstNode : public Node
-{
- private:
- VResult vresult;
-
- public:
- ConstNode(T s) : vresult(1, (Result)s) {}
- const VResult &result() const { return vresult; }
- virtual Result total() const { return vresult[0]; };
- virtual size_t size() const { return 1; }
-
- /**
- * Return true if stat is binned.
- *@return False since constants aren't binned.
- */
- virtual bool binned() const { return false; }
-
- virtual std::string str() const { return to_string(vresult[0]); }
-};
-
-template <class Op>
-struct OpString;
-
-template<>
-struct OpString<std::plus<Result> >
-{
- static std::string str() { return "+"; }
-};
-
-template<>
-struct OpString<std::minus<Result> >
-{
- static std::string str() { return "-"; }
-};
-
-template<>
-struct OpString<std::multiplies<Result> >
-{
- static std::string str() { return "*"; }
-};
-
-template<>
-struct OpString<std::divides<Result> >
-{
- static std::string str() { return "/"; }
-};
-
-template<>
-struct OpString<std::modulus<Result> >
-{
- static std::string str() { return "%"; }
-};
-
-template<>
-struct OpString<std::negate<Result> >
-{
- static std::string str() { return "-"; }
-};
-
-template <class Op>
-class UnaryNode : public Node
-{
- public:
- NodePtr l;
- mutable VResult vresult;
-
- public:
- UnaryNode(NodePtr &p) : l(p) {}
-
- const VResult &result() const
- {
- const VResult &lvec = l->result();
- int size = lvec.size();
-
- assert(size > 0);
-
- vresult.resize(size);
- Op op;
- for (int i = 0; i < size; ++i)
- vresult[i] = op(lvec[i]);
-
- return vresult;
- }
-
- Result total() const {
- Op op;
- return op(l->total());
- }
-
- virtual size_t size() const { return l->size(); }
- /**
- * Return true if child of node is binned.
- *@return True if child of node is binned.
- */
- virtual bool binned() const { return l->binned(); }
-
- virtual std::string str() const
- {
- return OpString<Op>::str() + l->str();
- }
-};
-
-template <class Op>
-class BinaryNode : public Node
-{
- public:
- NodePtr l;
- NodePtr r;
- mutable VResult vresult;
-
- public:
- BinaryNode(NodePtr &a, NodePtr &b) : l(a), r(b) {}
-
- const VResult &result() const
- {
- Op op;
- const VResult &lvec = l->result();
- const VResult &rvec = r->result();
-
- assert(lvec.size() > 0 && rvec.size() > 0);
-
- if (lvec.size() == 1 && rvec.size() == 1) {
- vresult.resize(1);
- vresult[0] = op(lvec[0], rvec[0]);
- } else if (lvec.size() == 1) {
- int size = rvec.size();
- vresult.resize(size);
- for (int i = 0; i < size; ++i)
- vresult[i] = op(lvec[0], rvec[i]);
- } else if (rvec.size() == 1) {
- int size = lvec.size();
- vresult.resize(size);
- for (int i = 0; i < size; ++i)
- vresult[i] = op(lvec[i], rvec[0]);
- } else if (rvec.size() == lvec.size()) {
- int size = rvec.size();
- vresult.resize(size);
- for (int i = 0; i < size; ++i)
- vresult[i] = op(lvec[i], rvec[i]);
- }
-
- return vresult;
- }
-
- Result total() const {
- Op op;
- return op(l->total(), r->total());
- }
-
- virtual size_t size() const {
- int ls = l->size();
- int rs = r->size();
- if (ls == 1)
- return rs;
- else if (rs == 1)
- return ls;
- else {
- assert(ls == rs && "Node vector sizes are not equal");
- return ls;
- }
- }
- /**
- * Return true if any children of node are binned
- *@return True if either child of node is binned.
- */
- virtual bool binned() const { return (l->binned() || r->binned()); }
-
- virtual std::string str() const
- {
- return csprintf("(%s %s %s)", l->str(), OpString<Op>::str(), r->str());
- }
-};
-
-template <class Op>
-class SumNode : public Node
-{
- public:
- NodePtr l;
- mutable VResult vresult;
-
- public:
- SumNode(NodePtr &p) : l(p), vresult(1) {}
-
- const VResult &result() const
- {
- const VResult &lvec = l->result();
- int size = lvec.size();
- assert(size > 0);
-
- vresult[0] = 0.0;
-
- Op op;
- for (int i = 0; i < size; ++i)
- vresult[0] = op(vresult[0], lvec[i]);
-
- return vresult;
- }
-
- Result total() const
- {
- const VResult &lvec = l->result();
- int size = lvec.size();
- assert(size > 0);
-
- Result vresult = 0.0;
-
- Op op;
- for (int i = 0; i < size; ++i)
- vresult = op(vresult, lvec[i]);
-
- return vresult;
- }
-
- virtual size_t size() const { return 1; }
- /**
- * Return true if child of node is binned.
- *@return True if child of node is binned.
- */
- virtual bool binned() const { return l->binned(); }
-
- virtual std::string str() const
- {
- return csprintf("total(%s)", l->str());
- }
-};
-
-
-//////////////////////////////////////////////////////////////////////
-//
-// Visible Statistics Types
-//
-//////////////////////////////////////////////////////////////////////
-/**
- * @defgroup VisibleStats "Statistic Types"
- * These are the statistics that are used in the simulator. By default these
- * store counters and don't use binning, but are templatized to accept any type
- * and any Bin class.
- * @{
- */
-
-/**
- * This is an easy way to assign all your stats to be binned or not
- * binned. If the typedef is NoBin, nothing is binned. If it is
- * MainBin, then all stats are binned under that Bin.
- */
-#if STATS_BINNING
-typedef MainBin DefaultBin;
-#else
-typedef NoBin DefaultBin;
-#endif
-
-/**
- * This is a simple scalar statistic, like a counter.
- * @sa Stat, ScalarBase, StatStor
- */
-template <class Bin = DefaultBin>
-class Scalar
- : public Wrap<Scalar<Bin>,
- ScalarBase<StatStor, Bin>,
- ScalarStatData>
-{
- public:
- /** The base implementation. */
- typedef ScalarBase<StatStor, Bin> Base;
-
- Scalar()
- {
- this->setInit();
- }
-
- /**
- * Sets the stat equal to the given value. Calls the base implementation
- * of operator=
- * @param v The new value.
- */
- template <typename U>
- void operator=(const U &v) { Base::operator=(v); }
-};
-
-class Value
- : public Wrap<Value,
- ValueBase,
- ScalarStatData>
-{
- public:
- /** The base implementation. */
- typedef ValueBase Base;
-
- template <class T>
- Value &scalar(T &value)
- {
- Base::scalar(value);
- return *this;
- }
-
- template <class T>
- Value &functor(T &func)
- {
- Base::functor(func);
- return *this;
- }
-};
-
-/**
- * A stat that calculates the per cycle average of a value.
- * @sa Stat, ScalarBase, AvgStor
- */
-template <class Bin = DefaultBin>
-class Average
- : public Wrap<Average<Bin>,
- ScalarBase<AvgStor, Bin>,
- ScalarStatData>
-{
- public:
- /** The base implementation. */
- typedef ScalarBase<AvgStor, Bin> Base;
-
- Average()
- {
- this->setInit();
- }
-
- /**
- * Sets the stat equal to the given value. Calls the base implementation
- * of operator=
- * @param v The new value.
- */
- template <typename U>
- void operator=(const U &v) { Base::operator=(v); }
-};
-
-/**
- * A vector of scalar stats.
- * @sa Stat, VectorBase, StatStor
- */
-template <class Bin = DefaultBin>
-class Vector
- : public WrapVec<Vector<Bin>,
- VectorBase<StatStor, Bin>,
- VectorStatData>
-{
- public:
- /** The base implementation. */
- typedef ScalarBase<StatStor, Bin> Base;
-
- /**
- * Set this vector to have the given size.
- * @param size The new size.
- * @return A reference to this stat.
- */
- Vector &init(size_t size) {
- this->bin.init(size, this->params);
- this->setInit();
-
- return *this;
- }
-};
-
-/**
- * A vector of Average stats.
- * @sa Stat, VectorBase, AvgStor
- */
-template <class Bin = DefaultBin>
-class AverageVector
- : public WrapVec<AverageVector<Bin>,
- VectorBase<AvgStor, Bin>,
- VectorStatData>
-{
- public:
- /**
- * Set this vector to have the given size.
- * @param size The new size.
- * @return A reference to this stat.
- */
- AverageVector &init(size_t size) {
- this->bin.init(size, this->params);
- this->setInit();
-
- return *this;
- }
-};
-
-/**
- * A 2-Dimensional vecto of scalar stats.
- * @sa Stat, Vector2dBase, StatStor
- */
-template <class Bin = DefaultBin>
-class Vector2d
- : public WrapVec2d<Vector2d<Bin>,
- Vector2dBase<StatStor, Bin>,
- Vector2dStatData>
-{
- public:
- Vector2d &init(size_t _x, size_t _y) {
- this->statData()->x = this->x = _x;
- this->statData()->y = this->y = _y;
- this->bin.init(this->x * this->y, this->params);
- this->setInit();
-
- return *this;
- }
-};
-
-/**
- * A simple distribution stat.
- * @sa Stat, DistBase, DistStor
- */
-template <class Bin = DefaultBin>
-class Distribution
- : public Wrap<Distribution<Bin>,
- DistBase<DistStor, Bin>,
- DistStatData>
-{
- public:
- /** Base implementation. */
- typedef DistBase<DistStor, Bin> Base;
- /** The Parameter type. */
- typedef typename DistStor::Params Params;
-
- public:
- /**
- * Set the parameters of this distribution. @sa DistStor::Params
- * @param min The minimum value of the distribution.
- * @param max The maximum value of the distribution.
- * @param bkt The number of values in each bucket.
- * @return A reference to this distribution.
- */
- Distribution &init(Counter min, Counter max, Counter bkt) {
- this->params.min = min;
- this->params.max = max;
- this->params.bucket_size = bkt;
- this->params.size = (int)rint((max - min) / bkt + 1.0);
- this->bin.init(this->params);
- this->setInit();
-
- return *this;
- }
-};
-
-/**
- * Calculates the mean and variance of all the samples.
- * @sa Stat, DistBase, FancyStor
- */
-template <class Bin = DefaultBin>
-class StandardDeviation
- : public Wrap<StandardDeviation<Bin>,
- DistBase<FancyStor, Bin>,
- DistStatData>
-{
- public:
- /** The base implementation */
- typedef DistBase<DistStor, Bin> Base;
- /** The parameter type. */
- typedef typename DistStor::Params Params;
-
- public:
- /**
- * Construct and initialize this distribution.
- */
- StandardDeviation() {
- this->bin.init(this->params);
- this->setInit();
- }
-};
-
-/**
- * Calculates the per cycle mean and variance of the samples.
- * @sa Stat, DistBase, AvgFancy
- */
-template <class Bin = DefaultBin>
-class AverageDeviation
- : public Wrap<AverageDeviation<Bin>,
- DistBase<AvgFancy, Bin>,
- DistStatData>
-{
- public:
- /** The base implementation */
- typedef DistBase<DistStor, Bin> Base;
- /** The parameter type. */
- typedef typename DistStor::Params Params;
-
- public:
- /**
- * Construct and initialize this distribution.
- */
- AverageDeviation()
- {
- this->bin.init(this->params);
- this->setInit();
- }
-};
-
-/**
- * A vector of distributions.
- * @sa Stat, VectorDistBase, DistStor
- */
-template <class Bin = DefaultBin>
-class VectorDistribution
- : public WrapVec<VectorDistribution<Bin>,
- VectorDistBase<DistStor, Bin>,
- VectorDistStatData>
-{
- public:
- /** The base implementation */
- typedef VectorDistBase<DistStor, Bin> Base;
- /** The parameter type. */
- typedef typename DistStor::Params Params;
-
- public:
- /**
- * Initialize storage and parameters for this distribution.
- * @param size The size of the vector (the number of distributions).
- * @param min The minimum value of the distribution.
- * @param max The maximum value of the distribution.
- * @param bkt The number of values in each bucket.
- * @return A reference to this distribution.
- */
- VectorDistribution &init(int size, Counter min, Counter max, Counter bkt) {
- this->params.min = min;
- this->params.max = max;
- this->params.bucket_size = bkt;
- this->params.size = (int)rint((max - min) / bkt + 1.0);
- this->bin.init(size, this->params);
- this->setInit();
-
- return *this;
- }
-};
-
-/**
- * This is a vector of StandardDeviation stats.
- * @sa Stat, VectorDistBase, FancyStor
- */
-template <class Bin = DefaultBin>
-class VectorStandardDeviation
- : public WrapVec<VectorStandardDeviation<Bin>,
- VectorDistBase<FancyStor, Bin>,
- VectorDistStatData>
-{
- public:
- /** The base implementation */
- typedef VectorDistBase<FancyStor, Bin> Base;
- /** The parameter type. */
- typedef typename DistStor::Params Params;
-
- public:
- /**
- * Initialize storage for this distribution.
- * @param size The size of the vector.
- * @return A reference to this distribution.
- */
- VectorStandardDeviation &init(int size) {
- this->bin.init(size, this->params);
- this->setInit();
-
- return *this;
- }
-};
-
-/**
- * This is a vector of AverageDeviation stats.
- * @sa Stat, VectorDistBase, AvgFancy
- */
-template <class Bin = DefaultBin>
-class VectorAverageDeviation
- : public WrapVec<VectorAverageDeviation<Bin>,
- VectorDistBase<AvgFancy, Bin>,
- VectorDistStatData>
-{
- public:
- /** The base implementation */
- typedef VectorDistBase<AvgFancy, Bin> Base;
- /** The parameter type. */
- typedef typename DistStor::Params Params;
-
- public:
- /**
- * Initialize storage for this distribution.
- * @param size The size of the vector.
- * @return A reference to this distribution.
- */
- VectorAverageDeviation &init(int size) {
- this->bin.init(size, this->params);
- this->setInit();
-
- return *this;
- }
-};
-
-/**
- * A formula for statistics that is calculated when printed. A formula is
- * stored as a tree of Nodes that represent the equation to calculate.
- * @sa Stat, ScalarStat, VectorStat, Node, Temp
- */
-class FormulaBase : public DataAccess
-{
- protected:
- /** The root of the tree which represents the Formula */
- NodePtr root;
- friend class Temp;
-
- public:
- /**
- * Return the result of the Fomula in a vector. If there were no Vector
- * components to the Formula, then the vector is size 1. If there were,
- * like x/y with x being a vector of size 3, then the result returned will
- * be x[0]/y, x[1]/y, x[2]/y, respectively.
- * @return The result vector.
- */
- void result(VResult &vec) const;
-
- /**
- * Return the total Formula result. If there is a Vector
- * component to this Formula, then this is the result of the
- * Formula if the formula is applied after summing all the
- * components of the Vector. For example, if Formula is x/y where
- * x is size 3, then total() will return (x[1]+x[2]+x[3])/y. If
- * there is no Vector component, total() returns the same value as
- * the first entry in the VResult val() returns.
- * @return The total of the result vector.
- */
- Result total() const;
-
- /**
- * Return the number of elements in the tree.
- */
- size_t size() const;
-
- /**
- * Return true if Formula is binned. i.e. any of its children
- * nodes are binned
- * @return True if Formula is binned.
- */
- bool binned() const;
-
- bool check() const { return true; }
-
- /**
- * Formulas don't need to be reset
- */
- void reset();
-
- /**
- *
- */
- bool zero() const;
-
- /**
- *
- */
- void update(StatData *);
-
- std::string str() const;
-};
-
-class FormulaData : public VectorData
-{
- public:
- virtual std::string str() const = 0;
- virtual bool check() const { return true; }
-};
-
-template <class Stat>
-class FormulaStatData : public FormulaData
-{
- protected:
- Stat &s;
- mutable VResult vec;
- mutable VCounter cvec;
-
- public:
- FormulaStatData(Stat &stat) : s(stat) {}
-
- virtual bool binned() const { return s.binned(); }
- virtual bool zero() const { return s.zero(); }
- virtual void reset() { s.reset(); }
-
- virtual size_t size() const { return s.size(); }
- virtual const VResult &result() const
- {
- s.result(vec);
- return vec;
- }
- virtual Result total() const { return s.total(); }
- virtual VCounter &value() const { return cvec; }
- virtual void visit(Visit &visitor)
- {
- update();
- s.update(this);
- visitor.visit(*this);
- }
- virtual std::string str() const { return s.str(); }
-};
-
-class Temp;
-class Formula
- : public WrapVec<Formula,
- FormulaBase,
- FormulaStatData>
-{
- public:
- /**
- * Create and initialize thie formula, and register it with the database.
- */
- Formula();
-
- /**
- * Create a formula with the given root node, register it with the
- * database.
- * @param r The root of the expression tree.
- */
- Formula(Temp r);
-
- /**
- * Set an unitialized Formula to the given root.
- * @param r The root of the expression tree.
- * @return a reference to this formula.
- */
- const Formula &operator=(Temp r);
-
- /**
- * Add the given tree to the existing one.
- * @param r The root of the expression tree.
- * @return a reference to this formula.
- */
- const Formula &operator+=(Temp r);
-};
-
-class FormulaNode : public Node
-{
- private:
- const Formula &formula;
- mutable VResult vec;
-
- public:
- FormulaNode(const Formula &f) : formula(f) {}
-
- virtual size_t size() const { return formula.size(); }
- virtual const VResult &result() const { formula.result(vec); return vec; }
- virtual Result total() const { return formula.total(); }
- virtual bool binned() const { return formula.binned(); }
-
- virtual std::string str() const { return formula.str(); }
-};
-
-/**
- * Helper class to construct formula node trees.
- */
-class Temp
-{
- protected:
- /**
- * Pointer to a Node object.
- */
- NodePtr node;
-
- public:
- /**
- * Copy the given pointer to this class.
- * @param n A pointer to a Node object to copy.
- */
- Temp(NodePtr n) : node(n) { }
-
- /**
- * Return the node pointer.
- * @return the node pointer.
- */
- operator NodePtr&() { return node;}
-
- public:
- /**
- * Create a new ScalarStatNode.
- * @param s The ScalarStat to place in a node.
- */
- template <class Bin>
- Temp(const Scalar<Bin> &s)
- : node(new ScalarStatNode(s.statData())) { }
-
- /**
- * Create a new ScalarStatNode.
- * @param s The ScalarStat to place in a node.
- */
- Temp(const Value &s)
- : node(new ScalarStatNode(s.statData())) { }
-
- /**
- * Create a new ScalarStatNode.
- * @param s The ScalarStat to place in a node.
- */
- template <class Bin>
- Temp(const Average<Bin> &s)
- : node(new ScalarStatNode(s.statData())) { }
-
- /**
- * Create a new VectorStatNode.
- * @param s The VectorStat to place in a node.
- */
- template <class Bin>
- Temp(const Vector<Bin> &s)
- : node(new VectorStatNode(s.statData())) { }
-
- /**
- *
- */
- Temp(const Formula &f)
- : node(new FormulaNode(f)) { }
-
- /**
- * Create a new ScalarProxyNode.
- * @param p The ScalarProxy to place in a node.
- */
- template <class Storage, class Bin>
- Temp(const ScalarProxy<Storage, Bin> &p)
- : node(new ScalarProxyNode<Storage, Bin>(p)) { }
-
- /**
- * Create a ConstNode
- * @param value The value of the const node.
- */
- Temp(signed char value)
- : node(new ConstNode<signed char>(value)) {}
-
- /**
- * Create a ConstNode
- * @param value The value of the const node.
- */
- Temp(unsigned char value)
- : node(new ConstNode<unsigned char>(value)) {}
-
- /**
- * Create a ConstNode
- * @param value The value of the const node.
- */
- Temp(signed short value)
- : node(new ConstNode<signed short>(value)) {}
-
- /**
- * Create a ConstNode
- * @param value The value of the const node.
- */
- Temp(unsigned short value)
- : node(new ConstNode<unsigned short>(value)) {}
-
- /**
- * Create a ConstNode
- * @param value The value of the const node.
- */
- Temp(signed int value)
- : node(new ConstNode<signed int>(value)) {}
-
- /**
- * Create a ConstNode
- * @param value The value of the const node.
- */
- Temp(unsigned int value)
- : node(new ConstNode<unsigned int>(value)) {}
-
- /**
- * Create a ConstNode
- * @param value The value of the const node.
- */
- Temp(signed long value)
- : node(new ConstNode<signed long>(value)) {}
-
- /**
- * Create a ConstNode
- * @param value The value of the const node.
- */
- Temp(unsigned long value)
- : node(new ConstNode<unsigned long>(value)) {}
-
- /**
- * Create a ConstNode
- * @param value The value of the const node.
- */
- Temp(signed long long value)
- : node(new ConstNode<signed long long>(value)) {}
-
- /**
- * Create a ConstNode
- * @param value The value of the const node.
- */
- Temp(unsigned long long value)
- : node(new ConstNode<unsigned long long>(value)) {}
-
- /**
- * Create a ConstNode
- * @param value The value of the const node.
- */
- Temp(float value)
- : node(new ConstNode<float>(value)) {}
-
- /**
- * Create a ConstNode
- * @param value The value of the const node.
- */
- Temp(double value)
- : node(new ConstNode<double>(value)) {}
-};
-
-
-/**
- * @}
- */
-
-void check();
-void reset();
-void registerResetCallback(Callback *cb);
-
-inline Temp
-operator+(Temp l, Temp r)
-{
- return NodePtr(new BinaryNode<std::plus<Result> >(l, r));
-}
-
-inline Temp
-operator-(Temp l, Temp r)
-{
- return NodePtr(new BinaryNode<std::minus<Result> >(l, r));
-}
-
-inline Temp
-operator*(Temp l, Temp r)
-{
- return NodePtr(new BinaryNode<std::multiplies<Result> >(l, r));
-}
-
-inline Temp
-operator/(Temp l, Temp r)
-{
- return NodePtr(new BinaryNode<std::divides<Result> >(l, r));
-}
-
-inline Temp
-operator-(Temp l)
-{
- return NodePtr(new UnaryNode<std::negate<Result> >(l));
-}
-
-template <typename T>
-inline Temp
-constant(T val)
-{
- return NodePtr(new ConstNode<T>(val));
-}
-
-inline Temp
-sum(Temp val)
-{
- return NodePtr(new SumNode<std::plus<Result> >(val));
-}
-
-/* namespace Stats */ }
-
-#endif // __BASE_STATISTICS_HH__
diff --git a/base/stats/text.cc b/base/stats/text.cc
deleted file mode 100644
index 3d77ff87d..000000000
--- a/base/stats/text.cc
+++ /dev/null
@@ -1,735 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#if defined(__APPLE__)
-#define _GLIBCPP_USE_C99 1
-#endif
-
-#include <iostream>
-#include <fstream>
-#include <string>
-
-#include "base/misc.hh"
-#include "base/statistics.hh"
-#include "base/stats/statdb.hh"
-#include "base/stats/text.hh"
-#include "base/stats/visit.hh"
-
-using namespace std;
-
-#ifndef NAN
-float __nan();
-/** Define Not a number. */
-#define NAN (__nan())
-/** Need to define __nan() */
-#define __M5_NAN
-#endif
-
-#ifdef __M5_NAN
-float
-__nan()
-{
- union {
- uint32_t ui;
- float f;
- } nan;
-
- nan.ui = 0x7fc00000;
- return nan.f;
-}
-#endif
-
-namespace Stats {
-
-Text::Text()
- : mystream(false), stream(NULL), compat(false), descriptions(false)
-{
-}
-
-Text::Text(std::ostream &stream)
- : mystream(false), stream(NULL), compat(false), descriptions(false)
-{
- open(stream);
-}
-
-Text::Text(const std::string &file)
- : mystream(false), stream(NULL), compat(false), descriptions(false)
-{
- open(file);
-}
-
-
-Text::~Text()
-{
- if (mystream) {
- assert(stream);
- delete stream;
- }
-}
-
-void
-Text::open(std::ostream &_stream)
-{
- if (stream)
- panic("stream already set!");
-
- mystream = false;
- stream = &_stream;
- assert(valid());
-}
-
-void
-Text::open(const std::string &file)
-{
- if (stream)
- panic("stream already set!");
-
- mystream = true;
- stream = new ofstream(file.c_str(), ios::trunc);
- assert(valid());
-}
-
-bool
-Text::valid() const
-{
- return stream != NULL;
-}
-
-void
-Text::output()
-{
- using namespace Database;
-
- ccprintf(*stream, "\n---------- Begin Simulation Statistics ----------\n");
- if (bins().empty() || bins().size() == 1) {
- stat_list_t::const_iterator i, end = stats().end();
- for (i = stats().begin(); i != end; ++i)
- (*i)->visit(*this);
- } else {
- ccprintf(*stream, "PRINTING BINNED STATS\n");
- bin_list_t::iterator i, end = bins().end();
- for (i = bins().begin(); i != end; ++i) {
- MainBin *bin = *i;
- bin->activate();
- ccprintf(*stream,"---%s Bin------------\n", bin->name());
- stat_list_t::const_iterator i, end = stats().end();
- for (i = stats().begin(); i != end; ++i)
- (*i)->visit(*this);
- ccprintf(*stream, "---------------------------------\n");
- }
- }
- ccprintf(*stream, "\n---------- End Simulation Statistics ----------\n");
- stream->flush();
-}
-
-bool
-Text::noOutput(const StatData &data)
-{
- if (!(data.flags & print))
- return true;
-
- if (data.prereq && data.prereq->zero())
- return true;
-
- return false;
-}
-
-string
-ValueToString(Result value, int precision, bool compat)
-{
- stringstream val;
-
- if (!isnan(value)) {
- if (precision != -1)
- val.precision(precision);
- else if (value == rint(value))
- val.precision(0);
-
- val.unsetf(ios::showpoint);
- val.setf(ios::fixed);
- val << value;
- } else {
- val << (compat ? "<err: div-0>" : "no value");
- }
-
- return val.str();
-}
-
-struct ScalarPrint
-{
- Result value;
- string name;
- string desc;
- StatFlags flags;
- bool compat;
- bool descriptions;
- int precision;
- Result pdf;
- Result cdf;
-
- void operator()(ostream &stream) const;
-};
-
-void
-ScalarPrint::operator()(ostream &stream) const
-{
- if (flags & nozero && value == 0.0 ||
- flags & nonan && isnan(value))
- return;
-
- stringstream pdfstr, cdfstr;
-
- if (!isnan(pdf))
- ccprintf(pdfstr, "%.2f%%", pdf * 100.0);
-
- if (!isnan(cdf))
- ccprintf(cdfstr, "%.2f%%", cdf * 100.0);
-
- if (compat && flags & __substat) {
- ccprintf(stream, "%32s %12s %10s %10s", name,
- ValueToString(value, precision, compat), pdfstr, cdfstr);
- } else {
- ccprintf(stream, "%-40s %12s %10s %10s", name,
- ValueToString(value, precision, compat), pdfstr, cdfstr);
- }
-
- if (descriptions) {
- if (!desc.empty())
- ccprintf(stream, " # %s", desc);
- }
- stream << endl;
-}
-
-struct VectorPrint
-{
- string name;
- string desc;
- vector<string> subnames;
- vector<string> subdescs;
- StatFlags flags;
- bool compat;
- bool descriptions;
- int precision;
- VResult vec;
- Result total;
-
- void operator()(ostream &stream) const;
-};
-
-void
-VectorPrint::operator()(std::ostream &stream) const
-{
- int _size = vec.size();
- Result _total = 0.0;
-
- if (flags & (pdf | cdf)) {
- for (int i = 0; i < _size; ++i) {
- _total += vec[i];
- }
- }
-
- string base = name + (compat ? "_" : "::");
-
- ScalarPrint print;
- print.name = name;
- print.desc = desc;
- print.precision = precision;
- print.descriptions = descriptions;
- print.flags = flags;
- print.pdf = NAN;
- print.cdf = NAN;
-
- bool havesub = !subnames.empty();
-
- if (_size == 1) {
- print.value = vec[0];
- print(stream);
- } else if (!compat) {
- for (int i = 0; i < _size; ++i) {
- if (havesub && (i >= subnames.size() || subnames[i].empty()))
- continue;
-
- print.name = base + (havesub ? subnames[i] : to_string(i));
- print.desc = subdescs.empty() ? desc : subdescs[i];
- print.value = vec[i];
-
- if (_total && (flags & pdf)) {
- print.pdf = vec[i] / _total;
- print.cdf += print.pdf;
- }
-
- print(stream);
- }
-
- if (flags & ::Stats::total) {
- print.name = base + "total";
- print.desc = desc;
- print.value = total;
- print(stream);
- }
- } else {
- if (flags & ::Stats::total) {
- print.value = total;
- print(stream);
- }
-
- Result _pdf = 0.0;
- Result _cdf = 0.0;
- if (flags & dist) {
- ccprintf(stream, "%s.start_dist\n", name);
- for (int i = 0; i < _size; ++i) {
- print.name = havesub ? subnames[i] : to_string(i);
- print.desc = subdescs.empty() ? desc : subdescs[i];
- print.flags |= __substat;
- print.value = vec[i];
-
- if (_total) {
- _pdf = vec[i] / _total;
- _cdf += _pdf;
- }
-
- if (flags & pdf)
- print.pdf = _pdf;
- if (flags & cdf)
- print.cdf = _cdf;
-
- print(stream);
- }
- ccprintf(stream, "%s.end_dist\n", name);
- } else {
- for (int i = 0; i < _size; ++i) {
- if (havesub && subnames[i].empty())
- continue;
-
- print.name = base;
- print.name += havesub ? subnames[i] : to_string(i);
- print.desc = subdescs.empty() ? desc : subdescs[i];
- print.value = vec[i];
-
- if (_total) {
- _pdf = vec[i] / _total;
- _cdf += _pdf;
- } else {
- _pdf = _cdf = NAN;
- }
-
- if (flags & pdf) {
- print.pdf = _pdf;
- print.cdf = _cdf;
- }
-
- print(stream);
- }
- }
- }
-}
-
-struct DistPrint
-{
- string name;
- string desc;
- StatFlags flags;
- bool compat;
- bool descriptions;
- int precision;
-
- Result min_val;
- Result max_val;
- Result underflow;
- Result overflow;
- VResult vec;
- Result sum;
- Result squares;
- Result samples;
-
- Counter min;
- Counter max;
- Counter bucket_size;
- int size;
- bool fancy;
-
- void operator()(ostream &stream) const;
-};
-
-void
-DistPrint::operator()(ostream &stream) const
-{
- if (fancy) {
- ScalarPrint print;
- string base = name + (compat ? "_" : "::");
-
- print.precision = precision;
- print.flags = flags;
- print.compat = compat;
- print.descriptions = descriptions;
- print.desc = desc;
- print.pdf = NAN;
- print.cdf = NAN;
-
- print.name = base + "mean";
- print.value = samples ? sum / samples : NAN;
- print(stream);
-
- print.name = base + "stdev";
- print.value = samples ? sqrt((samples * squares - sum * sum) /
- (samples * (samples - 1.0))) : NAN;
- print(stream);
-
- print.name = "**Ignore: " + base + "TOT";
- print.value = samples;
- print(stream);
- return;
- }
-
- assert(size == vec.size());
-
- Result total = 0.0;
-
- total += underflow;
- for (int i = 0; i < size; ++i)
- total += vec[i];
- total += overflow;
-
- string base = name + (compat ? "." : "::");
-
- ScalarPrint print;
- print.desc = compat ? "" : desc;
- print.flags = flags;
- print.compat = compat;
- print.descriptions = descriptions;
- print.precision = precision;
- print.pdf = NAN;
- print.cdf = NAN;
-
- if (compat) {
- ccprintf(stream, "%-42s", base + "start_dist");
- if (descriptions && !desc.empty())
- ccprintf(stream, " # %s", desc);
- stream << endl;
- }
-
- print.name = base + "samples";
- print.value = samples;
- print(stream);
-
- print.name = base + "min_value";
- print.value = min_val;
- print(stream);
-
- if (!compat || underflow > 0.0) {
- print.name = base + "underflows";
- print.value = underflow;
- if (!compat && total) {
- print.pdf = underflow / total;
- print.cdf += print.pdf;
- }
- print(stream);
- }
-
-
- if (!compat) {
- for (int i = 0; i < size; ++i) {
- stringstream namestr;
- namestr << name;
-
- Counter low = i * bucket_size + min;
- Counter high = ::min(low + bucket_size, max);
- namestr << low;
- if (low < high)
- namestr << "-" << high;
-
- print.name = namestr.str();
- print.value = vec[i];
- if (total) {
- print.pdf = vec[i] / total;
- print.cdf += print.pdf;
- }
- print(stream);
- }
-
- } else {
- Counter _min;
- Result _pdf;
- Result _cdf = 0.0;
-
- print.flags = flags | __substat;
-
- for (int i = 0; i < size; ++i) {
- if (flags & nozero && vec[i] == 0.0 ||
- flags & nonan && isnan(vec[i]))
- continue;
-
- _min = i * bucket_size + min;
- _pdf = vec[i] / total * 100.0;
- _cdf += _pdf;
-
-
- print.name = ValueToString(_min, 0, compat);
- print.value = vec[i];
- print.pdf = (flags & pdf) ? _pdf : NAN;
- print.cdf = (flags & cdf) ? _cdf : NAN;
- print(stream);
- }
-
- print.flags = flags;
- }
-
- if (!compat || overflow > 0.0) {
- print.name = base + "overflows";
- print.value = overflow;
- if (!compat && total) {
- print.pdf = overflow / total;
- print.cdf += print.pdf;
- } else {
- print.pdf = NAN;
- print.cdf = NAN;
- }
- print(stream);
- }
-
- print.pdf = NAN;
- print.cdf = NAN;
-
- if (!compat) {
- print.name = base + "total";
- print.value = total;
- print(stream);
- }
-
- print.name = base + "max_value";
- print.value = max_val;
- print(stream);
-
- if (!compat && samples != 0) {
- print.name = base + "mean";
- print.value = sum / samples;
- print(stream);
-
- print.name = base + "stdev";
- print.value = sqrt((samples * squares - sum * sum) /
- (samples * (samples - 1.0)));
- print(stream);
- }
-
- if (compat)
- ccprintf(stream, "%send_dist\n\n", base);
-}
-
-void
-Text::visit(const ScalarData &data)
-{
- if (noOutput(data))
- return;
-
- ScalarPrint print;
- print.value = data.result();
- print.name = data.name;
- print.desc = data.desc;
- print.flags = data.flags;
- print.compat = compat;
- print.descriptions = descriptions;
- print.precision = data.precision;
- print.pdf = NAN;
- print.cdf = NAN;
-
- print(*stream);
-}
-
-void
-Text::visit(const VectorData &data)
-{
- if (noOutput(data))
- return;
-
- int size = data.size();
- VectorPrint print;
-
- print.name = data.name;
- print.desc = data.desc;
- print.flags = data.flags;
- print.compat = compat;
- print.descriptions = descriptions;
- print.precision = data.precision;
- print.vec = data.result();
- print.total = data.total();
-
- if (!data.subnames.empty()) {
- for (int i = 0; i < size; ++i) {
- if (!data.subnames[i].empty()) {
- print.subnames = data.subnames;
- print.subnames.resize(size);
- for (int i = 0; i < size; ++i) {
- if (!data.subnames[i].empty() &&
- !data.subdescs[i].empty()) {
- print.subdescs = data.subdescs;
- print.subdescs.resize(size);
- break;
- }
- }
- break;
- }
- }
- }
-
- print(*stream);
-}
-
-void
-Text::visit(const Vector2dData &data)
-{
- if (noOutput(data))
- return;
-
- bool havesub = false;
- VectorPrint print;
-
- print.subnames = data.y_subnames;
- print.flags = data.flags;
- print.compat = compat;
- print.descriptions = descriptions;
- print.precision = data.precision;
-
- if (!data.subnames.empty()) {
- for (int i = 0; i < data.x; ++i)
- if (!data.subnames[i].empty())
- havesub = true;
- }
-
- VResult tot_vec(data.y);
- Result super_total = 0.0;
- for (int i = 0; i < data.x; ++i) {
- if (havesub && (i >= data.subnames.size() || data.subnames[i].empty()))
- continue;
-
- int iy = i * data.y;
- VResult yvec(data.y);
-
- Result total = 0.0;
- for (int j = 0; j < data.y; ++j) {
- yvec[j] = data.cvec[iy + j];
- tot_vec[j] += yvec[j];
- total += yvec[j];
- super_total += yvec[j];
- }
-
- print.name = data.name + "_" + (havesub ? data.subnames[i] : to_string(i));
- print.desc = data.desc;
- print.vec = yvec;
- print.total = total;
- print(*stream);
- }
-
- if ((data.flags & ::Stats::total) && (data.x > 1)) {
- print.name = data.name;
- print.desc = data.desc;
- print.vec = tot_vec;
- print.total = super_total;
- print(*stream);
- }
-}
-
-void
-Text::visit(const DistData &data)
-{
- if (noOutput(data))
- return;
-
- DistPrint print;
-
- print.name = data.name;
- print.desc = data.desc;
- print.flags = data.flags;
- print.compat = compat;
- print.descriptions = descriptions;
- print.precision = data.precision;
-
- print.min_val = data.data.min_val;
- print.max_val = data.data.max_val;
- print.underflow = data.data.underflow;
- print.overflow = data.data.overflow;
- print.vec.resize(data.data.cvec.size());
- for (int i = 0; i < print.vec.size(); ++i)
- print.vec[i] = (Result)data.data.cvec[i];
- print.sum = data.data.sum;
- print.squares = data.data.squares;
- print.samples = data.data.samples;
-
- print.min = data.data.min;
- print.max = data.data.max;
- print.bucket_size = data.data.bucket_size;
- print.size = data.data.size;
- print.fancy = data.data.fancy;
-
- print(*stream);
-}
-
-void
-Text::visit(const VectorDistData &data)
-{
- if (noOutput(data))
- return;
-
- for (int i = 0; i < data.size(); ++i) {
- DistPrint print;
-
- print.name = data.name +
- (data.subnames[i].empty() ? ("_" + to_string(i)) : data.subnames[i]);
- print.desc = data.subdescs[i].empty() ? data.desc : data.subdescs[i];
- print.flags = data.flags;
- print.compat = compat;
- print.descriptions = descriptions;
- print.precision = data.precision;
-
- print.min_val = data.data[i].min_val;
- print.max_val = data.data[i].max_val;
- print.underflow = data.data[i].underflow;
- print.overflow = data.data[i].overflow;
- print.vec.resize(data.data[i].cvec.size());
- for (int j = 0; j < print.vec.size(); ++j)
- print.vec[j] = (Result)data.data[i].cvec[j];
- print.sum = data.data[i].sum;
- print.squares = data.data[i].squares;
- print.samples = data.data[i].samples;
-
- print.min = data.data[i].min;
- print.max = data.data[i].max;
- print.bucket_size = data.data[i].bucket_size;
- print.size = data.data[i].size;
- print.fancy = data.data[i].fancy;
-
- print(*stream);
- }
-}
-
-void
-Text::visit(const FormulaData &data)
-{
- visit((const VectorData &)data);
-}
-
-/* namespace Stats */ }
diff --git a/base/traceflags.py b/base/traceflags.py
deleted file mode 100644
index 47ed59c3a..000000000
--- a/base/traceflags.py
+++ /dev/null
@@ -1,325 +0,0 @@
-#!/usr/bin/env python
-
-# Copyright (c) 2004-2005 The Regents of The University of Michigan
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met: redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer;
-# redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution;
-# neither the name of the copyright holders nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#
-# This file generates the header and source files for the flags
-# that control the tracing facility.
-#
-
-import sys
-
-if len(sys.argv) != 2:
- print "%s: Need argument (basename of cc/hh files)" % sys.argv[0]
- sys.exit(1)
-
-hhfilename = sys.argv[1] + '.hh'
-ccfilename = sys.argv[1] + '.cc'
-
-#
-# The list of trace flags that can be used to condition DPRINTFs etc.
-# To define a new flag, simply add it to this list.
-#
-baseFlags = [
- 'TCPIP',
- 'Bus',
- 'ScsiDisk',
- 'ScsiCtrl',
- 'ScsiNone',
- 'DMA',
- 'DMAReadVerbose',
- 'DMAWriteVerbose',
- 'TLB',
- 'SimpleDisk',
- 'SimpleDiskData',
- 'Clock',
- 'Regs',
- 'MC146818',
- 'IPI',
- 'Timer',
- 'Mbox',
- 'PCIA',
- 'PCIDEV',
- 'PciConfigAll',
- 'ISP',
- 'BADADDR',
- 'Console',
- 'ConsolePoll',
- 'ConsoleVerbose',
- 'AlphaConsole',
- 'Flow',
- 'Interrupt',
- 'Fault',
- 'Cycle',
- 'Loader',
- 'MMU',
- 'Ethernet',
- 'EthernetPIO',
- 'EthernetDMA',
- 'EthernetData',
- 'EthernetDesc',
- 'EthernetIntr',
- 'EthernetSM',
- 'EthernetCksum',
- 'GDBMisc',
- 'GDBAcc',
- 'GDBRead',
- 'GDBWrite',
- 'GDBSend',
- 'GDBRecv',
- 'GDBExtra',
- 'VtoPhys',
- 'Printf',
- 'DebugPrintf',
- 'Serialize',
- 'Event',
- 'PCEvent',
- 'Syscall',
- 'SyscallVerbose',
- 'DiskImage',
- 'DiskImageRead',
- 'DiskImageWrite',
- 'InstExec',
- 'BPredRAS',
- 'Cache',
- 'IIC',
- 'IICMore',
- 'MSHR',
- 'Chains',
- 'Pipeline',
- 'Stats',
- 'StatEvents',
- 'Context',
- 'Config',
- 'Sampler',
- 'WriteBarrier',
- 'IdeCtrl',
- 'IdeDisk',
- 'Tsunami',
- 'Uart',
- 'Split',
- 'SQL',
- 'Thread',
- 'Fetch',
- 'Decode',
- 'Rename',
- 'IEW',
- 'Commit',
- 'IQ',
- 'ROB',
- 'FreeList',
- 'RenameMap',
- 'LSQ',
- 'LSQUnit',
- 'StoreSet',
- 'MemDepUnit',
- 'DynInst',
- 'FullCPU',
- 'CommitRate',
- 'OzoneCPU',
- 'FE',
- 'IBE',
- 'BE',
- 'OzoneLSQ',
- 'HWPrefetch',
- 'Stack',
- 'DependGraph',
- 'Activity',
- 'Scoreboard',
- 'Writeback',
- 'Checker'
- ]
-
-#
-# "Compound" flags correspond to a set of base flags. These exist
-# solely for convenience in setting them via the command line: if a
-# compound flag is specified, all of the corresponding base flags are
-# set. Compound flags cannot be used directly in DPRINTFs etc.
-# To define a new compound flag, add a new entry to this hash
-# following the existing examples.
-#
-compoundFlagMap = {
- 'GDBAll' : [ 'GDBMisc', 'GDBAcc', 'GDBRead', 'GDBWrite', 'GDBSend', 'GDBRecv', 'GDBExtra' ],
- 'ScsiAll' : [ 'ScsiDisk', 'ScsiCtrl', 'ScsiNone' ],
- 'DiskImageAll' : [ 'DiskImage', 'DiskImageRead', 'DiskImageWrite' ],
- 'EthernetAll' : [ 'Ethernet', 'EthernetPIO', 'EthernetDMA', 'EthernetData' , 'EthernetDesc', 'EthernetIntr', 'EthernetSM', 'EthernetCksum' ],
- 'EthernetNoData' : [ 'Ethernet', 'EthernetPIO', 'EthernetDesc', 'EthernetIntr', 'EthernetSM', 'EthernetCksum' ],
- 'IdeAll' : [ 'IdeCtrl', 'IdeDisk' ],
- 'FullCPUAll' : [ 'Fetch', 'Decode', 'Rename', 'IEW', 'Commit', 'IQ', 'ROB', 'FreeList', 'RenameMap', 'LSQ', 'LSQUnit', 'StoreSet', 'MemDepUnit', 'DynInst', 'FullCPU', 'Activity','Scoreboard','Writeback'],
- 'OzoneCPUAll' : [ 'BE', 'FE', 'IBE', 'OzoneLSQ', 'OzoneCPU']
-}
-
-#############################################################
-#
-# Everything below this point generates the appropriate C++
-# declarations and definitions for the trace flags. If you are simply
-# adding or modifying flag definitions, you should not have to change
-# anything below.
-#
-
-import sys
-
-# extract just the compound flag names into a list
-compoundFlags = []
-compoundFlags.extend(compoundFlagMap.keys())
-compoundFlags.sort()
-
-#
-# First generate the header file. This defines the Flag enum
-# and some extern declarations for the .cc file.
-#
-try:
- hhfile = file(hhfilename, 'w')
-except IOError, e:
- sys.exit("can't open %s: %s" % (hhfilename, e))
-
-# file header boilerplate
-print >>hhfile, '''
-/*
- * DO NOT EDIT THIS FILE!
- *
- * Automatically generated from traceflags.py
- */
-
-#ifndef __BASE_TRACE_FLAGS_HH__
-#define __BASE_TRACE_FLAGS_HH__
-
-namespace Trace {
-
-enum Flags {
-''',
-
-# Generate the enum. Base flags come first, then compound flags.
-idx = 0
-for flag in baseFlags:
- print >>hhfile, ' %s = %d,' % (flag, idx)
- idx += 1
-
-numBaseFlags = idx
-print >>hhfile, ' NumFlags = %d,' % idx
-
-# put a comment in here to separate base from compound flags
-print >>hhfile, '''
- // The remaining enum values are *not* valid indices for Trace::flags.
- // They are "compound" flags, which correspond to sets of base
- // flags, and are used only by TraceParamContext::setFlags().
-''',
-
-for flag in compoundFlags:
- print >>hhfile, ' %s = %d,' % (flag, idx)
- idx += 1
-
-numCompoundFlags = idx - numBaseFlags
-print >>hhfile, ' NumCompoundFlags = %d' % numCompoundFlags
-
-# trailer boilerplate
-print >>hhfile, '''\
-}; // enum Flags
-
-// Array of strings for SimpleEnumParam
-extern const char *flagStrings[];
-extern const int numFlagStrings;
-
-// Array of arraay pointers: for each compound flag, gives the list of
-// base flags to set. Inidividual flag arrays are terminated by -1.
-extern const Flags *compoundFlags[];
-
-/* namespace Trace */ }
-
-#endif // __BASE_TRACE_FLAGS_HH__
-''',
-
-hhfile.close()
-
-#
-#
-# Print out .cc file with array definitions.
-#
-#
-try:
- ccfile = file(ccfilename, 'w')
-except OSError, e:
- sys.exit("can't open %s: %s" % (ccfilename, e))
-
-# file header
-print >>ccfile, '''
-/*
- * DO NOT EDIT THIS FILE!
- *
- * Automatically generated from traceflags.pl.
- */
-
-#include "base/traceflags.hh"
-
-using namespace Trace;
-
-const char *Trace::flagStrings[] =
-{
-''',
-
-# The string array is used by SimpleEnumParam to map the strings
-# provided by the user to enum values.
-for flag in baseFlags:
- print >>ccfile, ' "%s",' % flag
-
-for flag in compoundFlags:
- print >>ccfile, ' "%s",' % flag
-
-print >>ccfile, '};\n'
-
-numFlagStrings = len(baseFlags) + len(compoundFlags);
-
-print >>ccfile, 'const int Trace::numFlagStrings = %d;' % numFlagStrings
-print >>ccfile
-
-#
-# Now define the individual compound flag arrays. There is an array
-# for each compound flag listing the component base flags.
-#
-
-for flag in compoundFlags:
- flags = compoundFlagMap[flag]
- flags.append('(Flags)-1')
- print >>ccfile, 'static const Flags %sMap[] =' % flag
- print >>ccfile, '{ %s };' % (', '.join(flags))
- print >>ccfile
-
-#
-# Finally the compoundFlags[] array maps the compound flags
-# to their individual arrays/
-#
-print >>ccfile, 'const Flags *Trace::compoundFlags[] ='
-print >>ccfile, '{'
-
-for flag in compoundFlags:
- print >>ccfile, ' %sMap,' % flag
-
-# file trailer
-print >>ccfile, '};'
-
-ccfile.close()
-
diff --git a/build/SConstruct b/build/SConstruct
deleted file mode 100644
index 110a0f250..000000000
--- a/build/SConstruct
+++ /dev/null
@@ -1,421 +0,0 @@
-# -*- mode:python -*-
-
-# Copyright (c) 2004-2005 The Regents of The University of Michigan
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met: redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer;
-# redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution;
-# neither the name of the copyright holders nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-###################################################
-#
-# SCons top-level build description (SConstruct) file.
-#
-# To build M5, you need a directory with three things:
-# 1. A copy of this file (named SConstruct).
-# 2. A link named 'm5' to the top of the M5 simulator source tree.
-# 3. A link named 'ext' to the top of the M5 external source tree.
-#
-# Then type 'scons' to build the default configuration (see below), or
-# 'scons <CONFIG>/<binary>' to build some other configuration (e.g.,
-# 'ALPHA_FS/m5.opt' for the optimized full-system version).
-#
-###################################################
-
-# Python library imports
-import sys
-import os
-
-# Check for recent-enough Python and SCons versions
-EnsurePythonVersion(2,3)
-EnsureSConsVersion(0,96)
-
-# The absolute path to the current directory (where this file lives).
-ROOT = Dir('.').abspath
-
-# Paths to the M5 and external source trees (local symlinks).
-SRCDIR = os.path.join(ROOT, 'm5')
-EXT_SRCDIR = os.path.join(ROOT, 'ext')
-
-# Check for 'm5' and 'ext' links, die if they don't exist.
-if not os.path.isdir(SRCDIR):
- print "Error: '%s' must be a link to the M5 source tree." % SRCDIR
- Exit(1)
-
-if not os.path.isdir('ext'):
- print "Error: '%s' must be a link to the M5 external source tree." \
- % EXT_SRCDIR
- Exit(1)
-
-# tell python where to find m5 python code
-sys.path.append(os.path.join(SRCDIR, 'python'))
-
-###################################################
-#
-# Figure out which configurations to set up.
-#
-#
-# It's prohibitive to do all the combinations of base configurations
-# and options, so we have to infer which ones the user wants.
-#
-# 1. If there are command-line targets, the configuration(s) are inferred
-# from the directories of those targets. If scons was invoked from a
-# subdirectory (using 'scons -u'), those targets have to be
-# interpreted relative to that subdirectory.
-#
-# 2. If there are no command-line targets, and scons was invoked from a
-# subdirectory (using 'scons -u'), the configuration is inferred from
-# the name of the subdirectory.
-#
-# 3. If there are no command-line targets and scons was invoked from
-# the root build directory, a default configuration is used. The
-# built-in default is ALPHA_SE, but this can be overridden by setting the
-# M5_DEFAULT_CONFIG shell environment veriable.
-#
-# In cases 2 & 3, the specific file target defaults to 'm5.debug', but
-# this can be overridden by setting the M5_DEFAULT_BINARY shell
-# environment veriable.
-#
-###################################################
-
-# Find default configuration & binary.
-default_config = os.environ.get('M5_DEFAULT_CONFIG', 'ALPHA_SE')
-default_binary = os.environ.get('M5_DEFAULT_BINARY', 'm5.debug')
-
-# Ask SCons which directory it was invoked from. If you invoke SCons
-# from a subdirectory you must use the '-u' flag.
-launch_dir = GetLaunchDir()
-
-# Build a list 'my_targets' of all the targets relative to ROOT.
-if launch_dir == ROOT:
- # invoked from root build dir
- if len(COMMAND_LINE_TARGETS) != 0:
- # easy: use specified targets as is
- my_targets = COMMAND_LINE_TARGETS
- else:
- # default target (ALPHA_SE/m5.debug, unless overridden)
- target = os.path.join(default_config, default_binary)
- my_targets = [target]
- Default(target)
-else:
- # invoked from subdirectory
- if not launch_dir.startswith(ROOT):
- print "Error: launch dir (%s) not a subdirectory of ROOT (%s)!" \
- (launch_dir, ROOT)
- Exit(1)
- # make launch_dir relative to ROOT (strip ROOT plus slash off front)
- launch_dir = launch_dir[len(ROOT)+1:]
- if len(COMMAND_LINE_TARGETS) != 0:
- # make specified targets relative to ROOT
- my_targets = map(lambda x: os.path.join(launch_dir, x),
- COMMAND_LINE_TARGETS)
- else:
- # build default binary (m5.debug, unless overridden) using the
- # config inferred by the invocation directory (the first
- # subdirectory after ROOT)
- target = os.path.join(launch_dir.split('/')[0], default_binary)
- my_targets = [target]
- Default(target)
-
-# Normalize target paths (gets rid of '..' in the middle, etc.)
-my_targets = map(os.path.normpath, my_targets)
-
-# Generate a list of the unique configs that the collected targets reference.
-build_dirs = []
-for t in my_targets:
- dir = t.split('/')[0]
- if dir not in build_dirs:
- build_dirs.append(dir)
-
-###################################################
-#
-# Set up the default build environment. This environment is copied
-# and modified according to each selected configuration.
-#
-###################################################
-
-env = Environment(ENV = os.environ, # inherit user's environment vars
- ROOT = ROOT,
- SRCDIR = SRCDIR,
- EXT_SRCDIR = EXT_SRCDIR)
-
-env.SConsignFile("sconsign")
-
-# I waffle on this setting... it does avoid a few painful but
-# unnecessary builds, but it also seems to make trivial builds take
-# noticeably longer.
-if False:
- env.TargetSignatures('content')
-
-# M5_EXT is used by isa_parser.py to find the PLY package.
-env.Append(ENV = { 'M5_EXT' : EXT_SRCDIR })
-
-# Set up default C++ compiler flags
-env.Append(CCFLAGS='-pipe')
-env.Append(CCFLAGS='-fno-strict-aliasing')
-env.Append(CCFLAGS=Split('-Wall -Wno-sign-compare -Werror -Wundef'))
-if sys.platform == 'cygwin':
- # cygwin has some header file issues...
- env.Append(CCFLAGS=Split("-Wno-uninitialized"))
-env.Append(CPPPATH=[os.path.join(EXT_SRCDIR + '/dnet')])
-
-# Default libraries
-env.Append(LIBS=['z'])
-
-# Platform-specific configuration
-conf = Configure(env)
-
-# Check for <fenv.h> (C99 FP environment control)
-have_fenv = conf.CheckHeader('fenv.h', '<>')
-if not have_fenv:
- print "Warning: Header file <fenv.h> not found."
- print " This host has no IEEE FP rounding mode control."
-
-# Check for mysql.
-mysql_config = WhereIs('mysql_config')
-have_mysql = mysql_config != None
-
-# Check MySQL version.
-if have_mysql:
- mysql_version = os.popen(mysql_config + ' --version').read()
- mysql_version = mysql_version.split('.')
- mysql_major = int(mysql_version[0])
- mysql_minor = int(mysql_version[1])
- # This version check is probably overly conservative, but it deals
- # with the versions we have installed.
- if mysql_major < 4 or (mysql_major == 4 and mysql_minor < 1):
- print "Warning: MySQL v4.1 or newer required."
- have_mysql = False
-
-# Set up mysql_config commands.
-if have_mysql:
- mysql_config_include = mysql_config + ' --include'
- if os.system(mysql_config_include + ' > /dev/null') != 0:
- # older mysql_config versions don't support --include, use
- # --cflags instead
- mysql_config_include = mysql_config + ' --cflags | sed s/\\\'//g'
- # This seems to work in all versions
- mysql_config_libs = mysql_config + ' --libs'
-
-env = conf.Finish()
-
-# Define the universe of supported ISAs
-env['ALL_ISA_LIST'] = ['alpha', 'sparc', 'mips']
-
-# Define the universe of supported CPU models
-env['ALL_CPU_LIST'] = ['SimpleCPU', 'FastCPU', 'FullCPU', 'AlphaFullCPU',
- 'OzoneSimpleCPU', 'OzoneCPU', 'CheckerCPU']
-
-
-# Sticky options get saved in the options file so they persist from
-# one invocation to the next (unless overridden, in which case the new
-# value becomes sticky).
-sticky_opts = Options(args=ARGUMENTS)
-sticky_opts.AddOptions(
- EnumOption('TARGET_ISA', 'Target ISA', 'alpha', env['ALL_ISA_LIST']),
- BoolOption('FULL_SYSTEM', 'Full-system support', False),
- BoolOption('ALPHA_TLASER',
- 'Model Alpha TurboLaser platform (vs. Tsunami)', False),
- BoolOption('NO_FAST_ALLOC', 'Disable fast object allocator', False),
- BoolOption('EFENCE', 'Link with Electric Fence malloc debugger',
- False),
- BoolOption('SS_COMPATIBLE_FP',
- 'Make floating-point results compatible with SimpleScalar',
- False),
- BoolOption('USE_SSE2',
- 'Compile for SSE2 (-msse2) to get IEEE FP on x86 hosts',
- False),
- BoolOption('STATS_BINNING', 'Bin statistics by CPU mode', have_mysql),
- BoolOption('USE_MYSQL', 'Use MySQL for stats output', have_mysql),
- BoolOption('USE_FENV', 'Use <fenv.h> IEEE mode control', have_fenv),
- ('CC', 'C compiler', os.environ.get('CC', env['CC'])),
- ('CXX', 'C++ compiler', os.environ.get('CXX', env['CXX'])),
- BoolOption('BATCH', 'Use batch pool for build and tests', False),
- ('BATCH_CMD', 'Batch pool submission command name', 'qdo')
- )
-
-# 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)
- )
-
-# These options get exported to #defines in config/*.hh (see m5/SConscript).
-env.ExportOptions = ['FULL_SYSTEM', 'ALPHA_TLASER', 'USE_FENV', \
- 'USE_MYSQL', 'NO_FAST_ALLOC', 'SS_COMPATIBLE_FP', \
- 'STATS_BINNING']
-
-# Define a handy 'no-op' action
-def no_action(target, source, env):
- return 0
-
-env.NoAction = Action(no_action, None)
-
-# libelf build is described in its own SConscript file.
-# SConscript-global is the build in build/libelf shared among all
-# configs.
-env.SConscript('m5/libelf/SConscript-global', exports = 'env')
-
-###################################################
-#
-# Define a SCons builder for configuration flag headers.
-#
-###################################################
-
-# This function generates a config header file that #defines the
-# option symbol to the current option setting (0 or 1). The source
-# operands are the name of the option and a Value node containing the
-# value of the option.
-def build_config_file(target, source, env):
- (option, value) = [s.get_contents() for s in source]
- f = file(str(target[0]), 'w')
- print >> f, '#define', option, value
- f.close()
- return None
-
-# Generate the message to be printed when building the config file.
-def build_config_file_string(target, source, env):
- (option, value) = [s.get_contents() for s in source]
- return "Defining %s as %s in %s." % (option, value, target[0])
-
-# Combine the two functions into a scons Action object.
-config_action = Action(build_config_file, build_config_file_string)
-
-# The emitter munges the source & target node lists to reflect what
-# we're really doing.
-def config_emitter(target, source, env):
- # extract option name from Builder arg
- option = str(target[0])
- # True target is config header file
- target = os.path.join('config', option.lower() + '.hh')
- # Force value to 0/1 even if it's a Python bool
- val = int(eval(str(env[option])))
- # Sources are option name & value (packaged in SCons Value nodes)
- return ([target], [Value(option), Value(val)])
-
-config_builder = Builder(emitter = config_emitter, action = config_action)
-
-env.Append(BUILDERS = { 'ConfigFile' : config_builder })
-
-###################################################
-#
-# Define build environments for selected configurations.
-#
-###################################################
-
-# rename base env
-base_env = env
-
-for build_dir in build_dirs:
- # Make a copy of the default environment to use for this config.
- env = base_env.Copy()
-
- # Record what build_dir was in the environment
- env.Append(BUILD_DIR=build_dir);
-
- # Set env according to the build directory config.
-
- sticky_opts.files = []
- # Name of default options file is taken from 'default=' on command
- # line if set, otherwise name of build dir.
- default_options_file = os.path.join('default_options',
- ARGUMENTS.get('default', build_dir))
- if os.path.isfile(default_options_file):
- sticky_opts.files.append(default_options_file)
- current_options_file = os.path.join('options', build_dir)
- if os.path.isfile(current_options_file):
- sticky_opts.files.append(current_options_file)
- else:
- # if file doesn't exist, make sure at least the directory is there
- # so we can create it later
- opt_dir = os.path.dirname(current_options_file)
- if not os.path.isdir(opt_dir):
- os.mkdir(opt_dir)
- if not sticky_opts.files:
- print "%s: No options file found in options, using defaults." \
- % build_dir
-
- # Apply current option settings to env
- sticky_opts.Update(env)
- nonsticky_opts.Update(env)
-
- # Process option settings.
-
- if not have_fenv and env['USE_FENV']:
- print "Warning: <fenv.h> not available; " \
- "forcing USE_FENV to False in", build_dir + "."
- env['USE_FENV'] = False
-
- if not env['USE_FENV']:
- print "Warning: No IEEE FP rounding mode control in", build_dir + "."
- print " FP results may deviate slightly from other platforms."
-
- if env['EFENCE']:
- env.Append(LIBS=['efence'])
-
- if env['USE_MYSQL']:
- if not have_mysql:
- print "Warning: MySQL not available; " \
- "forcing USE_MYSQL to False in", build_dir + "."
- env['USE_MYSQL'] = False
- else:
- print "Compiling in", build_dir, "with MySQL support."
- env.ParseConfig(mysql_config_libs)
- env.ParseConfig(mysql_config_include)
-
- # Save sticky option settings back to current options file
- sticky_opts.Save(current_options_file, env)
-
- # Do this after we save setting back, or else we'll tack on an
- # extra 'qdo' every time we run scons.
- if env['BATCH']:
- env['CC'] = env['BATCH_CMD'] + ' ' + env['CC']
- env['CXX'] = env['BATCH_CMD'] + ' ' + env['CXX']
-
- if env['USE_SSE2']:
- env.Append(CCFLAGS='-msse2')
-
- # The m5/SConscript file sets up the build rules in 'env' according
- # to the configured options. It returns a list of environments,
- # one for each variant build (debug, opt, etc.)
- envList = SConscript('m5/SConscript', build_dir = build_dir,
- exports = 'env', duplicate = False)
-
- # Set up the regression tests for each build.
- for e in envList:
- SConscript('m5-test/SConscript',
- build_dir = os.path.join(build_dir, 'test', e.Label),
- exports = { 'env' : e }, duplicate = False)
-
-###################################################
-#
-# Let SCons do its thing. At this point SCons will use the defined
-# build environments to build the requested targets.
-#
-###################################################
-
diff --git a/build/default_options/ALPHA_FS b/build_opts/ALPHA_FS
index ddd69b9b3..ddd69b9b3 100644
--- a/build/default_options/ALPHA_FS
+++ b/build_opts/ALPHA_FS
diff --git a/build/default_options/ALPHA_FS_TL b/build_opts/ALPHA_FS_TL
index 4f3e201ec..4f3e201ec 100644
--- a/build/default_options/ALPHA_FS_TL
+++ b/build_opts/ALPHA_FS_TL
diff --git a/build/default_options/ALPHA_SE b/build_opts/ALPHA_SE
index 3fedc22ca..3fedc22ca 100644
--- a/build/default_options/ALPHA_SE
+++ b/build_opts/ALPHA_SE
diff --git a/build/default_options/MIPS_SE b/build_opts/MIPS_SE
index e74e2f69c..e74e2f69c 100644
--- a/build/default_options/MIPS_SE
+++ b/build_opts/MIPS_SE
diff --git a/build_opts/SPARC_FS b/build_opts/SPARC_FS
new file mode 100644
index 000000000..59d17eee9
--- /dev/null
+++ b/build_opts/SPARC_FS
@@ -0,0 +1,2 @@
+TARGET_ISA = 'sparc'
+FULL_SYSTEM = 1
diff --git a/build/default_options/SPARC_SE b/build_opts/SPARC_SE
index 3b256fc34..3b256fc34 100644
--- a/build/default_options/SPARC_SE
+++ b/build_opts/SPARC_SE
diff --git a/configs/test/SysPaths.py b/configs/test/SysPaths.py
new file mode 100644
index 000000000..c7c7db4e7
--- /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 os.path.join(DISKDIR, file)
+
+def binary(file):
+ return os.path.join(BINDIR, file)
+
+def script(file):
+ return os.path.join(SYSTEMDIR, 'boot', file)
+
diff --git a/configs/test/fs.py b/configs/test/fs.py
new file mode 100644
index 000000000..fdbf86abe
--- /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 = AtomicSimpleCPU(mem=Parent.magicbus2)
+ sim_console = SimConsole(listener=ConsoleListener(port=3456))
+ kernel = binary('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..75e832f5e
--- /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 = AtomicSimpleCPU(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/SConscript b/cpu/SConscript
deleted file mode 100644
index 3840b9d41..000000000
--- a/cpu/SConscript
+++ /dev/null
@@ -1,167 +0,0 @@
-# -*- mode:python -*-
-
-# Copyright (c) 2006 The Regents of The University of Michigan
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met: redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer;
-# redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution;
-# neither the name of the copyright holders nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-import os
-import os.path
-
-# Import build environment variable from SConstruct.
-Import('env')
-
-#################################################################
-#
-# Generate StaticInst execute() method signatures.
-#
-# There must be one signature for each CPU model compiled in.
-# Since the set of compiled-in models is flexible, we generate a
-# header containing the appropriate set of signatures on the fly.
-#
-#################################################################
-
-# CPU model-specific data is contained in cpu_models.py
-# Convert to SCons File node to get path handling
-models_db = File('cpu_models.py')
-# slurp in contents of file
-execfile(models_db.srcnode().abspath)
-
-# Template for execute() signature.
-exec_sig_template = '''
-virtual Fault execute(%s *xc, Trace::InstRecord *traceData) const = 0;
-'''
-
-mem_ini_sig_template = '''
-virtual Fault initiateAcc(%s *xc, Trace::InstRecord *traceData) const { panic("Not defined!"); };
-'''
-
-mem_comp_sig_template = '''
-virtual Fault completeAcc(uint8_t *data, %s *xc, Trace::InstRecord *traceData) const { panic("Not defined!"); return NoFault; };
-'''
-
-# Generate header.
-def gen_cpu_exec_signatures(target, source, env):
- f = open(str(target[0]), 'w')
- print >> f, '''
-#ifndef __CPU_STATIC_INST_EXEC_SIGS_HH__
-#define __CPU_STATIC_INST_EXEC_SIGS_HH__
-'''
- for cpu in env['CPU_MODELS']:
- xc_type = CpuModel.dict[cpu].strings['CPU_exec_context']
- print >> f, exec_sig_template % xc_type
- print >> f, mem_ini_sig_template % xc_type
- print >> f, mem_comp_sig_template % xc_type
- print >> f, '''
-#endif // __CPU_STATIC_INST_EXEC_SIGS_HH__
-'''
-
-# Generate string that gets printed when header is rebuilt
-def gen_sigs_string(target, source, env):
- return "Generating static_inst_exec_sigs.hh: " \
- + ', '.join(env['CPU_MODELS'])
-
-# Add command to generate header to environment.
-env.Command('static_inst_exec_sigs.hh', models_db,
- Action(gen_cpu_exec_signatures, gen_sigs_string,
- varlist = ['CPU_MODELS']))
-
-#################################################################
-#
-# Include CPU-model-specific files based on set of models
-# specified in CPU_MODELS build option.
-#
-#################################################################
-
-sources = []
-
-if 'SimpleCPU' in env['CPU_MODELS']:
- sources += Split('simple/cpu.cc')
-
-if 'FastCPU' in env['CPU_MODELS']:
- sources += Split('fast/cpu.cc')
-
-if 'AlphaFullCPU' in env['CPU_MODELS']:
- sources += Split('''
- o3/2bit_local_pred.cc
- o3/alpha_dyn_inst.cc
- o3/alpha_cpu.cc
- o3/alpha_cpu_builder.cc
- o3/bpred_unit.cc
- o3/btb.cc
- o3/commit.cc
- o3/decode.cc
- o3/fetch.cc
- o3/free_list.cc
- o3/fu_pool.cc
- o3/cpu.cc
- o3/iew.cc
- o3/inst_queue.cc
- o3/lsq_unit.cc
- o3/lsq.cc
- o3/mem_dep_unit.cc
- o3/ras.cc
- o3/rename.cc
- o3/rename_map.cc
- o3/rob.cc
- o3/scoreboard.cc
- o3/store_set.cc
- o3/tournament_pred.cc
- ''')
-
-if 'OzoneSimpleCPU' in env['CPU_MODELS']:
- sources += Split('''
- ozone/cpu.cc
- ozone/cpu_builder.cc
- ozone/dyn_inst.cc
- ozone/front_end.cc
- ozone/inorder_back_end.cc
- ozone/inst_queue.cc
- ozone/rename_table.cc
- ''')
-
-if 'OzoneCPU' in env['CPU_MODELS']:
- sources += Split('''
- ozone/back_end.cc
- ozone/lsq_unit.cc
- ozone/lw_back_end.cc
- ozone/lw_lsq.cc
- ''')
-
-if 'CheckerCPU' in env['CPU_MODELS']:
- sources += Split('''
- checker/cpu.cc
- checker/cpu_builder.cc
- checker/o3_cpu_builder.cc
- ''')
-
-# FullCPU sources are included from m5/SConscript since they're not
-# below this point in the file hierarchy.
-
-# Convert file names to SCons File objects. This takes care of the
-# path relative to the top of the directory tree.
-sources = [File(s) for s in sources]
-
-Return('sources')
-
diff --git a/cpu/base.cc b/cpu/base.cc
deleted file mode 100644
index de03b9eab..000000000
--- a/cpu/base.cc
+++ /dev/null
@@ -1,378 +0,0 @@
-/*
- * 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 <iostream>
-#include <string>
-#include <sstream>
-
-#include "base/cprintf.hh"
-#include "base/loader/symtab.hh"
-#include "base/misc.hh"
-#include "base/output.hh"
-#include "cpu/base.hh"
-#include "cpu/exec_context.hh"
-#include "cpu/profile.hh"
-#include "cpu/sampler/sampler.hh"
-#include "sim/param.hh"
-#include "sim/process.hh"
-#include "sim/sim_events.hh"
-#include "sim/system.hh"
-
-#include "base/trace.hh"
-
-using namespace std;
-
-vector<BaseCPU *> BaseCPU::cpuList;
-
-// This variable reflects the max number of threads in any CPU. Be
-// careful to only use it once all the CPUs that you care about have
-// been initialized
-int maxThreadsPerCPU = 1;
-
-#if FULL_SYSTEM
-BaseCPU::BaseCPU(Params *p)
- : SimObject(p->name), clock(p->clock), checkInterrupts(true),
- params(p), number_of_threads(p->numberOfThreads), system(p->system)
-#else
-BaseCPU::BaseCPU(Params *p)
- : SimObject(p->name), clock(p->clock), params(p),
- number_of_threads(p->numberOfThreads)
-#endif
-{
- DPRINTF(FullCPU, "BaseCPU: Creating object, mem address %#x.\n", this);
-
- // add self to global list of CPUs
- cpuList.push_back(this);
-
- DPRINTF(FullCPU, "BaseCPU: CPU added to cpuList, mem address %#x.\n",
- this);
-
- if (number_of_threads > maxThreadsPerCPU)
- maxThreadsPerCPU = number_of_threads;
-
- // allocate per-thread instruction-based event queues
- comInstEventQueue = new EventQueue *[number_of_threads];
- for (int i = 0; i < number_of_threads; ++i)
- comInstEventQueue[i] = new EventQueue("instruction-based event queue");
-
- //
- // set up instruction-count-based termination events, if any
- //
- if (p->max_insts_any_thread != 0)
- for (int i = 0; i < number_of_threads; ++i)
- new SimExitEvent(comInstEventQueue[i], p->max_insts_any_thread,
- "a thread reached the max instruction count");
-
- if (p->max_insts_all_threads != 0) {
- // allocate & initialize shared downcounter: each event will
- // decrement this when triggered; simulation will terminate
- // when counter reaches 0
- int *counter = new int;
- *counter = number_of_threads;
- for (int i = 0; i < number_of_threads; ++i)
- new CountedExitEvent(comInstEventQueue[i],
- "all threads reached the max instruction count",
- p->max_insts_all_threads, *counter);
- }
-
- // allocate per-thread load-based event queues
- comLoadEventQueue = new EventQueue *[number_of_threads];
- for (int i = 0; i < number_of_threads; ++i)
- comLoadEventQueue[i] = new EventQueue("load-based event queue");
-
- //
- // set up instruction-count-based termination events, if any
- //
- if (p->max_loads_any_thread != 0)
- for (int i = 0; i < number_of_threads; ++i)
- new SimExitEvent(comLoadEventQueue[i], p->max_loads_any_thread,
- "a thread reached the max load count");
-
- if (p->max_loads_all_threads != 0) {
- // allocate & initialize shared downcounter: each event will
- // decrement this when triggered; simulation will terminate
- // when counter reaches 0
- int *counter = new int;
- *counter = number_of_threads;
- for (int i = 0; i < number_of_threads; ++i)
- new CountedExitEvent(comLoadEventQueue[i],
- "all threads reached the max load count",
- p->max_loads_all_threads, *counter);
- }
-
-#if FULL_SYSTEM
- memset(interrupts, 0, sizeof(interrupts));
- intstatus = 0;
-#endif
-
- functionTracingEnabled = false;
- if (p->functionTrace) {
- functionTraceStream = simout.find(csprintf("ftrace.%s", name()));
- currentFunctionStart = currentFunctionEnd = 0;
- functionEntryTick = p->functionTraceStart;
-
- if (p->functionTraceStart == 0) {
- functionTracingEnabled = true;
- } else {
- Event *e =
- new EventWrapper<BaseCPU, &BaseCPU::enableFunctionTrace>(this,
- true);
- e->schedule(p->functionTraceStart);
- }
- }
-#if FULL_SYSTEM
- profileEvent = NULL;
- if (params->profile)
- profileEvent = new ProfileEvent(this, params->profile);
-#endif
-
-}
-
-BaseCPU::Params::Params()
-{
-#if FULL_SYSTEM
- profile = false;
-#endif
- checker = NULL;
-}
-
-void
-BaseCPU::enableFunctionTrace()
-{
- functionTracingEnabled = true;
-}
-
-BaseCPU::~BaseCPU()
-{
-}
-
-void
-BaseCPU::init()
-{
- if (!params->deferRegistration)
- registerExecContexts();
-}
-
-void
-BaseCPU::startup()
-{
-#if FULL_SYSTEM
- if (!params->deferRegistration && profileEvent)
- profileEvent->schedule(curTick);
-#endif
-}
-
-
-void
-BaseCPU::regStats()
-{
- using namespace Stats;
-
- numCycles
- .name(name() + ".numCycles")
- .desc("number of cpu cycles simulated")
- ;
-
- int size = execContexts.size();
- if (size > 1) {
- for (int i = 0; i < size; ++i) {
- stringstream namestr;
- ccprintf(namestr, "%s.ctx%d", name(), i);
- execContexts[i]->regStats(namestr.str());
- }
- } else if (size == 1)
- execContexts[0]->regStats(name());
-
-#if FULL_SYSTEM
-#endif
-}
-
-
-void
-BaseCPU::registerExecContexts()
-{
- for (int i = 0; i < execContexts.size(); ++i) {
- ExecContext *xc = execContexts[i];
-
- if (xc->status() == ExecContext::Suspended) {
-#if FULL_SYSTEM
- int id = params->cpu_id;
- if (id != -1)
- id += i;
-
- xc->setCpuId(system->registerExecContext(xc, id));
-#else
- xc->setCpuId(xc->getProcessPtr()->registerExecContext(xc));
-#endif
- }
- }
-}
-
-
-void
-BaseCPU::switchOut(Sampler *sampler)
-{
- panic("This CPU doesn't support sampling!");
-}
-
-void
-BaseCPU::takeOverFrom(BaseCPU *oldCPU)
-{
- assert(execContexts.size() == oldCPU->execContexts.size());
-
- for (int i = 0; i < execContexts.size(); ++i) {
- ExecContext *newXC = execContexts[i];
- ExecContext *oldXC = oldCPU->execContexts[i];
-
- newXC->takeOverFrom(oldXC);
- assert(newXC->readCpuId() == oldXC->readCpuId());
-#if FULL_SYSTEM
- system->replaceExecContext(newXC, newXC->readCpuId());
-#else
- assert(newXC->getProcessPtr() == oldXC->getProcessPtr());
- newXC->getProcessPtr()->replaceExecContext(newXC, newXC->readCpuId());
-#endif
- }
-
-#if FULL_SYSTEM
- for (int i = 0; i < TheISA::NumInterruptLevels; ++i)
- interrupts[i] = oldCPU->interrupts[i];
- intstatus = oldCPU->intstatus;
-
- for (int i = 0; i < execContexts.size(); ++i)
- execContexts[i]->profileClear();
-
- if (profileEvent)
- profileEvent->schedule(curTick);
-#endif
-}
-
-
-#if FULL_SYSTEM
-BaseCPU::ProfileEvent::ProfileEvent(BaseCPU *_cpu, int _interval)
- : Event(&mainEventQueue), cpu(_cpu), interval(_interval)
-{ }
-
-void
-BaseCPU::ProfileEvent::process()
-{
- for (int i = 0, size = cpu->execContexts.size(); i < size; ++i) {
- ExecContext *xc = cpu->execContexts[i];
- xc->profileSample();
- }
-
- schedule(curTick + interval);
-}
-
-void
-BaseCPU::post_interrupt(int int_num, int index)
-{
- DPRINTF(Interrupt, "Interrupt %d:%d posted\n", int_num, index);
-
- if (int_num < 0 || int_num >= TheISA::NumInterruptLevels)
- panic("int_num out of bounds\n");
-
- if (index < 0 || index >= sizeof(uint64_t) * 8)
- panic("int_num out of bounds\n");
-
- checkInterrupts = true;
- interrupts[int_num] |= 1 << index;
- intstatus |= (ULL(1) << int_num);
-}
-
-void
-BaseCPU::clear_interrupt(int int_num, int index)
-{
- DPRINTF(Interrupt, "Interrupt %d:%d cleared\n", int_num, index);
-
- if (int_num < 0 || int_num >= TheISA::NumInterruptLevels)
- panic("int_num out of bounds\n");
-
- if (index < 0 || index >= sizeof(uint64_t) * 8)
- panic("int_num out of bounds\n");
-
- interrupts[int_num] &= ~(1 << index);
- if (interrupts[int_num] == 0)
- intstatus &= ~(ULL(1) << int_num);
-}
-
-void
-BaseCPU::clear_interrupts()
-{
- DPRINTF(Interrupt, "Interrupts all cleared\n");
-
- memset(interrupts, 0, sizeof(interrupts));
- intstatus = 0;
-}
-
-
-void
-BaseCPU::serialize(std::ostream &os)
-{
- SERIALIZE_ARRAY(interrupts, TheISA::NumInterruptLevels);
- SERIALIZE_SCALAR(intstatus);
-}
-
-void
-BaseCPU::unserialize(Checkpoint *cp, const std::string &section)
-{
- UNSERIALIZE_ARRAY(interrupts, TheISA::NumInterruptLevels);
- UNSERIALIZE_SCALAR(intstatus);
-}
-
-#endif // FULL_SYSTEM
-
-void
-BaseCPU::traceFunctionsInternal(Addr pc)
-{
- if (!debugSymbolTable)
- return;
-
- // if pc enters different function, print new function symbol and
- // update saved range. Otherwise do nothing.
- if (pc < currentFunctionStart || pc >= currentFunctionEnd) {
- string sym_str;
- bool found = debugSymbolTable->findNearestSymbol(pc, sym_str,
- currentFunctionStart,
- currentFunctionEnd);
-
- if (!found) {
- // no symbol found: use addr as label
- sym_str = csprintf("0x%x", pc);
- currentFunctionStart = pc;
- currentFunctionEnd = pc + 1;
- }
-
- ccprintf(*functionTraceStream, " (%d)\n%d: %s",
- curTick - functionEntryTick, curTick, sym_str);
- functionEntryTick = curTick;
- }
-}
-
-
-DEFINE_SIM_OBJECT_CLASS_NAME("BaseCPU", BaseCPU)
diff --git a/cpu/base.hh b/cpu/base.hh
deleted file mode 100644
index dd776859d..000000000
--- a/cpu/base.hh
+++ /dev/null
@@ -1,238 +0,0 @@
-/*
- * 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 __CPU_BASE_HH__
-#define __CPU_BASE_HH__
-
-#include <vector>
-
-#include "base/statistics.hh"
-#include "config/full_system.hh"
-#include "cpu/sampler/sampler.hh"
-#include "sim/eventq.hh"
-#include "sim/sim_object.hh"
-#include "arch/isa_traits.hh"
-
-class BranchPred;
-class CheckerCPU;
-class ExecContext;
-class System;
-
-class BaseCPU : public SimObject
-{
- protected:
- // CPU's clock period in terms of the number of ticks of curTime.
- Tick clock;
-
- public:
- inline Tick frequency() const { return Clock::Frequency / clock; }
- inline Tick cycles(int numCycles) const { return clock * numCycles; }
- inline Tick curCycle() const { return curTick / clock; }
-
-#if FULL_SYSTEM
- protected:
- uint64_t interrupts[TheISA::NumInterruptLevels];
- uint64_t intstatus;
-
- public:
- virtual void post_interrupt(int int_num, int index);
- virtual void clear_interrupt(int int_num, int index);
- virtual void clear_interrupts();
- bool checkInterrupts;
-
- bool check_interrupt(int int_num) const {
- if (int_num > TheISA::NumInterruptLevels)
- panic("int_num out of bounds\n");
-
- return interrupts[int_num] != 0;
- }
-
- bool check_interrupts() const { return intstatus != 0; }
- uint64_t intr_status() const { return intstatus; }
-
- class ProfileEvent : public Event
- {
- private:
- BaseCPU *cpu;
- int interval;
-
- public:
- ProfileEvent(BaseCPU *cpu, int interval);
- void process();
- };
- ProfileEvent *profileEvent;
-#endif
-
- protected:
- std::vector<ExecContext *> execContexts;
-
- public:
-
- /// Notify the CPU that the indicated context is now active. The
- /// delay parameter indicates the number of ticks to wait before
- /// executing (typically 0 or 1).
- virtual void activateContext(int thread_num, int delay) {}
-
- /// Notify the CPU that the indicated context is now suspended.
- virtual void suspendContext(int thread_num) {}
-
- /// Notify the CPU that the indicated context is now deallocated.
- virtual void deallocateContext(int thread_num) {}
-
- /// Notify the CPU that the indicated context is now halted.
- virtual void haltContext(int thread_num) {}
-
- public:
- struct Params
- {
- std::string name;
- int numberOfThreads;
- bool deferRegistration;
- Counter max_insts_any_thread;
- Counter max_insts_all_threads;
- Counter max_loads_any_thread;
- Counter max_loads_all_threads;
- Tick clock;
- bool functionTrace;
- Tick functionTraceStart;
-#if FULL_SYSTEM
- System *system;
- int cpu_id;
- Tick profile;
-#endif
- BaseCPU *checker;
-
- Params();
- };
-
- const Params *params;
-
- BaseCPU(Params *params);
- virtual ~BaseCPU();
-
- virtual void init();
- virtual void startup();
- virtual void regStats();
-
- virtual void activateWhenReady(int tid) {};
-
- void registerExecContexts();
-
- /// Prepare for another CPU to take over execution. When it is
- /// is ready (drained pipe) it signals the sampler.
- virtual void switchOut(Sampler *);
-
- /// Take over execution from the given CPU. Used for warm-up and
- /// sampling.
- virtual void takeOverFrom(BaseCPU *);
-
- /**
- * Number of threads we're actually simulating (<= SMT_MAX_THREADS).
- * This is a constant for the duration of the simulation.
- */
- int number_of_threads;
-
- /**
- * Vector of per-thread instruction-based event queues. Used for
- * scheduling events based on number of instructions committed by
- * a particular thread.
- */
- EventQueue **comInstEventQueue;
-
- /**
- * Vector of per-thread load-based event queues. Used for
- * scheduling events based on number of loads committed by
- *a particular thread.
- */
- EventQueue **comLoadEventQueue;
-
-#if FULL_SYSTEM
- System *system;
-
- /**
- * Serialize this object to the given output stream.
- * @param os The stream to serialize to.
- */
- virtual void serialize(std::ostream &os);
-
- /**
- * Reconstruct the state of this object from a checkpoint.
- * @param cp The checkpoint use.
- * @param section The section name of this object
- */
- virtual void unserialize(Checkpoint *cp, const std::string &section);
-
-#endif
-
- /**
- * Return pointer to CPU's branch predictor (NULL if none).
- * @return Branch predictor pointer.
- */
- virtual BranchPred *getBranchPred() { return NULL; };
-
- virtual Counter totalInstructions() const { return 0; }
-
- // Function tracing
- private:
- bool functionTracingEnabled;
- std::ostream *functionTraceStream;
- Addr currentFunctionStart;
- Addr currentFunctionEnd;
- Tick functionEntryTick;
- void enableFunctionTrace();
- void traceFunctionsInternal(Addr pc);
-
- protected:
- void traceFunctions(Addr pc)
- {
- if (functionTracingEnabled)
- traceFunctionsInternal(pc);
- }
-
- private:
- static std::vector<BaseCPU *> cpuList; //!< Static global cpu list
-
- public:
- static int numSimulatedCPUs() { return cpuList.size(); }
- static Counter numSimulatedInstructions()
- {
- Counter total = 0;
-
- int size = cpuList.size();
- for (int i = 0; i < size; ++i)
- total += cpuList[i]->totalInstructions();
-
- return total;
- }
-
- public:
- // Number of CPU cycles simulated
- Stats::Scalar<> numCycles;
-};
-
-#endif // __CPU_BASE_HH__
diff --git a/cpu/cpu_exec_context.cc b/cpu/cpu_exec_context.cc
deleted file mode 100644
index e30295ef8..000000000
--- a/cpu/cpu_exec_context.cc
+++ /dev/null
@@ -1,315 +0,0 @@
-/*
- * Copyright (c) 2001-2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <string>
-
-#include "cpu/base.hh"
-#include "cpu/cpu_exec_context.hh"
-#include "cpu/exec_context.hh"
-
-#if FULL_SYSTEM
-#include "base/callback.hh"
-#include "base/cprintf.hh"
-#include "base/output.hh"
-#include "base/trace.hh"
-#include "cpu/profile.hh"
-#include "cpu/quiesce_event.hh"
-#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"
-#endif
-
-using namespace std;
-
-// constructor
-#if FULL_SYSTEM
-CPUExecContext::CPUExecContext(BaseCPU *_cpu, int _thread_num, System *_sys,
- AlphaITB *_itb, AlphaDTB *_dtb,
- FunctionalMemory *_mem,
- bool use_kernel_stats)
- : _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), func_exe_inst(0), storeCondFailures(0)
-{
- proxy = new ProxyExecContext<CPUExecContext>(this);
-
- quiesceEvent = new EndQuiesceEvent(proxy);
-
- memset(&regs, 0, sizeof(RegFile));
-
- if (cpu->params->profile) {
- profile = new FunctionProfile(system->kernelSymtab);
- Callback *cb =
- new MakeCallback<CPUExecContext,
- &CPUExecContext::dumpFuncProfile>(this);
- registerExitCallback(cb);
- }
-
- // let's fill with a dummy node for now so we don't get a segfault
- // on the first cycle when there's no node available.
- static ProfileNode dummyNode;
- profileNode = &dummyNode;
- profilePC = 3;
-
- if (use_kernel_stats) {
- kernelStats = new Kernel::Statistics(system);
- } else {
- kernelStats = NULL;
- }
-}
-#else
-CPUExecContext::CPUExecContext(BaseCPU *_cpu, int _thread_num,
- Process *_process, int _asid)
- : _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),
- func_exe_inst(0), storeCondFailures(0)
-{
- memset(&regs, 0, sizeof(RegFile));
- proxy = new ProxyExecContext<CPUExecContext>(this);
-}
-
-CPUExecContext::CPUExecContext(RegFile *regFile)
- : cpu(NULL), thread_num(-1), process(NULL), mem(NULL), asid(-1),
- func_exe_inst(0), storeCondFailures(0)
-{
- regs = *regFile;
- proxy = new ProxyExecContext<CPUExecContext>(this);
-}
-
-#endif
-
-CPUExecContext::~CPUExecContext()
-{
- delete proxy;
-}
-
-#if FULL_SYSTEM
-void
-CPUExecContext::dumpFuncProfile()
-{
- std::ostream *os = simout.create(csprintf("profile.%s.dat", cpu->name()));
- profile->dump(proxy, *os);
-}
-
-void
-CPUExecContext::profileClear()
-{
- if (profile)
- profile->clear();
-}
-
-void
-CPUExecContext::profileSample()
-{
- if (profile)
- profile->sample(profileNode, profilePC);
-}
-
-#endif
-
-void
-CPUExecContext::takeOverFrom(ExecContext *oldContext)
-{
- // some things should already be set up
- assert(mem == oldContext->getMemPtr());
-#if FULL_SYSTEM
- assert(system == oldContext->getSystemPtr());
-#else
- assert(process == oldContext->getProcessPtr());
-#endif
-
- // copy over functional state
- _status = oldContext->status();
- copyArchRegs(oldContext);
- cpu_id = oldContext->readCpuId();
-#if !FULL_SYSTEM
- func_exe_inst = oldContext->readFuncExeInst();
-#else
- EndQuiesceEvent *quiesce = oldContext->getQuiesceEvent();
- if (quiesce) {
- // Point the quiesce event's XC at this XC so that it wakes up
- // the proper CPU.
- quiesce->xc = proxy;
- }
- if (quiesceEvent) {
- quiesceEvent->xc = proxy;
- }
-#endif
-
- storeCondFailures = 0;
-
- oldContext->setStatus(ExecContext::Unallocated);
-}
-
-void
-CPUExecContext::serialize(ostream &os)
-{
- SERIALIZE_ENUM(_status);
- regs.serialize(os);
- // thread_num and cpu_id are deterministic from the config
- SERIALIZE_SCALAR(func_exe_inst);
- SERIALIZE_SCALAR(inst);
-
-#if FULL_SYSTEM
- Tick quiesceEndTick = 0;
- if (quiesceEvent->scheduled())
- quiesceEndTick = quiesceEvent->when();
- SERIALIZE_SCALAR(quiesceEndTick);
- if (kernelStats)
- kernelStats->serialize(os);
-#endif
-}
-
-
-void
-CPUExecContext::unserialize(Checkpoint *cp, const std::string &section)
-{
- UNSERIALIZE_ENUM(_status);
- regs.unserialize(cp, section);
- // thread_num and cpu_id are deterministic from the config
- UNSERIALIZE_SCALAR(func_exe_inst);
- UNSERIALIZE_SCALAR(inst);
-
-#if FULL_SYSTEM
- Tick quiesceEndTick;
- UNSERIALIZE_SCALAR(quiesceEndTick);
- if (quiesceEndTick)
- quiesceEvent->schedule(quiesceEndTick);
- if (kernelStats)
- kernelStats->unserialize(cp, section);
-#endif
-}
-
-
-void
-CPUExecContext::activate(int delay)
-{
- if (status() == ExecContext::Active)
- return;
-
- lastActivate = curTick;
-
- if (status() == ExecContext::Unallocated) {
- cpu->activateWhenReady(thread_num);
- return;
- }
-
- _status = ExecContext::Active;
-
- // status() == Suspended
- cpu->activateContext(thread_num, delay);
-}
-
-void
-CPUExecContext::suspend()
-{
- if (status() == ExecContext::Suspended)
- return;
-
- lastActivate = curTick;
- lastSuspend = curTick;
-/*
-#if FULL_SYSTEM
- // Don't change the status from active if there are pending interrupts
- if (cpu->check_interrupts()) {
- assert(status() == ExecContext::Active);
- return;
- }
-#endif
-*/
- _status = ExecContext::Suspended;
- cpu->suspendContext(thread_num);
-}
-
-void
-CPUExecContext::deallocate()
-{
- if (status() == ExecContext::Unallocated)
- return;
-
- _status = ExecContext::Unallocated;
- cpu->deallocateContext(thread_num);
-}
-
-void
-CPUExecContext::halt()
-{
- if (status() == ExecContext::Halted)
- return;
-
- _status = ExecContext::Halted;
- cpu->haltContext(thread_num);
-}
-
-
-void
-CPUExecContext::regStats(const string &name)
-{
-#if FULL_SYSTEM
- if (kernelStats)
- kernelStats->regStats(name + ".kern");
-#endif
-}
-
-void
-CPUExecContext::copyArchRegs(ExecContext *xc)
-{
- // First loop through the integer registers.
- for (int i = 0; i < AlphaISA::NumIntRegs; ++i) {
- setIntReg(i, xc->readIntReg(i));
- }
-
- // Then loop through the floating point registers.
- for (int i = 0; i < AlphaISA::NumFloatRegs; ++i) {
- setFloatRegDouble(i, xc->readFloatRegDouble(i));
- setFloatRegInt(i, xc->readFloatRegInt(i));
- }
-
- // Copy misc. registers
- regs.miscRegs.copyMiscRegs(xc);
-
- // Lastly copy PC/NPC
- setPC(xc->readPC());
- setNextPC(xc->readNextPC());
-}
-
diff --git a/cpu/cpu_exec_context.hh b/cpu/cpu_exec_context.hh
deleted file mode 100644
index 061fe450a..000000000
--- a/cpu/cpu_exec_context.hh
+++ /dev/null
@@ -1,524 +0,0 @@
-/*
- * Copyright (c) 2001-2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __CPU_CPU_EXEC_CONTEXT_HH__
-#define __CPU_CPU_EXEC_CONTEXT_HH__
-
-#include "arch/isa_traits.hh"
-#include "config/full_system.hh"
-#include "cpu/exec_context.hh"
-#include "mem/functional/functional.hh"
-#include "mem/mem_req.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
-
-#include "sim/system.hh"
-#include "arch/tlb.hh"
-
-class FunctionProfile;
-class ProfileNode;
-class MemoryController;
-
-namespace Kernel {
- class Statistics;
-};
-
-#else // !FULL_SYSTEM
-
-#include "sim/process.hh"
-
-#endif // FULL_SYSTEM
-
-//
-// The CPUExecContext object represents a functional context for
-// instruction execution. It incorporates everything required for
-// architecture-level functional simulation of a single thread.
-//
-
-class CPUExecContext
-{
- protected:
- typedef TheISA::RegFile RegFile;
- typedef TheISA::MachInst MachInst;
- typedef TheISA::MiscRegFile MiscRegFile;
- typedef TheISA::MiscReg MiscReg;
- public:
- typedef ExecContext::Status Status;
-
- private:
- Status _status;
-
- public:
- Status status() const { return _status; }
-
- void setStatus(Status newStatus) { _status = newStatus; }
-
- /// Set the status to Active. Optional delay indicates number of
- /// cycles to wait before beginning execution.
- void activate(int delay = 1);
-
- /// Set the status to Suspended.
- void suspend();
-
- /// Set the status to Unallocated.
- void deallocate();
-
- /// Set the status to Halted.
- void halt();
-
- protected:
- RegFile regs; // correct-path register context
-
- public:
- // pointer to CPU associated with this context
- BaseCPU *cpu;
-
- ProxyExecContext<CPUExecContext> *proxy;
-
- // Current instruction
- MachInst inst;
-
- // Index of hardware thread context on the CPU that this represents.
- int thread_num;
-
- // ID of this context w.r.t. the System or Process object to which
- // it belongs. For full-system mode, this is the system CPU ID.
- int cpu_id;
-
- Tick lastActivate;
- Tick lastSuspend;
-
-#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;
-
- FunctionProfile *profile;
- ProfileNode *profileNode;
- Addr profilePC;
- void dumpFuncProfile();
-
- EndQuiesceEvent *quiesceEvent;
-
- EndQuiesceEvent *getQuiesceEvent() { return quiesceEvent; }
-
- Tick readLastActivate() { return lastActivate; }
-
- Tick readLastSuspend() { return lastSuspend; }
-
- void profileClear();
-
- void profileSample();
-
- Kernel::Statistics *getKernelStats() { return kernelStats; }
-
- Kernel::Statistics *kernelStats;
-#else
- Process *process;
-
- FunctionalMemory *mem; // functional storage for process address space
-
- // Address space ID. Note that this is used for TIMING cache
- // simulation only; all functional memory accesses should use
- // one of the FunctionalMemory pointers above.
- short asid;
-
-#endif
-
- /**
- * Temporary storage to pass the source address from copy_load to
- * copy_store.
- * @todo Remove this temporary when we have a better way to do it.
- */
- Addr copySrcAddr;
- /**
- * Temp storage for the physical source address of a copy.
- * @todo Remove this temporary when we have a better way to do it.
- */
- Addr copySrcPhysAddr;
-
-
- /*
- * number of executed instructions, for matching with syscall trace
- * points in EIO files.
- */
- Counter func_exe_inst;
-
- //
- // Count failed store conditionals so we can warn of apparent
- // application deadlock situations.
- unsigned storeCondFailures;
-
- // constructor: initialize context from given process structure
-#if FULL_SYSTEM
- CPUExecContext(BaseCPU *_cpu, int _thread_num, System *_system,
- AlphaITB *_itb, AlphaDTB *_dtb, FunctionalMemory *_mem,
- bool use_kernel_stats = true);
-#else
- CPUExecContext(BaseCPU *_cpu, int _thread_num, Process *_process, int _asid);
- CPUExecContext(BaseCPU *_cpu, int _thread_num, FunctionalMemory *_mem,
- int _asid);
- // Constructor to use XC to pass reg file around. Not used for anything
- // else.
- CPUExecContext(RegFile *regFile);
-#endif
- virtual ~CPUExecContext();
-
- virtual void takeOverFrom(ExecContext *oldContext);
-
- void regStats(const std::string &name);
-
- void serialize(std::ostream &os);
- void unserialize(Checkpoint *cp, const std::string &section);
-
- BaseCPU *getCpuPtr() { return cpu; }
-
- ExecContext *getProxy() { return proxy; }
-
- int getThreadNum() { return thread_num; }
-
-#if FULL_SYSTEM
- System *getSystemPtr() { return system; }
-
- PhysicalMemory *getPhysMemPtr() { return physmem; }
-
- AlphaITB *getITBPtr() { return itb; }
-
- AlphaDTB *getDTBPtr() { return dtb; }
-
- bool validInstAddr(Addr addr) { return true; }
- bool validDataAddr(Addr addr) { return true; }
- int getInstAsid() { return regs.instAsid(); }
- int getDataAsid() { return regs.dataAsid(); }
-
- Fault translateInstReq(MemReqPtr &req)
- {
- return itb->translate(req);
- }
-
- Fault translateDataReadReq(MemReqPtr &req)
- {
- return dtb->translate(req, false);
- }
-
- Fault translateDataWriteReq(MemReqPtr &req)
- {
- return dtb->translate(req, true);
- }
-
-#else
- Process *getProcessPtr() { return process; }
-
- bool validInstAddr(Addr addr)
- { return process->validInstAddr(addr); }
-
- bool validDataAddr(Addr addr)
- { return process->validDataAddr(addr); }
-
- int getInstAsid() { return asid; }
- int getDataAsid() { return asid; }
-
- Fault 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)
- {
- return dummyTranslation(req);
- }
- Fault translateDataReadReq(MemReqPtr &req)
- {
- return dummyTranslation(req);
- }
- Fault translateDataWriteReq(MemReqPtr &req)
- {
- return dummyTranslation(req);
- }
-
-#endif
-
- template <class T>
- Fault read(MemReqPtr &req, T &data)
- {
-#if FULL_SYSTEM && defined(TARGET_ALPHA)
- if (req->flags & LOCKED) {
- req->xc->setMiscReg(TheISA::Lock_Addr_DepTag, req->paddr);
- req->xc->setMiscReg(TheISA::Lock_Flag_DepTag, true);
- }
-#endif
-
- Fault error;
- error = mem->read(req, data);
- data = LittleEndianGuest::gtoh(data);
- return error;
- }
-
- template <class T>
- Fault write(MemReqPtr &req, T &data)
- {
-#if FULL_SYSTEM && defined(TARGET_ALPHA)
- ExecContext *xc;
-
- // If this is a store conditional, act appropriately
- if (req->flags & LOCKED) {
- xc = req->xc;
-
- if (req->flags & UNCACHEABLE) {
- // Don't update result register (see stq_c in isa_desc)
- req->result = 2;
- xc->setStCondFailures(0);//Needed? [RGD]
- } else {
- bool lock_flag = xc->readMiscReg(TheISA::Lock_Flag_DepTag);
- Addr lock_addr = xc->readMiscReg(TheISA::Lock_Addr_DepTag);
- req->result = lock_flag;
- if (!lock_flag ||
- ((lock_addr & ~0xf) != (req->paddr & ~0xf))) {
- xc->setMiscReg(TheISA::Lock_Flag_DepTag, false);
- xc->setStCondFailures(xc->readStCondFailures() + 1);
- if (((xc->readStCondFailures()) % 100000) == 0) {
- std::cerr << "Warning: "
- << xc->readStCondFailures()
- << " consecutive store conditional failures "
- << "on cpu " << req->xc->readCpuId()
- << std::endl;
- }
- return NoFault;
- }
- else xc->setStCondFailures(0);
- }
- }
-
- // Need to clear any locked flags on other proccessors for
- // this address. Only do this for succsful Store Conditionals
- // and all other stores (WH64?). Unsuccessful Store
- // Conditionals would have returned above, and wouldn't fall
- // through.
- for (int i = 0; i < system->execContexts.size(); i++){
- xc = system->execContexts[i];
- if ((xc->readMiscReg(TheISA::Lock_Addr_DepTag) & ~0xf) ==
- (req->paddr & ~0xf)) {
- xc->setMiscReg(TheISA::Lock_Flag_DepTag, false);
- }
- }
-
-#endif
- return mem->write(req, (T)LittleEndianGuest::htog(data));
- }
-
- virtual bool misspeculating();
-
-
- MachInst getInst() { return inst; }
-
- void setInst(MachInst new_inst)
- {
- inst = new_inst;
- }
-
- Fault instRead(MemReqPtr &req)
- {
- return mem->read(req, inst);
- }
-
- void setCpuId(int id) { cpu_id = id; }
-
- int readCpuId() { return cpu_id; }
-
- FunctionalMemory *getMemPtr() { return mem; }
-
- void copyArchRegs(ExecContext *xc);
-
- //
- // New accessors for new decoder.
- //
- uint64_t readIntReg(int reg_idx)
- {
- return regs.intRegFile[reg_idx];
- }
-
- float readFloatRegSingle(int reg_idx)
- {
- return (float)regs.floatRegFile.d[reg_idx];
- }
-
- double readFloatRegDouble(int reg_idx)
- {
- return regs.floatRegFile.d[reg_idx];
- }
-
- uint64_t readFloatRegInt(int reg_idx)
- {
- return regs.floatRegFile.q[reg_idx];
- }
-
- void setIntReg(int reg_idx, uint64_t val)
- {
- regs.intRegFile[reg_idx] = val;
- }
-
- void setFloatRegSingle(int reg_idx, float val)
- {
- regs.floatRegFile.d[reg_idx] = (double)val;
- }
-
- void setFloatRegDouble(int reg_idx, double val)
- {
- regs.floatRegFile.d[reg_idx] = val;
- }
-
- void setFloatRegInt(int reg_idx, uint64_t val)
- {
- regs.floatRegFile.q[reg_idx] = val;
- }
-
- uint64_t readPC()
- {
- return regs.pc;
- }
-
- void setPC(uint64_t val)
- {
- regs.pc = val;
- }
-
- uint64_t readNextPC()
- {
- return regs.npc;
- }
-
- void setNextPC(uint64_t val)
- {
- regs.npc = val;
- }
-
- uint64_t readNextNPC()
- {
- return regs.nnpc;
- }
-
- void setNextNPC(uint64_t val)
- {
- regs.nnpc = val;
- }
-
-
- MiscReg readMiscReg(int misc_reg)
- {
- return regs.miscRegs.readReg(misc_reg);
- }
-
- MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault)
- {
- return regs.miscRegs.readRegWithEffect(misc_reg, fault, proxy);
- }
-
- Fault setMiscReg(int misc_reg, const MiscReg &val)
- {
- return regs.miscRegs.setReg(misc_reg, val);
- }
-
- Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val)
- {
- return regs.miscRegs.setRegWithEffect(misc_reg, val, proxy);
- }
-
- unsigned readStCondFailures() { return storeCondFailures; }
-
- void setStCondFailures(unsigned sc_failures)
- { storeCondFailures = sc_failures; }
-
- void clearArchRegs() { memset(&regs, 0, sizeof(regs)); }
-
-#if FULL_SYSTEM
- int readIntrFlag() { return regs.intrflag; }
- void setIntrFlag(int val) { regs.intrflag = val; }
- Fault hwrei();
- bool inPalMode() { return AlphaISA::PcPAL(regs.pc); }
- bool simPalCheck(int palFunc);
-#endif
-
-#if !FULL_SYSTEM
- TheISA::IntReg getSyscallArg(int i)
- {
- return regs.intRegFile[TheISA::ArgumentReg0 + i];
- }
-
- // used to shift args for indirect syscall
- void setSyscallArg(int i, TheISA::IntReg val)
- {
- regs.intRegFile[TheISA::ArgumentReg0 + i] = val;
- }
-
- void setSyscallReturn(SyscallReturn return_value)
- {
- TheISA::setSyscallReturn(return_value, &regs);
- }
-
- void syscall()
- {
- process->syscall(proxy);
- }
-
- Counter readFuncExeInst() { return func_exe_inst; }
-
- void setFuncExeInst(Counter new_val) { func_exe_inst = new_val; }
-#endif
-};
-
-
-// for non-speculative execution context, spec_mode is always false
-inline bool
-CPUExecContext::misspeculating()
-{
- return false;
-}
-
-#endif // __CPU_CPU_EXEC_CONTEXT_HH__
diff --git a/cpu/cpu_models.py b/cpu/cpu_models.py
deleted file mode 100644
index 2b1ae6277..000000000
--- a/cpu/cpu_models.py
+++ /dev/null
@@ -1,80 +0,0 @@
-# Copyright (c) 2003-2006 The Regents of The University of Michigan
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met: redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer;
-# redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution;
-# neither the name of the copyright holders nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-################
-# CpuModel class
-#
-# The CpuModel class encapsulates everything the ISA parser needs to
-# know about a particular CPU model.
-
-class CpuModel:
- # Dict of available CPU model objects. Accessible as CpuModel.dict.
- dict = {}
-
- # Constructor. Automatically adds models to CpuModel.dict.
- def __init__(self, name, filename, includes, strings):
- self.name = name
- self.filename = filename # filename for output exec code
- self.includes = includes # include files needed in exec file
- # The 'strings' dict holds all the per-CPU symbols we can
- # substitute into templates etc.
- self.strings = strings
- # Add self to dict
- CpuModel.dict[name] = self
-
-
-#
-# Define CPU models.
-#
-# Parameters are:
-# - name of model
-# - filename for generated ISA execution file
-# - includes needed for generated ISA execution file
-# - substitution strings for ISA description templates
-#
-
-CpuModel('SimpleCPU', 'simple_cpu_exec.cc',
- '#include "cpu/simple/cpu.hh"',
- { 'CPU_exec_context': 'SimpleCPU' })
-CpuModel('FastCPU', 'fast_cpu_exec.cc',
- '#include "cpu/fast/cpu.hh"',
- { 'CPU_exec_context': 'FastCPU' })
-CpuModel('FullCPU', 'full_cpu_exec.cc',
- '#include "encumbered/cpu/full/dyn_inst.hh"',
- { 'CPU_exec_context': 'DynInst' })
-CpuModel('AlphaFullCPU', 'alpha_o3_exec.cc',
- '#include "cpu/o3/alpha_dyn_inst.hh"',
- { 'CPU_exec_context': 'AlphaDynInst<AlphaSimpleImpl>' })
-CpuModel('OzoneSimpleCPU', 'ozone_simple_exec.cc',
- '#include "cpu/ozone/dyn_inst.hh"',
- { 'CPU_exec_context': 'OzoneDynInst<SimpleImpl>' })
-CpuModel('OzoneCPU', 'ozone_exec.cc',
- '#include "cpu/ozone/dyn_inst.hh"',
- { 'CPU_exec_context': 'OzoneDynInst<OzoneImpl>' })
-CpuModel('CheckerCPU', 'checker_cpu_exec.cc',
- '#include "cpu/checker/cpu.hh"',
- { 'CPU_exec_context': 'CheckerCPU' })
-
diff --git a/cpu/exec_context.hh b/cpu/exec_context.hh
deleted file mode 100644
index e1f1016e5..000000000
--- a/cpu/exec_context.hh
+++ /dev/null
@@ -1,382 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef __CPU_EXEC_CONTEXT_HH__
-#define __CPU_EXEC_CONTEXT_HH__
-
-#include "config/full_system.hh"
-#include "mem/mem_req.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 EndQuiesceEvent;
-class Event;
-class FunctionalMemory;
-class PhysicalMemory;
-class Process;
-class System;
-namespace Kernel {
- class Statistics;
-};
-
-class ExecContext
-{
- protected:
- typedef TheISA::RegFile RegFile;
- typedef TheISA::MachInst MachInst;
- typedef TheISA::IntReg IntReg;
- typedef TheISA::MiscRegFile MiscRegFile;
- typedef TheISA::MiscReg MiscReg;
- public:
- enum Status
- {
- /// Initialized but not running yet. All CPUs start in
- /// this state, but most transition to Active on cycle 1.
- /// In MP or SMT systems, non-primary contexts will stay
- /// in this state until a thread is assigned to them.
- Unallocated,
-
- /// Running. Instructions should be executed only when
- /// the context is in this state.
- Active,
-
- /// Temporarily inactive. Entered while waiting for
- /// synchronization, etc.
- Suspended,
-
- /// Permanently shut down. Entered when target executes
- /// m5exit pseudo-instruction. When all contexts enter
- /// this state, the simulation will terminate.
- Halted
- };
-
- virtual ~ExecContext() { };
-
- virtual BaseCPU *getCpuPtr() = 0;
-
- virtual void setCpuId(int id) = 0;
-
- virtual int readCpuId() = 0;
-
- virtual FunctionalMemory *getMemPtr() = 0;
-
-#if FULL_SYSTEM
- virtual System *getSystemPtr() = 0;
-
- virtual PhysicalMemory *getPhysMemPtr() = 0;
-
- virtual AlphaITB *getITBPtr() = 0;
-
- virtual AlphaDTB * getDTBPtr() = 0;
-
- virtual Kernel::Statistics *getKernelStats() = 0;
-#else
- virtual Process *getProcessPtr() = 0;
-#endif
-
- virtual Status status() const = 0;
-
- virtual void setStatus(Status new_status) = 0;
-
- /// Set the status to Active. Optional delay indicates number of
- /// cycles to wait before beginning execution.
- virtual void activate(int delay = 1) = 0;
-
- /// Set the status to Suspended.
- virtual void suspend() = 0;
-
- /// Set the status to Unallocated.
- virtual void deallocate() = 0;
-
- /// Set the status to Halted.
- virtual void halt() = 0;
-
-#if FULL_SYSTEM
- virtual void dumpFuncProfile() = 0;
-#endif
-
- virtual void takeOverFrom(ExecContext *old_context) = 0;
-
- virtual void regStats(const std::string &name) = 0;
-
- virtual void serialize(std::ostream &os) = 0;
- virtual void unserialize(Checkpoint *cp, const std::string &section) = 0;
-
-#if FULL_SYSTEM
- virtual EndQuiesceEvent *getQuiesceEvent() = 0;
-
- // Not necessarily the best location for these...
- // Having an extra function just to read these is obnoxious
- virtual Tick readLastActivate() = 0;
- virtual Tick readLastSuspend() = 0;
-
- virtual void profileClear() = 0;
- virtual void profileSample() = 0;
-#endif
-
- virtual int getThreadNum() = 0;
-
- // Also somewhat obnoxious. Really only used for the TLB fault.
- // However, may be quite useful in SPARC.
- virtual TheISA::MachInst getInst() = 0;
-
- virtual void copyArchRegs(ExecContext *xc) = 0;
-
- virtual void clearArchRegs() = 0;
-
- //
- // New accessors for new decoder.
- //
- virtual uint64_t readIntReg(int reg_idx) = 0;
-
- virtual float readFloatRegSingle(int reg_idx) = 0;
-
- virtual double readFloatRegDouble(int reg_idx) = 0;
-
- virtual uint64_t readFloatRegInt(int reg_idx) = 0;
-
- virtual void setIntReg(int reg_idx, uint64_t val) = 0;
-
- virtual void setFloatRegSingle(int reg_idx, float val) = 0;
-
- virtual void setFloatRegDouble(int reg_idx, double val) = 0;
-
- virtual void setFloatRegInt(int reg_idx, uint64_t val) = 0;
-
- virtual uint64_t readPC() = 0;
-
- virtual void setPC(uint64_t val) = 0;
-
- virtual uint64_t readNextPC() = 0;
-
- virtual void setNextPC(uint64_t val) = 0;
-
- virtual MiscReg readMiscReg(int misc_reg) = 0;
-
- virtual MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault) = 0;
-
- virtual Fault setMiscReg(int misc_reg, const MiscReg &val) = 0;
-
- virtual Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val) = 0;
-
- // Also not necessarily the best location for these two. Hopefully will go
- // away once we decide upon where st cond failures goes.
- virtual unsigned readStCondFailures() = 0;
-
- virtual void setStCondFailures(unsigned sc_failures) = 0;
-
-#if FULL_SYSTEM
- virtual bool inPalMode() = 0;
-#endif
-
- // Only really makes sense for old CPU model. Still could be useful though.
- virtual bool misspeculating() = 0;
-
-#if !FULL_SYSTEM
- virtual IntReg getSyscallArg(int i) = 0;
-
- // used to shift args for indirect syscall
- virtual void setSyscallArg(int i, IntReg val) = 0;
-
- virtual void setSyscallReturn(SyscallReturn return_value) = 0;
-
-// virtual void syscall() = 0;
-
- // Same with st cond failures.
- virtual Counter readFuncExeInst() = 0;
-#endif
-};
-
-template <class XC>
-class ProxyExecContext : public ExecContext
-{
- public:
- ProxyExecContext(XC *actual_xc)
- { actualXC = actual_xc; }
-
- private:
- XC *actualXC;
-
- public:
-
- BaseCPU *getCpuPtr() { return actualXC->getCpuPtr(); }
-
- void setCpuId(int id) { actualXC->setCpuId(id); }
-
- 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(); }
-
- Kernel::Statistics *getKernelStats() { return actualXC->getKernelStats(); }
-#else
- Process *getProcessPtr() { return actualXC->getProcessPtr(); }
-#endif
-
- Status status() const { return actualXC->status(); }
-
- void setStatus(Status new_status) { actualXC->setStatus(new_status); }
-
- /// Set the status to Active. Optional delay indicates number of
- /// cycles to wait before beginning execution.
- void activate(int delay = 1) { actualXC->activate(delay); }
-
- /// Set the status to Suspended.
- void suspend() { actualXC->suspend(); }
-
- /// Set the status to Unallocated.
- void deallocate() { actualXC->deallocate(); }
-
- /// Set the status to Halted.
- void halt() { actualXC->halt(); }
-
-#if FULL_SYSTEM
- void dumpFuncProfile() { actualXC->dumpFuncProfile(); }
-#endif
-
- void takeOverFrom(ExecContext *oldContext)
- { actualXC->takeOverFrom(oldContext); }
-
- void regStats(const std::string &name) { actualXC->regStats(name); }
-
- void serialize(std::ostream &os) { actualXC->serialize(os); }
- void unserialize(Checkpoint *cp, const std::string &section)
- { actualXC->unserialize(cp, section); }
-
-#if FULL_SYSTEM
- EndQuiesceEvent *getQuiesceEvent() { return actualXC->getQuiesceEvent(); }
-
- Tick readLastActivate() { return actualXC->readLastActivate(); }
- Tick readLastSuspend() { return actualXC->readLastSuspend(); }
-
- void profileClear() { return actualXC->profileClear(); }
- void profileSample() { return actualXC->profileSample(); }
-#endif
-
- int getThreadNum() { return actualXC->getThreadNum(); }
-
- // @todo: Do I need this?
- MachInst getInst() { return actualXC->getInst(); }
-
- // @todo: Do I need this?
- void copyArchRegs(ExecContext *xc) { actualXC->copyArchRegs(xc); }
-
- void clearArchRegs() { actualXC->clearArchRegs(); }
-
- //
- // New accessors for new decoder.
- //
- uint64_t readIntReg(int reg_idx)
- { return actualXC->readIntReg(reg_idx); }
-
- float readFloatRegSingle(int reg_idx)
- { return actualXC->readFloatRegSingle(reg_idx); }
-
- double readFloatRegDouble(int reg_idx)
- { return actualXC->readFloatRegDouble(reg_idx); }
-
- uint64_t readFloatRegInt(int reg_idx)
- { return actualXC->readFloatRegInt(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 setFloatRegDouble(int reg_idx, double val)
- { actualXC->setFloatRegDouble(reg_idx, val); }
-
- void setFloatRegInt(int reg_idx, uint64_t val)
- { actualXC->setFloatRegInt(reg_idx, val); }
-
- uint64_t readPC() { return actualXC->readPC(); }
-
- void setPC(uint64_t val) { actualXC->setPC(val); }
-
- uint64_t readNextPC() { return actualXC->readNextPC(); }
-
- void setNextPC(uint64_t val) { actualXC->setNextPC(val); }
-
- MiscReg readMiscReg(int misc_reg)
- { return actualXC->readMiscReg(misc_reg); }
-
- MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault)
- { return actualXC->readMiscRegWithEffect(misc_reg, fault); }
-
- Fault setMiscReg(int misc_reg, const MiscReg &val)
- { return actualXC->setMiscReg(misc_reg, val); }
-
- Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val)
- { return actualXC->setMiscRegWithEffect(misc_reg, val); }
-
- unsigned readStCondFailures()
- { return actualXC->readStCondFailures(); }
-
- void setStCondFailures(unsigned sc_failures)
- { actualXC->setStCondFailures(sc_failures); }
-#if FULL_SYSTEM
- bool inPalMode() { return actualXC->inPalMode(); }
-#endif
-
- // @todo: Fix this!
- bool misspeculating() { return actualXC->misspeculating(); }
-
-#if !FULL_SYSTEM
- IntReg getSyscallArg(int i) { return actualXC->getSyscallArg(i); }
-
- // used to shift args for indirect syscall
- void setSyscallArg(int i, IntReg val)
- { actualXC->setSyscallArg(i, val); }
-
- void setSyscallReturn(SyscallReturn return_value)
- { actualXC->setSyscallReturn(return_value); }
-
-// void syscall() { actualXC->syscall(); }
-
- Counter readFuncExeInst() { return actualXC->readFuncExeInst(); }
-#endif
-};
-
-#endif
diff --git a/cpu/exetrace.cc b/cpu/exetrace.cc
deleted file mode 100644
index d5eacd839..000000000
--- a/cpu/exetrace.cc
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
- * Copyright (c) 2001-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <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/static_inst.hh"
-
-using namespace std;
-
-
-////////////////////////////////////////////////////////////////////////
-//
-// Methods for the InstRecord object
-//
-
-
-void
-Trace::InstRecord::dump(ostream &outs)
-{
- if (flags[INTEL_FORMAT]) {
-#if FULL_SYSTEM
- bool is_trace_system = (cpu->system->name() == trace_system);
-#else
- bool is_trace_system = true;
-#endif
- if (is_trace_system) {
- ccprintf(outs, "%7d ) ", cycle);
- outs << "0x" << hex << PC << ":\t";
- if (staticInst->isLoad()) {
- outs << "<RD 0x" << hex << addr;
- outs << ">";
- } else if (staticInst->isStore()) {
- outs << "<WR 0x" << hex << addr;
- outs << ">";
- }
- outs << endl;
- }
- } else {
- if (flags[PRINT_CYCLE])
- ccprintf(outs, "%7d: ", cycle);
-
- outs << cpu->name() << " ";
-
- if (flags[TRACE_MISSPEC])
- outs << (misspeculating ? "-" : "+") << " ";
-
- if (flags[PRINT_THREAD_NUM])
- outs << "T" << thread << " : ";
-
-
- std::string sym_str;
- Addr sym_addr;
- if (debugSymbolTable
- && debugSymbolTable->findNearestSymbol(PC, sym_str, sym_addr)
- && flags[PC_SYMBOL]) {
- if (PC != sym_addr)
- sym_str += csprintf("+%d", PC - sym_addr);
- outs << "@" << sym_str << " : ";
- }
- else {
- outs << "0x" << hex << PC << " : ";
- }
-
- //
- // Print decoded instruction
- //
-
-#if defined(__GNUC__) && (__GNUC__ < 3)
- // There's a bug in gcc 2.x library that prevents setw()
- // from working properly on strings
- string mc(staticInst->disassemble(PC, debugSymbolTable));
- while (mc.length() < 26)
- mc += " ";
- outs << mc;
-#else
- outs << setw(26) << left << staticInst->disassemble(PC, debugSymbolTable);
-#endif
-
- outs << " : ";
-
- if (flags[PRINT_OP_CLASS]) {
- outs << opClassStrings[staticInst->opClass()] << " : ";
- }
-
- if (flags[PRINT_RESULT_DATA] && data_status != DataInvalid) {
- outs << " D=";
-#if 0
- if (data_status == DataDouble)
- ccprintf(outs, "%f", data.as_double);
- else
- ccprintf(outs, "%#018x", data.as_int);
-#else
- ccprintf(outs, "%#018x", data.as_int);
-#endif
- }
-
- if (flags[PRINT_EFF_ADDR] && addr_valid)
- outs << " A=0x" << hex << addr;
-
- if (flags[PRINT_INT_REGS] && regs_valid) {
- for (int i = 0; i < 32;)
- for (int j = i + 1; i <= j; i++)
- ccprintf(outs, "r%02d = %#018x%s", i, iregs->regs[i],
- ((i == j) ? "\n" : " "));
- outs << "\n";
- }
-
- if (flags[PRINT_FETCH_SEQ] && fetch_seq_valid)
- outs << " FetchSeq=" << dec << fetch_seq;
-
- if (flags[PRINT_CP_SEQ] && cp_seq_valid)
- outs << " CPSeq=" << dec << cp_seq;
-
- //
- // End of line...
- //
- outs << endl;
- }
-}
-
-
-vector<bool> Trace::InstRecord::flags(NUM_BITS);
-string Trace::InstRecord::trace_system;
-
-////////////////////////////////////////////////////////////////////////
-//
-// Parameter space for per-cycle execution address tracing options.
-// Derive from ParamContext so we can override checkParams() function.
-//
-class ExecutionTraceParamContext : public ParamContext
-{
- public:
- ExecutionTraceParamContext(const string &_iniSection)
- : ParamContext(_iniSection)
- {
- }
-
- void checkParams(); // defined at bottom of file
-};
-
-ExecutionTraceParamContext exeTraceParams("exetrace");
-
-Param<bool> exe_trace_spec(&exeTraceParams, "speculative",
- "capture speculative instructions", true);
-
-Param<bool> exe_trace_print_cycle(&exeTraceParams, "print_cycle",
- "print cycle number", true);
-Param<bool> exe_trace_print_opclass(&exeTraceParams, "print_opclass",
- "print op class", true);
-Param<bool> exe_trace_print_thread(&exeTraceParams, "print_thread",
- "print thread number", true);
-Param<bool> exe_trace_print_effaddr(&exeTraceParams, "print_effaddr",
- "print effective address", true);
-Param<bool> exe_trace_print_data(&exeTraceParams, "print_data",
- "print result data", true);
-Param<bool> exe_trace_print_iregs(&exeTraceParams, "print_iregs",
- "print all integer regs", false);
-Param<bool> exe_trace_print_fetchseq(&exeTraceParams, "print_fetchseq",
- "print fetch sequence number", false);
-Param<bool> exe_trace_print_cp_seq(&exeTraceParams, "print_cpseq",
- "print correct-path sequence number", false);
-Param<bool> exe_trace_pc_symbol(&exeTraceParams, "pc_symbol",
- "Use symbols for the PC if available", true);
-Param<bool> exe_trace_intel_format(&exeTraceParams, "intel_format",
- "print trace in intel compatible format", false);
-Param<string> exe_trace_system(&exeTraceParams, "trace_system",
- "print trace of which system (client or server)",
- "client");
-
-
-//
-// Helper function for ExecutionTraceParamContext::checkParams() just
-// to get us into the InstRecord namespace
-//
-void
-Trace::InstRecord::setParams()
-{
- flags[TRACE_MISSPEC] = exe_trace_spec;
-
- flags[PRINT_CYCLE] = exe_trace_print_cycle;
- flags[PRINT_OP_CLASS] = exe_trace_print_opclass;
- flags[PRINT_THREAD_NUM] = exe_trace_print_thread;
- flags[PRINT_RESULT_DATA] = exe_trace_print_effaddr;
- flags[PRINT_EFF_ADDR] = exe_trace_print_data;
- flags[PRINT_INT_REGS] = exe_trace_print_iregs;
- flags[PRINT_FETCH_SEQ] = exe_trace_print_fetchseq;
- flags[PRINT_CP_SEQ] = exe_trace_print_cp_seq;
- flags[PC_SYMBOL] = exe_trace_pc_symbol;
- flags[INTEL_FORMAT] = exe_trace_intel_format;
- trace_system = exe_trace_system;
-}
-
-void
-ExecutionTraceParamContext::checkParams()
-{
- Trace::InstRecord::setParams();
-}
-
diff --git a/cpu/exetrace.hh b/cpu/exetrace.hh
deleted file mode 100644
index 2f70e26e7..000000000
--- a/cpu/exetrace.hh
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * Copyright (c) 2001-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __EXETRACE_HH__
-#define __EXETRACE_HH__
-
-#include <fstream>
-#include <vector>
-
-#include "sim/host.hh"
-#include "cpu/inst_seq.hh" // for InstSeqNum
-#include "base/trace.hh"
-#include "cpu/exec_context.hh"
-#include "cpu/static_inst.hh"
-
-class BaseCPU;
-
-
-namespace Trace {
-
-class InstRecord : public Record
-{
- protected:
- typedef TheISA::IntRegFile IntRegFile;
-
- // The following fields are initialized by the constructor and
- // thus guaranteed to be valid.
- BaseCPU *cpu;
- // need to make this ref-counted so it doesn't go away before we
- // dump the record
- StaticInstPtr staticInst;
- Addr PC;
- bool misspeculating;
- unsigned thread;
-
- // The remaining fields are only valid for particular instruction
- // types (e.g, addresses for memory ops) or when particular
- // options are enabled (e.g., tracing full register contents).
- // Each data field has an associated valid flag to indicate
- // whether the data field is valid.
- Addr addr;
- bool addr_valid;
-
- union {
- uint64_t as_int;
- double as_double;
- } data;
- enum {
- DataInvalid = 0,
- DataInt8 = 1, // set to equal number of bytes
- DataInt16 = 2,
- DataInt32 = 4,
- DataInt64 = 8,
- DataDouble = 3
- } data_status;
-
- InstSeqNum fetch_seq;
- bool fetch_seq_valid;
-
- InstSeqNum cp_seq;
- bool cp_seq_valid;
-
- struct iRegFile {
- IntRegFile regs;
- };
- iRegFile *iregs;
- bool regs_valid;
-
- public:
- InstRecord(Tick _cycle, BaseCPU *_cpu,
- const StaticInstPtr &_staticInst,
- Addr _pc, bool spec, int _thread)
- : Record(_cycle), cpu(_cpu), staticInst(_staticInst), PC(_pc),
- misspeculating(spec), thread(_thread)
- {
- data_status = DataInvalid;
- addr_valid = false;
- regs_valid = false;
-
- fetch_seq_valid = false;
- cp_seq_valid = false;
- }
-
- virtual ~InstRecord() { }
-
- virtual void dump(std::ostream &outs);
-
- void setAddr(Addr a) { addr = a; addr_valid = true; }
-
- void setData(uint64_t d) { data.as_int = d; data_status = DataInt64; }
- void setData(uint32_t d) { data.as_int = d; data_status = DataInt32; }
- void setData(uint16_t d) { data.as_int = d; data_status = DataInt16; }
- void setData(uint8_t d) { data.as_int = d; data_status = DataInt8; }
-
- void setData(int64_t d) { setData((uint64_t)d); }
- void setData(int32_t d) { setData((uint32_t)d); }
- void setData(int16_t d) { setData((uint16_t)d); }
- void setData(int8_t d) { setData((uint8_t)d); }
-
- void setData(double d) { data.as_double = d; data_status = DataDouble; }
-
- void setFetchSeq(InstSeqNum seq)
- { fetch_seq = seq; fetch_seq_valid = true; }
-
- void setCPSeq(InstSeqNum seq)
- { cp_seq = seq; cp_seq_valid = true; }
-
- void setRegs(const IntRegFile &regs);
-
- void finalize() { theLog.append(this); }
-
- enum InstExecFlagBits {
- TRACE_MISSPEC = 0,
- PRINT_CYCLE,
- PRINT_OP_CLASS,
- PRINT_THREAD_NUM,
- PRINT_RESULT_DATA,
- PRINT_EFF_ADDR,
- PRINT_INT_REGS,
- PRINT_FETCH_SEQ,
- PRINT_CP_SEQ,
- PC_SYMBOL,
- INTEL_FORMAT,
- NUM_BITS
- };
-
- static std::vector<bool> flags;
- static std::string trace_system;
-
- static void setParams();
-
- static bool traceMisspec() { return flags[TRACE_MISSPEC]; }
-};
-
-
-inline void
-InstRecord::setRegs(const IntRegFile &regs)
-{
- if (!iregs)
- iregs = new iRegFile;
-
- memcpy(&iregs->regs, regs, sizeof(IntRegFile));
- regs_valid = true;
-}
-
-inline
-InstRecord *
-getInstRecord(Tick cycle, ExecContext *xc, BaseCPU *cpu,
- const StaticInstPtr staticInst,
- Addr pc, int thread = 0)
-{
- if (DTRACE(InstExec) &&
- (InstRecord::traceMisspec() || !xc->misspeculating())) {
- return new InstRecord(cycle, cpu, staticInst, pc,
- xc->misspeculating(), thread);
- }
-
- return NULL;
-}
-
-
-}
-
-#endif // __EXETRACE_HH__
diff --git a/cpu/memtest/memtest.cc b/cpu/memtest/memtest.cc
deleted file mode 100644
index 94b66b70b..000000000
--- a/cpu/memtest/memtest.cc
+++ /dev/null
@@ -1,441 +0,0 @@
-/*
- * 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.
- */
-
-// FIX ME: make trackBlkAddr use blocksize from actual cache, not hard coded
-
-#include <iomanip>
-#include <set>
-#include <sstream>
-#include <string>
-#include <vector>
-
-#include "base/misc.hh"
-#include "base/statistics.hh"
-#include "cpu/cpu_exec_context.hh"
-#include "cpu/memtest/memtest.hh"
-#include "mem/cache/base_cache.hh"
-#include "sim/builder.hh"
-#include "sim/sim_events.hh"
-#include "sim/stats.hh"
-
-using namespace std;
-using namespace TheISA;
-
-int TESTER_ALLOCATOR=0;
-
-MemTest::MemTest(const string &name,
- MemInterface *_cache_interface,
- FunctionalMemory *main_mem,
- FunctionalMemory *check_mem,
- unsigned _memorySize,
- unsigned _percentReads,
- unsigned _percentCopies,
- unsigned _percentUncacheable,
- unsigned _progressInterval,
- unsigned _percentSourceUnaligned,
- unsigned _percentDestUnaligned,
- Addr _traceAddr,
- Counter _max_loads)
- : SimObject(name),
- tickEvent(this),
- cacheInterface(_cache_interface),
- mainMem(main_mem),
- checkMem(check_mem),
- size(_memorySize),
- percentReads(_percentReads),
- percentCopies(_percentCopies),
- percentUncacheable(_percentUncacheable),
- progressInterval(_progressInterval),
- nextProgressMessage(_progressInterval),
- percentSourceUnaligned(_percentSourceUnaligned),
- percentDestUnaligned(percentDestUnaligned),
- maxLoads(_max_loads)
-{
- vector<string> cmd;
- cmd.push_back("/bin/ls");
- vector<string> null_vec;
- cpuXC = new CPUExecContext(NULL, 0, mainMem, 0);
-
- blockSize = cacheInterface->getBlockSize();
- blockAddrMask = blockSize - 1;
- traceBlockAddr = blockAddr(_traceAddr);
-
- //setup data storage with interesting values
- uint8_t *data1 = new uint8_t[size];
- uint8_t *data2 = new uint8_t[size];
- uint8_t *data3 = new uint8_t[size];
- memset(data1, 1, size);
- memset(data2, 2, size);
- memset(data3, 3, size);
- curTick = 0;
-
- baseAddr1 = 0x100000;
- baseAddr2 = 0x400000;
- uncacheAddr = 0x800000;
-
- // set up intial memory contents here
- mainMem->prot_write(baseAddr1, data1, size);
- checkMem->prot_write(baseAddr1, data1, size);
- mainMem->prot_write(baseAddr2, data2, size);
- checkMem->prot_write(baseAddr2, data2, size);
- mainMem->prot_write(uncacheAddr, data3, size);
- checkMem->prot_write(uncacheAddr, data3, size);
-
- delete [] data1;
- delete [] data2;
- delete [] data3;
-
- // set up counters
- noResponseCycles = 0;
- numReads = 0;
- tickEvent.schedule(0);
-
- id = TESTER_ALLOCATOR++;
-}
-
-static void
-printData(ostream &os, uint8_t *data, int nbytes)
-{
- os << hex << setfill('0');
- // assume little-endian: print bytes from highest address to lowest
- for (uint8_t *dp = data + nbytes - 1; dp >= data; --dp) {
- os << setw(2) << (unsigned)*dp;
- }
- os << dec;
-}
-
-void
-MemTest::completeRequest(MemReqPtr &req, uint8_t *data)
-{
- //Remove the address from the list of outstanding
- std::set<unsigned>::iterator removeAddr = outstandingAddrs.find(req->paddr);
- assert(removeAddr != outstandingAddrs.end());
- outstandingAddrs.erase(removeAddr);
-
- switch (req->cmd) {
- case Read:
- if (memcmp(req->data, data, req->size) != 0) {
- cerr << name() << ": on read of 0x" << hex << req->paddr
- << " (0x" << hex << blockAddr(req->paddr) << ")"
- << "@ cycle " << dec << curTick
- << ", cache returns 0x";
- printData(cerr, req->data, req->size);
- cerr << ", expected 0x";
- printData(cerr, data, req->size);
- cerr << endl;
- fatal("");
- }
-
- numReads++;
- numReadsStat++;
-
- if (numReads == nextProgressMessage) {
- ccprintf(cerr, "%s: completed %d read accesses @%d\n",
- name(), numReads, curTick);
- nextProgressMessage += progressInterval;
- }
-
- if (numReads >= maxLoads)
- SimExit(curTick, "Maximum number of loads reached!");
- break;
-
- case Write:
- numWritesStat++;
- break;
-
- case Copy:
- //Also remove dest from outstanding list
- removeAddr = outstandingAddrs.find(req->dest);
- assert(removeAddr != outstandingAddrs.end());
- outstandingAddrs.erase(removeAddr);
- numCopiesStat++;
- break;
-
- default:
- panic("invalid command");
- }
-
- if (blockAddr(req->paddr) == traceBlockAddr) {
- cerr << name() << ": completed "
- << (req->cmd.isWrite() ? "write" : "read")
- << " access of "
- << dec << req->size << " bytes at address 0x"
- << hex << req->paddr
- << " (0x" << hex << blockAddr(req->paddr) << ")"
- << ", value = 0x";
- printData(cerr, req->data, req->size);
- cerr << " @ cycle " << dec << curTick;
-
- cerr << endl;
- }
-
- noResponseCycles = 0;
- delete [] data;
-}
-
-
-void
-MemTest::regStats()
-{
- using namespace Stats;
-
-
- numReadsStat
- .name(name() + ".num_reads")
- .desc("number of read accesses completed")
- ;
-
- numWritesStat
- .name(name() + ".num_writes")
- .desc("number of write accesses completed")
- ;
-
- numCopiesStat
- .name(name() + ".num_copies")
- .desc("number of copy accesses completed")
- ;
-}
-
-void
-MemTest::tick()
-{
- if (!tickEvent.scheduled())
- tickEvent.schedule(curTick + cycles(1));
-
- if (++noResponseCycles >= 500000) {
- cerr << name() << ": deadlocked at cycle " << curTick << endl;
- fatal("");
- }
-
- if (cacheInterface->isBlocked()) {
- return;
- }
-
- //make new request
- unsigned cmd = random() % 100;
- unsigned offset = random() % size;
- unsigned base = random() % 2;
- uint64_t data = random();
- unsigned access_size = random() % 4;
- unsigned cacheable = random() % 100;
-
- //If we aren't doing copies, use id as offset, and do a false sharing
- //mem tester
- if (percentCopies == 0) {
- //We can eliminate the lower bits of the offset, and then use the id
- //to offset within the blks
- offset &= ~63; //Not the low order bits
- offset += id;
- access_size = 0;
- }
-
- MemReqPtr req = new MemReq();
-
- if (cacheable < percentUncacheable) {
- req->flags |= UNCACHEABLE;
- req->paddr = uncacheAddr + offset;
- } else {
- req->paddr = ((base) ? baseAddr1 : baseAddr2) + offset;
- }
- // bool probe = (random() % 2 == 1) && !req->isUncacheable();
- bool probe = false;
-
- req->size = 1 << access_size;
- req->data = new uint8_t[req->size];
- req->paddr &= ~(req->size - 1);
- req->time = curTick;
- req->xc = cpuXC->getProxy();
-
- if (cmd < percentReads) {
- // read
-
- //For now we only allow one outstanding request per addreess per tester
- //This means we assume CPU does write forwarding to reads that alias something
- //in the cpu store buffer.
- if (outstandingAddrs.find(req->paddr) != outstandingAddrs.end()) return;
- else outstandingAddrs.insert(req->paddr);
-
- req->cmd = Read;
- uint8_t *result = new uint8_t[8];
- checkMem->access(Read, req->paddr, result, req->size);
- if (blockAddr(req->paddr) == traceBlockAddr) {
- cerr << name()
- << ": initiating read "
- << ((probe) ? "probe of " : "access of ")
- << dec << req->size << " bytes from addr 0x"
- << hex << req->paddr
- << " (0x" << hex << blockAddr(req->paddr) << ")"
- << " at cycle "
- << dec << curTick << endl;
- }
- if (probe) {
- cacheInterface->probeAndUpdate(req);
- completeRequest(req, result);
- } else {
- req->completionEvent = new MemCompleteEvent(req, result, this);
- cacheInterface->access(req);
- }
- } else if (cmd < (100 - percentCopies)){
- // write
-
- //For now we only allow one outstanding request per addreess per tester
- //This means we assume CPU does write forwarding to reads that alias something
- //in the cpu store buffer.
- if (outstandingAddrs.find(req->paddr) != outstandingAddrs.end()) return;
- else outstandingAddrs.insert(req->paddr);
-
- req->cmd = Write;
- memcpy(req->data, &data, req->size);
- checkMem->access(Write, req->paddr, req->data, req->size);
- if (blockAddr(req->paddr) == traceBlockAddr) {
- cerr << name() << ": initiating write "
- << ((probe)?"probe of ":"access of ")
- << dec << req->size << " bytes (value = 0x";
- printData(cerr, req->data, req->size);
- cerr << ") to addr 0x"
- << hex << req->paddr
- << " (0x" << hex << blockAddr(req->paddr) << ")"
- << " at cycle "
- << dec << curTick << endl;
- }
- if (probe) {
- cacheInterface->probeAndUpdate(req);
- completeRequest(req, NULL);
- } else {
- req->completionEvent = new MemCompleteEvent(req, NULL, this);
- cacheInterface->access(req);
- }
- } else {
- // copy
- unsigned source_align = random() % 100;
- unsigned dest_align = random() % 100;
- unsigned offset2 = random() % size;
-
- Addr source = ((base) ? baseAddr1 : baseAddr2) + offset;
- Addr dest = ((base) ? baseAddr2 : baseAddr1) + offset2;
- if (outstandingAddrs.find(source) != outstandingAddrs.end()) return;
- else outstandingAddrs.insert(source);
- if (outstandingAddrs.find(dest) != outstandingAddrs.end()) return;
- else outstandingAddrs.insert(dest);
-
- if (source_align >= percentSourceUnaligned) {
- source = blockAddr(source);
- }
- if (dest_align >= percentDestUnaligned) {
- dest = blockAddr(dest);
- }
- req->cmd = Copy;
- req->flags &= ~UNCACHEABLE;
- req->paddr = source;
- req->dest = dest;
- delete [] req->data;
- req->data = new uint8_t[blockSize];
- req->size = blockSize;
- if (source == traceBlockAddr || dest == traceBlockAddr) {
- cerr << name()
- << ": initiating copy of "
- << dec << req->size << " bytes from addr 0x"
- << hex << source
- << " (0x" << hex << blockAddr(source) << ")"
- << " to addr 0x"
- << hex << dest
- << " (0x" << hex << blockAddr(dest) << ")"
- << " at cycle "
- << dec << curTick << endl;
- }
- cacheInterface->access(req);
- uint8_t result[blockSize];
- checkMem->access(Read, source, &result, blockSize);
- checkMem->access(Write, dest, &result, blockSize);
- }
-}
-
-
-void
-MemCompleteEvent::process()
-{
- tester->completeRequest(req, data);
- delete this;
-}
-
-
-const char *
-MemCompleteEvent::description()
-{
- return "memory access completion";
-}
-
-
-BEGIN_DECLARE_SIM_OBJECT_PARAMS(MemTest)
-
- SimObjectParam<BaseCache *> cache;
- SimObjectParam<FunctionalMemory *> main_mem;
- SimObjectParam<FunctionalMemory *> check_mem;
- Param<unsigned> memory_size;
- Param<unsigned> percent_reads;
- Param<unsigned> percent_copies;
- Param<unsigned> percent_uncacheable;
- Param<unsigned> progress_interval;
- Param<unsigned> percent_source_unaligned;
- Param<unsigned> percent_dest_unaligned;
- Param<Addr> trace_addr;
- Param<Counter> max_loads;
-
-END_DECLARE_SIM_OBJECT_PARAMS(MemTest)
-
-
-BEGIN_INIT_SIM_OBJECT_PARAMS(MemTest)
-
- INIT_PARAM(cache, "L1 cache"),
- INIT_PARAM(main_mem, "hierarchical memory"),
- INIT_PARAM(check_mem, "check memory"),
- INIT_PARAM(memory_size, "memory size"),
- INIT_PARAM(percent_reads, "target read percentage"),
- INIT_PARAM(percent_copies, "target copy percentage"),
- INIT_PARAM(percent_uncacheable, "target uncacheable percentage"),
- INIT_PARAM(progress_interval, "progress report interval (in accesses)"),
- INIT_PARAM(percent_source_unaligned,
- "percent of copy source address that are unaligned"),
- INIT_PARAM(percent_dest_unaligned,
- "percent of copy dest address that are unaligned"),
- INIT_PARAM(trace_addr, "address to trace"),
- INIT_PARAM(max_loads, "terminate when we have reached this load count")
-
-END_INIT_SIM_OBJECT_PARAMS(MemTest)
-
-
-CREATE_SIM_OBJECT(MemTest)
-{
- return new MemTest(getInstanceName(), cache->getInterface(), main_mem,
- check_mem, memory_size, percent_reads, percent_copies,
- percent_uncacheable, progress_interval,
- percent_source_unaligned, percent_dest_unaligned,
- trace_addr, max_loads);
-}
-
-REGISTER_SIM_OBJECT("MemTest", MemTest)
diff --git a/cpu/o3/alpha_cpu.hh b/cpu/o3/alpha_cpu.hh
deleted file mode 100644
index 5c89e3462..000000000
--- a/cpu/o3/alpha_cpu.hh
+++ /dev/null
@@ -1,430 +0,0 @@
-/*
- * Copyright (c) 2004-2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __CPU_O3_ALPHA_FULL_CPU_HH__
-#define __CPU_O3_ALPHA_FULL_CPU_HH__
-
-#include "arch/isa_traits.hh"
-#include "cpu/exec_context.hh"
-#include "cpu/o3/cpu.hh"
-#include "sim/byteswap.hh"
-
-class EndQuiesceEvent;
-namespace Kernel {
- class Statistics;
-};
-
-template <class Impl>
-class AlphaFullCPU : public FullO3CPU<Impl>
-{
- protected:
- typedef TheISA::IntReg IntReg;
- typedef TheISA::MiscReg MiscReg;
- typedef TheISA::RegFile RegFile;
- typedef TheISA::MiscRegFile MiscRegFile;
-
- public:
- typedef O3ThreadState<Impl> ImplState;
- typedef O3ThreadState<Impl> Thread;
- typedef typename Impl::Params Params;
-
- /** Constructs an AlphaFullCPU with the given parameters. */
- AlphaFullCPU(Params *params);
-
- class AlphaXC : public ExecContext
- {
- public:
- AlphaFullCPU<Impl> *cpu;
-
- O3ThreadState<Impl> *thread;
-
- virtual BaseCPU *getCpuPtr() { return cpu; }
-
- virtual void setCpuId(int id) { cpu->cpu_id = id; }
-
- virtual int readCpuId() { return cpu->cpu_id; }
-
- virtual FunctionalMemory *getMemPtr() { return thread->mem; }
-
-#if FULL_SYSTEM
- virtual System *getSystemPtr() { return cpu->system; }
-
- virtual PhysicalMemory *getPhysMemPtr() { return cpu->physmem; }
-
- virtual AlphaITB *getITBPtr() { return cpu->itb; }
-
- virtual AlphaDTB * getDTBPtr() { return cpu->dtb; }
-
- virtual Kernel::Statistics *getKernelStats()
- { return thread->kernelStats; }
-#else
- virtual Process *getProcessPtr() { return thread->process; }
-#endif
-
- virtual Status status() const { return thread->status(); }
-
- virtual void setStatus(Status new_status)
- { thread->setStatus(new_status); }
-
- /// Set the status to Active. Optional delay indicates number of
- /// cycles to wait before beginning execution.
- virtual void activate(int delay = 1);
-
- /// Set the status to Suspended.
- virtual void suspend();
-
- /// Set the status to Unallocated.
- virtual void deallocate();
-
- /// Set the status to Halted.
- virtual void halt();
-
-#if FULL_SYSTEM
- virtual void dumpFuncProfile();
-#endif
-
- virtual void takeOverFrom(ExecContext *old_context);
-
- virtual void regStats(const std::string &name);
-
- virtual void serialize(std::ostream &os);
- virtual void unserialize(Checkpoint *cp, const std::string &section);
-
-#if FULL_SYSTEM
- virtual EndQuiesceEvent *getQuiesceEvent();
-
- virtual Tick readLastActivate();
- virtual Tick readLastSuspend();
-
- virtual void profileClear();
- virtual void profileSample();
-#endif
-
- virtual int getThreadNum() { return thread->tid; }
-
- virtual TheISA::MachInst getInst();
-
- virtual void copyArchRegs(ExecContext *xc);
-
- virtual void clearArchRegs();
-
- virtual uint64_t readIntReg(int reg_idx);
-
- virtual float readFloatRegSingle(int reg_idx);
-
- virtual double readFloatRegDouble(int reg_idx);
-
- virtual uint64_t readFloatRegInt(int reg_idx);
-
- virtual void setIntReg(int reg_idx, uint64_t val);
-
- virtual void setFloatRegSingle(int reg_idx, float val);
-
- virtual void setFloatRegDouble(int reg_idx, double val);
-
- virtual void setFloatRegInt(int reg_idx, uint64_t val);
-
- virtual uint64_t readPC()
- { return cpu->readPC(thread->tid); }
-
- virtual void setPC(uint64_t val);
-
- virtual uint64_t readNextPC()
- { return cpu->readNextPC(thread->tid); }
-
- virtual void setNextPC(uint64_t val);
-
- virtual MiscReg readMiscReg(int misc_reg)
- { return cpu->readMiscReg(misc_reg, thread->tid); }
-
- virtual MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault)
- { return cpu->readMiscRegWithEffect(misc_reg, fault, thread->tid); }
-
- virtual Fault setMiscReg(int misc_reg, const MiscReg &val);
-
- virtual Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val);
-
- // @todo: Figure out where these store cond failures should go.
- virtual unsigned readStCondFailures()
- { return thread->storeCondFailures; }
-
- virtual void setStCondFailures(unsigned sc_failures)
- { thread->storeCondFailures = sc_failures; }
-
-#if FULL_SYSTEM
- virtual bool inPalMode()
- { return TheISA::PcPAL(cpu->readPC(thread->tid)); }
-#endif
-
- // Only really makes sense for old CPU model. Lots of code
- // outside the CPU still checks this function, so it will
- // always return false to keep everything working.
- virtual bool misspeculating() { return false; }
-
-#if !FULL_SYSTEM
- virtual IntReg getSyscallArg(int i);
-
- virtual void setSyscallArg(int i, IntReg val);
-
- virtual void setSyscallReturn(SyscallReturn return_value);
-
- virtual void syscall() { return cpu->syscall(thread->tid); }
-
- virtual Counter readFuncExeInst() { return thread->funcExeInst; }
-#endif
- };
-
-#if FULL_SYSTEM
- /** ITB pointer. */
- AlphaITB *itb;
- /** DTB pointer. */
- AlphaDTB *dtb;
-#endif
-
- /** Registers statistics. */
- void regStats();
-
-#if FULL_SYSTEM
- /** Translates instruction requestion. */
- Fault translateInstReq(MemReqPtr &req)
- {
- return itb->translate(req);
- }
-
- /** Translates data read request. */
- Fault translateDataReadReq(MemReqPtr &req)
- {
- return dtb->translate(req, false);
- }
-
- /** Translates data write request. */
- Fault translateDataWriteReq(MemReqPtr &req)
- {
- return dtb->translate(req, true);
- }
-
-#else
- 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;
- }
-
- /** Translates instruction requestion in syscall emulation mode. */
- Fault translateInstReq(MemReqPtr &req)
- {
- return dummyTranslation(req);
- }
-
- /** Translates data read request in syscall emulation mode. */
- Fault translateDataReadReq(MemReqPtr &req)
- {
- return dummyTranslation(req);
- }
-
- /** Translates data write request in syscall emulation mode. */
- Fault translateDataWriteReq(MemReqPtr &req)
- {
- return dummyTranslation(req);
- }
-
-#endif
- MiscReg readMiscReg(int misc_reg, unsigned tid);
-
- MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault, unsigned tid);
-
- Fault setMiscReg(int misc_reg, const MiscReg &val, unsigned tid);
-
- Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val, unsigned tid);
-
- void squashFromXC(unsigned tid);
-
-#if FULL_SYSTEM
- void post_interrupt(int int_num, int index);
-
- int readIntrFlag();
- /** Sets the interrupt flags. */
- void setIntrFlag(int val);
- /** HW return from error interrupt. */
- Fault hwrei(unsigned tid);
- /** Returns if a specific PC is a PAL mode PC. */
- bool inPalMode(uint64_t PC)
- { return AlphaISA::PcPAL(PC); }
-
- /** Traps to handle given fault. */
- void trap(Fault fault, unsigned tid);
- bool simPalCheck(int palFunc, unsigned tid);
-
- /** Processes any interrupts. */
- void processInterrupts();
-
- /** Halts the CPU. */
- void halt() { panic("Halt not implemented!\n"); }
-#endif
-
-
-#if !FULL_SYSTEM
- /** Executes a syscall.
- * @todo: Determine if this needs to be virtual.
- */
- void syscall(int thread_num);
- /** Gets a syscall argument. */
- IntReg getSyscallArg(int i, int tid);
-
- /** Used to shift args for indirect syscall. */
- void setSyscallArg(int i, IntReg val, int tid);
-
- /** Sets the return value of a syscall. */
- void setSyscallReturn(SyscallReturn return_value, int tid);
-#endif
-
- /** Read from memory function. */
- template <class T>
- Fault read(MemReqPtr &req, T &data)
- {
-#if 0
-#if FULL_SYSTEM && defined(TARGET_ALPHA)
- if (req->flags & LOCKED) {
- req->xc->setMiscReg(TheISA::Lock_Addr_DepTag, req->paddr);
- req->xc->setMiscReg(TheISA::Lock_Flag_DepTag, true);
- }
-#endif
-#endif
- Fault error;
-
-#if FULL_SYSTEM
- // @todo: Fix this LL/SC hack.
- if (req->flags & LOCKED) {
- lockAddr = req->paddr;
- lockFlag = true;
- }
-#endif
-
- error = this->mem->read(req, data);
- data = gtoh(data);
- return error;
- }
-
- /** CPU read function, forwards read to LSQ. */
- template <class T>
- Fault read(MemReqPtr &req, T &data, int load_idx)
- {
- return this->iew.ldstQueue.read(req, data, load_idx);
- }
-
- /** Write to memory function. */
- template <class T>
- Fault write(MemReqPtr &req, T &data)
- {
-#if 0
-#if FULL_SYSTEM && defined(TARGET_ALPHA)
- ExecContext *xc;
-
- // If this is a store conditional, act appropriately
- if (req->flags & LOCKED) {
- xc = req->xc;
-
- if (req->flags & UNCACHEABLE) {
- // Don't update result register (see stq_c in isa_desc)
- req->result = 2;
- xc->setStCondFailures(0);//Needed? [RGD]
- } else {
- bool lock_flag = xc->readMiscReg(TheISA::Lock_Flag_DepTag);
- Addr lock_addr = xc->readMiscReg(TheISA::Lock_Addr_DepTag);
- req->result = lock_flag;
- if (!lock_flag ||
- ((lock_addr & ~0xf) != (req->paddr & ~0xf))) {
- xc->setMiscReg(TheISA::Lock_Flag_DepTag, false);
- xc->setStCondFailures(xc->readStCondFailures() + 1);
- if (((xc->readStCondFailures()) % 100000) == 0) {
- std::cerr << "Warning: "
- << xc->readStCondFailures()
- << " consecutive store conditional failures "
- << "on cpu " << req->xc->readCpuId()
- << std::endl;
- }
- return NoFault;
- }
- else xc->setStCondFailures(0);
- }
- }
-
- // Need to clear any locked flags on other proccessors for
- // this address. Only do this for succsful Store Conditionals
- // and all other stores (WH64?). Unsuccessful Store
- // Conditionals would have returned above, and wouldn't fall
- // through.
- for (int i = 0; i < this->system->execContexts.size(); i++){
- xc = this->system->execContexts[i];
- if ((xc->readMiscReg(TheISA::Lock_Addr_DepTag) & ~0xf) ==
- (req->paddr & ~0xf)) {
- xc->setMiscReg(TheISA::Lock_Flag_DepTag, false);
- }
- }
-
-#endif
-#endif
-
-#if FULL_SYSTEM
- // @todo: Fix this LL/SC hack.
- if (req->flags & LOCKED) {
- if (req->flags & UNCACHEABLE) {
- req->result = 2;
- } else {
- if (this->lockFlag) {
- req->result = 1;
- } else {
- req->result = 0;
- return NoFault;
- }
- }
- }
-#endif
-
- return this->mem->write(req, (T)htog(data));
- }
-
- /** CPU write function, forwards write to LSQ. */
- template <class T>
- Fault write(MemReqPtr &req, T &data, int store_idx)
- {
- return this->iew.ldstQueue.write(req, data, store_idx);
- }
-
- Addr lockAddr;
-
- bool lockFlag;
-};
-
-#endif // __CPU_O3_ALPHA_FULL_CPU_HH__
diff --git a/cpu/o3/alpha_cpu_impl.hh b/cpu/o3/alpha_cpu_impl.hh
deleted file mode 100644
index 91cd3d9e6..000000000
--- a/cpu/o3/alpha_cpu_impl.hh
+++ /dev/null
@@ -1,776 +0,0 @@
-/*
- * Copyright (c) 2004-2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "arch/alpha/faults.hh"
-#include "base/cprintf.hh"
-#include "base/statistics.hh"
-#include "base/timebuf.hh"
-#include "cpu/checker/exec_context.hh"
-#include "mem/mem_interface.hh"
-#include "sim/sim_events.hh"
-#include "sim/stats.hh"
-
-#include "cpu/o3/alpha_cpu.hh"
-#include "cpu/o3/alpha_params.hh"
-#include "cpu/o3/comm.hh"
-#include "cpu/o3/thread_state.hh"
-
-#if FULL_SYSTEM
-#include "arch/alpha/osfpal.hh"
-#include "arch/isa_traits.hh"
-#include "cpu/quiesce_event.hh"
-#include "kern/kernel_stats.hh"
-#endif
-
-using namespace TheISA;
-
-template <class Impl>
-AlphaFullCPU<Impl>::AlphaFullCPU(Params *params)
-#if FULL_SYSTEM
- : FullO3CPU<Impl>(params), itb(params->itb), dtb(params->dtb)
-#else
- : FullO3CPU<Impl>(params)
-#endif
-{
- DPRINTF(FullCPU, "AlphaFullCPU: Creating AlphaFullCPU object.\n");
-
- this->thread.resize(this->numThreads);
-
- for (int i = 0; i < this->numThreads; ++i) {
-#if FULL_SYSTEM
- assert(this->numThreads == 1);
- this->thread[i] = new Thread(this, 0, params->mem);
- this->thread[i]->setStatus(ExecContext::Suspended);
-#else
- if (i < params->workload.size()) {
- DPRINTF(FullCPU, "FullCPU: Workload[%i]'s starting PC is %#x, "
- "process is %#x",
- i, params->workload[i]->prog_entry, this->thread[i]);
- this->thread[i] = new Thread(this, i, params->workload[i], i);
- assert(params->workload[i]->getMemory() != NULL);
-
- this->thread[i]->setStatus(ExecContext::Suspended);
- //usedTids[i] = true;
- //threadMap[i] = i;
- } else {
- //Allocate Empty execution context so M5 can use later
- //when scheduling threads to CPU
- Process* dummy_proc = NULL;
-
- this->thread[i] = new Thread(this, i, dummy_proc, i);
- //usedTids[i] = false;
- }
-#endif // !FULL_SYSTEM
-
- this->thread[i]->numInst = 0;
-
- ExecContext *xc_proxy;
-
- AlphaXC *alpha_xc_proxy = new AlphaXC;
-
- if (params->checker) {
- xc_proxy = new CheckerExecContext<AlphaXC>(alpha_xc_proxy, this->checker);
- } else {
- xc_proxy = alpha_xc_proxy;
- }
-
- alpha_xc_proxy->cpu = this;
- alpha_xc_proxy->thread = this->thread[i];
-
-#if FULL_SYSTEM
- this->thread[i]->quiesceEvent =
- new EndQuiesceEvent(xc_proxy);
- this->thread[i]->lastActivate = 0;
- this->thread[i]->lastSuspend = 0;
-#endif
- this->thread[i]->xcProxy = xc_proxy;
-
- this->execContexts.push_back(xc_proxy);
- }
-
-
- for (int i=0; i < this->numThreads; i++) {
- this->thread[i]->funcExeInst = 0;
- }
-
- // Sets CPU pointers. These must be set at this level because the CPU
- // pointers are defined to be the highest level of CPU class.
- this->fetch.setCPU(this);
- this->decode.setCPU(this);
- this->rename.setCPU(this);
- this->iew.setCPU(this);
- this->commit.setCPU(this);
-
- this->rob.setCPU(this);
- this->regFile.setCPU(this);
-
- lockAddr = 0;
- lockFlag = false;
-}
-
-template <class Impl>
-void
-AlphaFullCPU<Impl>::regStats()
-{
- // Register stats for everything that has stats.
- this->fullCPURegStats();
- this->fetch.regStats();
- this->decode.regStats();
- this->rename.regStats();
- this->iew.regStats();
- this->commit.regStats();
-}
-
-#if FULL_SYSTEM
-template <class Impl>
-void
-AlphaFullCPU<Impl>::AlphaXC::dumpFuncProfile()
-{
- // Currently not supported
-}
-#endif
-
-template <class Impl>
-void
-AlphaFullCPU<Impl>::AlphaXC::takeOverFrom(ExecContext *old_context)
-{
- // some things should already be set up
- assert(getMemPtr() == old_context->getMemPtr());
-#if FULL_SYSTEM
- assert(getSystemPtr() == old_context->getSystemPtr());
-#else
- assert(getProcessPtr() == old_context->getProcessPtr());
-#endif
-
- // copy over functional state
- setStatus(old_context->status());
- copyArchRegs(old_context);
- setCpuId(old_context->readCpuId());
-#if !FULL_SYSTEM
- thread->funcExeInst = old_context->readFuncExeInst();
-#else
- EndQuiesceEvent *other_quiesce = old_context->getQuiesceEvent();
- if (other_quiesce) {
- // Point the quiesce event's XC at this XC so that it wakes up
- // the proper CPU.
- other_quiesce->xc = this;
- }
- if (thread->quiesceEvent) {
- thread->quiesceEvent->xc = this;
- }
-
- // Transfer kernel stats from one CPU to the other.
- thread->kernelStats = old_context->getKernelStats();
-// storeCondFailures = 0;
- cpu->lockFlag = false;
-#endif
-
- old_context->setStatus(ExecContext::Unallocated);
-
- thread->inSyscall = false;
- thread->trapPending = false;
-}
-
-template <class Impl>
-void
-AlphaFullCPU<Impl>::AlphaXC::activate(int delay)
-{
- DPRINTF(FullCPU, "Calling activate on AlphaXC\n");
-
- if (thread->status() == ExecContext::Active)
- return;
-
-#if FULL_SYSTEM
- thread->lastActivate = curTick;
-#endif
-
- if (thread->status() == ExecContext::Unallocated) {
- cpu->activateWhenReady(thread->tid);
- return;
- }
-
- thread->setStatus(ExecContext::Active);
-
- // status() == Suspended
- cpu->activateContext(thread->tid, delay);
-}
-
-template <class Impl>
-void
-AlphaFullCPU<Impl>::AlphaXC::suspend()
-{
- DPRINTF(FullCPU, "Calling suspend on AlphaXC\n");
-
- if (thread->status() == ExecContext::Suspended)
- return;
-
-#if FULL_SYSTEM
- thread->lastActivate = curTick;
- thread->lastSuspend = curTick;
-#endif
-/*
-#if FULL_SYSTEM
- // Don't change the status from active if there are pending interrupts
- if (cpu->check_interrupts()) {
- assert(status() == ExecContext::Active);
- return;
- }
-#endif
-*/
- thread->setStatus(ExecContext::Suspended);
- cpu->suspendContext(thread->tid);
-}
-
-template <class Impl>
-void
-AlphaFullCPU<Impl>::AlphaXC::deallocate()
-{
- DPRINTF(FullCPU, "Calling deallocate on AlphaXC\n");
-
- if (thread->status() == ExecContext::Unallocated)
- return;
-
- thread->setStatus(ExecContext::Unallocated);
- cpu->deallocateContext(thread->tid);
-}
-
-template <class Impl>
-void
-AlphaFullCPU<Impl>::AlphaXC::halt()
-{
- DPRINTF(FullCPU, "Calling halt on AlphaXC\n");
-
- if (thread->status() == ExecContext::Halted)
- return;
-
- thread->setStatus(ExecContext::Halted);
- cpu->haltContext(thread->tid);
-}
-
-template <class Impl>
-void
-AlphaFullCPU<Impl>::AlphaXC::regStats(const std::string &name)
-{
-#if FULL_SYSTEM
- thread->kernelStats = new Kernel::Statistics(cpu->system);
- thread->kernelStats->regStats(name + ".kern");
-#endif
-}
-
-template <class Impl>
-void
-AlphaFullCPU<Impl>::AlphaXC::serialize(std::ostream &os)
-{
-#if FULL_SYSTEM
- if (thread->kernelStats)
- thread->kernelStats->serialize(os);
-#endif
-
-}
-
-template <class Impl>
-void
-AlphaFullCPU<Impl>::AlphaXC::unserialize(Checkpoint *cp, const std::string &section)
-{
-#if FULL_SYSTEM
- if (thread->kernelStats)
- thread->kernelStats->unserialize(cp, section);
-#endif
-
-}
-
-#if FULL_SYSTEM
-template <class Impl>
-EndQuiesceEvent *
-AlphaFullCPU<Impl>::AlphaXC::getQuiesceEvent()
-{
- return thread->quiesceEvent;
-}
-
-template <class Impl>
-Tick
-AlphaFullCPU<Impl>::AlphaXC::readLastActivate()
-{
- return thread->lastActivate;
-}
-
-template <class Impl>
-Tick
-AlphaFullCPU<Impl>::AlphaXC::readLastSuspend()
-{
- return thread->lastSuspend;
-}
-
-template <class Impl>
-void
-AlphaFullCPU<Impl>::AlphaXC::profileClear()
-{}
-
-template <class Impl>
-void
-AlphaFullCPU<Impl>::AlphaXC::profileSample()
-{}
-#endif
-
-template <class Impl>
-TheISA::MachInst
-AlphaFullCPU<Impl>::AlphaXC:: getInst()
-{
- return thread->inst;
-}
-
-template <class Impl>
-void
-AlphaFullCPU<Impl>::AlphaXC::copyArchRegs(ExecContext *xc)
-{
- // This function will mess things up unless the ROB is empty and
- // there are no instructions in the pipeline.
- unsigned tid = thread->tid;
- PhysRegIndex renamed_reg;
-
- // First loop through the integer registers.
- for (int i = 0; i < AlphaISA::NumIntRegs; ++i) {
- renamed_reg = cpu->renameMap[tid].lookup(i);
-
- DPRINTF(FullCPU, "FullCPU: Copying over register %i, had data %lli, "
- "now has data %lli.\n",
- renamed_reg, cpu->readIntReg(renamed_reg),
- xc->readIntReg(i));
-
- cpu->setIntReg(renamed_reg, xc->readIntReg(i));
- }
-
- // Then loop through the floating point registers.
- for (int i = 0; i < AlphaISA::NumFloatRegs; ++i) {
- renamed_reg = cpu->renameMap[tid].lookup(i + AlphaISA::FP_Base_DepTag);
- cpu->setFloatRegDouble(renamed_reg,
- xc->readFloatRegDouble(i));
- cpu->setFloatRegInt(renamed_reg,
- xc->readFloatRegInt(i));
- }
-
- // Copy the misc regs.
- cpu->regFile.miscRegs[tid].copyMiscRegs(xc);
-
- // Then finally set the PC and the next PC.
- cpu->setPC(xc->readPC(), tid);
- cpu->setNextPC(xc->readNextPC(), tid);
-#if !FULL_SYSTEM
- this->thread->funcExeInst = xc->readFuncExeInst();
-#endif
-}
-
-template <class Impl>
-void
-AlphaFullCPU<Impl>::AlphaXC::clearArchRegs()
-{}
-
-template <class Impl>
-uint64_t
-AlphaFullCPU<Impl>::AlphaXC::readIntReg(int reg_idx)
-{
- DPRINTF(Fault, "Reading int register through the XC!\n");
- return cpu->readArchIntReg(reg_idx, thread->tid);
-}
-
-template <class Impl>
-float
-AlphaFullCPU<Impl>::AlphaXC::readFloatRegSingle(int reg_idx)
-{
- DPRINTF(Fault, "Reading float register through the XC!\n");
- return cpu->readArchFloatRegSingle(reg_idx, thread->tid);
-}
-
-template <class Impl>
-double
-AlphaFullCPU<Impl>::AlphaXC::readFloatRegDouble(int reg_idx)
-{
- DPRINTF(Fault, "Reading float register through the XC!\n");
- return cpu->readArchFloatRegDouble(reg_idx, thread->tid);
-}
-
-template <class Impl>
-uint64_t
-AlphaFullCPU<Impl>::AlphaXC::readFloatRegInt(int reg_idx)
-{
- DPRINTF(Fault, "Reading floatint register through the XC!\n");
- return cpu->readArchFloatRegInt(reg_idx, thread->tid);
-}
-
-template <class Impl>
-void
-AlphaFullCPU<Impl>::AlphaXC::setIntReg(int reg_idx, uint64_t val)
-{
- DPRINTF(Fault, "Setting int register through the XC!\n");
- cpu->setArchIntReg(reg_idx, val, thread->tid);
-
- if (!thread->trapPending && !thread->inSyscall) {
- cpu->squashFromXC(thread->tid);
- }
-}
-
-template <class Impl>
-void
-AlphaFullCPU<Impl>::AlphaXC::setFloatRegSingle(int reg_idx, float val)
-{
- DPRINTF(Fault, "Setting float register through the XC!\n");
- cpu->setArchFloatRegSingle(reg_idx, val, thread->tid);
-
- if (!thread->trapPending && !thread->inSyscall) {
- cpu->squashFromXC(thread->tid);
- }
-}
-
-template <class Impl>
-void
-AlphaFullCPU<Impl>::AlphaXC::setFloatRegDouble(int reg_idx, double val)
-{
- DPRINTF(Fault, "Setting float register through the XC!\n");
- cpu->setArchFloatRegDouble(reg_idx, val, thread->tid);
-
- if (!thread->trapPending && !thread->inSyscall) {
- cpu->squashFromXC(thread->tid);
- }
-}
-
-template <class Impl>
-void
-AlphaFullCPU<Impl>::AlphaXC::setFloatRegInt(int reg_idx, uint64_t val)
-{
- DPRINTF(Fault, "Setting floatint register through the XC!\n");
- cpu->setArchFloatRegInt(reg_idx, val, thread->tid);
-
- if (!thread->trapPending && !thread->inSyscall) {
- cpu->squashFromXC(thread->tid);
- }
-}
-
-template <class Impl>
-void
-AlphaFullCPU<Impl>::AlphaXC::setPC(uint64_t val)
-{
- cpu->setPC(val, thread->tid);
-
- if (!thread->trapPending && !thread->inSyscall) {
- cpu->squashFromXC(thread->tid);
- }
-}
-
-template <class Impl>
-void
-AlphaFullCPU<Impl>::AlphaXC::setNextPC(uint64_t val)
-{
- cpu->setNextPC(val, thread->tid);
-
- if (!thread->trapPending && !thread->inSyscall) {
- cpu->squashFromXC(thread->tid);
- }
-}
-
-template <class Impl>
-Fault
-AlphaFullCPU<Impl>::AlphaXC::setMiscReg(int misc_reg, const MiscReg &val)
-{
- DPRINTF(Fault, "Setting misc register through the XC!\n");
-
- Fault ret_fault = cpu->setMiscReg(misc_reg, val, thread->tid);
-
- if (!thread->trapPending && !thread->inSyscall) {
- cpu->squashFromXC(thread->tid);
- }
-
- return ret_fault;
-}
-
-template <class Impl>
-Fault
-AlphaFullCPU<Impl>::AlphaXC::setMiscRegWithEffect(int misc_reg, const MiscReg &val)
-{
- DPRINTF(Fault, "Setting misc register through the XC!\n");
-
- Fault ret_fault = cpu->setMiscRegWithEffect(misc_reg, val, thread->tid);
-
- if (!thread->trapPending && !thread->inSyscall) {
- cpu->squashFromXC(thread->tid);
- }
-
- return ret_fault;
-}
-
-#if !FULL_SYSTEM
-
-template <class Impl>
-TheISA::IntReg
-AlphaFullCPU<Impl>::AlphaXC::getSyscallArg(int i)
-{
- return cpu->getSyscallArg(i, thread->tid);
-}
-
-template <class Impl>
-void
-AlphaFullCPU<Impl>::AlphaXC::setSyscallArg(int i, IntReg val)
-{
- cpu->setSyscallArg(i, val, thread->tid);
-}
-
-template <class Impl>
-void
-AlphaFullCPU<Impl>::AlphaXC::setSyscallReturn(SyscallReturn return_value)
-{
- cpu->setSyscallReturn(return_value, thread->tid);
-}
-
-#endif // FULL_SYSTEM
-
-template <class Impl>
-MiscReg
-AlphaFullCPU<Impl>::readMiscReg(int misc_reg, unsigned tid)
-{
- return this->regFile.readMiscReg(misc_reg, tid);
-}
-
-template <class Impl>
-MiscReg
-AlphaFullCPU<Impl>::readMiscRegWithEffect(int misc_reg, Fault &fault,
- unsigned tid)
-{
- return this->regFile.readMiscRegWithEffect(misc_reg, fault, tid);
-}
-
-template <class Impl>
-Fault
-AlphaFullCPU<Impl>::setMiscReg(int misc_reg, const MiscReg &val, unsigned tid)
-{
- return this->regFile.setMiscReg(misc_reg, val, tid);
-}
-
-template <class Impl>
-Fault
-AlphaFullCPU<Impl>::setMiscRegWithEffect(int misc_reg, const MiscReg &val,
- unsigned tid)
-{
- return this->regFile.setMiscRegWithEffect(misc_reg, val, tid);
-}
-
-template <class Impl>
-void
-AlphaFullCPU<Impl>::squashFromXC(unsigned tid)
-{
- this->thread[tid]->inSyscall = true;
- this->commit.generateXCEvent(tid);
-}
-
-#if FULL_SYSTEM
-
-template <class Impl>
-void
-AlphaFullCPU<Impl>::post_interrupt(int int_num, int index)
-{
- BaseCPU::post_interrupt(int_num, index);
-
- if (this->thread[0]->status() == ExecContext::Suspended) {
- DPRINTF(IPI,"Suspended Processor awoke\n");
-// xcProxies[0]->activate();
- this->execContexts[0]->activate();
- }
-}
-
-template <class Impl>
-int
-AlphaFullCPU<Impl>::readIntrFlag()
-{
- return this->regFile.readIntrFlag();
-}
-
-template <class Impl>
-void
-AlphaFullCPU<Impl>::setIntrFlag(int val)
-{
- this->regFile.setIntrFlag(val);
-}
-
-template <class Impl>
-Fault
-AlphaFullCPU<Impl>::hwrei(unsigned tid)
-{
- // Need to clear the lock flag upon returning from an interrupt.
- this->lockFlag = false;
-
- this->thread[tid]->kernelStats->hwrei();
-
- this->checkInterrupts = true;
-
- // FIXME: XXX check for interrupts? XXX
- return NoFault;
-}
-
-template <class Impl>
-bool
-AlphaFullCPU<Impl>::simPalCheck(int palFunc, unsigned tid)
-{
- if (this->thread[tid]->kernelStats)
- this->thread[tid]->kernelStats->callpal(palFunc,
- this->execContexts[tid]);
-
- switch (palFunc) {
- case PAL::halt:
- halt();
- if (--System::numSystemsRunning == 0)
- new SimExitEvent("all cpus halted");
- break;
-
- case PAL::bpt:
- case PAL::bugchk:
- if (this->system->breakpoint())
- return false;
- break;
- }
-
- return true;
-}
-
-template <class Impl>
-void
-AlphaFullCPU<Impl>::trap(Fault fault, unsigned tid)
-{
- fault->invoke(this->execContexts[tid]);
-}
-
-template <class Impl>
-void
-AlphaFullCPU<Impl>::processInterrupts()
-{
- // Check for interrupts here. For now can copy the code that
- // exists within isa_fullsys_traits.hh. Also assume that thread 0
- // is the one that handles the interrupts.
- // @todo: Possibly consolidate the interrupt checking code.
- // @todo: Allow other threads to handle interrupts.
-
- // Check if there are any outstanding interrupts
- //Handle the interrupts
- int ipl = 0;
- int summary = 0;
-
- this->checkInterrupts = false;
-
- if (this->readMiscReg(IPR_ASTRR, 0))
- panic("asynchronous traps not implemented\n");
-
- if (this->readMiscReg(IPR_SIRR, 0)) {
- for (int i = INTLEVEL_SOFTWARE_MIN;
- i < INTLEVEL_SOFTWARE_MAX; i++) {
- if (this->readMiscReg(IPR_SIRR, 0) & (ULL(1) << i)) {
- // See table 4-19 of the 21164 hardware reference
- ipl = (i - INTLEVEL_SOFTWARE_MIN) + 1;
- summary |= (ULL(1) << i);
- }
- }
- }
-
- uint64_t interrupts = this->intr_status();
-
- if (interrupts) {
- for (int i = INTLEVEL_EXTERNAL_MIN;
- i < INTLEVEL_EXTERNAL_MAX; i++) {
- if (interrupts & (ULL(1) << i)) {
- // See table 4-19 of the 21164 hardware reference
- ipl = i;
- summary |= (ULL(1) << i);
- }
- }
- }
-
- if (ipl && ipl > this->readMiscReg(IPR_IPLR, 0)) {
- this->setMiscReg(IPR_ISR, summary, 0);
- this->setMiscReg(IPR_INTID, ipl, 0);
- if (this->checker) {
- this->checker->cpuXCBase()->setMiscReg(IPR_ISR, summary);
- this->checker->cpuXCBase()->setMiscReg(IPR_INTID, ipl);
- }
- this->trap(Fault(new InterruptFault), 0);
- DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n",
- this->readMiscReg(IPR_IPLR, 0), ipl, summary);
- }
-}
-
-#endif // FULL_SYSTEM
-
-#if !FULL_SYSTEM
-
-template <class Impl>
-void
-AlphaFullCPU<Impl>::syscall(int tid)
-{
- DPRINTF(FullCPU, "AlphaFullCPU: [tid:%i] Executing syscall().\n\n", tid);
-
- DPRINTF(Activity,"Activity: syscall() called.\n");
-
- // Temporarily increase this by one to account for the syscall
- // instruction.
- ++(this->thread[tid]->funcExeInst);
-
- // Execute the actual syscall.
- this->thread[tid]->syscall();
-
- // Decrease funcExeInst by one as the normal commit will handle
- // incrementing it.
- --(this->thread[tid]->funcExeInst);
-}
-
-template <class Impl>
-TheISA::IntReg
-AlphaFullCPU<Impl>::getSyscallArg(int i, int tid)
-{
- return this->readArchIntReg(AlphaISA::ArgumentReg0 + i, tid);
-}
-
-template <class Impl>
-void
-AlphaFullCPU<Impl>::setSyscallArg(int i, IntReg val, int tid)
-{
- this->setArchIntReg(AlphaISA::ArgumentReg0 + i, val, tid);
-}
-
-template <class Impl>
-void
-AlphaFullCPU<Impl>::setSyscallReturn(SyscallReturn return_value, int tid)
-{
- // check for error condition. Alpha syscall convention is to
- // indicate success/failure in reg a3 (r19) and put the
- // return value itself in the standard return value reg (v0).
- if (return_value.successful()) {
- // no error
- this->setArchIntReg(SyscallSuccessReg, 0, tid);
- this->setArchIntReg(ReturnValueReg, return_value.value(), tid);
- } else {
- // got an error, return details
- this->setArchIntReg(SyscallSuccessReg, (IntReg) -1, tid);
- this->setArchIntReg(ReturnValueReg, -return_value.value(), tid);
- }
-}
-#endif
diff --git a/cpu/o3/alpha_dyn_inst.hh b/cpu/o3/alpha_dyn_inst.hh
deleted file mode 100644
index 1c5b738aa..000000000
--- a/cpu/o3/alpha_dyn_inst.hh
+++ /dev/null
@@ -1,268 +0,0 @@
-/*
- * Copyright (c) 2004-2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __CPU_O3_ALPHA_DYN_INST_HH__
-#define __CPU_O3_ALPHA_DYN_INST_HH__
-
-#include "cpu/base_dyn_inst.hh"
-#include "cpu/inst_seq.hh"
-#include "cpu/o3/alpha_cpu.hh"
-#include "cpu/o3/alpha_impl.hh"
-
-/**
- * Mostly implementation & ISA specific AlphaDynInst. As with most
- * other classes in the new CPU model, it is templated on the Impl to
- * allow for passing in of all types, such as the CPU type and the ISA
- * type. The AlphaDynInst serves as the primary interface to the CPU
- * for instructions that are executing.
- */
-template <class Impl>
-class AlphaDynInst : public BaseDynInst<Impl>
-{
- public:
- /** Typedef for the CPU. */
- typedef typename Impl::FullCPU FullCPU;
-
- /** Binary machine instruction type. */
- typedef TheISA::MachInst MachInst;
- /** Extended machine instruction type. */
- typedef TheISA::ExtMachInst ExtMachInst;
- /** Logical register index type. */
- typedef TheISA::RegIndex RegIndex;
- /** Integer register index type. */
- typedef TheISA::IntReg IntReg;
- /** Misc register index type. */
- typedef TheISA::MiscReg MiscReg;
-
- enum {
- MaxInstSrcRegs = TheISA::MaxInstSrcRegs, //< Max source regs
- MaxInstDestRegs = TheISA::MaxInstDestRegs, //< Max dest regs
- };
-
- public:
- /** BaseDynInst constructor given a binary instruction. */
- AlphaDynInst(ExtMachInst inst, Addr PC, Addr Pred_PC, InstSeqNum seq_num,
- FullCPU *cpu);
-
- /** BaseDynInst constructor given a static inst pointer. */
- AlphaDynInst(StaticInstPtr &_staticInst);
-
- /** Executes the instruction.*/
- Fault execute();
-
- /** Initiates the access. Only valid for memory operations. */
- Fault initiateAcc();
-
- /** Completes the access. Only valid for memory operations. */
- Fault completeAcc();
-
- private:
- /** Initializes variables. */
- void initVars();
-
- public:
- MiscReg readMiscReg(int misc_reg)
- {
- return this->cpu->readMiscReg(misc_reg, this->threadNumber);
- }
-
- MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault)
- {
- return this->cpu->readMiscRegWithEffect(misc_reg, fault,
- this->threadNumber);
- }
-
- Fault setMiscReg(int misc_reg, const MiscReg &val)
- {
- this->instResult.integer = val;
- return this->cpu->setMiscReg(misc_reg, val, this->threadNumber);
- }
-
- Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val)
- {
- return this->cpu->setMiscRegWithEffect(misc_reg, val,
- this->threadNumber);
- }
-
-#if FULL_SYSTEM
- /** Calls hardware return from error interrupt. */
- Fault hwrei();
- /** Reads interrupt flag. */
- int readIntrFlag();
- /** Sets interrupt flag. */
- void setIntrFlag(int val);
- /** Checks if system is in PAL mode. */
- bool inPalMode();
- /** Traps to handle specified fault. */
- void trap(Fault fault);
- bool simPalCheck(int palFunc);
-#else
- /** Calls a syscall. */
- void syscall();
-#endif
-
- private:
- /** Physical register index of the destination registers of this
- * instruction.
- */
- PhysRegIndex _destRegIdx[MaxInstDestRegs];
-
- /** Physical register index of the source registers of this
- * instruction.
- */
- PhysRegIndex _srcRegIdx[MaxInstSrcRegs];
-
- /** Physical register index of the previous producers of the
- * architected destinations.
- */
- PhysRegIndex _prevDestRegIdx[MaxInstDestRegs];
-
- public:
-
- // The register accessor methods provide the index of the
- // instruction's operand (e.g., 0 or 1), not the architectural
- // register index, to simplify the implementation of register
- // renaming. We find the architectural register index by indexing
- // into the instruction's own operand index table. Note that a
- // raw pointer to the StaticInst is provided instead of a
- // ref-counted StaticInstPtr to redice overhead. This is fine as
- // long as these methods don't copy the pointer into any long-term
- // storage (which is pretty hard to imagine they would have reason
- // to do).
-
- uint64_t readIntReg(const StaticInst *si, int idx)
- {
- return this->cpu->readIntReg(_srcRegIdx[idx]);
- }
-
- float readFloatRegSingle(const StaticInst *si, int idx)
- {
- return this->cpu->readFloatRegSingle(_srcRegIdx[idx]);
- }
-
- double readFloatRegDouble(const StaticInst *si, int idx)
- {
- return this->cpu->readFloatRegDouble(_srcRegIdx[idx]);
- }
-
- uint64_t readFloatRegInt(const StaticInst *si, int idx)
- {
- return this->cpu->readFloatRegInt(_srcRegIdx[idx]);
- }
-
- /** @todo: Make results into arrays so they can handle multiple dest
- * registers.
- */
- void setIntReg(const StaticInst *si, int idx, uint64_t val)
- {
- this->cpu->setIntReg(_destRegIdx[idx], val);
- BaseDynInst<Impl>::setIntReg(si, idx, val);
- }
-
- void setFloatRegSingle(const StaticInst *si, int idx, float val)
- {
- this->cpu->setFloatRegSingle(_destRegIdx[idx], val);
- BaseDynInst<Impl>::setFloatRegSingle(si, idx, val);
- }
-
- void setFloatRegDouble(const StaticInst *si, int idx, double val)
- {
- this->cpu->setFloatRegDouble(_destRegIdx[idx], val);
- BaseDynInst<Impl>::setFloatRegDouble(si, idx, val);
- }
-
- void setFloatRegInt(const StaticInst *si, int idx, uint64_t val)
- {
- this->cpu->setFloatRegInt(_destRegIdx[idx], val);
- BaseDynInst<Impl>::setFloatRegInt(si, idx, val);
- }
-
- /** Returns the physical register index of the i'th destination
- * register.
- */
- PhysRegIndex renamedDestRegIdx(int idx) const
- {
- return _destRegIdx[idx];
- }
-
- /** Returns the physical register index of the i'th source register. */
- PhysRegIndex renamedSrcRegIdx(int idx) const
- {
- return _srcRegIdx[idx];
- }
-
- /** Returns the physical register index of the previous physical register
- * that remapped to the same logical register index.
- */
- PhysRegIndex prevDestRegIdx(int idx) const
- {
- return _prevDestRegIdx[idx];
- }
-
- /** Renames a destination register to a physical register. Also records
- * the previous physical register that the logical register mapped to.
- */
- void renameDestReg(int idx,
- PhysRegIndex renamed_dest,
- PhysRegIndex previous_rename)
- {
- _destRegIdx[idx] = renamed_dest;
- _prevDestRegIdx[idx] = previous_rename;
- }
-
- /** Renames a source logical register to the physical register which
- * has/will produce that logical register's result.
- * @todo: add in whether or not the source register is ready.
- */
- void renameSrcReg(int idx, PhysRegIndex renamed_src)
- {
- _srcRegIdx[idx] = renamed_src;
- }
-
- public:
- /** Calculates EA part of a memory instruction. Currently unused,
- * though it may be useful in the future if we want to split
- * memory operations into EA calculation and memory access parts.
- */
- Fault calcEA()
- {
- return this->staticInst->eaCompInst()->execute(this, this->traceData);
- }
-
- /** Does the memory access part of a memory instruction. Currently unused,
- * though it may be useful in the future if we want to split
- * memory operations into EA calculation and memory access parts.
- */
- Fault memAccess()
- {
- return this->staticInst->memAccInst()->execute(this, this->traceData);
- }
-};
-
-#endif // __CPU_O3_ALPHA_DYN_INST_HH__
-
diff --git a/cpu/o3/cpu.cc b/cpu/o3/cpu.cc
deleted file mode 100644
index 8d72bdc41..000000000
--- a/cpu/o3/cpu.cc
+++ /dev/null
@@ -1,1183 +0,0 @@
-/*
- * Copyright (c) 2004-2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config/full_system.hh"
-
-#if FULL_SYSTEM
-#include "sim/system.hh"
-#else
-#include "sim/process.hh"
-#endif
-
-#include "cpu/activity.hh"
-#include "cpu/checker/cpu.hh"
-#include "cpu/cpu_exec_context.hh"
-#include "cpu/exec_context.hh"
-#include "cpu/o3/alpha_dyn_inst.hh"
-#include "cpu/o3/alpha_impl.hh"
-#include "cpu/o3/cpu.hh"
-
-#include "sim/root.hh"
-#include "sim/stat_control.hh"
-
-using namespace std;
-
-BaseFullCPU::BaseFullCPU(Params *params)
- : BaseCPU(params), cpu_id(0)
-{
-}
-
-void
-BaseFullCPU::regStats()
-{
- BaseCPU::regStats();
-}
-
-template <class Impl>
-FullO3CPU<Impl>::TickEvent::TickEvent(FullO3CPU<Impl> *c)
- : Event(&mainEventQueue, CPU_Tick_Pri), cpu(c)
-{
-}
-
-template <class Impl>
-void
-FullO3CPU<Impl>::TickEvent::process()
-{
- cpu->tick();
-}
-
-template <class Impl>
-const char *
-FullO3CPU<Impl>::TickEvent::description()
-{
- return "FullO3CPU tick event";
-}
-
-template <class Impl>
-FullO3CPU<Impl>::FullO3CPU(Params *params)
- : BaseFullCPU(params),
- tickEvent(this),
- removeInstsThisCycle(false),
- fetch(params),
- decode(params),
- rename(params),
- iew(params),
- commit(params),
-
- regFile(params->numPhysIntRegs, params->numPhysFloatRegs),
-
- freeList(params->numberOfThreads,//number of activeThreads
- TheISA::NumIntRegs, params->numPhysIntRegs,
- TheISA::NumFloatRegs, params->numPhysFloatRegs),
-
- rob(params->numROBEntries, params->squashWidth,
- params->smtROBPolicy, params->smtROBThreshold,
- params->numberOfThreads),
-
- scoreboard(params->numberOfThreads,//number of activeThreads
- TheISA::NumIntRegs, params->numPhysIntRegs,
- TheISA::NumFloatRegs, params->numPhysFloatRegs,
- TheISA::NumMiscRegs * number_of_threads,
- TheISA::ZeroReg),
-
- // For now just have these time buffers be pretty big.
- // @todo: Make these time buffer sizes parameters or derived
- // from latencies
- timeBuffer(5, 5),
- fetchQueue(5, 5),
- decodeQueue(5, 5),
- renameQueue(5, 5),
- iewQueue(5, 5),
- activityRec(NumStages, 10, params->activity),
-
- globalSeqNum(1),
-
-#if FULL_SYSTEM
- system(params->system),
- memCtrl(system->memctrl),
- physmem(system->physmem),
- mem(params->mem),
-#else
-// pTable(params->pTable),
- mem(params->workload[0]->getMemory()),
-#endif // FULL_SYSTEM
- switchCount(0),
- icacheInterface(params->icacheInterface),
- dcacheInterface(params->dcacheInterface),
- deferRegistration(params->deferRegistration),
- numThreads(number_of_threads)
-{
- _status = Idle;
-
- if (params->checker) {
- BaseCPU *temp_checker = params->checker;
- checker = dynamic_cast<Checker<DynInstPtr> *>(temp_checker);
- checker->setMemory(mem);
-#if FULL_SYSTEM
- checker->setSystem(params->system);
-#endif
- } else {
- checker = NULL;
- }
-
-#if !FULL_SYSTEM
- thread.resize(number_of_threads);
- tids.resize(number_of_threads);
-#endif
-
- // The stages also need their CPU pointer setup. However this
- // must be done at the upper level CPU because they have pointers
- // to the upper level CPU, and not this FullO3CPU.
-
- // Set up Pointers to the activeThreads list for each stage
- fetch.setActiveThreads(&activeThreads);
- decode.setActiveThreads(&activeThreads);
- rename.setActiveThreads(&activeThreads);
- iew.setActiveThreads(&activeThreads);
- commit.setActiveThreads(&activeThreads);
-
- // Give each of the stages the time buffer they will use.
- fetch.setTimeBuffer(&timeBuffer);
- decode.setTimeBuffer(&timeBuffer);
- rename.setTimeBuffer(&timeBuffer);
- iew.setTimeBuffer(&timeBuffer);
- commit.setTimeBuffer(&timeBuffer);
-
- // Also setup each of the stages' queues.
- fetch.setFetchQueue(&fetchQueue);
- decode.setFetchQueue(&fetchQueue);
- commit.setFetchQueue(&fetchQueue);
- decode.setDecodeQueue(&decodeQueue);
- rename.setDecodeQueue(&decodeQueue);
- rename.setRenameQueue(&renameQueue);
- iew.setRenameQueue(&renameQueue);
- iew.setIEWQueue(&iewQueue);
- commit.setIEWQueue(&iewQueue);
- commit.setRenameQueue(&renameQueue);
-
- commit.setFetchStage(&fetch);
- commit.setIEWStage(&iew);
- rename.setIEWStage(&iew);
- rename.setCommitStage(&commit);
-
-#if !FULL_SYSTEM
- int active_threads = params->workload.size();
-#else
- int active_threads = 1;
-#endif
-
- //Make Sure That this a Valid Architeture
- assert(params->numPhysIntRegs >= numThreads * TheISA::NumIntRegs);
- assert(params->numPhysFloatRegs >= numThreads * TheISA::NumFloatRegs);
-
- rename.setScoreboard(&scoreboard);
- iew.setScoreboard(&scoreboard);
-
- // Setup the rename map for whichever stages need it.
- PhysRegIndex lreg_idx = 0;
- PhysRegIndex freg_idx = params->numPhysIntRegs; //Index to 1 after int regs
-
- for (int tid=0; tid < numThreads; tid++) {
- bool bindRegs = (tid <= active_threads - 1);
-
- commitRenameMap[tid].init(TheISA::NumIntRegs,
- params->numPhysIntRegs,
- lreg_idx, //Index for Logical. Regs
-
- TheISA::NumFloatRegs,
- params->numPhysFloatRegs,
- freg_idx, //Index for Float Regs
-
- TheISA::NumMiscRegs,
-
- TheISA::ZeroReg,
- TheISA::ZeroReg,
-
- tid,
- false);
-
- renameMap[tid].init(TheISA::NumIntRegs,
- params->numPhysIntRegs,
- lreg_idx, //Index for Logical. Regs
-
- TheISA::NumFloatRegs,
- params->numPhysFloatRegs,
- freg_idx, //Index for Float Regs
-
- TheISA::NumMiscRegs,
-
- TheISA::ZeroReg,
- TheISA::ZeroReg,
-
- tid,
- bindRegs);
- }
-
- rename.setRenameMap(renameMap);
- commit.setRenameMap(commitRenameMap);
-
- // Give renameMap & rename stage access to the freeList;
- for (int i=0; i < numThreads; i++) {
- renameMap[i].setFreeList(&freeList);
- }
- rename.setFreeList(&freeList);
-
- // Setup the page table for whichever stages need it.
-#if !FULL_SYSTEM
-// fetch.setPageTable(pTable);
-// iew.setPageTable(pTable);
-#endif
-
- // Setup the ROB for whichever stages need it.
- commit.setROB(&rob);
-
- lastRunningCycle = curTick;
-
- contextSwitch = false;
-}
-
-template <class Impl>
-FullO3CPU<Impl>::~FullO3CPU()
-{
-}
-
-template <class Impl>
-void
-FullO3CPU<Impl>::fullCPURegStats()
-{
- BaseFullCPU::regStats();
-
- // Register any of the FullCPU's stats here.
- timesIdled
- .name(name() + ".timesIdled")
- .desc("Number of times that the entire CPU went into an idle state and"
- " unscheduled itself")
- .prereq(timesIdled);
-
- idleCycles
- .name(name() + ".idleCycles")
- .desc("Total number of cycles that the CPU has spent unscheduled due "
- "to idling")
- .prereq(idleCycles);
-
- // Number of Instructions simulated
- // --------------------------------
- // Should probably be in Base CPU but need templated
- // MaxThreads so put in here instead
- committedInsts
- .init(numThreads)
- .name(name() + ".committedInsts")
- .desc("Number of Instructions Simulated");
-
- totalCommittedInsts
- .name(name() + ".committedInsts_total")
- .desc("Number of Instructions Simulated");
-
- cpi
- .name(name() + ".cpi")
- .desc("CPI: Cycles Per Instruction")
- .precision(6);
- cpi = simTicks / committedInsts;
-
- totalCpi
- .name(name() + ".cpi_total")
- .desc("CPI: Total CPI of All Threads")
- .precision(6);
- totalCpi = simTicks / totalCommittedInsts;
-
- ipc
- .name(name() + ".ipc")
- .desc("IPC: Instructions Per Cycle")
- .precision(6);
- ipc = committedInsts / simTicks;
-
- totalIpc
- .name(name() + ".ipc_total")
- .desc("IPC: Total IPC of All Threads")
- .precision(6);
- totalIpc = totalCommittedInsts / simTicks;
-
-}
-
-template <class Impl>
-void
-FullO3CPU<Impl>::tick()
-{
- DPRINTF(FullCPU, "\n\nFullCPU: Ticking main, FullO3CPU.\n");
-
- ++numCycles;
-
-// activity = false;
-
- //Tick each of the stages
- fetch.tick();
-
- decode.tick();
-
- rename.tick();
-
- iew.tick();
-
- commit.tick();
-
-#if !FULL_SYSTEM
- doContextSwitch();
-#endif
-
- // Now advance the time buffers
- timeBuffer.advance();
-
- fetchQueue.advance();
- decodeQueue.advance();
- renameQueue.advance();
- iewQueue.advance();
-
- activityRec.advance();
-
- if (removeInstsThisCycle) {
- cleanUpRemovedInsts();
- }
-
- if (!tickEvent.scheduled()) {
- if (_status == SwitchedOut) {
- // increment stat
- lastRunningCycle = curTick;
- } else if (!activityRec.active()) {
- lastRunningCycle = curTick;
- timesIdled++;
- } else {
- tickEvent.schedule(curTick + cycles(1));
- }
- }
-
-#if !FULL_SYSTEM
- updateThreadPriority();
-#endif
-
-}
-
-template <class Impl>
-void
-FullO3CPU<Impl>::init()
-{
- if (!deferRegistration) {
- registerExecContexts();
- }
-
- // Set inSyscall so that the CPU doesn't squash when initially
- // setting up registers.
- for (int i = 0; i < number_of_threads; ++i)
- thread[i]->inSyscall = true;
-
- for (int tid=0; tid < number_of_threads; tid++) {
-#if FULL_SYSTEM
- ExecContext *src_xc = execContexts[tid];
-#else
- ExecContext *src_xc = thread[tid]->getXCProxy();
-#endif
- // Threads start in the Suspended State
- if (src_xc->status() != ExecContext::Suspended) {
- continue;
- }
-
-#if FULL_SYSTEM
- TheISA::initCPU(src_xc, src_xc->readCpuId());
-#endif
- }
-
- // Clear inSyscall.
- for (int i = 0; i < number_of_threads; ++i)
- thread[i]->inSyscall = false;
-
- // Initialize stages.
- fetch.initStage();
- iew.initStage();
- rename.initStage();
- commit.initStage();
-
- commit.setThreads(thread);
-}
-
-template <class Impl>
-void
-FullO3CPU<Impl>::insertThread(unsigned tid)
-{
- DPRINTF(FullCPU,"[tid:%i] Initializing thread data");
- // Will change now that the PC and thread state is internal to the CPU
- // and not in the CPUExecContext.
-#if 0
-#if FULL_SYSTEM
- ExecContext *src_xc = system->execContexts[tid];
-#else
- CPUExecContext *src_xc = thread[tid];
-#endif
-
- //Bind Int Regs to Rename Map
- for (int ireg = 0; ireg < TheISA::NumIntRegs; ireg++) {
- PhysRegIndex phys_reg = freeList.getIntReg();
-
- renameMap[tid].setEntry(ireg,phys_reg);
- scoreboard.setReg(phys_reg);
- }
-
- //Bind Float Regs to Rename Map
- for (int freg = 0; freg < TheISA::NumFloatRegs; freg++) {
- PhysRegIndex phys_reg = freeList.getFloatReg();
-
- renameMap[tid].setEntry(freg,phys_reg);
- scoreboard.setReg(phys_reg);
- }
-
- //Copy Thread Data Into RegFile
- this->copyFromXC(tid);
-
- //Set PC/NPC
- regFile.pc[tid] = src_xc->readPC();
- regFile.npc[tid] = src_xc->readNextPC();
-
- src_xc->setStatus(ExecContext::Active);
-
- activateContext(tid,1);
-
- //Reset ROB/IQ/LSQ Entries
- commit.rob->resetEntries();
- iew.resetEntries();
-#endif
-}
-
-template <class Impl>
-void
-FullO3CPU<Impl>::removeThread(unsigned tid)
-{
- DPRINTF(FullCPU,"[tid:%i] Removing thread data");
-#if 0
- //Unbind Int Regs from Rename Map
- for (int ireg = 0; ireg < TheISA::NumIntRegs; ireg++) {
- PhysRegIndex phys_reg = renameMap[tid].lookup(ireg);
-
- scoreboard.unsetReg(phys_reg);
- freeList.addReg(phys_reg);
- }
-
- //Unbind Float Regs from Rename Map
- for (int freg = 0; freg < TheISA::NumFloatRegs; freg++) {
- PhysRegIndex phys_reg = renameMap[tid].lookup(freg);
-
- scoreboard.unsetReg(phys_reg);
- freeList.addReg(phys_reg);
- }
-
- //Copy Thread Data From RegFile
- /* Fix Me:
- * Do we really need to do this if we are removing a thread
- * in the sense that it's finished (exiting)? If the thread is just
- * being suspended we might...
- */
-// this->copyToXC(tid);
-
- //Squash Throughout Pipeline
- fetch.squash(0,tid);
- decode.squash(tid);
- rename.squash(tid);
-
- assert(iew.ldstQueue.getCount(tid) == 0);
-
- //Reset ROB/IQ/LSQ Entries
- if (activeThreads.size() >= 1) {
- commit.rob->resetEntries();
- iew.resetEntries();
- }
-#endif
-}
-
-
-template <class Impl>
-void
-FullO3CPU<Impl>::activateWhenReady(int tid)
-{
- DPRINTF(FullCPU,"[tid:%i]: Checking if resources are available for incoming"
- "(e.g. PhysRegs/ROB/IQ/LSQ) \n",
- tid);
-
- bool ready = true;
-
- if (freeList.numFreeIntRegs() >= TheISA::NumIntRegs) {
- DPRINTF(FullCPU,"[tid:%i] Suspending thread due to not enough "
- "Phys. Int. Regs.\n",
- tid);
- ready = false;
- } else if (freeList.numFreeFloatRegs() >= TheISA::NumFloatRegs) {
- DPRINTF(FullCPU,"[tid:%i] Suspending thread due to not enough "
- "Phys. Float. Regs.\n",
- tid);
- ready = false;
- } else if (commit.rob->numFreeEntries() >=
- commit.rob->entryAmount(activeThreads.size() + 1)) {
- DPRINTF(FullCPU,"[tid:%i] Suspending thread due to not enough "
- "ROB entries.\n",
- tid);
- ready = false;
- } else if (iew.instQueue.numFreeEntries() >=
- iew.instQueue.entryAmount(activeThreads.size() + 1)) {
- DPRINTF(FullCPU,"[tid:%i] Suspending thread due to not enough "
- "IQ entries.\n",
- tid);
- ready = false;
- } else if (iew.ldstQueue.numFreeEntries() >=
- iew.ldstQueue.entryAmount(activeThreads.size() + 1)) {
- DPRINTF(FullCPU,"[tid:%i] Suspending thread due to not enough "
- "LSQ entries.\n",
- tid);
- ready = false;
- }
-
- if (ready) {
- insertThread(tid);
-
- contextSwitch = false;
-
- cpuWaitList.remove(tid);
- } else {
- suspendContext(tid);
-
- //blocks fetch
- contextSwitch = true;
-
- //do waitlist
- cpuWaitList.push_back(tid);
- }
-}
-
-template <class Impl>
-void
-FullO3CPU<Impl>::activateContext(int tid, int delay)
-{
- // Needs to set each stage to running as well.
- list<unsigned>::iterator isActive = find(
- activeThreads.begin(), activeThreads.end(), tid);
-
- if (isActive == activeThreads.end()) {
- //May Need to Re-code this if the delay variable is the
- //delay needed for thread to activate
- DPRINTF(FullCPU, "Adding Thread %i to active threads list\n",
- tid);
-
- activeThreads.push_back(tid);
- }
-
- assert(_status == Idle || _status == SwitchedOut);
-
- scheduleTickEvent(delay);
-
- // Be sure to signal that there's some activity so the CPU doesn't
- // deschedule itself.
- activityRec.activity();
- fetch.wakeFromQuiesce();
-
- _status = Running;
-}
-
-template <class Impl>
-void
-FullO3CPU<Impl>::suspendContext(int tid)
-{
- DPRINTF(FullCPU,"[tid: %i]: Suspended ...\n", tid);
- unscheduleTickEvent();
- _status = Idle;
-/*
- //Remove From Active List, if Active
- list<unsigned>::iterator isActive = find(
- activeThreads.begin(), activeThreads.end(), tid);
-
- if (isActive != activeThreads.end()) {
- DPRINTF(FullCPU,"[tid:%i]: Removing from active threads list\n",
- tid);
- activeThreads.erase(isActive);
- }
-*/
-}
-
-template <class Impl>
-void
-FullO3CPU<Impl>::deallocateContext(int tid)
-{
- DPRINTF(FullCPU,"[tid:%i]: Deallocating ...", tid);
-/*
- //Remove From Active List, if Active
- list<unsigned>::iterator isActive = find(
- activeThreads.begin(), activeThreads.end(), tid);
-
- if (isActive != activeThreads.end()) {
- DPRINTF(FullCPU,"[tid:%i]: Removing from active threads list\n",
- tid);
- activeThreads.erase(isActive);
-
- removeThread(tid);
- }
-*/
-}
-
-template <class Impl>
-void
-FullO3CPU<Impl>::haltContext(int tid)
-{
- DPRINTF(FullCPU,"[tid:%i]: Halted ...", tid);
-/*
- //Remove From Active List, if Active
- list<unsigned>::iterator isActive = find(
- activeThreads.begin(), activeThreads.end(), tid);
-
- if (isActive != activeThreads.end()) {
- DPRINTF(FullCPU,"[tid:%i]: Removing from active threads list\n",
- tid);
- activeThreads.erase(isActive);
-
- removeThread(tid);
- }
-*/
-}
-
-template <class Impl>
-void
-FullO3CPU<Impl>::switchOut(Sampler *_sampler)
-{
- sampler = _sampler;
- switchCount = 0;
- fetch.switchOut();
- decode.switchOut();
- rename.switchOut();
- iew.switchOut();
- commit.switchOut();
-
- // Wake the CPU and record activity so everything can drain out if
- // the CPU is currently idle.
- wakeCPU();
- activityRec.activity();
-}
-
-template <class Impl>
-void
-FullO3CPU<Impl>::signalSwitched()
-{
- if (++switchCount == NumStages) {
- fetch.doSwitchOut();
- rename.doSwitchOut();
- commit.doSwitchOut();
- instList.clear();
- while (!removeList.empty()) {
- removeList.pop();
- }
-
- if (checker)
- checker->switchOut(sampler);
-
- if (tickEvent.scheduled())
- tickEvent.squash();
- sampler->signalSwitched();
- _status = SwitchedOut;
- }
- assert(switchCount <= 5);
-}
-
-template <class Impl>
-void
-FullO3CPU<Impl>::takeOverFrom(BaseCPU *oldCPU)
-{
- // Flush out any old data from the time buffers.
- for (int i = 0; i < 10; ++i) {
- timeBuffer.advance();
- fetchQueue.advance();
- decodeQueue.advance();
- renameQueue.advance();
- iewQueue.advance();
- }
-
- activityRec.reset();
-
- BaseCPU::takeOverFrom(oldCPU);
-
- fetch.takeOverFrom();
- decode.takeOverFrom();
- rename.takeOverFrom();
- iew.takeOverFrom();
- commit.takeOverFrom();
-
- assert(!tickEvent.scheduled());
-
- // @todo: Figure out how to properly select the tid to put onto
- // the active threads list.
- int tid = 0;
-
- list<unsigned>::iterator isActive = find(
- activeThreads.begin(), activeThreads.end(), tid);
-
- if (isActive == activeThreads.end()) {
- //May Need to Re-code this if the delay variable is the delay
- //needed for thread to activate
- DPRINTF(FullCPU, "Adding Thread %i to active threads list\n",
- tid);
-
- activeThreads.push_back(tid);
- }
-
- // Set all statuses to active, schedule the CPU's tick event.
- // @todo: Fix up statuses so this is handled properly
- for (int i = 0; i < execContexts.size(); ++i) {
- ExecContext *xc = execContexts[i];
- if (xc->status() == ExecContext::Active && _status != Running) {
- _status = Running;
- tickEvent.schedule(curTick);
- }
- }
- if (!tickEvent.scheduled())
- tickEvent.schedule(curTick);
-}
-
-template <class Impl>
-uint64_t
-FullO3CPU<Impl>::readIntReg(int reg_idx)
-{
- return regFile.readIntReg(reg_idx);
-}
-
-template <class Impl>
-float
-FullO3CPU<Impl>::readFloatRegSingle(int reg_idx)
-{
- return regFile.readFloatRegSingle(reg_idx);
-}
-
-template <class Impl>
-double
-FullO3CPU<Impl>::readFloatRegDouble(int reg_idx)
-{
- return regFile.readFloatRegDouble(reg_idx);
-}
-
-template <class Impl>
-uint64_t
-FullO3CPU<Impl>::readFloatRegInt(int reg_idx)
-{
- return regFile.readFloatRegInt(reg_idx);
-}
-
-template <class Impl>
-void
-FullO3CPU<Impl>::setIntReg(int reg_idx, uint64_t val)
-{
- regFile.setIntReg(reg_idx, val);
-}
-
-template <class Impl>
-void
-FullO3CPU<Impl>::setFloatRegSingle(int reg_idx, float val)
-{
- regFile.setFloatRegSingle(reg_idx, val);
-}
-
-template <class Impl>
-void
-FullO3CPU<Impl>::setFloatRegDouble(int reg_idx, double val)
-{
- regFile.setFloatRegDouble(reg_idx, val);
-}
-
-template <class Impl>
-void
-FullO3CPU<Impl>::setFloatRegInt(int reg_idx, uint64_t val)
-{
- regFile.setFloatRegInt(reg_idx, val);
-}
-
-template <class Impl>
-uint64_t
-FullO3CPU<Impl>::readArchIntReg(int reg_idx, unsigned tid)
-{
- PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx);
-
- return regFile.readIntReg(phys_reg);
-}
-
-template <class Impl>
-float
-FullO3CPU<Impl>::readArchFloatRegSingle(int reg_idx, unsigned tid)
-{
- int idx = reg_idx + TheISA::FP_Base_DepTag;
- PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx);
-
- return regFile.readFloatRegSingle(phys_reg);
-}
-
-template <class Impl>
-double
-FullO3CPU<Impl>::readArchFloatRegDouble(int reg_idx, unsigned tid)
-{
- int idx = reg_idx + TheISA::FP_Base_DepTag;
- PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx);
-
- return regFile.readFloatRegDouble(phys_reg);
-}
-
-template <class Impl>
-uint64_t
-FullO3CPU<Impl>::readArchFloatRegInt(int reg_idx, unsigned tid)
-{
- int idx = reg_idx + TheISA::FP_Base_DepTag;
- PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx);
-
- return regFile.readFloatRegInt(phys_reg);
-}
-
-template <class Impl>
-void
-FullO3CPU<Impl>::setArchIntReg(int reg_idx, uint64_t val, unsigned tid)
-{
- PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx);
-
- regFile.setIntReg(phys_reg, val);
-}
-
-template <class Impl>
-void
-FullO3CPU<Impl>::setArchFloatRegSingle(int reg_idx, float val, unsigned tid)
-{
- PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx);
-
- regFile.setFloatRegSingle(phys_reg, val);
-}
-
-template <class Impl>
-void
-FullO3CPU<Impl>::setArchFloatRegDouble(int reg_idx, double val, unsigned tid)
-{
- PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx);
-
- regFile.setFloatRegDouble(phys_reg, val);
-}
-
-template <class Impl>
-void
-FullO3CPU<Impl>::setArchFloatRegInt(int reg_idx, uint64_t val, unsigned tid)
-{
- PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx);
-
- regFile.setFloatRegInt(phys_reg, val);
-}
-
-template <class Impl>
-uint64_t
-FullO3CPU<Impl>::readPC(unsigned tid)
-{
- return commit.readPC(tid);
-}
-
-template <class Impl>
-void
-FullO3CPU<Impl>::setPC(Addr new_PC,unsigned tid)
-{
- commit.setPC(new_PC, tid);
-}
-
-template <class Impl>
-uint64_t
-FullO3CPU<Impl>::readNextPC(unsigned tid)
-{
- return commit.readNextPC(tid);
-}
-
-template <class Impl>
-void
-FullO3CPU<Impl>::setNextPC(uint64_t val,unsigned tid)
-{
- commit.setNextPC(val, tid);
-}
-
-template <class Impl>
-typename FullO3CPU<Impl>::ListIt
-FullO3CPU<Impl>::addInst(DynInstPtr &inst)
-{
- instList.push_back(inst);
-
- return --(instList.end());
-}
-
-template <class Impl>
-void
-FullO3CPU<Impl>::instDone(unsigned tid)
-{
- // Keep an instruction count.
- thread[tid]->numInst++;
- thread[tid]->numInsts++;
- committedInsts[tid]++;
- totalCommittedInsts++;
-
- // Check for instruction-count-based events.
- comInstEventQueue[tid]->serviceEvents(thread[tid]->numInst);
-}
-
-template <class Impl>
-void
-FullO3CPU<Impl>::addToRemoveList(DynInstPtr &inst)
-{
- removeInstsThisCycle = true;
-
- removeList.push(inst->getInstListIt());
-}
-
-template <class Impl>
-void
-FullO3CPU<Impl>::removeFrontInst(DynInstPtr &inst)
-{
- DPRINTF(FullCPU, "FullCPU: Removing committed instruction [tid:%i] PC %#x "
- "[sn:%lli]\n",
- inst->threadNumber, inst->readPC(), inst->seqNum);
-
- removeInstsThisCycle = true;
-
- // Remove the front instruction.
- removeList.push(inst->getInstListIt());
-}
-
-template <class Impl>
-void
-FullO3CPU<Impl>::removeInstsNotInROB(unsigned tid)
-{
- DPRINTF(FullCPU, "FullCPU: Thread %i: Deleting instructions from instruction"
- " list.\n", tid);
-
- ListIt end_it;
-
- bool rob_empty = false;
-
- if (instList.empty()) {
- return;
- } else if (rob.isEmpty(/*tid*/)) {
- DPRINTF(FullCPU, "FullCPU: ROB is empty, squashing all insts.\n");
- end_it = instList.begin();
- rob_empty = true;
- } else {
- end_it = (rob.readTailInst(tid))->getInstListIt();
- DPRINTF(FullCPU, "FullCPU: ROB is not empty, squashing insts not in ROB.\n");
- }
-
- removeInstsThisCycle = true;
-
- ListIt inst_it = instList.end();
-
- inst_it--;
-
- // Walk through the instruction list, removing any instructions
- // that were inserted after the given instruction iterator, end_it.
- while (inst_it != end_it) {
- assert(!instList.empty());
-
- squashInstIt(inst_it, tid);
-
- inst_it--;
- }
-
- // If the ROB was empty, then we actually need to remove the first
- // instruction as well.
- if (rob_empty) {
- squashInstIt(inst_it, tid);
- }
-}
-
-template <class Impl>
-void
-FullO3CPU<Impl>::removeInstsUntil(const InstSeqNum &seq_num,
- unsigned tid)
-{
- assert(!instList.empty());
-
- removeInstsThisCycle = true;
-
- ListIt inst_iter = instList.end();
-
- inst_iter--;
-
- DPRINTF(FullCPU, "FullCPU: Deleting instructions from instruction "
- "list that are from [tid:%i] and above [sn:%lli] (end=%lli).\n",
- tid, seq_num, (*inst_iter)->seqNum);
-
- while ((*inst_iter)->seqNum > seq_num) {
-
- bool break_loop = (inst_iter == instList.begin());
-
- squashInstIt(inst_iter, tid);
-
- inst_iter--;
-
- if (break_loop)
- break;
- }
-}
-
-template <class Impl>
-inline void
-FullO3CPU<Impl>::squashInstIt(const ListIt &instIt, const unsigned &tid)
-{
- if ((*instIt)->threadNumber == tid) {
- DPRINTF(FullCPU, "FullCPU: Squashing instruction, "
- "[tid:%i] [sn:%lli] PC %#x\n",
- (*instIt)->threadNumber,
- (*instIt)->seqNum,
- (*instIt)->readPC());
-
- // Mark it as squashed.
- (*instIt)->setSquashed();
-
- // @todo: Formulate a consistent method for deleting
- // instructions from the instruction list
- // Remove the instruction from the list.
- removeList.push(instIt);
- }
-}
-
-template <class Impl>
-void
-FullO3CPU<Impl>::cleanUpRemovedInsts()
-{
- while (!removeList.empty()) {
- DPRINTF(FullCPU, "FullCPU: Removing instruction, "
- "[tid:%i] [sn:%lli] PC %#x\n",
- (*removeList.front())->threadNumber,
- (*removeList.front())->seqNum,
- (*removeList.front())->readPC());
-
- instList.erase(removeList.front());
-
- removeList.pop();
- }
-
- removeInstsThisCycle = false;
-}
-/*
-template <class Impl>
-void
-FullO3CPU<Impl>::removeAllInsts()
-{
- instList.clear();
-}
-*/
-template <class Impl>
-void
-FullO3CPU<Impl>::dumpInsts()
-{
- int num = 0;
-
- ListIt inst_list_it = instList.begin();
-
- cprintf("Dumping Instruction List\n");
-
- while (inst_list_it != instList.end()) {
- cprintf("Instruction:%i\nPC:%#x\n[tid:%i]\n[sn:%lli]\nIssued:%i\n"
- "Squashed:%i\n\n",
- num, (*inst_list_it)->readPC(), (*inst_list_it)->threadNumber,
- (*inst_list_it)->seqNum, (*inst_list_it)->isIssued(),
- (*inst_list_it)->isSquashed());
- inst_list_it++;
- ++num;
- }
-}
-/*
-template <class Impl>
-void
-FullO3CPU<Impl>::wakeDependents(DynInstPtr &inst)
-{
- iew.wakeDependents(inst);
-}
-*/
-template <class Impl>
-void
-FullO3CPU<Impl>::wakeCPU()
-{
- if (activityRec.active() || tickEvent.scheduled()) {
- DPRINTF(Activity, "CPU already running.\n");
- return;
- }
-
- DPRINTF(Activity, "Waking up CPU\n");
-
- idleCycles += (curTick - 1) - lastRunningCycle;
-
- tickEvent.schedule(curTick);
-}
-
-template <class Impl>
-int
-FullO3CPU<Impl>::getFreeTid()
-{
- for (int i=0; i < numThreads; i++) {
- if (!tids[i]) {
- tids[i] = true;
- return i;
- }
- }
-
- return -1;
-}
-
-template <class Impl>
-void
-FullO3CPU<Impl>::doContextSwitch()
-{
- if (contextSwitch) {
-
- //ADD CODE TO DEACTIVE THREAD HERE (???)
-
- for (int tid=0; tid < cpuWaitList.size(); tid++) {
- activateWhenReady(tid);
- }
-
- if (cpuWaitList.size() == 0)
- contextSwitch = true;
- }
-}
-
-template <class Impl>
-void
-FullO3CPU<Impl>::updateThreadPriority()
-{
- if (activeThreads.size() > 1)
- {
- //DEFAULT TO ROUND ROBIN SCHEME
- //e.g. Move highest priority to end of thread list
- list<unsigned>::iterator list_begin = activeThreads.begin();
- list<unsigned>::iterator list_end = activeThreads.end();
-
- unsigned high_thread = *list_begin;
-
- activeThreads.erase(list_begin);
-
- activeThreads.push_back(high_thread);
- }
-}
-
-// Forward declaration of FullO3CPU.
-template class FullO3CPU<AlphaSimpleImpl>;
diff --git a/cpu/o3/cpu.hh b/cpu/o3/cpu.hh
deleted file mode 100644
index 8db65d501..000000000
--- a/cpu/o3/cpu.hh
+++ /dev/null
@@ -1,521 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __CPU_O3_CPU_HH__
-#define __CPU_O3_CPU_HH__
-
-#include <iostream>
-#include <list>
-#include <queue>
-#include <set>
-#include <vector>
-
-#include "base/statistics.hh"
-#include "base/timebuf.hh"
-#include "config/full_system.hh"
-#include "cpu/activity.hh"
-#include "cpu/base.hh"
-#include "cpu/cpu_exec_context.hh"
-#include "cpu/o3/comm.hh"
-#include "cpu/o3/cpu_policy.hh"
-#include "cpu/o3/scoreboard.hh"
-#include "cpu/o3/thread_state.hh"
-#include "sim/process.hh"
-
-template <class>
-class Checker;
-class ExecContext;
-class MemInterface;
-class Process;
-
-class BaseFullCPU : public BaseCPU
-{
- //Stuff that's pretty ISA independent will go here.
- public:
- typedef BaseCPU::Params Params;
-
- BaseFullCPU(Params *params);
-
- void regStats();
-
- protected:
- int cpu_id;
-};
-
-template <class Impl>
-class FullO3CPU : public BaseFullCPU
-{
- public:
- // Typedefs from the Impl here.
- typedef typename Impl::CPUPol CPUPolicy;
- typedef typename Impl::Params Params;
- typedef typename Impl::DynInstPtr DynInstPtr;
-
- typedef O3ThreadState<Impl> Thread;
-
- typedef typename std::list<DynInstPtr>::iterator ListIt;
-
- public:
- enum Status {
- Running,
- Idle,
- Halted,
- Blocked,
- SwitchedOut
- };
-
- /** Overall CPU status. */
- Status _status;
-
- private:
- class TickEvent : public Event
- {
- private:
- /** Pointer to the CPU. */
- FullO3CPU<Impl> *cpu;
-
- public:
- /** Constructs a tick event. */
- TickEvent(FullO3CPU<Impl> *c);
-
- /** Processes a tick event, calling tick() on the CPU. */
- void process();
- /** Returns the description of the tick event. */
- const char *description();
- };
-
- /** The tick event used for scheduling CPU ticks. */
- TickEvent tickEvent;
-
- /** Schedule tick event, regardless of its current state. */
- void scheduleTickEvent(int delay)
- {
- if (tickEvent.squashed())
- tickEvent.reschedule(curTick + cycles(delay));
- else if (!tickEvent.scheduled())
- tickEvent.schedule(curTick + cycles(delay));
- }
-
- /** Unschedule tick event, regardless of its current state. */
- void unscheduleTickEvent()
- {
- if (tickEvent.scheduled())
- tickEvent.squash();
- }
-
- public:
- /** Constructs a CPU with the given parameters. */
- FullO3CPU(Params *params);
- /** Destructor. */
- ~FullO3CPU();
-
- /** Registers statistics. */
- void fullCPURegStats();
-
- /** Ticks CPU, calling tick() on each stage, and checking the overall
- * activity to see if the CPU should deschedule itself.
- */
- void tick();
-
- /** Initialize the CPU */
- void init();
-
- /** Setup CPU to insert a thread's context */
- void insertThread(unsigned tid);
-
- /** Remove all of a thread's context from CPU */
- void removeThread(unsigned tid);
-
- /** Count the Total Instructions Committed in the CPU. */
- virtual Counter totalInstructions() const
- {
- Counter total(0);
-
- for (int i=0; i < thread.size(); i++)
- total += thread[i]->numInst;
-
- return total;
- }
-
- /** Add Thread to Active Threads List. */
- void activateContext(int tid, int delay);
-
- /** Remove Thread from Active Threads List */
- void suspendContext(int tid);
-
- /** Remove Thread from Active Threads List &&
- * Remove Thread Context from CPU.
- */
- void deallocateContext(int tid);
-
- /** Remove Thread from Active Threads List &&
- * Remove Thread Context from CPU.
- */
- void haltContext(int tid);
-
- /** Activate a Thread When CPU Resources are Available. */
- void activateWhenReady(int tid);
-
- /** Add or Remove a Thread Context in the CPU. */
- void doContextSwitch();
-
- /** Update The Order In Which We Process Threads. */
- void updateThreadPriority();
-
- /** Executes a syscall on this cycle.
- * ---------------------------------------
- * Note: this is a virtual function. CPU-Specific
- * functionality defined in derived classes
- */
- virtual void syscall(int tid) { panic("Unimplemented!"); }
-
- /** Check if there are any system calls pending. */
- void checkSyscalls();
-
- /** Switches out this CPU.
- */
- void switchOut(Sampler *sampler);
-
- void signalSwitched();
-
- /** Takes over from another CPU.
- */
- void takeOverFrom(BaseCPU *oldCPU);
-
- /** Get the current instruction sequence number, and increment it. */
- InstSeqNum getAndIncrementInstSeq()
- { return globalSeqNum++; }
-
-#if FULL_SYSTEM
- /** Check if this address is a valid instruction address. */
- bool validInstAddr(Addr addr) { return true; }
-
- /** Check if this address is a valid data address. */
- bool validDataAddr(Addr addr) { return true; }
-
- /** Get instruction asid. */
- int getInstAsid(unsigned tid)
- { return regFile.miscRegs[tid].getInstAsid(); }
-
- /** Get data asid. */
- int getDataAsid(unsigned tid)
- { return regFile.miscRegs[tid].getDataAsid(); }
-#else
- /** Check if this address is a valid instruction address. */
- bool validInstAddr(Addr addr,unsigned tid)
- { return thread[tid]->validInstAddr(addr); }
-
- /** Check if this address is a valid data address. */
- bool validDataAddr(Addr addr,unsigned tid)
- { return thread[tid]->validDataAddr(addr); }
-
- /** Get instruction asid. */
- int getInstAsid(unsigned tid)
- { return thread[tid]->asid; }
-
- /** Get data asid. */
- int getDataAsid(unsigned tid)
- { return thread[tid]->asid; }
-
-#endif
-
- //
- // New accessors for new decoder.
- //
- uint64_t readIntReg(int reg_idx);
-
- float readFloatRegSingle(int reg_idx);
-
- double readFloatRegDouble(int reg_idx);
-
- uint64_t readFloatRegInt(int reg_idx);
-
- void setIntReg(int reg_idx, uint64_t val);
-
- void setFloatRegSingle(int reg_idx, float val);
-
- void setFloatRegDouble(int reg_idx, double val);
-
- void setFloatRegInt(int reg_idx, uint64_t val);
-
- uint64_t readArchIntReg(int reg_idx, unsigned tid);
-
- float readArchFloatRegSingle(int reg_idx, unsigned tid);
-
- double readArchFloatRegDouble(int reg_idx, unsigned tid);
-
- uint64_t readArchFloatRegInt(int reg_idx, unsigned tid);
-
- void setArchIntReg(int reg_idx, uint64_t val, unsigned tid);
-
- void setArchFloatRegSingle(int reg_idx, float val, unsigned tid);
-
- void setArchFloatRegDouble(int reg_idx, double val, unsigned tid);
-
- void setArchFloatRegInt(int reg_idx, uint64_t val, unsigned tid);
-
- uint64_t readPC(unsigned tid);
-
- void setPC(Addr new_PC,unsigned tid);
-
- uint64_t readNextPC(unsigned tid);
-
- void setNextPC(uint64_t val,unsigned tid);
-
- /** Function to add instruction onto the head of the list of the
- * instructions. Used when new instructions are fetched.
- */
- ListIt addInst(DynInstPtr &inst);
-
- /** Function to tell the CPU that an instruction has completed. */
- void instDone(unsigned tid);
-
- /** Add Instructions to the CPU Remove List*/
- void addToRemoveList(DynInstPtr &inst);
-
- /** Remove an instruction from the front end of the list. There's
- * no restriction on location of the instruction.
- */
- void removeFrontInst(DynInstPtr &inst);
-
- /** Remove all instructions that are not currently in the ROB. */
- void removeInstsNotInROB(unsigned tid);
-
- /** Remove all instructions younger than the given sequence number. */
- void removeInstsUntil(const InstSeqNum &seq_num,unsigned tid);
-
- inline void squashInstIt(const ListIt &instIt, const unsigned &tid);
-
- void cleanUpRemovedInsts();
-
- /** Remove all instructions from the list. */
-// void removeAllInsts();
-
- void dumpInsts();
-
- /** Basically a wrapper function so that instructions executed at
- * commit can tell the instruction queue that they have
- * completed. Eventually this hack should be removed.
- */
-// void wakeDependents(DynInstPtr &inst);
-
- public:
- /** List of all the instructions in flight. */
- std::list<DynInstPtr> instList;
-
- /** List of all the instructions that will be removed at the end of this
- * cycle.
- */
- std::queue<ListIt> removeList;
-
-#ifdef DEBUG
- std::set<InstSeqNum> snList;
-#endif
-
- /** Records if instructions need to be removed this cycle due to
- * being retired or squashed.
- */
- bool removeInstsThisCycle;
-
- protected:
- /** The fetch stage. */
- typename CPUPolicy::Fetch fetch;
-
- /** The decode stage. */
- typename CPUPolicy::Decode decode;
-
- /** The dispatch stage. */
- typename CPUPolicy::Rename rename;
-
- /** The issue/execute/writeback stages. */
- typename CPUPolicy::IEW iew;
-
- /** The commit stage. */
- typename CPUPolicy::Commit commit;
-
- /** The register file. */
- typename CPUPolicy::RegFile regFile;
-
- /** The free list. */
- typename CPUPolicy::FreeList freeList;
-
- /** The rename map. */
- typename CPUPolicy::RenameMap renameMap[Impl::MaxThreads];
-
- /** The commit rename map. */
- typename CPUPolicy::RenameMap commitRenameMap[Impl::MaxThreads];
-
- /** The re-order buffer. */
- typename CPUPolicy::ROB rob;
-
- /** Active Threads List */
- std::list<unsigned> activeThreads;
-
- /** Integer Register Scoreboard */
- Scoreboard scoreboard;
-
- public:
- /** Enum to give each stage a specific index, so when calling
- * activateStage() or deactivateStage(), they can specify which stage
- * is being activated/deactivated.
- */
- enum StageIdx {
- FetchIdx,
- DecodeIdx,
- RenameIdx,
- IEWIdx,
- CommitIdx,
- NumStages };
-
- /** Typedefs from the Impl to get the structs that each of the
- * time buffers should use.
- */
- typedef typename CPUPolicy::TimeStruct TimeStruct;
-
- typedef typename CPUPolicy::FetchStruct FetchStruct;
-
- typedef typename CPUPolicy::DecodeStruct DecodeStruct;
-
- typedef typename CPUPolicy::RenameStruct RenameStruct;
-
- typedef typename CPUPolicy::IEWStruct IEWStruct;
-
- /** The main time buffer to do backwards communication. */
- TimeBuffer<TimeStruct> timeBuffer;
-
- /** The fetch stage's instruction queue. */
- TimeBuffer<FetchStruct> fetchQueue;
-
- /** The decode stage's instruction queue. */
- TimeBuffer<DecodeStruct> decodeQueue;
-
- /** The rename stage's instruction queue. */
- TimeBuffer<RenameStruct> renameQueue;
-
- /** The IEW stage's instruction queue. */
- TimeBuffer<IEWStruct> iewQueue;
-
- public:
- ActivityRecorder activityRec;
-
- void activityThisCycle() { activityRec.activity(); }
-
- void activateStage(const StageIdx idx)
- { activityRec.activateStage(idx); }
-
- void deactivateStage(const StageIdx idx)
- { activityRec.deactivateStage(idx); }
-
- /** Wakes the CPU, rescheduling the CPU if it's not already active. */
- void wakeCPU();
-
- /** Gets a free thread id. Use if thread ids change across system. */
- int getFreeTid();
-
- public:
- /** Temporary function to get pointer to exec context. */
- ExecContext *xcBase(unsigned tid)
- {
- return thread[tid]->getXCProxy();
- }
-
- /** The global sequence number counter. */
- InstSeqNum globalSeqNum;
-
- Checker<DynInstPtr> *checker;
-
-#if FULL_SYSTEM
- /** Pointer to the system. */
- System *system;
-
- /** Pointer to the memory controller. */
- MemoryController *memCtrl;
- /** Pointer to physical memory. */
- PhysicalMemory *physmem;
-#endif
-
- /** Pointer to memory. */
- FunctionalMemory *mem;
-
- Sampler *sampler;
-
- int switchCount;
-
- // List of all ExecContexts.
- std::vector<Thread *> thread;
-
-#if 0
- /** Page table pointer. */
- PageTable *pTable;
-#endif
-
- /** Pointer to the icache interface. */
- MemInterface *icacheInterface;
- /** Pointer to the dcache interface. */
- MemInterface *dcacheInterface;
-
- /** Whether or not the CPU should defer its registration. */
- bool deferRegistration;
-
- /** Is there a context switch pending? */
- bool contextSwitch;
-
- /** Threads Scheduled to Enter CPU */
- std::list<int> cpuWaitList;
-
- /** The cycle that the CPU was last running, used for statistics. */
- Tick lastRunningCycle;
-
- /** Number of Threads CPU can process */
- unsigned numThreads;
-
- /** Mapping for system thread id to cpu id */
- std::map<unsigned,unsigned> threadMap;
-
- /** Available thread ids in the cpu*/
- std::vector<unsigned> tids;
-
- /** Stat for total number of times the CPU is descheduled. */
- Stats::Scalar<> timesIdled;
- /** Stat for total number of cycles the CPU spends descheduled. */
- Stats::Scalar<> idleCycles;
- /** Stat for the number of committed instructions per thread. */
- Stats::Vector<> committedInsts;
- /** Stat for the total number of committed instructions. */
- Stats::Scalar<> totalCommittedInsts;
- /** Stat for the CPI per thread. */
- Stats::Formula cpi;
- /** Stat for the total CPI. */
- Stats::Formula totalCpi;
- /** Stat for the IPC per thread. */
- Stats::Formula ipc;
- /** Stat for the total IPC. */
- Stats::Formula totalIpc;
-};
-
-#endif // __CPU_O3_CPU_HH__
diff --git a/cpu/o3/regfile.hh b/cpu/o3/regfile.hh
deleted file mode 100644
index ed1238d36..000000000
--- a/cpu/o3/regfile.hh
+++ /dev/null
@@ -1,266 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __CPU_O3_REGFILE_HH__
-#define __CPU_O3_REGFILE_HH__
-
-#include "arch/isa_traits.hh"
-#include "arch/faults.hh"
-#include "base/trace.hh"
-#include "config/full_system.hh"
-#include "cpu/o3/comm.hh"
-
-#if FULL_SYSTEM
-#include "kern/kernel_stats.hh"
-
-#endif
-
-#include <vector>
-
-/**
- * Simple physical register file class.
- * This really only depends on the ISA, and not the Impl. Things that are
- * in the ifdef FULL_SYSTEM are pretty dependent on the ISA, and probably
- * should go in the AlphaFullCPU.
- */
-template <class Impl>
-class PhysRegFile
-{
- protected:
- typedef TheISA::IntReg IntReg;
- typedef TheISA::FloatReg FloatReg;
- typedef TheISA::MiscRegFile MiscRegFile;
- typedef TheISA::MiscReg MiscReg;
- // Note that most of the definitions of the IntReg, FloatReg, etc. exist
- // within the Impl/ISA class and not within this PhysRegFile class.
-
- // Will make these registers public for now, but they probably should
- // be private eventually with some accessor functions.
- public:
- typedef typename Impl::FullCPU FullCPU;
-
- /**
- * Constructs a physical register file with the specified amount of
- * integer and floating point registers.
- */
- PhysRegFile(unsigned _numPhysicalIntRegs,
- unsigned _numPhysicalFloatRegs);
-
- //Everything below should be pretty well identical to the normal
- //register file that exists within AlphaISA class.
- //The duplication is unfortunate but it's better than having
- //different ways to access certain registers.
-
- //Add these in later when everything else is in place
-// void serialize(std::ostream &os);
-// void unserialize(Checkpoint *cp, const std::string &section);
-
- /** Reads an integer register. */
- uint64_t readIntReg(PhysRegIndex reg_idx)
- {
- assert(reg_idx < numPhysicalIntRegs);
-
- DPRINTF(IEW, "RegFile: Access to int register %i, has data "
- "%i\n", int(reg_idx), intRegFile[reg_idx]);
- return intRegFile[reg_idx];
- }
-
- /** Reads a floating point register (single precision). */
- float readFloatRegSingle(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 single, has "
- "data %8.8f\n", int(reg_idx), (float)floatRegFile[reg_idx].d);
-
- return (float)floatRegFile[reg_idx].d;
- }
-
- /** Reads a floating point register (double precision). */
- double readFloatRegDouble(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);
-
- return floatRegFile[reg_idx].d;
- }
-
- /** Reads a floating point register as an integer. */
- uint64_t readFloatRegInt(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 int, has data "
- "%lli\n", int(reg_idx), floatRegFile[reg_idx].q);
-
- return floatRegFile[reg_idx].q;
- }
-
- /** Sets an integer register to the given value. */
- void setIntReg(PhysRegIndex reg_idx, uint64_t val)
- {
- assert(reg_idx < numPhysicalIntRegs);
-
- DPRINTF(IEW, "RegFile: Setting int register %i to %lli\n",
- int(reg_idx), val);
-
- if (reg_idx != TheISA::ZeroReg)
- intRegFile[reg_idx] = val;
- }
-
- /** Sets a single precision floating point register to the given value. */
- void setFloatRegSingle(PhysRegIndex reg_idx, float 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);
-
- if (reg_idx != TheISA::ZeroReg)
- floatRegFile[reg_idx].d = (double)val;
- }
-
- /** Sets a double precision floating point register to the given value. */
- void setFloatRegDouble(PhysRegIndex reg_idx, double 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);
-
- if (reg_idx != TheISA::ZeroReg)
- floatRegFile[reg_idx].d = val;
- }
-
- /** Sets a floating point register to the given integer value. */
- void setFloatRegInt(PhysRegIndex reg_idx, uint64_t 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), val);
-
- if (reg_idx != TheISA::ZeroReg)
- floatRegFile[reg_idx].q = val;
- }
-
- //Consider leaving this stuff and below in some implementation specific
- //file as opposed to the general register file. Or have a derived class.
- MiscReg readMiscReg(int misc_reg, unsigned thread_id)
- {
- return miscRegs[thread_id].readReg(misc_reg);
- }
-
- MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault,
- unsigned thread_id)
- {
- return miscRegs[thread_id].readRegWithEffect(misc_reg, fault,
- cpu->xcBase(thread_id));
- }
-
- Fault setMiscReg(int misc_reg, const MiscReg &val, unsigned thread_id)
- {
- return miscRegs[thread_id].setReg(misc_reg, val);
- }
-
- Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val,
- unsigned thread_id)
- {
- return miscRegs[thread_id].setRegWithEffect(misc_reg, val,
- cpu->xcBase(thread_id));
- }
-
-#if FULL_SYSTEM
- int readIntrFlag() { return intrflag; }
- /** Sets an interrupt flag. */
- void setIntrFlag(int val) { intrflag = val; }
-#endif
-
- public:
- /** (signed) integer register file. */
- std::vector<IntReg> intRegFile;
-
- /** Floating point register file. */
- std::vector<FloatReg> floatRegFile;
-
- /** Miscellaneous register file. */
- MiscRegFile miscRegs[Impl::MaxThreads];
-
-#if FULL_SYSTEM
- private:
- int intrflag; // interrupt flag
-#endif
-
- private:
- /** CPU pointer. */
- FullCPU *cpu;
-
- public:
- /** Sets the CPU pointer. */
- void setCPU(FullCPU *cpu_ptr) { cpu = cpu_ptr; }
-
- /** Number of physical integer registers. */
- unsigned numPhysicalIntRegs;
- /** Number of physical floating point registers. */
- unsigned numPhysicalFloatRegs;
-};
-
-template <class Impl>
-PhysRegFile<Impl>::PhysRegFile(unsigned _numPhysicalIntRegs,
- unsigned _numPhysicalFloatRegs)
- : numPhysicalIntRegs(_numPhysicalIntRegs),
- numPhysicalFloatRegs(_numPhysicalFloatRegs)
-{
- intRegFile.resize(numPhysicalIntRegs);
- floatRegFile.resize(numPhysicalFloatRegs);
-
- //memset(intRegFile, 0, sizeof(*intRegFile));
- //memset(floatRegFile, 0, sizeof(*floatRegFile));
-}
-
-#endif
diff --git a/cpu/pc_event.hh b/cpu/pc_event.hh
deleted file mode 100644
index 7fa3902cc..000000000
--- a/cpu/pc_event.hh
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * 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 __PC_EVENT_HH__
-#define __PC_EVENT_HH__
-
-#include <vector>
-
-#include "mem/mem_req.hh"
-
-class ExecContext;
-class PCEventQueue;
-
-class PCEvent
-{
- protected:
- static const Addr badpc = MemReq::inval_addr;
-
- protected:
- std::string description;
- PCEventQueue *queue;
- Addr evpc;
-
- public:
- PCEvent(PCEventQueue *q, const std::string &desc, Addr pc);
-
- virtual ~PCEvent() { if (queue) remove(); }
-
- // for DPRINTF
- virtual const std::string name() const { return description; }
-
- std::string descr() const { return description; }
- Addr pc() const { return evpc; }
-
- bool remove();
- virtual void process(ExecContext *xc) = 0;
-};
-
-class PCEventQueue
-{
- protected:
- typedef PCEvent * record_t;
- class MapCompare {
- public:
- bool operator()(const record_t &l, const record_t &r) const {
- return l->pc() < r->pc();
- }
- bool operator()(const record_t &l, Addr pc) const {
- return l->pc() < pc;
- }
- bool operator()(Addr pc, const record_t &r) const {
- return pc < r->pc();
- }
- };
- typedef std::vector<record_t> map_t;
-
- public:
- typedef map_t::iterator iterator;
- typedef map_t::const_iterator const_iterator;
-
- protected:
- typedef std::pair<iterator, iterator> range_t;
- typedef std::pair<const_iterator, const_iterator> const_range_t;
-
- protected:
- map_t pc_map;
-
- bool doService(ExecContext *xc);
-
- public:
- PCEventQueue();
- ~PCEventQueue();
-
- bool remove(PCEvent *event);
- bool schedule(PCEvent *event);
- bool service(ExecContext *xc)
- {
- if (pc_map.empty())
- return false;
-
- return doService(xc);
- }
-
- range_t equal_range(Addr pc);
- range_t equal_range(PCEvent *event) { return equal_range(event->pc()); }
-
- void dump() const;
-};
-
-
-inline
-PCEvent::PCEvent(PCEventQueue *q, const std::string &desc, Addr pc)
- : description(desc), queue(q), evpc(pc)
-{
- queue->schedule(this);
-}
-
-inline bool
-PCEvent::remove()
-{
- if (!queue)
- panic("cannot remove an uninitialized event;");
-
- return queue->remove(this);
-}
-
-class BreakPCEvent : public PCEvent
-{
- protected:
- bool remove;
-
- public:
- BreakPCEvent(PCEventQueue *q, const std::string &desc, Addr addr,
- bool del = false);
- virtual void process(ExecContext *xc);
-};
-
-#endif // __PC_EVENT_HH__
diff --git a/cpu/simple/cpu.cc b/cpu/simple/cpu.cc
deleted file mode 100644
index c03945ffa..000000000
--- a/cpu/simple/cpu.cc
+++ /dev/null
@@ -1,955 +0,0 @@
-/*
- * 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 <cmath>
-#include <cstdio>
-#include <cstdlib>
-#include <iostream>
-#include <iomanip>
-#include <list>
-#include <sstream>
-#include <string>
-
-#include "base/cprintf.hh"
-#include "base/inifile.hh"
-#include "base/loader/symtab.hh"
-#include "base/misc.hh"
-#include "base/pollevent.hh"
-#include "base/range.hh"
-#include "base/stats/events.hh"
-#include "base/trace.hh"
-#include "cpu/base.hh"
-#include "cpu/cpu_exec_context.hh"
-#include "cpu/exec_context.hh"
-#include "cpu/exetrace.hh"
-#include "cpu/profile.hh"
-#include "cpu/sampler/sampler.hh"
-#include "cpu/simple/cpu.hh"
-#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 "sim/byteswap.hh"
-#include "sim/builder.hh"
-#include "sim/debug.hh"
-#include "sim/host.hh"
-#include "sim/sim_events.hh"
-#include "sim/sim_object.hh"
-#include "sim/stats.hh"
-
-#if FULL_SYSTEM
-#include "base/remote_gdb.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"
-#endif // FULL_SYSTEM
-
-using namespace std;
-//The SimpleCPU does alpha only
-using namespace AlphaISA;
-
-
-SimpleCPU::TickEvent::TickEvent(SimpleCPU *c, int w)
- : Event(&mainEventQueue, CPU_Tick_Pri), cpu(c), width(w)
-{
-}
-
-
-void
-SimpleCPU::init()
-{
- BaseCPU::init();
-#if FULL_SYSTEM
- for (int i = 0; i < execContexts.size(); ++i) {
- ExecContext *xc = execContexts[i];
-
- // initialize CPU, including PC
- TheISA::initCPU(xc, xc->readCpuId());
- }
-#endif
-}
-
-void
-SimpleCPU::TickEvent::process()
-{
- int count = width;
- do {
- cpu->tick();
- } while (--count > 0 && cpu->status() == Running);
-}
-
-const char *
-SimpleCPU::TickEvent::description()
-{
- return "SimpleCPU tick event";
-}
-
-
-SimpleCPU::CacheCompletionEvent::CacheCompletionEvent(SimpleCPU *_cpu)
- : Event(&mainEventQueue), cpu(_cpu)
-{
-}
-
-void SimpleCPU::CacheCompletionEvent::process()
-{
- cpu->processCacheCompletion();
-}
-
-const char *
-SimpleCPU::CacheCompletionEvent::description()
-{
- return "SimpleCPU cache completion event";
-}
-
-SimpleCPU::SimpleCPU(Params *p)
- : BaseCPU(p), tickEvent(this, p->width), cpuXC(NULL),
- cacheCompletionEvent(this)
-{
- _status = Idle;
-#if FULL_SYSTEM
- cpuXC = new CPUExecContext(this, 0, p->system, p->itb, p->dtb, p->mem);
-
-#else
- cpuXC = new CPUExecContext(this, /* thread_num */ 0, p->process,
- /* asid */ 0);
-#endif // !FULL_SYSTEM
- cpuXC->setStatus(ExecContext::Suspended);
- xcProxy = cpuXC->getProxy();
-
- icacheInterface = p->icache_interface;
- dcacheInterface = p->dcache_interface;
-
- memReq = new MemReq();
- memReq->xc = xcProxy;
- memReq->asid = 0;
- memReq->data = new uint8_t[64];
-
- numInst = 0;
- startNumInst = 0;
- numLoad = 0;
- startNumLoad = 0;
- lastIcacheStall = 0;
- lastDcacheStall = 0;
-
- execContexts.push_back(xcProxy);
-}
-
-SimpleCPU::~SimpleCPU()
-{
-}
-
-void
-SimpleCPU::switchOut(Sampler *s)
-{
- sampler = s;
- if (status() == DcacheMissStall) {
- DPRINTF(Sampler,"Outstanding dcache access, waiting for completion\n");
- _status = DcacheMissSwitch;
- }
- else {
- _status = SwitchedOut;
-
- if (tickEvent.scheduled())
- tickEvent.squash();
-
- sampler->signalSwitched();
- }
-}
-
-
-void
-SimpleCPU::takeOverFrom(BaseCPU *oldCPU)
-{
- BaseCPU::takeOverFrom(oldCPU);
-
- assert(!tickEvent.scheduled());
-
- // if any of this CPU's ExecContexts are active, mark the CPU as
- // running and schedule its tick event.
- for (int i = 0; i < execContexts.size(); ++i) {
- ExecContext *xc = execContexts[i];
- if (xc->status() == ExecContext::Active && _status != Running) {
- _status = Running;
- tickEvent.schedule(curTick);
- }
- }
-}
-
-
-void
-SimpleCPU::activateContext(int thread_num, int delay)
-{
- assert(thread_num == 0);
- assert(cpuXC);
-
- assert(_status == Idle || _status == SwitchedOut);
- notIdleFraction++;
- scheduleTickEvent(delay);
- _status = Running;
-}
-
-
-void
-SimpleCPU::suspendContext(int thread_num)
-{
- assert(thread_num == 0);
- assert(cpuXC);
-
- assert(_status == Running || _status == SwitchedOut);
- notIdleFraction--;
- unscheduleTickEvent();
- _status = Idle;
-}
-
-
-void
-SimpleCPU::deallocateContext(int thread_num)
-{
- // for now, these are equivalent
- suspendContext(thread_num);
-}
-
-
-void
-SimpleCPU::haltContext(int thread_num)
-{
- // for now, these are equivalent
- suspendContext(thread_num);
-}
-
-
-void
-SimpleCPU::regStats()
-{
- using namespace Stats;
-
- BaseCPU::regStats();
-
- numInsts
- .name(name() + ".num_insts")
- .desc("Number of instructions executed")
- ;
-
- numMemRefs
- .name(name() + ".num_refs")
- .desc("Number of memory references")
- ;
-
- notIdleFraction
- .name(name() + ".not_idle_fraction")
- .desc("Percentage of non-idle cycles")
- ;
-
- idleFraction
- .name(name() + ".idle_fraction")
- .desc("Percentage of idle cycles")
- ;
-
- icacheStallCycles
- .name(name() + ".icache_stall_cycles")
- .desc("ICache total stall cycles")
- .prereq(icacheStallCycles)
- ;
-
- dcacheStallCycles
- .name(name() + ".dcache_stall_cycles")
- .desc("DCache total stall cycles")
- .prereq(dcacheStallCycles)
- ;
-
- idleFraction = constant(1.0) - notIdleFraction;
-}
-
-void
-SimpleCPU::resetStats()
-{
- startNumInst = numInst;
- notIdleFraction = (_status != Idle);
-}
-
-void
-SimpleCPU::serialize(ostream &os)
-{
- BaseCPU::serialize(os);
- SERIALIZE_ENUM(_status);
- SERIALIZE_SCALAR(inst);
- nameOut(os, csprintf("%s.xc", name()));
- cpuXC->serialize(os);
- nameOut(os, csprintf("%s.tickEvent", name()));
- tickEvent.serialize(os);
- nameOut(os, csprintf("%s.cacheCompletionEvent", name()));
- cacheCompletionEvent.serialize(os);
-}
-
-void
-SimpleCPU::unserialize(Checkpoint *cp, const string &section)
-{
- BaseCPU::unserialize(cp, section);
- UNSERIALIZE_ENUM(_status);
- 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
-change_thread_state(int thread_number, int activate, int priority)
-{
-}
-
-Fault
-SimpleCPU::copySrcTranslate(Addr src)
-{
- static bool no_warn = true;
- int blk_size = (dcacheInterface) ? dcacheInterface->getBlockSize() : 64;
- // Only support block sizes of 64 atm.
- assert(blk_size == 64);
- int offset = src & (blk_size - 1);
-
- // Make sure block doesn't span page
- if (no_warn &&
- (src & PageMask) != ((src + blk_size) & PageMask) &&
- (src >> 40) != 0xfffffc) {
- warn("Copied block source spans pages %x.", src);
- no_warn = false;
- }
-
- memReq->reset(src & ~(blk_size - 1), blk_size);
-
- // translate to physical address
- Fault fault = cpuXC->translateDataReadReq(memReq);
-
- if (fault == NoFault) {
- cpuXC->copySrcAddr = src;
- cpuXC->copySrcPhysAddr = memReq->paddr + offset;
- } else {
- assert(!fault->isAlignmentFault());
-
- cpuXC->copySrcAddr = 0;
- cpuXC->copySrcPhysAddr = 0;
- }
- return fault;
-}
-
-Fault
-SimpleCPU::copy(Addr dest)
-{
- static bool no_warn = true;
- int blk_size = (dcacheInterface) ? dcacheInterface->getBlockSize() : 64;
- // Only support block sizes of 64 atm.
- assert(blk_size == 64);
- uint8_t data[blk_size];
- //assert(cpuXC->copySrcAddr);
- int offset = dest & (blk_size - 1);
-
- // Make sure block doesn't span page
- if (no_warn &&
- (dest & PageMask) != ((dest + blk_size) & PageMask) &&
- (dest >> 40) != 0xfffffc) {
- no_warn = false;
- warn("Copied block destination spans pages %x. ", dest);
- }
-
- memReq->reset(dest & ~(blk_size -1), blk_size);
- // translate to physical address
- Fault fault = cpuXC->translateDataWriteReq(memReq);
-
- if (fault == NoFault) {
- Addr dest_addr = memReq->paddr + offset;
- // Need to read straight from memory since we have more than 8 bytes.
- memReq->paddr = cpuXC->copySrcPhysAddr;
- cpuXC->mem->read(memReq, data);
- memReq->paddr = dest_addr;
- cpuXC->mem->write(memReq, data);
- if (dcacheInterface) {
- memReq->cmd = Copy;
- memReq->completionEvent = NULL;
- memReq->paddr = cpuXC->copySrcPhysAddr;
- memReq->dest = dest_addr;
- memReq->size = 64;
- memReq->time = curTick;
- memReq->flags &= ~INST_READ;
- dcacheInterface->access(memReq);
- }
- }
- else
- assert(!fault->isAlignmentFault());
-
- return fault;
-}
-
-// precise architected memory state accessor macros
-template <class T>
-Fault
-SimpleCPU::read(Addr addr, T &data, unsigned flags)
-{
- if (status() == DcacheMissStall || status() == DcacheMissSwitch) {
- Fault fault = cpuXC->read(memReq,data);
-
- if (traceData) {
- traceData->setAddr(memReq->vaddr);
- }
- return fault;
- }
-
- memReq->reset(addr, sizeof(T), flags);
-
- // translate to physical address
- Fault fault = cpuXC->translateDataReadReq(memReq);
-
- // if we have a cache, do cache access too
- if (fault == NoFault && dcacheInterface) {
- memReq->cmd = Read;
- memReq->completionEvent = NULL;
- memReq->time = curTick;
- memReq->flags &= ~INST_READ;
- MemAccessResult result = dcacheInterface->access(memReq);
-
- // 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 && dcacheInterface->doEvents()) {
- memReq->completionEvent = &cacheCompletionEvent;
- lastDcacheStall = curTick;
- unscheduleTickEvent();
- _status = DcacheMissStall;
- } else {
- // do functional access
- fault = cpuXC->read(memReq, data);
-
- }
- } else if(fault == NoFault) {
- // do functional access
- fault = cpuXC->read(memReq, data);
-
- }
-
- if (!dcacheInterface && (memReq->flags & UNCACHEABLE))
- recordEvent("Uncached Read");
-
- return fault;
-}
-
-#ifndef DOXYGEN_SHOULD_SKIP_THIS
-
-template
-Fault
-SimpleCPU::read(Addr addr, uint64_t &data, unsigned flags);
-
-template
-Fault
-SimpleCPU::read(Addr addr, uint32_t &data, unsigned flags);
-
-template
-Fault
-SimpleCPU::read(Addr addr, uint16_t &data, unsigned flags);
-
-template
-Fault
-SimpleCPU::read(Addr addr, uint8_t &data, unsigned flags);
-
-#endif //DOXYGEN_SHOULD_SKIP_THIS
-
-template<>
-Fault
-SimpleCPU::read(Addr addr, double &data, unsigned flags)
-{
- return read(addr, *(uint64_t*)&data, flags);
-}
-
-template<>
-Fault
-SimpleCPU::read(Addr addr, float &data, unsigned flags)
-{
- return read(addr, *(uint32_t*)&data, flags);
-}
-
-
-template<>
-Fault
-SimpleCPU::read(Addr addr, int32_t &data, unsigned flags)
-{
- return read(addr, (uint32_t&)data, flags);
-}
-
-
-template <class T>
-Fault
-SimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
-{
- memReq->reset(addr, sizeof(T), flags);
-
- // translate to physical address
- Fault fault = cpuXC->translateDataWriteReq(memReq);
-
- // do functional access
- if (fault == NoFault)
- fault = cpuXC->write(memReq, data);
-
- if (fault == NoFault && dcacheInterface) {
- memReq->cmd = Write;
- memcpy(memReq->data,(uint8_t *)&data,memReq->size);
- memReq->completionEvent = NULL;
- memReq->time = curTick;
- memReq->flags &= ~INST_READ;
- MemAccessResult result = dcacheInterface->access(memReq);
-
- // 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 && dcacheInterface->doEvents()) {
- memReq->completionEvent = &cacheCompletionEvent;
- lastDcacheStall = curTick;
- unscheduleTickEvent();
- _status = DcacheMissStall;
- }
- }
-
- if (res && (fault == NoFault))
- *res = memReq->result;
-
- if (!dcacheInterface && (memReq->flags & UNCACHEABLE))
- recordEvent("Uncached Write");
-
- return fault;
-}
-
-
-#ifndef DOXYGEN_SHOULD_SKIP_THIS
-template
-Fault
-SimpleCPU::write(uint64_t data, Addr addr, unsigned flags, uint64_t *res);
-
-template
-Fault
-SimpleCPU::write(uint32_t data, Addr addr, unsigned flags, uint64_t *res);
-
-template
-Fault
-SimpleCPU::write(uint16_t data, Addr addr, unsigned flags, uint64_t *res);
-
-template
-Fault
-SimpleCPU::write(uint8_t data, Addr addr, unsigned flags, uint64_t *res);
-
-#endif //DOXYGEN_SHOULD_SKIP_THIS
-
-template<>
-Fault
-SimpleCPU::write(double data, Addr addr, unsigned flags, uint64_t *res)
-{
- return write(*(uint64_t*)&data, addr, flags, res);
-}
-
-template<>
-Fault
-SimpleCPU::write(float data, Addr addr, unsigned flags, uint64_t *res)
-{
- return write(*(uint32_t*)&data, addr, flags, res);
-}
-
-
-template<>
-Fault
-SimpleCPU::write(int32_t data, Addr addr, unsigned flags, uint64_t *res)
-{
- return write((uint32_t)data, addr, flags, res);
-}
-
-
-#if FULL_SYSTEM
-Addr
-SimpleCPU::dbg_vtophys(Addr addr)
-{
- return vtophys(xcProxy, addr);
-}
-#endif // FULL_SYSTEM
-
-void
-SimpleCPU::processCacheCompletion()
-{
- switch (status()) {
- case IcacheMissStall:
- icacheStallCycles += curTick - lastIcacheStall;
- _status = IcacheMissComplete;
- scheduleTickEvent(1);
- break;
- case DcacheMissStall:
- if (memReq->cmd.isRead()) {
- curStaticInst->execute(this,traceData);
- if (traceData)
- traceData->finalize();
- }
- dcacheStallCycles += curTick - lastDcacheStall;
- _status = Running;
- scheduleTickEvent(1);
- break;
- case DcacheMissSwitch:
- if (memReq->cmd.isRead()) {
- curStaticInst->execute(this,traceData);
- if (traceData)
- traceData->finalize();
- }
- _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).
- return;
- default:
- panic("SimpleCPU::processCacheCompletion: bad state");
- break;
- }
-}
-
-#if FULL_SYSTEM
-void
-SimpleCPU::post_interrupt(int int_num, int index)
-{
- BaseCPU::post_interrupt(int_num, index);
-
- if (cpuXC->status() == ExecContext::Suspended) {
- DPRINTF(IPI,"Suspended Processor awoke\n");
- cpuXC->activate();
- }
-}
-#endif // FULL_SYSTEM
-
-/* start simulation, program loaded, processor precise state initialized */
-void
-SimpleCPU::tick()
-{
- numCycles++;
-
- traceData = NULL;
-
- Fault fault = NoFault;
-
-#if FULL_SYSTEM
- if (checkInterrupts && check_interrupts() && !cpuXC->inPalMode() &&
- status() != IcacheMissComplete) {
- int ipl = 0;
- int summary = 0;
- checkInterrupts = false;
-
- if (cpuXC->readMiscReg(IPR_SIRR)) {
- for (int i = INTLEVEL_SOFTWARE_MIN;
- i < INTLEVEL_SOFTWARE_MAX; i++) {
- if (cpuXC->readMiscReg(IPR_SIRR) & (ULL(1) << i)) {
- // See table 4-19 of 21164 hardware reference
- ipl = (i - INTLEVEL_SOFTWARE_MIN) + 1;
- summary |= (ULL(1) << i);
- }
- }
- }
-
- uint64_t interrupts = cpuXC->cpu->intr_status();
- for (int i = INTLEVEL_EXTERNAL_MIN;
- i < INTLEVEL_EXTERNAL_MAX; i++) {
- if (interrupts & (ULL(1) << i)) {
- // See table 4-19 of 21164 hardware reference
- ipl = i;
- summary |= (ULL(1) << i);
- }
- }
-
- if (cpuXC->readMiscReg(IPR_ASTRR))
- panic("asynchronous traps not implemented\n");
-
- if (ipl && ipl > cpuXC->readMiscReg(IPR_IPLR)) {
- cpuXC->setMiscReg(IPR_ISR, summary);
- cpuXC->setMiscReg(IPR_INTID, ipl);
-
- Fault(new InterruptFault)->invoke(xcProxy);
-
- DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n",
- cpuXC->readMiscReg(IPR_IPLR), ipl, summary);
- }
- }
-#endif
-
- // maintain $r0 semantics
- cpuXC->setIntReg(ZeroReg, 0);
-#ifdef TARGET_ALPHA
- cpuXC->setFloatRegDouble(ZeroReg, 0.0);
-#endif // TARGET_ALPHA
-
- if (status() == IcacheMissComplete) {
- // 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 {
- // Try to fetch an instruction
-
- // set up memory request for instruction fetch
-#if FULL_SYSTEM
-#define IFETCH_FLAGS(pc) ((pc) & 1) ? PHYSICAL : 0
-#else
-#define IFETCH_FLAGS(pc) 0
-#endif
-
- memReq->cmd = Read;
- memReq->reset(cpuXC->readPC() & ~3, sizeof(uint32_t),
- IFETCH_FLAGS(cpuXC->readPC()));
-
- fault = cpuXC->translateInstReq(memReq);
-
- if (fault == NoFault)
- fault = cpuXC->mem->read(memReq, inst);
-
- if (icacheInterface && fault == NoFault) {
- memReq->completionEvent = NULL;
-
- memReq->time = curTick;
- memReq->flags |= INST_READ;
- MemAccessResult result = icacheInterface->access(memReq);
-
- // 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()) {
- memReq->completionEvent = &cacheCompletionEvent;
- lastIcacheStall = curTick;
- unscheduleTickEvent();
- _status = IcacheMissStall;
- return;
- }
- }
- }
-
- // If we've got a valid instruction (i.e., no fault on instruction
- // fetch), then execute it.
- if (fault == NoFault) {
-
- // keep an instruction count
- numInst++;
- numInsts++;
-
- // check for instruction-count-based events
- comInstEventQueue[0]->serviceEvents(numInst);
-
- // decode the instruction
- inst = gtoh(inst);
- curStaticInst = StaticInst::decode(makeExtMI(inst, cpuXC->readPC()));
-
- traceData = Trace::getInstRecord(curTick, xcProxy, this, curStaticInst,
- cpuXC->readPC());
-
-#if FULL_SYSTEM
- cpuXC->setInst(inst);
-#endif // FULL_SYSTEM
-
- cpuXC->func_exe_inst++;
-
- fault = curStaticInst->execute(this, traceData);
-
-#if FULL_SYSTEM
- if (system->kernelBinning->fnbin) {
- assert(cpuXC->getKernelStats());
- system->kernelBinning->execute(xcProxy, inst);
- }
-
- if (cpuXC->profile) {
- bool usermode =
- (cpuXC->readMiscReg(AlphaISA::IPR_DTB_CM) & 0x18) != 0;
- cpuXC->profilePC = usermode ? 1 : cpuXC->readPC();
- ProfileNode *node = cpuXC->profile->consume(xcProxy, inst);
- if (node)
- cpuXC->profileNode = node;
- }
-#endif
-
- if (curStaticInst->isMemRef()) {
- numMemRefs++;
- }
-
- if (curStaticInst->isLoad()) {
- ++numLoad;
- comLoadEventQueue[0]->serviceEvents(numLoad);
- }
-
- // 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())) {
- traceData->finalize();
- }
-
- traceFunctions(cpuXC->readPC());
-
- } // if (fault == NoFault)
-
- if (fault != NoFault) {
-#if FULL_SYSTEM
- fault->invoke(xcProxy);
-#else // !FULL_SYSTEM
- fatal("fault (%d) detected @ PC 0x%08p", fault, cpuXC->readPC());
-#endif // FULL_SYSTEM
- }
- else {
-#if THE_ISA != MIPS_ISA
- // go to the next instruction
- cpuXC->setPC(cpuXC->readNextPC());
- cpuXC->setNextPC(cpuXC->readNextPC() + sizeof(MachInst));
-#else
- // go to the next instruction
- cpuXC->setPC(cpuXC->readNextPC());
- cpuXC->setNextPC(cpuXC->readNextNPC());
- cpuXC->setNextNPC(cpuXC->readNextNPC() + sizeof(MachInst));
-#endif
-
- }
-
-#if FULL_SYSTEM
- Addr oldpc;
- do {
- oldpc = cpuXC->readPC();
- system->pcEventQueue.service(xcProxy);
- } while (oldpc != cpuXC->readPC());
-#endif
-
- assert(status() == Running ||
- status() == Idle ||
- status() == DcacheMissStall);
-
- if (status() == Running && !tickEvent.scheduled())
- tickEvent.schedule(curTick + cycles(1));
-}
-
-////////////////////////////////////////////////////////////////////////
-//
-// SimpleCPU Simulation Object
-//
-BEGIN_DECLARE_SIM_OBJECT_PARAMS(SimpleCPU)
-
- Param<Counter> max_insts_any_thread;
- Param<Counter> max_insts_all_threads;
- Param<Counter> max_loads_any_thread;
- Param<Counter> max_loads_all_threads;
-
-#if FULL_SYSTEM
- SimObjectParam<AlphaITB *> itb;
- SimObjectParam<AlphaDTB *> dtb;
- SimObjectParam<FunctionalMemory *> mem;
- SimObjectParam<System *> system;
- Param<int> cpu_id;
- Param<Tick> profile;
-#else
- SimObjectParam<Process *> workload;
-#endif // FULL_SYSTEM
-
- Param<int> clock;
- SimObjectParam<BaseMem *> icache;
- SimObjectParam<BaseMem *> dcache;
-
- Param<bool> defer_registration;
- Param<int> width;
- Param<bool> function_trace;
- Param<Tick> function_trace_start;
-
-END_DECLARE_SIM_OBJECT_PARAMS(SimpleCPU)
-
-BEGIN_INIT_SIM_OBJECT_PARAMS(SimpleCPU)
-
- INIT_PARAM(max_insts_any_thread,
- "terminate when any thread reaches this inst count"),
- INIT_PARAM(max_insts_all_threads,
- "terminate when all threads have reached this inst count"),
- INIT_PARAM(max_loads_any_thread,
- "terminate when any thread reaches this load count"),
- INIT_PARAM(max_loads_all_threads,
- "terminate when all threads have reached this load count"),
-
-#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, ""),
-#else
- INIT_PARAM(workload, "processes to run"),
-#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"),
- INIT_PARAM(function_trace_start, "Cycle to start function trace")
-
-END_INIT_SIM_OBJECT_PARAMS(SimpleCPU)
-
-
-CREATE_SIM_OBJECT(SimpleCPU)
-{
- SimpleCPU::Params *params = new SimpleCPU::Params();
- params->name = getInstanceName();
- params->numberOfThreads = 1;
- params->max_insts_any_thread = max_insts_any_thread;
- params->max_insts_all_threads = max_insts_all_threads;
- params->max_loads_any_thread = max_loads_any_thread;
- params->max_loads_all_threads = max_loads_all_threads;
- params->deferRegistration = defer_registration;
- 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;
-
-#if FULL_SYSTEM
- params->itb = itb;
- params->dtb = dtb;
- params->mem = mem;
- params->system = system;
- params->cpu_id = cpu_id;
- params->profile = profile;
-#else
- params->process = workload;
-#endif
-
- SimpleCPU *cpu = new SimpleCPU(params);
- return cpu;
-}
-
-REGISTER_SIM_OBJECT("SimpleCPU", SimpleCPU)
-
diff --git a/cpu/simple/cpu.hh b/cpu/simple/cpu.hh
deleted file mode 100644
index 4ab9a1c3e..000000000
--- a/cpu/simple/cpu.hh
+++ /dev/null
@@ -1,363 +0,0 @@
-/*
- * 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 __CPU_SIMPLE_CPU_SIMPLE_CPU_HH__
-#define __CPU_SIMPLE_CPU_SIMPLE_CPU_HH__
-
-#include "base/statistics.hh"
-#include "config/full_system.hh"
-#include "cpu/base.hh"
-#include "cpu/cpu_exec_context.hh"
-#include "cpu/pc_event.hh"
-#include "cpu/sampler/sampler.hh"
-#include "cpu/static_inst.hh"
-#include "sim/eventq.hh"
-
-// forward declarations
-#if FULL_SYSTEM
-class Processor;
-class AlphaITB;
-class AlphaDTB;
-class PhysicalMemory;
-
-class RemoteGDB;
-class GDBListener;
-
-#else
-
-class Process;
-
-#endif // FULL_SYSTEM
-
-class ExecContext;
-class MemInterface;
-class Checkpoint;
-
-namespace Trace {
- class InstRecord;
-}
-
-class SimpleCPU : public BaseCPU
-{
- protected:
- typedef TheISA::MachInst MachInst;
- typedef TheISA::MiscReg MiscReg;
- public:
- // main simulation loop (one cycle)
- void tick();
- virtual void init();
-
- private:
- struct TickEvent : public Event
- {
- SimpleCPU *cpu;
- int width;
-
- TickEvent(SimpleCPU *c, int w);
- void process();
- const char *description();
- };
-
- TickEvent tickEvent;
-
- /// Schedule tick event, regardless of its current state.
- void scheduleTickEvent(int numCycles)
- {
- if (tickEvent.squashed())
- tickEvent.reschedule(curTick + cycles(numCycles));
- else if (!tickEvent.scheduled())
- tickEvent.schedule(curTick + cycles(numCycles));
- }
-
- /// Unschedule tick event, regardless of its current state.
- void unscheduleTickEvent()
- {
- if (tickEvent.scheduled())
- tickEvent.squash();
- }
-
- private:
- Trace::InstRecord *traceData;
-
- public:
- //
- enum Status {
- Running,
- Idle,
- IcacheMissStall,
- IcacheMissComplete,
- DcacheMissStall,
- DcacheMissSwitch,
- SwitchedOut
- };
-
- private:
- Status _status;
-
- public:
- void post_interrupt(int int_num, int index);
-
- void zero_fill_64(Addr addr) {
- static int warned = 0;
- if (!warned) {
- warn ("WH64 is not implemented");
- warned = 1;
- }
- };
-
- public:
- struct Params : public BaseCPU::Params
- {
- MemInterface *icache_interface;
- MemInterface *dcache_interface;
- int width;
-#if FULL_SYSTEM
- AlphaITB *itb;
- AlphaDTB *dtb;
- FunctionalMemory *mem;
-#else
- Process *process;
-#endif
- };
- SimpleCPU(Params *params);
- virtual ~SimpleCPU();
-
- public:
- // execution context
- CPUExecContext *cpuXC;
-
- ExecContext *xcProxy;
-
- void switchOut(Sampler *s);
- void takeOverFrom(BaseCPU *oldCPU);
-
-#if FULL_SYSTEM
- Addr dbg_vtophys(Addr addr);
-
- 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;
-
- // Pointer to the sampler that is telling us to switchover.
- // Used to signal the completion of the pipe drain and schedule
- // the next switchover
- Sampler *sampler;
-
- 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);
- virtual void suspendContext(int thread_num);
- virtual void deallocateContext(int thread_num);
- virtual void haltContext(int thread_num);
-
- // statistics
- virtual void regStats();
- virtual void resetStats();
-
- // number of simulated instructions
- Counter numInst;
- Counter startNumInst;
- Stats::Scalar<> numInsts;
-
- virtual Counter totalInstructions() const
- {
- return numInst - startNumInst;
- }
-
- // number of simulated memory references
- Stats::Scalar<> numMemRefs;
-
- // number of simulated loads
- Counter numLoad;
- Counter startNumLoad;
-
- // number of idle cycles
- Stats::Average<> notIdleFraction;
- Stats::Formula idleFraction;
-
- // number of cycles stalled for I-cache misses
- Stats::Scalar<> icacheStallCycles;
- Counter lastIcacheStall;
-
- // number of cycles stalled for D-cache misses
- Stats::Scalar<> dcacheStallCycles;
- Counter lastDcacheStall;
-
- void processCacheCompletion();
-
- virtual void serialize(std::ostream &os);
- virtual void unserialize(Checkpoint *cp, const std::string &section);
-
- template <class T>
- Fault read(Addr addr, T &data, unsigned flags);
-
- template <class T>
- Fault write(T data, Addr addr, unsigned flags, uint64_t *res);
-
- // These functions are only used in CPU models that split
- // effective address computation from the actual memory access.
- void setEA(Addr EA) { panic("SimpleCPU::setEA() not implemented\n"); }
- Addr getEA() { panic("SimpleCPU::getEA() not implemented\n"); }
-
- void prefetch(Addr addr, unsigned flags)
- {
- // need to do this...
- }
-
- void writeHint(Addr addr, int size, unsigned flags)
- {
- // need to do this...
- }
-
- Fault copySrcTranslate(Addr src);
-
- Fault copy(Addr dest);
-
- // The register accessor methods provide the index of the
- // instruction's operand (e.g., 0 or 1), not the architectural
- // register index, to simplify the implementation of register
- // renaming. We find the architectural register index by indexing
- // into the instruction's own operand index table. Note that a
- // raw pointer to the StaticInst is provided instead of a
- // ref-counted StaticInstPtr to redice overhead. This is fine as
- // long as these methods don't copy the pointer into any long-term
- // storage (which is pretty hard to imagine they would have reason
- // to do).
-
- uint64_t readIntReg(const StaticInst *si, int idx)
- {
- return cpuXC->readIntReg(si->srcRegIdx(idx));
- }
-
- float readFloatRegSingle(const StaticInst *si, int idx)
- {
- int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
- return cpuXC->readFloatRegSingle(reg_idx);
- }
-
- double readFloatRegDouble(const StaticInst *si, int idx)
- {
- int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
- return cpuXC->readFloatRegDouble(reg_idx);
- }
-
- uint64_t readFloatRegInt(const StaticInst *si, int idx)
- {
- int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
- return cpuXC->readFloatRegInt(reg_idx);
- }
-
- void setIntReg(const StaticInst *si, int idx, uint64_t val)
- {
- cpuXC->setIntReg(si->destRegIdx(idx), val);
- }
-
- void setFloatRegSingle(const StaticInst *si, int idx, float val)
- {
- int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
- cpuXC->setFloatRegSingle(reg_idx, val);
- }
-
- void setFloatRegDouble(const StaticInst *si, int idx, double val)
- {
- int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
- cpuXC->setFloatRegDouble(reg_idx, val);
- }
-
- void setFloatRegInt(const StaticInst *si, int idx, uint64_t val)
- {
- int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
- cpuXC->setFloatRegInt(reg_idx, val);
- }
-
- uint64_t readPC() { return cpuXC->readPC(); }
- void setNextPC(uint64_t val) { cpuXC->setNextPC(val); }
-
- MiscReg readMiscReg(int misc_reg)
- {
- return cpuXC->readMiscReg(misc_reg);
- }
-
- MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault)
- {
- return cpuXC->readMiscRegWithEffect(misc_reg, fault);
- }
-
- Fault setMiscReg(int misc_reg, const MiscReg &val)
- {
- return cpuXC->setMiscReg(misc_reg, val);
- }
-
- Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val)
- {
- return cpuXC->setMiscRegWithEffect(misc_reg, val);
- }
-
-#if FULL_SYSTEM
- Fault hwrei() { return cpuXC->hwrei(); }
- int readIntrFlag() { return cpuXC->readIntrFlag(); }
- void setIntrFlag(int val) { cpuXC->setIntrFlag(val); }
- bool inPalMode() { return cpuXC->inPalMode(); }
- void ev5_trap(Fault fault) { fault->invoke(xcProxy); }
- bool simPalCheck(int palFunc) { return cpuXC->simPalCheck(palFunc); }
-#else
- void syscall() { cpuXC->syscall(); }
-#endif
-
- bool misspeculating() { return cpuXC->misspeculating(); }
- ExecContext *xcBase() { return xcProxy; }
-};
-
-#endif // __CPU_SIMPLE_CPU_SIMPLE_CPU_HH__
diff --git a/cpu/static_inst.hh b/cpu/static_inst.hh
deleted file mode 100644
index b9d782b7b..000000000
--- a/cpu/static_inst.hh
+++ /dev/null
@@ -1,475 +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.
- */
-
-#ifndef __CPU_STATIC_INST_HH__
-#define __CPU_STATIC_INST_HH__
-
-#include <bitset>
-#include <string>
-
-#include "base/hashmap.hh"
-#include "base/refcnt.hh"
-#include "encumbered/cpu/full/op_class.hh"
-#include "sim/host.hh"
-#include "arch/isa_traits.hh"
-
-// forward declarations
-struct AlphaSimpleImpl;
-struct OzoneImpl;
-struct SimpleImpl;
-class ExecContext;
-class DynInst;
-
-template <class Impl>
-class AlphaDynInst;
-
-template <class Impl>
-class OzoneDynInst;
-
-class CheckerCPU;
-class FastCPU;
-class SimpleCPU;
-class InorderCPU;
-class SymbolTable;
-
-namespace Trace {
- class InstRecord;
-}
-
-/**
- * Base, ISA-independent static instruction class.
- *
- * The main component of this class is the vector of flags and the
- * associated methods for reading them. Any object that can rely
- * solely on these flags can process instructions without being
- * recompiled for multiple ISAs.
- */
-class StaticInstBase : public RefCounted
-{
- protected:
-
- /// Set of boolean static instruction properties.
- ///
- /// Notes:
- /// - The IsInteger and IsFloating flags are based on the class of
- /// registers accessed by the instruction. Although most
- /// instructions will have exactly one of these two flags set, it
- /// is possible for an instruction to have neither (e.g., direct
- /// unconditional branches, memory barriers) or both (e.g., an
- /// FP/int conversion).
- /// - If IsMemRef is set, then exactly one of IsLoad or IsStore
- /// will be set.
- /// - If IsControl is set, then exactly one of IsDirectControl or
- /// IsIndirect Control will be set, and exactly one of
- /// IsCondControl or IsUncondControl will be set.
- /// - IsSerializing, IsMemBarrier, and IsWriteBarrier are
- /// implemented as flags since in the current model there's no
- /// other way for instructions to inject behavior into the
- /// pipeline outside of fetch. Once we go to an exec-in-exec CPU
- /// model we should be able to get rid of these flags and
- /// implement this behavior via the execute() methods.
- ///
- enum Flags {
- IsNop, ///< Is a no-op (no effect at all).
-
- IsInteger, ///< References integer regs.
- IsFloating, ///< References FP regs.
-
- IsMemRef, ///< References memory (load, store, or prefetch).
- IsLoad, ///< Reads from memory (load or prefetch).
- IsStore, ///< Writes to memory.
- IsStoreConditional, ///< Store conditional instruction.
- IsInstPrefetch, ///< Instruction-cache prefetch.
- IsDataPrefetch, ///< Data-cache prefetch.
- IsCopy, ///< Fast Cache block copy
-
- IsControl, ///< Control transfer instruction.
- IsDirectControl, ///< PC relative control transfer.
- IsIndirectControl, ///< Register indirect control transfer.
- IsCondControl, ///< Conditional control transfer.
- IsUncondControl, ///< Unconditional control transfer.
- IsCall, ///< Subroutine call.
- IsReturn, ///< Subroutine return.
-
- IsCondDelaySlot,///< Conditional Delay-Slot Instruction
-
- IsThreadSync, ///< Thread synchronization operation.
-
- IsSerializing, ///< Serializes pipeline: won't execute until all
- /// older instructions have committed.
- IsSerializeBefore,
- IsSerializeAfter,
- IsMemBarrier, ///< Is a memory barrier
- IsWriteBarrier, ///< Is a write barrier
-
- IsNonSpeculative, ///< Should not be executed speculatively
- IsQuiesce, ///< Is a quiesce instruction
-
- IsIprAccess, ///< Accesses IPRs
- IsUnverifiable, ///< Can't be verified by a checker
-
- NumFlags
- };
-
- /// Flag values for this instruction.
- std::bitset<NumFlags> flags;
-
- /// See opClass().
- OpClass _opClass;
-
- /// See numSrcRegs().
- int8_t _numSrcRegs;
-
- /// See numDestRegs().
- int8_t _numDestRegs;
-
- /// The following are used to track physical register usage
- /// for machines with separate int & FP reg files.
- //@{
- int8_t _numFPDestRegs;
- int8_t _numIntDestRegs;
- //@}
-
- /// Constructor.
- /// It's important to initialize everything here to a sane
- /// default, since the decoder generally only overrides
- /// the fields that are meaningful for the particular
- /// instruction.
- StaticInstBase(OpClass __opClass)
- : _opClass(__opClass), _numSrcRegs(0), _numDestRegs(0),
- _numFPDestRegs(0), _numIntDestRegs(0)
- {
- }
-
- public:
-
- /// @name Register information.
- /// The sum of numFPDestRegs() and numIntDestRegs() equals
- /// numDestRegs(). The former two functions are used to track
- /// physical register usage for machines with separate int & FP
- /// reg files.
- //@{
- /// Number of source registers.
- int8_t numSrcRegs() const { return _numSrcRegs; }
- /// Number of destination registers.
- int8_t numDestRegs() const { return _numDestRegs; }
- /// Number of floating-point destination regs.
- int8_t numFPDestRegs() const { return _numFPDestRegs; }
- /// Number of integer destination regs.
- int8_t numIntDestRegs() const { return _numIntDestRegs; }
- //@}
-
- /// @name Flag accessors.
- /// These functions are used to access the values of the various
- /// instruction property flags. See StaticInstBase::Flags for descriptions
- /// of the individual flags.
- //@{
-
- bool isNop() const { return flags[IsNop]; }
-
- bool isMemRef() const { return flags[IsMemRef]; }
- bool isLoad() const { return flags[IsLoad]; }
- bool isStore() const { return flags[IsStore]; }
- bool isStoreConditional() const { return flags[IsStoreConditional]; }
- bool isInstPrefetch() const { return flags[IsInstPrefetch]; }
- bool isDataPrefetch() const { return flags[IsDataPrefetch]; }
- bool isCopy() const { return flags[IsCopy];}
-
- bool isInteger() const { return flags[IsInteger]; }
- bool isFloating() const { return flags[IsFloating]; }
-
- bool isControl() const { return flags[IsControl]; }
- bool isCall() const { return flags[IsCall]; }
- bool isReturn() const { return flags[IsReturn]; }
- bool isDirectCtrl() const { return flags[IsDirectControl]; }
- bool isIndirectCtrl() const { return flags[IsIndirectControl]; }
- bool isCondCtrl() const { return flags[IsCondControl]; }
- bool isUncondCtrl() const { return flags[IsUncondControl]; }
-
- bool isThreadSync() const { return flags[IsThreadSync]; }
- bool isSerializing() const { return flags[IsSerializing] ||
- flags[IsSerializeBefore] ||
- flags[IsSerializeAfter]; }
- bool isSerializeBefore() const { return flags[IsSerializeBefore]; }
- bool isSerializeAfter() const { return flags[IsSerializeAfter]; }
- bool isMemBarrier() const { return flags[IsMemBarrier]; }
- bool isWriteBarrier() const { return flags[IsWriteBarrier]; }
- bool isNonSpeculative() const { return flags[IsNonSpeculative]; }
- bool isQuiesce() const { return flags[IsQuiesce]; }
- bool isIprAccess() const { return flags[IsIprAccess]; }
- bool isUnverifiable() const { return flags[IsUnverifiable]; }
- //@}
-
- /// Operation class. Used to select appropriate function unit in issue.
- OpClass opClass() const { return _opClass; }
-};
-
-
-// forward declaration
-class StaticInstPtr;
-
-/**
- * Generic yet ISA-dependent static instruction class.
- *
- * This class builds on StaticInstBase, defining fields and interfaces
- * that are generic across all ISAs but that differ in details
- * according to the specific ISA being used.
- */
-class StaticInst : public StaticInstBase
-{
- public:
-
- /// Binary machine instruction type.
- typedef TheISA::MachInst MachInst;
- /// Binary extended machine instruction type.
- typedef TheISA::ExtMachInst ExtMachInst;
- /// Logical register index type.
- typedef TheISA::RegIndex RegIndex;
-
- enum {
- MaxInstSrcRegs = TheISA::MaxInstSrcRegs, //< Max source regs
- MaxInstDestRegs = TheISA::MaxInstDestRegs, //< Max dest regs
- };
-
-
- /// Return logical index (architectural reg num) of i'th destination reg.
- /// Only the entries from 0 through numDestRegs()-1 are valid.
- RegIndex destRegIdx(int i) const { return _destRegIdx[i]; }
-
- /// Return logical index (architectural reg num) of i'th source reg.
- /// Only the entries from 0 through numSrcRegs()-1 are valid.
- RegIndex srcRegIdx(int i) const { return _srcRegIdx[i]; }
-
- /// Pointer to a statically allocated "null" instruction object.
- /// Used to give eaCompInst() and memAccInst() something to return
- /// when called on non-memory instructions.
- static StaticInstPtr nullStaticInstPtr;
-
- /**
- * Memory references only: returns "fake" instruction representing
- * the effective address part of the memory operation. Used to
- * obtain the dependence info (numSrcRegs and srcRegIdx[]) for
- * just the EA computation.
- */
- virtual const
- StaticInstPtr &eaCompInst() const { return nullStaticInstPtr; }
-
- /**
- * Memory references only: returns "fake" instruction representing
- * the memory access part of the memory operation. Used to
- * obtain the dependence info (numSrcRegs and srcRegIdx[]) for
- * just the memory access (not the EA computation).
- */
- virtual const
- StaticInstPtr &memAccInst() const { return nullStaticInstPtr; }
-
- /// The binary machine instruction.
- const ExtMachInst machInst;
-
- protected:
-
- /// See destRegIdx().
- RegIndex _destRegIdx[MaxInstDestRegs];
- /// See srcRegIdx().
- RegIndex _srcRegIdx[MaxInstSrcRegs];
-
- /**
- * Base mnemonic (e.g., "add"). Used by generateDisassembly()
- * methods. Also useful to readily identify instructions from
- * within the debugger when #cachedDisassembly has not been
- * initialized.
- */
- const char *mnemonic;
-
- /**
- * String representation of disassembly (lazily evaluated via
- * disassemble()).
- */
- mutable std::string *cachedDisassembly;
-
- /**
- * Internal function to generate disassembly string.
- */
- virtual std::string
- generateDisassembly(Addr pc, const SymbolTable *symtab) const = 0;
-
- /// Constructor.
- StaticInst(const char *_mnemonic, ExtMachInst _machInst, OpClass __opClass)
- : StaticInstBase(__opClass),
- machInst(_machInst), mnemonic(_mnemonic), cachedDisassembly(0)
- {
- }
-
- public:
-
- virtual ~StaticInst()
- {
- if (cachedDisassembly)
- delete cachedDisassembly;
- }
-
-/**
- * The execute() signatures are auto-generated by scons based on the
- * set of CPU models we are compiling in today.
- */
-#include "cpu/static_inst_exec_sigs.hh"
-
- /**
- * Return the target address for a PC-relative branch.
- * Invalid if not a PC-relative branch (i.e. isDirectCtrl()
- * should be true).
- */
- virtual Addr branchTarget(Addr branchPC) const
- {
- panic("StaticInst::branchTarget() called on instruction "
- "that is not a PC-relative branch.");
- }
-
- /**
- * Return the target address for an indirect branch (jump). The
- * register value is read from the supplied execution context, so
- * the result is valid only if the execution context is about to
- * execute the branch in question. Invalid if not an indirect
- * branch (i.e. isIndirectCtrl() should be true).
- */
- virtual Addr branchTarget(ExecContext *xc) const
- {
- panic("StaticInst::branchTarget() called on instruction "
- "that is not an indirect branch.");
- }
-
- /**
- * Return true if the instruction is a control transfer, and if so,
- * return the target address as well.
- */
- bool hasBranchTarget(Addr pc, ExecContext *xc, Addr &tgt) const;
-
- /**
- * Return string representation of disassembled instruction.
- * The default version of this function will call the internal
- * virtual generateDisassembly() function to get the string,
- * then cache it in #cachedDisassembly. If the disassembly
- * should not be cached, this function should be overridden directly.
- */
- virtual const std::string &disassemble(Addr pc,
- const SymbolTable *symtab = 0) const
- {
- if (!cachedDisassembly)
- cachedDisassembly =
- new std::string(generateDisassembly(pc, symtab));
-
- return *cachedDisassembly;
- }
-
- /// Decoded instruction cache type.
- /// For now we're using a generic hash_map; this seems to work
- /// pretty well.
- typedef m5::hash_map<ExtMachInst, StaticInstPtr> DecodeCache;
-
- /// A cache of decoded instruction objects.
- static DecodeCache decodeCache;
-
- /**
- * Dump some basic stats on the decode cache hash map.
- * Only gets called if DECODE_CACHE_HASH_STATS is defined.
- */
- static void dumpDecodeCacheStats();
-
- /// Decode a machine instruction.
- /// @param mach_inst The binary instruction to decode.
- /// @retval A pointer to the corresponding StaticInst object.
- //This is defined as inline below.
- static StaticInstPtr decode(ExtMachInst mach_inst);
-};
-
-typedef RefCountingPtr<StaticInstBase> StaticInstBasePtr;
-
-/// Reference-counted pointer to a StaticInst object.
-/// This type should be used instead of "StaticInst *" so that
-/// StaticInst objects can be properly reference-counted.
-class StaticInstPtr : public RefCountingPtr<StaticInst>
-{
- public:
- /// Constructor.
- StaticInstPtr()
- : RefCountingPtr<StaticInst>()
- {
- }
-
- /// Conversion from "StaticInst *".
- StaticInstPtr(StaticInst *p)
- : RefCountingPtr<StaticInst>(p)
- {
- }
-
- /// Copy constructor.
- StaticInstPtr(const StaticInstPtr &r)
- : RefCountingPtr<StaticInst>(r)
- {
- }
-
- /// Construct directly from machine instruction.
- /// Calls StaticInst::decode().
- StaticInstPtr(TheISA::ExtMachInst mach_inst)
- : RefCountingPtr<StaticInst>(StaticInst::decode(mach_inst))
- {
- }
-
- /// Convert to pointer to StaticInstBase class.
- operator const StaticInstBasePtr()
- {
- return this->get();
- }
-};
-
-inline StaticInstPtr
-StaticInst::decode(StaticInst::ExtMachInst mach_inst)
-{
-#ifdef DECODE_CACHE_HASH_STATS
- // Simple stats on decode hash_map. Turns out the default
- // hash function is as good as anything I could come up with.
- const int dump_every_n = 10000000;
- static int decodes_til_dump = dump_every_n;
-
- if (--decodes_til_dump == 0) {
- dumpDecodeCacheStats();
- decodes_til_dump = dump_every_n;
- }
-#endif
-
- DecodeCache::iterator iter = decodeCache.find(mach_inst);
- if (iter != decodeCache.end()) {
- return iter->second;
- }
-
- StaticInstPtr si = TheISA::decodeInst(mach_inst);
- decodeCache[mach_inst] = si;
- return si;
-}
-
-#endif // __CPU_STATIC_INST_HH__
diff --git a/dev/alpha_console.cc b/dev/alpha_console.cc
deleted file mode 100644
index 6ca5e3a06..000000000
--- a/dev/alpha_console.cc
+++ /dev/null
@@ -1,356 +0,0 @@
-/*
- * Copyright (c) 2001-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @file
- * Alpha Console Definition
- */
-
-#include <cstddef>
-#include <cstdio>
-#include <string>
-
-#include "arch/alpha/system.hh"
-#include "base/inifile.hh"
-#include "base/str.hh"
-#include "base/trace.hh"
-#include "cpu/base.hh"
-#include "cpu/exec_context.hh"
-#include "dev/alpha_console.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 "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)
-{
- 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));
- }
-
- alphaAccess = new Access;
- alphaAccess->last_offset = size - 1;
-
- alphaAccess->version = ALPHA_ACCESS_VERSION;
- alphaAccess->diskUnit = 1;
-
- alphaAccess->diskCount = 0;
- alphaAccess->diskPAddr = 0;
- alphaAccess->diskBlock = 0;
- alphaAccess->diskOperation = 0;
- alphaAccess->outputChar = 0;
- alphaAccess->inputChar = 0;
- bzero(alphaAccess->cpuStack, sizeof(alphaAccess->cpuStack));
-
- system->setAlphaAccess(addr);
-}
-
-void
-AlphaConsole::startup()
-{
- 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();
-}
-
-Fault
-AlphaConsole::read(MemReqPtr &req, uint8_t *data)
-{
- memset(data, 0, req->size);
-
- Addr daddr = req->paddr - (addr & EV5::PAddrImplMask);
-
- switch (req->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;
- break;
- case offsetof(AlphaAccess, version):
- *(uint32_t*)data = alphaAccess->version;
- break;
- case offsetof(AlphaAccess, numCPUs):
- *(uint32_t*)data = alphaAccess->numCPUs;
- break;
- case offsetof(AlphaAccess, intrClockFrequency):
- *(uint32_t*)data = alphaAccess->intrClockFrequency;
- break;
- default:
- // Old console code read in everyting as a 32bit int
- *(uint32_t*)data = *(uint32_t*)(consoleData + daddr);
-
- }
- 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();
- break;
- case offsetof(AlphaAccess, cpuClock):
- *(uint64_t*)data = alphaAccess->cpuClock;
- break;
- case offsetof(AlphaAccess, mem_size):
- *(uint64_t*)data = alphaAccess->mem_size;
- break;
- case offsetof(AlphaAccess, kernStart):
- *(uint64_t*)data = alphaAccess->kernStart;
- break;
- case offsetof(AlphaAccess, kernEnd):
- *(uint64_t*)data = alphaAccess->kernEnd;
- break;
- case offsetof(AlphaAccess, entryPoint):
- *(uint64_t*)data = alphaAccess->entryPoint;
- break;
- case offsetof(AlphaAccess, diskUnit):
- *(uint64_t*)data = alphaAccess->diskUnit;
- break;
- case offsetof(AlphaAccess, diskCount):
- *(uint64_t*)data = alphaAccess->diskCount;
- break;
- case offsetof(AlphaAccess, diskPAddr):
- *(uint64_t*)data = alphaAccess->diskPAddr;
- break;
- case offsetof(AlphaAccess, diskBlock):
- *(uint64_t*)data = alphaAccess->diskBlock;
- break;
- case offsetof(AlphaAccess, diskOperation):
- *(uint64_t*)data = alphaAccess->diskOperation;
- break;
- case offsetof(AlphaAccess, outputChar):
- *(uint64_t*)data = 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];
- else
- panic("Unknown 64bit access, %#x\n", daddr);
- }
- break;
- default:
- return genMachineCheckFault();
- }
-
- return NoFault;
-}
-
-Fault
-AlphaConsole::write(MemReqPtr &req, const uint8_t *data)
-{
- uint64_t val;
-
- switch (req->size) {
- case sizeof(uint32_t):
- val = *(uint32_t *)data;
- break;
-
- case sizeof(uint64_t):
- val = *(uint64_t *)data;
- break;
- default:
- return genMachineCheckFault();
- }
-
- Addr daddr = req->paddr - (addr & EV5::PAddrImplMask);
- ExecContext *other_xc;
-
- switch (daddr) {
- case offsetof(AlphaAccess, diskUnit):
- alphaAccess->diskUnit = val;
- break;
-
- case offsetof(AlphaAccess, diskCount):
- alphaAccess->diskCount = val;
- break;
-
- case offsetof(AlphaAccess, diskPAddr):
- alphaAccess->diskPAddr = val;
- break;
-
- case offsetof(AlphaAccess, diskBlock):
- alphaAccess->diskBlock = val;
- break;
-
- case offsetof(AlphaAccess, diskOperation):
- if (val == 0x13)
- disk->read(alphaAccess->diskPAddr, alphaAccess->diskBlock,
- alphaAccess->diskCount);
- else
- panic("Invalid disk operation!");
-
- break;
-
- case offsetof(AlphaAccess, outputChar):
- console->out((char)(val & 0xff));
- break;
-
- other_xc->activate(); //Start the cpu
- break;
-
- default:
- int cpunum = (daddr - offsetof(AlphaAccess, cpuStack)) /
- sizeof(alphaAccess->cpuStack[0]);
- warn("%d: Trying to launch CPU number %d!", curTick, cpunum);
- assert(val > 0 && "Must not access primary cpu");
- if (cpunum >= 0 && cpunum < 64)
- alphaAccess->cpuStack[cpunum] = val;
- else
- panic("Unknown 64bit access, %#x\n", daddr);
- }
-
- return NoFault;
-}
-
-Tick
-AlphaConsole::cacheAccess(MemReqPtr &req)
-{
- return curTick + 1000;
-}
-
-void
-AlphaConsole::Access::serialize(ostream &os)
-{
- SERIALIZE_SCALAR(last_offset);
- SERIALIZE_SCALAR(version);
- SERIALIZE_SCALAR(numCPUs);
- SERIALIZE_SCALAR(mem_size);
- SERIALIZE_SCALAR(cpuClock);
- SERIALIZE_SCALAR(intrClockFrequency);
- SERIALIZE_SCALAR(kernStart);
- SERIALIZE_SCALAR(kernEnd);
- SERIALIZE_SCALAR(entryPoint);
- SERIALIZE_SCALAR(diskUnit);
- SERIALIZE_SCALAR(diskCount);
- SERIALIZE_SCALAR(diskPAddr);
- SERIALIZE_SCALAR(diskBlock);
- SERIALIZE_SCALAR(diskOperation);
- SERIALIZE_SCALAR(outputChar);
- SERIALIZE_SCALAR(inputChar);
- SERIALIZE_ARRAY(cpuStack,64);
-}
-
-void
-AlphaConsole::Access::unserialize(Checkpoint *cp, const std::string &section)
-{
- UNSERIALIZE_SCALAR(last_offset);
- UNSERIALIZE_SCALAR(version);
- UNSERIALIZE_SCALAR(numCPUs);
- UNSERIALIZE_SCALAR(mem_size);
- UNSERIALIZE_SCALAR(cpuClock);
- UNSERIALIZE_SCALAR(intrClockFrequency);
- UNSERIALIZE_SCALAR(kernStart);
- UNSERIALIZE_SCALAR(kernEnd);
- UNSERIALIZE_SCALAR(entryPoint);
- UNSERIALIZE_SCALAR(diskUnit);
- UNSERIALIZE_SCALAR(diskCount);
- UNSERIALIZE_SCALAR(diskPAddr);
- UNSERIALIZE_SCALAR(diskBlock);
- UNSERIALIZE_SCALAR(diskOperation);
- UNSERIALIZE_SCALAR(outputChar);
- UNSERIALIZE_SCALAR(inputChar);
- UNSERIALIZE_ARRAY(cpuStack, 64);
-}
-
-void
-AlphaConsole::serialize(ostream &os)
-{
- alphaAccess->serialize(os);
-}
-
-void
-AlphaConsole::unserialize(Checkpoint *cp, const std::string &section)
-{
- alphaAccess->unserialize(cp, section);
-}
-
-BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaConsole)
-
- SimObjectParam<SimConsole *> sim_console;
- SimObjectParam<SimpleDisk *> disk;
- SimObjectParam<MemoryController *> mmu;
- Param<Addr> 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)
-
-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(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)
-
-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);
-}
-
-REGISTER_SIM_OBJECT("AlphaConsole", AlphaConsole)
diff --git a/dev/alpha_console.hh b/dev/alpha_console.hh
deleted file mode 100644
index f63c6ad7e..000000000
--- a/dev/alpha_console.hh
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright (c) 2001-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @file
- * System Console Interface
- */
-
-#ifndef __ALPHA_CONSOLE_HH__
-#define __ALPHA_CONSOLE_HH__
-
-#include "base/range.hh"
-#include "dev/alpha_access.h"
-#include "dev/io_device.hh"
-#include "sim/host.hh"
-#include "sim/sim_object.hh"
-
-class BaseCPU;
-class SimConsole;
-class AlphaSystem;
-class SimpleDisk;
-class MemoryController;
-
-/**
- * Memory mapped interface to the system console. This device
- * represents a shared data region between the OS Kernel and the
- * System Console.
- *
- * The system console is a small standalone program that is initially
- * run when the system boots. It contains the necessary code to
- * access the boot disk, to read/write from the console, and to pass
- * boot parameters to the kernel.
- *
- * This version of the system console is very different from the one
- * that would be found in a real system. Many of the functions use
- * some sort of backdoor to get their job done. For example, reading
- * from the boot device on a real system would require a minimal
- * device driver to access the disk controller, but since we have a
- * simulator here, we are able to bypass the disk controller and
- * access the disk image directly. There are also some things like
- * reading the kernel off the disk image into memory that are normally
- * taken care of by the console that are now taken care of by the
- * simulator.
- *
- * These shortcuts are acceptable since the system console is
- * primarily used doing boot before the kernel has loaded its device
- * drivers.
- */
-class AlphaConsole : public PioDevice
-{
- protected:
- struct Access : public AlphaAccess
- {
- void serialize(std::ostream &os);
- void unserialize(Checkpoint *cp, const std::string &section);
- };
-
- union {
- Access *alphaAccess;
- uint8_t *consoleData;
- };
-
- /** the disk must be accessed from the console */
- SimpleDisk *disk;
-
- /** the system console (the terminal) is accessable from the console */
- SimConsole *console;
-
- /** a pointer to the system we are running in */
- AlphaSystem *system;
-
- /** a pointer to the CPU boot cpu */
- BaseCPU *cpu;
-
- Addr addr;
- static const Addr size = sizeof(struct AlphaAccess);
-
- 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);
-
- 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);
-
- /**
- * 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
deleted file mode 100644
index 87d683a5d..000000000
--- a/dev/baddev.cc
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @file
- * BadDevice implemenation
- */
-
-#include <deque>
-#include <string>
-#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 "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)
-{
- mmu->add_child(this, RangeSize(addr, size));
-
- if (pio_bus) {
- pioInterface = newPioInterface(name, hier, pio_bus, this,
- &BadDevice::cacheAccess);
- pioInterface->addAddrRange(RangeSize(addr, size));
- }
-
-}
-
-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)
-{
- panic("Device %s not imlpmented\n", devname);
- return NoFault;
-}
-
-Tick
-BadDevice::cacheAccess(MemReqPtr &req)
-{
- return curTick;
-}
-
-BEGIN_DECLARE_SIM_OBJECT_PARAMS(BadDevice)
-
- 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")
-
-END_INIT_SIM_OBJECT_PARAMS(BadDevice)
-
-CREATE_SIM_OBJECT(BadDevice)
-{
- return new BadDevice(getInstanceName(), addr, mmu, hier, pio_bus,
- devicename);
-}
-
-REGISTER_SIM_OBJECT("BadDevice", BadDevice)
diff --git a/dev/baddev.hh b/dev/baddev.hh
deleted file mode 100644
index 189f28331..000000000
--- a/dev/baddev.hh
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @file
- * This devices just panics when touched. For example if you have a
- * kernel that touches the frame buffer which isn't allowed.
- */
-
-#ifndef __DEV_BADDEV_HH__
-#define __DEV_BADDEV_HH__
-
-#include "base/range.hh"
-#include "dev/io_device.hh"
-
-class MemoryController;
-
-/**
- * BadDevice
- * This device just panics when accessed. It is supposed to warn
- * the user that the kernel they are running has unsupported
- * options (i.e. frame buffer)
- */
-class BadDevice : public PioDevice
-{
- private:
- Addr addr;
- static const Addr size = 0xf;
-
- std::string devname;
-
- public:
- /**
- * Constructor for the Baddev Class.
- * @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 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);
-
- /**
- * 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 // __DEV_BADDEV_HH__
diff --git a/dev/disk_image.cc b/dev/disk_image.cc
deleted file mode 100644
index 447c54697..000000000
--- a/dev/disk_image.cc
+++ /dev/null
@@ -1,471 +0,0 @@
-/*
- * Copyright (c) 2001-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @file
- * Disk Image Definitions
- */
-
-#include <sys/types.h>
-#include <sys/uio.h>
-#include <errno.h>
-#include <unistd.h>
-
-#include <cstdio>
-#include <cstring>
-#include <fstream>
-#include <string>
-
-#include "base/callback.hh"
-#include "base/misc.hh"
-#include "base/trace.hh"
-#include "dev/disk_image.hh"
-#include "sim/builder.hh"
-#include "sim/sim_exit.hh"
-#include "sim/byteswap.hh"
-
-using namespace std;
-
-////////////////////////////////////////////////////////////////////////
-//
-// Raw Disk image
-//
-RawDiskImage::RawDiskImage(const string &name, const string &filename,
- bool rd_only)
- : DiskImage(name), disk_size(0)
-{ open(filename, rd_only); }
-
-RawDiskImage::~RawDiskImage()
-{ close(); }
-
-void
-RawDiskImage::open(const string &filename, bool rd_only)
-{
- if (!filename.empty()) {
- initialized = true;
- readonly = rd_only;
- file = filename;
-
- ios::openmode mode = ios::in | ios::binary;
- if (!readonly)
- mode |= ios::out;
- stream.open(file.c_str(), mode);
- if (!stream.is_open())
- panic("Error opening %s", filename);
- }
-}
-
-void
-RawDiskImage::close()
-{
- stream.close();
-}
-
-off_t
-RawDiskImage::size() const
-{
- if (disk_size == 0) {
- if (!stream.is_open())
- panic("file not open!\n");
- stream.seekg(0, ios::end);
- disk_size = stream.tellg();
- }
-
- return disk_size / SectorSize;
-}
-
-off_t
-RawDiskImage::read(uint8_t *data, off_t offset) const
-{
- if (!initialized)
- panic("RawDiskImage not initialized");
-
- if (!stream.is_open())
- panic("file not open!\n");
-
- if (stream.seekg(offset * SectorSize, ios::beg) < 0)
- panic("Could not seek to location in file");
-
- streampos pos = stream.tellg();
- stream.read((char *)data, SectorSize);
-
- DPRINTF(DiskImageRead, "read: offset=%d\n", (uint64_t)offset);
- DDUMP(DiskImageRead, data, SectorSize);
-
- return stream.tellg() - pos;
-}
-
-off_t
-RawDiskImage::write(const uint8_t *data, off_t offset)
-{
- if (!initialized)
- panic("RawDiskImage not initialized");
-
- if (readonly)
- panic("Cannot write to a read only disk image");
-
- if (!stream.is_open())
- panic("file not open!\n");
-
- if (stream.seekp(offset * SectorSize, ios::beg) < 0)
- panic("Could not seek to location in file");
-
- DPRINTF(DiskImageWrite, "write: offset=%d\n", (uint64_t)offset);
- DDUMP(DiskImageWrite, data, SectorSize);
-
- streampos pos = stream.tellp();
- stream.write((const char *)data, SectorSize);
- return stream.tellp() - pos;
-}
-
-DEFINE_SIM_OBJECT_CLASS_NAME("DiskImage", DiskImage)
-
-BEGIN_DECLARE_SIM_OBJECT_PARAMS(RawDiskImage)
-
- Param<string> image_file;
- Param<bool> read_only;
-
-END_DECLARE_SIM_OBJECT_PARAMS(RawDiskImage)
-
-BEGIN_INIT_SIM_OBJECT_PARAMS(RawDiskImage)
-
- INIT_PARAM(image_file, "disk image file"),
- INIT_PARAM_DFLT(read_only, "read only image", false)
-
-END_INIT_SIM_OBJECT_PARAMS(RawDiskImage)
-
-
-CREATE_SIM_OBJECT(RawDiskImage)
-{
- return new RawDiskImage(getInstanceName(), image_file, read_only);
-}
-
-REGISTER_SIM_OBJECT("RawDiskImage", RawDiskImage)
-
-////////////////////////////////////////////////////////////////////////
-//
-// Copy on Write Disk image
-//
-const int CowDiskImage::VersionMajor = 1;
-const int CowDiskImage::VersionMinor = 0;
-
-CowDiskImage::CowDiskImage(const string &name, DiskImage *kid, int hash_size)
- : DiskImage(name), child(kid), table(NULL)
-{ init(hash_size); }
-
-class CowDiskCallback : public Callback
-{
- private:
- CowDiskImage *image;
-
- public:
- CowDiskCallback(CowDiskImage *i) : image(i) {}
- void process() { image->save(); delete this; }
-};
-
-CowDiskImage::CowDiskImage(const string &name, DiskImage *kid, int hash_size,
- const string &file, bool read_only)
- : DiskImage(name), filename(file), child(kid), table(NULL)
-{
- if (!open(filename)) {
- assert(!read_only && "why have a non-existent read only file?");
- init(hash_size);
- }
-
- if (!read_only)
- registerExitCallback(new CowDiskCallback(this));
-}
-
-CowDiskImage::~CowDiskImage()
-{
- SectorTable::iterator i = table->begin();
- SectorTable::iterator end = table->end();
-
- while (i != end) {
- delete (*i).second;
- ++i;
- }
-}
-
-void
-SafeRead(ifstream &stream, void *data, int count)
-{
- stream.read((char *)data, count);
- if (!stream.is_open())
- panic("file not open");
-
- if (stream.eof())
- panic("premature end-of-file");
-
- if (stream.bad() || stream.fail())
- panic("error reading cowdisk image");
-}
-
-template<class T>
-void
-SafeRead(ifstream &stream, T &data)
-{
- SafeRead(stream, &data, sizeof(data));
-}
-
-template<class T>
-void
-SafeReadSwap(ifstream &stream, T &data)
-{
- SafeRead(stream, &data, sizeof(data));
- data = letoh(data); //is this the proper byte order conversion?
-}
-
-bool
-CowDiskImage::open(const string &file)
-{
- ifstream stream(file.c_str());
- if (!stream.is_open())
- return false;
-
- if (stream.fail() || stream.bad())
- panic("Error opening %s", file);
-
- uint64_t magic;
- SafeRead(stream, magic);
-
- if (memcmp(&magic, "COWDISK!", sizeof(magic)) != 0)
- panic("Could not open %s: Invalid magic", file);
-
- uint32_t major, minor;
- SafeReadSwap(stream, major);
- SafeReadSwap(stream, minor);
-
- if (major != VersionMajor && minor != VersionMinor)
- panic("Could not open %s: invalid version %d.%d != %d.%d",
- file, major, minor, VersionMajor, VersionMinor);
-
- uint64_t sector_count;
- SafeReadSwap(stream, sector_count);
- table = new SectorTable(sector_count);
-
-
- for (uint64_t i = 0; i < sector_count; i++) {
- uint64_t offset;
- SafeReadSwap(stream, offset);
-
- Sector *sector = new Sector;
- SafeRead(stream, sector, sizeof(Sector));
-
- assert(table->find(offset) == table->end());
- (*table)[offset] = sector;
- }
-
- stream.close();
-
- initialized = true;
- return true;
-}
-
-void
-CowDiskImage::init(int hash_size)
-{
- table = new SectorTable(hash_size);
-
- initialized = true;
-}
-
-void
-SafeWrite(ofstream &stream, const void *data, int count)
-{
- stream.write((const char *)data, count);
- if (!stream.is_open())
- panic("file not open");
-
- if (stream.eof())
- panic("premature end-of-file");
-
- if (stream.bad() || stream.fail())
- panic("error reading cowdisk image");
-}
-
-template<class T>
-void
-SafeWrite(ofstream &stream, const T &data)
-{
- SafeWrite(stream, &data, sizeof(data));
-}
-
-template<class T>
-void
-SafeWriteSwap(ofstream &stream, const T &data)
-{
- T swappeddata = letoh(data); //is this the proper byte order conversion?
- SafeWrite(stream, &swappeddata, sizeof(data));
-}
-void
-CowDiskImage::save()
-{
- save(filename);
-}
-
-void
-CowDiskImage::save(const string &file)
-{
- if (!initialized)
- panic("RawDiskImage not initialized");
-
- ofstream stream(file.c_str());
- if (!stream.is_open() || stream.fail() || stream.bad())
- panic("Error opening %s", file);
-
- uint64_t magic;
- memcpy(&magic, "COWDISK!", sizeof(magic));
- SafeWrite(stream, magic);
-
- SafeWriteSwap(stream, (uint32_t)VersionMajor);
- SafeWriteSwap(stream, (uint32_t)VersionMinor);
- SafeWriteSwap(stream, (uint64_t)table->size());
-
- uint64_t size = table->size();
- SectorTable::iterator iter = table->begin();
- SectorTable::iterator end = table->end();
-
- for (uint64_t i = 0; i < size; i++) {
- if (iter == end)
- panic("Incorrect Table Size during save of COW disk image");
-
- SafeWriteSwap(stream, (uint64_t)(*iter).first);
- SafeWrite(stream, (*iter).second->data, sizeof(Sector));
- ++iter;
- }
-
- stream.close();
-}
-
-void
-CowDiskImage::writeback()
-{
- SectorTable::iterator i = table->begin();
- SectorTable::iterator end = table->end();
-
- while (i != end) {
- child->write((*i).second->data, (*i).first);
- ++i;
- }
-}
-
-off_t
-CowDiskImage::size() const
-{ return child->size(); }
-
-off_t
-CowDiskImage::read(uint8_t *data, off_t offset) const
-{
- if (!initialized)
- panic("CowDiskImage not initialized");
-
- if (offset > size())
- panic("access out of bounds");
-
- SectorTable::const_iterator i = table->find(offset);
- if (i == table->end())
- return child->read(data, offset);
- else {
- memcpy(data, (*i).second->data, SectorSize);
- DPRINTF(DiskImageRead, "read: offset=%d\n", (uint64_t)offset);
- DDUMP(DiskImageRead, data, SectorSize);
- return SectorSize;
- }
-}
-
-off_t
-CowDiskImage::write(const uint8_t *data, off_t offset)
-{
- if (!initialized)
- panic("RawDiskImage not initialized");
-
- if (offset > size())
- panic("access out of bounds");
-
- SectorTable::iterator i = table->find(offset);
- if (i == table->end()) {
- Sector *sector = new Sector;
- memcpy(sector, data, SectorSize);
- table->insert(make_pair(offset, sector));
- } else {
- memcpy((*i).second->data, data, SectorSize);
- }
-
- DPRINTF(DiskImageWrite, "write: offset=%d\n", (uint64_t)offset);
- DDUMP(DiskImageWrite, data, SectorSize);
-
- return SectorSize;
-}
-
-void
-CowDiskImage::serialize(ostream &os)
-{
- string cowFilename = name() + ".cow";
- SERIALIZE_SCALAR(cowFilename);
- save(Checkpoint::dir() + "/" + cowFilename);
-}
-
-void
-CowDiskImage::unserialize(Checkpoint *cp, const string &section)
-{
- string cowFilename;
- UNSERIALIZE_SCALAR(cowFilename);
- cowFilename = cp->cptDir + "/" + cowFilename;
- open(cowFilename);
-}
-
-BEGIN_DECLARE_SIM_OBJECT_PARAMS(CowDiskImage)
-
- SimObjectParam<DiskImage *> child;
- Param<string> image_file;
- Param<int> table_size;
- Param<bool> read_only;
-
-END_DECLARE_SIM_OBJECT_PARAMS(CowDiskImage)
-
-BEGIN_INIT_SIM_OBJECT_PARAMS(CowDiskImage)
-
- INIT_PARAM(child, "child image"),
- INIT_PARAM_DFLT(image_file, "disk image file", ""),
- INIT_PARAM_DFLT(table_size, "initial table size", 65536),
- INIT_PARAM_DFLT(read_only, "don't write back to the copy-on-write file",
- true)
-
-END_INIT_SIM_OBJECT_PARAMS(CowDiskImage)
-
-
-CREATE_SIM_OBJECT(CowDiskImage)
-{
- if (((string)image_file).empty())
- return new CowDiskImage(getInstanceName(), child, table_size);
- else
- return new CowDiskImage(getInstanceName(), child, table_size,
- image_file, read_only);
-}
-
-REGISTER_SIM_OBJECT("CowDiskImage", CowDiskImage)
diff --git a/dev/etherbus.cc b/dev/etherbus.cc
deleted file mode 100644
index c6b131e8e..000000000
--- a/dev/etherbus.cc
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * 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
- * Device module for modelling an ethernet hub
- */
-
-#include <cmath>
-#include <deque>
-#include <string>
-#include <vector>
-
-#include "base/trace.hh"
-#include "dev/etherbus.hh"
-#include "dev/etherdump.hh"
-#include "dev/etherint.hh"
-#include "dev/etherpkt.hh"
-#include "sim/builder.hh"
-#include "sim/root.hh"
-
-using namespace std;
-
-EtherBus::EtherBus(const string &name, double speed, bool loop,
- EtherDump *packet_dump)
- : SimObject(name), ticksPerByte(speed), loopback(loop),
- event(&mainEventQueue, this), sender(0), dump(packet_dump)
-{
-}
-
-void
-EtherBus::txDone()
-{
- devlist_t::iterator i = devlist.begin();
- devlist_t::iterator end = devlist.end();
-
- DPRINTF(Ethernet, "ethernet packet received: length=%d\n", packet->length);
- DDUMP(EthernetData, packet->data, packet->length);
-
- while (i != end) {
- if (loopback || *i != sender)
- (*i)->sendPacket(packet);
- ++i;
- }
-
- sender->sendDone();
-
- if (dump)
- dump->dump(packet);
-
- sender = 0;
- packet = 0;
-}
-
-void
-EtherBus::reg(EtherInt *dev)
-{ devlist.push_back(dev); }
-
-bool
-EtherBus::send(EtherInt *sndr, PacketPtr &pkt)
-{
- if (busy()) {
- DPRINTF(Ethernet, "ethernet packet not sent, bus busy\n", curTick);
- return false;
- }
-
- DPRINTF(Ethernet, "ethernet packet sent: length=%d\n", pkt->length);
- DDUMP(EthernetData, pkt->data, pkt->length);
-
- packet = pkt;
- sender = sndr;
- int delay = (int)ceil(((double)pkt->length * ticksPerByte) + 1.0);
- DPRINTF(Ethernet, "scheduling packet: delay=%d, (rate=%f)\n",
- delay, ticksPerByte);
- event.schedule(curTick + delay);
-
- return true;
-}
-
-BEGIN_DECLARE_SIM_OBJECT_PARAMS(EtherBus)
-
- Param<bool> loopback;
- Param<double> speed;
- SimObjectParam<EtherDump *> packet_dump;
-
-END_DECLARE_SIM_OBJECT_PARAMS(EtherBus)
-
-BEGIN_INIT_SIM_OBJECT_PARAMS(EtherBus)
-
- INIT_PARAM(loopback, "send the packet back to the sending interface"),
- INIT_PARAM(speed, "bus speed in ticks per byte"),
- INIT_PARAM(packet_dump, "object to dump network packets to")
-
-END_INIT_SIM_OBJECT_PARAMS(EtherBus)
-
-CREATE_SIM_OBJECT(EtherBus)
-{
- return new EtherBus(getInstanceName(), speed, loopback, packet_dump);
-}
-
-REGISTER_SIM_OBJECT("EtherBus", EtherBus)
diff --git a/dev/etherbus.hh b/dev/etherbus.hh
deleted file mode 100644
index ca859d85f..000000000
--- a/dev/etherbus.hh
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * 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
- * Device module for modelling an ethernet hub
- */
-
-#ifndef __ETHERBUS_H__
-#define __ETHERBUS_H__
-
-#include "sim/eventq.hh"
-#include "dev/etherpkt.hh"
-#include "sim/sim_object.hh"
-
-class EtherDump;
-class EtherInt;
-class EtherBus : public SimObject
-{
- protected:
- typedef std::list<EtherInt *> devlist_t;
- devlist_t devlist;
- double ticksPerByte;
- bool loopback;
-
- protected:
- class DoneEvent : public Event
- {
- protected:
- EtherBus *bus;
-
- public:
- DoneEvent(EventQueue *q, EtherBus *b)
- : Event(q), bus(b) {}
- virtual void process() { bus->txDone(); }
- virtual const char *description() { return "ethernet bus completion"; }
- };
-
- DoneEvent event;
- PacketPtr packet;
- EtherInt *sender;
- EtherDump *dump;
-
- public:
- EtherBus(const std::string &name, double speed, bool loopback,
- EtherDump *dump);
- virtual ~EtherBus() {}
-
- void txDone();
- void reg(EtherInt *dev);
- bool busy() const { return (bool)packet; }
- bool send(EtherInt *sender, PacketPtr &packet);
-};
-
-#endif // __ETHERBUS_H__
diff --git a/dev/etherdump.cc b/dev/etherdump.cc
deleted file mode 100644
index d8a51fc5b..000000000
--- a/dev/etherdump.cc
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * 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
- * Simple object for creating a simple pcap style packet trace
- */
-
-#include <sys/time.h>
-
-#include <algorithm>
-#include <string>
-
-#include "base/misc.hh"
-#include "base/output.hh"
-#include "dev/etherdump.hh"
-#include "sim/builder.hh"
-#include "sim/root.hh"
-
-using std::string;
-
-EtherDump::EtherDump(const string &name, const string &file, int max)
- : SimObject(name), stream(file.c_str()), maxlen(max)
-{
-}
-
-#define DLT_EN10MB 1 // Ethernet (10Mb)
-#define TCPDUMP_MAGIC 0xa1b2c3d4
-#define PCAP_VERSION_MAJOR 2
-#define PCAP_VERSION_MINOR 4
-
-struct pcap_file_header {
- uint32_t magic;
- uint16_t version_major;
- uint16_t version_minor;
- int32_t thiszone; // gmt to local correction
- uint32_t sigfigs; // accuracy of timestamps
- uint32_t snaplen; // max length saved portion of each pkt
- uint32_t linktype; // data link type (DLT_*)
-};
-
-struct pcap_pkthdr {
- uint32_t seconds;
- uint32_t microseconds;
- uint32_t caplen; // length of portion present
- uint32_t len; // length this packet (off wire)
-};
-
-void
-EtherDump::init()
-{
- curtime = time(NULL);
- struct pcap_file_header hdr;
- hdr.magic = TCPDUMP_MAGIC;
- hdr.version_major = PCAP_VERSION_MAJOR;
- hdr.version_minor = PCAP_VERSION_MINOR;
-
- hdr.thiszone = -5 * 3600;
- hdr.snaplen = 1500;
- hdr.sigfigs = 0;
- hdr.linktype = DLT_EN10MB;
-
- stream.write(reinterpret_cast<char *>(&hdr), sizeof(hdr));
-
- /*
- * output an empty packet with the current time so that we know
- * when the simulation began. This allows us to correlate packets
- * to sim_cycles.
- */
- pcap_pkthdr pkthdr;
- pkthdr.seconds = curtime;
- pkthdr.microseconds = 0;
- pkthdr.caplen = 0;
- pkthdr.len = 0;
- stream.write(reinterpret_cast<char *>(&pkthdr), sizeof(pkthdr));
-
- stream.flush();
-}
-
-void
-EtherDump::dumpPacket(PacketPtr &packet)
-{
- pcap_pkthdr pkthdr;
- pkthdr.seconds = curtime + (curTick / Clock::Int::s);
- pkthdr.microseconds = (curTick / Clock::Int::us) % ULL(1000000);
- pkthdr.caplen = std::min(packet->length, maxlen);
- pkthdr.len = packet->length;
- stream.write(reinterpret_cast<char *>(&pkthdr), sizeof(pkthdr));
- stream.write(reinterpret_cast<char *>(packet->data), pkthdr.caplen);
- stream.flush();
-}
-
-BEGIN_DECLARE_SIM_OBJECT_PARAMS(EtherDump)
-
- Param<string> file;
- Param<int> maxlen;
-
-END_DECLARE_SIM_OBJECT_PARAMS(EtherDump)
-
-BEGIN_INIT_SIM_OBJECT_PARAMS(EtherDump)
-
- INIT_PARAM(file, "file to dump packets to"),
- INIT_PARAM(maxlen, "max portion of packet data to dump")
-
-END_INIT_SIM_OBJECT_PARAMS(EtherDump)
-
-CREATE_SIM_OBJECT(EtherDump)
-{
- return new EtherDump(getInstanceName(), simout.resolve(file), maxlen);
-}
-
-REGISTER_SIM_OBJECT("EtherDump", EtherDump)
diff --git a/dev/etherdump.hh b/dev/etherdump.hh
deleted file mode 100644
index 149192cd7..000000000
--- a/dev/etherdump.hh
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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
- * Simple object for creating a simple pcap style packet trace
- */
-
-#ifndef __ETHERDUMP_H__
-#define __ETHERDUMP_H__
-
-#include <fstream>
-#include "dev/etherpkt.hh"
-#include "sim/sim_object.hh"
-
-/*
- * Simple object for creating a simple pcap style packet trace
- */
-class EtherDump : public SimObject
-{
- private:
- std::ofstream stream;
- const int maxlen;
- void dumpPacket(PacketPtr &packet);
- void init();
-
- Tick curtime;
-
- public:
- EtherDump(const std::string &name, const std::string &file, int max);
-
- inline void dump(PacketPtr &pkt) { dumpPacket(pkt); }
-};
-
-#endif // __ETHERDUMP_H__
diff --git a/dev/etherint.hh b/dev/etherint.hh
deleted file mode 100644
index e397846ae..000000000
--- a/dev/etherint.hh
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * 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
- * Class representing the actual interface between two ethernet
- * components.
- */
-
-#ifndef __DEV_ETHERINT_HH__
-#define __DEV_ETHERINT_HH__
-
-#include <string>
-
-#include "dev/etherpkt.hh"
-#include "sim/sim_object.hh"
-
-/*
- * Class representing the actual interface between two ethernet
- * components. These components are intended to attach to another
- * ethernet interface on one side and whatever device on the other.
- */
-class EtherInt : public SimObject
-{
- protected:
- EtherInt *peer;
-
- public:
- EtherInt(const std::string &name) : SimObject(name), peer(NULL) {}
- virtual ~EtherInt() {}
-
- void setPeer(EtherInt *p);
-
- void recvDone() { peer->sendDone(); }
- virtual void sendDone() = 0;
-
- bool sendPacket(PacketPtr packet)
- { return peer ? peer->recvPacket(packet) : true; }
- virtual bool recvPacket(PacketPtr packet) = 0;
-};
-
-#endif // __DEV_ETHERINT_HH__
diff --git a/dev/etherlink.cc b/dev/etherlink.cc
deleted file mode 100644
index f68332926..000000000
--- a/dev/etherlink.cc
+++ /dev/null
@@ -1,300 +0,0 @@
-/*
- * 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
- * Device module for modelling a fixed bandwidth full duplex ethernet link
- */
-
-#include <cmath>
-#include <deque>
-#include <string>
-#include <vector>
-
-#include "base/random.hh"
-#include "base/trace.hh"
-#include "dev/etherdump.hh"
-#include "dev/etherint.hh"
-#include "dev/etherlink.hh"
-#include "dev/etherpkt.hh"
-#include "sim/builder.hh"
-#include "sim/serialize.hh"
-#include "sim/system.hh"
-#include "sim/root.hh"
-
-using namespace std;
-
-EtherLink::EtherLink(const string &name, EtherInt *peer0, EtherInt *peer1,
- double rate, Tick delay, Tick delayVar, EtherDump *dump)
- : SimObject(name)
-{
- link[0] = new Link(name + ".link0", this, 0, rate, delay, delayVar, dump);
- link[1] = new Link(name + ".link1", this, 1, rate, delay, delayVar, dump);
-
- interface[0] = new Interface(name + ".int0", link[0], link[1]);
- interface[1] = new Interface(name + ".int1", link[1], link[0]);
-
- interface[0]->setPeer(peer0);
- peer0->setPeer(interface[0]);
- interface[1]->setPeer(peer1);
- peer1->setPeer(interface[1]);
-}
-
-EtherLink::~EtherLink()
-{
- delete link[0];
- delete link[1];
-
- delete interface[0];
- delete interface[1];
-}
-
-EtherLink::Interface::Interface(const string &name, Link *tx, Link *rx)
- : EtherInt(name), txlink(tx)
-{
- tx->setTxInt(this);
- rx->setRxInt(this);
-}
-
-EtherLink::Link::Link(const string &name, EtherLink *p, int num,
- double rate, Tick delay, Tick delay_var, EtherDump *d)
- : objName(name), parent(p), number(num), txint(NULL), rxint(NULL),
- ticksPerByte(rate), linkDelay(delay), delayVar(delay_var), dump(d),
- doneEvent(this)
-{ }
-
-void
-EtherLink::serialize(ostream &os)
-{
- link[0]->serialize("link0", os);
- link[1]->serialize("link1", os);
-}
-
-void
-EtherLink::unserialize(Checkpoint *cp, const string &section)
-{
- link[0]->unserialize("link0", cp, section);
- link[1]->unserialize("link1", cp, section);
-}
-
-void
-EtherLink::Link::txComplete(PacketPtr packet)
-{
- DPRINTF(Ethernet, "packet received: len=%d\n", packet->length);
- DDUMP(EthernetData, packet->data, packet->length);
- rxint->sendPacket(packet);
-}
-
-class LinkDelayEvent : public Event
-{
- protected:
- EtherLink::Link *link;
- PacketPtr packet;
-
- public:
- // non-scheduling version for createForUnserialize()
- LinkDelayEvent();
- LinkDelayEvent(EtherLink::Link *link, PacketPtr pkt, Tick when);
-
- void process();
-
- virtual void serialize(ostream &os);
- virtual void unserialize(Checkpoint *cp, const string &section);
- static Serializable *createForUnserialize(Checkpoint *cp,
- const string &section);
-};
-
-void
-EtherLink::Link::txDone()
-{
- if (dump)
- dump->dump(packet);
-
- if (linkDelay > 0) {
- DPRINTF(Ethernet, "packet delayed: delay=%d\n", linkDelay);
- new LinkDelayEvent(this, packet, curTick + linkDelay);
- } else {
- txComplete(packet);
- }
-
- packet = 0;
- assert(!busy());
-
- txint->sendDone();
-}
-
-bool
-EtherLink::Link::transmit(PacketPtr pkt)
-{
- if (busy()) {
- DPRINTF(Ethernet, "packet not sent, link busy\n");
- return false;
- }
-
- DPRINTF(Ethernet, "packet sent: len=%d\n", pkt->length);
- DDUMP(EthernetData, pkt->data, pkt->length);
-
- packet = pkt;
- Tick delay = (Tick)ceil(((double)pkt->length * ticksPerByte) + 1.0);
- if (delayVar != 0) {
- Random<Tick> var;
- delay += var.uniform(0, delayVar);
- }
- DPRINTF(Ethernet, "scheduling packet: delay=%d, (rate=%f)\n",
- delay, ticksPerByte);
- doneEvent.schedule(curTick + delay);
-
- return true;
-}
-
-void
-EtherLink::Link::serialize(const string &base, ostream &os)
-{
- bool packet_exists = packet;
- paramOut(os, base + ".packet_exists", packet_exists);
- if (packet_exists)
- packet->serialize(base + ".packet", os);
-
- bool event_scheduled = doneEvent.scheduled();
- paramOut(os, base + ".event_scheduled", event_scheduled);
- if (event_scheduled) {
- Tick event_time = doneEvent.when();
- paramOut(os, base + ".event_time", event_time);
- }
-
-}
-
-void
-EtherLink::Link::unserialize(const string &base, Checkpoint *cp,
- const string &section)
-{
- bool packet_exists;
- paramIn(cp, section, base + ".packet_exists", packet_exists);
- if (packet_exists) {
- packet = new PacketData(16384);
- packet->unserialize(base + ".packet", cp, section);
- }
-
- bool event_scheduled;
- paramIn(cp, section, base + ".event_scheduled", event_scheduled);
- if (event_scheduled) {
- Tick event_time;
- paramIn(cp, section, base + ".event_time", event_time);
- doneEvent.schedule(event_time);
- }
-}
-
-LinkDelayEvent::LinkDelayEvent()
- : Event(&mainEventQueue), link(NULL)
-{
- setFlags(AutoSerialize);
- setFlags(AutoDelete);
-}
-
-LinkDelayEvent::LinkDelayEvent(EtherLink::Link *l, PacketPtr p, Tick when)
- : Event(&mainEventQueue), link(l), packet(p)
-{
- setFlags(AutoSerialize);
- setFlags(AutoDelete);
- schedule(when);
-}
-
-void
-LinkDelayEvent::process()
-{
- link->txComplete(packet);
-}
-
-void
-LinkDelayEvent::serialize(ostream &os)
-{
- paramOut(os, "type", string("LinkDelayEvent"));
- Event::serialize(os);
-
- EtherLink *parent = link->parent;
- bool number = link->number;
- SERIALIZE_OBJPTR(parent);
- SERIALIZE_SCALAR(number);
-
- packet->serialize("packet", os);
-}
-
-
-void
-LinkDelayEvent::unserialize(Checkpoint *cp, const string &section)
-{
- Event::unserialize(cp, section);
-
- EtherLink *parent;
- bool number;
- UNSERIALIZE_OBJPTR(parent);
- UNSERIALIZE_SCALAR(number);
-
- link = parent->link[number];
-
- packet = new PacketData(16384);
- packet->unserialize("packet", cp, section);
-}
-
-
-Serializable *
-LinkDelayEvent::createForUnserialize(Checkpoint *cp, const string &section)
-{
- return new LinkDelayEvent();
-}
-
-REGISTER_SERIALIZEABLE("LinkDelayEvent", LinkDelayEvent)
-
-BEGIN_DECLARE_SIM_OBJECT_PARAMS(EtherLink)
-
- SimObjectParam<EtherInt *> int1;
- SimObjectParam<EtherInt *> int2;
- Param<double> speed;
- Param<Tick> delay;
- Param<Tick> delay_var;
- SimObjectParam<EtherDump *> dump;
-
-END_DECLARE_SIM_OBJECT_PARAMS(EtherLink)
-
-BEGIN_INIT_SIM_OBJECT_PARAMS(EtherLink)
-
- INIT_PARAM(int1, "interface 1"),
- INIT_PARAM(int2, "interface 2"),
- INIT_PARAM(speed, "link speed in bits per second"),
- INIT_PARAM(delay, "transmit delay of packets in us"),
- INIT_PARAM(delay_var, "Difference in amount of time to traverse wire"),
- INIT_PARAM(dump, "object to dump network packets to")
-
-END_INIT_SIM_OBJECT_PARAMS(EtherLink)
-
-CREATE_SIM_OBJECT(EtherLink)
-{
- return new EtherLink(getInstanceName(), int1, int2, speed, delay, delay_var,
- dump);
-}
-
-REGISTER_SIM_OBJECT("EtherLink", EtherLink)
diff --git a/dev/etherlink.hh b/dev/etherlink.hh
deleted file mode 100644
index 305007d9e..000000000
--- a/dev/etherlink.hh
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * 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
- * Device module for modelling a fixed bandwidth full duplex ethernet link
- */
-
-#ifndef __DEV_ETHERLINK_HH__
-#define __DEV_ETHERLINK_HH__
-
-#include "dev/etherint.hh"
-#include "dev/etherpkt.hh"
-#include "sim/eventq.hh"
-#include "sim/host.hh"
-#include "sim/sim_object.hh"
-
-class EtherDump;
-class Checkpoint;
-/*
- * Model for a fixed bandwidth full duplex ethernet link
- */
-class EtherLink : public SimObject
-{
- protected:
- class Interface;
-
- friend class LinkDelayEvent;
- /*
- * Model for a single uni-directional link
- */
- class Link
- {
- protected:
- std::string objName;
-
- EtherLink *parent;
- int number;
-
- Interface *txint;
- Interface *rxint;
-
- double ticksPerByte;
- Tick linkDelay;
- Tick delayVar;
- EtherDump *dump;
-
- protected:
- /*
- * Transfer is complete
- */
- PacketPtr packet;
- void txDone();
- typedef EventWrapper<Link, &Link::txDone> DoneEvent;
- friend void DoneEvent::process();
- DoneEvent doneEvent;
-
- friend class LinkDelayEvent;
- void txComplete(PacketPtr packet);
-
- public:
- Link(const std::string &name, EtherLink *p, int num,
- double rate, Tick delay, Tick delay_var, EtherDump *dump);
- ~Link() {}
-
- const std::string name() const { return objName; }
-
- bool busy() const { return (bool)packet; }
- bool transmit(PacketPtr packet);
-
- void setTxInt(Interface *i) { assert(!txint); txint = i; }
- void setRxInt(Interface *i) { assert(!rxint); rxint = i; }
-
- void serialize(const std::string &base, std::ostream &os);
- void unserialize(const std::string &base, Checkpoint *cp,
- const std::string &section);
- };
-
- /*
- * Interface at each end of the link
- */
- class Interface : public EtherInt
- {
- private:
- Link *txlink;
-
- public:
- Interface(const std::string &name, Link *txlink, Link *rxlink);
- bool recvPacket(PacketPtr packet) { return txlink->transmit(packet); }
- void sendDone() { peer->sendDone(); }
- };
-
- Link *link[2];
- EtherInt *interface[2];
-
- public:
- EtherLink(const std::string &name, EtherInt *peer0, EtherInt *peer1,
- double rate, Tick delay, Tick delayVar, EtherDump *dump);
- virtual ~EtherLink();
-
- virtual void serialize(std::ostream &os);
- virtual void unserialize(Checkpoint *cp, const std::string &section);
-
-};
-
-#endif // __ETHERLINK_HH__
diff --git a/dev/etherpkt.cc b/dev/etherpkt.cc
deleted file mode 100644
index 44dbd7c18..000000000
--- a/dev/etherpkt.cc
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <iostream>
-
-#include "base/misc.hh"
-#include "dev/etherpkt.hh"
-#include "sim/serialize.hh"
-
-using namespace std;
-
-void
-PacketData::serialize(const string &base, ostream &os)
-{
- paramOut(os, base + ".length", length);
- paramOut(os, base + ".slack", slack);
- arrayParamOut(os, base + ".data", data, length);
-}
-
-void
-PacketData::unserialize(const string &base, Checkpoint *cp,
- const string &section)
-{
- paramIn(cp, section, base + ".length", length);
- paramIn(cp, section, base + ".slack", slack);
- if (length)
- arrayParamIn(cp, section, base + ".data", data, length);
-}
diff --git a/dev/etherpkt.hh b/dev/etherpkt.hh
deleted file mode 100644
index cb9022d72..000000000
--- a/dev/etherpkt.hh
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * 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
- * Reference counted class containing ethernet packet data
- */
-
-#ifndef __ETHERPKT_HH__
-#define __ETHERPKT_HH__
-
-#include <iosfwd>
-#include <memory>
-#include <assert.h>
-
-#include "base/refcnt.hh"
-#include "sim/host.hh"
-
-/*
- * Reference counted class containing ethernet packet data
- */
-class Checkpoint;
-class PacketData : public RefCounted
-{
- public:
- /*
- * Pointer to packet data will be deleted
- */
- uint8_t *data;
-
- /*
- * Length of the current packet
- */
- int length;
-
- /*
- * Extra space taken up by the packet in whatever data structure
- * it is in.
- *
- * NOTE: This can only be use by *one* data structure at a time!
- */
- int slack;
-
- public:
- PacketData() : data(NULL), length(0), slack(0) { }
- explicit PacketData(size_t size)
- : data(new uint8_t[size]), length(0), slack(0) { }
- PacketData(std::auto_ptr<uint8_t> d, int l, int s = 0)
- : data(d.release()), length(l), slack(s) { }
- ~PacketData() { if (data) delete [] data; }
-
- public:
- void serialize(const std::string &base, std::ostream &os);
- void unserialize(const std::string &base, Checkpoint *cp,
- const std::string &section);
-};
-
-typedef RefCountingPtr<PacketData> PacketPtr;
-
-#endif // __ETHERPKT_HH__
diff --git a/dev/ethertap.cc b/dev/ethertap.cc
deleted file mode 100644
index 7589991ef..000000000
--- a/dev/ethertap.cc
+++ /dev/null
@@ -1,345 +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.
- */
-
-/* @file
- * Interface to connect a simulated ethernet device to the real world
- */
-
-#if defined(__OpenBSD__) || defined(__APPLE__)
-#include <sys/param.h>
-#endif
-#include <netinet/in.h>
-
-#include <unistd.h>
-
-#include <deque>
-#include <string>
-
-#include "base/misc.hh"
-#include "base/pollevent.hh"
-#include "base/socket.hh"
-#include "base/trace.hh"
-#include "dev/etherdump.hh"
-#include "dev/etherint.hh"
-#include "dev/etherpkt.hh"
-#include "dev/ethertap.hh"
-#include "sim/builder.hh"
-
-using namespace std;
-
-/**
- */
-class TapListener
-{
- protected:
- /**
- */
- class Event : public PollEvent
- {
- protected:
- TapListener *listener;
-
- public:
- Event(TapListener *l, int fd, int e)
- : PollEvent(fd, e), listener(l) {}
-
- virtual void process(int revent) { listener->accept(); }
- };
-
- friend class Event;
- Event *event;
-
- protected:
- ListenSocket listener;
- EtherTap *tap;
- int port;
-
- public:
- TapListener(EtherTap *t, int p)
- : event(NULL), tap(t), port(p) {}
- ~TapListener() { if (event) delete event; }
-
- void accept();
- void listen();
-};
-
-void
-TapListener::listen()
-{
- while (!listener.listen(port, true)) {
- DPRINTF(Ethernet, "TapListener(listen): Can't bind port %d\n", port);
- port++;
- }
-
- ccprintf(cerr, "Listening for tap connection on port %d\n", port);
- event = new Event(this, listener.getfd(), POLLIN|POLLERR);
- pollQueue.schedule(event);
-}
-
-void
-TapListener::accept()
-{
- if (!listener.islistening())
- panic("TapListener(accept): cannot accept if we're not listening!");
-
- int sfd = listener.accept(true);
- if (sfd != -1)
- tap->attach(sfd);
-}
-
-/**
- */
-class TapEvent : public PollEvent
-{
- protected:
- EtherTap *tap;
-
- public:
- TapEvent(EtherTap *_tap, int fd, int e)
- : PollEvent(fd, e), tap(_tap) {}
- virtual void process(int revent) { tap->process(revent); }
-};
-
-EtherTap::EtherTap(const string &name, EtherDump *d, int port, int bufsz)
- : EtherInt(name), event(NULL), socket(-1), buflen(bufsz), dump(d),
- txEvent(this)
-{
- buffer = new char[buflen];
- listener = new TapListener(this, port);
- listener->listen();
-}
-
-EtherTap::~EtherTap()
-{
- if (event)
- delete event;
- if (buffer)
- delete [] buffer;
-
- delete listener;
-}
-
-void
-EtherTap::attach(int fd)
-{
- if (socket != -1)
- close(fd);
-
- buffer_offset = 0;
- data_len = 0;
- socket = fd;
- DPRINTF(Ethernet, "EtherTap attached\n");
- event = new TapEvent(this, socket, POLLIN|POLLERR);
- pollQueue.schedule(event);
-}
-
-void
-EtherTap::detach()
-{
- DPRINTF(Ethernet, "EtherTap detached\n");
- delete event;
- event = 0;
- close(socket);
- socket = -1;
-}
-
-bool
-EtherTap::recvPacket(PacketPtr packet)
-{
- if (dump)
- dump->dump(packet);
-
- DPRINTF(Ethernet, "EtherTap output len=%d\n", packet->length);
- DDUMP(EthernetData, packet->data, packet->length);
- u_int32_t len = htonl(packet->length);
- write(socket, &len, sizeof(len));
- write(socket, packet->data, packet->length);
-
- recvDone();
-
- return true;
-}
-
-void
-EtherTap::sendDone()
-{}
-
-void
-EtherTap::process(int revent)
-{
- if (revent & POLLERR) {
- detach();
- return;
- }
-
- char *data = buffer + sizeof(u_int32_t);
- if (!(revent & POLLIN))
- return;
-
- if (buffer_offset < data_len + sizeof(u_int32_t)) {
- int len = read(socket, buffer + buffer_offset, buflen - buffer_offset);
- if (len == 0) {
- detach();
- return;
- }
-
- buffer_offset += len;
-
- if (data_len == 0)
- data_len = ntohl(*(u_int32_t *)buffer);
-
- DPRINTF(Ethernet, "Received data from peer: len=%d buffer_offset=%d "
- "data_len=%d\n", len, buffer_offset, data_len);
- }
-
- while (data_len != 0 && buffer_offset >= data_len + sizeof(u_int32_t)) {
- PacketPtr packet;
- packet = new PacketData(data_len);
- packet->length = data_len;
- memcpy(packet->data, data, data_len);
-
- buffer_offset -= data_len + sizeof(u_int32_t);
- assert(buffer_offset >= 0);
- if (buffer_offset > 0) {
- memmove(buffer, data + data_len, buffer_offset);
- data_len = ntohl(*(u_int32_t *)buffer);
- } else
- data_len = 0;
-
- DPRINTF(Ethernet, "EtherTap input len=%d\n", packet->length);
- DDUMP(EthernetData, packet->data, packet->length);
- if (!sendPacket(packet)) {
- DPRINTF(Ethernet, "bus busy...buffer for retransmission\n");
- packetBuffer.push(packet);
- if (!txEvent.scheduled())
- txEvent.schedule(curTick + retryTime);
- } else if (dump) {
- dump->dump(packet);
- }
- }
-}
-
-void
-EtherTap::retransmit()
-{
- if (packetBuffer.empty())
- return;
-
- PacketPtr packet = packetBuffer.front();
- if (sendPacket(packet)) {
- if (dump)
- dump->dump(packet);
- DPRINTF(Ethernet, "EtherTap retransmit\n");
- packetBuffer.front() = NULL;
- packetBuffer.pop();
- }
-
- if (!packetBuffer.empty() && !txEvent.scheduled())
- txEvent.schedule(curTick + retryTime);
-}
-
-//=====================================================================
-
-void
-EtherTap::serialize(ostream &os)
-{
- SERIALIZE_SCALAR(socket);
- SERIALIZE_SCALAR(buflen);
- uint8_t *buffer = (uint8_t *)this->buffer;
- SERIALIZE_ARRAY(buffer, buflen);
- SERIALIZE_SCALAR(buffer_offset);
- SERIALIZE_SCALAR(data_len);
-
- bool tapevent_present = false;
- if (event) {
- tapevent_present = true;
- SERIALIZE_SCALAR(tapevent_present);
- event->serialize(os);
- }
- else {
- SERIALIZE_SCALAR(tapevent_present);
- }
-}
-
-void
-EtherTap::unserialize(Checkpoint *cp, const std::string &section)
-{
- UNSERIALIZE_SCALAR(socket);
- UNSERIALIZE_SCALAR(buflen);
- uint8_t *buffer = (uint8_t *)this->buffer;
- UNSERIALIZE_ARRAY(buffer, buflen);
- UNSERIALIZE_SCALAR(buffer_offset);
- UNSERIALIZE_SCALAR(data_len);
-
- bool tapevent_present;
- UNSERIALIZE_SCALAR(tapevent_present);
- if (tapevent_present) {
- event = new TapEvent(this, socket, POLLIN|POLLERR);
-
- event->unserialize(cp,section);
-
- if (event->queued()) {
- pollQueue.schedule(event);
- }
- }
-}
-
-//=====================================================================
-
-BEGIN_DECLARE_SIM_OBJECT_PARAMS(EtherTap)
-
- SimObjectParam<EtherInt *> peer;
- SimObjectParam<EtherDump *> dump;
- Param<unsigned> port;
- Param<unsigned> bufsz;
-
-END_DECLARE_SIM_OBJECT_PARAMS(EtherTap)
-
-BEGIN_INIT_SIM_OBJECT_PARAMS(EtherTap)
-
- INIT_PARAM_DFLT(peer, "peer interface", NULL),
- INIT_PARAM_DFLT(dump, "object to dump network packets to", NULL),
- INIT_PARAM_DFLT(port, "tap port", 3500),
- INIT_PARAM_DFLT(bufsz, "tap buffer size", 10000)
-
-END_INIT_SIM_OBJECT_PARAMS(EtherTap)
-
-
-CREATE_SIM_OBJECT(EtherTap)
-{
- EtherTap *tap = new EtherTap(getInstanceName(), dump, port, bufsz);
-
- if (peer) {
- tap->setPeer(peer);
- peer->setPeer(tap);
- }
-
- return tap;
-}
-
-REGISTER_SIM_OBJECT("EtherTap", EtherTap)
diff --git a/dev/ethertap.hh b/dev/ethertap.hh
deleted file mode 100644
index 069ba734f..000000000
--- a/dev/ethertap.hh
+++ /dev/null
@@ -1,107 +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.
- */
-
-/* @file
- * Interface to connect a simulated ethernet device to the real world
- */
-
-#ifndef __ETHERTAP_HH__
-#define __ETHERTAP_HH__
-
-#include <queue>
-#include <string>
-
-#include "dev/etherint.hh"
-#include "dev/etherpkt.hh"
-#include "sim/eventq.hh"
-#include "base/pollevent.hh"
-#include "sim/sim_object.hh"
-
-class TapEvent;
-class TapListener;
-
-/*
- * Interface to connect a simulated ethernet device to the real world
- */
-class EtherTap : public EtherInt
-{
- protected:
- friend class TapEvent;
- TapEvent *event;
-
- protected:
- friend class TapListener;
- TapListener *listener;
- int socket;
- char *buffer;
- int buflen;
- int32_t buffer_offset;
- int32_t data_len;
-
- EtherDump *dump;
-
- void attach(int fd);
- void detach();
-
- protected:
- std::string device;
- std::queue<PacketPtr> packetBuffer;
-
- void process(int revent);
- void enqueue(PacketData *packet);
- void retransmit();
-
- /*
- */
- class TxEvent : public Event
- {
- protected:
- EtherTap *tap;
-
- public:
- TxEvent(EtherTap *_tap)
- : Event(&mainEventQueue), tap(_tap) {}
- void process() { tap->retransmit(); }
- virtual const char *description() { return "retransmit event"; }
- };
-
- friend class TxEvent;
- TxEvent txEvent;
-
- public:
- EtherTap(const std::string &name, EtherDump *dump, int port, int bufsz);
- virtual ~EtherTap();
-
- virtual bool recvPacket(PacketPtr packet);
- virtual void sendDone();
-
- virtual void serialize(std::ostream &os);
- virtual void unserialize(Checkpoint *cp, const std::string &section);
-};
-
-#endif // __ETHERTAP_HH__
diff --git a/dev/ide_ctrl.cc b/dev/ide_ctrl.cc
deleted file mode 100644
index 05c756f04..000000000
--- a/dev/ide_ctrl.cc
+++ /dev/null
@@ -1,813 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <cstddef>
-#include <cstdlib>
-#include <string>
-#include <vector>
-
-#include "base/trace.hh"
-#include "cpu/intr_control.hh"
-#include "dev/ide_ctrl.hh"
-#include "dev/ide_disk.hh"
-#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 "sim/builder.hh"
-#include "sim/sim_object.hh"
-
-using namespace std;
-using namespace TheISA;
-
-////
-// Initialization and destruction
-////
-
-IdeController::IdeController(Params *p)
- : PciDev(p)
-{
- // initialize the PIO interface addresses
- pri_cmd_addr = 0;
- pri_cmd_size = BARSize[0];
-
- pri_ctrl_addr = 0;
- pri_ctrl_size = BARSize[1];
-
- sec_cmd_addr = 0;
- sec_cmd_size = BARSize[2];
-
- sec_ctrl_addr = 0;
- sec_ctrl_size = BARSize[3];
-
- // initialize the bus master interface (BMI) address to be configured
- // via PCI
- bmi_addr = 0;
- bmi_size = BARSize[4];
-
- // zero out all of the registers
- memset(bmi_regs.data, 0, sizeof(bmi_regs));
- memset(config_regs.data, 0, sizeof(config_regs.data));
-
- // setup initial values
- // enable both channels
- config_regs.idetim0 = htole((uint16_t)IDETIM_DECODE_EN);
- config_regs.idetim1 = htole((uint16_t)IDETIM_DECODE_EN);
- bmi_regs.bmis0 = DMA1CAP | DMA0CAP;
- bmi_regs.bmis1 = DMA1CAP | DMA0CAP;
-
- // reset all internal variables
- io_enabled = false;
- 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;
- dev[1] = 0;
-
- if (params()->disks.size() > 3)
- panic("IDE controllers support a maximum of 4 devices attached!\n");
-
- for (int i = 0; i < params()->disks.size(); i++) {
- disks[i] = params()->disks[i];
- disks[i]->setController(this, dmaInterface);
- }
-}
-
-IdeController::~IdeController()
-{
- for (int i = 0; i < 4; i++)
- if (disks[i])
- delete disks[i];
-}
-
-////
-// Utility functions
-///
-
-void
-IdeController::parseAddr(const Addr &addr, Addr &offset, IdeChannel &channel,
- IdeRegType &reg_type)
-{
- offset = addr;
-
- if (addr >= pri_cmd_addr && addr < (pri_cmd_addr + pri_cmd_size)) {
- offset -= pri_cmd_addr;
- reg_type = COMMAND_BLOCK;
- channel = PRIMARY;
- } else if (addr >= pri_ctrl_addr &&
- addr < (pri_ctrl_addr + pri_ctrl_size)) {
- offset -= pri_ctrl_addr;
- reg_type = CONTROL_BLOCK;
- channel = PRIMARY;
- } else if (addr >= sec_cmd_addr &&
- addr < (sec_cmd_addr + sec_cmd_size)) {
- offset -= sec_cmd_addr;
- reg_type = COMMAND_BLOCK;
- channel = SECONDARY;
- } else if (addr >= sec_ctrl_addr &&
- addr < (sec_ctrl_addr + sec_ctrl_size)) {
- offset -= sec_ctrl_addr;
- reg_type = CONTROL_BLOCK;
- channel = SECONDARY;
- } else if (addr >= bmi_addr && addr < (bmi_addr + bmi_size)) {
- offset -= bmi_addr;
- reg_type = BMI_BLOCK;
- channel = (offset < BMIC1) ? PRIMARY : SECONDARY;
- } else {
- panic("IDE controller access to invalid address: %#x\n", addr);
- }
-}
-
-int
-IdeController::getDisk(IdeChannel channel)
-{
- int disk = 0;
- uint8_t *devBit = &dev[0];
-
- if (channel == SECONDARY) {
- disk += 2;
- devBit = &dev[1];
- }
-
- disk += *devBit;
-
- assert(*devBit == 0 || *devBit == 1);
-
- return disk;
-}
-
-int
-IdeController::getDisk(IdeDisk *diskPtr)
-{
- for (int i = 0; i < 4; i++) {
- if ((long)diskPtr == (long)disks[i])
- return i;
- }
- return -1;
-}
-
-bool
-IdeController::isDiskSelected(IdeDisk *diskPtr)
-{
- for (int i = 0; i < 4; i++) {
- if ((long)diskPtr == (long)disks[i]) {
- // is disk is on primary or secondary channel
- int channel = i/2;
- // is disk the master or slave
- int devID = i%2;
-
- return (dev[channel] == devID);
- }
- }
- panic("Unable to find disk by pointer!!\n");
-}
-
-////
-// Command completion
-////
-
-void
-IdeController::setDmaComplete(IdeDisk *disk)
-{
- int diskNum = getDisk(disk);
-
- if (diskNum < 0)
- panic("Unable to find disk based on pointer %#x\n", disk);
-
- if (diskNum < 2) {
- // clear the start/stop bit in the command register
- bmi_regs.bmic0 &= ~SSBM;
- // clear the bus master active bit in the status register
- bmi_regs.bmis0 &= ~BMIDEA;
- // set the interrupt bit
- bmi_regs.bmis0 |= IDEINTS;
- } else {
- // clear the start/stop bit in the command register
- bmi_regs.bmic1 &= ~SSBM;
- // clear the bus master active bit in the status register
- bmi_regs.bmis1 &= ~BMIDEA;
- // set the interrupt bit
- bmi_regs.bmis1 |= IDEINTS;
- }
-}
-
-////
-// 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)
-{
- int config_offset;
-
- if (offset < PCI_DEVICE_SPECIFIC) {
- PciDev::readConfig(offset, size, data);
- } else if (offset >= IDE_CTRL_CONF_START &&
- (offset + size) <= IDE_CTRL_CONF_END) {
-
- config_offset = offset - IDE_CTRL_CONF_START;
-
- switch (size) {
- case sizeof(uint8_t):
- *data = config_regs.data[config_offset];
- break;
- case sizeof(uint16_t):
- *(uint16_t*)data = *(uint16_t*)&config_regs.data[config_offset];
- break;
- case sizeof(uint32_t):
- *(uint32_t*)data = *(uint32_t*)&config_regs.data[config_offset];
- break;
- default:
- panic("Invalid PCI configuration read size!\n");
- }
-
-
-
- } 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);
- break;
- case sizeof(uint16_t):
- DPRINTF(IdeCtrl, "PCI read offset: %#x size: %d data: %#x\n",
- offset, size, *(uint16_t*)data);
- break;
- case sizeof(uint32_t):
- DPRINTF(IdeCtrl, "PCI read offset: %#x size: %d data: %#x\n",
- offset, size, *(uint32_t*)data);
- break;
- default:
- panic("Invalid PCI configuration read size!\n");
- }
-
-}
-
-void
-IdeController::writeConfig(int offset, int size, const uint8_t *data)
-{
- int config_offset;
-
- if (offset < PCI_DEVICE_SPECIFIC) {
- PciDev::writeConfig(offset, size, data);
- } else if (offset >= IDE_CTRL_CONF_START &&
- (offset + size) <= IDE_CTRL_CONF_END) {
-
- config_offset = offset - IDE_CTRL_CONF_START;
-
- switch(size) {
- case sizeof(uint8_t):
- config_regs.data[config_offset] = *data;
- break;
- case sizeof(uint16_t):
- *(uint16_t*)&config_regs.data[config_offset] = *(uint16_t*)data;
- break;
- case sizeof(uint32_t):
- *(uint32_t*)&config_regs.data[config_offset] = *(uint32_t*)data;
- break;
- default:
- panic("Invalid PCI configuration write size!\n");
- }
- } else {
- panic("Write of unimplemented PCI config. register: %x\n", offset);
- }
-
- switch(size) {
- case sizeof(uint8_t):
- DPRINTF(IdeCtrl, "PCI write offset: %#x size: %d data: %#x\n",
- offset, size, (uint32_t)*data);
- break;
- case sizeof(uint16_t):
- DPRINTF(IdeCtrl, "PCI write offset: %#x size: %d data: %#x\n",
- offset, size, *(uint16_t*)data);
- break;
- case sizeof(uint32_t):
- DPRINTF(IdeCtrl, "PCI write offset: %#x size: %d data: %#x\n",
- offset, size, *(uint32_t*)data);
- break;
- default:
- panic("Invalid PCI configuration write size!\n");
- }
-
- // Catch the writes to specific PCI registers that have side affects
- // (like updating the PIO ranges)
- switch (offset) {
- case PCI_COMMAND:
- if (letoh(config.command) & PCI_CMD_IOSE)
- io_enabled = true;
- else
- io_enabled = false;
-
- if (letoh(config.command) & PCI_CMD_BME)
- bm_enabled = true;
- else
- bm_enabled = false;
- break;
-
- case PCI0_BASE_ADDR0:
- 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) {
- 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) {
- 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) {
- 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) {
- 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)
-{
- Addr offset;
- IdeChannel channel;
- IdeRegType reg_type;
- int disk;
-
- parseAddr(req->paddr, offset, channel, reg_type);
-
- if (!io_enabled)
- return NoFault;
-
- switch (reg_type) {
- case BMI_BLOCK:
- switch (req->size) {
- case sizeof(uint8_t):
- *data = bmi_regs.data[offset];
- break;
- case sizeof(uint16_t):
- *(uint16_t*)data = *(uint16_t*)&bmi_regs.data[offset];
- break;
- case sizeof(uint32_t):
- *(uint32_t*)data = *(uint32_t*)&bmi_regs.data[offset];
- break;
- default:
- panic("IDE read of BMI reg invalid size: %#x\n", req->size);
- }
- break;
-
- case COMMAND_BLOCK:
- case CONTROL_BLOCK:
- disk = getDisk(channel);
-
- if (disks[disk] == NULL)
- break;
-
- switch (offset) {
- case DATA_OFFSET:
- switch (req->size) {
- case sizeof(uint16_t):
- disks[disk]->read(offset, reg_type, data);
- break;
-
- case sizeof(uint32_t):
- disks[disk]->read(offset, reg_type, data);
- disks[disk]->read(offset, reg_type, &data[2]);
- break;
-
- default:
- panic("IDE read of data reg invalid size: %#x\n", req->size);
- }
- break;
- default:
- if (req->size == sizeof(uint8_t)) {
- disks[disk]->read(offset, reg_type, data);
- } else
- panic("IDE read of command reg of invalid size: %#x\n", req->size);
- }
- break;
- default:
- panic("IDE controller read of unknown register block type!\n");
- }
-
- if (req->size == 1)
- DPRINTF(IdeCtrl, "read from offset: %#x size: %#x data: %#x\n",
- offset, req->size, (uint32_t)*data);
- else if (req->size == 2)
- DPRINTF(IdeCtrl, "read from offset: %#x size: %#x data: %#x\n",
- offset, req->size, *(uint16_t*)data);
- else
- DPRINTF(IdeCtrl, "read from offset: %#x size: %#x data: %#x\n",
- offset, req->size, *(uint32_t*)data);
-
- return NoFault;
-}
-
-Fault
-IdeController::write(MemReqPtr &req, const uint8_t *data)
-{
- Addr offset;
- IdeChannel channel;
- IdeRegType reg_type;
- int disk;
- uint8_t oldVal, newVal;
-
- parseAddr(req->paddr, offset, channel, reg_type);
-
- if (!io_enabled)
- return NoFault;
-
- switch (reg_type) {
- case BMI_BLOCK:
- if (!bm_enabled)
- return NoFault;
-
- 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);
-
- // select the current disk based on DEV bit
- disk = getDisk(channel);
-
- oldVal = bmi_regs.chan[channel].bmic;
- newVal = *data;
-
- // if a DMA transfer is in progress, R/W control cannot change
- if (oldVal & SSBM) {
- if ((oldVal & RWCON) ^ (newVal & RWCON)) {
- (oldVal & RWCON) ? newVal |= RWCON : newVal &= ~RWCON;
- }
- }
-
- // see if the start/stop bit is being changed
- if ((oldVal & SSBM) ^ (newVal & SSBM)) {
- if (oldVal & SSBM) {
- // stopping DMA transfer
- DPRINTF(IdeCtrl, "Stopping DMA transfer\n");
-
- // clear the BMIDEA bit
- bmi_regs.chan[channel].bmis =
- bmi_regs.chan[channel].bmis & ~BMIDEA;
-
- if (disks[disk] == NULL)
- panic("DMA stop for disk %d which does not exist\n",
- disk);
-
- // inform the disk of the DMA transfer abort
- disks[disk]->abortDma();
- } else {
- // starting DMA transfer
- DPRINTF(IdeCtrl, "Starting DMA transfer\n");
-
- // set the BMIDEA bit
- bmi_regs.chan[channel].bmis =
- bmi_regs.chan[channel].bmis | BMIDEA;
-
- if (disks[disk] == NULL)
- panic("DMA start for disk %d which does not exist\n",
- disk);
-
- // inform the disk of the DMA transfer start
- disks[disk]->startDma(letoh(bmi_regs.chan[channel].bmidtp));
- }
- }
-
- // update the register value
- bmi_regs.chan[channel].bmic = newVal;
- break;
-
- // Bus master IDE status register
- case BMIS0:
- case BMIS1:
- if (req->size != sizeof(uint8_t))
- panic("Invalid BMIS write size: %x\n", req->size);
-
- oldVal = bmi_regs.chan[channel].bmis;
- newVal = *data;
-
- // the BMIDEA bit is RO
- newVal |= (oldVal & BMIDEA);
-
- // to reset (set 0) IDEINTS and IDEDMAE, write 1 to each
- if ((oldVal & IDEINTS) && (newVal & IDEINTS))
- newVal &= ~IDEINTS; // clear the interrupt?
- else
- (oldVal & IDEINTS) ? newVal |= IDEINTS : newVal &= ~IDEINTS;
-
- if ((oldVal & IDEDMAE) && (newVal & IDEDMAE))
- newVal &= ~IDEDMAE;
- else
- (oldVal & IDEDMAE) ? newVal |= IDEDMAE : newVal &= ~IDEDMAE;
-
- bmi_regs.chan[channel].bmis = newVal;
- break;
-
- // Bus master IDE descriptor table pointer register
- case BMIDTP0:
- case BMIDTP1:
- {
- if (req->size != sizeof(uint32_t))
- panic("Invalid BMIDTP write size: %x\n", req->size);
-
- uint32_t host_data = letoh(*(uint32_t*)data);
- host_data &= ~0x3;
- bmi_regs.chan[channel].bmidtp = htole(host_data);
- }
- break;
-
- default:
- if (req->size != sizeof(uint8_t) &&
- req->size != sizeof(uint16_t) &&
- req->size != sizeof(uint32_t))
- panic("IDE controller write of invalid write size: %x\n",
- req->size);
-
- // do a default copy of data into the registers
- memcpy(&bmi_regs.data[offset], data, req->size);
- }
- break;
- case COMMAND_BLOCK:
- if (offset == IDE_SELECT_OFFSET) {
- uint8_t *devBit = &dev[channel];
- *devBit = (letoh(*data) & IDE_SELECT_DEV_BIT) ? 1 : 0;
- }
- // fall-through ok!
- case CONTROL_BLOCK:
- disk = getDisk(channel);
-
- if (disks[disk] == NULL)
- break;
-
- switch (offset) {
- case DATA_OFFSET:
- switch (req->size) {
- case sizeof(uint16_t):
- disks[disk]->write(offset, reg_type, data);
- break;
-
- case sizeof(uint32_t):
- disks[disk]->write(offset, reg_type, data);
- disks[disk]->write(offset, reg_type, &data[2]);
- break;
- default:
- panic("IDE write of data reg invalid size: %#x\n", req->size);
- }
- break;
- default:
- if (req->size == sizeof(uint8_t)) {
- disks[disk]->write(offset, reg_type, data);
- } else
- panic("IDE write of command reg of invalid size: %#x\n", req->size);
- }
- break;
- default:
- panic("IDE controller write of unknown register block type!\n");
- }
- if (req->size == 1)
- DPRINTF(IdeCtrl, "write to offset: %#x size: %#x data: %#x\n",
- offset, req->size, (uint32_t)*data);
- else if (req->size == 2)
- DPRINTF(IdeCtrl, "write to offset: %#x size: %#x data: %#x\n",
- offset, req->size, *(uint16_t*)data);
- else
- DPRINTF(IdeCtrl, "write to offset: %#x size: %#x data: %#x\n",
- offset, req->size, *(uint32_t*)data);
-
- return NoFault;
-}
-
-////
-// Serialization
-////
-
-void
-IdeController::serialize(std::ostream &os)
-{
- // Serialize the PciDev base class
- PciDev::serialize(os);
-
- // Serialize register addresses and sizes
- SERIALIZE_SCALAR(pri_cmd_addr);
- SERIALIZE_SCALAR(pri_cmd_size);
- SERIALIZE_SCALAR(pri_ctrl_addr);
- SERIALIZE_SCALAR(pri_ctrl_size);
- SERIALIZE_SCALAR(sec_cmd_addr);
- SERIALIZE_SCALAR(sec_cmd_size);
- SERIALIZE_SCALAR(sec_ctrl_addr);
- SERIALIZE_SCALAR(sec_ctrl_size);
- SERIALIZE_SCALAR(bmi_addr);
- SERIALIZE_SCALAR(bmi_size);
-
- // Serialize registers
- SERIALIZE_ARRAY(bmi_regs.data,
- sizeof(bmi_regs.data) / sizeof(bmi_regs.data[0]));
- SERIALIZE_ARRAY(dev, sizeof(dev) / sizeof(dev[0]));
- SERIALIZE_ARRAY(config_regs.data,
- sizeof(config_regs.data) / sizeof(config_regs.data[0]));
-
- // Serialize internal state
- SERIALIZE_SCALAR(io_enabled);
- SERIALIZE_SCALAR(bm_enabled);
- SERIALIZE_ARRAY(cmd_in_progress,
- sizeof(cmd_in_progress) / sizeof(cmd_in_progress[0]));
-}
-
-void
-IdeController::unserialize(Checkpoint *cp, const std::string &section)
-{
- // Unserialize the PciDev base class
- PciDev::unserialize(cp, section);
-
- // Unserialize register addresses and sizes
- UNSERIALIZE_SCALAR(pri_cmd_addr);
- UNSERIALIZE_SCALAR(pri_cmd_size);
- UNSERIALIZE_SCALAR(pri_ctrl_addr);
- UNSERIALIZE_SCALAR(pri_ctrl_size);
- UNSERIALIZE_SCALAR(sec_cmd_addr);
- UNSERIALIZE_SCALAR(sec_cmd_size);
- UNSERIALIZE_SCALAR(sec_ctrl_addr);
- UNSERIALIZE_SCALAR(sec_ctrl_size);
- UNSERIALIZE_SCALAR(bmi_addr);
- UNSERIALIZE_SCALAR(bmi_size);
-
- // Unserialize registers
- UNSERIALIZE_ARRAY(bmi_regs.data,
- sizeof(bmi_regs.data) / sizeof(bmi_regs.data[0]));
- UNSERIALIZE_ARRAY(dev, sizeof(dev) / sizeof(dev[0]));
- UNSERIALIZE_ARRAY(config_regs.data,
- sizeof(config_regs.data) / sizeof(config_regs.data[0]));
-
- // Unserialize internal state
- UNSERIALIZE_SCALAR(io_enabled);
- 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));
- }
-}
-
-#ifndef DOXYGEN_SHOULD_SKIP_THIS
-
-BEGIN_DECLARE_SIM_OBJECT_PARAMS(IdeController)
-
- Param<Addr> addr;
- SimObjectVectorParam<IdeDisk *> disks;
- SimObjectParam<MemoryController *> mmu;
- 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;
-
-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(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)
-
-END_INIT_SIM_OBJECT_PARAMS(IdeController)
-
-CREATE_SIM_OBJECT(IdeController)
-{
- IdeController::Params *params = new IdeController::Params;
- params->name = getInstanceName();
- params->mmu = mmu;
- params->configSpace = configspace;
- params->configData = configdata;
- params->plat = platform;
- params->busNum = pci_bus;
- params->deviceNum = pci_dev;
- params->functionNum = pci_func;
-
- 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);
-}
-
-REGISTER_SIM_OBJECT("IdeController", IdeController)
-
-#endif //DOXYGEN_SHOULD_SKIP_THIS
diff --git a/dev/ide_ctrl.hh b/dev/ide_ctrl.hh
deleted file mode 100644
index 0fbaf9207..000000000
--- a/dev/ide_ctrl.hh
+++ /dev/null
@@ -1,246 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @file
- * Simple PCI IDE controller with bus mastering capability and UDMA
- * modeled after controller in the Intel PIIX4 chip
- */
-
-#ifndef __IDE_CTRL_HH__
-#define __IDE_CTRL_HH__
-
-#include "dev/pcidev.hh"
-#include "dev/pcireg.h"
-#include "dev/io_device.hh"
-
-#define BMIC0 0x0 // Bus master IDE command register
-#define BMIS0 0x2 // Bus master IDE status register
-#define BMIDTP0 0x4 // Bus master IDE descriptor table pointer register
-#define BMIC1 0x8 // Bus master IDE command register
-#define BMIS1 0xa // Bus master IDE status register
-#define BMIDTP1 0xc // Bus master IDE descriptor table pointer register
-
-// Bus master IDE command register bit fields
-#define RWCON 0x08 // Bus master read/write control
-#define SSBM 0x01 // Start/stop bus master
-
-// Bus master IDE status register bit fields
-#define DMA1CAP 0x40 // Drive 1 DMA capable
-#define DMA0CAP 0x20 // Drive 0 DMA capable
-#define IDEINTS 0x04 // IDE Interrupt Status
-#define IDEDMAE 0x02 // IDE DMA error
-#define BMIDEA 0x01 // Bus master IDE active
-
-// IDE Command byte fields
-#define IDE_SELECT_OFFSET (6)
-#define IDE_SELECT_DEV_BIT 0x10
-
-#define IDE_FEATURE_OFFSET IDE_ERROR_OFFSET
-#define IDE_COMMAND_OFFSET IDE_STATUS_OFFSET
-
-// IDE Timing Register bit fields
-#define IDETIM_DECODE_EN 0x8000
-
-// PCI device specific register byte offsets
-#define IDE_CTRL_CONF_START 0x40
-#define IDE_CTRL_CONF_END ((IDE_CTRL_CONF_START) + sizeof(config_regs))
-
-
-enum IdeRegType {
- COMMAND_BLOCK,
- CONTROL_BLOCK,
- BMI_BLOCK
-};
-
-class BaseInterface;
-class Bus;
-class HierParams;
-class IdeDisk;
-class IntrControl;
-class PciConfigAll;
-class PhysicalMemory;
-class Platform;
-
-/**
- * Device model for an Intel PIIX4 IDE controller
- */
-
-class IdeController : public PciDev
-{
- friend class IdeDisk;
-
- enum IdeChannel {
- PRIMARY = 0,
- SECONDARY = 1
- };
-
- private:
- /** Primary command block registers */
- Addr pri_cmd_addr;
- Addr pri_cmd_size;
- /** Primary control block registers */
- Addr pri_ctrl_addr;
- Addr pri_ctrl_size;
- /** Secondary command block registers */
- Addr sec_cmd_addr;
- Addr sec_cmd_size;
- /** Secondary control block registers */
- Addr sec_ctrl_addr;
- Addr sec_ctrl_size;
- /** Bus master interface (BMI) registers */
- Addr bmi_addr;
- Addr bmi_size;
-
- private:
- /** Registers used for bus master interface */
- union {
- uint8_t data[16];
-
- struct {
- uint8_t bmic0;
- uint8_t reserved_0;
- uint8_t bmis0;
- uint8_t reserved_1;
- uint32_t bmidtp0;
- uint8_t bmic1;
- uint8_t reserved_2;
- uint8_t bmis1;
- uint8_t reserved_3;
- uint32_t bmidtp1;
- };
-
- struct {
- uint8_t bmic;
- uint8_t reserved_4;
- uint8_t bmis;
- uint8_t reserved_5;
- uint32_t bmidtp;
- } chan[2];
-
- } bmi_regs;
- /** Shadows of the device select bit */
- uint8_t dev[2];
- /** Registers used in device specific PCI configuration */
- union {
- uint8_t data[22];
-
- struct {
- uint16_t idetim0;
- uint16_t idetim1;
- uint8_t sidetim;
- uint8_t reserved_0[3];
- uint8_t udmactl;
- uint8_t reserved_1;
- uint16_t udmatim;
- uint8_t reserved_2[8];
- uint16_t ideconfig;
- };
- } config_regs;
-
- // Internal management variables
- bool io_enabled;
- bool bm_enabled;
- bool cmd_in_progress[4];
-
- private:
- /** IDE disks connected to controller */
- IdeDisk *disks[4];
-
- private:
- /** Parse the access address to pass on to device */
- void parseAddr(const Addr &addr, Addr &offset, IdeChannel &channel,
- IdeRegType &reg_type);
-
- /** Select the disk based on the channel and device bit */
- int getDisk(IdeChannel channel);
-
- /** Select the disk based on a pointer */
- int getDisk(IdeDisk *diskPtr);
-
- public:
- /** See if a disk is selected based on its pointer */
- bool isDiskSelected(IdeDisk *diskPtr);
-
- public:
- struct Params : public PciDev::Params
- {
- /** 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; }
-
- public:
- 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);
-
- 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.
- */
- virtual Fault read(MemReqPtr &req, uint8_t *data);
-
- /**
- * 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.
- */
- virtual Fault write(MemReqPtr &req, const uint8_t *data);
-
- /**
- * Serialize this object to the given output stream.
- * @param os The stream to serialize to.
- */
- virtual void serialize(std::ostream &os);
-
- /**
- * Reconstruct the state of this object from a checkpoint.
- * @param cp The checkpoint use.
- * @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 // __IDE_CTRL_HH_
diff --git a/dev/ide_disk.cc b/dev/ide_disk.cc
deleted file mode 100644
index c13556ed6..000000000
--- a/dev/ide_disk.cc
+++ /dev/null
@@ -1,1286 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @file
- * Device model implementation for an IDE disk
- */
-
-#include <cerrno>
-#include <cstring>
-#include <deque>
-#include <string>
-
-#include "base/cprintf.hh" // csprintf
-#include "base/trace.hh"
-#include "dev/disk_image.hh"
-#include "dev/ide_disk.hh"
-#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"
-#include "arch/isa_traits.hh"
-
-using namespace std;
-using namespace TheISA;
-
-IdeDisk::IdeDisk(const string &name, DiskImage *img, PhysicalMemory *phys,
- int id, Tick delay)
- : SimObject(name), ctrl(NULL), image(img), physmem(phys), diskDelay(delay),
- dmaTransferEvent(this), dmaReadWaitEvent(this),
- dmaWriteWaitEvent(this), dmaPrdReadEvent(this),
- dmaReadEvent(this), dmaWriteEvent(this)
-{
- // Reset the device state
- reset(id);
-
- // fill out the drive ID structure
- memset(&driveID, 0, sizeof(struct ataparams));
-
- // Calculate LBA and C/H/S values
- uint16_t cylinders;
- uint8_t heads;
- uint8_t sectors;
-
- uint32_t lba_size = image->size();
- if (lba_size >= 16383*16*63) {
- cylinders = 16383;
- heads = 16;
- sectors = 63;
- } else {
- if (lba_size >= 63)
- sectors = 63;
- else
- sectors = lba_size;
-
- if ((lba_size / sectors) >= 16)
- heads = 16;
- else
- heads = (lba_size / sectors);
-
- cylinders = lba_size / (heads * sectors);
- }
-
- // Setup the model name
- strncpy((char *)driveID.atap_model, "5MI EDD si k",
- sizeof(driveID.atap_model));
- // Set the maximum multisector transfer size
- driveID.atap_multi = MAX_MULTSECT;
- // IORDY supported, IORDY disabled, LBA enabled, DMA enabled
- driveID.atap_capabilities1 = 0x7;
- // UDMA support, EIDE support
- driveID.atap_extensions = 0x6;
- // Setup default C/H/S settings
- driveID.atap_cylinders = cylinders;
- driveID.atap_sectors = sectors;
- driveID.atap_heads = heads;
- // Setup the current multisector transfer size
- driveID.atap_curmulti = MAX_MULTSECT;
- driveID.atap_curmulti_valid = 0x1;
- // Number of sectors on disk
- driveID.atap_capacity = lba_size;
- // Multiword DMA mode 2 and below supported
- driveID.atap_dmamode_supp = 0x400;
- // Set PIO mode 4 and 3 supported
- driveID.atap_piomode_supp = 0x3;
- // Set DMA mode 4 and below supported
- driveID.atap_udmamode_supp = 0x1f;
- // Statically set hardware config word
- driveID.atap_hwreset_res = 0x4001;
-
- //arbitrary for now...
- driveID.atap_ata_major = WDC_VER_ATA7;
-}
-
-IdeDisk::~IdeDisk()
-{
- // destroy the data buffer
- delete [] dataBuffer;
-}
-
-void
-IdeDisk::reset(int id)
-{
- // initialize the data buffer and shadow registers
- dataBuffer = new uint8_t[MAX_DMA_SIZE];
-
- memset(dataBuffer, 0, MAX_DMA_SIZE);
- memset(&cmdReg, 0, sizeof(CommandReg_t));
- memset(&curPrd.entry, 0, sizeof(PrdEntry_t));
-
- dmaInterfaceBytes = 0;
- curPrdAddr = 0;
- curSector = 0;
- cmdBytes = 0;
- cmdBytesLeft = 0;
- drqBytesLeft = 0;
- dmaRead = false;
- intrPending = false;
-
- // set the device state to idle
- dmaState = Dma_Idle;
-
- if (id == DEV0) {
- devState = Device_Idle_S;
- devID = DEV0;
- } else if (id == DEV1) {
- devState = Device_Idle_NS;
- devID = DEV1;
- } else {
- panic("Invalid device ID: %#x\n", id);
- }
-
- // set the device ready bit
- status = STATUS_DRDY_BIT;
-
- /* The error register must be set to 0x1 on start-up to
- indicate that no diagnostic error was detected */
- cmdReg.error = 0x1;
-}
-
-////
-// Utility functions
-////
-
-bool
-IdeDisk::isDEVSelect()
-{
- return ctrl->isDiskSelected(this);
-}
-
-Addr
-IdeDisk::pciToDma(Addr pciAddr)
-{
- if (ctrl)
- return ctrl->plat->pciToDma(pciAddr);
- else
- 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
-////
-
-void
-IdeDisk::read(const Addr &offset, IdeRegType reg_type, uint8_t *data)
-{
- DevAction_t action = ACT_NONE;
-
- switch (reg_type) {
- case COMMAND_BLOCK:
- switch (offset) {
- // Data transfers occur two bytes at a time
- case DATA_OFFSET:
- *(uint16_t*)data = cmdReg.data;
- action = ACT_DATA_READ_SHORT;
- break;
- case ERROR_OFFSET:
- *data = cmdReg.error;
- break;
- case NSECTOR_OFFSET:
- *data = cmdReg.sec_count;
- break;
- case SECTOR_OFFSET:
- *data = cmdReg.sec_num;
- break;
- case LCYL_OFFSET:
- *data = cmdReg.cyl_low;
- break;
- case HCYL_OFFSET:
- *data = cmdReg.cyl_high;
- break;
- case DRIVE_OFFSET:
- *data = cmdReg.drive;
- break;
- case STATUS_OFFSET:
- *data = status;
- action = ACT_STAT_READ;
- break;
- default:
- panic("Invalid IDE command register offset: %#x\n", offset);
- }
- break;
- case CONTROL_BLOCK:
- if (offset == ALTSTAT_OFFSET)
- *data = status;
- else
- panic("Invalid IDE control register offset: %#x\n", offset);
- break;
- default:
- panic("Unknown register block!\n");
- }
-
- if (action != ACT_NONE)
- updateState(action);
-}
-
-void
-IdeDisk::write(const Addr &offset, IdeRegType reg_type, const uint8_t *data)
-{
- DevAction_t action = ACT_NONE;
-
- switch (reg_type) {
- case COMMAND_BLOCK:
- switch (offset) {
- case DATA_OFFSET:
- cmdReg.data = *(uint16_t*)data;
- action = ACT_DATA_WRITE_SHORT;
- break;
- case FEATURES_OFFSET:
- break;
- case NSECTOR_OFFSET:
- cmdReg.sec_count = *data;
- break;
- case SECTOR_OFFSET:
- cmdReg.sec_num = *data;
- break;
- case LCYL_OFFSET:
- cmdReg.cyl_low = *data;
- break;
- case HCYL_OFFSET:
- cmdReg.cyl_high = *data;
- break;
- case DRIVE_OFFSET:
- cmdReg.drive = *data;
- action = ACT_SELECT_WRITE;
- break;
- case COMMAND_OFFSET:
- cmdReg.command = *data;
- action = ACT_CMD_WRITE;
- break;
- default:
- panic("Invalid IDE command register offset: %#x\n", offset);
- }
- break;
- case CONTROL_BLOCK:
- if (offset == CONTROL_OFFSET) {
- if (*data & CONTROL_RST_BIT) {
- // force the device into the reset state
- devState = Device_Srst;
- action = ACT_SRST_SET;
- } else if (devState == Device_Srst && !(*data & CONTROL_RST_BIT))
- action = ACT_SRST_CLEAR;
-
- nIENBit = (*data & CONTROL_IEN_BIT) ? true : false;
- }
- else
- panic("Invalid IDE control register offset: %#x\n", offset);
- break;
- default:
- panic("Unknown register block!\n");
- }
-
- if (action != ACT_NONE)
- updateState(action);
-}
-
-////
-// Perform DMA transactions
-////
-
-void
-IdeDisk::doDmaTransfer()
-{
- if (dmaState != Dma_Transfer || devState != Transfer_Data_Dma)
- 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();
- }
-}
-
-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()),
- curPrd.getByteCount(), (cmdBytesLeft/SectorSize),
- curPrd.getEOT(), curSector);
-
- // the prd pointer has already been translated, so just do an increment
- curPrdAddr = curPrdAddr + sizeof(PrdEntry_t);
-
- if (dmaRead)
- doDmaRead();
- else
- doDmaWrite();
-}
-
-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()
-{
- /** @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());
-
- uint32_t bytesInPage = bytesInDmaPage(curPrd.getBaseAddr(),
- (uint32_t)curPrd.getByteCount());
-
- dmaInterfaceBytes = bytesInPage;
-
- if (bytesInPage == TheISA::VMPageSize)
- dmaReadFullPages++;
- dmaReadBytes += bytesInPage;
- dmaReadTxs++;
- dmaInterface->doDMA(Read, dmaAddr, bytesInPage,
- curTick + totalDiskDelay, &dmaReadEvent);
- } else {
- // schedule dmaReadEvent with sectorDelay (dmaReadDone)
- dmaReadEvent.schedule(curTick + totalDiskDelay);
- }
-}
-
-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);
-
- // 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();
- bytesWritten += SectorSize) {
-
- writeDisk(curSector++, (uint8_t *)(dataBuffer + bytesWritten));
- }
-
- // check for the EOT
- if (curPrd.getEOT()) {
- assert(cmdBytesLeft == 0);
- dmaState = Dma_Idle;
- updateState(ACT_DMA_DONE);
- } else {
- doDmaTransfer();
- }
-}
-
-void
-IdeDisk::doDmaWrite()
-{
- /** @todo we need to figure out what the delay actually will be */
- Tick totalDiskDelay = diskDelay + (curPrd.getByteCount() / SectorSize);
-
- 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());
-
- dmaInterfaceBytes = bytesInPage;
-
- if (bytesInPage == TheISA::VMPageSize)
- dmaWriteFullPages++;
- dmaWriteBytes += bytesInPage;
- dmaWriteTxs++;
-
- dmaInterface->doDMA(WriteInvalidate, dmaAddr,
- bytesInPage, curTick + totalDiskDelay,
- &dmaWriteEvent);
- } else {
- // schedule event with disk delay (dmaWriteDone)
- dmaWriteEvent.schedule(curTick + totalDiskDelay);
- }
-}
-
-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);
- dmaState = Dma_Idle;
- updateState(ACT_DMA_DONE);
- } else {
- doDmaTransfer();
- }
-}
-
-////
-// Disk utility routines
-///
-
-void
-IdeDisk::readDisk(uint32_t sector, uint8_t *data)
-{
- uint32_t bytesRead = image->read(data, sector);
-
- if (bytesRead != SectorSize)
- panic("Can't read from %s. Only %d of %d read. errno=%d\n",
- name(), bytesRead, SectorSize, errno);
-}
-
-void
-IdeDisk::writeDisk(uint32_t sector, uint8_t *data)
-{
- uint32_t bytesWritten = image->write(data, sector);
-
- if (bytesWritten != SectorSize)
- panic("Can't write to %s. Only %d of %d written. errno=%d\n",
- name(), bytesWritten, SectorSize, errno);
-}
-
-////
-// Setup and handle commands
-////
-
-void
-IdeDisk::startDma(const uint32_t &prdTableBase)
-{
- if (dmaState != Dma_Start)
- panic("Inconsistent DMA state, should be in Dma_Start!\n");
-
- if (devState != Transfer_Data_Dma)
- panic("Inconsistent device state for DMA start!\n");
-
- // PRD base address is given by bits 31:2
- curPrdAddr = pciToDma((Addr)(prdTableBase & ~ULL(0x3)));
-
- dmaState = Dma_Transfer;
-
- // schedule dma transfer (doDmaTransfer)
- dmaTransferEvent.schedule(curTick + 1);
-}
-
-void
-IdeDisk::abortDma()
-{
- if (dmaState == Dma_Idle)
- panic("Inconsistent DMA state, should be Start or Transfer!");
-
- if (devState != Transfer_Data_Dma && devState != Prepare_Data_Dma)
- panic("Inconsistent device state, should be Transfer or Prepare!\n");
-
- updateState(ACT_CMD_ERROR);
-}
-
-void
-IdeDisk::startCommand()
-{
- DevAction_t action = ACT_NONE;
- uint32_t size = 0;
- dmaRead = false;
-
- // Decode commands
- switch (cmdReg.command) {
- // Supported non-data commands
- case WDSF_READ_NATIVE_MAX:
- size = image->size() - 1;
- cmdReg.sec_num = (size & 0xff);
- cmdReg.cyl_low = ((size & 0xff00) >> 8);
- cmdReg.cyl_high = ((size & 0xff0000) >> 16);
- cmdReg.head = ((size & 0xf000000) >> 24);
-
- devState = Command_Execution;
- action = ACT_CMD_COMPLETE;
- break;
-
- case WDCC_RECAL:
- case WDCC_IDP:
- case WDCC_STANDBY_IMMED:
- case WDCC_FLUSHCACHE:
- case WDSF_VERIFY:
- case WDSF_SEEK:
- case SET_FEATURES:
- case WDCC_SETMULTI:
- devState = Command_Execution;
- action = ACT_CMD_COMPLETE;
- break;
-
- // Supported PIO data-in commands
- case WDCC_IDENTIFY:
- cmdBytes = cmdBytesLeft = sizeof(struct ataparams);
- devState = Prepare_Data_In;
- action = ACT_DATA_READY;
- break;
-
- case WDCC_READMULTI:
- case WDCC_READ:
- if (!(cmdReg.drive & DRIVE_LBA_BIT))
- panic("Attempt to perform CHS access, only supports LBA\n");
-
- if (cmdReg.sec_count == 0)
- cmdBytes = cmdBytesLeft = (256 * SectorSize);
- else
- cmdBytes = cmdBytesLeft = (cmdReg.sec_count * SectorSize);
-
- curSector = getLBABase();
-
- /** @todo make this a scheduled event to simulate disk delay */
- devState = Prepare_Data_In;
- action = ACT_DATA_READY;
- break;
-
- // Supported PIO data-out commands
- case WDCC_WRITEMULTI:
- case WDCC_WRITE:
- if (!(cmdReg.drive & DRIVE_LBA_BIT))
- panic("Attempt to perform CHS access, only supports LBA\n");
-
- if (cmdReg.sec_count == 0)
- cmdBytes = cmdBytesLeft = (256 * SectorSize);
- else
- cmdBytes = cmdBytesLeft = (cmdReg.sec_count * SectorSize);
-
- curSector = getLBABase();
-
- devState = Prepare_Data_Out;
- action = ACT_DATA_READY;
- break;
-
- // Supported DMA commands
- case WDCC_WRITEDMA:
- dmaRead = true; // a write to the disk is a DMA read from memory
- case WDCC_READDMA:
- if (!(cmdReg.drive & DRIVE_LBA_BIT))
- panic("Attempt to perform CHS access, only supports LBA\n");
-
- if (cmdReg.sec_count == 0)
- cmdBytes = cmdBytesLeft = (256 * SectorSize);
- else
- cmdBytes = cmdBytesLeft = (cmdReg.sec_count * SectorSize);
-
- curSector = getLBABase();
-
- devState = Prepare_Data_Dma;
- action = ACT_DMA_READY;
- break;
-
- default:
- panic("Unsupported ATA command: %#x\n", cmdReg.command);
- }
-
- if (action != ACT_NONE) {
- // set the BSY bit
- status |= STATUS_BSY_BIT;
- // clear the DRQ bit
- status &= ~STATUS_DRQ_BIT;
- // clear the DF bit
- status &= ~STATUS_DF_BIT;
-
- updateState(action);
- }
-}
-
-////
-// Handle setting and clearing interrupts
-////
-
-void
-IdeDisk::intrPost()
-{
- DPRINTF(IdeDisk, "Posting Interrupt\n");
- if (intrPending)
- panic("Attempt to post an interrupt with one pending\n");
-
- intrPending = true;
-
- // talk to controller to set interrupt
- if (ctrl) {
- ctrl->bmi_regs.bmis0 |= IDEINTS;
- ctrl->intrPost();
- }
-}
-
-void
-IdeDisk::intrClear()
-{
- DPRINTF(IdeDisk, "Clearing Interrupt\n");
- if (!intrPending)
- panic("Attempt to clear a non-pending interrupt\n");
-
- intrPending = false;
-
- // talk to controller to clear interrupt
- if (ctrl)
- ctrl->intrClear();
-}
-
-////
-// Manage the device internal state machine
-////
-
-void
-IdeDisk::updateState(DevAction_t action)
-{
- switch (devState) {
- case Device_Srst:
- if (action == ACT_SRST_SET) {
- // set the BSY bit
- status |= STATUS_BSY_BIT;
- } else if (action == ACT_SRST_CLEAR) {
- // clear the BSY bit
- status &= ~STATUS_BSY_BIT;
-
- // reset the device state
- reset(devID);
- }
- break;
-
- case Device_Idle_S:
- if (action == ACT_SELECT_WRITE && !isDEVSelect()) {
- devState = Device_Idle_NS;
- } else if (action == ACT_CMD_WRITE) {
- startCommand();
- }
-
- break;
-
- case Device_Idle_SI:
- if (action == ACT_SELECT_WRITE && !isDEVSelect()) {
- devState = Device_Idle_NS;
- intrClear();
- } else if (action == ACT_STAT_READ || isIENSet()) {
- devState = Device_Idle_S;
- intrClear();
- } else if (action == ACT_CMD_WRITE) {
- intrClear();
- startCommand();
- }
-
- break;
-
- case Device_Idle_NS:
- if (action == ACT_SELECT_WRITE && isDEVSelect()) {
- if (!isIENSet() && intrPending) {
- devState = Device_Idle_SI;
- intrPost();
- }
- if (isIENSet() || !intrPending) {
- devState = Device_Idle_S;
- }
- }
- break;
-
- case Command_Execution:
- if (action == ACT_CMD_COMPLETE) {
- // clear the BSY bit
- setComplete();
-
- if (!isIENSet()) {
- devState = Device_Idle_SI;
- intrPost();
- } else {
- devState = Device_Idle_S;
- }
- }
- break;
-
- case Prepare_Data_In:
- if (action == ACT_CMD_ERROR) {
- // clear the BSY bit
- setComplete();
-
- if (!isIENSet()) {
- devState = Device_Idle_SI;
- intrPost();
- } else {
- devState = Device_Idle_S;
- }
- } else if (action == ACT_DATA_READY) {
- // clear the BSY bit
- status &= ~STATUS_BSY_BIT;
- // set the DRQ bit
- status |= STATUS_DRQ_BIT;
-
- // copy the data into the data buffer
- if (cmdReg.command == WDCC_IDENTIFY) {
- // Reset the drqBytes for this block
- drqBytesLeft = sizeof(struct ataparams);
-
- memcpy((void *)dataBuffer, (void *)&driveID,
- sizeof(struct ataparams));
- } else {
- // Reset the drqBytes for this block
- drqBytesLeft = SectorSize;
-
- readDisk(curSector++, dataBuffer);
- }
-
- // put the first two bytes into the data register
- memcpy((void *)&cmdReg.data, (void *)dataBuffer,
- sizeof(uint16_t));
-
- if (!isIENSet()) {
- devState = Data_Ready_INTRQ_In;
- intrPost();
- } else {
- devState = Transfer_Data_In;
- }
- }
- break;
-
- case Data_Ready_INTRQ_In:
- if (action == ACT_STAT_READ) {
- devState = Transfer_Data_In;
- intrClear();
- }
- break;
-
- case Transfer_Data_In:
- if (action == ACT_DATA_READ_BYTE || action == ACT_DATA_READ_SHORT) {
- if (action == ACT_DATA_READ_BYTE) {
- panic("DEBUG: READING DATA ONE BYTE AT A TIME!\n");
- } else {
- drqBytesLeft -= 2;
- cmdBytesLeft -= 2;
-
- // copy next short into data registers
- if (drqBytesLeft)
- memcpy((void *)&cmdReg.data,
- (void *)&dataBuffer[SectorSize - drqBytesLeft],
- sizeof(uint16_t));
- }
-
- if (drqBytesLeft == 0) {
- if (cmdBytesLeft == 0) {
- // Clear the BSY bit
- setComplete();
- devState = Device_Idle_S;
- } else {
- devState = Prepare_Data_In;
- // set the BSY_BIT
- status |= STATUS_BSY_BIT;
- // clear the DRQ_BIT
- status &= ~STATUS_DRQ_BIT;
-
- /** @todo change this to a scheduled event to simulate
- disk delay */
- updateState(ACT_DATA_READY);
- }
- }
- }
- break;
-
- case Prepare_Data_Out:
- if (action == ACT_CMD_ERROR || cmdBytesLeft == 0) {
- // clear the BSY bit
- setComplete();
-
- if (!isIENSet()) {
- devState = Device_Idle_SI;
- intrPost();
- } else {
- devState = Device_Idle_S;
- }
- } else if (action == ACT_DATA_READY && cmdBytesLeft != 0) {
- // clear the BSY bit
- status &= ~STATUS_BSY_BIT;
- // set the DRQ bit
- status |= STATUS_DRQ_BIT;
-
- // clear the data buffer to get it ready for writes
- memset(dataBuffer, 0, MAX_DMA_SIZE);
-
- // reset the drqBytes for this block
- drqBytesLeft = SectorSize;
-
- if (cmdBytesLeft == cmdBytes || isIENSet()) {
- devState = Transfer_Data_Out;
- } else {
- devState = Data_Ready_INTRQ_Out;
- intrPost();
- }
- }
- break;
-
- case Data_Ready_INTRQ_Out:
- if (action == ACT_STAT_READ) {
- devState = Transfer_Data_Out;
- intrClear();
- }
- break;
-
- case Transfer_Data_Out:
- if (action == ACT_DATA_WRITE_BYTE ||
- action == ACT_DATA_WRITE_SHORT) {
-
- if (action == ACT_DATA_READ_BYTE) {
- panic("DEBUG: WRITING DATA ONE BYTE AT A TIME!\n");
- } else {
- // copy the latest short into the data buffer
- memcpy((void *)&dataBuffer[SectorSize - drqBytesLeft],
- (void *)&cmdReg.data,
- sizeof(uint16_t));
-
- drqBytesLeft -= 2;
- cmdBytesLeft -= 2;
- }
-
- if (drqBytesLeft == 0) {
- // copy the block to the disk
- writeDisk(curSector++, dataBuffer);
-
- // set the BSY bit
- status |= STATUS_BSY_BIT;
- // set the seek bit
- status |= STATUS_SEEK_BIT;
- // clear the DRQ bit
- status &= ~STATUS_DRQ_BIT;
-
- devState = Prepare_Data_Out;
-
- /** @todo change this to a scheduled event to simulate
- disk delay */
- updateState(ACT_DATA_READY);
- }
- }
- break;
-
- case Prepare_Data_Dma:
- if (action == ACT_CMD_ERROR) {
- // clear the BSY bit
- setComplete();
-
- if (!isIENSet()) {
- devState = Device_Idle_SI;
- intrPost();
- } else {
- devState = Device_Idle_S;
- }
- } else if (action == ACT_DMA_READY) {
- // clear the BSY bit
- status &= ~STATUS_BSY_BIT;
- // set the DRQ bit
- status |= STATUS_DRQ_BIT;
-
- devState = Transfer_Data_Dma;
-
- if (dmaState != Dma_Idle)
- panic("Inconsistent DMA state, should be Dma_Idle\n");
-
- dmaState = Dma_Start;
- // wait for the write to the DMA start bit
- }
- break;
-
- case Transfer_Data_Dma:
- if (action == ACT_CMD_ERROR || action == ACT_DMA_DONE) {
- // clear the BSY bit
- setComplete();
- // set the seek bit
- status |= STATUS_SEEK_BIT;
- // clear the controller state for DMA transfer
- ctrl->setDmaComplete(this);
-
- if (!isIENSet()) {
- devState = Device_Idle_SI;
- intrPost();
- } else {
- devState = Device_Idle_S;
- }
- }
- break;
-
- default:
- panic("Unknown IDE device state: %#x\n", devState);
- }
-}
-
-void
-IdeDisk::serialize(ostream &os)
-{
- // Check all outstanding events to see if they are scheduled
- // these are all mutually exclusive
- Tick reschedule = 0;
- Events_t event = None;
-
- int eventCount = 0;
-
- if (dmaTransferEvent.scheduled()) {
- reschedule = dmaTransferEvent.when();
- event = Transfer;
- eventCount++;
- }
- if (dmaReadWaitEvent.scheduled()) {
- reschedule = dmaReadWaitEvent.when();
- event = ReadWait;
- eventCount++;
- }
- if (dmaWriteWaitEvent.scheduled()) {
- reschedule = dmaWriteWaitEvent.when();
- event = WriteWait;
- eventCount++;
- }
- if (dmaPrdReadEvent.scheduled()) {
- reschedule = dmaPrdReadEvent.when();
- event = PrdRead;
- eventCount++;
- }
- if (dmaReadEvent.scheduled()) {
- reschedule = dmaReadEvent.when();
- event = DmaRead;
- eventCount++;
- }
- if (dmaWriteEvent.scheduled()) {
- reschedule = dmaWriteEvent.when();
- event = DmaWrite;
- eventCount++;
- }
-
- assert(eventCount <= 1);
-
- SERIALIZE_SCALAR(reschedule);
- SERIALIZE_ENUM(event);
-
- // Serialize device registers
- SERIALIZE_SCALAR(cmdReg.data);
- SERIALIZE_SCALAR(cmdReg.sec_count);
- SERIALIZE_SCALAR(cmdReg.sec_num);
- SERIALIZE_SCALAR(cmdReg.cyl_low);
- SERIALIZE_SCALAR(cmdReg.cyl_high);
- SERIALIZE_SCALAR(cmdReg.drive);
- SERIALIZE_SCALAR(cmdReg.command);
- SERIALIZE_SCALAR(status);
- SERIALIZE_SCALAR(nIENBit);
- SERIALIZE_SCALAR(devID);
-
- // Serialize the PRD related information
- SERIALIZE_SCALAR(curPrd.entry.baseAddr);
- SERIALIZE_SCALAR(curPrd.entry.byteCount);
- SERIALIZE_SCALAR(curPrd.entry.endOfTable);
- SERIALIZE_SCALAR(curPrdAddr);
-
- // 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);
- SERIALIZE_ARRAY(dataBuffer, MAX_DMA_SIZE);
-}
-
-void
-IdeDisk::unserialize(Checkpoint *cp, const string &section)
-{
- // Reschedule events that were outstanding
- // these are all mutually exclusive
- Tick reschedule = 0;
- Events_t event = None;
-
- UNSERIALIZE_SCALAR(reschedule);
- UNSERIALIZE_ENUM(event);
-
- switch (event) {
- case None : break;
- case Transfer : dmaTransferEvent.schedule(reschedule); break;
- case ReadWait : dmaReadWaitEvent.schedule(reschedule); break;
- case WriteWait : dmaWriteWaitEvent.schedule(reschedule); break;
- case PrdRead : dmaPrdReadEvent.schedule(reschedule); break;
- case DmaRead : dmaReadEvent.schedule(reschedule); break;
- case DmaWrite : dmaWriteEvent.schedule(reschedule); break;
- }
-
- // Unserialize device registers
- UNSERIALIZE_SCALAR(cmdReg.data);
- UNSERIALIZE_SCALAR(cmdReg.sec_count);
- UNSERIALIZE_SCALAR(cmdReg.sec_num);
- UNSERIALIZE_SCALAR(cmdReg.cyl_low);
- UNSERIALIZE_SCALAR(cmdReg.cyl_high);
- UNSERIALIZE_SCALAR(cmdReg.drive);
- UNSERIALIZE_SCALAR(cmdReg.command);
- UNSERIALIZE_SCALAR(status);
- UNSERIALIZE_SCALAR(nIENBit);
- UNSERIALIZE_SCALAR(devID);
-
- // Unserialize the PRD related information
- UNSERIALIZE_SCALAR(curPrd.entry.baseAddr);
- UNSERIALIZE_SCALAR(curPrd.entry.byteCount);
- UNSERIALIZE_SCALAR(curPrd.entry.endOfTable);
- UNSERIALIZE_SCALAR(curPrdAddr);
-
- // 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);
- UNSERIALIZE_ARRAY(dataBuffer, MAX_DMA_SIZE);
-}
-
-#ifndef DOXYGEN_SHOULD_SKIP_THIS
-
-enum DriveID { master, slave };
-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;
-
-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)
-
-END_INIT_SIM_OBJECT_PARAMS(IdeDisk)
-
-
-CREATE_SIM_OBJECT(IdeDisk)
-{
- return new IdeDisk(getInstanceName(), image, physmem, driveID, delay);
-}
-
-REGISTER_SIM_OBJECT("IdeDisk", IdeDisk)
-
-#endif //DOXYGEN_SHOULD_SKIP_THIS
diff --git a/dev/ide_disk.hh b/dev/ide_disk.hh
deleted file mode 100644
index 402ae44ee..000000000
--- a/dev/ide_disk.hh
+++ /dev/null
@@ -1,373 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @file
- * Device model for an IDE disk
- */
-
-#ifndef __IDE_DISK_HH__
-#define __IDE_DISK_HH__
-
-#include "base/statistics.hh"
-#include "dev/disk_image.hh"
-#include "dev/ide_atareg.h"
-#include "dev/ide_ctrl.hh"
-#include "dev/ide_wdcreg.h"
-#include "dev/io_device.hh"
-#include "sim/eventq.hh"
-
-#define DMA_BACKOFF_PERIOD 200
-
-#define MAX_DMA_SIZE (131072) // 128K
-#define MAX_MULTSECT (128)
-
-#define PRD_BASE_MASK 0xfffffffe
-#define PRD_COUNT_MASK 0xfffe
-#define PRD_EOT_MASK 0x8000
-
-typedef struct PrdEntry {
- uint32_t baseAddr;
- uint16_t byteCount;
- uint16_t endOfTable;
-} PrdEntry_t;
-
-class PrdTableEntry {
- public:
- PrdEntry_t entry;
-
- uint32_t getBaseAddr()
- {
- return (entry.baseAddr & PRD_BASE_MASK);
- }
-
- uint32_t getByteCount()
- {
- return ((entry.byteCount == 0) ? MAX_DMA_SIZE :
- (entry.byteCount & PRD_COUNT_MASK));
- }
-
- uint16_t getEOT()
- {
- return (entry.endOfTable & PRD_EOT_MASK);
- }
-};
-
-#define DATA_OFFSET (0)
-#define ERROR_OFFSET (1)
-#define FEATURES_OFFSET (1)
-#define NSECTOR_OFFSET (2)
-#define SECTOR_OFFSET (3)
-#define LCYL_OFFSET (4)
-#define HCYL_OFFSET (5)
-#define SELECT_OFFSET (6)
-#define DRIVE_OFFSET (6)
-#define STATUS_OFFSET (7)
-#define COMMAND_OFFSET (7)
-
-#define CONTROL_OFFSET (2)
-#define ALTSTAT_OFFSET (2)
-
-#define SELECT_DEV_BIT 0x10
-#define CONTROL_RST_BIT 0x04
-#define CONTROL_IEN_BIT 0x02
-#define STATUS_BSY_BIT 0x80
-#define STATUS_DRDY_BIT 0x40
-#define STATUS_DRQ_BIT 0x08
-#define STATUS_SEEK_BIT 0x10
-#define STATUS_DF_BIT 0x20
-#define DRIVE_LBA_BIT 0x40
-
-#define DEV0 (0)
-#define DEV1 (1)
-
-typedef struct CommandReg {
- uint16_t data;
- uint8_t error;
- uint8_t sec_count;
- uint8_t sec_num;
- uint8_t cyl_low;
- uint8_t cyl_high;
- union {
- uint8_t drive;
- uint8_t head;
- };
- uint8_t command;
-} CommandReg_t;
-
-typedef enum Events {
- None = 0,
- Transfer,
- ReadWait,
- WriteWait,
- PrdRead,
- DmaRead,
- DmaWrite
-} Events_t;
-
-typedef enum DevAction {
- ACT_NONE = 0,
- ACT_CMD_WRITE,
- ACT_CMD_COMPLETE,
- ACT_CMD_ERROR,
- ACT_SELECT_WRITE,
- ACT_STAT_READ,
- ACT_DATA_READY,
- ACT_DATA_READ_BYTE,
- ACT_DATA_READ_SHORT,
- ACT_DATA_WRITE_BYTE,
- ACT_DATA_WRITE_SHORT,
- ACT_DMA_READY,
- ACT_DMA_DONE,
- ACT_SRST_SET,
- ACT_SRST_CLEAR
-} DevAction_t;
-
-typedef enum DevState {
- // Device idle
- Device_Idle_S = 0,
- Device_Idle_SI,
- Device_Idle_NS,
-
- // Software reset
- Device_Srst,
-
- // Non-data commands
- Command_Execution,
-
- // PIO data-in (data to host)
- Prepare_Data_In,
- Data_Ready_INTRQ_In,
- Transfer_Data_In,
-
- // PIO data-out (data from host)
- Prepare_Data_Out,
- Data_Ready_INTRQ_Out,
- Transfer_Data_Out,
-
- // DMA protocol
- Prepare_Data_Dma,
- Transfer_Data_Dma
-} DevState_t;
-
-typedef enum DmaState {
- Dma_Idle = 0,
- Dma_Start,
- Dma_Transfer
-} DmaState_t;
-
-class PhysicalMemory;
-class IdeController;
-
-/**
- * IDE Disk device model
- */
-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. */
- int diskDelay;
-
- private:
- /** Drive identification structure for this disk */
- struct ataparams driveID;
- /** Data buffer for transfers */
- uint8_t *dataBuffer;
- /** Number of bytes in command data transfer */
- uint32_t cmdBytes;
- /** Number of bytes left in command data transfer */
- uint32_t cmdBytesLeft;
- /** Number of bytes left in DRQ block */
- uint32_t drqBytesLeft;
- /** Current sector in access */
- uint32_t curSector;
- /** Command block registers */
- CommandReg_t cmdReg;
- /** Status register */
- uint8_t status;
- /** Interrupt enable bit */
- bool nIENBit;
- /** Device state */
- DevState_t devState;
- /** Dma state */
- DmaState_t dmaState;
- /** Dma transaction is a read */
- bool dmaRead;
- /** PRD table base address */
- 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 */
- bool intrPending;
-
- Stats::Scalar<> dmaReadFullPages;
- Stats::Scalar<> dmaReadBytes;
- Stats::Scalar<> dmaReadTxs;
- Stats::Scalar<> dmaWriteFullPages;
- Stats::Scalar<> dmaWriteBytes;
- Stats::Scalar<> dmaWriteTxs;
-
- public:
- /**
- * 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);
-
- /**
- * Delete the data buffer.
- */
- ~IdeDisk();
-
- /**
- * Reset the device state
- */
- void reset(int id);
-
- /**
- * Register statistics.
- */
- void regStats();
-
-
- /**
- * Set the controller for this device
- * @param c The IDE controller
- */
- void setController(IdeController *c, DMAInterface<Bus> *dmaIntr) {
- if (ctrl) panic("Cannot change the controller once set!\n");
- ctrl = c;
- dmaInterface = dmaIntr;
- }
-
- // Device register read/write
- void read(const Addr &offset, IdeRegType regtype, uint8_t *data);
- void write(const Addr &offset, IdeRegType regtype, const uint8_t *data);
-
- // Start/abort functions
- void startDma(const uint32_t &prdTableBase);
- void abortDma();
-
- private:
- void startCommand();
-
- // Interrupt management
- void intrPost();
- void intrClear();
-
- // DMA stuff
- void doDmaTransfer();
- friend class EventWrapper<IdeDisk, &IdeDisk::doDmaTransfer>;
- EventWrapper<IdeDisk, &IdeDisk::doDmaTransfer> dmaTransferEvent;
-
- void doDmaRead();
- friend class EventWrapper<IdeDisk, &IdeDisk::doDmaRead>;
- EventWrapper<IdeDisk, &IdeDisk::doDmaRead> dmaReadWaitEvent;
-
- void doDmaWrite();
- friend class EventWrapper<IdeDisk, &IdeDisk::doDmaWrite>;
- EventWrapper<IdeDisk, &IdeDisk::doDmaWrite> dmaWriteWaitEvent;
-
- void dmaPrdReadDone();
- friend class EventWrapper<IdeDisk, &IdeDisk::dmaPrdReadDone>;
- EventWrapper<IdeDisk, &IdeDisk::dmaPrdReadDone> dmaPrdReadEvent;
-
- void dmaReadDone();
- friend class EventWrapper<IdeDisk, &IdeDisk::dmaReadDone>;
- EventWrapper<IdeDisk, &IdeDisk::dmaReadDone> dmaReadEvent;
-
- void dmaWriteDone();
- friend class EventWrapper<IdeDisk, &IdeDisk::dmaWriteDone>;
- EventWrapper<IdeDisk, &IdeDisk::dmaWriteDone> dmaWriteEvent;
-
- // Disk image read/write
- void readDisk(uint32_t sector, uint8_t *data);
- void writeDisk(uint32_t sector, uint8_t *data);
-
- // State machine management
- void updateState(DevAction_t action);
-
- // Utility functions
- bool isBSYSet() { return (status & STATUS_BSY_BIT); }
- bool isIENSet() { return nIENBit; }
- bool isDEVSelect();
-
- void setComplete()
- {
- // clear out the status byte
- status = 0;
- // set the DRDY bit
- status |= STATUS_DRDY_BIT;
- // set the SEEK bit
- status |= STATUS_SEEK_BIT;
- }
-
- uint32_t getLBABase()
- {
- return (Addr)(((cmdReg.head & 0xf) << 24) | (cmdReg.cyl_high << 16) |
- (cmdReg.cyl_low << 8) | (cmdReg.sec_num));
- }
-
- 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.
- */
- void serialize(std::ostream &os);
-
- /**
- * Reconstruct the state of this object from a checkpoint.
- * @param cp The checkpoint to use.
- * @param section The section name describing this object.
- */
- void unserialize(Checkpoint *cp, const std::string &section);
-};
-
-
-#endif // __IDE_DISK_HH__
diff --git a/dev/io_device.cc b/dev/io_device.cc
deleted file mode 100644
index 6ab876ab8..000000000
--- a/dev/io_device.cc
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#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)
-{}
-
-PioDevice::~PioDevice()
-{
- if (pioInterface)
- delete pioInterface;
-}
-
-DEFINE_SIM_OBJECT_CLASS_NAME("PioDevice", PioDevice)
-
-DmaDevice::DmaDevice(const std::string &name, Platform *p)
- : PioDevice(name, p), dmaInterface(NULL)
-{}
-
-DmaDevice::~DmaDevice()
-{
- if (dmaInterface)
- delete dmaInterface;
-}
-
-DEFINE_SIM_OBJECT_CLASS_NAME("DmaDevice", DmaDevice)
-
diff --git a/dev/io_device.hh b/dev/io_device.hh
deleted file mode 100644
index bcfd062b9..000000000
--- a/dev/io_device.hh
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __DEV_IO_DEVICE_HH__
-#define __DEV_IO_DEVICE_HH__
-
-#include "mem/functional/functional.hh"
-
-class BaseInterface;
-class Bus;
-class HierParams;
-class Platform;
-template <class BusType> class DMAInterface;
-
-class PioDevice : public FunctionalMemory
-{
- protected:
- Platform *platform;
- BaseInterface *pioInterface;
- Tick pioLatency;
-
- public:
- PioDevice(const std::string &name, Platform *p);
- virtual ~PioDevice();
-};
-
-class DmaDevice : public PioDevice
-{
- protected:
- DMAInterface<Bus> *dmaInterface;
-
- public:
- DmaDevice(const std::string &name, Platform *p);
- virtual ~DmaDevice();
-};
-
-#endif // __DEV_IO_DEVICE_HH__
diff --git a/dev/isa_fake.cc b/dev/isa_fake.cc
deleted file mode 100644
index 2afebbded..000000000
--- a/dev/isa_fake.cc
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @file
- * Isa Fake Device implementation
- */
-
-#include <deque>
-#include <string>
-#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 "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)
-{
- 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));
- }
-}
-
-Fault
-IsaFake::read(MemReqPtr &req, uint8_t *data)
-{
- DPRINTF(Tsunami, "read va=%#x size=%d\n",
- req->vaddr, req->size);
-
-#if TRACING_ON
- Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask)) >> 6;
-#endif
-
- switch (req->size) {
-
- case sizeof(uint64_t):
- *(uint64_t*)data = 0xFFFFFFFFFFFFFFFFULL;
- 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");
- }
- 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;
-}
-
-Tick
-IsaFake::cacheAccess(MemReqPtr &req)
-{
- return curTick;
-}
-
-BEGIN_DECLARE_SIM_OBJECT_PARAMS(IsaFake)
-
- SimObjectParam<MemoryController *> mmu;
- Param<Addr> addr;
- SimObjectParam<Bus*> pio_bus;
- Param<Tick> pio_latency;
- SimObjectParam<HierParams *> hier;
- Param<Addr> size;
-
-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)
-
-END_INIT_SIM_OBJECT_PARAMS(IsaFake)
-
-CREATE_SIM_OBJECT(IsaFake)
-{
- return new IsaFake(getInstanceName(), addr, mmu, hier, pio_bus, size);
-}
-
-REGISTER_SIM_OBJECT("IsaFake", IsaFake)
diff --git a/dev/isa_fake.hh b/dev/isa_fake.hh
deleted file mode 100644
index 73e40c681..000000000
--- a/dev/isa_fake.hh
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @file
- * Declaration of a fake device.
- */
-
-#ifndef __ISA_FAKE_HH__
-#define __ISA_FAKE_HH__
-
-#include "dev/tsunami.hh"
-#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
-{
- private:
- /** The address in memory that we respond to */
- Addr addr;
-
- 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
- */
- IsaFake(const std::string &name, Addr a, MemoryController *mmu,
- HierParams *hier, Bus *pio_bus, Addr size = 0x8);
-
- /**
- * 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);
-
- /**
- * 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);
-};
-
-#endif // __ISA_FAKE_HH__
diff --git a/dev/ns_gige.cc b/dev/ns_gige.cc
deleted file mode 100644
index ed8c794f9..000000000
--- a/dev/ns_gige.cc
+++ /dev/null
@@ -1,3105 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @file
- * Device module for modelling the National Semiconductor
- * DP83820 ethernet controller. Does not support priority queueing
- */
-#include <cstdio>
-#include <deque>
-#include <string>
-
-#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 "sim/builder.hh"
-#include "sim/debug.hh"
-#include "sim/host.hh"
-#include "sim/stats.hh"
-#include "arch/vtophys.hh"
-
-const char *NsRxStateStrings[] =
-{
- "rxIdle",
- "rxDescRefr",
- "rxDescRead",
- "rxFifoBlock",
- "rxFragWrite",
- "rxDescWrite",
- "rxAdvance"
-};
-
-const char *NsTxStateStrings[] =
-{
- "txIdle",
- "txDescRefr",
- "txDescRead",
- "txFifoBlock",
- "txFragRead",
- "txDescWrite",
- "txAdvance"
-};
-
-const char *NsDmaState[] =
-{
- "dmaIdle",
- "dmaReading",
- "dmaWriting",
- "dmaReadWaiting",
- "dmaWriteWaiting"
-};
-
-using namespace std;
-using namespace Net;
-using namespace TheISA;
-
-///////////////////////////////////////////////////////////////////////
-//
-// NSGigE PCI Device
-//
-NSGigE::NSGigE(Params *p)
- : PciDev(p), ioEnable(false),
- txFifo(p->tx_fifo_size), rxFifo(p->rx_fifo_size),
- txPacket(0), rxPacket(0), txPacketBufPtr(NULL), rxPacketBufPtr(NULL),
- txXferLen(0), rxXferLen(0), clock(p->clock),
- txState(txIdle), txEnable(false), CTDD(false),
- txFragPtr(0), txDescCnt(0), txDmaState(dmaIdle), rxState(rxIdle),
- rxEnable(false), CRDD(false), rxPktBytes(0),
- rxFragPtr(0), rxDescCnt(0), rxDmaState(dmaIdle), extstsEnable(false),
- eepromState(eepromStart), rxDmaReadEvent(this), rxDmaWriteEvent(this),
- txDmaReadEvent(this), txDmaWriteEvent(this),
- dmaDescFree(p->dma_desc_free), dmaDataFree(p->dma_data_free),
- txDelay(p->tx_delay), rxDelay(p->rx_delay),
- rxKickTick(0), rxKickEvent(this), txKickTick(0), txKickEvent(this),
- 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),
- 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;
- dmaWriteDelay = p->dma_write_delay;
- dmaReadFactor = p->dma_read_factor;
- dmaWriteFactor = p->dma_write_factor;
-
- regsReset();
- memcpy(&rom.perfectMatch, p->eaddr.bytes(), ETH_ADDR_LEN);
-
- memset(&rxDesc32, 0, sizeof(rxDesc32));
- memset(&txDesc32, 0, sizeof(txDesc32));
- memset(&rxDesc64, 0, sizeof(rxDesc64));
- memset(&txDesc64, 0, sizeof(txDesc64));
-}
-
-NSGigE::~NSGigE()
-{}
-
-void
-NSGigE::regStats()
-{
- txBytes
- .name(name() + ".txBytes")
- .desc("Bytes Transmitted")
- .prereq(txBytes)
- ;
-
- rxBytes
- .name(name() + ".rxBytes")
- .desc("Bytes Received")
- .prereq(rxBytes)
- ;
-
- txPackets
- .name(name() + ".txPackets")
- .desc("Number of Packets Transmitted")
- .prereq(txBytes)
- ;
-
- rxPackets
- .name(name() + ".rxPackets")
- .desc("Number of Packets Received")
- .prereq(rxBytes)
- ;
-
- txIpChecksums
- .name(name() + ".txIpChecksums")
- .desc("Number of tx IP Checksums done by device")
- .precision(0)
- .prereq(txBytes)
- ;
-
- rxIpChecksums
- .name(name() + ".rxIpChecksums")
- .desc("Number of rx IP Checksums done by device")
- .precision(0)
- .prereq(rxBytes)
- ;
-
- txTcpChecksums
- .name(name() + ".txTcpChecksums")
- .desc("Number of tx TCP Checksums done by device")
- .precision(0)
- .prereq(txBytes)
- ;
-
- rxTcpChecksums
- .name(name() + ".rxTcpChecksums")
- .desc("Number of rx TCP Checksums done by device")
- .precision(0)
- .prereq(rxBytes)
- ;
-
- txUdpChecksums
- .name(name() + ".txUdpChecksums")
- .desc("Number of tx UDP Checksums done by device")
- .precision(0)
- .prereq(txBytes)
- ;
-
- rxUdpChecksums
- .name(name() + ".rxUdpChecksums")
- .desc("Number of rx UDP Checksums done by device")
- .precision(0)
- .prereq(rxBytes)
- ;
-
- descDmaReads
- .name(name() + ".descDMAReads")
- .desc("Number of descriptors the device read w/ DMA")
- .precision(0)
- ;
-
- descDmaWrites
- .name(name() + ".descDMAWrites")
- .desc("Number of descriptors the device wrote w/ DMA")
- .precision(0)
- ;
-
- descDmaRdBytes
- .name(name() + ".descDmaReadBytes")
- .desc("number of descriptor bytes read w/ DMA")
- .precision(0)
- ;
-
- descDmaWrBytes
- .name(name() + ".descDmaWriteBytes")
- .desc("number of descriptor bytes write w/ DMA")
- .precision(0)
- ;
-
- txBandwidth
- .name(name() + ".txBandwidth")
- .desc("Transmit Bandwidth (bits/s)")
- .precision(0)
- .prereq(txBytes)
- ;
-
- rxBandwidth
- .name(name() + ".rxBandwidth")
- .desc("Receive Bandwidth (bits/s)")
- .precision(0)
- .prereq(rxBytes)
- ;
-
- totBandwidth
- .name(name() + ".totBandwidth")
- .desc("Total Bandwidth (bits/s)")
- .precision(0)
- .prereq(totBytes)
- ;
-
- totPackets
- .name(name() + ".totPackets")
- .desc("Total Packets")
- .precision(0)
- .prereq(totBytes)
- ;
-
- totBytes
- .name(name() + ".totBytes")
- .desc("Total Bytes")
- .precision(0)
- .prereq(totBytes)
- ;
-
- totPacketRate
- .name(name() + ".totPPS")
- .desc("Total Tranmission Rate (packets/s)")
- .precision(0)
- .prereq(totBytes)
- ;
-
- txPacketRate
- .name(name() + ".txPPS")
- .desc("Packet Tranmission Rate (packets/s)")
- .precision(0)
- .prereq(txBytes)
- ;
-
- rxPacketRate
- .name(name() + ".rxPPS")
- .desc("Packet Reception Rate (packets/s)")
- .precision(0)
- .prereq(rxBytes)
- ;
-
- postedSwi
- .name(name() + ".postedSwi")
- .desc("number of software interrupts posted to CPU")
- .precision(0)
- ;
-
- totalSwi
- .name(name() + ".totalSwi")
- .desc("total number of Swi written to ISR")
- .precision(0)
- ;
-
- coalescedSwi
- .name(name() + ".coalescedSwi")
- .desc("average number of Swi's coalesced into each post")
- .precision(0)
- ;
-
- postedRxIdle
- .name(name() + ".postedRxIdle")
- .desc("number of rxIdle interrupts posted to CPU")
- .precision(0)
- ;
-
- totalRxIdle
- .name(name() + ".totalRxIdle")
- .desc("total number of RxIdle written to ISR")
- .precision(0)
- ;
-
- coalescedRxIdle
- .name(name() + ".coalescedRxIdle")
- .desc("average number of RxIdle's coalesced into each post")
- .precision(0)
- ;
-
- postedRxOk
- .name(name() + ".postedRxOk")
- .desc("number of RxOk interrupts posted to CPU")
- .precision(0)
- ;
-
- totalRxOk
- .name(name() + ".totalRxOk")
- .desc("total number of RxOk written to ISR")
- .precision(0)
- ;
-
- coalescedRxOk
- .name(name() + ".coalescedRxOk")
- .desc("average number of RxOk's coalesced into each post")
- .precision(0)
- ;
-
- postedRxDesc
- .name(name() + ".postedRxDesc")
- .desc("number of RxDesc interrupts posted to CPU")
- .precision(0)
- ;
-
- totalRxDesc
- .name(name() + ".totalRxDesc")
- .desc("total number of RxDesc written to ISR")
- .precision(0)
- ;
-
- coalescedRxDesc
- .name(name() + ".coalescedRxDesc")
- .desc("average number of RxDesc's coalesced into each post")
- .precision(0)
- ;
-
- postedTxOk
- .name(name() + ".postedTxOk")
- .desc("number of TxOk interrupts posted to CPU")
- .precision(0)
- ;
-
- totalTxOk
- .name(name() + ".totalTxOk")
- .desc("total number of TxOk written to ISR")
- .precision(0)
- ;
-
- coalescedTxOk
- .name(name() + ".coalescedTxOk")
- .desc("average number of TxOk's coalesced into each post")
- .precision(0)
- ;
-
- postedTxIdle
- .name(name() + ".postedTxIdle")
- .desc("number of TxIdle interrupts posted to CPU")
- .precision(0)
- ;
-
- totalTxIdle
- .name(name() + ".totalTxIdle")
- .desc("total number of TxIdle written to ISR")
- .precision(0)
- ;
-
- coalescedTxIdle
- .name(name() + ".coalescedTxIdle")
- .desc("average number of TxIdle's coalesced into each post")
- .precision(0)
- ;
-
- postedTxDesc
- .name(name() + ".postedTxDesc")
- .desc("number of TxDesc interrupts posted to CPU")
- .precision(0)
- ;
-
- totalTxDesc
- .name(name() + ".totalTxDesc")
- .desc("total number of TxDesc written to ISR")
- .precision(0)
- ;
-
- coalescedTxDesc
- .name(name() + ".coalescedTxDesc")
- .desc("average number of TxDesc's coalesced into each post")
- .precision(0)
- ;
-
- postedRxOrn
- .name(name() + ".postedRxOrn")
- .desc("number of RxOrn posted to CPU")
- .precision(0)
- ;
-
- totalRxOrn
- .name(name() + ".totalRxOrn")
- .desc("total number of RxOrn written to ISR")
- .precision(0)
- ;
-
- coalescedRxOrn
- .name(name() + ".coalescedRxOrn")
- .desc("average number of RxOrn's coalesced into each post")
- .precision(0)
- ;
-
- coalescedTotal
- .name(name() + ".coalescedTotal")
- .desc("average number of interrupts coalesced into each post")
- .precision(0)
- ;
-
- postedInterrupts
- .name(name() + ".postedInterrupts")
- .desc("number of posts to CPU")
- .precision(0)
- ;
-
- droppedPackets
- .name(name() + ".droppedPackets")
- .desc("number of packets dropped")
- .precision(0)
- ;
-
- coalescedSwi = totalSwi / postedInterrupts;
- coalescedRxIdle = totalRxIdle / postedInterrupts;
- coalescedRxOk = totalRxOk / postedInterrupts;
- coalescedRxDesc = totalRxDesc / postedInterrupts;
- coalescedTxOk = totalTxOk / postedInterrupts;
- coalescedTxIdle = totalTxIdle / postedInterrupts;
- coalescedTxDesc = totalTxDesc / postedInterrupts;
- coalescedRxOrn = totalRxOrn / postedInterrupts;
-
- coalescedTotal = (totalSwi + totalRxIdle + totalRxOk + totalRxDesc +
- totalTxOk + totalTxIdle + totalTxDesc +
- totalRxOrn) / postedInterrupts;
-
- txBandwidth = txBytes * Stats::constant(8) / simSeconds;
- rxBandwidth = rxBytes * Stats::constant(8) / simSeconds;
- totBandwidth = txBandwidth + rxBandwidth;
- totBytes = txBytes + rxBytes;
- totPackets = txPackets + rxPackets;
-
- txPacketRate = txPackets / simSeconds;
- 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)
-{
- if (offset < PCI_DEVICE_SPECIFIC)
- PciDev::writeConfig(offset, size, 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
- // need to properly implement it
- case PCI_COMMAND:
- if (config.data[offset] & PCI_CMD_IOSE)
- 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;
- }
-}
-
-/**
- * This reads the device registers, which are detailed in the NS83820
- * spec sheet
- */
-Fault
-NSGigE::read(MemReqPtr &req, uint8_t *data)
-{
- assert(ioEnable);
-
- //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);
-
-
- // there are some reserved registers, you can see ns_gige_reg.h and
- // the spec sheet for details
- if (daddr > LAST && daddr <= RESERVED) {
- panic("Accessing reserved register");
- } else if (daddr > RESERVED && daddr <= 0x3FC) {
- readConfig(daddr & 0xff, req->size, data);
- return NoFault;
- } else if (daddr >= MIB_START && daddr <= MIB_END) {
- // don't implement all the MIB's. hopefully the kernel
- // doesn't actually DEPEND upon their values
- // MIB are just hardware stats keepers
- uint32_t &reg = *(uint32_t *) data;
- reg = 0;
- return NoFault;
- } 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;
-
- case CFGR:
- reg = regs.config;
- break;
-
- case MEAR:
- reg = regs.mear;
- break;
-
- case PTSCR:
- reg = regs.ptscr;
- break;
-
- case ISR:
- reg = regs.isr;
- devIntrClear(ISR_ALL);
- break;
-
- case IMR:
- reg = regs.imr;
- break;
-
- case IER:
- reg = regs.ier;
- break;
-
- case IHR:
- reg = regs.ihr;
- break;
-
- case TXDP:
- reg = regs.txdp;
- break;
-
- case TXDP_HI:
- reg = regs.txdp_hi;
- break;
-
- case TX_CFG:
- reg = regs.txcfg;
- break;
-
- case GPIOR:
- reg = regs.gpior;
- break;
-
- case RXDP:
- reg = regs.rxdp;
- break;
-
- case RXDP_HI:
- reg = regs.rxdp_hi;
- break;
-
- case RX_CFG:
- reg = regs.rxcfg;
- break;
-
- case PQCR:
- reg = regs.pqcr;
- 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;
-
- 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;
- }
-
- panic("reading RFDR for something other than pattern"
- " matching or hashing! %#x\n", rfaddr);
- }
- break;
-
- case SRR:
- reg = regs.srr;
- break;
-
- case MIBC:
- reg = regs.mibc;
- reg &= ~(MIBC_MIBS | MIBC_ACLR);
- break;
-
- case VRCR:
- reg = regs.vrcr;
- break;
-
- case VTCR:
- reg = regs.vtcr;
- break;
-
- case VDR:
- reg = regs.vdr;
- break;
-
- case CCSR:
- reg = regs.ccsr;
- break;
-
- case TBICR:
- reg = regs.tbicr;
- break;
-
- case TBISR:
- reg = regs.tbisr;
- break;
-
- case TANAR:
- reg = regs.tanar;
- break;
-
- case TANLPAR:
- reg = regs.tanlpar;
- break;
-
- case TANER:
- reg = regs.taner;
- break;
-
- case TESR:
- reg = regs.tesr;
- 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;
-
- default:
- panic("reading unimplemented register: addr=%#x", daddr);
- }
-
- DPRINTF(EthernetPIO, "read from %#x: data=%d data=%#x\n",
- daddr, reg, reg);
- }
- break;
-
- default:
- panic("accessing register with invalid size: addr=%#x, size=%d",
- daddr, req->size);
- }
-
- return NoFault;
-}
-
-Fault
-NSGigE::write(MemReqPtr &req, const uint8_t *data)
-{
- 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);
-
- if (daddr > LAST && daddr <= RESERVED) {
- panic("Accessing reserved register");
- } else if (daddr > RESERVED && daddr <= 0x3FC) {
- writeConfig(daddr & 0xff, req->size, data);
- return NoFault;
- } else if (daddr > 0x3FC)
- panic("Something is messed up!\n");
-
- if (req->size == sizeof(uint32_t)) {
- uint32_t reg = *(uint32_t *)data;
- uint16_t rfaddr;
-
- DPRINTF(EthernetPIO, "write data=%d data=%#x\n", reg, reg);
-
- switch (daddr) {
- case CR:
- regs.command = reg;
- if (reg & CR_TXD) {
- txEnable = false;
- } else if (reg & CR_TXE) {
- txEnable = true;
-
- // the kernel is enabling the transmit machine
- if (txState == txIdle)
- txKick();
- }
-
- if (reg & CR_RXD) {
- rxEnable = false;
- } else if (reg & CR_RXE) {
- rxEnable = true;
-
- if (rxState == rxIdle)
- rxKick();
- }
-
- if (reg & CR_TXR)
- txReset();
-
- if (reg & CR_RXR)
- rxReset();
-
- if (reg & CR_SWI)
- devIntrPost(ISR_SWI);
-
- if (reg & CR_RST) {
- txReset();
- rxReset();
-
- regsReset();
- }
- break;
-
- case CFGR:
- if (reg & CFGR_LNKSTS ||
- reg & CFGR_SPDSTS ||
- reg & CFGR_DUPSTS ||
- reg & CFGR_RESERVED ||
- reg & CFGR_T64ADDR ||
- reg & CFGR_PCI64_DET)
-
- // First clear all writable bits
- regs.config &= CFGR_LNKSTS | CFGR_SPDSTS | CFGR_DUPSTS |
- CFGR_RESERVED | CFGR_T64ADDR |
- CFGR_PCI64_DET;
- // Now set the appropriate writable bits
- regs.config |= reg & ~(CFGR_LNKSTS | CFGR_SPDSTS | CFGR_DUPSTS |
- CFGR_RESERVED | CFGR_T64ADDR |
- CFGR_PCI64_DET);
-
-// all these #if 0's are because i don't THINK the kernel needs to
-// have these implemented. if there is a problem relating to one of
-// these, you may need to add functionality in.
- if (reg & CFGR_TBI_EN) ;
- if (reg & CFGR_MODE_1000) ;
-
- if (reg & CFGR_AUTO_1000)
- panic("CFGR_AUTO_1000 not implemented!\n");
-
- if (reg & CFGR_PINT_DUPSTS ||
- reg & CFGR_PINT_LNKSTS ||
- reg & CFGR_PINT_SPDSTS)
- ;
-
- if (reg & CFGR_TMRTEST) ;
- if (reg & CFGR_MRM_DIS) ;
- if (reg & CFGR_MWI_DIS) ;
-
- if (reg & CFGR_T64ADDR) ;
- // panic("CFGR_T64ADDR is read only register!\n");
-
- if (reg & CFGR_PCI64_DET)
- panic("CFGR_PCI64_DET is read only register!\n");
-
- if (reg & CFGR_DATA64_EN) ;
- if (reg & CFGR_M64ADDR) ;
- if (reg & CFGR_PHY_RST) ;
- if (reg & CFGR_PHY_DIS) ;
-
- if (reg & CFGR_EXTSTS_EN)
- extstsEnable = true;
- else
- extstsEnable = false;
-
- if (reg & CFGR_REQALG) ;
- if (reg & CFGR_SB) ;
- if (reg & CFGR_POW) ;
- if (reg & CFGR_EXD) ;
- if (reg & CFGR_PESEL) ;
- if (reg & CFGR_BROM_DIS) ;
- if (reg & CFGR_EXT_125) ;
- if (reg & CFGR_BEM) ;
- break;
-
- case MEAR:
- // Clear writable bits
- regs.mear &= MEAR_EEDO;
- // Set appropriate writable bits
- regs.mear |= reg & ~MEAR_EEDO;
-
- // FreeBSD uses the EEPROM to read PMATCH (for the MAC address)
- // even though it could get it through RFDR
- if (reg & MEAR_EESEL) {
- // Rising edge of clock
- if (reg & MEAR_EECLK && !eepromClk)
- eepromKick();
- }
- else {
- eepromState = eepromStart;
- regs.mear &= ~MEAR_EEDI;
- }
-
- eepromClk = reg & MEAR_EECLK;
-
- // since phy is completely faked, MEAR_MD* don't matter
- if (reg & MEAR_MDIO) ;
- if (reg & MEAR_MDDIR) ;
- if (reg & MEAR_MDC) ;
- break;
-
- case PTSCR:
- regs.ptscr = reg & ~(PTSCR_RBIST_RDONLY);
- // these control BISTs for various parts of chip - we
- // don't care or do just fake that the BIST is done
- if (reg & PTSCR_RBIST_EN)
- regs.ptscr |= PTSCR_RBIST_DONE;
- if (reg & PTSCR_EEBIST_EN)
- regs.ptscr &= ~PTSCR_EEBIST_EN;
- if (reg & PTSCR_EELOAD_EN)
- regs.ptscr &= ~PTSCR_EELOAD_EN;
- break;
-
- case ISR: /* writing to the ISR has no effect */
- panic("ISR is a read only register!\n");
-
- case IMR:
- regs.imr = reg;
- devIntrChangeMask();
- break;
-
- case IER:
- regs.ier = reg;
- break;
-
- case IHR:
- regs.ihr = reg;
- /* not going to implement real interrupt holdoff */
- break;
-
- case TXDP:
- regs.txdp = (reg & 0xFFFFFFFC);
- assert(txState == txIdle);
- CTDD = false;
- break;
-
- case TXDP_HI:
- regs.txdp_hi = reg;
- break;
-
- case TX_CFG:
- regs.txcfg = reg;
-#if 0
- if (reg & TX_CFG_CSI) ;
- if (reg & TX_CFG_HBI) ;
- if (reg & TX_CFG_MLB) ;
- if (reg & TX_CFG_ATP) ;
- if (reg & TX_CFG_ECRETRY) {
- /*
- * this could easily be implemented, but considering
- * the network is just a fake pipe, wouldn't make
- * sense to do this
- */
- }
-
- if (reg & TX_CFG_BRST_DIS) ;
-#endif
-
-#if 0
- /* we handle our own DMA, ignore the kernel's exhortations */
- if (reg & TX_CFG_MXDMA) ;
-#endif
-
- // also, we currently don't care about fill/drain
- // thresholds though this may change in the future with
- // more realistic networks or a driver which changes it
- // according to feedback
-
- break;
-
- case GPIOR:
- // Only write writable bits
- regs.gpior &= GPIOR_UNUSED | GPIOR_GP5_IN | GPIOR_GP4_IN
- | GPIOR_GP3_IN | GPIOR_GP2_IN | GPIOR_GP1_IN;
- regs.gpior |= reg & ~(GPIOR_UNUSED | GPIOR_GP5_IN | GPIOR_GP4_IN
- | GPIOR_GP3_IN | GPIOR_GP2_IN | GPIOR_GP1_IN);
- /* these just control general purpose i/o pins, don't matter */
- break;
-
- case RXDP:
- regs.rxdp = reg;
- CRDD = false;
- break;
-
- case RXDP_HI:
- regs.rxdp_hi = reg;
- break;
-
- case RX_CFG:
- regs.rxcfg = reg;
-#if 0
- if (reg & RX_CFG_AEP) ;
- if (reg & RX_CFG_ARP) ;
- if (reg & RX_CFG_STRIPCRC) ;
- if (reg & RX_CFG_RX_RD) ;
- if (reg & RX_CFG_ALP) ;
- if (reg & RX_CFG_AIRL) ;
-
- /* we handle our own DMA, ignore what kernel says about it */
- if (reg & RX_CFG_MXDMA) ;
-
- //also, we currently don't care about fill/drain thresholds
- //though this may change in the future with more realistic
- //networks or a driver which changes it according to feedback
- if (reg & (RX_CFG_DRTH | RX_CFG_DRTH0)) ;
-#endif
- break;
-
- case PQCR:
- /* there is no priority queueing used in the linux 2.6 driver */
- regs.pqcr = reg;
- break;
-
- case WCSR:
- /* not going to implement wake on LAN */
- regs.wcsr = reg;
- break;
-
- case PCR:
- /* not going to implement pause control */
- regs.pcr = reg;
- break;
-
- case RFCR:
- regs.rfcr = reg;
-
- rxFilterEnable = (reg & RFCR_RFEN) ? true : false;
- acceptBroadcast = (reg & RFCR_AAB) ? true : false;
- acceptMulticast = (reg & RFCR_AAM) ? true : false;
- acceptUnicast = (reg & RFCR_AAU) ? true : false;
- acceptPerfect = (reg & RFCR_APM) ? true : false;
- acceptArp = (reg & RFCR_AARP) ? true : false;
- multicastHashEnable = (reg & RFCR_MHEN) ? true : false;
-
-#if 0
- if (reg & RFCR_APAT)
- panic("RFCR_APAT not implemented!\n");
-#endif
- if (reg & RFCR_UHEN)
- panic("Unicast hash filtering not used by drivers!\n");
-
- if (reg & RFCR_ULM)
- panic("RFCR_ULM not implemented!\n");
-
- break;
-
- case RFDR:
- rfaddr = (uint16_t)(regs.rfcr & RFCR_RFADDR);
- switch (rfaddr) {
- case 0x000:
- rom.perfectMatch[0] = (uint8_t)reg;
- rom.perfectMatch[1] = (uint8_t)(reg >> 8);
- break;
- case 0x002:
- rom.perfectMatch[2] = (uint8_t)reg;
- rom.perfectMatch[3] = (uint8_t)(reg >> 8);
- break;
- case 0x004:
- rom.perfectMatch[4] = (uint8_t)reg;
- rom.perfectMatch[5] = (uint8_t)(reg >> 8);
- break;
- default:
-
- if (rfaddr >= FHASH_ADDR &&
- rfaddr < FHASH_ADDR + FHASH_SIZE) {
-
- // Only word-aligned writes supported
- if (rfaddr % 2)
- panic("unaligned write to filter hash table!");
-
- rom.filterHash[rfaddr - FHASH_ADDR] = (uint8_t)reg;
- rom.filterHash[rfaddr - FHASH_ADDR + 1]
- = (uint8_t)(reg >> 8);
- break;
- }
- panic("writing RFDR for something other than pattern matching\
- or hashing! %#x\n", rfaddr);
- }
-
- case BRAR:
- regs.brar = reg;
- break;
-
- case BRDR:
- panic("the driver never uses BRDR, something is wrong!\n");
-
- case SRR:
- panic("SRR is read only register!\n");
-
- case MIBC:
- panic("the driver never uses MIBC, something is wrong!\n");
-
- case VRCR:
- regs.vrcr = reg;
- break;
-
- case VTCR:
- regs.vtcr = reg;
- break;
-
- case VDR:
- panic("the driver never uses VDR, something is wrong!\n");
-
- case CCSR:
- /* not going to implement clockrun stuff */
- regs.ccsr = reg;
- break;
-
- case TBICR:
- regs.tbicr = reg;
- if (reg & TBICR_MR_LOOPBACK)
- panic("TBICR_MR_LOOPBACK never used, something wrong!\n");
-
- if (reg & TBICR_MR_AN_ENABLE) {
- regs.tanlpar = regs.tanar;
- regs.tbisr |= (TBISR_MR_AN_COMPLETE | TBISR_MR_LINK_STATUS);
- }
-
-#if 0
- if (reg & TBICR_MR_RESTART_AN) ;
-#endif
-
- break;
-
- case TBISR:
- panic("TBISR is read only register!\n");
-
- case TANAR:
- // Only write the writable bits
- regs.tanar &= TANAR_RF1 | TANAR_RF2 | TANAR_UNUSED;
- regs.tanar |= reg & ~(TANAR_RF1 | TANAR_RF2 | TANAR_UNUSED);
-
- // Pause capability unimplemented
-#if 0
- if (reg & TANAR_PS2) ;
- if (reg & TANAR_PS1) ;
-#endif
-
- break;
-
- case TANLPAR:
- panic("this should only be written to by the fake phy!\n");
-
- case TANER:
- panic("TANER is read only register!\n");
-
- case TESR:
- regs.tesr = reg;
- break;
-
- default:
- panic("invalid register access daddr=%#x", daddr);
- }
- } else {
- panic("Invalid Request Size");
- }
-
- return NoFault;
-}
-
-void
-NSGigE::devIntrPost(uint32_t interrupts)
-{
- if (interrupts & ISR_RESERVE)
- panic("Cannot set a reserved interrupt");
-
- if (interrupts & ISR_NOIMPL)
- warn("interrupt not implemented %#x\n", interrupts);
-
- interrupts &= ISR_IMPL;
- regs.isr |= interrupts;
-
- if (interrupts & regs.imr) {
- if (interrupts & ISR_SWI) {
- totalSwi++;
- }
- if (interrupts & ISR_RXIDLE) {
- totalRxIdle++;
- }
- if (interrupts & ISR_RXOK) {
- totalRxOk++;
- }
- if (interrupts & ISR_RXDESC) {
- totalRxDesc++;
- }
- if (interrupts & ISR_TXOK) {
- totalTxOk++;
- }
- if (interrupts & ISR_TXIDLE) {
- totalTxIdle++;
- }
- if (interrupts & ISR_TXDESC) {
- totalTxDesc++;
- }
- if (interrupts & ISR_RXORN) {
- totalRxOrn++;
- }
- }
-
- DPRINTF(EthernetIntr,
- "interrupt written to ISR: intr=%#x isr=%#x imr=%#x\n",
- interrupts, regs.isr, regs.imr);
-
- if ((regs.isr & regs.imr)) {
- Tick when = curTick;
- if ((regs.isr & regs.imr & ISR_NODELAY) == 0)
- when += intrDelay;
- cpuIntrPost(when);
- }
-}
-
-/* writing this interrupt counting stats inside this means that this function
- is now limited to being used to clear all interrupts upon the kernel
- reading isr and servicing. just telling you in case you were thinking
- of expanding use.
-*/
-void
-NSGigE::devIntrClear(uint32_t interrupts)
-{
- if (interrupts & ISR_RESERVE)
- panic("Cannot clear a reserved interrupt");
-
- if (regs.isr & regs.imr & ISR_SWI) {
- postedSwi++;
- }
- if (regs.isr & regs.imr & ISR_RXIDLE) {
- postedRxIdle++;
- }
- if (regs.isr & regs.imr & ISR_RXOK) {
- postedRxOk++;
- }
- if (regs.isr & regs.imr & ISR_RXDESC) {
- postedRxDesc++;
- }
- if (regs.isr & regs.imr & ISR_TXOK) {
- postedTxOk++;
- }
- if (regs.isr & regs.imr & ISR_TXIDLE) {
- postedTxIdle++;
- }
- if (regs.isr & regs.imr & ISR_TXDESC) {
- postedTxDesc++;
- }
- if (regs.isr & regs.imr & ISR_RXORN) {
- postedRxOrn++;
- }
-
- if (regs.isr & regs.imr & ISR_IMPL)
- postedInterrupts++;
-
- interrupts &= ~ISR_NOIMPL;
- regs.isr &= ~interrupts;
-
- DPRINTF(EthernetIntr,
- "interrupt cleared from ISR: intr=%x isr=%x imr=%x\n",
- interrupts, regs.isr, regs.imr);
-
- if (!(regs.isr & regs.imr))
- cpuIntrClear();
-}
-
-void
-NSGigE::devIntrChangeMask()
-{
- DPRINTF(EthernetIntr, "interrupt mask changed: isr=%x imr=%x masked=%x\n",
- regs.isr, regs.imr, regs.isr & regs.imr);
-
- if (regs.isr & regs.imr)
- cpuIntrPost(curTick);
- else
- cpuIntrClear();
-}
-
-void
-NSGigE::cpuIntrPost(Tick when)
-{
- // If the interrupt you want to post is later than an interrupt
- // already scheduled, just let it post in the coming one and don't
- // schedule another.
- // HOWEVER, must be sure that the scheduled intrTick is in the
- // future (this was formerly the source of a bug)
- /**
- * @todo this warning should be removed and the intrTick code should
- * be fixed.
- */
- assert(when >= curTick);
- assert(intrTick >= curTick || intrTick == 0);
- if (when > intrTick && intrTick != 0) {
- DPRINTF(EthernetIntr, "don't need to schedule event...intrTick=%d\n",
- intrTick);
- return;
- }
-
- intrTick = when;
- if (intrTick < curTick) {
- debug_break();
- intrTick = curTick;
- }
-
- DPRINTF(EthernetIntr, "going to schedule an interrupt for intrTick=%d\n",
- intrTick);
-
- if (intrEvent)
- intrEvent->squash();
- intrEvent = new IntrEvent(this, true);
- intrEvent->schedule(intrTick);
-}
-
-void
-NSGigE::cpuInterrupt()
-{
- assert(intrTick == curTick);
-
- // Whether or not there's a pending interrupt, we don't care about
- // it anymore
- intrEvent = 0;
- intrTick = 0;
-
- // Don't send an interrupt if there's already one
- if (cpuPendingIntr) {
- DPRINTF(EthernetIntr,
- "would send an interrupt now, but there's already pending\n");
- } else {
- // Send interrupt
- cpuPendingIntr = true;
-
- DPRINTF(EthernetIntr, "posting interrupt\n");
- intrPost();
- }
-}
-
-void
-NSGigE::cpuIntrClear()
-{
- if (!cpuPendingIntr)
- return;
-
- if (intrEvent) {
- intrEvent->squash();
- intrEvent = 0;
- }
-
- intrTick = 0;
-
- cpuPendingIntr = false;
-
- DPRINTF(EthernetIntr, "clearing interrupt\n");
- intrClear();
-}
-
-bool
-NSGigE::cpuIntrPending() const
-{ return cpuPendingIntr; }
-
-void
-NSGigE::txReset()
-{
-
- DPRINTF(Ethernet, "transmit reset\n");
-
- CTDD = false;
- txEnable = false;;
- txFragPtr = 0;
- assert(txDescCnt == 0);
- txFifo.clear();
- txState = txIdle;
- assert(txDmaState == dmaIdle);
-}
-
-void
-NSGigE::rxReset()
-{
- DPRINTF(Ethernet, "receive reset\n");
-
- CRDD = false;
- assert(rxPktBytes == 0);
- rxEnable = false;
- rxFragPtr = 0;
- assert(rxDescCnt == 0);
- assert(rxDmaState == dmaIdle);
- rxFifo.clear();
- rxState = rxIdle;
-}
-
-void
-NSGigE::regsReset()
-{
- memset(&regs, 0, sizeof(regs));
- regs.config = (CFGR_LNKSTS | CFGR_TBI_EN | CFGR_MODE_1000);
- regs.mear = 0x12;
- regs.txcfg = 0x120; // set drain threshold to 1024 bytes and
- // fill threshold to 32 bytes
- regs.rxcfg = 0x4; // set drain threshold to 16 bytes
- regs.srr = 0x0103; // set the silicon revision to rev B or 0x103
- regs.mibc = MIBC_FRZ;
- regs.vdr = 0x81; // set the vlan tag type to 802.1q
- regs.tesr = 0xc000; // TBI capable of both full and half duplex
- regs.brar = 0xffffffff;
-
- extstsEnable = false;
- acceptBroadcast = false;
- acceptMulticast = false;
- acceptUnicast = false;
- acceptPerfect = false;
- 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;
- }
-
- Tick factor = ((rxDmaLen + ULL(63)) >> ULL(6)) * dmaReadFactor;
- Tick start = curTick + dmaReadDelay + factor;
- rxDmaReadEvent.schedule(start);
- return true;
-}
-
-void
-NSGigE::rxDmaReadDone()
-{
- assert(rxDmaState == dmaReading);
- rxDmaReadCopy();
-
- // If the transmit state machine has a pending DMA, let it go first
- if (txDmaState == dmaReadWaiting || txDmaState == dmaWriteWaiting)
- txKick();
-
- 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);
- return true;
-}
-
-void
-NSGigE::rxDmaWriteDone()
-{
- assert(rxDmaState == dmaWriting);
- rxDmaWriteCopy();
-
- // If the transmit state machine has a pending DMA, let it go first
- if (txDmaState == dmaReadWaiting || txDmaState == dmaWriteWaiting)
- txKick();
-
- rxKick();
-}
-
-void
-NSGigE::rxKick()
-{
- bool is64bit = (bool)(regs.config & CFGR_M64ADDR);
-
- DPRINTF(EthernetSM,
- "receive kick rxState=%s (rxBuf.size=%d) %d-bit\n",
- NsRxStateStrings[rxState], rxFifo.size(), is64bit ? 64 : 32);
-
- Addr link, bufptr;
- uint32_t &cmdsts = is64bit ? rxDesc64.cmdsts : rxDesc32.cmdsts;
- uint32_t &extsts = is64bit ? rxDesc64.extsts : rxDesc32.extsts;
-
- next:
- if (clock) {
- if (rxKickTick > curTick) {
- DPRINTF(EthernetSM, "receive kick exiting, can't run till %d\n",
- rxKickTick);
-
- goto exit;
- }
-
- // Go to the next state machine clock tick.
- rxKickTick = curTick + cycles(1);
- }
-
- switch(rxDmaState) {
- case dmaReadWaiting:
- if (doRxDmaRead())
- goto exit;
- break;
- case dmaWriteWaiting:
- if (doRxDmaWrite())
- goto exit;
- break;
- default:
- break;
- }
-
- link = is64bit ? (Addr)rxDesc64.link : (Addr)rxDesc32.link;
- bufptr = is64bit ? (Addr)rxDesc64.bufptr : (Addr)rxDesc32.bufptr;
-
- // see state machine from spec for details
- // the way this works is, if you finish work on one state and can
- // go directly to another, you do that through jumping to the
- // label "next". however, if you have intermediate work, like DMA
- // so that you can't go to the next state yet, you go to exit and
- // exit the loop. however, when the DMA is done it will trigger
- // an event and come back to this loop.
- switch (rxState) {
- case rxIdle:
- if (!rxEnable) {
- DPRINTF(EthernetSM, "Receive Disabled! Nothing to do.\n");
- goto exit;
- }
-
- if (CRDD) {
- rxState = rxDescRefr;
-
- rxDmaAddr = regs.rxdp & 0x3fffffff;
- rxDmaData =
- is64bit ? (void *)&rxDesc64.link : (void *)&rxDesc32.link;
- rxDmaLen = is64bit ? sizeof(rxDesc64.link) : sizeof(rxDesc32.link);
- rxDmaFree = dmaDescFree;
-
- descDmaReads++;
- descDmaRdBytes += rxDmaLen;
-
- if (doRxDmaRead())
- goto exit;
- } else {
- rxState = rxDescRead;
-
- rxDmaAddr = regs.rxdp & 0x3fffffff;
- rxDmaData = is64bit ? (void *)&rxDesc64 : (void *)&rxDesc32;
- rxDmaLen = is64bit ? sizeof(rxDesc64) : sizeof(rxDesc32);
- rxDmaFree = dmaDescFree;
-
- descDmaReads++;
- descDmaRdBytes += rxDmaLen;
-
- if (doRxDmaRead())
- goto exit;
- }
- break;
-
- case rxDescRefr:
- if (rxDmaState != dmaIdle)
- goto exit;
-
- rxState = rxAdvance;
- break;
-
- case rxDescRead:
- if (rxDmaState != dmaIdle)
- goto exit;
-
- DPRINTF(EthernetDesc, "rxDesc: addr=%08x read descriptor\n",
- regs.rxdp & 0x3fffffff);
- DPRINTF(EthernetDesc,
- "rxDesc: link=%#x bufptr=%#x cmdsts=%08x extsts=%08x\n",
- link, bufptr, cmdsts, extsts);
-
- if (cmdsts & CMDSTS_OWN) {
- devIntrPost(ISR_RXIDLE);
- rxState = rxIdle;
- goto exit;
- } else {
- rxState = rxFifoBlock;
- rxFragPtr = bufptr;
- rxDescCnt = cmdsts & CMDSTS_LEN_MASK;
- }
- break;
-
- case rxFifoBlock:
- if (!rxPacket) {
- /**
- * @todo in reality, we should be able to start processing
- * the packet as it arrives, and not have to wait for the
- * full packet ot be in the receive fifo.
- */
- if (rxFifo.empty())
- goto exit;
-
- DPRINTF(EthernetSM, "****processing receive of new packet****\n");
-
- // If we don't have a packet, grab a new one from the fifo.
- rxPacket = rxFifo.front();
- rxPktBytes = rxPacket->length;
- rxPacketBufPtr = rxPacket->data;
-
-#if TRACING_ON
- if (DTRACE(Ethernet)) {
- IpPtr ip(rxPacket);
- if (ip) {
- DPRINTF(Ethernet, "ID is %d\n", ip->id());
- TcpPtr tcp(ip);
- if (tcp) {
- DPRINTF(Ethernet,
- "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n",
- tcp->sport(), tcp->dport(), tcp->seq(),
- tcp->ack());
- }
- }
- }
-#endif
-
- // sanity check - i think the driver behaves like this
- assert(rxDescCnt >= rxPktBytes);
- rxFifo.pop();
- }
-
-
- // dont' need the && rxDescCnt > 0 if driver sanity check
- // above holds
- if (rxPktBytes > 0) {
- rxState = rxFragWrite;
- // don't need min<>(rxPktBytes,rxDescCnt) if above sanity
- // check holds
- rxXferLen = rxPktBytes;
-
- rxDmaAddr = rxFragPtr & 0x3fffffff;
- rxDmaData = rxPacketBufPtr;
- rxDmaLen = rxXferLen;
- rxDmaFree = dmaDataFree;
-
- if (doRxDmaWrite())
- goto exit;
-
- } else {
- rxState = rxDescWrite;
-
- //if (rxPktBytes == 0) { /* packet is done */
- assert(rxPktBytes == 0);
- DPRINTF(EthernetSM, "done with receiving packet\n");
-
- cmdsts |= CMDSTS_OWN;
- cmdsts &= ~CMDSTS_MORE;
- cmdsts |= CMDSTS_OK;
- cmdsts &= 0xffff0000;
- cmdsts += rxPacket->length; //i.e. set CMDSTS_SIZE
-
-#if 0
- /*
- * all the driver uses these are for its own stats keeping
- * which we don't care about, aren't necessary for
- * functionality and doing this would just slow us down.
- * if they end up using this in a later version for
- * functional purposes, just undef
- */
- if (rxFilterEnable) {
- cmdsts &= ~CMDSTS_DEST_MASK;
- const EthAddr &dst = rxFifoFront()->dst();
- if (dst->unicast())
- cmdsts |= CMDSTS_DEST_SELF;
- if (dst->multicast())
- cmdsts |= CMDSTS_DEST_MULTI;
- if (dst->broadcast())
- cmdsts |= CMDSTS_DEST_MASK;
- }
-#endif
-
- IpPtr ip(rxPacket);
- if (extstsEnable && ip) {
- extsts |= EXTSTS_IPPKT;
- rxIpChecksums++;
- if (cksum(ip) != 0) {
- DPRINTF(EthernetCksum, "Rx IP Checksum Error\n");
- extsts |= EXTSTS_IPERR;
- }
- TcpPtr tcp(ip);
- UdpPtr udp(ip);
- if (tcp) {
- extsts |= EXTSTS_TCPPKT;
- rxTcpChecksums++;
- if (cksum(tcp) != 0) {
- DPRINTF(EthernetCksum, "Rx TCP Checksum Error\n");
- extsts |= EXTSTS_TCPERR;
-
- }
- } else if (udp) {
- extsts |= EXTSTS_UDPPKT;
- rxUdpChecksums++;
- if (cksum(udp) != 0) {
- DPRINTF(EthernetCksum, "Rx UDP Checksum Error\n");
- extsts |= EXTSTS_UDPERR;
- }
- }
- }
- rxPacket = 0;
-
- /*
- * the driver seems to always receive into desc buffers
- * of size 1514, so you never have a pkt that is split
- * into multiple descriptors on the receive side, so
- * i don't implement that case, hence the assert above.
- */
-
- DPRINTF(EthernetDesc,
- "rxDesc: addr=%08x writeback cmdsts extsts\n",
- regs.rxdp & 0x3fffffff);
- DPRINTF(EthernetDesc,
- "rxDesc: link=%#x bufptr=%#x cmdsts=%08x extsts=%08x\n",
- link, bufptr, cmdsts, extsts);
-
- rxDmaAddr = regs.rxdp & 0x3fffffff;
- rxDmaData = &cmdsts;
- if (is64bit) {
- rxDmaAddr += offsetof(ns_desc64, cmdsts);
- rxDmaLen = sizeof(rxDesc64.cmdsts) + sizeof(rxDesc64.extsts);
- } else {
- rxDmaAddr += offsetof(ns_desc32, cmdsts);
- rxDmaLen = sizeof(rxDesc32.cmdsts) + sizeof(rxDesc32.extsts);
- }
- rxDmaFree = dmaDescFree;
-
- descDmaWrites++;
- descDmaWrBytes += rxDmaLen;
-
- if (doRxDmaWrite())
- goto exit;
- }
- break;
-
- case rxFragWrite:
- if (rxDmaState != dmaIdle)
- goto exit;
-
- rxPacketBufPtr += rxXferLen;
- rxFragPtr += rxXferLen;
- rxPktBytes -= rxXferLen;
-
- rxState = rxFifoBlock;
- break;
-
- case rxDescWrite:
- if (rxDmaState != dmaIdle)
- goto exit;
-
- assert(cmdsts & CMDSTS_OWN);
-
- assert(rxPacket == 0);
- devIntrPost(ISR_RXOK);
-
- if (cmdsts & CMDSTS_INTR)
- devIntrPost(ISR_RXDESC);
-
- if (!rxEnable) {
- DPRINTF(EthernetSM, "Halting the RX state machine\n");
- rxState = rxIdle;
- goto exit;
- } else
- rxState = rxAdvance;
- break;
-
- case rxAdvance:
- if (link == 0) {
- devIntrPost(ISR_RXIDLE);
- rxState = rxIdle;
- CRDD = true;
- goto exit;
- } else {
- if (rxDmaState != dmaIdle)
- goto exit;
- rxState = rxDescRead;
- regs.rxdp = link;
- CRDD = false;
-
- rxDmaAddr = regs.rxdp & 0x3fffffff;
- rxDmaData = is64bit ? (void *)&rxDesc64 : (void *)&rxDesc32;
- rxDmaLen = is64bit ? sizeof(rxDesc64) : sizeof(rxDesc32);
- rxDmaFree = dmaDescFree;
-
- if (doRxDmaRead())
- goto exit;
- }
- break;
-
- default:
- panic("Invalid rxState!");
- }
-
- DPRINTF(EthernetSM, "entering next rxState=%s\n",
- NsRxStateStrings[rxState]);
- goto next;
-
- exit:
- /**
- * @todo do we want to schedule a future kick?
- */
- DPRINTF(EthernetSM, "rx state machine exited rxState=%s\n",
- NsRxStateStrings[rxState]);
-
- if (clock && !rxKickEvent.scheduled())
- rxKickEvent.schedule(rxKickTick);
-}
-
-void
-NSGigE::transmit()
-{
- if (txFifo.empty()) {
- DPRINTF(Ethernet, "nothing to transmit\n");
- return;
- }
-
- DPRINTF(Ethernet, "Attempt Pkt Transmit: txFifo length=%d\n",
- txFifo.size());
- if (interface->sendPacket(txFifo.front())) {
-#if TRACING_ON
- if (DTRACE(Ethernet)) {
- IpPtr ip(txFifo.front());
- if (ip) {
- DPRINTF(Ethernet, "ID is %d\n", ip->id());
- TcpPtr tcp(ip);
- if (tcp) {
- DPRINTF(Ethernet,
- "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n",
- tcp->sport(), tcp->dport(), tcp->seq(),
- tcp->ack());
- }
- }
- }
-#endif
-
- DDUMP(EthernetData, txFifo.front()->data, txFifo.front()->length);
- txBytes += txFifo.front()->length;
- txPackets++;
-
- DPRINTF(Ethernet, "Successful Xmit! now txFifoAvail is %d\n",
- txFifo.avail());
- txFifo.pop();
-
- /*
- * normally do a writeback of the descriptor here, and ONLY
- * after that is done, send this interrupt. but since our
- * stuff never actually fails, just do this interrupt here,
- * otherwise the code has to stray from this nice format.
- * besides, it's functionally the same.
- */
- devIntrPost(ISR_TXOK);
- }
-
- if (!txFifo.empty() && !txEvent.scheduled()) {
- DPRINTF(Ethernet, "reschedule transmit\n");
- txEvent.schedule(curTick + retryTime);
- }
-}
-
-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;
- }
-
- Tick factor = ((txDmaLen + ULL(63)) >> ULL(6)) * dmaReadFactor;
- Tick start = curTick + dmaReadDelay + factor;
- txDmaReadEvent.schedule(start);
- return true;
-}
-
-void
-NSGigE::txDmaReadDone()
-{
- assert(txDmaState == dmaReading);
- txDmaReadCopy();
-
- // If the receive state machine has a pending DMA, let it go first
- if (rxDmaState == dmaReadWaiting || rxDmaState == dmaWriteWaiting)
- rxKick();
-
- 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);
- return true;
-}
-
-void
-NSGigE::txDmaWriteDone()
-{
- assert(txDmaState == dmaWriting);
- txDmaWriteCopy();
-
- // If the receive state machine has a pending DMA, let it go first
- if (rxDmaState == dmaReadWaiting || rxDmaState == dmaWriteWaiting)
- rxKick();
-
- txKick();
-}
-
-void
-NSGigE::txKick()
-{
- bool is64bit = (bool)(regs.config & CFGR_M64ADDR);
-
- DPRINTF(EthernetSM, "transmit kick txState=%s %d-bit\n",
- NsTxStateStrings[txState], is64bit ? 64 : 32);
-
- Addr link, bufptr;
- uint32_t &cmdsts = is64bit ? txDesc64.cmdsts : txDesc32.cmdsts;
- uint32_t &extsts = is64bit ? txDesc64.extsts : txDesc32.extsts;
-
- next:
- if (clock) {
- if (txKickTick > curTick) {
- DPRINTF(EthernetSM, "transmit kick exiting, can't run till %d\n",
- txKickTick);
- goto exit;
- }
-
- // Go to the next state machine clock tick.
- txKickTick = curTick + cycles(1);
- }
-
- switch(txDmaState) {
- case dmaReadWaiting:
- if (doTxDmaRead())
- goto exit;
- break;
- case dmaWriteWaiting:
- if (doTxDmaWrite())
- goto exit;
- break;
- default:
- break;
- }
-
- link = is64bit ? (Addr)txDesc64.link : (Addr)txDesc32.link;
- bufptr = is64bit ? (Addr)txDesc64.bufptr : (Addr)txDesc32.bufptr;
- switch (txState) {
- case txIdle:
- if (!txEnable) {
- DPRINTF(EthernetSM, "Transmit disabled. Nothing to do.\n");
- goto exit;
- }
-
- if (CTDD) {
- txState = txDescRefr;
-
- txDmaAddr = regs.txdp & 0x3fffffff;
- txDmaData =
- is64bit ? (void *)&txDesc64.link : (void *)&txDesc32.link;
- txDmaLen = is64bit ? sizeof(txDesc64.link) : sizeof(txDesc32.link);
- txDmaFree = dmaDescFree;
-
- descDmaReads++;
- descDmaRdBytes += txDmaLen;
-
- if (doTxDmaRead())
- goto exit;
-
- } else {
- txState = txDescRead;
-
- txDmaAddr = regs.txdp & 0x3fffffff;
- txDmaData = is64bit ? (void *)&txDesc64 : (void *)&txDesc32;
- txDmaLen = is64bit ? sizeof(txDesc64) : sizeof(txDesc32);
- txDmaFree = dmaDescFree;
-
- descDmaReads++;
- descDmaRdBytes += txDmaLen;
-
- if (doTxDmaRead())
- goto exit;
- }
- break;
-
- case txDescRefr:
- if (txDmaState != dmaIdle)
- goto exit;
-
- txState = txAdvance;
- break;
-
- case txDescRead:
- if (txDmaState != dmaIdle)
- goto exit;
-
- DPRINTF(EthernetDesc, "txDesc: addr=%08x read descriptor\n",
- regs.txdp & 0x3fffffff);
- DPRINTF(EthernetDesc,
- "txDesc: link=%#x bufptr=%#x cmdsts=%#08x extsts=%#08x\n",
- link, bufptr, cmdsts, extsts);
-
- if (cmdsts & CMDSTS_OWN) {
- txState = txFifoBlock;
- txFragPtr = bufptr;
- txDescCnt = cmdsts & CMDSTS_LEN_MASK;
- } else {
- devIntrPost(ISR_TXIDLE);
- txState = txIdle;
- goto exit;
- }
- break;
-
- case txFifoBlock:
- if (!txPacket) {
- DPRINTF(EthernetSM, "****starting the tx of a new packet****\n");
- txPacket = new PacketData(16384);
- txPacketBufPtr = txPacket->data;
- }
-
- if (txDescCnt == 0) {
- DPRINTF(EthernetSM, "the txDescCnt == 0, done with descriptor\n");
- if (cmdsts & CMDSTS_MORE) {
- DPRINTF(EthernetSM, "there are more descriptors to come\n");
- txState = txDescWrite;
-
- cmdsts &= ~CMDSTS_OWN;
-
- txDmaAddr = regs.txdp & 0x3fffffff;
- txDmaData = &cmdsts;
- if (is64bit) {
- txDmaAddr += offsetof(ns_desc64, cmdsts);
- txDmaLen = sizeof(txDesc64.cmdsts);
- } else {
- txDmaAddr += offsetof(ns_desc32, cmdsts);
- txDmaLen = sizeof(txDesc32.cmdsts);
- }
- txDmaFree = dmaDescFree;
-
- if (doTxDmaWrite())
- goto exit;
-
- } else { /* this packet is totally done */
- DPRINTF(EthernetSM, "This packet is done, let's wrap it up\n");
- /* deal with the the packet that just finished */
- if ((regs.vtcr & VTCR_PPCHK) && extstsEnable) {
- IpPtr ip(txPacket);
- if (extsts & EXTSTS_UDPPKT) {
- UdpPtr udp(ip);
- udp->sum(0);
- udp->sum(cksum(udp));
- txUdpChecksums++;
- } else if (extsts & EXTSTS_TCPPKT) {
- TcpPtr tcp(ip);
- tcp->sum(0);
- tcp->sum(cksum(tcp));
- txTcpChecksums++;
- }
- if (extsts & EXTSTS_IPPKT) {
- ip->sum(0);
- ip->sum(cksum(ip));
- txIpChecksums++;
- }
- }
-
- txPacket->length = txPacketBufPtr - txPacket->data;
- // this is just because the receive can't handle a
- // packet bigger want to make sure
- if (txPacket->length > 1514)
- panic("transmit packet too large, %s > 1514\n",
- txPacket->length);
-
-#ifndef NDEBUG
- bool success =
-#endif
- txFifo.push(txPacket);
- assert(success);
-
- /*
- * this following section is not tqo spec, but
- * functionally shouldn't be any different. normally,
- * the chip will wait til the transmit has occurred
- * before writing back the descriptor because it has
- * to wait to see that it was successfully transmitted
- * to decide whether to set CMDSTS_OK or not.
- * however, in the simulator since it is always
- * successfully transmitted, and writing it exactly to
- * spec would complicate the code, we just do it here
- */
-
- cmdsts &= ~CMDSTS_OWN;
- cmdsts |= CMDSTS_OK;
-
- DPRINTF(EthernetDesc,
- "txDesc writeback: cmdsts=%08x extsts=%08x\n",
- cmdsts, extsts);
-
- txDmaFree = dmaDescFree;
- txDmaAddr = regs.txdp & 0x3fffffff;
- txDmaData = &cmdsts;
- if (is64bit) {
- txDmaAddr += offsetof(ns_desc64, cmdsts);
- txDmaLen =
- sizeof(txDesc64.cmdsts) + sizeof(txDesc64.extsts);
- } else {
- txDmaAddr += offsetof(ns_desc32, cmdsts);
- txDmaLen =
- sizeof(txDesc32.cmdsts) + sizeof(txDesc32.extsts);
- }
-
- descDmaWrites++;
- descDmaWrBytes += txDmaLen;
-
- transmit();
- txPacket = 0;
-
- if (!txEnable) {
- DPRINTF(EthernetSM, "halting TX state machine\n");
- txState = txIdle;
- goto exit;
- } else
- txState = txAdvance;
-
- if (doTxDmaWrite())
- goto exit;
- }
- } else {
- DPRINTF(EthernetSM, "this descriptor isn't done yet\n");
- if (!txFifo.full()) {
- txState = txFragRead;
-
- /*
- * The number of bytes transferred is either whatever
- * is left in the descriptor (txDescCnt), or if there
- * is not enough room in the fifo, just whatever room
- * is left in the fifo
- */
- txXferLen = min<uint32_t>(txDescCnt, txFifo.avail());
-
- txDmaAddr = txFragPtr & 0x3fffffff;
- txDmaData = txPacketBufPtr;
- txDmaLen = txXferLen;
- txDmaFree = dmaDataFree;
-
- if (doTxDmaRead())
- goto exit;
- } else {
- txState = txFifoBlock;
- transmit();
-
- goto exit;
- }
-
- }
- break;
-
- case txFragRead:
- if (txDmaState != dmaIdle)
- goto exit;
-
- txPacketBufPtr += txXferLen;
- txFragPtr += txXferLen;
- txDescCnt -= txXferLen;
- txFifo.reserve(txXferLen);
-
- txState = txFifoBlock;
- break;
-
- case txDescWrite:
- if (txDmaState != dmaIdle)
- goto exit;
-
- if (cmdsts & CMDSTS_INTR)
- devIntrPost(ISR_TXDESC);
-
- if (!txEnable) {
- DPRINTF(EthernetSM, "halting TX state machine\n");
- txState = txIdle;
- goto exit;
- } else
- txState = txAdvance;
- break;
-
- case txAdvance:
- if (link == 0) {
- devIntrPost(ISR_TXIDLE);
- txState = txIdle;
- goto exit;
- } else {
- if (txDmaState != dmaIdle)
- goto exit;
- txState = txDescRead;
- regs.txdp = link;
- CTDD = false;
-
- txDmaAddr = link & 0x3fffffff;
- txDmaData = is64bit ? (void *)&txDesc64 : (void *)&txDesc32;
- txDmaLen = is64bit ? sizeof(txDesc64) : sizeof(txDesc32);
- txDmaFree = dmaDescFree;
-
- if (doTxDmaRead())
- goto exit;
- }
- break;
-
- default:
- panic("invalid state");
- }
-
- DPRINTF(EthernetSM, "entering next txState=%s\n",
- NsTxStateStrings[txState]);
- goto next;
-
- exit:
- /**
- * @todo do we want to schedule a future kick?
- */
- DPRINTF(EthernetSM, "tx state machine exited txState=%s\n",
- NsTxStateStrings[txState]);
-
- if (clock && !txKickEvent.scheduled())
- txKickEvent.schedule(txKickTick);
-}
-
-/**
- * Advance the EEPROM state machine
- * Called on rising edge of EEPROM clock bit in MEAR
- */
-void
-NSGigE::eepromKick()
-{
- switch (eepromState) {
-
- case eepromStart:
-
- // Wait for start bit
- if (regs.mear & MEAR_EEDI) {
- // Set up to get 2 opcode bits
- eepromState = eepromGetOpcode;
- eepromBitsToRx = 2;
- eepromOpcode = 0;
- }
- break;
-
- case eepromGetOpcode:
- eepromOpcode <<= 1;
- eepromOpcode += (regs.mear & MEAR_EEDI) ? 1 : 0;
- --eepromBitsToRx;
-
- // Done getting opcode
- if (eepromBitsToRx == 0) {
- if (eepromOpcode != EEPROM_READ)
- panic("only EEPROM reads are implemented!");
-
- // Set up to get address
- eepromState = eepromGetAddress;
- eepromBitsToRx = 6;
- eepromAddress = 0;
- }
- break;
-
- case eepromGetAddress:
- eepromAddress <<= 1;
- eepromAddress += (regs.mear & MEAR_EEDI) ? 1 : 0;
- --eepromBitsToRx;
-
- // Done getting address
- if (eepromBitsToRx == 0) {
-
- if (eepromAddress >= EEPROM_SIZE)
- panic("EEPROM read access out of range!");
-
- switch (eepromAddress) {
-
- case EEPROM_PMATCH2_ADDR:
- eepromData = rom.perfectMatch[5];
- eepromData <<= 8;
- eepromData += rom.perfectMatch[4];
- break;
-
- case EEPROM_PMATCH1_ADDR:
- eepromData = rom.perfectMatch[3];
- eepromData <<= 8;
- eepromData += rom.perfectMatch[2];
- break;
-
- case EEPROM_PMATCH0_ADDR:
- eepromData = rom.perfectMatch[1];
- eepromData <<= 8;
- eepromData += rom.perfectMatch[0];
- break;
-
- default:
- panic("FreeBSD driver only uses EEPROM to read PMATCH!");
- }
- // Set up to read data
- eepromState = eepromRead;
- eepromBitsToRx = 16;
-
- // Clear data in bit
- regs.mear &= ~MEAR_EEDI;
- }
- break;
-
- case eepromRead:
- // Clear Data Out bit
- regs.mear &= ~MEAR_EEDO;
- // Set bit to value of current EEPROM bit
- regs.mear |= (eepromData & 0x8000) ? MEAR_EEDO : 0x0;
-
- eepromData <<= 1;
- --eepromBitsToRx;
-
- // All done
- if (eepromBitsToRx == 0) {
- eepromState = eepromStart;
- }
- break;
-
- default:
- panic("invalid EEPROM state");
- }
-
-}
-
-void
-NSGigE::transferDone()
-{
- if (txFifo.empty()) {
- DPRINTF(Ethernet, "transfer complete: txFifo empty...nothing to do\n");
- return;
- }
-
- DPRINTF(Ethernet, "transfer complete: data in txFifo...schedule xmit\n");
-
- if (txEvent.scheduled())
- txEvent.reschedule(curTick + cycles(1));
- else
- txEvent.schedule(curTick + cycles(1));
-}
-
-bool
-NSGigE::rxFilter(const PacketPtr &packet)
-{
- EthPtr eth = packet;
- bool drop = true;
- string type;
-
- const EthAddr &dst = eth->dst();
- if (dst.unicast()) {
- // If we're accepting all unicast addresses
- if (acceptUnicast)
- drop = false;
-
- // If we make a perfect match
- if (acceptPerfect && dst == rom.perfectMatch)
- drop = false;
-
- if (acceptArp && eth->type() == ETH_TYPE_ARP)
- drop = false;
-
- } else if (dst.broadcast()) {
- // if we're accepting broadcasts
- if (acceptBroadcast)
- drop = false;
-
- } else if (dst.multicast()) {
- // if we're accepting all multicasts
- if (acceptMulticast)
- drop = false;
-
- // Multicast hashing faked - all packets accepted
- if (multicastHashEnable)
- drop = false;
- }
-
- if (drop) {
- DPRINTF(Ethernet, "rxFilter drop\n");
- DDUMP(EthernetData, packet->data, packet->length);
- }
-
- return drop;
-}
-
-bool
-NSGigE::recvPacket(PacketPtr packet)
-{
- rxBytes += packet->length;
- rxPackets++;
-
- DPRINTF(Ethernet, "Receiving packet from wire, rxFifoAvail=%d\n",
- rxFifo.avail());
-
- if (!rxEnable) {
- DPRINTF(Ethernet, "receive disabled...packet dropped\n");
- return true;
- }
-
- if (!rxFilterEnable) {
- DPRINTF(Ethernet,
- "receive packet filtering disabled . . . packet dropped\n");
- return true;
- }
-
- if (rxFilter(packet)) {
- DPRINTF(Ethernet, "packet filtered...dropped\n");
- return true;
- }
-
- if (rxFifo.avail() < packet->length) {
-#if TRACING_ON
- IpPtr ip(packet);
- TcpPtr tcp(ip);
- if (ip) {
- DPRINTF(Ethernet,
- "packet won't fit in receive buffer...pkt ID %d dropped\n",
- ip->id());
- if (tcp) {
- DPRINTF(Ethernet, "Seq=%d\n", tcp->seq());
- }
- }
-#endif
- droppedPackets++;
- devIntrPost(ISR_RXORN);
- return false;
- }
-
- rxFifo.push(packet);
-
- rxKick();
- return true;
-}
-
-//=====================================================================
-//
-//
-void
-NSGigE::serialize(ostream &os)
-{
- // Serialize the PciDev base class
- PciDev::serialize(os);
-
- /*
- * Finalize any DMA events now.
- */
- if (rxDmaReadEvent.scheduled())
- rxDmaReadCopy();
- if (rxDmaWriteEvent.scheduled())
- rxDmaWriteCopy();
- if (txDmaReadEvent.scheduled())
- txDmaReadCopy();
- if (txDmaWriteEvent.scheduled())
- txDmaWriteCopy();
-
- /*
- * Serialize the device registers
- */
- SERIALIZE_SCALAR(regs.command);
- SERIALIZE_SCALAR(regs.config);
- SERIALIZE_SCALAR(regs.mear);
- SERIALIZE_SCALAR(regs.ptscr);
- SERIALIZE_SCALAR(regs.isr);
- SERIALIZE_SCALAR(regs.imr);
- SERIALIZE_SCALAR(regs.ier);
- SERIALIZE_SCALAR(regs.ihr);
- SERIALIZE_SCALAR(regs.txdp);
- SERIALIZE_SCALAR(regs.txdp_hi);
- SERIALIZE_SCALAR(regs.txcfg);
- SERIALIZE_SCALAR(regs.gpior);
- SERIALIZE_SCALAR(regs.rxdp);
- SERIALIZE_SCALAR(regs.rxdp_hi);
- SERIALIZE_SCALAR(regs.rxcfg);
- SERIALIZE_SCALAR(regs.pqcr);
- SERIALIZE_SCALAR(regs.wcsr);
- SERIALIZE_SCALAR(regs.pcr);
- SERIALIZE_SCALAR(regs.rfcr);
- SERIALIZE_SCALAR(regs.rfdr);
- SERIALIZE_SCALAR(regs.brar);
- SERIALIZE_SCALAR(regs.brdr);
- SERIALIZE_SCALAR(regs.srr);
- SERIALIZE_SCALAR(regs.mibc);
- SERIALIZE_SCALAR(regs.vrcr);
- SERIALIZE_SCALAR(regs.vtcr);
- SERIALIZE_SCALAR(regs.vdr);
- SERIALIZE_SCALAR(regs.ccsr);
- SERIALIZE_SCALAR(regs.tbicr);
- SERIALIZE_SCALAR(regs.tbisr);
- SERIALIZE_SCALAR(regs.tanar);
- SERIALIZE_SCALAR(regs.tanlpar);
- SERIALIZE_SCALAR(regs.taner);
- SERIALIZE_SCALAR(regs.tesr);
-
- SERIALIZE_ARRAY(rom.perfectMatch, ETH_ADDR_LEN);
- SERIALIZE_ARRAY(rom.filterHash, FHASH_SIZE);
-
- SERIALIZE_SCALAR(ioEnable);
-
- /*
- * Serialize the data Fifos
- */
- rxFifo.serialize("rxFifo", os);
- txFifo.serialize("txFifo", os);
-
- /*
- * Serialize the various helper variables
- */
- bool txPacketExists = txPacket;
- SERIALIZE_SCALAR(txPacketExists);
- if (txPacketExists) {
- txPacket->length = txPacketBufPtr - txPacket->data;
- txPacket->serialize("txPacket", os);
- uint32_t txPktBufPtr = (uint32_t) (txPacketBufPtr - txPacket->data);
- SERIALIZE_SCALAR(txPktBufPtr);
- }
-
- bool rxPacketExists = rxPacket;
- SERIALIZE_SCALAR(rxPacketExists);
- if (rxPacketExists) {
- rxPacket->serialize("rxPacket", os);
- uint32_t rxPktBufPtr = (uint32_t) (rxPacketBufPtr - rxPacket->data);
- SERIALIZE_SCALAR(rxPktBufPtr);
- }
-
- SERIALIZE_SCALAR(txXferLen);
- SERIALIZE_SCALAR(rxXferLen);
-
- /*
- * Serialize Cached Descriptors
- */
- SERIALIZE_SCALAR(rxDesc64.link);
- SERIALIZE_SCALAR(rxDesc64.bufptr);
- SERIALIZE_SCALAR(rxDesc64.cmdsts);
- SERIALIZE_SCALAR(rxDesc64.extsts);
- SERIALIZE_SCALAR(txDesc64.link);
- SERIALIZE_SCALAR(txDesc64.bufptr);
- SERIALIZE_SCALAR(txDesc64.cmdsts);
- SERIALIZE_SCALAR(txDesc64.extsts);
- SERIALIZE_SCALAR(rxDesc32.link);
- SERIALIZE_SCALAR(rxDesc32.bufptr);
- SERIALIZE_SCALAR(rxDesc32.cmdsts);
- SERIALIZE_SCALAR(rxDesc32.extsts);
- SERIALIZE_SCALAR(txDesc32.link);
- SERIALIZE_SCALAR(txDesc32.bufptr);
- SERIALIZE_SCALAR(txDesc32.cmdsts);
- SERIALIZE_SCALAR(txDesc32.extsts);
- SERIALIZE_SCALAR(extstsEnable);
-
- /*
- * Serialize tx state machine
- */
- int txState = this->txState;
- SERIALIZE_SCALAR(txState);
- SERIALIZE_SCALAR(txEnable);
- SERIALIZE_SCALAR(CTDD);
- SERIALIZE_SCALAR(txFragPtr);
- SERIALIZE_SCALAR(txDescCnt);
- int txDmaState = this->txDmaState;
- SERIALIZE_SCALAR(txDmaState);
- SERIALIZE_SCALAR(txKickTick);
-
- /*
- * Serialize rx state machine
- */
- int rxState = this->rxState;
- SERIALIZE_SCALAR(rxState);
- SERIALIZE_SCALAR(rxEnable);
- SERIALIZE_SCALAR(CRDD);
- SERIALIZE_SCALAR(rxPktBytes);
- SERIALIZE_SCALAR(rxFragPtr);
- SERIALIZE_SCALAR(rxDescCnt);
- int rxDmaState = this->rxDmaState;
- SERIALIZE_SCALAR(rxDmaState);
- SERIALIZE_SCALAR(rxKickTick);
-
- /*
- * Serialize EEPROM state machine
- */
- int eepromState = this->eepromState;
- SERIALIZE_SCALAR(eepromState);
- SERIALIZE_SCALAR(eepromClk);
- SERIALIZE_SCALAR(eepromBitsToRx);
- SERIALIZE_SCALAR(eepromOpcode);
- SERIALIZE_SCALAR(eepromAddress);
- SERIALIZE_SCALAR(eepromData);
-
- /*
- * If there's a pending transmit, store the time so we can
- * reschedule it later
- */
- Tick transmitTick = txEvent.scheduled() ? txEvent.when() - curTick : 0;
- SERIALIZE_SCALAR(transmitTick);
-
- /*
- * receive address filter settings
- */
- SERIALIZE_SCALAR(rxFilterEnable);
- SERIALIZE_SCALAR(acceptBroadcast);
- SERIALIZE_SCALAR(acceptMulticast);
- SERIALIZE_SCALAR(acceptUnicast);
- SERIALIZE_SCALAR(acceptPerfect);
- SERIALIZE_SCALAR(acceptArp);
- SERIALIZE_SCALAR(multicastHashEnable);
-
- /*
- * Keep track of pending interrupt status.
- */
- SERIALIZE_SCALAR(intrTick);
- SERIALIZE_SCALAR(cpuPendingIntr);
- Tick intrEventTick = 0;
- if (intrEvent)
- intrEventTick = intrEvent->when();
- SERIALIZE_SCALAR(intrEventTick);
-
-}
-
-void
-NSGigE::unserialize(Checkpoint *cp, const std::string &section)
-{
- // Unserialize the PciDev base class
- PciDev::unserialize(cp, section);
-
- UNSERIALIZE_SCALAR(regs.command);
- UNSERIALIZE_SCALAR(regs.config);
- UNSERIALIZE_SCALAR(regs.mear);
- UNSERIALIZE_SCALAR(regs.ptscr);
- UNSERIALIZE_SCALAR(regs.isr);
- UNSERIALIZE_SCALAR(regs.imr);
- UNSERIALIZE_SCALAR(regs.ier);
- UNSERIALIZE_SCALAR(regs.ihr);
- UNSERIALIZE_SCALAR(regs.txdp);
- UNSERIALIZE_SCALAR(regs.txdp_hi);
- UNSERIALIZE_SCALAR(regs.txcfg);
- UNSERIALIZE_SCALAR(regs.gpior);
- UNSERIALIZE_SCALAR(regs.rxdp);
- UNSERIALIZE_SCALAR(regs.rxdp_hi);
- UNSERIALIZE_SCALAR(regs.rxcfg);
- UNSERIALIZE_SCALAR(regs.pqcr);
- UNSERIALIZE_SCALAR(regs.wcsr);
- UNSERIALIZE_SCALAR(regs.pcr);
- UNSERIALIZE_SCALAR(regs.rfcr);
- UNSERIALIZE_SCALAR(regs.rfdr);
- UNSERIALIZE_SCALAR(regs.brar);
- UNSERIALIZE_SCALAR(regs.brdr);
- UNSERIALIZE_SCALAR(regs.srr);
- UNSERIALIZE_SCALAR(regs.mibc);
- UNSERIALIZE_SCALAR(regs.vrcr);
- UNSERIALIZE_SCALAR(regs.vtcr);
- UNSERIALIZE_SCALAR(regs.vdr);
- UNSERIALIZE_SCALAR(regs.ccsr);
- UNSERIALIZE_SCALAR(regs.tbicr);
- UNSERIALIZE_SCALAR(regs.tbisr);
- UNSERIALIZE_SCALAR(regs.tanar);
- UNSERIALIZE_SCALAR(regs.tanlpar);
- UNSERIALIZE_SCALAR(regs.taner);
- UNSERIALIZE_SCALAR(regs.tesr);
-
- UNSERIALIZE_ARRAY(rom.perfectMatch, ETH_ADDR_LEN);
- UNSERIALIZE_ARRAY(rom.filterHash, FHASH_SIZE);
-
- UNSERIALIZE_SCALAR(ioEnable);
-
- /*
- * unserialize the data fifos
- */
- rxFifo.unserialize("rxFifo", cp, section);
- txFifo.unserialize("txFifo", cp, section);
-
- /*
- * unserialize the various helper variables
- */
- bool txPacketExists;
- UNSERIALIZE_SCALAR(txPacketExists);
- if (txPacketExists) {
- txPacket = new PacketData(16384);
- txPacket->unserialize("txPacket", cp, section);
- uint32_t txPktBufPtr;
- UNSERIALIZE_SCALAR(txPktBufPtr);
- txPacketBufPtr = (uint8_t *) txPacket->data + txPktBufPtr;
- } else
- txPacket = 0;
-
- bool rxPacketExists;
- UNSERIALIZE_SCALAR(rxPacketExists);
- rxPacket = 0;
- if (rxPacketExists) {
- rxPacket = new PacketData(16384);
- rxPacket->unserialize("rxPacket", cp, section);
- uint32_t rxPktBufPtr;
- UNSERIALIZE_SCALAR(rxPktBufPtr);
- rxPacketBufPtr = (uint8_t *) rxPacket->data + rxPktBufPtr;
- } else
- rxPacket = 0;
-
- UNSERIALIZE_SCALAR(txXferLen);
- UNSERIALIZE_SCALAR(rxXferLen);
-
- /*
- * Unserialize Cached Descriptors
- */
- UNSERIALIZE_SCALAR(rxDesc64.link);
- UNSERIALIZE_SCALAR(rxDesc64.bufptr);
- UNSERIALIZE_SCALAR(rxDesc64.cmdsts);
- UNSERIALIZE_SCALAR(rxDesc64.extsts);
- UNSERIALIZE_SCALAR(txDesc64.link);
- UNSERIALIZE_SCALAR(txDesc64.bufptr);
- UNSERIALIZE_SCALAR(txDesc64.cmdsts);
- UNSERIALIZE_SCALAR(txDesc64.extsts);
- UNSERIALIZE_SCALAR(rxDesc32.link);
- UNSERIALIZE_SCALAR(rxDesc32.bufptr);
- UNSERIALIZE_SCALAR(rxDesc32.cmdsts);
- UNSERIALIZE_SCALAR(rxDesc32.extsts);
- UNSERIALIZE_SCALAR(txDesc32.link);
- UNSERIALIZE_SCALAR(txDesc32.bufptr);
- UNSERIALIZE_SCALAR(txDesc32.cmdsts);
- UNSERIALIZE_SCALAR(txDesc32.extsts);
- UNSERIALIZE_SCALAR(extstsEnable);
-
- /*
- * unserialize tx state machine
- */
- int txState;
- UNSERIALIZE_SCALAR(txState);
- this->txState = (TxState) txState;
- UNSERIALIZE_SCALAR(txEnable);
- UNSERIALIZE_SCALAR(CTDD);
- UNSERIALIZE_SCALAR(txFragPtr);
- UNSERIALIZE_SCALAR(txDescCnt);
- int txDmaState;
- UNSERIALIZE_SCALAR(txDmaState);
- this->txDmaState = (DmaState) txDmaState;
- UNSERIALIZE_SCALAR(txKickTick);
- if (txKickTick)
- txKickEvent.schedule(txKickTick);
-
- /*
- * unserialize rx state machine
- */
- int rxState;
- UNSERIALIZE_SCALAR(rxState);
- this->rxState = (RxState) rxState;
- UNSERIALIZE_SCALAR(rxEnable);
- UNSERIALIZE_SCALAR(CRDD);
- UNSERIALIZE_SCALAR(rxPktBytes);
- UNSERIALIZE_SCALAR(rxFragPtr);
- UNSERIALIZE_SCALAR(rxDescCnt);
- int rxDmaState;
- UNSERIALIZE_SCALAR(rxDmaState);
- this->rxDmaState = (DmaState) rxDmaState;
- UNSERIALIZE_SCALAR(rxKickTick);
- if (rxKickTick)
- rxKickEvent.schedule(rxKickTick);
-
- /*
- * Unserialize EEPROM state machine
- */
- int eepromState;
- UNSERIALIZE_SCALAR(eepromState);
- this->eepromState = (EEPROMState) eepromState;
- UNSERIALIZE_SCALAR(eepromClk);
- UNSERIALIZE_SCALAR(eepromBitsToRx);
- UNSERIALIZE_SCALAR(eepromOpcode);
- UNSERIALIZE_SCALAR(eepromAddress);
- UNSERIALIZE_SCALAR(eepromData);
-
- /*
- * If there's a pending transmit, reschedule it now
- */
- Tick transmitTick;
- UNSERIALIZE_SCALAR(transmitTick);
- if (transmitTick)
- txEvent.schedule(curTick + transmitTick);
-
- /*
- * unserialize receive address filter settings
- */
- UNSERIALIZE_SCALAR(rxFilterEnable);
- UNSERIALIZE_SCALAR(acceptBroadcast);
- UNSERIALIZE_SCALAR(acceptMulticast);
- UNSERIALIZE_SCALAR(acceptUnicast);
- UNSERIALIZE_SCALAR(acceptPerfect);
- UNSERIALIZE_SCALAR(acceptArp);
- UNSERIALIZE_SCALAR(multicastHashEnable);
-
- /*
- * Keep track of pending interrupt status.
- */
- UNSERIALIZE_SCALAR(intrTick);
- UNSERIALIZE_SCALAR(cpuPendingIntr);
- Tick intrEventTick;
- UNSERIALIZE_SCALAR(intrEventTick);
- if (intrEventTick) {
- 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)
-
- SimObjectParam<EtherInt *> peer;
- SimObjectParam<NSGigE *> device;
-
-END_DECLARE_SIM_OBJECT_PARAMS(NSGigEInt)
-
-BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigEInt)
-
- INIT_PARAM_DFLT(peer, "peer interface", NULL),
- INIT_PARAM(device, "Ethernet device of this interface")
-
-END_INIT_SIM_OBJECT_PARAMS(NSGigEInt)
-
-CREATE_SIM_OBJECT(NSGigEInt)
-{
- NSGigEInt *dev_int = new NSGigEInt(getInstanceName(), device);
-
- EtherInt *p = (EtherInt *)peer;
- if (p) {
- dev_int->setPeer(p);
- p->setPeer(dev_int);
- }
-
- return dev_int;
-}
-
-REGISTER_SIM_OBJECT("NSGigEInt", NSGigEInt)
-
-
-BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigE)
-
- Param<Tick> clock;
-
- Param<Addr> addr;
- SimObjectParam<MemoryController *> mmu;
- SimObjectParam<PhysicalMemory *> physmem;
- 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<HierParams *> hier;
- SimObjectParam<Bus*> pio_bus;
- SimObjectParam<Bus*> dma_bus;
- SimObjectParam<Bus*> payload_bus;
- Param<bool> dma_desc_free;
- Param<bool> dma_data_free;
- Param<Tick> dma_read_delay;
- Param<Tick> dma_write_delay;
- 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;
- Param<Tick> tx_delay;
- Param<uint32_t> rx_fifo_size;
- Param<uint32_t> tx_fifo_size;
-
- Param<bool> rx_filter;
- Param<string> hardware_address;
- Param<bool> rx_thread;
- Param<bool> tx_thread;
- Param<bool> rss;
-
-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(configspace, "PCI Configspace"),
- INIT_PARAM(configdata, "PCI Config data"),
- INIT_PARAM(platform, "Platform"),
- INIT_PARAM(pci_bus, "PCI bus"),
- INIT_PARAM(pci_dev, "PCI device number"),
- INIT_PARAM(pci_func, "PCI function code"),
-
- 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"),
- INIT_PARAM(dma_write_delay, "fixed delay for dma writes"),
- 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"),
- INIT_PARAM(tx_delay, "Transmit Delay"),
- INIT_PARAM(rx_fifo_size, "max size in bytes of rxFifo"),
- INIT_PARAM(tx_fifo_size, "max size in bytes of txFifo"),
-
- INIT_PARAM(rx_filter, "Enable Receive Filter"),
- INIT_PARAM(hardware_address, "Ethernet Hardware Address"),
- INIT_PARAM(rx_thread, ""),
- INIT_PARAM(tx_thread, ""),
- INIT_PARAM(rss, "")
-
-END_INIT_SIM_OBJECT_PARAMS(NSGigE)
-
-
-CREATE_SIM_OBJECT(NSGigE)
-{
- NSGigE::Params *params = new NSGigE::Params;
-
- params->name = getInstanceName();
-
- params->clock = clock;
-
- params->mmu = mmu;
- params->pmem = physmem;
- params->configSpace = configspace;
- params->configData = configdata;
- params->plat = platform;
- params->busNum = pci_bus;
- params->deviceNum = pci_dev;
- params->functionNum = pci_func;
-
- params->hier = hier;
- params->pio_bus = pio_bus;
- params->header_bus = dma_bus;
- params->payload_bus = payload_bus;
- params->dma_desc_free = dma_desc_free;
- params->dma_data_free = dma_data_free;
- params->dma_read_delay = dma_read_delay;
- params->dma_write_delay = dma_write_delay;
- 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->intr_delay = intr_delay;
-
- params->rx_delay = rx_delay;
- params->tx_delay = tx_delay;
- params->rx_fifo_size = rx_fifo_size;
- params->tx_fifo_size = tx_fifo_size;
-
- params->rx_filter = rx_filter;
- params->eaddr = hardware_address;
- params->rx_thread = rx_thread;
- params->tx_thread = tx_thread;
- params->rss = rss;
-
- return new NSGigE(params);
-}
-
-REGISTER_SIM_OBJECT("NSGigE", NSGigE)
diff --git a/dev/ns_gige.hh b/dev/ns_gige.hh
deleted file mode 100644
index 59c55056e..000000000
--- a/dev/ns_gige.hh
+++ /dev/null
@@ -1,487 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @file
- * Device module for modelling the National Semiconductor
- * DP83820 ethernet controller
- */
-
-#ifndef __DEV_NS_GIGE_HH__
-#define __DEV_NS_GIGE_HH__
-
-#include "base/inet.hh"
-#include "base/statistics.hh"
-#include "dev/etherint.hh"
-#include "dev/etherpkt.hh"
-#include "dev/io_device.hh"
-#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
-const uint16_t FHASH_ADDR = 0x100;
-const uint16_t FHASH_SIZE = 0x100;
-
-// EEPROM constants
-const uint8_t EEPROM_READ = 0x2;
-const uint8_t EEPROM_SIZE = 64; // Size in words of NSC93C46 EEPROM
-const uint8_t EEPROM_PMATCH2_ADDR = 0xA; // EEPROM Address of PMATCH word 2
-const uint8_t EEPROM_PMATCH1_ADDR = 0xB; // EEPROM Address of PMATCH word 1
-const uint8_t EEPROM_PMATCH0_ADDR = 0xC; // EEPROM Address of PMATCH word 0
-
-/**
- * Ethernet device registers
- */
-struct dp_regs {
- uint32_t command;
- uint32_t config;
- uint32_t mear;
- uint32_t ptscr;
- uint32_t isr;
- uint32_t imr;
- uint32_t ier;
- uint32_t ihr;
- uint32_t txdp;
- uint32_t txdp_hi;
- uint32_t txcfg;
- uint32_t gpior;
- uint32_t rxdp;
- uint32_t rxdp_hi;
- uint32_t rxcfg;
- uint32_t pqcr;
- uint32_t wcsr;
- uint32_t pcr;
- uint32_t rfcr;
- uint32_t rfdr;
- uint32_t brar;
- uint32_t brdr;
- uint32_t srr;
- uint32_t mibc;
- uint32_t vrcr;
- uint32_t vtcr;
- uint32_t vdr;
- uint32_t ccsr;
- uint32_t tbicr;
- uint32_t tbisr;
- uint32_t tanar;
- uint32_t tanlpar;
- uint32_t taner;
- uint32_t tesr;
-};
-
-struct dp_rom {
- /**
- * for perfect match memory.
- * the linux driver doesn't use any other ROM
- */
- uint8_t perfectMatch[ETH_ADDR_LEN];
-
- /**
- * for hash table memory.
- * used by the freebsd driver
- */
- uint8_t filterHash[FHASH_SIZE];
-};
-
-class NSGigEInt;
-class PhysicalMemory;
-class BaseInterface;
-class HierParams;
-class Bus;
-class PciConfigAll;
-
-/**
- * NS DP83820 Ethernet device model
- */
-class NSGigE : public PciDev
-{
- public:
- /** Transmit State Machine states */
- enum TxState
- {
- txIdle,
- txDescRefr,
- txDescRead,
- txFifoBlock,
- txFragRead,
- txDescWrite,
- txAdvance
- };
-
- /** Receive State Machine States */
- enum RxState
- {
- rxIdle,
- rxDescRefr,
- rxDescRead,
- rxFifoBlock,
- rxFragWrite,
- rxDescWrite,
- rxAdvance
- };
-
- enum DmaState
- {
- dmaIdle,
- dmaReading,
- dmaWriting,
- dmaReadWaiting,
- dmaWriteWaiting
- };
-
- /** EEPROM State Machine States */
- enum EEPROMState
- {
- eepromStart,
- eepromGetOpcode,
- eepromGetAddress,
- eepromRead
- };
-
- private:
- Addr addr;
- static const Addr size = sizeof(dp_regs);
-
- protected:
- /** device register file */
- dp_regs regs;
- dp_rom rom;
-
- /** pci settings */
- bool ioEnable;
-#if 0
- bool memEnable;
- bool bmEnable;
-#endif
-
- /*** BASIC STRUCTURES FOR TX/RX ***/
- /* Data FIFOs */
- PacketFifo txFifo;
- PacketFifo rxFifo;
-
- /** various helper vars */
- PacketPtr txPacket;
- PacketPtr rxPacket;
- uint8_t *txPacketBufPtr;
- uint8_t *rxPacketBufPtr;
- uint32_t txXferLen;
- uint32_t rxXferLen;
- bool rxDmaFree;
- bool txDmaFree;
-
- /** DescCaches */
- ns_desc32 txDesc32;
- ns_desc32 rxDesc32;
- ns_desc64 txDesc64;
- ns_desc64 rxDesc64;
-
- /* state machine cycle time */
- Tick clock;
- inline Tick cycles(int numCycles) const { return numCycles * clock; }
-
- /* tx State Machine */
- TxState txState;
- bool txEnable;
-
- /** Current Transmit Descriptor Done */
- bool CTDD;
- /** halt the tx state machine after next packet */
- bool txHalt;
- /** ptr to the next byte in the current fragment */
- Addr txFragPtr;
- /** count of bytes remaining in the current descriptor */
- uint32_t txDescCnt;
- DmaState txDmaState;
-
- /** rx State Machine */
- RxState rxState;
- bool rxEnable;
-
- /** Current Receive Descriptor Done */
- bool CRDD;
- /** num of bytes in the current packet being drained from rxDataFifo */
- uint32_t rxPktBytes;
- /** halt the rx state machine after current packet */
- bool rxHalt;
- /** ptr to the next byte in current fragment */
- Addr rxFragPtr;
- /** count of bytes remaining in the current descriptor */
- uint32_t rxDescCnt;
- DmaState rxDmaState;
-
- bool extstsEnable;
-
- /** EEPROM State Machine */
- EEPROMState eepromState;
- bool eepromClk;
- uint8_t eepromBitsToRx;
- uint8_t eepromOpcode;
- uint8_t eepromAddress;
- uint16_t eepromData;
-
- protected:
- Tick dmaReadDelay;
- Tick dmaWriteDelay;
-
- Tick dmaReadFactor;
- Tick dmaWriteFactor;
-
- void *rxDmaData;
- Addr rxDmaAddr;
- 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>;
- EventWrapper<NSGigE, &NSGigE::rxDmaReadDone> rxDmaReadEvent;
-
- void rxDmaWriteDone();
- friend class EventWrapper<NSGigE, &NSGigE::rxDmaWriteDone>;
- EventWrapper<NSGigE, &NSGigE::rxDmaWriteDone> rxDmaWriteEvent;
-
- void txDmaReadDone();
- friend class EventWrapper<NSGigE, &NSGigE::txDmaReadDone>;
- EventWrapper<NSGigE, &NSGigE::txDmaReadDone> txDmaReadEvent;
-
- void txDmaWriteDone();
- friend class EventWrapper<NSGigE, &NSGigE::txDmaWriteDone>;
- EventWrapper<NSGigE, &NSGigE::txDmaWriteDone> txDmaWriteEvent;
-
- bool dmaDescFree;
- bool dmaDataFree;
-
- protected:
- Tick txDelay;
- Tick rxDelay;
-
- void txReset();
- void rxReset();
- void regsReset();
-
- void rxKick();
- Tick rxKickTick;
- typedef EventWrapper<NSGigE, &NSGigE::rxKick> RxKickEvent;
- friend void RxKickEvent::process();
- RxKickEvent rxKickEvent;
-
- void txKick();
- Tick txKickTick;
- typedef EventWrapper<NSGigE, &NSGigE::txKick> TxKickEvent;
- friend void TxKickEvent::process();
- TxKickEvent txKickEvent;
-
- void eepromKick();
-
- /**
- * Retransmit event
- */
- void transmit();
- void txEventTransmit()
- {
- transmit();
- if (txState == txFifoBlock)
- txKick();
- }
- typedef EventWrapper<NSGigE, &NSGigE::txEventTransmit> TxEvent;
- friend void TxEvent::process();
- TxEvent txEvent;
-
- void txDump() const;
- void rxDump() const;
-
- /**
- * receive address filter
- */
- bool rxFilterEnable;
- bool rxFilter(const PacketPtr &packet);
- bool acceptBroadcast;
- bool acceptMulticast;
- bool acceptUnicast;
- bool acceptPerfect;
- bool acceptArp;
- bool multicastHashEnable;
-
- PhysicalMemory *physmem;
-
- /**
- * Interrupt management
- */
- void devIntrPost(uint32_t interrupts);
- void devIntrClear(uint32_t interrupts);
- void devIntrChangeMask();
-
- Tick intrDelay;
- Tick intrTick;
- bool cpuPendingIntr;
- void cpuIntrPost(Tick when);
- void cpuInterrupt();
- void cpuIntrClear();
-
- typedef EventWrapper<NSGigE, &NSGigE::cpuInterrupt> IntrEvent;
- friend void IntrEvent::process();
- IntrEvent *intrEvent;
- NSGigEInt *interface;
-
- 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;
- Tick dma_write_delay;
- Tick dma_read_factor;
- Tick dma_write_factor;
- bool rx_filter;
- Net::EthAddr eaddr;
- uint32_t tx_fifo_size;
- uint32_t rx_fifo_size;
- bool rx_thread;
- bool tx_thread;
- bool rss;
- bool dma_no_allocate;
- };
-
- NSGigE(Params *params);
- ~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 Fault read(MemReqPtr &req, uint8_t *data);
- virtual Fault write(MemReqPtr &req, const uint8_t *data);
-
- bool cpuIntrPending() const;
- void cpuIntrAck() { cpuIntrClear(); }
-
- bool recvPacket(PacketPtr packet);
- void transferDone();
-
- void setInterface(NSGigEInt *i) { assert(!interface); interface = i; }
-
- virtual void serialize(std::ostream &os);
- virtual void unserialize(Checkpoint *cp, const std::string &section);
-
- public:
- void regStats();
-
- private:
- Stats::Scalar<> txBytes;
- Stats::Scalar<> rxBytes;
- Stats::Scalar<> txPackets;
- Stats::Scalar<> rxPackets;
- Stats::Scalar<> txIpChecksums;
- Stats::Scalar<> rxIpChecksums;
- Stats::Scalar<> txTcpChecksums;
- Stats::Scalar<> rxTcpChecksums;
- Stats::Scalar<> txUdpChecksums;
- Stats::Scalar<> rxUdpChecksums;
- Stats::Scalar<> descDmaReads;
- Stats::Scalar<> descDmaWrites;
- Stats::Scalar<> descDmaRdBytes;
- Stats::Scalar<> descDmaWrBytes;
- Stats::Formula totBandwidth;
- Stats::Formula totPackets;
- Stats::Formula totBytes;
- Stats::Formula totPacketRate;
- Stats::Formula txBandwidth;
- Stats::Formula rxBandwidth;
- Stats::Formula txPacketRate;
- Stats::Formula rxPacketRate;
- Stats::Scalar<> postedSwi;
- Stats::Formula coalescedSwi;
- Stats::Scalar<> totalSwi;
- Stats::Scalar<> postedRxIdle;
- Stats::Formula coalescedRxIdle;
- Stats::Scalar<> totalRxIdle;
- Stats::Scalar<> postedRxOk;
- Stats::Formula coalescedRxOk;
- Stats::Scalar<> totalRxOk;
- Stats::Scalar<> postedRxDesc;
- Stats::Formula coalescedRxDesc;
- Stats::Scalar<> totalRxDesc;
- Stats::Scalar<> postedTxOk;
- Stats::Formula coalescedTxOk;
- Stats::Scalar<> totalTxOk;
- Stats::Scalar<> postedTxIdle;
- Stats::Formula coalescedTxIdle;
- Stats::Scalar<> totalTxIdle;
- Stats::Scalar<> postedTxDesc;
- Stats::Formula coalescedTxDesc;
- Stats::Scalar<> totalTxDesc;
- Stats::Scalar<> postedRxOrn;
- Stats::Formula coalescedRxOrn;
- Stats::Scalar<> totalRxOrn;
- Stats::Formula coalescedTotal;
- Stats::Scalar<> postedInterrupts;
- Stats::Scalar<> droppedPackets;
-
- public:
- Tick cacheAccess(MemReqPtr &req);
-};
-
-/*
- * Ethernet Interface for an Ethernet Device
- */
-class NSGigEInt : public EtherInt
-{
- private:
- NSGigE *dev;
-
- public:
- NSGigEInt(const std::string &name, NSGigE *d)
- : EtherInt(name), dev(d) { dev->setInterface(this); }
-
- virtual bool recvPacket(PacketPtr pkt) { return dev->recvPacket(pkt); }
- virtual void sendDone() { dev->transferDone(); }
-};
-
-#endif // __DEV_NS_GIGE_HH__
diff --git a/dev/pciconfigall.cc b/dev/pciconfigall.cc
deleted file mode 100644
index d55084fa5..000000000
--- a/dev/pciconfigall.cc
+++ /dev/null
@@ -1,229 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/* @file
- * PCI Configspace implementation
- */
-
-#include <deque>
-#include <string>
-#include <vector>
-#include <bitset>
-
-#include "base/trace.hh"
-#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 "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)
-{
- mmu->add_child(this, RangeSize(addr, size));
-
- if (pio_bus) {
- pioInterface = newPioInterface(name + ".pio", hier, pio_bus, this,
- &PciConfigAll::cacheAccess);
- pioInterface->addAddrRange(RangeSize(addr, size));
- pioLatency = pio_latency * pio_bus->clockRate;
- }
-
- // Make all the pointers to devices null
- for(int x=0; x < MAX_PCI_DEV; x++)
- for(int y=0; y < MAX_PCI_FUNC; y++)
- devices[x][y] = NULL;
-}
-
-// If two interrupts share the same line largely bad things will happen.
-// Since we don't track how many times an interrupt was set and correspondingly
-// cleared two devices on the same interrupt line and assert and deassert each
-// others interrupt "line". Interrupts will not work correctly.
-void
-PciConfigAll::startup()
-{
- bitset<256> intLines;
- PciDev *tempDev;
- uint8_t intline;
-
- for (int x = 0; x < MAX_PCI_DEV; x++) {
- for (int y = 0; y < MAX_PCI_FUNC; y++) {
- if (devices[x][y] != NULL) {
- tempDev = devices[x][y];
- intline = tempDev->interruptLine();
- if (intLines.test(intline))
- warn("Interrupt line %#X is used multiple times"
- "(You probably want to fix this).\n", (uint32_t)intline);
- else
- intLines.set(intline);
- } // devices != NULL
- } // PCI_FUNC
- } // PCI_DEV
-
-}
-
-Fault
-PciConfigAll::read(MemReqPtr &req, uint8_t *data)
-{
-
- Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask));
-
- DPRINTF(PciConfigAll, "read va=%#x da=%#x size=%d\n",
- req->vaddr, daddr, req->size);
-
- 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");
- }
- }
-
- DPRINTFN("PCI Configspace ERROR: read daddr=%#x size=%d\n",
- daddr, req->size);
-
- return NoFault;
-}
-
-Fault
-PciConfigAll::write(MemReqPtr &req, const uint8_t *data)
-{
- Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask));
-
- int device = (daddr >> 11) & 0x1F;
- int func = (daddr >> 8) & 0x7;
- int reg = daddr & 0xFF;
-
- 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;
-}
-
-void
-PciConfigAll::serialize(std::ostream &os)
-{
- /*
- * There is no state associated with this object that requires
- * serialization. The only real state are the device pointers
- * which are all setup by the constructor of the PciDev class
- */
-}
-
-void
-PciConfigAll::unserialize(Checkpoint *cp, const std::string &section)
-{
- /*
- * There is no state associated with this object that requires
- * serialization. The only real state are the device pointers
- * which are all setup by the constructor of the PciDev class
- */
-}
-
-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<Tick> pio_latency;
- SimObjectParam<HierParams *> hier;
-
-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)
-
-END_INIT_SIM_OBJECT_PARAMS(PciConfigAll)
-
-CREATE_SIM_OBJECT(PciConfigAll)
-{
- return new PciConfigAll(getInstanceName(), addr, mmu, hier, pio_bus,
- pio_latency);
-}
-
-REGISTER_SIM_OBJECT("PciConfigAll", PciConfigAll)
-
-#endif // DOXYGEN_SHOULD_SKIP_THIS
diff --git a/dev/pciconfigall.hh b/dev/pciconfigall.hh
deleted file mode 100644
index c6a0241d8..000000000
--- a/dev/pciconfigall.hh
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * @file
- * PCI Config space implementation.
- */
-
-#ifndef __PCICONFIGALL_HH__
-#define __PCICONFIGALL_HH__
-
-#include "dev/pcireg.h"
-#include "base/range.hh"
-#include "dev/io_device.hh"
-
-
-static const uint32_t MAX_PCI_DEV = 32;
-static const uint32_t MAX_PCI_FUNC = 8;
-
-class PciDev;
-class MemoryController;
-
-/**
- * PCI Config Space
- * All of PCI config space needs to return -1 on Tsunami, except
- * the devices that exist. This device maps the entire bus config
- * space and passes the requests on to TsunamiPCIDev devices as
- * appropriate.
- */
-class PciConfigAll : public PioDevice
-{
- private:
- Addr addr;
- static const Addr size = 0xffffff;
-
- /**
- * Pointers to all the devices that are registered with this
- * particular config space.
- */
- PciDev* devices[MAX_PCI_DEV][MAX_PCI_FUNC];
-
- 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
- */
- PciConfigAll(const std::string &name, Addr a, MemoryController *mmu,
- HierParams *hier, Bus *pio_bus, Tick pio_latency);
-
-
- /**
- * Check if a device exists.
- * @param pcidev PCI device to check
- * @param pcifunc PCI function to check
- * @return true if device exists, false otherwise
- */
- bool deviceExists(uint32_t pcidev, uint32_t pcifunc)
- { return devices[pcidev][pcifunc] != NULL ? true : false; }
-
- /**
- * Registers a device with the config space object.
- * @param pcidev PCI device to register
- * @param pcifunc PCI function to register
- * @param device device to register
- */
- void registerDevice(uint8_t pcidev, uint8_t pcifunc, PciDev *device)
- { devices[pcidev][pcifunc] = device; }
-
- /**
- * 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.
- */
- virtual Fault read(MemReqPtr &req, uint8_t *data);
-
- /**
- * Write to PCI config spcae. If the device does not exit the simulator
- * panics. If it does it is passed on the PciDev::WriteConfig (or the virtual
- * function that overrides it).
- * @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);
-
- /**
- * Start up function to check if more than one person is using an interrupt line
- * and print a warning if such a case exists
- */
- virtual void startup();
-
- /**
- * Serialize this object to the given output stream.
- * @param os The stream to serialize to.
- */
- virtual void serialize(std::ostream &os);
-
- /**
- * Reconstruct the state of this object from a checkpoint.
- * @param cp The checkpoint use.
- * @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
deleted file mode 100644
index a05ee3803..000000000
--- a/dev/pcidev.cc
+++ /dev/null
@@ -1,427 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/* @file
- * A single PCI device configuration space entry.
- */
-
-#include <list>
-#include <sstream>
-#include <string>
-#include <vector>
-
-#include "base/inifile.hh"
-#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 "sim/builder.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)
-{
- // copy the config data from the PciConfigData object
- if (configData) {
- memcpy(config.data, configData->config.data, sizeof(config.data));
- memcpy(BARSize, configData->BARSize, sizeof(BARSize));
- memcpy(BARAddrs, configData->BARAddrs, sizeof(BARAddrs));
- } else
- panic("NULL pointer to configuration data");
-
- // Setup pointer in config space to point to this entry
- if (p->configSpace->deviceExists(p->deviceNum, p->functionNum))
- panic("Two PCI devices occuping same dev: %#x func: %#x",
- p->deviceNum, p->functionNum);
- else
- 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"); }
-
-Fault
-PciDev::readBar2(MemReqPtr &req, Addr daddr, uint8_t *data)
-{ panic("not implemented"); }
-
-Fault
-PciDev::readBar3(MemReqPtr &req, Addr daddr, uint8_t *data)
-{ panic("not implemented"); }
-
-Fault
-PciDev::readBar4(MemReqPtr &req, Addr daddr, uint8_t *data)
-{ panic("not implemented"); }
-
-Fault
-PciDev::readBar5(MemReqPtr &req, Addr daddr, uint8_t *data)
-{ panic("not implemented"); }
-
-Fault
-PciDev::writeBar0(MemReqPtr &req, Addr daddr, const uint8_t *data)
-{ panic("not implemented"); }
-
-Fault
-PciDev::writeBar1(MemReqPtr &req, Addr daddr, const uint8_t *data)
-{ panic("not implemented"); }
-
-Fault
-PciDev::writeBar2(MemReqPtr &req, Addr daddr, const uint8_t *data)
-{ panic("not implemented"); }
-
-Fault
-PciDev::writeBar3(MemReqPtr &req, Addr daddr, const uint8_t *data)
-{ panic("not implemented"); }
-
-Fault
-PciDev::writeBar4(MemReqPtr &req, Addr daddr, const uint8_t *data)
-{ panic("not implemented"); }
-
-Fault
-PciDev::writeBar5(MemReqPtr &req, Addr daddr, const uint8_t *data)
-{ panic("not implemented"); }
-
-void
-PciDev::readConfig(int offset, int size, 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];
- break;
- case sizeof(uint32_t):
- *(uint32_t*)data = *(uint32_t*)&config.data[offset];
- break;
- default:
- panic("Invalid PCI configuration read size!\n");
- }
-
- 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)
-{
- 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");
- }
- break;
-
- 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;
- }
-
- // 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
-
- config.baseAddr[barnum] = letoh(
- (~(BARSize[barnum] - 1) & ~bar_mask) |
- (letoh(config.baseAddr[barnum]) & bar_mask));
- } else {
- MemoryController *mmu = params()->mmu;
-
- config.baseAddr[barnum] = letoh(
- (letoh(data32) & ~bar_mask) |
- (letoh(config.baseAddr[barnum]) & bar_mask));
-
- 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;
- }
- }
- 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;
-
- default:
- panic("invalid access size");
- }
-}
-
-void
-PciDev::serialize(ostream &os)
-{
- SERIALIZE_ARRAY(BARSize, sizeof(BARSize) / sizeof(BARSize[0]));
- SERIALIZE_ARRAY(BARAddrs, sizeof(BARAddrs) / sizeof(BARAddrs[0]));
- SERIALIZE_ARRAY(config.data, sizeof(config.data) / sizeof(config.data[0]));
-}
-
-void
-PciDev::unserialize(Checkpoint *cp, const std::string &section)
-{
- UNSERIALIZE_ARRAY(BARSize, sizeof(BARSize) / sizeof(BARSize[0]));
- 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
-
-BEGIN_DECLARE_SIM_OBJECT_PARAMS(PciConfigData)
-
- Param<uint16_t> VendorID;
- Param<uint16_t> DeviceID;
- Param<uint16_t> Command;
- Param<uint16_t> Status;
- Param<uint8_t> Revision;
- Param<uint8_t> ProgIF;
- Param<uint8_t> SubClassCode;
- Param<uint8_t> ClassCode;
- Param<uint8_t> CacheLineSize;
- Param<uint8_t> LatencyTimer;
- Param<uint8_t> HeaderType;
- Param<uint8_t> BIST;
- Param<uint32_t> BAR0;
- Param<uint32_t> BAR1;
- Param<uint32_t> BAR2;
- Param<uint32_t> BAR3;
- Param<uint32_t> BAR4;
- Param<uint32_t> BAR5;
- Param<uint32_t> CardbusCIS;
- Param<uint16_t> SubsystemVendorID;
- Param<uint16_t> SubsystemID;
- Param<uint32_t> ExpansionROM;
- Param<uint8_t> InterruptLine;
- Param<uint8_t> InterruptPin;
- Param<uint8_t> MinimumGrant;
- Param<uint8_t> MaximumLatency;
- Param<uint32_t> BAR0Size;
- Param<uint32_t> BAR1Size;
- Param<uint32_t> BAR2Size;
- Param<uint32_t> BAR3Size;
- Param<uint32_t> BAR4Size;
- Param<uint32_t> BAR5Size;
-
-END_DECLARE_SIM_OBJECT_PARAMS(PciConfigData)
-
-BEGIN_INIT_SIM_OBJECT_PARAMS(PciConfigData)
-
- INIT_PARAM(VendorID, "Vendor ID"),
- INIT_PARAM(DeviceID, "Device ID"),
- INIT_PARAM_DFLT(Command, "Command Register", 0x00),
- INIT_PARAM_DFLT(Status, "Status Register", 0x00),
- INIT_PARAM_DFLT(Revision, "Device Revision", 0x00),
- INIT_PARAM_DFLT(ProgIF, "Programming Interface", 0x00),
- INIT_PARAM(SubClassCode, "Sub-Class Code"),
- INIT_PARAM(ClassCode, "Class Code"),
- INIT_PARAM_DFLT(CacheLineSize, "System Cacheline Size", 0x00),
- INIT_PARAM_DFLT(LatencyTimer, "PCI Latency Timer", 0x00),
- INIT_PARAM_DFLT(HeaderType, "PCI Header Type", 0x00),
- INIT_PARAM_DFLT(BIST, "Built In Self Test", 0x00),
- INIT_PARAM_DFLT(BAR0, "Base Address Register 0", 0x00),
- INIT_PARAM_DFLT(BAR1, "Base Address Register 1", 0x00),
- INIT_PARAM_DFLT(BAR2, "Base Address Register 2", 0x00),
- INIT_PARAM_DFLT(BAR3, "Base Address Register 3", 0x00),
- INIT_PARAM_DFLT(BAR4, "Base Address Register 4", 0x00),
- INIT_PARAM_DFLT(BAR5, "Base Address Register 5", 0x00),
- INIT_PARAM_DFLT(CardbusCIS, "Cardbus Card Information Structure", 0x00),
- INIT_PARAM_DFLT(SubsystemVendorID, "Subsystem Vendor ID", 0x00),
- INIT_PARAM_DFLT(SubsystemID, "Subsystem ID", 0x00),
- INIT_PARAM_DFLT(ExpansionROM, "Expansion ROM Base Address Register", 0x00),
- INIT_PARAM(InterruptLine, "Interrupt Line Register"),
- INIT_PARAM(InterruptPin, "Interrupt Pin Register"),
- INIT_PARAM_DFLT(MinimumGrant, "Minimum Grant", 0x00),
- INIT_PARAM_DFLT(MaximumLatency, "Maximum Latency", 0x00),
- INIT_PARAM_DFLT(BAR0Size, "Base Address Register 0 Size", 0x00),
- INIT_PARAM_DFLT(BAR1Size, "Base Address Register 1 Size", 0x00),
- INIT_PARAM_DFLT(BAR2Size, "Base Address Register 2 Size", 0x00),
- INIT_PARAM_DFLT(BAR3Size, "Base Address Register 3 Size", 0x00),
- INIT_PARAM_DFLT(BAR4Size, "Base Address Register 4 Size", 0x00),
- INIT_PARAM_DFLT(BAR5Size, "Base Address Register 5 Size", 0x00)
-
-END_INIT_SIM_OBJECT_PARAMS(PciConfigData)
-
-CREATE_SIM_OBJECT(PciConfigData)
-{
- PciConfigData *data = new PciConfigData(getInstanceName());
-
- data->config.vendor = htole(VendorID);
- data->config.device = htole(DeviceID);
- data->config.command = htole(Command);
- data->config.status = htole(Status);
- data->config.revision = htole(Revision);
- data->config.progIF = htole(ProgIF);
- data->config.subClassCode = htole(SubClassCode);
- data->config.classCode = htole(ClassCode);
- data->config.cacheLineSize = htole(CacheLineSize);
- data->config.latencyTimer = htole(LatencyTimer);
- data->config.headerType = htole(HeaderType);
- data->config.bist = htole(BIST);
-
- data->config.baseAddr0 = htole(BAR0);
- data->config.baseAddr1 = htole(BAR1);
- data->config.baseAddr2 = htole(BAR2);
- data->config.baseAddr3 = htole(BAR3);
- data->config.baseAddr4 = htole(BAR4);
- data->config.baseAddr5 = htole(BAR5);
- data->config.cardbusCIS = htole(CardbusCIS);
- data->config.subsystemVendorID = htole(SubsystemVendorID);
- data->config.subsystemID = htole(SubsystemVendorID);
- data->config.expansionROM = htole(ExpansionROM);
- data->config.interruptLine = htole(InterruptLine);
- data->config.interruptPin = htole(InterruptPin);
- data->config.minimumGrant = htole(MinimumGrant);
- data->config.maximumLatency = htole(MaximumLatency);
-
- data->BARSize[0] = BAR0Size;
- data->BARSize[1] = BAR1Size;
- data->BARSize[2] = BAR2Size;
- data->BARSize[3] = BAR3Size;
- data->BARSize[4] = BAR4Size;
- data->BARSize[5] = BAR5Size;
-
- return data;
-}
-
-REGISTER_SIM_OBJECT("PciConfigData", PciConfigData)
-
-#endif // DOXYGEN_SHOULD_SKIP_THIS
diff --git a/dev/pcidev.hh b/dev/pcidev.hh
deleted file mode 100644
index bdfc6b932..000000000
--- a/dev/pcidev.hh
+++ /dev/null
@@ -1,298 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/* @file
- * Interface for devices using PCI configuration
- */
-
-#ifndef __DEV_PCIDEV_HH__
-#define __DEV_PCIDEV_HH__
-
-#include "dev/io_device.hh"
-#include "dev/pcireg.h"
-#include "dev/platform.hh"
-
-#define BAR_IO_MASK 0x3
-#define BAR_MEM_MASK 0xF
-#define BAR_IO_SPACE_BIT 0x1
-#define BAR_IO_SPACE(x) ((x) & BAR_IO_SPACE_BIT)
-#define BAR_NUMBER(x) (((x) - PCI0_BASE_ADDR0) >> 0x2);
-
-class PciConfigAll;
-class MemoryController;
-
-
-/**
- * This class encapulates the first 64 bytes of a singles PCI
- * devices config space that in configured by the configuration file.
- */
-class PciConfigData : public SimObject
-{
- public:
- /**
- * Constructor to initialize the devices config space to 0.
- */
- PciConfigData(const std::string &name)
- : SimObject(name)
- {
- memset(config.data, 0, sizeof(config.data));
- memset(BARAddrs, 0, sizeof(BARAddrs));
- memset(BARSize, 0, sizeof(BARSize));
- }
-
- /** The first 64 bytes */
- PCIConfig config;
-
- /** The size of the BARs */
- uint32_t BARSize[6];
-
- /** The addresses of the BARs */
- Addr BARAddrs[6];
-};
-
-/**
- * PCI device, base implemnation is only config space.
- * Each device is connected to a PCIConfigSpace device
- * which returns -1 for everything but the pcidevs that
- * register with it. This object registers with the PCIConfig space
- * object.
- */
-class PciDev : public DmaDevice
-{
- public:
- struct 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.
- */
- PciConfigAll *configSpace;
-
- /**
- * A pointer to the object that contains the first 64 bytes of
- * config space
- */
- PciConfigData *configData;
-
- /** The bus number we are on */
- uint32_t busNum;
-
- /** The device number we have */
- uint32_t deviceNum;
-
- /** The function number */
- uint32_t functionNum;
- };
-
- protected:
- Params *_params;
-
- public:
- const Params *params() const { return _params; }
-
- protected:
- /** The current config space. Unlike the PciConfigData this is
- * updated during simulation while continues to reflect what was
- * in the config file.
- */
- PCIConfig config;
-
- /** The size of the BARs */
- uint32_t BARSize[6];
-
- /** The current address mapping of the BARs */
- Addr BARAddrs[6];
-
- bool
- isBAR(Addr addr, int bar) const
- {
- assert(bar >= 0 && bar < 6);
- return BARAddrs[bar] <= addr && addr < BARAddrs[bar] + BARSize[bar];
- }
-
- int
- getBAR(Addr addr)
- {
- for (int i = 0; i <= 5; ++i)
- if (isBAR(addr, i))
- return i;
-
- return -1;
- }
-
- bool
- getBAR(Addr paddr, Addr &daddr, int &bar)
- {
- int b = getBAR(paddr);
- if (b < 0)
- return false;
-
- daddr = paddr - BARAddrs[b];
- bar = b;
- return true;
- }
-
- protected:
- Platform *plat;
- PciConfigData *configData;
-
- public:
- Addr pciToDma(Addr pciAddr) const
- { return plat->pciToDma(pciAddr); }
-
- void
- intrPost()
- { plat->postPciInt(configData->config.interruptLine); }
-
- void
- intrClear()
- { plat->clearPciInt(configData->config.interruptLine); }
-
- uint8_t
- interruptLine()
- { return configData->config.interruptLine; }
-
- public:
- /**
- * Constructor for PCI Dev. This function copies data from the
- * config file object PCIConfigData and registers the device with
- * a PciConfigAll object.
- */
- 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
- * for normal operations that it does not need to override.
- * @param offset the offset into config space
- * @param size the size of the write
- * @param data the data to write
- */
- virtual void writeConfig(int offset, int size, const uint8_t* data);
-
-
- /**
- * Read from 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
- * for normal operations that it does not need to override.
- * @param offset the offset into config space
- * @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);
-
- /**
- * Serialize this object to the given output stream.
- * @param os The stream to serialize to.
- */
- virtual void serialize(std::ostream &os);
-
- /**
- * Reconstruct the state of this object from a checkpoint.
- * @param cp The checkpoint use.
- * @param section The section name of this object
- */
- 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
deleted file mode 100644
index 639009be9..000000000
--- a/dev/pktfifo.cc
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "base/misc.hh"
-#include "dev/pktfifo.hh"
-
-using namespace std;
-
-bool
-PacketFifo::copyout(void *dest, int offset, int len)
-{
- char *data = (char *)dest;
- if (offset + len >= size())
- return false;
-
- list<PacketPtr>::iterator p = fifo.begin();
- list<PacketPtr>::iterator end = fifo.end();
- while (len > 0) {
- while (offset >= (*p)->length) {
- offset -= (*p)->length;
- ++p;
- }
-
- if (p == end)
- panic("invalid fifo");
-
- int size = min((*p)->length - offset, len);
- memcpy(data, (*p)->data, size);
- offset = 0;
- len -= size;
- data += size;
- ++p;
- }
-
- return true;
-}
-
-
-void
-PacketFifo::serialize(const string &base, ostream &os)
-{
- paramOut(os, base + ".size", _size);
- paramOut(os, base + ".maxsize", _maxsize);
- paramOut(os, base + ".reserved", _reserved);
- paramOut(os, base + ".packets", fifo.size());
-
- int i = 0;
- list<PacketPtr>::iterator p = fifo.begin();
- list<PacketPtr>::iterator end = fifo.end();
- while (p != end) {
- (*p)->serialize(csprintf("%s.packet%d", base, i), os);
- ++p;
- ++i;
- }
-}
-
-void
-PacketFifo::unserialize(const string &base, Checkpoint *cp,
- const string &section)
-{
- paramIn(cp, section, base + ".size", _size);
-// paramIn(cp, section, base + ".maxsize", _maxsize);
- paramIn(cp, section, base + ".reserved", _reserved);
- int fifosize;
- paramIn(cp, section, base + ".packets", fifosize);
-
- fifo.clear();
-
- for (int i = 0; i < fifosize; ++i) {
- PacketPtr p = new PacketData(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
deleted file mode 100644
index e245840a8..000000000
--- a/dev/pktfifo.hh
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __DEV_PKTFIFO_HH__
-#define __DEV_PKTFIFO_HH__
-
-#include <iosfwd>
-#include <list>
-#include <string>
-
-#include "dev/etherpkt.hh"
-#include "sim/serialize.hh"
-
-class Checkpoint;
-class PacketFifo
-{
- public:
- typedef std::list<PacketPtr> fifo_list;
- typedef fifo_list::iterator iterator;
-
- protected:
- std::list<PacketPtr> fifo;
- int _maxsize;
- int _size;
- int _reserved;
-
- public:
- explicit PacketFifo(int max) : _maxsize(max), _size(0), _reserved(0) {}
- virtual ~PacketFifo() {}
-
- int packets() const { return fifo.size(); }
- int maxsize() const { return _maxsize; }
- int size() const { return _size; }
- int reserved() const { return _reserved; }
- int avail() const { return _maxsize - _size - _reserved; }
- bool empty() const { return size() <= 0; }
- bool full() const { return avail() <= 0; }
-
- int reserve(int len = 0)
- {
- _reserved += len;
- assert(avail() >= 0);
- return _reserved;
- }
-
- iterator begin() { return fifo.begin(); }
- iterator end() { return fifo.end(); }
-
- PacketPtr front() { return fifo.front(); }
-
- bool push(PacketPtr ptr)
- {
- assert(ptr->length);
- assert(_reserved <= ptr->length);
- assert(ptr->slack == 0);
- if (avail() < ptr->length - _reserved)
- return false;
-
- _size += ptr->length;
- fifo.push_back(ptr);
- _reserved = 0;
- return true;
- }
-
- void pop()
- {
- if (empty())
- return;
-
- PacketPtr &packet = fifo.front();
- _size -= packet->length;
- _size -= packet->slack;
- packet->slack = 0;
- packet = NULL;
- fifo.pop_front();
- }
-
- void clear()
- {
- for (iterator i = begin(); i != end(); ++i)
- (*i)->slack = 0;
- fifo.clear();
- _size = 0;
- _reserved = 0;
- }
-
- void remove(iterator i)
- {
- PacketPtr &packet = *i;
- if (i != fifo.begin()) {
- iterator prev = i;
- --prev;
- assert(prev != fifo.end());
- (*prev)->slack += packet->length;
- } else {
- _size -= packet->length;
- _size -= packet->slack;
- }
-
- packet->slack = 0;
- packet = NULL;
- fifo.erase(i);
- }
-
- bool copyout(void *dest, int offset, int len);
-
- int countPacketsBefore(iterator end)
- {
- iterator i = fifo.begin();
- int count = 0;
-
- while (i != end) {
- ++count;
- ++i;
- }
-
- return count;
- }
-
- int countPacketsAfter(iterator i)
- {
- iterator end = fifo.end();
- int count = 0;
-
- while (i != end) {
- ++count;
- ++i;
- }
-
- return count;
- }
-
-
-/**
- * Serialization stuff
- */
- public:
- void serialize(const std::string &base, std::ostream &os);
- void unserialize(const std::string &base,
- Checkpoint *cp, const std::string &section);
-};
-
-#endif // __DEV_PKTFIFO_HH__
diff --git a/dev/platform.cc b/dev/platform.cc
deleted file mode 100644
index 5b667b12c..000000000
--- a/dev/platform.cc
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "dev/platform.hh"
-#include "sim/builder.hh"
-#include "sim/sim_exit.hh"
-
-using namespace std;
-using namespace TheISA;
-
-Platform::Platform(const string &name, IntrControl *intctrl, PciConfigAll *pci)
- : SimObject(name), intrctrl(intctrl), pciconfig(pci)
-{
-}
-
-Platform::~Platform()
-{
-}
-
-void
-Platform::postPciInt(int line)
-{
- panic("No PCI interrupt support in platform.");
-}
-
-void
-Platform::clearPciInt(int line)
-{
- panic("No PCI interrupt support in platform.");
-}
-
-Addr
-Platform::pciToDma(Addr pciAddr) const
-{
- panic("No PCI dma support in platform.");
-}
-
-DEFINE_SIM_OBJECT_CLASS_NAME("Platform", Platform)
-
diff --git a/dev/platform.hh b/dev/platform.hh
deleted file mode 100644
index 1ee645454..000000000
--- a/dev/platform.hh
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * @file
- * Generic interface for platforms
- */
-
-#ifndef __DEV_PLATFORM_HH__
-#define __DEV_PLATFORM_HH__
-
-#include "sim/sim_object.hh"
-#include "arch/isa_traits.hh"
-
-class PciConfigAll;
-class IntrControl;
-class SimConsole;
-class Uart;
-
-class Platform : public SimObject
-{
- public:
- /** Pointer to the interrupt controller */
- IntrControl *intrctrl;
-
- /** Pointer to the PCI configuration space */
- PciConfigAll *pciconfig;
-
- /** Pointer to the UART, set by the uart */
- Uart *uart;
-
- public:
- Platform(const std::string &name, IntrControl *intctrl, PciConfigAll *pci);
- virtual ~Platform();
- virtual void postConsoleInt() = 0;
- virtual void clearConsoleInt() = 0;
- virtual Tick intrFrequency() = 0;
- virtual void postPciInt(int line);
- virtual void clearPciInt(int line);
- virtual Addr pciToDma(Addr pciAddr) const;
-};
-
-#endif // __DEV_PLATFORM_HH__
diff --git a/dev/simconsole.cc b/dev/simconsole.cc
deleted file mode 100644
index b818e61f4..000000000
--- a/dev/simconsole.cc
+++ /dev/null
@@ -1,415 +0,0 @@
-/*
- * Copyright (c) 2001-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/* @file
- * Implements the user interface to a serial console
- */
-
-#include <sys/ioctl.h>
-#include <sys/termios.h>
-#include <sys/types.h>
-#include <errno.h>
-#include <poll.h>
-#include <unistd.h>
-
-#include <iostream>
-#include <fstream>
-#include <sstream>
-#include <string>
-
-#include "base/misc.hh"
-#include "base/output.hh"
-#include "base/socket.hh"
-#include "base/trace.hh"
-#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;
-
-////////////////////////////////////////////////////////////////////////
-//
-//
-
-SimConsole::Event::Event(SimConsole *c, int fd, int e)
- : PollEvent(fd, e), cons(c)
-{
-}
-
-void
-SimConsole::Event::process(int revent)
-{
- if (revent & POLLIN)
- cons->data();
- else if (revent & POLLNVAL)
- cons->detach();
-}
-
-SimConsole::SimConsole(const string &name, ostream *os, int num)
- : SimObject(name), event(NULL), number(num), in_fd(-1), out_fd(-1),
- listener(NULL), txbuf(16384), rxbuf(16384), outfile(os)
-#if TRACING_ON == 1
- , linebuf(16384)
-#endif
-{
- if (outfile)
- outfile->setf(ios::unitbuf);
-}
-
-SimConsole::~SimConsole()
-{
- close();
-}
-
-void
-SimConsole::close()
-{
- if (in_fd != -1)
- ::close(in_fd);
-
- if (out_fd != in_fd && out_fd != -1)
- ::close(out_fd);
-}
-
-void
-SimConsole::attach(int in, int out, ConsoleListener *l)
-{
- in_fd = in;
- out_fd = out;
- listener = l;
-
- event = new Event(this, in, POLLIN);
- pollQueue.schedule(event);
-
- stringstream stream;
- ccprintf(stream, "==== m5 slave console: Console %d ====", number);
-
- // we need an actual carriage return followed by a newline for the
- // terminal
- stream << "\r\n";
-
- write((const uint8_t *)stream.str().c_str(), stream.str().size());
-
-
- DPRINTFN("attach console %d\n", number);
-
- txbuf.readall(out);
-}
-
-void
-SimConsole::detach()
-{
- close();
- in_fd = -1;
- out_fd = -1;
-
- pollQueue.remove(event);
-
- if (listener) {
- listener->add(this);
- listener = NULL;
- }
-
- DPRINTFN("detach console %d\n", number);
-}
-
-void
-SimConsole::data()
-{
- uint8_t buf[1024];
- int len;
-
- len = read(buf, sizeof(buf));
- if (len) {
- rxbuf.write((char *)buf, len);
- // Inform the UART there is data available
- uart->dataAvailable();
- }
-}
-
-size_t
-SimConsole::read(uint8_t *buf, size_t len)
-{
- if (in_fd < 0)
- panic("Console not properly attached.\n");
-
- size_t ret;
- do {
- ret = ::read(in_fd, buf, len);
- } while (ret == -1 && errno == EINTR);
-
-
- if (ret < 0)
- DPRINTFN("Read failed.\n");
-
- if (ret <= 0) {
- detach();
- return 0;
- }
-
- return ret;
-}
-
-// Console output.
-size_t
-SimConsole::write(const uint8_t *buf, size_t len)
-{
- if (out_fd < 0)
- panic("Console not properly attached.\n");
-
- size_t ret;
- for (;;) {
- ret = ::write(out_fd, buf, len);
-
- if (ret >= 0)
- break;
-
- if (errno != EINTR)
- detach();
- }
-
- return ret;
-}
-
-#define MORE_PENDING (ULL(1) << 61)
-#define RECEIVE_SUCCESS (ULL(0) << 62)
-#define RECEIVE_NONE (ULL(2) << 62)
-#define RECEIVE_ERROR (ULL(3) << 62)
-
-bool
-SimConsole::in(uint8_t &c)
-{
- bool empty, ret;
-
- empty = rxbuf.empty();
- ret = !empty;
- if (!empty) {
- rxbuf.read((char *)&c, 1);
- empty = rxbuf.empty();
- }
-
- DPRINTF(ConsoleVerbose, "in: \'%c\' %#02x more: %d, return: %d\n",
- isprint(c) ? c : ' ', c, !empty, ret);
-
- return ret;
-}
-
-uint64_t
-SimConsole::console_in()
-{
- uint8_t c;
- uint64_t value;
-
- if (in(c)) {
- value = RECEIVE_SUCCESS | c;
- if (!rxbuf.empty())
- value |= MORE_PENDING;
- } else {
- value = RECEIVE_NONE;
- }
-
- DPRINTF(ConsoleVerbose, "console_in: return: %#x\n", value);
-
- return value;
-}
-
-void
-SimConsole::out(char c)
-{
-#if TRACING_ON == 1
- if (DTRACE(Console)) {
- static char last = '\0';
-
- if (c != '\n' && c != '\r' ||
- last != '\n' && last != '\r') {
- if (c == '\n' || c == '\r') {
- int size = linebuf.size();
- char *buffer = new char[size + 1];
- linebuf.read(buffer, size);
- buffer[size] = '\0';
- DPRINTF(Console, "%s\n", buffer);
- delete [] buffer;
- } else {
- linebuf.write(c);
- }
- }
-
- last = c;
- }
-#endif
-
- txbuf.write(c);
-
- if (out_fd >= 0)
- write(c);
-
- if (outfile)
- outfile->write(&c, 1);
-
- DPRINTF(ConsoleVerbose, "out: \'%c\' %#02x\n",
- isprint(c) ? c : ' ', (int)c);
-
-}
-
-
-void
-SimConsole::serialize(ostream &os)
-{
-}
-
-void
-SimConsole::unserialize(Checkpoint *cp, const std::string &section)
-{
-}
-
-
-BEGIN_DECLARE_SIM_OBJECT_PARAMS(SimConsole)
-
- SimObjectParam<ConsoleListener *> listener;
- SimObjectParam<IntrControl *> intr_control;
- Param<string> output;
- Param<bool> append_name;
- Param<int> number;
-
-END_DECLARE_SIM_OBJECT_PARAMS(SimConsole)
-
-BEGIN_INIT_SIM_OBJECT_PARAMS(SimConsole)
-
- INIT_PARAM(listener, "console listener"),
- INIT_PARAM(intr_control, "interrupt controller"),
- INIT_PARAM(output, "file to dump output to"),
- INIT_PARAM_DFLT(append_name, "append name() to filename", true),
- INIT_PARAM_DFLT(number, "console number", 0)
-
-END_INIT_SIM_OBJECT_PARAMS(SimConsole)
-
-CREATE_SIM_OBJECT(SimConsole)
-{
- string filename = output;
- ostream *stream = NULL;
-
- if (!filename.empty()) {
- if (append_name)
- filename += "." + getInstanceName();
- stream = simout.find(filename);
- }
-
- SimConsole *console = new SimConsole(getInstanceName(), stream, number);
- ((ConsoleListener *)listener)->add(console);
-
- return console;
-}
-
-REGISTER_SIM_OBJECT("SimConsole", SimConsole)
-
-////////////////////////////////////////////////////////////////////////
-//
-//
-
-ConsoleListener::ConsoleListener(const string &name)
- : SimObject(name), event(NULL)
-{}
-
-ConsoleListener::~ConsoleListener()
-{
- if (event)
- delete event;
-}
-
-void
-ConsoleListener::Event::process(int revent)
-{
- listener->accept();
-}
-
-///////////////////////////////////////////////////////////////////////
-// socket creation and console attach
-//
-
-void
-ConsoleListener::listen(int port)
-{
- while (!listener.listen(port, true)) {
- DPRINTF(Console,
- ": can't bind address console port %d inuse PID %d\n",
- port, getpid());
- port++;
- }
-
- ccprintf(cerr, "Listening for console connection on port %d\n", port);
-
- event = new Event(this, listener.getfd(), POLLIN);
- pollQueue.schedule(event);
-}
-
-void
-ConsoleListener::add(SimConsole *cons)
-{ ConsoleList.push_back(cons);}
-
-void
-ConsoleListener::accept()
-{
- if (!listener.islistening())
- panic("%s: cannot accept a connection if not listening!", name());
-
- int sfd = listener.accept(true);
- if (sfd != -1) {
- iter_t i = ConsoleList.begin();
- iter_t end = ConsoleList.end();
- if (i == end) {
- close(sfd);
- } else {
- (*i)->attach(sfd, this);
- i = ConsoleList.erase(i);
- }
- }
-}
-
-BEGIN_DECLARE_SIM_OBJECT_PARAMS(ConsoleListener)
-
- Param<int> port;
-
-END_DECLARE_SIM_OBJECT_PARAMS(ConsoleListener)
-
-BEGIN_INIT_SIM_OBJECT_PARAMS(ConsoleListener)
-
- INIT_PARAM_DFLT(port, "listen port", 3456)
-
-END_INIT_SIM_OBJECT_PARAMS(ConsoleListener)
-
-CREATE_SIM_OBJECT(ConsoleListener)
-{
- ConsoleListener *listener = new ConsoleListener(getInstanceName());
- listener->listen(port);
-
- return listener;
-}
-
-REGISTER_SIM_OBJECT("ConsoleListener", ConsoleListener)
diff --git a/dev/simconsole.hh b/dev/simconsole.hh
deleted file mode 100644
index cf0641f9e..000000000
--- a/dev/simconsole.hh
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Copyright (c) 2001-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/* @file
- * User Console Interface
- */
-
-#ifndef __CONSOLE_HH__
-#define __CONSOLE_HH__
-
-#include <iostream>
-
-#include "base/circlebuf.hh"
-#include "cpu/intr_control.hh"
-#include "base/pollevent.hh"
-#include "base/socket.hh"
-#include "sim/sim_object.hh"
-
-class ConsoleListener;
-class Uart;
-
-class SimConsole : public SimObject
-{
- public:
- Uart *uart;
-
- protected:
- class Event : public PollEvent
- {
- protected:
- SimConsole *cons;
-
- public:
- Event(SimConsole *c, int fd, int e);
- void process(int revent);
- };
-
- friend class Event;
- Event *event;
-
- protected:
- int number;
- int in_fd;
- int out_fd;
- ConsoleListener *listener;
-
- public:
- SimConsole(const std::string &name, std::ostream *os, int num);
- ~SimConsole();
-
- protected:
- CircleBuf txbuf;
- CircleBuf rxbuf;
- std::ostream *outfile;
-#if TRACING_ON == 1
- CircleBuf linebuf;
-#endif
-
- public:
- ///////////////////////
- // Terminal Interface
-
- void attach(int fd, ConsoleListener *l = NULL) { attach(fd, fd, l); }
- void attach(int in, int out, ConsoleListener *l = NULL);
- void detach();
-
- void data();
-
- void close();
- void read(uint8_t &c) { read(&c, 1); }
- size_t read(uint8_t *buf, size_t len);
- void write(uint8_t c) { write(&c, 1); }
- size_t write(const uint8_t *buf, size_t len);
-
- public:
- /////////////////
- // OS interface
-
- // Get a character from the console.
- bool in(uint8_t &value);
-
- // get a character from the console in the console specific format
- // corresponds to GETC:
- // retval<63:61>
- // 000: success: character received
- // 001: success: character received, more pending
- // 100: failure: no character ready
- // 110: failure: character received with error
- // 111: failure: character received with error, more pending
- // retval<31:0>
- // character read from console
- //
- // Interrupts are cleared when the buffer is empty.
- uint64_t console_in();
-
- // Send a character to the console
- void out(char c);
-
- //Ask the console if data is available
- bool dataAvailable() { return !rxbuf.empty(); }
-
- virtual void serialize(std::ostream &os);
- virtual void unserialize(Checkpoint *cp, const std::string &section);
-};
-
-class ConsoleListener : public SimObject
-{
- protected:
- class Event : public PollEvent
- {
- protected:
- ConsoleListener *listener;
-
- public:
- Event(ConsoleListener *l, int fd, int e)
- : PollEvent(fd, e), listener(l) {}
- void process(int revent);
- };
-
- friend class Event;
- Event *event;
-
- typedef std::list<SimConsole *> list_t;
- typedef list_t::iterator iter_t;
- list_t ConsoleList;
-
- protected:
- ListenSocket listener;
-
- public:
- ConsoleListener(const std::string &name);
- ~ConsoleListener();
-
- void add(SimConsole *cons);
-
- void accept();
- void listen(int port);
-};
-
-#endif // __CONSOLE_HH__
diff --git a/dev/simple_disk.cc b/dev/simple_disk.cc
deleted file mode 100644
index b8c5d44ab..000000000
--- a/dev/simple_disk.cc
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright (c) 2001-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/* @file
- * Simple disk interface for the system console
- */
-
-#include <sys/types.h>
-#include <sys/uio.h>
-#include <fcntl.h>
-#include <unistd.h>
-
-#include <cstring>
-#include <string>
-
-#include "base/misc.hh"
-#include "base/trace.hh"
-#include "dev/disk_image.hh"
-#include "dev/simple_disk.hh"
-#include "mem/functional/physical.hh"
-#include "sim/builder.hh"
-
-using namespace std;
-
-SimpleDisk::SimpleDisk(const string &name, PhysicalMemory *pmem,
- DiskImage *img)
- : SimObject(name), physmem(pmem), image(img)
-{}
-
-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);
-
- if (count & (SectorSize - 1))
- panic("Not reading a multiple of a sector (count = %d)", count);
-
- for (int i = 0, j = 0; i < count; i += SectorSize, j++)
- image->read(data + i, block + j);
-
- DPRINTF(SimpleDisk, "read block=%#x len=%d\n", (uint64_t)block, count);
- DDUMP(SimpleDiskData, data, count);
-}
-
-void
-SimpleDisk::write(Addr addr, baddr_t block, int count)
-{
- panic("unimplemented!\n");
-
-#if 0
- uint8_t *data = physmem->dma_addr(addr, count);
- if (!data)
- panic("dma out of range! write addr=%#x count=%d\n", addr, count);
-
- image->write(data, block, count);
-#endif
-}
-
-BEGIN_DECLARE_SIM_OBJECT_PARAMS(SimpleDisk)
-
- SimObjectParam<PhysicalMemory *> physmem;
- SimObjectParam<DiskImage *> disk;
-
-END_DECLARE_SIM_OBJECT_PARAMS(SimpleDisk)
-
-BEGIN_INIT_SIM_OBJECT_PARAMS(SimpleDisk)
-
- INIT_PARAM(physmem, "Physical Memory"),
- INIT_PARAM(disk, "Disk Image")
-
-END_INIT_SIM_OBJECT_PARAMS(SimpleDisk)
-
-CREATE_SIM_OBJECT(SimpleDisk)
-{
- return new SimpleDisk(getInstanceName(), physmem, disk);
-}
-
-REGISTER_SIM_OBJECT("SimpleDisk", SimpleDisk)
diff --git a/dev/simple_disk.hh b/dev/simple_disk.hh
deleted file mode 100644
index 57f81c5a9..000000000
--- a/dev/simple_disk.hh
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (c) 2001-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/* @file
- * Simple disk interface for the system console
- */
-
-#ifndef __DEV_SIMPLE_DISK_HH__
-#define __DEV_SIMPLE_DISK_HH__
-
-#include "sim/sim_object.hh"
-#include "arch/isa_traits.hh"
-
-class DiskImage;
-class PhysicalMemory;
-
-/*
- * Trivial interface to a disk image used by the System Console
- */
-class SimpleDisk : public SimObject
-{
- public:
- typedef uint64_t baddr_t;
-
- protected:
- PhysicalMemory *physmem;
- DiskImage *image;
-
- public:
- SimpleDisk(const std::string &name, PhysicalMemory *pmem, DiskImage *img);
- ~SimpleDisk();
-
- void read(Addr addr, baddr_t block, int count) const;
- void write(Addr addr, baddr_t block, int count);
-};
-
-#endif // __DEV_SIMPLE_DISK_HH__
diff --git a/dev/sinic.cc b/dev/sinic.cc
deleted file mode 100644
index 0853717ba..000000000
--- a/dev/sinic.cc
+++ /dev/null
@@ -1,1905 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <cstdio>
-#include <deque>
-#include <string>
-
-#include "base/inet.hh"
-#include "cpu/exec_context.hh"
-#include "cpu/intr_control.hh"
-#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 "sim/builder.hh"
-#include "sim/debug.hh"
-#include "sim/eventq.hh"
-#include "sim/host.hh"
-#include "sim/stats.hh"
-#include "arch/vtophys.hh"
-
-using namespace Net;
-using namespace TheISA;
-
-namespace Sinic {
-
-const char *RxStateStrings[] =
-{
- "rxIdle",
- "rxFifoBlock",
- "rxBeginCopy",
- "rxCopy",
- "rxCopyDone"
-};
-
-const char *TxStateStrings[] =
-{
- "txIdle",
- "txFifoBlock",
- "txBeginCopy",
- "txCopy",
- "txCopyDone"
-};
-
-
-///////////////////////////////////////////////////////////////////////
-//
-// Sinic PCI Device
-//
-Base::Base(Params *p)
- : PciDev(p), rxEnable(false), txEnable(false), clock(p->clock),
- intrDelay(p->intr_delay), intrTick(0), cpuIntrEnable(false),
- cpuPendingIntr(false), intrEvent(0), interface(NULL)
-{
-}
-
-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),
- dmaWriteDelay(p->dma_write_delay), dmaWriteFactor(p->dma_write_factor)
-{
- 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()
-{}
-
-void
-Device::regStats()
-{
- rxBytes
- .name(name() + ".rxBytes")
- .desc("Bytes Received")
- .prereq(rxBytes)
- ;
-
- rxBandwidth
- .name(name() + ".rxBandwidth")
- .desc("Receive Bandwidth (bits/s)")
- .precision(0)
- .prereq(rxBytes)
- ;
-
- rxPackets
- .name(name() + ".rxPackets")
- .desc("Number of Packets Received")
- .prereq(rxBytes)
- ;
-
- rxPacketRate
- .name(name() + ".rxPPS")
- .desc("Packet Reception Rate (packets/s)")
- .precision(0)
- .prereq(rxBytes)
- ;
-
- rxIpPackets
- .name(name() + ".rxIpPackets")
- .desc("Number of IP Packets Received")
- .prereq(rxBytes)
- ;
-
- rxTcpPackets
- .name(name() + ".rxTcpPackets")
- .desc("Number of Packets Received")
- .prereq(rxBytes)
- ;
-
- rxUdpPackets
- .name(name() + ".rxUdpPackets")
- .desc("Number of UDP Packets Received")
- .prereq(rxBytes)
- ;
-
- rxIpChecksums
- .name(name() + ".rxIpChecksums")
- .desc("Number of rx IP Checksums done by device")
- .precision(0)
- .prereq(rxBytes)
- ;
-
- rxTcpChecksums
- .name(name() + ".rxTcpChecksums")
- .desc("Number of rx TCP Checksums done by device")
- .precision(0)
- .prereq(rxBytes)
- ;
-
- rxUdpChecksums
- .name(name() + ".rxUdpChecksums")
- .desc("Number of rx UDP Checksums done by device")
- .precision(0)
- .prereq(rxBytes)
- ;
-
- totBandwidth
- .name(name() + ".totBandwidth")
- .desc("Total Bandwidth (bits/s)")
- .precision(0)
- .prereq(totBytes)
- ;
-
- totPackets
- .name(name() + ".totPackets")
- .desc("Total Packets")
- .precision(0)
- .prereq(totBytes)
- ;
-
- totBytes
- .name(name() + ".totBytes")
- .desc("Total Bytes")
- .precision(0)
- .prereq(totBytes)
- ;
-
- totPacketRate
- .name(name() + ".totPPS")
- .desc("Total Tranmission Rate (packets/s)")
- .precision(0)
- .prereq(totBytes)
- ;
-
- txBytes
- .name(name() + ".txBytes")
- .desc("Bytes Transmitted")
- .prereq(txBytes)
- ;
-
- txBandwidth
- .name(name() + ".txBandwidth")
- .desc("Transmit Bandwidth (bits/s)")
- .precision(0)
- .prereq(txBytes)
- ;
-
- txPackets
- .name(name() + ".txPackets")
- .desc("Number of Packets Transmitted")
- .prereq(txBytes)
- ;
-
- txPacketRate
- .name(name() + ".txPPS")
- .desc("Packet Tranmission Rate (packets/s)")
- .precision(0)
- .prereq(txBytes)
- ;
-
- txIpPackets
- .name(name() + ".txIpPackets")
- .desc("Number of IP Packets Transmitted")
- .prereq(txBytes)
- ;
-
- txTcpPackets
- .name(name() + ".txTcpPackets")
- .desc("Number of TCP Packets Transmitted")
- .prereq(txBytes)
- ;
-
- txUdpPackets
- .name(name() + ".txUdpPackets")
- .desc("Number of Packets Transmitted")
- .prereq(txBytes)
- ;
-
- txIpChecksums
- .name(name() + ".txIpChecksums")
- .desc("Number of tx IP Checksums done by device")
- .precision(0)
- .prereq(txBytes)
- ;
-
- txTcpChecksums
- .name(name() + ".txTcpChecksums")
- .desc("Number of tx TCP Checksums done by device")
- .precision(0)
- .prereq(txBytes)
- ;
-
- txUdpChecksums
- .name(name() + ".txUdpChecksums")
- .desc("Number of tx UDP Checksums done by device")
- .precision(0)
- .prereq(txBytes)
- ;
-
- txBandwidth = txBytes * Stats::constant(8) / simSeconds;
- rxBandwidth = rxBytes * Stats::constant(8) / simSeconds;
- totBandwidth = txBandwidth + rxBandwidth;
- totBytes = txBytes + rxBytes;
- totPackets = txPackets + rxPackets;
- txPacketRate = txPackets / simSeconds;
- 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)
-{
- int size = virtualRegs.size();
- if (index > size)
- panic("Trying to access a vnic that doesn't exist %d > %d\n",
- index, size);
-}
-
-void
-Device::prepareRead(int cpu, int index)
-{
- using namespace Regs;
- prepareIO(cpu, index);
-
- VirtualReg &vnic = virtualRegs[index];
-
- // update rx registers
- uint64_t rxdone = vnic.RxDone;
- rxdone = set_RxDone_Packets(rxdone, rxFifo.countPacketsAfter(rxFifoPtr));
- rxdone = set_RxDone_Empty(rxdone, rxFifo.empty());
- rxdone = set_RxDone_High(rxdone, rxFifo.size() > regs.RxFifoMark);
- rxdone = set_RxDone_NotHigh(rxdone, rxLow);
- regs.RxData = vnic.RxData;
- regs.RxDone = rxdone;
- regs.RxWait = rxdone;
-
- // update tx regsiters
- uint64_t txdone = vnic.TxDone;
- txdone = set_TxDone_Packets(txdone, txFifo.packets());
- txdone = set_TxDone_Full(txdone, txFifo.avail() < regs.TxMaxCopy);
- txdone = set_TxDone_Low(txdone, txFifo.size() < regs.TxFifoMark);
- regs.TxData = vnic.TxData;
- regs.TxDone = txdone;
- regs.TxWait = txdone;
-}
-
-void
-Device::prepareWrite(int cpu, int index)
-{
- prepareIO(cpu, index);
-}
-
-/**
- * I/O read of device register
- */
-Fault
-Device::read(MemReqPtr &req, uint8_t *data)
-{
- 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();
- }
-
- return fault;
-}
-
-Fault
-Device::readBar0(MemReqPtr &req, Addr daddr, uint8_t *data)
-{
- int cpu = (req->xc->readMiscReg(TheISA::IPR_PALtemp16) >> 8) & 0xff;
- Addr index = daddr >> Regs::VirtualShift;
- Addr raddr = daddr & Regs::VirtualMask;
-
- 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);
-
- 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);
-
- 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);
-
- prepareRead(cpu, index);
-
- uint64_t value = 0;
- if (req->size == 4) {
- uint32_t &reg = *(uint32_t *)data;
- reg = regData32(raddr);
- value = reg;
- }
-
- if (req->size == 8) {
- uint64_t &reg = *(uint64_t *)data;
- reg = regData64(raddr);
- 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);
-
- // reading the interrupt status register has the side effect of
- // clearing it
- if (raddr == Regs::IntrStatus)
- devIntrClear();
-
- return NoFault;
-}
-
-/**
- * IPR read of device register
- */
-Fault
-Device::iprRead(Addr daddr, int cpu, uint64_t &result)
-{
- if (!regValid(daddr))
- panic("invalid address: da=%#x", daddr);
-
- const Regs::Info &info = regInfo(daddr);
- if (!info.read)
- panic("reading %s (write only): cpu=%d da=%#x", info.name, cpu, daddr);
-
- DPRINTF(EthernetPIO, "IPR read %s: cpu=%d da=%#x\n",
- info.name, cpu, daddr);
-
- prepareRead(cpu, 0);
-
- if (info.size == 4)
- result = regData32(daddr);
-
- if (info.size == 8)
- result = regData64(daddr);
-
- DPRINTF(EthernetPIO, "IPR read %s: cpu=%s da=%#x val=%#x\n",
- info.name, cpu, result);
-
- return NoFault;
-}
-
-/**
- * I/O write of device register
- */
-Fault
-Device::write(MemReqPtr &req, const uint8_t *data)
-{
- 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);
-
- 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;
- Addr index = daddr >> Regs::VirtualShift;
- Addr raddr = daddr & Regs::VirtualMask;
-
- if (!regValid(raddr))
- panic("invalid address: cpu=%d da=%#x pa=%#x va=%#x size=%d",
- cpu, daddr, req->paddr, req->vaddr, req->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);
-
- if (req->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);
-
- 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);
-
- prepareWrite(cpu, index);
-
- switch (raddr) {
- case Regs::Config:
- changeConfig(reg32);
- break;
-
- case Regs::Command:
- command(reg32);
- break;
-
- case Regs::IntrStatus:
- devIntrClear(regs.IntrStatus & reg32);
- break;
-
- case Regs::IntrMask:
- devIntrChangeMask(reg32);
- break;
-
- case Regs::RxData:
- if (Regs::get_RxDone_Busy(vnic.RxDone))
- panic("receive machine busy with another request! rxState=%s",
- RxStateStrings[rxState]);
-
- vnic.rxUnique = rxUnique++;
- vnic.RxDone = Regs::RxDone_Busy;
- vnic.RxData = reg64;
-
- if (Regs::get_RxData_Vaddr(reg64)) {
- Addr vaddr = Regs::get_RxData_Addr(reg64);
- Addr paddr = vtophys(req->xc, vaddr);
- DPRINTF(EthernetPIO, "write RxData vnic %d (rxunique %d): "
- "vaddr=%#x, paddr=%#x\n",
- index, vnic.rxUnique, vaddr, paddr);
-
- vnic.RxData = Regs::set_RxData_Addr(vnic.RxData, paddr);
- } else {
- DPRINTF(EthernetPIO, "write RxData vnic %d (rxunique %d)\n",
- index, vnic.rxUnique);
- }
-
- if (vnic.rxPacket == rxFifo.end()) {
- DPRINTF(EthernetPIO, "request new packet...appending to rxList\n");
- rxList.push_back(index);
- } else {
- DPRINTF(EthernetPIO, "packet exists...appending to rxBusy\n");
- rxBusy.push_back(index);
- }
-
- if (rxEnable && (rxState == rxIdle || rxState == rxFifoBlock)) {
- rxState = rxFifoBlock;
- rxKick();
- }
- break;
-
- case Regs::TxData:
- if (Regs::get_TxDone_Busy(vnic.TxDone))
- panic("transmit machine busy with another request! txState=%s",
- TxStateStrings[txState]);
-
- vnic.txUnique = txUnique++;
- vnic.TxDone = Regs::TxDone_Busy;
- vnic.TxData = reg64;
-
- if (Regs::get_TxData_Vaddr(reg64)) {
- 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);
- } else {
- DPRINTF(EthernetPIO, "write TxData vnic %d (rxunique %d)\n",
- index, vnic.txUnique);
- }
-
- if (txList.empty() || txList.front() != index)
- txList.push_back(index);
- if (txEnable && txState == txIdle && txList.front() == index) {
- txState = txFifoBlock;
- txKick();
- }
- break;
- }
-
- return NoFault;
-}
-
-void
-Device::devIntrPost(uint32_t interrupts)
-{
- if ((interrupts & Regs::Intr_Res))
- panic("Cannot set a reserved interrupt");
-
- regs.IntrStatus |= interrupts;
-
- DPRINTF(EthernetIntr,
- "interrupt written to intStatus: intr=%#x status=%#x mask=%#x\n",
- interrupts, regs.IntrStatus, regs.IntrMask);
-
- interrupts = regs.IntrStatus & regs.IntrMask;
-
- // Intr_RxHigh is special, we only signal it if we've emptied the fifo
- // and then filled it above the high watermark
- if (rxEmpty)
- rxEmpty = false;
- else
- interrupts &= ~Regs::Intr_RxHigh;
-
- // Intr_TxLow is special, we only signal it if we've filled up the fifo
- // and then dropped below the low watermark
- if (txFull)
- txFull = false;
- else
- interrupts &= ~Regs::Intr_TxLow;
-
- if (interrupts) {
- Tick when = curTick;
- if ((interrupts & Regs::Intr_NoDelay) == 0)
- when += intrDelay;
- cpuIntrPost(when);
- }
-}
-
-void
-Device::devIntrClear(uint32_t interrupts)
-{
- if ((interrupts & Regs::Intr_Res))
- panic("Cannot clear a reserved interrupt");
-
- regs.IntrStatus &= ~interrupts;
-
- DPRINTF(EthernetIntr,
- "interrupt cleared from intStatus: intr=%x status=%x mask=%x\n",
- interrupts, regs.IntrStatus, regs.IntrMask);
-
- if (!(regs.IntrStatus & regs.IntrMask))
- cpuIntrClear();
-}
-
-void
-Device::devIntrChangeMask(uint32_t newmask)
-{
- if (regs.IntrMask == newmask)
- return;
-
- regs.IntrMask = newmask;
-
- DPRINTF(EthernetIntr,
- "interrupt mask changed: intStatus=%x intMask=%x masked=%x\n",
- regs.IntrStatus, regs.IntrMask, regs.IntrStatus & regs.IntrMask);
-
- if (regs.IntrStatus & regs.IntrMask)
- cpuIntrPost(curTick);
- else
- cpuIntrClear();
-}
-
-void
-Base::cpuIntrPost(Tick when)
-{
- // If the interrupt you want to post is later than an interrupt
- // already scheduled, just let it post in the coming one and don't
- // schedule another.
- // HOWEVER, must be sure that the scheduled intrTick is in the
- // future (this was formerly the source of a bug)
- /**
- * @todo this warning should be removed and the intrTick code should
- * be fixed.
- */
- assert(when >= curTick);
- assert(intrTick >= curTick || intrTick == 0);
- if (!cpuIntrEnable) {
- DPRINTF(EthernetIntr, "interrupts not enabled.\n",
- intrTick);
- return;
- }
-
- if (when > intrTick && intrTick != 0) {
- DPRINTF(EthernetIntr, "don't need to schedule event...intrTick=%d\n",
- intrTick);
- return;
- }
-
- intrTick = when;
- if (intrTick < curTick) {
- debug_break();
- intrTick = curTick;
- }
-
- DPRINTF(EthernetIntr, "going to schedule an interrupt for intrTick=%d\n",
- intrTick);
-
- if (intrEvent)
- intrEvent->squash();
- intrEvent = new IntrEvent(this, true);
- intrEvent->schedule(intrTick);
-}
-
-void
-Base::cpuInterrupt()
-{
- assert(intrTick == curTick);
-
- // Whether or not there's a pending interrupt, we don't care about
- // it anymore
- intrEvent = 0;
- intrTick = 0;
-
- // Don't send an interrupt if there's already one
- if (cpuPendingIntr) {
- DPRINTF(EthernetIntr,
- "would send an interrupt now, but there's already pending\n");
- } else {
- // Send interrupt
- cpuPendingIntr = true;
-
- DPRINTF(EthernetIntr, "posting interrupt\n");
- intrPost();
- }
-}
-
-void
-Base::cpuIntrClear()
-{
- if (!cpuPendingIntr)
- return;
-
- if (intrEvent) {
- intrEvent->squash();
- intrEvent = 0;
- }
-
- intrTick = 0;
-
- cpuPendingIntr = false;
-
- DPRINTF(EthernetIntr, "clearing cchip interrupt\n");
- intrClear();
-}
-
-bool
-Base::cpuIntrPending() const
-{ return cpuPendingIntr; }
-
-void
-Device::changeConfig(uint32_t newconf)
-{
- uint32_t changed = regs.Config ^ newconf;
- if (!changed)
- return;
-
- regs.Config = newconf;
-
- if ((changed & Regs::Config_IntEn)) {
- cpuIntrEnable = regs.Config & Regs::Config_IntEn;
- if (cpuIntrEnable) {
- if (regs.IntrStatus & regs.IntrMask)
- cpuIntrPost(curTick);
- } else {
- cpuIntrClear();
- }
- }
-
- if ((changed & Regs::Config_TxEn)) {
- txEnable = regs.Config & Regs::Config_TxEn;
- if (txEnable)
- txKick();
- }
-
- if ((changed & Regs::Config_RxEn)) {
- rxEnable = regs.Config & Regs::Config_RxEn;
- if (rxEnable)
- rxKick();
- }
-}
-
-void
-Device::command(uint32_t command)
-{
- if (command & Regs::Command_Intr)
- devIntrPost(Regs::Intr_Soft);
-
- if (command & Regs::Command_Reset)
- reset();
-}
-
-void
-Device::reset()
-{
- using namespace Regs;
-
- memset(&regs, 0, sizeof(regs));
-
- regs.Config = 0;
- if (params()->rx_thread)
- regs.Config |= Config_RxThread;
- if (params()->tx_thread)
- regs.Config |= Config_TxThread;
- if (params()->rss)
- regs.Config |= Config_RSS;
- if (params()->zero_copy)
- regs.Config |= Config_ZeroCopy;
- if (params()->delay_copy)
- regs.Config |= Config_DelayCopy;
- if (params()->virtual_addr)
- regs.Config |= Config_Vaddr;
-
- if (params()->delay_copy && params()->zero_copy)
- panic("Can't delay copy and zero copy");
-
- regs.IntrMask = Intr_Soft | Intr_RxHigh | Intr_RxPacket | Intr_TxLow;
- regs.RxMaxCopy = params()->rx_max_copy;
- regs.TxMaxCopy = params()->tx_max_copy;
- regs.RxMaxIntr = params()->rx_max_intr;
- regs.VirtualCount = params()->virtual_count;
- regs.RxFifoSize = params()->rx_fifo_size;
- regs.TxFifoSize = params()->tx_fifo_size;
- regs.RxFifoMark = params()->rx_fifo_threshold;
- regs.TxFifoMark = params()->tx_fifo_threshold;
- regs.HwAddr = params()->eaddr;
-
- rxList.clear();
- rxBusy.clear();
- rxActive = -1;
- txList.clear();
-
- rxState = rxIdle;
- txState = txIdle;
-
- rxFifo.clear();
- rxFifoPtr = rxFifo.end();
- txFifo.clear();
- rxEmpty = false;
- rxLow = true;
- txFull = false;
-
- int size = virtualRegs.size();
- virtualRegs.clear();
- virtualRegs.resize(size);
- for (int i = 0; i < size; ++i)
- virtualRegs[i].rxPacket = rxFifo.end();
-}
-
-void
-Device::rxDmaCopy()
-{
- 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)
- txKick();
-
- rxKick();
-}
-
-void
-Device::rxKick()
-{
- VirtualReg *vnic = NULL;
-
- DPRINTF(EthernetSM, "rxKick: rxState=%s (rxFifo.size=%d)\n",
- RxStateStrings[rxState], rxFifo.size());
-
- if (rxKickTick > curTick) {
- DPRINTF(EthernetSM, "rxKick: exiting, can't run till %d\n",
- rxKickTick);
- return;
- }
-
- next:
- if (rxState == rxIdle)
- goto exit;
-
- if (rxActive == -1) {
- if (rxState != rxFifoBlock)
- panic("no active vnic while in state %s", RxStateStrings[rxState]);
-
- DPRINTF(EthernetSM, "processing rxState=%s\n",
- RxStateStrings[rxState]);
- } else {
- vnic = &virtualRegs[rxActive];
- DPRINTF(EthernetSM,
- "processing rxState=%s for vnic %d (rxunique %d)\n",
- RxStateStrings[rxState], rxActive, vnic->rxUnique);
- }
-
- switch (rxState) {
- case rxFifoBlock:
- if (DTRACE(EthernetSM)) {
- PacketFifo::iterator end = rxFifo.end();
- int size = virtualRegs.size();
- for (int i = 0; i < size; ++i) {
- VirtualReg *vn = &virtualRegs[i];
- if (vn->rxPacket != end &&
- !Regs::get_RxDone_Busy(vn->RxDone)) {
- DPRINTF(EthernetSM,
- "vnic %d (rxunique %d), has outstanding packet %d\n",
- i, vn->rxUnique,
- rxFifo.countPacketsBefore(vn->rxPacket));
- }
- }
- }
-
- if (!rxBusy.empty()) {
- rxActive = rxBusy.front();
- rxBusy.pop_front();
- vnic = &virtualRegs[rxActive];
-
- if (vnic->rxPacket == rxFifo.end())
- panic("continuing vnic without packet\n");
-
- DPRINTF(EthernetSM,
- "continue processing for vnic %d (rxunique %d)\n",
- rxActive, vnic->rxUnique);
-
- rxState = rxBeginCopy;
-
- break;
- }
-
- if (rxFifoPtr == rxFifo.end()) {
- DPRINTF(EthernetSM, "receive waiting for data. Nothing to do.\n");
- goto exit;
- }
-
- if (rxList.empty())
- panic("Not idle, but nothing to do!");
-
- assert(!rxFifo.empty());
-
- rxActive = rxList.front();
- rxList.pop_front();
- vnic = &virtualRegs[rxActive];
-
- DPRINTF(EthernetSM,
- "processing new packet for vnic %d (rxunique %d)\n",
- rxActive, vnic->rxUnique);
-
- // Grab a new packet from the fifo.
- vnic->rxPacket = rxFifoPtr++;
- vnic->rxPacketOffset = 0;
- vnic->rxPacketBytes = (*vnic->rxPacket)->length;
- assert(vnic->rxPacketBytes);
-
- vnic->rxDoneData = 0;
- /* scope for variables */ {
- IpPtr ip(*vnic->rxPacket);
- if (ip) {
- DPRINTF(Ethernet, "ID is %d\n", ip->id());
- vnic->rxDoneData |= Regs::RxDone_IpPacket;
- rxIpChecksums++;
- if (cksum(ip) != 0) {
- DPRINTF(EthernetCksum, "Rx IP Checksum Error\n");
- vnic->rxDoneData |= Regs::RxDone_IpError;
- }
- TcpPtr tcp(ip);
- UdpPtr udp(ip);
- if (tcp) {
- DPRINTF(Ethernet,
- "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n",
- tcp->sport(), tcp->dport(), tcp->seq(),
- tcp->ack());
- vnic->rxDoneData |= Regs::RxDone_TcpPacket;
- rxTcpChecksums++;
- if (cksum(tcp) != 0) {
- DPRINTF(EthernetCksum, "Rx TCP Checksum Error\n");
- vnic->rxDoneData |= Regs::RxDone_TcpError;
- }
- } else if (udp) {
- vnic->rxDoneData |= Regs::RxDone_UdpPacket;
- rxUdpChecksums++;
- if (cksum(udp) != 0) {
- DPRINTF(EthernetCksum, "Rx UDP Checksum Error\n");
- vnic->rxDoneData |= Regs::RxDone_UdpError;
- }
- }
- }
- }
- rxState = rxBeginCopy;
- break;
-
- case rxBeginCopy:
- if (dmaInterface && dmaInterface->busy())
- goto exit;
-
- rxDmaAddr = plat->pciToDma(Regs::get_RxData_Addr(vnic->RxData));
- rxDmaLen = 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();
- break;
-
- case rxCopy:
- DPRINTF(EthernetSM, "receive machine still copying\n");
- goto exit;
-
- case rxCopyDone:
- vnic->RxDone = vnic->rxDoneData;
- vnic->RxDone |= Regs::RxDone_Complete;
-
- if (vnic->rxPacketBytes == rxDmaLen) {
- // Packet is complete. Indicate how many bytes were copied
- vnic->RxDone = Regs::set_RxDone_CopyLen(vnic->RxDone, rxDmaLen);
-
- DPRINTF(EthernetSM,
- "rxKick: packet complete on vnic %d (rxunique %d)\n",
- rxActive, vnic->rxUnique);
- rxFifo.remove(vnic->rxPacket);
- vnic->rxPacket = rxFifo.end();
- } else {
- vnic->rxPacketBytes -= rxDmaLen;
- vnic->rxPacketOffset += rxDmaLen;
- vnic->RxDone |= Regs::RxDone_More;
- vnic->RxDone = Regs::set_RxDone_CopyLen(vnic->RxDone,
- vnic->rxPacketBytes);
- DPRINTF(EthernetSM,
- "rxKick: packet not complete on vnic %d (rxunique %d): "
- "%d bytes left\n",
- rxActive, vnic->rxUnique, vnic->rxPacketBytes);
- }
-
- rxActive = -1;
- rxState = rxBusy.empty() && rxList.empty() ? rxIdle : rxFifoBlock;
-
- if (rxFifo.empty()) {
- devIntrPost(Regs::Intr_RxEmpty);
- rxEmpty = true;
- }
-
- if (rxFifo.size() < params()->rx_fifo_low_mark)
- rxLow = true;
-
- if (rxFifo.size() > params()->rx_fifo_threshold)
- rxLow = false;
-
- devIntrPost(Regs::Intr_RxDMA);
- break;
-
- default:
- panic("Invalid rxState!");
- }
-
- DPRINTF(EthernetSM, "entering next rxState=%s\n",
- RxStateStrings[rxState]);
-
- goto next;
-
- exit:
- /**
- * @todo do we want to schedule a future kick?
- */
- DPRINTF(EthernetSM, "rx state machine exited rxState=%s\n",
- RxStateStrings[rxState]);
-}
-
-void
-Device::txDmaCopy()
-{
- 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)
- rxKick();
-
- txKick();
-}
-
-void
-Device::transmit()
-{
- if (txFifo.empty()) {
- DPRINTF(Ethernet, "nothing to transmit\n");
- return;
- }
-
- uint32_t interrupts;
- PacketPtr packet = txFifo.front();
- if (!interface->sendPacket(packet)) {
- DPRINTF(Ethernet, "Packet Transmit: failed txFifo available %d\n",
- txFifo.avail());
- goto reschedule;
- }
-
- txFifo.pop();
-#if TRACING_ON
- if (DTRACE(Ethernet)) {
- IpPtr ip(packet);
- if (ip) {
- DPRINTF(Ethernet, "ID is %d\n", ip->id());
- TcpPtr tcp(ip);
- if (tcp) {
- DPRINTF(Ethernet,
- "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n",
- tcp->sport(), tcp->dport(), tcp->seq(),
- tcp->ack());
- }
- }
- }
-#endif
-
- DDUMP(EthernetData, packet->data, packet->length);
- txBytes += packet->length;
- txPackets++;
-
- DPRINTF(Ethernet, "Packet Transmit: successful txFifo Available %d\n",
- txFifo.avail());
-
- interrupts = Regs::Intr_TxPacket;
- if (txFifo.size() < regs.TxFifoMark)
- interrupts |= Regs::Intr_TxLow;
- devIntrPost(interrupts);
-
- reschedule:
- if (!txFifo.empty() && !txEvent.scheduled()) {
- DPRINTF(Ethernet, "reschedule transmit\n");
- txEvent.schedule(curTick + retryTime);
- }
-}
-
-void
-Device::txKick()
-{
- VirtualReg *vnic;
- DPRINTF(EthernetSM, "txKick: txState=%s (txFifo.size=%d)\n",
- TxStateStrings[txState], txFifo.size());
-
- if (txKickTick > curTick) {
- DPRINTF(EthernetSM, "txKick: exiting, can't run till %d\n",
- txKickTick);
- return;
- }
-
- next:
- if (txState == txIdle)
- goto exit;
-
- assert(!txList.empty());
- vnic = &virtualRegs[txList.front()];
-
- switch (txState) {
- case txFifoBlock:
- assert(Regs::get_TxDone_Busy(vnic->TxDone));
- if (!txPacket) {
- // Grab a new packet from the fifo.
- txPacket = new PacketData(16384);
- txPacketOffset = 0;
- }
-
- if (txFifo.avail() - txPacket->length <
- Regs::get_TxData_Len(vnic->TxData)) {
- DPRINTF(EthernetSM, "transmit fifo full. Nothing to do.\n");
- goto exit;
- }
-
- txState = txBeginCopy;
- break;
-
- case txBeginCopy:
- if (dmaInterface && dmaInterface->busy())
- goto exit;
-
- txDmaAddr = plat->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();
- break;
-
- case txCopy:
- DPRINTF(EthernetSM, "transmit machine still copying\n");
- goto exit;
-
- case txCopyDone:
- vnic->TxDone = txDmaLen | Regs::TxDone_Complete;
- txPacket->length += txDmaLen;
- if ((vnic->TxData & Regs::TxData_More)) {
- txPacketOffset += txDmaLen;
- txState = txIdle;
- devIntrPost(Regs::Intr_TxDMA);
- break;
- }
-
- assert(txPacket->length <= txFifo.avail());
- if ((vnic->TxData & Regs::TxData_Checksum)) {
- IpPtr ip(txPacket);
- if (ip) {
- TcpPtr tcp(ip);
- if (tcp) {
- tcp->sum(0);
- tcp->sum(cksum(tcp));
- txTcpChecksums++;
- }
-
- UdpPtr udp(ip);
- if (udp) {
- udp->sum(0);
- udp->sum(cksum(udp));
- txUdpChecksums++;
- }
-
- ip->sum(0);
- ip->sum(cksum(ip));
- txIpChecksums++;
- }
- }
-
- txFifo.push(txPacket);
- if (txFifo.avail() < regs.TxMaxCopy) {
- devIntrPost(Regs::Intr_TxFull);
- txFull = true;
- }
- txPacket = 0;
- transmit();
- txList.pop_front();
- txState = txList.empty() ? txIdle : txFifoBlock;
- devIntrPost(Regs::Intr_TxDMA);
- break;
-
- default:
- panic("Invalid txState!");
- }
-
- DPRINTF(EthernetSM, "entering next txState=%s\n",
- TxStateStrings[txState]);
-
- goto next;
-
- exit:
- /**
- * @todo do we want to schedule a future kick?
- */
- DPRINTF(EthernetSM, "tx state machine exited txState=%s\n",
- TxStateStrings[txState]);
-}
-
-void
-Device::transferDone()
-{
- if (txFifo.empty()) {
- DPRINTF(Ethernet, "transfer complete: txFifo empty...nothing to do\n");
- return;
- }
-
- DPRINTF(Ethernet, "transfer complete: data in txFifo...schedule xmit\n");
-
- if (txEvent.scheduled())
- txEvent.reschedule(curTick + cycles(1));
- else
- txEvent.schedule(curTick + cycles(1));
-}
-
-bool
-Device::rxFilter(const PacketPtr &packet)
-{
- if (!Regs::get_Config_Filter(regs.Config))
- return false;
-
- panic("receive filter not implemented\n");
- bool drop = true;
-
-#if 0
- string type;
-
- EthHdr *eth = packet->eth();
- if (eth->unicast()) {
- // If we're accepting all unicast addresses
- if (acceptUnicast)
- drop = false;
-
- // If we make a perfect match
- if (acceptPerfect && params->eaddr == eth.dst())
- drop = false;
-
- if (acceptArp && eth->type() == ETH_TYPE_ARP)
- drop = false;
-
- } else if (eth->broadcast()) {
- // if we're accepting broadcasts
- if (acceptBroadcast)
- drop = false;
-
- } else if (eth->multicast()) {
- // if we're accepting all multicasts
- if (acceptMulticast)
- drop = false;
-
- }
-
- if (drop) {
- DPRINTF(Ethernet, "rxFilter drop\n");
- DDUMP(EthernetData, packet->data, packet->length);
- }
-#endif
- return drop;
-}
-
-bool
-Device::recvPacket(PacketPtr packet)
-{
- rxBytes += packet->length;
- rxPackets++;
-
- DPRINTF(Ethernet, "Receiving packet from wire, rxFifo Available is %d\n",
- rxFifo.avail());
-
- if (!rxEnable) {
- DPRINTF(Ethernet, "receive disabled...packet dropped\n");
- return true;
- }
-
- if (rxFilter(packet)) {
- DPRINTF(Ethernet, "packet filtered...dropped\n");
- return true;
- }
-
- if (rxFifo.size() >= regs.RxFifoMark)
- devIntrPost(Regs::Intr_RxHigh);
-
- if (!rxFifo.push(packet)) {
- DPRINTF(Ethernet,
- "packet will not fit in receive buffer...packet dropped\n");
- return false;
- }
-
- // If we were at the last element, back up one ot go to the new
- // last element of the list.
- if (rxFifoPtr == rxFifo.end())
- --rxFifoPtr;
-
- devIntrPost(Regs::Intr_RxPacket);
- rxKick();
- return true;
-}
-
-//=====================================================================
-//
-//
-void
-Base::serialize(ostream &os)
-{
- // Serialize the PciDev base class
- PciDev::serialize(os);
-
- SERIALIZE_SCALAR(rxEnable);
- SERIALIZE_SCALAR(txEnable);
- SERIALIZE_SCALAR(cpuIntrEnable);
-
- /*
- * Keep track of pending interrupt status.
- */
- SERIALIZE_SCALAR(intrTick);
- SERIALIZE_SCALAR(cpuPendingIntr);
- Tick intrEventTick = 0;
- if (intrEvent)
- intrEventTick = intrEvent->when();
- SERIALIZE_SCALAR(intrEventTick);
-}
-
-void
-Base::unserialize(Checkpoint *cp, const std::string &section)
-{
- // Unserialize the PciDev base class
- PciDev::unserialize(cp, section);
-
- UNSERIALIZE_SCALAR(rxEnable);
- UNSERIALIZE_SCALAR(txEnable);
- UNSERIALIZE_SCALAR(cpuIntrEnable);
-
- /*
- * Keep track of pending interrupt status.
- */
- UNSERIALIZE_SCALAR(intrTick);
- UNSERIALIZE_SCALAR(cpuPendingIntr);
- Tick intrEventTick;
- UNSERIALIZE_SCALAR(intrEventTick);
- if (intrEventTick) {
- intrEvent = new IntrEvent(this, true);
- intrEvent->schedule(intrEventTick);
- }
-}
-
-void
-Device::serialize(ostream &os)
-{
- int count;
-
- // Serialize the PciDev base class
- Base::serialize(os);
-
- if (rxState == rxCopy)
- panic("can't serialize with an in flight dma request rxState=%s",
- RxStateStrings[rxState]);
-
- if (txState == txCopy)
- panic("can't serialize with an in flight dma request txState=%s",
- TxStateStrings[txState]);
-
- /*
- * Serialize the device registers
- */
- SERIALIZE_SCALAR(regs.Config);
- SERIALIZE_SCALAR(regs.IntrStatus);
- SERIALIZE_SCALAR(regs.IntrMask);
- SERIALIZE_SCALAR(regs.RxMaxCopy);
- SERIALIZE_SCALAR(regs.TxMaxCopy);
- SERIALIZE_SCALAR(regs.RxMaxIntr);
- SERIALIZE_SCALAR(regs.VirtualCount);
- SERIALIZE_SCALAR(regs.RxData);
- SERIALIZE_SCALAR(regs.RxDone);
- SERIALIZE_SCALAR(regs.TxData);
- SERIALIZE_SCALAR(regs.TxDone);
-
- /*
- * Serialize the virtual nic state
- */
- int virtualRegsSize = virtualRegs.size();
- SERIALIZE_SCALAR(virtualRegsSize);
- for (int i = 0; i < virtualRegsSize; ++i) {
- VirtualReg *vnic = &virtualRegs[i];
-
- string reg = csprintf("vnic%d", i);
- paramOut(os, reg + ".RxData", vnic->RxData);
- paramOut(os, reg + ".RxDone", vnic->RxDone);
- paramOut(os, reg + ".TxData", vnic->TxData);
- paramOut(os, reg + ".TxDone", vnic->TxDone);
-
- bool rxPacketExists = vnic->rxPacket != rxFifo.end();
- paramOut(os, reg + ".rxPacketExists", rxPacketExists);
- if (rxPacketExists) {
- int rxPacket = 0;
- PacketFifo::iterator i = rxFifo.begin();
- while (i != vnic->rxPacket) {
- assert(i != rxFifo.end());
- ++i;
- ++rxPacket;
- }
-
- paramOut(os, reg + ".rxPacket", rxPacket);
- paramOut(os, reg + ".rxPacketOffset", vnic->rxPacketOffset);
- paramOut(os, reg + ".rxPacketBytes", vnic->rxPacketBytes);
- }
- paramOut(os, reg + ".rxDoneData", vnic->rxDoneData);
- }
-
- int rxFifoPtr = rxFifo.countPacketsBefore(this->rxFifoPtr);
- SERIALIZE_SCALAR(rxFifoPtr);
-
- SERIALIZE_SCALAR(rxActive);
-
- VirtualList::iterator i, end;
- for (count = 0, i = rxList.begin(), end = rxList.end(); i != end; ++i)
- paramOut(os, csprintf("rxList%d", count++), *i);
- int rxListSize = count;
- SERIALIZE_SCALAR(rxListSize);
-
- for (count = 0, i = rxBusy.begin(), end = rxBusy.end(); i != end; ++i)
- paramOut(os, csprintf("rxBusy%d", count++), *i);
- int rxBusySize = count;
- SERIALIZE_SCALAR(rxBusySize);
-
- for (count = 0, i = txList.begin(), end = txList.end(); i != end; ++i)
- paramOut(os, csprintf("txList%d", count++), *i);
- int txListSize = count;
- SERIALIZE_SCALAR(txListSize);
-
- /*
- * Serialize rx state machine
- */
- int rxState = this->rxState;
- SERIALIZE_SCALAR(rxState);
- SERIALIZE_SCALAR(rxEmpty);
- SERIALIZE_SCALAR(rxLow);
- rxFifo.serialize("rxFifo", os);
-
- /*
- * Serialize tx state machine
- */
- int txState = this->txState;
- SERIALIZE_SCALAR(txState);
- SERIALIZE_SCALAR(txFull);
- txFifo.serialize("txFifo", os);
- bool txPacketExists = txPacket;
- SERIALIZE_SCALAR(txPacketExists);
- if (txPacketExists) {
- txPacket->serialize("txPacket", os);
- SERIALIZE_SCALAR(txPacketOffset);
- SERIALIZE_SCALAR(txPacketBytes);
- }
-
- /*
- * If there's a pending transmit, store the time so we can
- * reschedule it later
- */
- Tick transmitTick = txEvent.scheduled() ? txEvent.when() - curTick : 0;
- SERIALIZE_SCALAR(transmitTick);
-}
-
-void
-Device::unserialize(Checkpoint *cp, const std::string &section)
-{
- // Unserialize the PciDev base class
- Base::unserialize(cp, section);
-
- /*
- * Unserialize the device registers
- */
- UNSERIALIZE_SCALAR(regs.Config);
- UNSERIALIZE_SCALAR(regs.IntrStatus);
- UNSERIALIZE_SCALAR(regs.IntrMask);
- UNSERIALIZE_SCALAR(regs.RxMaxCopy);
- UNSERIALIZE_SCALAR(regs.TxMaxCopy);
- UNSERIALIZE_SCALAR(regs.RxMaxIntr);
- UNSERIALIZE_SCALAR(regs.VirtualCount);
- UNSERIALIZE_SCALAR(regs.RxData);
- UNSERIALIZE_SCALAR(regs.RxDone);
- UNSERIALIZE_SCALAR(regs.TxData);
- UNSERIALIZE_SCALAR(regs.TxDone);
-
- UNSERIALIZE_SCALAR(rxActive);
-
- int rxListSize;
- UNSERIALIZE_SCALAR(rxListSize);
- rxList.clear();
- for (int i = 0; i < rxListSize; ++i) {
- int value;
- paramIn(cp, section, csprintf("rxList%d", i), value);
- rxList.push_back(value);
- }
-
- int rxBusySize;
- UNSERIALIZE_SCALAR(rxBusySize);
- rxBusy.clear();
- for (int i = 0; i < rxBusySize; ++i) {
- int value;
- paramIn(cp, section, csprintf("rxBusy%d", i), value);
- rxBusy.push_back(value);
- }
-
- int txListSize;
- UNSERIALIZE_SCALAR(txListSize);
- txList.clear();
- for (int i = 0; i < txListSize; ++i) {
- int value;
- paramIn(cp, section, csprintf("txList%d", i), value);
- txList.push_back(value);
- }
-
- /*
- * Unserialize rx state machine
- */
- int rxState;
- UNSERIALIZE_SCALAR(rxState);
- UNSERIALIZE_SCALAR(rxEmpty);
- UNSERIALIZE_SCALAR(rxLow);
- this->rxState = (RxState) rxState;
- rxFifo.unserialize("rxFifo", cp, section);
-
- int rxFifoPtr;
- UNSERIALIZE_SCALAR(rxFifoPtr);
- this->rxFifoPtr = rxFifo.begin();
- for (int i = 0; i < rxFifoPtr; ++i)
- ++this->rxFifoPtr;
-
- /*
- * Unserialize tx state machine
- */
- int txState;
- UNSERIALIZE_SCALAR(txState);
- UNSERIALIZE_SCALAR(txFull);
- this->txState = (TxState) txState;
- txFifo.unserialize("txFifo", cp, section);
- bool txPacketExists;
- UNSERIALIZE_SCALAR(txPacketExists);
- txPacket = 0;
- if (txPacketExists) {
- txPacket = new PacketData(16384);
- txPacket->unserialize("txPacket", cp, section);
- UNSERIALIZE_SCALAR(txPacketOffset);
- UNSERIALIZE_SCALAR(txPacketBytes);
- }
-
- /*
- * unserialize the virtual nic registers/state
- *
- * this must be done after the unserialization of the rxFifo
- * because the packet iterators depend on the fifo being populated
- */
- int virtualRegsSize;
- UNSERIALIZE_SCALAR(virtualRegsSize);
- virtualRegs.clear();
- virtualRegs.resize(virtualRegsSize);
- for (int i = 0; i < virtualRegsSize; ++i) {
- VirtualReg *vnic = &virtualRegs[i];
- string reg = csprintf("vnic%d", i);
-
- paramIn(cp, section, reg + ".RxData", vnic->RxData);
- paramIn(cp, section, reg + ".RxDone", vnic->RxDone);
- paramIn(cp, section, reg + ".TxData", vnic->TxData);
- paramIn(cp, section, reg + ".TxDone", vnic->TxDone);
-
- vnic->rxUnique = rxUnique++;
- vnic->txUnique = txUnique++;
-
- bool rxPacketExists;
- paramIn(cp, section, reg + ".rxPacketExists", rxPacketExists);
- if (rxPacketExists) {
- int rxPacket;
- paramIn(cp, section, reg + ".rxPacket", rxPacket);
- vnic->rxPacket = rxFifo.begin();
- while (rxPacket--)
- ++vnic->rxPacket;
-
- paramIn(cp, section, reg + ".rxPacketOffset",
- vnic->rxPacketOffset);
- paramIn(cp, section, reg + ".rxPacketBytes", vnic->rxPacketBytes);
- } else {
- vnic->rxPacket = rxFifo.end();
- }
- paramIn(cp, section, reg + ".rxDoneData", vnic->rxDoneData);
- }
-
- /*
- * If there's a pending transmit, reschedule it now
- */
- Tick transmitTick;
- UNSERIALIZE_SCALAR(transmitTick);
- 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);
-
- 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;
- SimObjectParam<Device *> device;
-
-END_DECLARE_SIM_OBJECT_PARAMS(Interface)
-
-BEGIN_INIT_SIM_OBJECT_PARAMS(Interface)
-
- INIT_PARAM_DFLT(peer, "peer interface", NULL),
- INIT_PARAM(device, "Ethernet device of this interface")
-
-END_INIT_SIM_OBJECT_PARAMS(Interface)
-
-CREATE_SIM_OBJECT(Interface)
-{
- Interface *dev_int = new Interface(getInstanceName(), device);
-
- EtherInt *p = (EtherInt *)peer;
- if (p) {
- dev_int->setPeer(p);
- p->setPeer(dev_int);
- }
-
- return dev_int;
-}
-
-REGISTER_SIM_OBJECT("SinicInt", Interface)
-
-
-BEGIN_DECLARE_SIM_OBJECT_PARAMS(Device)
-
- Param<Tick> clock;
-
- Param<Addr> addr;
- SimObjectParam<MemoryController *> mmu;
- SimObjectParam<PhysicalMemory *> physmem;
- 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<HierParams *> hier;
- SimObjectParam<Bus*> pio_bus;
- SimObjectParam<Bus*> dma_bus;
- SimObjectParam<Bus*> payload_bus;
- 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;
- Param<uint32_t> rx_max_copy;
- Param<uint32_t> tx_max_copy;
- Param<uint32_t> rx_max_intr;
- Param<uint32_t> rx_fifo_size;
- Param<uint32_t> tx_fifo_size;
- Param<uint32_t> rx_fifo_threshold;
- Param<uint32_t> rx_fifo_low_mark;
- Param<uint32_t> tx_fifo_high_mark;
- Param<uint32_t> tx_fifo_threshold;
-
- Param<bool> rx_filter;
- Param<string> hardware_address;
- Param<bool> rx_thread;
- Param<bool> tx_thread;
- Param<bool> rss;
- Param<uint32_t> virtual_count;
- Param<bool> zero_copy;
- Param<bool> delay_copy;
- Param<bool> virtual_addr;
-
-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(configspace, "PCI Configspace"),
- INIT_PARAM(configdata, "PCI Config data"),
- INIT_PARAM(platform, "Platform"),
- INIT_PARAM(pci_bus, "PCI bus"),
- INIT_PARAM(pci_dev, "PCI device number"),
- INIT_PARAM(pci_func, "PCI function code"),
-
- 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"),
- INIT_PARAM(rx_max_copy, "rx max copy"),
- INIT_PARAM(tx_max_copy, "rx max copy"),
- INIT_PARAM(rx_max_intr, "rx max intr"),
- INIT_PARAM(rx_fifo_size, "max size in bytes of rxFifo"),
- INIT_PARAM(tx_fifo_size, "max size in bytes of txFifo"),
- INIT_PARAM(rx_fifo_threshold, "max size in bytes of rxFifo"),
- INIT_PARAM(rx_fifo_low_mark, "max size in bytes of rxFifo"),
- INIT_PARAM(tx_fifo_high_mark, "max size in bytes of txFifo"),
- INIT_PARAM(tx_fifo_threshold, "max size in bytes of txFifo"),
-
- INIT_PARAM(rx_filter, "Enable Receive Filter"),
- INIT_PARAM(hardware_address, "Ethernet Hardware Address"),
- INIT_PARAM(rx_thread, ""),
- INIT_PARAM(tx_thread, ""),
- INIT_PARAM(rss, ""),
- INIT_PARAM(virtual_count, ""),
- INIT_PARAM(zero_copy, ""),
- INIT_PARAM(delay_copy, ""),
- INIT_PARAM(virtual_addr, "")
-
-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->configSpace = configspace;
- params->configData = configdata;
- params->plat = platform;
- params->busNum = pci_bus;
- params->deviceNum = pci_dev;
- params->functionNum = pci_func;
-
- 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;
- params->rx_max_copy = rx_max_copy;
- params->tx_max_copy = tx_max_copy;
- params->rx_max_intr = rx_max_intr;
- params->rx_fifo_size = rx_fifo_size;
- params->tx_fifo_size = tx_fifo_size;
- params->rx_fifo_threshold = rx_fifo_threshold;
- params->rx_fifo_low_mark = rx_fifo_low_mark;
- params->tx_fifo_high_mark = tx_fifo_high_mark;
- params->tx_fifo_threshold = tx_fifo_threshold;
-
- params->rx_filter = rx_filter;
- params->eaddr = hardware_address;
- params->rx_thread = rx_thread;
- params->tx_thread = tx_thread;
- params->rss = rss;
- params->virtual_count = virtual_count;
- params->zero_copy = zero_copy;
- params->delay_copy = delay_copy;
- params->virtual_addr = virtual_addr;
-
- return new Device(params);
-}
-
-REGISTER_SIM_OBJECT("Sinic", Device)
-
-/* namespace Sinic */ }
diff --git a/dev/sinic.hh b/dev/sinic.hh
deleted file mode 100644
index 892b3ab69..000000000
--- a/dev/sinic.hh
+++ /dev/null
@@ -1,401 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __DEV_SINIC_HH__
-#define __DEV_SINIC_HH__
-
-#include "base/inet.hh"
-#include "base/statistics.hh"
-#include "dev/etherint.hh"
-#include "dev/etherpkt.hh"
-#include "dev/io_device.hh"
-#include "dev/pcidev.hh"
-#include "dev/pktfifo.hh"
-#include "dev/sinicreg.hh"
-#include "mem/bus/bus.hh"
-#include "sim/eventq.hh"
-
-namespace Sinic {
-
-class Interface;
-class Base : public PciDev
-{
- protected:
- bool rxEnable;
- bool txEnable;
- Tick clock;
- inline Tick cycles(int numCycles) const { return numCycles * clock; }
-
- protected:
- Tick intrDelay;
- Tick intrTick;
- bool cpuIntrEnable;
- bool cpuPendingIntr;
- void cpuIntrPost(Tick when);
- void cpuInterrupt();
- void cpuIntrClear();
-
- typedef EventWrapper<Base, &Base::cpuInterrupt> IntrEvent;
- friend void IntrEvent::process();
- IntrEvent *intrEvent;
- Interface *interface;
-
- bool cpuIntrPending() const;
- void cpuIntrAck() { cpuIntrClear(); }
-
-/**
- * Serialization stuff
- */
- public:
- virtual void serialize(std::ostream &os);
- virtual void unserialize(Checkpoint *cp, const std::string &section);
-
-/**
- * Construction/Destruction/Parameters
- */
- public:
- struct Params : public PciDev::Params
- {
- Tick clock;
- Tick intr_delay;
- };
-
- Base(Params *p);
-};
-
-class Device : public Base
-{
- protected:
- Platform *plat;
- PhysicalMemory *physmem;
-
- protected:
- /** Receive State Machine States */
- enum RxState {
- rxIdle,
- rxFifoBlock,
- rxBeginCopy,
- rxCopy,
- rxCopyDone
- };
-
- /** Transmit State Machine states */
- enum TxState {
- txIdle,
- txFifoBlock,
- txBeginCopy,
- txCopy,
- txCopyDone
- };
-
- /** device register file */
- struct {
- uint32_t Config; // 0x00
- uint32_t Command; // 0x04
- uint32_t IntrStatus; // 0x08
- uint32_t IntrMask; // 0x0c
- uint32_t RxMaxCopy; // 0x10
- uint32_t TxMaxCopy; // 0x14
- uint32_t RxMaxIntr; // 0x18
- uint32_t VirtualCount; // 0x1c
- uint32_t RxFifoSize; // 0x20
- uint32_t TxFifoSize; // 0x24
- uint32_t RxFifoMark; // 0x28
- uint32_t TxFifoMark; // 0x2c
- uint64_t RxData; // 0x30
- uint64_t RxDone; // 0x38
- uint64_t RxWait; // 0x40
- uint64_t TxData; // 0x48
- uint64_t TxDone; // 0x50
- uint64_t TxWait; // 0x58
- uint64_t HwAddr; // 0x60
- } regs;
-
- struct VirtualReg {
- uint64_t RxData;
- uint64_t RxDone;
- uint64_t TxData;
- uint64_t TxDone;
-
- PacketFifo::iterator rxPacket;
- int rxPacketOffset;
- int rxPacketBytes;
- uint64_t rxDoneData;
-
- Counter rxUnique;
- Counter txUnique;
-
- VirtualReg()
- : RxData(0), RxDone(0), TxData(0), TxDone(0),
- rxPacketOffset(0), rxPacketBytes(0), rxDoneData(0)
- { }
- };
- typedef std::vector<VirtualReg> VirtualRegs;
- typedef std::list<int> VirtualList;
- Counter rxUnique;
- Counter txUnique;
- VirtualRegs virtualRegs;
- VirtualList rxList;
- VirtualList rxBusy;
- int rxActive;
- VirtualList txList;
-
- uint8_t &regData8(Addr daddr) { return *((uint8_t *)&regs + daddr); }
- 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;
- PacketFifo::iterator rxFifoPtr;
- bool rxEmpty;
- bool rxLow;
- Addr rxDmaAddr;
- uint8_t *rxDmaData;
- int rxDmaLen;
-
- TxState txState;
- PacketFifo txFifo;
- bool txFull;
- PacketPtr txPacket;
- int txPacketOffset;
- int txPacketBytes;
- Addr txDmaAddr;
- uint8_t *txDmaData;
- int txDmaLen;
-
- protected:
- void reset();
-
- void rxKick();
- Tick rxKickTick;
- typedef EventWrapper<Device, &Device::rxKick> RxKickEvent;
- friend void RxKickEvent::process();
-
- void txKick();
- Tick txKickTick;
- typedef EventWrapper<Device, &Device::txKick> TxKickEvent;
- friend void TxKickEvent::process();
-
- /**
- * Retransmit event
- */
- void transmit();
- void txEventTransmit()
- {
- transmit();
- if (txState == txFifoBlock)
- txKick();
- }
- typedef EventWrapper<Device, &Device::txEventTransmit> TxEvent;
- friend void TxEvent::process();
- TxEvent txEvent;
-
- void txDump() const;
- void rxDump() const;
-
- /**
- * receive address filter
- */
- bool rxFilter(const PacketPtr &packet);
-
-/**
- * device configuration
- */
- void changeConfig(uint32_t newconfig);
- void command(uint32_t command);
-
-/**
- * device ethernet interface
- */
- public:
- bool recvPacket(PacketPtr packet);
- void transferDone();
- void setInterface(Interface *i) { assert(!interface); interface = i; }
-
-/**
- * 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;
-
- Tick dmaReadDelay;
- Tick dmaReadFactor;
- Tick dmaWriteDelay;
- Tick dmaWriteFactor;
-
-/**
- * Interrupt management
- */
- protected:
- void devIntrPost(uint32_t interrupts);
- void devIntrClear(uint32_t interrupts = Regs::Intr_All);
- 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);
-
- 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);
-
-/**
- * Statistics
- */
- private:
- Stats::Scalar<> rxBytes;
- Stats::Formula rxBandwidth;
- Stats::Scalar<> rxPackets;
- Stats::Formula rxPacketRate;
- Stats::Scalar<> rxIpPackets;
- Stats::Scalar<> rxTcpPackets;
- Stats::Scalar<> rxUdpPackets;
- Stats::Scalar<> rxIpChecksums;
- Stats::Scalar<> rxTcpChecksums;
- Stats::Scalar<> rxUdpChecksums;
-
- Stats::Scalar<> txBytes;
- Stats::Formula txBandwidth;
- Stats::Formula totBandwidth;
- Stats::Formula totPackets;
- Stats::Formula totBytes;
- Stats::Formula totPacketRate;
- Stats::Scalar<> txPackets;
- Stats::Formula txPacketRate;
- Stats::Scalar<> txIpPackets;
- Stats::Scalar<> txTcpPackets;
- Stats::Scalar<> txUdpPackets;
- Stats::Scalar<> txIpChecksums;
- Stats::Scalar<> txTcpChecksums;
- Stats::Scalar<> txUdpChecksums;
-
- public:
- virtual void regStats();
-
-/**
- * Serialization stuff
- */
- public:
- virtual void serialize(std::ostream &os);
- virtual void unserialize(Checkpoint *cp, const std::string &section);
-
-/**
- * Construction/Destruction/Parameters
- */
- 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;
- uint32_t tx_max_copy;
- uint32_t rx_max_intr;
- uint32_t rx_fifo_size;
- uint32_t tx_fifo_size;
- uint32_t rx_fifo_threshold;
- uint32_t rx_fifo_low_mark;
- uint32_t tx_fifo_high_mark;
- uint32_t tx_fifo_threshold;
- Tick dma_read_delay;
- Tick dma_read_factor;
- Tick dma_write_delay;
- Tick dma_write_factor;
- bool dma_no_allocate;
- bool rx_thread;
- bool tx_thread;
- bool rss;
- uint32_t virtual_count;
- bool zero_copy;
- bool delay_copy;
- bool virtual_addr;
- };
-
- protected:
- const Params *params() const { return (const Params *)_params; }
-
- public:
- Device(Params *params);
- ~Device();
-};
-
-/*
- * Ethernet Interface for an Ethernet Device
- */
-class Interface : public EtherInt
-{
- private:
- Device *dev;
-
- public:
- Interface(const std::string &name, Device *d)
- : EtherInt(name), dev(d) { dev->setInterface(this); }
-
- virtual bool recvPacket(PacketPtr pkt) { return dev->recvPacket(pkt); }
- virtual void sendDone() { dev->transferDone(); }
-};
-
-/* namespace Sinic */ }
-
-#endif // __DEV_SINIC_HH__
diff --git a/dev/tsunami.cc b/dev/tsunami.cc
deleted file mode 100644
index 58fc7434e..000000000
--- a/dev/tsunami.cc
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @file
- * Implementation of Tsunami platform.
- */
-
-#include <deque>
-#include <string>
-#include <vector>
-
-#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"
-
-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)
-{
- // set the back pointer from the system to myself
- system->platform = this;
-
- for (int i = 0; i < Tsunami::Max_CPUs; i++)
- intr_sum_type[i] = 0;
-}
-
-Tick
-Tsunami::intrFrequency()
-{
- return io->frequency();
-}
-
-void
-Tsunami::postConsoleInt()
-{
- io->postPIC(0x10);
-}
-
-void
-Tsunami::clearConsoleInt()
-{
- io->clearPIC(0x10);
-}
-
-void
-Tsunami::postPciInt(int line)
-{
- cchip->postDRIR(line);
-}
-
-void
-Tsunami::clearPciInt(int line)
-{
- cchip->clearDRIR(line);
-}
-
-Addr
-Tsunami::pciToDma(Addr pciAddr) const
-{
- return pchip->translatePciToDma(pciAddr);
-}
-
-void
-Tsunami::serialize(std::ostream &os)
-{
- SERIALIZE_ARRAY(intr_sum_type, Tsunami::Max_CPUs);
-}
-
-void
-Tsunami::unserialize(Checkpoint *cp, const std::string &section)
-{
- UNSERIALIZE_ARRAY(intr_sum_type, Tsunami::Max_CPUs);
-}
-
-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")
-
-END_INIT_SIM_OBJECT_PARAMS(Tsunami)
-
-CREATE_SIM_OBJECT(Tsunami)
-{
- return new Tsunami(getInstanceName(), system, intrctrl, pciconfig);
-}
-
-REGISTER_SIM_OBJECT("Tsunami", Tsunami)
diff --git a/dev/tsunami.hh b/dev/tsunami.hh
deleted file mode 100644
index 7fd91d5b2..000000000
--- a/dev/tsunami.hh
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * @file
- * Declaration of top level class for the Tsunami chipset. This class just
- * retains pointers to all its children so the children can communicate.
- */
-
-#ifndef __DEV_TSUNAMI_HH__
-#define __DEV_TSUNAMI_HH__
-
-#include "dev/platform.hh"
-
-class IdeController;
-class TlaserClock;
-class NSGigE;
-class TsunamiCChip;
-class TsunamiPChip;
-class TsunamiIO;
-class PciConfigAll;
-class System;
-
-/**
- * Top level class for Tsunami Chipset emulation.
- * This structure just contains pointers to all the
- * children so the children can commnicate to do the
- * read work
- */
-
-class Tsunami : public Platform
-{
- public:
- /** Max number of CPUs in a Tsunami */
- static const int Max_CPUs = 64;
-
- /** Pointer to the system */
- System *system;
-
- /** Pointer to the TsunamiIO device which has the RTC */
- TsunamiIO *io;
-
- /** Pointer to the Tsunami CChip.
- * The chip contains some configuration information and
- * all the interrupt mask and status registers
- */
- TsunamiCChip *cchip;
-
- /** Pointer to the Tsunami PChip.
- * The pchip is the interface to the PCI bus, in our case
- * it does not have to do much.
- */
- TsunamiPChip *pchip;
-
- int intr_sum_type[Tsunami::Max_CPUs];
- int ipi_pending[Tsunami::Max_CPUs];
-
- public:
- /**
- * Constructor for the Tsunami Class.
- * @param name name of the object
- * @param intrctrl pointer to the interrupt controller
- */
- Tsunami(const std::string &name, System *s, IntrControl *intctrl,
- PciConfigAll *pci);
-
- /**
- * Return the interrupting frequency to AlphaAccess
- * @return frequency of RTC interrupts
- */
- virtual Tick intrFrequency();
-
- /**
- * Cause the cpu to post a serial interrupt to the CPU.
- */
- virtual void postConsoleInt();
-
- /**
- * Clear a posted CPU interrupt (id=55)
- */
- virtual void clearConsoleInt();
-
- /**
- * Cause the chipset to post a cpi interrupt to the CPU.
- */
- virtual void postPciInt(int line);
-
- /**
- * Clear a posted PCI->CPU interrupt
- */
- virtual void clearPciInt(int line);
-
- virtual Addr pciToDma(Addr pciAddr) const;
-
- /**
- * Serialize this object to the given output stream.
- * @param os The stream to serialize to.
- */
- virtual void serialize(std::ostream &os);
-
- /**
- * Reconstruct the state of this object from a checkpoint.
- * @param cp The checkpoint use.
- * @param section The section name of this object
- */
- virtual void unserialize(Checkpoint *cp, const std::string &section);
-};
-
-#endif // __DEV_TSUNAMI_HH__
diff --git a/dev/tsunami_cchip.cc b/dev/tsunami_cchip.cc
deleted file mode 100644
index 2649fe27a..000000000
--- a/dev/tsunami_cchip.cc
+++ /dev/null
@@ -1,580 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @file
- * Emulation of the Tsunami CChip CSRs
- */
-
-#include <deque>
-#include <string>
-#include <vector>
-
-#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 "cpu/exec_context.hh"
-#include "cpu/intr_control.hh"
-#include "sim/builder.hh"
-#include "sim/system.hh"
-
-using namespace std;
-//Should this be AlphaISA?
-using namespace TheISA;
-
-TsunamiCChip::TsunamiCChip(const string &name, Tsunami *t, Addr a,
- MemoryController *mmu, HierParams *hier,
- Bus* pio_bus, Tick pio_latency)
- : PioDevice(name, t), addr(a), tsunami(t)
-{
- 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;
- }
-
- drir = 0;
- ipint = 0;
- itint = 0;
-
- for (int x = 0; x < Tsunami::Max_CPUs; x++)
- {
- dim[x] = 0;
- dir[x] = 0;
- }
-
- //Put back pointer in tsunami
- tsunami->cchip = this;
-}
-
-Fault
-TsunamiCChip::read(MemReqPtr &req, uint8_t *data)
-{
- DPRINTF(Tsunami, "read va=%#x size=%d\n", req->vaddr, req->size);
-
- Addr regnum = (req->paddr - (addr & EV5::PAddrImplMask)) >> 6;
- Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask));
-
- ExecContext *xc = req->xc;
-
- switch (req->size) {
-
- case sizeof(uint64_t):
- if (daddr & TSDEV_CC_BDIMS)
- {
- *(uint64_t*)data = dim[(daddr >> 4) & 0x3F];
- return NoFault;
- }
-
- if (daddr & TSDEV_CC_BDIRS)
- {
- *(uint64_t*)data = dir[(daddr >> 4) & 0x3F];
- return NoFault;
- }
-
- switch(regnum) {
- case TSDEV_CC_CSR:
- *(uint64_t*)data = 0x0;
- return NoFault;
- case TSDEV_CC_MTR:
- panic("TSDEV_CC_MTR not implemeted\n");
- return NoFault;
- case TSDEV_CC_MISC:
- *(uint64_t*)data = (ipint << 8) & 0xF |
- (itint << 4) & 0xF |
- (xc->readCpuId() & 0x3);
- return NoFault;
- case TSDEV_CC_AAR0:
- case TSDEV_CC_AAR1:
- case TSDEV_CC_AAR2:
- case TSDEV_CC_AAR3:
- *(uint64_t*)data = 0;
- return NoFault;
- case TSDEV_CC_DIM0:
- *(uint64_t*)data = dim[0];
- return NoFault;
- case TSDEV_CC_DIM1:
- *(uint64_t*)data = dim[1];
- return NoFault;
- case TSDEV_CC_DIM2:
- *(uint64_t*)data = dim[2];
- return NoFault;
- case TSDEV_CC_DIM3:
- *(uint64_t*)data = dim[3];
- return NoFault;
- case TSDEV_CC_DIR0:
- *(uint64_t*)data = dir[0];
- return NoFault;
- case TSDEV_CC_DIR1:
- *(uint64_t*)data = dir[1];
- return NoFault;
- case TSDEV_CC_DIR2:
- *(uint64_t*)data = dir[2];
- return NoFault;
- case TSDEV_CC_DIR3:
- *(uint64_t*)data = dir[3];
- return NoFault;
- case TSDEV_CC_DRIR:
- *(uint64_t*)data = drir;
- return NoFault;
- case TSDEV_CC_PRBEN:
- panic("TSDEV_CC_PRBEN not implemented\n");
- return NoFault;
- case TSDEV_CC_IIC0:
- case TSDEV_CC_IIC1:
- case TSDEV_CC_IIC2:
- case TSDEV_CC_IIC3:
- panic("TSDEV_CC_IICx not implemented\n");
- return NoFault;
- case TSDEV_CC_MPR0:
- case TSDEV_CC_MPR1:
- case TSDEV_CC_MPR2:
- case TSDEV_CC_MPR3:
- panic("TSDEV_CC_MPRx not implemented\n");
- return NoFault;
- case TSDEV_CC_IPIR:
- *(uint64_t*)data = ipint;
- return NoFault;
- case TSDEV_CC_ITIR:
- *(uint64_t*)data = itint;
- return NoFault;
- 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);
-
- return NoFault;
-}
-
-Fault
-TsunamiCChip::write(MemReqPtr &req, const uint8_t *data)
-{
- DPRINTF(Tsunami, "write - va=%#x value=%#x size=%d \n",
- req->vaddr, *(uint64_t*)data, req->size);
-
- Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask));
- Addr regnum = (req->paddr - (addr & EV5::PAddrImplMask)) >> 6;
-
- bool supportedWrite = false;
-
- 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);
-
- }
-
-
- }
- }
- 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 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;
-
- if(!supportedWrite)
- panic("TSDEV_CC_MISC write not implemented\n");
-
- 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");
- }
-
- break;
- case sizeof(uint32_t):
- case sizeof(uint16_t):
- case sizeof(uint8_t):
- default:
- panic("invalid access size(?) for tsunami register!\n");
- }
-
- DPRINTFN("Tsunami ERROR: write daddr=%#x size=%d\n", daddr, req->size);
-
- return NoFault;
-}
-
-void
-TsunamiCChip::clearIPI(uint64_t ipintr)
-{
- int numcpus = tsunami->intrctrl->cpu->system->execContexts.size();
- assert(numcpus <= Tsunami::Max_CPUs);
-
- if (ipintr) {
- for (int cpunum=0; cpunum < numcpus; cpunum++) {
- // Check each cpu bit
- uint64_t cpumask = ULL(1) << cpunum;
- if (ipintr & cpumask) {
- // Check if there is a pending ipi
- if (ipint & cpumask) {
- ipint &= ~cpumask;
- tsunami->intrctrl->clear(cpunum, TheISA::INTLEVEL_IRQ3, 0);
- DPRINTF(IPI, "clear IPI IPI cpu=%d\n", cpunum);
- }
- else
- warn("clear IPI for CPU=%d, but NO IPI\n", cpunum);
- }
- }
- }
- else
- panic("Big IPI Clear, but not processors indicated\n");
-}
-
-void
-TsunamiCChip::clearITI(uint64_t itintr)
-{
- int numcpus = tsunami->intrctrl->cpu->system->execContexts.size();
- assert(numcpus <= Tsunami::Max_CPUs);
-
- if (itintr) {
- for (int i=0; i < numcpus; i++) {
- uint64_t cpumask = ULL(1) << i;
- if (itintr & cpumask & itint) {
- tsunami->intrctrl->clear(i, TheISA::INTLEVEL_IRQ2, 0);
- itint &= ~cpumask;
- DPRINTF(Tsunami, "clearing rtc interrupt to cpu=%d\n", i);
- }
- }
- }
- else
- panic("Big ITI Clear, but not processors indicated\n");
-}
-
-void
-TsunamiCChip::reqIPI(uint64_t ipreq)
-{
- int numcpus = tsunami->intrctrl->cpu->system->execContexts.size();
- assert(numcpus <= Tsunami::Max_CPUs);
-
- if (ipreq) {
- for (int cpunum=0; cpunum < numcpus; cpunum++) {
- // Check each cpu bit
- uint64_t cpumask = ULL(1) << cpunum;
- if (ipreq & cpumask) {
- // Check if there is already an ipi (bits 8:11)
- if (!(ipint & cpumask)) {
- ipint |= cpumask;
- tsunami->intrctrl->post(cpunum, TheISA::INTLEVEL_IRQ3, 0);
- DPRINTF(IPI, "send IPI cpu=%d\n", cpunum);
- }
- else
- warn("post IPI for CPU=%d, but IPI already\n", cpunum);
- }
- }
- }
- else
- panic("Big IPI Request, but not processors indicated\n");
-}
-
-
-void
-TsunamiCChip::postRTC()
-{
- int size = tsunami->intrctrl->cpu->system->execContexts.size();
- assert(size <= Tsunami::Max_CPUs);
-
- 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);
- }
- }
-
-}
-
-void
-TsunamiCChip::postDRIR(uint32_t interrupt)
-{
- uint64_t bitvector = ULL(1) << interrupt;
- uint64_t size = tsunami->intrctrl->cpu->system->execContexts.size();
- assert(size <= Tsunami::Max_CPUs);
- drir |= bitvector;
-
- 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,"
- "interrupt %d\n",i, interrupt);
- }
- }
-}
-
-void
-TsunamiCChip::clearDRIR(uint32_t interrupt)
-{
- uint64_t bitvector = ULL(1) << interrupt;
- uint64_t size = tsunami->intrctrl->cpu->system->execContexts.size();
- assert(size <= Tsunami::Max_CPUs);
-
- if (drir & bitvector)
- {
- 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,"
- "interrupt %d\n",i, interrupt);
-
- }
- 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)
-{
- SERIALIZE_ARRAY(dim, Tsunami::Max_CPUs);
- SERIALIZE_ARRAY(dir, Tsunami::Max_CPUs);
- SERIALIZE_SCALAR(ipint);
- SERIALIZE_SCALAR(itint);
- SERIALIZE_SCALAR(drir);
-}
-
-void
-TsunamiCChip::unserialize(Checkpoint *cp, const std::string &section)
-{
- UNSERIALIZE_ARRAY(dim, Tsunami::Max_CPUs);
- UNSERIALIZE_ARRAY(dir, Tsunami::Max_CPUs);
- UNSERIALIZE_SCALAR(ipint);
- UNSERIALIZE_SCALAR(itint);
- UNSERIALIZE_SCALAR(drir);
-}
-
-BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiCChip)
-
- SimObjectParam<Tsunami *> tsunami;
- SimObjectParam<MemoryController *> mmu;
- Param<Addr> addr;
- SimObjectParam<Bus*> pio_bus;
- Param<Tick> pio_latency;
- SimObjectParam<HierParams *> hier;
-
-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)
-
-END_INIT_SIM_OBJECT_PARAMS(TsunamiCChip)
-
-CREATE_SIM_OBJECT(TsunamiCChip)
-{
- return new TsunamiCChip(getInstanceName(), tsunami, addr, mmu, hier,
- pio_bus, pio_latency);
-}
-
-REGISTER_SIM_OBJECT("TsunamiCChip", TsunamiCChip)
diff --git a/dev/tsunami_cchip.hh b/dev/tsunami_cchip.hh
deleted file mode 100644
index d88ad375f..000000000
--- a/dev/tsunami_cchip.hh
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @file
- * Emulation of the Tsunami CChip CSRs
- */
-
-#ifndef __TSUNAMI_CCHIP_HH__
-#define __TSUNAMI_CCHIP_HH__
-
-#include "dev/tsunami.hh"
-#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
-{
- 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.
- * This is our access to all the other tsunami
- * devices.
- */
- Tsunami *tsunami;
-
- /**
- * The dims are device interrupt mask registers.
- * One exists for each CPU, the DRIR X DIM = DIR
- */
- uint64_t dim[Tsunami::Max_CPUs];
-
- /**
- * The dirs are device interrupt registers.
- * One exists for each CPU, the DRIR X DIM = DIR
- */
- uint64_t dir[Tsunami::Max_CPUs];
-
- /**
- * This register contains bits for each PCI interrupt
- * that can occur.
- */
- uint64_t drir;
-
- /** Indicator of which CPUs have an IPI interrupt */
- uint64_t ipint;
-
- /** Indicator of which CPUs have an RTC interrupt */
- uint64_t itint;
-
- 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
- */
- 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);
-
-
- /**
- * 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);
-
- /**
- * post an RTC interrupt to the CPU
- */
- void postRTC();
-
- /**
- * post an interrupt to the CPU.
- * @param interrupt the interrupt number to post (0-64)
- */
- void postDRIR(uint32_t interrupt);
-
- /**
- * clear an interrupt previously posted to the CPU.
- * @param interrupt the interrupt number to post (0-64)
- */
- void clearDRIR(uint32_t interrupt);
-
- /**
- * post an ipi interrupt to the CPU.
- * @param ipintr the cpu number to clear(bitvector)
- */
- void clearIPI(uint64_t ipintr);
-
- /**
- * clear a timer interrupt previously posted to the CPU.
- * @param itintr the cpu number to clear(bitvector)
- */
- void clearITI(uint64_t itintr);
-
- /**
- * request an interrupt be posted to the CPU.
- * @param ipreq the cpu number to interrupt(bitvector)
- */
- void reqIPI(uint64_t ipreq);
-
-
- /**
- * Serialize this object to the given output stream.
- * @param os The stream to serialize to.
- */
- virtual void serialize(std::ostream &os);
-
- /**
- * Reconstruct the state of this object from a checkpoint.
- * @param cp The checkpoint use.
- * @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_CCHIP_HH__
diff --git a/dev/tsunami_io.cc b/dev/tsunami_io.cc
deleted file mode 100644
index e66d6653b..000000000
--- a/dev/tsunami_io.cc
+++ /dev/null
@@ -1,719 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @file
- * Tsunami I/O including PIC, PIT, RTC, DMA
- */
-
-#include <sys/time.h>
-
-#include <deque>
-#include <string>
-#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/tsunami_cchip.hh"
-#include "dev/tsunamireg.h"
-#include "dev/rtcreg.h"
-#include "mem/functional/memory_control.hh"
-
-using namespace std;
-//Should this be AlphaISA?
-using namespace TheISA;
-
-TsunamiIO::RTC::RTC(const string &name, Tsunami* t, Tick i)
- : _name(name), event(t, i), addr(0)
-{
- memset(clock_data, 0, sizeof(clock_data));
- stat_regA = RTCA_32768HZ | RTCA_1024HZ;
- stat_regB = RTCB_PRDC_IE |RTCB_BIN | RTCB_24HR;
-}
-
-void
-TsunamiIO::RTC::set_time(time_t t)
-{
- struct tm tm;
- gmtime_r(&t, &tm);
-
- sec = tm.tm_sec;
- min = tm.tm_min;
- hour = tm.tm_hour;
- wday = tm.tm_wday + 1;
- mday = tm.tm_mday;
- mon = tm.tm_mon + 1;
- year = tm.tm_year;
-
- DPRINTFN("Real-time clock set to %s", asctime(&tm));
-}
-
-void
-TsunamiIO::RTC::writeAddr(const uint8_t *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)
-{
- if (addr < RTC_STAT_REGA)
- clock_data[addr] = *data;
- else {
- switch (addr) {
- case RTC_STAT_REGA:
- if (*data != (RTCA_32768HZ | RTCA_1024HZ))
- panic("Unimplemented RTC register A value write!\n");
- stat_regA = *data;
- break;
- case RTC_STAT_REGB:
- 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 (!event.scheduled())
- event.scheduleIntr();
- } else {
- if (event.scheduled())
- event.deschedule();
- }
- stat_regB = *data;
- break;
- case RTC_STAT_REGC:
- case RTC_STAT_REGD:
- panic("RTC status registers C and D are not implemented.\n");
- break;
- }
- }
-}
-
-void
-TsunamiIO::RTC::readData(uint8_t *data)
-{
- if (addr < RTC_STAT_REGA)
- *data = clock_data[addr];
- else {
- switch (addr) {
- case RTC_STAT_REGA:
- // toggle UIP bit for linux
- stat_regA ^= RTCA_UIP;
- *data = stat_regA;
- break;
- case RTC_STAT_REGB:
- *data = stat_regB;
- break;
- case RTC_STAT_REGC:
- case RTC_STAT_REGD:
- *data = 0x00;
- break;
- }
- }
-}
-
-void
-TsunamiIO::RTC::serialize(const string &base, ostream &os)
-{
- paramOut(os, base + ".addr", addr);
- arrayParamOut(os, base + ".clock_data", clock_data, sizeof(clock_data));
- paramOut(os, base + ".stat_regA", stat_regA);
- paramOut(os, base + ".stat_regB", stat_regB);
-}
-
-void
-TsunamiIO::RTC::unserialize(const string &base, Checkpoint *cp,
- const string &section)
-{
- paramIn(cp, section, base + ".addr", addr);
- arrayParamIn(cp, section, base + ".clock_data", clock_data,
- sizeof(clock_data));
- paramIn(cp, section, base + ".stat_regA", stat_regA);
- paramIn(cp, section, base + ".stat_regB", stat_regB);
-
- // We're not unserializing the event here, but we need to
- // rescehedule the event since curTick was moved forward by the
- // checkpoint
- event.reschedule(curTick + event.interval);
-}
-
-TsunamiIO::RTC::RTCEvent::RTCEvent(Tsunami*t, Tick i)
- : Event(&mainEventQueue), tsunami(t), interval(i)
-{
- DPRINTF(MC146818, "RTC Event Initilizing\n");
- schedule(curTick + interval);
-}
-
-void
-TsunamiIO::RTC::RTCEvent::scheduleIntr()
-{
- schedule(curTick + interval);
-}
-
-void
-TsunamiIO::RTC::RTCEvent::process()
-{
- DPRINTF(MC146818, "RTC Timer Interrupt\n");
- schedule(curTick + interval);
- //Actually interrupt the processor here
- tsunami->cchip->postRTC();
-}
-
-const char *
-TsunamiIO::RTC::RTCEvent::description()
-{
- return "tsunami RTC interrupt";
-}
-
-TsunamiIO::PITimer::PITimer(const string &name)
- : _name(name), counter0(name + ".counter0"), counter1(name + ".counter1"),
- counter2(name + ".counter2")
-{
- counter[0] = &counter0;
- counter[1] = &counter0;
- counter[2] = &counter0;
-}
-
-void
-TsunamiIO::PITimer::writeControl(const uint8_t *data)
-{
- int rw;
- int sel;
-
- sel = GET_CTRL_SEL(*data);
-
- if (sel == PIT_READ_BACK)
- panic("PITimer Read-Back Command is not implemented.\n");
-
- 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));
- }
-}
-
-void
-TsunamiIO::PITimer::serialize(const string &base, ostream &os)
-{
- // serialize the counters
- counter0.serialize(base + ".counter0", os);
- counter1.serialize(base + ".counter1", os);
- counter2.serialize(base + ".counter2", os);
-}
-
-void
-TsunamiIO::PITimer::unserialize(const string &base, Checkpoint *cp,
- const string &section)
-{
- // unserialze the counters
- counter0.unserialize(base + ".counter0", cp, section);
- counter1.unserialize(base + ".counter1", cp, section);
- counter2.unserialize(base + ".counter2", cp, section);
-}
-
-TsunamiIO::PITimer::Counter::Counter(const string &name)
- : _name(name), event(this), count(0), latched_count(0), period(0),
- mode(0), output_high(false), latch_on(false), read_byte(LSB),
- write_byte(LSB)
-{
-
-}
-
-void
-TsunamiIO::PITimer::Counter::latchCount()
-{
- // behave like a real latch
- if(!latch_on) {
- latch_on = true;
- read_byte = LSB;
- latched_count = count;
- }
-}
-
-void
-TsunamiIO::PITimer::Counter::read(uint8_t *data)
-{
- if (latch_on) {
- switch (read_byte) {
- case LSB:
- read_byte = MSB;
- *data = (uint8_t)latched_count;
- break;
- case MSB:
- read_byte = LSB;
- latch_on = false;
- *data = latched_count >> 8;
- break;
- }
- } else {
- switch (read_byte) {
- case LSB:
- read_byte = MSB;
- *data = (uint8_t)count;
- break;
- case MSB:
- read_byte = LSB;
- *data = count >> 8;
- break;
- }
- }
-}
-
-void
-TsunamiIO::PITimer::Counter::write(const uint8_t *data)
-{
- switch (write_byte) {
- case LSB:
- count = (count & 0xFF00) | *data;
-
- if (event.scheduled())
- event.deschedule();
- output_high = false;
- write_byte = MSB;
- break;
-
- case MSB:
- count = (count & 0x00FF) | (*data << 8);
- period = count;
-
- if (period > 0) {
- DPRINTF(Tsunami, "Timer set to curTick + %d\n",
- count * event.interval);
- event.schedule(curTick + count * event.interval);
- }
- write_byte = LSB;
- break;
- }
-}
-
-void
-TsunamiIO::PITimer::Counter::setRW(int rw_val)
-{
- if (rw_val != PIT_RW_16BIT)
- panic("Only LSB/MSB read/write is implemented.\n");
-}
-
-void
-TsunamiIO::PITimer::Counter::setMode(int mode_val)
-{
- if(mode_val != PIT_MODE_INTTC && mode_val != PIT_MODE_RATEGEN &&
- mode_val != PIT_MODE_SQWAVE)
- panic("PIT mode %#x is not implemented: \n", mode_val);
-
- mode = mode_val;
-}
-
-void
-TsunamiIO::PITimer::Counter::setBCD(int bcd_val)
-{
- if (bcd_val != PIT_BCD_FALSE)
- panic("PITimer does not implement BCD counts.\n");
-}
-
-bool
-TsunamiIO::PITimer::Counter::outputHigh()
-{
- return output_high;
-}
-
-void
-TsunamiIO::PITimer::Counter::serialize(const string &base, ostream &os)
-{
- paramOut(os, base + ".count", count);
- paramOut(os, base + ".latched_count", latched_count);
- paramOut(os, base + ".period", period);
- paramOut(os, base + ".mode", mode);
- paramOut(os, base + ".output_high", output_high);
- paramOut(os, base + ".latch_on", latch_on);
- paramOut(os, base + ".read_byte", read_byte);
- paramOut(os, base + ".write_byte", write_byte);
-
- Tick event_tick = 0;
- if (event.scheduled())
- event_tick = event.when();
- paramOut(os, base + ".event_tick", event_tick);
-}
-
-void
-TsunamiIO::PITimer::Counter::unserialize(const string &base, Checkpoint *cp,
- const string &section)
-{
- paramIn(cp, section, base + ".count", count);
- paramIn(cp, section, base + ".latched_count", latched_count);
- paramIn(cp, section, base + ".period", period);
- paramIn(cp, section, base + ".mode", mode);
- paramIn(cp, section, base + ".output_high", output_high);
- paramIn(cp, section, base + ".latch_on", latch_on);
- paramIn(cp, section, base + ".read_byte", read_byte);
- paramIn(cp, section, base + ".write_byte", write_byte);
-
- Tick event_tick;
- paramIn(cp, section, base + ".event_tick", event_tick);
- if (event_tick)
- event.schedule(event_tick);
-}
-
-TsunamiIO::PITimer::Counter::CounterEvent::CounterEvent(Counter* c_ptr)
- : Event(&mainEventQueue)
-{
- interval = (Tick)(Clock::Float::s / 1193180.0);
- counter = c_ptr;
-}
-
-void
-TsunamiIO::PITimer::Counter::CounterEvent::process()
-{
- DPRINTF(Tsunami, "Timer Interrupt\n");
- switch (counter->mode) {
- case PIT_MODE_INTTC:
- counter->output_high = true;
- case PIT_MODE_RATEGEN:
- case PIT_MODE_SQWAVE:
- break;
- default:
- panic("Unimplemented PITimer mode.\n");
- }
-}
-
-const char *
-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)
-{
- 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;
- }
-
- // set the back pointer from tsunami to myself
- tsunami->io = this;
-
- timerData = 0;
- rtc.set_time(init_time == 0 ? time(NULL) : init_time);
- picr = 0;
- picInterrupting = false;
-}
-
-Tick
-TsunamiIO::frequency() const
-{
- return Clock::Frequency / clockInterval;
-}
-
-Fault
-TsunamiIO::read(MemReqPtr &req, uint8_t *data)
-{
- DPRINTF(Tsunami, "io read va=%#x size=%d IOPorrt=%#x\n",
- req->vaddr, req->size, req->vaddr & 0xfff);
-
- Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask));
-
-
- switch(req->size) {
- case sizeof(uint8_t):
- switch(daddr) {
- // PIC1 mask read
- case TSDEV_PIC1_MASK:
- *(uint8_t*)data = ~mask1;
- return NoFault;
- case TSDEV_PIC2_MASK:
- *(uint8_t*)data = ~mask2;
- return NoFault;
- case TSDEV_PIC1_ISR:
- // !!! If this is modified 64bit case needs to be too
- // Pal code has to do a 64 bit physical read because there is
- // no load physical byte instruction
- *(uint8_t*)data = picr;
- return NoFault;
- case TSDEV_PIC2_ISR:
- // PIC2 not implemnted... just return 0
- *(uint8_t*)data = 0x00;
- return NoFault;
- case TSDEV_TMR0_DATA:
- pitimer.counter0.read(data);
- return NoFault;
- case TSDEV_TMR1_DATA:
- pitimer.counter1.read(data);
- return NoFault;
- case TSDEV_TMR2_DATA:
- pitimer.counter2.read(data);
- return NoFault;
- case TSDEV_RTC_DATA:
- rtc.readData(data);
- return NoFault;
- case TSDEV_CTRL_PORTB:
- if (pitimer.counter2.outputHigh())
- *data = PORTB_SPKR_HIGH;
- else
- *data = 0x00;
- return NoFault;
- default:
- panic("I/O Read - va%#x size %d\n", req->vaddr, req->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);
- }
- panic("I/O Read - va%#x size %d\n", req->vaddr, req->size);
-
- return NoFault;
-}
-
-Fault
-TsunamiIO::write(MemReqPtr &req, const uint8_t *data)
-{
-
-#if TRACING_ON
- uint8_t dt = *(uint8_t*)data;
- uint64_t dt64 = dt;
-#endif
-
- DPRINTF(Tsunami, "io write - va=%#x size=%d IOPort=%#x Data=%#x\n",
- req->vaddr, req->size, req->vaddr & 0xfff, dt64);
-
- Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask));
-
- 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);
- }
- case sizeof(uint16_t):
- case sizeof(uint32_t):
- case sizeof(uint64_t):
- default:
- panic("I/O Write - invalid size - va %#x size %d\n",
- req->vaddr, req->size);
- }
-
-
- return NoFault;
-}
-
-void
-TsunamiIO::postPIC(uint8_t bitvector)
-{
- //PIC2 Is not implemented, because nothing of interest there
- picr |= bitvector;
- if (picr & mask1) {
- tsunami->cchip->postDRIR(55);
- DPRINTF(Tsunami, "posting pic interrupt to cchip\n");
- }
-}
-
-void
-TsunamiIO::clearPIC(uint8_t bitvector)
-{
- //PIC2 Is not implemented, because nothing of interest there
- picr &= ~bitvector;
- if (!(picr & mask1)) {
- tsunami->cchip->clearDRIR(55);
- DPRINTF(Tsunami, "clearing pic interrupt to cchip\n");
- }
-}
-
-Tick
-TsunamiIO::cacheAccess(MemReqPtr &req)
-{
- return curTick + pioLatency;
-}
-
-void
-TsunamiIO::serialize(ostream &os)
-{
- SERIALIZE_SCALAR(timerData);
- SERIALIZE_SCALAR(mask1);
- SERIALIZE_SCALAR(mask2);
- SERIALIZE_SCALAR(mode1);
- SERIALIZE_SCALAR(mode2);
- SERIALIZE_SCALAR(picr);
- SERIALIZE_SCALAR(picInterrupting);
-
- // Serialize the timers
- pitimer.serialize("pitimer", os);
- rtc.serialize("rtc", os);
-}
-
-void
-TsunamiIO::unserialize(Checkpoint *cp, const string &section)
-{
- UNSERIALIZE_SCALAR(timerData);
- UNSERIALIZE_SCALAR(mask1);
- UNSERIALIZE_SCALAR(mask2);
- UNSERIALIZE_SCALAR(mode1);
- UNSERIALIZE_SCALAR(mode2);
- UNSERIALIZE_SCALAR(picr);
- UNSERIALIZE_SCALAR(picInterrupting);
-
- // Unserialize the timers
- pitimer.unserialize("pitimer", cp, section);
- rtc.unserialize("rtc", cp, 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<Tick> pio_latency;
- SimObjectParam<HierParams *> hier;
- Param<Tick> frequency;
-
-END_DECLARE_SIM_OBJECT_PARAMS(TsunamiIO)
-
-BEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiIO)
-
- INIT_PARAM(tsunami, "Tsunami"),
- 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")
-
-END_INIT_SIM_OBJECT_PARAMS(TsunamiIO)
-
-CREATE_SIM_OBJECT(TsunamiIO)
-{
- return new TsunamiIO(getInstanceName(), tsunami, time, addr, mmu, hier,
- pio_bus, pio_latency, frequency);
-}
-
-REGISTER_SIM_OBJECT("TsunamiIO", TsunamiIO)
diff --git a/dev/tsunami_io.hh b/dev/tsunami_io.hh
deleted file mode 100644
index b024ecd14..000000000
--- a/dev/tsunami_io.hh
+++ /dev/null
@@ -1,371 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @file
- * Tsunami I/O Space mapping including RTC/timer interrupts
- */
-
-#ifndef __DEV_TSUNAMI_IO_HH__
-#define __DEV_TSUNAMI_IO_HH__
-
-#include "dev/io_device.hh"
-#include "base/range.hh"
-#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
-{
- 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:
- /** Real-Time Clock (MC146818) */
- class RTC
- {
- private:
- /** Event for RTC periodic interrupt */
- struct RTCEvent : public Event
- {
- /** A pointer back to tsunami to create interrupt the processor. */
- Tsunami* tsunami;
- Tick interval;
-
- RTCEvent(Tsunami* t, Tick i);
-
- /** Schedule the RTC periodic interrupt */
- void scheduleIntr();
-
- /** Event process to occur at interrupt*/
- virtual void process();
-
- /** Event description */
- virtual const char *description();
- };
-
- private:
- std::string _name;
- const std::string &name() const { return _name; }
-
- /** RTC periodic interrupt event */
- RTCEvent event;
-
- /** Current RTC register address/index */
- int addr;
-
- /** Data for real-time clock function */
- union {
- uint8_t clock_data[10];
-
- struct {
- uint8_t sec;
- uint8_t sec_alrm;
- uint8_t min;
- uint8_t min_alrm;
- uint8_t hour;
- uint8_t hour_alrm;
- uint8_t wday;
- uint8_t mday;
- uint8_t mon;
- uint8_t year;
- };
- };
-
- /** RTC status register A */
- uint8_t stat_regA;
-
- /** RTC status register B */
- uint8_t stat_regB;
-
- public:
- RTC(const std::string &name, Tsunami* t, Tick i);
-
- /** Set the initial RTC time/date */
- void set_time(time_t t);
-
- /** RTC address port: write address of RTC RAM data to access */
- void writeAddr(const uint8_t *data);
-
- /** RTC write data */
- void writeData(const uint8_t *data);
-
- /** RTC read data */
- void readData(uint8_t *data);
-
- /**
- * Serialize this object to the given output stream.
- * @param os The stream to serialize to.
- */
- void serialize(const std::string &base, std::ostream &os);
-
- /**
- * Reconstruct the state of this object from a checkpoint.
- * @param cp The checkpoint use.
- * @param section The section name of this object
- */
- void unserialize(const std::string &base, Checkpoint *cp,
- const std::string &section);
- };
-
- /** Programmable Interval Timer (Intel 8254) */
- class PITimer
- {
- /** Counter element for PIT */
- class Counter
- {
- /** Event for counter interrupt */
- class CounterEvent : public Event
- {
- private:
- /** Pointer back to Counter */
- Counter* counter;
- Tick interval;
-
- public:
- CounterEvent(Counter*);
-
- /** Event process */
- virtual void process();
-
- /** Event description */
- virtual const char *description();
-
- friend class Counter;
- };
-
- private:
- std::string _name;
- const std::string &name() const { return _name; }
-
- CounterEvent event;
-
- /** Current count value */
- uint16_t count;
-
- /** Latched count */
- uint16_t latched_count;
-
- /** Interrupt period */
- uint16_t period;
-
- /** Current mode of operation */
- uint8_t mode;
-
- /** Output goes high when the counter reaches zero */
- bool output_high;
-
- /** State of the count latch */
- bool latch_on;
-
- /** Set of values for read_byte and write_byte */
- enum {LSB, MSB};
-
- /** Determine which byte of a 16-bit count value to read/write */
- uint8_t read_byte, write_byte;
-
- public:
- Counter(const std::string &name);
-
- /** Latch the current count (if one is not already latched) */
- void latchCount();
-
- /** Set the read/write mode */
- void setRW(int rw_val);
-
- /** Set operational mode */
- void setMode(int mode_val);
-
- /** Set count encoding */
- void setBCD(int bcd_val);
-
- /** Read a count byte */
- void read(uint8_t *data);
-
- /** Write a count byte */
- void write(const uint8_t *data);
-
- /** Is the output high? */
- bool outputHigh();
-
- /**
- * Serialize this object to the given output stream.
- * @param os The stream to serialize to.
- */
- void serialize(const std::string &base, std::ostream &os);
-
- /**
- * Reconstruct the state of this object from a checkpoint.
- * @param cp The checkpoint use.
- * @param section The section name of this object
- */
- void unserialize(const std::string &base, Checkpoint *cp,
- const std::string &section);
- };
-
- private:
- std::string _name;
- const std::string &name() const { return _name; }
-
- /** PIT has three seperate counters */
- Counter *counter[3];
-
- public:
- /** Public way to access individual counters (avoid array accesses) */
- Counter counter0;
- Counter counter1;
- Counter counter2;
-
- PITimer(const std::string &name);
-
- /** Write control word */
- void writeControl(const uint8_t* data);
-
- /**
- * Serialize this object to the given output stream.
- * @param os The stream to serialize to.
- */
- void serialize(const std::string &base, std::ostream &os);
-
- /**
- * Reconstruct the state of this object from a checkpoint.
- * @param cp The checkpoint use.
- * @param section The section name of this object
- */
- void unserialize(const std::string &base, Checkpoint *cp,
- const std::string &section);
- };
-
- /** Mask of the PIC1 */
- uint8_t mask1;
-
- /** Mask of the PIC2 */
- uint8_t mask2;
-
- /** Mode of PIC1. Not used for anything */
- uint8_t mode1;
-
- /** Mode of PIC2. Not used for anything */
- uint8_t mode2;
-
- /** Raw PIC interrupt register before masking */
- uint8_t picr; //Raw PIC interrput register
-
- /** Is the pic interrupting right now or not. */
- bool picInterrupting;
-
- Tick clockInterval;
-
- /** A pointer to the Tsunami device which be belong to */
- Tsunami *tsunami;
-
- /** Intel 8253 Periodic Interval Timer */
- PITimer pitimer;
-
- RTC rtc;
-
- /** The interval is set via two writes to the PIT.
- * This variable contains a flag as to how many writes have happened, and
- * the time so far.
- */
- uint16_t timerData;
-
- public:
- /**
- * Return the freqency of the RTC
- * @return interrupt rate of the RTC
- */
- Tick frequency() const;
-
- /**
- * 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.
- */
- 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);
-
- /**
- * 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);
-
- /**
- * Post an PIC interrupt to the CPU via the CChip
- * @param bitvector interrupt to post.
- */
- void postPIC(uint8_t bitvector);
-
- /**
- * Clear a posted interrupt
- * @param bitvector interrupt to clear
- */
- void clearPIC(uint8_t bitvector);
-
- /**
- * Serialize this object to the given output stream.
- * @param os The stream to serialize to.
- */
- virtual void serialize(std::ostream &os);
-
- /**
- * Reconstruct the state of this object from a checkpoint.
- * @param cp The checkpoint use.
- * @param section The section name of this object
- */
- 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
deleted file mode 100644
index 46efc3dfe..000000000
--- a/dev/tsunami_pchip.cc
+++ /dev/null
@@ -1,388 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @file
- * Tsunami PChip (pci)
- */
-
-#include <deque>
-#include <string>
-#include <vector>
-
-#include "base/trace.hh"
-#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 "sim/builder.hh"
-#include "sim/system.hh"
-
-using namespace std;
-//Should this be AlphaISA?
-using namespace TheISA;
-
-TsunamiPChip::TsunamiPChip(const string &name, Tsunami *t, Addr a,
- MemoryController *mmu, HierParams *hier,
- Bus *pio_bus, Tick pio_latency)
- : PioDevice(name, t), addr(a), tsunami(t)
-{
- mmu->add_child(this, RangeSize(addr, size));
-
- for (int i = 0; i < 4; i++) {
- wsba[i] = 0;
- wsm[i] = 0;
- 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;
-}
-
-Fault
-TsunamiPChip::read(MemReqPtr &req, uint8_t *data)
-{
- 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):
- default:
- panic("invalid access size(?) for tsunami register!\n\n");
- }
- DPRINTFN("Tsunami PChip ERROR: read daddr=%#x size=%d\n", daddr, req->size);
-
- return NoFault;
-}
-
-Fault
-TsunamiPChip::write(MemReqPtr &req, const uint8_t *data)
-{
- 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;
-}
-
-#define DMA_ADDR_MASK ULL(0x3ffffffff)
-
-Addr
-TsunamiPChip::translatePciToDma(Addr busAddr)
-{
- // compare the address to the window base registers
- uint64_t tbaMask = 0;
- uint64_t baMask = 0;
-
- uint64_t windowMask = 0;
- uint64_t windowBase = 0;
-
- uint64_t pteEntry = 0;
-
- Addr pteAddr;
- Addr dmaAddr;
-
-#if 0
- DPRINTF(IdeDisk, "Translation for bus address: %#x\n", busAddr);
- for (int i = 0; i < 4; i++) {
- DPRINTF(IdeDisk, "(%d) base:%#x mask:%#x\n",
- i, wsba[i], wsm[i]);
-
- windowBase = wsba[i];
- windowMask = ~wsm[i] & (ULL(0xfff) << 20);
-
- if ((busAddr & windowMask) == (windowBase & windowMask)) {
- DPRINTF(IdeDisk, "Would have matched %d (wb:%#x wm:%#x --> ba&wm:%#x wb&wm:%#x)\n",
- i, windowBase, windowMask, (busAddr & windowMask),
- (windowBase & windowMask));
- }
- }
-#endif
-
- for (int i = 0; i < 4; i++) {
-
- windowBase = wsba[i];
- windowMask = ~wsm[i] & (ULL(0xfff) << 20);
-
- if ((busAddr & windowMask) == (windowBase & windowMask)) {
-
- if (wsba[i] & 0x1) { // see if enabled
- if (wsba[i] & 0x2) { // see if SG bit is set
- /** @todo
- This currently is faked by just doing a direct
- read from memory, however, to be realistic, this
- needs to actually do a bus transaction. The process
- is explained in the tsunami documentation on page
- 10-12 and basically munges the address to look up a
- PTE from a table in memory and then uses that mapping
- to create an address for the SG page
- */
-
- tbaMask = ~(((wsm[i] & (ULL(0xfff) << 20)) >> 10) | ULL(0x3ff));
- 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));
-
- dmaAddr = ((pteEntry & ~ULL(0x1)) << 12) | (busAddr & ULL(0x1fff));
-
- } else {
- baMask = (wsm[i] & (ULL(0xfff) << 20)) | ULL(0xfffff);
- tbaMask = ~baMask;
- dmaAddr = (tba[i] & tbaMask) | (busAddr & baMask);
- }
-
- return (dmaAddr & DMA_ADDR_MASK);
- }
- }
- }
-
- // if no match was found, then return the original address
- return busAddr;
-}
-
-void
-TsunamiPChip::serialize(std::ostream &os)
-{
- SERIALIZE_SCALAR(pctl);
- SERIALIZE_ARRAY(wsba, 4);
- SERIALIZE_ARRAY(wsm, 4);
- SERIALIZE_ARRAY(tba, 4);
-}
-
-void
-TsunamiPChip::unserialize(Checkpoint *cp, const std::string &section)
-{
- UNSERIALIZE_SCALAR(pctl);
- UNSERIALIZE_ARRAY(wsba, 4);
- UNSERIALIZE_ARRAY(wsm, 4);
- 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<Tick> pio_latency;
- SimObjectParam<HierParams *> hier;
-
-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)
-
-END_INIT_SIM_OBJECT_PARAMS(TsunamiPChip)
-
-CREATE_SIM_OBJECT(TsunamiPChip)
-{
- return new TsunamiPChip(getInstanceName(), tsunami, addr, mmu, hier,
- pio_bus, pio_latency);
-}
-
-REGISTER_SIM_OBJECT("TsunamiPChip", TsunamiPChip)
diff --git a/dev/tsunami_pchip.hh b/dev/tsunami_pchip.hh
deleted file mode 100644
index c1d95431b..000000000
--- a/dev/tsunami_pchip.hh
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @file
- * Tsunami PCI interface CSRs
- */
-
-#ifndef __TSUNAMI_PCHIP_HH__
-#define __TSUNAMI_PCHIP_HH__
-
-#include "dev/tsunami.hh"
-#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
-{
- 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;
-
- /** Window Base addresses */
- uint64_t wsba[4];
-
- /** Window masks */
- uint64_t wsm[4];
-
- /** Translated Base Addresses */
- uint64_t tba[4];
-
- 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
- */
- TsunamiPChip(const std::string &name, Tsunami *t, Addr a,
- MemoryController *mmu, HierParams *hier, Bus *pio_bus,
- Tick pio_latency);
-
- /**
- * Translate a PCI bus address to a memory address for DMA.
- * @todo Andrew says this needs to be fixed. What's wrong with it?
- * @param busAddr PCI address to translate.
- * @return memory system address
- */
- 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);
-
- /**
- * Serialize this object to the given output stream.
- * @param os The stream to serialize to.
- */
- virtual void serialize(std::ostream &os);
-
- /**
- * Reconstruct the state of this object from a checkpoint.
- * @param cp The checkpoint use.
- * @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
deleted file mode 100644
index b2eeb8e9f..000000000
--- a/dev/uart.cc
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @file
- * Implements a 8250 UART
- */
-
-#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)
-{
- 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;
-
- // set back pointers
- cons->uart = this;
- 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
deleted file mode 100644
index 78b1dc68e..000000000
--- a/dev/uart.hh
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @file
- * Base class for UART
- */
-
-#ifndef __UART_HH__
-#define __UART_HH__
-
-#include "base/range.hh"
-#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
-{
-
- protected:
- int status;
- Addr addr;
- Addr size;
- 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;
-
-
- /**
- * Inform the uart that there is data available.
- */
- virtual void dataAvailable() = 0;
-
-
- /**
- * Return if we have an interrupt pending
- * @return interrupt status
- */
- 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);
-};
-
-#endif // __UART_HH__
diff --git a/dev/uart8250.cc b/dev/uart8250.cc
deleted file mode 100644
index 65bccee86..000000000
--- a/dev/uart8250.cc
+++ /dev/null
@@ -1,349 +0,0 @@
-/*
- * Copyright (c) 2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @file
- * Implements a 8250 UART
- */
-
-#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/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;
-using namespace TheISA;
-
-Uart8250::IntrEvent::IntrEvent(Uart8250 *u, int bit)
- : Event(&mainEventQueue), uart(u)
-{
- DPRINTF(Uart, "UART Interrupt Event Initilizing\n");
- intrBit = bit;
-}
-
-const char *
-Uart8250::IntrEvent::description()
-{
- return "uart interrupt delay event";
-}
-
-void
-Uart8250::IntrEvent::process()
-{
- if (intrBit & uart->IER) {
- DPRINTF(Uart, "UART InterEvent, interrupting\n");
- uart->platform->postConsoleInt();
- uart->status |= intrBit;
- }
- else
- DPRINTF(Uart, "UART InterEvent, not interrupting\n");
-
-}
-
-/* The linux serial driver (8250.c about line 1182) loops reading from
- * the device until the device reports it has no more data to
- * read. After a maximum of 255 iterations the code prints "serial8250
- * too much work for irq X," and breaks out of the loop. Since the
- * simulated system is so much slower than the actual system, if a
- * user is typing on the keyboard it is very easy for them to provide
- * input at a fast enough rate to not allow the loop to exit and thus
- * the error to be printed. This magic number provides a delay between
- * the time the UART receives a character to send to the simulated
- * system and the time it actually notifies the system it has a
- * character to send to alleviate this problem. --Ali
- */
-void
-Uart8250::IntrEvent::scheduleIntr()
-{
- static const Tick interval = (Tick)((Clock::Float::s / 2e9) * 450);
- DPRINTF(Uart, "Scheduling IER interrupt for %#x, at cycle %lld\n", intrBit,
- curTick + interval);
- if (!scheduled())
- schedule(curTick + interval);
- else
- reschedule(curTick + interval);
-}
-
-
-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)
-{
- IER = 0;
- DLAB = 0;
- LCR = 0;
- MCR = 0;
-
-}
-
-Fault
-Uart8250::read(MemReqPtr &req, uint8_t *data)
-{
- Addr daddr = req->paddr - (addr & EV5::PAddrImplMask);
- DPRINTF(Uart, " read register %#x\n", daddr);
-
- assert(req->size == 1);
-
- switch (daddr) {
- case 0x0:
- if (!(LCR & 0x80)) { // read byte
- if (cons->dataAvailable())
- cons->in(*data);
- else {
- *(uint8_t*)data = 0;
- // A limited amount of these are ok.
- DPRINTF(Uart, "empty read of RX register\n");
- }
- status &= ~RX_INT;
- platform->clearConsoleInt();
-
- if (cons->dataAvailable() && (IER & UART_IER_RDI))
- rxIntrEvent.scheduleIntr();
- } else { // dll divisor latch
- ;
- }
- break;
- case 0x1:
- if (!(LCR & 0x80)) { // Intr Enable Register(IER)
- *(uint8_t*)data = IER;
- } else { // DLM divisor latch MSB
- ;
- }
- break;
- case 0x2: // Intr Identification Register (IIR)
- 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;
- else if (status & TX_INT)
- *(uint8_t*)data = IIR_TXID;
- else
- *(uint8_t*)data = IIR_NOPEND;
-
- //Tx interrupts are cleared on IIR reads
- status &= ~TX_INT;
- break;
- case 0x3: // Line Control Register (LCR)
- *(uint8_t*)data = LCR;
- break;
- case 0x4: // Modem Control Register (MCR)
- break;
- case 0x5: // Line Status Register (LSR)
- uint8_t lsr;
- lsr = 0;
- // check if there are any bytes to be read
- if (cons->dataAvailable())
- lsr = UART_LSR_DR;
- lsr |= UART_LSR_TEMT | UART_LSR_THRE;
- *(uint8_t*)data = lsr;
- break;
- case 0x6: // Modem Status Register (MSR)
- *(uint8_t*)data = 0;
- break;
- case 0x7: // Scratch Register (SCR)
- *(uint8_t*)data = 0; // doesn't exist with at 8250.
- break;
- default:
- panic("Tried to access a UART port that doesn't exist\n");
- break;
- }
-
- return NoFault;
-
-}
-
-Fault
-Uart8250::write(MemReqPtr &req, const uint8_t *data)
-{
- Addr daddr = req->paddr - (addr & EV5::PAddrImplMask);
-
- DPRINTF(Uart, " write register %#x value %#x\n", daddr, *(uint8_t*)data);
-
- switch (daddr) {
- case 0x0:
- if (!(LCR & 0x80)) { // write byte
- cons->out(*(uint8_t *)data);
- platform->clearConsoleInt();
- status &= ~TX_INT;
- if (UART_IER_THRI & IER)
- txIntrEvent.scheduleIntr();
- } else { // dll divisor latch
- ;
- }
- break;
- case 0x1:
- if (!(LCR & 0x80)) { // Intr Enable Register(IER)
- IER = *(uint8_t*)data;
- if (UART_IER_THRI & IER)
- {
- DPRINTF(Uart, "IER: IER_THRI set, scheduling TX intrrupt\n");
- txIntrEvent.scheduleIntr();
- }
- else
- {
- DPRINTF(Uart, "IER: IER_THRI cleared, descheduling TX intrrupt\n");
- if (txIntrEvent.scheduled())
- txIntrEvent.deschedule();
- if (status & TX_INT)
- platform->clearConsoleInt();
- status &= ~TX_INT;
- }
-
- if ((UART_IER_RDI & IER) && cons->dataAvailable()) {
- DPRINTF(Uart, "IER: IER_RDI set, scheduling RX intrrupt\n");
- rxIntrEvent.scheduleIntr();
- } else {
- DPRINTF(Uart, "IER: IER_RDI cleared, descheduling RX intrrupt\n");
- if (rxIntrEvent.scheduled())
- rxIntrEvent.deschedule();
- if (status & RX_INT)
- platform->clearConsoleInt();
- status &= ~RX_INT;
- }
- } else { // DLM divisor latch MSB
- ;
- }
- break;
- case 0x2: // FIFO Control Register (FCR)
- break;
- case 0x3: // Line Control Register (LCR)
- LCR = *(uint8_t*)data;
- break;
- case 0x4: // Modem Control Register (MCR)
- if (*(uint8_t*)data == (UART_MCR_LOOP | 0x0A))
- MCR = 0x9A;
- break;
- case 0x7: // Scratch Register (SCR)
- // We are emulating a 8250 so we don't have a scratch reg
- break;
- default:
- panic("Tried to access a UART port that doesn't exist\n");
- break;
- }
- return NoFault;
-}
-
-void
-Uart8250::dataAvailable()
-{
- // if the kernel wants an interrupt when we have data
- if (IER & UART_IER_RDI)
- {
- platform->postConsoleInt();
- status |= RX_INT;
- }
-
-}
-
-
-
-void
-Uart8250::serialize(ostream &os)
-{
- SERIALIZE_SCALAR(status);
- SERIALIZE_SCALAR(IER);
- SERIALIZE_SCALAR(DLAB);
- SERIALIZE_SCALAR(LCR);
- SERIALIZE_SCALAR(MCR);
- Tick rxintrwhen;
- if (rxIntrEvent.scheduled())
- rxintrwhen = rxIntrEvent.when();
- else
- rxintrwhen = 0;
- Tick txintrwhen;
- if (txIntrEvent.scheduled())
- txintrwhen = txIntrEvent.when();
- else
- txintrwhen = 0;
- SERIALIZE_SCALAR(rxintrwhen);
- SERIALIZE_SCALAR(txintrwhen);
-}
-
-void
-Uart8250::unserialize(Checkpoint *cp, const std::string &section)
-{
- UNSERIALIZE_SCALAR(status);
- UNSERIALIZE_SCALAR(IER);
- UNSERIALIZE_SCALAR(DLAB);
- UNSERIALIZE_SCALAR(LCR);
- UNSERIALIZE_SCALAR(MCR);
- Tick rxintrwhen;
- Tick txintrwhen;
- UNSERIALIZE_SCALAR(rxintrwhen);
- UNSERIALIZE_SCALAR(txintrwhen);
- if (rxintrwhen != 0)
- rxIntrEvent.schedule(rxintrwhen);
- if (txintrwhen != 0)
- txIntrEvent.schedule(txintrwhen);
-}
-
-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<Tick> pio_latency;
- SimObjectParam<HierParams *> hier;
-
-
-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)
-
-END_INIT_SIM_OBJECT_PARAMS(Uart8250)
-
-CREATE_SIM_OBJECT(Uart8250)
-{
- return new Uart8250(getInstanceName(), console, mmu, addr, size, hier,
- pio_bus, pio_latency, platform);
-}
-
-REGISTER_SIM_OBJECT("Uart8250", Uart8250)
diff --git a/dev/uart8250.hh b/dev/uart8250.hh
deleted file mode 100644
index 63d1da3cf..000000000
--- a/dev/uart8250.hh
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (c) 2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @file
- * Defines a 8250 UART
- */
-
-#ifndef __TSUNAMI_UART_HH__
-#define __TSUNAMI_UART_HH__
-
-#include "dev/tsunamireg.h"
-#include "base/range.hh"
-#include "dev/io_device.hh"
-#include "dev/uart.hh"
-
-
-/* UART8250 Interrupt ID Register
- * bit 0 Interrupt Pending 0 = true, 1 = false
- * bit 2:1 ID of highest priority interrupt
- * bit 7:3 zeroes
- */
-#define 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)*/
-
-class SimConsole;
-class MemoryController;
-class Platform;
-
-class Uart8250 : public Uart
-{
-
-
- protected:
- uint8_t IER, DLAB, LCR, MCR;
-
- class IntrEvent : public Event
- {
- protected:
- Uart8250 *uart;
- int intrBit;
- public:
- IntrEvent(Uart8250 *u, int bit);
- virtual void process();
- virtual const char *description();
- void scheduleIntr();
- };
-
- IntrEvent txIntrEvent;
- 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);
-
- virtual Fault read(MemReqPtr &req, uint8_t *data);
- virtual Fault write(MemReqPtr &req, const uint8_t *data);
-
-
- /**
- * Inform the uart that there is data available.
- */
- virtual void dataAvailable();
-
-
- /**
- * Return if we have an interrupt pending
- * @return interrupt status
- */
- virtual bool intStatus() { return status ? true : false; }
-
- virtual void serialize(std::ostream &os);
- virtual void unserialize(Checkpoint *cp, const std::string &section);
-
-};
-
-#endif // __TSUNAMI_UART_HH__
diff --git a/encumbered/cpu/full/op_class.hh b/encumbered/cpu/full/op_class.hh
deleted file mode 100644
index ff53b58d2..000000000
--- a/encumbered/cpu/full/op_class.hh
+++ /dev/null
@@ -1,64 +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.
- */
-
-#ifndef __ENCUMBERED_CPU_FULL_OP_CLASS_HH__
-#define __ENCUMBERED_CPU_FULL_OP_CLASS_HH__
-
-/**
- * @file
- * Definition of operation classes.
- */
-
-/**
- * Instruction operation classes. These classes are used for
- * 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 */
-};
-
-/**
- * Array mapping OpClass enum values to strings. Defined in fu_pool.cc.
- */
-extern const char *opClassStrings[];
-
-#endif // __ENCUMBERED_CPU_FULL_OP_CLASS_HH__
diff --git a/ext/dnet/LICENSE b/ext/dnet/LICENSE
new file mode 100644
index 000000000..95ecd51e6
--- /dev/null
+++ b/ext/dnet/LICENSE
@@ -0,0 +1,28 @@
+
+ Copyright (c) 2000-2004 Dug Song <dugsong@monkey.org>
+ All rights reserved, all wrongs reversed.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. 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.
+ 3. The names of the authors and copyright holders may not be used to
+ endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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.
+
diff --git a/ext/dnet/dnet/addr.h b/ext/dnet/dnet/addr.h
new file mode 100644
index 000000000..584e3aba3
--- /dev/null
+++ b/ext/dnet/dnet/addr.h
@@ -0,0 +1,67 @@
+/*
+ * addr.h
+ *
+ * Network address operations.
+ *
+ * Copyright (c) 2000 Dug Song <dugsong@monkey.org>
+ *
+ * $Id: addr.h,v 1.12 2003/02/27 03:44:55 dugsong Exp $
+ */
+
+#ifndef DNET_ADDR_H
+#define DNET_ADDR_H
+
+#define ADDR_TYPE_NONE 0 /* No address set */
+#define ADDR_TYPE_ETH 1 /* Ethernet */
+#define ADDR_TYPE_IP 2 /* Internet Protocol v4 */
+#define ADDR_TYPE_IP6 3 /* Internet Protocol v6 */
+
+struct addr {
+ uint16_t addr_type;
+ uint16_t addr_bits;
+ union {
+ eth_addr_t __eth;
+ ip_addr_t __ip;
+ ip6_addr_t __ip6;
+
+ uint8_t __data8[16];
+ uint16_t __data16[8];
+ uint32_t __data32[4];
+ } __addr_u;
+};
+#define addr_eth __addr_u.__eth
+#define addr_ip __addr_u.__ip
+#define addr_ip6 __addr_u.__ip6
+#define addr_data8 __addr_u.__data8
+#define addr_data16 __addr_u.__data16
+#define addr_data32 __addr_u.__data32
+
+#define addr_pack(addr, type, bits, data, len) do { \
+ (addr)->addr_type = type; \
+ (addr)->addr_bits = bits; \
+ memmove((addr)->addr_data8, (char *)data, len); \
+} while (0)
+
+__BEGIN_DECLS
+int addr_cmp(const struct addr *a, const struct addr *b);
+
+int addr_bcast(const struct addr *a, struct addr *b);
+int addr_net(const struct addr *a, struct addr *b);
+
+char *addr_ntop(const struct addr *src, char *dst, size_t size);
+int addr_pton(const char *src, struct addr *dst);
+
+char *addr_ntoa(const struct addr *a);
+#define addr_aton addr_pton
+
+int addr_ntos(const struct addr *a, struct sockaddr *sa);
+int addr_ston(const struct sockaddr *sa, struct addr *a);
+
+int addr_btos(uint16_t bits, struct sockaddr *sa);
+int addr_stob(const struct sockaddr *sa, uint16_t *bits);
+
+int addr_btom(uint16_t bits, void *mask, size_t size);
+int addr_mtob(const void *mask, size_t size, uint16_t *bits);
+__END_DECLS
+
+#endif /* DNET_ADDR_H */
diff --git a/ext/dnet/dnet/arp.h b/ext/dnet/dnet/arp.h
new file mode 100644
index 000000000..d3c162410
--- /dev/null
+++ b/ext/dnet/dnet/arp.h
@@ -0,0 +1,103 @@
+/*
+ * arp.h
+ *
+ * Address Resolution Protocol.
+ * RFC 826
+ *
+ * Copyright (c) 2000 Dug Song <dugsong@monkey.org>
+ *
+ * $Id: arp.h,v 1.12 2003/03/16 17:39:17 dugsong Exp $
+ */
+
+#ifndef DNET_ARP_H
+#define DNET_ARP_H
+
+#define ARP_HDR_LEN 8 /* base ARP header length */
+#define ARP_ETHIP_LEN 20 /* base ARP message length */
+
+#ifndef __GNUC__
+# define __attribute__(x)
+# pragma pack(1)
+#endif
+
+/*
+ * ARP header
+ */
+struct arp_hdr {
+ uint16_t ar_hrd; /* format of hardware address */
+ uint16_t ar_pro; /* format of protocol address */
+ uint8_t ar_hln; /* length of hardware address (ETH_ADDR_LEN) */
+ uint8_t ar_pln; /* length of protocol address (IP_ADDR_LEN) */
+ uint16_t ar_op; /* operation */
+};
+
+/*
+ * Hardware address format
+ */
+#define ARP_HRD_ETH 0x0001 /* ethernet hardware */
+#define ARP_HRD_IEEE802 0x0006 /* IEEE 802 hardware */
+
+/*
+ * Protocol address format
+ */
+#define ARP_PRO_IP 0x0800 /* IP protocol */
+
+/*
+ * ARP operation
+ */
+#define ARP_OP_REQUEST 1 /* request to resolve ha given pa */
+#define ARP_OP_REPLY 2 /* response giving hardware address */
+#define ARP_OP_REVREQUEST 3 /* request to resolve pa given ha */
+#define ARP_OP_REVREPLY 4 /* response giving protocol address */
+
+/*
+ * Ethernet/IP ARP message
+ */
+struct arp_ethip {
+ uint8_t ar_sha[ETH_ADDR_LEN]; /* sender hardware address */
+ uint8_t ar_spa[IP_ADDR_LEN]; /* sender protocol address */
+ uint8_t ar_tha[ETH_ADDR_LEN]; /* target hardware address */
+ uint8_t ar_tpa[IP_ADDR_LEN]; /* target protocol address */
+};
+
+/*
+ * ARP cache entry
+ */
+struct arp_entry {
+ struct addr arp_pa; /* protocol address */
+ struct addr arp_ha; /* hardware address */
+};
+
+#ifndef __GNUC__
+# pragma pack()
+#endif
+
+#define arp_pack_hdr_ethip(hdr, op, sha, spa, tha, tpa) do { \
+ struct arp_hdr *pack_arp_p = (struct arp_hdr *)(hdr); \
+ struct arp_ethip *pack_ethip_p = (struct arp_ethip *) \
+ ((uint8_t *)(hdr) + ARP_HDR_LEN); \
+ pack_arp_p->ar_hrd = htons(ARP_HRD_ETH); \
+ pack_arp_p->ar_pro = htons(ARP_PRO_IP); \
+ pack_arp_p->ar_hln = ETH_ADDR_LEN; \
+ pack_arp_p->ar_pln = IP_ADDR_LEN; \
+ pack_arp_p->ar_op = htons(op); \
+ memmove(pack_ethip_p->ar_sha, &(sha), ETH_ADDR_LEN); \
+ memmove(pack_ethip_p->ar_spa, &(spa), IP_ADDR_LEN); \
+ memmove(pack_ethip_p->ar_tha, &(tha), ETH_ADDR_LEN); \
+ memmove(pack_ethip_p->ar_tpa, &(tpa), IP_ADDR_LEN); \
+} while (0)
+
+typedef struct arp_handle arp_t;
+
+typedef int (*arp_handler)(const struct arp_entry *entry, void *arg);
+
+__BEGIN_DECLS
+arp_t *arp_open(void);
+int arp_add(arp_t *arp, const struct arp_entry *entry);
+int arp_delete(arp_t *arp, const struct arp_entry *entry);
+int arp_get(arp_t *arp, struct arp_entry *entry);
+int arp_loop(arp_t *arp, arp_handler callback, void *arg);
+arp_t *arp_close(arp_t *arp);
+__END_DECLS
+
+#endif /* DNET_ARP_H */
diff --git a/ext/dnet/dnet/blob.h b/ext/dnet/dnet/blob.h
new file mode 100644
index 000000000..a3be7897d
--- /dev/null
+++ b/ext/dnet/dnet/blob.h
@@ -0,0 +1,56 @@
+/*
+ * blob.h
+ *
+ * Binary blob handling.
+ *
+ * Copyright (c) 2002 Dug Song <dugsong@monkey.org>
+ *
+ * $Id: blob.h,v 1.2 2002/04/05 03:06:44 dugsong Exp $
+ */
+
+#ifndef DNET_BLOB_H
+#define DNET_BLOB_H
+
+typedef struct blob {
+ u_char *base; /* start of data */
+ int off; /* offset into data */
+ int end; /* end of data */
+ int size; /* size of allocation */
+} blob_t;
+
+__BEGIN_DECLS
+blob_t *blob_new(void);
+
+int blob_read(blob_t *b, void *buf, int len);
+int blob_write(blob_t *b, const void *buf, int len);
+
+int blob_seek(blob_t *b, int off, int whence);
+#define blob_skip(b, l) blob_seek(b, l, SEEK_CUR)
+#define blob_rewind(b) blob_seek(b, 0, SEEK_SET)
+
+#define blob_offset(b) ((b)->off)
+#define blob_left(b) ((b)->end - (b)->off)
+
+int blob_index(blob_t *b, const void *buf, int len);
+int blob_rindex(blob_t *b, const void *buf, int len);
+
+int blob_pack(blob_t *b, const char *fmt, ...);
+int blob_unpack(blob_t *b, const char *fmt, ...);
+
+int blob_insert(blob_t *b, const void *buf, int len);
+int blob_delete(blob_t *b, void *buf, int len);
+
+int blob_print(blob_t *b, char *style, int len);
+
+blob_t *blob_free(blob_t *b);
+
+int blob_register_alloc(size_t size, void *(*bmalloc)(size_t),
+ void (*bfree)(void *), void *(*brealloc)(void *, size_t));
+#ifdef va_start
+typedef int (*blob_fmt_cb)(int pack, int len, blob_t *b, va_list *arg);
+
+int blob_register_pack(char c, blob_fmt_cb fmt_cb);
+#endif
+__END_DECLS
+
+#endif /* DNET_BLOB_H */
diff --git a/ext/dnet/dnet/eth.h b/ext/dnet/dnet/eth.h
new file mode 100644
index 000000000..da3033066
--- /dev/null
+++ b/ext/dnet/dnet/eth.h
@@ -0,0 +1,77 @@
+/*
+ * eth.h
+ *
+ * Ethernet.
+ *
+ * Copyright (c) 2000 Dug Song <dugsong@monkey.org>
+ *
+ * $Id: eth.h,v 1.15 2004/01/03 08:47:23 dugsong Exp $
+ */
+
+#ifndef DNET_ETH_H
+#define DNET_ETH_H
+
+#define ETH_ADDR_LEN 6
+#define ETH_ADDR_BITS 48
+#define ETH_TYPE_LEN 2
+#define ETH_CRC_LEN 4
+#define ETH_HDR_LEN 14
+
+#define ETH_LEN_MIN 64 /* minimum frame length with CRC */
+#define ETH_LEN_MAX 1518 /* maximum frame length with CRC */
+
+#define ETH_MTU (ETH_LEN_MAX - ETH_HDR_LEN - ETH_CRC_LEN)
+#define ETH_MIN (ETH_LEN_MIN - ETH_HDR_LEN - ETH_CRC_LEN)
+
+typedef struct eth_addr {
+ uint8_t data[ETH_ADDR_LEN];
+} eth_addr_t;
+
+struct eth_hdr {
+ eth_addr_t eth_dst; /* destination address */
+ eth_addr_t eth_src; /* source address */
+ uint16_t eth_type; /* payload type */
+};
+
+/*
+ * Ethernet payload types - http://standards.ieee.org/regauth/ethertype
+ */
+#define ETH_TYPE_PUP 0x0200 /* PUP protocol */
+#define ETH_TYPE_IP 0x0800 /* IP protocol */
+#define ETH_TYPE_ARP 0x0806 /* address resolution protocol */
+#define ETH_TYPE_REVARP 0x8035 /* reverse addr resolution protocol */
+#define ETH_TYPE_8021Q 0x8100 /* IEEE 802.1Q VLAN tagging */
+#define ETH_TYPE_IPV6 0x86DD /* IPv6 protocol */
+#define ETH_TYPE_MPLS 0x8847 /* MPLS */
+#define ETH_TYPE_MPLS_MCAST 0x8848 /* MPLS Multicast */
+#define ETH_TYPE_PPPOEDISC 0x8863 /* PPP Over Ethernet Discovery Stage */
+#define ETH_TYPE_PPPOE 0x8864 /* PPP Over Ethernet Session Stage */
+#define ETH_TYPE_LOOPBACK 0x9000 /* used to test interfaces */
+
+#define ETH_IS_MULTICAST(ea) (*(ea) & 0x01) /* is address mcast/bcast? */
+
+#define ETH_ADDR_BROADCAST "\xff\xff\xff\xff\xff\xff"
+
+#define eth_pack_hdr(h, dst, src, type) do { \
+ struct eth_hdr *eth_pack_p = (struct eth_hdr *)(h); \
+ memmove(&eth_pack_p->eth_dst, &(dst), ETH_ADDR_LEN); \
+ memmove(&eth_pack_p->eth_src, &(src), ETH_ADDR_LEN); \
+ eth_pack_p->eth_type = htons(type); \
+} while (0)
+
+typedef struct eth_handle eth_t;
+
+__BEGIN_DECLS
+eth_t *eth_open(const char *device);
+int eth_get(eth_t *e, eth_addr_t *ea);
+int eth_set(eth_t *e, const eth_addr_t *ea);
+size_t eth_send(eth_t *e, const void *buf, size_t len);
+eth_t *eth_close(eth_t *e);
+
+char *eth_ntop(const eth_addr_t *eth, char *dst, size_t len);
+int eth_pton(const char *src, eth_addr_t *dst);
+char *eth_ntoa(const eth_addr_t *eth);
+#define eth_aton eth_pton
+__END_DECLS
+
+#endif /* DNET_ETH_H */
diff --git a/ext/dnet/dnet/fw.h b/ext/dnet/dnet/fw.h
new file mode 100644
index 000000000..ebda8e7eb
--- /dev/null
+++ b/ext/dnet/dnet/fw.h
@@ -0,0 +1,54 @@
+/*
+ * fw.h
+ *
+ * Network firewalling operations.
+ *
+ * Copyright (c) 2001 Dug Song <dugsong@monkey.org>
+ *
+ * $Id: fw.h,v 1.13 2002/12/14 04:02:36 dugsong Exp $
+ */
+
+#ifndef DNET_FW_H
+#define DNET_FW_H
+
+struct fw_rule {
+ char fw_device[INTF_NAME_LEN]; /* interface name */
+ uint8_t fw_op; /* operation */
+ uint8_t fw_dir; /* direction */
+ uint8_t fw_proto; /* IP protocol */
+ struct addr fw_src; /* src address / net */
+ struct addr fw_dst; /* dst address / net */
+ uint16_t fw_sport[2]; /* range / ICMP type */
+ uint16_t fw_dport[2]; /* range / ICMP code */
+};
+
+#define FW_OP_ALLOW 1
+#define FW_OP_BLOCK 2
+
+#define FW_DIR_IN 1
+#define FW_DIR_OUT 2
+
+#define fw_pack_rule(rule, dev, op, dir, p, s, d, sp1, sp2, dp1, dp2) \
+do { \
+ strlcpy((rule)->fw_device, dev, sizeof((rule)->fw_device)); \
+ (rule)->fw_op = op; (rule)->fw_dir = dir; \
+ (rule)->fw_proto = p; \
+ memmove(&(rule)->fw_src, &(s), sizeof((rule)->fw_src)); \
+ memmove(&(rule)->fw_dst, &(d), sizeof((rule)->fw_dst)); \
+ (rule)->fw_sport[0] = sp1; (rule)->fw_sport[1] = sp2; \
+ (rule)->fw_dport[0] = dp1; (rule)->fw_dport[1] = dp2; \
+} while (0)
+
+typedef struct fw_handle fw_t;
+
+typedef int (*fw_handler)(const struct fw_rule *rule, void *arg);
+
+__BEGIN_DECLS
+fw_t *fw_open(void);
+int fw_add(fw_t *f, const struct fw_rule *rule);
+int fw_delete(fw_t *f, const struct fw_rule *rule);
+int fw_loop(fw_t *f, fw_handler callback, void *arg);
+fw_t *fw_close(fw_t *f);
+__END_DECLS
+
+#endif /* DNET_FW_H */
diff --git a/ext/dnet/dnet/icmp.h b/ext/dnet/dnet/icmp.h
new file mode 100644
index 000000000..e997d5887
--- /dev/null
+++ b/ext/dnet/dnet/icmp.h
@@ -0,0 +1,265 @@
+/*
+ * icmp.h
+ *
+ * Internet Control Message Protocol.
+ * RFC 792, 950, 1256, 1393, 1475, 2002, 2521
+ *
+ * Copyright (c) 2000 Dug Song <dugsong@monkey.org>
+ *
+ * $Id: icmp.h,v 1.14 2003/03/16 17:39:17 dugsong Exp $
+ */
+
+#ifndef DNET_ICMP_H
+#define DNET_ICMP_H
+
+#define ICMP_HDR_LEN 4 /* base ICMP header length */
+#define ICMP_LEN_MIN 8 /* minimum ICMP message size, with header */
+
+#ifndef __GNUC__
+# define __attribute__(x)
+# pragma pack(1)
+#endif
+
+/*
+ * ICMP header
+ */
+struct icmp_hdr {
+ uint8_t icmp_type; /* type of message, see below */
+ uint8_t icmp_code; /* type sub code */
+ uint16_t icmp_cksum; /* ones complement cksum of struct */
+};
+
+/*
+ * Types (icmp_type) and codes (icmp_code) -
+ * http://www.iana.org/assignments/icmp-parameters
+ */
+#define ICMP_CODE_NONE 0 /* for types without codes */
+#define ICMP_ECHOREPLY 0 /* echo reply */
+#define ICMP_UNREACH 3 /* dest unreachable, codes: */
+#define ICMP_UNREACH_NET 0 /* bad net */
+#define ICMP_UNREACH_HOST 1 /* bad host */
+#define ICMP_UNREACH_PROTO 2 /* bad protocol */
+#define ICMP_UNREACH_PORT 3 /* bad port */
+#define ICMP_UNREACH_NEEDFRAG 4 /* IP_DF caused drop */
+#define ICMP_UNREACH_SRCFAIL 5 /* src route failed */
+#define ICMP_UNREACH_NET_UNKNOWN 6 /* unknown net */
+#define ICMP_UNREACH_HOST_UNKNOWN 7 /* unknown host */
+#define ICMP_UNREACH_ISOLATED 8 /* src host isolated */
+#define ICMP_UNREACH_NET_PROHIB 9 /* for crypto devs */
+#define ICMP_UNREACH_HOST_PROHIB 10 /* ditto */
+#define ICMP_UNREACH_TOSNET 11 /* bad tos for net */
+#define ICMP_UNREACH_TOSHOST 12 /* bad tos for host */
+#define ICMP_UNREACH_FILTER_PROHIB 13 /* prohibited access */
+#define ICMP_UNREACH_HOST_PRECEDENCE 14 /* precedence error */
+#define ICMP_UNREACH_PRECEDENCE_CUTOFF 15 /* precedence cutoff */
+#define ICMP_SRCQUENCH 4 /* packet lost, slow down */
+#define ICMP_REDIRECT 5 /* shorter route, codes: */
+#define ICMP_REDIRECT_NET 0 /* for network */
+#define ICMP_REDIRECT_HOST 1 /* for host */
+#define ICMP_REDIRECT_TOSNET 2 /* for tos and net */
+#define ICMP_REDIRECT_TOSHOST 3 /* for tos and host */
+#define ICMP_ALTHOSTADDR 6 /* alternate host address */
+#define ICMP_ECHO 8 /* echo service */
+#define ICMP_RTRADVERT 9 /* router advertise, codes: */
+#define ICMP_RTRADVERT_NORMAL 0 /* normal */
+#define ICMP_RTRADVERT_NOROUTE_COMMON 16 /* selective routing */
+#define ICMP_RTRSOLICIT 10 /* router solicitation */
+#define ICMP_TIMEXCEED 11 /* time exceeded, code: */
+#define ICMP_TIMEXCEED_INTRANS 0 /* ttl==0 in transit */
+#define ICMP_TIMEXCEED_REASS 1 /* ttl==0 in reass */
+#define ICMP_PARAMPROB 12 /* ip header bad */
+#define ICMP_PARAMPROB_ERRATPTR 0 /* req. opt. absent */
+#define ICMP_PARAMPROB_OPTABSENT 1 /* req. opt. absent */
+#define ICMP_PARAMPROB_LENGTH 2 /* bad length */
+#define ICMP_TSTAMP 13 /* timestamp request */
+#define ICMP_TSTAMPREPLY 14 /* timestamp reply */
+#define ICMP_INFO 15 /* information request */
+#define ICMP_INFOREPLY 16 /* information reply */
+#define ICMP_MASK 17 /* address mask request */
+#define ICMP_MASKREPLY 18 /* address mask reply */
+#define ICMP_TRACEROUTE 30 /* traceroute */
+#define ICMP_DATACONVERR 31 /* data conversion error */
+#define ICMP_MOBILE_REDIRECT 32 /* mobile host redirect */
+#define ICMP_IPV6_WHEREAREYOU 33 /* IPv6 where-are-you */
+#define ICMP_IPV6_IAMHERE 34 /* IPv6 i-am-here */
+#define ICMP_MOBILE_REG 35 /* mobile registration req */
+#define ICMP_MOBILE_REGREPLY 36 /* mobile registration reply */
+#define ICMP_DNS 37 /* domain name request */
+#define ICMP_DNSREPLY 38 /* domain name reply */
+#define ICMP_SKIP 39 /* SKIP */
+#define ICMP_PHOTURIS 40 /* Photuris */
+#define ICMP_PHOTURIS_UNKNOWN_INDEX 0 /* unknown sec index */
+#define ICMP_PHOTURIS_AUTH_FAILED 1 /* auth failed */
+#define ICMP_PHOTURIS_DECOMPRESS_FAILED 2 /* decompress failed */
+#define ICMP_PHOTURIS_DECRYPT_FAILED 3 /* decrypt failed */
+#define ICMP_PHOTURIS_NEED_AUTHN 4 /* no authentication */
+#define ICMP_PHOTURIS_NEED_AUTHZ 5 /* no authorization */
+#define ICMP_TYPE_MAX 40
+
+#define ICMP_INFOTYPE(type) \
+ ((type) == ICMP_ECHOREPLY || (type) == ICMP_ECHO || \
+ (type) == ICMP_RTRADVERT || (type) == ICMP_RTRSOLICIT || \
+ (type) == ICMP_TSTAMP || (type) == ICMP_TSTAMPREPLY || \
+ (type) == ICMP_INFO || (type) == ICMP_INFOREPLY || \
+ (type) == ICMP_MASK || (type) == ICMP_MASKREPLY)
+
+/*
+ * Echo message data
+ */
+struct icmp_msg_echo {
+ uint16_t icmp_id;
+ uint16_t icmp_seq;
+ uint8_t icmp_data __flexarr; /* optional data */
+};
+
+/*
+ * Fragmentation-needed (unreachable) message data
+ */
+struct icmp_msg_needfrag {
+ uint16_t icmp_void; /* must be zero */
+ uint16_t icmp_mtu; /* MTU of next-hop network */
+ uint8_t icmp_ip __flexarr; /* IP hdr + 8 bytes of pkt */
+};
+
+/*
+ * Unreachable, source quench, redirect, time exceeded,
+ * parameter problem message data
+ */
+struct icmp_msg_quote {
+ uint32_t icmp_void; /* must be zero */
+#define icmp_gwaddr icmp_void /* router IP address to use */
+#define icmp_pptr icmp_void /* ptr to bad octet field */
+ uint8_t icmp_ip __flexarr; /* IP hdr + 8 bytes of pkt */
+};
+
+/*
+ * Router advertisement message data, RFC 1256
+ */
+struct icmp_msg_rtradvert {
+ uint8_t icmp_num_addrs; /* # of address / pref pairs */
+ uint8_t icmp_wpa; /* words / address == 2 */
+ uint16_t icmp_lifetime; /* route lifetime in seconds */
+ struct icmp_msg_rtr_data {
+ uint32_t icmp_void;
+#define icmp_gwaddr icmp_void /* router IP address */
+ uint32_t icmp_pref; /* router preference (usu 0) */
+ } icmp_rtr __flexarr; /* variable # of routers */
+};
+#define ICMP_RTR_PREF_NODEFAULT 0x80000000 /* do not use as default gw */
+
+/*
+ * Timestamp message data
+ */
+struct icmp_msg_tstamp {
+ uint32_t icmp_id; /* identifier */
+ uint32_t icmp_seq; /* sequence number */
+ uint32_t icmp_ts_orig; /* originate timestamp */
+ uint32_t icmp_ts_rx; /* receive timestamp */
+ uint32_t icmp_ts_tx; /* transmit timestamp */
+};
+
+/*
+ * Address mask message data, RFC 950
+ */
+struct icmp_msg_mask {
+ uint32_t icmp_id; /* identifier */
+ uint32_t icmp_seq; /* sequence number */
+ uint32_t icmp_mask; /* address mask */
+};
+
+/*
+ * Traceroute message data, RFC 1393, RFC 1812
+ */
+struct icmp_msg_traceroute {
+ uint16_t icmp_id; /* identifier */
+ uint16_t icmp_void; /* unused */
+ uint16_t icmp_ohc; /* outbound hop count */
+ uint16_t icmp_rhc; /* return hop count */
+ uint32_t icmp_speed; /* link speed, bytes/sec */
+ uint32_t icmp_mtu; /* MTU in bytes */
+};
+
+/*
+ * Domain name reply message data, RFC 1788
+ */
+struct icmp_msg_dnsreply {
+ uint16_t icmp_id; /* identifier */
+ uint16_t icmp_seq; /* sequence number */
+ uint32_t icmp_ttl; /* time-to-live */
+ uint8_t icmp_names __flexarr; /* variable number of names */
+};
+
+/*
+ * Generic identifier, sequence number data
+ */
+struct icmp_msg_idseq {
+ uint16_t icmp_id;
+ uint16_t icmp_seq;
+};
+
+/*
+ * ICMP message union
+ */
+union icmp_msg {
+ struct icmp_msg_echo echo; /* ICMP_ECHO{REPLY} */
+ struct icmp_msg_quote unreach; /* ICMP_UNREACH */
+ struct icmp_msg_needfrag needfrag; /* ICMP_UNREACH_NEEDFRAG */
+ struct icmp_msg_quote srcquench; /* ICMP_SRCQUENCH */
+ struct icmp_msg_quote redirect; /* ICMP_REDIRECT (set to 0) */
+ uint32_t rtrsolicit; /* ICMP_RTRSOLICIT */
+ struct icmp_msg_rtradvert rtradvert; /* ICMP_RTRADVERT */
+ struct icmp_msg_quote timexceed; /* ICMP_TIMEXCEED */
+ struct icmp_msg_quote paramprob; /* ICMP_PARAMPROB */
+ struct icmp_msg_tstamp tstamp; /* ICMP_TSTAMP{REPLY} */
+ struct icmp_msg_idseq info; /* ICMP_INFO{REPLY} */
+ struct icmp_msg_mask mask; /* ICMP_MASK{REPLY} */
+ struct icmp_msg_traceroute traceroute; /* ICMP_TRACEROUTE */
+ struct icmp_msg_idseq dns; /* ICMP_DNS */
+ struct icmp_msg_dnsreply dnsreply; /* ICMP_DNSREPLY */
+};
+
+#ifndef __GNUC__
+# pragma pack()
+#endif
+
+#define icmp_pack_hdr(hdr, type, code) do { \
+ struct icmp_hdr *icmp_pack_p = (struct icmp_hdr *)(hdr); \
+ icmp_pack_p->icmp_type = type; icmp_pack_p->icmp_code = code; \
+} while (0)
+
+#define icmp_pack_hdr_echo(hdr, type, code, id, seq, data, len) do { \
+ struct icmp_msg_echo *echo_pack_p = (struct icmp_msg_echo *) \
+ ((uint8_t *)(hdr) + ICMP_HDR_LEN); \
+ icmp_pack_hdr(hdr, type, code); \
+ echo_pack_p->icmp_id = htons(id); \
+ echo_pack_p->icmp_seq = htons(seq); \
+ memmove(echo_pack_p->icmp_data, data, len); \
+} while (0)
+
+#define icmp_pack_hdr_quote(hdr, type, code, word, pkt, len) do { \
+ struct icmp_msg_quote *quote_pack_p = (struct icmp_msg_quote *) \
+ ((uint8_t *)(hdr) + ICMP_HDR_LEN); \
+ icmp_pack_hdr(hdr, type, code); \
+ quote_pack_p->icmp_void = htonl(word); \
+ memmove(quote_pack_p->icmp_ip, pkt, len); \
+} while (0)
+
+#define icmp_pack_hdr_mask(hdr, type, code, id, seq, mask) do { \
+ struct icmp_msg_mask *mask_pack_p = (struct icmp_msg_mask *) \
+ ((uint8_t *)(hdr) + ICMP_HDR_LEN); \
+ icmp_pack_hdr(hdr, type, code); \
+ mask_pack_p->icmp_id = htons(id); \
+ mask_pack_p->icmp_seq = htons(seq); \
+ mask_pack_p->icmp_mask = htonl(mask); \
+} while (0)
+
+#define icmp_pack_hdr_needfrag(hdr, type, code, mtu, pkt, len) do { \
+ struct icmp_msg_needfrag *frag_pack_p = \
+ (struct icmp_msg_needfrag *)((uint8_t *)(hdr) + ICMP_HDR_LEN); \
+ icmp_pack_hdr(hdr, type, code); \
+ frag_pack_p->icmp_void = 0; \
+ frag_pack_p->icmp_mtu = htons(mtu); \
+ memmove(frag_pack_p->icmp_ip, pkt, len); \
+} while (0)
+
+#endif /* DNET_ICMP_H */
diff --git a/ext/dnet/dnet/intf.h b/ext/dnet/dnet/intf.h
new file mode 100644
index 000000000..38acd4356
--- /dev/null
+++ b/ext/dnet/dnet/intf.h
@@ -0,0 +1,68 @@
+/*
+ * intf.c
+ *
+ * Network interface operations.
+ *
+ * Copyright (c) 2000 Dug Song <dugsong@monkey.org>
+ *
+ * $Id: intf.h,v 1.16 2004/01/13 07:41:09 dugsong Exp $
+ */
+
+#ifndef DNET_INTF_H
+#define DNET_INTF_H
+
+/*
+ * Interface entry
+ */
+#define INTF_NAME_LEN 16
+
+struct intf_entry {
+ u_int intf_len; /* length of entry */
+ char intf_name[INTF_NAME_LEN]; /* interface name */
+ u_short intf_type; /* interface type (r/o) */
+ u_short intf_flags; /* interface flags */
+ u_int intf_mtu; /* interface MTU */
+ struct addr intf_addr; /* interface address */
+ struct addr intf_dst_addr; /* point-to-point dst */
+ struct addr intf_link_addr; /* link-layer address */
+ u_int intf_alias_num; /* number of aliases */
+ struct addr intf_alias_addrs __flexarr; /* array of aliases */
+};
+
+/*
+ * MIB-II interface types - http://www.iana.org/assignments/ianaiftype-mib
+ */
+#define INTF_TYPE_OTHER 1 /* other */
+#define INTF_TYPE_ETH 6 /* Ethernet */
+#define INTF_TYPE_TOKENRING 9 /* Token Ring */
+#define INTF_TYPE_FDDI 15 /* FDDI */
+#define INTF_TYPE_PPP 23 /* Point-to-Point Protocol */
+#define INTF_TYPE_LOOPBACK 24 /* software loopback */
+#define INTF_TYPE_SLIP 28 /* Serial Line Interface Protocol */
+#define INTF_TYPE_TUN 53 /* proprietary virtual/internal */
+
+/*
+ * Interface flags
+ */
+#define INTF_FLAG_UP 0x01 /* enable interface */
+#define INTF_FLAG_LOOPBACK 0x02 /* is a loopback net (r/o) */
+#define INTF_FLAG_POINTOPOINT 0x04 /* point-to-point link (r/o) */
+#define INTF_FLAG_NOARP 0x08 /* disable ARP */
+#define INTF_FLAG_BROADCAST 0x10 /* supports broadcast (r/o) */
+#define INTF_FLAG_MULTICAST 0x20 /* supports multicast (r/o) */
+
+typedef struct intf_handle intf_t;
+
+typedef int (*intf_handler)(const struct intf_entry *entry, void *arg);
+
+__BEGIN_DECLS
+intf_t *intf_open(void);
+int intf_get(intf_t *i, struct intf_entry *entry);
+int intf_get_src(intf_t *i, struct intf_entry *entry, struct addr *src);
+int intf_get_dst(intf_t *i, struct intf_entry *entry, struct addr *dst);
+int intf_set(intf_t *i, const struct intf_entry *entry);
+int intf_loop(intf_t *i, intf_handler callback, void *arg);
+intf_t *intf_close(intf_t *i);
+__END_DECLS
+
+#endif /* DNET_INTF_H */
diff --git a/ext/dnet/dnet/ip.h b/ext/dnet/dnet/ip.h
new file mode 100644
index 000000000..95b7718fb
--- /dev/null
+++ b/ext/dnet/dnet/ip.h
@@ -0,0 +1,487 @@
+/*
+ * ip.h
+ *
+ * Internet Protocol (RFC 791).
+ *
+ * Copyright (c) 2000 Dug Song <dugsong@monkey.org>
+ *
+ * $Id: ip.h,v 1.23 2003/03/16 17:39:17 dugsong Exp $
+ */
+
+#ifndef DNET_IP_H
+#define DNET_IP_H
+
+#define IP_ADDR_LEN 4 /* IP address length */
+#define IP_ADDR_BITS 32 /* IP address bits */
+
+#define IP_HDR_LEN 20 /* base IP header length */
+#define IP_OPT_LEN 2 /* base IP option length */
+#define IP_OPT_LEN_MAX 40
+#define IP_HDR_LEN_MAX (IP_HDR_LEN + IP_OPT_LEN_MAX)
+
+#define IP_LEN_MAX 65535
+#define IP_LEN_MIN IP_HDR_LEN
+
+typedef uint32_t ip_addr_t;
+
+#ifndef __GNUC__
+# define __attribute__(x)
+# pragma pack(1)
+#endif
+
+/*
+ * IP header, without options
+ */
+struct ip_hdr {
+#if DNET_BYTESEX == DNET_BIG_ENDIAN
+ uint8_t ip_v:4, /* version */
+ ip_hl:4; /* header length (incl any options) */
+#elif DNET_BYTESEX == DNET_LIL_ENDIAN
+ uint8_t ip_hl:4,
+ ip_v:4;
+#else
+# error "need to include <dnet.h>"
+#endif
+ uint8_t ip_tos; /* type of service */
+ uint16_t ip_len; /* total length (incl header) */
+ uint16_t ip_id; /* identification */
+ uint16_t ip_off; /* fragment offset and flags */
+ uint8_t ip_ttl; /* time to live */
+ uint8_t ip_p; /* protocol */
+ uint16_t ip_sum; /* checksum */
+ ip_addr_t ip_src; /* source address */
+ ip_addr_t ip_dst; /* destination address */
+};
+
+/*
+ * Type of service (ip_tos), RFC 1349 ("obsoleted by RFC 2474")
+ */
+#define IP_TOS_DEFAULT 0x00 /* default */
+#define IP_TOS_LOWDELAY 0x10 /* low delay */
+#define IP_TOS_THROUGHPUT 0x08 /* high throughput */
+#define IP_TOS_RELIABILITY 0x04 /* high reliability */
+#define IP_TOS_LOWCOST 0x02 /* low monetary cost - XXX */
+#define IP_TOS_ECT 0x02 /* ECN-capable transport */
+#define IP_TOS_CE 0x01 /* congestion experienced */
+
+/*
+ * IP precedence (high 3 bits of ip_tos), hopefully unused
+ */
+#define IP_TOS_PREC_ROUTINE 0x00
+#define IP_TOS_PREC_PRIORITY 0x20
+#define IP_TOS_PREC_IMMEDIATE 0x40
+#define IP_TOS_PREC_FLASH 0x60
+#define IP_TOS_PREC_FLASHOVERRIDE 0x80
+#define IP_TOS_PREC_CRITIC_ECP 0xa0
+#define IP_TOS_PREC_INTERNETCONTROL 0xc0
+#define IP_TOS_PREC_NETCONTROL 0xe0
+
+/*
+ * Fragmentation flags (ip_off)
+ */
+#define IP_RF 0x8000 /* reserved */
+#define IP_DF 0x4000 /* don't fragment */
+#define IP_MF 0x2000 /* more fragments (not last frag) */
+#define IP_OFFMASK 0x1fff /* mask for fragment offset */
+
+/*
+ * Time-to-live (ip_ttl), seconds
+ */
+#define IP_TTL_DEFAULT 64 /* default ttl, RFC 1122, RFC 1340 */
+#define IP_TTL_MAX 255 /* maximum ttl */
+
+/*
+ * Protocol (ip_p) - http://www.iana.org/assignments/protocol-numbers
+ */
+#define IP_PROTO_IP 0 /* dummy for IP */
+#define IP_PROTO_HOPOPTS IP_PROTO_IP /* IPv6 hop-by-hop options */
+#define IP_PROTO_ICMP 1 /* ICMP */
+#define IP_PROTO_IGMP 2 /* IGMP */
+#define IP_PROTO_GGP 3 /* gateway-gateway protocol */
+#define IP_PROTO_IPIP 4 /* IP in IP */
+#define IP_PROTO_ST 5 /* ST datagram mode */
+#define IP_PROTO_TCP 6 /* TCP */
+#define IP_PROTO_CBT 7 /* CBT */
+#define IP_PROTO_EGP 8 /* exterior gateway protocol */
+#define IP_PROTO_IGP 9 /* interior gateway protocol */
+#define IP_PROTO_BBNRCC 10 /* BBN RCC monitoring */
+#define IP_PROTO_NVP 11 /* Network Voice Protocol */
+#define IP_PROTO_PUP 12 /* PARC universal packet */
+#define IP_PROTO_ARGUS 13 /* ARGUS */
+#define IP_PROTO_EMCON 14 /* EMCON */
+#define IP_PROTO_XNET 15 /* Cross Net Debugger */
+#define IP_PROTO_CHAOS 16 /* Chaos */
+#define IP_PROTO_UDP 17 /* UDP */
+#define IP_PROTO_MUX 18 /* multiplexing */
+#define IP_PROTO_DCNMEAS 19 /* DCN measurement */
+#define IP_PROTO_HMP 20 /* Host Monitoring Protocol */
+#define IP_PROTO_PRM 21 /* Packet Radio Measurement */
+#define IP_PROTO_IDP 22 /* Xerox NS IDP */
+#define IP_PROTO_TRUNK1 23 /* Trunk-1 */
+#define IP_PROTO_TRUNK2 24 /* Trunk-2 */
+#define IP_PROTO_LEAF1 25 /* Leaf-1 */
+#define IP_PROTO_LEAF2 26 /* Leaf-2 */
+#define IP_PROTO_RDP 27 /* "Reliable Datagram" proto */
+#define IP_PROTO_IRTP 28 /* Inet Reliable Transaction */
+#define IP_PROTO_TP 29 /* ISO TP class 4 */
+#define IP_PROTO_NETBLT 30 /* Bulk Data Transfer */
+#define IP_PROTO_MFPNSP 31 /* MFE Network Services */
+#define IP_PROTO_MERITINP 32 /* Merit Internodal Protocol */
+#define IP_PROTO_SEP 33 /* Sequential Exchange proto */
+#define IP_PROTO_3PC 34 /* Third Party Connect proto */
+#define IP_PROTO_IDPR 35 /* Interdomain Policy Route */
+#define IP_PROTO_XTP 36 /* Xpress Transfer Protocol */
+#define IP_PROTO_DDP 37 /* Datagram Delivery Proto */
+#define IP_PROTO_CMTP 38 /* IDPR Ctrl Message Trans */
+#define IP_PROTO_TPPP 39 /* TP++ Transport Protocol */
+#define IP_PROTO_IL 40 /* IL Transport Protocol */
+#define IP_PROTO_IPV6 41 /* IPv6 */
+#define IP_PROTO_SDRP 42 /* Source Demand Routing */
+#define IP_PROTO_ROUTING 43 /* IPv6 routing header */
+#define IP_PROTO_FRAGMENT 44 /* IPv6 fragmentation header */
+#define IP_PROTO_RSVP 46 /* Reservation protocol */
+#define IP_PROTO_GRE 47 /* General Routing Encap */
+#define IP_PROTO_MHRP 48 /* Mobile Host Routing */
+#define IP_PROTO_ENA 49 /* ENA */
+#define IP_PROTO_ESP 50 /* Encap Security Payload */
+#define IP_PROTO_AH 51 /* Authentication Header */
+#define IP_PROTO_INLSP 52 /* Integated Net Layer Sec */
+#define IP_PROTO_SWIPE 53 /* SWIPE */
+#define IP_PROTO_NARP 54 /* NBMA Address Resolution */
+#define IP_PROTO_MOBILE 55 /* Mobile IP, RFC 2004 */
+#define IP_PROTO_TLSP 56 /* Transport Layer Security */
+#define IP_PROTO_SKIP 57 /* SKIP */
+#define IP_PROTO_ICMPV6 58 /* ICMP for IPv6 */
+#define IP_PROTO_NONE 59 /* IPv6 no next header */
+#define IP_PROTO_DSTOPTS 60 /* IPv6 destination options */
+#define IP_PROTO_ANYHOST 61 /* any host internal proto */
+#define IP_PROTO_CFTP 62 /* CFTP */
+#define IP_PROTO_ANYNET 63 /* any local network */
+#define IP_PROTO_EXPAK 64 /* SATNET and Backroom EXPAK */
+#define IP_PROTO_KRYPTOLAN 65 /* Kryptolan */
+#define IP_PROTO_RVD 66 /* MIT Remote Virtual Disk */
+#define IP_PROTO_IPPC 67 /* Inet Pluribus Packet Core */
+#define IP_PROTO_DISTFS 68 /* any distributed fs */
+#define IP_PROTO_SATMON 69 /* SATNET Monitoring */
+#define IP_PROTO_VISA 70 /* VISA Protocol */
+#define IP_PROTO_IPCV 71 /* Inet Packet Core Utility */
+#define IP_PROTO_CPNX 72 /* Comp Proto Net Executive */
+#define IP_PROTO_CPHB 73 /* Comp Protocol Heart Beat */
+#define IP_PROTO_WSN 74 /* Wang Span Network */
+#define IP_PROTO_PVP 75 /* Packet Video Protocol */
+#define IP_PROTO_BRSATMON 76 /* Backroom SATNET Monitor */
+#define IP_PROTO_SUNND 77 /* SUN ND Protocol */
+#define IP_PROTO_WBMON 78 /* WIDEBAND Monitoring */
+#define IP_PROTO_WBEXPAK 79 /* WIDEBAND EXPAK */
+#define IP_PROTO_EON 80 /* ISO CNLP */
+#define IP_PROTO_VMTP 81 /* Versatile Msg Transport*/
+#define IP_PROTO_SVMTP 82 /* Secure VMTP */
+#define IP_PROTO_VINES 83 /* VINES */
+#define IP_PROTO_TTP 84 /* TTP */
+#define IP_PROTO_NSFIGP 85 /* NSFNET-IGP */
+#define IP_PROTO_DGP 86 /* Dissimilar Gateway Proto */
+#define IP_PROTO_TCF 87 /* TCF */
+#define IP_PROTO_EIGRP 88 /* EIGRP */
+#define IP_PROTO_OSPF 89 /* Open Shortest Path First */
+#define IP_PROTO_SPRITERPC 90 /* Sprite RPC Protocol */
+#define IP_PROTO_LARP 91 /* Locus Address Resolution */
+#define IP_PROTO_MTP 92 /* Multicast Transport Proto */
+#define IP_PROTO_AX25 93 /* AX.25 Frames */
+#define IP_PROTO_IPIPENCAP 94 /* yet-another IP encap */
+#define IP_PROTO_MICP 95 /* Mobile Internet Ctrl */
+#define IP_PROTO_SCCSP 96 /* Semaphore Comm Sec Proto */
+#define IP_PROTO_ETHERIP 97 /* Ethernet in IPv4 */
+#define IP_PROTO_ENCAP 98 /* encapsulation header */
+#define IP_PROTO_ANYENC 99 /* private encryption scheme */
+#define IP_PROTO_GMTP 100 /* GMTP */
+#define IP_PROTO_IFMP 101 /* Ipsilon Flow Mgmt Proto */
+#define IP_PROTO_PNNI 102 /* PNNI over IP */
+#define IP_PROTO_PIM 103 /* Protocol Indep Multicast */
+#define IP_PROTO_ARIS 104 /* ARIS */
+#define IP_PROTO_SCPS 105 /* SCPS */
+#define IP_PROTO_QNX 106 /* QNX */
+#define IP_PROTO_AN 107 /* Active Networks */
+#define IP_PROTO_IPCOMP 108 /* IP Payload Compression */
+#define IP_PROTO_SNP 109 /* Sitara Networks Protocol */
+#define IP_PROTO_COMPAQPEER 110 /* Compaq Peer Protocol */
+#define IP_PROTO_IPXIP 111 /* IPX in IP */
+#define IP_PROTO_VRRP 112 /* Virtual Router Redundancy */
+#define IP_PROTO_PGM 113 /* PGM Reliable Transport */
+#define IP_PROTO_ANY0HOP 114 /* 0-hop protocol */
+#define IP_PROTO_L2TP 115 /* Layer 2 Tunneling Proto */
+#define IP_PROTO_DDX 116 /* D-II Data Exchange (DDX) */
+#define IP_PROTO_IATP 117 /* Interactive Agent Xfer */
+#define IP_PROTO_STP 118 /* Schedule Transfer Proto */
+#define IP_PROTO_SRP 119 /* SpectraLink Radio Proto */
+#define IP_PROTO_UTI 120 /* UTI */
+#define IP_PROTO_SMP 121 /* Simple Message Protocol */
+#define IP_PROTO_SM 122 /* SM */
+#define IP_PROTO_PTP 123 /* Performance Transparency */
+#define IP_PROTO_ISIS 124 /* ISIS over IPv4 */
+#define IP_PROTO_FIRE 125 /* FIRE */
+#define IP_PROTO_CRTP 126 /* Combat Radio Transport */
+#define IP_PROTO_CRUDP 127 /* Combat Radio UDP */
+#define IP_PROTO_SSCOPMCE 128 /* SSCOPMCE */
+#define IP_PROTO_IPLT 129 /* IPLT */
+#define IP_PROTO_SPS 130 /* Secure Packet Shield */
+#define IP_PROTO_PIPE 131 /* Private IP Encap in IP */
+#define IP_PROTO_SCTP 132 /* Stream Ctrl Transmission */
+#define IP_PROTO_FC 133 /* Fibre Channel */
+#define IP_PROTO_RSVPIGN 134 /* RSVP-E2E-IGNORE */
+#define IP_PROTO_RAW 255 /* Raw IP packets */
+#define IP_PROTO_RESERVED IP_PROTO_RAW /* Reserved */
+#define IP_PROTO_MAX 255
+
+/*
+ * Option types (opt_type) - http://www.iana.org/assignments/ip-parameters
+ */
+#define IP_OPT_CONTROL 0x00 /* control */
+#define IP_OPT_DEBMEAS 0x40 /* debugging & measurement */
+#define IP_OPT_COPY 0x80 /* copy into all fragments */
+#define IP_OPT_RESERVED1 0x20
+#define IP_OPT_RESERVED2 0x60
+
+#define IP_OPT_EOL 0 /* end of option list */
+#define IP_OPT_NOP 1 /* no operation */
+#define IP_OPT_SEC (2|IP_OPT_COPY) /* DoD basic security */
+#define IP_OPT_LSRR (3|IP_OPT_COPY) /* loose source route */
+#define IP_OPT_TS (4|IP_OPT_DEBMEAS) /* timestamp */
+#define IP_OPT_ESEC (5|IP_OPT_COPY) /* DoD extended security */
+#define IP_OPT_CIPSO (6|IP_OPT_COPY) /* commercial security */
+#define IP_OPT_RR 7 /* record route */
+#define IP_OPT_SATID (8|IP_OPT_COPY) /* stream ID (obsolete) */
+#define IP_OPT_SSRR (9|IP_OPT_COPY) /* strict source route */
+#define IP_OPT_ZSU 10 /* experimental measurement */
+#define IP_OPT_MTUP 11 /* MTU probe */
+#define IP_OPT_MTUR 12 /* MTU reply */
+#define IP_OPT_FINN (13|IP_OPT_COPY|IP_OPT_DEBMEAS) /* exp flow control */
+#define IP_OPT_VISA (14|IP_OPT_COPY) /* exp access control */
+#define IP_OPT_ENCODE 15 /* ??? */
+#define IP_OPT_IMITD (16|IP_OPT_COPY) /* IMI traffic descriptor */
+#define IP_OPT_EIP (17|IP_OPT_COPY) /* extended IP, RFC 1385 */
+#define IP_OPT_TR (18|IP_OPT_DEBMEAS) /* traceroute */
+#define IP_OPT_ADDEXT (19|IP_OPT_COPY) /* IPv7 ext addr, RFC 1475 */
+#define IP_OPT_RTRALT (20|IP_OPT_COPY) /* router alert, RFC 2113 */
+#define IP_OPT_SDB (21|IP_OPT_COPY) /* directed bcast, RFC 1770 */
+#define IP_OPT_NSAPA (22|IP_OPT_COPY) /* NSAP addresses */
+#define IP_OPT_DPS (23|IP_OPT_COPY) /* dynamic packet state */
+#define IP_OPT_UMP (24|IP_OPT_COPY) /* upstream multicast */
+#define IP_OPT_MAX 25
+
+#define IP_OPT_COPIED(o) ((o) & 0x80)
+#define IP_OPT_CLASS(o) ((o) & 0x60)
+#define IP_OPT_NUMBER(o) ((o) & 0x1f)
+#define IP_OPT_TYPEONLY(o) ((o) == IP_OPT_EOL || (o) == IP_OPT_NOP)
+
+/*
+ * Security option data - RFC 791, 3.1
+ */
+struct ip_opt_data_sec {
+ uint16_t s; /* security */
+ uint16_t c; /* compartments */
+ uint16_t h; /* handling restrictions */
+ uint8_t tcc[3]; /* transmission control code */
+} __attribute__((__packed__));
+
+#define IP_OPT_SEC_UNCLASS 0x0000 /* unclassified */
+#define IP_OPT_SEC_CONFID 0xf135 /* confidential */
+#define IP_OPT_SEC_EFTO 0x789a /* EFTO */
+#define IP_OPT_SEC_MMMM 0xbc4d /* MMMM */
+#define IP_OPT_SEC_PROG 0x5e26 /* PROG */
+#define IP_OPT_SEC_RESTR 0xaf13 /* restricted */
+#define IP_OPT_SEC_SECRET 0xd788 /* secret */
+#define IP_OPT_SEC_TOPSECRET 0x6bc5 /* top secret */
+
+/*
+ * {Loose Source, Record, Strict Source} Route option data - RFC 791, 3.1
+ */
+struct ip_opt_data_rr {
+ uint8_t ptr; /* from start of option, >= 4 */
+ uint32_t iplist __flexarr; /* list of IP addresses */
+} __attribute__((__packed__));
+
+/*
+ * Timestamp option data - RFC 791, 3.1
+ */
+struct ip_opt_data_ts {
+ uint8_t ptr; /* from start of option, >= 5 */
+#if DNET_BYTESEX == DNET_BIG_ENDIAN
+ uint8_t oflw:4, /* number of IPs skipped */
+ flg:4; /* address[ / timestamp] flag */
+#elif DNET_BYTESEX == DNET_LIL_ENDIAN
+ uint8_t flg:4,
+ oflw:4;
+#endif
+ uint32_t ipts __flexarr; /* IP address [/ timestamp] pairs */
+} __attribute__((__packed__));
+
+#define IP_OPT_TS_TSONLY 0 /* timestamps only */
+#define IP_OPT_TS_TSADDR 1 /* IP address / timestamp pairs */
+#define IP_OPT_TS_PRESPEC 3 /* IP address / zero timestamp pairs */
+
+/*
+ * Traceroute option data - RFC 1393, 2.2
+ */
+struct ip_opt_data_tr {
+ uint16_t id; /* ID number */
+ uint16_t ohc; /* outbound hop count */
+ uint16_t rhc; /* return hop count */
+ uint32_t origip; /* originator IP address */
+} __attribute__((__packed__));
+
+/*
+ * IP option (following IP header)
+ */
+struct ip_opt {
+ uint8_t opt_type; /* option type */
+ uint8_t opt_len; /* option length >= IP_OPT_LEN */
+ union ip_opt_data {
+ struct ip_opt_data_sec sec; /* IP_OPT_SEC */
+ struct ip_opt_data_rr rr; /* IP_OPT_{L,S}RR */
+ struct ip_opt_data_ts ts; /* IP_OPT_TS */
+ uint16_t satid; /* IP_OPT_SATID */
+ uint16_t mtu; /* IP_OPT_MTU{P,R} */
+ struct ip_opt_data_tr tr; /* IP_OPT_TR */
+ uint32_t addext[2]; /* IP_OPT_ADDEXT */
+ uint16_t rtralt; /* IP_OPT_RTRALT */
+ uint32_t sdb[9]; /* IP_OPT_SDB */
+ uint8_t data8[IP_OPT_LEN_MAX - IP_OPT_LEN];
+ } opt_data;
+} __attribute__((__packed__));
+
+#ifndef __GNUC__
+# pragma pack()
+#endif
+
+/*
+ * Classful addressing
+ */
+#define IP_CLASSA(i) (((uint32_t)(i) & htonl(0x80000000)) == \
+ htonl(0x00000000))
+#define IP_CLASSA_NET (htonl(0xff000000))
+#define IP_CLASSA_NSHIFT 24
+#define IP_CLASSA_HOST (htonl(0x00ffffff))
+#define IP_CLASSA_MAX 128
+
+#define IP_CLASSB(i) (((uint32_t)(i) & htonl(0xc0000000)) == \
+ htonl(0x80000000))
+#define IP_CLASSB_NET (htonl(0xffff0000))
+#define IP_CLASSB_NSHIFT 16
+#define IP_CLASSB_HOST (htonl(0x0000ffff))
+#define IP_CLASSB_MAX 65536
+
+#define IP_CLASSC(i) (((uint32_t)(i) & htonl(0xe0000000)) == \
+ htonl(0xc0000000))
+#define IP_CLASSC_NET (htonl(0xffffff00))
+#define IP_CLASSC_NSHIFT 8
+#define IP_CLASSC_HOST (htonl(0x000000ff))
+
+#define IP_CLASSD(i) (((uint32_t)(i) & htonl(0xf0000000)) == \
+ htonl(0xe0000000))
+/* These ones aren't really net and host fields, but routing needn't know. */
+#define IP_CLASSD_NET (htonl(0xf0000000))
+#define IP_CLASSD_NSHIFT 28
+#define IP_CLASSD_HOST (htonl(0x0fffffff))
+#define IP_MULTICAST(i) IP_CLASSD(i)
+
+#define IP_EXPERIMENTAL(i) (((uint32_t)(i) & htonl(0xf0000000)) == \
+ htonl(0xf0000000))
+#define IP_BADCLASS(i) (((uint32_t)(i) & htonl(0xf0000000)) == \
+ htonl(0xf0000000))
+#define IP_LOCAL_GROUP(i) (((uint32_t)(i) & htonl(0xffffff00)) == \
+ htonl(0xe0000000))
+/*
+ * Reserved addresses
+ */
+#define IP_ADDR_ANY (htonl(0x00000000)) /* 0.0.0.0 */
+#define IP_ADDR_BROADCAST (htonl(0xffffffff)) /* 255.255.255.255 */
+#define IP_ADDR_LOOPBACK (htonl(0x7f000001)) /* 127.0.0.1 */
+#define IP_ADDR_MCAST_ALL (htonl(0xe0000001)) /* 224.0.0.1 */
+#define IP_ADDR_MCAST_LOCAL (htonl(0xe00000ff)) /* 224.0.0.225 */
+
+#define ip_pack_hdr(hdr, tos, len, id, off, ttl, p, src, dst) do { \
+ struct ip_hdr *ip_pack_p = (struct ip_hdr *)(hdr); \
+ ip_pack_p->ip_v = 4; ip_pack_p->ip_hl = 5; \
+ ip_pack_p->ip_tos = tos; ip_pack_p->ip_len = htons(len); \
+ ip_pack_p->ip_id = htons(id); ip_pack_p->ip_off = htons(off); \
+ ip_pack_p->ip_ttl = ttl; ip_pack_p->ip_p = p; \
+ ip_pack_p->ip_src = src; ip_pack_p->ip_dst = dst; \
+} while (0)
+
+typedef struct ip_handle ip_t;
+
+__BEGIN_DECLS
+ip_t *ip_open(void);
+size_t ip_send(ip_t *i, const void *buf, size_t len);
+ip_t *ip_close(ip_t *i);
+
+char *ip_ntop(const ip_addr_t *ip, char *dst, size_t len);
+int ip_pton(const char *src, ip_addr_t *dst);
+char *ip_ntoa(const ip_addr_t *ip);
+#define ip_aton ip_pton
+
+size_t ip_add_option(void *buf, size_t len,
+ int proto, const void *optbuf, size_t optlen);
+void ip_checksum(void *buf, size_t len);
+
+inline int
+ip_cksum_add(const void *buf, size_t len, int cksum)
+{
+ uint16_t *sp = (uint16_t *)buf;
+ int n, sn;
+
+ sn = len / 2;
+ n = (sn + 15) / 16;
+
+ /* XXX - unroll loop using Duff's device. */
+ switch (sn % 16) {
+ case 0: do {
+ cksum += *sp++;
+ case 15:
+ cksum += *sp++;
+ case 14:
+ cksum += *sp++;
+ case 13:
+ cksum += *sp++;
+ case 12:
+ cksum += *sp++;
+ case 11:
+ cksum += *sp++;
+ case 10:
+ cksum += *sp++;
+ case 9:
+ cksum += *sp++;
+ case 8:
+ cksum += *sp++;
+ case 7:
+ cksum += *sp++;
+ case 6:
+ cksum += *sp++;
+ case 5:
+ cksum += *sp++;
+ case 4:
+ cksum += *sp++;
+ case 3:
+ cksum += *sp++;
+ case 2:
+ cksum += *sp++;
+ case 1:
+ cksum += *sp++;
+ } while (--n > 0);
+ }
+ if (len & 1)
+ cksum += htons(*(u_char *)sp << 8);
+
+ return (cksum);
+}
+
+inline uint16_t
+ip_cksum_carry(int x)
+{
+ x = (x >> 16) + (x & 0xffff);
+ return ~(x + (x >> 16)) & 0xffff;
+}
+
+__END_DECLS
+
+#endif /* DNET_IP_H */
diff --git a/ext/dnet/dnet/ip6.h b/ext/dnet/dnet/ip6.h
new file mode 100644
index 000000000..7fae29b47
--- /dev/null
+++ b/ext/dnet/dnet/ip6.h
@@ -0,0 +1,183 @@
+/*
+ * ip6.h
+ *
+ * Internet Protocol, Version 6 (RFC 2460).
+ *
+ * Copyright (c) 2002 Dug Song <dugsong@monkey.org>
+ *
+ * $Id: ip6.h,v 1.6 2004/02/23 10:01:15 dugsong Exp $
+ */
+
+#ifndef DNET_IP6_H
+#define DNET_IP6_H
+
+#define IP6_ADDR_LEN 16
+#define IP6_ADDR_BITS 128
+
+#define IP6_HDR_LEN 40 /* IPv6 header length */
+#define IP6_LEN_MIN IP6_HDR_LEN
+#define IP6_LEN_MAX 65535 /* non-jumbo payload */
+
+#define IP6_MTU_MIN 1280 /* minimum MTU (1024 + 256) */
+
+typedef struct ip6_addr {
+ uint8_t data[IP6_ADDR_LEN];
+} ip6_addr_t;
+
+#ifndef __GNUC__
+# define __attribute__(x)
+# pragma pack(1)
+#endif
+
+/*
+ * IPv6 header
+ */
+struct ip6_hdr {
+ union {
+ struct ip6_hdr_ctl {
+ uint32_t ip6_un1_flow; /* 20 bits of flow ID */
+ uint16_t ip6_un1_plen; /* payload length */
+ uint8_t ip6_un1_nxt; /* next header */
+ uint8_t ip6_un1_hlim; /* hop limit */
+ } ip6_un1;
+ uint8_t ip6_un2_vfc; /* 4 bits version, top 4 bits class */
+ } ip6_ctlun;
+ ip6_addr_t ip6_src;
+ ip6_addr_t ip6_dst;
+} __attribute__((__packed__));
+
+#define ip6_vfc ip6_ctlun.ip6_un2_vfc
+#define ip6_flow ip6_ctlun.ip6_un1.ip6_un1_flow
+#define ip6_plen ip6_ctlun.ip6_un1.ip6_un1_plen
+#define ip6_nxt ip6_ctlun.ip6_un1.ip6_un1_nxt /* IP_PROTO_* */
+#define ip6_hlim ip6_ctlun.ip6_un1.ip6_un1_hlim
+
+#define IP6_VERSION 0x60
+#define IP6_VERSION_MASK 0xf0 /* ip6_vfc version */
+
+#if DNET_BYTESEX == DNET_BIG_ENDIAN
+#define IP6_FLOWINFO_MASK 0x0fffffff /* ip6_flow info (28 bits) */
+#define IP6_FLOWLABEL_MASK 0x000fffff /* ip6_flow label (20 bits) */
+#elif DNET_BYTESEX == DNET_LIL_ENDIAN
+#define IP6_FLOWINFO_MASK 0xffffff0f /* ip6_flow info (28 bits) */
+#define IP6_FLOWLABEL_MASK 0xffff0f00 /* ip6_flow label (20 bits) */
+#endif
+
+/*
+ * Hop limit (ip6_hlim)
+ */
+#define IP6_HLIM_DEFAULT 64
+#define IP6_HLIM_MAX 255
+
+/*
+ * Preferred extension header order from RFC 2460, 4.1:
+ *
+ * IP_PROTO_IPV6, IP_PROTO_HOPOPTS, IP_PROTO_DSTOPTS, IP_PROTO_ROUTING,
+ * IP_PROTO_FRAGMENT, IP_PROTO_AH, IP_PROTO_ESP, IP_PROTO_DSTOPTS, IP_PROTO_*
+ */
+
+/*
+ * Routing header data (IP_PROTO_ROUTING)
+ */
+struct ip6_ext_data_routing {
+ uint8_t type; /* routing type */
+ uint8_t segleft; /* segments left */
+ /* followed by routing type specific data */
+} __attribute__((__packed__));
+
+struct ip6_ext_data_routing0 {
+ uint8_t type; /* always zero */
+ uint8_t segleft; /* segments left */
+ uint8_t reserved; /* reserved field */
+ uint8_t slmap[3]; /* strict/loose bit map */
+ ip6_addr_t addr[1]; /* up to 23 addresses */
+} __attribute__((__packed__));
+
+/*
+ * Fragment header data (IP_PROTO_FRAGMENT)
+ */
+struct ip6_ext_data_fragment {
+ uint16_t offlg; /* offset, reserved, and flag */
+ uint32_t ident; /* identification */
+} __attribute__((__packed__));
+
+/*
+ * Fragmentation offset, reserved, and flags (offlg)
+ */
+#if DNET_BYTESEX == DNET_BIG_ENDIAN
+#define IP6_OFF_MASK 0xfff8 /* mask out offset from offlg */
+#define IP6_RESERVED_MASK 0x0006 /* reserved bits in offlg */
+#define IP6_MORE_FRAG 0x0001 /* more-fragments flag */
+#elif DNET_BYTESEX == DNET_LIL_ENDIAN
+#define IP6_OFF_MASK 0xf8ff /* mask out offset from offlg */
+#define IP6_RESERVED_MASK 0x0600 /* reserved bits in offlg */
+#define IP6_MORE_FRAG 0x0100 /* more-fragments flag */
+#endif
+
+/*
+ * Option types, for IP_PROTO_HOPOPTS, IP_PROTO_DSTOPTS headers
+ */
+#define IP6_OPT_PAD1 0x00 /* 00 0 00000 */
+#define IP6_OPT_PADN 0x01 /* 00 0 00001 */
+#define IP6_OPT_JUMBO 0xC2 /* 11 0 00010 = 194 */
+#define IP6_OPT_JUMBO_LEN 6
+#define IP6_OPT_RTALERT 0x05 /* 00 0 00101 */
+#define IP6_OPT_RTALERT_LEN 4
+#define IP6_OPT_RTALERT_MLD 0 /* Datagram contains an MLD message */
+#define IP6_OPT_RTALERT_RSVP 1 /* Datagram contains an RSVP message */
+#define IP6_OPT_RTALERT_ACTNET 2 /* contains an Active Networks msg */
+#define IP6_OPT_LEN_MIN 2
+
+#define IP6_OPT_TYPE(o) ((o) & 0xC0) /* high 2 bits of opt_type */
+#define IP6_OPT_TYPE_SKIP 0x00 /* continue processing on failure */
+#define IP6_OPT_TYPE_DISCARD 0x40 /* discard packet on failure */
+#define IP6_OPT_TYPE_FORCEICMP 0x80 /* discard and send ICMP on failure */
+#define IP6_OPT_TYPE_ICMP 0xC0 /* ...only if non-multicast dst */
+
+#define IP6_OPT_MUTABLE 0x20 /* option data may change en route */
+
+/*
+ * Extension header (chained via {ip6,ext}_nxt, following IPv6 header)
+ */
+struct ip6_ext_hdr {
+ uint8_t ext_nxt; /* next header */
+ uint8_t ext_len; /* following length in units of 8 octets */
+ union {
+ struct ip6_ext_data_routing routing;
+ struct ip6_ext_data_fragment fragment;
+ } ext_data;
+} __attribute__((__packed__));
+
+#ifndef __GNUC__
+# pragma pack()
+#endif
+
+/*
+ * Reserved addresses
+ */
+#define IP6_ADDR_UNSPEC \
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+#define IP6_ADDR_LOOPBACK \
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01"
+
+#define ip6_pack_hdr(hdr, fc, fl, plen, nxt, hlim, src, dst) do { \
+ struct ip6_hdr *ip6 = (struct ip6_hdr *)(hdr); \
+ ip6->ip6_flow = htonl(((uint32_t)(fc) << 28) & \
+ (IP6_FLOWLABEL_MASK | (fl))); \
+ ip6->ip6_vfc = (IP6_VERSION | ((fc) >> 4)); \
+ ip6->ip6_plen = htons((plen)); \
+ ip6->ip6_nxt = (nxt); ip6->ip6_hlim = (hlim); \
+ memmove(&ip6->ip6_src, &(src), IP6_ADDR_LEN); \
+ memmove(&ip6->ip6_dst, &(dst), IP6_ADDR_LEN); \
+} while (0);
+
+__BEGIN_DECLS
+char *ip6_ntop(const ip6_addr_t *ip6, char *dst, size_t size);
+int ip6_pton(const char *src, ip6_addr_t *dst);
+char *ip6_ntoa(const ip6_addr_t *ip6);
+#define ip6_aton ip6_pton
+
+void ip6_checksum(void *buf, size_t len);
+__END_DECLS
+
+#endif /* DNET_IP6_H */
diff --git a/ext/dnet/dnet/os.h b/ext/dnet/dnet/os.h
new file mode 100644
index 000000000..cae244781
--- /dev/null
+++ b/ext/dnet/dnet/os.h
@@ -0,0 +1,117 @@
+/*
+ * os.h
+ *
+ * Sleazy OS-specific defines.
+ *
+ * Copyright (c) 2000 Dug Song <dugsong@monkey.org>
+ *
+ * $Id: os.h,v 1.10 2004/05/04 03:19:42 dugsong Exp $
+ */
+
+#ifndef DNET_OS_H
+#define DNET_OS_H
+
+#ifdef _WIN32
+# include <windows.h>
+# include <winsock2.h>
+# include <stdint.h>
+/* XXX */
+# undef IP_OPT_LSRR
+# undef IP_OPT_TS
+# undef IP_OPT_RR
+# undef IP_OPT_SSRR
+#else
+# include <sys/param.h>
+# include <sys/types.h>
+# include <sys/socket.h>
+# include <netinet/in.h>
+# include <arpa/inet.h>
+# include <netdb.h>
+# ifdef __bsdi__
+# include <machine/types.h>
+ typedef u_int8_t uint8_t;
+ typedef u_int16_t uint16_t;
+ typedef u_int32_t uint32_t;
+ typedef u_int64_t uint64_t;
+# else
+# include <inttypes.h>
+# endif
+#endif
+
+#define DNET_LIL_ENDIAN 1234
+#define DNET_BIG_ENDIAN 4321
+
+/* BSD and IRIX */
+#ifdef BYTE_ORDER
+#if BYTE_ORDER == LITTLE_ENDIAN
+# define DNET_BYTESEX DNET_LIL_ENDIAN
+#elif BYTE_ORDER == BIG_ENDIAN
+# define DNET_BYTESEX DNET_BIG_ENDIAN
+#endif
+#endif
+
+/* Linux */
+#ifdef __BYTE_ORDER
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+# define DNET_BYTESEX DNET_LIL_ENDIAN
+#elif __BYTE_ORDER == __BIG_ENDIAN
+# define DNET_BYTESEX DNET_BIG_ENDIAN
+#endif
+#endif
+
+/* Solaris */
+#if defined(_BIT_FIELDS_LTOH)
+# define DNET_BYTESEX DNET_LIL_ENDIAN
+#elif defined (_BIT_FIELDS_HTOL)
+# define DNET_BYTESEX DNET_BIG_ENDIAN
+#endif
+
+/* Nastiness from old BIND code. */
+#ifndef DNET_BYTESEX
+# if defined(vax) || defined(ns32000) || defined(sun386) || defined(i386) || \
+ defined(MIPSEL) || defined(_MIPSEL) || defined(BIT_ZERO_ON_RIGHT) || \
+ defined(__alpha__) || defined(__alpha)
+# define DNET_BYTESEX DNET_LIL_ENDIAN
+# elif defined(sel) || defined(pyr) || defined(mc68000) || defined(sparc) || \
+ defined(is68k) || defined(tahoe) || defined(ibm032) || defined(ibm370) || \
+ defined(MIPSEB) || defined(_MIPSEB) || defined(_IBMR2) || defined(DGUX) ||\
+ defined(apollo) || defined(__convex__) || defined(_CRAY) || \
+ defined(__hppa) || defined(__hp9000) || \
+ defined(__hp9000s300) || defined(__hp9000s700) || defined(__ia64) || \
+ defined (BIT_ZERO_ON_LEFT) || defined(m68k)
+# define DNET_BYTESEX DNET_BIG_ENDIAN
+# else
+# error "bytesex unknown"
+# endif
+#endif
+
+/* C++ support. */
+#undef __BEGIN_DECLS
+#undef __END_DECLS
+#ifdef __cplusplus
+# define __BEGIN_DECLS extern "C" {
+# define __END_DECLS } /* extern "C" */
+#else
+# define __BEGIN_DECLS
+# define __END_DECLS
+#endif
+
+/* Support for flexible arrays. */
+#undef __flexarr
+#if defined(__GNUC__) && ((__GNUC__ > 2) || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97))
+/* GCC 2.97 supports C99 flexible array members. */
+# define __flexarr []
+#else
+# ifdef __GNUC__
+# define __flexarr [0]
+# else
+# if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L
+# define __flexarr []
+# else
+/* Some other non-C99 compiler. Approximate with [1]. */
+# define __flexarr [1]
+# endif
+# endif
+#endif
+
+#endif /* DNET_OS_H */
diff --git a/ext/dnet/dnet/rand.h b/ext/dnet/dnet/rand.h
new file mode 100644
index 000000000..49121930c
--- /dev/null
+++ b/ext/dnet/dnet/rand.h
@@ -0,0 +1,33 @@
+/*
+ * rand.h
+ *
+ * Pseudo-random number generation, based on OpenBSD arc4random().
+ *
+ * Copyright (c) 2000 Dug Song <dugsong@monkey.org>
+ * Copyright (c) 1996 David Mazieres <dm@lcs.mit.edu>
+ *
+ * $Id: rand.h,v 1.4 2002/04/07 19:01:25 dugsong Exp $
+ */
+
+#ifndef DNET_RAND_H
+#define DNET_RAND_H
+
+typedef struct rand_handle rand_t;
+
+__BEGIN_DECLS
+rand_t *rand_open(void);
+
+int rand_get(rand_t *r, void *buf, size_t len);
+int rand_set(rand_t *r, const void *seed, size_t len);
+int rand_add(rand_t *r, const void *buf, size_t len);
+
+uint8_t rand_uint8(rand_t *r);
+uint16_t rand_uint16(rand_t *r);
+uint32_t rand_uint32(rand_t *r);
+
+int rand_shuffle(rand_t *r, void *base, size_t nmemb, size_t size);
+
+rand_t *rand_close(rand_t *r);
+__END_DECLS
+
+#endif /* DNET_RAND_H */
diff --git a/ext/dnet/dnet/route.h b/ext/dnet/dnet/route.h
new file mode 100644
index 000000000..74c21419c
--- /dev/null
+++ b/ext/dnet/dnet/route.h
@@ -0,0 +1,35 @@
+/*
+ * route.c
+ *
+ * Kernel route table operations.
+ *
+ * Copyright (c) 2000 Dug Song <dugsong@monkey.org>
+ *
+ * $Id: route.h,v 1.6 2002/02/04 04:02:22 dugsong Exp $
+ */
+
+#ifndef DNET_ROUTE_H
+#define DNET_ROUTE_H
+
+/*
+ * Routing table entry
+ */
+struct route_entry {
+ struct addr route_dst; /* destination address */
+ struct addr route_gw; /* gateway address */
+};
+
+typedef struct route_handle route_t;
+
+typedef int (*route_handler)(const struct route_entry *entry, void *arg);
+
+__BEGIN_DECLS
+route_t *route_open(void);
+int route_add(route_t *r, const struct route_entry *entry);
+int route_delete(route_t *r, const struct route_entry *entry);
+int route_get(route_t *r, struct route_entry *entry);
+int route_loop(route_t *r, route_handler callback, void *arg);
+route_t *route_close(route_t *r);
+__END_DECLS
+
+#endif /* DNET_ROUTE_H */
diff --git a/ext/dnet/dnet/tcp.h b/ext/dnet/dnet/tcp.h
new file mode 100644
index 000000000..008946384
--- /dev/null
+++ b/ext/dnet/dnet/tcp.h
@@ -0,0 +1,158 @@
+/*
+ * tcp.h
+ *
+ * Transmission Control Protocol (RFC 793).
+ *
+ * Copyright (c) 2000 Dug Song <dugsong@monkey.org>
+ *
+ * $Id: tcp.h,v 1.17 2004/02/23 10:02:11 dugsong Exp $
+ */
+
+#ifndef DNET_TCP_H
+#define DNET_TCP_H
+
+#define TCP_HDR_LEN 20 /* base TCP header length */
+#define TCP_OPT_LEN 2 /* base TCP option length */
+#define TCP_OPT_LEN_MAX 40
+#define TCP_HDR_LEN_MAX (TCP_HDR_LEN + TCP_OPT_LEN_MAX)
+
+#ifndef __GNUC__
+# define __attribute__(x)
+# pragma pack(1)
+#endif
+
+/*
+ * TCP header, without options
+ */
+struct tcp_hdr {
+ uint16_t th_sport; /* source port */
+ uint16_t th_dport; /* destination port */
+ uint32_t th_seq; /* sequence number */
+ uint32_t th_ack; /* acknowledgment number */
+#if DNET_BYTESEX == DNET_BIG_ENDIAN
+ uint8_t th_off:4, /* data offset */
+ th_x2:4; /* (unused) */
+#elif DNET_BYTESEX == DNET_LIL_ENDIAN
+ uint8_t th_x2:4,
+ th_off:4;
+#else
+# error "need to include <dnet.h>"
+#endif
+ uint8_t th_flags; /* control flags */
+ uint16_t th_win; /* window */
+ uint16_t th_sum; /* checksum */
+ uint16_t th_urp; /* urgent pointer */
+};
+
+/*
+ * TCP control flags (th_flags)
+ */
+#define TH_FIN 0x01 /* end of data */
+#define TH_SYN 0x02 /* synchronize sequence numbers */
+#define TH_RST 0x04 /* reset connection */
+#define TH_PUSH 0x08 /* push */
+#define TH_ACK 0x10 /* acknowledgment number set */
+#define TH_URG 0x20 /* urgent pointer set */
+#define TH_ECE 0x40 /* ECN echo, RFC 3168 */
+#define TH_CWR 0x80 /* congestion window reduced */
+
+#define TCP_PORT_MAX 65535 /* maximum port */
+#define TCP_WIN_MAX 65535 /* maximum (unscaled) window */
+
+/*
+ * Sequence number comparison macros
+ */
+#define TCP_SEQ_LT(a,b) ((int)((a)-(b)) < 0)
+#define TCP_SEQ_LEQ(a,b) ((int)((a)-(b)) <= 0)
+#define TCP_SEQ_GT(a,b) ((int)((a)-(b)) > 0)
+#define TCP_SEQ_GEQ(a,b) ((int)((a)-(b)) >= 0)
+
+/*
+ * TCP FSM states
+ */
+#define TCP_STATE_CLOSED 0 /* closed */
+#define TCP_STATE_LISTEN 1 /* listening from connection */
+#define TCP_STATE_SYN_SENT 2 /* active, have sent SYN */
+#define TCP_STATE_SYN_RECEIVED 3 /* have sent and received SYN */
+
+#define TCP_STATE_ESTABLISHED 4 /* established */
+#define TCP_STATE_CLOSE_WAIT 5 /* rcvd FIN, waiting for close */
+
+#define TCP_STATE_FIN_WAIT_1 6 /* have closed, sent FIN */
+#define TCP_STATE_CLOSING 7 /* closed xchd FIN, await FIN-ACK */
+#define TCP_STATE_LAST_ACK 8 /* had FIN and close, await FIN-ACK */
+
+#define TCP_STATE_FIN_WAIT_2 9 /* have closed, FIN is acked */
+#define TCP_STATE_TIME_WAIT 10 /* in 2*MSL quiet wait after close */
+#define TCP_STATE_MAX 11
+
+/*
+ * Options (opt_type) - http://www.iana.org/assignments/tcp-parameters
+ */
+#define TCP_OPT_EOL 0 /* end of option list */
+#define TCP_OPT_NOP 1 /* no operation */
+#define TCP_OPT_MSS 2 /* maximum segment size */
+#define TCP_OPT_WSCALE 3 /* window scale factor, RFC 1072 */
+#define TCP_OPT_SACKOK 4 /* SACK permitted, RFC 2018 */
+#define TCP_OPT_SACK 5 /* SACK, RFC 2018 */
+#define TCP_OPT_ECHO 6 /* echo (obsolete), RFC 1072 */
+#define TCP_OPT_ECHOREPLY 7 /* echo reply (obsolete), RFC 1072 */
+#define TCP_OPT_TIMESTAMP 8 /* timestamp, RFC 1323 */
+#define TCP_OPT_POCONN 9 /* partial order conn, RFC 1693 */
+#define TCP_OPT_POSVC 10 /* partial order service, RFC 1693 */
+#define TCP_OPT_CC 11 /* connection count, RFC 1644 */
+#define TCP_OPT_CCNEW 12 /* CC.NEW, RFC 1644 */
+#define TCP_OPT_CCECHO 13 /* CC.ECHO, RFC 1644 */
+#define TCP_OPT_ALTSUM 14 /* alt checksum request, RFC 1146 */
+#define TCP_OPT_ALTSUMDATA 15 /* alt checksum data, RFC 1146 */
+#define TCP_OPT_SKEETER 16 /* Skeeter */
+#define TCP_OPT_BUBBA 17 /* Bubba */
+#define TCP_OPT_TRAILSUM 18 /* trailer checksum */
+#define TCP_OPT_MD5 19 /* MD5 signature, RFC 2385 */
+#define TCP_OPT_SCPS 20 /* SCPS capabilities */
+#define TCP_OPT_SNACK 21 /* selective negative acks */
+#define TCP_OPT_REC 22 /* record boundaries */
+#define TCP_OPT_CORRUPT 23 /* corruption experienced */
+#define TCP_OPT_SNAP 24 /* SNAP */
+#define TCP_OPT_TCPCOMP 26 /* TCP compression filter */
+#define TCP_OPT_MAX 27
+
+#define TCP_OPT_TYPEONLY(type) \
+ ((type) == TCP_OPT_EOL || (type) == TCP_OPT_NOP)
+
+/*
+ * TCP option (following TCP header)
+ */
+struct tcp_opt {
+ uint8_t opt_type; /* option type */
+ uint8_t opt_len; /* option length >= TCP_OPT_LEN */
+ union tcp_opt_data {
+ uint16_t mss; /* TCP_OPT_MSS */
+ uint8_t wscale; /* TCP_OPT_WSCALE */
+ uint16_t sack[19]; /* TCP_OPT_SACK */
+ uint32_t echo; /* TCP_OPT_ECHO{REPLY} */
+ uint32_t timestamp[2]; /* TCP_OPT_TIMESTAMP */
+ uint32_t cc; /* TCP_OPT_CC{NEW,ECHO} */
+ uint8_t cksum; /* TCP_OPT_ALTSUM */
+ uint8_t md5[16]; /* TCP_OPT_MD5 */
+ uint8_t data8[TCP_OPT_LEN_MAX - TCP_OPT_LEN];
+ } opt_data;
+} __attribute__((__packed__));
+
+#ifndef __GNUC__
+# pragma pack()
+#endif
+
+#define tcp_pack_hdr(hdr, sport, dport, seq, ack, flags, win, urp) do { \
+ struct tcp_hdr *tcp_pack_p = (struct tcp_hdr *)(hdr); \
+ tcp_pack_p->th_sport = htons(sport); \
+ tcp_pack_p->th_dport = htons(dport); \
+ tcp_pack_p->th_seq = htonl(seq); \
+ tcp_pack_p->th_ack = htonl(ack); \
+ tcp_pack_p->th_x2 = 0; tcp_pack_p->th_off = 5; \
+ tcp_pack_p->th_flags = flags; \
+ tcp_pack_p->th_win = htons(win); \
+ tcp_pack_p->th_urp = htons(urp); \
+} while (0)
+
+#endif /* DNET_TCP_H */
diff --git a/ext/dnet/dnet/udp.h b/ext/dnet/dnet/udp.h
new file mode 100644
index 000000000..73839a92a
--- /dev/null
+++ b/ext/dnet/dnet/udp.h
@@ -0,0 +1,32 @@
+/*
+ * udp.h
+ *
+ * User Datagram Protocol (RFC 768).
+ *
+ * Copyright (c) 2000 Dug Song <dugsong@monkey.org>
+ *
+ * $Id: udp.h,v 1.8 2002/04/02 05:05:39 dugsong Exp $
+ */
+
+#ifndef DNET_UDP_H
+#define DNET_UDP_H
+
+#define UDP_HDR_LEN 8
+
+struct udp_hdr {
+ uint16_t uh_sport; /* source port */
+ uint16_t uh_dport; /* destination port */
+ uint16_t uh_ulen; /* udp length (including header) */
+ uint16_t uh_sum; /* udp checksum */
+};
+
+#define UDP_PORT_MAX 65535
+
+#define udp_pack_hdr(hdr, sport, dport, ulen) do { \
+ struct udp_hdr *udp_pack_p = (struct udp_hdr *)(hdr); \
+ udp_pack_p->uh_sport = htons(sport); \
+ udp_pack_p->uh_dport = htons(dport); \
+ udp_pack_p->uh_ulen = htons(ulen); \
+} while (0)
+
+#endif /* DNET_UDP_H */
diff --git a/ext/ply/CHANGES b/ext/ply/CHANGES
new file mode 100644
index 000000000..9c7334066
--- /dev/null
+++ b/ext/ply/CHANGES
@@ -0,0 +1,158 @@
+Version 1.3
+------------------------------
+12/10/02: jmdyck
+ Various minor adjustments to the code that Dave checked in today.
+ Updated test/yacc_{inf,unused}.exp to reflect today's changes.
+
+12/10/02: beazley
+ Incorporated a variety of minor bug fixes to empty production
+ handling and infinite recursion checking. Contributed by
+ Michael Dyck.
+
+12/10/02: beazley
+ Removed bogus recover() method call in yacc.restart()
+
+Version 1.2
+------------------------------
+11/27/02: beazley
+ Lexer and parser objects are now available as an attribute
+ of tokens and slices respectively. For example:
+
+ def t_NUMBER(t):
+ r'\d+'
+ print t.lexer
+
+ def p_expr_plus(t):
+ 'expr: expr PLUS expr'
+ print t.lexer
+ print t.parser
+
+ This can be used for state management (if needed).
+
+10/31/02: beazley
+ Modified yacc.py to work with Python optimize mode. To make
+ this work, you need to use
+
+ yacc.yacc(optimize=1)
+
+ Furthermore, you need to first run Python in normal mode
+ to generate the necessary parsetab.py files. After that,
+ you can use python -O or python -OO.
+
+ Note: optimized mode turns off a lot of error checking.
+ Only use when you are sure that your grammar is working.
+ Make sure parsetab.py is up to date!
+
+10/30/02: beazley
+ Added cloning of Lexer objects. For example:
+
+ import copy
+ l = lex.lex()
+ lc = copy.copy(l)
+
+ l.input("Some text")
+ lc.input("Some other text")
+ ...
+
+ This might be useful if the same "lexer" is meant to
+ be used in different contexts---or if multiple lexers
+ are running concurrently.
+
+10/30/02: beazley
+ Fixed subtle bug with first set computation and empty productions.
+ Patch submitted by Michael Dyck.
+
+10/30/02: beazley
+ Fixed error messages to use "filename:line: message" instead
+ of "filename:line. message". This makes error reporting more
+ friendly to emacs. Patch submitted by François Pinard.
+
+10/30/02: beazley
+ Improvements to parser.out file. Terminals and nonterminals
+ are sorted instead of being printed in random order.
+ Patch submitted by François Pinard.
+
+10/30/02: beazley
+ Improvements to parser.out file output. Rules are now printed
+ in a way that's easier to understand. Contributed by Russ Cox.
+
+10/30/02: beazley
+ Added 'nonassoc' associativity support. This can be used
+ to disable the chaining of operators like a < b < c.
+ To use, simply specify 'nonassoc' in the precedence table
+
+ precedence = (
+ ('nonassoc', 'LESSTHAN', 'GREATERTHAN'), # Nonassociative operators
+ ('left', 'PLUS', 'MINUS'),
+ ('left', 'TIMES', 'DIVIDE'),
+ ('right', 'UMINUS'), # Unary minus operator
+ )
+
+ Patch contributed by Russ Cox.
+
+10/30/02: beazley
+ Modified the lexer to provide optional support for Python -O and -OO
+ modes. To make this work, Python *first* needs to be run in
+ unoptimized mode. This reads the lexing information and creates a
+ file "lextab.py". Then, run lex like this:
+
+ # module foo.py
+ ...
+ ...
+ lex.lex(optimize=1)
+
+ Once the lextab file has been created, subsequent calls to
+ lex.lex() will read data from the lextab file instead of using
+ introspection. In optimized mode (-O, -OO) everything should
+ work normally despite the loss of doc strings.
+
+ To change the name of the file 'lextab.py' use the following:
+
+ lex.lex(lextab="footab")
+
+ (this creates a file footab.py)
+
+
+Version 1.1 October 25, 2001
+------------------------------
+
+10/25/01: beazley
+ Modified the table generator to produce much more compact data.
+ This should greatly reduce the size of the parsetab.py[c] file.
+ Caveat: the tables still need to be constructed so a little more
+ work is done in parsetab on import.
+
+10/25/01: beazley
+ There may be a possible bug in the cycle detector that reports errors
+ about infinite recursion. I'm having a little trouble tracking it
+ down, but if you get this problem, you can disable the cycle
+ detector as follows:
+
+ yacc.yacc(check_recursion = 0)
+
+10/25/01: beazley
+ Fixed a bug in lex.py that sometimes caused illegal characters to be
+ reported incorrectly. Reported by Sverre Jørgensen.
+
+7/8/01 : beazley
+ Added a reference to the underlying lexer object when tokens are handled by
+ functions. The lexer is available as the 'lexer' attribute. This
+ was added to provide better lexing support for languages such as Fortran
+ where certain types of tokens can't be conveniently expressed as regular
+ expressions (and where the tokenizing function may want to perform a
+ little backtracking). Suggested by Pearu Peterson.
+
+6/20/01 : beazley
+ Modified yacc() function so that an optional starting symbol can be specified.
+ For example:
+
+ yacc.yacc(start="statement")
+
+ Normally yacc always treats the first production rule as the starting symbol.
+ However, if you are debugging your grammar it may be useful to specify
+ an alternative starting symbol. Idea suggested by Rich Salz.
+
+Version 1.0 June 18, 2001
+--------------------------
+Initial public offering
+
diff --git a/ext/ply/COPYING b/ext/ply/COPYING
new file mode 100644
index 000000000..b1e3f5a26
--- /dev/null
+++ b/ext/ply/COPYING
@@ -0,0 +1,504 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+ When we speak of free software, we are referring to freedom of use,
+not price. Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard. To achieve this, non-free programs must be
+allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
+
+
diff --git a/ext/ply/README b/ext/ply/README
new file mode 100644
index 000000000..35b458d4c
--- /dev/null
+++ b/ext/ply/README
@@ -0,0 +1,249 @@
+PLY (Python Lex-Yacc) Version 1.2 (November 27, 2002)
+
+David M. Beazley
+Department of Computer Science
+University of Chicago
+Chicago, IL 60637
+beazley@cs.uchicago.edu
+
+Copyright (C) 2001 David M. Beazley
+
+$Header: /home/stever/bk/newmem2/ext/ply/README 1.1 03/06/06 14:53:34-00:00 stever@ $
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+See the file COPYING for a complete copy of the LGPL.
+
+Introduction
+============
+
+PLY is a 100% Python implementation of the common parsing tools lex
+and yacc. Although several other parsing tools are available for
+Python, there are several reasons why you might want to consider PLY:
+
+ - The tools are very closely modeled after traditional lex/yacc.
+ If you know how to use these tools in C, you will find PLY
+ to be similar.
+
+ - PLY provides *very* extensive error reporting and diagnostic
+ information to assist in parser construction. The original
+ implementation was developed for instructional purposes. As
+ a result, the system tries to identify the most common types
+ of errors made by novice users.
+
+ - PLY provides full support for empty productions, error recovery,
+ precedence specifiers, and moderately ambiguous grammars.
+
+ - Parsing is based on LR-parsing which is fast, memory efficient,
+ better suited to large grammars, and which has a number of nice
+ properties when dealing with syntax errors and other parsing problems.
+ Currently, PLY builds its parsing tables using the SLR algorithm which
+ is slightly weaker than LALR(1) used in traditional yacc.
+
+ - Like John Aycock's excellent SPARK toolkit, PLY uses Python
+ reflection to build lexers and parsers. This greatly simplifies
+ the task of parser construction since it reduces the number of files
+ and eliminates the need to run a separate lex/yacc tool before
+ running your program.
+
+ - PLY can be used to build parsers for "real" programming languages.
+ Although it is not ultra-fast due to its Python implementation,
+ PLY can be used to parse grammars consisting of several hundred
+ rules (as might be found for a language like C). The lexer and LR
+ parser are also reasonably efficient when parsing typically
+ sized programs.
+
+The original version of PLY was developed for an Introduction to
+Compilers course where students used it to build a compiler for a
+simple Pascal-like language. Their compiler had to include lexical
+analysis, parsing, type checking, type inference, and generation of
+assembly code for the SPARC processor. Because of this, the current
+implementation has been extensively tested and debugged. In addition,
+most of the API and error checking steps have been adapted to address
+common usability problems.
+
+How to Use
+==========
+
+PLY consists of two files : lex.py and yacc.py. To use the system,
+simply copy these files to your project and import them like standard
+Python modules.
+
+The file doc/ply.html contains complete documentation on how to use
+the system.
+
+The example directory contains several different examples including a
+PLY specification for ANSI C as given in K&R 2nd Ed. Note: To use
+the examples, you will need to copy the lex.py and yacc.py files to
+the example directory.
+
+A simple example is found at the end of this document
+
+Requirements
+============
+PLY requires the use of Python 2.0 or greater. It should work on
+just about any platform.
+
+Resources
+=========
+
+More information about PLY can be obtained on the PLY webpage at:
+
+ http://systems.cs.uchicago.edu/ply
+
+For a detailed overview of parsing theory, consult the excellent
+book "Compilers : Principles, Techniques, and Tools" by Aho, Sethi, and
+Ullman. The topics found in "Lex & Yacc" by Levine, Mason, and Brown
+may also be useful.
+
+Given that this is the first release, I welcome your comments on how
+to improve the current implementation. See the TODO file for things that
+still need to be done.
+
+Acknowledgments
+===============
+
+A special thanks is in order for all of the students in CS326 who
+suffered through about 25 different versions of these tools :-).
+
+Example
+=======
+
+Here is a simple example showing a PLY implementation of a calculator with variables.
+
+# -----------------------------------------------------------------------------
+# calc.py
+#
+# A simple calculator with variables.
+# -----------------------------------------------------------------------------
+
+tokens = (
+ 'NAME','NUMBER',
+ 'PLUS','MINUS','TIMES','DIVIDE','EQUALS',
+ 'LPAREN','RPAREN',
+ )
+
+# Tokens
+
+t_PLUS = r'\+'
+t_MINUS = r'-'
+t_TIMES = r'\*'
+t_DIVIDE = r'/'
+t_EQUALS = r'='
+t_LPAREN = r'\('
+t_RPAREN = r'\)'
+t_NAME = r'[a-zA-Z_][a-zA-Z0-9_]*'
+
+def t_NUMBER(t):
+ r'\d+'
+ try:
+ t.value = int(t.value)
+ except ValueError:
+ print "Integer value too large", t.value
+ t.value = 0
+ return t
+
+# Ignored characters
+t_ignore = " \t"
+
+def t_newline(t):
+ r'\n+'
+ t.lineno += t.value.count("\n")
+
+def t_error(t):
+ print "Illegal character '%s'" % t.value[0]
+ t.skip(1)
+
+# Build the lexer
+import lex
+lex.lex()
+
+# Precedence rules for the arithmetic operators
+precedence = (
+ ('left','PLUS','MINUS'),
+ ('left','TIMES','DIVIDE'),
+ ('right','UMINUS'),
+ )
+
+# dictionary of names (for storing variables)
+names = { }
+
+def p_statement_assign(t):
+ 'statement : NAME EQUALS expression'
+ names[t[1]] = t[3]
+
+def p_statement_expr(t):
+ 'statement : expression'
+ print t[1]
+
+def p_expression_binop(t):
+ '''expression : expression PLUS expression
+ | expression MINUS expression
+ | expression TIMES expression
+ | expression DIVIDE expression'''
+ if t[2] == '+' : t[0] = t[1] + t[3]
+ elif t[2] == '-': t[0] = t[1] - t[3]
+ elif t[2] == '*': t[0] = t[1] * t[3]
+ elif t[2] == '/': t[0] = t[1] / t[3]
+
+def p_expression_uminus(t):
+ 'expression : MINUS expression %prec UMINUS'
+ t[0] = -t[2]
+
+def p_expression_group(t):
+ 'expression : LPAREN expression RPAREN'
+ t[0] = t[2]
+
+def p_expression_number(t):
+ 'expression : NUMBER'
+ t[0] = t[1]
+
+def p_expression_name(t):
+ 'expression : NAME'
+ try:
+ t[0] = names[t[1]]
+ except LookupError:
+ print "Undefined name '%s'" % t[1]
+ t[0] = 0
+
+def p_error(t):
+ print "Syntax error at '%s'" % t.value
+
+import yacc
+yacc.yacc()
+
+while 1:
+ try:
+ s = raw_input('calc > ')
+ except EOFError:
+ break
+ yacc.parse(s)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ext/ply/TODO b/ext/ply/TODO
new file mode 100644
index 000000000..b2978150d
--- /dev/null
+++ b/ext/ply/TODO
@@ -0,0 +1,22 @@
+The PLY to-do list:
+
+$Header: /home/stever/bk/newmem2/ext/ply/TODO 1.1 03/06/06 14:53:34-00:00 stever@ $
+
+1. Create a Python package using distutils
+
+2. More interesting parsing examples.
+
+3. Work on the ANSI C grammar so that it can actually parse C programs. To do this,
+ some extra code needs to be added to the lexer to deal with typedef names and enumeration
+ constants.
+
+4. Get LALR(1) to work. Hard, but not impossible.
+
+5. More tests in the test directory.
+
+6. Performance improvements and cleanup in yacc.py.
+
+7. More documentation.
+
+8. Lots and lots of cleanup.
+
diff --git a/ext/ply/doc/ply.html b/ext/ply/doc/ply.html
new file mode 100644
index 000000000..2596066fe
--- /dev/null
+++ b/ext/ply/doc/ply.html
@@ -0,0 +1,1642 @@
+<html>
+<head>
+<title>PLY (Python Lex-Yacc)</title>
+</head>
+<body bgcolor="#ffffff">
+
+<h1>PLY (Python Lex-Yacc)</h1>
+
+<b>
+David M. Beazley <br>
+Department of Computer Science <br>
+University of Chicago <br>
+Chicago, IL 60637 <br>
+beazley@cs.uchicago.edu <br>
+</b>
+
+<p>
+Documentation version: $Header: /home/stever/bk/newmem2/ext/ply/doc/ply.html 1.1 03/06/06 14:53:34-00:00 stever@ $
+
+<h2>Introduction</h2>
+
+PLY is a Python-only implementation of the popular compiler
+construction tools lex and yacc. The implementation borrows ideas
+from a number of previous efforts; most notably John Aycock's SPARK
+toolkit. However, the overall flavor of the implementation is more
+closely modeled after the C version of lex and yacc. The other
+significant feature of PLY is that it provides extensive input
+validation and error reporting--much more so than other Python parsing
+tools.
+
+<p>
+Early versions of PLY were developed to support the Introduction to
+Compilers Course at the University of Chicago. In this course,
+students built a fully functional compiler for a simple Pascal-like
+language. Their compiler, implemented entirely in Python, had to
+include lexical analysis, parsing, type checking, type inference,
+nested scoping, and code generation for the SPARC processor.
+Approximately 30 different compiler implementations were completed in
+this course. Most of PLY's interface and operation has been motivated by common
+usability problems encountered by students.
+
+<p>
+Because PLY was primarily developed as an instructional tool, you will
+find it to be <em>MUCH</em> more picky about token and grammar rule
+specification than most other Python parsing tools. In part, this
+added formality is meant to catch common programming mistakes made by
+novice users. However, advanced users will also find such features to
+be useful when building complicated grammars for real programming
+languages. It should also be noted that PLY does not provide much in the way
+of bells and whistles (e.g., automatic construction of abstract syntax trees,
+tree traversal, etc.). Instead, you will find a bare-bones, yet
+fully capable lex/yacc implementation written entirely in Python.
+
+<p>
+The rest of this document assumes that you are somewhat familar with
+parsing theory, syntax directed translation, and automatic tools such
+as lex and yacc. If you are unfamilar with these topics, you will
+probably want to consult an introductory text such as "Compilers:
+Principles, Techniques, and Tools", by Aho, Sethi, and Ullman. "Lex
+and Yacc" by John Levine may also be handy.
+
+<h2>PLY Overview</h2>
+
+PLY consists of two separate tools; <tt>lex.py</tt> and
+<tt>yacc.py</tt>. <tt>lex.py</tt> is used to break input text into a
+collection of tokens specified by a collection of regular expression
+rules. <tt>yacc.py</tt> is used to recognize language syntax that has
+been specified in the form of a context free grammar. Currently,
+<tt>yacc.py</tt> uses LR parsing and generates its parsing tables
+using the SLR algorithm. LALR(1) parsing may be supported in a future
+release.
+
+<p>
+The two tools are meant to work together. Specifically,
+<tt>lex.py</tt> provides an external interface in the form of a
+<tt>token()</tt> function that returns the next valid token on the
+input stream. <tt>yacc.py</tt> calls this repeatedly to retrieve
+tokens and invoke grammar rules. The output of <tt>yacc.py</tt> is
+often an Abstract Syntax Tree (AST). However, this is entirely up to
+the user. If desired, <tt>yacc.py</tt> can also be used to implement
+simple one-pass compilers.
+
+<p>
+Like its Unix counterpart, <tt>yacc.py</tt> provides most of the
+features you expect including extensive error checking, grammar
+validation, support for empty productions, error tokens, and ambiguity
+resolution via precedence rules. The primary difference between
+<tt>yacc.py</tt> and <tt>yacc</tt> is the use of SLR parsing instead
+of LALR(1). Although this slightly restricts the types of grammars
+than can be successfully parsed, it is sufficiently powerful to handle most
+kinds of normal programming language constructs.
+
+<p>
+Finally, it is important to note that PLY relies on reflection
+(introspection) to build its lexers and parsers. Unlike traditional
+lex/yacc which require a special input file that is converted into a
+separate source file, the specifications given to PLY <em>are</em>
+valid Python programs. This means that there are no extra source
+files nor is there a special compiler construction step (e.g., running
+yacc to generate Python code for the compiler).
+
+<h2>Lex Example</h2>
+
+<tt>lex.py</tt> is used to write tokenizers. To do this, each token
+must be defined by a regular expression rule. The following file
+implements a very simple lexer for tokenizing simple integer expressions:
+
+<blockquote>
+<pre>
+# ------------------------------------------------------------
+# calclex.py
+#
+# tokenizer for a simple expression evaluator for
+# numbers and +,-,*,/
+# ------------------------------------------------------------
+import lex
+
+# List of token names. This is always required
+tokens = (
+ 'NUMBER',
+ 'PLUS',
+ 'MINUS',
+ 'TIMES',
+ 'DIVIDE',
+ 'LPAREN',
+ 'RPAREN',
+)
+
+# Regular expression rules for simple tokens
+t_PLUS = r'\+'
+t_MINUS = r'-'
+t_TIMES = r'\*'
+t_DIVIDE = r'/'
+t_LPAREN = r'\('
+t_RPAREN = r'\)'
+
+# A regular expression rule with some action code
+def t_NUMBER(t):
+ r'\d+'
+ try:
+ t.value = int(t.value)
+ except ValueError:
+ print "Line %d: Number %s is too large!" % (t.lineno,t.value)
+ t.value = 0
+ return t
+
+# Define a rule so we can track line numbers
+def t_newline(t):
+ r'\n+'
+ t.lineno += len(t.value)
+
+# A string containing ignored characters (spaces and tabs)
+t_ignore = ' \t'
+
+# Error handling rule
+def t_error(t):
+ print "Illegal character '%s'" % t.value[0]
+ t.skip(1)
+
+# Build the lexer
+lex.lex()
+
+# Test it out
+data = '''
+3 + 4 * 10
+ + -20 *2
+'''
+
+# Give the lexer some input
+lex.input(data)
+
+# Tokenize
+while 1:
+ tok = lex.token()
+ if not tok: break # No more input
+ print tok
+</pre>
+</blockquote>
+
+In the example, the <tt>tokens</tt> list defines all of the possible
+token names that can be produced by the lexer. This list is always required
+and is used to perform a variety of validation checks. Following the <tt>tokens</tt>
+list, regular expressions are written for each token. Each of these
+rules are defined by making declarations with a special prefix <tt>t_</tt> to indicate that it
+defines a token. For simple tokens, the regular expression can
+be specified as strings such as this (note: Python raw strings are used since they are the
+most convenient way to write regular expression strings):
+
+<blockquote>
+<pre>
+t_PLUS = r'\+'
+</pre>
+</blockquote>
+
+In this case, the name following the <tt>t_</tt> must exactly match one of the
+names supplied in <tt>tokens</tt>. If some kind of action needs to be performed,
+a token rule can be specified as a function. For example:
+
+<blockquote>
+<pre>
+def t_NUMBER(t):
+ r'\d+'
+ try:
+ t.value = int(t.value)
+ except ValueError:
+ print "Number %s is too large!" % t.value
+ t.value = 0
+ return t
+</pre>
+</blockquote>
+
+In this case, the regular expression rule is specified in the function documentation string.
+The function always takes a single argument which is an instance of
+<tt>LexToken</tt>. This object has attributes of <tt>t.type</tt> which is the token type,
+<tt>t.value</tt> which is the lexeme, and <tt>t.lineno</tt> which is the current line number.
+By default, <tt>t.type</tt> is set to the name following the <tt>t_</tt> prefix. The action
+function can modify the contents of the <tt>LexToken</tt> object as appropriate. However,
+when it is done, the resulting token should be returned. If no value is returned by the action
+function, the token is simply discarded and the next token read.
+
+<p>
+The rule <tt>t_newline()</tt> illustrates a regular expression rule
+for a discarded token. In this case, a rule is written to match
+newlines so that proper line number tracking can be performed.
+By returning no value, the function causes the newline character to be
+discarded.
+
+<p>
+The special <tt>t_ignore</tt> rule is reserved by <tt>lex.py</tt> for characters
+that should be completely ignored in the input stream.
+Usually this is used to skip over whitespace and other non-essential characters.
+Although it is possible to define a regular expression rule for whitespace in a manner
+similar to <tt>t_newline()</tt>, the use of <tt>t_ignore</tt> provides substantially better
+lexing performance because it is handled as a special case and is checked in a much
+more efficient manner than the normal regular expression rules.
+
+<p>
+Finally, the <tt>t_error()</tt>
+function is used to handle lexing errors that occur when illegal
+characters are detected. In this case, the <tt>t.value</tt> attribute contains the
+rest of the input string that has not been tokenized. In the example, we simply print
+the offending character and skip ahead one character by calling <tt>t.skip(1)</tt>.
+
+<p>
+To build the lexer, the function <tt>lex.lex()</tt> is used. This function
+uses Python reflection (or introspection) to read the the regular expression rules
+out of the calling context and build the lexer. Once the lexer has been built, two functions can
+be used to control the lexer.
+
+<ul>
+<li><tt>lex.input(data)</tt>. Reset the lexer and store a new input string.
+<li><tt>lex.token()</tt>. Return the next token. Returns a special <tt>LexToken</tt> instance on success or
+None if the end of the input text has been reached.
+</ul>
+
+The code at the bottom of the example shows how the lexer is actually used. When executed,
+the following output will be produced:
+
+<blockquote>
+<pre>
+$ python example.py
+LexToken(NUMBER,3,2)
+LexToken(PLUS,'+',2)
+LexToken(NUMBER,4,2)
+LexToken(TIMES,'*',2)
+LexToken(NUMBER,10,2)
+LexToken(PLUS,'+',3)
+LexToken(MINUS,'-',3)
+LexToken(NUMBER,20,3)
+LexToken(TIMES,'*',3)
+LexToken(NUMBER,2,3)
+</pre>
+</blockquote>
+
+<h2>Lex Implementation Notes</h2>
+
+<ul>
+<li><tt>lex.py</tt> uses the <tt>re</tt> module to do its patten matching. When building the master regular expression,
+rules are added in the following order:
+<p>
+<ol>
+<li>All tokens defined by functions are added in the same order as they appear in the lexer file.
+<li>Tokens defined by strings are added by sorting them in order of decreasing regular expression length (longer expressions
+are added first).
+</ol>
+<p>
+Without this ordering, it can be difficult to correctly match certain types of tokens. For example, if you
+wanted to have separate tokens for "=" and "==", you need to make sure that "==" is checked first. By sorting regular
+expressions in order of decreasing length, this problem is solved for rules defined as strings. For functions,
+the order can be explicitly controlled since rules appearing first are checked first.
+
+<P>
+<li>The lexer requires input to be supplied as a single input string. Since most machines have more than enough memory, this
+rarely presents a performance concern. However, it means that the lexer currently can't be used with streaming data
+such as open files or sockets. This limitation is primarily a side-effect of using the <tt>re</tt> module.
+
+<p>
+<li>
+To handle reserved words, it is usually easier to just match an identifier and do a special name lookup in a function
+like this:
+
+<blockquote>
+<pre>
+reserved = {
+ 'if' : 'IF',
+ 'then' : 'THEN',
+ 'else' : 'ELSE',
+ 'while' : 'WHILE',
+ ...
+}
+
+def t_ID(t):
+ r'[a-zA-Z_][a-zA-Z_0-9]*'
+ t.type = reserved.get(t.value,'ID') # Check for reserved words
+ return t
+</pre>
+</blockquote>
+
+<p>
+<li>The lexer requires tokens to be defined as class instances with <tt>t.type</tt>, <tt>t.value</tt>, and <tt>t.lineno</tt>
+attributes. By default, tokens are created as instances of the <tt>LexToken</tt> class defined internally to <tt>lex.py</tt>.
+If desired, you can create new kinds of tokens provided that they have the three required attributes. However,
+in practice, it is probably safer to stick with the default.
+
+<p>
+<li>The only safe attribute for assigning token properties is <tt>t.value</tt>. In some cases, you may want to attach
+a number of different properties to a token (e.g., symbol table entries for identifiers). To do this, replace <tt>t.value</tt>
+with a tuple or class instance. For example:
+
+<blockquote>
+<pre>
+def t_ID(t):
+ ...
+ # For identifiers, create a (lexeme, symtab) tuple
+ t.value = (t.value, symbol_lookup(t.value))
+ ...
+ return t
+</pre>
+</blockquote>
+
+Although allowed, do NOT assign additional attributes to the token object. For example,
+<blockquote>
+<pre>
+def t_ID(t):
+ ...
+ # Bad implementation of above
+ t.symtab = symbol_lookup(t.value)
+ ...
+</pre>
+</blockquote>
+
+The reason you don't want to do this is that the <tt>yacc.py</tt>
+module only provides public access to the <tt>t.value</tt> attribute of each token.
+Therefore, any other attributes you assign are inaccessible (if you are familiar
+with the internals of C lex/yacc, <tt>t.value</tt> is the same as <tt>yylval.tok</tt>).
+
+<p>
+<li>To track line numbers, the lexer internally maintains a line
+number variable. Each token automatically gets the value of the
+current line number in the <tt>t.lineno</tt> attribute. To modify the
+current line number, simply change the <tt>t.lineno</tt> attribute
+in a function rule (as previously shown for
+<tt>t_newline()</tt>). Even if the resulting token is discarded,
+changes to the line number remain in effect for subsequent tokens.
+
+<p>
+<li>To support multiple scanners in the same application, the <tt>lex.lex()</tt> function
+actually returns a special <tt>Lexer</tt> object. This object has two methods
+<tt>input()</tt> and <tt>token()</tt> that can be used to supply input and get tokens. For example:
+
+<blockquote>
+<pre>
+lexer = lex.lex()
+lexer.input(sometext)
+while 1:
+ tok = lexer.token()
+ if not tok: break
+ print tok
+</pre>
+</blockquote>
+
+The functions <tt>lex.input()</tt> and <tt>lex.token()</tt> are bound to the <tt>input()</tt>
+and <tt>token()</tt> methods of the last lexer created by the lex module.
+
+
+<p>
+<li>To reduce compiler startup time and improve performance, the lexer can be built in optimized mode as follows:
+
+<blockquote>
+<pre>
+lex.lex(optimize=1)
+</pre>
+</blockquote>
+
+When used, most error checking and validation is disabled. This provides a slight performance
+gain while tokenizing and tends to chop a few tenths of a second off startup time. Since it disables
+error checking, this mode is not the default and is not recommended during development. However, once
+you have your compiler fully working, it is usually safe to disable the error checks.
+
+<p>
+<li>You can enable some additional debugging by building the lexer like this:
+
+<blockquote>
+<pre>
+lex.lex(debug=1)
+</pre>
+</blockquote>
+
+<p>
+<li>To help you debug your lexer, <tt>lex.py</tt> comes with a simple main program which will either
+tokenize input read from standard input or from a file. To use it, simply put this in your lexer:
+
+<blockquote>
+<pre>
+if __name__ == '__main__':
+ lex.runmain()
+</pre>
+</blockquote>
+
+Then, run you lexer as a main program such as <tt>python mylex.py</tt>
+
+<p>
+<li>Since the lexer is written entirely in Python, its performance is
+largely determined by that of the Python <tt>re</tt> module. Although
+the lexer has been written to be as efficient as possible, it's not
+blazingly fast when used on very large input files. Sorry. If
+performance is concern, you might consider upgrading to the most
+recent version of Python, creating a hand-written lexer, or offloading
+the lexer into a C extension module. In defense of <tt>lex.py</tt>,
+it's performance is not <em>that</em> bad when used on reasonably
+sized input files. For instance, lexing a 4700 line C program with
+32000 input tokens takes about 20 seconds on a 200 Mhz PC. Obviously,
+it will run much faster on a more speedy machine.
+
+</ul>
+
+<h2>Parsing basics</h2>
+
+<tt>yacc.py</tt> is used to parse language syntax. Before showing an
+example, there are a few important bits of background that must be
+mentioned. First, <tt>syntax</tt> is usually specified in terms of a
+context free grammar (CFG). For example, if you wanted to parse
+simple arithmetic expressions, you might first write an unambiguous
+grammar specification like this:
+
+<blockquote>
+<pre>
+expression : expression + term
+ | expression - term
+ | term
+
+term : term * factor
+ | term / factor
+ | factor
+
+factor : NUMBER
+ | ( expression )
+</pre>
+</blockquote>
+
+Next, the semantic behavior of a language is often specified using a
+technique known as syntax directed translation. In syntax directed
+translation, attributes are attached to each symbol in a given grammar
+rule along with an action. Whenever a particular grammar rule is
+recognized, the action describes what to do. For example, given the
+expression grammar above, you might write the specification for a
+simple calculator like this:
+
+<blockquote>
+<pre>
+Grammar Action
+-------------------------------- --------------------------------------------
+expression0 : expression1 + term expression0.val = expression1.val + term.val
+ | expression1 - term expression0.val = expression1.val - term.val
+ | term expression0.val = term.val
+
+term0 : term1 * factor term0.val = term1.val * factor.val
+ | term1 / factor term0.val = term1.val / factor.val
+ | factor term0.val = factor.val
+
+factor : NUMBER factor.val = int(NUMBER.lexval)
+ | ( expression ) factor.val = expression.val
+</pre>
+</blockquote>
+
+Finally, Yacc uses a parsing technique known as LR-parsing or shift-reduce parsing. LR parsing is a
+bottom up technique that tries to recognize the right-hand-side of various grammar rules.
+Whenever a valid right-hand-side is found in the input, the appropriate action code is triggered and the
+grammar symbols are replaced by the grammar symbol on the left-hand-side.
+
+<p>
+LR parsing is commonly implemented by shifting grammar symbols onto a stack and looking at the stack and the next
+input token for patterns. The details of the algorithm can be found in a compiler text, but the
+following example illustrates the steps that are performed if you wanted to parse the expression
+<tt>3 + 5 * (10 - 20)</tt> using the grammar defined above:
+
+<blockquote>
+<pre>
+Step Symbol Stack Input Tokens Action
+---- --------------------- --------------------- -------------------------------
+1 $ 3 + 5 * ( 10 - 20 )$ Shift 3
+2 $ 3 + 5 * ( 10 - 20 )$ Reduce factor : NUMBER
+3 $ factor + 5 * ( 10 - 20 )$ Reduce term : factor
+4 $ term + 5 * ( 10 - 20 )$ Reduce expr : term
+5 $ expr + 5 * ( 10 - 20 )$ Shift +
+6 $ expr + 5 * ( 10 - 20 )$ Shift 5
+7 $ expr + 5 * ( 10 - 20 )$ Reduce factor : NUMBER
+8 $ expr + factor * ( 10 - 20 )$ Reduce term : factor
+9 $ expr + term * ( 10 - 20 )$ Shift *
+10 $ expr + term * ( 10 - 20 )$ Shift (
+11 $ expr + term * ( 10 - 20 )$ Shift 10
+12 $ expr + term * ( 10 - 20 )$ Reduce factor : NUMBER
+13 $ expr + term * ( factor - 20 )$ Reduce term : factor
+14 $ expr + term * ( term - 20 )$ Reduce expr : term
+15 $ expr + term * ( expr - 20 )$ Shift -
+16 $ expr + term * ( expr - 20 )$ Shift 20
+17 $ expr + term * ( expr - 20 )$ Reduce factor : NUMBER
+18 $ expr + term * ( expr - factor )$ Reduce term : factor
+19 $ expr + term * ( expr - term )$ Reduce expr : expr - term
+20 $ expr + term * ( expr )$ Shift )
+21 $ expr + term * ( expr ) $ Reduce factor : (expr)
+22 $ expr + term * factor $ Reduce term : term * factor
+23 $ expr + term $ Reduce expr : expr + term
+24 $ expr $ Reduce expr
+25 $ $ Success!
+</pre>
+</blockquote>
+
+When parsing the expression, an underlying state machine and the current input token determine what to do next.
+If the next token looks like part of a valid grammar rule (based on other items on the stack), it is generally shifted
+onto the stack. If the top of the stack contains a valid right-hand-side of a grammar rule, it is
+usually "reduced" and the symbols replaced with the symbol on the left-hand-side. When this reduction occurs, the
+appropriate action is triggered (if defined). If the input token can't be shifted and the top of stack doesn't match
+any grammar rules, a syntax error has occurred and the parser must take some kind of recovery step (or bail out).
+
+<p>
+It is important to note that the underlying implementation is actually built around a large finite-state machine
+and some tables. The construction of these tables is quite complicated and beyond the scope of this discussion.
+However, subtle details of this process explain why, in the example above, the parser chooses to shift a token
+onto the stack in step 9 rather than reducing the rule <tt>expr : expr + term</tt>.
+
+<h2>Yacc example</h2>
+
+Suppose you wanted to make a grammar for simple arithmetic expressions as previously described. Here is
+how you would do it with <tt>yacc.py</tt>:
+
+<blockquote>
+<pre>
+# Yacc example
+
+import yacc
+
+# Get the token map from the lexer. This is required.
+from calclex import tokens
+
+def p_expression_plus(t):
+ 'expression : expression PLUS term'
+ t[0] = t[1] + t[3]
+
+def p_expression_minus(t):
+ 'expression : expression MINUS term'
+ t[0] = t[1] - t[3]
+
+def p_expression_term(t):
+ 'expression : term'
+ t[0] = t[1]
+
+def p_term_times(t):
+ 'term : term TIMES factor'
+ t[0] = t[1] * t[3]
+
+def p_term_div(t):
+ 'term : term DIVIDE factor'
+ t[0] = t[1] / t[3]
+
+def p_term_factor(t):
+ 'term : factor'
+ t[0] = t[1]
+
+def p_factor_num(t):
+ 'factor : NUMBER'
+ t[0] = t[1]
+
+def p_factor_expr(t):
+ 'factor : LPAREN expression RPAREN'
+ t[0] = t[2]
+
+# Error rule for syntax errors
+def p_error(t):
+ print "Syntax error in input!"
+
+# Build the parser
+yacc.yacc()
+
+while 1:
+ try:
+ s = raw_input('calc > ')
+ except EOFError:
+ break
+ if not s: continue
+ result = yacc.parse(s)
+ print result
+</pre>
+</blockquote>
+
+In this example, each grammar rule is defined by a Python function where the docstring to that function contains the
+appropriate context-free grammar specification (an idea borrowed from John Aycock's SPARK toolkit). Each function accepts a single
+argument <tt>t</tt> that is a sequence containing the values of each grammar symbol in the corresponding rule. The values of
+<tt>t[i]</tt> are mapped to grammar symbols as shown here:
+
+<blockquote>
+<pre>
+def p_expression_plus(t):
+ 'expression : expression PLUS term'
+ # ^ ^ ^ ^
+ # t[0] t[1] t[2] t[3]
+
+ t[0] = t[1] + t[3]
+</pre>
+</blockquote>
+
+For tokens, the "value" in the corresponding <tt>t[i]</tt> is the
+<em>same</em> as the value of the <tt>t.value</tt> attribute assigned
+in the lexer module. For non-terminals, the value is determined by
+whatever is placed in <tt>t[0]</tt> when rules are reduced. This
+value can be anything at all. However, it probably most common for
+the value to be a simple Python type, a tuple, or an instance. In this example, we
+are relying on the fact that the <tt>NUMBER</tt> token stores an integer value in its value
+field. All of the other rules simply perform various types of integer operations and store
+the result.
+
+<p>
+The first rule defined in the yacc specification determines the starting grammar
+symbol (in this case, a rule for <tt>expression</tt> appears first). Whenever
+the starting rule is reduced by the parser and no more input is available, parsing
+stops and the final value is returned (this value will be whatever the top-most rule
+placed in <tt>t[0]</tt>).
+
+<p>The <tt>p_error(t)</tt> rule is defined to catch syntax errors. See the error handling section
+below for more detail.
+
+<p>
+To build the parser, call the <tt>yacc.yacc()</tt> function. This function
+looks at the module and attempts to construct all of the LR parsing tables for the grammar
+you have specified. The first time <tt>yacc.yacc()</tt> is invoked, you will get a message
+such as this:
+
+<blockquote>
+<pre>
+$ python calcparse.py
+yacc: Generating SLR parsing table...
+calc >
+</pre>
+</blockquote>
+
+Since table construction is relatively expensive (especially for large
+grammars), the resulting parsing table is written to the current
+directory in a file called <tt>parsetab.py</tt>. In addition, a
+debugging file called <tt>parser.out</tt> is created. On subsequent
+executions, <tt>yacc</tt> will reload the table from
+<tt>parsetab.py</tt> unless it has detected a change in the underlying
+grammar (in which case the tables and <tt>parsetab.py</tt> file are
+regenerated).
+
+<p>
+If any errors are detected in your grammar specification, <tt>yacc.py</tt> will produce
+diagnostic messages and possibly raise an exception. Some of the errors that can be detected include:
+
+<ul>
+<li>Duplicated function names (if more than one rule function have the same name in the grammar file).
+<li>Shift/reduce and reduce/reduce conflicts generated by ambiguous grammars.
+<li>Badly specified grammar rules.
+<li>Infinite recursion (rules that can never terminate).
+<li>Unused rules and tokens
+<li>Undefined rules and tokens
+</ul>
+
+The next few sections now discuss a few finer points of grammar construction.
+
+<h2>Combining Grammar Rule Functions</h2>
+
+When grammar rules are similar, they can be combined into a single function.
+For example, consider the two rules in our earlier example:
+
+<blockquote>
+<pre>
+def p_expression_plus(t):
+ 'expression : expression PLUS term'
+ t[0] = t[1] + t[3]
+
+def p_expression_minus(t):
+ 'expression : expression MINUS term'
+ t[0] = t[1] - t[3]
+</pre>
+</blockquote>
+
+Instead of writing two functions, you might write a single function like this:
+
+<blockquote>
+<pre>
+def p_expression(t):
+ '''expression : expression PLUS term
+ | expression MINUS term'''
+ if t[2] == '+':
+ t[0] = t[1] + t[3]
+ elif t[2] == '-':
+ t[0] = t[1] - t[3]
+</pre>
+</blockquote>
+
+In general, the doc string for any given function can contain multiple grammar rules. So, it would
+have also been legal (although possibly confusing) to write this:
+
+<blockquote>
+<pre>
+def p_binary_operators(t):
+ '''expression : expression PLUS term
+ | expression MINUS term
+ term : term TIMES factor
+ | term DIVIDE factor'''
+ if t[2] == '+':
+ t[0] = t[1] + t[3]
+ elif t[2] == '-':
+ t[0] = t[1] - t[3]
+ elif t[2] == '*':
+ t[0] = t[1] * t[3]
+ elif t[2] == '/':
+ t[0] = t[1] / t[3]
+</pre>
+</blockquote>
+
+When combining grammar rules into a single function, it is usually a good idea for all of the rules to have
+a similar structure (e.g., the same number of terms). Otherwise, the corresponding action code may be more
+complicated than necessary.
+
+<h2>Empty Productions</h2>
+
+<tt>yacc.py</tt> can handle empty productions by defining a rule like this:
+
+<blockquote>
+<pre>
+def p_empty(t):
+ 'empty :'
+ pass
+</pre>
+</blockquote>
+
+Now to use the empty production, simply use 'empty' as a symbol. For example:
+
+<blockquote>
+<pre>
+def p_optitem(t):
+ 'optitem : item'
+ ' | empty'
+ ...
+</pre>
+</blockquote>
+
+<h2>Dealing With Ambiguous Grammars</h2>
+
+The expression grammar given in the earlier example has been written in a special format to eliminate ambiguity.
+However, in many situations, it is extremely difficult or awkward to write grammars in this format. A
+much more natural way to express the grammar is in a more compact form like this:
+
+<blockquote>
+<pre>
+expression : expression PLUS expression
+ | expression MINUS expression
+ | expression TIMES expression
+ | expression DIVIDE expression
+ | LPAREN expression RPAREN
+ | NUMBER
+</pre>
+</blockquote>
+
+Unfortunately, this grammar specification is ambiguous. For example, if you are parsing the string
+"3 * 4 + 5", there is no way to tell how the operators are supposed to be grouped.
+For example, does this expression mean "(3 * 4) + 5" or is it "3 * (4+5)"?
+
+<p>
+When an ambiguous grammar is given to <tt>yacc.py</tt> it will print messages about "shift/reduce conflicts"
+or a "reduce/reduce conflicts". A shift/reduce conflict is caused when the parser generator can't decide
+whether or not to reduce a rule or shift a symbol on the parsing stack. For example, consider
+the string "3 * 4 + 5" and the internal parsing stack:
+
+<blockquote>
+<pre>
+Step Symbol Stack Input Tokens Action
+---- --------------------- --------------------- -------------------------------
+1 $ 3 * 4 + 5$ Shift 3
+2 $ 3 * 4 + 5$ Reduce : expression : NUMBER
+3 $ expr * 4 + 5$ Shift *
+4 $ expr * 4 + 5$ Shift 4
+5 $ expr * 4 + 5$ Reduce: expression : NUMBER
+6 $ expr * expr + 5$ SHIFT/REDUCE CONFLICT ????
+</pre>
+</blockquote>
+
+In this case, when the parser reaches step 6, it has two options. One is the reduce the
+rule <tt>expr : expr * expr</tt> on the stack. The other option is to shift the
+token <tt>+</tt> on the stack. Both options are perfectly legal from the rules
+of the context-free-grammar.
+
+<p>
+By default, all shift/reduce conflicts are resolved in favor of shifting. Therefore, in the above
+example, the parser will always shift the <tt>+</tt> instead of reducing. Although this
+strategy works in many cases (including the ambiguous if-then-else), it is not enough for arithmetic
+expressions. In fact, in the above example, the decision to shift <tt>+</tt> is completely wrong---we should have
+reduced <tt>expr * expr</tt> since multiplication has higher precedence than addition.
+
+<p>To resolve ambiguity, especially in expression grammars, <tt>yacc.py</tt> allows individual
+tokens to be assigned a precedence level and associativity. This is done by adding a variable
+<tt>precedence</tt> to the grammar file like this:
+
+<blockquote>
+<pre>
+precedence = (
+ ('left', 'PLUS', 'MINUS'),
+ ('left', 'TIMES', 'DIVIDE'),
+)
+</pre>
+</blockquote>
+
+This declaration specifies that <tt>PLUS</tt>/<tt>MINUS</tt> have
+the same precedence level and are left-associative and that
+<tt>TIMES</tt>/<tt>DIVIDE</tt> have the same precedence and are left-associative.
+Furthermore, the declaration specifies that <tt>TIMES</tt>/<tt>DIVIDE</tt> have higher
+precedence than <tt>PLUS</tt>/<tt>MINUS</tt> (since they appear later in the
+precedence specification).
+
+<p>
+The precedence specification is used to attach a numerical precedence value and associativity direction
+to each grammar rule. This is always determined by the precedence of the right-most terminal symbol. Therefore,
+if PLUS/MINUS had a precedence of 1 and TIMES/DIVIDE had a precedence of 2, the grammar rules
+would have precedence values as follows:
+
+<blockquote>
+<pre>
+expression : expression PLUS expression # prec = 1, left
+ | expression MINUS expression # prec = 1, left
+ | expression TIMES expression # prec = 2, left
+ | expression DIVIDE expression # prec = 2, left
+ | LPAREN expression RPAREN # prec = unknown
+ | NUMBER # prec = unknown
+</pre>
+</blockquote>
+
+When shift/reduce conflicts are encountered, the parser generator resolves the conflict by
+looking at the precedence rules and associativity specifiers.
+
+<p>
+<ol>
+<li>If the current token has higher precedence, it is shifted.
+<li>If the grammar rule on the stack has higher precedence, the rule is reduced.
+<li>If the current token and the grammar rule have the same precedence, the
+rule is reduced for left associativity, whereas the token is shifted for right associativity.
+<li>If nothing is known about the precedence, shift/reduce conflicts are resolved in
+favor of shifting (the default).
+</ol>
+
+<p>
+When shift/reduce conflicts are resolved using the first three techniques (with the help of
+precedence rules), <tt>yacc.py</tt> will report no errors or conflicts in the grammar.
+
+<p>
+One problem with the precedence specifier technique is that it is sometimes necessary to
+change the precedence of an operator in certain contents. For example, consider a unary-minus operator
+in "3 + 4 * -5". Normally, unary minus has a very high precedence--being evaluated before the multiply.
+However, in our precedence specifier, MINUS has a lower precedence than TIMES. To deal with this,
+precedence rules can be given for fictitious tokens like this:
+
+<blockquote>
+<pre>
+precedence = (
+ ('left', 'PLUS', 'MINUS'),
+ ('left', 'TIMES', 'DIVIDE'),
+ ('right', 'UMINUS'), # Unary minus operator
+)
+</pre>
+</blockquote>
+
+Now, in the grammar file, we can write our unary minus rule like this:
+
+<blockquote>
+<pre>
+def p_expr_uminus(t):
+ 'expression : MINUS expression %prec UMINUS'
+ t[0] = -t[2]
+</pre>
+</blockquote>
+
+In this case, <tt>%prec UMINUS</tt> overrides the default rule precedence--setting it to that
+of UMINUS in the precedence specifier.
+
+<p>
+It is also possible to specify non-associativity in the <tt>precedence</tt> table. This would
+be used when you <em>don't</em> want operations to chain together. For example, suppose
+you wanted to support a comparison operators like <tt>&lt;</tt> and <tt>&gt;</tt> but you didn't want to allow
+combinations like <tt>a &lt; b &lt; c</tt>. To do this, simply specify a rule like this:
+
+<blockquote>
+<pre>
+precedence = (
+ ('nonassoc', 'LESSTHAN', 'GREATERTHAN'), # Nonassociative operators
+ ('left', 'PLUS', 'MINUS'),
+ ('left', 'TIMES', 'DIVIDE'),
+ ('right', 'UMINUS'), # Unary minus operator
+)
+</pre>
+</blockquote>
+
+<p>
+Reduce/reduce conflicts are caused when there are multiple grammar
+rules that can be applied to a given set of symbols. This kind of
+conflict is almost always bad and is always resolved by picking the
+rule that appears first in the grammar file. Reduce/reduce conflicts
+are almost always caused when different sets of grammar rules somehow
+generate the same set of symbols. For example:
+
+<blockquote>
+<pre>
+assignment : ID EQUALS NUMBER
+ | ID EQUALS expression
+
+expression : expression PLUS expression
+ | expression MINUS expression
+ | expression TIMES expression
+ | expression DIVIDE expression
+ | LPAREN expression RPAREN
+ | NUMBER
+</pre>
+</blockquote>
+
+In this case, a reduce/reduce conflict exists between these two rules:
+
+<blockquote>
+<pre>
+assignment : ID EQUALS NUMBER
+expression : NUMBER
+</pre>
+</blockquote>
+
+For example, if you wrote "a = 5", the parser can't figure out if this
+is supposed to reduced as <tt>assignment : ID EQUALS NUMBER</tt> or
+whether it's supposed to reduce the 5 as an expression and then reduce
+the rule <tt>assignment : ID EQUALS expression</tt>.
+
+<h2>The parser.out file</h2>
+
+Tracking down shift/reduce and reduce/reduce conflicts is one of the finer pleasures of using an LR
+parsing algorithm. To assist in debugging, <tt>yacc.py</tt> creates a debugging file called
+'parser.out' when it generates the parsing table. The contents of this file look like the following:
+
+<blockquote>
+<pre>
+Unused terminals:
+
+
+Grammar
+
+Rule 1 expression -> expression PLUS expression
+Rule 2 expression -> expression MINUS expression
+Rule 3 expression -> expression TIMES expression
+Rule 4 expression -> expression DIVIDE expression
+Rule 5 expression -> NUMBER
+Rule 6 expression -> LPAREN expression RPAREN
+
+Terminals, with rules where they appear
+
+TIMES : 3
+error :
+MINUS : 2
+RPAREN : 6
+LPAREN : 6
+DIVIDE : 4
+PLUS : 1
+NUMBER : 5
+
+Nonterminals, with rules where they appear
+
+expression : 1 1 2 2 3 3 4 4 6 0
+
+
+Parsing method: SLR
+
+
+state 0
+
+ S' -> . expression
+ expression -> . expression PLUS expression
+ expression -> . expression MINUS expression
+ expression -> . expression TIMES expression
+ expression -> . expression DIVIDE expression
+ expression -> . NUMBER
+ expression -> . LPAREN expression RPAREN
+
+ NUMBER shift and go to state 3
+ LPAREN shift and go to state 2
+
+
+state 1
+
+ S' -> expression .
+ expression -> expression . PLUS expression
+ expression -> expression . MINUS expression
+ expression -> expression . TIMES expression
+ expression -> expression . DIVIDE expression
+
+ PLUS shift and go to state 6
+ MINUS shift and go to state 5
+ TIMES shift and go to state 4
+ DIVIDE shift and go to state 7
+
+
+state 2
+
+ expression -> LPAREN . expression RPAREN
+ expression -> . expression PLUS expression
+ expression -> . expression MINUS expression
+ expression -> . expression TIMES expression
+ expression -> . expression DIVIDE expression
+ expression -> . NUMBER
+ expression -> . LPAREN expression RPAREN
+
+ NUMBER shift and go to state 3
+ LPAREN shift and go to state 2
+
+
+state 3
+
+ expression -> NUMBER .
+
+ $ reduce using rule 5
+ PLUS reduce using rule 5
+ MINUS reduce using rule 5
+ TIMES reduce using rule 5
+ DIVIDE reduce using rule 5
+ RPAREN reduce using rule 5
+
+
+state 4
+
+ expression -> expression TIMES . expression
+ expression -> . expression PLUS expression
+ expression -> . expression MINUS expression
+ expression -> . expression TIMES expression
+ expression -> . expression DIVIDE expression
+ expression -> . NUMBER
+ expression -> . LPAREN expression RPAREN
+
+ NUMBER shift and go to state 3
+ LPAREN shift and go to state 2
+
+
+state 5
+
+ expression -> expression MINUS . expression
+ expression -> . expression PLUS expression
+ expression -> . expression MINUS expression
+ expression -> . expression TIMES expression
+ expression -> . expression DIVIDE expression
+ expression -> . NUMBER
+ expression -> . LPAREN expression RPAREN
+
+ NUMBER shift and go to state 3
+ LPAREN shift and go to state 2
+
+
+state 6
+
+ expression -> expression PLUS . expression
+ expression -> . expression PLUS expression
+ expression -> . expression MINUS expression
+ expression -> . expression TIMES expression
+ expression -> . expression DIVIDE expression
+ expression -> . NUMBER
+ expression -> . LPAREN expression RPAREN
+
+ NUMBER shift and go to state 3
+ LPAREN shift and go to state 2
+
+
+state 7
+
+ expression -> expression DIVIDE . expression
+ expression -> . expression PLUS expression
+ expression -> . expression MINUS expression
+ expression -> . expression TIMES expression
+ expression -> . expression DIVIDE expression
+ expression -> . NUMBER
+ expression -> . LPAREN expression RPAREN
+
+ NUMBER shift and go to state 3
+ LPAREN shift and go to state 2
+
+
+state 8
+
+ expression -> LPAREN expression . RPAREN
+ expression -> expression . PLUS expression
+ expression -> expression . MINUS expression
+ expression -> expression . TIMES expression
+ expression -> expression . DIVIDE expression
+
+ RPAREN shift and go to state 13
+ PLUS shift and go to state 6
+ MINUS shift and go to state 5
+ TIMES shift and go to state 4
+ DIVIDE shift and go to state 7
+
+
+state 9
+
+ expression -> expression TIMES expression .
+ expression -> expression . PLUS expression
+ expression -> expression . MINUS expression
+ expression -> expression . TIMES expression
+ expression -> expression . DIVIDE expression
+
+ $ reduce using rule 3
+ PLUS reduce using rule 3
+ MINUS reduce using rule 3
+ TIMES reduce using rule 3
+ DIVIDE reduce using rule 3
+ RPAREN reduce using rule 3
+
+ ! PLUS [ shift and go to state 6 ]
+ ! MINUS [ shift and go to state 5 ]
+ ! TIMES [ shift and go to state 4 ]
+ ! DIVIDE [ shift and go to state 7 ]
+
+state 10
+
+ expression -> expression MINUS expression .
+ expression -> expression . PLUS expression
+ expression -> expression . MINUS expression
+ expression -> expression . TIMES expression
+ expression -> expression . DIVIDE expression
+
+ $ reduce using rule 2
+ PLUS reduce using rule 2
+ MINUS reduce using rule 2
+ RPAREN reduce using rule 2
+ TIMES shift and go to state 4
+ DIVIDE shift and go to state 7
+
+ ! TIMES [ reduce using rule 2 ]
+ ! DIVIDE [ reduce using rule 2 ]
+ ! PLUS [ shift and go to state 6 ]
+ ! MINUS [ shift and go to state 5 ]
+
+state 11
+
+ expression -> expression PLUS expression .
+ expression -> expression . PLUS expression
+ expression -> expression . MINUS expression
+ expression -> expression . TIMES expression
+ expression -> expression . DIVIDE expression
+
+ $ reduce using rule 1
+ PLUS reduce using rule 1
+ MINUS reduce using rule 1
+ RPAREN reduce using rule 1
+ TIMES shift and go to state 4
+ DIVIDE shift and go to state 7
+
+ ! TIMES [ reduce using rule 1 ]
+ ! DIVIDE [ reduce using rule 1 ]
+ ! PLUS [ shift and go to state 6 ]
+ ! MINUS [ shift and go to state 5 ]
+
+state 12
+
+ expression -> expression DIVIDE expression .
+ expression -> expression . PLUS expression
+ expression -> expression . MINUS expression
+ expression -> expression . TIMES expression
+ expression -> expression . DIVIDE expression
+
+ $ reduce using rule 4
+ PLUS reduce using rule 4
+ MINUS reduce using rule 4
+ TIMES reduce using rule 4
+ DIVIDE reduce using rule 4
+ RPAREN reduce using rule 4
+
+ ! PLUS [ shift and go to state 6 ]
+ ! MINUS [ shift and go to state 5 ]
+ ! TIMES [ shift and go to state 4 ]
+ ! DIVIDE [ shift and go to state 7 ]
+
+state 13
+
+ expression -> LPAREN expression RPAREN .
+
+ $ reduce using rule 6
+ PLUS reduce using rule 6
+ MINUS reduce using rule 6
+ TIMES reduce using rule 6
+ DIVIDE reduce using rule 6
+ RPAREN reduce using rule 6
+</pre>
+</blockquote>
+
+In the file, each state of the grammar is described. Within each state the "." indicates the current
+location of the parse within any applicable grammar rules. In addition, the actions for each valid
+input token are listed. When a shift/reduce or reduce/reduce conflict arises, rules <em>not</em> selected
+are prefixed with an !. For example:
+
+<blockquote>
+<pre>
+ ! TIMES [ reduce using rule 2 ]
+ ! DIVIDE [ reduce using rule 2 ]
+ ! PLUS [ shift and go to state 6 ]
+ ! MINUS [ shift and go to state 5 ]
+</pre>
+</blockquote>
+
+By looking at these rules (and with a little practice), you can usually track down the source
+of most parsing conflicts. It should also be stressed that not all shift-reduce conflicts are
+bad. However, the only way to be sure that they are resolved correctly is to look at <tt>parser.out</tt>.
+
+<h2>Syntax Error Handling</h2>
+
+When a syntax error occurs during parsing, the error is immediately
+detected (i.e., the parser does not read any more tokens beyond the
+source of the error). Error recovery in LR parsers is a delicate
+topic that involves ancient rituals and black-magic. The recovery mechanism
+provided by <tt>yacc.py</tt> is comparable to Unix yacc so you may want
+consult a book like O'Reilly's "Lex and Yacc" for some of the finer details.
+
+<p>
+When a syntax error occurs, <tt>yacc.py</tt> performs the following steps:
+
+<ol>
+<li>On the first occurrence of an error, the user-defined <tt>p_error()</tt> function
+is called with the offending token as an argument. Afterwards, the parser enters
+an "error-recovery" mode in which it will not make future calls to <tt>p_error()</tt> until it
+has successfully shifted at least 3 tokens onto the parsing stack.
+
+<p>
+<li>If no recovery action is taken in <tt>p_error()</tt>, the offending lookahead token is replaced
+with a special <tt>error</tt> token.
+
+<p>
+<li>If the offending lookahead token is already set to <tt>error</tt>, the top item of the parsing stack is
+deleted.
+
+<p>
+<li>If the entire parsing stack is unwound, the parser enters a restart state and attempts to start
+parsing from its initial state.
+
+<p>
+<li>If a grammar rule accepts <tt>error</tt> as a token, it will be
+shifted onto the parsing stack.
+
+<p>
+<li>If the top item of the parsing stack is <tt>error</tt>, lookahead tokens will be discarded until the
+parser can successfully shift a new symbol or reduce a rule involving <tt>error</tt>.
+</ol>
+
+<h4>Recovery and resynchronization with error rules</h4>
+
+The most well-behaved approach for handling syntax errors is to write grammar rules that include the <tt>error</tt>
+token. For example, suppose your language had a grammar rule for a print statement like this:
+
+<blockquote>
+<pre>
+def p_statement_print(t):
+ 'statement : PRINT expr SEMI'
+ ...
+</pre>
+</blockquote>
+
+To account for the possibility of a bad expression, you might write an additional grammar rule like this:
+
+<blockquote>
+<pre>
+def p_statement_print_error(t):
+ 'statement : PRINT error SEMI'
+ print "Syntax error in print statement. Bad expression"
+
+</pre>
+</blockquote>
+
+In this case, the <tt>error</tt> token will match any sequence of
+tokens that might appear up to the first semicolon that is
+encountered. Once the semicolon is reached, the rule will be
+invoked and the <tt>error</tt> token will go away.
+
+<p>
+This type of recovery is sometimes known as parser resynchronization.
+The <tt>error</tt> token acts as a wildcard for any bad input text and
+the token immediately following <tt>error</tt> acts as a
+synchronization token.
+
+<p>
+It is important to note that the <tt>error</tt> token usually does not appear as the last token
+on the right in an error rule. For example:
+
+<blockquote>
+<pre>
+def p_statement_print_error(t):
+ 'statement : PRINT error'
+ print "Syntax error in print statement. Bad expression"
+</pre>
+</blockquote>
+
+This is because the first bad token encountered will cause the rule to
+be reduced--which may make it difficult to recover if more bad tokens
+immediately follow.
+
+<h4>Panic mode recovery</h4>
+
+An alternative error recovery scheme is to enter a panic mode recovery in which tokens are
+discarded to a point where the parser might be able to recover in some sensible manner.
+
+<p>
+Panic mode recovery is implemented entirely in the <tt>p_error()</tt> function. For example, this
+function starts discarding tokens until it reaches a closing '}'. Then, it restarts the
+parser in its initial state.
+
+<blockquote>
+<pre>
+def p_error(t):
+ print "Whoa. You are seriously hosed."
+ # Read ahead looking for a closing '}'
+ while 1:
+ tok = yacc.token() # Get the next token
+ if not tok or tok.type == 'RBRACE': break
+ yacc.restart()
+</pre>
+</blockquote>
+
+<p>
+This function simply discards the bad token and tells the parser that the error was ok.
+
+<blockquote>
+<pre>
+def p_error(t):
+ print "Syntax error at token", t.type
+ # Just discard the token and tell the parser it's okay.
+ yacc.errok()
+</pre>
+</blockquote>
+
+<P>
+Within the <tt>p_error()</tt> function, three functions are available to control the behavior
+of the parser:
+<p>
+<ul>
+<li><tt>yacc.errok()</tt>. This resets the parser state so it doesn't think it's in error-recovery
+mode. This will prevent an <tt>error</tt> token from being generated and will reset the internal
+error counters so that the next syntax error will call <tt>p_error()</tt> again.
+
+<p>
+<li><tt>yacc.token()</tt>. This returns the next token on the input stream.
+
+<p>
+<li><tt>yacc.restart()</tt>. This discards the entire parsing stack and resets the parser
+to its initial state.
+</ul>
+
+Note: these functions are only available when invoking <tt>p_error()</tt> and are not available
+at any other time.
+
+<p>
+To supply the next lookahead token to the parser, <tt>p_error()</tt> can return a token. This might be
+useful if trying to synchronize on special characters. For example:
+
+<blockquote>
+<pre>
+def p_error(t):
+ # Read ahead looking for a terminating ";"
+ while 1:
+ tok = yacc.token() # Get the next token
+ if not tok or tok.type == 'SEMI': break
+ yacc.errok()
+
+ # Return SEMI to the parser as the next lookahead token
+ return tok
+</pre>
+</blockquote>
+
+<h4>General comments on error handling</h4>
+
+For normal types of languages, error recovery with error rules and resynchronization characters is probably the most reliable
+technique. This is because you can instrument the grammar to catch errors at selected places where it is relatively easy
+to recover and continue parsing. Panic mode recovery is really only useful in certain specialized applications where you might want
+to discard huge portions of the input text to find a valid restart point.
+
+<h2>Line Number Tracking</h2>
+
+<tt>yacc.py</tt> automatically tracks line numbers for all of the grammar symbols and tokens it processes. To retrieve the line
+numbers, two functions are used in grammar rules:
+
+<ul>
+<li><tt>t.lineno(num)</tt>. Return the starting line number for symbol <em>num</em>
+<li><tt>t.linespan(num)</tt>. Return a tuple (startline,endline) with the starting and ending line number for symbol <em>num</em>.
+</ul>
+
+For example:
+
+<blockquote>
+<pre>
+def t_expression(t):
+ 'expression : expression PLUS expression'
+ t.lineno(1) # Line number of the left expression
+ t.lineno(2) # line number of the PLUS operator
+ t.lineno(3) # line number of the right expression
+ ...
+ start,end = t.linespan(3) # Start,end lines of the right expression
+
+</pre>
+</blockquote>
+
+Since line numbers are managed internally by the parser, there is usually no need to modify the line
+numbers. However, if you want to save the line numbers in a parse-tree node, you will need to make your own
+private copy.
+
+<h2>AST Construction</h2>
+
+<tt>yacc.py</tt> provides no special functions for constructing an abstract syntax tree. However, such
+construction is easy enough to do on your own. Simply create a data structure for abstract syntax tree nodes
+and assign nodes to <tt>t[0]</tt> in each rule.
+
+For example:
+
+<blockquote>
+<pre>
+class Expr: pass
+
+class BinOp(Expr):
+ def __init__(self,left,op,right):
+ self.type = "binop"
+ self.left = left
+ self.right = right
+ self.op = op
+
+class Number(Expr):
+ def __init__(self,value):
+ self.type = "number"
+ self.value = value
+
+def p_expression_binop(t):
+ '''expression : expression PLUS expression
+ | expression MINUS expression
+ | expression TIMES expression
+ | expression DIVIDE expression'''
+
+ t[0] = BinOp(t[1],t[2],t[3])
+
+def p_expression_group(t):
+ 'expression : LPAREN expression RPAREN'
+ t[0] = t[2]
+
+def p_expression_number(t):
+ 'expression : NUMBER'
+ t[0] = Number(t[1])
+</pre>
+</blockquote>
+
+To simplify tree traversal, it may make sense to pick a very generic tree structure for your parse tree nodes.
+For example:
+
+<blockquote>
+<pre>
+class Node:
+ def __init__(self,type,children=None,leaf=None):
+ self.type = type
+ if children:
+ self.children = children
+ else:
+ self.children = [ ]
+ self.leaf = leaf
+
+def p_expression_binop(t):
+ '''expression : expression PLUS expression
+ | expression MINUS expression
+ | expression TIMES expression
+ | expression DIVIDE expression'''
+
+ t[0] = Node("binop", [t[1],t[3]], t[2])
+</pre>
+</blockquote>
+
+<h2>Yacc implementation notes</h2>
+
+<ul>
+<li>By default, <tt>yacc.py</tt> relies on <tt>lex.py</tt> for tokenizing. However, an alternative tokenizer
+can be supplied as follows:
+
+<blockquote>
+<pre>
+yacc.parse(lexer=x)
+</pre>
+</blockquote>
+in this case, <tt>x</tt> must be a Lexer object that minimally has a <tt>x.token()</tt> method for retrieving the next
+token. If an input string is given to <tt>yacc.parse()</tt>, the lexer must also have an <tt>x.input()</tt> method.
+
+<p>
+<li>By default, the yacc generates tables in debugging mode (which produces the parser.out file and other output).
+To disable this, use
+
+<blockquote>
+<pre>
+yacc.yacc(debug=0)
+</pre>
+</blockquote>
+
+<p>
+<li>To change the name of the <tt>parsetab.py</tt> file, use:
+
+<blockquote>
+<pre>
+yacc.yacc(tabmodule="foo")
+</pre>
+</blockquote>
+
+<P>
+<li>To print copious amounts of debugging during parsing, use:
+
+<blockquote>
+<pre>
+yacc.parse(debug=1)
+</pre>
+</blockquote>
+
+<p>
+<li>The <tt>yacc.yacc()</tt> function really returns a parser object. If you want to support multiple
+parsers in the same application, do this:
+
+<blockquote>
+<pre>
+p = yacc.yacc()
+...
+p.parse()
+</pre>
+</blockquote>
+
+Note: The function <tt>yacc.parse()</tt> is bound to the last parser that was generated.
+
+<p>
+<li>Since the generation of the SLR tables is relatively expensive, previously generated tables are
+cached and reused if possible. The decision to regenerate the tables is determined by taking an MD5
+checksum of all grammar rules and precedence rules. Only in the event of a mismatch are the tables regenerated.
+
+<p>
+It should be noted that table generation is reasonably efficient, even for grammars that involve around a 100 rules
+and several hundred states. For more complex languages such as C, table generation may take 30-60 seconds on a slow
+machine. Please be patient.
+
+<p>
+<li>Since LR parsing is mostly driven by tables, the performance of the parser is largely independent of the
+size of the grammar. The biggest bottlenecks will be the lexer and the complexity of your grammar rules.
+</ul>
+
+<h2>Parser and Lexer State Management</h2>
+
+In advanced parsing applications, you may want to have multiple
+parsers and lexers. Furthermore, the parser may want to control the
+behavior of the lexer in some way.
+
+<p>
+To do this, it is important to note that both the lexer and parser are
+actually implemented as objects. These objects are returned by the
+<tt>lex()</tt> and <tt>yacc()</tt> functions respectively. For example:
+
+<blockquote>
+<pre>
+lexer = lex.lex() # Return lexer object
+parser = yacc.yacc() # Return parser object
+</pre>
+</blockquote>
+
+Within lexer and parser rules, these objects are also available. In the lexer,
+the "lexer" attribute of a token refers to the lexer object in use. For example:
+
+<blockquote>
+<pre>
+def t_NUMBER(t):
+ r'\d+'
+ ...
+ print t.lexer # Show lexer object
+</pre>
+</blockquote>
+
+In the parser, the "lexer" and "parser" attributes refer to the lexer
+and parser objects respectively.
+
+<blockquote>
+<pre>
+def p_expr_plus(t):
+ 'expr : expr PLUS expr'
+ ...
+ print t.parser # Show parser object
+ print t.lexer # Show lexer object
+</pre>
+</blockquote>
+
+If necessary, arbitrary attributes can be attached to the lexer or parser object.
+For example, if you wanted to have different parsing modes, you could attach a mode
+attribute to the parser object and look at it later.
+
+<h2>Using Python's Optimized Mode</h2>
+
+Because PLY uses information from doc-strings, parsing and lexing
+information must be gathered while running the Python interpreter in
+normal mode (i.e., not with the -O or -OO options). However, if you
+specify optimized mode like this:
+
+<blockquote>
+<pre>
+lex.lex(optimize=1)
+yacc.yacc(optimize=1)
+</pre>
+</blockquote>
+
+then PLY can later be used when Python runs in optimized mode. To make this work,
+make sure you first run Python in normal mode. Once the lexing and parsing tables
+have been generated the first time, run Python in optimized mode. PLY will use
+the tables without the need for doc strings.
+
+<p>
+Beware: running PLY in optimized mode disables a lot of error
+checking. You should only do this when your project has stabilized
+and you don't need to do any debugging.
+
+<h2>Where to go from here?</h2>
+
+The <tt>examples</tt> directory of the PLY distribution contains several simple examples. Please consult a
+compilers textbook for the theory and underlying implementation details or LR parsing.
+
+</body>
+</html>
+
+
+
+
+
+
+
diff --git a/ext/ply/example/ansic/README b/ext/ply/example/ansic/README
new file mode 100644
index 000000000..e049d3b4e
--- /dev/null
+++ b/ext/ply/example/ansic/README
@@ -0,0 +1,2 @@
+This example is incomplete. Was going to specify an ANSI C parser.
+This is part of it.
diff --git a/ext/ply/example/ansic/clex.py b/ext/ply/example/ansic/clex.py
new file mode 100644
index 000000000..afd995208
--- /dev/null
+++ b/ext/ply/example/ansic/clex.py
@@ -0,0 +1,161 @@
+# ----------------------------------------------------------------------
+# clex.py
+#
+# A lexer for ANSI C.
+# ----------------------------------------------------------------------
+
+import lex
+
+# Reserved words
+reserved = (
+ 'AUTO', 'BREAK', 'CASE', 'CHAR', 'CONST', 'CONTINUE', 'DEFAULT', 'DO', 'DOUBLE',
+ 'ELSE', 'ENUM', 'EXTERN', 'FLOAT', 'FOR', 'GOTO', 'IF', 'INT', 'LONG', 'REGISTER',
+ 'RETURN', 'SHORT', 'SIGNED', 'SIZEOF', 'STATIC', 'STRUCT', 'SWITCH', 'TYPEDEF',
+ 'UNION', 'UNSIGNED', 'VOID', 'VOLATILE', 'WHILE',
+ )
+
+tokens = reserved + (
+ # Literals (identifier, integer constant, float constant, string constant, char const)
+ 'ID', 'TYPEID', 'ICONST', 'FCONST', 'SCONST', 'CCONST',
+
+ # Operators (+,-,*,/,%,|,&,~,^,<<,>>, ||, &&, !, <, <=, >, >=, ==, !=)
+ 'PLUS', 'MINUS', 'TIMES', 'DIVIDE', 'MOD',
+ 'OR', 'AND', 'NOT', 'XOR', 'LSHIFT', 'RSHIFT',
+ 'LOR', 'LAND', 'LNOT',
+ 'LT', 'LE', 'GT', 'GE', 'EQ', 'NE',
+
+ # Assignment (=, *=, /=, %=, +=, -=, <<=, >>=, &=, ^=, |=)
+ 'EQUALS', 'TIMESEQUAL', 'DIVEQUAL', 'MODEQUAL', 'PLUSEQUAL', 'MINUSEQUAL',
+ 'LSHIFTEQUAL','RSHIFTEQUAL', 'ANDEQUAL', 'XOREQUAL', 'OREQUAL',
+
+ # Increment/decrement (++,--)
+ 'PLUSPLUS', 'MINUSMINUS',
+
+ # Structure dereference (->)
+ 'ARROW',
+
+ # Conditional operator (?)
+ 'CONDOP',
+
+ # Delimeters ( ) [ ] { } , . ; :
+ 'LPAREN', 'RPAREN',
+ 'LBRACKET', 'RBRACKET',
+ 'LBRACE', 'RBRACE',
+ 'COMMA', 'PERIOD', 'SEMI', 'COLON',
+
+ # Ellipsis (...)
+ 'ELLIPSIS',
+ )
+
+# Completely ignored characters
+t_ignore = ' \t\x0c'
+
+# Newlines
+def t_NEWLINE(t):
+ r'\n+'
+ t.lineno += t.value.count("\n")
+
+# Operators
+t_PLUS = r'\+'
+t_MINUS = r'-'
+t_TIMES = r'\*'
+t_DIVIDE = r'/'
+t_MOD = r'%'
+t_OR = r'\|'
+t_AND = r'&'
+t_NOT = r'~'
+t_XOR = r'^'
+t_LSHIFT = r'<<'
+t_RSHIFT = r'>>'
+t_LOR = r'\|\|'
+t_LAND = r'&&'
+t_LNOT = r'!'
+t_LT = r'<'
+t_GT = r'>'
+t_LE = r'<='
+t_GE = r'>='
+t_EQ = r'=='
+t_NE = r'!='
+
+# Assignment operators
+
+t_EQUALS = r'='
+t_TIMESEQUAL = r'\*='
+t_DIVEQUAL = r'/='
+t_MODEQUAL = r'%='
+t_PLUSEQUAL = r'\+='
+t_MINUSEQUAL = r'-='
+t_LSHIFTEQUAL = r'<<='
+t_RSHIFTEQUAL = r'>>='
+t_ANDEQUAL = r'&='
+t_OREQUAL = r'\|='
+t_XOREQUAL = r'^='
+
+# Increment/decrement
+t_PLUSPLUS = r'\+\+'
+t_MINUSMINUS = r'--'
+
+# ->
+t_ARROW = r'->'
+
+# ?
+t_CONDOP = r'\?'
+
+# Delimeters
+t_LPAREN = r'\('
+t_RPAREN = r'\)'
+t_LBRACKET = r'\['
+t_RBRACKET = r'\]'
+t_LBRACE = r'\{'
+t_RBRACE = r'\}'
+t_COMMA = r','
+t_PERIOD = r'\.'
+t_SEMI = r';'
+t_COLON = r':'
+t_ELLIPSIS = r'\.\.\.'
+
+# Identifiers and reserved words
+
+reserved_map = { }
+for r in reserved:
+ reserved_map[r.lower()] = r
+
+def t_ID(t):
+ r'[A-Za-z_][\w_]*'
+ t.type = reserved_map.get(t.value,"ID")
+ return t
+
+# Integer literal
+t_ICONST = r'\d+([uU]|[lL]|[uU][lL]|[lL][uU])?'
+
+# Floating literal
+t_FCONST = r'((\d+)(\.\d+)(e(\+|-)?(\d+))? | (\d+)e(\+|-)?(\d+))([lL]|[fF])?'
+
+# String literal
+t_SCONST = r'\"([^\\\n]|(\\.))*?\"'
+
+# Character constant 'c' or L'c'
+t_CCONST = r'(L)?\'([^\\\n]|(\\.))*?\''
+
+# Comments
+def t_comment(t):
+ r' /\*(.|\n)*?\*/'
+ t.lineno += t.value.count('\n')
+
+# Preprocessor directive (ignored)
+def t_preprocessor(t):
+ r'\#(.)*?\n'
+ t.lineno += 1
+
+def t_error(t):
+ print "Illegal character %s" % repr(t.value[0])
+ t.skip(1)
+
+lexer = lex.lex(optimize=1)
+if __name__ == "__main__":
+ lex.runmain(lexer)
+
+
+
+
+
diff --git a/ext/ply/example/ansic/cparse.py b/ext/ply/example/ansic/cparse.py
new file mode 100644
index 000000000..ddfd5c72b
--- /dev/null
+++ b/ext/ply/example/ansic/cparse.py
@@ -0,0 +1,859 @@
+# -----------------------------------------------------------------------------
+# cparse.py
+#
+# Simple parser for ANSI C. Based on the grammar in K&R, 2nd Ed.
+# -----------------------------------------------------------------------------
+
+import yacc
+import clex
+
+# Get the token map
+tokens = clex.tokens
+
+# translation-unit:
+
+def p_translation_unit_1(t):
+ 'translation_unit : external_declaration'
+ pass
+
+def p_translation_unit_2(t):
+ 'translation_unit : translation_unit external_declaration'
+ pass
+
+# external-declaration:
+
+def p_external_declaration_1(t):
+ 'external_declaration : function_definition'
+ pass
+
+def p_external_declaration_2(t):
+ 'external_declaration : declaration'
+ pass
+
+# function-definition:
+
+def p_function_definition_1(t):
+ 'function_definition : declaration_specifiers declarator declaration_list compound_statement'
+ pass
+
+def p_function_definition_2(t):
+ 'function_definition : declarator declaration_list compound_statement'
+ pass
+
+def p_function_definition_3(t):
+ 'function_definition : declarator compound_statement'
+ pass
+
+def p_function_definition_4(t):
+ 'function_definition : declaration_specifiers declarator compound_statement'
+ pass
+
+# declaration:
+
+def p_declaration_1(t):
+ 'declaration : declaration_specifiers init_declarator_list SEMI'
+ pass
+
+def p_declaration_2(t):
+ 'declaration : declaration_specifiers SEMI'
+ pass
+
+# declaration-list:
+
+def p_declaration_list_1(t):
+ 'declaration_list : declaration'
+ pass
+
+def p_declaration_list_2(t):
+ 'declaration_list : declaration_list declaration '
+ pass
+
+# declaration-specifiers
+def p_declaration_specifiers_1(t):
+ 'declaration_specifiers : storage_class_specifier declaration_specifiers'
+ pass
+
+def p_declaration_specifiers_2(t):
+ 'declaration_specifiers : type_specifier declaration_specifiers'
+ pass
+
+def p_declaration_specifiers_3(t):
+ 'declaration_specifiers : type_qualifier declaration_specifiers'
+ pass
+
+def p_declaration_specifiers_4(t):
+ 'declaration_specifiers : storage_class_specifier'
+ pass
+
+def p_declaration_specifiers_5(t):
+ 'declaration_specifiers : type_specifier'
+ pass
+
+def p_declaration_specifiers_6(t):
+ 'declaration_specifiers : type_qualifier'
+ pass
+
+# storage-class-specifier
+def p_storage_class_specifier(t):
+ '''storage_class_specifier : AUTO
+ | REGISTER
+ | STATIC
+ | EXTERN
+ | TYPEDEF
+ '''
+ pass
+
+# type-specifier:
+def p_type_specifier(t):
+ '''type_specifier : VOID
+ | CHAR
+ | SHORT
+ | INT
+ | LONG
+ | FLOAT
+ | DOUBLE
+ | SIGNED
+ | UNSIGNED
+ | struct_or_union_specifier
+ | enum_specifier
+ | TYPEID
+ '''
+ pass
+
+# type-qualifier:
+def p_type_qualifier(t):
+ '''type_qualifier : CONST
+ | VOLATILE'''
+ pass
+
+# struct-or-union-specifier
+
+def p_struct_or_union_specifier_1(t):
+ 'struct_or_union_specifier : struct_or_union ID LBRACE struct_declaration_list RBRACE'
+ pass
+
+def p_struct_or_union_specifier_2(t):
+ 'struct_or_union_specifier : struct_or_union LBRACE struct_declaration_list RBRACE'
+ pass
+
+def p_struct_or_union_specifier_3(t):
+ 'struct_or_union_specifier : struct_or_union ID'
+ pass
+
+# struct-or-union:
+def p_struct_or_union(t):
+ '''struct_or_union : STRUCT
+ | UNION
+ '''
+ pass
+
+# struct-declaration-list:
+
+def p_struct_declaration_list_1(t):
+ 'struct_declaration_list : struct_declaration'
+ pass
+
+def p_struct_declaration_list_2(t):
+ 'struct_declaration_list : struct_declarator_list struct_declaration'
+ pass
+
+# init-declarator-list:
+
+def p_init_declarator_list_1(t):
+ 'init_declarator_list : init_declarator'
+ pass
+
+def p_init_declarator_list_2(t):
+ 'init_declarator_list : init_declarator_list COMMA init_declarator'
+ pass
+
+# init-declarator
+
+def p_init_declarator_1(t):
+ 'init_declarator : declarator'
+ pass
+
+def p_init_declarator_2(t):
+ 'init_declarator : declarator EQUALS initializer'
+ pass
+
+# struct-declaration:
+
+def p_struct_declaration(t):
+ 'struct_declaration : specifier_qualifier_list struct_declarator_list SEMI'
+ pass
+
+# specifier-qualifier-list:
+
+def p_specifier_qualifier_list_1(t):
+ 'specifier_qualifier_list : type_specifier specifier_qualifier_list'
+ pass
+
+def p_specifier_qualifier_list_2(t):
+ 'specifier_qualifier_list : type_specifier'
+ pass
+
+def p_specifier_qualifier_list_3(t):
+ 'specifier_qualifier_list : type_qualifier specifier_qualifier_list'
+ pass
+
+def p_specifier_qualifier_list_4(t):
+ 'specifier_qualifier_list : type_qualifier'
+ pass
+
+# struct-declarator-list:
+
+def p_struct_declarator_list_1(t):
+ 'struct_declarator_list : struct_declarator'
+ pass
+
+def p_struct_declarator_list_2(t):
+ 'struct_declarator_list : struct_declarator_list COMMA struct_declarator'
+ pass
+
+# struct-declarator:
+
+def p_struct_declarator_1(t):
+ 'struct_declarator : declarator'
+ pass
+
+def p_struct_declarator_2(t):
+ 'struct_declarator : declarator COLON constant_expression'
+ pass
+
+def p_struct_declarator_3(t):
+ 'struct_declarator : COLON constant_expression'
+ pass
+
+# enum-specifier:
+
+def p_enum_specifier_1(t):
+ 'enum_specifier : ENUM ID LBRACE enumerator_list RBRACE'
+ pass
+
+def p_enum_specifier_2(t):
+ 'enum_specifier : ENUM LBRACE enumerator_list RBRACE'
+ pass
+
+def p_enum_specifier_3(t):
+ 'enum_specifier : ENUM ID'
+ pass
+
+# enumerator_list:
+def p_enumerator_list_1(t):
+ 'enumerator_list : enumerator'
+ pass
+
+def p_enumerator_list_2(t):
+ 'enumerator_list : enumerator_list COMMA enumerator'
+ pass
+
+# enumerator:
+def p_enumerator_1(t):
+ 'enumerator : ID'
+ pass
+
+def p_enumerator_2(t):
+ 'enumerator : ID EQUALS constant_expression'
+ pass
+
+# declarator:
+
+def p_declarator_1(t):
+ 'declarator : pointer direct_declarator'
+ pass
+
+def p_declarator_2(t):
+ 'declarator : direct_declarator'
+ pass
+
+# direct-declarator:
+
+def p_direct_declarator_1(t):
+ 'direct_declarator : ID'
+ pass
+
+def p_direct_declarator_2(t):
+ 'direct_declarator : LPAREN declarator RPAREN'
+ pass
+
+def p_direct_declarator_3(t):
+ 'direct_declarator : direct_declarator LBRACKET constant_expression_opt RBRACKET'
+ pass
+
+def p_direct_declarator_4(t):
+ 'direct_declarator : direct_declarator LPAREN parameter_type_list RPAREN '
+ pass
+
+def p_direct_declarator_5(t):
+ 'direct_declarator : direct_declarator LPAREN identifier_list RPAREN '
+ pass
+
+def p_direct_declarator_6(t):
+ 'direct_declarator : direct_declarator LPAREN RPAREN '
+ pass
+
+# pointer:
+def p_pointer_1(t):
+ 'pointer : TIMES type_qualifier_list'
+ pass
+
+def p_pointer_2(t):
+ 'pointer : TIMES'
+ pass
+
+def p_pointer_3(t):
+ 'pointer : TIMES type_qualifier_list pointer'
+ pass
+
+def p_pointer_4(t):
+ 'pointer : TIMES pointer'
+ pass
+
+# type-qualifier-list:
+
+def p_type_qualifier_list_1(t):
+ 'type_qualifier_list : type_qualifier'
+ pass
+
+def p_type_qualifier_list_2(t):
+ 'type_qualifier_list : type_qualifier_list type_qualifier'
+ pass
+
+# parameter-type-list:
+
+def p_parameter_type_list_1(t):
+ 'parameter_type_list : parameter_list'
+ pass
+
+def p_parameter_type_list_2(t):
+ 'parameter_type_list : parameter_list COMMA ELLIPSIS'
+ pass
+
+# parameter-list:
+
+def p_parameter_list_1(t):
+ 'parameter_list : parameter_declaration'
+ pass
+
+def p_parameter_list_2(t):
+ 'parameter_list : parameter_list COMMA parameter_declaration'
+ pass
+
+# parameter-declaration:
+def p_parameter_declaration_1(t):
+ 'parameter_declaration : declaration_specifiers declarator'
+ pass
+
+def p_parameter_declaration_2(t):
+ 'parameter_declaration : declaration_specifiers abstract_declarator_opt'
+ pass
+
+# identifier-list:
+def p_identifier_list_1(t):
+ 'identifier_list : ID'
+ pass
+
+def p_identifier_list_2(t):
+ 'identifier_list : identifier_list COMMA ID'
+ pass
+
+# initializer:
+
+def p_initializer_1(t):
+ 'initializer : assignment_expression'
+ pass
+
+def p_initializer_2(t):
+ '''initializer : LBRACE initializer_list RBRACE
+ | LBRACE initializer_list COMMA RBRACE'''
+ pass
+
+# initializer-list:
+
+def p_initializer_list_1(t):
+ 'initializer_list : initializer'
+ pass
+
+def p_initializer_list_2(t):
+ 'initializer_list : initializer_list COMMA initializer'
+ pass
+
+# type-name:
+
+def p_type_name(t):
+ 'type_name : specifier_qualifier_list abstract_declarator_opt'
+ pass
+
+def p_abstract_declarator_opt_1(t):
+ 'abstract_declarator_opt : empty'
+ pass
+
+def p_abstract_declarator_opt_2(t):
+ 'abstract_declarator_opt : abstract_declarator'
+ pass
+
+# abstract-declarator:
+
+def p_abstract_declarator_1(t):
+ 'abstract_declarator : pointer '
+ pass
+
+def p_abstract_declarator_2(t):
+ 'abstract_declarator : pointer direct_abstract_declarator'
+ pass
+
+def p_abstract_declarator_3(t):
+ 'abstract_declarator : direct_abstract_declarator'
+ pass
+
+# direct-abstract-declarator:
+
+def p_direct_abstract_declarator_1(t):
+ 'direct_abstract_declarator : LPAREN abstract_declarator RPAREN'
+ pass
+
+def p_direct_abstract_declarator_2(t):
+ 'direct_abstract_declarator : direct_abstract_declarator LBRACKET constant_expression_opt RBRACKET'
+ pass
+
+def p_direct_abstract_declarator_3(t):
+ 'direct_abstract_declarator : LBRACKET constant_expression_opt RBRACKET'
+ pass
+
+def p_direct_abstract_declarator_4(t):
+ 'direct_abstract_declarator : direct_abstract_declarator LPAREN parameter_type_list_opt RPAREN'
+ pass
+
+def p_direct_abstract_declarator_5(t):
+ 'direct_abstract_declarator : LPAREN parameter_type_list_opt RPAREN'
+ pass
+
+# Optional fields in abstract declarators
+
+def p_constant_expression_opt_1(t):
+ 'constant_expression_opt : empty'
+ pass
+
+def p_constant_expression_opt_2(t):
+ 'constant_expression_opt : constant_expression'
+ pass
+
+def p_parameter_type_list_opt_1(t):
+ 'parameter_type_list_opt : empty'
+ pass
+
+def p_parameter_type_list_opt_2(t):
+ 'parameter_type_list_opt : parameter_type_list'
+ pass
+
+# statement:
+
+def p_statement(t):
+ '''
+ statement : labeled_statement
+ | expression_statement
+ | compound_statement
+ | selection_statement
+ | iteration_statement
+ | jump_statement
+ '''
+ pass
+
+# labeled-statement:
+
+def p_labeled_statement_1(t):
+ 'labeled_statement : ID COLON statement'
+ pass
+
+def p_labeled_statement_2(t):
+ 'labeled_statement : CASE constant_expression COLON statement'
+ pass
+
+def p_labeled_statement_3(t):
+ 'labeled_statement : DEFAULT COLON statement'
+ pass
+
+# expression-statement:
+def p_expression_statement(t):
+ 'expression_statement : expression_opt SEMI'
+ pass
+
+# compound-statement:
+
+def p_compound_statement_1(t):
+ 'compound_statement : LBRACE declaration_list statement_list RBRACE'
+ pass
+
+def p_compound_statement_2(t):
+ 'compound_statement : LBRACE statement_list RBRACE'
+ pass
+
+def p_compound_statement_3(t):
+ 'compound_statement : LBRACE declaration_list RBRACE'
+ pass
+
+def p_compound_statement_4(t):
+ 'compound_statement : LBRACE RBRACE'
+ pass
+
+# statement-list:
+
+def p_statement_list_1(t):
+ 'statement_list : statement'
+ pass
+
+def p_statement_list_2(t):
+ 'statement_list : statement_list statement'
+ pass
+
+# selection-statement
+
+def p_selection_statement_1(t):
+ 'selection_statement : IF LPAREN expression RPAREN statement'
+ pass
+
+def p_selection_statement_2(t):
+ 'selection_statement : IF LPAREN expression RPAREN statement ELSE statement '
+ pass
+
+def p_selection_statement_3(t):
+ 'selection_statement : SWITCH LPAREN expression RPAREN statement '
+ pass
+
+# iteration_statement:
+
+def p_iteration_statement_1(t):
+ 'iteration_statement : WHILE LPAREN expression RPAREN statement'
+ pass
+
+def p_iteration_statement_2(t):
+ 'iteration_statement : FOR LPAREN expression_opt SEMI expression_opt SEMI expression_opt RPAREN statement '
+ pass
+
+def p_iteration_statement_3(t):
+ 'iteration_statement : DO statement WHILE LPAREN expression RPAREN SEMI'
+ pass
+
+# jump_statement:
+
+def p_jump_statement_1(t):
+ 'jump_statement : GOTO ID SEMI'
+ pass
+
+def p_jump_statement_2(t):
+ 'jump_statement : CONTINUE SEMI'
+ pass
+
+def p_jump_statement_3(t):
+ 'jump_statement : BREAK SEMI'
+ pass
+
+def p_jump_statement_4(t):
+ 'jump_statement : RETURN expression_opt SEMI'
+ pass
+
+def p_expression_opt_1(t):
+ 'expression_opt : empty'
+ pass
+
+def p_expression_opt_2(t):
+ 'expression_opt : expression'
+ pass
+
+# expression:
+def p_expression_1(t):
+ 'expression : assignment_expression'
+ pass
+
+def p_expression_2(t):
+ 'expression : expression COMMA assignment_expression'
+ pass
+
+# assigment_expression:
+def p_assignment_expression_1(t):
+ 'assignment_expression : conditional_expression'
+ pass
+
+def p_assignment_expression_2(t):
+ 'assignment_expression : unary_expression assignment_operator assignment_expression'
+ pass
+
+# assignment_operator:
+def p_assignment_operator(t):
+ '''
+ assignment_operator : EQUALS
+ | TIMESEQUAL
+ | DIVEQUAL
+ | MODEQUAL
+ | PLUSEQUAL
+ | MINUSEQUAL
+ | LSHIFTEQUAL
+ | RSHIFTEQUAL
+ | ANDEQUAL
+ | OREQUAL
+ | XOREQUAL
+ '''
+ pass
+
+# conditional-expression
+def p_conditional_expression_1(t):
+ 'conditional_expression : logical_or_expression'
+ pass
+
+def p_conditional_expression_2(t):
+ 'conditional_expression : logical_or_expression CONDOP expression COLON conditional_expression '
+ pass
+
+# constant-expression
+
+def p_constant_expression(t):
+ 'constant_expression : conditional_expression'
+ pass
+
+# logical-or-expression
+
+def p_logical_or_expression_1(t):
+ 'logical_or_expression : logical_and_expression'
+ pass
+
+def p_logical_or_expression_2(t):
+ 'logical_or_expression : logical_or_expression LOR logical_and_expression'
+ pass
+
+# logical-and-expression
+
+def p_logical_and_expression_1(t):
+ 'logical_and_expression : inclusive_or_expression'
+ pass
+
+def p_logical_and_expression_2(t):
+ 'logical_and_expression : logical_and_expression LAND inclusive_or_expression'
+ pass
+
+# inclusive-or-expression:
+
+def p_inclusive_or_expression_1(t):
+ 'inclusive_or_expression : exclusive_or_expression'
+ pass
+
+def p_inclusive_or_expression_2(t):
+ 'inclusive_or_expression : inclusive_or_expression OR exclusive_or_expression'
+ pass
+
+# exclusive-or-expression:
+
+def p_exclusive_or_expression_1(t):
+ 'exclusive_or_expression : and_expression'
+ pass
+
+def p_exclusive_or_expression_2(t):
+ 'exclusive_or_expression : exclusive_or_expression XOR and_expression'
+ pass
+
+# AND-expression
+
+def p_and_expression_1(t):
+ 'and_expression : equality_expression'
+ pass
+
+def p_and_expression_2(t):
+ 'and_expression : and_expression AND equality_expression'
+ pass
+
+
+# equality-expression:
+def p_equality_expression_1(t):
+ 'equality_expression : relational_expression'
+ pass
+
+def p_equality_expression_2(t):
+ 'equality_expression : equality_expression EQ relational_expression'
+ pass
+
+def p_equality_expression_3(t):
+ 'equality_expression : equality_expression NE relational_expression'
+ pass
+
+
+# relational-expression:
+def p_relational_expression_1(t):
+ 'relational_expression : shift_expression'
+ pass
+
+def p_relational_expression_2(t):
+ 'relational_expression : relational_expression LT shift_expression'
+ pass
+
+def p_relational_expression_3(t):
+ 'relational_expression : relational_expression GT shift_expression'
+ pass
+
+def p_relational_expression_4(t):
+ 'relational_expression : relational_expression LE shift_expression'
+ pass
+
+def p_relational_expression_5(t):
+ 'relational_expression : relational_expression GE shift_expression'
+ pass
+
+# shift-expression
+
+def p_shift_expression_1(t):
+ 'shift_expression : additive_expression'
+ pass
+
+def p_shift_expression_2(t):
+ 'shift_expression : shift_expression LSHIFT additive_expression'
+ pass
+
+def p_shift_expression_3(t):
+ 'shift_expression : shift_expression RSHIFT additive_expression'
+ pass
+
+# additive-expression
+
+def p_additive_expression_1(t):
+ 'additive_expression : multiplicative_expression'
+ pass
+
+def p_additive_expression_2(t):
+ 'additive_expression : additive_expression PLUS multiplicative_expression'
+ pass
+
+def p_additive_expression_3(t):
+ 'additive_expression : additive_expression MINUS multiplicative_expression'
+ pass
+
+# multiplicative-expression
+
+def p_multiplicative_expression_1(t):
+ 'multiplicative_expression : cast_expression'
+ pass
+
+def p_multiplicative_expression_2(t):
+ 'multiplicative_expression : multiplicative_expression TIMES cast_expression'
+ pass
+
+def p_multiplicative_expression_3(t):
+ 'multiplicative_expression : multiplicative_expression DIVIDE cast_expression'
+ pass
+
+def p_multiplicative_expression_4(t):
+ 'multiplicative_expression : multiplicative_expression MOD cast_expression'
+ pass
+
+# cast-expression:
+
+def p_cast_expression_1(t):
+ 'cast_expression : unary_expression'
+ pass
+
+def p_cast_expression_2(t):
+ 'cast_expression : LPAREN type_name RPAREN cast_expression'
+ pass
+
+# unary-expression:
+def p_unary_expression_1(t):
+ 'unary_expression : postfix_expression'
+ pass
+
+def p_unary_expression_2(t):
+ 'unary_expression : PLUSPLUS unary_expression'
+ pass
+
+def p_unary_expression_3(t):
+ 'unary_expression : MINUSMINUS unary_expression'
+ pass
+
+def p_unary_expression_4(t):
+ 'unary_expression : unary_operator cast_expression'
+ pass
+
+def p_unary_expression_5(t):
+ 'unary_expression : SIZEOF unary_expression'
+ pass
+
+def p_unary_expression_6(t):
+ 'unary_expression : SIZEOF LPAREN type_name RPAREN'
+ pass
+
+#unary-operator
+def p_unary_operator(t):
+ '''unary_operator : AND
+ | TIMES
+ | PLUS
+ | MINUS
+ | NOT
+ | LNOT '''
+ pass
+
+# postfix-expression:
+def p_postfix_expression_1(t):
+ 'postfix_expression : primary_expression'
+ pass
+
+def p_postfix_expression_2(t):
+ 'postfix_expression : postfix_expression LBRACKET expression RBRACKET'
+ pass
+
+def p_postfix_expression_3(t):
+ 'postfix_expression : postfix_expression LPAREN argument_expression_list RPAREN'
+ pass
+
+def p_postfix_expression_4(t):
+ 'postfix_expression : postfix_expression LPAREN RPAREN'
+ pass
+
+def p_postfix_expression_5(t):
+ 'postfix_expression : postfix_expression PERIOD ID'
+ pass
+
+def p_postfix_expression_6(t):
+ 'postfix_expression : postfix_expression ARROW ID'
+ pass
+
+def p_postfix_expression_7(t):
+ 'postfix_expression : postfix_expression PLUSPLUS'
+ pass
+
+def p_postfix_expression_8(t):
+ 'postfix_expression : postfix_expression MINUSMINUS'
+ pass
+
+# primary-expression:
+def p_primary_expression(t):
+ '''primary_expression : ID
+ | constant
+ | SCONST
+ | LPAREN expression RPAREN'''
+ pass
+
+# argument-expression-list:
+def p_argument_expression_list(t):
+ '''argument_expression_list : assignment_expression
+ | argument_expression_list COMMA assignment_expression'''
+ pass
+
+# constant:
+def p_constant(t):
+ '''constant : ICONST
+ | FCONST
+ | CCONST'''
+ pass
+
+
+def p_empty(t):
+ 'empty : '
+ pass
+
+def p_error(t):
+ print "Whoa. We're hosed"
+
+import profile
+# Build the grammar
+profile.run("yacc.yacc()")
+
+
+
+
diff --git a/ext/ply/example/calc/calc.py b/ext/ply/example/calc/calc.py
new file mode 100644
index 000000000..aeb23c246
--- /dev/null
+++ b/ext/ply/example/calc/calc.py
@@ -0,0 +1,108 @@
+# -----------------------------------------------------------------------------
+# calc.py
+#
+# A simple calculator with variables. This is from O'Reilly's
+# "Lex and Yacc", p. 63.
+# -----------------------------------------------------------------------------
+
+tokens = (
+ 'NAME','NUMBER',
+ 'PLUS','MINUS','TIMES','DIVIDE','EQUALS',
+ 'LPAREN','RPAREN',
+ )
+
+# Tokens
+
+t_PLUS = r'\+'
+t_MINUS = r'-'
+t_TIMES = r'\*'
+t_DIVIDE = r'/'
+t_EQUALS = r'='
+t_LPAREN = r'\('
+t_RPAREN = r'\)'
+t_NAME = r'[a-zA-Z_][a-zA-Z0-9_]*'
+
+def t_NUMBER(t):
+ r'\d+'
+ try:
+ t.value = int(t.value)
+ except ValueError:
+ print "Integer value too large", t.value
+ t.value = 0
+ return t
+
+t_ignore = " \t"
+
+def t_newline(t):
+ r'\n+'
+ t.lineno += t.value.count("\n")
+
+def t_error(t):
+ print "Illegal character '%s'" % t.value[0]
+ t.skip(1)
+
+# Build the lexer
+import lex
+lex.lex()
+
+# Parsing rules
+
+precedence = (
+ ('left','PLUS','MINUS'),
+ ('left','TIMES','DIVIDE'),
+ ('right','UMINUS'),
+ )
+
+# dictionary of names
+names = { }
+
+def p_statement_assign(t):
+ 'statement : NAME EQUALS expression'
+ names[t[1]] = t[3]
+
+def p_statement_expr(t):
+ 'statement : expression'
+ print t[1]
+
+def p_expression_binop(t):
+ '''expression : expression PLUS expression
+ | expression MINUS expression
+ | expression TIMES expression
+ | expression DIVIDE expression'''
+ if t[2] == '+' : t[0] = t[1] + t[3]
+ elif t[2] == '-': t[0] = t[1] - t[3]
+ elif t[2] == '*': t[0] = t[1] * t[3]
+ elif t[2] == '/': t[0] = t[1] / t[3]
+
+def p_expression_uminus(t):
+ 'expression : MINUS expression %prec UMINUS'
+ t[0] = -t[2]
+
+def p_expression_group(t):
+ 'expression : LPAREN expression RPAREN'
+ t[0] = t[2]
+
+def p_expression_number(t):
+ 'expression : NUMBER'
+ t[0] = t[1]
+
+def p_expression_name(t):
+ 'expression : NAME'
+ try:
+ t[0] = names[t[1]]
+ except LookupError:
+ print "Undefined name '%s'" % t[1]
+ t[0] = 0
+
+def p_error(t):
+ print "Syntax error at '%s'" % t.value
+
+import yacc
+yacc.yacc()
+
+while 1:
+ try:
+ s = raw_input('calc > ')
+ except EOFError:
+ break
+ yacc.parse(s)
diff --git a/ext/ply/example/hedit/hedit.py b/ext/ply/example/hedit/hedit.py
new file mode 100644
index 000000000..f00427bf5
--- /dev/null
+++ b/ext/ply/example/hedit/hedit.py
@@ -0,0 +1,44 @@
+# -----------------------------------------------------------------------------
+# hedit.py
+#
+# Paring of Fortran H Edit descriptions (Contributed by Pearu Peterson)
+#
+# These tokens can't be easily tokenized because they are of the following
+# form:
+#
+# nHc1...cn
+#
+# where n is a positive integer and c1 ... cn are characters.
+#
+# This example shows how to modify the state of the lexer to parse
+# such tokens
+# -----------------------------------------------------------------------------
+
+tokens = (
+ 'H_EDIT_DESCRIPTOR',
+ )
+
+# Tokens
+t_ignore = " \t\n"
+
+def t_H_EDIT_DESCRIPTOR(t):
+ r"\d+H.*" # This grabs all of the remaining text
+ i = t.value.index('H')
+ n = eval(t.value[:i])
+
+ # Adjust the tokenizing position
+ t.lexer.lexpos -= len(t.value) - (i+1+n)
+
+ t.value = t.value[i+1:i+1+n]
+ return t
+
+def t_error(t):
+ print "Illegal character '%s'" % t.value[0]
+ t.skip(1)
+
+# Build the lexer
+import lex
+lex.lex()
+lex.runmain()
+
+
diff --git a/ext/ply/example/optcalc/README b/ext/ply/example/optcalc/README
new file mode 100644
index 000000000..6d196f0ee
--- /dev/null
+++ b/ext/ply/example/optcalc/README
@@ -0,0 +1,9 @@
+An example showing how to use Python optimized mode.
+To run:
+
+ - First run 'python calc.py'
+
+ - Then run 'python -OO calc.py'
+
+If working corretly, the second version should run the
+same way.
diff --git a/ext/ply/example/optcalc/calc.py b/ext/ply/example/optcalc/calc.py
new file mode 100644
index 000000000..fa66cda5b
--- /dev/null
+++ b/ext/ply/example/optcalc/calc.py
@@ -0,0 +1,110 @@
+# -----------------------------------------------------------------------------
+# calc.py
+#
+# A simple calculator with variables. This is from O'Reilly's
+# "Lex and Yacc", p. 63.
+# -----------------------------------------------------------------------------
+
+tokens = (
+ 'NAME','NUMBER',
+ 'PLUS','MINUS','TIMES','DIVIDE','EQUALS',
+ 'LPAREN','RPAREN',
+ )
+
+# Tokens
+
+t_PLUS = r'\+'
+t_MINUS = r'-'
+t_TIMES = r'\*'
+t_DIVIDE = r'/'
+t_EQUALS = r'='
+t_LPAREN = r'\('
+t_RPAREN = r'\)'
+t_NAME = r'[a-zA-Z_][a-zA-Z0-9_]*'
+
+def t_NUMBER(t):
+ r'\d+'
+ try:
+ t.value = int(t.value)
+ except ValueError:
+ print "Integer value too large", t.value
+ t.value = 0
+ return t
+
+t_ignore = " \t"
+
+def t_newline(t):
+ r'\n+'
+ t.lineno += t.value.count("\n")
+
+def t_error(t):
+ print "Illegal character '%s'" % t.value[0]
+ t.skip(1)
+
+# Build the lexer
+import lex
+lex.lex(optimize=1)
+
+# Parsing rules
+
+precedence = (
+ ('left','PLUS','MINUS'),
+ ('left','TIMES','DIVIDE'),
+ ('right','UMINUS'),
+ )
+
+# dictionary of names
+names = { }
+
+def p_statement_assign(t):
+ 'statement : NAME EQUALS expression'
+ names[t[1]] = t[3]
+
+def p_statement_expr(t):
+ 'statement : expression'
+ print t[1]
+
+def p_expression_binop(t):
+ '''expression : expression PLUS expression
+ | expression MINUS expression
+ | expression TIMES expression
+ | expression DIVIDE expression'''
+ if t[2] == '+' : t[0] = t[1] + t[3]
+ elif t[2] == '-': t[0] = t[1] - t[3]
+ elif t[2] == '*': t[0] = t[1] * t[3]
+ elif t[2] == '/': t[0] = t[1] / t[3]
+ elif t[2] == '<': t[0] = t[1] < t[3]
+
+def p_expression_uminus(t):
+ 'expression : MINUS expression %prec UMINUS'
+ t[0] = -t[2]
+
+def p_expression_group(t):
+ 'expression : LPAREN expression RPAREN'
+ t[0] = t[2]
+
+def p_expression_number(t):
+ 'expression : NUMBER'
+ t[0] = t[1]
+
+def p_expression_name(t):
+ 'expression : NAME'
+ try:
+ t[0] = names[t[1]]
+ except LookupError:
+ print "Undefined name '%s'" % t[1]
+ t[0] = 0
+
+def p_error(t):
+ print "Syntax error at '%s'" % t.value
+
+import yacc
+yacc.yacc(optimize=1)
+
+while 1:
+ try:
+ s = raw_input('calc > ')
+ except EOFError:
+ break
+ yacc.parse(s)
+
diff --git a/ext/ply/lex.py b/ext/ply/lex.py
new file mode 100644
index 000000000..7ad7a394b
--- /dev/null
+++ b/ext/ply/lex.py
@@ -0,0 +1,681 @@
+#-----------------------------------------------------------------------------
+# ply: lex.py
+#
+# Author: David M. Beazley (beazley@cs.uchicago.edu)
+# Department of Computer Science
+# University of Chicago
+# Chicago, IL 60637
+#
+# Copyright (C) 2001, David M. Beazley
+#
+# $Header: /home/stever/bk/newmem2/ext/ply/lex.py 1.1 03/06/06 14:53:34-00:00 stever@ $
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+# See the file COPYING for a complete copy of the LGPL.
+#
+#
+# This module automatically constructs a lexical analysis module from regular
+# expression rules defined in a user-defined module. The idea is essentially the same
+# as that used in John Aycock's Spark framework, but the implementation works
+# at the module level rather than requiring the use of classes.
+#
+# This module tries to provide an interface that is closely modeled after
+# the traditional lex interface in Unix. It also differs from Spark
+# in that:
+#
+# - It provides more extensive error checking and reporting if
+# the user supplies a set of regular expressions that can't
+# be compiled or if there is any other kind of a problem in
+# the specification.
+#
+# - The interface is geared towards LALR(1) and LR(1) parser
+# generators. That is tokens are generated one at a time
+# rather than being generated in advanced all in one step.
+#
+# There are a few limitations of this module
+#
+# - The module interface makes it somewhat awkward to support more
+# than one lexer at a time. Although somewhat inelegant from a
+# design perspective, this is rarely a practical concern for
+# most compiler projects.
+#
+# - The lexer requires that the entire input text be read into
+# a string before scanning. I suppose that most machines have
+# enough memory to make this a minor issues, but it makes
+# the lexer somewhat difficult to use in interactive sessions
+# or with streaming data.
+#
+#-----------------------------------------------------------------------------
+
+r"""
+lex.py
+
+This module builds lex-like scanners based on regular expression rules.
+To use the module, simply write a collection of regular expression rules
+and actions like this:
+
+# lexer.py
+import lex
+
+# Define a list of valid tokens
+tokens = (
+ 'IDENTIFIER', 'NUMBER', 'PLUS', 'MINUS'
+ )
+
+# Define tokens as functions
+def t_IDENTIFIER(t):
+ r' ([a-zA-Z_](\w|_)* '
+ return t
+
+def t_NUMBER(t):
+ r' \d+ '
+ return t
+
+# Some simple tokens with no actions
+t_PLUS = r'\+'
+t_MINUS = r'-'
+
+# Initialize the lexer
+lex.lex()
+
+The tokens list is required and contains a complete list of all valid
+token types that the lexer is allowed to produce. Token types are
+restricted to be valid identifiers. This means that 'MINUS' is a valid
+token type whereas '-' is not.
+
+Rules are defined by writing a function with a name of the form
+t_rulename. Each rule must accept a single argument which is
+a token object generated by the lexer. This token has the following
+attributes:
+
+ t.type = type string of the token. This is initially set to the
+ name of the rule without the leading t_
+ t.value = The value of the lexeme.
+ t.lineno = The value of the line number where the token was encountered
+
+For example, the t_NUMBER() rule above might be called with the following:
+
+ t.type = 'NUMBER'
+ t.value = '42'
+ t.lineno = 3
+
+Each rule returns the token object it would like to supply to the
+parser. In most cases, the token t is returned with few, if any
+modifications. To discard a token for things like whitespace or
+comments, simply return nothing. For instance:
+
+def t_whitespace(t):
+ r' \s+ '
+ pass
+
+For faster lexing, you can also define this in terms of the ignore set like this:
+
+t_ignore = ' \t'
+
+The characters in this string are ignored by the lexer. Use of this feature can speed
+up parsing significantly since scanning will immediately proceed to the next token.
+
+lex requires that the token returned by each rule has an attribute
+t.type. Other than this, rules are free to return any kind of token
+object that they wish and may construct a new type of token object
+from the attributes of t (provided the new object has the required
+type attribute).
+
+If illegal characters are encountered, the scanner executes the
+function t_error(t) where t is a token representing the rest of the
+string that hasn't been matched. If this function isn't defined, a
+LexError exception is raised. The .text attribute of this exception
+object contains the part of the string that wasn't matched.
+
+The t.skip(n) method can be used to skip ahead n characters in the
+input stream. This is usually only used in the error handling rule.
+For instance, the following rule would print an error message and
+continue:
+
+def t_error(t):
+ print "Illegal character in input %s" % t.value[0]
+ t.skip(1)
+
+Of course, a nice scanner might wish to skip more than one character
+if the input looks very corrupted.
+
+The lex module defines a t.lineno attribute on each token that can be used
+to track the current line number in the input. The value of this
+variable is not modified by lex so it is up to your lexer module
+to correctly update its value depending on the lexical properties
+of the input language. To do this, you might write rules such as
+the following:
+
+def t_newline(t):
+ r' \n+ '
+ t.lineno += t.value.count("\n")
+
+To initialize your lexer so that it can be used, simply call the lex.lex()
+function in your rule file. If there are any errors in your
+specification, warning messages or an exception will be generated to
+alert you to the problem.
+
+(dave: this needs to be rewritten)
+To use the newly constructed lexer from another module, simply do
+this:
+
+ import lex
+ import lexer
+ plex.input("position = initial + rate*60")
+
+ while 1:
+ token = plex.token() # Get a token
+ if not token: break # No more tokens
+ ... do whatever ...
+
+Assuming that the module 'lexer' has initialized plex as shown
+above, parsing modules can safely import 'plex' without having
+to import the rule file or any additional imformation about the
+scanner you have defined.
+"""
+
+# -----------------------------------------------------------------------------
+
+
+__version__ = "1.3"
+
+import re, types, sys, copy
+
+# Exception thrown when invalid token encountered and no default
+class LexError(Exception):
+ def __init__(self,message,s):
+ self.args = (message,)
+ self.text = s
+
+# Token class
+class LexToken:
+ def __str__(self):
+ return "LexToken(%s,%r,%d)" % (self.type,self.value,self.lineno)
+ def __repr__(self):
+ return str(self)
+ def skip(self,n):
+ try:
+ self._skipn += n
+ except AttributeError:
+ self._skipn = n
+
+# -----------------------------------------------------------------------------
+# Lexer class
+#
+# input() - Store a new string in the lexer
+# token() - Get the next token
+# -----------------------------------------------------------------------------
+
+class Lexer:
+ def __init__(self):
+ self.lexre = None # Master regular expression
+ self.lexdata = None # Actual input data (as a string)
+ self.lexpos = 0 # Current position in input text
+ self.lexlen = 0 # Length of the input text
+ self.lexindexfunc = [ ] # Reverse mapping of groups to functions and types
+ self.lexerrorf = None # Error rule (if any)
+ self.lextokens = None # List of valid tokens
+ self.lexignore = None # Ignored characters
+ self.lineno = 1 # Current line number
+ self.debug = 0 # Debugging mode
+ self.optimize = 0 # Optimized mode
+ self.token = self.errtoken
+
+ def __copy__(self):
+ c = Lexer()
+ c.lexre = self.lexre
+ c.lexdata = self.lexdata
+ c.lexpos = self.lexpos
+ c.lexlen = self.lexlen
+ c.lenindexfunc = self.lexindexfunc
+ c.lexerrorf = self.lexerrorf
+ c.lextokens = self.lextokens
+ c.lexignore = self.lexignore
+ c.lineno = self.lineno
+ c.optimize = self.optimize
+ c.token = c.realtoken
+
+ # ------------------------------------------------------------
+ # input() - Push a new string into the lexer
+ # ------------------------------------------------------------
+ def input(self,s):
+ if not isinstance(s,types.StringType):
+ raise ValueError, "Expected a string"
+ self.lexdata = s
+ self.lexpos = 0
+ self.lexlen = len(s)
+ self.token = self.realtoken
+
+ # Change the token routine to point to realtoken()
+ global token
+ if token == self.errtoken:
+ token = self.token
+
+ # ------------------------------------------------------------
+ # errtoken() - Return error if token is called with no data
+ # ------------------------------------------------------------
+ def errtoken(self):
+ raise RuntimeError, "No input string given with input()"
+
+ # ------------------------------------------------------------
+ # token() - Return the next token from the Lexer
+ #
+ # Note: This function has been carefully implemented to be as fast
+ # as possible. Don't make changes unless you really know what
+ # you are doing
+ # ------------------------------------------------------------
+ def realtoken(self):
+ # Make local copies of frequently referenced attributes
+ lexpos = self.lexpos
+ lexlen = self.lexlen
+ lexignore = self.lexignore
+ lexdata = self.lexdata
+
+ while lexpos < lexlen:
+ # This code provides some short-circuit code for whitespace, tabs, and other ignored characters
+ if lexdata[lexpos] in lexignore:
+ lexpos += 1
+ continue
+
+ # Look for a regular expression match
+ m = self.lexre.match(lexdata,lexpos)
+ if m:
+ i = m.lastindex
+ lexpos = m.end()
+ tok = LexToken()
+ tok.value = m.group()
+ tok.lineno = self.lineno
+ tok.lexer = self
+ func,tok.type = self.lexindexfunc[i]
+ if not func:
+ self.lexpos = lexpos
+ return tok
+
+ # If token is processed by a function, call it
+ self.lexpos = lexpos
+ newtok = func(tok)
+ self.lineno = tok.lineno # Update line number
+
+ # Every function must return a token, if nothing, we just move to next token
+ if not newtok: continue
+
+ # Verify type of the token. If not in the token map, raise an error
+ if not self.optimize:
+ if not self.lextokens.has_key(newtok.type):
+ raise LexError, ("%s:%d: Rule '%s' returned an unknown token type '%s'" % (
+ func.func_code.co_filename, func.func_code.co_firstlineno,
+ func.__name__, newtok.type),lexdata[lexpos:])
+
+ return newtok
+
+ # No match. Call t_error() if defined.
+ if self.lexerrorf:
+ tok = LexToken()
+ tok.value = self.lexdata[lexpos:]
+ tok.lineno = self.lineno
+ tok.type = "error"
+ tok.lexer = self
+ oldpos = lexpos
+ newtok = self.lexerrorf(tok)
+ lexpos += getattr(tok,"_skipn",0)
+ if oldpos == lexpos:
+ # Error method didn't change text position at all. This is an error.
+ self.lexpos = lexpos
+ raise LexError, ("Scanning error. Illegal character '%s'" % (lexdata[lexpos]), lexdata[lexpos:])
+ if not newtok: continue
+ self.lexpos = lexpos
+ return newtok
+
+ self.lexpos = lexpos
+ raise LexError, ("No match found", lexdata[lexpos:])
+
+ # No more input data
+ self.lexpos = lexpos + 1
+ return None
+
+
+# -----------------------------------------------------------------------------
+# validate_file()
+#
+# This checks to see if there are duplicated t_rulename() functions or strings
+# in the parser input file. This is done using a simple regular expression
+# match on each line in the filename.
+# -----------------------------------------------------------------------------
+
+def validate_file(filename):
+ import os.path
+ base,ext = os.path.splitext(filename)
+ if ext != '.py': return 1 # No idea what the file is. Return OK
+
+ try:
+ f = open(filename)
+ lines = f.readlines()
+ f.close()
+ except IOError:
+ return 1 # Oh well
+
+ fre = re.compile(r'\s*def\s+(t_[a-zA-Z_0-9]*)\(')
+ sre = re.compile(r'\s*(t_[a-zA-Z_0-9]*)\s*=')
+ counthash = { }
+ linen = 1
+ noerror = 1
+ for l in lines:
+ m = fre.match(l)
+ if not m:
+ m = sre.match(l)
+ if m:
+ name = m.group(1)
+ prev = counthash.get(name)
+ if not prev:
+ counthash[name] = linen
+ else:
+ print "%s:%d: Rule %s redefined. Previously defined on line %d" % (filename,linen,name,prev)
+ noerror = 0
+ linen += 1
+ return noerror
+
+# -----------------------------------------------------------------------------
+# _read_lextab(module)
+#
+# Reads lexer table from a lextab file instead of using introspection.
+# -----------------------------------------------------------------------------
+
+def _read_lextab(lexer, fdict, module):
+ exec "import %s as lextab" % module
+ lexer.lexre = re.compile(lextab._lexre, re.VERBOSE)
+ lexer.lexindexfunc = lextab._lextab
+ for i in range(len(lextab._lextab)):
+ t = lexer.lexindexfunc[i]
+ if t:
+ if t[0]:
+ lexer.lexindexfunc[i] = (fdict[t[0]],t[1])
+ lexer.lextokens = lextab._lextokens
+ lexer.lexignore = lextab._lexignore
+ if lextab._lexerrorf:
+ lexer.lexerrorf = fdict[lextab._lexerrorf]
+
+# -----------------------------------------------------------------------------
+# lex(module)
+#
+# Build all of the regular expression rules from definitions in the supplied module
+# -----------------------------------------------------------------------------
+def lex(module=None,debug=0,optimize=0,lextab="lextab"):
+ ldict = None
+ regex = ""
+ error = 0
+ files = { }
+ lexer = Lexer()
+ lexer.debug = debug
+ lexer.optimize = optimize
+ global token,input
+
+ if module:
+ if not isinstance(module, types.ModuleType):
+ raise ValueError,"Expected a module"
+
+ ldict = module.__dict__
+
+ else:
+ # No module given. We might be able to get information from the caller.
+ try:
+ raise RuntimeError
+ except RuntimeError:
+ e,b,t = sys.exc_info()
+ f = t.tb_frame
+ f = f.f_back # Walk out to our calling function
+ ldict = f.f_globals # Grab its globals dictionary
+
+ if optimize and lextab:
+ try:
+ _read_lextab(lexer,ldict, lextab)
+ if not lexer.lexignore: lexer.lexignore = ""
+ token = lexer.token
+ input = lexer.input
+ return lexer
+
+ except ImportError:
+ pass
+
+ # Get the tokens map
+ tokens = ldict.get("tokens",None)
+ if not tokens:
+ raise SyntaxError,"lex: module does not define 'tokens'"
+ if not (isinstance(tokens,types.ListType) or isinstance(tokens,types.TupleType)):
+ raise SyntaxError,"lex: tokens must be a list or tuple."
+
+ # Build a dictionary of valid token names
+ lexer.lextokens = { }
+ if not optimize:
+
+ # Utility function for verifying tokens
+ def is_identifier(s):
+ for c in s:
+ if not (c.isalnum() or c == '_'): return 0
+ return 1
+
+ for n in tokens:
+ if not is_identifier(n):
+ print "lex: Bad token name '%s'" % n
+ error = 1
+ if lexer.lextokens.has_key(n):
+ print "lex: Warning. Token '%s' multiply defined." % n
+ lexer.lextokens[n] = None
+ else:
+ for n in tokens: lexer.lextokens[n] = None
+
+
+ if debug:
+ print "lex: tokens = '%s'" % lexer.lextokens.keys()
+
+ # Get a list of symbols with the t_ prefix
+ tsymbols = [f for f in ldict.keys() if f[:2] == 't_']
+
+ # Now build up a list of functions and a list of strings
+ fsymbols = [ ]
+ ssymbols = [ ]
+ for f in tsymbols:
+ if isinstance(ldict[f],types.FunctionType):
+ fsymbols.append(ldict[f])
+ elif isinstance(ldict[f],types.StringType):
+ ssymbols.append((f,ldict[f]))
+ else:
+ print "lex: %s not defined as a function or string" % f
+ error = 1
+
+ # Sort the functions by line number
+ fsymbols.sort(lambda x,y: cmp(x.func_code.co_firstlineno,y.func_code.co_firstlineno))
+
+ # Sort the strings by regular expression length
+ ssymbols.sort(lambda x,y: (len(x[1]) < len(y[1])) - (len(x[1]) > len(y[1])))
+
+ # Check for non-empty symbols
+ if len(fsymbols) == 0 and len(ssymbols) == 0:
+ raise SyntaxError,"lex: no rules of the form t_rulename are defined."
+
+ # Add all of the rules defined with actions first
+ for f in fsymbols:
+
+ line = f.func_code.co_firstlineno
+ file = f.func_code.co_filename
+ files[file] = None
+
+ if not optimize:
+ if f.func_code.co_argcount > 1:
+ print "%s:%d: Rule '%s' has too many arguments." % (file,line,f.__name__)
+ error = 1
+ continue
+
+ if f.func_code.co_argcount < 1:
+ print "%s:%d: Rule '%s' requires an argument." % (file,line,f.__name__)
+ error = 1
+ continue
+
+ if f.__name__ == 't_ignore':
+ print "%s:%d: Rule '%s' must be defined as a string." % (file,line,f.__name__)
+ error = 1
+ continue
+
+ if f.__name__ == 't_error':
+ lexer.lexerrorf = f
+ continue
+
+ if f.__doc__:
+ if not optimize:
+ try:
+ c = re.compile(f.__doc__, re.VERBOSE)
+ except re.error,e:
+ print "%s:%d: Invalid regular expression for rule '%s'. %s" % (file,line,f.__name__,e)
+ error = 1
+ continue
+
+ if debug:
+ print "lex: Adding rule %s -> '%s'" % (f.__name__,f.__doc__)
+
+ # Okay. The regular expression seemed okay. Let's append it to the master regular
+ # expression we're building
+
+ if (regex): regex += "|"
+ regex += "(?P<%s>%s)" % (f.__name__,f.__doc__)
+ else:
+ print "%s:%d: No regular expression defined for rule '%s'" % (file,line,f.__name__)
+
+ # Now add all of the simple rules
+ for name,r in ssymbols:
+
+ if name == 't_ignore':
+ lexer.lexignore = r
+ continue
+
+ if not optimize:
+ if name == 't_error':
+ raise SyntaxError,"lex: Rule 't_error' must be defined as a function"
+ error = 1
+ continue
+
+ if not lexer.lextokens.has_key(name[2:]):
+ print "lex: Rule '%s' defined for an unspecified token %s." % (name,name[2:])
+ error = 1
+ continue
+ try:
+ c = re.compile(r,re.VERBOSE)
+ except re.error,e:
+ print "lex: Invalid regular expression for rule '%s'. %s" % (name,e)
+ error = 1
+ continue
+ if debug:
+ print "lex: Adding rule %s -> '%s'" % (name,r)
+
+ if regex: regex += "|"
+ regex += "(?P<%s>%s)" % (name,r)
+
+ if not optimize:
+ for f in files.keys():
+ if not validate_file(f):
+ error = 1
+ try:
+ if debug:
+ print "lex: regex = '%s'" % regex
+ lexer.lexre = re.compile(regex, re.VERBOSE)
+
+ # Build the index to function map for the matching engine
+ lexer.lexindexfunc = [ None ] * (max(lexer.lexre.groupindex.values())+1)
+ for f,i in lexer.lexre.groupindex.items():
+ handle = ldict[f]
+ if isinstance(handle,types.FunctionType):
+ lexer.lexindexfunc[i] = (handle,handle.__name__[2:])
+ else:
+ # If rule was specified as a string, we build an anonymous
+ # callback function to carry out the action
+ lexer.lexindexfunc[i] = (None,f[2:])
+
+ # If a lextab was specified, we create a file containing the precomputed
+ # regular expression and index table
+
+ if lextab and optimize:
+ lt = open(lextab+".py","w")
+ lt.write("# %s.py. This file automatically created by PLY. Don't edit.\n" % lextab)
+ lt.write("_lexre = %s\n" % repr(regex))
+ lt.write("_lextab = [\n");
+ for i in range(0,len(lexer.lexindexfunc)):
+ t = lexer.lexindexfunc[i]
+ if t:
+ if t[0]:
+ lt.write(" ('%s',%s),\n"% (t[0].__name__, repr(t[1])))
+ else:
+ lt.write(" (None,%s),\n" % repr(t[1]))
+ else:
+ lt.write(" None,\n")
+
+ lt.write("]\n");
+ lt.write("_lextokens = %s\n" % repr(lexer.lextokens))
+ lt.write("_lexignore = %s\n" % repr(lexer.lexignore))
+ if (lexer.lexerrorf):
+ lt.write("_lexerrorf = %s\n" % repr(lexer.lexerrorf.__name__))
+ else:
+ lt.write("_lexerrorf = None\n")
+ lt.close()
+
+ except re.error,e:
+ print "lex: Fatal error. Unable to compile regular expression rules. %s" % e
+ error = 1
+ if error:
+ raise SyntaxError,"lex: Unable to build lexer."
+ if not lexer.lexerrorf:
+ print "lex: Warning. no t_error rule is defined."
+
+ if not lexer.lexignore: lexer.lexignore = ""
+
+ # Create global versions of the token() and input() functions
+ token = lexer.token
+ input = lexer.input
+
+ return lexer
+
+# -----------------------------------------------------------------------------
+# run()
+#
+# This runs the lexer as a main program
+# -----------------------------------------------------------------------------
+
+def runmain(lexer=None,data=None):
+ if not data:
+ try:
+ filename = sys.argv[1]
+ f = open(filename)
+ data = f.read()
+ f.close()
+ except IndexError:
+ print "Reading from standard input (type EOF to end):"
+ data = sys.stdin.read()
+
+ if lexer:
+ _input = lexer.input
+ else:
+ _input = input
+ _input(data)
+ if lexer:
+ _token = lexer.token
+ else:
+ _token = token
+
+ while 1:
+ tok = _token()
+ if not tok: break
+ print "(%s,'%s',%d)" % (tok.type, tok.value, tok.lineno)
+
+
+
+
diff --git a/ext/ply/test/README b/ext/ply/test/README
new file mode 100644
index 000000000..bca748497
--- /dev/null
+++ b/ext/ply/test/README
@@ -0,0 +1,9 @@
+This directory mostly contains tests for various types of error
+conditions. To run:
+
+ $ python testlex.py .
+ $ python testyacc.py .
+
+(make sure lex.py and yacc.py exist in this directory before
+running the tests).
+
diff --git a/ext/ply/test/calclex.py b/ext/ply/test/calclex.py
new file mode 100644
index 000000000..f8eb91a09
--- /dev/null
+++ b/ext/ply/test/calclex.py
@@ -0,0 +1,46 @@
+# -----------------------------------------------------------------------------
+# calclex.py
+# -----------------------------------------------------------------------------
+
+tokens = (
+ 'NAME','NUMBER',
+ 'PLUS','MINUS','TIMES','DIVIDE','EQUALS',
+ 'LPAREN','RPAREN',
+ )
+
+# Tokens
+
+t_PLUS = r'\+'
+t_MINUS = r'-'
+t_TIMES = r'\*'
+t_DIVIDE = r'/'
+t_EQUALS = r'='
+t_LPAREN = r'\('
+t_RPAREN = r'\)'
+t_NAME = r'[a-zA-Z_][a-zA-Z0-9_]*'
+
+def t_NUMBER(t):
+ r'\d+'
+ try:
+ t.value = int(t.value)
+ except ValueError:
+ print "Integer value too large", t.value
+ t.value = 0
+ return t
+
+t_ignore = " \t"
+
+def t_newline(t):
+ r'\n+'
+ t.lineno += t.value.count("\n")
+
+def t_error(t):
+ print "Illegal character '%s'" % t.value[0]
+ t.skip(1)
+
+# Build the lexer
+import lex
+lex.lex()
+
+
+
diff --git a/ext/ply/test/lex_doc1.exp b/ext/ply/test/lex_doc1.exp
new file mode 100644
index 000000000..29381911d
--- /dev/null
+++ b/ext/ply/test/lex_doc1.exp
@@ -0,0 +1 @@
+./lex_doc1.py:15: No regular expression defined for rule 't_NUMBER'
diff --git a/ext/ply/test/lex_doc1.py b/ext/ply/test/lex_doc1.py
new file mode 100644
index 000000000..fb0fb885e
--- /dev/null
+++ b/ext/ply/test/lex_doc1.py
@@ -0,0 +1,27 @@
+# lex_token.py
+#
+# Missing documentation string
+
+import lex
+
+tokens = [
+ "PLUS",
+ "MINUS",
+ "NUMBER",
+ ]
+
+t_PLUS = r'\+'
+t_MINUS = r'-'
+def t_NUMBER(t):
+ pass
+
+def t_error(t):
+ pass
+
+
+import sys
+sys.tracebacklimit = 0
+
+lex.lex()
+
+
diff --git a/ext/ply/test/lex_dup1.exp b/ext/ply/test/lex_dup1.exp
new file mode 100644
index 000000000..22bca3190
--- /dev/null
+++ b/ext/ply/test/lex_dup1.exp
@@ -0,0 +1,2 @@
+./lex_dup1.py:17: Rule t_NUMBER redefined. Previously defined on line 15
+SyntaxError: lex: Unable to build lexer.
diff --git a/ext/ply/test/lex_dup1.py b/ext/ply/test/lex_dup1.py
new file mode 100644
index 000000000..88bbe00e9
--- /dev/null
+++ b/ext/ply/test/lex_dup1.py
@@ -0,0 +1,27 @@
+# lex_token.py
+#
+# Duplicated rule specifiers
+
+import lex
+
+tokens = [
+ "PLUS",
+ "MINUS",
+ "NUMBER",
+ ]
+
+t_PLUS = r'\+'
+t_MINUS = r'-'
+t_NUMBER = r'\d+'
+
+t_NUMBER = r'\d+'
+
+def t_error(t):
+ pass
+
+import sys
+sys.tracebacklimit = 0
+
+lex.lex()
+
+
diff --git a/ext/ply/test/lex_dup2.exp b/ext/ply/test/lex_dup2.exp
new file mode 100644
index 000000000..883bdad46
--- /dev/null
+++ b/ext/ply/test/lex_dup2.exp
@@ -0,0 +1,2 @@
+./lex_dup2.py:19: Rule t_NUMBER redefined. Previously defined on line 15
+SyntaxError: lex: Unable to build lexer.
diff --git a/ext/ply/test/lex_dup2.py b/ext/ply/test/lex_dup2.py
new file mode 100644
index 000000000..65e0b21a2
--- /dev/null
+++ b/ext/ply/test/lex_dup2.py
@@ -0,0 +1,31 @@
+# lex_token.py
+#
+# Duplicated rule specifiers
+
+import lex
+
+tokens = [
+ "PLUS",
+ "MINUS",
+ "NUMBER",
+ ]
+
+t_PLUS = r'\+'
+t_MINUS = r'-'
+def t_NUMBER(t):
+ r'\d+'
+ pass
+
+def t_NUMBER(t):
+ r'\d+'
+ pass
+
+def t_error(t):
+ pass
+
+import sys
+sys.tracebacklimit = 0
+
+lex.lex()
+
+
diff --git a/ext/ply/test/lex_dup3.exp b/ext/ply/test/lex_dup3.exp
new file mode 100644
index 000000000..916612aa1
--- /dev/null
+++ b/ext/ply/test/lex_dup3.exp
@@ -0,0 +1,2 @@
+./lex_dup3.py:17: Rule t_NUMBER redefined. Previously defined on line 15
+SyntaxError: lex: Unable to build lexer.
diff --git a/ext/ply/test/lex_dup3.py b/ext/ply/test/lex_dup3.py
new file mode 100644
index 000000000..424101823
--- /dev/null
+++ b/ext/ply/test/lex_dup3.py
@@ -0,0 +1,29 @@
+# lex_token.py
+#
+# Duplicated rule specifiers
+
+import lex
+
+tokens = [
+ "PLUS",
+ "MINUS",
+ "NUMBER",
+ ]
+
+t_PLUS = r'\+'
+t_MINUS = r'-'
+t_NUMBER = r'\d+'
+
+def t_NUMBER(t):
+ r'\d+'
+ pass
+
+def t_error(t):
+ pass
+
+import sys
+sys.tracebacklimit = 0
+
+lex.lex()
+
+
diff --git a/ext/ply/test/lex_empty.exp b/ext/ply/test/lex_empty.exp
new file mode 100644
index 000000000..af38602d5
--- /dev/null
+++ b/ext/ply/test/lex_empty.exp
@@ -0,0 +1 @@
+SyntaxError: lex: no rules of the form t_rulename are defined.
diff --git a/ext/ply/test/lex_empty.py b/ext/ply/test/lex_empty.py
new file mode 100644
index 000000000..6472832f1
--- /dev/null
+++ b/ext/ply/test/lex_empty.py
@@ -0,0 +1,18 @@
+# lex_token.py
+#
+# No rules defined
+
+import lex
+
+tokens = [
+ "PLUS",
+ "MINUS",
+ "NUMBER",
+ ]
+
+import sys
+sys.tracebacklimit = 0
+
+lex.lex()
+
+
diff --git a/ext/ply/test/lex_error1.exp b/ext/ply/test/lex_error1.exp
new file mode 100644
index 000000000..baa19e5b3
--- /dev/null
+++ b/ext/ply/test/lex_error1.exp
@@ -0,0 +1 @@
+lex: Warning. no t_error rule is defined.
diff --git a/ext/ply/test/lex_error1.py b/ext/ply/test/lex_error1.py
new file mode 100644
index 000000000..ed7980346
--- /dev/null
+++ b/ext/ply/test/lex_error1.py
@@ -0,0 +1,22 @@
+# lex_token.py
+#
+# Missing t_error() rule
+
+import lex
+
+tokens = [
+ "PLUS",
+ "MINUS",
+ "NUMBER",
+ ]
+
+t_PLUS = r'\+'
+t_MINUS = r'-'
+t_NUMBER = r'\d+'
+
+import sys
+sys.tracebacklimit = 0
+
+lex.lex()
+
+
diff --git a/ext/ply/test/lex_error2.exp b/ext/ply/test/lex_error2.exp
new file mode 100644
index 000000000..fb1b55c8b
--- /dev/null
+++ b/ext/ply/test/lex_error2.exp
@@ -0,0 +1 @@
+SyntaxError: lex: Rule 't_error' must be defined as a function
diff --git a/ext/ply/test/lex_error2.py b/ext/ply/test/lex_error2.py
new file mode 100644
index 000000000..80020f72b
--- /dev/null
+++ b/ext/ply/test/lex_error2.py
@@ -0,0 +1,24 @@
+# lex_token.py
+#
+# t_error defined, but not function
+
+import lex
+
+tokens = [
+ "PLUS",
+ "MINUS",
+ "NUMBER",
+ ]
+
+t_PLUS = r'\+'
+t_MINUS = r'-'
+t_NUMBER = r'\d+'
+
+t_error = "foo"
+
+import sys
+sys.tracebacklimit = 0
+
+lex.lex()
+
+
diff --git a/ext/ply/test/lex_error3.exp b/ext/ply/test/lex_error3.exp
new file mode 100644
index 000000000..936828f93
--- /dev/null
+++ b/ext/ply/test/lex_error3.exp
@@ -0,0 +1,2 @@
+./lex_error3.py:17: Rule 't_error' requires an argument.
+SyntaxError: lex: Unable to build lexer.
diff --git a/ext/ply/test/lex_error3.py b/ext/ply/test/lex_error3.py
new file mode 100644
index 000000000..46facf589
--- /dev/null
+++ b/ext/ply/test/lex_error3.py
@@ -0,0 +1,25 @@
+# lex_token.py
+#
+# t_error defined as function, but with wrong # args
+
+import lex
+
+tokens = [
+ "PLUS",
+ "MINUS",
+ "NUMBER",
+ ]
+
+t_PLUS = r'\+'
+t_MINUS = r'-'
+t_NUMBER = r'\d+'
+
+def t_error():
+ pass
+
+import sys
+sys.tracebacklimit = 0
+
+lex.lex()
+
+
diff --git a/ext/ply/test/lex_error4.exp b/ext/ply/test/lex_error4.exp
new file mode 100644
index 000000000..242516576
--- /dev/null
+++ b/ext/ply/test/lex_error4.exp
@@ -0,0 +1,2 @@
+./lex_error4.py:17: Rule 't_error' has too many arguments.
+SyntaxError: lex: Unable to build lexer.
diff --git a/ext/ply/test/lex_error4.py b/ext/ply/test/lex_error4.py
new file mode 100644
index 000000000..d777fee84
--- /dev/null
+++ b/ext/ply/test/lex_error4.py
@@ -0,0 +1,25 @@
+# lex_token.py
+#
+# t_error defined as function, but too many args
+
+import lex
+
+tokens = [
+ "PLUS",
+ "MINUS",
+ "NUMBER",
+ ]
+
+t_PLUS = r'\+'
+t_MINUS = r'-'
+t_NUMBER = r'\d+'
+
+def t_error(t,s):
+ pass
+
+import sys
+sys.tracebacklimit = 0
+
+lex.lex()
+
+
diff --git a/ext/ply/test/lex_hedit.exp b/ext/ply/test/lex_hedit.exp
new file mode 100644
index 000000000..0b09827c6
--- /dev/null
+++ b/ext/ply/test/lex_hedit.exp
@@ -0,0 +1,3 @@
+(H_EDIT_DESCRIPTOR,'abc',1)
+(H_EDIT_DESCRIPTOR,'abcdefghij',1)
+(H_EDIT_DESCRIPTOR,'xy',1)
diff --git a/ext/ply/test/lex_hedit.py b/ext/ply/test/lex_hedit.py
new file mode 100644
index 000000000..68f9fcbd1
--- /dev/null
+++ b/ext/ply/test/lex_hedit.py
@@ -0,0 +1,44 @@
+# -----------------------------------------------------------------------------
+# hedit.py
+#
+# Paring of Fortran H Edit descriptions (Contributed by Pearu Peterson)
+#
+# These tokens can't be easily tokenized because they are of the following
+# form:
+#
+# nHc1...cn
+#
+# where n is a positive integer and c1 ... cn are characters.
+#
+# This example shows how to modify the state of the lexer to parse
+# such tokens
+# -----------------------------------------------------------------------------
+
+tokens = (
+ 'H_EDIT_DESCRIPTOR',
+ )
+
+# Tokens
+t_ignore = " \t\n"
+
+def t_H_EDIT_DESCRIPTOR(t):
+ r"\d+H.*" # This grabs all of the remaining text
+ i = t.value.index('H')
+ n = eval(t.value[:i])
+
+ # Adjust the tokenizing position
+ t.lexer.lexpos -= len(t.value) - (i+1+n)
+ t.value = t.value[i+1:i+1+n]
+ return t
+
+def t_error(t):
+ print "Illegal character '%s'" % t.value[0]
+ t.skip(1)
+
+# Build the lexer
+import lex
+lex.lex()
+lex.runmain(data="3Habc 10Habcdefghij 2Hxy")
+
+
+
diff --git a/ext/ply/test/lex_ignore.exp b/ext/ply/test/lex_ignore.exp
new file mode 100644
index 000000000..c3b04a154
--- /dev/null
+++ b/ext/ply/test/lex_ignore.exp
@@ -0,0 +1,2 @@
+./lex_ignore.py:17: Rule 't_ignore' must be defined as a string.
+SyntaxError: lex: Unable to build lexer.
diff --git a/ext/ply/test/lex_ignore.py b/ext/ply/test/lex_ignore.py
new file mode 100644
index 000000000..49c303f81
--- /dev/null
+++ b/ext/ply/test/lex_ignore.py
@@ -0,0 +1,29 @@
+# lex_token.py
+#
+# Improperly specific ignore declaration
+
+import lex
+
+tokens = [
+ "PLUS",
+ "MINUS",
+ "NUMBER",
+ ]
+
+t_PLUS = r'\+'
+t_MINUS = r'-'
+t_NUMBER = r'\d+'
+
+def t_ignore(t):
+ ' \t'
+ pass
+
+def t_error(t):
+ pass
+
+import sys
+sys.tracebacklimit = 0
+
+lex.lex()
+
+
diff --git a/ext/ply/test/lex_re1.exp b/ext/ply/test/lex_re1.exp
new file mode 100644
index 000000000..634eefefe
--- /dev/null
+++ b/ext/ply/test/lex_re1.exp
@@ -0,0 +1,2 @@
+lex: Invalid regular expression for rule 't_NUMBER'. unbalanced parenthesis
+SyntaxError: lex: Unable to build lexer.
diff --git a/ext/ply/test/lex_re1.py b/ext/ply/test/lex_re1.py
new file mode 100644
index 000000000..4a055ad72
--- /dev/null
+++ b/ext/ply/test/lex_re1.py
@@ -0,0 +1,25 @@
+# lex_token.py
+#
+# Bad regular expression in a string
+
+import lex
+
+tokens = [
+ "PLUS",
+ "MINUS",
+ "NUMBER",
+ ]
+
+t_PLUS = r'\+'
+t_MINUS = r'-'
+t_NUMBER = r'(\d+'
+
+def t_error(t):
+ pass
+
+import sys
+sys.tracebacklimit = 0
+
+lex.lex()
+
+
diff --git a/ext/ply/test/lex_rule1.exp b/ext/ply/test/lex_rule1.exp
new file mode 100644
index 000000000..0c23ca294
--- /dev/null
+++ b/ext/ply/test/lex_rule1.exp
@@ -0,0 +1,2 @@
+lex: t_NUMBER not defined as a function or string
+SyntaxError: lex: Unable to build lexer.
diff --git a/ext/ply/test/lex_rule1.py b/ext/ply/test/lex_rule1.py
new file mode 100644
index 000000000..ff3764ea1
--- /dev/null
+++ b/ext/ply/test/lex_rule1.py
@@ -0,0 +1,25 @@
+# lex_token.py
+#
+# Rule defined as some other type
+
+import lex
+
+tokens = [
+ "PLUS",
+ "MINUS",
+ "NUMBER",
+ ]
+
+t_PLUS = r'\+'
+t_MINUS = r'-'
+t_NUMBER = 1
+
+def t_error(t):
+ pass
+
+import sys
+sys.tracebacklimit = 0
+
+lex.lex()
+
+
diff --git a/ext/ply/test/lex_token1.exp b/ext/ply/test/lex_token1.exp
new file mode 100644
index 000000000..3792831fa
--- /dev/null
+++ b/ext/ply/test/lex_token1.exp
@@ -0,0 +1 @@
+SyntaxError: lex: module does not define 'tokens'
diff --git a/ext/ply/test/lex_token1.py b/ext/ply/test/lex_token1.py
new file mode 100644
index 000000000..e8eca2b63
--- /dev/null
+++ b/ext/ply/test/lex_token1.py
@@ -0,0 +1,19 @@
+# lex_token.py
+#
+# Tests for absence of tokens variable
+
+import lex
+
+t_PLUS = r'\+'
+t_MINUS = r'-'
+t_NUMBER = r'\d+'
+
+def t_error(t):
+ pass
+
+import sys
+sys.tracebacklimit = 0
+
+lex.lex()
+
+
diff --git a/ext/ply/test/lex_token2.exp b/ext/ply/test/lex_token2.exp
new file mode 100644
index 000000000..3f98fe51d
--- /dev/null
+++ b/ext/ply/test/lex_token2.exp
@@ -0,0 +1 @@
+SyntaxError: lex: tokens must be a list or tuple.
diff --git a/ext/ply/test/lex_token2.py b/ext/ply/test/lex_token2.py
new file mode 100644
index 000000000..38b34dabe
--- /dev/null
+++ b/ext/ply/test/lex_token2.py
@@ -0,0 +1,21 @@
+# lex_token.py
+#
+# Tests for tokens of wrong type
+
+import lex
+
+tokens = "PLUS MINUS NUMBER"
+
+t_PLUS = r'\+'
+t_MINUS = r'-'
+t_NUMBER = r'\d+'
+
+def t_error(t):
+ pass
+
+import sys
+sys.tracebacklimit = 0
+
+lex.lex()
+
+
diff --git a/ext/ply/test/lex_token3.exp b/ext/ply/test/lex_token3.exp
new file mode 100644
index 000000000..d991d3c37
--- /dev/null
+++ b/ext/ply/test/lex_token3.exp
@@ -0,0 +1,2 @@
+lex: Rule 't_MINUS' defined for an unspecified token MINUS.
+SyntaxError: lex: Unable to build lexer.
diff --git a/ext/ply/test/lex_token3.py b/ext/ply/test/lex_token3.py
new file mode 100644
index 000000000..909f9180d
--- /dev/null
+++ b/ext/ply/test/lex_token3.py
@@ -0,0 +1,24 @@
+# lex_token.py
+#
+# tokens is right type, but is missing a token for one rule
+
+import lex
+
+tokens = [
+ "PLUS",
+ "NUMBER",
+ ]
+
+t_PLUS = r'\+'
+t_MINUS = r'-'
+t_NUMBER = r'\d+'
+
+def t_error(t):
+ pass
+
+import sys
+sys.tracebacklimit = 0
+
+lex.lex()
+
+
diff --git a/ext/ply/test/lex_token4.exp b/ext/ply/test/lex_token4.exp
new file mode 100644
index 000000000..3dd88e05a
--- /dev/null
+++ b/ext/ply/test/lex_token4.exp
@@ -0,0 +1,2 @@
+lex: Bad token name '-'
+SyntaxError: lex: Unable to build lexer.
diff --git a/ext/ply/test/lex_token4.py b/ext/ply/test/lex_token4.py
new file mode 100644
index 000000000..d77d1662c
--- /dev/null
+++ b/ext/ply/test/lex_token4.py
@@ -0,0 +1,26 @@
+# lex_token.py
+#
+# Bad token name
+
+import lex
+
+tokens = [
+ "PLUS",
+ "MINUS",
+ "-",
+ "NUMBER",
+ ]
+
+t_PLUS = r'\+'
+t_MINUS = r'-'
+t_NUMBER = r'\d+'
+
+def t_error(t):
+ pass
+
+import sys
+sys.tracebacklimit = 0
+
+lex.lex()
+
+
diff --git a/ext/ply/test/lex_token5.exp b/ext/ply/test/lex_token5.exp
new file mode 100644
index 000000000..d7bcb2e7c
--- /dev/null
+++ b/ext/ply/test/lex_token5.exp
@@ -0,0 +1 @@
+lex.LexError: ./lex_token5.py:16: Rule 't_NUMBER' returned an unknown token type 'NUM'
diff --git a/ext/ply/test/lex_token5.py b/ext/ply/test/lex_token5.py
new file mode 100644
index 000000000..d9b0c96aa
--- /dev/null
+++ b/ext/ply/test/lex_token5.py
@@ -0,0 +1,31 @@
+# lex_token.py
+#
+# Return a bad token name
+
+import lex
+
+tokens = [
+ "PLUS",
+ "MINUS",
+ "NUMBER",
+ ]
+
+t_PLUS = r'\+'
+t_MINUS = r'-'
+
+def t_NUMBER(t):
+ r'\d+'
+ t.type = "NUM"
+ return t
+
+def t_error(t):
+ pass
+
+import sys
+sys.tracebacklimit = 0
+
+lex.lex()
+lex.input("1234")
+t = lex.token()
+
+
diff --git a/ext/ply/test/testlex.py b/ext/ply/test/testlex.py
new file mode 100755
index 000000000..df000b83d
--- /dev/null
+++ b/ext/ply/test/testlex.py
@@ -0,0 +1,57 @@
+#!/usr/local/bin
+# ----------------------------------------------------------------------
+# testlex.py
+#
+# Run tests for the lexing module
+# ----------------------------------------------------------------------
+
+import sys,os,glob
+
+if len(sys.argv) < 2:
+ print "Usage: python testlex.py directory"
+ raise SystemExit
+
+dirname = None
+make = 0
+
+for o in sys.argv[1:]:
+ if o == '-make':
+ make = 1
+ else:
+ dirname = o
+ break
+
+if not dirname:
+ print "Usage: python testlex.py [-make] directory"
+ raise SystemExit
+
+f = glob.glob("%s/%s" % (dirname,"lex_*.py"))
+
+print "**** Running tests for lex ****"
+
+for t in f:
+ name = t[:-3]
+ print "Testing %-32s" % name,
+ if make:
+ if not os.path.exists("%s.exp" % name):
+ os.system("python %s.py >%s.exp 2>&1" % (name,name))
+ passed = 1
+ else:
+ os.system("python %s.py >%s.out 2>&1" % (name,name))
+ a = os.system("diff %s.out %s.exp >%s.dif" % (name,name,name))
+ if a == 0:
+ passed = 1
+ else:
+ passed = 0
+
+ if passed:
+ print "Passed"
+ else:
+ print "Failed. See %s.dif" % name
+
+
+
+
+
+
+
diff --git a/ext/ply/test/testyacc.py b/ext/ply/test/testyacc.py
new file mode 100644
index 000000000..a185cbb29
--- /dev/null
+++ b/ext/ply/test/testyacc.py
@@ -0,0 +1,58 @@
+#!/usr/local/bin
+# ----------------------------------------------------------------------
+# testyacc.py
+#
+# Run tests for the yacc module
+# ----------------------------------------------------------------------
+
+import sys,os,glob
+
+if len(sys.argv) < 2:
+ print "Usage: python testyacc.py directory"
+ raise SystemExit
+
+dirname = None
+make = 0
+
+for o in sys.argv[1:]:
+ if o == '-make':
+ make = 1
+ else:
+ dirname = o
+ break
+
+if not dirname:
+ print "Usage: python testyacc.py [-make] directory"
+ raise SystemExit
+
+f = glob.glob("%s/%s" % (dirname,"yacc_*.py"))
+
+print "**** Running tests for yacc ****"
+
+for t in f:
+ name = t[:-3]
+ print "Testing %-32s" % name,
+ os.system("rm -f %s/parsetab.*" % dirname)
+ if make:
+ if not os.path.exists("%s.exp" % name):
+ os.system("python %s.py >%s.exp 2>&1" % (name,name))
+ passed = 1
+ else:
+ os.system("python %s.py >%s.out 2>&1" % (name,name))
+ a = os.system("diff %s.out %s.exp >%s.dif" % (name,name,name))
+ if a == 0:
+ passed = 1
+ else:
+ passed = 0
+
+ if passed:
+ print "Passed"
+ else:
+ print "Failed. See %s.dif" % name
+
+
+
+
+
+
+
diff --git a/ext/ply/test/yacc_badargs.exp b/ext/ply/test/yacc_badargs.exp
new file mode 100644
index 000000000..b145c51f2
--- /dev/null
+++ b/ext/ply/test/yacc_badargs.exp
@@ -0,0 +1,3 @@
+./yacc_badargs.py:21: Rule 'p_statement_assign' has too many arguments.
+./yacc_badargs.py:25: Rule 'p_statement_expr' requires an argument.
+yacc.YaccError: Unable to construct parser.
diff --git a/ext/ply/test/yacc_badargs.py b/ext/ply/test/yacc_badargs.py
new file mode 100644
index 000000000..12075efcc
--- /dev/null
+++ b/ext/ply/test/yacc_badargs.py
@@ -0,0 +1,67 @@
+# -----------------------------------------------------------------------------
+# yacc_badargs.py
+#
+# Rules with wrong # args
+# -----------------------------------------------------------------------------
+import sys
+sys.tracebacklimit = 0
+
+from calclex import tokens
+
+# Parsing rules
+precedence = (
+ ('left','PLUS','MINUS'),
+ ('left','TIMES','DIVIDE'),
+ ('right','UMINUS'),
+ )
+
+# dictionary of names
+names = { }
+
+def p_statement_assign(t,s):
+ 'statement : NAME EQUALS expression'
+ names[t[1]] = t[3]
+
+def p_statement_expr():
+ 'statement : expression'
+ print t[1]
+
+def p_expression_binop(t):
+ '''expression : expression PLUS expression
+ | expression MINUS expression
+ | expression TIMES expression
+ | expression DIVIDE expression'''
+ if t[2] == '+' : t[0] = t[1] + t[3]
+ elif t[2] == '-': t[0] = t[1] - t[3]
+ elif t[2] == '*': t[0] = t[1] * t[3]
+ elif t[3] == '/': t[0] = t[1] / t[3]
+
+def p_expression_uminus(t):
+ 'expression : MINUS expression %prec UMINUS'
+ t[0] = -t[2]
+
+def p_expression_group(t):
+ 'expression : LPAREN expression RPAREN'
+ t[0] = t[2]
+
+def p_expression_number(t):
+ 'expression : NUMBER'
+ t[0] = t[1]
+
+def p_expression_name(t):
+ 'expression : NAME'
+ try:
+ t[0] = names[t[1]]
+ except LookupError:
+ print "Undefined name '%s'" % t[1]
+ t[0] = 0
+
+def p_error(t):
+ print "Syntax error at '%s'" % t.value
+
+import yacc
+yacc.yacc()
+
+
+
+
diff --git a/ext/ply/test/yacc_badprec.exp b/ext/ply/test/yacc_badprec.exp
new file mode 100644
index 000000000..7764b0246
--- /dev/null
+++ b/ext/ply/test/yacc_badprec.exp
@@ -0,0 +1 @@
+yacc.YaccError: precedence must be a list or tuple.
diff --git a/ext/ply/test/yacc_badprec.py b/ext/ply/test/yacc_badprec.py
new file mode 100644
index 000000000..55bf7720d
--- /dev/null
+++ b/ext/ply/test/yacc_badprec.py
@@ -0,0 +1,63 @@
+# -----------------------------------------------------------------------------
+# yacc_badprec.py
+#
+# Bad precedence specifier
+# -----------------------------------------------------------------------------
+import sys
+sys.tracebacklimit = 0
+
+from calclex import tokens
+
+# Parsing rules
+precedence = "blah"
+
+# dictionary of names
+names = { }
+
+def p_statement_assign(t):
+ 'statement : NAME EQUALS expression'
+ names[t[1]] = t[3]
+
+def p_statement_expr(t):
+ 'statement : expression'
+ print t[1]
+
+def p_expression_binop(t):
+ '''expression : expression PLUS expression
+ | expression MINUS expression
+ | expression TIMES expression
+ | expression DIVIDE expression'''
+ if t[2] == '+' : t[0] = t[1] + t[3]
+ elif t[2] == '-': t[0] = t[1] - t[3]
+ elif t[2] == '*': t[0] = t[1] * t[3]
+ elif t[3] == '/': t[0] = t[1] / t[3]
+
+def p_expression_uminus(t):
+ 'expression : MINUS expression %prec UMINUS'
+ t[0] = -t[2]
+
+def p_expression_group(t):
+ 'expression : LPAREN expression RPAREN'
+ t[0] = t[2]
+
+def p_expression_number(t):
+ 'expression : NUMBER'
+ t[0] = t[1]
+
+def p_expression_name(t):
+ 'expression : NAME'
+ try:
+ t[0] = names[t[1]]
+ except LookupError:
+ print "Undefined name '%s'" % t[1]
+ t[0] = 0
+
+def p_error(t):
+ print "Syntax error at '%s'" % t.value
+
+import yacc
+yacc.yacc()
+
+
+
+
diff --git a/ext/ply/test/yacc_badprec2.exp b/ext/ply/test/yacc_badprec2.exp
new file mode 100644
index 000000000..1df1427b2
--- /dev/null
+++ b/ext/ply/test/yacc_badprec2.exp
@@ -0,0 +1,3 @@
+yacc: Invalid precedence table.
+yacc: Generating SLR parsing table...
+yacc: 4 shift/reduce conflicts
diff --git a/ext/ply/test/yacc_badprec2.py b/ext/ply/test/yacc_badprec2.py
new file mode 100644
index 000000000..9cbc99827
--- /dev/null
+++ b/ext/ply/test/yacc_badprec2.py
@@ -0,0 +1,67 @@
+# -----------------------------------------------------------------------------
+# yacc_badprec2.py
+#
+# Bad precedence
+# -----------------------------------------------------------------------------
+import sys
+sys.tracebacklimit = 0
+
+from calclex import tokens
+
+# Parsing rules
+precedence = (
+ 42,
+ ('left','TIMES','DIVIDE'),
+ ('right','UMINUS'),
+ )
+
+# dictionary of names
+names = { }
+
+def p_statement_assign(t):
+ 'statement : NAME EQUALS expression'
+ names[t[1]] = t[3]
+
+def p_statement_expr(t):
+ 'statement : expression'
+ print t[1]
+
+def p_expression_binop(t):
+ '''expression : expression PLUS expression
+ | expression MINUS expression
+ | expression TIMES expression
+ | expression DIVIDE expression'''
+ if t[2] == '+' : t[0] = t[1] + t[3]
+ elif t[2] == '-': t[0] = t[1] - t[3]
+ elif t[2] == '*': t[0] = t[1] * t[3]
+ elif t[3] == '/': t[0] = t[1] / t[3]
+
+def p_expression_uminus(t):
+ 'expression : MINUS expression %prec UMINUS'
+ t[0] = -t[2]
+
+def p_expression_group(t):
+ 'expression : LPAREN expression RPAREN'
+ t[0] = t[2]
+
+def p_expression_number(t):
+ 'expression : NUMBER'
+ t[0] = t[1]
+
+def p_expression_name(t):
+ 'expression : NAME'
+ try:
+ t[0] = names[t[1]]
+ except LookupError:
+ print "Undefined name '%s'" % t[1]
+ t[0] = 0
+
+def p_error(t):
+ print "Syntax error at '%s'" % t.value
+
+import yacc
+yacc.yacc()
+
+
+
+
diff --git a/ext/ply/test/yacc_badrule.exp b/ext/ply/test/yacc_badrule.exp
new file mode 100644
index 000000000..553779778
--- /dev/null
+++ b/ext/ply/test/yacc_badrule.exp
@@ -0,0 +1,5 @@
+./yacc_badrule.py:22: Syntax error. Expected ':'
+./yacc_badrule.py:26: Syntax error in rule 'statement'
+./yacc_badrule.py:31: Syntax error. Expected ':'
+./yacc_badrule.py:40: Syntax error. Expected ':'
+yacc.YaccError: Unable to construct parser.
diff --git a/ext/ply/test/yacc_badrule.py b/ext/ply/test/yacc_badrule.py
new file mode 100644
index 000000000..cad3a967e
--- /dev/null
+++ b/ext/ply/test/yacc_badrule.py
@@ -0,0 +1,67 @@
+# -----------------------------------------------------------------------------
+# yacc_badrule.py
+#
+# Syntax problems in the rule strings
+# -----------------------------------------------------------------------------
+import sys
+sys.tracebacklimit = 0
+
+from calclex import tokens
+
+# Parsing rules
+precedence = (
+ ('left','PLUS','MINUS'),
+ ('left','TIMES','DIVIDE'),
+ ('right','UMINUS'),
+ )
+
+# dictionary of names
+names = { }
+
+def p_statement_assign(t):
+ 'statement NAME EQUALS expression'
+ names[t[1]] = t[3]
+
+def p_statement_expr(t):
+ 'statement'
+ print t[1]
+
+def p_expression_binop(t):
+ '''expression : expression PLUS expression
+ expression MINUS expression
+ | expression TIMES expression
+ | expression DIVIDE expression'''
+ if t[2] == '+' : t[0] = t[1] + t[3]
+ elif t[2] == '-': t[0] = t[1] - t[3]
+ elif t[2] == '*': t[0] = t[1] * t[3]
+ elif t[3] == '/': t[0] = t[1] / t[3]
+
+def p_expression_uminus(t):
+ 'expression: MINUS expression %prec UMINUS'
+ t[0] = -t[2]
+
+def p_expression_group(t):
+ 'expression : LPAREN expression RPAREN'
+ t[0] = t[2]
+
+def p_expression_number(t):
+ 'expression : NUMBER'
+ t[0] = t[1]
+
+def p_expression_name(t):
+ 'expression : NAME'
+ try:
+ t[0] = names[t[1]]
+ except LookupError:
+ print "Undefined name '%s'" % t[1]
+ t[0] = 0
+
+def p_error(t):
+ print "Syntax error at '%s'" % t.value
+
+import yacc
+yacc.yacc()
+
+
+
+
diff --git a/ext/ply/test/yacc_badtok.exp b/ext/ply/test/yacc_badtok.exp
new file mode 100644
index 000000000..f6e64726c
--- /dev/null
+++ b/ext/ply/test/yacc_badtok.exp
@@ -0,0 +1 @@
+yacc.YaccError: tokens must be a list or tuple.
diff --git a/ext/ply/test/yacc_badtok.py b/ext/ply/test/yacc_badtok.py
new file mode 100644
index 000000000..a17d26aaa
--- /dev/null
+++ b/ext/ply/test/yacc_badtok.py
@@ -0,0 +1,68 @@
+# -----------------------------------------------------------------------------
+# yacc_badtok.py
+#
+# A grammar, but tokens is a bad datatype
+# -----------------------------------------------------------------------------
+
+import sys
+sys.tracebacklimit = 0
+
+tokens = "Hello"
+
+# Parsing rules
+precedence = (
+ ('left','PLUS','MINUS'),
+ ('left','TIMES','DIVIDE'),
+ ('right','UMINUS'),
+ )
+
+# dictionary of names
+names = { }
+
+def p_statement_assign(t):
+ 'statement : NAME EQUALS expression'
+ names[t[1]] = t[3]
+
+def p_statement_expr(t):
+ 'statement : expression'
+ print t[1]
+
+def p_expression_binop(t):
+ '''expression : expression PLUS expression
+ | expression MINUS expression
+ | expression TIMES expression
+ | expression DIVIDE expression'''
+ if t[2] == '+' : t[0] = t[1] + t[3]
+ elif t[2] == '-': t[0] = t[1] - t[3]
+ elif t[2] == '*': t[0] = t[1] * t[3]
+ elif t[3] == '/': t[0] = t[1] / t[3]
+
+def p_expression_uminus(t):
+ 'expression : MINUS expression %prec UMINUS'
+ t[0] = -t[2]
+
+def p_expression_group(t):
+ 'expression : LPAREN expression RPAREN'
+ t[0] = t[2]
+
+def p_expression_number(t):
+ 'expression : NUMBER'
+ t[0] = t[1]
+
+def p_expression_name(t):
+ 'expression : NAME'
+ try:
+ t[0] = names[t[1]]
+ except LookupError:
+ print "Undefined name '%s'" % t[1]
+ t[0] = 0
+
+def p_error(t):
+ print "Syntax error at '%s'" % t.value
+
+import yacc
+yacc.yacc()
+
+
+
+
diff --git a/ext/ply/test/yacc_dup.exp b/ext/ply/test/yacc_dup.exp
new file mode 100644
index 000000000..99f3fe22c
--- /dev/null
+++ b/ext/ply/test/yacc_dup.exp
@@ -0,0 +1,4 @@
+./yacc_dup.py:25: Function p_statement redefined. Previously defined on line 21
+yacc: Warning. Token 'EQUALS' defined, but not used.
+yacc: Warning. There is 1 unused token.
+yacc: Generating SLR parsing table...
diff --git a/ext/ply/test/yacc_dup.py b/ext/ply/test/yacc_dup.py
new file mode 100644
index 000000000..557cd0ae1
--- /dev/null
+++ b/ext/ply/test/yacc_dup.py
@@ -0,0 +1,67 @@
+# -----------------------------------------------------------------------------
+# yacc_dup.py
+#
+# Duplicated rule name
+# -----------------------------------------------------------------------------
+import sys
+sys.tracebacklimit = 0
+
+from calclex import tokens
+
+# Parsing rules
+precedence = (
+ ('left','PLUS','MINUS'),
+ ('left','TIMES','DIVIDE'),
+ ('right','UMINUS'),
+ )
+
+# dictionary of names
+names = { }
+
+def p_statement(t):
+ 'statement : NAME EQUALS expression'
+ names[t[1]] = t[3]
+
+def p_statement(t):
+ 'statement : expression'
+ print t[1]
+
+def p_expression_binop(t):
+ '''expression : expression PLUS expression
+ | expression MINUS expression
+ | expression TIMES expression
+ | expression DIVIDE expression'''
+ if t[2] == '+' : t[0] = t[1] + t[3]
+ elif t[2] == '-': t[0] = t[1] - t[3]
+ elif t[2] == '*': t[0] = t[1] * t[3]
+ elif t[3] == '/': t[0] = t[1] / t[3]
+
+def p_expression_uminus(t):
+ 'expression : MINUS expression %prec UMINUS'
+ t[0] = -t[2]
+
+def p_expression_group(t):
+ 'expression : LPAREN expression RPAREN'
+ t[0] = t[2]
+
+def p_expression_number(t):
+ 'expression : NUMBER'
+ t[0] = t[1]
+
+def p_expression_name(t):
+ 'expression : NAME'
+ try:
+ t[0] = names[t[1]]
+ except LookupError:
+ print "Undefined name '%s'" % t[1]
+ t[0] = 0
+
+def p_error(t):
+ print "Syntax error at '%s'" % t.value
+
+import yacc
+yacc.yacc()
+
+
+
+
diff --git a/ext/ply/test/yacc_error1.exp b/ext/ply/test/yacc_error1.exp
new file mode 100644
index 000000000..980fc905c
--- /dev/null
+++ b/ext/ply/test/yacc_error1.exp
@@ -0,0 +1 @@
+yacc.YaccError: ./yacc_error1.py:59: p_error() requires 1 argument.
diff --git a/ext/ply/test/yacc_error1.py b/ext/ply/test/yacc_error1.py
new file mode 100644
index 000000000..413004520
--- /dev/null
+++ b/ext/ply/test/yacc_error1.py
@@ -0,0 +1,67 @@
+# -----------------------------------------------------------------------------
+# yacc_error1.py
+#
+# Bad p_error() function
+# -----------------------------------------------------------------------------
+import sys
+sys.tracebacklimit = 0
+
+from calclex import tokens
+
+# Parsing rules
+precedence = (
+ ('left','PLUS','MINUS'),
+ ('left','TIMES','DIVIDE'),
+ ('right','UMINUS'),
+ )
+
+# dictionary of names
+names = { }
+
+def p_statement_assign(t):
+ 'statement : NAME EQUALS expression'
+ names[t[1]] = t[3]
+
+def p_statement_expr(t):
+ 'statement : expression'
+ print t[1]
+
+def p_expression_binop(t):
+ '''expression : expression PLUS expression
+ | expression MINUS expression
+ | expression TIMES expression
+ | expression DIVIDE expression'''
+ if t[2] == '+' : t[0] = t[1] + t[3]
+ elif t[2] == '-': t[0] = t[1] - t[3]
+ elif t[2] == '*': t[0] = t[1] * t[3]
+ elif t[3] == '/': t[0] = t[1] / t[3]
+
+def p_expression_uminus(t):
+ 'expression : MINUS expression %prec UMINUS'
+ t[0] = -t[2]
+
+def p_expression_group(t):
+ 'expression : LPAREN expression RPAREN'
+ t[0] = t[2]
+
+def p_expression_number(t):
+ 'expression : NUMBER'
+ t[0] = t[1]
+
+def p_expression_name(t):
+ 'expression : NAME'
+ try:
+ t[0] = names[t[1]]
+ except LookupError:
+ print "Undefined name '%s'" % t[1]
+ t[0] = 0
+
+def p_error(t,s):
+ print "Syntax error at '%s'" % t.value
+
+import yacc
+yacc.yacc()
+
+
+
+
diff --git a/ext/ply/test/yacc_error2.exp b/ext/ply/test/yacc_error2.exp
new file mode 100644
index 000000000..d0573b4dd
--- /dev/null
+++ b/ext/ply/test/yacc_error2.exp
@@ -0,0 +1 @@
+yacc.YaccError: ./yacc_error2.py:59: p_error() requires 1 argument.
diff --git a/ext/ply/test/yacc_error2.py b/ext/ply/test/yacc_error2.py
new file mode 100644
index 000000000..d4fd1d219
--- /dev/null
+++ b/ext/ply/test/yacc_error2.py
@@ -0,0 +1,67 @@
+# -----------------------------------------------------------------------------
+# yacc_error1.py
+#
+# Bad p_error() function
+# -----------------------------------------------------------------------------
+import sys
+sys.tracebacklimit = 0
+
+from calclex import tokens
+
+# Parsing rules
+precedence = (
+ ('left','PLUS','MINUS'),
+ ('left','TIMES','DIVIDE'),
+ ('right','UMINUS'),
+ )
+
+# dictionary of names
+names = { }
+
+def p_statement_assign(t):
+ 'statement : NAME EQUALS expression'
+ names[t[1]] = t[3]
+
+def p_statement_expr(t):
+ 'statement : expression'
+ print t[1]
+
+def p_expression_binop(t):
+ '''expression : expression PLUS expression
+ | expression MINUS expression
+ | expression TIMES expression
+ | expression DIVIDE expression'''
+ if t[2] == '+' : t[0] = t[1] + t[3]
+ elif t[2] == '-': t[0] = t[1] - t[3]
+ elif t[2] == '*': t[0] = t[1] * t[3]
+ elif t[3] == '/': t[0] = t[1] / t[3]
+
+def p_expression_uminus(t):
+ 'expression : MINUS expression %prec UMINUS'
+ t[0] = -t[2]
+
+def p_expression_group(t):
+ 'expression : LPAREN expression RPAREN'
+ t[0] = t[2]
+
+def p_expression_number(t):
+ 'expression : NUMBER'
+ t[0] = t[1]
+
+def p_expression_name(t):
+ 'expression : NAME'
+ try:
+ t[0] = names[t[1]]
+ except LookupError:
+ print "Undefined name '%s'" % t[1]
+ t[0] = 0
+
+def p_error():
+ print "Syntax error at '%s'" % t.value
+
+import yacc
+yacc.yacc()
+
+
+
+
diff --git a/ext/ply/test/yacc_error3.exp b/ext/ply/test/yacc_error3.exp
new file mode 100644
index 000000000..31eaee754
--- /dev/null
+++ b/ext/ply/test/yacc_error3.exp
@@ -0,0 +1 @@
+yacc.YaccError: 'p_error' defined, but is not a function.
diff --git a/ext/ply/test/yacc_error3.py b/ext/ply/test/yacc_error3.py
new file mode 100644
index 000000000..7093fab48
--- /dev/null
+++ b/ext/ply/test/yacc_error3.py
@@ -0,0 +1,66 @@
+# -----------------------------------------------------------------------------
+# yacc_error1.py
+#
+# Bad p_error() function
+# -----------------------------------------------------------------------------
+import sys
+sys.tracebacklimit = 0
+
+from calclex import tokens
+
+# Parsing rules
+precedence = (
+ ('left','PLUS','MINUS'),
+ ('left','TIMES','DIVIDE'),
+ ('right','UMINUS'),
+ )
+
+# dictionary of names
+names = { }
+
+def p_statement_assign(t):
+ 'statement : NAME EQUALS expression'
+ names[t[1]] = t[3]
+
+def p_statement_expr(t):
+ 'statement : expression'
+ print t[1]
+
+def p_expression_binop(t):
+ '''expression : expression PLUS expression
+ | expression MINUS expression
+ | expression TIMES expression
+ | expression DIVIDE expression'''
+ if t[2] == '+' : t[0] = t[1] + t[3]
+ elif t[2] == '-': t[0] = t[1] - t[3]
+ elif t[2] == '*': t[0] = t[1] * t[3]
+ elif t[3] == '/': t[0] = t[1] / t[3]
+
+def p_expression_uminus(t):
+ 'expression : MINUS expression %prec UMINUS'
+ t[0] = -t[2]
+
+def p_expression_group(t):
+ 'expression : LPAREN expression RPAREN'
+ t[0] = t[2]
+
+def p_expression_number(t):
+ 'expression : NUMBER'
+ t[0] = t[1]
+
+def p_expression_name(t):
+ 'expression : NAME'
+ try:
+ t[0] = names[t[1]]
+ except LookupError:
+ print "Undefined name '%s'" % t[1]
+ t[0] = 0
+
+p_error = "blah"
+
+import yacc
+yacc.yacc()
+
+
+
+
diff --git a/ext/ply/test/yacc_inf.exp b/ext/ply/test/yacc_inf.exp
new file mode 100644
index 000000000..a7f47dada
--- /dev/null
+++ b/ext/ply/test/yacc_inf.exp
@@ -0,0 +1,5 @@
+yacc: Warning. Token 'NUMBER' defined, but not used.
+yacc: Warning. There is 1 unused token.
+yacc: Infinite recursion detected for symbol 'statement'.
+yacc: Infinite recursion detected for symbol 'expression'.
+yacc.YaccError: Unable to construct parser.
diff --git a/ext/ply/test/yacc_inf.py b/ext/ply/test/yacc_inf.py
new file mode 100644
index 000000000..885e2c4df
--- /dev/null
+++ b/ext/ply/test/yacc_inf.py
@@ -0,0 +1,55 @@
+# -----------------------------------------------------------------------------
+# yacc_inf.py
+#
+# Infinite recursion
+# -----------------------------------------------------------------------------
+import sys
+sys.tracebacklimit = 0
+
+from calclex import tokens
+
+# Parsing rules
+precedence = (
+ ('left','PLUS','MINUS'),
+ ('left','TIMES','DIVIDE'),
+ ('right','UMINUS'),
+ )
+
+# dictionary of names
+names = { }
+
+def p_statement_assign(t):
+ 'statement : NAME EQUALS expression'
+ names[t[1]] = t[3]
+
+def p_statement_expr(t):
+ 'statement : expression'
+ print t[1]
+
+def p_expression_binop(t):
+ '''expression : expression PLUS expression
+ | expression MINUS expression
+ | expression TIMES expression
+ | expression DIVIDE expression'''
+ if t[2] == '+' : t[0] = t[1] + t[3]
+ elif t[2] == '-': t[0] = t[1] - t[3]
+ elif t[2] == '*': t[0] = t[1] * t[3]
+ elif t[3] == '/': t[0] = t[1] / t[3]
+
+def p_expression_uminus(t):
+ 'expression : MINUS expression %prec UMINUS'
+ t[0] = -t[2]
+
+def p_expression_group(t):
+ 'expression : LPAREN expression RPAREN'
+ t[0] = t[2]
+
+def p_error(t):
+ print "Syntax error at '%s'" % t.value
+
+import yacc
+yacc.yacc()
+
+
+
+
diff --git a/ext/ply/test/yacc_missing1.exp b/ext/ply/test/yacc_missing1.exp
new file mode 100644
index 000000000..065d6a54a
--- /dev/null
+++ b/ext/ply/test/yacc_missing1.exp
@@ -0,0 +1,2 @@
+./yacc_missing1.py:22: Symbol 'location' used, but not defined as a token or a rule.
+yacc.YaccError: Unable to construct parser.
diff --git a/ext/ply/test/yacc_missing1.py b/ext/ply/test/yacc_missing1.py
new file mode 100644
index 000000000..e63904d0e
--- /dev/null
+++ b/ext/ply/test/yacc_missing1.py
@@ -0,0 +1,67 @@
+# -----------------------------------------------------------------------------
+# yacc_missing1.py
+#
+# Grammar with a missing rule
+# -----------------------------------------------------------------------------
+import sys
+sys.tracebacklimit = 0
+
+from calclex import tokens
+
+# Parsing rules
+precedence = (
+ ('left','PLUS','MINUS'),
+ ('left','TIMES','DIVIDE'),
+ ('right','UMINUS'),
+ )
+
+# dictionary of names
+names = { }
+
+def p_statement_assign(t):
+ 'statement : location EQUALS expression'
+ names[t[1]] = t[3]
+
+def p_statement_expr(t):
+ 'statement : expression'
+ print t[1]
+
+def p_expression_binop(t):
+ '''expression : expression PLUS expression
+ | expression MINUS expression
+ | expression TIMES expression
+ | expression DIVIDE expression'''
+ if t[2] == '+' : t[0] = t[1] + t[3]
+ elif t[2] == '-': t[0] = t[1] - t[3]
+ elif t[2] == '*': t[0] = t[1] * t[3]
+ elif t[3] == '/': t[0] = t[1] / t[3]
+
+def p_expression_uminus(t):
+ 'expression : MINUS expression %prec UMINUS'
+ t[0] = -t[2]
+
+def p_expression_group(t):
+ 'expression : LPAREN expression RPAREN'
+ t[0] = t[2]
+
+def p_expression_number(t):
+ 'expression : NUMBER'
+ t[0] = t[1]
+
+def p_expression_name(t):
+ 'expression : NAME'
+ try:
+ t[0] = names[t[1]]
+ except LookupError:
+ print "Undefined name '%s'" % t[1]
+ t[0] = 0
+
+def p_error(t):
+ print "Syntax error at '%s'" % t.value
+
+import yacc
+yacc.yacc()
+
+
+
+
diff --git a/ext/ply/test/yacc_nodoc.exp b/ext/ply/test/yacc_nodoc.exp
new file mode 100644
index 000000000..3f52a3287
--- /dev/null
+++ b/ext/ply/test/yacc_nodoc.exp
@@ -0,0 +1,2 @@
+./yacc_nodoc.py:25: No documentation string specified in function 'p_statement_expr'
+yacc: Generating SLR parsing table...
diff --git a/ext/ply/test/yacc_nodoc.py b/ext/ply/test/yacc_nodoc.py
new file mode 100644
index 000000000..e3941bdaa
--- /dev/null
+++ b/ext/ply/test/yacc_nodoc.py
@@ -0,0 +1,66 @@
+# -----------------------------------------------------------------------------
+# yacc_nodoc.py
+#
+# Rule with a missing doc-string
+# -----------------------------------------------------------------------------
+import sys
+sys.tracebacklimit = 0
+
+from calclex import tokens
+
+# Parsing rules
+precedence = (
+ ('left','PLUS','MINUS'),
+ ('left','TIMES','DIVIDE'),
+ ('right','UMINUS'),
+ )
+
+# dictionary of names
+names = { }
+
+def p_statement_assign(t):
+ 'statement : NAME EQUALS expression'
+ names[t[1]] = t[3]
+
+def p_statement_expr(t):
+ print t[1]
+
+def p_expression_binop(t):
+ '''expression : expression PLUS expression
+ | expression MINUS expression
+ | expression TIMES expression
+ | expression DIVIDE expression'''
+ if t[2] == '+' : t[0] = t[1] + t[3]
+ elif t[2] == '-': t[0] = t[1] - t[3]
+ elif t[2] == '*': t[0] = t[1] * t[3]
+ elif t[3] == '/': t[0] = t[1] / t[3]
+
+def p_expression_uminus(t):
+ 'expression : MINUS expression %prec UMINUS'
+ t[0] = -t[2]
+
+def p_expression_group(t):
+ 'expression : LPAREN expression RPAREN'
+ t[0] = t[2]
+
+def p_expression_number(t):
+ 'expression : NUMBER'
+ t[0] = t[1]
+
+def p_expression_name(t):
+ 'expression : NAME'
+ try:
+ t[0] = names[t[1]]
+ except LookupError:
+ print "Undefined name '%s'" % t[1]
+ t[0] = 0
+
+def p_error(t):
+ print "Syntax error at '%s'" % t.value
+
+import yacc
+yacc.yacc()
+
+
+
+
diff --git a/ext/ply/test/yacc_noerror.exp b/ext/ply/test/yacc_noerror.exp
new file mode 100644
index 000000000..986fa31fa
--- /dev/null
+++ b/ext/ply/test/yacc_noerror.exp
@@ -0,0 +1,2 @@
+yacc: Warning. no p_error() function is defined.
+yacc: Generating SLR parsing table...
diff --git a/ext/ply/test/yacc_noerror.py b/ext/ply/test/yacc_noerror.py
new file mode 100644
index 000000000..d92f48ea6
--- /dev/null
+++ b/ext/ply/test/yacc_noerror.py
@@ -0,0 +1,64 @@
+# -----------------------------------------------------------------------------
+# yacc_noerror.py
+#
+# No p_error() rule defined.
+# -----------------------------------------------------------------------------
+import sys
+sys.tracebacklimit = 0
+
+from calclex import tokens
+
+# Parsing rules
+precedence = (
+ ('left','PLUS','MINUS'),
+ ('left','TIMES','DIVIDE'),
+ ('right','UMINUS'),
+ )
+
+# dictionary of names
+names = { }
+
+def p_statement_assign(t):
+ 'statement : NAME EQUALS expression'
+ names[t[1]] = t[3]
+
+def p_statement_expr(t):
+ 'statement : expression'
+ print t[1]
+
+def p_expression_binop(t):
+ '''expression : expression PLUS expression
+ | expression MINUS expression
+ | expression TIMES expression
+ | expression DIVIDE expression'''
+ if t[2] == '+' : t[0] = t[1] + t[3]
+ elif t[2] == '-': t[0] = t[1] - t[3]
+ elif t[2] == '*': t[0] = t[1] * t[3]
+ elif t[3] == '/': t[0] = t[1] / t[3]
+
+def p_expression_uminus(t):
+ 'expression : MINUS expression %prec UMINUS'
+ t[0] = -t[2]
+
+def p_expression_group(t):
+ 'expression : LPAREN expression RPAREN'
+ t[0] = t[2]
+
+def p_expression_number(t):
+ 'expression : NUMBER'
+ t[0] = t[1]
+
+def p_expression_name(t):
+ 'expression : NAME'
+ try:
+ t[0] = names[t[1]]
+ except LookupError:
+ print "Undefined name '%s'" % t[1]
+ t[0] = 0
+
+import yacc
+yacc.yacc()
+
+
+
+
diff --git a/ext/ply/test/yacc_nop.exp b/ext/ply/test/yacc_nop.exp
new file mode 100644
index 000000000..062878b9e
--- /dev/null
+++ b/ext/ply/test/yacc_nop.exp
@@ -0,0 +1,2 @@
+./yacc_nop.py:25: Warning. Possible grammar rule 'statement_expr' defined without p_ prefix.
+yacc: Generating SLR parsing table...
diff --git a/ext/ply/test/yacc_nop.py b/ext/ply/test/yacc_nop.py
new file mode 100644
index 000000000..c599ffd5d
--- /dev/null
+++ b/ext/ply/test/yacc_nop.py
@@ -0,0 +1,67 @@
+# -----------------------------------------------------------------------------
+# yacc_nop.py
+#
+# Possible grammar rule defined without p_ prefix
+# -----------------------------------------------------------------------------
+import sys
+sys.tracebacklimit = 0
+
+from calclex import tokens
+
+# Parsing rules
+precedence = (
+ ('left','PLUS','MINUS'),
+ ('left','TIMES','DIVIDE'),
+ ('right','UMINUS'),
+ )
+
+# dictionary of names
+names = { }
+
+def p_statement_assign(t):
+ 'statement : NAME EQUALS expression'
+ names[t[1]] = t[3]
+
+def statement_expr(t):
+ 'statement : expression'
+ print t[1]
+
+def p_expression_binop(t):
+ '''expression : expression PLUS expression
+ | expression MINUS expression
+ | expression TIMES expression
+ | expression DIVIDE expression'''
+ if t[2] == '+' : t[0] = t[1] + t[3]
+ elif t[2] == '-': t[0] = t[1] - t[3]
+ elif t[2] == '*': t[0] = t[1] * t[3]
+ elif t[3] == '/': t[0] = t[1] / t[3]
+
+def p_expression_uminus(t):
+ 'expression : MINUS expression %prec UMINUS'
+ t[0] = -t[2]
+
+def p_expression_group(t):
+ 'expression : LPAREN expression RPAREN'
+ t[0] = t[2]
+
+def p_expression_number(t):
+ 'expression : NUMBER'
+ t[0] = t[1]
+
+def p_expression_name(t):
+ 'expression : NAME'
+ try:
+ t[0] = names[t[1]]
+ except LookupError:
+ print "Undefined name '%s'" % t[1]
+ t[0] = 0
+
+def p_error(t):
+ print "Syntax error at '%s'" % t.value
+
+import yacc
+yacc.yacc()
+
+
+
+
diff --git a/ext/ply/test/yacc_notfunc.exp b/ext/ply/test/yacc_notfunc.exp
new file mode 100644
index 000000000..271167341
--- /dev/null
+++ b/ext/ply/test/yacc_notfunc.exp
@@ -0,0 +1,4 @@
+yacc: Warning. 'p_statement_assign' not defined as a function
+yacc: Warning. Token 'EQUALS' defined, but not used.
+yacc: Warning. There is 1 unused token.
+yacc: Generating SLR parsing table...
diff --git a/ext/ply/test/yacc_notfunc.py b/ext/ply/test/yacc_notfunc.py
new file mode 100644
index 000000000..f61663d60
--- /dev/null
+++ b/ext/ply/test/yacc_notfunc.py
@@ -0,0 +1,65 @@
+# -----------------------------------------------------------------------------
+# yacc_notfunc.py
+#
+# p_rule not defined as a function
+# -----------------------------------------------------------------------------
+import sys
+sys.tracebacklimit = 0
+
+from calclex import tokens
+
+# Parsing rules
+precedence = (
+ ('left','PLUS','MINUS'),
+ ('left','TIMES','DIVIDE'),
+ ('right','UMINUS'),
+ )
+
+# dictionary of names
+names = { }
+
+p_statement_assign = "Blah"
+
+def p_statement_expr(t):
+ 'statement : expression'
+ print t[1]
+
+def p_expression_binop(t):
+ '''expression : expression PLUS expression
+ | expression MINUS expression
+ | expression TIMES expression
+ | expression DIVIDE expression'''
+ if t[2] == '+' : t[0] = t[1] + t[3]
+ elif t[2] == '-': t[0] = t[1] - t[3]
+ elif t[2] == '*': t[0] = t[1] * t[3]
+ elif t[3] == '/': t[0] = t[1] / t[3]
+
+def p_expression_uminus(t):
+ 'expression : MINUS expression %prec UMINUS'
+ t[0] = -t[2]
+
+def p_expression_group(t):
+ 'expression : LPAREN expression RPAREN'
+ t[0] = t[2]
+
+def p_expression_number(t):
+ 'expression : NUMBER'
+ t[0] = t[1]
+
+def p_expression_name(t):
+ 'expression : NAME'
+ try:
+ t[0] = names[t[1]]
+ except LookupError:
+ print "Undefined name '%s'" % t[1]
+ t[0] = 0
+
+def p_error(t):
+ print "Syntax error at '%s'" % t.value
+
+import yacc
+yacc.yacc()
+
+
+
+
diff --git a/ext/ply/test/yacc_notok.exp b/ext/ply/test/yacc_notok.exp
new file mode 100644
index 000000000..708f6f597
--- /dev/null
+++ b/ext/ply/test/yacc_notok.exp
@@ -0,0 +1 @@
+yacc.YaccError: module does not define a list 'tokens'
diff --git a/ext/ply/test/yacc_notok.py b/ext/ply/test/yacc_notok.py
new file mode 100644
index 000000000..dfa0059be
--- /dev/null
+++ b/ext/ply/test/yacc_notok.py
@@ -0,0 +1,66 @@
+# -----------------------------------------------------------------------------
+# yacc_notok.py
+#
+# A grammar, but we forgot to import the tokens list
+# -----------------------------------------------------------------------------
+
+import sys
+sys.tracebacklimit = 0
+
+# Parsing rules
+precedence = (
+ ('left','PLUS','MINUS'),
+ ('left','TIMES','DIVIDE'),
+ ('right','UMINUS'),
+ )
+
+# dictionary of names
+names = { }
+
+def p_statement_assign(t):
+ 'statement : NAME EQUALS expression'
+ names[t[1]] = t[3]
+
+def p_statement_expr(t):
+ 'statement : expression'
+ print t[1]
+
+def p_expression_binop(t):
+ '''expression : expression PLUS expression
+ | expression MINUS expression
+ | expression TIMES expression
+ | expression DIVIDE expression'''
+ if t[2] == '+' : t[0] = t[1] + t[3]
+ elif t[2] == '-': t[0] = t[1] - t[3]
+ elif t[2] == '*': t[0] = t[1] * t[3]
+ elif t[3] == '/': t[0] = t[1] / t[3]
+
+def p_expression_uminus(t):
+ 'expression : MINUS expression %prec UMINUS'
+ t[0] = -t[2]
+
+def p_expression_group(t):
+ 'expression : LPAREN expression RPAREN'
+ t[0] = t[2]
+
+def p_expression_number(t):
+ 'expression : NUMBER'
+ t[0] = t[1]
+
+def p_expression_name(t):
+ 'expression : NAME'
+ try:
+ t[0] = names[t[1]]
+ except LookupError:
+ print "Undefined name '%s'" % t[1]
+ t[0] = 0
+
+def p_error(t):
+ print "Syntax error at '%s'" % t.value
+
+import yacc
+yacc.yacc()
+
+
+
+
diff --git a/ext/ply/test/yacc_rr.exp b/ext/ply/test/yacc_rr.exp
new file mode 100644
index 000000000..0ec556d16
--- /dev/null
+++ b/ext/ply/test/yacc_rr.exp
@@ -0,0 +1,2 @@
+yacc: Generating SLR parsing table...
+yacc: 1 reduce/reduce conflict
diff --git a/ext/ply/test/yacc_rr.py b/ext/ply/test/yacc_rr.py
new file mode 100644
index 000000000..c061c2c17
--- /dev/null
+++ b/ext/ply/test/yacc_rr.py
@@ -0,0 +1,71 @@
+# -----------------------------------------------------------------------------
+# yacc_rr.py
+#
+# A grammar with a reduce/reduce conflict
+# -----------------------------------------------------------------------------
+import sys
+sys.tracebacklimit = 0
+
+from calclex import tokens
+
+# Parsing rules
+precedence = (
+ ('left','PLUS','MINUS'),
+ ('left','TIMES','DIVIDE'),
+ ('right','UMINUS'),
+ )
+
+# dictionary of names
+names = { }
+
+def p_statement_assign(t):
+ 'statement : NAME EQUALS expression'
+ names[t[1]] = t[3]
+
+def p_statement_assign_2(t):
+ 'statement : NAME EQUALS NUMBER'
+ names[t[1]] = t[3]
+
+def p_statement_expr(t):
+ 'statement : expression'
+ print t[1]
+
+def p_expression_binop(t):
+ '''expression : expression PLUS expression
+ | expression MINUS expression
+ | expression TIMES expression
+ | expression DIVIDE expression'''
+ if t[2] == '+' : t[0] = t[1] + t[3]
+ elif t[2] == '-': t[0] = t[1] - t[3]
+ elif t[2] == '*': t[0] = t[1] * t[3]
+ elif t[3] == '/': t[0] = t[1] / t[3]
+
+def p_expression_uminus(t):
+ 'expression : MINUS expression %prec UMINUS'
+ t[0] = -t[2]
+
+def p_expression_group(t):
+ 'expression : LPAREN expression RPAREN'
+ t[0] = t[2]
+
+def p_expression_number(t):
+ 'expression : NUMBER'
+ t[0] = t[1]
+
+def p_expression_name(t):
+ 'expression : NAME'
+ try:
+ t[0] = names[t[1]]
+ except LookupError:
+ print "Undefined name '%s'" % t[1]
+ t[0] = 0
+
+def p_error(t):
+ print "Syntax error at '%s'" % t.value
+
+import yacc
+yacc.yacc()
+
+
+
+
diff --git a/ext/ply/test/yacc_simple.exp b/ext/ply/test/yacc_simple.exp
new file mode 100644
index 000000000..de7964b6f
--- /dev/null
+++ b/ext/ply/test/yacc_simple.exp
@@ -0,0 +1 @@
+yacc: Generating SLR parsing table...
diff --git a/ext/ply/test/yacc_simple.py b/ext/ply/test/yacc_simple.py
new file mode 100644
index 000000000..7b4b40b17
--- /dev/null
+++ b/ext/ply/test/yacc_simple.py
@@ -0,0 +1,67 @@
+# -----------------------------------------------------------------------------
+# yacc_simple.py
+#
+# A simple, properly specifier grammar
+# -----------------------------------------------------------------------------
+import sys
+sys.tracebacklimit = 0
+
+from calclex import tokens
+
+# Parsing rules
+precedence = (
+ ('left','PLUS','MINUS'),
+ ('left','TIMES','DIVIDE'),
+ ('right','UMINUS'),
+ )
+
+# dictionary of names
+names = { }
+
+def p_statement_assign(t):
+ 'statement : NAME EQUALS expression'
+ names[t[1]] = t[3]
+
+def p_statement_expr(t):
+ 'statement : expression'
+ print t[1]
+
+def p_expression_binop(t):
+ '''expression : expression PLUS expression
+ | expression MINUS expression
+ | expression TIMES expression
+ | expression DIVIDE expression'''
+ if t[2] == '+' : t[0] = t[1] + t[3]
+ elif t[2] == '-': t[0] = t[1] - t[3]
+ elif t[2] == '*': t[0] = t[1] * t[3]
+ elif t[3] == '/': t[0] = t[1] / t[3]
+
+def p_expression_uminus(t):
+ 'expression : MINUS expression %prec UMINUS'
+ t[0] = -t[2]
+
+def p_expression_group(t):
+ 'expression : LPAREN expression RPAREN'
+ t[0] = t[2]
+
+def p_expression_number(t):
+ 'expression : NUMBER'
+ t[0] = t[1]
+
+def p_expression_name(t):
+ 'expression : NAME'
+ try:
+ t[0] = names[t[1]]
+ except LookupError:
+ print "Undefined name '%s'" % t[1]
+ t[0] = 0
+
+def p_error(t):
+ print "Syntax error at '%s'" % t.value
+
+import yacc
+yacc.yacc()
+
+
+
+
diff --git a/ext/ply/test/yacc_sr.exp b/ext/ply/test/yacc_sr.exp
new file mode 100644
index 000000000..7225ad94b
--- /dev/null
+++ b/ext/ply/test/yacc_sr.exp
@@ -0,0 +1,2 @@
+yacc: Generating SLR parsing table...
+yacc: 20 shift/reduce conflicts
diff --git a/ext/ply/test/yacc_sr.py b/ext/ply/test/yacc_sr.py
new file mode 100644
index 000000000..4341f6997
--- /dev/null
+++ b/ext/ply/test/yacc_sr.py
@@ -0,0 +1,62 @@
+# -----------------------------------------------------------------------------
+# yacc_sr.py
+#
+# A grammar with shift-reduce conflicts
+# -----------------------------------------------------------------------------
+import sys
+sys.tracebacklimit = 0
+
+from calclex import tokens
+
+# Parsing rules
+
+# dictionary of names
+names = { }
+
+def p_statement_assign(t):
+ 'statement : NAME EQUALS expression'
+ names[t[1]] = t[3]
+
+def p_statement_expr(t):
+ 'statement : expression'
+ print t[1]
+
+def p_expression_binop(t):
+ '''expression : expression PLUS expression
+ | expression MINUS expression
+ | expression TIMES expression
+ | expression DIVIDE expression'''
+ if t[2] == '+' : t[0] = t[1] + t[3]
+ elif t[2] == '-': t[0] = t[1] - t[3]
+ elif t[2] == '*': t[0] = t[1] * t[3]
+ elif t[3] == '/': t[0] = t[1] / t[3]
+
+def p_expression_uminus(t):
+ 'expression : MINUS expression'
+ t[0] = -t[2]
+
+def p_expression_group(t):
+ 'expression : LPAREN expression RPAREN'
+ t[0] = t[2]
+
+def p_expression_number(t):
+ 'expression : NUMBER'
+ t[0] = t[1]
+
+def p_expression_name(t):
+ 'expression : NAME'
+ try:
+ t[0] = names[t[1]]
+ except LookupError:
+ print "Undefined name '%s'" % t[1]
+ t[0] = 0
+
+def p_error(t):
+ print "Syntax error at '%s'" % t.value
+
+import yacc
+yacc.yacc()
+
+
+
+
diff --git a/ext/ply/test/yacc_term1.exp b/ext/ply/test/yacc_term1.exp
new file mode 100644
index 000000000..422d2bacd
--- /dev/null
+++ b/ext/ply/test/yacc_term1.exp
@@ -0,0 +1,2 @@
+./yacc_term1.py:22: Illegal rule name 'NUMBER'. Already defined as a token.
+yacc.YaccError: Unable to construct parser.
diff --git a/ext/ply/test/yacc_term1.py b/ext/ply/test/yacc_term1.py
new file mode 100644
index 000000000..97a2e7a60
--- /dev/null
+++ b/ext/ply/test/yacc_term1.py
@@ -0,0 +1,67 @@
+# -----------------------------------------------------------------------------
+# yacc_term1.py
+#
+# Terminal used on the left-hand-side
+# -----------------------------------------------------------------------------
+import sys
+sys.tracebacklimit = 0
+
+from calclex import tokens
+
+# Parsing rules
+precedence = (
+ ('left','PLUS','MINUS'),
+ ('left','TIMES','DIVIDE'),
+ ('right','UMINUS'),
+ )
+
+# dictionary of names
+names = { }
+
+def p_statement_assign(t):
+ 'NUMBER : NAME EQUALS expression'
+ names[t[1]] = t[3]
+
+def p_statement_expr(t):
+ 'statement : expression'
+ print t[1]
+
+def p_expression_binop(t):
+ '''expression : expression PLUS expression
+ | expression MINUS expression
+ | expression TIMES expression
+ | expression DIVIDE expression'''
+ if t[2] == '+' : t[0] = t[1] + t[3]
+ elif t[2] == '-': t[0] = t[1] - t[3]
+ elif t[2] == '*': t[0] = t[1] * t[3]
+ elif t[3] == '/': t[0] = t[1] / t[3]
+
+def p_expression_uminus(t):
+ 'expression : MINUS expression %prec UMINUS'
+ t[0] = -t[2]
+
+def p_expression_group(t):
+ 'expression : LPAREN expression RPAREN'
+ t[0] = t[2]
+
+def p_expression_number(t):
+ 'expression : NUMBER'
+ t[0] = t[1]
+
+def p_expression_name(t):
+ 'expression : NAME'
+ try:
+ t[0] = names[t[1]]
+ except LookupError:
+ print "Undefined name '%s'" % t[1]
+ t[0] = 0
+
+def p_error(t):
+ print "Syntax error at '%s'" % t.value
+
+import yacc
+yacc.yacc()
+
+
+
+
diff --git a/ext/ply/test/yacc_unused.exp b/ext/ply/test/yacc_unused.exp
new file mode 100644
index 000000000..390754de3
--- /dev/null
+++ b/ext/ply/test/yacc_unused.exp
@@ -0,0 +1,4 @@
+./yacc_unused.py:60: Symbol 'COMMA' used, but not defined as a token or a rule.
+yacc: Symbol 'COMMA' is unreachable.
+yacc: Symbol 'exprlist' is unreachable.
+yacc.YaccError: Unable to construct parser.
diff --git a/ext/ply/test/yacc_unused.py b/ext/ply/test/yacc_unused.py
new file mode 100644
index 000000000..4cbd63327
--- /dev/null
+++ b/ext/ply/test/yacc_unused.py
@@ -0,0 +1,76 @@
+# -----------------------------------------------------------------------------
+# yacc_unused.py
+#
+# A grammar with an unused rule
+# -----------------------------------------------------------------------------
+import sys
+sys.tracebacklimit = 0
+
+from calclex import tokens
+
+# Parsing rules
+precedence = (
+ ('left','PLUS','MINUS'),
+ ('left','TIMES','DIVIDE'),
+ ('right','UMINUS'),
+ )
+
+# dictionary of names
+names = { }
+
+def p_statement_assign(t):
+ 'statement : NAME EQUALS expression'
+ names[t[1]] = t[3]
+
+def p_statement_expr(t):
+ 'statement : expression'
+ print t[1]
+
+def p_expression_binop(t):
+ '''expression : expression PLUS expression
+ | expression MINUS expression
+ | expression TIMES expression
+ | expression DIVIDE expression'''
+ if t[2] == '+' : t[0] = t[1] + t[3]
+ elif t[2] == '-': t[0] = t[1] - t[3]
+ elif t[2] == '*': t[0] = t[1] * t[3]
+ elif t[3] == '/': t[0] = t[1] / t[3]
+
+def p_expression_uminus(t):
+ 'expression : MINUS expression %prec UMINUS'
+ t[0] = -t[2]
+
+def p_expression_group(t):
+ 'expression : LPAREN expression RPAREN'
+ t[0] = t[2]
+
+def p_expression_number(t):
+ 'expression : NUMBER'
+ t[0] = t[1]
+
+def p_expression_name(t):
+ 'expression : NAME'
+ try:
+ t[0] = names[t[1]]
+ except LookupError:
+ print "Undefined name '%s'" % t[1]
+ t[0] = 0
+
+def p_expr_list(t):
+ 'exprlist : exprlist COMMA expression'
+ pass
+
+def p_expr_list_2(t):
+ 'exprlist : expression'
+ pass
+
+
+def p_error(t):
+ print "Syntax error at '%s'" % t.value
+
+import yacc
+yacc.yacc()
+
+
+
+
diff --git a/ext/ply/test/yacc_uprec.exp b/ext/ply/test/yacc_uprec.exp
new file mode 100644
index 000000000..b1a71a250
--- /dev/null
+++ b/ext/ply/test/yacc_uprec.exp
@@ -0,0 +1,2 @@
+./yacc_uprec.py:35: Nothing known about the precedence of 'UMINUS'
+yacc.YaccError: Unable to construct parser.
diff --git a/ext/ply/test/yacc_uprec.py b/ext/ply/test/yacc_uprec.py
new file mode 100644
index 000000000..139ce6318
--- /dev/null
+++ b/ext/ply/test/yacc_uprec.py
@@ -0,0 +1,62 @@
+# -----------------------------------------------------------------------------
+# yacc_uprec.py
+#
+# A grammar with a bad %prec specifier
+# -----------------------------------------------------------------------------
+import sys
+sys.tracebacklimit = 0
+
+from calclex import tokens
+
+# Parsing rules
+
+# dictionary of names
+names = { }
+
+def p_statement_assign(t):
+ 'statement : NAME EQUALS expression'
+ names[t[1]] = t[3]
+
+def p_statement_expr(t):
+ 'statement : expression'
+ print t[1]
+
+def p_expression_binop(t):
+ '''expression : expression PLUS expression
+ | expression MINUS expression
+ | expression TIMES expression
+ | expression DIVIDE expression'''
+ if t[2] == '+' : t[0] = t[1] + t[3]
+ elif t[2] == '-': t[0] = t[1] - t[3]
+ elif t[2] == '*': t[0] = t[1] * t[3]
+ elif t[3] == '/': t[0] = t[1] / t[3]
+
+def p_expression_uminus(t):
+ 'expression : MINUS expression %prec UMINUS'
+ t[0] = -t[2]
+
+def p_expression_group(t):
+ 'expression : LPAREN expression RPAREN'
+ t[0] = t[2]
+
+def p_expression_number(t):
+ 'expression : NUMBER'
+ t[0] = t[1]
+
+def p_expression_name(t):
+ 'expression : NAME'
+ try:
+ t[0] = names[t[1]]
+ except LookupError:
+ print "Undefined name '%s'" % t[1]
+ t[0] = 0
+
+def p_error(t):
+ print "Syntax error at '%s'" % t.value
+
+import yacc
+yacc.yacc()
+
+
+
+
diff --git a/ext/ply/yacc.py b/ext/ply/yacc.py
new file mode 100644
index 000000000..1041745ed
--- /dev/null
+++ b/ext/ply/yacc.py
@@ -0,0 +1,1846 @@
+#-----------------------------------------------------------------------------
+# ply: yacc.py
+#
+# Author: David M. Beazley (beazley@cs.uchicago.edu)
+# Department of Computer Science
+# University of Chicago
+# Chicago, IL 60637
+#
+# Copyright (C) 2001, David M. Beazley
+#
+# $Header: /home/stever/bk/newmem2/ext/ply/yacc.py 1.3 03/06/06 14:59:28-00:00 stever@ $
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+# See the file COPYING for a complete copy of the LGPL.
+#
+#
+# This implements an LR parser that is constructed from grammar rules defined
+# as Python functions. Roughly speaking, this module is a cross between
+# John Aycock's Spark system and the GNU bison utility.
+#
+# Disclaimer: This is a work in progress. SLR parsing seems to work fairly
+# well and there is extensive error checking. LALR(1) is in progress. The
+# rest of this file is a bit of a mess. Please pardon the dust.
+#
+# The current implementation is only somewhat object-oriented. The
+# LR parser itself is defined in terms of an object (which allows multiple
+# parsers to co-exist). However, most of the variables used during table
+# construction are defined in terms of global variables. Users shouldn't
+# notice unless they are trying to define multiple parsers at the same
+# time using threads (in which case they should have their head examined).
+#-----------------------------------------------------------------------------
+
+__version__ = "1.3"
+
+#-----------------------------------------------------------------------------
+# === User configurable parameters ===
+#
+# Change these to modify the default behavior of yacc (if you wish)
+#-----------------------------------------------------------------------------
+
+yaccdebug = 1 # Debugging mode. If set, yacc generates a
+ # a 'parser.out' file in the current directory
+
+debug_file = 'parser.out' # Default name of the debugging file
+tab_module = 'parsetab' # Default name of the table module
+default_lr = 'SLR' # Default LR table generation method
+
+error_count = 3 # Number of symbols that must be shifted to leave recovery mode
+
+import re, types, sys, cStringIO, md5, os.path
+
+# Exception raised for yacc-related errors
+class YaccError(Exception): pass
+
+#-----------------------------------------------------------------------------
+# === LR Parsing Engine ===
+#
+# The following classes are used for the LR parser itself. These are not
+# used during table construction and are independent of the actual LR
+# table generation algorithm
+#-----------------------------------------------------------------------------
+
+# This class is used to hold non-terminal grammar symbols during parsing.
+# It normally has the following attributes set:
+# .type = Grammar symbol type
+# .value = Symbol value
+# .lineno = Starting line number
+# .endlineno = Ending line number (optional, set automatically)
+
+class YaccSymbol:
+ def __str__(self): return self.type
+ def __repr__(self): return str(self)
+
+# This class is a wrapper around the objects actually passed to each
+# grammar rule. Index lookup and assignment actually assign the
+# .value attribute of the underlying YaccSymbol object.
+# The lineno() method returns the line number of a given
+# item (or 0 if not defined). The linespan() method returns
+# a tuple of (startline,endline) representing the range of lines
+# for a symbol.
+
+class YaccSlice:
+ def __init__(self,s):
+ self.slice = s
+ self.pbstack = []
+
+ def __getitem__(self,n):
+ return self.slice[n].value
+
+ def __setitem__(self,n,v):
+ self.slice[n].value = v
+
+ def __len__(self):
+ return len(self.slice)
+
+ def lineno(self,n):
+ return getattr(self.slice[n],"lineno",0)
+
+ def linespan(self,n):
+ startline = getattr(self.slice[n],"lineno",0)
+ endline = getattr(self.slice[n],"endlineno",startline)
+ return startline,endline
+
+ def pushback(self,n):
+ if n <= 0:
+ raise ValueError, "Expected a positive value"
+ if n > (len(self.slice)-1):
+ raise ValueError, "Can't push %d tokens. Only %d are available." % (n,len(self.slice)-1)
+ for i in range(0,n):
+ self.pbstack.append(self.slice[-i-1])
+
+# The LR Parsing engine. This is defined as a class so that multiple parsers
+# can exist in the same process. A user never instantiates this directly.
+# Instead, the global yacc() function should be used to create a suitable Parser
+# object.
+
+class Parser:
+ def __init__(self,magic=None):
+
+ # This is a hack to keep users from trying to instantiate a Parser
+ # object directly.
+
+ if magic != "xyzzy":
+ raise YaccError, "Can't instantiate Parser. Use yacc() instead."
+
+ # Reset internal state
+ self.productions = None # List of productions
+ self.errorfunc = None # Error handling function
+ self.action = { } # LR Action table
+ self.goto = { } # LR goto table
+ self.require = { } # Attribute require table
+ self.method = "Unknown LR" # Table construction method used
+
+ def errok(self):
+ self.errorcount = 0
+
+ def restart(self):
+ del self.statestack[:]
+ del self.symstack[:]
+ sym = YaccSymbol()
+ sym.type = '$'
+ self.symstack.append(sym)
+ self.statestack.append(0)
+
+ def parse(self,input=None,lexer=None,debug=0):
+ lookahead = None # Current lookahead symbol
+ lookaheadstack = [ ] # Stack of lookahead symbols
+ actions = self.action # Local reference to action table
+ goto = self.goto # Local reference to goto table
+ prod = self.productions # Local reference to production list
+ pslice = YaccSlice(None) # Slice object passed to grammar rules
+ pslice.parser = self # Parser object
+ self.errorcount = 0 # Used during error recovery
+
+ # If no lexer was given, we will try to use the lex module
+ if not lexer:
+ import lex as lexer
+
+ pslice.lexer = lexer
+
+ # If input was supplied, pass to lexer
+ if input:
+ lexer.input(input)
+
+ # Tokenize function
+ get_token = lexer.token
+
+ statestack = [ ] # Stack of parsing states
+ self.statestack = statestack
+ symstack = [ ] # Stack of grammar symbols
+ self.symstack = symstack
+
+ errtoken = None # Err token
+
+ # The start state is assumed to be (0,$)
+ statestack.append(0)
+ sym = YaccSymbol()
+ sym.type = '$'
+ symstack.append(sym)
+
+ while 1:
+ # Get the next symbol on the input. If a lookahead symbol
+ # is already set, we just use that. Otherwise, we'll pull
+ # the next token off of the lookaheadstack or from the lexer
+ if not lookahead:
+ if not lookaheadstack:
+ lookahead = get_token() # Get the next token
+ else:
+ lookahead = lookaheadstack.pop()
+ if not lookahead:
+ lookahead = YaccSymbol()
+ lookahead.type = '$'
+ if debug:
+ print "%-20s : %s" % (lookahead, [xx.type for xx in symstack])
+
+ # Check the action table
+ s = statestack[-1]
+ ltype = lookahead.type
+ t = actions.get((s,ltype),None)
+
+ if t is not None:
+ if t > 0:
+ # shift a symbol on the stack
+ if ltype == '$':
+ # Error, end of input
+ print "yacc: Parse error. EOF"
+ return
+ statestack.append(t)
+ symstack.append(lookahead)
+ lookahead = None
+
+ # Decrease error count on successful shift
+ if self.errorcount > 0:
+ self.errorcount -= 1
+
+ continue
+
+ if t < 0:
+ # reduce a symbol on the stack, emit a production
+ p = prod[-t]
+ pname = p.name
+ plen = p.len
+
+ # Get production function
+ sym = YaccSymbol()
+ sym.type = pname # Production name
+ sym.value = None
+
+ if plen:
+ targ = symstack[-plen-1:]
+ targ[0] = sym
+ try:
+ sym.lineno = targ[1].lineno
+ sym.endlineno = getattr(targ[-1],"endlineno",targ[-1].lineno)
+ except AttributeError:
+ sym.lineno = 0
+ del symstack[-plen:]
+ del statestack[-plen:]
+ else:
+ sym.lineno = 0
+ targ = [ sym ]
+ pslice.slice = targ
+ pslice.pbstack = []
+ # Call the grammar rule with our special slice object
+ p.func(pslice)
+
+ # Validate attributes of the resulting value attribute
+# if require:
+# try:
+# t0 = targ[0]
+# r = Requires.get(t0.type,None)
+# t0d = t0.__dict__
+# if r:
+# for field in r:
+# tn = t0
+# for fname in field:
+# try:
+# tf = tn.__dict__
+# tn = tf.get(fname)
+# except StandardError:
+# tn = None
+# if not tn:
+# print "%s:%d: Rule %s doesn't set required attribute '%s'" % \
+# (p.file,p.line,p.name,".".join(field))
+# except TypeError,LookupError:
+# print "Bad requires directive " % r
+# pass
+
+
+ # If there was a pushback, put that on the stack
+ if pslice.pbstack:
+ lookaheadstack.append(lookahead)
+ for _t in pslice.pbstack:
+ lookaheadstack.append(_t)
+ lookahead = None
+
+ symstack.append(sym)
+ statestack.append(goto[statestack[-1],pname])
+ continue
+
+ if t == 0:
+ n = symstack[-1]
+ return getattr(n,"value",None)
+
+ if t == None:
+ # We have some kind of parsing error here. To handle this,
+ # we are going to push the current token onto the tokenstack
+ # and replace it with an 'error' token. If there are any synchronization
+ # rules, they may catch it.
+ #
+ # In addition to pushing the error token, we call call the user defined p_error()
+ # function if this is the first syntax error. This function is only called
+ # if errorcount == 0.
+
+ if not self.errorcount:
+ self.errorcount = error_count
+ errtoken = lookahead
+ if errtoken.type == '$':
+ errtoken = None # End of file!
+ if self.errorfunc:
+ global errok,token,restart
+ errok = self.errok # Set some special functions available in error recovery
+ token = get_token
+ restart = self.restart
+ tok = self.errorfunc(errtoken)
+ del errok, token, restart # Delete special functions
+
+ if not self.errorcount:
+ # User must have done some kind of panic mode recovery on their own. The returned token
+ # is the next lookahead
+ lookahead = tok
+ errtoken = None
+ continue
+ else:
+ if errtoken:
+ if hasattr(errtoken,"lineno"): lineno = lookahead.lineno
+ else: lineno = 0
+ if lineno:
+ print "yacc: Syntax error at line %d, token=%s" % (lineno, errtoken.type)
+ else:
+ print "yacc: Syntax error, token=%s" % errtoken.type
+ else:
+ print "yacc: Parse error in input. EOF"
+ return
+
+ else:
+ self.errorcount = error_count
+
+ # case 1: the statestack only has 1 entry on it. If we're in this state, the
+ # entire parse has been rolled back and we're completely hosed. The token is
+ # discarded and we just keep going.
+
+ if len(statestack) <= 1 and lookahead.type != '$':
+ lookahead = None
+ errtoken = None
+ # Nuke the pushback stack
+ del lookaheadstack[:]
+ continue
+
+ # case 2: the statestack has a couple of entries on it, but we're
+ # at the end of the file. nuke the top entry and generate an error token
+
+ # Start nuking entries on the stack
+ if lookahead.type == '$':
+ # Whoa. We're really hosed here. Bail out
+ return
+
+ if lookahead.type != 'error':
+ sym = symstack[-1]
+ if sym.type == 'error':
+ # Hmmm. Error is on top of stack, we'll just nuke input
+ # symbol and continue
+ lookahead = None
+ continue
+ t = YaccSymbol()
+ t.type = 'error'
+ if hasattr(lookahead,"lineno"):
+ t.lineno = lookahead.lineno
+ t.value = lookahead
+ lookaheadstack.append(lookahead)
+ lookahead = t
+ else:
+ symstack.pop()
+ statestack.pop()
+
+ continue
+
+ # Call an error function here
+ raise RuntimeError, "yacc: internal parser error!!!\n"
+
+# -----------------------------------------------------------------------------
+# === Parser Construction ===
+#
+# The following functions and variables are used to implement the yacc() function
+# itself. This is pretty hairy stuff involving lots of error checking,
+# construction of LR items, kernels, and so forth. Although a lot of
+# this work is done using global variables, the resulting Parser object
+# is completely self contained--meaning that it is safe to repeatedly
+# call yacc() with different grammars in the same application.
+# -----------------------------------------------------------------------------
+
+# -----------------------------------------------------------------------------
+# validate_file()
+#
+# This function checks to see if there are duplicated p_rulename() functions
+# in the parser module file. Without this function, it is really easy for
+# users to make mistakes by cutting and pasting code fragments (and it's a real
+# bugger to try and figure out why the resulting parser doesn't work). Therefore,
+# we just do a little regular expression pattern matching of def statements
+# to try and detect duplicates.
+# -----------------------------------------------------------------------------
+
+def validate_file(filename):
+ base,ext = os.path.splitext(filename)
+ if ext != '.py': return 1 # No idea. Assume it's okay.
+
+ try:
+ f = open(filename)
+ lines = f.readlines()
+ f.close()
+ except IOError:
+ return 1 # Oh well
+
+ # Match def p_funcname(
+ fre = re.compile(r'\s*def\s+(p_[a-zA-Z_0-9]*)\(')
+ counthash = { }
+ linen = 1
+ noerror = 1
+ for l in lines:
+ m = fre.match(l)
+ if m:
+ name = m.group(1)
+ prev = counthash.get(name)
+ if not prev:
+ counthash[name] = linen
+ else:
+ print "%s:%d: Function %s redefined. Previously defined on line %d" % (filename,linen,name,prev)
+ noerror = 0
+ linen += 1
+ return noerror
+
+# This function looks for functions that might be grammar rules, but which don't have the proper p_suffix.
+def validate_dict(d):
+ for n,v in d.items():
+ if n[0:2] == 'p_' and isinstance(v,types.FunctionType): continue
+ if n[0:2] == 't_': continue
+
+ if n[0:2] == 'p_':
+ print "yacc: Warning. '%s' not defined as a function" % n
+ if isinstance(v,types.FunctionType) and v.func_code.co_argcount == 1:
+ try:
+ doc = v.__doc__.split(" ")
+ if doc[1] == ':':
+ print "%s:%d: Warning. Possible grammar rule '%s' defined without p_ prefix." % (v.func_code.co_filename, v.func_code.co_firstlineno,n)
+ except StandardError:
+ pass
+
+# -----------------------------------------------------------------------------
+# === GRAMMAR FUNCTIONS ===
+#
+# The following global variables and functions are used to store, manipulate,
+# and verify the grammar rules specified by the user.
+# -----------------------------------------------------------------------------
+
+# Initialize all of the global variables used during grammar construction
+def initialize_vars():
+ global Productions, Prodnames, Prodmap, Terminals
+ global Nonterminals, First, Follow, Precedence, LRitems
+ global Errorfunc, Signature, Requires
+
+ Productions = [None] # A list of all of the productions. The first
+ # entry is always reserved for the purpose of
+ # building an augmented grammar
+
+ Prodnames = { } # A dictionary mapping the names of nonterminals to a list of all
+ # productions of that nonterminal.
+
+ Prodmap = { } # A dictionary that is only used to detect duplicate
+ # productions.
+
+ Terminals = { } # A dictionary mapping the names of terminal symbols to a
+ # list of the rules where they are used.
+
+ Nonterminals = { } # A dictionary mapping names of nonterminals to a list
+ # of rule numbers where they are used.
+
+ First = { } # A dictionary of precomputed FIRST(x) symbols
+
+ Follow = { } # A dictionary of precomputed FOLLOW(x) symbols
+
+ Precedence = { } # Precedence rules for each terminal. Contains tuples of the
+ # form ('right',level) or ('nonassoc', level) or ('left',level)
+
+ LRitems = [ ] # A list of all LR items for the grammar. These are the
+ # productions with the "dot" like E -> E . PLUS E
+
+ Errorfunc = None # User defined error handler
+
+ Signature = md5.new() # Digital signature of the grammar rules, precedence
+ # and other information. Used to determined when a
+ # parsing table needs to be regenerated.
+
+ Requires = { } # Requires list
+
+ # File objects used when creating the parser.out debugging file
+ global _vf, _vfc
+ _vf = cStringIO.StringIO()
+ _vfc = cStringIO.StringIO()
+
+# -----------------------------------------------------------------------------
+# class Production:
+#
+# This class stores the raw information about a single production or grammar rule.
+# It has a few required attributes:
+#
+# name - Name of the production (nonterminal)
+# prod - A list of symbols making up its production
+# number - Production number.
+#
+# In addition, a few additional attributes are used to help with debugging or
+# optimization of table generation.
+#
+# file - File where production action is defined.
+# lineno - Line number where action is defined
+# func - Action function
+# prec - Precedence level
+# lr_next - Next LR item. Example, if we are ' E -> E . PLUS E'
+# then lr_next refers to 'E -> E PLUS . E'
+# lr_index - LR item index (location of the ".") in the prod list.
+# len - Length of the production (number of symbols on right hand side)
+# -----------------------------------------------------------------------------
+
+class Production:
+ def __init__(self,**kw):
+ for k,v in kw.items():
+ setattr(self,k,v)
+ self.lr_index = -1
+ self.lr0_added = 0 # Flag indicating whether or not added to LR0 closure
+ self.usyms = [ ]
+
+ def __str__(self):
+ if self.prod:
+ s = "%s -> %s" % (self.name," ".join(self.prod))
+ else:
+ s = "%s -> <empty>" % self.name
+ return s
+
+ def __repr__(self):
+ return str(self)
+
+ # Compute lr_items from the production
+ def lr_item(self,n):
+ if n > len(self.prod): return None
+ p = Production()
+ p.name = self.name
+ p.prod = list(self.prod)
+ p.number = self.number
+ p.lr_index = n
+ p.prod.insert(n,".")
+ p.prod = tuple(p.prod)
+ p.len = len(p.prod)
+ p.usyms = self.usyms
+
+ # Precompute list of productions immediately following
+ try:
+ p.lrafter = Prodnames[p.prod[n+1]]
+ except (IndexError,KeyError),e:
+ p.lrafter = []
+ try:
+ p.lrbefore = p.prod[n-1]
+ except IndexError:
+ p.lrbefore = None
+
+ return p
+
+class MiniProduction:
+ pass
+
+# Utility function
+def is_identifier(s):
+ for c in s:
+ if not (c.isalnum() or c == '_'): return 0
+ return 1
+
+# -----------------------------------------------------------------------------
+# add_production()
+#
+# Given an action function, this function assembles a production rule.
+# The production rule is assumed to be found in the function's docstring.
+# This rule has the general syntax:
+#
+# name1 ::= production1
+# | production2
+# | production3
+# ...
+# | productionn
+# name2 ::= production1
+# | production2
+# ...
+# -----------------------------------------------------------------------------
+
+def add_production(f,file,line,prodname,syms):
+
+ if Terminals.has_key(prodname):
+ print "%s:%d: Illegal rule name '%s'. Already defined as a token." % (file,line,prodname)
+ return -1
+ if prodname == 'error':
+ print "%s:%d: Illegal rule name '%s'. error is a reserved word." % (file,line,prodname)
+ return -1
+
+ if not is_identifier(prodname):
+ print "%s:%d: Illegal rule name '%s'" % (file,line,prodname)
+ return -1
+
+ for s in syms:
+ if not is_identifier(s) and s != '%prec':
+ print "%s:%d: Illegal name '%s' in rule '%s'" % (file,line,s, prodname)
+ return -1
+
+ # See if the rule is already in the rulemap
+ map = "%s -> %s" % (prodname,syms)
+ if Prodmap.has_key(map):
+ m = Prodmap[map]
+ print "%s:%d: Duplicate rule %s." % (file,line, m)
+ print "%s:%d: Previous definition at %s:%d" % (file,line, m.file, m.line)
+ return -1
+
+ p = Production()
+ p.name = prodname
+ p.prod = syms
+ p.file = file
+ p.line = line
+ p.func = f
+ p.number = len(Productions)
+
+
+ Productions.append(p)
+ Prodmap[map] = p
+ if not Nonterminals.has_key(prodname):
+ Nonterminals[prodname] = [ ]
+
+ # Add all terminals to Terminals
+ i = 0
+ while i < len(p.prod):
+ t = p.prod[i]
+ if t == '%prec':
+ try:
+ precname = p.prod[i+1]
+ except IndexError:
+ print "%s:%d: Syntax error. Nothing follows %%prec." % (p.file,p.line)
+ return -1
+
+ prec = Precedence.get(precname,None)
+ if not prec:
+ print "%s:%d: Nothing known about the precedence of '%s'" % (p.file,p.line,precname)
+ return -1
+ else:
+ p.prec = prec
+ del p.prod[i]
+ del p.prod[i]
+ continue
+
+ if Terminals.has_key(t):
+ Terminals[t].append(p.number)
+ # Is a terminal. We'll assign a precedence to p based on this
+ if not hasattr(p,"prec"):
+ p.prec = Precedence.get(t,('right',0))
+ else:
+ if not Nonterminals.has_key(t):
+ Nonterminals[t] = [ ]
+ Nonterminals[t].append(p.number)
+ i += 1
+
+ if not hasattr(p,"prec"):
+ p.prec = ('right',0)
+
+ # Set final length of productions
+ p.len = len(p.prod)
+ p.prod = tuple(p.prod)
+
+ # Calculate unique syms in the production
+ p.usyms = [ ]
+ for s in p.prod:
+ if s not in p.usyms:
+ p.usyms.append(s)
+
+ # Add to the global productions list
+ try:
+ Prodnames[p.name].append(p)
+ except KeyError:
+ Prodnames[p.name] = [ p ]
+ return 0
+
+# Given a raw rule function, this function rips out its doc string
+# and adds rules to the grammar
+
+def add_function(f):
+ line = f.func_code.co_firstlineno
+ file = f.func_code.co_filename
+ error = 0
+
+ if f.func_code.co_argcount > 1:
+ print "%s:%d: Rule '%s' has too many arguments." % (file,line,f.__name__)
+ return -1
+
+ if f.func_code.co_argcount < 1:
+ print "%s:%d: Rule '%s' requires an argument." % (file,line,f.__name__)
+ return -1
+
+ if f.__doc__:
+ # Split the doc string into lines
+ pstrings = f.__doc__.splitlines()
+ lastp = None
+ dline = line
+ for ps in pstrings:
+ dline += 1
+ p = ps.split()
+ if not p: continue
+ try:
+ if p[0] == '|':
+ # This is a continuation of a previous rule
+ if not lastp:
+ print "%s:%d: Misplaced '|'." % (file,dline)
+ return -1
+ prodname = lastp
+ if len(p) > 1:
+ syms = p[1:]
+ else:
+ syms = [ ]
+ else:
+ prodname = p[0]
+ lastp = prodname
+ assign = p[1]
+ if len(p) > 2:
+ syms = p[2:]
+ else:
+ syms = [ ]
+ if assign != ':' and assign != '::=':
+ print "%s:%d: Syntax error. Expected ':'" % (file,dline)
+ return -1
+ e = add_production(f,file,dline,prodname,syms)
+ error += e
+ except StandardError:
+ print "%s:%d: Syntax error in rule '%s'" % (file,dline,ps)
+ error -= 1
+ else:
+ print "%s:%d: No documentation string specified in function '%s'" % (file,line,f.__name__)
+ return error
+
+
+# Cycle checking code (Michael Dyck)
+
+def compute_reachable():
+ '''
+ Find each symbol that can be reached from the start symbol.
+ Print a warning for any nonterminals that can't be reached.
+ (Unused terminals have already had their warning.)
+ '''
+ Reachable = { }
+ for s in Terminals.keys() + Nonterminals.keys():
+ Reachable[s] = 0
+
+ mark_reachable_from( Productions[0].prod[0], Reachable )
+
+ for s in Nonterminals.keys():
+ if not Reachable[s]:
+ print "yacc: Symbol '%s' is unreachable." % s
+
+def mark_reachable_from(s, Reachable):
+ '''
+ Mark all symbols that are reachable from symbol s.
+ '''
+ if Reachable[s]:
+ # We've already reached symbol s.
+ return
+ Reachable[s] = 1
+ for p in Prodnames.get(s,[]):
+ for r in p.prod:
+ mark_reachable_from(r, Reachable)
+
+# -----------------------------------------------------------------------------
+# compute_terminates()
+#
+# This function looks at the various parsing rules and tries to detect
+# infinite recursion cycles (grammar rules where there is no possible way
+# to derive a string of only terminals).
+# -----------------------------------------------------------------------------
+def compute_terminates():
+ '''
+ Raise an error for any symbols that don't terminate.
+ '''
+ Terminates = {}
+
+ # Terminals:
+ for t in Terminals.keys():
+ Terminates[t] = 1
+
+ Terminates['$'] = 1
+
+ # Nonterminals:
+
+ # Initialize to false:
+ for n in Nonterminals.keys():
+ Terminates[n] = 0
+
+ # Then propagate termination until no change:
+ while 1:
+ some_change = 0
+ for (n,pl) in Prodnames.items():
+ # Nonterminal n terminates iff any of its productions terminates.
+ for p in pl:
+ # Production p terminates iff all of its rhs symbols terminate.
+ for s in p.prod:
+ if not Terminates[s]:
+ # The symbol s does not terminate,
+ # so production p does not terminate.
+ p_terminates = 0
+ break
+ else:
+ # didn't break from the loop,
+ # so every symbol s terminates
+ # so production p terminates.
+ p_terminates = 1
+
+ if p_terminates:
+ # symbol n terminates!
+ if not Terminates[n]:
+ Terminates[n] = 1
+ some_change = 1
+ # Don't need to consider any more productions for this n.
+ break
+
+ if not some_change:
+ break
+
+ some_error = 0
+ for (s,terminates) in Terminates.items():
+ if not terminates:
+ if not Prodnames.has_key(s) and not Terminals.has_key(s) and s != 'error':
+ # s is used-but-not-defined, and we've already warned of that,
+ # so it would be overkill to say that it's also non-terminating.
+ pass
+ else:
+ print "yacc: Infinite recursion detected for symbol '%s'." % s
+ some_error = 1
+
+ return some_error
+
+# -----------------------------------------------------------------------------
+# verify_productions()
+#
+# This function examines all of the supplied rules to see if they seem valid.
+# -----------------------------------------------------------------------------
+def verify_productions(cycle_check=1):
+ error = 0
+ for p in Productions:
+ if not p: continue
+
+ for s in p.prod:
+ if not Prodnames.has_key(s) and not Terminals.has_key(s) and s != 'error':
+ print "%s:%d: Symbol '%s' used, but not defined as a token or a rule." % (p.file,p.line,s)
+ error = 1
+ continue
+
+ unused_tok = 0
+ # Now verify all of the tokens
+ if yaccdebug:
+ _vf.write("Unused terminals:\n\n")
+ for s,v in Terminals.items():
+ if s != 'error' and not v:
+ print "yacc: Warning. Token '%s' defined, but not used." % s
+ if yaccdebug: _vf.write(" %s\n"% s)
+ unused_tok += 1
+
+ # Print out all of the productions
+ if yaccdebug:
+ _vf.write("\nGrammar\n\n")
+ for i in range(1,len(Productions)):
+ _vf.write("Rule %-5d %s\n" % (i, Productions[i]))
+
+ unused_prod = 0
+ # Verify the use of all productions
+ for s,v in Nonterminals.items():
+ if not v:
+ p = Prodnames[s][0]
+ print "%s:%d: Warning. Rule '%s' defined, but not used." % (p.file,p.line, s)
+ unused_prod += 1
+
+
+ if unused_tok == 1:
+ print "yacc: Warning. There is 1 unused token."
+ if unused_tok > 1:
+ print "yacc: Warning. There are %d unused tokens." % unused_tok
+
+ if unused_prod == 1:
+ print "yacc: Warning. There is 1 unused rule."
+ if unused_prod > 1:
+ print "yacc: Warning. There are %d unused rules." % unused_prod
+
+ if yaccdebug:
+ _vf.write("\nTerminals, with rules where they appear\n\n")
+ ks = Terminals.keys()
+ ks.sort()
+ for k in ks:
+ _vf.write("%-20s : %s\n" % (k, " ".join([str(s) for s in Terminals[k]])))
+ _vf.write("\nNonterminals, with rules where they appear\n\n")
+ ks = Nonterminals.keys()
+ ks.sort()
+ for k in ks:
+ _vf.write("%-20s : %s\n" % (k, " ".join([str(s) for s in Nonterminals[k]])))
+
+ if (cycle_check):
+ compute_reachable()
+ error += compute_terminates()
+# error += check_cycles()
+ return error
+
+# -----------------------------------------------------------------------------
+# build_lritems()
+#
+# This function walks the list of productions and builds a complete set of the
+# LR items. The LR items are stored in two ways: First, they are uniquely
+# numbered and placed in the list _lritems. Second, a linked list of LR items
+# is built for each production. For example:
+#
+# E -> E PLUS E
+#
+# Creates the list
+#
+# [E -> . E PLUS E, E -> E . PLUS E, E -> E PLUS . E, E -> E PLUS E . ]
+# -----------------------------------------------------------------------------
+
+def build_lritems():
+ for p in Productions:
+ lastlri = p
+ lri = p.lr_item(0)
+ i = 0
+ while 1:
+ lri = p.lr_item(i)
+ lastlri.lr_next = lri
+ if not lri: break
+ lri.lr_num = len(LRitems)
+ LRitems.append(lri)
+ lastlri = lri
+ i += 1
+
+ # In order for the rest of the parser generator to work, we need to
+ # guarantee that no more lritems are generated. Therefore, we nuke
+ # the p.lr_item method. (Only used in debugging)
+ # Production.lr_item = None
+
+# -----------------------------------------------------------------------------
+# add_precedence()
+#
+# Given a list of precedence rules, add to the precedence table.
+# -----------------------------------------------------------------------------
+
+def add_precedence(plist):
+ plevel = 0
+ error = 0
+ for p in plist:
+ plevel += 1
+ try:
+ prec = p[0]
+ terms = p[1:]
+ if prec != 'left' and prec != 'right' and prec != 'nonassoc':
+ print "yacc: Invalid precedence '%s'" % prec
+ return -1
+ for t in terms:
+ if Precedence.has_key(t):
+ print "yacc: Precedence already specified for terminal '%s'" % t
+ error += 1
+ continue
+ Precedence[t] = (prec,plevel)
+ except:
+ print "yacc: Invalid precedence table."
+ error += 1
+
+ return error
+
+# -----------------------------------------------------------------------------
+# augment_grammar()
+#
+# Compute the augmented grammar. This is just a rule S' -> start where start
+# is the starting symbol.
+# -----------------------------------------------------------------------------
+
+def augment_grammar(start=None):
+ if not start:
+ start = Productions[1].name
+ Productions[0] = Production(name="S'",prod=[start],number=0,len=1,prec=('right',0),func=None)
+ Productions[0].usyms = [ start ]
+ Nonterminals[start].append(0)
+
+
+# -------------------------------------------------------------------------
+# first()
+#
+# Compute the value of FIRST1(beta) where beta is a tuple of symbols.
+#
+# During execution of compute_first1, the result may be incomplete.
+# Afterward (e.g., when called from compute_follow()), it will be complete.
+# -------------------------------------------------------------------------
+def first(beta):
+
+ # We are computing First(x1,x2,x3,...,xn)
+ result = [ ]
+ for x in beta:
+ x_produces_empty = 0
+
+ # Add all the non-<empty> symbols of First[x] to the result.
+ for f in First[x]:
+ if f == '<empty>':
+ x_produces_empty = 1
+ else:
+ if f not in result: result.append(f)
+
+ if x_produces_empty:
+ # We have to consider the next x in beta,
+ # i.e. stay in the loop.
+ pass
+ else:
+ # We don't have to consider any further symbols in beta.
+ break
+ else:
+ # There was no 'break' from the loop,
+ # so x_produces_empty was true for all x in beta,
+ # so beta produces empty as well.
+ result.append('<empty>')
+
+ return result
+
+
+# FOLLOW(x)
+# Given a non-terminal. This function computes the set of all symbols
+# that might follow it. Dragon book, p. 189.
+
+def compute_follow(start=None):
+ # Add '$' to the follow list of the start symbol
+ for k in Nonterminals.keys():
+ Follow[k] = [ ]
+
+ if not start:
+ start = Productions[1].name
+
+ Follow[start] = [ '$' ]
+
+ while 1:
+ didadd = 0
+ for p in Productions[1:]:
+ # Here is the production set
+ for i in range(len(p.prod)):
+ B = p.prod[i]
+ if Nonterminals.has_key(B):
+ # Okay. We got a non-terminal in a production
+ fst = first(p.prod[i+1:])
+ hasempty = 0
+ for f in fst:
+ if f != '<empty>' and f not in Follow[B]:
+ Follow[B].append(f)
+ didadd = 1
+ if f == '<empty>':
+ hasempty = 1
+ if hasempty or i == (len(p.prod)-1):
+ # Add elements of follow(a) to follow(b)
+ for f in Follow[p.name]:
+ if f not in Follow[B]:
+ Follow[B].append(f)
+ didadd = 1
+ if not didadd: break
+
+ if 0 and yaccdebug:
+ _vf.write('\nFollow:\n')
+ for k in Nonterminals.keys():
+ _vf.write("%-20s : %s\n" % (k, " ".join([str(s) for s in Follow[k]])))
+
+# -------------------------------------------------------------------------
+# compute_first1()
+#
+# Compute the value of FIRST1(X) for all symbols
+# -------------------------------------------------------------------------
+def compute_first1():
+
+ # Terminals:
+ for t in Terminals.keys():
+ First[t] = [t]
+
+ First['$'] = ['$']
+ First['#'] = ['#'] # what's this for?
+
+ # Nonterminals:
+
+ # Initialize to the empty set:
+ for n in Nonterminals.keys():
+ First[n] = []
+
+ # Then propagate symbols until no change:
+ while 1:
+ some_change = 0
+ for n in Nonterminals.keys():
+ for p in Prodnames[n]:
+ for f in first(p.prod):
+ if f not in First[n]:
+ First[n].append( f )
+ some_change = 1
+ if not some_change:
+ break
+
+ if 0 and yaccdebug:
+ _vf.write('\nFirst:\n')
+ for k in Nonterminals.keys():
+ _vf.write("%-20s : %s\n" %
+ (k, " ".join([str(s) for s in First[k]])))
+
+# -----------------------------------------------------------------------------
+# === SLR Generation ===
+#
+# The following functions are used to construct SLR (Simple LR) parsing tables
+# as described on p.221-229 of the dragon book.
+# -----------------------------------------------------------------------------
+
+# Global variables for the LR parsing engine
+def lr_init_vars():
+ global _lr_action, _lr_goto, _lr_method
+ global _lr_goto_cache
+
+ _lr_action = { } # Action table
+ _lr_goto = { } # Goto table
+ _lr_method = "Unknown" # LR method used
+ _lr_goto_cache = { }
+
+# Compute the LR(0) closure operation on I, where I is a set of LR(0) items.
+# prodlist is a list of productions.
+
+_add_count = 0 # Counter used to detect cycles
+
+def lr0_closure(I):
+ global _add_count
+
+ _add_count += 1
+ prodlist = Productions
+
+ # Add everything in I to J
+ J = I[:]
+ didadd = 1
+ while didadd:
+ didadd = 0
+ for j in J:
+ for x in j.lrafter:
+ if x.lr0_added == _add_count: continue
+ # Add B --> .G to J
+ J.append(x.lr_next)
+ x.lr0_added = _add_count
+ didadd = 1
+
+ return J
+
+# Compute the LR(0) goto function goto(I,X) where I is a set
+# of LR(0) items and X is a grammar symbol. This function is written
+# in a way that guarantees uniqueness of the generated goto sets
+# (i.e. the same goto set will never be returned as two different Python
+# objects). With uniqueness, we can later do fast set comparisons using
+# id(obj) instead of element-wise comparison.
+
+def lr0_goto(I,x):
+ # First we look for a previously cached entry
+ g = _lr_goto_cache.get((id(I),x),None)
+ if g: return g
+
+ # Now we generate the goto set in a way that guarantees uniqueness
+ # of the result
+
+ s = _lr_goto_cache.get(x,None)
+ if not s:
+ s = { }
+ _lr_goto_cache[x] = s
+
+ gs = [ ]
+ for p in I:
+ n = p.lr_next
+ if n and n.lrbefore == x:
+ s1 = s.get(id(n),None)
+ if not s1:
+ s1 = { }
+ s[id(n)] = s1
+ gs.append(n)
+ s = s1
+ g = s.get('$',None)
+ if not g:
+ if gs:
+ g = lr0_closure(gs)
+ s['$'] = g
+ else:
+ s['$'] = gs
+ _lr_goto_cache[(id(I),x)] = g
+ return g
+
+# Compute the kernel of a set of LR(0) items
+def lr0_kernel(I):
+ KI = [ ]
+ for p in I:
+ if p.name == "S'" or p.lr_index > 0 or p.len == 0:
+ KI.append(p)
+
+ return KI
+
+_lr0_cidhash = { }
+
+# Compute the LR(0) sets of item function
+def lr0_items():
+
+ C = [ lr0_closure([Productions[0].lr_next]) ]
+ i = 0
+ for I in C:
+ _lr0_cidhash[id(I)] = i
+ i += 1
+
+ # Loop over the items in C and each grammar symbols
+ i = 0
+ while i < len(C):
+ I = C[i]
+ i += 1
+
+ # Collect all of the symbols that could possibly be in the goto(I,X) sets
+ asyms = { }
+ for ii in I:
+ for s in ii.usyms:
+ asyms[s] = None
+
+ for x in asyms.keys():
+ g = lr0_goto(I,x)
+ if not g: continue
+ if _lr0_cidhash.has_key(id(g)): continue
+ _lr0_cidhash[id(g)] = len(C)
+ C.append(g)
+
+ return C
+
+# -----------------------------------------------------------------------------
+# slr_parse_table()
+#
+# This function constructs an SLR table.
+# -----------------------------------------------------------------------------
+def slr_parse_table():
+ global _lr_method
+ goto = _lr_goto # Goto array
+ action = _lr_action # Action array
+ actionp = { } # Action production array (temporary)
+
+ _lr_method = "SLR"
+
+ n_srconflict = 0
+ n_rrconflict = 0
+
+ if yaccdebug:
+ _vf.write("\n\nParsing method: SLR\n\n")
+
+ # Step 1: Construct C = { I0, I1, ... IN}, collection of LR(0) items
+ # This determines the number of states
+
+ C = lr0_items()
+
+ # Build the parser table, state by state
+ st = 0
+ for I in C:
+ # Loop over each production in I
+ actlist = [ ] # List of actions
+
+ if yaccdebug:
+ _vf.write("\nstate %d\n\n" % st)
+ for p in I:
+ _vf.write(" (%d) %s\n" % (p.number, str(p)))
+ _vf.write("\n")
+
+ for p in I:
+ try:
+ if p.prod[-1] == ".":
+ if p.name == "S'":
+ # Start symbol. Accept!
+ action[st,"$"] = 0
+ actionp[st,"$"] = p
+ else:
+ # We are at the end of a production. Reduce!
+ for a in Follow[p.name]:
+ actlist.append((a,p,"reduce using rule %d (%s)" % (p.number,p)))
+ r = action.get((st,a),None)
+ if r is not None:
+ # Whoa. Have a shift/reduce or reduce/reduce conflict
+ if r > 0:
+ # Need to decide on shift or reduce here
+ # By default we favor shifting. Need to add
+ # some precedence rules here.
+ sprec,slevel = Productions[actionp[st,a].number].prec
+ rprec,rlevel = Precedence.get(a,('right',0))
+ if (slevel < rlevel) or ((slevel == rlevel) and (rprec == 'left')):
+ # We really need to reduce here.
+ action[st,a] = -p.number
+ actionp[st,a] = p
+ if not slevel and not rlevel:
+ _vfc.write("shift/reduce conflict in state %d resolved as reduce.\n" % st)
+ _vf.write(" ! shift/reduce conflict for %s resolved as reduce.\n" % a)
+ n_srconflict += 1
+ elif (slevel == rlevel) and (rprec == 'nonassoc'):
+ action[st,a] = None
+ else:
+ # Hmmm. Guess we'll keep the shift
+ if not slevel and not rlevel:
+ _vfc.write("shift/reduce conflict in state %d resolved as shift.\n" % st)
+ _vf.write(" ! shift/reduce conflict for %s resolved as shift.\n" % a)
+ n_srconflict +=1
+ elif r < 0:
+ # Reduce/reduce conflict. In this case, we favor the rule
+ # that was defined first in the grammar file
+ oldp = Productions[-r]
+ pp = Productions[p.number]
+ if oldp.line > pp.line:
+ action[st,a] = -p.number
+ actionp[st,a] = p
+ # print "Reduce/reduce conflict in state %d" % st
+ n_rrconflict += 1
+ _vfc.write("reduce/reduce conflict in state %d resolved using rule %d (%s).\n" % (st, actionp[st,a].number, actionp[st,a]))
+ _vf.write(" ! reduce/reduce conflict for %s resolved using rule %d (%s).\n" % (a,actionp[st,a].number, actionp[st,a]))
+ else:
+ print "Unknown conflict in state %d" % st
+ else:
+ action[st,a] = -p.number
+ actionp[st,a] = p
+ else:
+ i = p.lr_index
+ a = p.prod[i+1] # Get symbol right after the "."
+ if Terminals.has_key(a):
+ g = lr0_goto(I,a)
+ j = _lr0_cidhash.get(id(g),-1)
+ if j >= 0:
+ # We are in a shift state
+ actlist.append((a,p,"shift and go to state %d" % j))
+ r = action.get((st,a),None)
+ if r is not None:
+ # Whoa have a shift/reduce or shift/shift conflict
+ if r > 0:
+ if r != j:
+ print "Shift/shift conflict in state %d" % st
+ elif r < 0:
+ # Do a precedence check.
+ # - if precedence of reduce rule is higher, we reduce.
+ # - if precedence of reduce is same and left assoc, we reduce.
+ # - otherwise we shift
+ rprec,rlevel = Productions[actionp[st,a].number].prec
+ sprec,slevel = Precedence.get(a,('right',0))
+ if (slevel > rlevel) or ((slevel == rlevel) and (rprec != 'left')):
+ # We decide to shift here... highest precedence to shift
+ action[st,a] = j
+ actionp[st,a] = p
+ if not slevel and not rlevel:
+ n_srconflict += 1
+ _vfc.write("shift/reduce conflict in state %d resolved as shift.\n" % st)
+ _vf.write(" ! shift/reduce conflict for %s resolved as shift.\n" % a)
+ elif (slevel == rlevel) and (rprec == 'nonassoc'):
+ action[st,a] = None
+ else:
+ # Hmmm. Guess we'll keep the reduce
+ if not slevel and not rlevel:
+ n_srconflict +=1
+ _vfc.write("shift/reduce conflict in state %d resolved as reduce.\n" % st)
+ _vf.write(" ! shift/reduce conflict for %s resolved as reduce.\n" % a)
+
+ else:
+ print "Unknown conflict in state %d" % st
+ else:
+ action[st,a] = j
+ actionp[st,a] = p
+
+ except StandardError,e:
+ raise YaccError, "Hosed in slr_parse_table", e
+
+ # Print the actions associated with each terminal
+ if yaccdebug:
+ for a,p,m in actlist:
+ if action.has_key((st,a)):
+ if p is actionp[st,a]:
+ _vf.write(" %-15s %s\n" % (a,m))
+ _vf.write("\n")
+ for a,p,m in actlist:
+ if action.has_key((st,a)):
+ if p is not actionp[st,a]:
+ _vf.write(" ! %-15s [ %s ]\n" % (a,m))
+
+ # Construct the goto table for this state
+ if yaccdebug:
+ _vf.write("\n")
+ nkeys = { }
+ for ii in I:
+ for s in ii.usyms:
+ if Nonterminals.has_key(s):
+ nkeys[s] = None
+ for n in nkeys.keys():
+ g = lr0_goto(I,n)
+ j = _lr0_cidhash.get(id(g),-1)
+ if j >= 0:
+ goto[st,n] = j
+ if yaccdebug:
+ _vf.write(" %-15s shift and go to state %d\n" % (n,j))
+
+ st += 1
+
+ if n_srconflict == 1:
+ print "yacc: %d shift/reduce conflict" % n_srconflict
+ if n_srconflict > 1:
+ print "yacc: %d shift/reduce conflicts" % n_srconflict
+ if n_rrconflict == 1:
+ print "yacc: %d reduce/reduce conflict" % n_rrconflict
+ if n_rrconflict > 1:
+ print "yacc: %d reduce/reduce conflicts" % n_rrconflict
+
+
+# -----------------------------------------------------------------------------
+# ==== LALR(1) Parsing ====
+# **** UNFINISHED! 6/16/01
+# -----------------------------------------------------------------------------
+
+
+# Compute the lr1_closure of a set I. I is a list of tuples (p,a) where
+# p is a LR0 item and a is a terminal
+
+_lr1_add_count = 0
+
+def lr1_closure(I):
+ global _lr1_add_count
+
+ _lr1_add_count += 1
+
+ J = I[:]
+
+ # Loop over items (p,a) in I.
+ ji = 0
+ while ji < len(J):
+ p,a = J[ji]
+ # p = [ A -> alpha . B beta]
+
+ # For each production B -> gamma
+ for B in p.lr1_after:
+ f = tuple(p.lr1_beta + (a,))
+
+ # For each terminal b in first(Beta a)
+ for b in first(f):
+ # Check if (B -> . gamma, b) is in J
+ # Only way this can happen is if the add count mismatches
+ pn = B.lr_next
+ if pn.lr_added.get(b,0) == _lr1_add_count: continue
+ pn.lr_added[b] = _lr1_add_count
+ J.append((pn,b))
+ ji += 1
+
+ return J
+
+def lalr_parse_table():
+
+ # Compute some lr1 information about all of the productions
+ for p in LRitems:
+ try:
+ after = p.prod[p.lr_index + 1]
+ p.lr1_after = Prodnames[after]
+ p.lr1_beta = p.prod[p.lr_index + 2:]
+ except LookupError:
+ p.lr1_after = [ ]
+ p.lr1_beta = [ ]
+ p.lr_added = { }
+
+ # Compute the LR(0) items
+ C = lr0_items()
+ CK = []
+ for I in C:
+ CK.append(lr0_kernel(I))
+
+ print CK
+
+# -----------------------------------------------------------------------------
+# ==== LR Utility functions ====
+# -----------------------------------------------------------------------------
+
+# -----------------------------------------------------------------------------
+# _lr_write_tables()
+#
+# This function writes the LR parsing tables to a file
+# -----------------------------------------------------------------------------
+
+def lr_write_tables(modulename=tab_module):
+ filename = modulename + ".py"
+ try:
+ f = open(filename,"w")
+
+ f.write("""
+# %s
+# This file is automatically generated. Do not edit.
+
+_lr_method = %s
+
+_lr_signature = %s
+""" % (filename, repr(_lr_method), repr(Signature.digest())))
+
+ # Change smaller to 0 to go back to original tables
+ smaller = 1
+
+ # Factor out names to try and make smaller
+ if smaller:
+ items = { }
+
+ for k,v in _lr_action.items():
+ i = items.get(k[1])
+ if not i:
+ i = ([],[])
+ items[k[1]] = i
+ i[0].append(k[0])
+ i[1].append(v)
+
+ f.write("\n_lr_action_items = {")
+ for k,v in items.items():
+ f.write("%r:([" % k)
+ for i in v[0]:
+ f.write("%r," % i)
+ f.write("],[")
+ for i in v[1]:
+ f.write("%r," % i)
+
+ f.write("]),")
+ f.write("}\n")
+
+ f.write("""
+_lr_action = { }
+for _k, _v in _lr_action_items.items():
+ for _x,_y in zip(_v[0],_v[1]):
+ _lr_action[(_x,_k)] = _y
+del _lr_action_items
+""")
+
+ else:
+ f.write("\n_lr_action = { ");
+ for k,v in _lr_action.items():
+ f.write("(%r,%r):%r," % (k[0],k[1],v))
+ f.write("}\n");
+
+ if smaller:
+ # Factor out names to try and make smaller
+ items = { }
+
+ for k,v in _lr_goto.items():
+ i = items.get(k[1])
+ if not i:
+ i = ([],[])
+ items[k[1]] = i
+ i[0].append(k[0])
+ i[1].append(v)
+
+ f.write("\n_lr_goto_items = {")
+ for k,v in items.items():
+ f.write("%r:([" % k)
+ for i in v[0]:
+ f.write("%r," % i)
+ f.write("],[")
+ for i in v[1]:
+ f.write("%r," % i)
+
+ f.write("]),")
+ f.write("}\n")
+
+ f.write("""
+_lr_goto = { }
+for _k, _v in _lr_goto_items.items():
+ for _x,_y in zip(_v[0],_v[1]):
+ _lr_goto[(_x,_k)] = _y
+del _lr_goto_items
+""")
+ else:
+ f.write("\n_lr_goto = { ");
+ for k,v in _lr_goto.items():
+ f.write("(%r,%r):%r," % (k[0],k[1],v))
+ f.write("}\n");
+
+ # Write production table
+ f.write("_lr_productions = [\n")
+ for p in Productions:
+ if p:
+ if (p.func):
+ f.write(" (%r,%d,%r,%r,%d),\n" % (p.name, p.len, p.func.__name__,p.file,p.line))
+ else:
+ f.write(" (%r,%d,None,None,None),\n" % (p.name, p.len))
+ else:
+ f.write(" None,\n")
+ f.write("]\n")
+ f.close()
+
+ except IOError,e:
+ print "Unable to create '%s'" % filename
+ print e
+ return
+
+def lr_read_tables(module=tab_module,optimize=0):
+ global _lr_action, _lr_goto, _lr_productions, _lr_method
+ try:
+ exec "import %s as parsetab" % module
+
+ if (optimize) or (Signature.digest() == parsetab._lr_signature):
+ _lr_action = parsetab._lr_action
+ _lr_goto = parsetab._lr_goto
+ _lr_productions = parsetab._lr_productions
+ _lr_method = parsetab._lr_method
+ return 1
+ else:
+ return 0
+
+ except (ImportError,AttributeError):
+ return 0
+
+# -----------------------------------------------------------------------------
+# yacc(module)
+#
+# Build the parser module
+# -----------------------------------------------------------------------------
+
+def yacc(method=default_lr, debug=yaccdebug, module=None, tabmodule=tab_module, start=None, check_recursion=1, optimize=0):
+ global yaccdebug
+ yaccdebug = debug
+
+ initialize_vars()
+ files = { }
+ error = 0
+
+ # Add starting symbol to signature
+ if start:
+ Signature.update(start)
+
+ # Try to figure out what module we are working with
+ if module:
+ # User supplied a module object.
+ if not isinstance(module, types.ModuleType):
+ raise ValueError,"Expected a module"
+
+ ldict = module.__dict__
+
+ else:
+ # No module given. We might be able to get information from the caller.
+ # Throw an exception and unwind the traceback to get the globals
+
+ try:
+ raise RuntimeError
+ except RuntimeError:
+ e,b,t = sys.exc_info()
+ f = t.tb_frame
+ f = f.f_back # Walk out to our calling function
+ ldict = f.f_globals # Grab its globals dictionary
+
+ # If running in optimized mode. We're going to
+
+ if (optimize and lr_read_tables(tabmodule,1)):
+ # Read parse table
+ del Productions[:]
+ for p in _lr_productions:
+ if not p:
+ Productions.append(None)
+ else:
+ m = MiniProduction()
+ m.name = p[0]
+ m.len = p[1]
+ m.file = p[3]
+ m.line = p[4]
+ if p[2]:
+ m.func = ldict[p[2]]
+ Productions.append(m)
+
+ else:
+ # Get the tokens map
+ tokens = ldict.get("tokens",None)
+
+ if not tokens:
+ raise YaccError,"module does not define a list 'tokens'"
+ if not (isinstance(tokens,types.ListType) or isinstance(tokens,types.TupleType)):
+ raise YaccError,"tokens must be a list or tuple."
+
+ # Check to see if a requires dictionary is defined.
+ requires = ldict.get("require",None)
+ if requires:
+ if not (isinstance(requires,types.DictType)):
+ raise YaccError,"require must be a dictionary."
+
+ for r,v in requires.items():
+ try:
+ if not (isinstance(v,types.ListType)):
+ raise TypeError
+ v1 = [x.split(".") for x in v]
+ Requires[r] = v1
+ except StandardError:
+ print "Invalid specification for rule '%s' in require. Expected a list of strings" % r
+
+
+ # Build the dictionary of terminals. We a record a 0 in the
+ # dictionary to track whether or not a terminal is actually
+ # used in the grammar
+
+ if 'error' in tokens:
+ print "yacc: Illegal token 'error'. Is a reserved word."
+ raise YaccError,"Illegal token name"
+
+ for n in tokens:
+ if Terminals.has_key(n):
+ print "yacc: Warning. Token '%s' multiply defined." % n
+ Terminals[n] = [ ]
+
+ Terminals['error'] = [ ]
+
+ # Get the precedence map (if any)
+ prec = ldict.get("precedence",None)
+ if prec:
+ if not (isinstance(prec,types.ListType) or isinstance(prec,types.TupleType)):
+ raise YaccError,"precedence must be a list or tuple."
+ add_precedence(prec)
+ Signature.update(repr(prec))
+
+ for n in tokens:
+ if not Precedence.has_key(n):
+ Precedence[n] = ('right',0) # Default, right associative, 0 precedence
+
+ # Look for error handler
+ ef = ldict.get('p_error',None)
+ if ef:
+ if not isinstance(ef,types.FunctionType):
+ raise YaccError,"'p_error' defined, but is not a function."
+ eline = ef.func_code.co_firstlineno
+ efile = ef.func_code.co_filename
+ files[efile] = None
+
+ if (ef.func_code.co_argcount != 1):
+ raise YaccError,"%s:%d: p_error() requires 1 argument." % (efile,eline)
+ global Errorfunc
+ Errorfunc = ef
+ else:
+ print "yacc: Warning. no p_error() function is defined."
+
+ # Get the list of built-in functions with p_ prefix
+ symbols = [ldict[f] for f in ldict.keys()
+ if (isinstance(ldict[f],types.FunctionType) and ldict[f].__name__[:2] == 'p_'
+ and ldict[f].__name__ != 'p_error')]
+
+ # Check for non-empty symbols
+ if len(symbols) == 0:
+ raise YaccError,"no rules of the form p_rulename are defined."
+
+ # Sort the symbols by line number
+ symbols.sort(lambda x,y: cmp(x.func_code.co_firstlineno,y.func_code.co_firstlineno))
+
+ # Add all of the symbols to the grammar
+ for f in symbols:
+ if (add_function(f)) < 0:
+ error += 1
+ else:
+ files[f.func_code.co_filename] = None
+
+ # Make a signature of the docstrings
+ for f in symbols:
+ if f.__doc__:
+ Signature.update(f.__doc__)
+
+ lr_init_vars()
+
+ if error:
+ raise YaccError,"Unable to construct parser."
+
+ if not lr_read_tables(tabmodule):
+
+ # Validate files
+ for filename in files.keys():
+ if not validate_file(filename):
+ error = 1
+
+ # Validate dictionary
+ validate_dict(ldict)
+
+ if start and not Prodnames.has_key(start):
+ raise YaccError,"Bad starting symbol '%s'" % start
+
+ augment_grammar(start)
+ error = verify_productions(cycle_check=check_recursion)
+ otherfunc = [ldict[f] for f in ldict.keys()
+ if (isinstance(ldict[f],types.FunctionType) and ldict[f].__name__[:2] != 'p_')]
+
+ if error:
+ raise YaccError,"Unable to construct parser."
+
+ build_lritems()
+ compute_first1()
+ compute_follow(start)
+
+ if method == 'SLR':
+ slr_parse_table()
+ elif method == 'LALR1':
+ lalr_parse_table()
+ return
+ else:
+ raise YaccError, "Unknown parsing method '%s'" % method
+
+ lr_write_tables(tabmodule)
+
+ if yaccdebug:
+ try:
+ f = open(debug_file,"w")
+ f.write(_vfc.getvalue())
+ f.write("\n\n")
+ f.write(_vf.getvalue())
+ f.close()
+ except IOError,e:
+ print "yacc: can't create '%s'" % debug_file,e
+
+ # Made it here. Create a parser object and set up its internal state.
+ # Set global parse() method to bound method of parser object.
+
+ p = Parser("xyzzy")
+ p.productions = Productions
+ p.errorfunc = Errorfunc
+ p.action = _lr_action
+ p.goto = _lr_goto
+ p.method = _lr_method
+ p.require = Requires
+
+ global parse
+ parse = p.parse
+
+ # Clean up all of the globals we created
+ if (not optimize):
+ yacc_cleanup()
+ return p
+
+# yacc_cleanup function. Delete all of the global variables
+# used during table construction
+
+def yacc_cleanup():
+ global _lr_action, _lr_goto, _lr_method, _lr_goto_cache
+ del _lr_action, _lr_goto, _lr_method, _lr_goto_cache
+
+ global Productions, Prodnames, Prodmap, Terminals
+ global Nonterminals, First, Follow, Precedence, LRitems
+ global Errorfunc, Signature, Requires
+
+ del Productions, Prodnames, Prodmap, Terminals
+ del Nonterminals, First, Follow, Precedence, LRitems
+ del Errorfunc, Signature, Requires
+
+ global _vf, _vfc
+ del _vf, _vfc
+
+
+# Stub that raises an error if parsing is attempted without first calling yacc()
+def parse(*args,**kwargs):
+ raise YaccError, "yacc: No parser built with yacc()"
+
diff --git a/kern/linux/events.cc b/kern/linux/events.cc
deleted file mode 100644
index 9f50eef04..000000000
--- a/kern/linux/events.cc
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (c) 2004-2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "arch/arguments.hh"
-#include "base/trace.hh"
-#include "cpu/exec_context.hh"
-#include "kern/linux/events.hh"
-#include "kern/linux/printk.hh"
-#include "kern/system_events.hh"
-#include "sim/system.hh"
-
-
-namespace Linux {
-
-void
-DebugPrintkEvent::process(ExecContext *xc)
-{
- if (DTRACE(DebugPrintf)) {
- if (!raw) {
- StringWrap name(xc->getSystemPtr()->name() + ".dprintk");
- DPRINTFN("");
- }
-
- AlphaArguments args(xc);
- Printk(args);
- SkipFuncEvent::process(xc);
- }
-}
-
-} // namespace linux
diff --git a/kern/linux/linux.hh b/kern/linux/linux.hh
deleted file mode 100644
index 0dbccf546..000000000
--- a/kern/linux/linux.hh
+++ /dev/null
@@ -1,341 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __LINUX_HH__
-#define __LINUX_HH__
-#include "config/full_system.hh"
-
-#if FULL_SYSTEM
-
-class Linux {};
-
-#else //!FULL_SYSTEM
-
-#include <dirent.h>
-#include <errno.h>
-#include <fcntl.h> // for host open() flags
-#include <string.h> // for memset()
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include "sim/syscall_emul.hh"
-
-///
-/// This class encapsulates the types, structures, constants,
-/// functions, and syscall-number mappings specific to the Alpha Linux
-/// syscall interface.
-///
-class Linux {
-
- public:
-
- //@{
- /// Basic Linux types.
- typedef uint64_t size_t;
- typedef uint64_t off_t;
- typedef int64_t time_t;
- typedef uint32_t uid_t;
- typedef uint32_t gid_t;
- //@}
-
-#if BSD_HOST
- typedef struct stat hst_stat;
- typedef struct stat hst_stat64;
-#else
- typedef struct stat hst_stat ;
- typedef struct stat64 hst_stat64;
-#endif
-
-
- //@{
- /// open(2) flag values.
- static const int TGT_O_RDONLY = 00000000; //!< O_RDONLY
- static const int TGT_O_WRONLY = 00000001; //!< O_WRONLY
- static const int TGT_O_RDWR = 00000002; //!< O_RDWR
- static const int TGT_O_NONBLOCK = 00000004; //!< O_NONBLOCK
- static const int TGT_O_APPEND = 00000010; //!< O_APPEND
- static const int TGT_O_CREAT = 00001000; //!< O_CREAT
- static const int TGT_O_TRUNC = 00002000; //!< O_TRUNC
- static const int TGT_O_EXCL = 00004000; //!< O_EXCL
- static const int TGT_O_NOCTTY = 00010000; //!< O_NOCTTY
- static const int TGT_O_SYNC = 00040000; //!< O_SYNC
- static const int TGT_O_DRD = 00100000; //!< O_DRD
- static const int TGT_O_DIRECTIO = 00200000; //!< O_DIRECTIO
- static const int TGT_O_CACHE = 00400000; //!< O_CACHE
- static const int TGT_O_DSYNC = 02000000; //!< O_DSYNC
- static const int TGT_O_RSYNC = 04000000; //!< O_RSYNC
- //@}
-
- /// This table maps the target open() flags to the corresponding
- /// host open() flags.
- static OpenFlagTransTable openFlagTable[];
-
- /// Number of entries in openFlagTable[].
- static const int NUM_OPEN_FLAGS;
-
- /// Stat buffer. Note that we can't call it 'stat' since that
- /// gets #defined to something else on some systems.
- struct tgt_stat {
- uint32_t st_dev; //!< device
- uint32_t st_ino; //!< inode
- uint32_t st_mode; //!< mode
- uint32_t st_nlink; //!< link count
- uint32_t st_uid; //!< owner's user ID
- uint32_t st_gid; //!< owner's group ID
- uint32_t st_rdev; //!< device number
- int32_t _pad1; //!< for alignment
- int64_t st_size; //!< file size in bytes
- uint64_t st_atimeX; //!< time of last access
- uint64_t st_mtimeX; //!< time of last modification
- uint64_t st_ctimeX; //!< time of last status change
- uint32_t st_blksize; //!< optimal I/O block size
- int32_t st_blocks; //!< number of blocks allocated
- uint32_t st_flags; //!< flags
- uint32_t st_gen; //!< unknown
- };
-
- // same for stat64
- struct tgt_stat64 {
- uint64_t st_dev;
- uint64_t st_ino;
- uint64_t st_rdev;
- int64_t st_size;
- uint64_t st_blocks;
-
- uint32_t st_mode;
- uint32_t st_uid;
- uint32_t st_gid;
- uint32_t st_blksize;
- uint32_t st_nlink;
- uint32_t __pad0;
-
- uint64_t tgt_st_atime;
- uint64_t st_atime_nsec;
- uint64_t tgt_st_mtime;
- uint64_t st_mtime_nsec;
- uint64_t tgt_st_ctime;
- uint64_t st_ctime_nsec;
- int64_t ___unused[3];
- };
-
- /// Length of strings in struct utsname (plus 1 for null char).
- static const int _SYS_NMLN = 65;
-
- /// Interface struct for uname().
- struct utsname {
- char sysname[_SYS_NMLN]; //!< System name.
- char nodename[_SYS_NMLN]; //!< Node name.
- char release[_SYS_NMLN]; //!< OS release.
- char version[_SYS_NMLN]; //!< OS version.
- char machine[_SYS_NMLN]; //!< Machine type.
- };
-
-
- //@{
- /// ioctl() command codes.
- static const unsigned TIOCGETP = 0x40067408;
- static const unsigned TIOCSETP = 0x80067409;
- static const unsigned TIOCSETN = 0x8006740a;
- static const unsigned TIOCSETC = 0x80067411;
- static const unsigned TIOCGETC = 0x40067412;
- static const unsigned FIONREAD = 0x4004667f;
- static const unsigned TIOCISATTY = 0x2000745e;
- static const unsigned TIOCGETS = 0x402c7413;
- static const unsigned TIOCGETA = 0x40127417;
- //@}
-
- /// Resource enumeration for getrlimit().
- enum rlimit_resources {
- TGT_RLIMIT_CPU = 0,
- TGT_RLIMIT_FSIZE = 1,
- TGT_RLIMIT_DATA = 2,
- TGT_RLIMIT_STACK = 3,
- TGT_RLIMIT_CORE = 4,
- TGT_RLIMIT_RSS = 5,
- TGT_RLIMIT_NOFILE = 6,
- TGT_RLIMIT_AS = 7,
- TGT_RLIMIT_VMEM = 7,
- TGT_RLIMIT_NPROC = 8,
- TGT_RLIMIT_MEMLOCK = 9,
- TGT_RLIMIT_LOCKS = 10
- };
-
- /// Limit struct for getrlimit/setrlimit.
- struct rlimit {
- uint64_t rlim_cur; //!< soft limit
- uint64_t rlim_max; //!< hard limit
- };
-
-
- /// For mmap().
- static const unsigned TGT_MAP_ANONYMOUS = 0x10;
-
- /// For gettimeofday().
- struct timeval {
- int64_t tv_sec; //!< seconds
- int64_t tv_usec; //!< microseconds
- };
-
- // For writev/readv
- struct tgt_iovec {
- uint64_t iov_base; // void *
- uint64_t iov_len;
- };
-
- //@{
- /// For getrusage().
- static const int TGT_RUSAGE_SELF = 0;
- static const int TGT_RUSAGE_CHILDREN = -1;
- static const int TGT_RUSAGE_BOTH = -2;
- //@}
-
- /// For getrusage().
- struct rusage {
- struct timeval ru_utime; //!< user time used
- struct timeval ru_stime; //!< system time used
- int64_t ru_maxrss; //!< max rss
- int64_t ru_ixrss; //!< integral shared memory size
- int64_t ru_idrss; //!< integral unshared data "
- int64_t ru_isrss; //!< integral unshared stack "
- int64_t ru_minflt; //!< page reclaims - total vmfaults
- int64_t ru_majflt; //!< page faults
- int64_t ru_nswap; //!< swaps
- int64_t ru_inblock; //!< block input operations
- int64_t ru_oublock; //!< block output operations
- int64_t ru_msgsnd; //!< messages sent
- int64_t ru_msgrcv; //!< messages received
- int64_t ru_nsignals; //!< signals received
- int64_t ru_nvcsw; //!< voluntary context switches
- int64_t ru_nivcsw; //!< involuntary "
- };
-
- /// Helper function to convert a host stat buffer to a target stat
- /// buffer. Also copies the target buffer out to the simulated
- /// memory space. Used by stat(), fstat(), and lstat().
-#if !BSD_HOST
- static void
- copyOutStatBuf(FunctionalMemory *mem, Addr addr, hst_stat *host)
- {
- TypedBufferArg<Linux::tgt_stat> tgt(addr);
-
- tgt->st_dev = htog(host->st_dev);
- tgt->st_ino = htog(host->st_ino);
- tgt->st_mode = htog(host->st_mode);
- tgt->st_nlink = htog(host->st_nlink);
- tgt->st_uid = htog(host->st_uid);
- tgt->st_gid = htog(host->st_gid);
- tgt->st_rdev = htog(host->st_rdev);
- tgt->st_size = htog(host->st_size);
- tgt->st_atimeX = htog(host->st_atime);
- tgt->st_mtimeX = htog(host->st_mtime);
- tgt->st_ctimeX = htog(host->st_ctime);
- tgt->st_blksize = htog(host->st_blksize);
- tgt->st_blocks = htog(host->st_blocks);
-
- tgt.copyOut(mem);
- }
-#else
- // Third version for bsd systems which no longer have any support for
- // the old stat() call and stat() is actually a stat64()
- static void
- copyOutStatBuf(FunctionalMemory *mem, Addr addr, hst_stat64 *host)
- {
- TypedBufferArg<Linux::tgt_stat> tgt(addr);
-
- tgt->st_dev = htog(host->st_dev);
- tgt->st_ino = htog(host->st_ino);
- tgt->st_mode = htog(host->st_mode);
- tgt->st_nlink = htog(host->st_nlink);
- tgt->st_uid = htog(host->st_uid);
- tgt->st_gid = htog(host->st_gid);
- tgt->st_rdev = htog(host->st_rdev);
- tgt->st_size = htog(host->st_size);
- tgt->st_atimeX = htog(host->st_atime);
- tgt->st_mtimeX = htog(host->st_mtime);
- tgt->st_ctimeX = htog(host->st_ctime);
- tgt->st_blksize = htog(host->st_blksize);
- tgt->st_blocks = htog(host->st_blocks);
-
- tgt.copyOut(mem);
- }
-#endif
-
-
- // Same for stat64
- static void
- copyOutStat64Buf(FunctionalMemory *mem, int fd, Addr addr, hst_stat64 *host)
- {
- TypedBufferArg<Linux::tgt_stat64> tgt(addr);
-
- // fd == 1 checks are because libc does some checks
- // that the stdout is interactive vs. a file
- // this makes it work on non-linux systems
- if (fd == 1)
- tgt->st_dev = htog((uint64_t)0xA);
- else
- tgt->st_dev = htog((uint64_t)host->st_dev);
- // XXX What about STAT64_HAS_BROKEN_ST_INO ???
- tgt->st_ino = htog((uint64_t)host->st_ino);
- if (fd == 1)
- tgt->st_rdev = htog((uint64_t)0x880d);
- else
- tgt->st_rdev = htog((uint64_t)host->st_rdev);
- tgt->st_size = htog((int64_t)host->st_size);
- tgt->st_blocks = htog((uint64_t)host->st_blocks);
-
- if (fd == 1)
- tgt->st_mode = htog((uint32_t)0x2190);
- else
- tgt->st_mode = htog((uint32_t)host->st_mode);
- tgt->st_uid = htog((uint32_t)host->st_uid);
- tgt->st_gid = htog((uint32_t)host->st_gid);
- tgt->st_blksize = htog((uint32_t)host->st_blksize);
- tgt->st_nlink = htog((uint32_t)host->st_nlink);
- tgt->tgt_st_atime = htog((uint64_t)host->st_atime);
- tgt->tgt_st_mtime = htog((uint64_t)host->st_mtime);
- tgt->tgt_st_ctime = htog((uint64_t)host->st_ctime);
-#if defined(STAT_HAVE_NSEC)
- tgt->st_atime_nsec = htog(host->st_atime_nsec);
- tgt->st_mtime_nsec = htog(host->st_mtime_nsec);
- tgt->st_ctime_nsec = htog(host->st_ctime_nsec);
-#else
- tgt->st_atime_nsec = 0;
- tgt->st_mtime_nsec = 0;
- tgt->st_ctime_nsec = 0;
-#endif
-
- tgt.copyOut(mem);
- }
-
-}; // class Linux
-
-
-#endif // FULL_SYSTEM
-
-#endif // __LINUX_HH__
diff --git a/kern/linux/printk.cc b/kern/linux/printk.cc
deleted file mode 100644
index f5313759b..000000000
--- a/kern/linux/printk.cc
+++ /dev/null
@@ -1,261 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <sys/types.h>
-#include <algorithm>
-
-#include "base/trace.hh"
-#include "arch/arguments.hh"
-
-using namespace std;
-
-
-void
-Printk(AlphaArguments args)
-{
- char *p = (char *)args++;
-
- ios::fmtflags saved_flags = DebugOut().flags();
- char old_fill = DebugOut().fill();
- int old_precision = DebugOut().precision();
-
- while (*p) {
- switch (*p) {
- case '%': {
- bool more = true;
- bool islong = false;
- bool leftjustify = false;
- bool format = false;
- bool zero = false;
- int width = 0;
- while (more && *++p) {
- switch (*p) {
- case 'l':
- case 'L':
- islong = true;
- break;
- case '-':
- leftjustify = true;
- break;
- case '#':
- format = true;
- break;
- case '0':
- if (width)
- width *= 10;
- else
- zero = true;
- break;
- default:
- if (*p >= '1' && *p <= '9')
- width = 10 * width + *p - '0';
- else
- more = false;
- break;
- }
- }
-
- bool hexnum = false;
- bool octal = false;
- bool sign = false;
- switch (*p) {
- case 'X':
- case 'x':
- hexnum = true;
- break;
- case 'O':
- case 'o':
- octal = true;
- break;
- case 'D':
- case 'd':
- sign = true;
- break;
- case 'P':
- format = true;
- case 'p':
- hexnum = true;
- break;
- }
-
- switch (*p) {
- case 'D':
- case 'd':
- case 'U':
- case 'u':
- case 'X':
- case 'x':
- case 'O':
- case 'o':
- case 'P':
- case 'p': {
- if (hexnum)
- DebugOut() << hex;
-
- if (octal)
- DebugOut() << oct;
-
- if (format) {
- if (!zero)
- DebugOut().setf(ios::showbase);
- else {
- if (hexnum) {
- DebugOut() << "0x";
- width -= 2;
- } else if (octal) {
- DebugOut() << "0";
- width -= 1;
- }
- }
- }
-
- if (zero)
- DebugOut().fill('0');
-
- if (width > 0)
- DebugOut().width(width);
-
- if (leftjustify && !zero)
- DebugOut().setf(ios::left);
-
- if (sign) {
- if (islong)
- DebugOut() << (int64_t)args;
- else
- DebugOut() << (int32_t)args;
- } else {
- if (islong)
- DebugOut() << (uint64_t)args;
- else
- DebugOut() << (uint32_t)args;
- }
-
- if (zero)
- DebugOut().fill(' ');
-
- if (width > 0)
- DebugOut().width(0);
-
- DebugOut() << dec;
-
- ++args;
- }
- break;
-
- case 's': {
- char *s = (char *)args;
- if (!s)
- s = "<NULL>";
-
- if (width > 0)
- DebugOut().width(width);
- if (leftjustify)
- DebugOut().setf(ios::left);
-
- DebugOut() << s;
- ++args;
- }
- break;
- case 'C':
- case 'c': {
- uint64_t mask = (*p == 'C') ? 0xffL : 0x7fL;
- uint64_t num;
- int width;
-
- if (islong) {
- num = (uint64_t)args;
- width = sizeof(uint64_t);
- } else {
- num = (uint32_t)args;
- width = sizeof(uint32_t);
- }
-
- while (width-- > 0) {
- char c = (char)(num & mask);
- if (c)
- DebugOut() << c;
- num >>= 8;
- }
-
- ++args;
- }
- break;
- case 'b': {
- uint64_t n = (uint64_t)args++;
- char *s = (char *)args++;
- DebugOut() << s << ": " << n;
- }
- break;
- case 'n':
- case 'N': {
- args += 2;
-#if 0
- uint64_t n = (uint64_t)args++;
- struct reg_values *rv = (struct reg_values *)args++;
-#endif
- }
- break;
- case 'r':
- case 'R': {
- args += 2;
-#if 0
- uint64_t n = (uint64_t)args++;
- struct reg_desc *rd = (struct reg_desc *)args++;
-#endif
- }
- break;
- case '%':
- DebugOut() << '%';
- break;
- }
- ++p;
- }
- break;
- case '\n':
- DebugOut() << endl;
- ++p;
- break;
- case '\r':
- ++p;
- if (*p != '\n')
- DebugOut() << endl;
- break;
-
- default: {
- size_t len = strcspn(p, "%\n\r\0");
- DebugOut().write(p, len);
- p += len;
- }
- }
- }
-
- DebugOut().flags(saved_flags);
- DebugOut().fill(old_fill);
- DebugOut().precision(old_precision);
-}
-
diff --git a/kern/linux/printk.hh b/kern/linux/printk.hh
deleted file mode 100644
index 45eab6b88..000000000
--- a/kern/linux/printk.hh
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __PRINTK_HH__
-#define __PRINTK_HH__
-
-class AlphaArguments;
-
-void Printk(AlphaArguments args);
-
-#endif // __PRINTK_HH__
diff --git a/kern/system_events.cc b/kern/system_events.cc
deleted file mode 100644
index 221eb228d..000000000
--- a/kern/system_events.cc
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "encumbered/cpu/full/cpu.hh"
-#include "kern/kernel_stats.hh"
-
-using namespace TheISA;
-
-void
-SkipFuncEvent::process(ExecContext *xc)
-{
- Addr newpc = xc->readIntReg(ReturnAddressReg);
-
- DPRINTF(PCEvent, "skipping %s: pc=%x, newpc=%x\n", description,
- xc->readPC(), newpc);
-
- xc->setPC(newpc);
- xc->setNextPC(xc->readPC() + sizeof(TheISA::MachInst));
-
- BranchPred *bp = xc->getCpuPtr()->getBranchPred();
- if (bp != NULL) {
- bp->popRAS(xc->getThreadNum());
- }
-}
-
-
-FnEvent::FnEvent(PCEventQueue *q, const std::string &desc, Addr addr,
- Stats::MainBin *bin)
- : PCEvent(q, desc, addr), _name(desc), mybin(bin)
-{
-}
-
-void
-FnEvent::process(ExecContext *xc)
-{
- if (xc->misspeculating())
- return;
-
- xc->getSystemPtr()->kernelBinning->call(xc, mybin);
-}
-
-void
-IdleStartEvent::process(ExecContext *xc)
-{
- if (xc->getKernelStats())
- xc->getKernelStats()->setIdleProcess(
- xc->readMiscReg(AlphaISA::IPR_PALtemp23), xc);
- remove();
-}
-
-void
-InterruptStartEvent::process(ExecContext *xc)
-{
- if (xc->getKernelStats())
- xc->getKernelStats()->mode(Kernel::interrupt, xc);
-}
-
-void
-InterruptEndEvent::process(ExecContext *xc)
-{
- // We go back to kernel, if we are user, inside the rti
- // pal code we will get switched to user because of the ICM write
- if (xc->getKernelStats())
- xc->getKernelStats()->mode(Kernel::kernel, xc);
-}
diff --git a/kern/tru64/dump_mbuf.hh b/kern/tru64/dump_mbuf.hh
deleted file mode 100644
index 0ff5da3d7..000000000
--- a/kern/tru64/dump_mbuf.hh
+++ /dev/null
@@ -1,38 +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.
- */
-
-#ifndef __DUMP_MBUF_HH__
-#define __DUMP_MBUF_HH__
-
-class AlphaArguments;
-
-namespace tru64 {
- void DumpMbuf(AlphaArguments args);
-}
-
-#endif // __DUMP_MBUF_HH__
diff --git a/kern/tru64/printf.cc b/kern/tru64/printf.cc
deleted file mode 100644
index 77ac17c3a..000000000
--- a/kern/tru64/printf.cc
+++ /dev/null
@@ -1,266 +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 <sys/types.h>
-#include <algorithm>
-
-#include "base/cprintf.hh"
-#include "base/trace.hh"
-#include "sim/host.hh"
-#include "arch/arguments.hh"
-#include "arch/vtophys.hh"
-
-using namespace std;
-
-namespace tru64 {
-
-void
-Printf(AlphaArguments args)
-{
- char *p = (char *)args++;
-
- ios::fmtflags saved_flags = DebugOut().flags();
- char old_fill = DebugOut().fill();
- int old_precision = DebugOut().precision();
-
- while (*p) {
- switch (*p) {
- case '%': {
- bool more = true;
- bool islong = false;
- bool leftjustify = false;
- bool format = false;
- bool zero = false;
- int width = 0;
- while (more && *++p) {
- switch (*p) {
- case 'l':
- case 'L':
- islong = true;
- break;
- case '-':
- leftjustify = true;
- break;
- case '#':
- format = true;
- break;
- case '0':
- if (width)
- width *= 10;
- else
- zero = true;
- break;
- default:
- if (*p >= '1' && *p <= '9')
- width = 10 * width + *p - '0';
- else
- more = false;
- break;
- }
- }
-
- bool hexnum = false;
- bool octal = false;
- bool sign = false;
- switch (*p) {
- case 'X':
- case 'x':
- hexnum = true;
- break;
- case 'O':
- case 'o':
- octal = true;
- break;
- case 'D':
- case 'd':
- sign = true;
- break;
- case 'P':
- format = true;
- case 'p':
- hexnum = true;
- break;
- }
-
- switch (*p) {
- case 'D':
- case 'd':
- case 'U':
- case 'u':
- case 'X':
- case 'x':
- case 'O':
- case 'o':
- case 'P':
- case 'p': {
- if (hexnum)
- DebugOut() << hex;
-
- if (octal)
- DebugOut() << oct;
-
- if (format) {
- if (!zero)
- DebugOut().setf(ios::showbase);
- else {
- if (hexnum) {
- DebugOut() << "0x";
- width -= 2;
- } else if (octal) {
- DebugOut() << "0";
- width -= 1;
- }
- }
- }
-
- if (zero)
- DebugOut().fill('0');
-
- if (width > 0)
- DebugOut().width(width);
-
- if (leftjustify && !zero)
- DebugOut().setf(ios::left);
-
- if (sign) {
- if (islong)
- DebugOut() << (int64_t)args;
- else
- DebugOut() << (int32_t)args;
- } else {
- if (islong)
- DebugOut() << (uint64_t)args;
- else
- DebugOut() << (uint32_t)args;
- }
-
- if (zero)
- DebugOut().fill(' ');
-
- if (width > 0)
- DebugOut().width(0);
-
- DebugOut() << dec;
-
- ++args;
- }
- break;
-
- case 's': {
- char *s = (char *)args;
- if (!s)
- s = "<NULL>";
-
- if (width > 0)
- DebugOut().width(width);
- if (leftjustify)
- DebugOut().setf(ios::left);
-
- DebugOut() << s;
- ++args;
- }
- break;
- case 'C':
- case 'c': {
- uint64_t mask = (*p == 'C') ? 0xffL : 0x7fL;
- uint64_t num;
- int width;
-
- if (islong) {
- num = (uint64_t)args;
- width = sizeof(uint64_t);
- } else {
- num = (uint32_t)args;
- width = sizeof(uint32_t);
- }
-
- while (width-- > 0) {
- char c = (char)(num & mask);
- if (c)
- DebugOut() << c;
- num >>= 8;
- }
-
- ++args;
- }
- break;
- case 'b': {
- uint64_t n = (uint64_t)args++;
- char *s = (char *)args++;
- DebugOut() << s << ": " << n;
- }
- break;
- case 'n':
- case 'N': {
- args += 2;
-#if 0
- uint64_t n = (uint64_t)args++;
- struct reg_values *rv = (struct reg_values *)args++;
-#endif
- }
- break;
- case 'r':
- case 'R': {
- args += 2;
-#if 0
- uint64_t n = (uint64_t)args++;
- struct reg_desc *rd = (struct reg_desc *)args++;
-#endif
- }
- break;
- case '%':
- DebugOut() << '%';
- break;
- }
- ++p;
- }
- break;
- case '\n':
- DebugOut() << endl;
- ++p;
- break;
- case '\r':
- ++p;
- if (*p != '\n')
- DebugOut() << endl;
- break;
-
- default: {
- size_t len = strcspn(p, "%\n\r\0");
- DebugOut().write(p, len);
- p += len;
- }
- }
- }
-
- DebugOut().flags(saved_flags);
- DebugOut().fill(old_fill);
- DebugOut().precision(old_precision);
-}
-
-} // namespace Tru64
diff --git a/kern/tru64/printf.hh b/kern/tru64/printf.hh
deleted file mode 100644
index a48b4482c..000000000
--- a/kern/tru64/printf.hh
+++ /dev/null
@@ -1,38 +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.
- */
-
-#ifndef __PRINTF_HH__
-#define __PRINTF_HH__
-
-class AlphaArguments;
-
-namespace tru64 {
- void Printf(AlphaArguments args);
-}
-
-#endif // __PRINTF_HH__
diff --git a/kern/tru64/tru64.hh b/kern/tru64/tru64.hh
deleted file mode 100644
index b8adab8a8..000000000
--- a/kern/tru64/tru64.hh
+++ /dev/null
@@ -1,1324 +0,0 @@
-/*
- * Copyright (c) 2001-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __TRU64_HH__
-#define __TRU64_HH__
-#include "config/full_system.hh"
-
-#if FULL_SYSTEM
-
-class Tru64 {};
-
-#else //!FULL_SYSTEM
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#if defined(__OpenBSD__) || defined(__APPLE__) || defined(__FreeBSD__)
-#include <sys/param.h>
-#include <sys/mount.h>
-#else
-#include <sys/statfs.h>
-#endif
-
-#include <dirent.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <string.h> // for memset()
-#include <unistd.h>
-
-#include "cpu/base.hh"
-#include "sim/root.hh"
-#include "sim/syscall_emul.hh"
-
-using namespace std;
-
-typedef struct stat global_stat;
-typedef struct statfs global_statfs;
-typedef struct dirent global_dirent;
-
-///
-/// This class encapsulates the types, structures, constants,
-/// functions, and syscall-number mappings specific to the Alpha Tru64
-/// syscall interface.
-///
-class Tru64 {
-
- public:
-
- //@{
- /// Basic Tru64 types.
- typedef uint64_t size_t;
- typedef uint64_t off_t;
- typedef uint16_t nlink_t;
- typedef int32_t dev_t;
- typedef uint32_t uid_t;
- typedef uint32_t gid_t;
- typedef uint32_t time_t;
- typedef uint32_t mode_t;
- typedef uint32_t ino_t;
- typedef struct { int val[2]; } quad;
- typedef quad fsid_t;
- //@}
-
- //@{
- /// open(2) flag values.
- static const int TGT_O_RDONLY = 00000000;
- static const int TGT_O_WRONLY = 00000001;
- static const int TGT_O_RDWR = 00000002;
- static const int TGT_O_NONBLOCK = 00000004;
- static const int TGT_O_APPEND = 00000010;
- static const int TGT_O_CREAT = 00001000;
- static const int TGT_O_TRUNC = 00002000;
- static const int TGT_O_EXCL = 00004000;
- static const int TGT_O_NOCTTY = 00010000;
- static const int TGT_O_SYNC = 00040000;
- static const int TGT_O_DRD = 00100000;
- static const int TGT_O_DIRECTIO = 00200000;
- static const int TGT_O_CACHE = 00400000;
- static const int TGT_O_DSYNC = 02000000;
- static const int TGT_O_RSYNC = 04000000;
- //@}
-
- /// This table maps the target open() flags to the corresponding
- /// host open() flags.
- static OpenFlagTransTable openFlagTable[];
-
- /// Number of entries in openFlagTable[].
- static const int NUM_OPEN_FLAGS;
-
- /// Stat buffer. Note that Tru64 v5.0+ use a new "F64" stat
- /// structure, and a new set of syscall numbers for stat calls.
- /// On some hosts (notably Linux) define st_atime, st_mtime, and
- /// st_ctime as macros, so we append an X to get around this.
- struct F64_stat {
- dev_t st_dev; //!< st_dev
- int32_t st_retired1; //!< st_retired1
- mode_t st_mode; //!< st_mode
- nlink_t st_nlink; //!< st_nlink
- uint16_t st_nlink_reserved; //!< st_nlink_reserved
- uid_t st_uid; //!< st_uid
- gid_t st_gid; //!< st_gid
- dev_t st_rdev; //!< st_rdev
- dev_t st_ldev; //!< st_ldev
- off_t st_size; //!< st_size
- time_t st_retired2; //!< st_retired2
- int32_t st_uatime; //!< st_uatime
- time_t st_retired3; //!< st_retired3
- int32_t st_umtime; //!< st_umtime
- time_t st_retired4; //!< st_retired4
- int32_t st_uctime; //!< st_uctime
- int32_t st_retired5; //!< st_retired5
- int32_t st_retired6; //!< st_retired6
- uint32_t st_flags; //!< st_flags
- uint32_t st_gen; //!< st_gen
- uint64_t st_spare[4]; //!< st_spare[4]
- ino_t st_ino; //!< st_ino
- int32_t st_ino_reserved; //!< st_ino_reserved
- time_t st_atimeX; //!< st_atime
- int32_t st_atime_reserved; //!< st_atime_reserved
- time_t st_mtimeX; //!< st_mtime
- int32_t st_mtime_reserved; //!< st_mtime_reserved
- time_t st_ctimeX; //!< st_ctime
- int32_t st_ctime_reserved; //!< st_ctime_reserved
- uint64_t st_blksize; //!< st_blksize
- uint64_t st_blocks; //!< st_blocks
- };
-
-
- /// Old Tru64 v4.x stat struct.
- /// Tru64 maintains backwards compatibility with v4.x by
- /// implementing another set of stat functions using the old
- /// structure definition and binding them to the old syscall
- /// numbers.
-
- struct pre_F64_stat {
- dev_t st_dev;
- ino_t st_ino;
- mode_t st_mode;
- nlink_t st_nlink;
- uid_t st_uid __attribute__ ((aligned(sizeof(uid_t))));
- gid_t st_gid;
- dev_t st_rdev;
- off_t st_size __attribute__ ((aligned(sizeof(off_t))));
- time_t st_atimeX;
- int32_t st_uatime;
- time_t st_mtimeX;
- int32_t st_umtime;
- time_t st_ctimeX;
- int32_t st_uctime;
- uint32_t st_blksize;
- int32_t st_blocks;
- uint32_t st_flags;
- uint32_t st_gen;
- };
-
- /// For statfs().
- struct F64_statfs {
- int16_t f_type;
- int16_t f_flags;
- int32_t f_retired1;
- int32_t f_retired2;
- int32_t f_retired3;
- int32_t f_retired4;
- int32_t f_retired5;
- int32_t f_retired6;
- int32_t f_retired7;
- fsid_t f_fsid;
- int32_t f_spare[9];
- char f_retired8[90];
- char f_retired9[90];
- uint64_t dummy[10]; // was union mount_info mount_info;
- uint64_t f_flags2;
- int64_t f_spare2[14];
- int64_t f_fsize;
- int64_t f_bsize;
- int64_t f_blocks;
- int64_t f_bfree;
- int64_t f_bavail;
- int64_t f_files;
- int64_t f_ffree;
- char f_mntonname[1024];
- char f_mntfromname[1024];
- };
-
- /// For old Tru64 v4.x statfs()
- struct pre_F64_statfs {
- int16_t f_type;
- int16_t f_flags;
- int32_t f_fsize;
- int32_t f_bsize;
- int32_t f_blocks;
- int32_t f_bfree;
- int32_t f_bavail;
- int32_t f_files;
- int32_t f_ffree;
- fsid_t f_fsid;
- int32_t f_spare[9];
- char f_mntonname[90];
- char f_mntfromname[90];
- uint64_t dummy[10]; // was union mount_info mount_info;
- };
-
- /// For getdirentries().
- struct dirent
- {
- ino_t d_ino; //!< file number of entry
- uint16_t d_reclen; //!< length of this record
- uint16_t d_namlen; //!< length of string in d_name
- char d_name[256]; //!< dummy name length
- };
-
-
- /// Length of strings in struct utsname (plus 1 for null char).
- static const int _SYS_NMLN = 32;
-
- /// Interface struct for uname().
- struct utsname {
- char sysname[_SYS_NMLN]; //!< System name.
- char nodename[_SYS_NMLN]; //!< Node name.
- char release[_SYS_NMLN]; //!< OS release.
- char version[_SYS_NMLN]; //!< OS version.
- char machine[_SYS_NMLN]; //!< Machine type.
- };
-
- //@{
- /// ioctl() command codes.
- static const unsigned TIOCGETP = 0x40067408;
- static const unsigned TIOCSETP = 0x80067409;
- static const unsigned TIOCSETN = 0x8006740a;
- static const unsigned TIOCSETC = 0x80067411;
- static const unsigned TIOCGETC = 0x40067412;
- static const unsigned FIONREAD = 0x4004667f;
- static const unsigned TIOCISATTY = 0x2000745e;
- // TIOCGETS not defined in tru64, so I made up a number
- static const unsigned TIOCGETS = 0x40000000;
- static const unsigned TIOCGETA = 0x402c7413;
- //@}
-
- /// Resource enumeration for getrlimit().
- enum rlimit_resources {
- TGT_RLIMIT_CPU = 0,
- TGT_RLIMIT_FSIZE = 1,
- TGT_RLIMIT_DATA = 2,
- TGT_RLIMIT_STACK = 3,
- TGT_RLIMIT_CORE = 4,
- TGT_RLIMIT_RSS = 5,
- TGT_RLIMIT_NOFILE = 6,
- TGT_RLIMIT_AS = 7,
- TGT_RLIMIT_VMEM = 7
- };
-
- /// Limit struct for getrlimit/setrlimit.
- struct rlimit {
- uint64_t rlim_cur; //!< soft limit
- uint64_t rlim_max; //!< hard limit
- };
-
-
- /// For mmap().
- static const unsigned TGT_MAP_ANONYMOUS = 0x10;
-
-
- //@{
- /// For getsysinfo().
- static const unsigned GSI_PLATFORM_NAME = 103; //!< platform name as string
- static const unsigned GSI_CPU_INFO = 59; //!< CPU information
- static const unsigned GSI_PROC_TYPE = 60; //!< get proc_type
- static const unsigned GSI_MAX_CPU = 30; //!< max # cpu's on this machine
- static const unsigned GSI_CPUS_IN_BOX = 55; //!< number of CPUs in system
- static const unsigned GSI_PHYSMEM = 19; //!< Physical memory in KB
- static const unsigned GSI_CLK_TCK = 42; //!< clock freq in Hz
- //@}
-
- /// For getsysinfo() GSI_CPU_INFO option.
- struct cpu_info {
- uint32_t current_cpu; //!< current_cpu
- uint32_t cpus_in_box; //!< cpus_in_box
- uint32_t cpu_type; //!< cpu_type
- uint32_t ncpus; //!< ncpus
- uint64_t cpus_present; //!< cpus_present
- uint64_t cpus_running; //!< cpus_running
- uint64_t cpu_binding; //!< cpu_binding
- uint64_t cpu_ex_binding; //!< cpu_ex_binding
- uint32_t mhz; //!< mhz
- uint32_t unused[3]; //!< future expansion
- };
-
- //@{
- /// For setsysinfo().
- static const unsigned SSI_IEEE_FP_CONTROL = 14; //!< ieee_set_fp_control()
- //@}
-
- /// For gettimeofday.
- struct timeval {
- uint32_t tv_sec; //!< seconds
- uint32_t tv_usec; //!< microseconds
- };
-
- //@{
- /// For getrusage().
- static const int TGT_RUSAGE_THREAD = 1;
- static const int TGT_RUSAGE_SELF = 0;
- static const int TGT_RUSAGE_CHILDREN = -1;
- //@}
-
- /// For getrusage().
- struct rusage {
- struct timeval ru_utime; //!< user time used
- struct timeval ru_stime; //!< system time used
- uint64_t ru_maxrss; //!< ru_maxrss
- uint64_t ru_ixrss; //!< integral shared memory size
- uint64_t ru_idrss; //!< integral unshared data "
- uint64_t ru_isrss; //!< integral unshared stack "
- uint64_t ru_minflt; //!< page reclaims - total vmfaults
- uint64_t ru_majflt; //!< page faults
- uint64_t ru_nswap; //!< swaps
- uint64_t ru_inblock; //!< block input operations
- uint64_t ru_oublock; //!< block output operations
- uint64_t ru_msgsnd; //!< messages sent
- uint64_t ru_msgrcv; //!< messages received
- uint64_t ru_nsignals; //!< signals received
- uint64_t ru_nvcsw; //!< voluntary context switches
- uint64_t ru_nivcsw; //!< involuntary "
- };
-
- /// For sigreturn().
- struct sigcontext {
- int64_t sc_onstack; //!< sigstack state to restore
- int64_t sc_mask; //!< signal mask to restore
- int64_t sc_pc; //!< pc at time of signal
- int64_t sc_ps; //!< psl to retore
- int64_t sc_regs[32]; //!< processor regs 0 to 31
- int64_t sc_ownedfp; //!< fp has been used
- int64_t sc_fpregs[32]; //!< fp regs 0 to 31
- uint64_t sc_fpcr; //!< floating point control reg
- uint64_t sc_fp_control; //!< software fpcr
- int64_t sc_reserved1; //!< reserved for kernel
- uint32_t sc_kreserved1; //!< reserved for kernel
- uint32_t sc_kreserved2; //!< reserved for kernel
- size_t sc_ssize; //!< stack size
- caddr_t sc_sbase; //!< stack start
- uint64_t sc_traparg_a0; //!< a0 argument to trap on exc
- uint64_t sc_traparg_a1; //!< a1 argument to trap on exc
- uint64_t sc_traparg_a2; //!< a2 argument to trap on exc
- uint64_t sc_fp_trap_pc; //!< imprecise pc
- uint64_t sc_fp_trigger_sum; //!< Exception summary at trigg
- uint64_t sc_fp_trigger_inst; //!< Instruction at trigger pc
- };
-
-
- /// For table().
- static const int TBL_SYSINFO = 12;
-
- /// For table().
- struct tbl_sysinfo {
- uint64_t si_user; //!< User time
- uint64_t si_nice; //!< Nice time
- uint64_t si_sys; //!< System time
- uint64_t si_idle; //!< Idle time
- uint64_t si_hz; //!< hz
- uint64_t si_phz; //!< phz
- uint64_t si_boottime; //!< Boot time in seconds
- uint64_t wait; //!< Wait time
- uint32_t si_max_procs; //!< rpb->rpb_numprocs
- uint32_t pad; //!< padding
- };
-
-
- /// For stack_create.
- struct vm_stack {
- // was void *
- Addr address; //!< address hint
- size_t rsize; //!< red zone size
- size_t ysize; //!< yellow zone size
- size_t gsize; //!< green zone size
- size_t swap; //!< amount of swap to reserve
- size_t incr; //!< growth increment
- uint64_t align; //!< address alignment
- uint64_t flags; //!< MAP_FIXED etc.
- // was struct memalloc_attr *
- Addr attr; //!< allocation policy
- uint64_t reserved; //!< reserved
- };
-
- /// Return values for nxm calls.
- enum {
- KERN_NOT_RECEIVER = 7,
- KERN_NOT_IN_SET = 12
- };
-
- /// For nxm_task_init.
- static const int NXM_TASK_INIT_VP = 2; //!< initial thread is VP
-
- /// Task attribute structure.
- struct nxm_task_attr {
- int64_t nxm_callback; //!< nxm_callback
- unsigned int nxm_version; //!< nxm_version
- unsigned short nxm_uniq_offset; //!< nxm_uniq_offset
- unsigned short flags; //!< flags
- int nxm_quantum; //!< nxm_quantum
- int pad1; //!< pad1
- int64_t pad2; //!< pad2
- };
-
- /// Signal set.
- typedef uint64_t sigset_t;
-
- /// Thread state shared between user & kernel.
- struct ushared_state {
- sigset_t sigmask; //!< thread signal mask
- sigset_t sig; //!< thread pending mask
- // struct nxm_pth_state *
- Addr pth_id; //!< out-of-line state
- int flags; //!< shared flags
-#define US_SIGSTACK 0x1 // thread called sigaltstack
-#define US_ONSTACK 0x2 // thread is running on altstack
-#define US_PROFILE 0x4 // thread called profil
-#define US_SYSCALL 0x8 // thread in syscall
-#define US_TRAP 0x10 // thread has trapped
-#define US_YELLOW 0x20 // thread has mellowed yellow
-#define US_YZONE 0x40 // thread has zoned out
-#define US_FP_OWNED 0x80 // thread used floating point
-
- int cancel_state; //!< thread's cancelation state
-#define US_CANCEL 0x1 // cancel pending
-#define US_NOCANCEL 0X2 // synch cancel disabled
-#define US_SYS_NOCANCEL 0x4 // syscall cancel disabled
-#define US_ASYNC_NOCANCEL 0x8 // asynch cancel disabled
-#define US_CANCEL_BITS (US_NOCANCEL|US_SYS_NOCANCEL|US_ASYNC_NOCANCEL)
-#define US_CANCEL_MASK (US_CANCEL|US_NOCANCEL|US_SYS_NOCANCEL| \
- US_ASYNC_NOCANCEL)
-
- // These are semi-shared. They are always visible to
- // the kernel but are never context-switched by the library.
-
- int nxm_ssig; //!< scheduler's synchronous signals
- int reserved1; //!< reserved1
- int64_t nxm_active; //!< scheduler active
- int64_t reserved2; //!< reserved2
- };
-
- struct nxm_sched_state {
- struct ushared_state nxm_u; //!< state own by user thread
- unsigned int nxm_bits; //!< scheduler state / slot
- int nxm_quantum; //!< quantum count-down value
- int nxm_set_quantum; //!< quantum reset value
- int nxm_sysevent; //!< syscall state
- // struct nxm_upcall *
- Addr nxm_uc_ret; //!< stack ptr of null thread
- // void *
- Addr nxm_tid; //!< scheduler's thread id
- int64_t nxm_va; //!< page fault address
- // struct nxm_pth_state *
- Addr nxm_pthid; //!< id of null thread
- uint64_t nxm_bound_pcs_count; //!< bound PCS thread count
- int64_t pad[2]; //!< pad
- };
-
- /// nxm_shared.
- struct nxm_shared {
- int64_t nxm_callback; //!< address of upcall routine
- unsigned int nxm_version; //!< version number
- unsigned short nxm_uniq_offset; //!< correction factor for TEB
- unsigned short pad1; //!< pad1
- int64_t space[2]; //!< future growth
- struct nxm_sched_state nxm_ss[1]; //!< array of shared areas
- };
-
- /// nxm_slot_state_t.
- enum nxm_slot_state_t {
- NXM_SLOT_AVAIL,
- NXM_SLOT_BOUND,
- NXM_SLOT_UNBOUND,
- NXM_SLOT_EMPTY
- };
-
- /// nxm_config_info
- struct nxm_config_info {
- int nxm_nslots_per_rad; //!< max number of VP slots per RAD
- int nxm_nrads; //!< max number of RADs
- // nxm_slot_state_t *
- Addr nxm_slot_state; //!< per-VP slot state
- // struct nxm_shared *
- Addr nxm_rad[1]; //!< per-RAD shared areas
- };
-
- /// For nxm_thread_create.
- enum nxm_thread_type {
- NXM_TYPE_SCS = 0,
- NXM_TYPE_VP = 1,
- NXM_TYPE_MANAGER = 2
- };
-
- /// Thread attributes.
- struct nxm_thread_attr {
- int version; //!< version
- int type; //!< type
- int cancel_flags; //!< cancel_flags
- int priority; //!< priority
- int policy; //!< policy
- int signal_type; //!< signal_type
- // void *
- Addr pthid; //!< pthid
- sigset_t sigmask; //!< sigmask
- /// Initial register values.
- struct {
- uint64_t pc; //!< pc
- uint64_t sp; //!< sp
- uint64_t a0; //!< a0
- } registers;
- uint64_t pad2[2]; //!< pad2
- };
-
- /// Helper function to convert a host stat buffer to a target stat
- /// buffer. Also copies the target buffer out to the simulated
- /// memory space. Used by stat(), fstat(), and lstat().
- template <class T>
- static void
- copyOutStatBuf(FunctionalMemory *mem, Addr addr, global_stat *host)
- {
- TypedBufferArg<T> tgt(addr);
-
- tgt->st_dev = htog(host->st_dev);
- tgt->st_ino = htog(host->st_ino);
- tgt->st_mode = htog(host->st_mode);
- tgt->st_nlink = htog(host->st_nlink);
- tgt->st_uid = htog(host->st_uid);
- tgt->st_gid = htog(host->st_gid);
- tgt->st_rdev = htog(host->st_rdev);
- tgt->st_size = htog(host->st_size);
- tgt->st_atimeX = htog(host->st_atime);
- tgt->st_mtimeX = htog(host->st_mtime);
- tgt->st_ctimeX = htog(host->st_ctime);
- tgt->st_blksize = htog(host->st_blksize);
- tgt->st_blocks = htog(host->st_blocks);
-
- tgt.copyOut(mem);
- }
-
- /// Helper function to convert a host statfs buffer to a target statfs
- /// buffer. Also copies the target buffer out to the simulated
- /// memory space. Used by statfs() and fstatfs().
- template <class T>
- static void
- copyOutStatfsBuf(FunctionalMemory *mem, Addr addr, global_statfs *host)
- {
- TypedBufferArg<T> tgt(addr);
-
-#if defined(__OpenBSD__) || defined(__APPLE__) || defined(__FreeBSD__)
- tgt->f_type = 0;
-#else
- tgt->f_type = htog(host->f_type);
-#endif
- tgt->f_bsize = htog(host->f_bsize);
- tgt->f_blocks = htog(host->f_blocks);
- tgt->f_bfree = htog(host->f_bfree);
- tgt->f_bavail = htog(host->f_bavail);
- tgt->f_files = htog(host->f_files);
- tgt->f_ffree = htog(host->f_ffree);
-
- // Is this as string normally?
- memcpy(&tgt->f_fsid, &host->f_fsid, sizeof(host->f_fsid));
-
- tgt.copyOut(mem);
- }
-
- class F64 {
- public:
- static void copyOutStatBuf(FunctionalMemory *mem, Addr addr,
- global_stat *host)
- {
- Tru64::copyOutStatBuf<Tru64::F64_stat>(mem, addr, host);
- }
-
- static void copyOutStatfsBuf(FunctionalMemory *mem, Addr addr,
- global_statfs *host)
- {
- Tru64::copyOutStatfsBuf<Tru64::F64_statfs>(mem, addr, host);
- }
- };
-
- class PreF64 {
- public:
- static void copyOutStatBuf(FunctionalMemory *mem, Addr addr,
- global_stat *host)
- {
- Tru64::copyOutStatBuf<Tru64::pre_F64_stat>(mem, addr, host);
- }
-
- static void copyOutStatfsBuf(FunctionalMemory *mem, Addr addr,
- global_statfs *host)
- {
- Tru64::copyOutStatfsBuf<Tru64::pre_F64_statfs>(mem, addr, host);
- }
- };
-
- /// Helper function to convert a host stat buffer to an old pre-F64
- /// (4.x) target stat buffer. Also copies the target buffer out to
- /// the simulated memory space. Used by pre_F64_stat(),
- /// pre_F64_fstat(), and pre_F64_lstat().
- static void
- copyOutPreF64StatBuf(FunctionalMemory *mem, Addr addr, struct stat *host)
- {
- TypedBufferArg<Tru64::pre_F64_stat> tgt(addr);
-
- tgt->st_dev = htog(host->st_dev);
- tgt->st_ino = htog(host->st_ino);
- tgt->st_mode = htog(host->st_mode);
- tgt->st_nlink = htog(host->st_nlink);
- tgt->st_uid = htog(host->st_uid);
- tgt->st_gid = htog(host->st_gid);
- tgt->st_rdev = htog(host->st_rdev);
- tgt->st_size = htog(host->st_size);
- tgt->st_atimeX = htog(host->st_atime);
- tgt->st_mtimeX = htog(host->st_mtime);
- tgt->st_ctimeX = htog(host->st_ctime);
- tgt->st_blksize = htog(host->st_blksize);
- tgt->st_blocks = htog(host->st_blocks);
-
- tgt.copyOut(mem);
- }
-
-
- /// The target system's hostname.
- static const char *hostname;
-
-
- /// Target getdirentries() handler.
- static SyscallReturn
- getdirentriesFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
- {
-#ifdef __CYGWIN__
- panic("getdirent not implemented on cygwin!");
-#else
- int fd = process->sim_fd(xc->getSyscallArg(0));
- Addr tgt_buf = xc->getSyscallArg(1);
- int tgt_nbytes = xc->getSyscallArg(2);
- Addr tgt_basep = xc->getSyscallArg(3);
-
- char * const host_buf = new char[tgt_nbytes];
-
- // just pass basep through uninterpreted.
- TypedBufferArg<int64_t> basep(tgt_basep);
- basep.copyIn(xc->getMemPtr());
- long host_basep = (off_t)htog((int64_t)*basep);
- int host_result = getdirentries(fd, host_buf, tgt_nbytes, &host_basep);
-
- // check for error
- if (host_result < 0) {
- delete [] host_buf;
- return -errno;
- }
-
- // no error: copy results back to target space
- Addr tgt_buf_ptr = tgt_buf;
- char *host_buf_ptr = host_buf;
- char *host_buf_end = host_buf + host_result;
- while (host_buf_ptr < host_buf_end) {
- global_dirent *host_dp = (global_dirent *)host_buf_ptr;
- int namelen = strlen(host_dp->d_name);
-
- // Actual size includes padded string rounded up for alignment.
- // Subtract 256 for dummy char array in Tru64::dirent definition.
- // Add 1 to namelen for terminating null char.
- int tgt_bufsize = sizeof(Tru64::dirent) - 256 + roundUp(namelen+1, 8);
- TypedBufferArg<Tru64::dirent> tgt_dp(tgt_buf_ptr, tgt_bufsize);
- tgt_dp->d_ino = host_dp->d_ino;
- tgt_dp->d_reclen = tgt_bufsize;
- tgt_dp->d_namlen = namelen;
- strcpy(tgt_dp->d_name, host_dp->d_name);
- tgt_dp.copyOut(xc->getMemPtr());
-
- tgt_buf_ptr += tgt_bufsize;
- host_buf_ptr += host_dp->d_reclen;
- }
-
- delete [] host_buf;
-
- *basep = htog((int64_t)host_basep);
- basep.copyOut(xc->getMemPtr());
-
- return tgt_buf_ptr - tgt_buf;
-#endif
- }
-
- /// Target sigreturn() handler.
- static SyscallReturn
- sigreturnFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
- {
- using TheISA::RegFile;
- TypedBufferArg<Tru64::sigcontext> sc(xc->getSyscallArg(0));
-
- sc.copyIn(xc->getMemPtr());
-
- // Restore state from sigcontext structure.
- // Note that we'll advance PC <- NPC before the end of the cycle,
- // so we need to restore the desired PC into NPC.
- // The current regs->pc will get clobbered.
- xc->setNextPC(htog(sc->sc_pc));
-
- for (int i = 0; i < 31; ++i) {
- xc->setIntReg(i, htog(sc->sc_regs[i]));
- xc->setFloatRegInt(i, htog(sc->sc_fpregs[i]));
- }
-
- xc->setMiscReg(TheISA::Fpcr_DepTag, htog(sc->sc_fpcr));
-
- return 0;
- }
-
- /// Target table() handler.
- static SyscallReturn
- tableFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
- {
- int id = xc->getSyscallArg(0); // table ID
- int index = xc->getSyscallArg(1); // index into table
- // arg 2 is buffer pointer; type depends on table ID
- int nel = xc->getSyscallArg(3); // number of elements
- int lel = xc->getSyscallArg(4); // expected element size
-
- switch (id) {
- case Tru64::TBL_SYSINFO: {
- if (index != 0 || nel != 1 || lel != sizeof(Tru64::tbl_sysinfo))
- return -EINVAL;
- TypedBufferArg<Tru64::tbl_sysinfo> elp(xc->getSyscallArg(2));
-
- const int clk_hz = one_million;
- elp->si_user = htog(curTick / (Clock::Frequency / clk_hz));
- elp->si_nice = htog(0);
- elp->si_sys = htog(0);
- elp->si_idle = htog(0);
- elp->wait = htog(0);
- elp->si_hz = htog(clk_hz);
- elp->si_phz = htog(clk_hz);
- elp->si_boottime = htog(seconds_since_epoch); // seconds since epoch?
- elp->si_max_procs = htog(process->numCpus());
- elp.copyOut(xc->getMemPtr());
- return 0;
- }
-
- default:
- cerr << "table(): id " << id << " unknown." << endl;
- return -EINVAL;
- }
- }
-
- //
- // Mach syscalls -- identified by negated syscall numbers
- //
-
- /// Create a stack region for a thread.
- static SyscallReturn
- stack_createFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
- {
- TypedBufferArg<Tru64::vm_stack> argp(xc->getSyscallArg(0));
-
- argp.copyIn(xc->getMemPtr());
-
- // if the user chose an address, just let them have it. Otherwise
- // pick one for them.
- if (htog(argp->address) == 0) {
- argp->address = htog(process->next_thread_stack_base);
- int stack_size = (htog(argp->rsize) + htog(argp->ysize) +
- htog(argp->gsize));
- process->next_thread_stack_base -= stack_size;
- argp.copyOut(xc->getMemPtr());
- }
-
- return 0;
- }
-
- /// NXM library version stamp.
- static
- const int NXM_LIB_VERSION = 301003;
-
- /// This call sets up the interface between the user and kernel
- /// schedulers by creating a shared-memory region. The shared memory
- /// region has several structs, some global, some per-RAD, some per-VP.
- static SyscallReturn
- nxm_task_initFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
- {
- TypedBufferArg<Tru64::nxm_task_attr> attrp(xc->getSyscallArg(0));
- TypedBufferArg<Addr> configptr_ptr(xc->getSyscallArg(1));
-
- attrp.copyIn(xc->getMemPtr());
-
- if (gtoh(attrp->nxm_version) != NXM_LIB_VERSION) {
- cerr << "nxm_task_init: thread library version mismatch! "
- << "got " << attrp->nxm_version
- << ", expected " << NXM_LIB_VERSION << endl;
- abort();
- }
-
- if (gtoh(attrp->flags) != Tru64::NXM_TASK_INIT_VP) {
- cerr << "nxm_task_init: bad flag value " << attrp->flags
- << " (expected " << Tru64::NXM_TASK_INIT_VP << ")" << endl;
- abort();
- }
-
- const Addr base_addr = 0x12000; // was 0x3f0000000LL;
- Addr cur_addr = base_addr; // next addresses to use
- // first comes the config_info struct
- Addr config_addr = cur_addr;
- cur_addr += sizeof(Tru64::nxm_config_info);
- // next comes the per-cpu state vector
- Addr slot_state_addr = cur_addr;
- int slot_state_size =
- process->numCpus() * sizeof(Tru64::nxm_slot_state_t);
- cur_addr += slot_state_size;
- // now the per-RAD state struct (we only support one RAD)
- cur_addr = 0x14000; // bump up addr for alignment
- Addr rad_state_addr = cur_addr;
- int rad_state_size =
- (sizeof(Tru64::nxm_shared)
- + (process->numCpus()-1) * sizeof(Tru64::nxm_sched_state));
- cur_addr += rad_state_size;
-
- // now initialize a config_info struct and copy it out to user space
- TypedBufferArg<Tru64::nxm_config_info> config(config_addr);
-
- config->nxm_nslots_per_rad = htog(process->numCpus());
- config->nxm_nrads = htog(1); // only one RAD in our system!
- config->nxm_slot_state = htog(slot_state_addr);
- config->nxm_rad[0] = htog(rad_state_addr);
-
- config.copyOut(xc->getMemPtr());
-
- // initialize the slot_state array and copy it out
- TypedBufferArg<Tru64::nxm_slot_state_t> slot_state(slot_state_addr,
- slot_state_size);
- for (int i = 0; i < process->numCpus(); ++i) {
- // CPU 0 is bound to the calling process; all others are available
- // XXX this code should have an endian conversion, but I don't think
- // it works anyway
- slot_state[i] =
- (i == 0) ? Tru64::NXM_SLOT_BOUND : Tru64::NXM_SLOT_AVAIL;
- }
-
- slot_state.copyOut(xc->getMemPtr());
-
- // same for the per-RAD "shared" struct. Note that we need to
- // allocate extra bytes for the per-VP array which is embedded at
- // the end.
- TypedBufferArg<Tru64::nxm_shared> rad_state(rad_state_addr,
- rad_state_size);
-
- rad_state->nxm_callback = attrp->nxm_callback;
- rad_state->nxm_version = attrp->nxm_version;
- rad_state->nxm_uniq_offset = attrp->nxm_uniq_offset;
- for (int i = 0; i < process->numCpus(); ++i) {
- Tru64::nxm_sched_state *ssp = &rad_state->nxm_ss[i];
- ssp->nxm_u.sigmask = htog(0);
- ssp->nxm_u.sig = htog(0);
- ssp->nxm_u.flags = htog(0);
- ssp->nxm_u.cancel_state = htog(0);
- ssp->nxm_u.nxm_ssig = 0;
- ssp->nxm_bits = htog(0);
- ssp->nxm_quantum = attrp->nxm_quantum;
- ssp->nxm_set_quantum = attrp->nxm_quantum;
- ssp->nxm_sysevent = htog(0);
-
- if (i == 0) {
- uint64_t uniq = xc->readMiscReg(TheISA::Uniq_DepTag);
- ssp->nxm_u.pth_id = htog(uniq + gtoh(attrp->nxm_uniq_offset));
- ssp->nxm_u.nxm_active = htog(uniq | 1);
- }
- else {
- ssp->nxm_u.pth_id = htog(0);
- ssp->nxm_u.nxm_active = htog(0);
- }
- }
-
- rad_state.copyOut(xc->getMemPtr());
-
- //
- // copy pointer to shared config area out to user
- //
- *configptr_ptr = htog(config_addr);
- configptr_ptr.copyOut(xc->getMemPtr());
-
- // Register this as a valid address range with the process
- process->nxm_start = base_addr;
- process->nxm_end = cur_addr;
-
- return 0;
- }
-
- /// Initialize execution context.
- static void
- init_exec_context(ExecContext *ec,
- Tru64::nxm_thread_attr *attrp, uint64_t uniq_val)
- {
- ec->clearArchRegs();
-
- ec->setIntReg(TheISA::ArgumentReg0, gtoh(attrp->registers.a0));
- ec->setIntReg(27/*t12*/, gtoh(attrp->registers.pc));
- ec->setIntReg(TheISA::StackPointerReg, gtoh(attrp->registers.sp));
- ec->setMiscReg(TheISA::Uniq_DepTag, uniq_val);
-
- ec->setPC(gtoh(attrp->registers.pc));
- ec->setNextPC(gtoh(attrp->registers.pc) + sizeof(TheISA::MachInst));
-
- ec->activate();
- }
-
- /// Create thread.
- static SyscallReturn
- nxm_thread_createFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
- {
- TypedBufferArg<Tru64::nxm_thread_attr> attrp(xc->getSyscallArg(0));
- TypedBufferArg<uint64_t> kidp(xc->getSyscallArg(1));
- int thread_index = xc->getSyscallArg(2);
-
- // get attribute args
- attrp.copyIn(xc->getMemPtr());
-
- if (gtoh(attrp->version) != NXM_LIB_VERSION) {
- cerr << "nxm_thread_create: thread library version mismatch! "
- << "got " << attrp->version
- << ", expected " << NXM_LIB_VERSION << endl;
- abort();
- }
-
- if (thread_index < 0 | thread_index > process->numCpus()) {
- cerr << "nxm_thread_create: bad thread index " << thread_index
- << endl;
- abort();
- }
-
- // On a real machine, the per-RAD shared structure is in
- // shared memory, so both the user and kernel can get at it.
- // We don't have that luxury, so we just copy it in and then
- // back out again.
- int rad_state_size =
- (sizeof(Tru64::nxm_shared) +
- (process->numCpus()-1) * sizeof(Tru64::nxm_sched_state));
-
- TypedBufferArg<Tru64::nxm_shared> rad_state(0x14000,
- rad_state_size);
- rad_state.copyIn(xc->getMemPtr());
-
- uint64_t uniq_val = gtoh(attrp->pthid) - gtoh(rad_state->nxm_uniq_offset);
-
- if (gtoh(attrp->type) == Tru64::NXM_TYPE_MANAGER) {
- // DEC pthreads seems to always create one of these (in
- // addition to N application threads), but we don't use it,
- // so don't bother creating it.
-
- // This is supposed to be a port number. Make something up.
- *kidp = htog(99);
- kidp.copyOut(xc->getMemPtr());
-
- return 0;
- } else if (gtoh(attrp->type) == Tru64::NXM_TYPE_VP) {
- // A real "virtual processor" kernel thread. Need to fork
- // this thread on another CPU.
- Tru64::nxm_sched_state *ssp = &rad_state->nxm_ss[thread_index];
-
- if (gtoh(ssp->nxm_u.nxm_active) != 0)
- return (int) Tru64::KERN_NOT_RECEIVER;
-
- ssp->nxm_u.pth_id = attrp->pthid;
- ssp->nxm_u.nxm_active = htog(uniq_val | 1);
-
- rad_state.copyOut(xc->getMemPtr());
-
- Addr slot_state_addr = 0x12000 + sizeof(Tru64::nxm_config_info);
- int slot_state_size =
- process->numCpus() * sizeof(Tru64::nxm_slot_state_t);
-
- TypedBufferArg<Tru64::nxm_slot_state_t>
- slot_state(slot_state_addr,
- slot_state_size);
-
- slot_state.copyIn(xc->getMemPtr());
-
- if (slot_state[thread_index] != Tru64::NXM_SLOT_AVAIL) {
- cerr << "nxm_thread_createFunc: requested VP slot "
- << thread_index << " not available!" << endl;
- fatal("");
- }
-
- // XXX This should have an endian conversion but I think this code
- // doesn't work anyway
- slot_state[thread_index] = Tru64::NXM_SLOT_BOUND;
-
- slot_state.copyOut(xc->getMemPtr());
-
- // Find a free simulator execution context.
- for (int i = 0; i < process->numCpus(); ++i) {
- ExecContext *xc = process->execContexts[i];
-
- if (xc->status() == ExecContext::Suspended) {
- // inactive context... grab it
- init_exec_context(xc, attrp, uniq_val);
-
- // This is supposed to be a port number, but we'll try
- // and get away with just sticking the thread index
- // here.
- *kidp = htog(thread_index);
- kidp.copyOut(xc->getMemPtr());
-
- return 0;
- }
- }
-
- // fell out of loop... no available inactive context
- cerr << "nxm_thread_create: no idle contexts available." << endl;
- abort();
- } else {
- cerr << "nxm_thread_create: can't handle thread type "
- << attrp->type << endl;
- abort();
- }
-
- return 0;
- }
-
- /// Thread idle call (like yield()).
- static SyscallReturn
- nxm_idleFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
- {
- return 0;
- }
-
- /// Block thread.
- static SyscallReturn
- nxm_thread_blockFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
- {
- uint64_t tid = xc->getSyscallArg(0);
- uint64_t secs = xc->getSyscallArg(1);
- uint64_t flags = xc->getSyscallArg(2);
- uint64_t action = xc->getSyscallArg(3);
- uint64_t usecs = xc->getSyscallArg(4);
-
- cout << xc->getCpuPtr()->name() << ": nxm_thread_block " << tid << " "
- << secs << " " << flags << " " << action << " " << usecs << endl;
-
- return 0;
- }
-
- /// block.
- static SyscallReturn
- nxm_blockFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
- {
- Addr uaddr = xc->getSyscallArg(0);
- uint64_t val = xc->getSyscallArg(1);
- uint64_t secs = xc->getSyscallArg(2);
- uint64_t usecs = xc->getSyscallArg(3);
- uint64_t flags = xc->getSyscallArg(4);
-
- BaseCPU *cpu = xc->getCpuPtr();
-
- cout << cpu->name() << ": nxm_block "
- << hex << uaddr << dec << " " << val
- << " " << secs << " " << usecs
- << " " << flags << endl;
-
- return 0;
- }
-
- /// Unblock thread.
- static SyscallReturn
- nxm_unblockFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
- {
- Addr uaddr = xc->getSyscallArg(0);
-
- cout << xc->getCpuPtr()->name() << ": nxm_unblock "
- << hex << uaddr << dec << endl;
-
- return 0;
- }
-
- /// Switch thread priority.
- static SyscallReturn
- swtch_priFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
- {
- // Attempts to switch to another runnable thread (if there is
- // one). Returns false if there are no other threads to run
- // (i.e., the thread can reasonably spin-wait) or true if there
- // are other threads.
- //
- // Since we assume at most one "kernel" thread per CPU, it's
- // always safe to return false here.
- return 0; //false;
- }
-
-
- /// Activate exec context waiting on a channel. Just activate one
- /// by default.
- static int
- activate_waiting_context(Addr uaddr, Process *process,
- bool activate_all = false)
- {
- int num_activated = 0;
-
- list<Process::WaitRec>::iterator i = process->waitList.begin();
- list<Process::WaitRec>::iterator end = process->waitList.end();
-
- while (i != end && (num_activated == 0 || activate_all)) {
- if (i->waitChan == uaddr) {
- // found waiting process: make it active
- ExecContext *newCtx = i->waitingContext;
- assert(newCtx->status() == ExecContext::Suspended);
- newCtx->activate();
-
- // get rid of this record
- i = process->waitList.erase(i);
-
- ++num_activated;
- } else {
- ++i;
- }
- }
-
- return num_activated;
- }
-
- /// M5 hacked-up lock acquire.
- static void
- m5_lock_mutex(Addr uaddr, Process *process, ExecContext *xc)
- {
- TypedBufferArg<uint64_t> lockp(uaddr);
-
- lockp.copyIn(xc->getMemPtr());
-
- if (gtoh(*lockp) == 0) {
- // lock is free: grab it
- *lockp = htog(1);
- lockp.copyOut(xc->getMemPtr());
- } else {
- // lock is busy: disable until free
- process->waitList.push_back(Process::WaitRec(uaddr, xc));
- xc->suspend();
- }
- }
-
- /// M5 unlock call.
- static void
- m5_unlock_mutex(Addr uaddr, Process *process, ExecContext *xc)
- {
- TypedBufferArg<uint64_t> lockp(uaddr);
-
- lockp.copyIn(xc->getMemPtr());
- assert(*lockp != 0);
-
- // Check for a process waiting on the lock.
- int num_waiting = activate_waiting_context(uaddr, process);
-
- // clear lock field if no waiting context is taking over the lock
- if (num_waiting == 0) {
- *lockp = 0;
- lockp.copyOut(xc->getMemPtr());
- }
- }
-
- /// Lock acquire syscall handler.
- static SyscallReturn
- m5_mutex_lockFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
- {
- Addr uaddr = xc->getSyscallArg(0);
-
- m5_lock_mutex(uaddr, process, xc);
-
- // Return 0 since we will always return to the user with the lock
- // acquired. We will just keep the context inactive until that is
- // true.
- return 0;
- }
-
- /// Try lock (non-blocking).
- static SyscallReturn
- m5_mutex_trylockFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
- {
- Addr uaddr = xc->getSyscallArg(0);
- TypedBufferArg<uint64_t> lockp(uaddr);
-
- lockp.copyIn(xc->getMemPtr());
-
- if (gtoh(*lockp) == 0) {
- // lock is free: grab it
- *lockp = htog(1);
- lockp.copyOut(xc->getMemPtr());
- return 0;
- } else {
- return 1;
- }
- }
-
- /// Unlock syscall handler.
- static SyscallReturn
- m5_mutex_unlockFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
- {
- Addr uaddr = xc->getSyscallArg(0);
-
- m5_unlock_mutex(uaddr, process, xc);
-
- return 0;
- }
-
- /// Signal ocndition.
- static SyscallReturn
- m5_cond_signalFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
- {
- Addr cond_addr = xc->getSyscallArg(0);
-
- // Wake up one process waiting on the condition variable.
- activate_waiting_context(cond_addr, process);
-
- return 0;
- }
-
- /// Wake up all processes waiting on the condition variable.
- static SyscallReturn
- m5_cond_broadcastFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
- {
- Addr cond_addr = xc->getSyscallArg(0);
-
- activate_waiting_context(cond_addr, process, true);
-
- return 0;
- }
-
- /// Wait on a condition.
- static SyscallReturn
- m5_cond_waitFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
- {
- Addr cond_addr = xc->getSyscallArg(0);
- Addr lock_addr = xc->getSyscallArg(1);
- TypedBufferArg<uint64_t> condp(cond_addr);
- TypedBufferArg<uint64_t> lockp(lock_addr);
-
- // user is supposed to acquire lock before entering
- lockp.copyIn(xc->getMemPtr());
- assert(gtoh(*lockp) != 0);
-
- m5_unlock_mutex(lock_addr, process, xc);
-
- process->waitList.push_back(Process::WaitRec(cond_addr, xc));
- xc->suspend();
-
- return 0;
- }
-
- /// Thread exit.
- static SyscallReturn
- m5_thread_exitFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
- {
- assert(xc->status() == ExecContext::Active);
- xc->deallocate();
-
- return 0;
- }
-
- /// Indirect syscall invocation (call #0).
- static SyscallReturn
- indirectSyscallFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
- {
- int new_callnum = xc->getSyscallArg(0);
- LiveProcess *lp = dynamic_cast<LiveProcess*>(process);
- assert(lp);
-
- for (int i = 0; i < 5; ++i)
- xc->setSyscallArg(i, xc->getSyscallArg(i+1));
-
-
- SyscallDesc *new_desc = lp->getDesc(new_callnum);
- if (desc == NULL)
- fatal("Syscall %d out of range", callnum);
-
- new_desc->doSyscall(new_callnum, process, xc);
-
- return 0;
- }
-
-}; // class Tru64
-
-
-#endif // FULL_SYSTEM
-
-#endif // __TRU64_HH__
diff --git a/kern/tru64/tru64_events.cc b/kern/tru64/tru64_events.cc
deleted file mode 100644
index 8f2be6d9b..000000000
--- a/kern/tru64/tru64_events.cc
+++ /dev/null
@@ -1,95 +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 "cpu/exec_context.hh"
-#include "cpu/base.hh"
-#include "kern/system_events.hh"
-#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/arguments.hh"
-#include "arch/isa_traits.hh"
-#include "sim/system.hh"
-
-using namespace TheISA;
-
-//void SkipFuncEvent::process(ExecContext *xc);
-
-void
-BadAddrEvent::process(ExecContext *xc)
-{
- // The following gross hack is the equivalent function to the
- // annotation for vmunix::badaddr in:
- // simos/simulation/apps/tcl/osf/tlaser.tcl
-
- uint64_t a0 = xc->readIntReg(ArgumentReg0);
-
- if (!TheISA::IsK0Seg(a0) ||
- xc->getSystemPtr()->memctrl->badaddr(
- TheISA::K0Seg2Phys(a0) & EV5::PAddrImplMask)) {
-
- DPRINTF(BADADDR, "badaddr arg=%#x bad\n", a0);
- xc->setIntReg(ReturnValueReg, 0x1);
- SkipFuncEvent::process(xc);
- }
- else
- DPRINTF(BADADDR, "badaddr arg=%#x good\n", a0);
-}
-
-void
-PrintfEvent::process(ExecContext *xc)
-{
- if (DTRACE(Printf)) {
- DebugOut() << curTick << ": " << xc->getCpuPtr()->name() << ": ";
-
- AlphaArguments args(xc);
- tru64::Printf(args);
- }
-}
-
-void
-DebugPrintfEvent::process(ExecContext *xc)
-{
- if (DTRACE(DebugPrintf)) {
- if (!raw)
- DebugOut() << curTick << ": " << xc->getCpuPtr()->name() << ": ";
-
- AlphaArguments args(xc);
- tru64::Printf(args);
- }
-}
-
-void
-DumpMbufEvent::process(ExecContext *xc)
-{
- if (DTRACE(DebugPrintf)) {
- AlphaArguments args(xc);
- tru64::DumpMbuf(args);
- }
-}
diff --git a/python/SConscript b/python/SConscript
deleted file mode 100644
index a34d3f2d5..000000000
--- a/python/SConscript
+++ /dev/null
@@ -1,207 +0,0 @@
-# -*- mode:python -*-
-
-# Copyright (c) 2004-2005 The Regents of The University of Michigan
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met: redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer;
-# redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution;
-# neither the name of the copyright holders nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-import os, os.path, re, sys
-
-Import('env')
-
-import scons_helper
-
-def WriteEmbeddedPyFile(target, source, path, name, ext, filename):
- if isinstance(source, str):
- source = file(source, 'r')
-
- if isinstance(target, str):
- target = file(target, 'w')
-
- print >>target, "AddModule(%s, %s, %s, %s, '''\\" % \
- (`path`, `name`, `ext`, `filename`)
-
- for line in source:
- line = line
- # escape existing backslashes
- line = line.replace('\\', '\\\\')
- # escape existing triple quotes
- line = line.replace("'''", r"\'\'\'")
-
- print >>target, line,
-
- print >>target, "''')"
- print >>target
-
-def WriteCFile(target, source, name):
- if isinstance(source, str):
- source = file(source, 'r')
-
- if isinstance(target, str):
- target = file(target, 'w')
-
- print >>target, 'const char %s_string[] = {' % name
-
- count = 0
- from array import array
- try:
- while True:
- foo = array('B')
- foo.fromfile(source, 10000)
- l = [ str(i) for i in foo.tolist() ]
- count += len(l)
- for i in xrange(0,9999,20):
- print >>target, ','.join(l[i:i+20]) + ','
- except EOFError:
- l = [ str(i) for i in foo.tolist() ]
- count += len(l)
- for i in xrange(0,len(l),20):
- print >>target, ','.join(l[i:i+20]) + ','
- print >>target, ','.join(l[i:]) + ','
-
- print >>target, '};'
- print >>target, 'const int %s_length = %d;' % (name, count)
- print >>target
-
-def splitpath(path):
- dir,file = os.path.split(path)
- path = []
- assert(file)
- while dir:
- dir,base = os.path.split(dir)
- path.insert(0, base)
- return path, file
-
-def MakeEmbeddedPyFile(target, source, env):
- target = file(str(target[0]), 'w')
-
- tree = {}
- for src in source:
- src = str(src)
- path,pyfile = splitpath(src)
- node = tree
- for dir in path:
- if not node.has_key(dir):
- node[dir] = { }
- node = node[dir]
-
- name,ext = pyfile.split('.')
- if name == '__init__':
- node['.hasinit'] = True
- node[pyfile] = (src,name,ext,src)
-
- done = False
- while not done:
- done = True
- for name,entry in tree.items():
- if not isinstance(entry, dict): continue
- if entry.has_key('.hasinit'): continue
-
- done = False
- del tree[name]
- for key,val in entry.iteritems():
- if tree.has_key(key):
- raise NameError, \
- "dir already has %s can't add it again" % key
- tree[key] = val
-
- files = []
- def populate(node, path = []):
- names = node.keys()
- names.sort()
- for name in names:
- if name == '.hasinit':
- continue
-
- entry = node[name]
- if isinstance(entry, dict):
- if not entry.has_key('.hasinit'):
- raise NameError, 'package directory missing __init__.py'
- populate(entry, path + [ name ])
- else:
- pyfile,name,ext,filename = entry
- files.append((pyfile, path, name, ext, filename))
- populate(tree)
-
- for pyfile, path, name, ext, filename in files:
- WriteEmbeddedPyFile(target, pyfile, path, name, ext, filename)
-
-def MakeDefinesPyFile(target, source, env):
- f = file(str(target[0]), 'w')
- print >>f, "import __main__"
- print >>f, "__main__.m5_build_env = ",
- print >>f, source[0]
- f.close()
-
-CFileCounter = 0
-def MakePythonCFile(target, source, env):
- global CFileCounter
- target = file(str(target[0]), 'w')
-
- print >>target, '''\
-#include "base/embedfile.hh"
-
-namespace {
-'''
- for src in source:
- src = str(src)
- fname = os.path.basename(src)
- name = 'embedded_file%d' % CFileCounter
- CFileCounter += 1
- WriteCFile(target, src, name)
- print >>target, '''\
-EmbedMap %(name)s("%(fname)s",
- %(name)s_string, %(name)s_length);
-
-''' % locals()
- print >>target, '''\
-
-/* namespace */ }
-'''
-
-# base list of .py files to embed
-embedded_py_files = [ '../util/pbs/jobfile.py' ]
-# add all .py files in python/m5
-objpath = os.path.join(env['SRCDIR'], 'python', 'm5')
-for root, dirs, files in os.walk(objpath, topdown=True):
- for i,dir in enumerate(dirs):
- if dir == 'SCCS':
- del dirs[i]
- break
-
- assert(root.startswith(objpath))
- for f in files:
- if f.endswith('.py'):
- embedded_py_files.append(os.path.join(root, f))
-
-embedfile_hh = os.path.join(env['SRCDIR'], 'base/embedfile.hh')
-
-optionDict = dict([(opt, env[opt]) for opt in env.ExportOptions])
-env.Command('defines.py', Value(optionDict), MakeDefinesPyFile)
-
-env.Command('embedded_py.py', embedded_py_files, MakeEmbeddedPyFile)
-env.Depends('embedded_py.cc', embedfile_hh)
-env.Command('embedded_py.cc',
- ['string_importer.py', 'defines.py', 'embedded_py.py'],
- MakePythonCFile)
diff --git a/python/m5/objects/AlphaConsole.py b/python/m5/objects/AlphaConsole.py
deleted file mode 100644
index f8f034682..000000000
--- a/python/m5/objects/AlphaConsole.py
+++ /dev/null
@@ -1,9 +0,0 @@
-from m5 import *
-from Device import PioDevice
-
-class AlphaConsole(PioDevice):
- 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")
diff --git a/python/m5/objects/BadDevice.py b/python/m5/objects/BadDevice.py
deleted file mode 100644
index 3fba4637d..000000000
--- a/python/m5/objects/BadDevice.py
+++ /dev/null
@@ -1,6 +0,0 @@
-from m5 import *
-from Device import PioDevice
-
-class BadDevice(PioDevice):
- 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
deleted file mode 100644
index a90203729..000000000
--- a/python/m5/objects/BaseCPU.py
+++ /dev/null
@@ -1,29 +0,0 @@
-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")
-
- 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:
- workload = VectorParam.Process("processes to run")
-
- max_insts_all_threads = Param.Counter(0,
- "terminate when all threads have reached this inst count")
- max_insts_any_thread = Param.Counter(0,
- "terminate when any thread reaches this inst count")
- max_loads_all_threads = Param.Counter(0,
- "terminate when all threads have reached this load count")
- max_loads_any_thread = Param.Counter(0,
- "terminate when any thread reaches this load count")
-
- defer_registration = Param.Bool(False,
- "defer registration with system (for sampling)")
-
- clock = Param.Clock(Parent.clock, "clock speed")
diff --git a/python/m5/objects/Bus.py b/python/m5/objects/Bus.py
deleted file mode 100644
index 26509d7d2..000000000
--- a/python/m5/objects/Bus.py
+++ /dev/null
@@ -1,7 +0,0 @@
-from m5 import *
-from BaseHier import BaseHier
-
-class Bus(BaseHier):
- type = 'Bus'
- clock = Param.Clock("bus frequency")
- width = Param.Int("bus width in bytes")
diff --git a/python/m5/objects/Device.py b/python/m5/objects/Device.py
deleted file mode 100644
index d7ca014a9..000000000
--- a/python/m5/objects/Device.py
+++ /dev/null
@@ -1,35 +0,0 @@
-from m5 import *
-from FunctionalMemory import FunctionalMemory
-
-# 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):
- 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")
-
-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'
- abstract = True
- platform = Param.Platform(Parent.any, "Platform")
-
-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
deleted file mode 100644
index 68b21b404..000000000
--- a/python/m5/objects/Ethernet.py
+++ /dev/null
@@ -1,119 +0,0 @@
-from m5 import *
-from Device import DmaDevice
-from Pci import PciDevice
-
-class EtherInt(SimObject):
- type = 'EtherInt'
- abstract = True
- peer = Param.EtherInt(NULL, "peer interface")
-
-class EtherLink(SimObject):
- type = 'EtherLink'
- int1 = Param.EtherInt("interface 1")
- int2 = Param.EtherInt("interface 2")
- delay = Param.Latency('0us', "packet transmit delay")
- delay_var = Param.Latency('0ns', "packet transmit delay variability")
- speed = Param.NetworkBandwidth('1Gbps', "link speed")
- dump = Param.EtherDump(NULL, "dump object")
-
-class EtherBus(SimObject):
- type = 'EtherBus'
- loopback = Param.Bool(True, "send packet back to the sending interface")
- dump = Param.EtherDump(NULL, "dump object")
- speed = Param.NetworkBandwidth('100Mbps', "bus speed in bits per second")
-
-class EtherTap(EtherInt):
- type = 'EtherTap'
- bufsz = Param.Int(10000, "tap buffer size")
- dump = Param.EtherDump(NULL, "dump object")
- port = Param.UInt16(3500, "tap port")
-
-class EtherDump(SimObject):
- type = 'EtherDump'
- file = Param.String("dump file")
- maxlen = Param.Int(96, "max portion of packet data to dump")
-
-if build_env['ALPHA_TLASER']:
-
- class EtherDev(DmaDevice):
- type = 'EtherDev'
- hardware_address = Param.EthernetAddr(NextEthernetAddr,
- "Ethernet Hardware Address")
-
- dma_data_free = Param.Bool(False, "DMA of Data is free")
- dma_desc_free = Param.Bool(False, "DMA of Descriptors is free")
- 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_filter = Param.Bool(True, "Enable Receive Filter")
- rx_delay = Param.Latency('1us', "Receive Delay")
- tx_delay = Param.Latency('1us', "Transmit Delay")
-
- intr_delay = Param.Latency('0us', "Interrupt Delay")
- payload_bus = Param.Bus(NULL, "The IO Bus to attach to for payload")
- physmem = Param.PhysicalMemory(Parent.any, "Physical Memory")
- tlaser = Param.Turbolaser(Parent.any, "Turbolaser")
-
- class EtherDevInt(EtherInt):
- type = 'EtherDevInt'
- device = Param.EtherDev("Ethernet device of this interface")
-
-class EtherDevBase(PciDevice):
- hardware_address = Param.EthernetAddr(NextEthernetAddr,
- "Ethernet Hardware Address")
-
- 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")
- rx_fifo_size = Param.MemorySize('512kB', "max size of rx fifo")
- tx_fifo_size = Param.MemorySize('512kB', "max size of tx fifo")
-
- rx_filter = Param.Bool(True, "Enable Receive Filter")
- intr_delay = Param.Latency('10us', "Interrupt propagation delay")
- rx_thread = Param.Bool(False, "dedicated kernel thread for transmit")
- tx_thread = Param.Bool(False, "dedicated kernel threads for receive")
- rss = Param.Bool(False, "Receive Side Scaling")
-
-class NSGigE(EtherDevBase):
- type = 'NSGigE'
-
- dma_data_free = Param.Bool(False, "DMA of Data is free")
- dma_desc_free = Param.Bool(False, "DMA of Descriptors is free")
-
-
-class NSGigEInt(EtherInt):
- type = 'NSGigEInt'
- device = Param.NSGigE("Ethernet device of this interface")
-
-class Sinic(EtherDevBase):
- type = 'Sinic'
-
- rx_max_copy = Param.MemorySize('1514B', "rx max copy")
- tx_max_copy = Param.MemorySize('16kB', "tx max copy")
- rx_max_intr = Param.UInt32(10, "max rx packets per interrupt")
- rx_fifo_threshold = Param.MemorySize('384kB', "rx fifo high threshold")
- rx_fifo_low_mark = Param.MemorySize('128kB', "rx fifo low threshold")
- tx_fifo_high_mark = Param.MemorySize('384kB', "tx fifo high threshold")
- tx_fifo_threshold = Param.MemorySize('128kB', "tx fifo low threshold")
- virtual_count = Param.UInt32(1, "Virtualized SINIC")
- zero_copy = Param.Bool(False, "Zero copy receive")
- delay_copy = Param.Bool(False, "Delayed copy transmit")
- virtual_addr = Param.Bool(False, "Virtual addressing")
-
-class SinicInt(EtherInt):
- type = 'SinicInt'
- device = Param.Sinic("Ethernet device of this interface")
diff --git a/python/m5/objects/Ide.py b/python/m5/objects/Ide.py
deleted file mode 100644
index 6855ec653..000000000
--- a/python/m5/objects/Ide.py
+++ /dev/null
@@ -1,15 +0,0 @@
-from m5 import *
-from Pci import PciDevice
-
-class IdeID(Enum): vals = ['master', 'slave']
-
-class IdeDisk(SimObject):
- type = 'IdeDisk'
- 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'
- disks = VectorParam.IdeDisk("IDE disks attached to this controller")
diff --git a/python/m5/objects/Pci.py b/python/m5/objects/Pci.py
deleted file mode 100644
index 4124d0b92..000000000
--- a/python/m5/objects/Pci.py
+++ /dev/null
@@ -1,55 +0,0 @@
-from m5 import *
-from Device import FooPioDevice, DmaDevice
-
-class PciConfigData(SimObject):
- type = 'PciConfigData'
- VendorID = Param.UInt16("Vendor ID")
- DeviceID = Param.UInt16("Device ID")
- Command = Param.UInt16(0, "Command")
- Status = Param.UInt16(0, "Status")
- Revision = Param.UInt8(0, "Device")
- ProgIF = Param.UInt8(0, "Programming Interface")
- SubClassCode = Param.UInt8(0, "Sub-Class Code")
- ClassCode = Param.UInt8(0, "Class Code")
- CacheLineSize = Param.UInt8(0, "System Cacheline Size")
- LatencyTimer = Param.UInt8(0, "PCI Latency Timer")
- HeaderType = Param.UInt8(0, "PCI Header Type")
- BIST = Param.UInt8(0, "Built In Self Test")
-
- BAR0 = Param.UInt32(0x00, "Base Address Register 0")
- BAR1 = Param.UInt32(0x00, "Base Address Register 1")
- BAR2 = Param.UInt32(0x00, "Base Address Register 2")
- BAR3 = Param.UInt32(0x00, "Base Address Register 3")
- BAR4 = Param.UInt32(0x00, "Base Address Register 4")
- BAR5 = Param.UInt32(0x00, "Base Address Register 5")
- BAR0Size = Param.MemorySize32('0B', "Base Address Register 0 Size")
- BAR1Size = Param.MemorySize32('0B', "Base Address Register 1 Size")
- BAR2Size = Param.MemorySize32('0B', "Base Address Register 2 Size")
- BAR3Size = Param.MemorySize32('0B', "Base Address Register 3 Size")
- BAR4Size = Param.MemorySize32('0B', "Base Address Register 4 Size")
- BAR5Size = Param.MemorySize32('0B', "Base Address Register 5 Size")
-
- CardbusCIS = Param.UInt32(0x00, "Cardbus Card Information Structure")
- SubsystemID = Param.UInt16(0x00, "Subsystem ID")
- SubsystemVendorID = Param.UInt16(0x00, "Subsystem Vendor ID")
- ExpansionROM = Param.UInt32(0x00, "Expansion ROM Base Address")
- InterruptLine = Param.UInt8(0x00, "Interrupt Line")
- InterruptPin = Param.UInt8(0x00, "Interrupt Pin")
- MaximumLatency = Param.UInt8(0x00, "Maximum Latency")
- MinimumGrant = Param.UInt8(0x00, "Minimum Grant")
-
-class PciConfigAll(FooPioDevice):
- 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")
- configdata = Param.PciConfigData(Parent.any, "PCI Config data")
- configspace = Param.PciConfigAll(Parent.any, "PCI Configspace")
-
-class PciFake(PciDevice):
- type = 'PciFake'
diff --git a/python/m5/objects/PhysicalMemory.py b/python/m5/objects/PhysicalMemory.py
deleted file mode 100644
index f50937ee6..000000000
--- a/python/m5/objects/PhysicalMemory.py
+++ /dev/null
@@ -1,8 +0,0 @@
-from m5 import *
-from FunctionalMemory import FunctionalMemory
-
-class PhysicalMemory(FunctionalMemory):
- type = 'PhysicalMemory'
- range = Param.AddrRange("Device Address")
- file = Param.String('', "memory mapped file")
- mmu = Param.MemoryController(Parent.any, "Memory Controller")
diff --git a/python/m5/objects/Process.py b/python/m5/objects/Process.py
deleted file mode 100644
index b4ccc1bec..000000000
--- a/python/m5/objects/Process.py
+++ /dev/null
@@ -1,17 +0,0 @@
-from m5 import *
-class Process(SimObject):
- type = 'Process'
- abstract = True
- output = Param.String('cout', 'filename for stdout/stderr')
-
-class LiveProcess(Process):
- type = 'LiveProcess'
- executable = Param.String('', "executable (overrides cmd[0] if set)")
- cmd = VectorParam.String("command line (executable plus arguments)")
- env = VectorParam.String('', "environment settings")
- input = Param.String('cin', "filename for stdin")
-
-class EioProcess(Process):
- type = 'EioProcess'
- chkpt = Param.String('', "EIO checkpoint file name (optional)")
- file = Param.String("EIO trace file name")
diff --git a/python/m5/objects/Root.py b/python/m5/objects/Root.py
deleted file mode 100644
index 23b13fc67..000000000
--- a/python/m5/objects/Root.py
+++ /dev/null
@@ -1,25 +0,0 @@
-from m5 import *
-from HierParams import HierParams
-from Serialize import Serialize
-from Statistics import Statistics
-from Trace import Trace
-from ExeTrace import ExecutionTrace
-
-class Root(SimObject):
- type = 'Root'
- clock = Param.RootClock('200MHz', "tick frequency")
- max_tick = Param.Tick('0', "maximum simulation ticks (0 = infinite)")
- progress_interval = Param.Tick('0',
- "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()
- serialize = Serialize()
diff --git a/python/m5/objects/SimpleDisk.py b/python/m5/objects/SimpleDisk.py
deleted file mode 100644
index 48448e6e5..000000000
--- a/python/m5/objects/SimpleDisk.py
+++ /dev/null
@@ -1,5 +0,0 @@
-from m5 import *
-class SimpleDisk(SimObject):
- type = 'SimpleDisk'
- disk = Param.DiskImage("Disk Image")
- physmem = Param.PhysicalMemory(Parent.any, "Physical Memory")
diff --git a/python/m5/objects/System.py b/python/m5/objects/System.py
deleted file mode 100644
index 5925cadf5..000000000
--- a/python/m5/objects/System.py
+++ /dev/null
@@ -1,21 +0,0 @@
-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")
-
-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
deleted file mode 100644
index 5425f421f..000000000
--- a/python/m5/objects/Tsunami.py
+++ /dev/null
@@ -1,27 +0,0 @@
-from m5 import *
-from Device import FooPioDevice
-from Platform import Platform
-
-class Tsunami(Platform):
- type = 'Tsunami'
- pciconfig = Param.PciConfigAll("PCI configuration")
- system = Param.System(Parent.any, "system")
-
-class TsunamiCChip(FooPioDevice):
- type = 'TsunamiCChip'
- tsunami = Param.Tsunami(Parent.any, "Tsunami")
-
-class IsaFake(FooPioDevice):
- type = 'IsaFake'
- size = Param.Addr("Size of address range")
-
-class TsunamiIO(FooPioDevice):
- 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):
- type = 'TsunamiPChip'
- tsunami = Param.Tsunami(Parent.any, "Tsunami")
diff --git a/python/m5/objects/Uart.py b/python/m5/objects/Uart.py
deleted file mode 100644
index 6eda5cdb3..000000000
--- a/python/m5/objects/Uart.py
+++ /dev/null
@@ -1,16 +0,0 @@
-from m5 import *
-from Device import PioDevice
-
-class Uart(PioDevice):
- type = 'Uart'
- abstract = True
- console = Param.SimConsole(Parent.any, "The console")
- size = Param.Addr(0x8, "Device size")
-
-class Uart8250(Uart):
- type = 'Uart8250'
-
-if build_env['ALPHA_TLASER']:
- class Uart8530(Uart):
- type = 'Uart8530'
-
diff --git a/sim/byteswap.hh b/sim/byteswap.hh
deleted file mode 100644
index c5d8801ab..000000000
--- a/sim/byteswap.hh
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * Copyright (c) 2004 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-//The purpose of this file is to provide endainness conversion utility
-//functions. Depending on the endianness of the guest system, either
-//the LittleEndianGuest or BigEndianGuest namespace is used.
-
-#ifndef __SIM_BYTE_SWAP_HH__
-#define __SIM_BYTE_SWAP_HH__
-
-#include "sim/host.hh"
-
-// This lets us figure out what the byte order of the host system is
-#if defined(linux)
-#include <endian.h>
-#else
-#include <machine/endian.h>
-#endif
-
-//These functions actually perform the swapping for parameters
-//of various bit lengths
-static inline uint64_t
-swap_byte64(uint64_t x)
-{
- return (uint64_t)((((uint64_t)(x) & 0xff) << 56) |
- ((uint64_t)(x) & 0xff00ULL) << 40 |
- ((uint64_t)(x) & 0xff0000ULL) << 24 |
- ((uint64_t)(x) & 0xff000000ULL) << 8 |
- ((uint64_t)(x) & 0xff00000000ULL) >> 8 |
- ((uint64_t)(x) & 0xff0000000000ULL) >> 24 |
- ((uint64_t)(x) & 0xff000000000000ULL) >> 40 |
- ((uint64_t)(x) & 0xff00000000000000ULL) >> 56) ;
-}
-
-static inline uint32_t
-swap_byte32(uint32_t x)
-{
- return (uint32_t)(((uint32_t)(x) & 0xff) << 24 |
- ((uint32_t)(x) & 0xff00) << 8 | ((uint32_t)(x) & 0xff0000) >> 8 |
- ((uint32_t)(x) & 0xff000000) >> 24);
-
-}
-
-static inline uint16_t
-swap_byte16(uint16_t x)
-{
- return (uint16_t)(((uint16_t)(x) & 0xff) << 8 |
- ((uint16_t)(x) & 0xff00) >> 8);
-}
-
-//This lets the compiler figure out how to call the swap_byte functions above
-//for different data types.
-static inline uint64_t swap_byte(uint64_t x) {return swap_byte64(x);}
-static inline int64_t swap_byte(int64_t x) {return swap_byte64((uint64_t)x);}
-static inline uint32_t swap_byte(uint32_t x) {return swap_byte32(x);}
-static inline int32_t swap_byte(int32_t x) {return swap_byte32((uint32_t)x);}
-#if defined(__APPLE__)
-static inline long swap_byte(long x) {return swap_byte32((long)x);}
-static inline unsigned long swap_byte(unsigned long x)
- { return swap_byte32((unsigned long)x);}
-#endif
-static inline uint16_t swap_byte(uint16_t x) {return swap_byte32(x);}
-static inline int16_t swap_byte(int16_t x) {return swap_byte16((uint16_t)x);}
-static inline uint8_t swap_byte(uint8_t x) {return x;}
-static inline int8_t swap_byte(int8_t x) {return x;}
-static inline double swap_byte(double x) {return swap_byte64((uint64_t)x);}
-static inline float swap_byte(float x) {return swap_byte32((uint32_t)x);}
-
-//The conversion functions with fixed endianness on both ends don't need to
-//be in a namespace
-template <typename T> static inline T betole(T value) {return swap_byte(value);}
-template <typename T> static inline T letobe(T value) {return swap_byte(value);}
-
-//For conversions not involving the guest system, we can define the functions
-//conditionally based on the BYTE_ORDER macro and outside of the namespaces
-#if BYTE_ORDER == BIG_ENDIAN
-template <typename T> static inline T htole(T value) {return swap_byte(value);}
-template <typename T> static inline T letoh(T value) {return swap_byte(value);}
-template <typename T> static inline T htobe(T value) {return value;}
-template <typename T> static inline T betoh(T value) {return value;}
-#elif BYTE_ORDER == LITTLE_ENDIAN
-template <typename T> static inline T htole(T value) {return value;}
-template <typename T> static inline T letoh(T value) {return value;}
-template <typename T> static inline T htobe(T value) {return swap_byte(value);}
-template <typename T> static inline T betoh(T value) {return swap_byte(value);}
-#else
- #error Invalid Endianess
-#endif
-
-namespace BigEndianGuest
-{
- template <typename T>
- static inline T gtole(T value) {return betole(value);}
- template <typename T>
- static inline T letog(T value) {return letobe(value);}
- template <typename T>
- static inline T gtobe(T value) {return value;}
- template <typename T>
- static inline T betog(T value) {return value;}
- template <typename T>
- static inline T htog(T value) {return htobe(value);}
- template <typename T>
- static inline T gtoh(T value) {return betoh(value);}
-}
-
-namespace LittleEndianGuest
-{
- template <typename T>
- static inline T gtole(T value) {return value;}
- template <typename T>
- static inline T letog(T value) {return value;}
- template <typename T>
- static inline T gtobe(T value) {return letobe(value);}
- template <typename T>
- static inline T betog(T value) {return betole(value);}
- template <typename T>
- static inline T htog(T value) {return htole(value);}
- template <typename T>
- static inline T gtoh(T value) {return letoh(value);}
-}
-#endif // __SIM_BYTE_SWAP_HH__
diff --git a/sim/eventq.cc b/sim/eventq.cc
deleted file mode 100644
index 0884db994..000000000
--- a/sim/eventq.cc
+++ /dev/null
@@ -1,259 +0,0 @@
-/*
- * Copyright (c) 2000-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 <assert.h>
-
-#include <iostream>
-#include <string>
-#include <sstream>
-#include <vector>
-
-#include "cpu/smt.hh"
-#include "base/misc.hh"
-
-#include "sim/eventq.hh"
-#include "base/trace.hh"
-#include "sim/root.hh"
-
-using namespace std;
-
-//
-// Main Event Queue
-//
-// Events on this queue are processed at the *beginning* of each
-// cycle, before the pipeline simulation is performed.
-//
-EventQueue mainEventQueue("MainEventQueue");
-
-void
-EventQueue::insert(Event *event)
-{
- if (head == NULL || event->when() < head->when() ||
- (event->when() == head->when() &&
- event->priority() <= head->priority())) {
- event->next = head;
- head = event;
- } else {
- Event *prev = head;
- Event *curr = head->next;
-
- while (curr) {
- if (event->when() <= curr->when() &&
- (event->when() < curr->when() ||
- event->priority() <= curr->priority()))
- break;
-
- prev = curr;
- curr = curr->next;
- }
-
- event->next = curr;
- prev->next = event;
- }
-}
-
-void
-EventQueue::remove(Event *event)
-{
- if (head == NULL)
- return;
-
- if (head == event){
- head = event->next;
- return;
- }
-
- Event *prev = head;
- Event *curr = head->next;
- while (curr && curr != event) {
- prev = curr;
- curr = curr->next;
- }
-
- if (curr == event)
- prev->next = curr->next;
-}
-
-void
-EventQueue::serviceOne()
-{
- Event *event = head;
- event->clearFlags(Event::Scheduled);
- head = event->next;
-
- // handle action
- if (!event->squashed())
- event->process();
- else
- event->clearFlags(Event::Squashed);
-
- if (event->getFlags(Event::AutoDelete) && !event->scheduled())
- delete event;
-}
-
-
-void
-Event::serialize(std::ostream &os)
-{
- SERIALIZE_SCALAR(_when);
- SERIALIZE_SCALAR(_priority);
- SERIALIZE_ENUM(_flags);
-}
-
-
-void
-Event::unserialize(Checkpoint *cp, const string &section)
-{
- if (scheduled())
- deschedule();
-
- UNSERIALIZE_SCALAR(_when);
- UNSERIALIZE_SCALAR(_priority);
-
- // need to see if original event was in a scheduled, unsquashed
- // state, but don't want to restore those flags in the current
- // object itself (since they aren't immediately true)
- UNSERIALIZE_ENUM(_flags);
- bool wasScheduled = (_flags & Scheduled) && !(_flags & Squashed);
- _flags &= ~(Squashed | Scheduled);
-
- if (wasScheduled) {
- DPRINTF(Config, "rescheduling at %d\n", _when);
- schedule(_when);
- }
-}
-
-void
-EventQueue::serialize(ostream &os)
-{
- std::list<Event *> eventPtrs;
-
- int numEvents = 0;
- Event *event = head;
- while (event) {
- if (event->getFlags(Event::AutoSerialize)) {
- eventPtrs.push_back(event);
- paramOut(os, csprintf("event%d", numEvents++), event->name());
- }
- event = event->next;
- }
-
- SERIALIZE_SCALAR(numEvents);
-
- for (std::list<Event *>::iterator it=eventPtrs.begin();
- it != eventPtrs.end(); ++it) {
- (*it)->nameOut(os);
- (*it)->serialize(os);
- }
-}
-
-void
-EventQueue::unserialize(Checkpoint *cp, const std::string &section)
-{
- int numEvents;
- UNSERIALIZE_SCALAR(numEvents);
-
- std::string eventName;
- for (int i = 0; i < numEvents; i++) {
- // get the pointer value associated with the event
- paramIn(cp, section, csprintf("event%d", i), eventName);
-
- // create the event based on its pointer value
- Serializable::create(cp, eventName);
- }
-}
-
-void
-EventQueue::dump()
-{
- cprintf("============================================================\n");
- cprintf("EventQueue Dump (cycle %d)\n", curTick);
- cprintf("------------------------------------------------------------\n");
-
- if (empty())
- cprintf("<No Events>\n");
- else {
- Event *event = head;
- while (event) {
- event->dump();
- event = event->next;
- }
- }
-
- cprintf("============================================================\n");
-}
-
-extern "C"
-void
-dumpMainQueue()
-{
- mainEventQueue.dump();
-}
-
-
-const char *
-Event::description()
-{
- return "generic";
-}
-
-#if TRACING_ON
-void
-Event::trace(const char *action)
-{
- // This DPRINTF is unconditional because calls to this function
- // are protected by an 'if (DTRACE(Event))' in the inlined Event
- // methods.
- //
- // This is just a default implementation for derived classes where
- // it's not worth doing anything special. If you want to put a
- // more informative message in the trace, override this method on
- // the particular subclass where you have the information that
- // needs to be printed.
- DPRINTFN("%s event %s @ %d\n", description(), action, when());
-}
-#endif
-
-void
-Event::dump()
-{
- cprintf("Event (%s)\n", description());
- cprintf("Flags: %#x\n", _flags);
-#if TRACING_ON
- cprintf("Created: %d\n", when_created);
-#endif
- if (scheduled()) {
-#if TRACING_ON
- cprintf("Scheduled at %d\n", when_scheduled);
-#endif
- cprintf("Scheduled for %d, priority %d\n", when(), _priority);
- }
- else {
- cprintf("Not Scheduled\n");
- }
-}
diff --git a/sim/faults.cc b/sim/faults.cc
deleted file mode 100644
index 701384989..000000000
--- a/sim/faults.cc
+++ /dev/null
@@ -1,46 +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 "sim/faults.hh"
-#include "cpu/exec_context.hh"
-#include "cpu/base.hh"
-
-#if !FULL_SYSTEM
-void FaultBase::invoke(ExecContext * xc)
-{
- fatal("fault (%s) detected @ PC 0x%08p", name(), xc->readPC());
-}
-#else
-void FaultBase::invoke(ExecContext * xc)
-{
- DPRINTF(Fault, "Fault %s at PC: %#x\n", name(), xc->readPC());
- xc->getCpuPtr()->recordEvent(csprintf("Fault %s", name()));
-
- assert(!xc->misspeculating());
-}
-#endif
diff --git a/sim/faults.hh b/sim/faults.hh
deleted file mode 100644
index 18601e8f1..000000000
--- a/sim/faults.hh
+++ /dev/null
@@ -1,67 +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.
- */
-
-#ifndef __FAULTS_HH__
-#define __FAULTS_HH__
-
-#include "base/refcnt.hh"
-#include "sim/stats.hh"
-#include "config/full_system.hh"
-
-class ExecContext;
-class FaultBase;
-typedef RefCountingPtr<FaultBase> Fault;
-
-typedef const char * FaultName;
-typedef Stats::Scalar<> FaultStat;
-
-// Each class has it's name statically define in _name,
-// and has a virtual function to access it's name.
-// The function is necessary because otherwise, all objects
-// which are being accessed cast as a FaultBase * (namely
-// all faults returned using the Fault type) will use the
-// generic FaultBase name.
-
-class FaultBase : public RefCounted
-{
- public:
- virtual FaultName name() = 0;
-#if FULL_SYSTEM
- virtual void invoke(ExecContext * xc);
-#else
- virtual void invoke(ExecContext * xc);
-#endif
-// template<typename T>
-// bool isA() {return dynamic_cast<T *>(this);}
- virtual bool isMachineCheckFault() {return false;}
- virtual bool isAlignmentFault() {return false;}
-};
-
-FaultBase * const NoFault = 0;
-
-#endif // __FAULTS_HH__
diff --git a/sim/host.hh b/sim/host.hh
deleted file mode 100644
index f7e64f23c..000000000
--- a/sim/host.hh
+++ /dev/null
@@ -1,65 +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.
- */
-
-/**
- * @file
- * Defines host-dependent types:
- * Counter, Tick, and (indirectly) {int,uint}{8,16,32,64}_t.
- */
-
-#ifndef __HOST_HH__
-#define __HOST_HH__
-
-#include <inttypes.h>
-
-/** uint64_t constant */
-#define ULL(N) ((uint64_t)N##ULL)
-/** int64_t constant */
-#define LL(N) (((int64_t)N##LL)
-
-/** Statistics counter type. Not much excuse for not using a 64-bit
- * integer here, but if you're desperate and only run short
- * simulations you could make this 32 bits.
- */
-typedef int64_t Counter;
-
-/**
- * Clock cycle count type.
- * @note using an unsigned breaks the cache.
- */
-typedef int64_t Tick;
-
-/**
- * Address type
- * This will probably be moved somewhere else in the near future.
- * This should be at least as big as the biggest address width in use
- * in the system, which will probably be 64 bits.
- */
-typedef uint64_t Addr;
-
-#endif // __HOST_H__
diff --git a/sim/main.cc b/sim/main.cc
deleted file mode 100644
index 6f6143506..000000000
--- a/sim/main.cc
+++ /dev/null
@@ -1,429 +0,0 @@
-/*
- * Copyright (c) 2000-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 sim/main.cc
-///
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <errno.h>
-#include <libgen.h>
-#include <stdlib.h>
-#include <signal.h>
-
-#include <list>
-#include <string>
-#include <vector>
-
-#include "base/copyright.hh"
-#include "base/embedfile.hh"
-#include "base/inifile.hh"
-#include "base/misc.hh"
-#include "base/output.hh"
-#include "base/pollevent.hh"
-#include "base/statistics.hh"
-#include "base/str.hh"
-#include "base/time.hh"
-#include "cpu/base.hh"
-#include "cpu/smt.hh"
-#include "python/pyconfig.hh"
-#include "sim/async.hh"
-#include "sim/builder.hh"
-#include "sim/configfile.hh"
-#include "sim/host.hh"
-#include "sim/sim_events.hh"
-#include "sim/sim_exit.hh"
-#include "sim/sim_object.hh"
-#include "sim/stat_control.hh"
-#include "sim/stats.hh"
-#include "sim/root.hh"
-
-using namespace std;
-
-// See async.h.
-volatile bool async_event = false;
-volatile bool async_dump = false;
-volatile bool async_dumpreset = false;
-volatile bool async_exit = false;
-volatile bool async_io = false;
-volatile bool async_alarm = false;
-
-/// Stats signal handler.
-void
-dumpStatsHandler(int sigtype)
-{
- async_event = true;
- async_dump = true;
-}
-
-void
-dumprstStatsHandler(int sigtype)
-{
- async_event = true;
- async_dumpreset = true;
-}
-
-/// Exit signal handler.
-void
-exitNowHandler(int sigtype)
-{
- async_event = true;
- async_exit = true;
-}
-
-/// Abort signal handler.
-void
-abortHandler(int sigtype)
-{
- cerr << "Program aborted at cycle " << curTick << endl;
-
-#if TRACING_ON
- // dump trace buffer, if there is one
- Trace::theLog.dump(cerr);
-#endif
-}
-
-/// Simulator executable name
-char *myProgName = "";
-
-/// Show brief help message.
-void
-showBriefHelp(ostream &out)
-{
- char *prog = basename(myProgName);
-
- ccprintf(out, "Usage:\n");
- ccprintf(out,
-"%s [-d <dir>] [-E <var>[=<val>]] [-I <dir>] [-P <python>]\n"
-" [--<var>=<val>] <config file>\n"
-"\n"
-" -d set the output directory to <dir>\n"
-" -E set the environment variable <var> to <val> (or 'True')\n"
-" -I add the directory <dir> to python's path\n"
-" -P execute <python> directly in the configuration\n"
-" --var=val set the python variable <var> to '<val>'\n"
-" <configfile> config file name (ends in .py)\n\n",
- prog);
-
- ccprintf(out, "%s -X\n -X extract embedded files\n\n", prog);
- ccprintf(out, "%s -h\n -h print short help\n\n", prog);
-}
-
-/// Print welcome message.
-void
-sayHello(ostream &out)
-{
- extern const char *compileDate; // from date.cc
-
- ccprintf(out, "M5 Simulator System\n");
- // display copyright
- ccprintf(out, "%s\n", briefCopyright);
- ccprintf(out, "M5 compiled on %d\n", compileDate);
-
- char *host = getenv("HOSTNAME");
- if (!host)
- host = getenv("HOST");
-
- if (host)
- ccprintf(out, "M5 executing on %s\n", host);
-
- ccprintf(out, "M5 simulation started %s\n", Time::start);
-}
-
-///
-/// Echo the command line for posterity in such a way that it can be
-/// used to rerun the same simulation (given the same .ini files).
-///
-void
-echoCommandLine(int argc, char **argv, ostream &out)
-{
- out << "command line: " << argv[0];
- for (int i = 1; i < argc; i++) {
- string arg(argv[i]);
-
- out << ' ';
-
- // If the arg contains spaces, we need to quote it.
- // The rest of this is overkill to make it look purty.
-
- // print dashes first outside quotes
- int non_dash_pos = arg.find_first_not_of("-");
- out << arg.substr(0, non_dash_pos); // print dashes
- string body = arg.substr(non_dash_pos); // the rest
-
- // if it's an assignment, handle the lhs & rhs separately
- int eq_pos = body.find("=");
- if (eq_pos == string::npos) {
- out << quote(body);
- }
- else {
- string lhs(body.substr(0, eq_pos));
- string rhs(body.substr(eq_pos + 1));
-
- out << quote(lhs) << "=" << quote(rhs);
- }
- }
- out << endl << endl;
-}
-
-char *
-getOptionString(int &index, int argc, char **argv)
-{
- char *option = argv[index] + 2;
- if (*option != '\0')
- return option;
-
- // We didn't find an argument, it must be in the next variable.
- if (++index >= argc)
- panic("option string for option '%s' not found", argv[index - 1]);
-
- return argv[index];
-}
-
-int
-main(int argc, char **argv)
-{
- // Save off program name
- myProgName = argv[0];
-
- signal(SIGFPE, SIG_IGN); // may occur on misspeculated paths
- signal(SIGTRAP, SIG_IGN);
- signal(SIGUSR1, dumpStatsHandler); // dump intermediate stats
- signal(SIGUSR2, dumprstStatsHandler); // dump and reset stats
- signal(SIGINT, exitNowHandler); // dump final stats and exit
- signal(SIGABRT, abortHandler);
-
- bool configfile_found = false;
- PythonConfig pyconfig;
- string outdir;
-
- if (argc < 2) {
- showBriefHelp(cerr);
- exit(1);
- }
-
- sayHello(cerr);
-
- // Parse command-line options.
- // Since most of the complex options are handled through the
- // config database, we don't mess with getopts, and just parse
- // manually.
- for (int i = 1; i < argc; ++i) {
- char *arg_str = argv[i];
-
- // if arg starts with '--', parse as a special python option
- // of the format --<python var>=<string value>, if the arg
- // starts with '-', it should be a simulator option with a
- // format similar to getopt. In any other case, treat the
- // option as a configuration file name and load it.
- if (arg_str[0] == '-' && arg_str[1] == '-') {
- string str = &arg_str[2];
- string var, val;
-
- if (!split_first(str, var, val, '='))
- panic("Could not parse configuration argument '%s'\n"
- "Expecting --<variable>=<value>\n", arg_str);
-
- pyconfig.setVariable(var, val);
- } else if (arg_str[0] == '-') {
- char *option;
- string var, val;
-
- // switch on second char
- switch (arg_str[1]) {
- case 'd':
- outdir = getOptionString(i, argc, argv);
- break;
-
- case 'h':
- showBriefHelp(cerr);
- exit(1);
-
- case 'E':
- option = getOptionString(i, argc, argv);
- if (!split_first(option, var, val, '='))
- val = "True";
-
- if (setenv(var.c_str(), val.c_str(), true) == -1)
- panic("setenv: %s\n", strerror(errno));
- break;
-
- case 'I':
- option = getOptionString(i, argc, argv);
- pyconfig.addPath(option);
- break;
-
- case 'P':
- option = getOptionString(i, argc, argv);
- pyconfig.writeLine(option);
- break;
-
- case 'X': {
- list<EmbedFile> lst;
- EmbedMap::all(lst);
- list<EmbedFile>::iterator i = lst.begin();
- list<EmbedFile>::iterator end = lst.end();
-
- while (i != end) {
- cprintf("Embedded File: %s\n", i->name);
- cout.write(i->data, i->length);
- ++i;
- }
-
- return 0;
- }
-
- default:
- showBriefHelp(cerr);
- panic("invalid argument '%s'\n", arg_str);
- }
- } else {
- string file(arg_str);
- string base, ext;
-
- if (!split_last(file, base, ext, '.') || ext != "py")
- panic("Config file '%s' must end in '.py'\n", file);
-
- pyconfig.load(file);
- configfile_found = true;
- }
- }
-
- if (outdir.empty()) {
- char *env = getenv("OUTPUT_DIR");
- outdir = env ? env : ".";
- }
-
- simout.setDirectory(outdir);
-
- char *env = getenv("CONFIG_OUTPUT");
- if (!env)
- env = "config.out";
- configStream = simout.find(env);
-
- if (!configfile_found)
- panic("no configuration file specified!");
-
- // The configuration database is now complete; start processing it.
- IniFile inifile;
- if (!pyconfig.output(inifile))
- panic("Error processing python code");
-
- // Initialize statistics database
- Stats::InitSimStats();
-
- // Now process the configuration hierarchy and create the SimObjects.
- ConfigHierarchy configHierarchy(inifile);
- configHierarchy.build();
- configHierarchy.createSimObjects();
-
- // Parse and check all non-config-hierarchy parameters.
- ParamContext::parseAllContexts(inifile);
- ParamContext::checkAllContexts();
-
- // Print hello message to stats file if it's actually a file. If
- // it's not (i.e. it's cout or cerr) then we already did it above.
- if (simout.isFile(*outputStream))
- sayHello(*outputStream);
-
- // Echo command line and all parameter settings to stats file as well.
- echoCommandLine(argc, argv, *outputStream);
- ParamContext::showAllContexts(*configStream);
-
- // Do a second pass to finish initializing the sim objects
- SimObject::initAll();
-
- // Restore checkpointed state, if any.
- configHierarchy.unserializeSimObjects();
-
- // Done processing the configuration database.
- // Check for unreferenced entries.
- if (inifile.printUnreferenced())
- panic("unreferenced sections/entries in the intermediate ini file");
-
- SimObject::regAllStats();
-
- // uncomment the following to get PC-based execution-time profile
-#ifdef DO_PROFILE
- init_profile((char *)&_init, (char *)&_fini);
-#endif
-
- // Check to make sure that the stats package is properly initialized
- Stats::check();
-
- // Reset to put the stats in a consistent state.
- Stats::reset();
-
- warn("Entering event queue. Starting simulation...\n");
- SimStartup();
- while (!mainEventQueue.empty()) {
- assert(curTick <= mainEventQueue.nextTick() &&
- "event scheduled in the past");
-
- // forward current cycle to the time of the first event on the
- // queue
- curTick = mainEventQueue.nextTick();
- mainEventQueue.serviceOne();
-
- if (async_event) {
- async_event = false;
- if (async_dump) {
- async_dump = false;
-
- using namespace Stats;
- SetupEvent(Dump, curTick);
- }
-
- if (async_dumpreset) {
- async_dumpreset = false;
-
- using namespace Stats;
- SetupEvent(Dump | Reset, curTick);
- }
-
- if (async_exit) {
- async_exit = false;
- new SimExitEvent("User requested STOP");
- }
-
- if (async_io || async_alarm) {
- async_io = false;
- async_alarm = false;
- pollQueue.service();
- }
- }
- }
-
- // This should never happen... every conceivable way for the
- // simulation to terminate (hit max cycles/insts, signal,
- // simulated system halts/exits) generates an exit event, so we
- // should never run out of events on the queue.
- exitNow("no events on event loop! All CPUs must be idle.", 1);
-
- return 0;
-}
diff --git a/sim/param.cc b/sim/param.cc
deleted file mode 100644
index bc81881d3..000000000
--- a/sim/param.cc
+++ /dev/null
@@ -1,794 +0,0 @@
-/*
- * 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 <algorithm>
-#include <cassert>
-#include <cstdio>
-#include <list>
-#include <string>
-#include <vector>
-
-#include "base/inifile.hh"
-#include "base/misc.hh"
-#include "base/range.hh"
-#include "base/str.hh"
-#include "base/trace.hh"
-#include "sim/config_node.hh"
-#include "sim/configfile.hh"
-#include "sim/param.hh"
-#include "sim/sim_object.hh"
-
-using namespace std;
-
-
-////////////////////////////////////////////////////////////////////////
-//
-// BaseParam member definitions
-//
-////////////////////////////////////////////////////////////////////////
-
-void
-BaseParam::die(const string &err) const
-{
- context->printErrorProlog(cerr);
- cerr << " parameter '" << name << "': "
- << err << endl;
- abort();
-}
-
-
-////////////////////////////////////////////////////////////////////////
-//
-// Param<T> and VectorParam<T> member definitions
-//
-// We implement parsing & displaying values for various parameter
-// types T using a set of overloaded functions:
-//
-// - parseParam(string s, T &value) parses s into value
-// - showParam(ostream &os, T &value) displays value on os
-//
-// By making these independent functions, we can reuse the same code
-// for type T in both Param<T> and VectorParam<T>.
-//
-// For enum types, the parseParam function requires additional
-// arguments, in which case we must specialize the Param<T>::parse and
-// VectorParam<T>::parse calls as well.
-//
-// Type-specific instances come first, followed by more generic
-// templated versions and their instantiations.
-//
-////////////////////////////////////////////////////////////////////////
-
-//
-// The base implementations use to_number for parsing and '<<' for
-// displaying, suitable for integer types.
-//
-template <class T>
-bool
-parseParam(const string &s, T &value)
-{
- return to_number(s, value);
-}
-
-template <class T>
-void
-showParam(ostream &os, T const &value)
-{
- os << value;
-}
-
-//
-// Template specializations:
-// - char (8-bit integer)
-// - floating-point types
-// - bool
-// - string
-//
-
-// Treat 8-bit ints (chars) as ints on output, not as chars
-template <>
-void
-showParam(ostream &os, const char &value)
-{
- os << (int)value;
-}
-
-
-template <>
-void
-showParam(ostream &os, const unsigned char &value)
-{
- os << (unsigned int)value;
-}
-
-
-// Use sscanf() for FP types as to_number() only handles integers
-template <>
-bool
-parseParam(const string &s, float &value)
-{
- return (sscanf(s.c_str(), "%f", &value) == 1);
-}
-
-template <>
-bool
-parseParam(const string &s, double &value)
-{
- return (sscanf(s.c_str(), "%lf", &value) == 1);
-}
-
-// Be flexible about what we take for bool
-template <>
-bool
-parseParam(const string &s, bool &value)
-{
- const string &ls = to_lower(s);
-
- if (ls == "true" || ls == "t" || ls == "yes" || ls == "y" || ls == "1") {
- value = true;
- return true;
- }
-
- if (ls == "false" || ls == "f" || ls == "no" || ls == "n" || ls == "0") {
- value = false;
- return true;
- }
-
- return false;
-}
-
-// Display bools as strings
-template <>
-void
-showParam(ostream &os, const bool &value)
-{
- os << (value ? "true" : "false");
-}
-
-
-// String requires no processing to speak of
-template <>
-bool
-parseParam(const string &s, string &value)
-{
- value = s;
- return true;
-}
-
-template <>
-bool
-parseParam(const string &s, Range<uint32_t> &value)
-{
- value = s;
- return value.valid();
-}
-
-template <>
-bool
-parseParam(const string &s, Range<uint64_t> &value)
-{
- value = s;
- return value.valid();
-}
-
-//
-// End of parseParam/showParam definitions. Now we move on to
-// incorporate them into the Param/VectorParam parse() and showValue()
-// methods.
-//
-
-// These definitions for Param<T>::parse and VectorParam<T>::parse
-// work for any type for which parseParam() takes only two arguments
-// (i.e., all the fundamental types like int, bool, etc.), thanks to
-// overloading.
-template <class T>
-void
-Param<T>::parse(const string &s)
-{
- if (parseParam(s, value)) {
- wasSet = true;
- }
- else {
- string err("could not parse \"");
-
- err += s;
- err += "\"";
-
- die(err);
- }
-}
-
-template <class T>
-void
-VectorParam<T>::parse(const string &s)
-{
- if (s.empty()) {
- wasSet = true;
- return;
- }
-
- vector<string> tokens;
-
- tokenize(tokens, s, ' ');
-
- value.resize(tokens.size());
-
- for (int i = 0; i < tokens.size(); i++) {
- // need to parse into local variable to handle vector<bool>,
- // for which operator[] returns a special reference class
- // that's not the same as 'bool&', (since it's a packed
- // vector)
- T scalar_value;
- if (!parseParam(tokens[i], scalar_value)) {
- string err("could not parse \"");
-
- err += s;
- err += "\"";
-
- die(err);
- }
-
- // assign parsed value to vector
- value[i] = scalar_value;
- }
-
- wasSet = true;
-}
-
-// These definitions for Param<T>::showValue() and
-// VectorParam<T>::showValue() work for any type where showParam()
-// takes only two arguments (i.e., everything but the SimpleEnum and
-// MappedEnum classes).
-template <class T>
-void
-Param<T>::showValue(ostream &os) const
-{
- showParam(os, value);
-}
-
-template <class T>
-void
-VectorParam<T>::showValue(ostream &os) const
-{
- for (int i = 0; i < value.size(); i++) {
- if (i != 0) {
- os << " ";
- }
- showParam(os, value[i]);
- }
-}
-
-
-#ifdef INSURE_BUILD
-#define INSTANTIATE_PARAM_TEMPLATES(type, typestr) \
-void Param<type>::showType(ostream &os) const { os << typestr; } \
-void VectorParam<type>::showType(ostream &os) const { \
- os << "vector of " << typestr; \
-} \
-template Param<type>; \
-template VectorParam<type>;
-
-#else
-// instantiate all four methods (parse/show, scalar/vector) for basic
-// types that can use the above templates
-#define INSTANTIATE_PARAM_TEMPLATES(type, typestr) \
-template bool parseParam<type>(const string &s, type &value); \
-template void showParam<type>(ostream &os, type const &value); \
-template void Param<type>::parse(const string &); \
-template void VectorParam<type>::parse(const string &); \
-template void Param<type>::showValue(ostream &) const; \
-template void VectorParam<type>::showValue(ostream &) const; \
-template <> void Param<type>::showType(ostream &os) const { os << typestr; } \
-template <> void VectorParam<type>::showType(ostream &os) const { \
- os << "vector of " << typestr; \
-}
-#endif
-
-INSTANTIATE_PARAM_TEMPLATES(unsigned long long, "ull")
-INSTANTIATE_PARAM_TEMPLATES(signed long long, "sll")
-INSTANTIATE_PARAM_TEMPLATES(unsigned long, "uns long")
-INSTANTIATE_PARAM_TEMPLATES(signed long, "long")
-INSTANTIATE_PARAM_TEMPLATES(unsigned int, "uns")
-INSTANTIATE_PARAM_TEMPLATES(signed int, "int")
-INSTANTIATE_PARAM_TEMPLATES(unsigned short, "uns short")
-INSTANTIATE_PARAM_TEMPLATES(signed short, "short")
-INSTANTIATE_PARAM_TEMPLATES(unsigned char, "uns char")
-INSTANTIATE_PARAM_TEMPLATES(signed char, "char")
-
-INSTANTIATE_PARAM_TEMPLATES(float, "float")
-INSTANTIATE_PARAM_TEMPLATES(double, "double")
-
-INSTANTIATE_PARAM_TEMPLATES(bool, "bool")
-INSTANTIATE_PARAM_TEMPLATES(string, "string")
-
-INSTANTIATE_PARAM_TEMPLATES(Range<uint64_t>, "uint64 range")
-INSTANTIATE_PARAM_TEMPLATES(Range<uint32_t>, "uint32 range")
-
-#undef INSTANTIATE_PARAM_TEMPLATES
-
-//
-// SimpleEnumParam & MappedEnumParam must specialize their parse(),
-// showValue(), and showType() methods.
-//
-
-//
-// SimpleEnumParam & SimpleEnumVectorParam
-//
-bool
-parseEnumParam(const char *const *map, const int num_values,
- const string &s, int &value)
-{
- for (int i = 0; i < num_values; ++i) {
- if (s == map[i]) {
- value = i;
- return true;
- }
- }
-
- return false;
-}
-
-void
-showEnumParam(ostream &os,
- const char *const *map, const int num_values,
- int value)
-{
- assert(0 <= value && value < num_values);
- os << map[value];
-}
-
-void
-showEnumType(ostream &os,
- const char *const *map, const int num_values)
-{
- os << "{" << map[0];
- for (int i = 1; i < num_values; ++i)
- os << "," << map[i];
-
- os << "}";
-}
-
-
-//
-// MappedEnumParam & MappedEnumVectorParam
-//
-bool
-parseEnumParam(const EnumParamMap *map, const int num_values,
- const string &s, int &value)
-{
- for (int i = 0; i < num_values; ++i) {
- if (s == map[i].name) {
- value = map[i].value;
- return true;
- }
- }
-
- return false;
-}
-
-void
-showEnumParam(ostream &os,
- const EnumParamMap *map, const int num_values,
- int value)
-{
- for (int i = 0; i < num_values; ++i) {
- if (value == map[i].value) {
- os << map[i].name;
- return;
- }
- }
-
- // if we can't find a reverse mapping just print the int value
- os << value;
-}
-
-void
-showEnumType(ostream &os,
- const EnumParamMap *map, const int num_values)
-{
- os << "{" << map[0].name;
- for (int i = 1; i < num_values; ++i)
- os << "," << map[i].name;
-
- os << "}";
-}
-
-
-template <class Map>
-void
-EnumParam<Map>::parse(const string &s)
-{
- if (parseEnumParam(map, num_values, s, value)) {
- wasSet = true;
- } else {
- string err("no match for enum string \"");
-
- err += s;
- err += "\"";
-
- die(err);
- }
-}
-
-template <class Map>
-void
-EnumVectorParam<Map>::parse(const string &s)
-{
- vector<string> tokens;
-
- if (s.empty()) {
- wasSet = true;
- return;
- }
-
- tokenize(tokens, s, ' ');
-
- value.resize(tokens.size());
-
- for (int i = 0; i < tokens.size(); i++) {
- if (!parseEnumParam(map, num_values, tokens[i], value[i])) {
- string err("no match for enum string \"");
-
- err += s;
- err += "\"";
-
- die(err);
- }
- }
-
- wasSet = true;
-}
-
-template <class Map>
-void
-EnumParam<Map>::showValue(ostream &os) const
-{
- showEnumParam(os, map, num_values, value);
-}
-
-template <class Map>
-void
-EnumVectorParam<Map>::showValue(ostream &os) const
-{
- for (int i = 0; i < value.size(); i++) {
- if (i != 0) {
- os << " ";
- }
- showEnumParam(os, map, num_values, value[i]);
- }
-}
-
-template <class Map>
-void
-EnumParam<Map>::showType(ostream &os) const
-{
- showEnumType(os, map, num_values);
-}
-
-template <class Map>
-void
-EnumVectorParam<Map>::showType(ostream &os) const
-{
- os << "vector of";
- showEnumType(os, map, num_values);
-}
-
-template class EnumParam<const char *>;
-template class EnumVectorParam<const char *>;
-
-template class EnumParam<EnumParamMap>;
-template class EnumVectorParam<EnumParamMap>;
-
-////////////////////////////////////////////////////////////////////////
-//
-// SimObjectBaseParam methods
-//
-////////////////////////////////////////////////////////////////////////
-
-bool
-parseSimObjectParam(ParamContext *context, const string &s, SimObject *&value)
-{
- SimObject *obj;
-
- if (to_lower(s) == "null") {
- // explicitly set to null by user; assume that's OK
- obj = NULL;
- }
- else {
- obj = context->resolveSimObject(s);
-
- if (obj == NULL)
- return false;
- }
-
- value = obj;
- return true;
-}
-
-
-void
-SimObjectBaseParam::showValue(ostream &os, SimObject *value) const
-{
- os << (value ? value->name() : "null");
-}
-
-void
-SimObjectBaseParam::parse(const string &s, SimObject *&value)
-{
- if (parseSimObjectParam(context, s, value)) {
- wasSet = true;
- }
- else {
- string err("could not resolve object name \"");
-
- err += s;
- err += "\"";
-
- die(err);
- }
-}
-
-void
-SimObjectBaseParam::parse(const string &s, vector<SimObject *>&value)
-{
- vector<string> tokens;
-
- tokenize(tokens, s, ' ');
-
- value.resize(tokens.size());
-
- for (int i = 0; i < tokens.size(); i++) {
- if (!parseSimObjectParam(context, tokens[i], value[i])) {
- string err("could not resolve object name \"");
-
- err += s;
- err += "\"";
-
- die(err);
- }
- }
-
- wasSet = true;
-}
-
-////////////////////////////////////////////////////////////////////////
-//
-// ParamContext member definitions
-//
-////////////////////////////////////////////////////////////////////////
-
-list<ParamContext *> *ParamContext::ctxList = NULL;
-
-ParamContext::ParamContext(const string &_iniSection, InitPhase _initPhase)
- : iniFilePtr(NULL), // initialized on call to parseParams()
- iniSection(_iniSection), paramList(NULL),
- initPhase(_initPhase)
-{
- // Put this context on global list for initialization
- if (initPhase != NoAutoInit) {
- if (ctxList == NULL)
- ctxList = new list<ParamContext *>();
-
- // keep list sorted by ascending initPhase values
- list<ParamContext *>::iterator i = ctxList->begin();
- list<ParamContext *>::iterator end = ctxList->end();
- for (; i != end; ++i) {
- if (initPhase <= (*i)->initPhase) {
- // found where we want to insert
- break;
- }
- }
- // (fall through case: insert at end)
- ctxList->insert(i, this);
- }
-}
-
-
-void
-ParamContext::addParam(BaseParam *param)
-{
- getParamList()->push_back(param);
-}
-
-
-void
-ParamContext::parseParams(IniFile &iniFile)
-{
- iniFilePtr = &iniFile; // set object member
-
- ParamList::iterator i;
-
- for (i = getParamList()->begin(); i != getParamList()->end(); ++i) {
- string string_value;
-
- if (iniFile.find(iniSection, (*i)->name, string_value))
- (*i)->parse(string_value);
- }
-}
-
-
-// Check parameter values for validity & consistency. Default
-// implementation is no-op; derive subclass & override to add
-// actual functionality here.
-void
-ParamContext::checkParams()
-{
- // nada
-}
-
-
-// Clean up context-related objects at end of execution. Default
-// implementation is no-op; derive subclass & override to add actual
-// functionality here.
-void
-ParamContext::cleanup()
-{
- // nada
-}
-
-
-void
-ParamContext::describeParams(ostream &os)
-{
- ParamList::iterator i;
-
- for (i = getParamList()->begin(); i != getParamList()->end(); ++i) {
- BaseParam *p = *i;
-
- os << p->name << " (";
- p->showType(os);
- os << "): " << p->description << "\n";
- }
-}
-
-
-
-void
-ParamContext::showParams(ostream &os)
-{
- ParamList::iterator i;
-
- for (i = getParamList()->begin(); i != getParamList()->end(); ++i) {
- BaseParam *p = *i;
-
- if (p->isValid()) {
- os << p->name << "=";
- p->showValue(os);
- os << endl;
- }
- else {
- os << "// "<< p->name << " not specified" << endl;
- }
- }
-}
-
-
-void
-ParamContext::printErrorProlog(ostream &os)
-{
- os << "Parameter error in section [" << iniSection << "]: " << endl;
-}
-
-//
-// Resolve an object name to a SimObject pointer. The object will be
-// created as a side-effect if necessary. If the name contains a
-// colon (e.g., "iq:IQ"), then the object is local (invisible to
-// outside this context). If there is no colon, the name needs to be
-// resolved through the configuration hierarchy (only possible for
-// SimObjectBuilder objects, which return non-NULL for configNode()).
-//
-SimObject *
-ParamContext::resolveSimObject(const string &name)
-{
- ConfigNode *n = getConfigNode();
- return n ? n->resolveSimObject(name) : NULL;
-}
-
-
-//
-// static method: call parseParams() on all registered contexts
-//
-void
-ParamContext::parseAllContexts(IniFile &iniFile)
-{
- list<ParamContext *>::iterator iter;
-
- for (iter = ctxList->begin(); iter != ctxList->end(); ++iter) {
- ParamContext *pc = *iter;
-
- pc->parseParams(iniFile);
- }
-}
-
-
-//
-// static method: call checkParams() on all registered contexts
-//
-void
-ParamContext::checkAllContexts()
-{
- list<ParamContext *>::iterator iter;
-
- for (iter = ctxList->begin(); iter != ctxList->end(); ++iter) {
- ParamContext *pc = *iter;
-
- pc->checkParams();
- }
-}
-
-
-//
-// static method: call showParams() on all registered contexts
-//
-void
-ParamContext::showAllContexts(ostream &os)
-{
- list<ParamContext *>::iterator iter;
-
- for (iter = ctxList->begin(); iter != ctxList->end(); ++iter) {
- ParamContext *pc = *iter;
-
- os << "[" << pc->iniSection << "]" << endl;
- pc->showParams(os);
- os << endl;
- }
-}
-
-
-//
-// static method: call cleanup() on all registered contexts
-//
-void
-ParamContext::cleanupAllContexts()
-{
- list<ParamContext *>::iterator iter;
-
- for (iter = ctxList->begin(); iter != ctxList->end(); ++iter) {
- ParamContext *pc = *iter;
-
- pc->cleanup();
- }
-}
-
-
-//
-// static method: call describeParams() on all registered contexts
-//
-void
-ParamContext::describeAllContexts(ostream &os)
-{
- list<ParamContext *>::iterator iter;
-
- for (iter = ctxList->begin(); iter != ctxList->end(); ++iter) {
- ParamContext *pc = *iter;
-
- os << "[" << pc->iniSection << "]\n";
- pc->describeParams(os);
- os << endl;
- }
-}
diff --git a/sim/process.cc b/sim/process.cc
deleted file mode 100644
index a84a4f7ba..000000000
--- a/sim/process.cc
+++ /dev/null
@@ -1,446 +0,0 @@
-/*
- * Copyright (c) 2001-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <unistd.h>
-#include <fcntl.h>
-
-#include <cstdio>
-#include <string>
-
-#include "base/intmath.hh"
-#include "base/loader/object_file.hh"
-#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 "sim/builder.hh"
-#include "sim/process.hh"
-#include "sim/stats.hh"
-#include "sim/syscall_emul.hh"
-
-#include "arch/process.hh"
-
-using namespace std;
-using namespace TheISA;
-
-//
-// The purpose of this code is to fake the loader & syscall mechanism
-// when there's no OS: thus there's no resone to use it in FULL_SYSTEM
-// mode when we do have an OS
-//
-#if FULL_SYSTEM
-#error "process.cc not compatible with FULL_SYSTEM"
-#endif
-
-// current number of allocated processes
-int num_processes = 0;
-
-Process::Process(const string &nm,
- int stdin_fd, // initial I/O descriptors
- int stdout_fd,
- int stderr_fd)
- : SimObject(nm)
-{
- // 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;
- fd_map[STDERR_FILENO] = stderr_fd;
-
- // mark remaining fds as free
- for (int i = 3; i <= MAX_FD; ++i) {
- fd_map[i] = -1;
- }
-
- mmap_start = mmap_end = 0;
- nxm_start = nxm_end = 0;
- // other parameters will be initialized when the program is loaded
-}
-
-void
-Process::regStats()
-{
- using namespace Stats;
-
- num_syscalls
- .name(name() + ".PROG:num_syscalls")
- .desc("Number of system calls")
- ;
-}
-
-//
-// static helper functions
-//
-int
-Process::openInputFile(const string &filename)
-{
- int fd = open(filename.c_str(), O_RDONLY);
-
- if (fd == -1) {
- perror(NULL);
- cerr << "unable to open \"" << filename << "\" for reading\n";
- fatal("can't open input file");
- }
-
- return fd;
-}
-
-
-int
-Process::openOutputFile(const string &filename)
-{
- int fd = open(filename.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0774);
-
- if (fd == -1) {
- perror(NULL);
- cerr << "unable to open \"" << filename << "\" for writing\n";
- fatal("can't open output file");
- }
-
- return fd;
-}
-
-
-int
-Process::registerExecContext(ExecContext *xc)
-{
- // add to list
- 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 myIndex;
-}
-
-void
-Process::startup()
-{
- if (execContexts.empty())
- return;
-
- // 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);
-}
-
-void
-Process::replaceExecContext(ExecContext *xc, int xcIndex)
-{
- if (xcIndex >= execContexts.size()) {
- panic("replaceExecContext: bad xcIndex, %d >= %d\n",
- xcIndex, execContexts.size());
- }
-
- execContexts[xcIndex] = xc;
-}
-
-// map simulator fd sim_fd to target fd tgt_fd
-void
-Process::dup_fd(int sim_fd, int tgt_fd)
-{
- if (tgt_fd < 0 || tgt_fd > MAX_FD)
- panic("Process::dup_fd tried to dup past MAX_FD (%d)", tgt_fd);
-
- fd_map[tgt_fd] = sim_fd;
-}
-
-
-// generate new target fd for sim_fd
-int
-Process::alloc_fd(int sim_fd)
-{
- // in case open() returns an error, don't allocate a new fd
- if (sim_fd == -1)
- return -1;
-
- // find first free target fd
- for (int free_fd = 0; free_fd < MAX_FD; ++free_fd) {
- if (fd_map[free_fd] == -1) {
- fd_map[free_fd] = sim_fd;
- return free_fd;
- }
- }
-
- panic("Process::alloc_fd: out of file descriptors!");
-}
-
-
-// free target fd (e.g., after close)
-void
-Process::free_fd(int tgt_fd)
-{
- if (fd_map[tgt_fd] == -1)
- warn("Process::free_fd: request to free unused fd %d", tgt_fd);
-
- fd_map[tgt_fd] = -1;
-}
-
-
-// look up simulator fd for given target fd
-int
-Process::sim_fd(int tgt_fd)
-{
- if (tgt_fd > MAX_FD)
- return -1;
-
- return fd_map[tgt_fd];
-}
-
-
-
-//
-// need to declare these here since there is no concrete Process type
-// that can be constructed (i.e., no REGISTER_SIM_OBJECT() macro call,
-// which is where these get declared for concrete types).
-//
-DEFINE_SIM_OBJECT_CLASS_NAME("Process", Process)
-
-
-////////////////////////////////////////////////////////////////////////
-//
-// LiveProcess member definitions
-//
-////////////////////////////////////////////////////////////////////////
-
-
-static void
-copyStringArray(vector<string> &strings, Addr array_ptr, Addr data_ptr,
- FunctionalMemory *memory)
-{
- Addr data_ptr_swap;
- for (int i = 0; i < strings.size(); ++i) {
- data_ptr_swap = htog(data_ptr);
- memory->access(Write, array_ptr, &data_ptr_swap, sizeof(Addr));
- memory->writeString(data_ptr, strings[i].c_str());
- array_ptr += sizeof(Addr);
- data_ptr += strings[i].size() + 1;
- }
- // add NULL terminator
- data_ptr = 0;
- memory->access(Write, array_ptr, &data_ptr, sizeof(Addr));
-}
-
-LiveProcess::LiveProcess(const string &nm, ObjectFile *objFile,
- int stdin_fd, int stdout_fd, int stderr_fd,
- vector<string> &argv, vector<string> &envp)
- : Process(nm, stdin_fd, stdout_fd, stderr_fd)
-{
- 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) {
- debugSymbolTable = new SymbolTable();
- if (!objFile->loadGlobalSymbols(debugSymbolTable) ||
- !objFile->loadLocalSymbols(debugSymbolTable)) {
- // didn't load any symbols
- delete debugSymbolTable;
- 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;
-
- // Set pointer for next thread stack. Reserve 8M for main stack.
- next_thread_stack_base = stack_base - (8 * 1024 * 1024);
-
- // 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 arg_data_size = 0;
- for (int i = 0; i < argv.size(); ++i) {
- arg_data_size += argv[i].size() + 1;
- }
- int env_data_size = 0;
- for (int i = 0; i < envp.size(); ++i) {
- env_data_size += envp[i].size() + 1;
- }
-
- int space_needed =
- argv_array_size + envp_array_size + arg_data_size + env_data_size;
- // for SimpleScalar compatibility
- if (space_needed < 16384)
- space_needed = 16384;
-
- // set bottom of stack
- stack_min = stack_base - space_needed;
- // align it
- stack_min &= ~7;
- stack_size = stack_base - stack_min;
-
- // map out initial stack contents
- Addr argv_array_base = stack_min + sizeof(uint64_t); // 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));
-}
-
-void
-LiveProcess::syscall(ExecContext *xc)
-{
- num_syscalls++;
-
- int64_t callnum = xc->readIntReg(SyscallNumReg);
-
- SyscallDesc *desc = getDesc(callnum);
- if (desc == NULL)
- fatal("Syscall %d out of range", callnum);
-
- desc->doSyscall(callnum, this, xc);
-}
-
-LiveProcess *
-LiveProcess::create(const string &nm,
- 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)
diff --git a/sim/process.hh b/sim/process.hh
deleted file mode 100644
index 3a48f128c..000000000
--- a/sim/process.hh
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * Copyright (c) 2001-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __PROCESS_HH__
-#define __PROCESS_HH__
-
-//
-// The purpose of this code is to fake the loader & syscall mechanism
-// when there's no OS: thus there's no reason to use it in FULL_SYSTEM
-// mode when we do have an OS.
-//
-#include "config/full_system.hh"
-
-#if !FULL_SYSTEM
-
-#include <vector>
-
-#include "arch/isa_traits.hh"
-#include "sim/sim_object.hh"
-#include "sim/stats.hh"
-#include "base/statistics.hh"
-#include "base/trace.hh"
-
-class CPUExecContext;
-class ExecContext;
-class FunctionalMemory;
-class SyscallDesc;
-class Process : public SimObject
-{
- protected:
- typedef TheISA::RegFile RegFile;
- typedef TheISA::MachInst MachInst;
- public:
-
- // have we initialized an execution context from this process? If
- // yes, subsequent contexts are assumed to be for dynamically
- // created threads and are not initialized.
- bool initialContextLoaded;
-
- // execution contexts associated with this process
- std::vector<ExecContext *> execContexts;
-
- // number of CPUs (esxec contexts, really) assigned to this process.
- unsigned int numCpus() { return execContexts.size(); }
-
- // record of blocked context
- struct WaitRec
- {
- Addr waitChan;
- ExecContext *waitingContext;
-
- 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)
- unsigned stack_size; // initial stack size
- Addr stack_min; // lowest address accessed on the stack
-
- // addr to use for next stack region (for multithreaded apps)
- Addr next_thread_stack_base;
-
- // Base of region for mmaps (when user doesn't specify an address).
- Addr mmap_start;
- Addr mmap_end;
-
- // Base of region for nxm data
- Addr nxm_start;
- Addr nxm_end;
-
- std::string prog_fname; // file name
- Addr prog_entry; // entry point (initial PC)
-
- Stats::Scalar<> num_syscalls; // number of syscalls executed
-
-
- protected:
- // constructor
- Process(const std::string &nm,
- int stdin_fd, // initial I/O descriptors
- int stdout_fd,
- int stderr_fd);
-
- // post initialization startup
- virtual void startup();
-
- protected:
- FunctionalMemory *memory;
-
- private:
- // file descriptor remapping support
- static const int MAX_FD = 256; // max legal fd value
- int fd_map[MAX_FD+1];
-
- public:
- // static helper functions to generate file descriptors for constructor
- static int openInputFile(const std::string &filename);
- static int openOutputFile(const std::string &filename);
-
- // override of virtual SimObject method: register statistics
- virtual void regStats();
-
- // register an execution context for this process.
- // returns xc's cpu number (index into execContexts[])
- int registerExecContext(ExecContext *xc);
-
-
- void replaceExecContext(ExecContext *xc, int xcIndex);
-
- // map simulator fd sim_fd to target fd tgt_fd
- void dup_fd(int sim_fd, int tgt_fd);
-
- // generate new target fd for sim_fd
- int alloc_fd(int sim_fd);
-
- // free target fd (e.g., after close)
- void free_fd(int tgt_fd);
-
- // 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; }
-};
-
-//
-// "Live" process with system calls redirected to host system
-//
-class ObjectFile;
-class LiveProcess : public Process
-{
- protected:
- LiveProcess(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);
-
- 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 SyscallDesc* getDesc(int callnum) { panic("Must be implemented."); }
-
-};
-
-
-#endif // !FULL_SYSTEM
-
-#endif // __PROCESS_HH__
diff --git a/sim/pseudo_inst.cc b/sim/pseudo_inst.cc
deleted file mode 100644
index 2d737c0a2..000000000
--- a/sim/pseudo_inst.cc
+++ /dev/null
@@ -1,291 +0,0 @@
-/*
- * Copyright (c) 2003-2006 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <errno.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <cstdio>
-
-#include <string>
-
-#include "sim/pseudo_inst.hh"
-#include "arch/vtophys.hh"
-#include "cpu/base.hh"
-#include "cpu/sampler/sampler.hh"
-#include "cpu/exec_context.hh"
-#include "cpu/quiesce_event.hh"
-#include "kern/kernel_stats.hh"
-#include "sim/param.hh"
-#include "sim/serialize.hh"
-#include "sim/sim_exit.hh"
-#include "sim/stat_control.hh"
-#include "sim/stats.hh"
-#include "sim/system.hh"
-#include "sim/debug.hh"
-#include "sim/vptr.hh"
-
-using namespace std;
-
-extern Sampler *SampCPU;
-
-using namespace Stats;
-using namespace TheISA;
-
-namespace AlphaPseudo
-{
- bool doStatisticsInsts;
- bool doCheckpointInsts;
- bool doQuiesce;
-
- void
- arm(ExecContext *xc)
- {
- if (xc->getKernelStats())
- xc->getKernelStats()->arm();
- }
-
- void
- quiesce(ExecContext *xc)
- {
- if (!doQuiesce)
- return;
-
- xc->suspend();
- if (xc->getKernelStats())
- xc->getKernelStats()->quiesce();
- }
-
- void
- quiesceNs(ExecContext *xc, uint64_t ns)
- {
- if (!doQuiesce || ns == 0)
- return;
-
- EndQuiesceEvent *quiesceEvent = xc->getQuiesceEvent();
-
- if (quiesceEvent->scheduled())
- quiesceEvent->reschedule(curTick + Clock::Int::ns * ns);
- else
- quiesceEvent->schedule(curTick + Clock::Int::ns * ns);
-
- xc->suspend();
- if (xc->getKernelStats())
- xc->getKernelStats()->quiesce();
- }
-
- void
- quiesceCycles(ExecContext *xc, uint64_t cycles)
- {
- if (!doQuiesce || cycles == 0)
- return;
-
- EndQuiesceEvent *quiesceEvent = xc->getQuiesceEvent();
-
- if (quiesceEvent->scheduled())
- quiesceEvent->reschedule(curTick +
- xc->getCpuPtr()->cycles(cycles));
- else
- quiesceEvent->schedule(curTick +
- xc->getCpuPtr()->cycles(cycles));
-
- xc->suspend();
- if (xc->getKernelStats())
- xc->getKernelStats()->quiesce();
- }
-
- uint64_t
- quiesceTime(ExecContext *xc)
- {
- return (xc->readLastActivate() - xc->readLastSuspend()) / Clock::Int::ns;
- }
-
- void
- ivlb(ExecContext *xc)
- {
- if (xc->getKernelStats())
- xc->getKernelStats()->ivlb();
- }
-
- void
- ivle(ExecContext *xc)
- {
- }
-
- void
- m5exit_old(ExecContext *xc)
- {
- SimExit(curTick, "m5_exit_old instruction encountered");
- }
-
- void
- m5exit(ExecContext *xc, Tick delay)
- {
- Tick when = curTick + delay * Clock::Int::ns;
- SimExit(when, "m5_exit instruction encountered");
- }
-
- void
- resetstats(ExecContext *xc, Tick delay, Tick period)
- {
- if (!doStatisticsInsts)
- return;
-
-
- Tick when = curTick + delay * Clock::Int::ns;
- Tick repeat = period * Clock::Int::ns;
-
- using namespace Stats;
- SetupEvent(Reset, when, repeat);
- }
-
- void
- dumpstats(ExecContext *xc, Tick delay, Tick period)
- {
- if (!doStatisticsInsts)
- return;
-
-
- Tick when = curTick + delay * Clock::Int::ns;
- Tick repeat = period * Clock::Int::ns;
-
- using namespace Stats;
- SetupEvent(Dump, when, repeat);
- }
-
- void
- addsymbol(ExecContext *xc, Addr addr, Addr symbolAddr)
- {
- char symb[100];
- CopyString(xc, symb, symbolAddr, 100);
- std::string symbol(symb);
-
- DPRINTF(Loader, "Loaded symbol: %s @ %#llx\n", symbol, addr);
-
- xc->getSystemPtr()->kernelSymtab->insert(addr,symbol);
- }
-
- void
- dumpresetstats(ExecContext *xc, Tick delay, Tick period)
- {
- if (!doStatisticsInsts)
- return;
-
-
- Tick when = curTick + delay * Clock::Int::ns;
- Tick repeat = period * Clock::Int::ns;
-
- using namespace Stats;
- SetupEvent(Dump|Reset, when, repeat);
- }
-
- void
- m5checkpoint(ExecContext *xc, Tick delay, Tick period)
- {
- if (!doCheckpointInsts)
- return;
-
-
- Tick when = curTick + delay * Clock::Int::ns;
- Tick repeat = period * Clock::Int::ns;
-
- Checkpoint::setup(when, repeat);
- }
-
- uint64_t
- readfile(ExecContext *xc, Addr vaddr, uint64_t len, uint64_t offset)
- {
- const string &file = xc->getCpuPtr()->system->params()->readfile;
- if (file.empty()) {
- return ULL(0);
- }
-
- uint64_t result = 0;
-
- int fd = ::open(file.c_str(), O_RDONLY, 0);
- if (fd < 0)
- panic("could not open file %s\n", file);
-
- if (::lseek(fd, offset, SEEK_SET) < 0)
- panic("could not seek: %s", strerror(errno));
-
- char *buf = new char[len];
- char *p = buf;
- while (len > 0) {
- int bytes = ::read(fd, p, len);
- if (bytes <= 0)
- break;
-
- p += bytes;
- result += bytes;
- len -= bytes;
- }
-
- close(fd);
- CopyIn(xc, vaddr, buf, result);
- delete [] buf;
- return result;
- }
-
- class Context : public ParamContext
- {
- public:
- Context(const string &section) : ParamContext(section) {}
- void checkParams();
- };
-
- Context context("pseudo_inst");
-
- Param<bool> __quiesce(&context, "quiesce",
- "enable quiesce instructions",
- true);
- Param<bool> __statistics(&context, "statistics",
- "enable statistics pseudo instructions",
- true);
- Param<bool> __checkpoint(&context, "checkpoint",
- "enable checkpoint pseudo instructions",
- true);
-
- void
- Context::checkParams()
- {
- doQuiesce = __quiesce;
- doStatisticsInsts = __statistics;
- doCheckpointInsts = __checkpoint;
- }
-
- void debugbreak(ExecContext *xc)
- {
- debug_break();
- }
-
- void switchcpu(ExecContext *xc)
- {
- if (SampCPU)
- SampCPU->switchCPUs();
- }
-}
diff --git a/sim/sim_object.cc b/sim/sim_object.cc
deleted file mode 100644
index f34e17fe6..000000000
--- a/sim/sim_object.cc
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
- * Copyright (c) 2001-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <assert.h>
-
-#include "base/callback.hh"
-#include "base/inifile.hh"
-#include "base/match.hh"
-#include "base/misc.hh"
-#include "base/trace.hh"
-#include "base/stats/events.hh"
-#include "sim/configfile.hh"
-#include "sim/host.hh"
-#include "sim/sim_object.hh"
-#include "sim/stats.hh"
-#include "sim/param.hh"
-
-using namespace std;
-
-
-////////////////////////////////////////////////////////////////////////
-//
-// SimObject member definitions
-//
-////////////////////////////////////////////////////////////////////////
-
-//
-// static list of all SimObjects, used for initialization etc.
-//
-SimObject::SimObjectList SimObject::simObjectList;
-
-namespace Stats {
- extern ObjectMatch event_ignore;
-}
-
-//
-// SimObject constructor: used to maintain static simObjectList
-//
-SimObject::SimObject(Params *p)
- : _params(p)
-{
-#ifdef DEBUG
- doDebugBreak = false;
-#endif
-
- doRecordEvent = !Stats::event_ignore.match(name());
- simObjectList.push_back(this);
-}
-
-//
-// SimObject constructor: used to maintain static simObjectList
-//
-SimObject::SimObject(const string &_name)
- : _params(new Params)
-{
- _params->name = _name;
-#ifdef DEBUG
- doDebugBreak = false;
-#endif
-
- doRecordEvent = !Stats::event_ignore.match(name());
- simObjectList.push_back(this);
-}
-
-void
-SimObject::init()
-{
-}
-
-//
-// no default statistics, so nothing to do in base implementation
-//
-void
-SimObject::regStats()
-{
-}
-
-void
-SimObject::regFormulas()
-{
-}
-
-void
-SimObject::resetStats()
-{
-}
-
-//
-// static function:
-// call regStats() on all SimObjects and then regFormulas() on all
-// SimObjects.
-//
-struct SimObjectResetCB : public Callback
-{
- virtual void process() { SimObject::resetAllStats(); }
-};
-
-namespace {
- static SimObjectResetCB StatResetCB;
-}
-
-void
-SimObject::regAllStats()
-{
- SimObjectList::iterator i;
- SimObjectList::iterator end = simObjectList.end();
-
- /**
- * @todo change cprintfs to DPRINTFs
- */
- for (i = simObjectList.begin(); i != end; ++i) {
-#ifdef STAT_DEBUG
- cprintf("registering stats for %s\n", (*i)->name());
-#endif
- (*i)->regStats();
- }
-
- for (i = simObjectList.begin(); i != end; ++i) {
-#ifdef STAT_DEBUG
- cprintf("registering formulas for %s\n", (*i)->name());
-#endif
- (*i)->regFormulas();
- }
-
- Stats::registerResetCallback(&StatResetCB);
-}
-
-//
-// static function: call init() on all SimObjects.
-//
-void
-SimObject::initAll()
-{
- SimObjectList::iterator i = simObjectList.begin();
- SimObjectList::iterator end = simObjectList.end();
-
- for (; i != end; ++i) {
- SimObject *obj = *i;
- obj->init();
- }
-}
-
-//
-// static function: call resetStats() on all SimObjects.
-//
-void
-SimObject::resetAllStats()
-{
- SimObjectList::iterator i = simObjectList.begin();
- SimObjectList::iterator end = simObjectList.end();
-
- for (; i != end; ++i) {
- SimObject *obj = *i;
- obj->resetStats();
- }
-}
-
-//
-// static function: serialize all SimObjects.
-//
-void
-SimObject::serializeAll(ostream &os)
-{
- SimObjectList::reverse_iterator ri = simObjectList.rbegin();
- SimObjectList::reverse_iterator rend = simObjectList.rend();
-
- for (; ri != rend; ++ri) {
- SimObject *obj = *ri;
- obj->nameOut(os);
- obj->serialize(os);
- }
-}
-
-#ifdef DEBUG
-//
-// static function: flag which objects should have the debugger break
-//
-void
-SimObject::debugObjectBreak(const string &objs)
-{
- SimObjectList::const_iterator i = simObjectList.begin();
- SimObjectList::const_iterator end = simObjectList.end();
-
- ObjectMatch match(objs);
- for (; i != end; ++i) {
- SimObject *obj = *i;
- obj->doDebugBreak = match.match(obj->name());
- }
-}
-
-extern "C"
-void
-debugObjectBreak(const char *objs)
-{
- SimObject::debugObjectBreak(string(objs));
-}
-#endif
-
-void
-SimObject::recordEvent(const std::string &stat)
-{
- if (doRecordEvent)
- Stats::recordEvent(stat);
-}
-
-DEFINE_SIM_OBJECT_CLASS_NAME("SimObject", SimObject)
diff --git a/sim/sim_object.hh b/sim/sim_object.hh
deleted file mode 100644
index 59d9daf45..000000000
--- a/sim/sim_object.hh
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (c) 2001-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/* @file
- * User Console Definitions
- */
-
-#ifndef __SIM_OBJECT_HH__
-#define __SIM_OBJECT_HH__
-
-#include <map>
-#include <list>
-#include <vector>
-#include <iostream>
-
-#include "sim/serialize.hh"
-#include "sim/startup.hh"
-
-/*
- * Abstract superclass for simulation objects. Represents things that
- * correspond to physical components and can be specified via the
- * config file (CPUs, caches, etc.).
- */
-class SimObject : public Serializable, protected StartupCallback
-{
- public:
- struct Params {
- std::string name;
- };
-
- protected:
- Params *_params;
-
- public:
- const Params *params() const { return _params; }
-
- private:
- friend class Serializer;
-
- typedef std::vector<SimObject *> SimObjectList;
-
- // list of all instantiated simulation objects
- static SimObjectList simObjectList;
-
- public:
- SimObject(Params *_params);
- SimObject(const std::string &_name);
-
- virtual ~SimObject() {}
-
- virtual const std::string name() const { return params()->name; }
-
- // initialization pass of all objects.
- // Gets invoked after construction, before unserialize.
- virtual void init();
- static void initAll();
-
- // register statistics for this object
- virtual void regStats();
- virtual void regFormulas();
- virtual void resetStats();
-
- // static: call reg_stats on all SimObjects
- static void regAllStats();
-
- // static: call resetStats on all SimObjects
- static void resetAllStats();
-
- // static: call nameOut() & serialize() on all SimObjects
- static void serializeAll(std::ostream &);
-
-#ifdef DEBUG
- public:
- bool doDebugBreak;
- static void debugObjectBreak(const std::string &objs);
-#endif
-
- public:
- bool doRecordEvent;
- void recordEvent(const std::string &stat);
-};
-
-#endif // __SIM_OBJECT_HH__
diff --git a/sim/syscall_emul.cc b/sim/syscall_emul.cc
deleted file mode 100644
index 00168b025..000000000
--- a/sim/syscall_emul.cc
+++ /dev/null
@@ -1,441 +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 <fcntl.h>
-#include <unistd.h>
-
-#include <string>
-#include <iostream>
-
-#include "sim/syscall_emul.hh"
-#include "base/trace.hh"
-#include "cpu/exec_context.hh"
-#include "cpu/base.hh"
-#include "sim/process.hh"
-
-#include "sim/sim_events.hh"
-
-using namespace std;
-using namespace TheISA;
-
-void
-SyscallDesc::doSyscall(int callnum, Process *process, ExecContext *xc)
-{
- DPRINTFR(SyscallVerbose, "%s: syscall %s called\n",
- xc->getCpuPtr()->name(), name);
-
- SyscallReturn retval = (*funcPtr)(this, callnum, process, xc);
-
- DPRINTFR(SyscallVerbose, "%s: syscall %s returns %d\n",
- xc->getCpuPtr()->name(), name, retval.value());
-
- if (!(flags & SyscallDesc::SuppressReturnValue))
- xc->setSyscallReturn(retval);
-}
-
-
-SyscallReturn
-unimplementedFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
-{
- fatal("syscall %s (#%d) unimplemented.", desc->name, callnum);
-}
-
-
-SyscallReturn
-ignoreFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
-{
- warn("ignoring syscall %s(%d, %d, ...)", desc->name,
- xc->getSyscallArg(0), xc->getSyscallArg(1));
-
- return 0;
-}
-
-
-SyscallReturn
-exitFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
-{
- new SimExitEvent("syscall caused exit", xc->getSyscallArg(0) & 0xff);
-
- return 1;
-}
-
-
-SyscallReturn
-getpagesizeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
-{
- return (int)VMPageSize;
-}
-
-
-SyscallReturn
-obreakFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
-{
- // change brk addr to first arg
- Addr new_brk = xc->getSyscallArg(0);
- if (new_brk != 0)
- {
- p->brk_point = xc->getSyscallArg(0);
- }
- DPRINTF(SyscallVerbose, "Break Point changed to: %#X\n", p->brk_point);
- return p->brk_point;
-}
-
-
-SyscallReturn
-closeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
-{
- int target_fd = xc->getSyscallArg(0);
- int status = close(p->sim_fd(target_fd));
- if (status >= 0)
- p->free_fd(target_fd);
- return status;
-}
-
-
-SyscallReturn
-readFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
-{
- int fd = p->sim_fd(xc->getSyscallArg(0));
- int nbytes = xc->getSyscallArg(2);
- BufferArg bufArg(xc->getSyscallArg(1), nbytes);
-
- int bytes_read = read(fd, bufArg.bufferPtr(), nbytes);
-
- if (bytes_read != -1)
- bufArg.copyOut(xc->getMemPtr());
-
- return bytes_read;
-}
-
-SyscallReturn
-writeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
-{
- int fd = p->sim_fd(xc->getSyscallArg(0));
- int nbytes = xc->getSyscallArg(2);
- BufferArg bufArg(xc->getSyscallArg(1), nbytes);
-
- bufArg.copyIn(xc->getMemPtr());
-
- int bytes_written = write(fd, bufArg.bufferPtr(), nbytes);
-
- fsync(fd);
-
- return bytes_written;
-}
-
-
-SyscallReturn
-lseekFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
-{
- int fd = p->sim_fd(xc->getSyscallArg(0));
- uint64_t offs = xc->getSyscallArg(1);
- int whence = xc->getSyscallArg(2);
-
- off_t result = lseek(fd, offs, whence);
-
- return (result == (off_t)-1) ? -errno : result;
-}
-
-
-SyscallReturn
-munmapFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
-{
- // given that we don't really implement mmap, munmap is really easy
- return 0;
-}
-
-
-const char *hostname = "m5.eecs.umich.edu";
-
-SyscallReturn
-gethostnameFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
-{
- int name_len = xc->getSyscallArg(1);
- BufferArg name(xc->getSyscallArg(0), name_len);
-
- strncpy((char *)name.bufferPtr(), hostname, name_len);
-
- name.copyOut(xc->getMemPtr());
-
- return 0;
-}
-
-SyscallReturn
-unlinkFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
-{
- string path;
-
- if (xc->getMemPtr()->readString(path, xc->getSyscallArg(0)) != NoFault)
- return (TheISA::IntReg)-EFAULT;
-
- int result = unlink(path.c_str());
- return (result == -1) ? -errno : result;
-}
-
-SyscallReturn
-renameFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
-{
- string old_name;
-
- if (xc->getMemPtr()->readString(old_name, xc->getSyscallArg(0)) != NoFault)
- return -EFAULT;
-
- string new_name;
-
- if (xc->getMemPtr()->readString(new_name, xc->getSyscallArg(1)) != NoFault)
- return -EFAULT;
-
- int64_t result = rename(old_name.c_str(), new_name.c_str());
- return (result == -1) ? -errno : result;
-}
-
-SyscallReturn
-truncateFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
-{
- string path;
-
- if (xc->getMemPtr()->readString(path, xc->getSyscallArg(0)) != NoFault)
- return -EFAULT;
-
- off_t length = xc->getSyscallArg(1);
-
- int result = truncate(path.c_str(), length);
- return (result == -1) ? -errno : result;
-}
-
-SyscallReturn
-ftruncateFunc(SyscallDesc *desc, int num, Process *process, ExecContext *xc)
-{
- int fd = process->sim_fd(xc->getSyscallArg(0));
-
- if (fd < 0)
- return -EBADF;
-
- off_t length = xc->getSyscallArg(1);
-
- int result = ftruncate(fd, length);
- return (result == -1) ? -errno : result;
-}
-
-SyscallReturn
-chownFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
-{
- string path;
-
- if (xc->getMemPtr()->readString(path, xc->getSyscallArg(0)) != NoFault)
- return -EFAULT;
-
- /* XXX endianess */
- uint32_t owner = xc->getSyscallArg(1);
- uid_t hostOwner = owner;
- uint32_t group = xc->getSyscallArg(2);
- gid_t hostGroup = group;
-
- int result = chown(path.c_str(), hostOwner, hostGroup);
- return (result == -1) ? -errno : result;
-}
-
-SyscallReturn
-fchownFunc(SyscallDesc *desc, int num, Process *process, ExecContext *xc)
-{
- int fd = process->sim_fd(xc->getSyscallArg(0));
-
- if (fd < 0)
- return -EBADF;
-
- /* XXX endianess */
- uint32_t owner = xc->getSyscallArg(1);
- uid_t hostOwner = owner;
- uint32_t group = xc->getSyscallArg(2);
- gid_t hostGroup = group;
-
- int result = fchown(fd, hostOwner, hostGroup);
- return (result == -1) ? -errno : result;
-}
-
-
-SyscallReturn
-fcntlFunc(SyscallDesc *desc, int num, Process *process,
- ExecContext *xc)
-{
- int fd = xc->getSyscallArg(0);
-
- if (fd < 0 || process->sim_fd(fd) < 0)
- return -EBADF;
-
- int cmd = xc->getSyscallArg(1);
- switch (cmd) {
- case 0: // F_DUPFD
- // if we really wanted to support this, we'd need to do it
- // in the target fd space.
- warn("fcntl(%d, F_DUPFD) not supported, error returned\n", fd);
- return -EMFILE;
-
- case 1: // F_GETFD (get close-on-exec flag)
- case 2: // F_SETFD (set close-on-exec flag)
- return 0;
-
- case 3: // F_GETFL (get file flags)
- case 4: // F_SETFL (set file flags)
- // not sure if this is totally valid, but we'll pass it through
- // to the underlying OS
- warn("fcntl(%d, %d) passed through to host\n", fd, cmd);
- return fcntl(process->sim_fd(fd), cmd);
- // return 0;
-
- case 7: // F_GETLK (get lock)
- case 8: // F_SETLK (set lock)
- case 9: // F_SETLKW (set lock and wait)
- // don't mess with file locking... just act like it's OK
- warn("File lock call (fcntl(%d, %d)) ignored.\n", fd, cmd);
- return 0;
-
- default:
- warn("Unknown fcntl command %d\n", cmd);
- return 0;
- }
-}
-
-SyscallReturn
-pipePseudoFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
-{
- int fds[2], sim_fds[2];
- int pipe_retval = pipe(fds);
-
- if (pipe_retval < 0) {
- // error
- return pipe_retval;
- }
-
- sim_fds[0] = process->alloc_fd(fds[0]);
- sim_fds[1] = process->alloc_fd(fds[1]);
-
- // Alpha Linux convention for pipe() is that fd[0] is returned as
- // the return value of the function, and fd[1] is returned in r20.
- xc->setIntReg(SyscallPseudoReturnReg, sim_fds[1]);
- return sim_fds[0];
-}
-
-
-SyscallReturn
-getpidPseudoFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
-{
- // Make up a PID. There's no interprocess communication in
- // fake_syscall mode, so there's no way for a process to know it's
- // not getting a unique value.
-
- xc->setIntReg(SyscallPseudoReturnReg, 99);
- return 100;
-}
-
-
-SyscallReturn
-getuidPseudoFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
-{
- // Make up a UID and EUID... it shouldn't matter, and we want the
- // simulation to be deterministic.
-
- // EUID goes in r20.
- xc->setIntReg(SyscallPseudoReturnReg, 100); //EUID
- return 100; // UID
-}
-
-
-SyscallReturn
-getgidPseudoFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
-{
- // Get current group ID. EGID goes in r20.
- xc->setIntReg(SyscallPseudoReturnReg, 100); //EGID
- return 100;
-}
-
-
-SyscallReturn
-setuidFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
-{
- // can't fathom why a benchmark would call this.
- warn("Ignoring call to setuid(%d)\n", xc->getSyscallArg(0));
- return 0;
-}
-
-SyscallReturn
-getpidFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
-{
- // Make up a PID. There's no interprocess communication in
- // fake_syscall mode, so there's no way for a process to know it's
- // not getting a unique value.
-
- xc->setIntReg(SyscallPseudoReturnReg, 99); //PID
- return 100;
-}
-
-SyscallReturn
-getppidFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
-{
- return 99;
-}
-
-SyscallReturn
-getuidFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
-{
- return 100; // UID
-}
-
-SyscallReturn
-geteuidFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
-{
- return 100; // UID
-}
-
-SyscallReturn
-getgidFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
-{
- return 100;
-}
-
-SyscallReturn
-getegidFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
-{
- return 100;
-}
-
-
diff --git a/sim/syscall_emul.hh b/sim/syscall_emul.hh
deleted file mode 100644
index 35129bcb4..000000000
--- a/sim/syscall_emul.hh
+++ /dev/null
@@ -1,832 +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.
- */
-
-#ifndef __SIM_SYSCALL_EMUL_HH__
-#define __SIM_SYSCALL_EMUL_HH__
-
-#define BSD_HOST (defined(__APPLE__) || defined(__OpenBSD__) || \
- defined(__FreeBSD__))
-
-///
-/// @file syscall_emul.hh
-///
-/// This file defines objects used to emulate syscalls from the target
-/// application on the host machine.
-
-#include <errno.h>
-#include <string>
-#ifdef __CYGWIN32__
-#include <sys/fcntl.h> // for O_BINARY
-#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/trace.hh"
-#include "cpu/exec_context.hh"
-#include "sim/process.hh"
-
-///
-/// System call descriptor.
-///
-class SyscallDesc {
-
- public:
-
- /// Typedef for target syscall handler functions.
- typedef SyscallReturn (*FuncPtr)(SyscallDesc *, int num,
- Process *, ExecContext *);
-
- const char *name; //!< Syscall name (e.g., "open").
- FuncPtr funcPtr; //!< Pointer to emulation function.
- int flags; //!< Flags (see Flags enum).
-
- /// Flag values for controlling syscall behavior.
- enum Flags {
- /// Don't set return regs according to funcPtr return value.
- /// Used for syscalls with non-standard return conventions
- /// that explicitly set the ExecContext regs (e.g.,
- /// sigreturn).
- SuppressReturnValue = 1
- };
-
- /// Constructor.
- SyscallDesc(const char *_name, FuncPtr _funcPtr, int _flags = 0)
- : name(_name), funcPtr(_funcPtr), flags(_flags)
- {
- }
-
- /// Emulate the syscall. Public interface for calling through funcPtr.
- void doSyscall(int callnum, Process *proc, ExecContext *xc);
-};
-
-
-class BaseBufferArg {
-
- public:
-
- BaseBufferArg(Addr _addr, int _size) : addr(_addr), size(_size)
- {
- bufPtr = new uint8_t[size];
- // clear out buffer: in case we only partially populate this,
- // and then do a copyOut(), we want to make sure we don't
- // introduce any random junk into the simulated address space
- memset(bufPtr, 0, size);
- }
-
- virtual ~BaseBufferArg() { delete [] bufPtr; }
-
- //
- // copy data into simulator space (read from target memory)
- //
- virtual bool copyIn(FunctionalMemory *mem)
- {
- mem->access(Read, 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)
- {
- mem->access(Write, addr, bufPtr, size);
- return true; // no EFAULT detection for now
- }
-
- protected:
- Addr addr;
- int size;
- uint8_t *bufPtr;
-};
-
-
-class BufferArg : public BaseBufferArg
-{
- public:
- BufferArg(Addr _addr, int _size) : BaseBufferArg(_addr, _size) { }
- void *bufferPtr() { return bufPtr; }
-};
-
-template <class T>
-class TypedBufferArg : public BaseBufferArg
-{
- public:
- // user can optionally specify a specific number of bytes to
- // allocate to deal with those structs that have variable-size
- // arrays at the end
- TypedBufferArg(Addr _addr, int _size = sizeof(T))
- : BaseBufferArg(_addr, _size)
- { }
-
- // type case
- operator T*() { return (T *)bufPtr; }
-
- // dereference operators
- T &operator*() { return *((T *)bufPtr); }
- T* operator->() { return (T *)bufPtr; }
- T &operator[](int i) { return ((T *)bufPtr)[i]; }
-};
-
-//////////////////////////////////////////////////////////////////////
-//
-// The following emulation functions are generic enough that they
-// don't need to be recompiled for different emulated OS's. They are
-// defined in sim/syscall_emul.cc.
-//
-//////////////////////////////////////////////////////////////////////
-
-
-/// Handler for unimplemented syscalls that we haven't thought about.
-SyscallReturn unimplementedFunc(SyscallDesc *desc, int num,
- Process *p, ExecContext *xc);
-
-/// Handler for unimplemented syscalls that we never intend to
-/// implement (signal handling, etc.) and should not affect the correct
-/// behavior of the program. Print a warning only if the appropriate
-/// trace flag is enabled. Return success to the target program.
-SyscallReturn ignoreFunc(SyscallDesc *desc, int num,
- Process *p, ExecContext *xc);
-
-/// Target exit() handler: terminate simulation.
-SyscallReturn exitFunc(SyscallDesc *desc, int num,
- Process *p, ExecContext *xc);
-
-/// Target getpagesize() handler.
-SyscallReturn getpagesizeFunc(SyscallDesc *desc, int num,
- Process *p, ExecContext *xc);
-
-/// Target obreak() handler: set brk address.
-SyscallReturn obreakFunc(SyscallDesc *desc, int num,
- Process *p, ExecContext *xc);
-
-/// Target close() handler.
-SyscallReturn closeFunc(SyscallDesc *desc, int num,
- Process *p, ExecContext *xc);
-
-/// Target read() handler.
-SyscallReturn readFunc(SyscallDesc *desc, int num,
- Process *p, ExecContext *xc);
-
-/// Target write() handler.
-SyscallReturn writeFunc(SyscallDesc *desc, int num,
- Process *p, ExecContext *xc);
-
-/// Target lseek() handler.
-SyscallReturn lseekFunc(SyscallDesc *desc, int num,
- Process *p, ExecContext *xc);
-
-/// Target munmap() handler.
-SyscallReturn munmapFunc(SyscallDesc *desc, int num,
- Process *p, ExecContext *xc);
-
-/// Target gethostname() handler.
-SyscallReturn gethostnameFunc(SyscallDesc *desc, int num,
- Process *p, ExecContext *xc);
-
-/// Target unlink() handler.
-SyscallReturn unlinkFunc(SyscallDesc *desc, int num,
- Process *p, ExecContext *xc);
-
-/// Target rename() handler.
-SyscallReturn renameFunc(SyscallDesc *desc, int num,
- Process *p, ExecContext *xc);
-
-
-/// Target truncate() handler.
-SyscallReturn truncateFunc(SyscallDesc *desc, int num,
- Process *p, ExecContext *xc);
-
-
-/// Target ftruncate() handler.
-SyscallReturn ftruncateFunc(SyscallDesc *desc, int num,
- Process *p, ExecContext *xc);
-
-
-/// Target chown() handler.
-SyscallReturn chownFunc(SyscallDesc *desc, int num,
- Process *p, ExecContext *xc);
-
-
-/// Target fchown() handler.
-SyscallReturn fchownFunc(SyscallDesc *desc, int num,
- Process *p, ExecContext *xc);
-
-/// Target fnctl() handler.
-SyscallReturn fcntlFunc(SyscallDesc *desc, int num,
- Process *process, ExecContext *xc);
-
-/// Target setuid() handler.
-SyscallReturn setuidFunc(SyscallDesc *desc, int num,
- Process *p, ExecContext *xc);
-
-/// Target getpid() handler.
-SyscallReturn getpidFunc(SyscallDesc *desc, int num,
- Process *p, ExecContext *xc);
-
-/// Target getuid() handler.
-SyscallReturn getuidFunc(SyscallDesc *desc, int num,
- Process *p, ExecContext *xc);
-
-/// Target getgid() handler.
-SyscallReturn getgidFunc(SyscallDesc *desc, int num,
- Process *p, ExecContext *xc);
-
-/// Target getppid() handler.
-SyscallReturn getppidFunc(SyscallDesc *desc, int num,
- Process *p, ExecContext *xc);
-
-/// Target geteuid() handler.
-SyscallReturn geteuidFunc(SyscallDesc *desc, int num,
- Process *p, ExecContext *xc);
-
-/// Target getegid() handler.
-SyscallReturn getegidFunc(SyscallDesc *desc, int num,
- Process *p, ExecContext *xc);
-
-
-
-/// Pseudo Funcs - These functions use a different return convension,
-/// returning a second value in a register other than the normal return register
-SyscallReturn pipePseudoFunc(SyscallDesc *desc, int num,
- Process *process, ExecContext *xc);
-
-/// Target getpidPseudo() handler.
-SyscallReturn getpidPseudoFunc(SyscallDesc *desc, int num,
- Process *p, ExecContext *xc);
-
-/// Target getuidPseudo() handler.
-SyscallReturn getuidPseudoFunc(SyscallDesc *desc, int num,
- Process *p, ExecContext *xc);
-
-/// Target getgidPseudo() handler.
-SyscallReturn getgidPseudoFunc(SyscallDesc *desc, int num,
- Process *p, ExecContext *xc);
-
-
-/// This struct is used to build an target-OS-dependent table that
-/// maps the target's open() flags to the host open() flags.
-struct OpenFlagTransTable {
- int tgtFlag; //!< Target system flag value.
- int hostFlag; //!< Corresponding host system flag value.
-};
-
-
-
-/// A readable name for 1,000,000, for converting microseconds to seconds.
-const int one_million = 1000000;
-
-/// Approximate seconds since the epoch (1/1/1970). About a billion,
-/// by my reckoning. We want to keep this a constant (not use the
-/// real-world time) to keep simulations repeatable.
-const unsigned seconds_since_epoch = 1000000000;
-
-/// Helper function to convert current elapsed time to seconds and
-/// microseconds.
-template <class T1, class T2>
-void
-getElapsedTime(T1 &sec, T2 &usec)
-{
- int elapsed_usecs = curTick / Clock::Int::us;
- sec = elapsed_usecs / one_million;
- usec = elapsed_usecs % one_million;
-}
-
-//////////////////////////////////////////////////////////////////////
-//
-// The following emulation functions are generic, but need to be
-// templated to account for differences in types, constants, etc.
-//
-//////////////////////////////////////////////////////////////////////
-
-/// Target ioctl() handler. For the most part, programs call ioctl()
-/// only to find out if their stdout is a tty, to determine whether to
-/// do line or block buffering.
-template <class OS>
-SyscallReturn
-ioctlFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
-{
- int fd = xc->getSyscallArg(0);
- unsigned req = xc->getSyscallArg(1);
-
- DPRINTF(SyscallVerbose, "ioctl(%d, 0x%x, ...)\n", fd, req);
-
- if (fd < 0 || process->sim_fd(fd) < 0) {
- // doesn't map to any simulator fd: not a valid target fd
- return -EBADF;
- }
-
- switch (req) {
- case OS::TIOCISATTY:
- case OS::TIOCGETP:
- case OS::TIOCSETP:
- case OS::TIOCSETN:
- case OS::TIOCSETC:
- case OS::TIOCGETC:
- case OS::TIOCGETS:
- case OS::TIOCGETA:
- return -ENOTTY;
-
- default:
- fatal("Unsupported ioctl call: ioctl(%d, 0x%x, ...) @ 0x%llx\n",
- fd, req, xc->readPC());
- }
-}
-
-/// Target open() handler.
-template <class OS>
-SyscallReturn
-openFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
-{
- std::string path;
-
- if (xc->getMemPtr()->readString(path, xc->getSyscallArg(0)) != NoFault)
- return -EFAULT;
-
- if (path == "/dev/sysdev0") {
- // This is a memory-mapped high-resolution timer device on Alpha.
- // We don't support it, so just punt.
- warn("Ignoring open(%s, ...)\n", path);
- return -ENOENT;
- }
-
- int tgtFlags = xc->getSyscallArg(1);
- int mode = xc->getSyscallArg(2);
- int hostFlags = 0;
-
- // translate open flags
- for (int i = 0; i < OS::NUM_OPEN_FLAGS; i++) {
- if (tgtFlags & OS::openFlagTable[i].tgtFlag) {
- tgtFlags &= ~OS::openFlagTable[i].tgtFlag;
- hostFlags |= OS::openFlagTable[i].hostFlag;
- }
- }
-
- // any target flags left?
- if (tgtFlags != 0)
- warn("Syscall: open: cannot decode flags 0x%x", tgtFlags);
-
-#ifdef __CYGWIN32__
- hostFlags |= O_BINARY;
-#endif
-
- DPRINTF(SyscallVerbose, "opening file %s\n", path.c_str());
-
- // open the file
- int fd = open(path.c_str(), hostFlags, mode);
-
- return (fd == -1) ? -errno : process->alloc_fd(fd);
-}
-
-
-/// Target chmod() handler.
-template <class OS>
-SyscallReturn
-chmodFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
-{
- std::string path;
-
- if (xc->getMemPtr()->readString(path, xc->getSyscallArg(0)) != NoFault)
- return -EFAULT;
-
- uint32_t mode = xc->getSyscallArg(1);
- mode_t hostMode = 0;
-
- // XXX translate mode flags via OS::something???
- hostMode = mode;
-
- // do the chmod
- int result = chmod(path.c_str(), hostMode);
- if (result < 0)
- return -errno;
-
- return 0;
-}
-
-
-/// Target fchmod() handler.
-template <class OS>
-SyscallReturn
-fchmodFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
-{
- int fd = xc->getSyscallArg(0);
- if (fd < 0 || process->sim_fd(fd) < 0) {
- // doesn't map to any simulator fd: not a valid target fd
- return -EBADF;
- }
-
- uint32_t mode = xc->getSyscallArg(1);
- mode_t hostMode = 0;
-
- // XXX translate mode flags via OS::someting???
- hostMode = mode;
-
- // do the fchmod
- int result = fchmod(process->sim_fd(fd), hostMode);
- if (result < 0)
- return -errno;
-
- return 0;
-}
-
-
-/// Target stat() handler.
-template <class OS>
-SyscallReturn
-statFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
-{
- std::string path;
-
- if (xc->getMemPtr()->readString(path, xc->getSyscallArg(0)) != NoFault)
- return -EFAULT;
-
- struct stat hostBuf;
- int result = stat(path.c_str(), &hostBuf);
-
- if (result < 0)
- return -errno;
-
- OS::copyOutStatBuf(xc->getMemPtr(), xc->getSyscallArg(1), &hostBuf);
-
- return 0;
-}
-
-
-/// Target fstat64() handler.
-template <class OS>
-SyscallReturn
-fstat64Func(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
-{
- int fd = xc->getSyscallArg(0);
- if (fd < 0 || process->sim_fd(fd) < 0) {
- // doesn't map to any simulator fd: not a valid target fd
- return -EBADF;
- }
-
-#if BSD_HOST
- struct stat hostBuf;
- int result = fstat(process->sim_fd(fd), &hostBuf);
-#else
- struct stat64 hostBuf;
- int result = fstat64(process->sim_fd(fd), &hostBuf);
-#endif
-
- if (result < 0)
- return -errno;
-
- OS::copyOutStat64Buf(xc->getMemPtr(), fd, xc->getSyscallArg(1), &hostBuf);
-
- return 0;
-}
-
-
-/// Target lstat() handler.
-template <class OS>
-SyscallReturn
-lstatFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
-{
- std::string path;
-
- if (xc->getMemPtr()->readString(path, xc->getSyscallArg(0)) != NoFault)
- return -EFAULT;
-
- struct stat hostBuf;
- int result = lstat(path.c_str(), &hostBuf);
-
- if (result < 0)
- return -errno;
-
- OS::copyOutStatBuf(xc->getMemPtr(), xc->getSyscallArg(1), &hostBuf);
-
- return 0;
-}
-
-/// Target lstat64() handler.
-template <class OS>
-SyscallReturn
-lstat64Func(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
-{
- std::string path;
-
- if (xc->getMemPtr()->readString(path, xc->getSyscallArg(0)) != NoFault)
- return -EFAULT;
-
-#if BSD_HOST
- struct stat hostBuf;
- int result = lstat(path.c_str(), &hostBuf);
-#else
- struct stat64 hostBuf;
- int result = lstat64(path.c_str(), &hostBuf);
-#endif
-
- if (result < 0)
- return -errno;
-
- OS::copyOutStat64Buf(xc->getMemPtr(), -1, xc->getSyscallArg(1), &hostBuf);
-
- return 0;
-}
-
-/// Target fstat() handler.
-template <class OS>
-SyscallReturn
-fstatFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
-{
- int fd = process->sim_fd(xc->getSyscallArg(0));
-
- DPRINTF(SyscallVerbose, "fstat(%d, ...)\n", fd);
-
- if (fd < 0)
- return -EBADF;
-
- struct stat hostBuf;
- int result = fstat(fd, &hostBuf);
-
- if (result < 0)
- return -errno;
-
- OS::copyOutStatBuf(xc->getMemPtr(), xc->getSyscallArg(1), &hostBuf);
- return 0;
-}
-
-
-/// Target statfs() handler.
-template <class OS>
-SyscallReturn
-statfsFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
-{
- std::string path;
-
- if (xc->getMemPtr()->readString(path, xc->getSyscallArg(0)) != NoFault)
- return -EFAULT;
-
- struct statfs hostBuf;
- int result = statfs(path.c_str(), &hostBuf);
-
- if (result < 0)
- return -errno;
-
- OS::copyOutStatfsBuf(xc->getMemPtr(), xc->getSyscallArg(1), &hostBuf);
-
- return 0;
-}
-
-
-/// Target fstatfs() handler.
-template <class OS>
-SyscallReturn
-fstatfsFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
-{
- int fd = process->sim_fd(xc->getSyscallArg(0));
-
- if (fd < 0)
- return -EBADF;
-
- struct statfs hostBuf;
- int result = fstatfs(fd, &hostBuf);
-
- if (result < 0)
- return -errno;
-
- OS::copyOutStatfsBuf(xc->getMemPtr(), xc->getSyscallArg(1), &hostBuf);
-
- return 0;
-}
-
-
-/// Target writev() handler.
-template <class OS>
-SyscallReturn
-writevFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
-{
- int fd = xc->getSyscallArg(0);
- if (fd < 0 || process->sim_fd(fd) < 0) {
- // doesn't map to any simulator fd: not a valid target fd
- return -EBADF;
- }
-
- 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));
- 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);
- }
-
- int result = writev(process->sim_fd(fd), hiov, count);
-
- for (int i = 0; i < count; ++i)
- {
- delete [] (char *)hiov[i].iov_base;
- }
-
- if (result < 0)
- return -errno;
-
- return 0;
-}
-
-
-/// Target mmap() handler.
-///
-/// We don't really handle mmap(). If the target is mmaping an
-/// anonymous region or /dev/zero, we can get away with doing basically
-/// nothing (since memory is initialized to zero and the simulator
-/// doesn't really check addresses anyway). Always print a warning,
-/// since this could be seriously broken if we're not mapping
-/// /dev/zero.
-//
-/// Someday we should explicitly check for /dev/zero in open, flag the
-/// file descriptor, and fail (or implement!) a non-anonymous mmap to
-/// anything else.
-template <class OS>
-SyscallReturn
-mmapFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
-{
- Addr start = xc->getSyscallArg(0);
- uint64_t length = xc->getSyscallArg(1);
- // int prot = xc->getSyscallArg(2);
- int flags = xc->getSyscallArg(3);
- // 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 (!(flags & OS::TGT_MAP_ANONYMOUS)) {
- warn("allowing mmap of file @ fd %d. "
- "This will break if not /dev/zero.", xc->getSyscallArg(4));
- }
-
- return start;
-}
-
-/// Target getrlimit() handler.
-template <class OS>
-SyscallReturn
-getrlimitFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
-{
- unsigned resource = xc->getSyscallArg(0);
- TypedBufferArg<typename OS::rlimit> rlp(xc->getSyscallArg(1));
-
- switch (resource) {
- case OS::TGT_RLIMIT_STACK:
- // max stack size in bytes: make up a number (2MB for now)
- rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024;
- rlp->rlim_cur = htog(rlp->rlim_cur);
- rlp->rlim_max = htog(rlp->rlim_max);
- break;
-
- default:
- std::cerr << "getrlimitFunc: unimplemented resource " << resource
- << std::endl;
- abort();
- break;
- }
-
- rlp.copyOut(xc->getMemPtr());
- return 0;
-}
-
-/// Target gettimeofday() handler.
-template <class OS>
-SyscallReturn
-gettimeofdayFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
-{
- TypedBufferArg<typename OS::timeval> tp(xc->getSyscallArg(0));
-
- getElapsedTime(tp->tv_sec, tp->tv_usec);
- tp->tv_sec += seconds_since_epoch;
- tp->tv_sec = htog(tp->tv_sec);
- tp->tv_usec = htog(tp->tv_usec);
-
- tp.copyOut(xc->getMemPtr());
-
- return 0;
-}
-
-
-/// Target utimes() handler.
-template <class OS>
-SyscallReturn
-utimesFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
-{
- std::string path;
-
- if (xc->getMemPtr()->readString(path, xc->getSyscallArg(0)) != NoFault)
- return -EFAULT;
-
- TypedBufferArg<typename OS::timeval [2]> tp(xc->getSyscallArg(1));
- tp.copyIn(xc->getMemPtr());
-
- struct timeval hostTimeval[2];
- for (int i = 0; i < 2; ++i)
- {
- hostTimeval[i].tv_sec = gtoh((*tp)[i].tv_sec);
- hostTimeval[i].tv_usec = gtoh((*tp)[i].tv_usec);
- }
- int result = utimes(path.c_str(), hostTimeval);
-
- if (result < 0)
- return -errno;
-
- return 0;
-}
-/// Target getrusage() function.
-template <class OS>
-SyscallReturn
-getrusageFunc(SyscallDesc *desc, int callnum, Process *process,
- ExecContext *xc)
-{
- int who = xc->getSyscallArg(0); // THREAD, SELF, or CHILDREN
- TypedBufferArg<typename OS::rusage> rup(xc->getSyscallArg(1));
-
- if (who != OS::TGT_RUSAGE_SELF) {
- // don't really handle THREAD or CHILDREN, but just warn and
- // plow ahead
- warn("getrusage() only supports RUSAGE_SELF. Parameter %d ignored.",
- who);
- }
-
- getElapsedTime(rup->ru_utime.tv_sec, rup->ru_utime.tv_usec);
- rup->ru_utime.tv_sec = htog(rup->ru_utime.tv_sec);
- rup->ru_utime.tv_usec = htog(rup->ru_utime.tv_usec);
-
- rup->ru_stime.tv_sec = 0;
- rup->ru_stime.tv_usec = 0;
- rup->ru_maxrss = 0;
- rup->ru_ixrss = 0;
- rup->ru_idrss = 0;
- rup->ru_isrss = 0;
- rup->ru_minflt = 0;
- rup->ru_majflt = 0;
- rup->ru_nswap = 0;
- rup->ru_inblock = 0;
- rup->ru_oublock = 0;
- rup->ru_msgsnd = 0;
- rup->ru_msgrcv = 0;
- rup->ru_nsignals = 0;
- rup->ru_nvcsw = 0;
- rup->ru_nivcsw = 0;
-
- rup.copyOut(xc->getMemPtr());
-
- return 0;
-}
-
-#endif // __SIM_SYSCALL_EMUL_HH__
diff --git a/sim/system.cc b/sim/system.cc
deleted file mode 100644
index 8820922c1..000000000
--- a/sim/system.cc
+++ /dev/null
@@ -1,185 +0,0 @@
-#include "base/loader/object_file.hh"
-#include "base/loader/symtab.hh"
-#include "base/remote_gdb.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 "sim/builder.hh"
-#include "arch/isa_traits.hh"
-#include "sim/byteswap.hh"
-#include "sim/system.hh"
-#include "base/trace.hh"
-
-using namespace std;
-using namespace TheISA;
-
-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)
-{
- // add self to global system list
- systemList.push_back(this);
-
- kernelSymtab = new SymbolTable;
- debugSymbolTable = new SymbolTable;
-
- /**
- * Load the kernel code into memory
- */
- // Load kernel code
- kernel = createObjectFile(params()->kernel_path);
- if (kernel == NULL)
- fatal("Could not load kernel file %s", params()->kernel_path);
-
- // Load program sections into memory
- kernel->loadSections(physmem, true);
-
- // setup entry points
- kernelStart = kernel->textBase();
- kernelEnd = kernel->bssBase() + kernel->bssSize();
- kernelEntry = kernel->entryPoint();
-
- // load symbols
- if (!kernel->loadGlobalSymbols(kernelSymtab))
- panic("could not load kernel symbols\n");
-
- if (!kernel->loadLocalSymbols(kernelSymtab))
- panic("could not load kernel local symbols\n");
-
- if (!kernel->loadGlobalSymbols(debugSymbolTable))
- panic("could not load kernel symbols\n");
-
- if (!kernel->loadLocalSymbols(debugSymbolTable))
- panic("could not load kernel local symbols\n");
-
- DPRINTF(Loader, "Kernel start = %#x\n", kernelStart);
- DPRINTF(Loader, "Kernel end = %#x\n", kernelEnd);
- DPRINTF(Loader, "Kernel entry = %#x\n", kernelEntry);
- DPRINTF(Loader, "Kernel loaded...\n");
-
- // increment the number of running systms
- numSystemsRunning++;
-
- kernelBinning = new Kernel::Binning(this);
-}
-
-System::~System()
-{
- delete kernelSymtab;
- delete kernel;
-
- delete kernelBinning;
-}
-
-
-
-
-int rgdb_wait = -1;
-
-int
-System::registerExecContext(ExecContext *xc, int id)
-{
- if (id == -1) {
- for (id = 0; id < execContexts.size(); id++) {
- if (!execContexts[id])
- break;
- }
- }
-
- if (execContexts.size() <= id)
- execContexts.resize(id + 1);
-
- if (execContexts[id])
- panic("Cannot have two CPUs with the same id (%d)\n", id);
-
- execContexts[id] = xc;
- numcpus++;
-
- RemoteGDB *rgdb = new RemoteGDB(this, xc);
- GDBListener *gdbl = new GDBListener(rgdb, 7000 + id);
- gdbl->listen();
- /**
- * Uncommenting this line waits for a remote debugger to connect
- * to the simulator before continuing.
- */
- if (rgdb_wait != -1 && rgdb_wait == id)
- gdbl->accept();
-
- if (remoteGDB.size() <= id) {
- remoteGDB.resize(id + 1);
- }
-
- remoteGDB[id] = rgdb;
-
- return id;
-}
-
-void
-System::startup()
-{
- int i;
- for (i = 0; i < execContexts.size(); i++)
- execContexts[i]->activate(0);
-}
-
-void
-System::replaceExecContext(ExecContext *xc, int id)
-{
- if (id >= execContexts.size()) {
- panic("replaceExecContext: bad id, %d >= %d\n",
- id, execContexts.size());
- }
-
- execContexts[id] = xc;
- remoteGDB[id]->replaceExecContext(xc);
-}
-
-void
-System::regStats()
-{
- kernelBinning->regStats(name() + ".kern");
-}
-
-void
-System::serialize(ostream &os)
-{
- kernelBinning->serialize(os);
-
- kernelSymtab->serialize("kernel_symtab", os);
-}
-
-
-void
-System::unserialize(Checkpoint *cp, const string &section)
-{
- kernelBinning->unserialize(cp, section);
-
- kernelSymtab->unserialize("kernel_symtab", cp, section);
-}
-
-void
-System::printSystems()
-{
- vector<System *>::iterator i = systemList.begin();
- vector<System *>::iterator end = systemList.end();
- for (; i != end; ++i) {
- System *sys = *i;
- cerr << "System " << sys->name() << ": " << hex << sys << endl;
- }
-}
-
-extern "C"
-void
-printSystems()
-{
- System::printSystems();
-}
-
-DEFINE_SIM_OBJECT_CLASS_NAME("System", System)
-
diff --git a/sim/system.hh b/sim/system.hh
deleted file mode 100644
index ea482a102..000000000
--- a/sim/system.hh
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * 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 __SYSTEM_HH__
-#define __SYSTEM_HH__
-
-#include <string>
-#include <vector>
-
-#include "base/statistics.hh"
-#include "base/loader/symtab.hh"
-#include "cpu/pc_event.hh"
-#include "kern/system_events.hh"
-#include "sim/sim_object.hh"
-
-class BaseCPU;
-class ExecContext;
-class GDBListener;
-class MemoryController;
-class ObjectFile;
-class PhysicalMemory;
-class Platform;
-class RemoteGDB;
-namespace Kernel { class Binning; }
-
-class System : public SimObject
-{
- public:
- MemoryController *memctrl;
- PhysicalMemory *physmem;
- Platform *platform;
- PCEventQueue pcEventQueue;
- uint64_t init_param;
-
- std::vector<ExecContext *> execContexts;
- int numcpus;
-
- int getNumCPUs()
- {
- if (numcpus != execContexts.size())
- panic("cpu array not fully populated!");
-
- return numcpus;
- }
-
- /** kernel symbol table */
- SymbolTable *kernelSymtab;
-
- /** Object pointer for the kernel code */
- ObjectFile *kernel;
-
- /** Begining of kernel code */
- Addr kernelStart;
-
- /** End of kernel code */
- Addr kernelEnd;
-
- /** Entry point in the kernel to start at */
- Addr kernelEntry;
-
- Kernel::Binning *kernelBinning;
-
- protected:
-
- /**
- * Fix up an address used to match PCs for hooking simulator
- * events on to target function executions. See comment in
- * system.cc for details.
- */
- virtual Addr fixFuncEventAddr(Addr addr) = 0;
-
- /**
- * Add a function-based event to the given function, to be looked
- * up in the specified symbol table.
- */
- template <class T>
- T *System::addFuncEvent(SymbolTable *symtab, const char *lbl)
- {
- Addr addr = 0; // initialize only to avoid compiler warning
-
- if (symtab->findAddress(lbl, addr)) {
- T *ev = new T(&pcEventQueue, lbl, fixFuncEventAddr(addr));
- return ev;
- }
-
- return NULL;
- }
-
- /** Add a function-based event to kernel code. */
- template <class T>
- T *System::addKernelFuncEvent(const char *lbl)
- {
- return addFuncEvent<T>(kernelSymtab, lbl);
- }
-
- public:
- std::vector<RemoteGDB *> remoteGDB;
- std::vector<GDBListener *> gdbListen;
- virtual bool breakpoint() = 0;
-
- public:
- struct Params
- {
- std::string name;
- Tick boot_cpu_frequency;
- MemoryController *memctrl;
- PhysicalMemory *physmem;
- uint64_t init_param;
- bool bin;
- std::vector<std::string> binned_fns;
- bool bin_int;
-
- std::string kernel_path;
- std::string readfile;
- };
-
- protected:
- Params *_params;
-
- public:
- System(Params *p);
- ~System();
-
- void startup();
-
- const Params *params() const { return (const Params *)_params; }
-
- public:
- /**
- * Returns the addess the kernel starts at.
- * @return address the kernel starts at
- */
- Addr getKernelStart() const { return kernelStart; }
-
- /**
- * Returns the addess the kernel ends at.
- * @return address the kernel ends at
- */
- Addr getKernelEnd() const { return kernelEnd; }
-
- /**
- * Returns the addess the entry point to the kernel code.
- * @return entry point of the kernel code
- */
- Addr getKernelEntry() const { return kernelEntry; }
-
- int registerExecContext(ExecContext *xc, int xcIndex);
- void replaceExecContext(ExecContext *xc, int xcIndex);
-
- void regStats();
- void serialize(std::ostream &os);
- void unserialize(Checkpoint *cp, const std::string &section);
-
- public:
- ////////////////////////////////////////////
- //
- // STATIC GLOBAL SYSTEM LIST
- //
- ////////////////////////////////////////////
-
- static std::vector<System *> systemList;
- static int numSystemsRunning;
-
- static void printSystems();
-
-
-};
-
-#endif // __SYSTEM_HH__
diff --git a/sim/vptr.hh b/sim/vptr.hh
deleted file mode 100644
index 0ec452f25..000000000
--- a/sim/vptr.hh
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __ARCH_ALPHA_VPTR_HH__
-#define __ARCH_ALPHA_VPTR_HH__
-
-#include "arch/vtophys.hh"
-#include "arch/isa_traits.hh"
-
-class ExecContext;
-
-template <class T>
-class VPtr
-{
- public:
- typedef T Type;
-
- private:
- ExecContext *xc;
- Addr ptr;
-
- public:
- ExecContext *GetXC() const { return xc; }
- Addr GetPointer() const { return ptr; }
-
- public:
- explicit VPtr(ExecContext *_xc, Addr p = 0) : xc(_xc), ptr(p) { }
- template <class U>
- VPtr(const VPtr<U> &vp) : xc(vp.GetXC()), ptr(vp.GetPointer()) {}
- ~VPtr() {}
-
- bool operator!() const
- {
- return ptr == 0;
- }
-
- VPtr<T> operator+(int offset)
- {
- VPtr<T> ptr(*this);
- ptr += offset;
-
- return ptr;
- }
-
- const VPtr<T> &operator+=(int offset)
- {
- ptr += offset;
- assert((ptr & (TheISA::PageBytes - 1)) + sizeof(T)
- < TheISA::PageBytes);
-
- return *this;
- }
-
- const VPtr<T> &operator=(Addr p)
- {
- assert((p & (TheISA::PageBytes - 1)) + sizeof(T)
- < TheISA::PageBytes);
- ptr = p;
-
- return *this;
- }
-
- template <class U>
- const VPtr<T> &operator=(const VPtr<U> &vp)
- {
- xc = vp.GetXC();
- ptr = vp.GetPointer();
-
- return *this;
- }
-
- operator T *()
- {
- void *addr = vtomem(xc, ptr, sizeof(T));
- return (T *)addr;
- }
-
- T *operator->()
- {
- void *addr = vtomem(xc, ptr, sizeof(T));
- return (T *)addr;
- }
-
- T &operator*()
- {
- void *addr = vtomem(xc, ptr, sizeof(T));
- return *(T *)addr;
- }
-};
-
-#endif // __ARCH_ALPHA_VPTR_HH__
diff --git a/Doxyfile b/src/Doxyfile
index 38116f6b0..38116f6b0 100644
--- a/Doxyfile
+++ b/src/Doxyfile
diff --git a/src/SConscript b/src/SConscript
new file mode 100644
index 000000000..268bcc745
--- /dev/null
+++ b/src/SConscript
@@ -0,0 +1,400 @@
+# -*- mode:python -*-
+
+# Copyright (c) 2004-2005 The Regents of The University of Michigan
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met: redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer;
+# redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution;
+# neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import os
+import sys
+from os.path import isdir
+
+# This file defines how to build a particular configuration of M5
+# based on variable settings in the 'env' build environment.
+
+# Import build environment variable from SConstruct.
+Import('env')
+
+###################################################
+#
+# Define needed sources.
+#
+###################################################
+
+# Base sources used by all configurations.
+
+base_sources = Split('''
+ base/circlebuf.cc
+ base/copyright.cc
+ base/cprintf.cc
+ base/embedfile.cc
+ base/fast_alloc.cc
+ base/fifo_buffer.cc
+ base/hostinfo.cc
+ base/hybrid_pred.cc
+ base/inifile.cc
+ base/intmath.cc
+ base/match.cc
+ base/misc.cc
+ base/output.cc
+ base/pollevent.cc
+ base/range.cc
+ base/random.cc
+ base/sat_counter.cc
+ base/serializer.cc
+ base/socket.cc
+ base/statistics.cc
+ base/str.cc
+ base/time.cc
+ base/trace.cc
+ base/traceflags.cc
+ base/userinfo.cc
+ base/compression/lzss_compression.cc
+ base/loader/aout_object.cc
+ base/loader/ecoff_object.cc
+ base/loader/elf_object.cc
+ base/loader/object_file.cc
+ base/loader/symtab.cc
+ base/stats/events.cc
+ base/stats/statdb.cc
+ base/stats/visit.cc
+ base/stats/text.cc
+
+ cpu/activity.cc
+ cpu/base.cc
+ cpu/cpu_exec_context.cc
+ cpu/cpuevent.cc
+ cpu/exetrace.cc
+ cpu/op_class.cc
+ cpu/pc_event.cc
+ cpu/quiesce_event.cc
+ cpu/static_inst.cc
+ cpu/sampler/sampler.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
+
+ sim/builder.cc
+ sim/configfile.cc
+ sim/debug.cc
+ sim/eventq.cc
+ sim/faults.cc
+ sim/main.cc
+ sim/param.cc
+ sim/profile.cc
+ sim/root.cc
+ sim/serialize.cc
+ sim/sim_events.cc
+ sim/sim_exit.cc
+ sim/sim_object.cc
+ sim/startup.cc
+ sim/stat_context.cc
+ sim/stat_control.cc
+ sim/system.cc
+ sim/trace_context.cc
+ ''')
+
+# Old FullCPU sources
+full_cpu_sources = Split('''
+ encumbered/cpu/full/bpred.cc
+ encumbered/cpu/full/commit.cc
+ encumbered/cpu/full/cpu.cc
+ encumbered/cpu/full/create_vector.cc
+ encumbered/cpu/full/cv_spec_state.cc
+ encumbered/cpu/full/dd_queue.cc
+ encumbered/cpu/full/dep_link.cc
+ encumbered/cpu/full/dispatch.cc
+ encumbered/cpu/full/dyn_inst.cc
+ encumbered/cpu/full/execute.cc
+ encumbered/cpu/full/fetch.cc
+ encumbered/cpu/full/floss_reasons.cc
+ encumbered/cpu/full/fu_pool.cc
+ encumbered/cpu/full/inst_fifo.cc
+ encumbered/cpu/full/instpipe.cc
+ encumbered/cpu/full/issue.cc
+ encumbered/cpu/full/ls_queue.cc
+ encumbered/cpu/full/machine_queue.cc
+ encumbered/cpu/full/pipetrace.cc
+ encumbered/cpu/full/readyq.cc
+ encumbered/cpu/full/reg_info.cc
+ encumbered/cpu/full/rob_station.cc
+ encumbered/cpu/full/spec_memory.cc
+ encumbered/cpu/full/spec_state.cc
+ encumbered/cpu/full/storebuffer.cc
+ encumbered/cpu/full/writeback.cc
+ encumbered/cpu/full/iq/iq_station.cc
+ encumbered/cpu/full/iq/iqueue.cc
+ encumbered/cpu/full/iq/segmented/chain_info.cc
+ encumbered/cpu/full/iq/segmented/chain_wire.cc
+ encumbered/cpu/full/iq/segmented/iq_seg.cc
+ encumbered/cpu/full/iq/segmented/iq_segmented.cc
+ encumbered/cpu/full/iq/segmented/seg_chain.cc
+ encumbered/cpu/full/iq/seznec/iq_seznec.cc
+ encumbered/cpu/full/iq/standard/iq_standard.cc
+ ''')
+
+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
+ base/stats/mysql.cc
+ ''')
+
+# Full-system sources
+full_system_sources = Split('''
+ base/crc.cc
+ base/inet.cc
+ base/remote_gdb.cc
+
+ cpu/intr_control.cc
+ cpu/profile.cc
+
+ dev/alpha_console.cc
+ dev/baddev.cc
+ dev/disk_image.cc
+ dev/etherbus.cc
+ dev/etherdump.cc
+ dev/etherint.cc
+ dev/etherlink.cc
+ dev/etherpkt.cc
+ dev/ethertap.cc
+ dev/ide_ctrl.cc
+ dev/ide_disk.cc
+ dev/io_device.cc
+ dev/isa_fake.cc
+ dev/ns_gige.cc
+ dev/pciconfigall.cc
+ dev/pcidev.cc
+ dev/pcifake.cc
+ dev/pktfifo.cc
+ dev/platform.cc
+ dev/simconsole.cc
+ dev/simple_disk.cc
+ dev/sinic.cc
+ dev/tsunami.cc
+ dev/tsunami_cchip.cc
+ dev/tsunami_io.cc
+ dev/tsunami_fake.cc
+ dev/tsunami_pchip.cc
+
+ dev/uart.cc
+ dev/uart8250.cc
+
+ kern/kernel_binning.cc
+ kern/kernel_stats.cc
+ kern/system_events.cc
+ 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
+ ''')
+
+# turbolaser encumbered sources
+turbolaser_sources = Split('''
+ encumbered/dev/dma.cc
+ encumbered/dev/etherdev.cc
+ encumbered/dev/scsi.cc
+ encumbered/dev/scsi_ctrl.cc
+ encumbered/dev/scsi_disk.cc
+ encumbered/dev/scsi_none.cc
+ encumbered/dev/tlaser_clock.cc
+ encumbered/dev/tlaser_ipi.cc
+ encumbered/dev/tlaser_mbox.cc
+ encumbered/dev/tlaser_mc146818.cc
+ encumbered/dev/tlaser_node.cc
+ encumbered/dev/tlaser_pcia.cc
+ encumbered/dev/tlaser_pcidev.cc
+ encumbered/dev/tlaser_serial.cc
+ encumbered/dev/turbolaser.cc
+ encumbered/dev/uart8530.cc
+ ''')
+
+# Syscall emulation (non-full-system) sources
+syscall_emulation_sources = Split('''
+ 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())])
+
+arch_sources = SConscript('arch/SConscript',
+ exports = 'env', duplicate = False)
+
+cpu_sources = SConscript('cpu/SConscript',
+ exports = 'env', duplicate = False)
+
+# This is outside of cpu/SConscript since the source directory isn't
+# underneath 'cpu'.
+if 'FullCPU' in env['CPU_MODELS']:
+ cpu_sources += full_cpu_sources
+
+# Set up complete list of sources based on configuration.
+sources = base_sources + arch_sources + cpu_sources
+
+if env['FULL_SYSTEM']:
+ sources += full_system_sources
+ if env['ALPHA_TLASER']:
+ sources += turbolaser_sources
+else:
+ sources += syscall_emulation_sources
+
+if env['USE_MYSQL']:
+ sources += mysql_sources
+
+for opt in env.ExportOptions:
+ env.ConfigFile(opt)
+
+###################################################
+#
+# Special build rules.
+#
+###################################################
+
+# base/traceflags.{cc,hh} are generated from base/traceflags.py.
+# $TARGET.base will expand to "<build-dir>/base/traceflags".
+env.Command(Split('base/traceflags.hh base/traceflags.cc'),
+ 'base/traceflags.py',
+ 'python $SOURCE $TARGET.base')
+
+SConscript('python/SConscript', exports = ['env'], duplicate=0)
+
+# This function adds the specified sources to the given build
+# environment, and returns a list of all the corresponding SCons
+# Object nodes (including an extra one for date.cc). We explicitly
+# add the Object nodes so we can set up special dependencies for
+# date.cc.
+def make_objs(sources, env):
+ objs = [env.Object(s) for s in sources]
+ # make date.cc depend on all other objects so it always gets
+ # recompiled whenever anything else does
+ date_obj = env.Object('base/date.cc')
+ env.Depends(date_obj, objs)
+ objs.append(date_obj)
+ return objs
+
+###################################################
+#
+# Define binaries. Each different build type (debug, opt, etc.) gets
+# a slightly different build environment.
+#
+###################################################
+
+# Include file paths are rooted in this directory. SCons will
+# automatically expand '.' to refer to both the source directory and
+# the corresponding build directory to pick up generated include
+# files.
+env.Append(CPPPATH='.')
+
+# Debug binary
+debugEnv = env.Copy(OBJSUFFIX='.do')
+debugEnv.Label = 'debug'
+debugEnv.Append(CCFLAGS=Split('-g3 -gdwarf-2 -O0'))
+debugEnv.Append(CPPDEFINES='DEBUG')
+tlist = debugEnv.Program(target = 'm5.debug',
+ source = make_objs(sources, debugEnv))
+debugEnv.M5Binary = tlist[0]
+
+# Optimized binary
+optEnv = env.Copy()
+optEnv.Label = 'opt'
+optEnv.Append(CCFLAGS=Split('-g -O3'))
+tlist = optEnv.Program(target = 'm5.opt',
+ source = make_objs(sources, optEnv))
+optEnv.M5Binary = tlist[0]
+
+# "Fast" binary
+fastEnv = env.Copy(OBJSUFFIX='.fo')
+fastEnv.Label = 'fast'
+fastEnv.Append(CCFLAGS=Split('-O3'))
+fastEnv.Append(CPPDEFINES='NDEBUG')
+fastEnv.Program(target = 'm5.fast.unstripped',
+ source = make_objs(sources, fastEnv))
+tlist = fastEnv.Command(target = 'm5.fast',
+ source = 'm5.fast.unstripped',
+ action = 'strip $SOURCE -o $TARGET')
+fastEnv.M5Binary = tlist[0]
+
+# Profiled binary
+profEnv = env.Copy(OBJSUFFIX='.po')
+profEnv.Label = 'prof'
+profEnv.Append(CCFLAGS=Split('-O3 -g -pg'), LINKFLAGS='-pg')
+tlist = profEnv.Program(target = 'm5.prof',
+ source = make_objs(sources, profEnv))
+profEnv.M5Binary = tlist[0]
+
+envList = [debugEnv, optEnv, fastEnv, profEnv]
+
+Return('envList')
diff --git a/src/arch/SConscript b/src/arch/SConscript
new file mode 100644
index 000000000..9c193207f
--- /dev/null
+++ b/src/arch/SConscript
@@ -0,0 +1,150 @@
+# -*- mode:python -*-
+
+# Copyright (c) 2006 The Regents of The University of Michigan
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met: redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer;
+# redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution;
+# neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import os.path
+
+# Import build environment variable from SConstruct.
+Import('env')
+
+# Right now there are no source files immediately in this directory
+sources = []
+
+#################################################################
+#
+# ISA "switch header" generation.
+#
+# Auto-generate arch headers that include the right ISA-specific
+# header based on the setting of THE_ISA preprocessor variable.
+#
+#################################################################
+
+# List of headers to generate
+isa_switch_hdrs = Split('''
+ arguments.hh
+ constants.hh
+ faults.hh
+ isa_traits.hh
+ process.hh
+ regfile.hh
+ stacktrace.hh
+ tlb.hh
+ types.hh
+ utility.hh
+ vtophys.hh
+ ''')
+
+# Generate the header. target[0] is the full path of the output
+# header to generate. 'source' is a dummy variable, since we get the
+# list of ISAs from env['ALL_ISA_LIST'].
+def gen_switch_hdr(target, source, env):
+ fname = str(target[0])
+ basename = os.path.basename(fname)
+ f = open(fname, 'w')
+ f.write('#include "arch/isa_specific.hh"\n')
+ cond = '#if'
+ for isa in env['ALL_ISA_LIST']:
+ f.write('%s THE_ISA == %s_ISA\n#include "arch/%s/%s"\n'
+ % (cond, isa.upper(), isa, basename))
+ cond = '#elif'
+ f.write('#else\n#error "THE_ISA not set"\n#endif\n')
+ f.close()
+ return 0
+
+# String to print when generating header
+def gen_switch_hdr_string(target, source, env):
+ return "Generating ISA switch header " + str(target[0])
+
+# Build SCons Action object. 'varlist' specifies env vars that this
+# action depends on; when env['ALL_ISA_LIST'] changes these actions
+# should get re-executed.
+switch_hdr_action = Action(gen_switch_hdr, gen_switch_hdr_string,
+ varlist=['ALL_ISA_LIST'])
+
+# Instantiate actions for each header
+for hdr in isa_switch_hdrs:
+ env.Command(hdr, [], switch_hdr_action)
+
+#################################################################
+#
+# Include architecture-specific files.
+#
+#################################################################
+
+#
+# Build a SCons scanner for ISA files
+#
+import SCons.Scanner
+
+isa_scanner = SCons.Scanner.Classic("ISAScan",
+ [".isa", ".ISA"],
+ "SRCDIR",
+ r'^\s*##include\s+"([\w/.-]*)"')
+
+env.Append(SCANNERS = isa_scanner)
+
+#
+# Now create a Builder object that uses isa_parser.py to generate C++
+# output from the ISA description (*.isa) files.
+#
+
+# Convert to File node to fix path
+isa_parser = File('isa_parser.py')
+cpu_models_file = File('../cpu/cpu_models.py')
+
+# This sucks in the defintions of the CpuModel objects.
+execfile(cpu_models_file.srcnode().abspath)
+
+# Several files are generated from the ISA description.
+# We always get the basic decoder and header file.
+isa_desc_gen_files = Split('decoder.cc decoder.hh')
+# We also get an execute file for each selected CPU model.
+isa_desc_gen_files += [CpuModel.dict[cpu].filename
+ for cpu in env['CPU_MODELS']]
+
+# The emitter patches up the sources & targets to include the
+# autogenerated files as targets and isa parser itself as a source.
+def isa_desc_emitter(target, source, env):
+ return (isa_desc_gen_files, [isa_parser, cpu_models_file] + source)
+
+# Pieces are in place, so create the builder.
+isa_desc_builder = Builder(action='python2.4 $SOURCES $TARGET.dir $CPU_MODELS',
+ emitter = isa_desc_emitter)
+
+env.Append(BUILDERS = { 'ISADesc' : isa_desc_builder })
+
+#
+# Now include other ISA-specific sources from the ISA subdirectories.
+#
+
+isa = env['TARGET_ISA'] # someday this may be a list of ISAs
+
+# Let the target architecture define what additional sources it needs
+sources += SConscript(os.path.join(isa, 'SConscript'),
+ exports = 'env', duplicate = False)
+
+Return('sources')
diff --git a/src/arch/alpha/SConscript b/src/arch/alpha/SConscript
new file mode 100644
index 000000000..1b20f8b1f
--- /dev/null
+++ b/src/arch/alpha/SConscript
@@ -0,0 +1,93 @@
+# -*- mode:python -*-
+
+# Copyright (c) 2004-2005 The Regents of The University of Michigan
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met: redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer;
+# redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution;
+# neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import os
+import sys
+from os.path import isdir
+
+# This file defines how to build a particular configuration of M5
+# based on variable settings in the 'env' build environment.
+
+# Import build environment variable from SConstruct.
+Import('env')
+
+###################################################
+#
+# Define needed sources.
+#
+###################################################
+
+# Base sources used by all configurations.
+base_sources = Split('''
+ faults.cc
+ isa_traits.cc
+ ''')
+
+# Full-system sources
+full_system_sources = Split('''
+ tlb.cc
+ arguments.cc
+ ev5.cc
+ osfpal.cc
+ stacktrace.cc
+ vtophys.cc
+ system.cc
+ freebsd/system.cc
+ linux/system.cc
+ tru64/system.cc
+ ''')
+
+
+# Syscall emulation (non-full-system) sources
+syscall_emulation_sources = Split('''
+ linux/linux.cc
+ linux/process.cc
+ tru64/tru64.cc
+ tru64/process.cc
+ process.cc
+ ''')
+
+# Set up complete list of sources based on configuration.
+sources = base_sources
+
+if env['FULL_SYSTEM']:
+ sources += full_system_sources
+else:
+ sources += syscall_emulation_sources
+
+# Convert file names to SCons File objects. This takes care of the
+# path relative to the top of the directory tree.
+sources = [File(s) for s in sources]
+
+# Add in files generated by the ISA description.
+isa_desc_files = env.ISADesc('isa/main.isa')
+# Only non-header files need to be compiled.
+isa_desc_sources = [f for f in isa_desc_files if not f.path.endswith('.hh')]
+sources += isa_desc_sources
+
+Return('sources')
diff --git a/arch/alpha/aout_machdep.h b/src/arch/alpha/aout_machdep.h
index df9d9ac6a..df9d9ac6a 100644
--- a/arch/alpha/aout_machdep.h
+++ b/src/arch/alpha/aout_machdep.h
diff --git a/src/arch/alpha/arguments.cc b/src/arch/alpha/arguments.cc
new file mode 100644
index 000000000..adc371682
--- /dev/null
+++ b/src/arch/alpha/arguments.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/alpha/arguments.hh"
+#include "arch/alpha/vtophys.hh"
+#include "cpu/exec_context.hh"
+#include "mem/vport.hh"
+
+using namespace AlphaISA;
+
+AlphaArguments::Data::~Data()
+{
+ while (!data.empty()) {
+ delete [] data.front();
+ data.pop_front();
+ }
+}
+
+char *
+AlphaArguments::Data::alloc(size_t size)
+{
+ char *buf = new char[size];
+ data.push_back(buf);
+ return buf;
+}
+
+uint64_t
+AlphaArguments::getArg(bool fp)
+{
+ if (number < 6) {
+ if (fp)
+ return xc->readFloatRegBits(16 + number);
+ else
+ return xc->readIntReg(16 + number);
+ } else {
+ Addr sp = xc->readIntReg(30);
+ 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/src/arch/alpha/arguments.hh b/src/arch/alpha/arguments.hh
new file mode 100644
index 000000000..bd1c6cb1d
--- /dev/null
+++ b/src/arch/alpha/arguments.hh
@@ -0,0 +1,147 @@
+/*
+ * 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_ARGUMENTS_HH__
+#define __ARCH_ALPHA_ARGUMENTS_HH__
+
+#include <assert.h>
+
+#include "arch/alpha/vtophys.hh"
+#include "base/refcnt.hh"
+#include "sim/host.hh"
+
+class ExecContext;
+
+namespace AlphaISA {
+
+class AlphaArguments
+{
+ protected:
+ ExecContext *xc;
+ int number;
+ uint64_t getArg(bool fp = false);
+
+ protected:
+ class Data : public RefCounted
+ {
+ public:
+ Data(){}
+ ~Data();
+
+ private:
+ std::list<char *> data;
+
+ public:
+ char *alloc(size_t size);
+ };
+
+ RefCountingPtr<Data> data;
+
+ public:
+ AlphaArguments(ExecContext *ctx, int n = 0)
+ : xc(ctx), number(n), data(NULL)
+ { assert(number >= 0); data = new Data;}
+ AlphaArguments(const AlphaArguments &args)
+ : xc(args.xc), number(args.number), data(args.data) {}
+ ~AlphaArguments() {}
+
+ ExecContext *getExecContext() const { return xc; }
+
+ const AlphaArguments &operator=(const AlphaArguments &args) {
+ xc = args.xc;
+ number = args.number;
+ data = args.data;
+ return *this;
+ }
+
+ AlphaArguments &operator++() {
+ ++number;
+ assert(number >= 0);
+ return *this;
+ }
+
+ AlphaArguments operator++(int) {
+ AlphaArguments args = *this;
+ ++number;
+ assert(number >= 0);
+ return args;
+ }
+
+ AlphaArguments &operator--() {
+ --number;
+ assert(number >= 0);
+ return *this;
+ }
+
+ AlphaArguments operator--(int) {
+ AlphaArguments args = *this;
+ --number;
+ assert(number >= 0);
+ return args;
+ }
+
+ const AlphaArguments &operator+=(int index) {
+ number += index;
+ assert(number >= 0);
+ return *this;
+ }
+
+ const AlphaArguments &operator-=(int index) {
+ number -= index;
+ assert(number >= 0);
+ return *this;
+ }
+
+ AlphaArguments operator[](int index) {
+ return AlphaArguments(xc, index);
+ }
+
+ template <class T>
+ operator T() {
+ assert(sizeof(T) <= sizeof(uint64_t));
+ T data = static_cast<T>(getArg());
+ return data;
+ }
+
+ template <class T>
+ operator T *() {
+ T *buf = (T *)data->alloc(sizeof(T));
+ CopyData(xc, buf, getArg(), sizeof(T));
+ return buf;
+ }
+
+ operator char *() {
+ char *buf = data->alloc(2048);
+ CopyStringOut(xc, buf, getArg(), 2048);
+ return buf;
+ }
+};
+
+}; // namespace AlphaISA
+
+#endif // __ARCH_ALPHA_ARGUMENTS_HH__
diff --git a/arch/alpha/ecoff_machdep.h b/src/arch/alpha/ecoff_machdep.h
index 9341b8ff7..9341b8ff7 100644
--- a/arch/alpha/ecoff_machdep.h
+++ b/src/arch/alpha/ecoff_machdep.h
diff --git a/src/arch/alpha/ev5.cc b/src/arch/alpha/ev5.cc
new file mode 100644
index 000000000..a242282ec
--- /dev/null
+++ b/src/arch/alpha/ev5.cc
@@ -0,0 +1,584 @@
+/*
+ * Copyright (c) 2002-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "arch/alpha/tlb.hh"
+#include "arch/alpha/isa_traits.hh"
+#include "arch/alpha/osfpal.hh"
+#include "base/kgdb.h"
+#include "base/remote_gdb.hh"
+#include "base/stats/events.hh"
+#include "config/full_system.hh"
+#include "cpu/base.hh"
+#include "cpu/cpu_exec_context.hh"
+#include "cpu/exec_context.hh"
+#include "kern/kernel_stats.hh"
+#include "sim/debug.hh"
+#include "sim/sim_events.hh"
+
+#if FULL_SYSTEM
+
+using namespace EV5;
+
+////////////////////////////////////////////////////////////////////////
+//
+// Machine dependent functions
+//
+void
+AlphaISA::initCPU(ExecContext *xc, int cpuId)
+{
+ initIPRs(xc, cpuId);
+
+ xc->setIntReg(16, cpuId);
+ xc->setIntReg(0, cpuId);
+
+ xc->setPC(xc->readMiscReg(IPR_PAL_BASE) + (new ResetFault)->vect());
+ xc->setNextPC(xc->readPC() + sizeof(MachInst));
+}
+
+////////////////////////////////////////////////////////////////////////
+//
+//
+//
+void
+AlphaISA::initIPRs(ExecContext *xc, int cpuId)
+{
+ for (int i = 0; i < NumInternalProcRegs; ++i) {
+ xc->setMiscReg(i, 0);
+ }
+
+ xc->setMiscReg(IPR_PAL_BASE, PalBase);
+ xc->setMiscReg(IPR_MCSR, 0x6);
+ xc->setMiscReg(IPR_PALtemp16, cpuId);
+}
+
+
+template <class CPU>
+void
+AlphaISA::processInterrupts(CPU *cpu)
+{
+ //Check if there are any outstanding interrupts
+ //Handle the interrupts
+ int ipl = 0;
+ int summary = 0;
+
+ cpu->checkInterrupts = false;
+
+ if (cpu->readMiscReg(IPR_ASTRR))
+ panic("asynchronous traps not implemented\n");
+
+ if (cpu->readMiscReg(IPR_SIRR)) {
+ for (int i = INTLEVEL_SOFTWARE_MIN;
+ i < INTLEVEL_SOFTWARE_MAX; i++) {
+ if (cpu->readMiscReg(IPR_SIRR) & (ULL(1) << i)) {
+ // See table 4-19 of the 21164 hardware reference
+ ipl = (i - INTLEVEL_SOFTWARE_MIN) + 1;
+ summary |= (ULL(1) << i);
+ }
+ }
+ }
+
+ uint64_t interrupts = cpu->intr_status();
+
+ if (interrupts) {
+ for (int i = INTLEVEL_EXTERNAL_MIN;
+ i < INTLEVEL_EXTERNAL_MAX; i++) {
+ if (interrupts & (ULL(1) << i)) {
+ // See table 4-19 of the 21164 hardware reference
+ ipl = i;
+ summary |= (ULL(1) << i);
+ }
+ }
+ }
+
+ if (ipl && ipl > cpu->readMiscReg(IPR_IPLR)) {
+ cpu->setMiscReg(IPR_ISR, summary);
+ cpu->setMiscReg(IPR_INTID, ipl);
+ cpu->trap(new InterruptFault);
+ DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n",
+ cpu->readMiscReg(IPR_IPLR), ipl, summary);
+ }
+
+}
+
+template <class CPU>
+void
+AlphaISA::zeroRegisters(CPU *cpu)
+{
+ // Insure ISA semantics
+ // (no longer very clean due to the change in setIntReg() in the
+ // cpu model. Consider changing later.)
+ cpu->cpuXC->setIntReg(ZeroReg, 0);
+ cpu->cpuXC->setFloatReg(ZeroReg, 0.0);
+}
+
+Fault
+CPUExecContext::hwrei()
+{
+ if (!inPalMode())
+ return new UnimplementedOpcodeFault;
+
+ setNextPC(readMiscReg(AlphaISA::IPR_EXC_ADDR));
+
+ if (!misspeculating()) {
+ if (kernelStats)
+ kernelStats->hwrei();
+
+ cpu->checkInterrupts = true;
+ }
+
+ // FIXME: XXX check for interrupts? XXX
+ return NoFault;
+}
+
+int
+AlphaISA::MiscRegFile::getInstAsid()
+{
+ return EV5::ITB_ASN_ASN(ipr[IPR_ITB_ASN]);
+}
+
+int
+AlphaISA::MiscRegFile::getDataAsid()
+{
+ return EV5::DTB_ASN_ASN(ipr[IPR_DTB_ASN]);
+}
+
+AlphaISA::MiscReg
+AlphaISA::MiscRegFile::readIpr(int idx, Fault &fault, ExecContext *xc)
+{
+ uint64_t retval = 0; // return value, default 0
+
+ switch (idx) {
+ case AlphaISA::IPR_PALtemp0:
+ case AlphaISA::IPR_PALtemp1:
+ case AlphaISA::IPR_PALtemp2:
+ case AlphaISA::IPR_PALtemp3:
+ case AlphaISA::IPR_PALtemp4:
+ case AlphaISA::IPR_PALtemp5:
+ case AlphaISA::IPR_PALtemp6:
+ case AlphaISA::IPR_PALtemp7:
+ case AlphaISA::IPR_PALtemp8:
+ case AlphaISA::IPR_PALtemp9:
+ case AlphaISA::IPR_PALtemp10:
+ case AlphaISA::IPR_PALtemp11:
+ case AlphaISA::IPR_PALtemp12:
+ case AlphaISA::IPR_PALtemp13:
+ case AlphaISA::IPR_PALtemp14:
+ case AlphaISA::IPR_PALtemp15:
+ case AlphaISA::IPR_PALtemp16:
+ case AlphaISA::IPR_PALtemp17:
+ case AlphaISA::IPR_PALtemp18:
+ case AlphaISA::IPR_PALtemp19:
+ case AlphaISA::IPR_PALtemp20:
+ case AlphaISA::IPR_PALtemp21:
+ case AlphaISA::IPR_PALtemp22:
+ case AlphaISA::IPR_PALtemp23:
+ case AlphaISA::IPR_PAL_BASE:
+
+ case AlphaISA::IPR_IVPTBR:
+ case AlphaISA::IPR_DC_MODE:
+ case AlphaISA::IPR_MAF_MODE:
+ case AlphaISA::IPR_ISR:
+ case AlphaISA::IPR_EXC_ADDR:
+ case AlphaISA::IPR_IC_PERR_STAT:
+ case AlphaISA::IPR_DC_PERR_STAT:
+ case AlphaISA::IPR_MCSR:
+ case AlphaISA::IPR_ASTRR:
+ case AlphaISA::IPR_ASTER:
+ case AlphaISA::IPR_SIRR:
+ case AlphaISA::IPR_ICSR:
+ case AlphaISA::IPR_ICM:
+ case AlphaISA::IPR_DTB_CM:
+ case AlphaISA::IPR_IPLR:
+ case AlphaISA::IPR_INTID:
+ case AlphaISA::IPR_PMCTR:
+ // no side-effect
+ retval = ipr[idx];
+ break;
+
+ case AlphaISA::IPR_CC:
+ retval |= ipr[idx] & ULL(0xffffffff00000000);
+ retval |= xc->getCpuPtr()->curCycle() & ULL(0x00000000ffffffff);
+ break;
+
+ case AlphaISA::IPR_VA:
+ retval = ipr[idx];
+ break;
+
+ case AlphaISA::IPR_VA_FORM:
+ case AlphaISA::IPR_MM_STAT:
+ case AlphaISA::IPR_IFAULT_VA_FORM:
+ case AlphaISA::IPR_EXC_MASK:
+ case AlphaISA::IPR_EXC_SUM:
+ retval = ipr[idx];
+ break;
+
+ case AlphaISA::IPR_DTB_PTE:
+ {
+ AlphaISA::PTE &pte = xc->getDTBPtr()->index(!xc->misspeculating());
+
+ retval |= ((u_int64_t)pte.ppn & ULL(0x7ffffff)) << 32;
+ retval |= ((u_int64_t)pte.xre & ULL(0xf)) << 8;
+ retval |= ((u_int64_t)pte.xwe & ULL(0xf)) << 12;
+ retval |= ((u_int64_t)pte.fonr & ULL(0x1)) << 1;
+ retval |= ((u_int64_t)pte.fonw & ULL(0x1))<< 2;
+ retval |= ((u_int64_t)pte.asma & ULL(0x1)) << 4;
+ retval |= ((u_int64_t)pte.asn & ULL(0x7f)) << 57;
+ }
+ break;
+
+ // write only registers
+ case AlphaISA::IPR_HWINT_CLR:
+ case AlphaISA::IPR_SL_XMIT:
+ case AlphaISA::IPR_DC_FLUSH:
+ case AlphaISA::IPR_IC_FLUSH:
+ case AlphaISA::IPR_ALT_MODE:
+ case AlphaISA::IPR_DTB_IA:
+ case AlphaISA::IPR_DTB_IAP:
+ case AlphaISA::IPR_ITB_IA:
+ case AlphaISA::IPR_ITB_IAP:
+ fault = new UnimplementedOpcodeFault;
+ break;
+
+ default:
+ // invalid IPR
+ fault = new UnimplementedOpcodeFault;
+ break;
+ }
+
+ return retval;
+}
+
+#ifdef DEBUG
+// Cause the simulator to break when changing to the following IPL
+int break_ipl = -1;
+#endif
+
+Fault
+AlphaISA::MiscRegFile::setIpr(int idx, uint64_t val, ExecContext *xc)
+{
+ uint64_t old;
+
+ if (xc->misspeculating())
+ return NoFault;
+
+ switch (idx) {
+ case AlphaISA::IPR_PALtemp0:
+ case AlphaISA::IPR_PALtemp1:
+ case AlphaISA::IPR_PALtemp2:
+ case AlphaISA::IPR_PALtemp3:
+ case AlphaISA::IPR_PALtemp4:
+ case AlphaISA::IPR_PALtemp5:
+ case AlphaISA::IPR_PALtemp6:
+ case AlphaISA::IPR_PALtemp7:
+ case AlphaISA::IPR_PALtemp8:
+ case AlphaISA::IPR_PALtemp9:
+ case AlphaISA::IPR_PALtemp10:
+ case AlphaISA::IPR_PALtemp11:
+ case AlphaISA::IPR_PALtemp12:
+ case AlphaISA::IPR_PALtemp13:
+ case AlphaISA::IPR_PALtemp14:
+ case AlphaISA::IPR_PALtemp15:
+ case AlphaISA::IPR_PALtemp16:
+ case AlphaISA::IPR_PALtemp17:
+ case AlphaISA::IPR_PALtemp18:
+ case AlphaISA::IPR_PALtemp19:
+ case AlphaISA::IPR_PALtemp20:
+ case AlphaISA::IPR_PALtemp21:
+ case AlphaISA::IPR_PALtemp22:
+ case AlphaISA::IPR_PAL_BASE:
+ case AlphaISA::IPR_IC_PERR_STAT:
+ case AlphaISA::IPR_DC_PERR_STAT:
+ case AlphaISA::IPR_PMCTR:
+ // write entire quad w/ no side-effect
+ ipr[idx] = val;
+ break;
+
+ case AlphaISA::IPR_CC_CTL:
+ // This IPR resets the cycle counter. We assume this only
+ // happens once... let's verify that.
+ assert(ipr[idx] == 0);
+ ipr[idx] = 1;
+ break;
+
+ case AlphaISA::IPR_CC:
+ // This IPR only writes the upper 64 bits. It's ok to write
+ // all 64 here since we mask out the lower 32 in rpcc (see
+ // isa_desc).
+ ipr[idx] = val;
+ break;
+
+ case AlphaISA::IPR_PALtemp23:
+ // write entire quad w/ no side-effect
+ old = ipr[idx];
+ ipr[idx] = val;
+ if (xc->getKernelStats())
+ xc->getKernelStats()->context(old, val, xc);
+ break;
+
+ case AlphaISA::IPR_DTB_PTE:
+ // write entire quad w/ no side-effect, tag is forthcoming
+ ipr[idx] = val;
+ break;
+
+ case AlphaISA::IPR_EXC_ADDR:
+ // second least significant bit in PC is always zero
+ ipr[idx] = val & ~2;
+ break;
+
+ case AlphaISA::IPR_ASTRR:
+ case AlphaISA::IPR_ASTER:
+ // only write least significant four bits - privilege mask
+ ipr[idx] = val & 0xf;
+ break;
+
+ case AlphaISA::IPR_IPLR:
+#ifdef DEBUG
+ if (break_ipl != -1 && break_ipl == (val & 0x1f))
+ debug_break();
+#endif
+
+ // only write least significant five bits - interrupt level
+ ipr[idx] = val & 0x1f;
+ if (xc->getKernelStats())
+ xc->getKernelStats()->swpipl(ipr[idx]);
+ break;
+
+ case AlphaISA::IPR_DTB_CM:
+ if (val & 0x18) {
+ if (xc->getKernelStats())
+ xc->getKernelStats()->mode(Kernel::user, xc);
+ } else {
+ if (xc->getKernelStats())
+ xc->getKernelStats()->mode(Kernel::kernel, xc);
+ }
+
+ case AlphaISA::IPR_ICM:
+ // only write two mode bits - processor mode
+ ipr[idx] = val & 0x18;
+ break;
+
+ case AlphaISA::IPR_ALT_MODE:
+ // only write two mode bits - processor mode
+ ipr[idx] = val & 0x18;
+ break;
+
+ case AlphaISA::IPR_MCSR:
+ // more here after optimization...
+ ipr[idx] = val;
+ break;
+
+ case AlphaISA::IPR_SIRR:
+ // only write software interrupt mask
+ ipr[idx] = val & 0x7fff0;
+ break;
+
+ case AlphaISA::IPR_ICSR:
+ ipr[idx] = val & ULL(0xffffff0300);
+ break;
+
+ case AlphaISA::IPR_IVPTBR:
+ case AlphaISA::IPR_MVPTBR:
+ ipr[idx] = val & ULL(0xffffffffc0000000);
+ break;
+
+ case AlphaISA::IPR_DC_TEST_CTL:
+ ipr[idx] = val & 0x1ffb;
+ break;
+
+ case AlphaISA::IPR_DC_MODE:
+ case AlphaISA::IPR_MAF_MODE:
+ ipr[idx] = val & 0x3f;
+ break;
+
+ case AlphaISA::IPR_ITB_ASN:
+ ipr[idx] = val & 0x7f0;
+ break;
+
+ case AlphaISA::IPR_DTB_ASN:
+ ipr[idx] = val & ULL(0xfe00000000000000);
+ break;
+
+ case AlphaISA::IPR_EXC_SUM:
+ case AlphaISA::IPR_EXC_MASK:
+ // any write to this register clears it
+ ipr[idx] = 0;
+ break;
+
+ case AlphaISA::IPR_INTID:
+ case AlphaISA::IPR_SL_RCV:
+ case AlphaISA::IPR_MM_STAT:
+ case AlphaISA::IPR_ITB_PTE_TEMP:
+ case AlphaISA::IPR_DTB_PTE_TEMP:
+ // read-only registers
+ return new UnimplementedOpcodeFault;
+
+ case AlphaISA::IPR_HWINT_CLR:
+ case AlphaISA::IPR_SL_XMIT:
+ case AlphaISA::IPR_DC_FLUSH:
+ case AlphaISA::IPR_IC_FLUSH:
+ // the following are write only
+ ipr[idx] = val;
+ break;
+
+ case AlphaISA::IPR_DTB_IA:
+ // really a control write
+ ipr[idx] = 0;
+
+ xc->getDTBPtr()->flushAll();
+ break;
+
+ case AlphaISA::IPR_DTB_IAP:
+ // really a control write
+ ipr[idx] = 0;
+
+ xc->getDTBPtr()->flushProcesses();
+ break;
+
+ case AlphaISA::IPR_DTB_IS:
+ // really a control write
+ ipr[idx] = val;
+
+ xc->getDTBPtr()->flushAddr(val,
+ DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN]));
+ break;
+
+ case AlphaISA::IPR_DTB_TAG: {
+ struct AlphaISA::PTE pte;
+
+ // FIXME: granularity hints NYI...
+ if (DTB_PTE_GH(ipr[AlphaISA::IPR_DTB_PTE]) != 0)
+ panic("PTE GH field != 0");
+
+ // write entire quad
+ ipr[idx] = val;
+
+ // construct PTE for new entry
+ pte.ppn = DTB_PTE_PPN(ipr[AlphaISA::IPR_DTB_PTE]);
+ pte.xre = DTB_PTE_XRE(ipr[AlphaISA::IPR_DTB_PTE]);
+ pte.xwe = DTB_PTE_XWE(ipr[AlphaISA::IPR_DTB_PTE]);
+ pte.fonr = DTB_PTE_FONR(ipr[AlphaISA::IPR_DTB_PTE]);
+ pte.fonw = DTB_PTE_FONW(ipr[AlphaISA::IPR_DTB_PTE]);
+ pte.asma = DTB_PTE_ASMA(ipr[AlphaISA::IPR_DTB_PTE]);
+ pte.asn = DTB_ASN_ASN(ipr[AlphaISA::IPR_DTB_ASN]);
+
+ // insert new TAG/PTE value into data TLB
+ xc->getDTBPtr()->insert(val, pte);
+ }
+ break;
+
+ case AlphaISA::IPR_ITB_PTE: {
+ struct AlphaISA::PTE pte;
+
+ // FIXME: granularity hints NYI...
+ if (ITB_PTE_GH(val) != 0)
+ panic("PTE GH field != 0");
+
+ // write entire quad
+ ipr[idx] = val;
+
+ // construct PTE for new entry
+ pte.ppn = ITB_PTE_PPN(val);
+ pte.xre = ITB_PTE_XRE(val);
+ pte.xwe = 0;
+ pte.fonr = ITB_PTE_FONR(val);
+ pte.fonw = ITB_PTE_FONW(val);
+ pte.asma = ITB_PTE_ASMA(val);
+ pte.asn = ITB_ASN_ASN(ipr[AlphaISA::IPR_ITB_ASN]);
+
+ // insert new TAG/PTE value into data TLB
+ xc->getITBPtr()->insert(ipr[AlphaISA::IPR_ITB_TAG], pte);
+ }
+ break;
+
+ case AlphaISA::IPR_ITB_IA:
+ // really a control write
+ ipr[idx] = 0;
+
+ xc->getITBPtr()->flushAll();
+ break;
+
+ case AlphaISA::IPR_ITB_IAP:
+ // really a control write
+ ipr[idx] = 0;
+
+ xc->getITBPtr()->flushProcesses();
+ break;
+
+ case AlphaISA::IPR_ITB_IS:
+ // really a control write
+ ipr[idx] = val;
+
+ xc->getITBPtr()->flushAddr(val,
+ ITB_ASN_ASN(ipr[AlphaISA::IPR_ITB_ASN]));
+ break;
+
+ default:
+ // invalid IPR
+ return new UnimplementedOpcodeFault;
+ }
+
+ // no error...
+ return NoFault;
+}
+
+void
+AlphaISA::copyIprs(ExecContext *src, ExecContext *dest)
+{
+ for (int i = IPR_Base_DepTag; i < NumInternalProcRegs; ++i) {
+ dest->setMiscReg(i, src->readMiscReg(i));
+ }
+}
+
+/**
+ * Check for special simulator handling of specific PAL calls.
+ * If return value is false, actual PAL call will be suppressed.
+ */
+bool
+CPUExecContext::simPalCheck(int palFunc)
+{
+ if (kernelStats)
+ kernelStats->callpal(palFunc, proxy);
+
+ switch (palFunc) {
+ case PAL::halt:
+ halt();
+ if (--System::numSystemsRunning == 0)
+ new SimExitEvent("all cpus halted");
+ break;
+
+ case PAL::bpt:
+ case PAL::bugchk:
+ if (system->breakpoint())
+ return false;
+ break;
+ }
+
+ return true;
+}
+
+#endif // FULL_SYSTEM
diff --git a/arch/alpha/ev5.hh b/src/arch/alpha/ev5.hh
index 7c8465cfb..7c8465cfb 100644
--- a/arch/alpha/ev5.hh
+++ b/src/arch/alpha/ev5.hh
diff --git a/arch/alpha/faults.cc b/src/arch/alpha/faults.cc
index 0083aa9f3..0083aa9f3 100644
--- a/arch/alpha/faults.cc
+++ b/src/arch/alpha/faults.cc
diff --git a/arch/alpha/faults.hh b/src/arch/alpha/faults.hh
index e8ccc6b79..e8ccc6b79 100644
--- a/arch/alpha/faults.hh
+++ b/src/arch/alpha/faults.hh
diff --git a/src/arch/alpha/freebsd/system.cc b/src/arch/alpha/freebsd/system.cc
new file mode 100644
index 000000000..3e50fb9a5
--- /dev/null
+++ b/src/arch/alpha/freebsd/system.cc
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * Modifications for the FreeBSD kernel.
+ * Based on kern/linux/linux_system.cc.
+ *
+ */
+
+#include "arch/alpha/system.hh"
+#include "arch/alpha/freebsd/system.hh"
+#include "base/loader/symtab.hh"
+#include "cpu/exec_context.hh"
+#include "mem/physical.hh"
+#include "mem/port.hh"
+#include "arch/isa_traits.hh"
+#include "sim/builder.hh"
+#include "sim/byteswap.hh"
+#include "arch/vtophys.hh"
+
+#define TIMER_FREQUENCY 1193180
+
+using namespace std;
+using namespace AlphaISA;
+
+FreebsdAlphaSystem::FreebsdAlphaSystem(Params *p)
+ : AlphaSystem(p)
+{
+ /**
+ * Any time DELAY is called just skip the function.
+ * Shouldn't we actually emulate the delay?
+ */
+ skipDelayEvent = addKernelFuncEvent<SkipFuncEvent>("DELAY");
+ skipCalibrateClocks =
+ addKernelFuncEvent<SkipCalibrateClocksEvent>("calibrate_clocks");
+}
+
+
+FreebsdAlphaSystem::~FreebsdAlphaSystem()
+{
+ delete skipDelayEvent;
+ delete skipCalibrateClocks;
+}
+
+
+void
+FreebsdAlphaSystem::doCalibrateClocks(ExecContext *xc)
+{
+ Addr ppc_vaddr = 0;
+ Addr timer_vaddr = 0;
+
+ ppc_vaddr = (Addr)xc->readIntReg(ArgumentReg1);
+ timer_vaddr = (Addr)xc->readIntReg(ArgumentReg2);
+
+ virtPort.write(ppc_vaddr, (uint32_t)Clock::Frequency);
+ virtPort.write(timer_vaddr, (uint32_t)TIMER_FREQUENCY);
+}
+
+
+void
+FreebsdAlphaSystem::SkipCalibrateClocksEvent::process(ExecContext *xc)
+{
+ SkipFuncEvent::process(xc);
+ ((FreebsdAlphaSystem *)xc->getSystemPtr())->doCalibrateClocks(xc);
+}
+
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(FreebsdAlphaSystem)
+
+ Param<Tick> boot_cpu_frequency;
+ SimObjectParam<PhysicalMemory *> physmem;
+
+ Param<string> kernel;
+ Param<string> console;
+ Param<string> pal;
+
+ Param<string> boot_osflags;
+ Param<string> readfile;
+ Param<unsigned int> init_param;
+
+ Param<uint64_t> system_type;
+ Param<uint64_t> system_rev;
+
+ Param<bool> bin;
+ VectorParam<string> binned_fns;
+ Param<bool> bin_int;
+
+END_DECLARE_SIM_OBJECT_PARAMS(FreebsdAlphaSystem)
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(FreebsdAlphaSystem)
+
+ 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(console, "file that contains the console code"),
+ INIT_PARAM(pal, "file that contains palcode"),
+ INIT_PARAM_DFLT(boot_osflags, "flags to pass to the kernel during boot",
+ "a"),
+ INIT_PARAM_DFLT(readfile, "file to read startup script from", ""),
+ INIT_PARAM_DFLT(init_param, "numerical value to pass into simulator", 0),
+ INIT_PARAM_DFLT(system_type, "Type of system we are emulating", 34),
+ INIT_PARAM_DFLT(system_rev, "Revision of system we are emulating", 1<<10),
+ INIT_PARAM_DFLT(bin, "is this system to be binned", false),
+ INIT_PARAM(binned_fns, "functions to be broken down and binned"),
+ INIT_PARAM_DFLT(bin_int, "is interrupt code binned seperately?", true)
+
+END_INIT_SIM_OBJECT_PARAMS(FreebsdAlphaSystem)
+
+CREATE_SIM_OBJECT(FreebsdAlphaSystem)
+{
+ AlphaSystem::Params *p = new AlphaSystem::Params;
+ p->name = getInstanceName();
+ p->boot_cpu_frequency = boot_cpu_frequency;
+ p->physmem = physmem;
+ p->kernel_path = kernel;
+ p->console_path = console;
+ p->palcode = pal;
+ p->boot_osflags = boot_osflags;
+ p->init_param = init_param;
+ p->readfile = readfile;
+ p->system_type = system_type;
+ p->system_rev = system_rev;
+ p->bin = bin;
+ p->binned_fns = binned_fns;
+ p->bin_int = bin_int;
+ return new FreebsdAlphaSystem(p);
+}
+
+REGISTER_SIM_OBJECT("FreebsdAlphaSystem", FreebsdAlphaSystem)
+
diff --git a/arch/alpha/freebsd/system.hh b/src/arch/alpha/freebsd/system.hh
index 5d996955e..5d996955e 100644
--- a/arch/alpha/freebsd/system.hh
+++ b/src/arch/alpha/freebsd/system.hh
diff --git a/src/arch/alpha/isa/branch.isa b/src/arch/alpha/isa/branch.isa
new file mode 100644
index 000000000..f9a425ed2
--- /dev/null
+++ b/src/arch/alpha/isa/branch.isa
@@ -0,0 +1,264 @@
+// -*- mode:c++ -*-
+
+// Copyright (c) 2003-2005 The Regents of The University of Michigan
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met: redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer;
+// redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution;
+// neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+////////////////////////////////////////////////////////////////////
+//
+// Control transfer instructions
+//
+
+output header {{
+
+ /**
+ * Base class for instructions whose disassembly is not purely a
+ * function of the machine instruction (i.e., it depends on the
+ * PC). This class overrides the disassemble() method to check
+ * the PC and symbol table values before re-using a cached
+ * disassembly string. This is necessary for branches and jumps,
+ * where the disassembly string includes the target address (which
+ * may depend on the PC and/or symbol table).
+ */
+ class PCDependentDisassembly : public AlphaStaticInst
+ {
+ protected:
+ /// Cached program counter from last disassembly
+ mutable Addr cachedPC;
+ /// Cached symbol table pointer from last disassembly
+ mutable const SymbolTable *cachedSymtab;
+
+ /// Constructor
+ PCDependentDisassembly(const char *mnem, ExtMachInst _machInst,
+ OpClass __opClass)
+ : AlphaStaticInst(mnem, _machInst, __opClass),
+ cachedPC(0), cachedSymtab(0)
+ {
+ }
+
+ const std::string &
+ disassemble(Addr pc, const SymbolTable *symtab) const;
+ };
+
+ /**
+ * Base class for branches (PC-relative control transfers),
+ * conditional or unconditional.
+ */
+ class Branch : public PCDependentDisassembly
+ {
+ protected:
+ /// Displacement to target address (signed).
+ int32_t disp;
+
+ /// Constructor.
+ Branch(const char *mnem, ExtMachInst _machInst, OpClass __opClass)
+ : PCDependentDisassembly(mnem, _machInst, __opClass),
+ disp(BRDISP << 2)
+ {
+ }
+
+ Addr branchTarget(Addr branchPC) const;
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+
+ /**
+ * Base class for jumps (register-indirect control transfers). In
+ * the Alpha ISA, these are always unconditional.
+ */
+ class Jump : public PCDependentDisassembly
+ {
+ protected:
+
+ /// Displacement to target address (signed).
+ int32_t disp;
+
+ public:
+ /// Constructor
+ Jump(const char *mnem, ExtMachInst _machInst, OpClass __opClass)
+ : PCDependentDisassembly(mnem, _machInst, __opClass),
+ disp(BRDISP)
+ {
+ }
+
+ Addr branchTarget(ExecContext *xc) const;
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+}};
+
+output decoder {{
+ Addr
+ Branch::branchTarget(Addr branchPC) const
+ {
+ return branchPC + 4 + disp;
+ }
+
+ Addr
+ Jump::branchTarget(ExecContext *xc) const
+ {
+ Addr NPC = xc->readPC() + 4;
+ uint64_t Rb = xc->readIntReg(_srcRegIdx[0]);
+ return (Rb & ~3) | (NPC & 1);
+ }
+
+ const std::string &
+ PCDependentDisassembly::disassemble(Addr pc,
+ const SymbolTable *symtab) const
+ {
+ if (!cachedDisassembly ||
+ pc != cachedPC || symtab != cachedSymtab)
+ {
+ if (cachedDisassembly)
+ delete cachedDisassembly;
+
+ cachedDisassembly =
+ new std::string(generateDisassembly(pc, symtab));
+ cachedPC = pc;
+ cachedSymtab = symtab;
+ }
+
+ return *cachedDisassembly;
+ }
+
+ std::string
+ Branch::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+ {
+ std::stringstream ss;
+
+ ccprintf(ss, "%-10s ", mnemonic);
+
+ // There's only one register arg (RA), but it could be
+ // either a source (the condition for conditional
+ // branches) or a destination (the link reg for
+ // unconditional branches)
+ if (_numSrcRegs > 0) {
+ printReg(ss, _srcRegIdx[0]);
+ ss << ",";
+ }
+ else if (_numDestRegs > 0) {
+ printReg(ss, _destRegIdx[0]);
+ ss << ",";
+ }
+
+#ifdef SS_COMPATIBLE_DISASSEMBLY
+ if (_numSrcRegs == 0 && _numDestRegs == 0) {
+ printReg(ss, 31);
+ ss << ",";
+ }
+#endif
+
+ Addr target = pc + 4 + disp;
+
+ std::string str;
+ if (symtab && symtab->findSymbol(target, str))
+ ss << str;
+ else
+ ccprintf(ss, "0x%x", target);
+
+ return ss.str();
+ }
+
+ std::string
+ Jump::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+ {
+ std::stringstream ss;
+
+ ccprintf(ss, "%-10s ", mnemonic);
+
+#ifdef SS_COMPATIBLE_DISASSEMBLY
+ if (_numDestRegs == 0) {
+ printReg(ss, 31);
+ ss << ",";
+ }
+#endif
+
+ if (_numDestRegs > 0) {
+ printReg(ss, _destRegIdx[0]);
+ ss << ",";
+ }
+
+ ccprintf(ss, "(r%d)", RB);
+
+ return ss.str();
+ }
+}};
+
+def template JumpOrBranchDecode {{
+ return (RA == 31)
+ ? (StaticInst *)new %(class_name)s(machInst)
+ : (StaticInst *)new %(class_name)sAndLink(machInst);
+}};
+
+def format CondBranch(code) {{
+ code = 'bool cond;\n' + code + '\nif (cond) NPC = NPC + disp;\n';
+ iop = InstObjParams(name, Name, 'Branch', CodeBlock(code),
+ ('IsDirectControl', 'IsCondControl'))
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ decode_block = BasicDecode.subst(iop)
+ exec_output = BasicExecute.subst(iop)
+}};
+
+let {{
+def UncondCtrlBase(name, Name, base_class, npc_expr, flags):
+ # Declare basic control transfer w/o link (i.e. link reg is R31)
+ nolink_code = 'NPC = %s;\n' % npc_expr
+ nolink_iop = InstObjParams(name, Name, base_class,
+ CodeBlock(nolink_code), flags)
+ header_output = BasicDeclare.subst(nolink_iop)
+ decoder_output = BasicConstructor.subst(nolink_iop)
+ exec_output = BasicExecute.subst(nolink_iop)
+
+ # Generate declaration of '*AndLink' version, append to decls
+ link_code = 'Ra = NPC & ~3;\n' + nolink_code
+ link_iop = InstObjParams(name, Name + 'AndLink', base_class,
+ CodeBlock(link_code), flags)
+ header_output += BasicDeclare.subst(link_iop)
+ decoder_output += BasicConstructor.subst(link_iop)
+ exec_output += BasicExecute.subst(link_iop)
+
+ # need to use link_iop for the decode template since it is expecting
+ # the shorter version of class_name (w/o "AndLink")
+
+ return (header_output, decoder_output,
+ JumpOrBranchDecode.subst(nolink_iop), exec_output)
+}};
+
+def format UncondBranch(*flags) {{
+ flags += ('IsUncondControl', 'IsDirectControl')
+ (header_output, decoder_output, decode_block, exec_output) = \
+ UncondCtrlBase(name, Name, 'Branch', 'NPC + disp', flags)
+}};
+
+def format Jump(*flags) {{
+ flags += ('IsUncondControl', 'IsIndirectControl')
+ (header_output, decoder_output, decode_block, exec_output) = \
+ UncondCtrlBase(name, Name, 'Jump', '(Rb & ~3) | (NPC & 1)', flags)
+}};
+
+
diff --git a/src/arch/alpha/isa/decoder.isa b/src/arch/alpha/isa/decoder.isa
new file mode 100644
index 000000000..e6b4c234f
--- /dev/null
+++ b/src/arch/alpha/isa/decoder.isa
@@ -0,0 +1,824 @@
+// -*- mode:c++ -*-
+
+// Copyright (c) 2003-2006 The Regents of The University of Michigan
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met: redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer;
+// redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution;
+// neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+////////////////////////////////////////////////////////////////////
+//
+// The actual decoder specification
+//
+
+decode OPCODE default Unknown::unknown() {
+
+ format LoadAddress {
+ 0x08: lda({{ Ra = Rb + disp; }});
+ 0x09: ldah({{ Ra = Rb + (disp << 16); }});
+ }
+
+ format LoadOrNop {
+ 0x0a: ldbu({{ Ra.uq = Mem.ub; }});
+ 0x0c: ldwu({{ Ra.uq = Mem.uw; }});
+ 0x0b: ldq_u({{ Ra = Mem.uq; }}, ea_code = {{ EA = (Rb + disp) & ~7; }});
+ 0x23: ldt({{ Fa = Mem.df; }});
+ 0x2a: ldl_l({{ Ra.sl = Mem.sl; }}, mem_flags = LOCKED);
+ 0x2b: ldq_l({{ Ra.uq = Mem.uq; }}, mem_flags = LOCKED);
+ 0x20: MiscPrefetch::copy_load({{ EA = Ra; }},
+ {{ fault = xc->copySrcTranslate(EA); }},
+ inst_flags = [IsMemRef, IsLoad, IsCopy]);
+ }
+
+ format LoadOrPrefetch {
+ 0x28: ldl({{ Ra.sl = Mem.sl; }});
+ 0x29: ldq({{ Ra.uq = Mem.uq; }}, pf_flags = EVICT_NEXT);
+ // IsFloating flag on lds gets the prefetch to disassemble
+ // using f31 instead of r31... funcitonally it's unnecessary
+ 0x22: lds({{ Fa.uq = s_to_t(Mem.ul); }},
+ pf_flags = PF_EXCLUSIVE, inst_flags = IsFloating);
+ }
+
+ format Store {
+ 0x0e: stb({{ Mem.ub = Ra<7:0>; }});
+ 0x0d: stw({{ Mem.uw = Ra<15:0>; }});
+ 0x2c: stl({{ Mem.ul = Ra<31:0>; }});
+ 0x2d: stq({{ Mem.uq = Ra.uq; }});
+ 0x0f: stq_u({{ Mem.uq = Ra.uq; }}, {{ EA = (Rb + disp) & ~7; }});
+ 0x26: sts({{ Mem.ul = t_to_s(Fa.uq); }});
+ 0x27: stt({{ Mem.df = Fa; }});
+ 0x24: MiscPrefetch::copy_store({{ EA = Rb; }},
+ {{ fault = xc->copy(EA); }},
+ inst_flags = [IsMemRef, IsStore, IsCopy]);
+ }
+
+ format StoreCond {
+ 0x2e: stl_c({{ Mem.ul = Ra<31:0>; }},
+ {{
+ uint64_t tmp = write_result;
+ // see stq_c
+ Ra = (tmp == 0 || tmp == 1) ? tmp : Ra;
+ }}, mem_flags = LOCKED, inst_flags = IsStoreConditional);
+ 0x2f: stq_c({{ Mem.uq = Ra; }},
+ {{
+ uint64_t tmp = write_result;
+ // If the write operation returns 0 or 1, then
+ // this was a conventional store conditional,
+ // and the value indicates the success/failure
+ // of the operation. If another value is
+ // returned, then this was a Turbolaser
+ // mailbox access, and we don't update the
+ // result register at all.
+ Ra = (tmp == 0 || tmp == 1) ? tmp : Ra;
+ }}, mem_flags = LOCKED, inst_flags = IsStoreConditional);
+ }
+
+ format IntegerOperate {
+
+ 0x10: decode INTFUNC { // integer arithmetic operations
+
+ 0x00: addl({{ Rc.sl = Ra.sl + Rb_or_imm.sl; }});
+ 0x40: addlv({{
+ uint32_t tmp = Ra.sl + Rb_or_imm.sl;
+ // signed overflow occurs when operands have same sign
+ // and sign of result does not match.
+ if (Ra.sl<31:> == Rb_or_imm.sl<31:> && tmp<31:> != Ra.sl<31:>)
+ fault = new IntegerOverflowFault;
+ Rc.sl = tmp;
+ }});
+ 0x02: s4addl({{ Rc.sl = (Ra.sl << 2) + Rb_or_imm.sl; }});
+ 0x12: s8addl({{ Rc.sl = (Ra.sl << 3) + Rb_or_imm.sl; }});
+
+ 0x20: addq({{ Rc = Ra + Rb_or_imm; }});
+ 0x60: addqv({{
+ uint64_t tmp = Ra + Rb_or_imm;
+ // signed overflow occurs when operands have same sign
+ // and sign of result does not match.
+ if (Ra<63:> == Rb_or_imm<63:> && tmp<63:> != Ra<63:>)
+ fault = new IntegerOverflowFault;
+ Rc = tmp;
+ }});
+ 0x22: s4addq({{ Rc = (Ra << 2) + Rb_or_imm; }});
+ 0x32: s8addq({{ Rc = (Ra << 3) + Rb_or_imm; }});
+
+ 0x09: subl({{ Rc.sl = Ra.sl - Rb_or_imm.sl; }});
+ 0x49: sublv({{
+ uint32_t tmp = Ra.sl - Rb_or_imm.sl;
+ // signed overflow detection is same as for add,
+ // except we need to look at the *complemented*
+ // sign bit of the subtrahend (Rb), i.e., if the initial
+ // signs are the *same* then no overflow can occur
+ if (Ra.sl<31:> != Rb_or_imm.sl<31:> && tmp<31:> != Ra.sl<31:>)
+ fault = new IntegerOverflowFault;
+ Rc.sl = tmp;
+ }});
+ 0x0b: s4subl({{ Rc.sl = (Ra.sl << 2) - Rb_or_imm.sl; }});
+ 0x1b: s8subl({{ Rc.sl = (Ra.sl << 3) - Rb_or_imm.sl; }});
+
+ 0x29: subq({{ Rc = Ra - Rb_or_imm; }});
+ 0x69: subqv({{
+ uint64_t tmp = Ra - Rb_or_imm;
+ // signed overflow detection is same as for add,
+ // except we need to look at the *complemented*
+ // sign bit of the subtrahend (Rb), i.e., if the initial
+ // signs are the *same* then no overflow can occur
+ if (Ra<63:> != Rb_or_imm<63:> && tmp<63:> != Ra<63:>)
+ fault = new IntegerOverflowFault;
+ Rc = tmp;
+ }});
+ 0x2b: s4subq({{ Rc = (Ra << 2) - Rb_or_imm; }});
+ 0x3b: s8subq({{ Rc = (Ra << 3) - Rb_or_imm; }});
+
+ 0x2d: cmpeq({{ Rc = (Ra == Rb_or_imm); }});
+ 0x6d: cmple({{ Rc = (Ra.sq <= Rb_or_imm.sq); }});
+ 0x4d: cmplt({{ Rc = (Ra.sq < Rb_or_imm.sq); }});
+ 0x3d: cmpule({{ Rc = (Ra.uq <= Rb_or_imm.uq); }});
+ 0x1d: cmpult({{ Rc = (Ra.uq < Rb_or_imm.uq); }});
+
+ 0x0f: cmpbge({{
+ int hi = 7;
+ int lo = 0;
+ uint64_t tmp = 0;
+ for (int i = 0; i < 8; ++i) {
+ tmp |= (Ra.uq<hi:lo> >= Rb_or_imm.uq<hi:lo>) << i;
+ hi += 8;
+ lo += 8;
+ }
+ Rc = tmp;
+ }});
+ }
+
+ 0x11: decode INTFUNC { // integer logical operations
+
+ 0x00: and({{ Rc = Ra & Rb_or_imm; }});
+ 0x08: bic({{ Rc = Ra & ~Rb_or_imm; }});
+ 0x20: bis({{ Rc = Ra | Rb_or_imm; }});
+ 0x28: ornot({{ Rc = Ra | ~Rb_or_imm; }});
+ 0x40: xor({{ Rc = Ra ^ Rb_or_imm; }});
+ 0x48: eqv({{ Rc = Ra ^ ~Rb_or_imm; }});
+
+ // conditional moves
+ 0x14: cmovlbs({{ Rc = ((Ra & 1) == 1) ? Rb_or_imm : Rc; }});
+ 0x16: cmovlbc({{ Rc = ((Ra & 1) == 0) ? Rb_or_imm : Rc; }});
+ 0x24: cmoveq({{ Rc = (Ra == 0) ? Rb_or_imm : Rc; }});
+ 0x26: cmovne({{ Rc = (Ra != 0) ? Rb_or_imm : Rc; }});
+ 0x44: cmovlt({{ Rc = (Ra.sq < 0) ? Rb_or_imm : Rc; }});
+ 0x46: cmovge({{ Rc = (Ra.sq >= 0) ? Rb_or_imm : Rc; }});
+ 0x64: cmovle({{ Rc = (Ra.sq <= 0) ? Rb_or_imm : Rc; }});
+ 0x66: cmovgt({{ Rc = (Ra.sq > 0) ? Rb_or_imm : Rc; }});
+
+ // For AMASK, RA must be R31.
+ 0x61: decode RA {
+ 31: amask({{ Rc = Rb_or_imm & ~ULL(0x17); }});
+ }
+
+ // For IMPLVER, RA must be R31 and the B operand
+ // must be the immediate value 1.
+ 0x6c: decode RA {
+ 31: decode IMM {
+ 1: decode INTIMM {
+ // return EV5 for FULL_SYSTEM and EV6 otherwise
+ 1: implver({{
+#if FULL_SYSTEM
+ Rc = 1;
+#else
+ Rc = 2;
+#endif
+ }});
+ }
+ }
+ }
+
+#if FULL_SYSTEM
+ // The mysterious 11.25...
+ 0x25: WarnUnimpl::eleven25();
+#endif
+ }
+
+ 0x12: decode INTFUNC {
+ 0x39: sll({{ Rc = Ra << Rb_or_imm<5:0>; }});
+ 0x34: srl({{ Rc = Ra.uq >> Rb_or_imm<5:0>; }});
+ 0x3c: sra({{ Rc = Ra.sq >> Rb_or_imm<5:0>; }});
+
+ 0x02: mskbl({{ Rc = Ra & ~(mask( 8) << (Rb_or_imm<2:0> * 8)); }});
+ 0x12: mskwl({{ Rc = Ra & ~(mask(16) << (Rb_or_imm<2:0> * 8)); }});
+ 0x22: mskll({{ Rc = Ra & ~(mask(32) << (Rb_or_imm<2:0> * 8)); }});
+ 0x32: mskql({{ Rc = Ra & ~(mask(64) << (Rb_or_imm<2:0> * 8)); }});
+
+ 0x52: mskwh({{
+ int bv = Rb_or_imm<2:0>;
+ Rc = bv ? (Ra & ~(mask(16) >> (64 - 8 * bv))) : Ra;
+ }});
+ 0x62: msklh({{
+ int bv = Rb_or_imm<2:0>;
+ Rc = bv ? (Ra & ~(mask(32) >> (64 - 8 * bv))) : Ra;
+ }});
+ 0x72: mskqh({{
+ int bv = Rb_or_imm<2:0>;
+ Rc = bv ? (Ra & ~(mask(64) >> (64 - 8 * bv))) : Ra;
+ }});
+
+ 0x06: extbl({{ Rc = (Ra.uq >> (Rb_or_imm<2:0> * 8))< 7:0>; }});
+ 0x16: extwl({{ Rc = (Ra.uq >> (Rb_or_imm<2:0> * 8))<15:0>; }});
+ 0x26: extll({{ Rc = (Ra.uq >> (Rb_or_imm<2:0> * 8))<31:0>; }});
+ 0x36: extql({{ Rc = (Ra.uq >> (Rb_or_imm<2:0> * 8)); }});
+
+ 0x5a: extwh({{
+ Rc = (Ra << (64 - (Rb_or_imm<2:0> * 8))<5:0>)<15:0>; }});
+ 0x6a: extlh({{
+ Rc = (Ra << (64 - (Rb_or_imm<2:0> * 8))<5:0>)<31:0>; }});
+ 0x7a: extqh({{
+ Rc = (Ra << (64 - (Rb_or_imm<2:0> * 8))<5:0>); }});
+
+ 0x0b: insbl({{ Rc = Ra< 7:0> << (Rb_or_imm<2:0> * 8); }});
+ 0x1b: inswl({{ Rc = Ra<15:0> << (Rb_or_imm<2:0> * 8); }});
+ 0x2b: insll({{ Rc = Ra<31:0> << (Rb_or_imm<2:0> * 8); }});
+ 0x3b: insql({{ Rc = Ra << (Rb_or_imm<2:0> * 8); }});
+
+ 0x57: inswh({{
+ int bv = Rb_or_imm<2:0>;
+ Rc = bv ? (Ra.uq<15:0> >> (64 - 8 * bv)) : 0;
+ }});
+ 0x67: inslh({{
+ int bv = Rb_or_imm<2:0>;
+ Rc = bv ? (Ra.uq<31:0> >> (64 - 8 * bv)) : 0;
+ }});
+ 0x77: insqh({{
+ int bv = Rb_or_imm<2:0>;
+ Rc = bv ? (Ra.uq >> (64 - 8 * bv)) : 0;
+ }});
+
+ 0x30: zap({{
+ uint64_t zapmask = 0;
+ for (int i = 0; i < 8; ++i) {
+ if (Rb_or_imm<i:>)
+ zapmask |= (mask(8) << (i * 8));
+ }
+ Rc = Ra & ~zapmask;
+ }});
+ 0x31: zapnot({{
+ uint64_t zapmask = 0;
+ for (int i = 0; i < 8; ++i) {
+ if (!Rb_or_imm<i:>)
+ zapmask |= (mask(8) << (i * 8));
+ }
+ Rc = Ra & ~zapmask;
+ }});
+ }
+
+ 0x13: decode INTFUNC { // integer multiplies
+ 0x00: mull({{ Rc.sl = Ra.sl * Rb_or_imm.sl; }}, IntMultOp);
+ 0x20: mulq({{ Rc = Ra * Rb_or_imm; }}, IntMultOp);
+ 0x30: umulh({{
+ uint64_t hi, lo;
+ mul128(Ra, Rb_or_imm, hi, lo);
+ Rc = hi;
+ }}, IntMultOp);
+ 0x40: mullv({{
+ // 32-bit multiply with trap on overflow
+ int64_t Rax = Ra.sl; // sign extended version of Ra.sl
+ int64_t Rbx = Rb_or_imm.sl;
+ int64_t tmp = Rax * Rbx;
+ // To avoid overflow, all the upper 32 bits must match
+ // the sign bit of the lower 32. We code this as
+ // checking the upper 33 bits for all 0s or all 1s.
+ uint64_t sign_bits = tmp<63:31>;
+ if (sign_bits != 0 && sign_bits != mask(33))
+ fault = new IntegerOverflowFault;
+ Rc.sl = tmp<31:0>;
+ }}, IntMultOp);
+ 0x60: mulqv({{
+ // 64-bit multiply with trap on overflow
+ uint64_t hi, lo;
+ mul128(Ra, Rb_or_imm, hi, lo);
+ // all the upper 64 bits must match the sign bit of
+ // the lower 64
+ if (!((hi == 0 && lo<63:> == 0) ||
+ (hi == mask(64) && lo<63:> == 1)))
+ fault = new IntegerOverflowFault;
+ Rc = lo;
+ }}, IntMultOp);
+ }
+
+ 0x1c: decode INTFUNC {
+ 0x00: decode RA { 31: sextb({{ Rc.sb = Rb_or_imm< 7:0>; }}); }
+ 0x01: decode RA { 31: sextw({{ Rc.sw = Rb_or_imm<15:0>; }}); }
+ 0x32: ctlz({{
+ uint64_t count = 0;
+ uint64_t temp = Rb;
+ if (temp<63:32>) temp >>= 32; else count += 32;
+ if (temp<31:16>) temp >>= 16; else count += 16;
+ if (temp<15:8>) temp >>= 8; else count += 8;
+ if (temp<7:4>) temp >>= 4; else count += 4;
+ if (temp<3:2>) temp >>= 2; else count += 2;
+ if (temp<1:1>) temp >>= 1; else count += 1;
+ if ((temp<0:0>) != 0x1) count += 1;
+ Rc = count;
+ }}, IntAluOp);
+
+ 0x33: cttz({{
+ uint64_t count = 0;
+ uint64_t temp = Rb;
+ if (!(temp<31:0>)) { temp >>= 32; count += 32; }
+ if (!(temp<15:0>)) { temp >>= 16; count += 16; }
+ if (!(temp<7:0>)) { temp >>= 8; count += 8; }
+ if (!(temp<3:0>)) { temp >>= 4; count += 4; }
+ if (!(temp<1:0>)) { temp >>= 2; count += 2; }
+ if (!(temp<0:0> & ULL(0x1))) count += 1;
+ Rc = count;
+ }}, IntAluOp);
+
+ format FailUnimpl {
+ 0x30: ctpop();
+ 0x31: perr();
+ 0x34: unpkbw();
+ 0x35: unpkbl();
+ 0x36: pkwb();
+ 0x37: pklb();
+ 0x38: minsb8();
+ 0x39: minsw4();
+ 0x3a: minub8();
+ 0x3b: minuw4();
+ 0x3c: maxub8();
+ 0x3d: maxuw4();
+ 0x3e: maxsb8();
+ 0x3f: maxsw4();
+ }
+
+ format BasicOperateWithNopCheck {
+ 0x70: decode RB {
+ 31: ftoit({{ Rc = Fa.uq; }}, FloatCvtOp);
+ }
+ 0x78: decode RB {
+ 31: ftois({{ Rc.sl = t_to_s(Fa.uq); }},
+ FloatCvtOp);
+ }
+ }
+ }
+ }
+
+ // Conditional branches.
+ format CondBranch {
+ 0x39: beq({{ cond = (Ra == 0); }});
+ 0x3d: bne({{ cond = (Ra != 0); }});
+ 0x3e: bge({{ cond = (Ra.sq >= 0); }});
+ 0x3f: bgt({{ cond = (Ra.sq > 0); }});
+ 0x3b: ble({{ cond = (Ra.sq <= 0); }});
+ 0x3a: blt({{ cond = (Ra.sq < 0); }});
+ 0x38: blbc({{ cond = ((Ra & 1) == 0); }});
+ 0x3c: blbs({{ cond = ((Ra & 1) == 1); }});
+
+ 0x31: fbeq({{ cond = (Fa == 0); }});
+ 0x35: fbne({{ cond = (Fa != 0); }});
+ 0x36: fbge({{ cond = (Fa >= 0); }});
+ 0x37: fbgt({{ cond = (Fa > 0); }});
+ 0x33: fble({{ cond = (Fa <= 0); }});
+ 0x32: fblt({{ cond = (Fa < 0); }});
+ }
+
+ // unconditional branches
+ format UncondBranch {
+ 0x30: br();
+ 0x34: bsr(IsCall);
+ }
+
+ // indirect branches
+ 0x1a: decode JMPFUNC {
+ format Jump {
+ 0: jmp();
+ 1: jsr(IsCall);
+ 2: ret(IsReturn);
+ 3: jsr_coroutine(IsCall, IsReturn);
+ }
+ }
+
+ // Square root and integer-to-FP moves
+ 0x14: decode FP_SHORTFUNC {
+ // Integer to FP register moves must have RB == 31
+ 0x4: decode RB {
+ 31: decode FP_FULLFUNC {
+ format BasicOperateWithNopCheck {
+ 0x004: itofs({{ Fc.uq = s_to_t(Ra.ul); }}, FloatCvtOp);
+ 0x024: itoft({{ Fc.uq = Ra.uq; }}, FloatCvtOp);
+ 0x014: FailUnimpl::itoff(); // VAX-format conversion
+ }
+ }
+ }
+
+ // Square root instructions must have FA == 31
+ 0xb: decode FA {
+ 31: decode FP_TYPEFUNC {
+ format FloatingPointOperate {
+#if SS_COMPATIBLE_FP
+ 0x0b: sqrts({{
+ if (Fb < 0.0)
+ fault = new ArithmeticFault;
+ Fc = sqrt(Fb);
+ }}, FloatSqrtOp);
+#else
+ 0x0b: sqrts({{
+ if (Fb.sf < 0.0)
+ fault = new ArithmeticFault;
+ Fc.sf = sqrt(Fb.sf);
+ }}, FloatSqrtOp);
+#endif
+ 0x2b: sqrtt({{
+ if (Fb < 0.0)
+ fault = new ArithmeticFault;
+ Fc = sqrt(Fb);
+ }}, FloatSqrtOp);
+ }
+ }
+ }
+
+ // VAX-format sqrtf and sqrtg are not implemented
+ 0xa: FailUnimpl::sqrtfg();
+ }
+
+ // IEEE floating point
+ 0x16: decode FP_SHORTFUNC_TOP2 {
+ // The top two bits of the short function code break this
+ // space into four groups: binary ops, compares, reserved, and
+ // conversions. See Table 4-12 of AHB. There are different
+ // special cases in these different groups, so we decode on
+ // these top two bits first just to select a decode strategy.
+ // Most of these instructions may have various trapping and
+ // rounding mode flags set; these are decoded in the
+ // FloatingPointDecode template used by the
+ // FloatingPointOperate format.
+
+ // add/sub/mul/div: just decode on the short function code
+ // and source type. All valid trapping and rounding modes apply.
+ 0: decode FP_TRAPMODE {
+ // check for valid trapping modes here
+ 0,1,5,7: decode FP_TYPEFUNC {
+ format FloatingPointOperate {
+#if SS_COMPATIBLE_FP
+ 0x00: adds({{ Fc = Fa + Fb; }});
+ 0x01: subs({{ Fc = Fa - Fb; }});
+ 0x02: muls({{ Fc = Fa * Fb; }}, FloatMultOp);
+ 0x03: divs({{ Fc = Fa / Fb; }}, FloatDivOp);
+#else
+ 0x00: adds({{ Fc.sf = Fa.sf + Fb.sf; }});
+ 0x01: subs({{ Fc.sf = Fa.sf - Fb.sf; }});
+ 0x02: muls({{ Fc.sf = Fa.sf * Fb.sf; }}, FloatMultOp);
+ 0x03: divs({{ Fc.sf = Fa.sf / Fb.sf; }}, FloatDivOp);
+#endif
+
+ 0x20: addt({{ Fc = Fa + Fb; }});
+ 0x21: subt({{ Fc = Fa - Fb; }});
+ 0x22: mult({{ Fc = Fa * Fb; }}, FloatMultOp);
+ 0x23: divt({{ Fc = Fa / Fb; }}, FloatDivOp);
+ }
+ }
+ }
+
+ // Floating-point compare instructions must have the default
+ // rounding mode, and may use the default trapping mode or
+ // /SU. Both trapping modes are treated the same by M5; the
+ // only difference on the real hardware (as far a I can tell)
+ // is that without /SU you'd get an imprecise trap if you
+ // tried to compare a NaN with something else (instead of an
+ // "unordered" result).
+ 1: decode FP_FULLFUNC {
+ format BasicOperateWithNopCheck {
+ 0x0a5, 0x5a5: cmpteq({{ Fc = (Fa == Fb) ? 2.0 : 0.0; }},
+ FloatCmpOp);
+ 0x0a7, 0x5a7: cmptle({{ Fc = (Fa <= Fb) ? 2.0 : 0.0; }},
+ FloatCmpOp);
+ 0x0a6, 0x5a6: cmptlt({{ Fc = (Fa < Fb) ? 2.0 : 0.0; }},
+ FloatCmpOp);
+ 0x0a4, 0x5a4: cmptun({{ // unordered
+ Fc = (!(Fa < Fb) && !(Fa == Fb) && !(Fa > Fb)) ? 2.0 : 0.0;
+ }}, FloatCmpOp);
+ }
+ }
+
+ // The FP-to-integer and integer-to-FP conversion insts
+ // require that FA be 31.
+ 3: decode FA {
+ 31: decode FP_TYPEFUNC {
+ format FloatingPointOperate {
+ 0x2f: decode FP_ROUNDMODE {
+ format FPFixedRounding {
+ // "chopped" i.e. round toward zero
+ 0: cvttq({{ Fc.sq = (int64_t)trunc(Fb); }},
+ Chopped);
+ // round to minus infinity
+ 1: cvttq({{ Fc.sq = (int64_t)floor(Fb); }},
+ MinusInfinity);
+ }
+ default: cvttq({{ Fc.sq = (int64_t)nearbyint(Fb); }});
+ }
+
+ // The cvtts opcode is overloaded to be cvtst if the trap
+ // mode is 2 or 6 (which are not valid otherwise)
+ 0x2c: decode FP_FULLFUNC {
+ format BasicOperateWithNopCheck {
+ // trap on denorm version "cvtst/s" is
+ // simulated same as cvtst
+ 0x2ac, 0x6ac: cvtst({{ Fc = Fb.sf; }});
+ }
+ default: cvtts({{ Fc.sf = Fb; }});
+ }
+
+ // The trapping mode for integer-to-FP conversions
+ // must be /SUI or nothing; /U and /SU are not
+ // allowed. The full set of rounding modes are
+ // supported though.
+ 0x3c: decode FP_TRAPMODE {
+ 0,7: cvtqs({{ Fc.sf = Fb.sq; }});
+ }
+ 0x3e: decode FP_TRAPMODE {
+ 0,7: cvtqt({{ Fc = Fb.sq; }});
+ }
+ }
+ }
+ }
+ }
+
+ // misc FP operate
+ 0x17: decode FP_FULLFUNC {
+ format BasicOperateWithNopCheck {
+ 0x010: cvtlq({{
+ Fc.sl = (Fb.uq<63:62> << 30) | Fb.uq<58:29>;
+ }});
+ 0x030: cvtql({{
+ Fc.uq = (Fb.uq<31:30> << 62) | (Fb.uq<29:0> << 29);
+ }});
+
+ // We treat the precise & imprecise trapping versions of
+ // cvtql identically.
+ 0x130, 0x530: cvtqlv({{
+ // To avoid overflow, all the upper 32 bits must match
+ // the sign bit of the lower 32. We code this as
+ // checking the upper 33 bits for all 0s or all 1s.
+ uint64_t sign_bits = Fb.uq<63:31>;
+ if (sign_bits != 0 && sign_bits != mask(33))
+ fault = new IntegerOverflowFault;
+ Fc.uq = (Fb.uq<31:30> << 62) | (Fb.uq<29:0> << 29);
+ }});
+
+ 0x020: cpys({{ // copy sign
+ Fc.uq = (Fa.uq<63:> << 63) | Fb.uq<62:0>;
+ }});
+ 0x021: cpysn({{ // copy sign negated
+ Fc.uq = (~Fa.uq<63:> << 63) | Fb.uq<62:0>;
+ }});
+ 0x022: cpyse({{ // copy sign and exponent
+ Fc.uq = (Fa.uq<63:52> << 52) | Fb.uq<51:0>;
+ }});
+
+ 0x02a: fcmoveq({{ Fc = (Fa == 0) ? Fb : Fc; }});
+ 0x02b: fcmovne({{ Fc = (Fa != 0) ? Fb : Fc; }});
+ 0x02c: fcmovlt({{ Fc = (Fa < 0) ? Fb : Fc; }});
+ 0x02d: fcmovge({{ Fc = (Fa >= 0) ? Fb : Fc; }});
+ 0x02e: fcmovle({{ Fc = (Fa <= 0) ? Fb : Fc; }});
+ 0x02f: fcmovgt({{ Fc = (Fa > 0) ? Fb : Fc; }});
+
+ 0x024: mt_fpcr({{ FPCR = Fa.uq; }}, IsIprAccess);
+ 0x025: mf_fpcr({{ Fa.uq = FPCR; }}, IsIprAccess);
+ }
+ }
+
+ // miscellaneous mem-format ops
+ 0x18: decode MEMFUNC {
+ format WarnUnimpl {
+ 0x8000: fetch();
+ 0xa000: fetch_m();
+ 0xe800: ecb();
+ }
+
+ format MiscPrefetch {
+ 0xf800: wh64({{ EA = Rb & ~ULL(63); }},
+ {{ xc->writeHint(EA, 64, memAccessFlags); }},
+ mem_flags = NO_FAULT,
+ inst_flags = [IsMemRef, IsDataPrefetch,
+ IsStore, MemWriteOp]);
+ }
+
+ format BasicOperate {
+ 0xc000: rpcc({{
+#if FULL_SYSTEM
+ /* Rb is a fake dependency so here is a fun way to get
+ * the parser to understand that.
+ */
+ Ra = xc->readMiscRegWithEffect(AlphaISA::IPR_CC, fault) + (Rb & 0);
+
+#else
+ Ra = curTick;
+#endif
+ }}, IsUnverifiable);
+
+ // All of the barrier instructions below do nothing in
+ // their execute() methods (hence the empty code blocks).
+ // All of their functionality is hard-coded in the
+ // pipeline based on the flags IsSerializing,
+ // IsMemBarrier, and IsWriteBarrier. In the current
+ // detailed CPU model, the execute() function only gets
+ // called at fetch, so there's no way to generate pipeline
+ // behavior at any other stage. Once we go to an
+ // exec-in-exec CPU model we should be able to get rid of
+ // these flags and implement this behavior via the
+ // execute() methods.
+
+ // trapb is just a barrier on integer traps, where excb is
+ // a barrier on integer and FP traps. "EXCB is thus a
+ // superset of TRAPB." (Alpha ARM, Sec 4.11.4) We treat
+ // them the same though.
+ 0x0000: trapb({{ }}, IsSerializing, IsSerializeBefore, No_OpClass);
+ 0x0400: excb({{ }}, IsSerializing, IsSerializeBefore, No_OpClass);
+ 0x4000: mb({{ }}, IsMemBarrier, MemReadOp);
+ 0x4400: wmb({{ }}, IsWriteBarrier, MemWriteOp);
+ }
+
+#if FULL_SYSTEM
+ format BasicOperate {
+ 0xe000: rc({{
+ Ra = xc->readIntrFlag();
+ xc->setIntrFlag(0);
+ }}, IsNonSpeculative);
+ 0xf000: rs({{
+ Ra = xc->readIntrFlag();
+ xc->setIntrFlag(1);
+ }}, IsNonSpeculative);
+ }
+#else
+ format FailUnimpl {
+ 0xe000: rc();
+ 0xf000: rs();
+ }
+#endif
+ }
+
+#if FULL_SYSTEM
+ 0x00: CallPal::call_pal({{
+ if (!palValid ||
+ (palPriv
+ && xc->readMiscRegWithEffect(AlphaISA::IPR_ICM, fault) != AlphaISA::mode_kernel)) {
+ // invalid pal function code, or attempt to do privileged
+ // PAL call in non-kernel mode
+ fault = new UnimplementedOpcodeFault;
+ }
+ else {
+ // check to see if simulator wants to do something special
+ // on this PAL call (including maybe suppress it)
+ bool dopal = xc->simPalCheck(palFunc);
+
+ if (dopal) {
+ xc->setMiscRegWithEffect(AlphaISA::IPR_EXC_ADDR, NPC);
+ NPC = xc->readMiscRegWithEffect(AlphaISA::IPR_PAL_BASE, fault) + palOffset;
+ }
+ }
+ }}, IsNonSpeculative);
+#else
+ 0x00: decode PALFUNC {
+ format EmulatedCallPal {
+ 0x00: halt ({{
+ SimExit(curTick, "halt instruction encountered");
+ }}, IsNonSpeculative);
+ 0x83: callsys({{
+ xc->syscall(R0);
+ }}, IsNonSpeculative);
+ // Read uniq reg into ABI return value register (r0)
+ 0x9e: rduniq({{ R0 = Runiq; }}, IsIprAccess);
+ // Write uniq reg with value from ABI arg register (r16)
+ 0x9f: wruniq({{ Runiq = R16; }}, IsIprAccess);
+ }
+ }
+#endif
+
+#if FULL_SYSTEM
+ 0x1b: decode PALMODE {
+ 0: OpcdecFault::hw_st_quad();
+ 1: decode HW_LDST_QUAD {
+ format HwLoad {
+ 0: hw_ld({{ EA = (Rb + disp) & ~3; }}, {{ Ra = Mem.ul; }}, L);
+ 1: hw_ld({{ EA = (Rb + disp) & ~7; }}, {{ Ra = Mem.uq; }}, Q);
+ }
+ }
+ }
+
+ 0x1f: decode PALMODE {
+ 0: OpcdecFault::hw_st_cond();
+ format HwStore {
+ 1: decode HW_LDST_COND {
+ 0: decode HW_LDST_QUAD {
+ 0: hw_st({{ EA = (Rb + disp) & ~3; }},
+ {{ Mem.ul = Ra<31:0>; }}, L);
+ 1: hw_st({{ EA = (Rb + disp) & ~7; }},
+ {{ Mem.uq = Ra.uq; }}, Q);
+ }
+
+ 1: FailUnimpl::hw_st_cond();
+ }
+ }
+ }
+
+ 0x19: decode PALMODE {
+ 0: OpcdecFault::hw_mfpr();
+ format HwMoveIPR {
+ 1: hw_mfpr({{
+ Ra = xc->readMiscRegWithEffect(ipr_index, fault);
+ }}, IsIprAccess);
+ }
+ }
+
+ 0x1d: decode PALMODE {
+ 0: OpcdecFault::hw_mtpr();
+ format HwMoveIPR {
+ 1: hw_mtpr({{
+ xc->setMiscRegWithEffect(ipr_index, Ra);
+ if (traceData) { traceData->setData(Ra); }
+ }}, IsIprAccess);
+ }
+ }
+
+ format BasicOperate {
+ 0x1e: decode PALMODE {
+ 0: OpcdecFault::hw_rei();
+ 1:hw_rei({{ xc->hwrei(); }}, IsSerializing, IsSerializeBefore);
+ }
+
+ // M5 special opcodes use the reserved 0x01 opcode space
+ 0x01: decode M5FUNC {
+ 0x00: arm({{
+ AlphaPseudo::arm(xc->xcBase());
+ }}, IsNonSpeculative);
+ 0x01: quiesce({{
+ AlphaPseudo::quiesce(xc->xcBase());
+ }}, IsNonSpeculative, IsQuiesce);
+ 0x02: quiesceNs({{
+ AlphaPseudo::quiesceNs(xc->xcBase(), R16);
+ }}, IsNonSpeculative, IsQuiesce);
+ 0x03: quiesceCycles({{
+ AlphaPseudo::quiesceCycles(xc->xcBase(), R16);
+ }}, IsNonSpeculative, IsQuiesce);
+ 0x04: quiesceTime({{
+ R0 = AlphaPseudo::quiesceTime(xc->xcBase());
+ }}, IsNonSpeculative);
+ 0x10: ivlb({{
+ AlphaPseudo::ivlb(xc->xcBase());
+ }}, No_OpClass, IsNonSpeculative);
+ 0x11: ivle({{
+ AlphaPseudo::ivle(xc->xcBase());
+ }}, No_OpClass, IsNonSpeculative);
+ 0x20: m5exit_old({{
+ AlphaPseudo::m5exit_old(xc->xcBase());
+ }}, No_OpClass, IsNonSpeculative);
+ 0x21: m5exit({{
+ AlphaPseudo::m5exit(xc->xcBase(), R16);
+ }}, No_OpClass, IsNonSpeculative);
+ 0x30: initparam({{ Ra = xc->xcBase()->getCpuPtr()->system->init_param; }});
+ 0x40: resetstats({{
+ AlphaPseudo::resetstats(xc->xcBase(), R16, R17);
+ }}, IsNonSpeculative);
+ 0x41: dumpstats({{
+ AlphaPseudo::dumpstats(xc->xcBase(), R16, R17);
+ }}, IsNonSpeculative);
+ 0x42: dumpresetstats({{
+ AlphaPseudo::dumpresetstats(xc->xcBase(), R16, R17);
+ }}, IsNonSpeculative);
+ 0x43: m5checkpoint({{
+ AlphaPseudo::m5checkpoint(xc->xcBase(), R16, R17);
+ }}, IsNonSpeculative);
+ 0x50: m5readfile({{
+ R0 = AlphaPseudo::readfile(xc->xcBase(), R16, R17, R18);
+ }}, IsNonSpeculative);
+ 0x51: m5break({{
+ AlphaPseudo::debugbreak(xc->xcBase());
+ }}, IsNonSpeculative);
+ 0x52: m5switchcpu({{
+ AlphaPseudo::switchcpu(xc->xcBase());
+ }}, IsNonSpeculative);
+ 0x53: m5addsymbol({{
+ AlphaPseudo::addsymbol(xc->xcBase(), R16, R17);
+ }}, IsNonSpeculative);
+ 0x54: m5panic({{
+ panic("M5 panic instruction called at pc=%#x.", xc->readPC());
+ }}, IsNonSpeculative);
+
+ }
+ }
+#endif
+}
diff --git a/src/arch/alpha/isa/fp.isa b/src/arch/alpha/isa/fp.isa
new file mode 100644
index 000000000..f855ca3a9
--- /dev/null
+++ b/src/arch/alpha/isa/fp.isa
@@ -0,0 +1,310 @@
+// -*- mode:c++ -*-
+
+// Copyright (c) 2003-2005 The Regents of The University of Michigan
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met: redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer;
+// redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution;
+// neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+////////////////////////////////////////////////////////////////////
+//
+// Floating-point instructions
+//
+// Note that many FP-type instructions which do not support all the
+// various rounding & trapping modes use the simpler format
+// BasicOperateWithNopCheck.
+//
+
+output exec {{
+ /// Check "FP enabled" machine status bit. Called when executing any FP
+ /// instruction in full-system mode.
+ /// @retval Full-system mode: NoFault if FP is enabled, FenFault
+ /// if not. Non-full-system mode: always returns NoFault.
+#if FULL_SYSTEM
+ inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc)
+ {
+ Fault fault = NoFault; // dummy... this ipr access should not fault
+ if (!EV5::ICSR_FPE(xc->readMiscRegWithEffect(AlphaISA::IPR_ICSR, fault))) {
+ fault = new FloatEnableFault;
+ }
+ return fault;
+ }
+#else
+ inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc)
+ {
+ return NoFault;
+ }
+#endif
+}};
+
+output header {{
+ /**
+ * Base class for general floating-point instructions. Includes
+ * support for various Alpha rounding and trapping modes. Only FP
+ * instructions that require this support are derived from this
+ * class; the rest derive directly from AlphaStaticInst.
+ */
+ class AlphaFP : public AlphaStaticInst
+ {
+ public:
+ /// Alpha FP rounding modes.
+ enum RoundingMode {
+ Chopped = 0, ///< round toward zero
+ Minus_Infinity = 1, ///< round toward minus infinity
+ Normal = 2, ///< round to nearest (default)
+ Dynamic = 3, ///< use FPCR setting (in instruction)
+ Plus_Infinity = 3 ///< round to plus inifinity (in FPCR)
+ };
+
+ /// Alpha FP trapping modes.
+ /// For instructions that produce integer results, the
+ /// "Underflow Enable" modes really mean "Overflow Enable", and
+ /// the assembly modifier is V rather than U.
+ enum TrappingMode {
+ /// default: nothing enabled
+ Imprecise = 0, ///< no modifier
+ /// underflow/overflow traps enabled, inexact disabled
+ Underflow_Imprecise = 1, ///< /U or /V
+ Underflow_Precise = 5, ///< /SU or /SV
+ /// underflow/overflow and inexact traps enabled
+ Underflow_Inexact_Precise = 7 ///< /SUI or /SVI
+ };
+
+ protected:
+ /// Map Alpha rounding mode to C99 constants from <fenv.h>.
+ static const int alphaToC99RoundingMode[];
+
+ /// Map enum RoundingMode values to disassembly suffixes.
+ static const char *roundingModeSuffix[];
+ /// Map enum TrappingMode values to FP disassembly suffixes.
+ static const char *fpTrappingModeSuffix[];
+ /// Map enum TrappingMode values to integer disassembly suffixes.
+ static const char *intTrappingModeSuffix[];
+
+ /// This instruction's rounding mode.
+ RoundingMode roundingMode;
+ /// This instruction's trapping mode.
+ TrappingMode trappingMode;
+
+ /// Have we warned about this instruction's unsupported
+ /// rounding mode (if applicable)?
+ mutable bool warnedOnRounding;
+
+ /// Have we warned about this instruction's unsupported
+ /// trapping mode (if applicable)?
+ mutable bool warnedOnTrapping;
+
+ /// Constructor
+ AlphaFP(const char *mnem, ExtMachInst _machInst, OpClass __opClass)
+ : AlphaStaticInst(mnem, _machInst, __opClass),
+ roundingMode((enum RoundingMode)FP_ROUNDMODE),
+ trappingMode((enum TrappingMode)FP_TRAPMODE),
+ warnedOnRounding(false),
+ warnedOnTrapping(false)
+ {
+ }
+
+ int getC99RoundingMode(uint64_t fpcr_val) const;
+
+ // This differs from the AlphaStaticInst version only in
+ // printing suffixes for non-default rounding & trapping modes.
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+
+}};
+
+
+output decoder {{
+ int
+ AlphaFP::getC99RoundingMode(uint64_t fpcr_val) const
+ {
+ if (roundingMode == Dynamic) {
+ return alphaToC99RoundingMode[bits(fpcr_val, 59, 58)];
+ }
+ else {
+ return alphaToC99RoundingMode[roundingMode];
+ }
+ }
+
+ std::string
+ AlphaFP::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+ {
+ std::string mnem_str(mnemonic);
+
+#ifndef SS_COMPATIBLE_DISASSEMBLY
+ std::string suffix("");
+ suffix += ((_destRegIdx[0] >= FP_Base_DepTag)
+ ? fpTrappingModeSuffix[trappingMode]
+ : intTrappingModeSuffix[trappingMode]);
+ suffix += roundingModeSuffix[roundingMode];
+
+ if (suffix != "") {
+ mnem_str = csprintf("%s/%s", mnemonic, suffix);
+ }
+#endif
+
+ std::stringstream ss;
+ ccprintf(ss, "%-10s ", mnem_str.c_str());
+
+ // just print the first two source regs... if there's
+ // a third one, it's a read-modify-write dest (Rc),
+ // e.g. for CMOVxx
+ if (_numSrcRegs > 0) {
+ printReg(ss, _srcRegIdx[0]);
+ }
+ if (_numSrcRegs > 1) {
+ ss << ",";
+ printReg(ss, _srcRegIdx[1]);
+ }
+
+ // just print the first dest... if there's a second one,
+ // it's generally implicit
+ if (_numDestRegs > 0) {
+ if (_numSrcRegs > 0)
+ ss << ",";
+ printReg(ss, _destRegIdx[0]);
+ }
+
+ return ss.str();
+ }
+
+ const int AlphaFP::alphaToC99RoundingMode[] = {
+ FE_TOWARDZERO, // Chopped
+ FE_DOWNWARD, // Minus_Infinity
+ FE_TONEAREST, // Normal
+ FE_UPWARD // Dynamic in inst, Plus_Infinity in FPCR
+ };
+
+ const char *AlphaFP::roundingModeSuffix[] = { "c", "m", "", "d" };
+ // mark invalid trapping modes, but don't fail on them, because
+ // you could decode anything on a misspeculated path
+ const char *AlphaFP::fpTrappingModeSuffix[] =
+ { "", "u", "INVTM2", "INVTM3", "INVTM4", "su", "INVTM6", "sui" };
+ const char *AlphaFP::intTrappingModeSuffix[] =
+ { "", "v", "INVTM2", "INVTM3", "INVTM4", "sv", "INVTM6", "svi" };
+}};
+
+// FP instruction class execute method template. Handles non-standard
+// rounding modes.
+def template FloatingPointExecute {{
+ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ if (trappingMode != Imprecise && !warnedOnTrapping) {
+ warn("%s: non-standard trapping mode not supported",
+ generateDisassembly(0, NULL));
+ warnedOnTrapping = true;
+ }
+
+ Fault fault = NoFault;
+
+ %(fp_enable_check)s;
+ %(op_decl)s;
+ %(op_rd)s;
+#if USE_FENV
+ if (roundingMode == Normal) {
+ %(code)s;
+ } else {
+ fesetround(getC99RoundingMode(
+ xc->readMiscReg(AlphaISA::Fpcr_DepTag)));
+ %(code)s;
+ fesetround(FE_TONEAREST);
+ }
+#else
+ if (roundingMode != Normal && !warnedOnRounding) {
+ warn("%s: non-standard rounding mode not supported",
+ generateDisassembly(0, NULL));
+ warnedOnRounding = true;
+ }
+ %(code)s;
+#endif
+
+ if (fault == NoFault) {
+ %(op_wb)s;
+ }
+
+ return fault;
+ }
+}};
+
+// FP instruction class execute method template where no dynamic
+// rounding mode control is needed. Like BasicExecute, but includes
+// check & warning for non-standard trapping mode.
+def template FPFixedRoundingExecute {{
+ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ if (trappingMode != Imprecise && !warnedOnTrapping) {
+ warn("%s: non-standard trapping mode not supported",
+ generateDisassembly(0, NULL));
+ warnedOnTrapping = true;
+ }
+
+ Fault fault = NoFault;
+
+ %(fp_enable_check)s;
+ %(op_decl)s;
+ %(op_rd)s;
+ %(code)s;
+
+ if (fault == NoFault) {
+ %(op_wb)s;
+ }
+
+ return fault;
+ }
+}};
+
+def template FloatingPointDecode {{
+ {
+ AlphaStaticInst *i = new %(class_name)s(machInst);
+ if (FC == 31) {
+ i = makeNop(i);
+ }
+ return i;
+ }
+}};
+
+// General format for floating-point operate instructions:
+// - Checks trapping and rounding mode flags. Trapping modes
+// currently unimplemented (will fail).
+// - Generates NOP if FC == 31.
+def format FloatingPointOperate(code, *opt_args) {{
+ iop = InstObjParams(name, Name, 'AlphaFP', CodeBlock(code), opt_args)
+ decode_block = FloatingPointDecode.subst(iop)
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ exec_output = FloatingPointExecute.subst(iop)
+}};
+
+// Special format for cvttq where rounding mode is pre-decoded
+def format FPFixedRounding(code, class_suffix, *opt_args) {{
+ Name += class_suffix
+ iop = InstObjParams(name, Name, 'AlphaFP', CodeBlock(code), opt_args)
+ decode_block = FloatingPointDecode.subst(iop)
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ exec_output = FPFixedRoundingExecute.subst(iop)
+}};
+
diff --git a/src/arch/alpha/isa/int.isa b/src/arch/alpha/isa/int.isa
new file mode 100644
index 000000000..e097c8467
--- /dev/null
+++ b/src/arch/alpha/isa/int.isa
@@ -0,0 +1,133 @@
+// -*- mode:c++ -*-
+
+// Copyright (c) 2003-2005 The Regents of The University of Michigan
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met: redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer;
+// redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution;
+// neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+////////////////////////////////////////////////////////////////////
+//
+// Integer operate instructions
+//
+
+output header {{
+ /**
+ * Base class for integer immediate instructions.
+ */
+ class IntegerImm : public AlphaStaticInst
+ {
+ protected:
+ /// Immediate operand value (unsigned 8-bit int).
+ uint8_t imm;
+
+ /// Constructor
+ IntegerImm(const char *mnem, ExtMachInst _machInst, OpClass __opClass)
+ : AlphaStaticInst(mnem, _machInst, __opClass), imm(INTIMM)
+ {
+ }
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+}};
+
+output decoder {{
+ std::string
+ IntegerImm::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+ {
+ std::stringstream ss;
+
+ ccprintf(ss, "%-10s ", mnemonic);
+
+ // just print the first source reg... if there's
+ // a second one, it's a read-modify-write dest (Rc),
+ // e.g. for CMOVxx
+ if (_numSrcRegs > 0) {
+ printReg(ss, _srcRegIdx[0]);
+ ss << ",";
+ }
+
+ ss << (int)imm;
+
+ if (_numDestRegs > 0) {
+ ss << ",";
+ printReg(ss, _destRegIdx[0]);
+ }
+
+ return ss.str();
+ }
+}};
+
+
+def template RegOrImmDecode {{
+ {
+ AlphaStaticInst *i =
+ (IMM) ? (AlphaStaticInst *)new %(class_name)sImm(machInst)
+ : (AlphaStaticInst *)new %(class_name)s(machInst);
+ if (RC == 31) {
+ i = makeNop(i);
+ }
+ return i;
+ }
+}};
+
+// Primary format for integer operate instructions:
+// - Generates both reg-reg and reg-imm versions if Rb_or_imm is used.
+// - Generates NOP if RC == 31.
+def format IntegerOperate(code, *opt_flags) {{
+ # If the code block contains 'Rb_or_imm', we define two instructions,
+ # one using 'Rb' and one using 'imm', and have the decoder select
+ # the right one.
+ uses_imm = (code.find('Rb_or_imm') != -1)
+ if uses_imm:
+ orig_code = code
+ # base code is reg version:
+ # rewrite by substituting 'Rb' for 'Rb_or_imm'
+ code = re.sub(r'Rb_or_imm', 'Rb', orig_code)
+ # generate immediate version by substituting 'imm'
+ # note that imm takes no extenstion, so we extend
+ # the regexp to replace any extension as well
+ imm_code = re.sub(r'Rb_or_imm(\.\w+)?', 'imm', orig_code)
+
+ # generate declaration for register version
+ cblk = CodeBlock(code)
+ iop = InstObjParams(name, Name, 'AlphaStaticInst', cblk, opt_flags)
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ exec_output = BasicExecute.subst(iop)
+
+ if uses_imm:
+ # append declaration for imm version
+ imm_cblk = CodeBlock(imm_code)
+ imm_iop = InstObjParams(name, Name + 'Imm', 'IntegerImm', imm_cblk,
+ opt_flags)
+ header_output += BasicDeclare.subst(imm_iop)
+ decoder_output += BasicConstructor.subst(imm_iop)
+ exec_output += BasicExecute.subst(imm_iop)
+ # decode checks IMM bit to pick correct version
+ decode_block = RegOrImmDecode.subst(iop)
+ else:
+ # no imm version: just check for nop
+ decode_block = OperateNopCheckDecode.subst(iop)
+}};
diff --git a/src/arch/alpha/isa/main.isa b/src/arch/alpha/isa/main.isa
new file mode 100644
index 000000000..25d9cc6e9
--- /dev/null
+++ b/src/arch/alpha/isa/main.isa
@@ -0,0 +1,461 @@
+// -*- mode:c++ -*-
+
+// Copyright (c) 2003-2005 The Regents of The University of Michigan
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met: redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer;
+// redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution;
+// neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+////////////////////////////////////////////////////////////////////
+//
+// Alpha ISA description file.
+//
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//
+// Output include file directives.
+//
+
+output header {{
+#include <sstream>
+#include <iostream>
+#include <iomanip>
+
+#include "config/ss_compatible_fp.hh"
+#include "cpu/static_inst.hh"
+#include "arch/alpha/faults.hh"
+#include "mem/request.hh" // some constructors use MemReq flags
+}};
+
+output decoder {{
+#include "base/cprintf.hh"
+#include "base/fenv.hh"
+#include "base/loader/symtab.hh"
+#include "config/ss_compatible_fp.hh"
+#include "cpu/exec_context.hh" // for Jump::branchTarget()
+
+#include <math.h>
+
+using namespace AlphaISA;
+}};
+
+output exec {{
+#include <math.h>
+
+#if FULL_SYSTEM
+#include "sim/pseudo_inst.hh"
+#endif
+#include "base/fenv.hh"
+#include "config/ss_compatible_fp.hh"
+#include "cpu/base.hh"
+#include "cpu/exetrace.hh"
+#include "sim/sim_exit.hh"
+#include "mem/packet_impl.hh"
+
+using namespace AlphaISA;
+}};
+
+////////////////////////////////////////////////////////////////////
+//
+// Namespace statement. Everything below this line will be in the
+// AlphaISAInst namespace.
+//
+
+
+namespace AlphaISA;
+
+////////////////////////////////////////////////////////////////////
+//
+// Bitfield definitions.
+//
+
+// Universal (format-independent) fields
+def bitfield PALMODE <32:32>;
+def bitfield OPCODE <31:26>;
+def bitfield RA <25:21>;
+def bitfield RB <20:16>;
+
+// Memory format
+def signed bitfield MEMDISP <15: 0>; // displacement
+def bitfield MEMFUNC <15: 0>; // function code (same field, unsigned)
+
+// Memory-format jumps
+def bitfield JMPFUNC <15:14>; // function code (disp<15:14>)
+def bitfield JMPHINT <13: 0>; // tgt Icache idx hint (disp<13:0>)
+
+// Branch format
+def signed bitfield BRDISP <20: 0>; // displacement
+
+// Integer operate format(s>;
+def bitfield INTIMM <20:13>; // integer immediate (literal)
+def bitfield IMM <12:12>; // immediate flag
+def bitfield INTFUNC <11: 5>; // function code
+def bitfield RC < 4: 0>; // dest reg
+
+// Floating-point operate format
+def bitfield FA <25:21>;
+def bitfield FB <20:16>;
+def bitfield FP_FULLFUNC <15: 5>; // complete function code
+ def bitfield FP_TRAPMODE <15:13>; // trapping mode
+ def bitfield FP_ROUNDMODE <12:11>; // rounding mode
+ def bitfield FP_TYPEFUNC <10: 5>; // type+func: handiest for decoding
+ def bitfield FP_SRCTYPE <10: 9>; // source reg type
+ def bitfield FP_SHORTFUNC < 8: 5>; // short function code
+ def bitfield FP_SHORTFUNC_TOP2 <8:7>; // top 2 bits of short func code
+def bitfield FC < 4: 0>; // dest reg
+
+// PALcode format
+def bitfield PALFUNC <25: 0>; // function code
+
+// EV5 PAL instructions:
+// HW_LD/HW_ST
+def bitfield HW_LDST_PHYS <15>; // address is physical
+def bitfield HW_LDST_ALT <14>; // use ALT_MODE IPR
+def bitfield HW_LDST_WRTCK <13>; // HW_LD only: fault if no write acc
+def bitfield HW_LDST_QUAD <12>; // size: 0=32b, 1=64b
+def bitfield HW_LDST_VPTE <11>; // HW_LD only: is PTE fetch
+def bitfield HW_LDST_LOCK <10>; // HW_LD only: is load locked
+def bitfield HW_LDST_COND <10>; // HW_ST only: is store conditional
+def signed bitfield HW_LDST_DISP <9:0>; // signed displacement
+
+// HW_REI
+def bitfield HW_REI_TYP <15:14>; // type: stalling vs. non-stallingk
+def bitfield HW_REI_MBZ <13: 0>; // must be zero
+
+// HW_MTPR/MW_MFPR
+def bitfield HW_IPR_IDX <15:0>; // IPR index
+
+// M5 instructions
+def bitfield M5FUNC <7:0>;
+
+def operand_types {{
+ 'sb' : ('signed int', 8),
+ 'ub' : ('unsigned int', 8),
+ 'sw' : ('signed int', 16),
+ 'uw' : ('unsigned int', 16),
+ 'sl' : ('signed int', 32),
+ 'ul' : ('unsigned int', 32),
+ 'sq' : ('signed int', 64),
+ 'uq' : ('unsigned int', 64),
+ 'sf' : ('float', 32),
+ 'df' : ('float', 64)
+}};
+
+def operands {{
+ # Int regs default to unsigned, but code should not count on this.
+ # For clarity, descriptions that depend on unsigned behavior should
+ # explicitly specify '.uq'.
+ 'Ra': ('IntReg', 'uq', 'PALMODE ? AlphaISA::reg_redir[RA] : RA',
+ 'IsInteger', 1),
+ 'Rb': ('IntReg', 'uq', 'PALMODE ? AlphaISA::reg_redir[RB] : RB',
+ 'IsInteger', 2),
+ 'Rc': ('IntReg', 'uq', 'PALMODE ? AlphaISA::reg_redir[RC] : RC',
+ 'IsInteger', 3),
+ 'Fa': ('FloatReg', 'df', 'FA', 'IsFloating', 1),
+ 'Fb': ('FloatReg', 'df', 'FB', 'IsFloating', 2),
+ 'Fc': ('FloatReg', 'df', 'FC', 'IsFloating', 3),
+ 'Mem': ('Mem', 'uq', None, ('IsMemRef', 'IsLoad', 'IsStore'), 4),
+ 'NPC': ('NPC', 'uq', None, ( None, None, 'IsControl' ), 4),
+ 'Runiq': ('ControlReg', 'uq', 'TheISA::Uniq_DepTag', None, 1),
+ 'FPCR': (' ControlReg', 'uq', 'TheISA::Fpcr_DepTag', None, 1),
+ # The next two are hacks for non-full-system call-pal emulation
+ 'R0': ('IntReg', 'uq', '0', None, 1),
+ 'R16': ('IntReg', 'uq', '16', None, 1),
+ 'R17': ('IntReg', 'uq', '17', None, 1),
+ 'R18': ('IntReg', 'uq', '18', None, 1)
+}};
+
+////////////////////////////////////////////////////////////////////
+//
+// Basic instruction classes/templates/formats etc.
+//
+
+output header {{
+// uncomment the following to get SimpleScalar-compatible disassembly
+// (useful for diffing output traces).
+// #define SS_COMPATIBLE_DISASSEMBLY
+
+ /**
+ * Base class for all Alpha static instructions.
+ */
+ class AlphaStaticInst : public StaticInst
+ {
+ protected:
+
+ /// Make AlphaISA register dependence tags directly visible in
+ /// this class and derived classes. Maybe these should really
+ /// live here and not in the AlphaISA namespace.
+ enum DependenceTags {
+ FP_Base_DepTag = AlphaISA::FP_Base_DepTag,
+ Fpcr_DepTag = AlphaISA::Fpcr_DepTag,
+ Uniq_DepTag = AlphaISA::Uniq_DepTag,
+ Lock_Flag_DepTag = AlphaISA::Lock_Flag_DepTag,
+ Lock_Addr_DepTag = AlphaISA::Lock_Addr_DepTag,
+ IPR_Base_DepTag = AlphaISA::IPR_Base_DepTag
+ };
+
+ /// Constructor.
+ AlphaStaticInst(const char *mnem, ExtMachInst _machInst,
+ OpClass __opClass)
+ : StaticInst(mnem, _machInst, __opClass)
+ {
+ }
+
+ /// Print a register name for disassembly given the unique
+ /// dependence tag number (FP or int).
+ void printReg(std::ostream &os, int reg) const;
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+}};
+
+output decoder {{
+ void
+ AlphaStaticInst::printReg(std::ostream &os, int reg) const
+ {
+ if (reg < FP_Base_DepTag) {
+ ccprintf(os, "r%d", reg);
+ }
+ else {
+ ccprintf(os, "f%d", reg - FP_Base_DepTag);
+ }
+ }
+
+ std::string
+ AlphaStaticInst::generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const
+ {
+ std::stringstream ss;
+
+ ccprintf(ss, "%-10s ", mnemonic);
+
+ // just print the first two source regs... if there's
+ // a third one, it's a read-modify-write dest (Rc),
+ // e.g. for CMOVxx
+ if (_numSrcRegs > 0) {
+ printReg(ss, _srcRegIdx[0]);
+ }
+ if (_numSrcRegs > 1) {
+ ss << ",";
+ printReg(ss, _srcRegIdx[1]);
+ }
+
+ // just print the first dest... if there's a second one,
+ // it's generally implicit
+ if (_numDestRegs > 0) {
+ if (_numSrcRegs > 0)
+ ss << ",";
+ printReg(ss, _destRegIdx[0]);
+ }
+
+ return ss.str();
+ }
+}};
+
+// Declarations for execute() methods.
+def template BasicExecDeclare {{
+ Fault execute(%(CPU_exec_context)s *, Trace::InstRecord *) const;
+}};
+
+// Basic instruction class declaration template.
+def template BasicDeclare {{
+ /**
+ * Static instruction class for "%(mnemonic)s".
+ */
+ class %(class_name)s : public %(base_class)s
+ {
+ public:
+ /// Constructor.
+ %(class_name)s(ExtMachInst machInst);
+
+ %(BasicExecDeclare)s
+ };
+}};
+
+// Basic instruction class constructor template.
+def template BasicConstructor {{
+ inline %(class_name)s::%(class_name)s(ExtMachInst machInst)
+ : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
+ {
+ %(constructor)s;
+ }
+}};
+
+// Basic instruction class execute method template.
+def template BasicExecute {{
+ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ Fault fault = NoFault;
+
+ %(fp_enable_check)s;
+ %(op_decl)s;
+ %(op_rd)s;
+ %(code)s;
+
+ if (fault == NoFault) {
+ %(op_wb)s;
+ }
+
+ return fault;
+ }
+}};
+
+// Basic decode template.
+def template BasicDecode {{
+ return new %(class_name)s(machInst);
+}};
+
+// Basic decode template, passing mnemonic in as string arg to constructor.
+def template BasicDecodeWithMnemonic {{
+ return new %(class_name)s("%(mnemonic)s", machInst);
+}};
+
+// The most basic instruction format... used only for a few misc. insts
+def format BasicOperate(code, *flags) {{
+ iop = InstObjParams(name, Name, 'AlphaStaticInst', CodeBlock(code), flags)
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ decode_block = BasicDecode.subst(iop)
+ exec_output = BasicExecute.subst(iop)
+}};
+
+
+
+////////////////////////////////////////////////////////////////////
+//
+// Nop
+//
+
+output header {{
+ /**
+ * Static instruction class for no-ops. This is a leaf class.
+ */
+ class Nop : public AlphaStaticInst
+ {
+ /// Disassembly of original instruction.
+ const std::string originalDisassembly;
+
+ public:
+ /// Constructor
+ Nop(const std::string _originalDisassembly, ExtMachInst _machInst)
+ : AlphaStaticInst("nop", _machInst, No_OpClass),
+ originalDisassembly(_originalDisassembly)
+ {
+ flags[IsNop] = true;
+ }
+
+ ~Nop() { }
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+
+ %(BasicExecDeclare)s
+ };
+
+ /// Helper function for decoding nops. Substitute Nop object
+ /// for original inst passed in as arg (and delete latter).
+ static inline
+ AlphaStaticInst *
+ makeNop(AlphaStaticInst *inst)
+ {
+ AlphaStaticInst *nop = new Nop(inst->disassemble(0), inst->machInst);
+ delete inst;
+ return nop;
+ }
+}};
+
+output decoder {{
+ std::string Nop::generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const
+ {
+#ifdef SS_COMPATIBLE_DISASSEMBLY
+ return originalDisassembly;
+#else
+ return csprintf("%-10s (%s)", "nop", originalDisassembly);
+#endif
+ }
+}};
+
+output exec {{
+ Fault
+ Nop::execute(%(CPU_exec_context)s *, Trace::InstRecord *) const
+ {
+ return NoFault;
+ }
+}};
+
+// integer & FP operate instructions use Rc as dest, so check for
+// Rc == 31 to detect nops
+def template OperateNopCheckDecode {{
+ {
+ AlphaStaticInst *i = new %(class_name)s(machInst);
+ if (RC == 31) {
+ i = makeNop(i);
+ }
+ return i;
+ }
+}};
+
+// Like BasicOperate format, but generates NOP if RC/FC == 31
+def format BasicOperateWithNopCheck(code, *opt_args) {{
+ iop = InstObjParams(name, Name, 'AlphaStaticInst', CodeBlock(code),
+ opt_args)
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ decode_block = OperateNopCheckDecode.subst(iop)
+ exec_output = BasicExecute.subst(iop)
+}};
+
+// Integer instruction templates, formats, etc.
+##include "int.isa"
+
+// Floating-point instruction templates, formats, etc.
+##include "fp.isa"
+
+// Memory instruction templates, formats, etc.
+##include "mem.isa"
+
+// Branch/jump instruction templates, formats, etc.
+##include "branch.isa"
+
+// PAL instruction templates, formats, etc.
+##include "pal.isa"
+
+// Opcdec fault instruction templates, formats, etc.
+##include "opcdec.isa"
+
+// Unimplemented instruction templates, formats, etc.
+##include "unimp.isa"
+
+// Unknown instruction templates, formats, etc.
+##include "unknown.isa"
+
+// Execution utility functions
+##include "util.isa"
+
+// The actual decoder
+##include "decoder.isa"
diff --git a/src/arch/alpha/isa/mem.isa b/src/arch/alpha/isa/mem.isa
new file mode 100644
index 000000000..b2e6fc07e
--- /dev/null
+++ b/src/arch/alpha/isa/mem.isa
@@ -0,0 +1,734 @@
+// -*- mode:c++ -*-
+
+// Copyright (c) 2003-2005 The Regents of The University of Michigan
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met: redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer;
+// redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution;
+// neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+////////////////////////////////////////////////////////////////////
+//
+// Memory-format instructions: LoadAddress, Load, Store
+//
+
+output header {{
+ /**
+ * Base class for general Alpha memory-format instructions.
+ */
+ class Memory : public AlphaStaticInst
+ {
+ protected:
+
+ /// Memory request flags. See mem_req_base.hh.
+ unsigned memAccessFlags;
+ /// Pointer to EAComp object.
+ const StaticInstPtr eaCompPtr;
+ /// Pointer to MemAcc object.
+ const StaticInstPtr memAccPtr;
+
+ /// Constructor
+ Memory(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
+ StaticInstPtr _eaCompPtr = nullStaticInstPtr,
+ StaticInstPtr _memAccPtr = nullStaticInstPtr)
+ : AlphaStaticInst(mnem, _machInst, __opClass),
+ memAccessFlags(0), eaCompPtr(_eaCompPtr), memAccPtr(_memAccPtr)
+ {
+ }
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+
+ public:
+
+ const StaticInstPtr &eaCompInst() const { return eaCompPtr; }
+ const StaticInstPtr &memAccInst() const { return memAccPtr; }
+ };
+
+ /**
+ * Base class for memory-format instructions using a 32-bit
+ * displacement (i.e. most of them).
+ */
+ class MemoryDisp32 : public Memory
+ {
+ protected:
+ /// Displacement for EA calculation (signed).
+ int32_t disp;
+
+ /// Constructor.
+ MemoryDisp32(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
+ StaticInstPtr _eaCompPtr = nullStaticInstPtr,
+ StaticInstPtr _memAccPtr = nullStaticInstPtr)
+ : Memory(mnem, _machInst, __opClass, _eaCompPtr, _memAccPtr),
+ disp(MEMDISP)
+ {
+ }
+ };
+
+
+ /**
+ * Base class for a few miscellaneous memory-format insts
+ * that don't interpret the disp field: wh64, fetch, fetch_m, ecb.
+ * None of these instructions has a destination register either.
+ */
+ class MemoryNoDisp : public Memory
+ {
+ protected:
+ /// Constructor
+ MemoryNoDisp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
+ StaticInstPtr _eaCompPtr = nullStaticInstPtr,
+ StaticInstPtr _memAccPtr = nullStaticInstPtr)
+ : Memory(mnem, _machInst, __opClass, _eaCompPtr, _memAccPtr)
+ {
+ }
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+}};
+
+
+output decoder {{
+ std::string
+ Memory::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+ {
+ return csprintf("%-10s %c%d,%d(r%d)", mnemonic,
+ flags[IsFloating] ? 'f' : 'r', RA, MEMDISP, RB);
+ }
+
+ std::string
+ MemoryNoDisp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+ {
+ return csprintf("%-10s (r%d)", mnemonic, RB);
+ }
+}};
+
+def format LoadAddress(code) {{
+ iop = InstObjParams(name, Name, 'MemoryDisp32', CodeBlock(code))
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ decode_block = BasicDecode.subst(iop)
+ exec_output = BasicExecute.subst(iop)
+}};
+
+
+def template LoadStoreDeclare {{
+ /**
+ * Static instruction class for "%(mnemonic)s".
+ */
+ class %(class_name)s : public %(base_class)s
+ {
+ protected:
+
+ /**
+ * "Fake" effective address computation class for "%(mnemonic)s".
+ */
+ class EAComp : public %(base_class)s
+ {
+ public:
+ /// Constructor
+ EAComp(ExtMachInst machInst);
+
+ %(BasicExecDeclare)s
+ };
+
+ /**
+ * "Fake" memory access instruction class for "%(mnemonic)s".
+ */
+ class MemAcc : public %(base_class)s
+ {
+ public:
+ /// Constructor
+ MemAcc(ExtMachInst machInst);
+
+ %(BasicExecDeclare)s
+ };
+
+ public:
+
+ /// Constructor.
+ %(class_name)s(ExtMachInst machInst);
+
+ %(BasicExecDeclare)s
+
+ %(InitiateAccDeclare)s
+
+ %(CompleteAccDeclare)s
+ };
+}};
+
+
+def template InitiateAccDeclare {{
+ Fault initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const;
+}};
+
+
+def template CompleteAccDeclare {{
+ Fault completeAcc(Packet *, %(CPU_exec_context)s *,
+ Trace::InstRecord *) const;
+}};
+
+
+def template LoadStoreConstructor {{
+ /** TODO: change op_class to AddrGenOp or something (requires
+ * creating new member of OpClass enum in op_class.hh, updating
+ * config files, etc.). */
+ inline %(class_name)s::EAComp::EAComp(ExtMachInst machInst)
+ : %(base_class)s("%(mnemonic)s (EAComp)", machInst, IntAluOp)
+ {
+ %(ea_constructor)s;
+ }
+
+ inline %(class_name)s::MemAcc::MemAcc(ExtMachInst machInst)
+ : %(base_class)s("%(mnemonic)s (MemAcc)", machInst, %(op_class)s)
+ {
+ %(memacc_constructor)s;
+ }
+
+ inline %(class_name)s::%(class_name)s(ExtMachInst machInst)
+ : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
+ new EAComp(machInst), new MemAcc(machInst))
+ {
+ %(constructor)s;
+ }
+}};
+
+
+def template EACompExecute {{
+ Fault
+ %(class_name)s::EAComp::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ Addr EA;
+ Fault fault = NoFault;
+
+ %(fp_enable_check)s;
+ %(op_decl)s;
+ %(op_rd)s;
+ %(code)s;
+
+ if (fault == NoFault) {
+ %(op_wb)s;
+ xc->setEA(EA);
+ }
+
+ return fault;
+ }
+}};
+
+def template LoadMemAccExecute {{
+ Fault
+ %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ Addr EA;
+ Fault fault = NoFault;
+
+ %(fp_enable_check)s;
+ %(op_decl)s;
+ %(op_rd)s;
+ EA = xc->getEA();
+
+ if (fault == NoFault) {
+ fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags);
+ %(code)s;
+ }
+
+ if (fault == NoFault) {
+ %(op_wb)s;
+ }
+
+ return fault;
+ }
+}};
+
+
+def template LoadExecute {{
+ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ Addr EA;
+ Fault fault = NoFault;
+
+ %(fp_enable_check)s;
+ %(op_decl)s;
+ %(op_rd)s;
+ %(ea_code)s;
+
+ if (fault == NoFault) {
+ fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags);
+ %(memacc_code)s;
+ }
+
+ if (fault == NoFault) {
+ %(op_wb)s;
+ }
+
+ return fault;
+ }
+}};
+
+
+def template LoadInitiateAcc {{
+ Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ Addr EA;
+ Fault fault = NoFault;
+
+ %(fp_enable_check)s;
+ %(op_src_decl)s;
+ %(op_rd)s;
+ %(ea_code)s;
+
+ if (fault == NoFault) {
+ fault = xc->read(EA, (uint%(mem_acc_size)d_t &)Mem, memAccessFlags);
+ }
+
+ return fault;
+ }
+}};
+
+
+def template LoadCompleteAcc {{
+ Fault %(class_name)s::completeAcc(Packet *pkt,
+ %(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ Fault fault = NoFault;
+
+ %(fp_enable_check)s;
+ %(op_decl)s;
+
+ Mem = pkt->get<typeof(Mem)>();
+
+ if (fault == NoFault) {
+ %(memacc_code)s;
+ }
+
+ if (fault == NoFault) {
+ %(op_wb)s;
+ }
+
+ return fault;
+ }
+}};
+
+
+def template StoreMemAccExecute {{
+ Fault
+ %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ Addr EA;
+ Fault fault = NoFault;
+ uint64_t write_result = 0;
+
+ %(fp_enable_check)s;
+ %(op_decl)s;
+ %(op_rd)s;
+ EA = xc->getEA();
+
+ if (fault == NoFault) {
+ %(code)s;
+ }
+
+ if (fault == NoFault) {
+ fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
+ memAccessFlags, &write_result);
+ if (traceData) { traceData->setData(Mem); }
+ }
+
+ if (fault == NoFault) {
+ %(postacc_code)s;
+ }
+
+ if (fault == NoFault) {
+ %(op_wb)s;
+ }
+
+ return fault;
+ }
+}};
+
+
+def template StoreExecute {{
+ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ Addr EA;
+ Fault fault = NoFault;
+ uint64_t write_result = 0;
+
+ %(fp_enable_check)s;
+ %(op_decl)s;
+ %(op_rd)s;
+ %(ea_code)s;
+
+ if (fault == NoFault) {
+ %(memacc_code)s;
+ }
+
+ if (fault == NoFault) {
+ fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
+ memAccessFlags, &write_result);
+ if (traceData) { traceData->setData(Mem); }
+ }
+
+ if (fault == NoFault) {
+ %(postacc_code)s;
+ }
+
+ if (fault == NoFault) {
+ %(op_wb)s;
+ }
+
+ return fault;
+ }
+}};
+
+def template StoreInitiateAcc {{
+ Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ Addr EA;
+ Fault fault = NoFault;
+
+ %(fp_enable_check)s;
+ %(op_decl)s;
+ %(op_rd)s;
+ %(ea_code)s;
+
+ if (fault == NoFault) {
+ %(memacc_code)s;
+ }
+
+ if (fault == NoFault) {
+ fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
+ memAccessFlags, NULL);
+ if (traceData) { traceData->setData(Mem); }
+ }
+
+ return fault;
+ }
+}};
+
+
+def template StoreCompleteAcc {{
+ Fault %(class_name)s::completeAcc(Packet *pkt,
+ %(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ Fault fault = NoFault;
+
+ %(fp_enable_check)s;
+ %(op_dest_decl)s;
+
+ if (fault == NoFault) {
+ %(postacc_code)s;
+ }
+
+ if (fault == NoFault) {
+ %(op_wb)s;
+ }
+
+ return fault;
+ }
+}};
+
+
+def template StoreCondCompleteAcc {{
+ Fault %(class_name)s::completeAcc(Packet *pkt,
+ %(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ Fault fault = NoFault;
+
+ %(fp_enable_check)s;
+ %(op_dest_decl)s;
+
+ uint64_t write_result = pkt->req->getScResult();
+
+ if (fault == NoFault) {
+ %(postacc_code)s;
+ }
+
+ if (fault == NoFault) {
+ %(op_wb)s;
+ }
+
+ return fault;
+ }
+}};
+
+
+def template MiscMemAccExecute {{
+ Fault %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ Addr EA;
+ Fault fault = NoFault;
+
+ %(fp_enable_check)s;
+ %(op_decl)s;
+ %(op_rd)s;
+ EA = xc->getEA();
+
+ if (fault == NoFault) {
+ %(code)s;
+ }
+
+ return NoFault;
+ }
+}};
+
+def template MiscExecute {{
+ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ Addr EA;
+ Fault fault = NoFault;
+
+ %(fp_enable_check)s;
+ %(op_decl)s;
+ %(op_rd)s;
+ %(ea_code)s;
+
+ if (fault == NoFault) {
+ %(memacc_code)s;
+ }
+
+ return NoFault;
+ }
+}};
+
+def template MiscInitiateAcc {{
+ Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ panic("Misc instruction does not support split access method!");
+ return NoFault;
+ }
+}};
+
+
+def template MiscCompleteAcc {{
+ Fault %(class_name)s::completeAcc(Packet *pkt,
+ %(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ panic("Misc instruction does not support split access method!");
+
+ return NoFault;
+ }
+}};
+
+// load instructions use Ra as dest, so check for
+// Ra == 31 to detect nops
+def template LoadNopCheckDecode {{
+ {
+ AlphaStaticInst *i = new %(class_name)s(machInst);
+ if (RA == 31) {
+ i = makeNop(i);
+ }
+ return i;
+ }
+}};
+
+
+// for some load instructions, Ra == 31 indicates a prefetch (not a nop)
+def template LoadPrefetchCheckDecode {{
+ {
+ if (RA != 31) {
+ return new %(class_name)s(machInst);
+ }
+ else {
+ return new %(class_name)sPrefetch(machInst);
+ }
+ }
+}};
+
+
+let {{
+def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
+ postacc_code = '', base_class = 'MemoryDisp32',
+ decode_template = BasicDecode, exec_template_base = ''):
+ # Make sure flags are in lists (convert to lists if not).
+ mem_flags = makeList(mem_flags)
+ inst_flags = makeList(inst_flags)
+
+ # add hook to get effective addresses into execution trace output.
+ ea_code += '\nif (traceData) { traceData->setAddr(EA); }\n'
+
+ # generate code block objects
+ ea_cblk = CodeBlock(ea_code)
+ memacc_cblk = CodeBlock(memacc_code)
+ postacc_cblk = CodeBlock(postacc_code)
+
+ # Some CPU models execute the memory operation as an atomic unit,
+ # while others want to separate them into an effective address
+ # computation and a memory access operation. As a result, we need
+ # to generate three StaticInst objects. Note that the latter two
+ # are nested inside the larger "atomic" one.
+
+ # generate InstObjParams for EAComp object
+ ea_iop = InstObjParams(name, Name, base_class, ea_cblk, inst_flags)
+
+ # generate InstObjParams for MemAcc object
+ memacc_iop = InstObjParams(name, Name, base_class, memacc_cblk, inst_flags)
+ # in the split execution model, the MemAcc portion is responsible
+ # for the post-access code.
+ memacc_iop.postacc_code = postacc_cblk.code
+
+ # generate InstObjParams for InitiateAcc, CompleteAcc object
+ # The code used depends on the template being used
+ if (exec_template_base == 'Load'):
+ initiateacc_cblk = CodeBlock(ea_code + memacc_code)
+ completeacc_cblk = CodeBlock(memacc_code + postacc_code)
+ elif (exec_template_base.startswith('Store')):
+ initiateacc_cblk = CodeBlock(ea_code + memacc_code)
+ completeacc_cblk = CodeBlock(postacc_code)
+ else:
+ initiateacc_cblk = ''
+ completeacc_cblk = ''
+
+ initiateacc_iop = InstObjParams(name, Name, base_class, initiateacc_cblk,
+ inst_flags)
+
+ completeacc_iop = InstObjParams(name, Name, base_class, completeacc_cblk,
+ inst_flags)
+
+ if (exec_template_base == 'Load'):
+ initiateacc_iop.ea_code = ea_cblk.code
+ initiateacc_iop.memacc_code = memacc_cblk.code
+ completeacc_iop.memacc_code = memacc_cblk.code
+ completeacc_iop.postacc_code = postacc_cblk.code
+ elif (exec_template_base.startswith('Store')):
+ initiateacc_iop.ea_code = ea_cblk.code
+ initiateacc_iop.memacc_code = memacc_cblk.code
+ completeacc_iop.postacc_code = postacc_cblk.code
+
+ # generate InstObjParams for unified execution
+ cblk = CodeBlock(ea_code + memacc_code + postacc_code)
+ iop = InstObjParams(name, Name, base_class, cblk, inst_flags)
+
+ iop.ea_constructor = ea_cblk.constructor
+ iop.ea_code = ea_cblk.code
+ iop.memacc_constructor = memacc_cblk.constructor
+ iop.memacc_code = memacc_cblk.code
+ iop.postacc_code = postacc_cblk.code
+
+ if mem_flags:
+ s = '\n\tmemAccessFlags = ' + string.join(mem_flags, '|') + ';'
+ iop.constructor += s
+ memacc_iop.constructor += s
+
+ # select templates
+
+ # define aliases... most StoreCond templates are the same as the
+ # corresponding Store templates (only CompleteAcc is different).
+ StoreCondMemAccExecute = StoreMemAccExecute
+ StoreCondExecute = StoreExecute
+ StoreCondInitiateAcc = StoreInitiateAcc
+
+ memAccExecTemplate = eval(exec_template_base + 'MemAccExecute')
+ fullExecTemplate = eval(exec_template_base + 'Execute')
+ initiateAccTemplate = eval(exec_template_base + 'InitiateAcc')
+ completeAccTemplate = eval(exec_template_base + 'CompleteAcc')
+
+ # (header_output, decoder_output, decode_block, exec_output)
+ return (LoadStoreDeclare.subst(iop), LoadStoreConstructor.subst(iop),
+ decode_template.subst(iop),
+ EACompExecute.subst(ea_iop)
+ + memAccExecTemplate.subst(memacc_iop)
+ + fullExecTemplate.subst(iop)
+ + initiateAccTemplate.subst(initiateacc_iop)
+ + completeAccTemplate.subst(completeacc_iop))
+}};
+
+
+def format LoadOrNop(memacc_code, ea_code = {{ EA = Rb + disp; }},
+ mem_flags = [], inst_flags = []) {{
+ (header_output, decoder_output, decode_block, exec_output) = \
+ LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
+ decode_template = LoadNopCheckDecode,
+ exec_template_base = 'Load')
+}};
+
+
+// Note that the flags passed in apply only to the prefetch version
+def format LoadOrPrefetch(memacc_code, ea_code = {{ EA = Rb + disp; }},
+ mem_flags = [], pf_flags = [], inst_flags = []) {{
+ # declare the load instruction object and generate the decode block
+ (header_output, decoder_output, decode_block, exec_output) = \
+ LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
+ decode_template = LoadPrefetchCheckDecode,
+ exec_template_base = 'Load')
+
+ # Declare the prefetch instruction object.
+
+ # Make sure flag args are lists so we can mess with them.
+ mem_flags = makeList(mem_flags)
+ pf_flags = makeList(pf_flags)
+ inst_flags = makeList(inst_flags)
+
+ pf_mem_flags = mem_flags + pf_flags + ['NO_FAULT']
+ pf_inst_flags = inst_flags + ['IsMemRef', 'IsLoad',
+ 'IsDataPrefetch', 'MemReadOp']
+
+ (pf_header_output, pf_decoder_output, _, pf_exec_output) = \
+ LoadStoreBase(name, Name + 'Prefetch', ea_code,
+ 'xc->prefetch(EA, memAccessFlags);',
+ pf_mem_flags, pf_inst_flags, exec_template_base = 'Misc')
+
+ header_output += pf_header_output
+ decoder_output += pf_decoder_output
+ exec_output += pf_exec_output
+}};
+
+
+def format Store(memacc_code, ea_code = {{ EA = Rb + disp; }},
+ mem_flags = [], inst_flags = []) {{
+ (header_output, decoder_output, decode_block, exec_output) = \
+ LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
+ exec_template_base = 'Store')
+}};
+
+
+def format StoreCond(memacc_code, postacc_code,
+ ea_code = {{ EA = Rb + disp; }},
+ mem_flags = [], inst_flags = []) {{
+ (header_output, decoder_output, decode_block, exec_output) = \
+ LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
+ postacc_code, exec_template_base = 'StoreCond')
+}};
+
+
+// Use 'MemoryNoDisp' as base: for wh64, fetch, ecb
+def format MiscPrefetch(ea_code, memacc_code,
+ mem_flags = [], inst_flags = []) {{
+ (header_output, decoder_output, decode_block, exec_output) = \
+ LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
+ base_class = 'MemoryNoDisp', exec_template_base = 'Misc')
+}};
+
+
diff --git a/src/arch/alpha/isa/opcdec.isa b/src/arch/alpha/isa/opcdec.isa
new file mode 100644
index 000000000..add4704dd
--- /dev/null
+++ b/src/arch/alpha/isa/opcdec.isa
@@ -0,0 +1,77 @@
+// -*- mode:c++ -*-
+
+// Copyright (c) 2003-2005 The Regents of The University of Michigan
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met: redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer;
+// redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution;
+// neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+////////////////////////////////////////////////////////////////////
+//
+// OPCDEC fault instructions
+//
+
+output header {{
+ /**
+ * Static instruction class for instructions that cause an OPCDEC fault
+ * when executed. This is currently only for PAL mode instructions
+ * executed in non-PAL mode.
+ */
+ class OpcdecFault : public AlphaStaticInst
+ {
+ public:
+ /// Constructor
+ OpcdecFault(ExtMachInst _machInst)
+ : AlphaStaticInst("opcdec fault", _machInst, No_OpClass)
+ {
+ }
+
+ %(BasicExecDeclare)s
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+}};
+
+output decoder {{
+ std::string
+ OpcdecFault::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+ {
+ return csprintf("%-10s (inst 0x%x, opcode 0x%x)",
+ " OPCDEC fault", machInst, OPCODE);
+ }
+}};
+
+output exec {{
+ Fault
+ OpcdecFault::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ return new UnimplementedOpcodeFault;
+ }
+}};
+
+def format OpcdecFault() {{
+ decode_block = 'return new OpcdecFault(machInst);\n'
+}};
+
diff --git a/src/arch/alpha/isa/pal.isa b/src/arch/alpha/isa/pal.isa
new file mode 100644
index 000000000..37de20617
--- /dev/null
+++ b/src/arch/alpha/isa/pal.isa
@@ -0,0 +1,278 @@
+// -*- mode:c++ -*-
+
+// Copyright (c) 2003-2005 The Regents of The University of Michigan
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met: redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer;
+// redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution;
+// neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+////////////////////////////////////////////////////////////////////
+//
+// PAL calls & PAL-specific instructions
+//
+
+output header {{
+ /**
+ * Base class for emulated call_pal calls (used only in
+ * non-full-system mode).
+ */
+ class EmulatedCallPal : public AlphaStaticInst
+ {
+ protected:
+
+ /// Constructor.
+ EmulatedCallPal(const char *mnem, ExtMachInst _machInst,
+ OpClass __opClass)
+ : AlphaStaticInst(mnem, _machInst, __opClass)
+ {
+ }
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+}};
+
+output decoder {{
+ std::string
+ EmulatedCallPal::generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const
+ {
+#ifdef SS_COMPATIBLE_DISASSEMBLY
+ return csprintf("%s %s", "call_pal", mnemonic);
+#else
+ return csprintf("%-10s %s", "call_pal", mnemonic);
+#endif
+ }
+}};
+
+def format EmulatedCallPal(code, *flags) {{
+ iop = InstObjParams(name, Name, 'EmulatedCallPal', CodeBlock(code), flags)
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ decode_block = BasicDecode.subst(iop)
+ exec_output = BasicExecute.subst(iop)
+}};
+
+output header {{
+ /**
+ * Base class for full-system-mode call_pal instructions.
+ * Probably could turn this into a leaf class and get rid of the
+ * parser template.
+ */
+ class CallPalBase : public AlphaStaticInst
+ {
+ protected:
+ int palFunc; ///< Function code part of instruction
+ int palOffset; ///< Target PC, offset from IPR_PAL_BASE
+ bool palValid; ///< is the function code valid?
+ bool palPriv; ///< is this call privileged?
+
+ /// Constructor.
+ CallPalBase(const char *mnem, ExtMachInst _machInst,
+ OpClass __opClass);
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+}};
+
+output decoder {{
+ inline
+ CallPalBase::CallPalBase(const char *mnem, ExtMachInst _machInst,
+ OpClass __opClass)
+ : AlphaStaticInst(mnem, _machInst, __opClass),
+ palFunc(PALFUNC)
+ {
+ // From the 21164 HRM (paraphrased):
+ // Bit 7 of the function code (mask 0x80) indicates
+ // whether the call is privileged (bit 7 == 0) or
+ // unprivileged (bit 7 == 1). The privileged call table
+ // starts at 0x2000, the unprivielged call table starts at
+ // 0x3000. Bits 5-0 (mask 0x3f) are used to calculate the
+ // offset.
+ const int palPrivMask = 0x80;
+ const int palOffsetMask = 0x3f;
+
+ // Pal call is invalid unless all other bits are 0
+ palValid = ((machInst & ~(palPrivMask | palOffsetMask)) == 0);
+ palPriv = ((machInst & palPrivMask) == 0);
+ int shortPalFunc = (machInst & palOffsetMask);
+ // Add 1 to base to set pal-mode bit
+ palOffset = (palPriv ? 0x2001 : 0x3001) + (shortPalFunc << 6);
+ }
+
+ std::string
+ CallPalBase::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+ {
+ return csprintf("%-10s %#x", "call_pal", palFunc);
+ }
+}};
+
+def format CallPal(code, *flags) {{
+ iop = InstObjParams(name, Name, 'CallPalBase', CodeBlock(code), flags)
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ decode_block = BasicDecode.subst(iop)
+ exec_output = BasicExecute.subst(iop)
+}};
+
+////////////////////////////////////////////////////////////////////
+//
+// hw_ld, hw_st
+//
+
+output header {{
+ /**
+ * Base class for hw_ld and hw_st.
+ */
+ class HwLoadStore : public Memory
+ {
+ protected:
+
+ /// Displacement for EA calculation (signed).
+ int16_t disp;
+
+ /// Constructor
+ HwLoadStore(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
+ StaticInstPtr _eaCompPtr = nullStaticInstPtr,
+ StaticInstPtr _memAccPtr = nullStaticInstPtr);
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+}};
+
+
+output decoder {{
+ inline
+ HwLoadStore::HwLoadStore(const char *mnem, ExtMachInst _machInst,
+ OpClass __opClass,
+ StaticInstPtr _eaCompPtr,
+ StaticInstPtr _memAccPtr)
+ : Memory(mnem, _machInst, __opClass, _eaCompPtr, _memAccPtr),
+ disp(HW_LDST_DISP)
+ {
+ memAccessFlags = 0;
+ if (HW_LDST_PHYS) memAccessFlags |= PHYSICAL;
+ if (HW_LDST_ALT) memAccessFlags |= ALTMODE;
+ if (HW_LDST_VPTE) memAccessFlags |= VPTE;
+ if (HW_LDST_LOCK) memAccessFlags |= LOCKED;
+ }
+
+ std::string
+ HwLoadStore::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+ {
+#ifdef SS_COMPATIBLE_DISASSEMBLY
+ return csprintf("%-10s r%d,%d(r%d)", mnemonic, RA, disp, RB);
+#else
+ // HW_LDST_LOCK and HW_LDST_COND are the same bit.
+ const char *lock_str =
+ (HW_LDST_LOCK) ? (flags[IsLoad] ? ",LOCK" : ",COND") : "";
+
+ return csprintf("%-10s r%d,%d(r%d)%s%s%s%s%s",
+ mnemonic, RA, disp, RB,
+ HW_LDST_PHYS ? ",PHYS" : "",
+ HW_LDST_ALT ? ",ALT" : "",
+ HW_LDST_QUAD ? ",QUAD" : "",
+ HW_LDST_VPTE ? ",VPTE" : "",
+ lock_str);
+#endif
+ }
+}};
+
+def format HwLoad(ea_code, memacc_code, class_ext, *flags) {{
+ (header_output, decoder_output, decode_block, exec_output) = \
+ LoadStoreBase(name, Name + class_ext, ea_code, memacc_code,
+ mem_flags = [], inst_flags = flags,
+ base_class = 'HwLoadStore', exec_template_base = 'Load')
+}};
+
+
+def format HwStore(ea_code, memacc_code, class_ext, *flags) {{
+ (header_output, decoder_output, decode_block, exec_output) = \
+ LoadStoreBase(name, Name + class_ext, ea_code, memacc_code,
+ mem_flags = [], inst_flags = flags,
+ base_class = 'HwLoadStore', exec_template_base = 'Store')
+}};
+
+
+def format HwStoreCond(ea_code, memacc_code, postacc_code, class_ext,
+ *flags) {{
+ (header_output, decoder_output, decode_block, exec_output) = \
+ LoadStoreBase(name, Name + class_ext, ea_code, memacc_code,
+ postacc_code, mem_flags = [], inst_flags = flags,
+ base_class = 'HwLoadStore')
+}};
+
+
+output header {{
+ /**
+ * Base class for hw_mfpr and hw_mtpr.
+ */
+ class HwMoveIPR : public AlphaStaticInst
+ {
+ protected:
+ /// Index of internal processor register.
+ int ipr_index;
+
+ /// Constructor
+ HwMoveIPR(const char *mnem, ExtMachInst _machInst, OpClass __opClass)
+ : AlphaStaticInst(mnem, _machInst, __opClass),
+ ipr_index(HW_IPR_IDX)
+ {
+ }
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+}};
+
+output decoder {{
+ std::string
+ HwMoveIPR::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+ {
+ if (_numSrcRegs > 0) {
+ // must be mtpr
+ return csprintf("%-10s r%d,IPR(%#x)",
+ mnemonic, RA, ipr_index);
+ }
+ else {
+ // must be mfpr
+ return csprintf("%-10s IPR(%#x),r%d",
+ mnemonic, ipr_index, RA);
+ }
+ }
+}};
+
+def format HwMoveIPR(code, *flags) {{
+ all_flags = ['IprAccessOp']
+ all_flags += flags
+ iop = InstObjParams(name, Name, 'HwMoveIPR', CodeBlock(code),
+ all_flags)
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ decode_block = BasicDecode.subst(iop)
+ exec_output = BasicExecute.subst(iop)
+}};
+
+
diff --git a/src/arch/alpha/isa/unimp.isa b/src/arch/alpha/isa/unimp.isa
new file mode 100644
index 000000000..c96498764
--- /dev/null
+++ b/src/arch/alpha/isa/unimp.isa
@@ -0,0 +1,170 @@
+// -*- mode:c++ -*-
+
+// Copyright (c) 2003-2005 The Regents of The University of Michigan
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met: redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer;
+// redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution;
+// neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+////////////////////////////////////////////////////////////////////
+//
+// Unimplemented instructions
+//
+
+output header {{
+ /**
+ * Static instruction class for unimplemented instructions that
+ * cause simulator termination. Note that these are recognized
+ * (legal) instructions that the simulator does not support; the
+ * 'Unknown' class is used for unrecognized/illegal instructions.
+ * This is a leaf class.
+ */
+ class FailUnimplemented : public AlphaStaticInst
+ {
+ public:
+ /// Constructor
+ FailUnimplemented(const char *_mnemonic, ExtMachInst _machInst)
+ : AlphaStaticInst(_mnemonic, _machInst, No_OpClass)
+ {
+ // don't call execute() (which panics) if we're on a
+ // speculative path
+ flags[IsNonSpeculative] = true;
+ }
+
+ %(BasicExecDeclare)s
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+
+ /**
+ * Base class for unimplemented instructions that cause a warning
+ * to be printed (but do not terminate simulation). This
+ * implementation is a little screwy in that it will print a
+ * warning for each instance of a particular unimplemented machine
+ * instruction, not just for each unimplemented opcode. Should
+ * probably make the 'warned' flag a static member of the derived
+ * class.
+ */
+ class WarnUnimplemented : public AlphaStaticInst
+ {
+ private:
+ /// Have we warned on this instruction yet?
+ mutable bool warned;
+
+ public:
+ /// Constructor
+ WarnUnimplemented(const char *_mnemonic, ExtMachInst _machInst)
+ : AlphaStaticInst(_mnemonic, _machInst, No_OpClass), warned(false)
+ {
+ // don't call execute() (which panics) if we're on a
+ // speculative path
+ flags[IsNonSpeculative] = true;
+ }
+
+ %(BasicExecDeclare)s
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+}};
+
+output decoder {{
+ std::string
+ FailUnimplemented::generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const
+ {
+ return csprintf("%-10s (unimplemented)", mnemonic);
+ }
+
+ std::string
+ WarnUnimplemented::generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const
+ {
+#ifdef SS_COMPATIBLE_DISASSEMBLY
+ return csprintf("%-10s", mnemonic);
+#else
+ return csprintf("%-10s (unimplemented)", mnemonic);
+#endif
+ }
+}};
+
+output exec {{
+ Fault
+ FailUnimplemented::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ panic("attempt to execute unimplemented instruction '%s' "
+ "(inst 0x%08x, opcode 0x%x)", mnemonic, machInst, OPCODE);
+ return new UnimplementedOpcodeFault;
+ }
+
+ Fault
+ WarnUnimplemented::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ if (!warned) {
+ warn("instruction '%s' unimplemented\n", mnemonic);
+ warned = true;
+ }
+
+ return NoFault;
+ }
+}};
+
+
+def format FailUnimpl() {{
+ iop = InstObjParams(name, 'FailUnimplemented')
+ decode_block = BasicDecodeWithMnemonic.subst(iop)
+}};
+
+def format WarnUnimpl() {{
+ iop = InstObjParams(name, 'WarnUnimplemented')
+ decode_block = BasicDecodeWithMnemonic.subst(iop)
+}};
+
+output header {{
+ /**
+ * Static instruction class for unknown (illegal) instructions.
+ * These cause simulator termination if they are executed in a
+ * non-speculative mode. This is a leaf class.
+ */
+ class Unknown : public AlphaStaticInst
+ {
+ public:
+ /// Constructor
+ Unknown(ExtMachInst _machInst)
+ : AlphaStaticInst("unknown", _machInst, No_OpClass)
+ {
+ // don't call execute() (which panics) if we're on a
+ // speculative path
+ flags[IsNonSpeculative] = true;
+ }
+
+ %(BasicExecDeclare)s
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+}};
+
diff --git a/src/arch/alpha/isa/unknown.isa b/src/arch/alpha/isa/unknown.isa
new file mode 100644
index 000000000..fb0cee54e
--- /dev/null
+++ b/src/arch/alpha/isa/unknown.isa
@@ -0,0 +1,57 @@
+// -*- mode:c++ -*-
+
+// Copyright (c) 2003-2005 The Regents of The University of Michigan
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met: redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer;
+// redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution;
+// neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+////////////////////////////////////////////////////////////////////
+//
+// Unknown instructions
+//
+
+output decoder {{
+ std::string
+ Unknown::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+ {
+ return csprintf("%-10s (inst 0x%x, opcode 0x%x)",
+ "unknown", machInst, OPCODE);
+ }
+}};
+
+output exec {{
+ Fault
+ Unknown::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ panic("attempt to execute unknown instruction "
+ "(inst 0x%08x, opcode 0x%x)", machInst, OPCODE);
+ return new UnimplementedOpcodeFault;
+ }
+}};
+
+def format Unknown() {{
+ decode_block = 'return new Unknown(machInst);\n'
+}};
+
diff --git a/src/arch/alpha/isa/util.isa b/src/arch/alpha/isa/util.isa
new file mode 100644
index 000000000..b4ee9cc8d
--- /dev/null
+++ b/src/arch/alpha/isa/util.isa
@@ -0,0 +1,117 @@
+// -*- mode:c++ -*-
+
+// Copyright (c) 2003-2005 The Regents of The University of Michigan
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met: redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer;
+// redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution;
+// neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+////////////////////////////////////////////////////////////////////
+//
+// Utility functions for execute methods
+//
+
+output exec {{
+
+ /// Return opa + opb, summing carry into third arg.
+ inline uint64_t
+ addc(uint64_t opa, uint64_t opb, int &carry)
+ {
+ uint64_t res = opa + opb;
+ if (res < opa || res < opb)
+ ++carry;
+ return res;
+ }
+
+ /// Multiply two 64-bit values (opa * opb), returning the 128-bit
+ /// product in res_hi and res_lo.
+ inline void
+ mul128(uint64_t opa, uint64_t opb, uint64_t &res_hi, uint64_t &res_lo)
+ {
+ // do a 64x64 --> 128 multiply using four 32x32 --> 64 multiplies
+ uint64_t opa_hi = opa<63:32>;
+ uint64_t opa_lo = opa<31:0>;
+ uint64_t opb_hi = opb<63:32>;
+ uint64_t opb_lo = opb<31:0>;
+
+ res_lo = opa_lo * opb_lo;
+
+ // The middle partial products logically belong in bit
+ // positions 95 to 32. Thus the lower 32 bits of each product
+ // sum into the upper 32 bits of the low result, while the
+ // upper 32 sum into the low 32 bits of the upper result.
+ uint64_t partial1 = opa_hi * opb_lo;
+ uint64_t partial2 = opa_lo * opb_hi;
+
+ uint64_t partial1_lo = partial1<31:0> << 32;
+ uint64_t partial1_hi = partial1<63:32>;
+ uint64_t partial2_lo = partial2<31:0> << 32;
+ uint64_t partial2_hi = partial2<63:32>;
+
+ // Add partial1_lo and partial2_lo to res_lo, keeping track
+ // of any carries out
+ int carry_out = 0;
+ res_lo = addc(partial1_lo, res_lo, carry_out);
+ res_lo = addc(partial2_lo, res_lo, carry_out);
+
+ // Now calculate the high 64 bits...
+ res_hi = (opa_hi * opb_hi) + partial1_hi + partial2_hi + carry_out;
+ }
+
+ /// Map 8-bit S-floating exponent to 11-bit T-floating exponent.
+ /// See Table 2-2 of Alpha AHB.
+ inline int
+ map_s(int old_exp)
+ {
+ int hibit = old_exp<7:>;
+ int lobits = old_exp<6:0>;
+
+ if (hibit == 1) {
+ return (lobits == 0x7f) ? 0x7ff : (0x400 | lobits);
+ }
+ else {
+ return (lobits == 0) ? 0 : (0x380 | lobits);
+ }
+ }
+
+ /// Convert a 32-bit S-floating value to the equivalent 64-bit
+ /// representation to be stored in an FP reg.
+ inline uint64_t
+ s_to_t(uint32_t s_val)
+ {
+ uint64_t tmp = s_val;
+ return (tmp<31:> << 63 // sign bit
+ | (uint64_t)map_s(tmp<30:23>) << 52 // exponent
+ | tmp<22:0> << 29); // fraction
+ }
+
+ /// Convert a 64-bit T-floating value to the equivalent 32-bit
+ /// S-floating representation to be stored in memory.
+ inline int32_t
+ t_to_s(uint64_t t_val)
+ {
+ return (t_val<63:62> << 30 // sign bit & hi exp bit
+ | t_val<58:29>); // rest of exp & fraction
+ }
+}};
+
diff --git a/src/arch/alpha/isa_traits.hh b/src/arch/alpha/isa_traits.hh
new file mode 100644
index 000000000..65c72115b
--- /dev/null
+++ b/src/arch/alpha/isa_traits.hh
@@ -0,0 +1,112 @@
+/*
+ * 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_ISA_TRAITS_HH__
+#define __ARCH_ALPHA_ISA_TRAITS_HH__
+
+namespace LittleEndianGuest {}
+
+#include "arch/alpha/types.hh"
+#include "arch/alpha/constants.hh"
+#include "arch/alpha/regfile.hh"
+#include "config/full_system.hh"
+#include "sim/host.hh"
+
+class StaticInstPtr;
+
+#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/isa_fullsys_traits.hh"
+#endif
+
+
+namespace AlphaISA
+{
+
+using namespace LittleEndianGuest;
+
+// redirected register map, really only used for the full system case.
+extern const int reg_redir[NumIntRegs];
+
+ StaticInstPtr decodeInst(ExtMachInst);
+
+#if !FULL_SYSTEM
+ static inline void setSyscallReturn(SyscallReturn return_value, RegFile *regs)
+ {
+ // check for error condition. Alpha syscall convention is to
+ // indicate success/failure in reg a3 (r19) and put the
+ // return value itself in the standard return value reg (v0).
+ if (return_value.successful()) {
+ // no error
+ regs->setIntReg(SyscallSuccessReg, 0);
+ regs->setIntReg(ReturnValueReg, return_value.value());
+ } else {
+ // got an error, return details
+ regs->setIntReg(SyscallSuccessReg, (IntReg)-1);
+ regs->setIntReg(ReturnValueReg, -return_value.value());
+ }
+ }
+#endif
+};
+
+#endif // __ARCH_ALPHA_ISA_TRAITS_HH__
diff --git a/arch/alpha/linux/aligned.hh b/src/arch/alpha/linux/aligned.hh
index cabecb283..cabecb283 100644
--- a/arch/alpha/linux/aligned.hh
+++ b/src/arch/alpha/linux/aligned.hh
diff --git a/arch/alpha/linux/hwrpb.hh b/src/arch/alpha/linux/hwrpb.hh
index 869ce026b..869ce026b 100644
--- a/arch/alpha/linux/hwrpb.hh
+++ b/src/arch/alpha/linux/hwrpb.hh
diff --git a/src/arch/alpha/linux/linux.cc b/src/arch/alpha/linux/linux.cc
new file mode 100644
index 000000000..f123ae1fe
--- /dev/null
+++ b/src/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/src/arch/alpha/linux/linux.hh b/src/arch/alpha/linux/linux.hh
new file mode 100644
index 000000000..f04e2bfa8
--- /dev/null
+++ b/src/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/src/arch/alpha/linux/process.cc b/src/arch/alpha/linux/process.cc
new file mode 100644
index 000000000..9f4f65db8
--- /dev/null
+++ b/src/arch/alpha/linux/process.cc
@@ -0,0 +1,591 @@
+/*
+ * 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"
+#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 "sim/process.hh"
+#include "sim/syscall_emul.hh"
+
+using namespace std;
+using namespace AlphaISA;
+
+
+
+/// Target uname() handler.
+static SyscallReturn
+unameFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+{
+ TypedBufferArg<Linux::utsname> name(xc->getSyscallArg(0));
+
+ strcpy(name->sysname, "Linux");
+ strcpy(name->nodename, "m5.eecs.umich.edu");
+ strcpy(name->release, "2.4.20");
+ strcpy(name->version, "#1 Mon Aug 18 11:32:15 EDT 2003");
+ strcpy(name->machine, "alpha");
+
+ name.copyOut(xc->getMemPort());
+ 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->getMemPort());
+ 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->getMemPort());
+ DPRINTFR(SyscallVerbose, "osf_setsysinfo(SSI_IEEE_FP_CONTROL): "
+ " setting FPCR to 0x%x\n", gtoh(*(uint64_t*)fpcr));
+ return 0;
+ }
+
+ default:
+ cerr << "osf_setsysinfo: unknown op " << op << endl;
+ abort();
+ break;
+ }
+
+ return 1;
+}
+
+
+SyscallDesc AlphaLinuxProcess::syscallDescs[] = {
+ /* 0 */ SyscallDesc("osf_syscall", unimplementedFunc),
+ /* 1 */ SyscallDesc("exit", exitFunc),
+ /* 2 */ SyscallDesc("fork", unimplementedFunc),
+ /* 3 */ SyscallDesc("read", readFunc),
+ /* 4 */ SyscallDesc("write", writeFunc),
+ /* 5 */ SyscallDesc("osf_old_open", unimplementedFunc),
+ /* 6 */ SyscallDesc("close", closeFunc),
+ /* 7 */ SyscallDesc("osf_wait4", unimplementedFunc),
+ /* 8 */ SyscallDesc("osf_old_creat", unimplementedFunc),
+ /* 9 */ SyscallDesc("link", unimplementedFunc),
+ /* 10 */ SyscallDesc("unlink", unlinkFunc),
+ /* 11 */ SyscallDesc("osf_execve", unimplementedFunc),
+ /* 12 */ SyscallDesc("chdir", unimplementedFunc),
+ /* 13 */ SyscallDesc("fchdir", unimplementedFunc),
+ /* 14 */ SyscallDesc("mknod", unimplementedFunc),
+ /* 15 */ SyscallDesc("chmod", chmodFunc<AlphaLinux>),
+ /* 16 */ SyscallDesc("chown", chownFunc),
+ /* 17 */ SyscallDesc("brk", obreakFunc),
+ /* 18 */ SyscallDesc("osf_getfsstat", unimplementedFunc),
+ /* 19 */ SyscallDesc("lseek", lseekFunc),
+ /* 20 */ SyscallDesc("getxpid", getpidPseudoFunc),
+ /* 21 */ SyscallDesc("osf_mount", unimplementedFunc),
+ /* 22 */ SyscallDesc("umount", unimplementedFunc),
+ /* 23 */ SyscallDesc("setuid", setuidFunc),
+ /* 24 */ SyscallDesc("getxuid", getuidPseudoFunc),
+ /* 25 */ SyscallDesc("exec_with_loader", unimplementedFunc),
+ /* 26 */ SyscallDesc("osf_ptrace", unimplementedFunc),
+ /* 27 */ SyscallDesc("osf_nrecvmsg", unimplementedFunc),
+ /* 28 */ SyscallDesc("osf_nsendmsg", unimplementedFunc),
+ /* 29 */ SyscallDesc("osf_nrecvfrom", unimplementedFunc),
+ /* 30 */ SyscallDesc("osf_naccept", unimplementedFunc),
+ /* 31 */ SyscallDesc("osf_ngetpeername", unimplementedFunc),
+ /* 32 */ SyscallDesc("osf_ngetsockname", unimplementedFunc),
+ /* 33 */ SyscallDesc("access", unimplementedFunc),
+ /* 34 */ SyscallDesc("osf_chflags", unimplementedFunc),
+ /* 35 */ SyscallDesc("osf_fchflags", unimplementedFunc),
+ /* 36 */ SyscallDesc("sync", unimplementedFunc),
+ /* 37 */ SyscallDesc("kill", unimplementedFunc),
+ /* 38 */ SyscallDesc("osf_old_stat", unimplementedFunc),
+ /* 39 */ SyscallDesc("setpgid", unimplementedFunc),
+ /* 40 */ SyscallDesc("osf_old_lstat", unimplementedFunc),
+ /* 41 */ SyscallDesc("dup", unimplementedFunc),
+ /* 42 */ SyscallDesc("pipe", pipePseudoFunc),
+ /* 43 */ SyscallDesc("osf_set_program_attributes", unimplementedFunc),
+ /* 44 */ SyscallDesc("osf_profil", unimplementedFunc),
+ /* 45 */ SyscallDesc("open", openFunc<AlphaLinux>),
+ /* 46 */ SyscallDesc("osf_old_sigaction", unimplementedFunc),
+ /* 47 */ SyscallDesc("getxgid", getgidPseudoFunc),
+ /* 48 */ SyscallDesc("osf_sigprocmask", ignoreFunc),
+ /* 49 */ SyscallDesc("osf_getlogin", unimplementedFunc),
+ /* 50 */ SyscallDesc("osf_setlogin", unimplementedFunc),
+ /* 51 */ SyscallDesc("acct", unimplementedFunc),
+ /* 52 */ SyscallDesc("sigpending", unimplementedFunc),
+ /* 53 */ SyscallDesc("osf_classcntl", unimplementedFunc),
+ /* 54 */ SyscallDesc("ioctl", ioctlFunc<AlphaLinux>),
+ /* 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<AlphaLinux>),
+ /* 68 */ SyscallDesc("lstat", lstatFunc<AlphaLinux>),
+ /* 69 */ SyscallDesc("osf_sbrk", unimplementedFunc),
+ /* 70 */ SyscallDesc("osf_sstk", unimplementedFunc),
+ /* 71 */ SyscallDesc("mmap", mmapFunc<AlphaLinux>),
+ /* 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<AlphaLinux>),
+ /* 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<AlphaLinux>),
+ /* 122 */ SyscallDesc("osf_settimeofday", unimplementedFunc),
+ /* 123 */ SyscallDesc("fchown", fchownFunc),
+ /* 124 */ SyscallDesc("fchmod", fchmodFunc<AlphaLinux>),
+ /* 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<AlphaLinux>),
+ /* 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<AlphaLinux>),
+ /* 360 */ SyscallDesc("settimeofday", unimplementedFunc),
+ /* 361 */ SyscallDesc("getitimer", unimplementedFunc),
+ /* 362 */ SyscallDesc("setitimer", unimplementedFunc),
+ /* 363 */ SyscallDesc("utimes", utimesFunc<AlphaLinux>),
+ /* 364 */ SyscallDesc("getrusage", getrusageFunc<AlphaLinux>),
+ /* 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<AlphaLinux>),
+ /* 427 */ SyscallDesc("fstat64", fstat64Func<AlphaLinux>),
+ /* 428 */ SyscallDesc("vserver", unimplementedFunc),
+ /* 429 */ SyscallDesc("mbind", unimplementedFunc),
+ /* 430 */ SyscallDesc("get_mempolicy", unimplementedFunc),
+ /* 431 */ SyscallDesc("set_mempolicy", unimplementedFunc),
+ /* 432 */ SyscallDesc("mq_open", unimplementedFunc),
+ /* 433 */ SyscallDesc("mq_unlink", unimplementedFunc),
+ /* 434 */ SyscallDesc("mq_timedsend", unimplementedFunc),
+ /* 435 */ SyscallDesc("mq_timedreceive", unimplementedFunc),
+ /* 436 */ SyscallDesc("mq_notify", unimplementedFunc),
+ /* 437 */ SyscallDesc("mq_getsetattr", unimplementedFunc),
+ /* 438 */ SyscallDesc("waitid", unimplementedFunc),
+ /* 439 */ SyscallDesc("add_key", unimplementedFunc),
+ /* 440 */ SyscallDesc("request_key", unimplementedFunc),
+ /* 441 */ SyscallDesc("keyctl", unimplementedFunc)
+};
+
+AlphaLinuxProcess::AlphaLinuxProcess(const std::string &name,
+ ObjectFile *objFile,
+ System *system,
+ int stdin_fd,
+ int stdout_fd,
+ int stderr_fd,
+ std::vector<std::string> &argv,
+ std::vector<std::string> &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;
+}
+
+
+
+SyscallDesc*
+AlphaLinuxProcess::getDesc(int callnum)
+{
+ if (callnum < 0 || callnum > Num_Syscall_Descs)
+ return NULL;
+ return &syscallDescs[callnum];
+}
diff --git a/src/arch/alpha/linux/process.hh b/src/arch/alpha/linux/process.hh
new file mode 100644
index 000000000..2e0566665
--- /dev/null
+++ b/src/arch/alpha/linux/process.hh
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2003-2004 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __ALPHA_LINUX_PROCESS_HH__
+#define __ALPHA_LINUX_PROCESS_HH__
+
+#include "arch/alpha/process.hh"
+
+namespace AlphaISA {
+
+/// A process with emulated Alpha/Linux syscalls.
+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);
+
+ virtual SyscallDesc* getDesc(int callnum);
+
+ /// The target system's hostname.
+ static const char *hostname;
+
+ /// Array of syscall descriptors, indexed by call number.
+ static SyscallDesc syscallDescs[];
+
+ const int Num_Syscall_Descs;
+};
+
+} // namespace AlphaISA
+#endif // __ALPHA_LINUX_PROCESS_HH__
diff --git a/src/arch/alpha/linux/system.cc b/src/arch/alpha/linux/system.cc
new file mode 100644
index 000000000..cdb96096c
--- /dev/null
+++ b/src/arch/alpha/linux/system.cc
@@ -0,0 +1,265 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * This code loads the linux kernel, console, pal and patches certain
+ * functions. The symbol tables are loaded so that traces can show
+ * the executing function and we can skip functions. Various delay
+ * loops are skipped and their final values manually computed to speed
+ * up boot time.
+ */
+
+#include "arch/arguments.hh"
+#include "arch/vtophys.hh"
+#include "arch/alpha/linux/system.hh"
+#include "arch/alpha/linux/threadinfo.hh"
+#include "arch/alpha/system.hh"
+#include "base/loader/symtab.hh"
+#include "cpu/exec_context.hh"
+#include "cpu/base.hh"
+#include "dev/platform.hh"
+#include "kern/linux/printk.hh"
+#include "kern/linux/events.hh"
+#include "mem/physical.hh"
+#include "mem/port.hh"
+#include "sim/builder.hh"
+#include "sim/byteswap.hh"
+
+using namespace std;
+using namespace AlphaISA;
+using namespace Linux;
+
+LinuxAlphaSystem::LinuxAlphaSystem(Params *p)
+ : AlphaSystem(p)
+{
+ Addr addr = 0;
+
+ /**
+ * The symbol swapper_pg_dir marks the beginning of the kernel and
+ * the location of bootloader passed arguments
+ */
+ if (!kernelSymtab->findAddress("swapper_pg_dir", KernelStart)) {
+ panic("Could not determine start location of kernel");
+ }
+
+ /**
+ * Since we aren't using a bootloader, we have to copy the
+ * kernel arguments directly into the kernel's memory.
+ */
+ 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))
+ virtPort.write(addr, (uint64_t)(Clock::Frequency /
+ p->boot_cpu_frequency));
+
+
+ /**
+ * EV5 only supports 127 ASNs so we are going to tell the kernel that the
+ * paritiuclar EV6 we have only supports 127 asns.
+ * @todo At some point we should change ev5.hh and the palcode to support
+ * 255 ASNs.
+ */
+ 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
+ kernelPanicEvent = addKernelFuncEvent<BreakPCEvent>("panic");
+ if (!kernelPanicEvent)
+ panic("could not find kernel symbol \'panic\'");
+
+#if 0
+ kernelDieEvent = addKernelFuncEvent<BreakPCEvent>("die_if_kernel");
+ if (!kernelDieEvent)
+ panic("could not find kernel symbol \'die_if_kernel\'");
+#endif
+
+#endif
+
+ /**
+ * Any time ide_delay_50ms, calibarte_delay or
+ * determine_cpu_caches is called just skip the
+ * function. Currently determine_cpu_caches only is used put
+ * information in proc, however if that changes in the future we
+ * will have to fill in the cache size variables appropriately.
+ */
+
+ skipIdeDelay50msEvent =
+ addKernelFuncEvent<SkipFuncEvent>("ide_delay_50ms");
+ skipDelayLoopEvent =
+ addKernelFuncEvent<SkipDelayLoopEvent>("calibrate_delay");
+ skipCacheProbeEvent =
+ addKernelFuncEvent<SkipFuncEvent>("determine_cpu_caches");
+ debugPrintkEvent = addKernelFuncEvent<DebugPrintkEvent>("dprintk");
+ idleStartEvent = addKernelFuncEvent<IdleStartEvent>("cpu_idle");
+
+ if (kernelSymtab->findAddress("alpha_switch_to", addr) && DTRACE(Thread)) {
+ printThreadEvent = new PrintThreadInfo(&pcEventQueue, "threadinfo",
+ addr + sizeof(MachInst) * 6);
+ } else {
+ printThreadEvent = NULL;
+ }
+
+ if (params()->bin_int) {
+ intStartEvent = addPalFuncEvent<InterruptStartEvent>("sys_int_21");
+ if (!intStartEvent)
+ panic("could not find symbol: sys_int_21\n");
+
+ intEndEvent = addPalFuncEvent<InterruptEndEvent>("rti_to_kern");
+ if (!intEndEvent)
+ panic("could not find symbol: rti_to_kern\n");
+
+ intEndEvent2 = addPalFuncEvent<InterruptEndEvent>("rti_to_user");
+ if (!intEndEvent2)
+ panic("could not find symbol: rti_to_user\n");
+
+ intEndEvent3 = addKernelFuncEvent<InterruptEndEvent>("do_softirq");
+ if (!intEndEvent3)
+ panic("could not find symbol: do_softirq\n");
+ }
+}
+
+LinuxAlphaSystem::~LinuxAlphaSystem()
+{
+#ifndef NDEBUG
+ delete kernelPanicEvent;
+#endif
+ delete skipIdeDelay50msEvent;
+ delete skipDelayLoopEvent;
+ delete skipCacheProbeEvent;
+ delete debugPrintkEvent;
+ delete idleStartEvent;
+ delete printThreadEvent;
+ delete intStartEvent;
+ delete intEndEvent;
+ delete intEndEvent2;
+}
+
+
+void
+LinuxAlphaSystem::setDelayLoop(ExecContext *xc)
+{
+ Addr addr = 0;
+ if (kernelSymtab->findAddress("loops_per_jiffy", addr)) {
+ Tick cpuFreq = xc->getCpuPtr()->frequency();
+ Tick intrFreq = platform->intrFrequency();
+ xc->getVirtPort(xc)->write(addr,
+ (uint32_t)((cpuFreq / intrFreq) * 0.9988));
+ }
+}
+
+
+void
+LinuxAlphaSystem::SkipDelayLoopEvent::process(ExecContext *xc)
+{
+ SkipFuncEvent::process(xc);
+ // calculate and set loops_per_jiffy
+ ((LinuxAlphaSystem *)xc->getSystemPtr())->setDelayLoop(xc);
+}
+
+void
+LinuxAlphaSystem::PrintThreadInfo::process(ExecContext *xc)
+{
+ Linux::ThreadInfo ti(xc);
+
+ DPRINTF(Thread, "Currently Executing Thread %s, pid %d, started at: %d\n",
+ ti.curTaskName(), ti.curTaskPID(), ti.curTaskStart());
+}
+
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(LinuxAlphaSystem)
+
+ Param<Tick> boot_cpu_frequency;
+ SimObjectParam<PhysicalMemory *> physmem;
+
+ Param<string> kernel;
+ Param<string> console;
+ Param<string> pal;
+
+ Param<string> boot_osflags;
+ Param<string> readfile;
+ Param<unsigned int> init_param;
+
+ Param<uint64_t> system_type;
+ Param<uint64_t> system_rev;
+
+ Param<bool> bin;
+ VectorParam<string> binned_fns;
+ Param<bool> bin_int;
+
+END_DECLARE_SIM_OBJECT_PARAMS(LinuxAlphaSystem)
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(LinuxAlphaSystem)
+
+ 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(console, "file that contains the console code"),
+ INIT_PARAM(pal, "file that contains palcode"),
+ INIT_PARAM_DFLT(boot_osflags, "flags to pass to the kernel during boot",
+ "a"),
+ INIT_PARAM_DFLT(readfile, "file to read startup script from", ""),
+ INIT_PARAM_DFLT(init_param, "numerical value to pass into simulator", 0),
+ INIT_PARAM_DFLT(system_type, "Type of system we are emulating", 34),
+ INIT_PARAM_DFLT(system_rev, "Revision of system we are emulating", 1<<10),
+ INIT_PARAM_DFLT(bin, "is this system to be binned", false),
+ INIT_PARAM(binned_fns, "functions to be broken down and binned"),
+ INIT_PARAM_DFLT(bin_int, "is interrupt code binned seperately?", true)
+
+END_INIT_SIM_OBJECT_PARAMS(LinuxAlphaSystem)
+
+CREATE_SIM_OBJECT(LinuxAlphaSystem)
+{
+ AlphaSystem::Params *p = new AlphaSystem::Params;
+ p->name = getInstanceName();
+ p->boot_cpu_frequency = boot_cpu_frequency;
+ p->physmem = physmem;
+ p->kernel_path = kernel;
+ p->console_path = console;
+ p->palcode = pal;
+ p->boot_osflags = boot_osflags;
+ p->init_param = init_param;
+ p->readfile = readfile;
+ p->system_type = system_type;
+ p->system_rev = system_rev;
+ p->bin = bin;
+ p->binned_fns = binned_fns;
+ p->bin_int = bin_int;
+ return new LinuxAlphaSystem(p);
+}
+
+REGISTER_SIM_OBJECT("LinuxAlphaSystem", LinuxAlphaSystem)
+
diff --git a/src/arch/alpha/linux/system.hh b/src/arch/alpha/linux/system.hh
new file mode 100644
index 000000000..0c1fb037e
--- /dev/null
+++ b/src/arch/alpha/linux/system.hh
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2004-2006 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __ARCH_ALPHA_LINUX_SYSTEM_HH__
+#define __ARCH_ALPHA_LINUX_SYSTEM_HH__
+
+class ExecContext;
+
+class BreakPCEvent;
+class IdleStartEvent;
+
+#include "arch/alpha/system.hh"
+#include "kern/linux/events.hh"
+
+using namespace AlphaISA;
+using namespace Linux;
+
+/**
+ * This class contains linux specific system code (Loading, Events, Binning).
+ * It points to objects that are the system binaries to load and patches them
+ * appropriately to work in simulator.
+ */
+class LinuxAlphaSystem : public AlphaSystem
+{
+ private:
+ class SkipDelayLoopEvent : public SkipFuncEvent
+ {
+ public:
+ SkipDelayLoopEvent(PCEventQueue *q, const std::string &desc, Addr addr)
+ : SkipFuncEvent(q, desc, addr) {}
+ virtual void process(ExecContext *xc);
+ };
+
+ class PrintThreadInfo : public PCEvent
+ {
+ public:
+ PrintThreadInfo(PCEventQueue *q, const std::string &desc, Addr addr)
+ : PCEvent(q, desc, addr) {}
+ virtual void process(ExecContext *xc);
+ };
+
+
+ /**
+ * Addresses defining where the kernel bootloader places various
+ * elements. Details found in include/asm-alpha/system.h
+ */
+ Addr KernelStart; // Lookup the symbol swapper_pg_dir
+
+ public:
+ Addr InitStack() const { return KernelStart + 0x02000; }
+ Addr EmptyPGT() const { return KernelStart + 0x04000; }
+ Addr EmptyPGE() const { return KernelStart + 0x08000; }
+ Addr ZeroPGE() const { return KernelStart + 0x0A000; }
+ Addr StartAddr() const { return KernelStart + 0x10000; }
+
+ Addr Param() const { return ZeroPGE() + 0x0; }
+ Addr CommandLine() const { return Param() + 0x0; }
+ Addr InitrdStart() const { return Param() + 0x100; }
+ Addr InitrdSize() const { return Param() + 0x108; }
+ static const int CommandLineSize = 256;
+
+ private:
+#ifndef NDEBUG
+ /** Event to halt the simulator if the kernel calls panic() */
+ BreakPCEvent *kernelPanicEvent;
+
+ /** Event to halt the simulator if the kernel calls die_if_kernel */
+ BreakPCEvent *kernelDieEvent;
+#endif
+
+ /**
+ * Event to skip determine_cpu_caches() because we don't support
+ * the IPRs that the code can access to figure out cache sizes
+ */
+ SkipFuncEvent *skipCacheProbeEvent;
+
+ /** PC based event to skip the ide_delay_50ms() call */
+ SkipFuncEvent *skipIdeDelay50msEvent;
+
+ /**
+ * PC based event to skip the dprink() call and emulate its
+ * functionality
+ */
+ DebugPrintkEvent *debugPrintkEvent;
+
+ /**
+ * Skip calculate_delay_loop() rather than waiting for this to be
+ * calculated
+ */
+ SkipDelayLoopEvent *skipDelayLoopEvent;
+
+ /**
+ * Event to print information about thread switches if the trace flag
+ * Thread is set
+ */
+ PrintThreadInfo *printThreadEvent;
+
+ /**
+ * Event to bin Interrupts seperately from kernel code
+ */
+ InterruptStartEvent *intStartEvent;
+
+ /**
+ * Event to bin Interrupts seperately from kernel code
+ */
+ InterruptEndEvent *intEndEvent;
+ InterruptEndEvent *intEndEvent2;
+ InterruptEndEvent *intEndEvent3;
+
+ /** Grab the PCBB of the idle process when it starts */
+ IdleStartEvent *idleStartEvent;
+
+ public:
+ LinuxAlphaSystem(Params *p);
+ ~LinuxAlphaSystem();
+
+ void setDelayLoop(ExecContext *xc);
+};
+
+#endif // __ARCH_ALPHA_LINUX_SYSTEM_HH__
diff --git a/arch/alpha/linux/thread_info.hh b/src/arch/alpha/linux/thread_info.hh
index 88791b00d..88791b00d 100644
--- a/arch/alpha/linux/thread_info.hh
+++ b/src/arch/alpha/linux/thread_info.hh
diff --git a/arch/alpha/linux/threadinfo.hh b/src/arch/alpha/linux/threadinfo.hh
index 8f03c9314..8f03c9314 100644
--- a/arch/alpha/linux/threadinfo.hh
+++ b/src/arch/alpha/linux/threadinfo.hh
diff --git a/arch/alpha/osfpal.cc b/src/arch/alpha/osfpal.cc
index a48bd28d9..a48bd28d9 100644
--- a/arch/alpha/osfpal.cc
+++ b/src/arch/alpha/osfpal.cc
diff --git a/arch/alpha/osfpal.hh b/src/arch/alpha/osfpal.hh
index f46d2bce1..f46d2bce1 100644
--- a/arch/alpha/osfpal.hh
+++ b/src/arch/alpha/osfpal.hh
diff --git a/src/arch/alpha/process.cc b/src/arch/alpha/process.cc
new file mode 100644
index 000000000..25ee79692
--- /dev/null
+++ b/src/arch/alpha/process.cc
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2003-2004 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "arch/alpha/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"
+
+
+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)
+{
+ 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, system,
+ stdin_fd, stdout_fd, stderr_fd,
+ argv, envp);
+ break;
+
+ case ObjectFile::Linux:
+ process = new AlphaLinuxProcess(nm, objFile, system,
+ stdin_fd, stdout_fd, stderr_fd,
+ argv, envp);
+ break;
+
+ default:
+ fatal("Unknown/unsupported operating system.");
+ }
+
+ if (process == NULL)
+ fatal("Unknown error creating process object.");
+ return process;
+}
+
+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/src/arch/alpha/process.hh b/src/arch/alpha/process.hh
new file mode 100644
index 000000000..d97b36e2d
--- /dev/null
+++ b/src/arch/alpha/process.hh
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2003-2004 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __ALPHA_PROCESS_HH__
+#define __ALPHA_PROCESS_HH__
+
+#include <string>
+#include <vector>
+#include "sim/process.hh"
+
+class ObjectFile;
+class System;
+
+
+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);
+
+};
+
+
+#endif // __ALPHA_PROCESS_HH__
diff --git a/src/arch/alpha/regfile.hh b/src/arch/alpha/regfile.hh
new file mode 100644
index 000000000..af01b7829
--- /dev/null
+++ b/src/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/src/arch/alpha/stacktrace.cc b/src/arch/alpha/stacktrace.cc
new file mode 100644
index 000000000..8691e12dc
--- /dev/null
+++ b/src/arch/alpha/stacktrace.cc
@@ -0,0 +1,344 @@
+/*
+ * Copyright (c) 2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <string>
+
+#include "arch/alpha/isa_traits.hh"
+#include "arch/alpha/stacktrace.hh"
+#include "arch/alpha/vtophys.hh"
+#include "base/bitfield.hh"
+#include "base/trace.hh"
+#include "cpu/base.hh"
+#include "cpu/exec_context.hh"
+#include "sim/system.hh"
+
+using namespace std;
+using namespace AlphaISA;
+
+ProcessInfo::ProcessInfo(ExecContext *_xc)
+ : xc(_xc)
+{
+ Addr addr = 0;
+
+ if (!xc->getSystemPtr()->kernelSymtab->findAddress("thread_info_size", addr))
+ panic("thread info not compiled into kernel\n");
+ 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 = 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 = 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 = 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 = gtoh(xc->getVirtPort()->read<int32_t>(addr));
+}
+
+Addr
+ProcessInfo::task(Addr ksp) const
+{
+ Addr base = ksp & ~0x3fff;
+ if (base == ULL(0xfffffc0000000000))
+ return 0;
+
+ return gtoh(xc->getVirtPort()->read<Addr>(base + task_off));
+}
+
+int
+ProcessInfo::pid(Addr ksp) const
+{
+ Addr task = this->task(ksp);
+ if (!task)
+ return -1;
+
+ return gtoh(xc->getVirtPort()->read<uint16_t>(task + pid_off));
+}
+
+string
+ProcessInfo::name(Addr ksp) const
+{
+ Addr task = this->task(ksp);
+ if (!task)
+ return "console";
+
+ char comm[256];
+ CopyStringOut(xc, comm, task + name_off, sizeof(comm));
+ if (!comm[0])
+ return "startup";
+
+ return comm;
+}
+
+StackTrace::StackTrace()
+ : xc(0), stack(64)
+{
+}
+
+StackTrace::StackTrace(ExecContext *_xc, StaticInstPtr inst)
+ : xc(0), stack(64)
+{
+ trace(_xc, inst);
+}
+
+StackTrace::~StackTrace()
+{
+}
+
+void
+StackTrace::trace(ExecContext *_xc, bool is_call)
+{
+ xc = _xc;
+
+ bool usermode = (xc->readMiscReg(AlphaISA::IPR_DTB_CM) & 0x18) != 0;
+
+ Addr pc = xc->readNextPC();
+ bool kernel = xc->getSystemPtr()->kernelStart <= pc &&
+ pc <= xc->getSystemPtr()->kernelEnd;
+
+ if (usermode) {
+ stack.push_back(user);
+ return;
+ }
+
+ if (!kernel) {
+ stack.push_back(console);
+ return;
+ }
+
+ SymbolTable *symtab = xc->getSystemPtr()->kernelSymtab;
+ Addr ksp = xc->readIntReg(TheISA::StackPointerReg);
+ Addr bottom = ksp & ~0x3fff;
+ Addr addr;
+
+ if (is_call) {
+ if (!symtab->findNearestAddr(pc, addr))
+ panic("could not find address %#x", pc);
+
+ stack.push_back(addr);
+ pc = xc->readPC();
+ }
+
+ Addr ra;
+ int size;
+
+ while (ksp > bottom) {
+ if (!symtab->findNearestAddr(pc, addr))
+ panic("could not find symbol for pc=%#x", pc);
+ assert(pc >= addr && "symbol botch: callpc < func");
+
+ stack.push_back(addr);
+
+ if (isEntry(addr))
+ return;
+
+ if (decodePrologue(ksp, pc, addr, size, ra)) {
+ if (!ra)
+ return;
+
+ if (size <= 0) {
+ stack.push_back(unknown);
+ return;
+ }
+
+ pc = ra;
+ ksp += size;
+ } else {
+ stack.push_back(unknown);
+ return;
+ }
+
+ bool kernel = xc->getSystemPtr()->kernelStart <= pc &&
+ pc <= xc->getSystemPtr()->kernelEnd;
+ if (!kernel)
+ return;
+
+ if (stack.size() >= 1000)
+ panic("unwinding too far");
+ }
+
+ panic("unwinding too far");
+}
+
+bool
+StackTrace::isEntry(Addr addr)
+{
+ if (addr == xc->readMiscReg(AlphaISA::IPR_PALtemp12))
+ return true;
+
+ if (addr == xc->readMiscReg(AlphaISA::IPR_PALtemp7))
+ return true;
+
+ if (addr == xc->readMiscReg(AlphaISA::IPR_PALtemp11))
+ return true;
+
+ if (addr == xc->readMiscReg(AlphaISA::IPR_PALtemp21))
+ return true;
+
+ if (addr == xc->readMiscReg(AlphaISA::IPR_PALtemp9))
+ return true;
+
+ if (addr == xc->readMiscReg(AlphaISA::IPR_PALtemp2))
+ return true;
+
+ return false;
+}
+
+bool
+StackTrace::decodeStack(MachInst inst, int &disp)
+{
+ // lda $sp, -disp($sp)
+ //
+ // Opcode<31:26> == 0x08
+ // RA<25:21> == 30
+ // RB<20:16> == 30
+ // Disp<15:0>
+ const MachInst mem_mask = 0xffff0000;
+ const MachInst lda_pattern = 0x23de0000;
+ const MachInst lda_disp_mask = 0x0000ffff;
+
+ // subq $sp, disp, $sp
+ // addq $sp, disp, $sp
+ //
+ // Opcode<31:26> == 0x10
+ // RA<25:21> == 30
+ // Lit<20:13>
+ // One<12> = 1
+ // Func<11:5> == 0x20 (addq)
+ // Func<11:5> == 0x29 (subq)
+ // RC<4:0> == 30
+ const MachInst intop_mask = 0xffe01fff;
+ const MachInst addq_pattern = 0x43c0141e;
+ const MachInst subq_pattern = 0x43c0153e;
+ const MachInst intop_disp_mask = 0x001fe000;
+ const int intop_disp_shift = 13;
+
+ if ((inst & mem_mask) == lda_pattern)
+ disp = -sext<16>(inst & lda_disp_mask);
+ else if ((inst & intop_mask) == addq_pattern)
+ disp = -int((inst & intop_disp_mask) >> intop_disp_shift);
+ else if ((inst & intop_mask) == subq_pattern)
+ disp = int((inst & intop_disp_mask) >> intop_disp_shift);
+ else
+ return false;
+
+ return true;
+}
+
+bool
+StackTrace::decodeSave(MachInst inst, int &reg, int &disp)
+{
+ // lda $stq, disp($sp)
+ //
+ // Opcode<31:26> == 0x08
+ // RA<25:21> == ?
+ // RB<20:16> == 30
+ // Disp<15:0>
+ const MachInst stq_mask = 0xfc1f0000;
+ const MachInst stq_pattern = 0xb41e0000;
+ const MachInst stq_disp_mask = 0x0000ffff;
+ const MachInst reg_mask = 0x03e00000;
+ const int reg_shift = 21;
+
+ if ((inst & stq_mask) == stq_pattern) {
+ reg = (inst & reg_mask) >> reg_shift;
+ disp = sext<16>(inst & stq_disp_mask);
+ } else {
+ return false;
+ }
+
+ return true;
+}
+
+/*
+ * Decode the function prologue for the function we're in, and note
+ * which registers are stored where, and how large the stack frame is.
+ */
+bool
+StackTrace::decodePrologue(Addr sp, Addr callpc, Addr func,
+ int &size, Addr &ra)
+{
+ size = 0;
+ ra = 0;
+
+ for (Addr pc = func; pc < callpc; pc += sizeof(MachInst)) {
+ MachInst inst;
+ CopyOut(xc, (uint8_t *)&inst, pc, sizeof(MachInst));
+
+ int reg, disp;
+ if (decodeStack(inst, disp)) {
+ if (size) {
+ // panic("decoding frame size again");
+ return true;
+ }
+ size += disp;
+ } else if (decodeSave(inst, reg, disp)) {
+ if (!ra && reg == ReturnAddressReg) {
+ CopyOut(xc, (uint8_t *)&ra, sp + disp, sizeof(Addr));
+ if (!ra) {
+ // panic("no return address value pc=%#x\n", pc);
+ return false;
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+#if TRACING_ON
+void
+StackTrace::dump()
+{
+ StringWrap name(xc->getCpuPtr()->name());
+ SymbolTable *symtab = xc->getSystemPtr()->kernelSymtab;
+
+ DPRINTFN("------ Stack ------\n");
+
+ string symbol;
+ for (int i = 0, size = stack.size(); i < size; ++i) {
+ Addr addr = stack[size - i - 1];
+ if (addr == user)
+ symbol = "user";
+ else if (addr == console)
+ symbol = "console";
+ else if (addr == unknown)
+ symbol = "unknown";
+ else
+ symtab->findSymbol(addr, symbol);
+
+ DPRINTFN("%#x: %s\n", addr, symbol);
+ }
+}
+#endif
diff --git a/arch/alpha/stacktrace.hh b/src/arch/alpha/stacktrace.hh
index 1d8d97a79..1d8d97a79 100644
--- a/arch/alpha/stacktrace.hh
+++ b/src/arch/alpha/stacktrace.hh
diff --git a/src/arch/alpha/system.cc b/src/arch/alpha/system.cc
new file mode 100644
index 000000000..4234019cd
--- /dev/null
+++ b/src/arch/alpha/system.cc
@@ -0,0 +1,280 @@
+/*
+ * Copyright (c) 2002-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "arch/alpha/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/physical.hh"
+#include "sim/byteswap.hh"
+#include "sim/builder.hh"
+
+
+using namespace LittleEndianGuest;
+
+AlphaSystem::AlphaSystem(Params *p)
+ : System(p)
+{
+ consoleSymtab = new SymbolTable;
+ palSymtab = new SymbolTable;
+
+
+ /**
+ * Load the pal, and console code into memory
+ */
+ // Load Console Code
+ console = createObjectFile(params()->console_path);
+ if (console == NULL)
+ fatal("Could not load console file %s", params()->console_path);
+
+ // Load pal file
+ pal = createObjectFile(params()->palcode);
+ if (pal == NULL)
+ fatal("Could not load PALcode file %s", params()->palcode);
+
+
+ // Load program sections into memory
+ pal->loadSections(&functionalPort, AlphaISA::LoadAddrMask);
+ console->loadSections(&functionalPort, AlphaISA::LoadAddrMask);
+
+ // load symbols
+ if (!console->loadGlobalSymbols(consoleSymtab))
+ panic("could not load console symbols\n");
+
+ if (!pal->loadGlobalSymbols(palSymtab))
+ panic("could not load pal symbols\n");
+
+ if (!pal->loadLocalSymbols(palSymtab))
+ panic("could not load pal symbols\n");
+
+ if (!console->loadGlobalSymbols(debugSymbolTable))
+ panic("could not load console symbols\n");
+
+ if (!pal->loadGlobalSymbols(debugSymbolTable))
+ panic("could not load pal symbols\n");
+
+ if (!pal->loadLocalSymbols(debugSymbolTable))
+ panic("could not load pal symbols\n");
+
+ Addr addr = 0;
+#ifndef NDEBUG
+ consolePanicEvent = addConsoleFuncEvent<BreakPCEvent>("panic");
+#endif
+
+ /**
+ * Copy the osflags (kernel arguments) into the consoles
+ * memory. (Presently Linux does not use the console service
+ * routine to get these command line arguments, but Tru64 and
+ * others do.)
+ */
+ if (consoleSymtab->findAddress("env_booted_osflags", addr)) {
+ virtPort.writeBlob(addr, (uint8_t*)params()->boot_osflags.c_str(),
+ strlen(params()->boot_osflags.c_str()));
+ }
+
+ /**
+ * Set the hardware reset parameter block system type and revision
+ * information to Tsunami.
+ */
+ if (consoleSymtab->findAddress("m5_rpb", addr)) {
+ 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");
+
+}
+
+AlphaSystem::~AlphaSystem()
+{
+ delete consoleSymtab;
+ delete console;
+ delete pal;
+#ifdef DEBUG
+ delete consolePanicEvent;
+#endif
+}
+
+/**
+ * This function fixes up addresses that are used to match PCs for
+ * hooking simulator events on to target function executions.
+ *
+ * Alpha binaries may have multiple global offset table (GOT)
+ * sections. A function that uses the GOT starts with a
+ * two-instruction prolog which sets the global pointer (gp == r29) to
+ * the appropriate GOT section. The proper gp value is calculated
+ * based on the function address, which must be passed by the caller
+ * in the procedure value register (pv aka t12 == r27). This sequence
+ * looks like the following:
+ *
+ * opcode Ra Rb offset
+ * ldah gp,X(pv) 09 29 27 X
+ * lda gp,Y(gp) 08 29 29 Y
+ *
+ * for some constant offsets X and Y. The catch is that the linker
+ * (or maybe even the compiler, I'm not sure) may recognize that the
+ * caller and callee are using the same GOT section, making this
+ * prolog redundant, and modify the call target to skip these
+ * instructions. If we check for execution of the first instruction
+ * of a function (the one the symbol points to) to detect when to skip
+ * it, we'll miss all these modified calls. It might work to
+ * unconditionally check for the third instruction, but not all
+ * functions have this prolog, and there's some chance that those
+ * first two instructions could have undesired consequences. So we do
+ * the Right Thing and pattern-match the first two instructions of the
+ * function to decide where to patch.
+ *
+ * Eventually this code should be moved into an ISA-specific file.
+ */
+Addr
+AlphaSystem::fixFuncEventAddr(Addr addr)
+{
+ // mask for just the opcode, Ra, and Rb fields (not the offset)
+ const uint32_t inst_mask = 0xffff0000;
+ // ldah gp,X(pv): opcode 9, Ra = 29, Rb = 27
+ const uint32_t gp_ldah_pattern = (9 << 26) | (29 << 21) | (27 << 16);
+ // lda gp,Y(gp): opcode 8, Ra = 29, rb = 29
+ const uint32_t gp_lda_pattern = (8 << 26) | (29 << 21) | (29 << 16);
+
+ 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* sizeof(AlphaISA::MachInst);
+ DPRINTF(Loader, "fixFuncEventAddr: %p -> %p", addr, new_addr);
+ return new_addr;
+ } else {
+ return addr;
+ }
+}
+
+
+void
+AlphaSystem::setAlphaAccess(Addr access)
+{
+ Addr addr = 0;
+ if (consoleSymtab->findAddress("m5AlphaAccess", addr)) {
+ virtPort.write(addr, htog(EV5::Phys2K0Seg(access)));
+ } else
+ panic("could not find m5AlphaAccess\n");
+}
+
+bool
+AlphaSystem::breakpoint()
+{
+ return remoteGDB[0]->trap(ALPHA_KENTRY_INT);
+}
+
+void
+AlphaSystem::serialize(std::ostream &os)
+{
+ System::serialize(os);
+ consoleSymtab->serialize("console_symtab", os);
+ palSymtab->serialize("pal_symtab", os);
+}
+
+
+void
+AlphaSystem::unserialize(Checkpoint *cp, const std::string &section)
+{
+ System::unserialize(cp,section);
+ consoleSymtab->unserialize("console_symtab", cp, section);
+ palSymtab->unserialize("pal_symtab", cp, section);
+}
+
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaSystem)
+
+ Param<Tick> boot_cpu_frequency;
+ SimObjectParam<PhysicalMemory *> physmem;
+
+ Param<std::string> kernel;
+ Param<std::string> console;
+ Param<std::string> pal;
+
+ Param<std::string> boot_osflags;
+ Param<std::string> readfile;
+ Param<unsigned int> init_param;
+
+ Param<uint64_t> system_type;
+ Param<uint64_t> system_rev;
+
+ Param<bool> bin;
+ VectorParam<std::string> binned_fns;
+ Param<bool> bin_int;
+
+END_DECLARE_SIM_OBJECT_PARAMS(AlphaSystem)
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(AlphaSystem)
+
+ INIT_PARAM(boot_cpu_frequency, "Frequency of the boot CPU"),
+ INIT_PARAM(physmem, "phsyical memory"),
+ INIT_PARAM(kernel, "file that contains the kernel code"),
+ INIT_PARAM(console, "file that contains the console code"),
+ INIT_PARAM(pal, "file that contains palcode"),
+ INIT_PARAM_DFLT(boot_osflags, "flags to pass to the kernel during boot",
+ "a"),
+ INIT_PARAM_DFLT(readfile, "file to read startup script from", ""),
+ INIT_PARAM_DFLT(init_param, "numerical value to pass into simulator", 0),
+ INIT_PARAM_DFLT(system_type, "Type of system we are emulating", 34),
+ INIT_PARAM_DFLT(system_rev, "Revision of system we are emulating", 1<<10),
+ INIT_PARAM_DFLT(bin, "is this system to be binned", false),
+ INIT_PARAM(binned_fns, "functions to be broken down and binned"),
+ INIT_PARAM_DFLT(bin_int, "is interrupt code binned seperately?", true)
+
+END_INIT_SIM_OBJECT_PARAMS(AlphaSystem)
+
+CREATE_SIM_OBJECT(AlphaSystem)
+{
+ AlphaSystem::Params *p = new AlphaSystem::Params;
+ p->name = getInstanceName();
+ p->boot_cpu_frequency = boot_cpu_frequency;
+ p->physmem = physmem;
+ p->kernel_path = kernel;
+ p->console_path = console;
+ p->palcode = pal;
+ p->boot_osflags = boot_osflags;
+ p->init_param = init_param;
+ p->readfile = readfile;
+ p->system_type = system_type;
+ p->system_rev = system_rev;
+ p->bin = bin;
+ p->binned_fns = binned_fns;
+ p->bin_int = bin_int;
+ return new AlphaSystem(p);
+}
+
+REGISTER_SIM_OBJECT("AlphaSystem", AlphaSystem)
+
+
diff --git a/src/arch/alpha/system.hh b/src/arch/alpha/system.hh
new file mode 100644
index 000000000..924e16826
--- /dev/null
+++ b/src/arch/alpha/system.hh
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2002-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __ARCH_ALPHA_SYSTEM_HH__
+#define __ARCH_ALPHA_SYSTEM_HH__
+
+#include <string>
+#include <vector>
+
+#include "sim/system.hh"
+#include "base/loader/symtab.hh"
+#include "cpu/pc_event.hh"
+#include "kern/system_events.hh"
+#include "sim/sim_object.hh"
+
+class AlphaSystem : public System
+{
+ public:
+ struct Params : public System::Params
+ {
+ std::string console_path;
+ std::string palcode;
+ uint64_t system_type;
+ uint64_t system_rev;
+ };
+
+ AlphaSystem(Params *p);
+
+ ~AlphaSystem();
+
+ virtual bool breakpoint();
+
+/**
+ * Serialization stuff
+ */
+ public:
+ virtual void serialize(std::ostream &os);
+ virtual void unserialize(Checkpoint *cp, const std::string &section);
+
+ /**
+ * Set the m5AlphaAccess pointer in the console
+ */
+ void setAlphaAccess(Addr access);
+
+ /** console symbol table */
+ SymbolTable *consoleSymtab;
+
+ /** pal symbol table */
+ SymbolTable *palSymtab;
+
+ /** Object pointer for the console code */
+ ObjectFile *console;
+
+ /** Object pointer for the PAL code */
+ ObjectFile *pal;
+
+#ifndef NDEBUG
+ /** Event to halt the simulator if the console calls panic() */
+ BreakPCEvent *consolePanicEvent;
+#endif
+ protected:
+ const Params *params() const { return (const Params *)_params; }
+
+ /** Add a function-based event to PALcode. */
+ template <class T>
+ T *AlphaSystem::addPalFuncEvent(const char *lbl)
+ {
+ return addFuncEvent<T>(palSymtab, lbl);
+ }
+
+ /** Add a function-based event to the console code. */
+ template <class T>
+ T *AlphaSystem::addConsoleFuncEvent(const char *lbl)
+ {
+ return addFuncEvent<T>(consoleSymtab, lbl);
+ }
+
+ virtual Addr fixFuncEventAddr(Addr addr);
+
+};
+
+#endif
+
diff --git a/src/arch/alpha/tlb.cc b/src/arch/alpha/tlb.cc
new file mode 100644
index 000000000..05b02d74b
--- /dev/null
+++ b/src/arch/alpha/tlb.cc
@@ -0,0 +1,628 @@
+/*
+ * 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 <vector>
+
+#include "arch/alpha/tlb.hh"
+#include "base/inifile.hh"
+#include "base/str.hh"
+#include "base/trace.hh"
+#include "config/alpha_tlaser.hh"
+#include "cpu/exec_context.hh"
+#include "sim/builder.hh"
+
+using namespace std;
+using namespace EV5;
+
+///////////////////////////////////////////////////////////////////////
+//
+// Alpha TLB
+//
+#ifdef DEBUG
+bool uncacheBit39 = false;
+bool uncacheBit40 = false;
+#endif
+
+#define MODE2MASK(X) (1 << (X))
+
+AlphaTLB::AlphaTLB(const string &name, int s)
+ : SimObject(name), size(s), nlu(0)
+{
+ table = new AlphaISA::PTE[size];
+ memset(table, 0, sizeof(AlphaISA::PTE[size]));
+}
+
+AlphaTLB::~AlphaTLB()
+{
+ if (table)
+ delete [] table;
+}
+
+// look up an entry in the TLB
+AlphaISA::PTE *
+AlphaTLB::lookup(Addr vpn, uint8_t asn) const
+{
+ // assume not found...
+ AlphaISA::PTE *retval = NULL;
+
+ PageTable::const_iterator i = lookupTable.find(vpn);
+ if (i != lookupTable.end()) {
+ while (i->first == vpn) {
+ int index = i->second;
+ AlphaISA::PTE *pte = &table[index];
+ assert(pte->valid);
+ if (vpn == pte->tag && (pte->asma || pte->asn == asn)) {
+ retval = pte;
+ break;
+ }
+
+ ++i;
+ }
+ }
+
+ DPRINTF(TLB, "lookup %#x, asn %#x -> %s ppn %#x\n", vpn, (int)asn,
+ retval ? "hit" : "miss", retval ? retval->ppn : 0);
+ return retval;
+}
+
+
+Fault
+AlphaTLB::checkCacheability(RequestPtr &req)
+{
+ // in Alpha, cacheability is controlled by upper-level bits of the
+ // physical address
+
+ /*
+ * We support having the uncacheable bit in either bit 39 or bit 40.
+ * The Turbolaser platform (and EV5) support having the bit in 39, but
+ * Tsunami (which Linux assumes uses an EV6) generates accesses with
+ * the bit in 40. So we must check for both, but we have debug flags
+ * to catch a weird case where both are used, which shouldn't happen.
+ */
+
+
+#if ALPHA_TLASER
+ if (req->getPaddr() & PAddrUncachedBit39) {
+#else
+ if (req->getPaddr() & PAddrUncachedBit43) {
+#endif
+ // IPR memory space not implemented
+ if (PAddrIprSpace(req->getPaddr())) {
+ return new UnimpFault("IPR memory space not implemented!");
+ } else {
+ // mark request as uncacheable
+ req->setFlags(req->getFlags() | UNCACHEABLE);
+
+#if !ALPHA_TLASER
+ // Clear bits 42:35 of the physical address (10-2 in Tsunami manual)
+ req->setPaddr(req->getPaddr() & PAddrUncachedMask);
+#endif
+ }
+ }
+ return NoFault;
+}
+
+
+// insert a new TLB entry
+void
+AlphaTLB::insert(Addr addr, AlphaISA::PTE &pte)
+{
+ AlphaISA::VAddr vaddr = addr;
+ if (table[nlu].valid) {
+ Addr oldvpn = table[nlu].tag;
+ PageTable::iterator i = lookupTable.find(oldvpn);
+
+ if (i == lookupTable.end())
+ panic("TLB entry not found in lookupTable");
+
+ int index;
+ while ((index = i->second) != nlu) {
+ if (table[index].tag != oldvpn)
+ panic("TLB entry not found in lookupTable");
+
+ ++i;
+ }
+
+ DPRINTF(TLB, "remove @%d: %#x -> %#x\n", nlu, oldvpn, table[nlu].ppn);
+
+ lookupTable.erase(i);
+ }
+
+ DPRINTF(TLB, "insert @%d: %#x -> %#x\n", nlu, vaddr.vpn(), pte.ppn);
+
+ table[nlu] = pte;
+ table[nlu].tag = vaddr.vpn();
+ table[nlu].valid = true;
+
+ lookupTable.insert(make_pair(vaddr.vpn(), nlu));
+ nextnlu();
+}
+
+void
+AlphaTLB::flushAll()
+{
+ DPRINTF(TLB, "flushAll\n");
+ memset(table, 0, sizeof(AlphaISA::PTE[size]));
+ lookupTable.clear();
+ nlu = 0;
+}
+
+void
+AlphaTLB::flushProcesses()
+{
+ PageTable::iterator i = lookupTable.begin();
+ PageTable::iterator end = lookupTable.end();
+ while (i != end) {
+ int index = i->second;
+ AlphaISA::PTE *pte = &table[index];
+ assert(pte->valid);
+
+ // we can't increment i after we erase it, so save a copy and
+ // increment it to get the next entry now
+ PageTable::iterator cur = i;
+ ++i;
+
+ if (!pte->asma) {
+ DPRINTF(TLB, "flush @%d: %#x -> %#x\n", index, pte->tag, pte->ppn);
+ pte->valid = false;
+ lookupTable.erase(cur);
+ }
+ }
+}
+
+void
+AlphaTLB::flushAddr(Addr addr, uint8_t asn)
+{
+ AlphaISA::VAddr vaddr = addr;
+
+ PageTable::iterator i = lookupTable.find(vaddr.vpn());
+ if (i == lookupTable.end())
+ return;
+
+ while (i->first == vaddr.vpn()) {
+ int index = i->second;
+ AlphaISA::PTE *pte = &table[index];
+ assert(pte->valid);
+
+ if (vaddr.vpn() == pte->tag && (pte->asma || pte->asn == asn)) {
+ DPRINTF(TLB, "flushaddr @%d: %#x -> %#x\n", index, vaddr.vpn(),
+ pte->ppn);
+
+ // invalidate this entry
+ pte->valid = false;
+
+ lookupTable.erase(i);
+ }
+
+ ++i;
+ }
+}
+
+
+void
+AlphaTLB::serialize(ostream &os)
+{
+ SERIALIZE_SCALAR(size);
+ SERIALIZE_SCALAR(nlu);
+
+ for (int i = 0; i < size; i++) {
+ nameOut(os, csprintf("%s.PTE%d", name(), i));
+ table[i].serialize(os);
+ }
+}
+
+void
+AlphaTLB::unserialize(Checkpoint *cp, const string &section)
+{
+ UNSERIALIZE_SCALAR(size);
+ UNSERIALIZE_SCALAR(nlu);
+
+ for (int i = 0; i < size; i++) {
+ table[i].unserialize(cp, csprintf("%s.PTE%d", section, i));
+ if (table[i].valid) {
+ lookupTable.insert(make_pair(table[i].tag, i));
+ }
+ }
+}
+
+
+///////////////////////////////////////////////////////////////////////
+//
+// Alpha ITB
+//
+AlphaITB::AlphaITB(const std::string &name, int size)
+ : AlphaTLB(name, size)
+{}
+
+
+void
+AlphaITB::regStats()
+{
+ hits
+ .name(name() + ".hits")
+ .desc("ITB hits");
+ misses
+ .name(name() + ".misses")
+ .desc("ITB misses");
+ acv
+ .name(name() + ".acv")
+ .desc("ITB acv");
+ accesses
+ .name(name() + ".accesses")
+ .desc("ITB accesses");
+
+ accesses = hits + misses;
+}
+
+
+Fault
+AlphaITB::translate(RequestPtr &req, ExecContext *xc) const
+{
+ if (AlphaISA::PcPAL(req->getVaddr())) {
+ // strip off PAL PC marker (lsb is 1)
+ req->setPaddr((req->getVaddr() & ~3) & PAddrImplMask);
+ hits++;
+ return NoFault;
+ }
+
+ if (req->getFlags() & PHYSICAL) {
+ req->setPaddr(req->getVaddr());
+ } else {
+ // verify that this is a good virtual address
+ if (!validVirtualAddress(req->getVaddr())) {
+ acv++;
+ return new ItbAcvFault(req->getVaddr());
+ }
+
+
+ // VA<42:41> == 2, VA<39:13> maps directly to PA<39:13> for EV5
+ // VA<47:41> == 0x7e, VA<40:13> maps directly to PA<40:13> for EV6
+#if ALPHA_TLASER
+ if ((MCSR_SP(xc->readMiscReg(AlphaISA::IPR_MCSR)) & 2) &&
+ VAddrSpaceEV5(req->getVaddr()) == 2) {
+#else
+ if (VAddrSpaceEV6(req->getVaddr()) == 0x7e) {
+#endif
+ // only valid in kernel mode
+ if (ICM_CM(xc->readMiscReg(AlphaISA::IPR_ICM)) !=
+ AlphaISA::mode_kernel) {
+ acv++;
+ return new ItbAcvFault(req->getVaddr());
+ }
+
+ req->setPaddr(req->getVaddr() & PAddrImplMask);
+
+#if !ALPHA_TLASER
+ // sign extend the physical address properly
+ if (req->getPaddr() & PAddrUncachedBit40)
+ req->setPaddr(req->getPaddr() | ULL(0xf0000000000));
+ else
+ 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->getVaddr()).vpn(),
+ asn);
+
+ if (!pte) {
+ misses++;
+ return new ItbPageFault(req->getVaddr());
+ }
+
+ 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
+ acv++;
+ return new ItbAcvFault(req->getVaddr());
+ }
+
+ hits++;
+ }
+ }
+
+ // check that the physical address is ok (catch bad physical addresses)
+ if (req->getPaddr() & ~PAddrImplMask)
+ return genMachineCheckFault();
+
+ return checkCacheability(req);
+
+}
+
+///////////////////////////////////////////////////////////////////////
+//
+// Alpha DTB
+//
+AlphaDTB::AlphaDTB(const std::string &name, int size)
+ : AlphaTLB(name, size)
+{}
+
+void
+AlphaDTB::regStats()
+{
+ read_hits
+ .name(name() + ".read_hits")
+ .desc("DTB read hits")
+ ;
+
+ read_misses
+ .name(name() + ".read_misses")
+ .desc("DTB read misses")
+ ;
+
+ read_acv
+ .name(name() + ".read_acv")
+ .desc("DTB read access violations")
+ ;
+
+ read_accesses
+ .name(name() + ".read_accesses")
+ .desc("DTB read accesses")
+ ;
+
+ write_hits
+ .name(name() + ".write_hits")
+ .desc("DTB write hits")
+ ;
+
+ write_misses
+ .name(name() + ".write_misses")
+ .desc("DTB write misses")
+ ;
+
+ write_acv
+ .name(name() + ".write_acv")
+ .desc("DTB write access violations")
+ ;
+
+ write_accesses
+ .name(name() + ".write_accesses")
+ .desc("DTB write accesses")
+ ;
+
+ hits
+ .name(name() + ".hits")
+ .desc("DTB hits")
+ ;
+
+ misses
+ .name(name() + ".misses")
+ .desc("DTB misses")
+ ;
+
+ acv
+ .name(name() + ".acv")
+ .desc("DTB access violations")
+ ;
+
+ accesses
+ .name(name() + ".accesses")
+ .desc("DTB accesses")
+ ;
+
+ hits = read_hits + write_hits;
+ misses = read_misses + write_misses;
+ acv = read_acv + write_acv;
+ accesses = read_accesses + write_accesses;
+}
+
+Fault
+AlphaDTB::translate(RequestPtr &req, ExecContext *xc, bool write) const
+{
+ Addr pc = xc->readPC();
+
+ AlphaISA::mode_type mode =
+ (AlphaISA::mode_type)DTB_CM_CM(xc->readMiscReg(AlphaISA::IPR_DTB_CM));
+
+
+ /**
+ * Check for alignment faults
+ */
+ 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->getFlags() & ALTMODE) ?
+ (AlphaISA::mode_type)ALT_MODE_AM(
+ xc->readMiscReg(AlphaISA::IPR_ALT_MODE))
+ : AlphaISA::mode_kernel;
+ }
+
+ if (req->getFlags() & PHYSICAL) {
+ req->setPaddr(req->getVaddr());
+ } else {
+ // verify that this is a good virtual address
+ if (!validVirtualAddress(req->getVaddr())) {
+ if (write) { write_acv++; } else { read_acv++; }
+ 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->getVaddr()) == 2) {
+#else
+ if (VAddrSpaceEV6(req->getVaddr()) == 0x7e) {
+#endif
+
+ // only valid in kernel mode
+ if (DTB_CM_CM(xc->readMiscReg(AlphaISA::IPR_DTB_CM)) !=
+ AlphaISA::mode_kernel) {
+ if (write) { write_acv++; } else { read_acv++; }
+ uint64_t flags = ((write ? MM_STAT_WR_MASK : 0) |
+ MM_STAT_ACV_MASK);
+ return new DtbAcvFault(req->getVaddr(), req->getFlags(), flags);
+ }
+
+ req->setPaddr(req->getVaddr() & PAddrImplMask);
+
+#if !ALPHA_TLASER
+ // sign extend the physical address properly
+ if (req->getPaddr() & PAddrUncachedBit40)
+ req->setPaddr(req->getPaddr() | ULL(0xf0000000000));
+ else
+ req->setPaddr(req->getPaddr() & ULL(0xffffffffff));
+#endif
+
+ } else {
+ if (write)
+ write_accesses++;
+ else
+ read_accesses++;
+
+ int asn = DTB_ASN_ASN(xc->readMiscReg(AlphaISA::IPR_DTB_ASN));
+
+ // not a physical address: need to look up pte
+ AlphaISA::PTE *pte = lookup(AlphaISA::VAddr(req->getVaddr()).vpn(),
+ asn);
+
+ if (!pte) {
+ // page fault
+ if (write) { write_misses++; } else { read_misses++; }
+ 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->setPaddr((pte->ppn << AlphaISA::PageShift) +
+ AlphaISA::VAddr(req->getVaddr()).offset());
+
+ if (write) {
+ if (!(pte->xwe & MODE2MASK(mode))) {
+ // declare the instruction access fault
+ write_acv++;
+ 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) {
+ write_acv++;
+ 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))) {
+ read_acv++;
+ 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) {
+ read_acv++;
+ uint64_t flags = MM_STAT_FONR_MASK;
+ return new DtbPageFault(req->getVaddr(), req->getFlags(), flags);
+ }
+ }
+ }
+
+ if (write)
+ write_hits++;
+ else
+ read_hits++;
+ }
+
+ // check that the physical address is ok (catch bad physical addresses)
+ if (req->getPaddr() & ~PAddrImplMask)
+ return genMachineCheckFault();
+
+ return checkCacheability(req);
+}
+
+AlphaISA::PTE &
+AlphaTLB::index(bool advance)
+{
+ AlphaISA::PTE *pte = &table[nlu];
+
+ if (advance)
+ nextnlu();
+
+ return *pte;
+}
+
+DEFINE_SIM_OBJECT_CLASS_NAME("AlphaTLB", AlphaTLB)
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaITB)
+
+ Param<int> size;
+
+END_DECLARE_SIM_OBJECT_PARAMS(AlphaITB)
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(AlphaITB)
+
+ INIT_PARAM_DFLT(size, "TLB size", 48)
+
+END_INIT_SIM_OBJECT_PARAMS(AlphaITB)
+
+
+CREATE_SIM_OBJECT(AlphaITB)
+{
+ return new AlphaITB(getInstanceName(), size);
+}
+
+REGISTER_SIM_OBJECT("AlphaITB", AlphaITB)
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaDTB)
+
+ Param<int> size;
+
+END_DECLARE_SIM_OBJECT_PARAMS(AlphaDTB)
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(AlphaDTB)
+
+ INIT_PARAM_DFLT(size, "TLB size", 64)
+
+END_INIT_SIM_OBJECT_PARAMS(AlphaDTB)
+
+
+CREATE_SIM_OBJECT(AlphaDTB)
+{
+ return new AlphaDTB(getInstanceName(), size);
+}
+
+REGISTER_SIM_OBJECT("AlphaDTB", AlphaDTB)
+
diff --git a/src/arch/alpha/tlb.hh b/src/arch/alpha/tlb.hh
new file mode 100644
index 000000000..f6256020e
--- /dev/null
+++ b/src/arch/alpha/tlb.hh
@@ -0,0 +1,121 @@
+/*
+ * 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 __ALPHA_MEMORY_HH__
+#define __ALPHA_MEMORY_HH__
+
+#include <map>
+
+#include "arch/alpha/ev5.hh"
+#include "arch/alpha/isa_traits.hh"
+#include "arch/alpha/faults.hh"
+#include "base/statistics.hh"
+#include "mem/request.hh"
+#include "sim/sim_object.hh"
+
+class ExecContext;
+
+class AlphaTLB : public SimObject
+{
+ protected:
+ typedef std::multimap<Addr, int> PageTable;
+ PageTable lookupTable; // Quick lookup into page table
+
+ AlphaISA::PTE *table; // the Page Table
+ int size; // TLB Size
+ int nlu; // not last used entry (for replacement)
+
+ void nextnlu() { if (++nlu >= size) nlu = 0; }
+ AlphaISA::PTE *lookup(Addr vpn, uint8_t asn) const;
+
+ public:
+ AlphaTLB(const std::string &name, int size);
+ virtual ~AlphaTLB();
+
+ int getsize() const { return size; }
+
+ AlphaISA::PTE &index(bool advance = true);
+ void insert(Addr vaddr, AlphaISA::PTE &pte);
+
+ void flushAll();
+ void flushProcesses();
+ void flushAddr(Addr addr, uint8_t asn);
+
+ // static helper functions... really EV5 VM traits
+ static bool validVirtualAddress(Addr vaddr) {
+ // unimplemented bits must be all 0 or all 1
+ Addr unimplBits = vaddr & EV5::VAddrUnImplMask;
+ return (unimplBits == 0) || (unimplBits == EV5::VAddrUnImplMask);
+ }
+
+ static Fault checkCacheability(RequestPtr &req);
+
+ // Checkpointing
+ virtual void serialize(std::ostream &os);
+ virtual void unserialize(Checkpoint *cp, const std::string &section);
+};
+
+class AlphaITB : public AlphaTLB
+{
+ protected:
+ mutable Stats::Scalar<> hits;
+ mutable Stats::Scalar<> misses;
+ mutable Stats::Scalar<> acv;
+ mutable Stats::Formula accesses;
+
+ public:
+ AlphaITB(const std::string &name, int size);
+ virtual void regStats();
+
+ Fault translate(RequestPtr &req, ExecContext *xc) const;
+};
+
+class AlphaDTB : public AlphaTLB
+{
+ protected:
+ mutable Stats::Scalar<> read_hits;
+ mutable Stats::Scalar<> read_misses;
+ mutable Stats::Scalar<> read_acv;
+ mutable Stats::Scalar<> read_accesses;
+ mutable Stats::Scalar<> write_hits;
+ mutable Stats::Scalar<> write_misses;
+ mutable Stats::Scalar<> write_acv;
+ mutable Stats::Scalar<> write_accesses;
+ Stats::Formula hits;
+ Stats::Formula misses;
+ Stats::Formula acv;
+ Stats::Formula accesses;
+
+ public:
+ AlphaDTB(const std::string &name, int size);
+ virtual void regStats();
+
+ Fault translate(RequestPtr &req, ExecContext *xc, bool write) const;
+};
+
+#endif // __ALPHA_MEMORY_HH__
diff --git a/src/arch/alpha/tru64/process.cc b/src/arch/alpha/tru64/process.cc
new file mode 100644
index 000000000..55f75f7d0
--- /dev/null
+++ b/src/arch/alpha/tru64/process.cc
@@ -0,0 +1,586 @@
+/*
+ * Copyright (c) 2001-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "arch/alpha/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 "sim/process.hh"
+#include "sim/syscall_emul.hh"
+
+using namespace std;
+using namespace AlphaISA;
+
+/// Target uname() handler.
+static SyscallReturn
+unameFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+{
+ TypedBufferArg<AlphaTru64::utsname> name(xc->getSyscallArg(0));
+
+ strcpy(name->sysname, "OSF1");
+ strcpy(name->nodename, "m5.eecs.umich.edu");
+ strcpy(name->release, "V5.1");
+ strcpy(name->version, "732");
+ strcpy(name->machine, "alpha");
+
+ name.copyOut(xc->getMemPort());
+ return 0;
+}
+
+/// Target getsysyinfo() handler.
+static SyscallReturn
+getsysinfoFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+{
+ unsigned op = xc->getSyscallArg(0);
+ unsigned nbytes = xc->getSyscallArg(2);
+
+ switch (op) {
+
+ case AlphaTru64::GSI_MAX_CPU: {
+ TypedBufferArg<uint32_t> max_cpu(xc->getSyscallArg(1));
+ *max_cpu = htog((uint32_t)process->numCpus());
+ max_cpu.copyOut(xc->getMemPort());
+ return 1;
+ }
+
+ 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->getMemPort());
+ return 1;
+ }
+
+ case AlphaTru64::GSI_PHYSMEM: {
+ TypedBufferArg<uint64_t> physmem(xc->getSyscallArg(1));
+ *physmem = htog((uint64_t)1024 * 1024); // physical memory in KB
+ physmem.copyOut(xc->getMemPort());
+ return 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());
+ infop->cpu_type = htog(57);
+ infop->ncpus = htog(process->numCpus());
+ uint64_t cpumask = (1 << process->numCpus()) - 1;
+ infop->cpus_present = infop->cpus_running = htog(cpumask);
+ infop->cpu_binding = htog(0);
+ infop->cpu_ex_binding = htog(0);
+ infop->mhz = htog(667);
+
+ infop.copyOut(xc->getMemPort());
+ return 1;
+ }
+
+ case AlphaTru64::GSI_PROC_TYPE: {
+ TypedBufferArg<uint64_t> proc_type(xc->getSyscallArg(1));
+ *proc_type = htog((uint64_t)11);
+ proc_type.copyOut(xc->getMemPort());
+ return 1;
+ }
+
+ case AlphaTru64::GSI_PLATFORM_NAME: {
+ BufferArg bufArg(xc->getSyscallArg(1), nbytes);
+ strncpy((char *)bufArg.bufferPtr(),
+ "COMPAQ Professional Workstation XP1000",
+ nbytes);
+ bufArg.copyOut(xc->getMemPort());
+ return 1;
+ }
+
+ case AlphaTru64::GSI_CLK_TCK: {
+ TypedBufferArg<uint64_t> clk_hz(xc->getSyscallArg(1));
+ *clk_hz = htog((uint64_t)1024);
+ clk_hz.copyOut(xc->getMemPort());
+ return 1;
+ }
+
+ default:
+ warn("getsysinfo: unknown op %d\n", op);
+ break;
+ }
+
+ return 0;
+}
+
+/// Target setsysyinfo() handler.
+static SyscallReturn
+setsysinfoFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+{
+ unsigned op = xc->getSyscallArg(0);
+
+ switch (op) {
+ case AlphaTru64::SSI_IEEE_FP_CONTROL:
+ warn("setsysinfo: ignoring ieee_set_fp_control() arg 0x%x\n",
+ xc->getSyscallArg(1));
+ break;
+
+ default:
+ warn("setsysinfo: unknown op %d\n", op);
+ break;
+ }
+
+ return 0;
+}
+
+
+/// Target 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)", AlphaTru64::indirectSyscallFunc,
+ SyscallDesc::SuppressReturnValue),
+ /* 1 */ SyscallDesc("exit", exitFunc),
+ /* 2 */ SyscallDesc("fork", unimplementedFunc),
+ /* 3 */ SyscallDesc("read", readFunc),
+ /* 4 */ SyscallDesc("write", writeFunc),
+ /* 5 */ SyscallDesc("old_open", unimplementedFunc),
+ /* 6 */ SyscallDesc("close", closeFunc),
+ /* 7 */ SyscallDesc("wait4", unimplementedFunc),
+ /* 8 */ SyscallDesc("old_creat", unimplementedFunc),
+ /* 9 */ SyscallDesc("link", unimplementedFunc),
+ /* 10 */ SyscallDesc("unlink", unlinkFunc),
+ /* 11 */ SyscallDesc("execv", unimplementedFunc),
+ /* 12 */ SyscallDesc("chdir", unimplementedFunc),
+ /* 13 */ SyscallDesc("fchdir", unimplementedFunc),
+ /* 14 */ SyscallDesc("mknod", unimplementedFunc),
+ /* 15 */ SyscallDesc("chmod", unimplementedFunc),
+ /* 16 */ SyscallDesc("chown", unimplementedFunc),
+ /* 17 */ SyscallDesc("obreak", obreakFunc),
+ /* 18 */ SyscallDesc("pre_F64_getfsstat", unimplementedFunc),
+ /* 19 */ SyscallDesc("lseek", lseekFunc),
+ /* 20 */ SyscallDesc("getpid", getpidPseudoFunc),
+ /* 21 */ SyscallDesc("mount", unimplementedFunc),
+ /* 22 */ SyscallDesc("unmount", unimplementedFunc),
+ /* 23 */ SyscallDesc("setuid", setuidFunc),
+ /* 24 */ SyscallDesc("getuid", getuidPseudoFunc),
+ /* 25 */ SyscallDesc("exec_with_loader", unimplementedFunc),
+ /* 26 */ SyscallDesc("ptrace", unimplementedFunc),
+ /* 27 */ SyscallDesc("recvmsg", unimplementedFunc),
+ /* 28 */ SyscallDesc("sendmsg", unimplementedFunc),
+ /* 29 */ SyscallDesc("recvfrom", unimplementedFunc),
+ /* 30 */ SyscallDesc("accept", unimplementedFunc),
+ /* 31 */ SyscallDesc("getpeername", unimplementedFunc),
+ /* 32 */ SyscallDesc("getsockname", unimplementedFunc),
+ /* 33 */ SyscallDesc("access", unimplementedFunc),
+ /* 34 */ SyscallDesc("chflags", unimplementedFunc),
+ /* 35 */ SyscallDesc("fchflags", unimplementedFunc),
+ /* 36 */ SyscallDesc("sync", unimplementedFunc),
+ /* 37 */ SyscallDesc("kill", unimplementedFunc),
+ /* 38 */ SyscallDesc("old_stat", unimplementedFunc),
+ /* 39 */ SyscallDesc("setpgid", unimplementedFunc),
+ /* 40 */ SyscallDesc("old_lstat", unimplementedFunc),
+ /* 41 */ SyscallDesc("dup", unimplementedFunc),
+ /* 42 */ SyscallDesc("pipe", unimplementedFunc),
+ /* 43 */ SyscallDesc("set_program_attributes", unimplementedFunc),
+ /* 44 */ SyscallDesc("profil", unimplementedFunc),
+ /* 45 */ SyscallDesc("open", openFunc<AlphaTru64>),
+ /* 46 */ SyscallDesc("obsolete osigaction", unimplementedFunc),
+ /* 47 */ SyscallDesc("getgid", getgidPseudoFunc),
+ /* 48 */ SyscallDesc("sigprocmask", ignoreFunc),
+ /* 49 */ SyscallDesc("getlogin", unimplementedFunc),
+ /* 50 */ SyscallDesc("setlogin", unimplementedFunc),
+ /* 51 */ SyscallDesc("acct", unimplementedFunc),
+ /* 52 */ SyscallDesc("sigpending", unimplementedFunc),
+ /* 53 */ SyscallDesc("classcntl", unimplementedFunc),
+ /* 54 */ SyscallDesc("ioctl", ioctlFunc<AlphaTru64>),
+ /* 55 */ SyscallDesc("reboot", unimplementedFunc),
+ /* 56 */ SyscallDesc("revoke", unimplementedFunc),
+ /* 57 */ SyscallDesc("symlink", unimplementedFunc),
+ /* 58 */ SyscallDesc("readlink", unimplementedFunc),
+ /* 59 */ SyscallDesc("execve", unimplementedFunc),
+ /* 60 */ SyscallDesc("umask", unimplementedFunc),
+ /* 61 */ SyscallDesc("chroot", unimplementedFunc),
+ /* 62 */ SyscallDesc("old_fstat", unimplementedFunc),
+ /* 63 */ SyscallDesc("getpgrp", unimplementedFunc),
+ /* 64 */ SyscallDesc("getpagesize", getpagesizeFunc),
+ /* 65 */ SyscallDesc("mremap", unimplementedFunc),
+ /* 66 */ SyscallDesc("vfork", unimplementedFunc),
+ /* 67 */ SyscallDesc("pre_F64_stat", statFunc<AlphaTru64::PreF64>),
+ /* 68 */ SyscallDesc("pre_F64_lstat", lstatFunc<AlphaTru64::PreF64>),
+ /* 69 */ SyscallDesc("sbrk", unimplementedFunc),
+ /* 70 */ SyscallDesc("sstk", unimplementedFunc),
+ /* 71 */ SyscallDesc("mmap", mmapFunc<AlphaTru64>),
+ /* 72 */ SyscallDesc("ovadvise", unimplementedFunc),
+ /* 73 */ SyscallDesc("munmap", munmapFunc),
+ /* 74 */ SyscallDesc("mprotect", ignoreFunc),
+ /* 75 */ SyscallDesc("madvise", unimplementedFunc),
+ /* 76 */ SyscallDesc("old_vhangup", unimplementedFunc),
+ /* 77 */ SyscallDesc("kmodcall", unimplementedFunc),
+ /* 78 */ SyscallDesc("mincore", unimplementedFunc),
+ /* 79 */ SyscallDesc("getgroups", unimplementedFunc),
+ /* 80 */ SyscallDesc("setgroups", unimplementedFunc),
+ /* 81 */ SyscallDesc("old_getpgrp", unimplementedFunc),
+ /* 82 */ SyscallDesc("setpgrp", unimplementedFunc),
+ /* 83 */ SyscallDesc("setitimer", unimplementedFunc),
+ /* 84 */ SyscallDesc("old_wait", unimplementedFunc),
+ /* 85 */ SyscallDesc("table", tableFunc),
+ /* 86 */ SyscallDesc("getitimer", unimplementedFunc),
+ /* 87 */ SyscallDesc("gethostname", gethostnameFunc),
+ /* 88 */ SyscallDesc("sethostname", unimplementedFunc),
+ /* 89 */ SyscallDesc("getdtablesize", unimplementedFunc),
+ /* 90 */ SyscallDesc("dup2", unimplementedFunc),
+ /* 91 */ SyscallDesc("pre_F64_fstat", fstatFunc<AlphaTru64::PreF64>),
+ /* 92 */ SyscallDesc("fcntl", fcntlFunc),
+ /* 93 */ SyscallDesc("select", unimplementedFunc),
+ /* 94 */ SyscallDesc("poll", unimplementedFunc),
+ /* 95 */ SyscallDesc("fsync", unimplementedFunc),
+ /* 96 */ SyscallDesc("setpriority", unimplementedFunc),
+ /* 97 */ SyscallDesc("socket", unimplementedFunc),
+ /* 98 */ SyscallDesc("connect", unimplementedFunc),
+ /* 99 */ SyscallDesc("old_accept", unimplementedFunc),
+ /* 100 */ SyscallDesc("getpriority", unimplementedFunc),
+ /* 101 */ SyscallDesc("old_send", unimplementedFunc),
+ /* 102 */ SyscallDesc("old_recv", unimplementedFunc),
+ /* 103 */ SyscallDesc("sigreturn", AlphaTru64::sigreturnFunc,
+ SyscallDesc::SuppressReturnValue),
+ /* 104 */ SyscallDesc("bind", unimplementedFunc),
+ /* 105 */ SyscallDesc("setsockopt", unimplementedFunc),
+ /* 106 */ SyscallDesc("listen", unimplementedFunc),
+ /* 107 */ SyscallDesc("plock", unimplementedFunc),
+ /* 108 */ SyscallDesc("old_sigvec", unimplementedFunc),
+ /* 109 */ SyscallDesc("old_sigblock", unimplementedFunc),
+ /* 110 */ SyscallDesc("old_sigsetmask", unimplementedFunc),
+ /* 111 */ SyscallDesc("sigsuspend", unimplementedFunc),
+ /* 112 */ SyscallDesc("sigstack", ignoreFunc),
+ /* 113 */ SyscallDesc("old_recvmsg", unimplementedFunc),
+ /* 114 */ SyscallDesc("old_sendmsg", unimplementedFunc),
+ /* 115 */ SyscallDesc("obsolete vtrace", unimplementedFunc),
+ /* 116 */ SyscallDesc("gettimeofday", gettimeofdayFunc<AlphaTru64>),
+ /* 117 */ SyscallDesc("getrusage", getrusageFunc<AlphaTru64>),
+ /* 118 */ SyscallDesc("getsockopt", unimplementedFunc),
+ /* 119 */ SyscallDesc("numa_syscalls", unimplementedFunc),
+ /* 120 */ SyscallDesc("readv", unimplementedFunc),
+ /* 121 */ SyscallDesc("writev", unimplementedFunc),
+ /* 122 */ SyscallDesc("settimeofday", unimplementedFunc),
+ /* 123 */ SyscallDesc("fchown", unimplementedFunc),
+ /* 124 */ SyscallDesc("fchmod", unimplementedFunc),
+ /* 125 */ SyscallDesc("old_recvfrom", unimplementedFunc),
+ /* 126 */ SyscallDesc("setreuid", unimplementedFunc),
+ /* 127 */ SyscallDesc("setregid", unimplementedFunc),
+ /* 128 */ SyscallDesc("rename", renameFunc),
+ /* 129 */ SyscallDesc("truncate", truncateFunc),
+ /* 130 */ SyscallDesc("ftruncate", ftruncateFunc),
+ /* 131 */ SyscallDesc("flock", unimplementedFunc),
+ /* 132 */ SyscallDesc("setgid", unimplementedFunc),
+ /* 133 */ SyscallDesc("sendto", unimplementedFunc),
+ /* 134 */ SyscallDesc("shutdown", unimplementedFunc),
+ /* 135 */ SyscallDesc("socketpair", unimplementedFunc),
+ /* 136 */ SyscallDesc("mkdir", unimplementedFunc),
+ /* 137 */ SyscallDesc("rmdir", unimplementedFunc),
+ /* 138 */ SyscallDesc("utimes", unimplementedFunc),
+ /* 139 */ SyscallDesc("obsolete 4.2 sigreturn", unimplementedFunc),
+ /* 140 */ SyscallDesc("adjtime", unimplementedFunc),
+ /* 141 */ SyscallDesc("old_getpeername", unimplementedFunc),
+ /* 142 */ SyscallDesc("gethostid", unimplementedFunc),
+ /* 143 */ SyscallDesc("sethostid", unimplementedFunc),
+ /* 144 */ SyscallDesc("getrlimit", getrlimitFunc<AlphaTru64>),
+ /* 145 */ SyscallDesc("setrlimit", ignoreFunc),
+ /* 146 */ SyscallDesc("old_killpg", unimplementedFunc),
+ /* 147 */ SyscallDesc("setsid", unimplementedFunc),
+ /* 148 */ SyscallDesc("quotactl", unimplementedFunc),
+ /* 149 */ SyscallDesc("oldquota", unimplementedFunc),
+ /* 150 */ SyscallDesc("old_getsockname", unimplementedFunc),
+ /* 151 */ SyscallDesc("pread", unimplementedFunc),
+ /* 152 */ SyscallDesc("pwrite", unimplementedFunc),
+ /* 153 */ SyscallDesc("pid_block", unimplementedFunc),
+ /* 154 */ SyscallDesc("pid_unblock", unimplementedFunc),
+ /* 155 */ SyscallDesc("signal_urti", unimplementedFunc),
+ /* 156 */ SyscallDesc("sigaction", ignoreFunc),
+ /* 157 */ SyscallDesc("sigwaitprim", unimplementedFunc),
+ /* 158 */ SyscallDesc("nfssvc", unimplementedFunc),
+ /* 159 */ SyscallDesc("getdirentries", 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),
+ /* 165 */ SyscallDesc("getdomainname", unimplementedFunc),
+ /* 166 */ SyscallDesc("setdomainname", unimplementedFunc),
+ /* 167 */ SyscallDesc("unknown #167", unimplementedFunc),
+ /* 168 */ SyscallDesc("unknown #168", unimplementedFunc),
+ /* 169 */ SyscallDesc("exportfs", unimplementedFunc),
+ /* 170 */ SyscallDesc("unknown #170", unimplementedFunc),
+ /* 171 */ SyscallDesc("unknown #171", unimplementedFunc),
+ /* 172 */ SyscallDesc("unknown #172", unimplementedFunc),
+ /* 173 */ SyscallDesc("unknown #173", unimplementedFunc),
+ /* 174 */ SyscallDesc("unknown #174", unimplementedFunc),
+ /* 175 */ SyscallDesc("unknown #175", unimplementedFunc),
+ /* 176 */ SyscallDesc("unknown #176", unimplementedFunc),
+ /* 177 */ SyscallDesc("unknown #177", unimplementedFunc),
+ /* 178 */ SyscallDesc("unknown #178", unimplementedFunc),
+ /* 179 */ SyscallDesc("unknown #179", unimplementedFunc),
+ /* 180 */ SyscallDesc("unknown #180", unimplementedFunc),
+ /* 181 */ SyscallDesc("alt_plock", unimplementedFunc),
+ /* 182 */ SyscallDesc("unknown #182", unimplementedFunc),
+ /* 183 */ SyscallDesc("unknown #183", unimplementedFunc),
+ /* 184 */ SyscallDesc("getmnt", unimplementedFunc),
+ /* 185 */ SyscallDesc("unknown #185", unimplementedFunc),
+ /* 186 */ SyscallDesc("unknown #186", unimplementedFunc),
+ /* 187 */ SyscallDesc("alt_sigpending", unimplementedFunc),
+ /* 188 */ SyscallDesc("alt_setsid", unimplementedFunc),
+ /* 189 */ SyscallDesc("unknown #189", unimplementedFunc),
+ /* 190 */ SyscallDesc("unknown #190", unimplementedFunc),
+ /* 191 */ SyscallDesc("unknown #191", unimplementedFunc),
+ /* 192 */ SyscallDesc("unknown #192", unimplementedFunc),
+ /* 193 */ SyscallDesc("unknown #193", unimplementedFunc),
+ /* 194 */ SyscallDesc("unknown #194", unimplementedFunc),
+ /* 195 */ SyscallDesc("unknown #195", unimplementedFunc),
+ /* 196 */ SyscallDesc("unknown #196", unimplementedFunc),
+ /* 197 */ SyscallDesc("unknown #197", unimplementedFunc),
+ /* 198 */ SyscallDesc("unknown #198", unimplementedFunc),
+ /* 199 */ SyscallDesc("swapon", unimplementedFunc),
+ /* 200 */ SyscallDesc("msgctl", unimplementedFunc),
+ /* 201 */ SyscallDesc("msgget", unimplementedFunc),
+ /* 202 */ SyscallDesc("msgrcv", unimplementedFunc),
+ /* 203 */ SyscallDesc("msgsnd", unimplementedFunc),
+ /* 204 */ SyscallDesc("semctl", unimplementedFunc),
+ /* 205 */ SyscallDesc("semget", unimplementedFunc),
+ /* 206 */ SyscallDesc("semop", unimplementedFunc),
+ /* 207 */ SyscallDesc("uname", unameFunc),
+ /* 208 */ SyscallDesc("lchown", unimplementedFunc),
+ /* 209 */ SyscallDesc("shmat", unimplementedFunc),
+ /* 210 */ SyscallDesc("shmctl", unimplementedFunc),
+ /* 211 */ SyscallDesc("shmdt", unimplementedFunc),
+ /* 212 */ SyscallDesc("shmget", unimplementedFunc),
+ /* 213 */ SyscallDesc("mvalid", unimplementedFunc),
+ /* 214 */ SyscallDesc("getaddressconf", unimplementedFunc),
+ /* 215 */ SyscallDesc("msleep", unimplementedFunc),
+ /* 216 */ SyscallDesc("mwakeup", unimplementedFunc),
+ /* 217 */ SyscallDesc("msync", unimplementedFunc),
+ /* 218 */ SyscallDesc("signal", unimplementedFunc),
+ /* 219 */ SyscallDesc("utc_gettime", unimplementedFunc),
+ /* 220 */ SyscallDesc("utc_adjtime", unimplementedFunc),
+ /* 221 */ SyscallDesc("unknown #221", unimplementedFunc),
+ /* 222 */ SyscallDesc("security", unimplementedFunc),
+ /* 223 */ SyscallDesc("kloadcall", unimplementedFunc),
+ /* 224 */ SyscallDesc("stat", statFunc<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),
+ /* 232 */ SyscallDesc("unknown #232", unimplementedFunc),
+ /* 233 */ SyscallDesc("getpgid", unimplementedFunc),
+ /* 234 */ SyscallDesc("getsid", unimplementedFunc),
+ /* 235 */ SyscallDesc("sigaltstack", ignoreFunc),
+ /* 236 */ SyscallDesc("waitid", unimplementedFunc),
+ /* 237 */ SyscallDesc("priocntlset", unimplementedFunc),
+ /* 238 */ SyscallDesc("sigsendset", unimplementedFunc),
+ /* 239 */ SyscallDesc("set_speculative", unimplementedFunc),
+ /* 240 */ SyscallDesc("msfs_syscall", unimplementedFunc),
+ /* 241 */ SyscallDesc("sysinfo", unimplementedFunc),
+ /* 242 */ SyscallDesc("uadmin", unimplementedFunc),
+ /* 243 */ SyscallDesc("fuser", unimplementedFunc),
+ /* 244 */ SyscallDesc("proplist_syscall", unimplementedFunc),
+ /* 245 */ SyscallDesc("ntp_adjtime", unimplementedFunc),
+ /* 246 */ SyscallDesc("ntp_gettime", unimplementedFunc),
+ /* 247 */ SyscallDesc("pathconf", unimplementedFunc),
+ /* 248 */ SyscallDesc("fpathconf", unimplementedFunc),
+ /* 249 */ SyscallDesc("sync2", unimplementedFunc),
+ /* 250 */ SyscallDesc("uswitch", unimplementedFunc),
+ /* 251 */ SyscallDesc("usleep_thread", unimplementedFunc),
+ /* 252 */ SyscallDesc("audcntl", unimplementedFunc),
+ /* 253 */ SyscallDesc("audgen", unimplementedFunc),
+ /* 254 */ SyscallDesc("sysfs", unimplementedFunc),
+ /* 255 */ SyscallDesc("subsys_info", unimplementedFunc),
+ /* 256 */ SyscallDesc("getsysinfo", getsysinfoFunc),
+ /* 257 */ SyscallDesc("setsysinfo", setsysinfoFunc),
+ /* 258 */ SyscallDesc("afs_syscall", unimplementedFunc),
+ /* 259 */ SyscallDesc("swapctl", unimplementedFunc),
+ /* 260 */ SyscallDesc("memcntl", unimplementedFunc),
+ /* 261 */ SyscallDesc("fdatasync", unimplementedFunc),
+ /* 262 */ SyscallDesc("oflock", unimplementedFunc),
+ /* 263 */ SyscallDesc("F64_readv", unimplementedFunc),
+ /* 264 */ SyscallDesc("F64_writev", unimplementedFunc),
+ /* 265 */ SyscallDesc("cdslxlate", unimplementedFunc),
+ /* 266 */ SyscallDesc("sendfile", unimplementedFunc),
+};
+
+
+
+SyscallDesc AlphaTru64Process::machSyscallDescs[] = {
+ /* 0 */ SyscallDesc("kern_invalid", unimplementedFunc),
+ /* 1 */ SyscallDesc("m5_mutex_lock", 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),
+ /* 11 */ SyscallDesc("thread_reply", unimplementedFunc),
+ /* 12 */ SyscallDesc("task_notify", unimplementedFunc),
+ /* 13 */ SyscallDesc("thread_self", unimplementedFunc),
+ /* 14 */ SyscallDesc("kern_invalid", unimplementedFunc),
+ /* 15 */ SyscallDesc("kern_invalid", unimplementedFunc),
+ /* 16 */ SyscallDesc("kern_invalid", unimplementedFunc),
+ /* 17 */ SyscallDesc("kern_invalid", unimplementedFunc),
+ /* 18 */ SyscallDesc("kern_invalid", unimplementedFunc),
+ /* 19 */ SyscallDesc("kern_invalid", unimplementedFunc),
+ /* 20 */ SyscallDesc("msg_send_trap", unimplementedFunc),
+ /* 21 */ SyscallDesc("msg_receive_trap", unimplementedFunc),
+ /* 22 */ SyscallDesc("msg_rpc_trap", unimplementedFunc),
+ /* 23 */ SyscallDesc("kern_invalid", unimplementedFunc),
+ /* 24 */ SyscallDesc("nxm_block", 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", AlphaTru64::nxm_thread_createFunc),
+ /* 33 */ SyscallDesc("nxm_task_init", AlphaTru64::nxm_task_initFunc),
+ /* 34 */ SyscallDesc("kern_invalid", unimplementedFunc),
+ /* 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", AlphaTru64::nxm_thread_blockFunc),
+ /* 40 */ SyscallDesc("nxm_thread_wakeup", unimplementedFunc),
+ /* 41 */ SyscallDesc("init_process", unimplementedFunc),
+ /* 42 */ SyscallDesc("nxm_get_binding", unimplementedFunc),
+ /* 43 */ SyscallDesc("map_fd", unimplementedFunc),
+ /* 44 */ SyscallDesc("nxm_resched", unimplementedFunc),
+ /* 45 */ SyscallDesc("nxm_set_cancel", unimplementedFunc),
+ /* 46 */ SyscallDesc("nxm_set_binding", unimplementedFunc),
+ /* 47 */ SyscallDesc("stack_create", AlphaTru64::stack_createFunc),
+ /* 48 */ SyscallDesc("nxm_get_state", unimplementedFunc),
+ /* 49 */ SyscallDesc("nxm_thread_suspend", unimplementedFunc),
+ /* 50 */ SyscallDesc("nxm_thread_resume", unimplementedFunc),
+ /* 51 */ SyscallDesc("nxm_signal_check", unimplementedFunc),
+ /* 52 */ SyscallDesc("htg_unix_syscall", unimplementedFunc),
+ /* 53 */ SyscallDesc("kern_invalid", unimplementedFunc),
+ /* 54 */ SyscallDesc("kern_invalid", unimplementedFunc),
+ /* 55 */ SyscallDesc("host_self", unimplementedFunc),
+ /* 56 */ SyscallDesc("host_priv_self", unimplementedFunc),
+ /* 57 */ SyscallDesc("kern_invalid", unimplementedFunc),
+ /* 58 */ SyscallDesc("kern_invalid", unimplementedFunc),
+ /* 59 */ SyscallDesc("swtch_pri", AlphaTru64::swtch_priFunc),
+ /* 60 */ SyscallDesc("swtch", unimplementedFunc),
+ /* 61 */ SyscallDesc("thread_switch", unimplementedFunc),
+ /* 62 */ SyscallDesc("semop_fast", unimplementedFunc),
+ /* 63 */ SyscallDesc("nxm_pshared_init", unimplementedFunc),
+ /* 64 */ SyscallDesc("nxm_pshared_block", unimplementedFunc),
+ /* 65 */ SyscallDesc("nxm_pshared_unblock", unimplementedFunc),
+ /* 66 */ SyscallDesc("nxm_pshared_destroy", unimplementedFunc),
+ /* 67 */ SyscallDesc("nxm_swtch_pri", AlphaTru64::swtch_priFunc),
+ /* 68 */ SyscallDesc("lw_syscall", unimplementedFunc),
+ /* 69 */ SyscallDesc("kern_invalid", unimplementedFunc),
+ /* 70 */ SyscallDesc("mach_sctimes_0", unimplementedFunc),
+ /* 71 */ SyscallDesc("mach_sctimes_1", unimplementedFunc),
+ /* 72 */ SyscallDesc("mach_sctimes_2", unimplementedFunc),
+ /* 73 */ SyscallDesc("mach_sctimes_3", unimplementedFunc),
+ /* 74 */ SyscallDesc("mach_sctimes_4", unimplementedFunc),
+ /* 75 */ SyscallDesc("mach_sctimes_5", unimplementedFunc),
+ /* 76 */ SyscallDesc("mach_sctimes_6", unimplementedFunc),
+ /* 77 */ SyscallDesc("mach_sctimes_7", unimplementedFunc),
+ /* 78 */ SyscallDesc("mach_sctimes_8", unimplementedFunc),
+ /* 79 */ SyscallDesc("mach_sctimes_9", unimplementedFunc),
+ /* 80 */ SyscallDesc("mach_sctimes_10", unimplementedFunc),
+ /* 81 */ SyscallDesc("mach_sctimes_11", unimplementedFunc),
+ /* 82 */ SyscallDesc("mach_sctimes_port_alloc_dealloc", unimplementedFunc)
+};
+
+SyscallDesc*
+AlphaTru64Process::getDesc(int callnum)
+{
+ if (callnum < -Num_Mach_Syscall_Descs || callnum > Num_Syscall_Descs)
+ return NULL;
+
+ if (callnum < 0)
+ return &machSyscallDescs[-callnum];
+ else
+ return &syscallDescs[callnum];
+}
+
+
+AlphaTru64Process::AlphaTru64Process(const std::string &name,
+ ObjectFile *objFile,
+ System *system,
+ int stdin_fd,
+ int stdout_fd,
+ int stderr_fd,
+ std::vector<std::string> &argv,
+ std::vector<std::string> &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/src/arch/alpha/tru64/process.hh b/src/arch/alpha/tru64/process.hh
new file mode 100644
index 000000000..1cde4cac0
--- /dev/null
+++ b/src/arch/alpha/tru64/process.hh
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2003-2004 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __ALPHA_TRU64_PROCESS_HH__
+#define __ALPHA_TRU64_PROCESS_HH__
+
+#include "arch/alpha/process.hh"
+
+namespace AlphaISA {
+/// A process with emulated Alpha Tru64 syscalls.
+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);
+
+ /// Array of syscall descriptors, indexed by call number.
+ static SyscallDesc syscallDescs[];
+
+ /// Array of mach syscall descriptors, indexed by call number.
+ static SyscallDesc machSyscallDescs[];
+
+ const int Num_Syscall_Descs;
+ const int Num_Mach_Syscall_Descs;
+
+ virtual SyscallDesc* getDesc(int callnum);
+};
+
+} // namespace AlphaISA
+
+#endif // __ALPHA_TRU64_PROCESS_HH__
diff --git a/src/arch/alpha/tru64/system.cc b/src/arch/alpha/tru64/system.cc
new file mode 100644
index 000000000..2ad06d679
--- /dev/null
+++ b/src/arch/alpha/tru64/system.cc
@@ -0,0 +1,151 @@
+/*
+ * 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/system.hh"
+#include "arch/isa_traits.hh"
+#include "arch/vtophys.hh"
+#include "base/loader/symtab.hh"
+#include "base/trace.hh"
+#include "cpu/base.hh"
+#include "cpu/exec_context.hh"
+#include "kern/tru64/tru64_events.hh"
+#include "kern/system_events.hh"
+#include "mem/physical.hh"
+#include "mem/port.hh"
+#include "sim/builder.hh"
+
+using namespace std;
+
+Tru64AlphaSystem::Tru64AlphaSystem(Tru64AlphaSystem::Params *p)
+ : AlphaSystem(p)
+{
+ Addr addr = 0;
+ if (kernelSymtab->findAddress("enable_async_printf", addr)) {
+ virtPort.write(addr, (uint32_t)0);
+ }
+
+#ifdef DEBUG
+ kernelPanicEvent = addKernelFuncEvent<BreakPCEvent>("panic");
+ if (!kernelPanicEvent)
+ panic("could not find kernel symbol \'panic\'");
+#endif
+
+ badaddrEvent = addKernelFuncEvent<BadAddrEvent>("badaddr");
+ if (!badaddrEvent)
+ panic("could not find kernel symbol \'badaddr\'");
+
+ skipPowerStateEvent =
+ addKernelFuncEvent<SkipFuncEvent>("tl_v48_capture_power_state");
+ skipScavengeBootEvent =
+ addKernelFuncEvent<SkipFuncEvent>("pmap_scavenge_boot");
+
+#if TRACING_ON
+ printfEvent = addKernelFuncEvent<PrintfEvent>("printf");
+ debugPrintfEvent = addKernelFuncEvent<DebugPrintfEvent>("m5printf");
+ debugPrintfrEvent = addKernelFuncEvent<DebugPrintfrEvent>("m5printfr");
+ dumpMbufEvent = addKernelFuncEvent<DumpMbufEvent>("m5_dump_mbuf");
+#endif
+}
+
+Tru64AlphaSystem::~Tru64AlphaSystem()
+{
+#ifdef DEBUG
+ delete kernelPanicEvent;
+#endif
+ delete badaddrEvent;
+ delete skipPowerStateEvent;
+ delete skipScavengeBootEvent;
+#if TRACING_ON
+ delete printfEvent;
+ delete debugPrintfEvent;
+ delete debugPrintfrEvent;
+ delete dumpMbufEvent;
+#endif
+}
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(Tru64AlphaSystem)
+
+ Param<Tick> boot_cpu_frequency;
+ SimObjectParam<PhysicalMemory *> physmem;
+
+ Param<string> kernel;
+ Param<string> console;
+ Param<string> pal;
+
+ Param<string> boot_osflags;
+ Param<string> readfile;
+ Param<unsigned int> init_param;
+
+ Param<uint64_t> system_type;
+ Param<uint64_t> system_rev;
+
+ Param<bool> bin;
+ VectorParam<string> binned_fns;
+
+END_DECLARE_SIM_OBJECT_PARAMS(Tru64AlphaSystem)
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(Tru64AlphaSystem)
+
+ 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(console, "file that contains the console code"),
+ INIT_PARAM(pal, "file that contains palcode"),
+ INIT_PARAM_DFLT(boot_osflags, "flags to pass to the kernel during boot",
+ "a"),
+ INIT_PARAM_DFLT(readfile, "file to read startup script from", ""),
+ INIT_PARAM_DFLT(init_param, "numerical value to pass into simulator", 0),
+ INIT_PARAM_DFLT(system_type, "Type of system we are emulating", 12),
+ INIT_PARAM_DFLT(system_rev, "Revision of system we are emulating", 2<<1),
+ INIT_PARAM_DFLT(bin, "is this system to be binned", false),
+ INIT_PARAM(binned_fns, "functions to be broken down and binned")
+
+END_INIT_SIM_OBJECT_PARAMS(Tru64AlphaSystem)
+
+CREATE_SIM_OBJECT(Tru64AlphaSystem)
+{
+ AlphaSystem::Params *p = new AlphaSystem::Params;
+ p->name = getInstanceName();
+ p->boot_cpu_frequency = boot_cpu_frequency;
+ p->physmem = physmem;
+ p->kernel_path = kernel;
+ p->console_path = console;
+ p->palcode = pal;
+ p->boot_osflags = boot_osflags;
+ p->init_param = init_param;
+ p->readfile = readfile;
+ p->system_type = system_type;
+ p->system_rev = system_rev;
+ p->bin = bin;
+ p->binned_fns = binned_fns;
+ p->bin_int = false;
+
+ return new Tru64AlphaSystem(p);
+}
+
+REGISTER_SIM_OBJECT("Tru64AlphaSystem", Tru64AlphaSystem)
diff --git a/arch/alpha/tru64/system.hh b/src/arch/alpha/tru64/system.hh
index 0e0cc1bc8..0e0cc1bc8 100644
--- a/arch/alpha/tru64/system.hh
+++ b/src/arch/alpha/tru64/system.hh
diff --git a/src/arch/alpha/tru64/tru64.cc b/src/arch/alpha/tru64/tru64.cc
new file mode 100644
index 000000000..4a3e653c1
--- /dev/null
+++ b/src/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/src/arch/alpha/tru64/tru64.hh b/src/arch/alpha/tru64/tru64.hh
new file mode 100644
index 000000000..19343ba23
--- /dev/null
+++ b/src/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/src/arch/alpha/types.hh b/src/arch/alpha/types.hh
new file mode 100644
index 000000000..d4cb482d8
--- /dev/null
+++ b/src/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/src/arch/alpha/utility.hh b/src/arch/alpha/utility.hh
new file mode 100644
index 000000000..6cc916307
--- /dev/null
+++ b/src/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/src/arch/alpha/vtophys.cc b/src/arch/alpha/vtophys.cc
new file mode 100644
index 000000000..41e9b80a3
--- /dev/null
+++ b/src/arch/alpha/vtophys.cc
@@ -0,0 +1,162 @@
+/*
+ * 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 <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/vport.hh"
+
+using namespace std;
+using namespace AlphaISA;
+
+AlphaISA::PageTableEntry
+AlphaISA::kernel_pte_lookup(FunctionalPort *mem, Addr ptbr, AlphaISA::VAddr vaddr)
+{
+ Addr level1_pte = ptbr + vaddr.level1();
+ 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 = 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 = mem->read<uint64_t>(level3_pte);
+ if (!level3.valid()) {
+ DPRINTF(VtoPhys, "level 3 PTE not valid, va = %#x\n", vaddr);
+ return 0;
+ }
+ return level3;
+}
+
+Addr
+AlphaISA::vtophys(Addr vaddr)
+{
+ Addr paddr = 0;
+ if (AlphaISA::IsUSeg(vaddr))
+ DPRINTF(VtoPhys, "vtophys: invalid vaddr %#x", vaddr);
+ else if (AlphaISA::IsK0Seg(vaddr))
+ paddr = AlphaISA::K0Seg2Phys(vaddr);
+ else
+ panic("vtophys: ptbr is not set on virtual lookup");
+
+ DPRINTF(VtoPhys, "vtophys(%#x) -> %#x\n", vaddr, paddr);
+
+ return paddr;
+}
+
+Addr
+AlphaISA::vtophys(ExecContext *xc, Addr addr)
+{
+ AlphaISA::VAddr vaddr = addr;
+ Addr ptbr = xc->readMiscReg(AlphaISA::IPR_PALtemp20);
+ Addr paddr = 0;
+ //@todo Andrew couldn't remember why he commented some of this code
+ //so I put it back in. Perhaps something to do with gdb debugging?
+ if (AlphaISA::PcPAL(vaddr) && (vaddr < EV5::PalMax)) {
+ paddr = vaddr & ~ULL(1);
+ } else {
+ if (AlphaISA::IsK0Seg(vaddr)) {
+ paddr = AlphaISA::K0Seg2Phys(vaddr);
+ } else if (!ptbr) {
+ paddr = vaddr;
+ } else {
+ AlphaISA::PageTableEntry pte =
+ kernel_pte_lookup(xc->getPhysPort(), ptbr, vaddr);
+ if (pte.valid())
+ paddr = pte.paddr() | vaddr.offset();
+ }
+ }
+
+
+ DPRINTF(VtoPhys, "vtophys(%#x) -> %#x\n", vaddr, paddr);
+
+ return paddr;
+}
+
+
+void
+AlphaISA::CopyOut(ExecContext *xc, void *dest, Addr src, size_t cplen)
+{
+ uint8_t *dst = (uint8_t *)dest;
+ VirtualPort *vp = xc->getVirtPort(xc);
+
+ vp->readBlob(src, dst, cplen);
+
+ xc->delVirtPort(vp);
+
+}
+
+void
+AlphaISA::CopyIn(ExecContext *xc, Addr dest, void *source, size_t cplen)
+{
+ uint8_t *src = (uint8_t *)source;
+ VirtualPort *vp = xc->getVirtPort(xc);
+
+ vp->writeBlob(dest, src, cplen);
+
+ xc->delVirtPort(vp);
+}
+
+void
+AlphaISA::CopyStringOut(ExecContext *xc, char *dst, Addr vaddr, size_t maxlen)
+{
+ int len = 0;
+ VirtualPort *vp = xc->getVirtPort(xc);
+
+ do {
+ vp->readBlob(vaddr++, (uint8_t*)dst++, 1);
+ len++;
+ } while (len < maxlen && dst[len] != 0 );
+
+ xc->delVirtPort(vp);
+ dst[len] = 0;
+}
+
+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();
+ }
+ xc->delVirtPort(vp);
+}
diff --git a/src/arch/alpha/vtophys.hh b/src/arch/alpha/vtophys.hh
new file mode 100644
index 000000000..7ab14bc5b
--- /dev/null
+++ b/src/arch/alpha/vtophys.hh
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2002-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __ARCH_ALPHA_VTOPHYS_H__
+#define __ARCH_ALPHA_VTOPHYS_H__
+
+#include "arch/alpha/isa_traits.hh"
+
+class ExecContext;
+class FunctionalPort;
+
+namespace AlphaISA {
+
+PageTableEntry
+kernel_pte_lookup(FunctionalPort *mem, Addr ptbr, AlphaISA::VAddr vaddr);
+
+Addr vtophys(Addr vaddr);
+Addr vtophys(ExecContext *xc, Addr vaddr);
+
+void CopyOut(ExecContext *xc, void *dst, Addr src, size_t len);
+void CopyIn(ExecContext *xc, Addr dst, void *src, size_t len);
+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/src/arch/isa_parser.py b/src/arch/isa_parser.py
new file mode 100755
index 000000000..c0758da50
--- /dev/null
+++ b/src/arch/isa_parser.py
@@ -0,0 +1,1810 @@
+# 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.
+
+import os
+import sys
+import re
+import string
+import traceback
+# get type names
+from types import *
+
+# Prepend the directory where the PLY lex & yacc modules are found
+# to the search path. Assumes we're compiling in a subdirectory
+# of 'build' in the current tree.
+sys.path[0:0] = [os.environ['M5_PLY']]
+
+import lex
+import yacc
+
+#####################################################################
+#
+# Lexer
+#
+# The PLY lexer module takes two things as input:
+# - A list of token names (the string list 'tokens')
+# - A regular expression describing a match for each token. The
+# regexp for token FOO can be provided in two ways:
+# - as a string variable named t_FOO
+# - as the doc string for a function named t_FOO. In this case,
+# the function is also executed, allowing an action to be
+# associated with each token match.
+#
+#####################################################################
+
+# Reserved words. These are listed separately as they are matched
+# using the same regexp as generic IDs, but distinguished in the
+# t_ID() function. The PLY documentation suggests this approach.
+reserved = (
+ 'BITFIELD', 'DECODE', 'DECODER', 'DEFAULT', 'DEF', 'EXEC', 'FORMAT',
+ 'HEADER', 'LET', 'NAMESPACE', 'OPERAND_TYPES', 'OPERANDS',
+ 'OUTPUT', 'SIGNED', 'TEMPLATE'
+ )
+
+# List of tokens. The lex module requires this.
+tokens = reserved + (
+ # identifier
+ 'ID',
+
+ # integer literal
+ 'INTLIT',
+
+ # string literal
+ 'STRLIT',
+
+ # code literal
+ 'CODELIT',
+
+ # ( ) [ ] { } < > , ; : :: *
+ 'LPAREN', 'RPAREN',
+ 'LBRACKET', 'RBRACKET',
+ 'LBRACE', 'RBRACE',
+ 'LESS', 'GREATER', 'EQUALS',
+ 'COMMA', 'SEMI', 'COLON', 'DBLCOLON',
+ 'ASTERISK',
+
+ # C preprocessor directives
+ 'CPPDIRECTIVE'
+
+# The following are matched but never returned. commented out to
+# suppress PLY warning
+ # newfile directive
+# 'NEWFILE',
+
+ # endfile directive
+# 'ENDFILE'
+)
+
+# Regular expressions for token matching
+t_LPAREN = r'\('
+t_RPAREN = r'\)'
+t_LBRACKET = r'\['
+t_RBRACKET = r'\]'
+t_LBRACE = r'\{'
+t_RBRACE = r'\}'
+t_LESS = r'\<'
+t_GREATER = r'\>'
+t_EQUALS = r'='
+t_COMMA = r','
+t_SEMI = r';'
+t_COLON = r':'
+t_DBLCOLON = r'::'
+t_ASTERISK = r'\*'
+
+# Identifiers and reserved words
+reserved_map = { }
+for r in reserved:
+ reserved_map[r.lower()] = r
+
+def t_ID(t):
+ r'[A-Za-z_]\w*'
+ t.type = reserved_map.get(t.value,'ID')
+ return t
+
+# Integer literal
+def t_INTLIT(t):
+ r'(0x[\da-fA-F]+)|\d+'
+ try:
+ t.value = int(t.value,0)
+ except ValueError:
+ error(t.lineno, 'Integer value "%s" too large' % t.value)
+ t.value = 0
+ return t
+
+# String literal. Note that these use only single quotes, and
+# can span multiple lines.
+def t_STRLIT(t):
+ r"(?m)'([^'])+'"
+ # strip off quotes
+ t.value = t.value[1:-1]
+ t.lineno += t.value.count('\n')
+ return t
+
+
+# "Code literal"... like a string literal, but delimiters are
+# '{{' and '}}' so they get formatted nicely under emacs c-mode
+def t_CODELIT(t):
+ r"(?m)\{\{([^\}]|}(?!\}))+\}\}"
+ # strip off {{ & }}
+ t.value = t.value[2:-2]
+ t.lineno += t.value.count('\n')
+ return t
+
+def t_CPPDIRECTIVE(t):
+ r'^\#[^\#].*\n'
+ t.lineno += t.value.count('\n')
+ return t
+
+def t_NEWFILE(t):
+ r'^\#\#newfile\s+"[\w/.-]*"'
+ fileNameStack.push((t.value[11:-1], t.lineno))
+ t.lineno = 0
+
+def t_ENDFILE(t):
+ r'^\#\#endfile'
+ (old_filename, t.lineno) = fileNameStack.pop()
+
+#
+# The functions t_NEWLINE, t_ignore, and t_error are
+# special for the lex module.
+#
+
+# Newlines
+def t_NEWLINE(t):
+ r'\n+'
+ t.lineno += t.value.count('\n')
+
+# Comments
+def t_comment(t):
+ r'//.*'
+
+# Completely ignored characters
+t_ignore = ' \t\x0c'
+
+# Error handler
+def t_error(t):
+ error(t.lineno, "illegal character '%s'" % t.value[0])
+ t.skip(1)
+
+# Build the lexer
+lex.lex()
+
+#####################################################################
+#
+# Parser
+#
+# Every function whose name starts with 'p_' defines a grammar rule.
+# The rule is encoded in the function's doc string, while the
+# function body provides the action taken when the rule is matched.
+# The argument to each function is a list of the values of the
+# rule's symbols: t[0] for the LHS, and t[1..n] for the symbols
+# on the RHS. For tokens, the value is copied from the t.value
+# attribute provided by the lexer. For non-terminals, the value
+# is assigned by the producing rule; i.e., the job of the grammar
+# rule function is to set the value for the non-terminal on the LHS
+# (by assigning to t[0]).
+#####################################################################
+
+# The LHS of the first grammar rule is used as the start symbol
+# (in this case, 'specification'). Note that this rule enforces
+# that there will be exactly one namespace declaration, with 0 or more
+# global defs/decls before and after it. The defs & decls before
+# the namespace decl will be outside the namespace; those after
+# will be inside. The decoder function is always inside the namespace.
+def p_specification(t):
+ 'specification : opt_defs_and_outputs name_decl opt_defs_and_outputs decode_block'
+ global_code = t[1]
+ isa_name = t[2]
+ namespace = isa_name + "Inst"
+ # wrap the decode block as a function definition
+ t[4].wrap_decode_block('''
+StaticInstPtr
+%(isa_name)s::decodeInst(%(isa_name)s::ExtMachInst machInst)
+{
+ using namespace %(namespace)s;
+''' % vars(), '}')
+ # both the latter output blocks and the decode block are in the namespace
+ namespace_code = t[3] + t[4]
+ # pass it all back to the caller of yacc.parse()
+ t[0] = (isa_name, namespace, global_code, namespace_code)
+
+# ISA name declaration looks like "namespace <foo>;"
+def p_name_decl(t):
+ 'name_decl : NAMESPACE ID SEMI'
+ t[0] = t[2]
+
+# 'opt_defs_and_outputs' is a possibly empty sequence of
+# def and/or output statements.
+def p_opt_defs_and_outputs_0(t):
+ 'opt_defs_and_outputs : empty'
+ t[0] = GenCode()
+
+def p_opt_defs_and_outputs_1(t):
+ 'opt_defs_and_outputs : defs_and_outputs'
+ t[0] = t[1]
+
+def p_defs_and_outputs_0(t):
+ 'defs_and_outputs : def_or_output'
+ t[0] = t[1]
+
+def p_defs_and_outputs_1(t):
+ 'defs_and_outputs : defs_and_outputs def_or_output'
+ t[0] = t[1] + t[2]
+
+# The list of possible definition/output statements.
+def p_def_or_output(t):
+ '''def_or_output : def_format
+ | def_bitfield
+ | def_template
+ | def_operand_types
+ | def_operands
+ | output_header
+ | output_decoder
+ | output_exec
+ | global_let'''
+ t[0] = t[1]
+
+# Output blocks 'output <foo> {{...}}' (C++ code blocks) are copied
+# directly to the appropriate output section.
+
+
+# Protect any non-dict-substitution '%'s in a format string
+# (i.e. those not followed by '(')
+def protect_non_subst_percents(s):
+ return re.sub(r'%(?!\()', '%%', s)
+
+# Massage output block by substituting in template definitions and bit
+# operators. We handle '%'s embedded in the string that don't
+# indicate template substitutions (or CPU-specific symbols, which get
+# handled in GenCode) by doubling them first so that the format
+# operation will reduce them back to single '%'s.
+def process_output(s):
+ s = protect_non_subst_percents(s)
+ # protects cpu-specific symbols too
+ s = protect_cpu_symbols(s)
+ return substBitOps(s % templateMap)
+
+def p_output_header(t):
+ 'output_header : OUTPUT HEADER CODELIT SEMI'
+ t[0] = GenCode(header_output = process_output(t[3]))
+
+def p_output_decoder(t):
+ 'output_decoder : OUTPUT DECODER CODELIT SEMI'
+ t[0] = GenCode(decoder_output = process_output(t[3]))
+
+def p_output_exec(t):
+ 'output_exec : OUTPUT EXEC CODELIT SEMI'
+ t[0] = GenCode(exec_output = process_output(t[3]))
+
+# global let blocks 'let {{...}}' (Python code blocks) are executed
+# directly when seen. Note that these execute in a special variable
+# context 'exportContext' to prevent the code from polluting this
+# script's namespace.
+def p_global_let(t):
+ 'global_let : LET CODELIT SEMI'
+ updateExportContext()
+ try:
+ exec fixPythonIndentation(t[2]) in exportContext
+ except Exception, exc:
+ error(t.lineno(1),
+ 'error: %s in global let block "%s".' % (exc, t[2]))
+ t[0] = GenCode() # contributes nothing to the output C++ file
+
+# Define the mapping from operand type extensions to C++ types and bit
+# widths (stored in operandTypeMap).
+def p_def_operand_types(t):
+ 'def_operand_types : DEF OPERAND_TYPES CODELIT SEMI'
+ try:
+ userDict = eval('{' + t[3] + '}')
+ except Exception, exc:
+ error(t.lineno(1),
+ 'error: %s in def operand_types block "%s".' % (exc, t[3]))
+ buildOperandTypeMap(userDict, t.lineno(1))
+ t[0] = GenCode() # contributes nothing to the output C++ file
+
+# Define the mapping from operand names to operand classes and other
+# traits. Stored in operandNameMap.
+def p_def_operands(t):
+ 'def_operands : DEF OPERANDS CODELIT SEMI'
+ if not globals().has_key('operandTypeMap'):
+ error(t.lineno(1),
+ 'error: operand types must be defined before operands')
+ try:
+ userDict = eval('{' + t[3] + '}')
+ except Exception, exc:
+ error(t.lineno(1),
+ 'error: %s in def operands block "%s".' % (exc, t[3]))
+ buildOperandNameMap(userDict, t.lineno(1))
+ t[0] = GenCode() # contributes nothing to the output C++ file
+
+# A bitfield definition looks like:
+# 'def [signed] bitfield <ID> [<first>:<last>]'
+# This generates a preprocessor macro in the output file.
+def p_def_bitfield_0(t):
+ 'def_bitfield : DEF opt_signed BITFIELD ID LESS INTLIT COLON INTLIT GREATER SEMI'
+ expr = 'bits(machInst, %2d, %2d)' % (t[6], t[8])
+ if (t[2] == 'signed'):
+ expr = 'sext<%d>(%s)' % (t[6] - t[8] + 1, expr)
+ hash_define = '#undef %s\n#define %s\t%s\n' % (t[4], t[4], expr)
+ t[0] = GenCode(header_output = hash_define)
+
+# alternate form for single bit: 'def [signed] bitfield <ID> [<bit>]'
+def p_def_bitfield_1(t):
+ 'def_bitfield : DEF opt_signed BITFIELD ID LESS INTLIT GREATER SEMI'
+ expr = 'bits(machInst, %2d, %2d)' % (t[6], t[6])
+ if (t[2] == 'signed'):
+ expr = 'sext<%d>(%s)' % (1, expr)
+ hash_define = '#undef %s\n#define %s\t%s\n' % (t[4], t[4], expr)
+ t[0] = GenCode(header_output = hash_define)
+
+def p_opt_signed_0(t):
+ 'opt_signed : SIGNED'
+ t[0] = t[1]
+
+def p_opt_signed_1(t):
+ 'opt_signed : empty'
+ t[0] = ''
+
+# Global map variable to hold templates
+templateMap = {}
+
+def p_def_template(t):
+ 'def_template : DEF TEMPLATE ID CODELIT SEMI'
+ templateMap[t[3]] = Template(t[4])
+ t[0] = GenCode()
+
+# An instruction format definition looks like
+# "def format <fmt>(<params>) {{...}};"
+def p_def_format(t):
+ 'def_format : DEF FORMAT ID LPAREN param_list RPAREN CODELIT SEMI'
+ (id, params, code) = (t[3], t[5], t[7])
+ defFormat(id, params, code, t.lineno(1))
+ t[0] = GenCode()
+
+# The formal parameter list for an instruction format is a possibly
+# empty list of comma-separated parameters. Positional (standard,
+# non-keyword) parameters must come first, followed by keyword
+# parameters, followed by a '*foo' parameter that gets excess
+# positional arguments (as in Python). Each of these three parameter
+# categories is optional.
+#
+# Note that we do not support the '**foo' parameter for collecting
+# otherwise undefined keyword args. Otherwise the parameter list is
+# (I believe) identical to what is supported in Python.
+#
+# The param list generates a tuple, where the first element is a list of
+# the positional params and the second element is a dict containing the
+# keyword params.
+def p_param_list_0(t):
+ 'param_list : positional_param_list COMMA nonpositional_param_list'
+ t[0] = t[1] + t[3]
+
+def p_param_list_1(t):
+ '''param_list : positional_param_list
+ | nonpositional_param_list'''
+ t[0] = t[1]
+
+def p_positional_param_list_0(t):
+ 'positional_param_list : empty'
+ t[0] = []
+
+def p_positional_param_list_1(t):
+ 'positional_param_list : ID'
+ t[0] = [t[1]]
+
+def p_positional_param_list_2(t):
+ 'positional_param_list : positional_param_list COMMA ID'
+ t[0] = t[1] + [t[3]]
+
+def p_nonpositional_param_list_0(t):
+ 'nonpositional_param_list : keyword_param_list COMMA excess_args_param'
+ t[0] = t[1] + t[3]
+
+def p_nonpositional_param_list_1(t):
+ '''nonpositional_param_list : keyword_param_list
+ | excess_args_param'''
+ t[0] = t[1]
+
+def p_keyword_param_list_0(t):
+ 'keyword_param_list : keyword_param'
+ t[0] = [t[1]]
+
+def p_keyword_param_list_1(t):
+ 'keyword_param_list : keyword_param_list COMMA keyword_param'
+ t[0] = t[1] + [t[3]]
+
+def p_keyword_param(t):
+ 'keyword_param : ID EQUALS expr'
+ t[0] = t[1] + ' = ' + t[3].__repr__()
+
+def p_excess_args_param(t):
+ 'excess_args_param : ASTERISK ID'
+ # Just concatenate them: '*ID'. Wrap in list to be consistent
+ # with positional_param_list and keyword_param_list.
+ t[0] = [t[1] + t[2]]
+
+# End of format definition-related rules.
+##############
+
+#
+# A decode block looks like:
+# decode <field1> [, <field2>]* [default <inst>] { ... }
+#
+def p_decode_block(t):
+ 'decode_block : DECODE ID opt_default LBRACE decode_stmt_list RBRACE'
+ default_defaults = defaultStack.pop()
+ codeObj = t[5]
+ # use the "default defaults" only if there was no explicit
+ # default statement in decode_stmt_list
+ if not codeObj.has_decode_default:
+ codeObj += default_defaults
+ codeObj.wrap_decode_block('switch (%s) {\n' % t[2], '}\n')
+ t[0] = codeObj
+
+# The opt_default statement serves only to push the "default defaults"
+# onto defaultStack. This value will be used by nested decode blocks,
+# and used and popped off when the current decode_block is processed
+# (in p_decode_block() above).
+def p_opt_default_0(t):
+ 'opt_default : empty'
+ # no default specified: reuse the one currently at the top of the stack
+ defaultStack.push(defaultStack.top())
+ # no meaningful value returned
+ t[0] = None
+
+def p_opt_default_1(t):
+ 'opt_default : DEFAULT inst'
+ # push the new default
+ codeObj = t[2]
+ codeObj.wrap_decode_block('\ndefault:\n', 'break;\n')
+ defaultStack.push(codeObj)
+ # no meaningful value returned
+ t[0] = None
+
+def p_decode_stmt_list_0(t):
+ 'decode_stmt_list : decode_stmt'
+ t[0] = t[1]
+
+def p_decode_stmt_list_1(t):
+ 'decode_stmt_list : decode_stmt decode_stmt_list'
+ if (t[1].has_decode_default and t[2].has_decode_default):
+ error(t.lineno(1), 'Two default cases in decode block')
+ t[0] = t[1] + t[2]
+
+#
+# Decode statement rules
+#
+# There are four types of statements allowed in a decode block:
+# 1. Format blocks 'format <foo> { ... }'
+# 2. Nested decode blocks
+# 3. Instruction definitions.
+# 4. C preprocessor directives.
+
+
+# Preprocessor directives found in a decode statement list are passed
+# through to the output, replicated to all of the output code
+# streams. This works well for ifdefs, so we can ifdef out both the
+# declarations and the decode cases generated by an instruction
+# definition. Handling them as part of the grammar makes it easy to
+# keep them in the right place with respect to the code generated by
+# the other statements.
+def p_decode_stmt_cpp(t):
+ 'decode_stmt : CPPDIRECTIVE'
+ t[0] = GenCode(t[1], t[1], t[1], t[1])
+
+# A format block 'format <foo> { ... }' sets the default instruction
+# format used to handle instruction definitions inside the block.
+# This format can be overridden by using an explicit format on the
+# instruction definition or with a nested format block.
+def p_decode_stmt_format(t):
+ 'decode_stmt : FORMAT push_format_id LBRACE decode_stmt_list RBRACE'
+ # The format will be pushed on the stack when 'push_format_id' is
+ # processed (see below). Once the parser has recognized the full
+ # production (though the right brace), we're done with the format,
+ # so now we can pop it.
+ formatStack.pop()
+ t[0] = t[4]
+
+# This rule exists so we can set the current format (& push the stack)
+# when we recognize the format name part of the format block.
+def p_push_format_id(t):
+ 'push_format_id : ID'
+ try:
+ formatStack.push(formatMap[t[1]])
+ t[0] = ('', '// format %s' % t[1])
+ except KeyError:
+ error(t.lineno(1), 'instruction format "%s" not defined.' % t[1])
+
+# Nested decode block: if the value of the current field matches the
+# specified constant, do a nested decode on some other field.
+def p_decode_stmt_decode(t):
+ 'decode_stmt : case_label COLON decode_block'
+ label = t[1]
+ codeObj = t[3]
+ # just wrap the decoding code from the block as a case in the
+ # outer switch statement.
+ codeObj.wrap_decode_block('\n%s:\n' % label)
+ codeObj.has_decode_default = (label == 'default')
+ t[0] = codeObj
+
+# Instruction definition (finally!).
+def p_decode_stmt_inst(t):
+ 'decode_stmt : case_label COLON inst SEMI'
+ label = t[1]
+ codeObj = t[3]
+ codeObj.wrap_decode_block('\n%s:' % label, 'break;\n')
+ codeObj.has_decode_default = (label == 'default')
+ t[0] = codeObj
+
+# The case label is either a list of one or more constants or 'default'
+def p_case_label_0(t):
+ 'case_label : intlit_list'
+ t[0] = ': '.join(map(lambda a: 'case %#x' % a, t[1]))
+
+def p_case_label_1(t):
+ 'case_label : DEFAULT'
+ t[0] = 'default'
+
+#
+# The constant list for a decode case label must be non-empty, but may have
+# one or more comma-separated integer literals in it.
+#
+def p_intlit_list_0(t):
+ 'intlit_list : INTLIT'
+ t[0] = [t[1]]
+
+def p_intlit_list_1(t):
+ 'intlit_list : intlit_list COMMA INTLIT'
+ t[0] = t[1]
+ t[0].append(t[3])
+
+# Define an instruction using the current instruction format (specified
+# by an enclosing format block).
+# "<mnemonic>(<args>)"
+def p_inst_0(t):
+ 'inst : ID LPAREN arg_list RPAREN'
+ # Pass the ID and arg list to the current format class to deal with.
+ currentFormat = formatStack.top()
+ codeObj = currentFormat.defineInst(t[1], t[3], t.lineno(1))
+ args = ','.join(map(str, t[3]))
+ args = re.sub('(?m)^', '//', args)
+ args = re.sub('^//', '', args)
+ comment = '\n// %s::%s(%s)\n' % (currentFormat.id, t[1], args)
+ codeObj.prepend_all(comment)
+ t[0] = codeObj
+
+# Define an instruction using an explicitly specified format:
+# "<fmt>::<mnemonic>(<args>)"
+def p_inst_1(t):
+ 'inst : ID DBLCOLON ID LPAREN arg_list RPAREN'
+ try:
+ format = formatMap[t[1]]
+ except KeyError:
+ error(t.lineno(1), 'instruction format "%s" not defined.' % t[1])
+ codeObj = format.defineInst(t[3], t[5], t.lineno(1))
+ comment = '\n// %s::%s(%s)\n' % (t[1], t[3], t[5])
+ codeObj.prepend_all(comment)
+ t[0] = codeObj
+
+# The arg list generates a tuple, where the first element is a list of
+# the positional args and the second element is a dict containing the
+# keyword args.
+def p_arg_list_0(t):
+ 'arg_list : positional_arg_list COMMA keyword_arg_list'
+ t[0] = ( t[1], t[3] )
+
+def p_arg_list_1(t):
+ 'arg_list : positional_arg_list'
+ t[0] = ( t[1], {} )
+
+def p_arg_list_2(t):
+ 'arg_list : keyword_arg_list'
+ t[0] = ( [], t[1] )
+
+def p_positional_arg_list_0(t):
+ 'positional_arg_list : empty'
+ t[0] = []
+
+def p_positional_arg_list_1(t):
+ 'positional_arg_list : expr'
+ t[0] = [t[1]]
+
+def p_positional_arg_list_2(t):
+ 'positional_arg_list : positional_arg_list COMMA expr'
+ t[0] = t[1] + [t[3]]
+
+def p_keyword_arg_list_0(t):
+ 'keyword_arg_list : keyword_arg'
+ t[0] = t[1]
+
+def p_keyword_arg_list_1(t):
+ 'keyword_arg_list : keyword_arg_list COMMA keyword_arg'
+ t[0] = t[1]
+ t[0].update(t[3])
+
+def p_keyword_arg(t):
+ 'keyword_arg : ID EQUALS expr'
+ t[0] = { t[1] : t[3] }
+
+#
+# Basic expressions. These constitute the argument values of
+# "function calls" (i.e. instruction definitions in the decode block)
+# and default values for formal parameters of format functions.
+#
+# Right now, these are either strings, integers, or (recursively)
+# lists of exprs (using Python square-bracket list syntax). Note that
+# bare identifiers are trated as string constants here (since there
+# isn't really a variable namespace to refer to).
+#
+def p_expr_0(t):
+ '''expr : ID
+ | INTLIT
+ | STRLIT
+ | CODELIT'''
+ t[0] = t[1]
+
+def p_expr_1(t):
+ '''expr : LBRACKET list_expr RBRACKET'''
+ t[0] = t[2]
+
+def p_list_expr_0(t):
+ 'list_expr : expr'
+ t[0] = [t[1]]
+
+def p_list_expr_1(t):
+ 'list_expr : list_expr COMMA expr'
+ t[0] = t[1] + [t[3]]
+
+def p_list_expr_2(t):
+ 'list_expr : empty'
+ t[0] = []
+
+#
+# Empty production... use in other rules for readability.
+#
+def p_empty(t):
+ 'empty :'
+ pass
+
+# Parse error handler. Note that the argument here is the offending
+# *token*, not a grammar symbol (hence the need to use t.value)
+def p_error(t):
+ if t:
+ error(t.lineno, "syntax error at '%s'" % t.value)
+ else:
+ error(0, "unknown syntax error", True)
+
+# END OF GRAMMAR RULES
+#
+# Now build the parser.
+yacc.yacc()
+
+
+#####################################################################
+#
+# Support Classes
+#
+#####################################################################
+
+# Expand template with CPU-specific references into a dictionary with
+# an entry for each CPU model name. The entry key is the model name
+# and the corresponding value is the template with the CPU-specific
+# refs substituted for that model.
+def expand_cpu_symbols_to_dict(template):
+ # Protect '%'s that don't go with CPU-specific terms
+ t = re.sub(r'%(?!\(CPU_)', '%%', template)
+ result = {}
+ for cpu in cpu_models:
+ result[cpu.name] = t % cpu.strings
+ return result
+
+# *If* the template has CPU-specific references, return a single
+# string containing a copy of the template for each CPU model with the
+# corresponding values substituted in. If the template has no
+# CPU-specific references, it is returned unmodified.
+def expand_cpu_symbols_to_string(template):
+ if template.find('%(CPU_') != -1:
+ return reduce(lambda x,y: x+y,
+ expand_cpu_symbols_to_dict(template).values())
+ else:
+ return template
+
+# Protect CPU-specific references by doubling the corresponding '%'s
+# (in preparation for substituting a different set of references into
+# the template).
+def protect_cpu_symbols(template):
+ return re.sub(r'%(?=\(CPU_)', '%%', template)
+
+###############
+# GenCode class
+#
+# The GenCode class encapsulates generated code destined for various
+# output files. The header_output and decoder_output attributes are
+# strings containing code destined for decoder.hh and decoder.cc
+# respectively. The decode_block attribute contains code to be
+# incorporated in the decode function itself (that will also end up in
+# decoder.cc). The exec_output attribute is a dictionary with a key
+# for each CPU model name; the value associated with a particular key
+# is the string of code for that CPU model's exec.cc file. The
+# has_decode_default attribute is used in the decode block to allow
+# explicit default clauses to override default default clauses.
+
+class GenCode:
+ # Constructor. At this point we substitute out all CPU-specific
+ # symbols. For the exec output, these go into the per-model
+ # dictionary. For all other output types they get collapsed into
+ # a single string.
+ def __init__(self,
+ header_output = '', decoder_output = '', exec_output = '',
+ decode_block = '', has_decode_default = False):
+ self.header_output = expand_cpu_symbols_to_string(header_output)
+ self.decoder_output = expand_cpu_symbols_to_string(decoder_output)
+ if isinstance(exec_output, dict):
+ self.exec_output = exec_output
+ elif isinstance(exec_output, str):
+ # If the exec_output arg is a single string, we replicate
+ # it for each of the CPU models, substituting and
+ # %(CPU_foo)s params appropriately.
+ self.exec_output = expand_cpu_symbols_to_dict(exec_output)
+ self.decode_block = expand_cpu_symbols_to_string(decode_block)
+ self.has_decode_default = has_decode_default
+
+ # Override '+' operator: generate a new GenCode object that
+ # concatenates all the individual strings in the operands.
+ def __add__(self, other):
+ exec_output = {}
+ for cpu in cpu_models:
+ n = cpu.name
+ exec_output[n] = self.exec_output[n] + other.exec_output[n]
+ return GenCode(self.header_output + other.header_output,
+ self.decoder_output + other.decoder_output,
+ exec_output,
+ self.decode_block + other.decode_block,
+ self.has_decode_default or other.has_decode_default)
+
+ # Prepend a string (typically a comment) to all the strings.
+ def prepend_all(self, pre):
+ self.header_output = pre + self.header_output
+ self.decoder_output = pre + self.decoder_output
+ self.decode_block = pre + self.decode_block
+ for cpu in cpu_models:
+ self.exec_output[cpu.name] = pre + self.exec_output[cpu.name]
+
+ # Wrap the decode block in a pair of strings (e.g., 'case foo:'
+ # and 'break;'). Used to build the big nested switch statement.
+ def wrap_decode_block(self, pre, post = ''):
+ self.decode_block = pre + indent(self.decode_block) + post
+
+################
+# Format object.
+#
+# A format object encapsulates an instruction format. It must provide
+# a defineInst() method that generates the code for an instruction
+# definition.
+
+exportContextSymbols = ('InstObjParams', 'CodeBlock',
+ 'makeList', 're', 'string')
+
+exportContext = {}
+
+def updateExportContext():
+ exportContext.update(exportDict(*exportContextSymbols))
+ exportContext.update(templateMap)
+
+def exportDict(*symNames):
+ return dict([(s, eval(s)) for s in symNames])
+
+
+class Format:
+ def __init__(self, id, params, code):
+ # constructor: just save away arguments
+ self.id = id
+ self.params = params
+ label = 'def format ' + id
+ self.user_code = compile(fixPythonIndentation(code), label, 'exec')
+ param_list = string.join(params, ", ")
+ f = '''def defInst(_code, _context, %s):
+ my_locals = vars().copy()
+ exec _code in _context, my_locals
+ return my_locals\n''' % param_list
+ c = compile(f, label + ' wrapper', 'exec')
+ exec c
+ self.func = defInst
+
+ def defineInst(self, name, args, lineno):
+ context = {}
+ updateExportContext()
+ context.update(exportContext)
+ context.update({ 'name': name, 'Name': string.capitalize(name) })
+ try:
+ vars = self.func(self.user_code, context, *args[0], **args[1])
+ except Exception, exc:
+ error(lineno, 'error defining "%s": %s.' % (name, exc))
+ for k in vars.keys():
+ if k not in ('header_output', 'decoder_output',
+ 'exec_output', 'decode_block'):
+ del vars[k]
+ return GenCode(**vars)
+
+# Special null format to catch an implicit-format instruction
+# definition outside of any format block.
+class NoFormat:
+ def __init__(self):
+ self.defaultInst = ''
+
+ def defineInst(self, name, args, lineno):
+ error(lineno,
+ 'instruction definition "%s" with no active format!' % name)
+
+# This dictionary maps format name strings to Format objects.
+formatMap = {}
+
+# Define a new format
+def defFormat(id, params, code, lineno):
+ # make sure we haven't already defined this one
+ if formatMap.get(id, None) != None:
+ error(lineno, 'format %s redefined.' % id)
+ # create new object and store in global map
+ formatMap[id] = Format(id, params, code)
+
+
+##############
+# Stack: a simple stack object. Used for both formats (formatStack)
+# and default cases (defaultStack). Simply wraps a list to give more
+# stack-like syntax and enable initialization with an argument list
+# (as opposed to an argument that's a list).
+
+class Stack(list):
+ def __init__(self, *items):
+ list.__init__(self, items)
+
+ def push(self, item):
+ self.append(item);
+
+ def top(self):
+ return self[-1]
+
+# The global format stack.
+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
+
+#
+# Indent every line in string 's' by two spaces
+# (except preprocessor directives).
+# Used to make nested code blocks look pretty.
+#
+def indent(s):
+ return re.sub(r'(?m)^(?!#)', ' ', s)
+
+#
+# Munge a somewhat arbitrarily formatted piece of Python code
+# (e.g. from a format 'let' block) into something whose indentation
+# will get by the Python parser.
+#
+# The two keys here are that Python will give a syntax error if
+# there's any whitespace at the beginning of the first line, and that
+# all lines at the same lexical nesting level must have identical
+# indentation. Unfortunately the way code literals work, an entire
+# let block tends to have some initial indentation. Rather than
+# trying to figure out what that is and strip it off, we prepend 'if
+# 1:' to make the let code the nested block inside the if (and have
+# the parser automatically deal with the indentation for us).
+#
+# We don't want to do this if (1) the code block is empty or (2) the
+# first line of the block doesn't have any whitespace at the front.
+
+def fixPythonIndentation(s):
+ # get rid of blank lines first
+ s = re.sub(r'(?m)^\s*\n', '', s);
+ if (s != '' and re.match(r'[ \t]', s[0])):
+ s = 'if 1:\n' + s
+ return s
+
+# Error handler. Just call exit. Output formatted to work under
+# 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 + ":"
+ spaces += " "
+ # 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))
+
+
+#####################################################################
+#
+# Bitfield Operator Support
+#
+#####################################################################
+
+bitOp1ArgRE = re.compile(r'<\s*(\w+)\s*:\s*>')
+
+bitOpWordRE = re.compile(r'(?<![\w\.])([\w\.]+)<\s*(\w+)\s*:\s*(\w+)\s*>')
+bitOpExprRE = re.compile(r'\)<\s*(\w+)\s*:\s*(\w+)\s*>')
+
+def substBitOps(code):
+ # first convert single-bit selectors to two-index form
+ # i.e., <n> --> <n:n>
+ code = bitOp1ArgRE.sub(r'<\1:\1>', code)
+ # simple case: selector applied to ID (name)
+ # i.e., foo<a:b> --> bits(foo, a, b)
+ code = bitOpWordRE.sub(r'bits(\1, \2, \3)', code)
+ # if selector is applied to expression (ending in ')'),
+ # we need to search backward for matching '('
+ match = bitOpExprRE.search(code)
+ while match:
+ exprEnd = match.start()
+ here = exprEnd - 1
+ nestLevel = 1
+ while nestLevel > 0:
+ if code[here] == '(':
+ nestLevel -= 1
+ elif code[here] == ')':
+ nestLevel += 1
+ here -= 1
+ if here < 0:
+ sys.exit("Didn't find '('!")
+ exprStart = here+1
+ newExpr = r'bits(%s, %s, %s)' % (code[exprStart:exprEnd+1],
+ match.group(1), match.group(2))
+ code = code[:exprStart] + newExpr + code[match.end():]
+ match = bitOpExprRE.search(code)
+ return code
+
+
+####################
+# Template objects.
+#
+# Template objects are format strings that allow substitution from
+# the attribute spaces of other objects (e.g. InstObjParams instances).
+
+class Template:
+ def __init__(self, t):
+ self.template = t
+
+ def subst(self, d):
+ # Start with the template namespace. Make a copy since we're
+ # going to modify it.
+ myDict = templateMap.copy()
+ # if the argument is a dictionary, we just use it.
+ if isinstance(d, dict):
+ myDict.update(d)
+ # if the argument is an object, we use its attribute map.
+ elif hasattr(d, '__dict__'):
+ myDict.update(d.__dict__)
+ else:
+ raise TypeError, "Template.subst() arg must be or have dictionary"
+ # Protect non-Python-dict substitutions (e.g. if there's a printf
+ # in the templated C++ code)
+ template = protect_non_subst_percents(self.template)
+ # CPU-model-specific substitutions are handled later (in GenCode).
+ template = protect_cpu_symbols(template)
+ return template % myDict
+
+ # Convert to string. This handles the case when a template with a
+ # CPU-specific term gets interpolated into another template or into
+ # an output block.
+ def __str__(self):
+ return expand_cpu_symbols_to_string(self.template)
+
+#####################################################################
+#
+# Code Parser
+#
+# The remaining code is the support for automatically extracting
+# instruction characteristics from pseudocode.
+#
+#####################################################################
+
+# Force the argument to be a list. Useful for flags, where a caller
+# can specify a singleton flag or a list of flags. Also usful for
+# converting tuples to lists so they can be modified.
+def makeList(arg):
+ if isinstance(arg, list):
+ return arg
+ elif isinstance(arg, tuple):
+ return list(arg)
+ elif not arg:
+ return []
+ else:
+ return [ arg ]
+
+# Generate operandTypeMap from the user's 'def operand_types'
+# statement.
+def buildOperandTypeMap(userDict, lineno):
+ global operandTypeMap
+ operandTypeMap = {}
+ for (ext, (desc, size)) in userDict.iteritems():
+ if desc == 'signed int':
+ ctype = 'int%d_t' % size
+ is_signed = 1
+ elif desc == 'unsigned int':
+ ctype = 'uint%d_t' % size
+ is_signed = 0
+ elif desc == 'float':
+ is_signed = 1 # shouldn't really matter
+ if size == 32:
+ ctype = 'float'
+ elif size == 64:
+ ctype = 'double'
+ if ctype == '':
+ error(lineno, 'Unrecognized type description "%s" in userDict')
+ operandTypeMap[ext] = (size, ctype, is_signed)
+
+#
+#
+#
+# Base class for operand descriptors. An instance of this class (or
+# actually a class derived from this one) represents a specific
+# operand for a code block (e.g, "Rc.sq" as a dest). Intermediate
+# derived classes encapsulates the traits of a particular operand type
+# (e.g., "32-bit integer register").
+#
+class Operand(object):
+ def __init__(self, full_name, ext, is_src, is_dest):
+ self.full_name = full_name
+ self.ext = ext
+ self.is_src = is_src
+ self.is_dest = is_dest
+ # The 'effective extension' (eff_ext) is either the actual
+ # extension, if one was explicitly provided, or the default.
+ if ext:
+ self.eff_ext = ext
+ else:
+ self.eff_ext = self.dflt_ext
+
+ (self.size, self.ctype, self.is_signed) = operandTypeMap[self.eff_ext]
+
+ # note that mem_acc_size is undefined for non-mem operands...
+ # template must be careful not to use it if it doesn't apply.
+ if self.isMem():
+ self.mem_acc_size = self.makeAccSize()
+ self.mem_acc_type = self.ctype
+
+ # Finalize additional fields (primarily code fields). This step
+ # is done separately since some of these fields may depend on the
+ # register index enumeration that hasn't been performed yet at the
+ # time of __init__().
+ def finalize(self):
+ self.flags = self.getFlags()
+ self.constructor = self.makeConstructor()
+ self.op_decl = self.makeDecl()
+
+ if self.is_src:
+ self.op_rd = self.makeRead()
+ self.op_src_decl = self.makeDecl()
+ else:
+ self.op_rd = ''
+ self.op_src_decl = ''
+
+ if self.is_dest:
+ self.op_wb = self.makeWrite()
+ self.op_dest_decl = self.makeDecl()
+ else:
+ self.op_wb = ''
+ self.op_dest_decl = ''
+
+ def isMem(self):
+ return 0
+
+ def isReg(self):
+ return 0
+
+ def isFloatReg(self):
+ return 0
+
+ def isIntReg(self):
+ return 0
+
+ def isControlReg(self):
+ return 0
+
+ def getFlags(self):
+ # note the empty slice '[:]' gives us a copy of self.flags[0]
+ # instead of a reference to it
+ my_flags = self.flags[0][:]
+ if self.is_src:
+ my_flags += self.flags[1]
+ if self.is_dest:
+ my_flags += self.flags[2]
+ return my_flags
+
+ def makeDecl(self):
+ # Note that initializations in the declarations are solely
+ # to avoid 'uninitialized variable' errors from the compiler.
+ return self.ctype + ' ' + self.base_name + ' = 0;\n';
+
+class IntRegOperand(Operand):
+ def isReg(self):
+ return 1
+
+ def isIntReg(self):
+ return 1
+
+ def makeConstructor(self):
+ c = ''
+ if self.is_src:
+ c += '\n\t_srcRegIdx[%d] = %s;' % \
+ (self.src_reg_idx, self.reg_spec)
+ if self.is_dest:
+ c += '\n\t_destRegIdx[%d] = %s;' % \
+ (self.dest_reg_idx, self.reg_spec)
+ return c
+
+ def makeRead(self):
+ if (self.ctype == 'float' or self.ctype == 'double'):
+ error(0, 'Attempt to read integer register as FP')
+ if (self.size == self.dflt_size):
+ return '%s = xc->readIntReg(this, %d);\n' % \
+ (self.base_name, self.src_reg_idx)
+ else:
+ return '%s = bits(xc->readIntReg(this, %d), %d, 0);\n' % \
+ (self.base_name, self.src_reg_idx, self.size-1)
+
+ def makeWrite(self):
+ if (self.ctype == 'float' or self.ctype == 'double'):
+ error(0, 'Attempt to write integer register as FP')
+ if (self.size != self.dflt_size and self.is_signed):
+ final_val = 'sext<%d>(%s)' % (self.size, self.base_name)
+ else:
+ final_val = self.base_name
+ wb = '''
+ {
+ %s final_val = %s;
+ xc->setIntReg(this, %d, final_val);\n
+ if (traceData) { traceData->setData(final_val); }
+ }''' % (self.dflt_ctype, final_val, self.dest_reg_idx)
+ return wb
+
+class FloatRegOperand(Operand):
+ def isReg(self):
+ return 1
+
+ def isFloatReg(self):
+ return 1
+
+ def makeConstructor(self):
+ c = ''
+ if self.is_src:
+ c += '\n\t_srcRegIdx[%d] = %s + FP_Base_DepTag;' % \
+ (self.src_reg_idx, self.reg_spec)
+ if self.is_dest:
+ c += '\n\t_destRegIdx[%d] = %s + FP_Base_DepTag;' % \
+ (self.dest_reg_idx, self.reg_spec)
+ return c
+
+ def makeRead(self):
+ bit_select = 0
+ width = 0;
+ if (self.ctype == 'float'):
+ func = 'readFloatReg'
+ width = 32;
+ elif (self.ctype == 'double'):
+ func = 'readFloatReg'
+ width = 64;
+ else:
+ 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
+ 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)
+ else:
+ return '%s = %s;\n' % (self.base_name, base)
+
+ def makeWrite(self):
+ final_val = self.base_name
+ final_ctype = self.ctype
+ widthSpecifier = ''
+ width = 0
+ if (self.ctype == 'float'):
+ width = 32
+ func = 'setFloatReg'
+ elif (self.ctype == 'double'):
+ width = 64
+ func = 'setFloatReg'
+ elif (self.ctype == 'uint32_t'):
+ func = 'setFloatRegBits'
+ width = 32
+ elif (self.ctype == 'uint64_t'):
+ func = 'setFloatRegBits'
+ width = 64
+ else:
+ 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%s);\n
+ if (traceData) { traceData->setData(final_val); }
+ }''' % (final_ctype, final_val, func, self.dest_reg_idx,
+ widthSpecifier)
+ return wb
+
+class ControlRegOperand(Operand):
+ def isReg(self):
+ return 1
+
+ def isControlReg(self):
+ return 1
+
+ def makeConstructor(self):
+ c = ''
+ if self.is_src:
+ c += '\n\t_srcRegIdx[%d] = %s;' % \
+ (self.src_reg_idx, self.reg_spec)
+ if self.is_dest:
+ c += '\n\t_destRegIdx[%d] = %s;' % \
+ (self.dest_reg_idx, self.reg_spec)
+ return c
+
+ def makeRead(self):
+ bit_select = 0
+ if (self.ctype == 'float' or self.ctype == 'double'):
+ error(0, 'Attempt to read control register as FP')
+ base = 'xc->readMiscReg(%s)' % self.reg_spec
+ if self.size == self.dflt_size:
+ return '%s = %s;\n' % (self.base_name, base)
+ else:
+ return '%s = bits(%s, %d, 0);\n' % \
+ (self.base_name, base, self.size-1)
+
+ def makeWrite(self):
+ if (self.ctype == 'float' or self.ctype == 'double'):
+ error(0, 'Attempt to write control register as FP')
+ wb = 'xc->setMiscReg(%s, %s);\n' % (self.reg_spec, self.base_name)
+ wb += 'if (traceData) { traceData->setData(%s); }' % \
+ self.base_name
+ return wb
+
+class MemOperand(Operand):
+ def isMem(self):
+ return 1
+
+ def makeConstructor(self):
+ return ''
+
+ def makeDecl(self):
+ # Note that initializations in the declarations are solely
+ # to avoid 'uninitialized variable' errors from the compiler.
+ # Declare memory data variable.
+ c = '%s %s = 0;\n' % (self.ctype, self.base_name)
+ return c
+
+ def makeRead(self):
+ return ''
+
+ def makeWrite(self):
+ return ''
+
+ # Return the memory access size *in bits*, suitable for
+ # forming a type via "uint%d_t". Divide by 8 if you want bytes.
+ def makeAccSize(self):
+ return self.size
+
+
+class NPCOperand(Operand):
+ def makeConstructor(self):
+ return ''
+
+ def makeRead(self):
+ return '%s = xc->readNextPC();\n' % self.base_name
+
+ def makeWrite(self):
+ return 'xc->setNextPC(%s);\n' % self.base_name
+
+class NNPCOperand(Operand):
+ def makeConstructor(self):
+ return ''
+
+ def makeRead(self):
+ return '%s = xc->readNextNPC();\n' % self.base_name
+
+ def makeWrite(self):
+ return 'xc->setNextNPC(%s);\n' % self.base_name
+
+def buildOperandNameMap(userDict, lineno):
+ global operandNameMap
+ operandNameMap = {}
+ for (op_name, val) in userDict.iteritems():
+ (base_cls_name, dflt_ext, reg_spec, flags, sort_pri) = val
+ (dflt_size, dflt_ctype, dflt_is_signed) = operandTypeMap[dflt_ext]
+ # Canonical flag structure is a triple of lists, where each list
+ # indicates the set of flags implied by this operand always, when
+ # used as a source, and when used as a dest, respectively.
+ # For simplicity this can be initialized using a variety of fairly
+ # obvious shortcuts; we convert these to canonical form here.
+ if not flags:
+ # no flags specified (e.g., 'None')
+ flags = ( [], [], [] )
+ elif isinstance(flags, str):
+ # a single flag: assumed to be unconditional
+ flags = ( [ flags ], [], [] )
+ elif isinstance(flags, list):
+ # a list of flags: also assumed to be unconditional
+ flags = ( flags, [], [] )
+ elif isinstance(flags, tuple):
+ # it's a tuple: it should be a triple,
+ # but each item could be a single string or a list
+ (uncond_flags, src_flags, dest_flags) = flags
+ flags = (makeList(uncond_flags),
+ makeList(src_flags), makeList(dest_flags))
+ # Accumulate attributes of new operand class in tmp_dict
+ tmp_dict = {}
+ for attr in ('dflt_ext', 'reg_spec', 'flags', 'sort_pri',
+ 'dflt_size', 'dflt_ctype', 'dflt_is_signed'):
+ tmp_dict[attr] = eval(attr)
+ tmp_dict['base_name'] = op_name
+ # New class name will be e.g. "IntReg_Ra"
+ cls_name = base_cls_name + '_' + op_name
+ # Evaluate string arg to get class object. Note that the
+ # actual base class for "IntReg" is "IntRegOperand", i.e. we
+ # have to append "Operand".
+ try:
+ base_cls = eval(base_cls_name + 'Operand')
+ except NameError:
+ error(lineno,
+ 'error: unknown operand base class "%s"' % base_cls_name)
+ # The following statement creates a new class called
+ # <cls_name> as a subclass of <base_cls> with the attributes
+ # in tmp_dict, just as if we evaluated a class declaration.
+ operandNameMap[op_name] = type(cls_name, (base_cls,), tmp_dict)
+
+ # Define operand variables.
+ operands = userDict.keys()
+
+ operandsREString = (r'''
+ (?<![\w\.]) # neg. lookbehind assertion: prevent partial matches
+ ((%s)(?:\.(\w+))?) # match: operand with optional '.' then suffix
+ (?![\w\.]) # neg. lookahead assertion: prevent partial matches
+ '''
+ % string.join(operands, '|'))
+
+ global operandsRE
+ operandsRE = re.compile(operandsREString, re.MULTILINE|re.VERBOSE)
+
+ # Same as operandsREString, but extension is mandatory, and only two
+ # groups are returned (base and ext, not full name as above).
+ # Used for subtituting '_' for '.' to make C++ identifiers.
+ operandsWithExtREString = (r'(?<![\w\.])(%s)\.(\w+)(?![\w\.])'
+ % string.join(operands, '|'))
+
+ global operandsWithExtRE
+ operandsWithExtRE = re.compile(operandsWithExtREString, re.MULTILINE)
+
+
+class OperandList:
+
+ # Find all the operands in the given code block. Returns an operand
+ # descriptor list (instance of class OperandList).
+ def __init__(self, code):
+ self.items = []
+ self.bases = {}
+ # delete comments so we don't match on reg specifiers inside
+ code = commentRE.sub('', code)
+ # search for operands
+ next_pos = 0
+ while 1:
+ match = operandsRE.search(code, next_pos)
+ if not match:
+ # no more matches: we're done
+ break
+ op = match.groups()
+ # regexp groups are operand full name, base, and extension
+ (op_full, op_base, op_ext) = op
+ # if the token following the operand is an assignment, this is
+ # a destination (LHS), else it's a source (RHS)
+ is_dest = (assignRE.match(code, match.end()) != None)
+ is_src = not is_dest
+ # see if we've already seen this one
+ op_desc = self.find_base(op_base)
+ if op_desc:
+ if op_desc.ext != op_ext:
+ error(0, 'Inconsistent extensions for operand %s' % \
+ op_base)
+ op_desc.is_src = op_desc.is_src or is_src
+ op_desc.is_dest = op_desc.is_dest or is_dest
+ else:
+ # new operand: create new descriptor
+ op_desc = operandNameMap[op_base](op_full, op_ext,
+ is_src, is_dest)
+ self.append(op_desc)
+ # start next search after end of current match
+ next_pos = match.end()
+ self.sort()
+ # enumerate source & dest register operands... used in building
+ # constructor later
+ self.numSrcRegs = 0
+ self.numDestRegs = 0
+ self.numFPDestRegs = 0
+ self.numIntDestRegs = 0
+ self.memOperand = None
+ for op_desc in self.items:
+ if op_desc.isReg():
+ if op_desc.is_src:
+ op_desc.src_reg_idx = self.numSrcRegs
+ self.numSrcRegs += 1
+ if op_desc.is_dest:
+ op_desc.dest_reg_idx = self.numDestRegs
+ self.numDestRegs += 1
+ if op_desc.isFloatReg():
+ self.numFPDestRegs += 1
+ elif op_desc.isIntReg():
+ self.numIntDestRegs += 1
+ elif op_desc.isMem():
+ if self.memOperand:
+ error(0, "Code block has more than one memory operand.")
+ self.memOperand = op_desc
+ # now make a final pass to finalize op_desc fields that may depend
+ # on the register enumeration
+ for op_desc in self.items:
+ op_desc.finalize()
+
+ def __len__(self):
+ return len(self.items)
+
+ def __getitem__(self, index):
+ return self.items[index]
+
+ def append(self, op_desc):
+ self.items.append(op_desc)
+ self.bases[op_desc.base_name] = op_desc
+
+ def find_base(self, base_name):
+ # like self.bases[base_name], but returns None if not found
+ # (rather than raising exception)
+ return self.bases.get(base_name)
+
+ # internal helper function for concat[Some]Attr{Strings|Lists}
+ def __internalConcatAttrs(self, attr_name, filter, result):
+ for op_desc in self.items:
+ if filter(op_desc):
+ result += getattr(op_desc, attr_name)
+ return result
+
+ # return a single string that is the concatenation of the (string)
+ # values of the specified attribute for all operands
+ def concatAttrStrings(self, attr_name):
+ return self.__internalConcatAttrs(attr_name, lambda x: 1, '')
+
+ # like concatAttrStrings, but only include the values for the operands
+ # for which the provided filter function returns true
+ def concatSomeAttrStrings(self, filter, attr_name):
+ return self.__internalConcatAttrs(attr_name, filter, '')
+
+ # return a single list that is the concatenation of the (list)
+ # values of the specified attribute for all operands
+ def concatAttrLists(self, attr_name):
+ return self.__internalConcatAttrs(attr_name, lambda x: 1, [])
+
+ # like concatAttrLists, but only include the values for the operands
+ # for which the provided filter function returns true
+ def concatSomeAttrLists(self, filter, attr_name):
+ return self.__internalConcatAttrs(attr_name, filter, [])
+
+ def sort(self):
+ self.items.sort(lambda a, b: a.sort_pri - b.sort_pri)
+
+# Regular expression object to match C++ comments
+# (used in findOperands())
+commentRE = re.compile(r'//.*\n')
+
+# Regular expression object to match assignment statements
+# (used in findOperands())
+assignRE = re.compile(r'\s*=(?!=)', re.MULTILINE)
+
+# Munge operand names in code string to make legal C++ variable names.
+# This means getting rid of the type extension if any.
+# (Will match base_name attribute of Operand object.)
+def substMungedOpNames(code):
+ return operandsWithExtRE.sub(r'\1', code)
+
+def joinLists(t):
+ return map(string.join, t)
+
+def makeFlagConstructor(flag_list):
+ if len(flag_list) == 0:
+ return ''
+ # filter out repeated flags
+ flag_list.sort()
+ i = 1
+ while i < len(flag_list):
+ if flag_list[i] == flag_list[i-1]:
+ del flag_list[i]
+ else:
+ i += 1
+ pre = '\n\tflags['
+ post = '] = true;'
+ code = pre + string.join(flag_list, post + pre) + post
+ return code
+
+class CodeBlock:
+ def __init__(self, code):
+ self.orig_code = code
+ self.operands = OperandList(code)
+ self.code = substMungedOpNames(substBitOps(code))
+ self.constructor = self.operands.concatAttrStrings('constructor')
+ self.constructor += \
+ '\n\t_numSrcRegs = %d;' % self.operands.numSrcRegs
+ self.constructor += \
+ '\n\t_numDestRegs = %d;' % self.operands.numDestRegs
+ self.constructor += \
+ '\n\t_numFPDestRegs = %d;' % self.operands.numFPDestRegs
+ self.constructor += \
+ '\n\t_numIntDestRegs = %d;' % self.operands.numIntDestRegs
+
+ self.op_decl = self.operands.concatAttrStrings('op_decl')
+
+ is_src = lambda op: op.is_src
+ is_dest = lambda op: op.is_dest
+
+ self.op_src_decl = \
+ self.operands.concatSomeAttrStrings(is_src, 'op_src_decl')
+ self.op_dest_decl = \
+ self.operands.concatSomeAttrStrings(is_dest, 'op_dest_decl')
+
+ self.op_rd = self.operands.concatAttrStrings('op_rd')
+ self.op_wb = self.operands.concatAttrStrings('op_wb')
+
+ self.flags = self.operands.concatAttrLists('flags')
+
+ if self.operands.memOperand:
+ self.mem_acc_size = self.operands.memOperand.mem_acc_size
+ self.mem_acc_type = self.operands.memOperand.mem_acc_type
+
+ # Make a basic guess on the operand class (function unit type).
+ # These are good enough for most cases, and will be overridden
+ # later otherwise.
+ if 'IsStore' in self.flags:
+ self.op_class = 'MemWriteOp'
+ elif 'IsLoad' in self.flags or 'IsPrefetch' in self.flags:
+ self.op_class = 'MemReadOp'
+ elif 'IsFloating' in self.flags:
+ self.op_class = 'FloatAddOp'
+ else:
+ self.op_class = 'IntAluOp'
+
+# Assume all instruction flags are of the form 'IsFoo'
+instFlagRE = re.compile(r'Is.*')
+
+# OpClass constants end in 'Op' except No_OpClass
+opClassRE = re.compile(r'.*Op|No_OpClass')
+
+class InstObjParams:
+ def __init__(self, mnem, class_name, base_class = '',
+ code = None, opt_args = [], *extras):
+ self.mnemonic = mnem
+ self.class_name = class_name
+ self.base_class = base_class
+ 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 = []
+ # Optional arguments are assumed to be either StaticInst flags
+ # or an OpClass value. To avoid having to import a complete
+ # list of these values to match against, we do it ad-hoc
+ # with regexps.
+ for oa in opt_args:
+ if instFlagRE.match(oa):
+ self.flags.append(oa)
+ elif opClassRE.match(oa):
+ self.op_class = oa
+ else:
+ error(0, 'InstObjParams: optional arg "%s" not recognized '
+ 'as StaticInst::Flag or OpClass.' % oa)
+
+ # add flag initialization to contructor here to include
+ # any flags added via opt_args
+ self.constructor += makeFlagConstructor(self.flags)
+
+ # if 'IsFloating' is set, add call to the FP enable check
+ # function (which should be provided by isa_desc via a declare)
+ if 'IsFloating' in self.flags:
+ self.fp_enable_check = 'fault = checkFpEnableFault(xc);'
+ else:
+ self.fp_enable_check = ''
+
+#######################
+#
+# Output file template
+#
+
+file_template = '''
+/*
+ * DO NOT EDIT THIS FILE!!!
+ *
+ * It was automatically generated from the ISA description in %(filename)s
+ */
+
+%(includes)s
+
+%(global_output)s
+
+namespace %(namespace)s {
+
+%(namespace_output)s
+
+} // namespace %(namespace)s
+
+%(decode_function)s
+'''
+
+
+# Update the output file only if the new contents are different from
+# the current contents. Minimizes the files that need to be rebuilt
+# after minor changes.
+def update_if_needed(file, contents):
+ update = False
+ if os.access(file, os.R_OK):
+ f = open(file, 'r')
+ old_contents = f.read()
+ f.close()
+ if contents != old_contents:
+ print 'Updating', file
+ os.remove(file) # in case it's write-protected
+ update = True
+ else:
+ print 'File', file, 'is unchanged'
+ else:
+ print 'Generating', file
+ update = True
+ if update:
+ f = open(file, 'w')
+ f.write(contents)
+ f.close()
+
+# This regular expression matches '##include' directives
+includeRE = re.compile(r'^\s*##include\s+"(?P<filename>[\w/.-]*)".*$',
+ re.MULTILINE)
+
+# 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
+ 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):
+ # 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)
+
+ # grab the last three path components of isa_desc_file to put in
+ # the output
+ filename = '/'.join(isa_desc_file.split('/')[-3:])
+
+ # generate decoder.hh
+ includes = '#include "base/bitfield.hh" // for bitfield support'
+ global_output = global_code.header_output
+ namespace_output = namespace_code.header_output
+ decode_function = ''
+ update_if_needed(output_dir + '/decoder.hh', file_template % vars())
+
+ # generate decoder.cc
+ includes = '#include "decoder.hh"'
+ global_output = global_code.decoder_output
+ namespace_output = namespace_code.decoder_output
+ # namespace_output += namespace_code.decode_block
+ decode_function = namespace_code.decode_block
+ update_if_needed(output_dir + '/decoder.cc', file_template % vars())
+
+ # generate per-cpu exec files
+ for cpu in cpu_models:
+ includes = '#include "decoder.hh"\n'
+ includes += cpu.includes
+ global_output = global_code.exec_output[cpu.name]
+ namespace_output = namespace_code.exec_output[cpu.name]
+ decode_function = ''
+ update_if_needed(output_dir + '/' + cpu.filename,
+ file_template % vars())
+
+# global list of CpuModel objects (see cpu_models.py)
+cpu_models = []
+
+# Called as script: get args from command line.
+# Args are: <path to cpu_models.py> <isa desc file> <output dir> <cpu models>
+if __name__ == '__main__':
+ execfile(sys.argv[1]) # read in CpuModel definitions
+ cpu_models = [CpuModel.dict[cpu] for cpu in sys.argv[4:]]
+ parse_isa_desc(sys.argv[2], sys.argv[3])
diff --git a/src/arch/isa_specific.hh b/src/arch/isa_specific.hh
new file mode 100644
index 000000000..91c9ffb68
--- /dev/null
+++ b/src/arch/isa_specific.hh
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2003-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __ARCH_ISA_SPECIFIC_HH__
+#define __ARCH_ISA_SPECIFIC_HH__
+
+//This file provides a mechanism for other source code to bring in
+//files from the ISA being compiled with
+
+//These are constants so you can selective compile code based on the isa
+//To use them, do something like
+//
+//#if THE_ISA == YOUR_FAVORITE_ISA
+// conditional_code
+//#endif
+//
+//Note that this is how this file sets up the other isa "hooks"
+
+//These macros have numerical values because otherwise the preprocessor
+//would treat them as 0 in comparisons.
+#define ALPHA_ISA 21064
+#define SPARC_ISA 42
+#define MIPS_ISA 34000
+
+//These tell the preprocessor where to find the files of a particular
+//ISA, and set the "TheISA" macro for use elsewhere.
+#if THE_ISA == ALPHA_ISA
+ #define TheISA AlphaISA
+#elif THE_ISA == SPARC_ISA
+ #define TheISA SparcISA
+#elif THE_ISA == MIPS_ISA
+ #define TheISA MipsISA
+#else
+ #error "THE_ISA not set"
+#endif
+
+#endif
diff --git a/src/arch/mips/SConscript b/src/arch/mips/SConscript
new file mode 100644
index 000000000..ef1ef25d6
--- /dev/null
+++ b/src/arch/mips/SConscript
@@ -0,0 +1,83 @@
+# -*- mode:python -*-
+
+# Copyright (c) 2004-2005 The Regents of The University of Michigan
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met: redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer;
+# redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution;
+# neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import os
+import sys
+from os.path import isdir
+
+# Import build environment variable from SConstruct.
+Import('env')
+
+###################################################
+#
+# Define needed sources.
+#
+###################################################
+
+# Base sources used by all configurations.
+base_sources = Split('''
+ faults.cc
+ isa_traits.cc
+ ''')
+
+# Full-system sources
+full_system_sources = Split('''
+ memory.cc
+ arguments.cc
+ mips34k.cc
+ osfpal.cc
+ stacktrace.cc
+ vtophys.cc
+ ''')
+
+# Syscall emulation (non-full-system) sources
+syscall_emulation_sources = Split('''
+ linux/linux.cc
+ linux/process.cc
+ process.cc
+ ''')
+
+# Set up complete list of sources based on configuration.
+sources = base_sources
+
+if env['FULL_SYSTEM']:
+ sources += full_system_sources
+else:
+ sources += syscall_emulation_sources
+
+# Convert file names to SCons File objects. This takes care of the
+# path relative to the top of the directory tree.
+sources = [File(s) for s in sources]
+
+# Add in files generated by the ISA description.
+isa_desc_files = env.ISADesc('isa/main.isa')
+# Only non-header files need to be compiled.
+isa_desc_sources = [f for f in isa_desc_files if not f.path.endswith('.hh')]
+sources += isa_desc_sources
+
+Return('sources')
diff --git a/src/arch/mips/faults.cc b/src/arch/mips/faults.cc
new file mode 100644
index 000000000..1b31dfa69
--- /dev/null
+++ b/src/arch/mips/faults.cc
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2003-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "arch/mips/faults.hh"
+#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;
+
+#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!");
+}
+
+#endif
+
+} // namespace MipsISA
+
diff --git a/src/arch/mips/faults.hh b/src/arch/mips/faults.hh
new file mode 100644
index 000000000..0bdabe29e
--- /dev/null
+++ b/src/arch/mips/faults.hh
@@ -0,0 +1,269 @@
+/*
+ * Copyright (c) 2003-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __MIPS_FAULTS_HH__
+#define __MIPS_FAULTS_HH__
+
+#include "sim/faults.hh"
+
+// 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:
+#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;
+}
+
+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;}
+};
+
+class ArithmeticFault : public MipsFault
+{
+ protected:
+ bool skipFaultingInstruction() {return true;}
+ private:
+ static FaultName _name;
+ static FaultVect _vect;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ FaultVect vect() {return _vect;}
+ FaultStat & countStat() {return _count;}
+#if FULL_SYSTEM
+ void invoke(ExecContext * xc);
+#endif
+};
+
+class InterruptFault : public MipsFault
+{
+ protected:
+ bool setRestartAddress() {return false;}
+ private:
+ static FaultName _name;
+ static FaultVect _vect;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ FaultVect vect() {return _vect;}
+ FaultStat & countStat() {return _count;}
+};
+
+class NDtbMissFault : public MipsFault
+{
+ private:
+ static FaultName _name;
+ static FaultVect _vect;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ FaultVect vect() {return _vect;}
+ FaultStat & countStat() {return _count;}
+};
+
+class PDtbMissFault : public MipsFault
+{
+ private:
+ static FaultName _name;
+ static FaultVect _vect;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ FaultVect vect() {return _vect;}
+ FaultStat & countStat() {return _count;}
+};
+
+class DtbPageFault : public MipsFault
+{
+ private:
+ static FaultName _name;
+ static FaultVect _vect;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ FaultVect vect() {return _vect;}
+ FaultStat & countStat() {return _count;}
+};
+
+class DtbAcvFault : public MipsFault
+{
+ private:
+ static FaultName _name;
+ static FaultVect _vect;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ FaultVect vect() {return _vect;}
+ FaultStat & countStat() {return _count;}
+};
+
+class ItbMissFault : public MipsFault
+{
+ private:
+ static FaultName _name;
+ static FaultVect _vect;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ FaultVect vect() {return _vect;}
+ FaultStat & countStat() {return _count;}
+};
+
+class ItbPageFault : public MipsFault
+{
+ private:
+ static FaultName _name;
+ static FaultVect _vect;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ FaultVect vect() {return _vect;}
+ FaultStat & countStat() {return _count;}
+};
+
+class ItbAcvFault : public MipsFault
+{
+ private:
+ static FaultName _name;
+ static FaultVect _vect;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ FaultVect vect() {return _vect;}
+ FaultStat & countStat() {return _count;}
+};
+
+class UnimplementedOpcodeFault : public MipsFault
+{
+ private:
+ static FaultName _name;
+ static FaultVect _vect;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ FaultVect vect() {return _vect;}
+ FaultStat & countStat() {return _count;}
+};
+
+class FloatEnableFault : public MipsFault
+{
+ private:
+ static FaultName _name;
+ static FaultVect _vect;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ FaultVect vect() {return _vect;}
+ FaultStat & countStat() {return _count;}
+};
+
+class PalFault : public MipsFault
+{
+ protected:
+ bool skipFaultingInstruction() {return true;}
+ private:
+ static FaultName _name;
+ static FaultVect _vect;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ FaultVect vect() {return _vect;}
+ FaultStat & countStat() {return _count;}
+};
+
+class IntegerOverflowFault : public MipsFault
+{
+ private:
+ static FaultName _name;
+ static FaultVect _vect;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ FaultVect vect() {return _vect;}
+ FaultStat & countStat() {return _count;}
+};
+
+} // MipsISA namespace
+
+#endif // __FAULTS_HH__
diff --git a/src/arch/mips/isa/base.isa b/src/arch/mips/isa/base.isa
new file mode 100644
index 000000000..b2a31c018
--- /dev/null
+++ b/src/arch/mips/isa/base.isa
@@ -0,0 +1,88 @@
+// -*- mode:c++ -*-
+
+////////////////////////////////////////////////////////////////////
+//
+// Base class for MIPS instructions, and some support functions
+//
+
+//Outputs to decoder.hh
+output header {{
+
+ using namespace MipsISA;
+
+
+ /**
+ * Base class for all MIPS static instructions.
+ */
+ class MipsStaticInst : public StaticInst
+ {
+ protected:
+
+ /// Make MipsISA register dependence tags directly visible in
+ /// this class and derived classes. Maybe these should really
+ /// live here and not in the MipsISA namespace.
+ /*enum DependenceTags {
+ FP_Base_DepTag = MipsISA::FP_Base_DepTag,
+ Fpcr_DepTag = MipsISA::Fpcr_DepTag,
+ Uniq_DepTag = MipsISA::Uniq_DepTag,
+ IPR_Base_DepTag = MipsISA::IPR_Base_DepTag
+ };*/
+
+ // Constructor
+ MipsStaticInst(const char *mnem, MachInst _machInst, OpClass __opClass)
+ : StaticInst(mnem, _machInst, __opClass)
+ {
+ }
+
+ /// Print a register name for disassembly given the unique
+ /// dependence tag number (FP or int).
+ void printReg(std::ostream &os, int reg) const;
+
+ std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+
+}};
+
+//Ouputs to decoder.cc
+output decoder {{
+
+ void MipsStaticInst::printReg(std::ostream &os, int reg) const
+ {
+ if (reg < FP_Base_DepTag) {
+ ccprintf(os, "r%d", reg);
+ }
+ else {
+ ccprintf(os, "f%d", reg - FP_Base_DepTag);
+ }
+ }
+
+ std::string MipsStaticInst::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+ {
+ std::stringstream ss;
+
+ ccprintf(ss, "%-10s ", mnemonic);
+
+ if(_numDestRegs > 0){
+ printReg(ss, _destRegIdx[0]);
+ }
+
+ if(_numSrcRegs > 0) {
+ ss << ",";
+ printReg(ss, _srcRegIdx[0]);
+ }
+
+ if(_numSrcRegs > 1) {
+ ss << ",";
+ printReg(ss, _srcRegIdx[1]);
+ }
+
+
+ if(mnemonic == "sll" || mnemonic == "sra"){
+ ccprintf(ss,", %d",SA);
+ }
+
+ return ss.str();
+ }
+
+}};
+
diff --git a/src/arch/mips/isa/bitfields.isa b/src/arch/mips/isa/bitfields.isa
new file mode 100644
index 000000000..e1124a591
--- /dev/null
+++ b/src/arch/mips/isa/bitfields.isa
@@ -0,0 +1,71 @@
+// -*- mode:c++ -*-
+
+////////////////////////////////////////////////////////////////////
+//
+// Bitfield definitions.
+//
+
+def bitfield OPCODE <31:26>;
+def bitfield OPCODE_HI <31:29>;
+def bitfield OPCODE_LO <28:26>;
+
+def bitfield REGIMM <20:16>;
+def bitfield REGIMM_HI <20:19>;
+def bitfield REGIMM_LO <18:16>;
+
+def bitfield FUNCTION < 5: 0>;
+def bitfield FUNCTION_HI < 5: 3>;
+def bitfield FUNCTION_LO < 2: 0>;
+
+// Integer operate format
+def bitfield RT <20:16>;
+def bitfield RT_HI <20:19>;
+def bitfield RT_LO <18:16>;
+
+def bitfield RS <25:21>;
+def bitfield RS_MSB <25:25>;
+def bitfield RS_HI <25:24>;
+def bitfield RS_LO <23:21>;
+def bitfield RS_SRL <25:22>;
+
+def bitfield RD <15:11>;
+
+def bitfield INTIMM <15: 0>; // integer immediate (literal)
+
+// Floating-point operate format
+def bitfield FMT <25:21>;
+def bitfield FR <25:21>;
+def bitfield FT <20:16>;
+def bitfield FS <15:11>;
+def bitfield FD <10:6>;
+
+def bitfield ND <17:17>;
+def bitfield TF <16:16>;
+def bitfield MOVCI <16:16>;
+def bitfield MOVCF <16:16>;
+def bitfield SRL <21:21>;
+def bitfield SRLV < 6: 6>;
+def bitfield SA <10: 6>;
+
+// Floating Point Condition Codes
+def bitfield CC <10:8>;
+def bitfield BRANCH_CC <20:18>;
+
+// CP0 Register Select
+def bitfield SEL < 2: 0>;
+
+// Interrupts
+def bitfield SC < 5: 5>;
+
+// Branch format
+def bitfield OFFSET <15: 0>; // displacement
+
+// Jmp format
+def bitfield JMPTARG <25: 0>;
+def bitfield HINT <10: 6>;
+
+def bitfield SYSCALLCODE <25: 6>;
+def bitfield TRAPCODE <15:13>;
+
+// M5 instructions
+def bitfield M5FUNC <7:0>;
diff --git a/src/arch/mips/isa/decoder.isa b/src/arch/mips/isa/decoder.isa
new file mode 100644
index 000000000..1454aba39
--- /dev/null
+++ b/src/arch/mips/isa/decoder.isa
@@ -0,0 +1,1688 @@
+ // -*- mode:c++ -*-
+
+////////////////////////////////////////////////////////////////////
+//
+// The actual MIPS32 ISA decoder
+// -----------------------------
+// The following instructions are specified in the MIPS32 ISA
+// Specification. Decoding closely follows the style specified
+// in the MIPS32 ISAthe specification document starting with Table
+// A-2 (document available @ www.mips.com)
+//
+//@todo: Distinguish "unknown/future" use insts from "reserved"
+// ones
+decode OPCODE_HI default Unknown::unknown() {
+
+ // Derived From ... Table A-2 MIPS32 ISA Manual
+ 0x0: decode OPCODE_LO {
+
+ 0x0: decode FUNCTION_HI {
+ 0x0: decode FUNCTION_LO {
+ 0x1: decode MOVCI {
+ format BasicOp {
+ 0: movf({{ if (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 { //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 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);}});
+ }
+ }
+
+ 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>; }});
+
+ 0x6: decode SRLV {
+ 0: srlv({{ Rd = Rt.uw >> Rs<4:0>; }});
+
+ //Hardcoded assuming 32-bit ISA, probably need parameter here
+ 1: rotrv({{ Rd = (Rt.uw << (32 - Rs<4:0>)) | (Rt.uw >> Rs<4:0>);}});
+ }
+
+ 0x7: srav({{
+ 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;
+ }});
+ }
+ }
+
+ 0x1: decode FUNCTION_LO {
+
+ //Table A-3 Note: "Specific encodings of the hint field are used
+ //to distinguish JR from JR.HB and JALR from JALR.HB"
+ format Jump {
+ 0x0: decode HINT {
+ 0:jr({{ NNPC = Rs & ~1; }},IsReturn);
+
+ 1:jr_hb({{ NNPC = Rs & ~1; clear_exe_inst_hazards(); }},IsReturn);
+ }
+
+ 0x1: decode HINT {
+ 0: jalr({{ Rd = NNPC; NNPC = Rs; }},IsCall,IsReturn);
+
+ 1: jalr_hb({{ Rd = NNPC; NNPC = Rs; clear_exe_inst_hazards();}},IsCall,IsReturn);
+ }
+ }
+
+ format BasicOp {
+ 0x2: movz({{ if (Rt == 0) Rd = Rs; }});
+ 0x3: movn({{ if (Rt != 0) Rd = Rs; }});
+ }
+
+ format 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 = 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.sd * Rt.sd;
+ HI = temp1<63:32>;
+ LO = temp1<31:0>;
+ }});
+
+ 0x1: multu({{
+ uint64_t temp1 = Rs.ud * Rt.ud;
+ HI = temp1<63:32>;
+ LO = temp1<31:0>;
+ }});
+
+ 0x2: div({{
+ HI = Rs.sd % Rt.sd;
+ LO = Rs.sd / Rt.sd;
+ }});
+
+ 0x3: divu({{
+ HI = Rs.ud % Rt.ud;
+ LO = Rs.ud / Rt.ud;
+ }});
+ }
+ }
+
+ 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 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}});
+ }
+ }
+ }
+
+ 0x6: decode FUNCTION_LO {
+ format Trap {
+ 0x0: tge({{ cond = (Rs.sw >= Rt.sw); }});
+ 0x1: tgeu({{ cond = (Rs.uw >= Rt.uw); }});
+ 0x2: tlt({{ cond = (Rs.sw < Rt.sw); }});
+ 0x3: tltu({{ cond = (Rs.uw >= Rt.uw); }});
+ 0x4: teq({{ cond = (Rs.sw == Rt.sw); }});
+ 0x6: tne({{ cond = (Rs.sw != Rt.sw); }});
+ }
+ }
+ }
+
+ 0x1: decode REGIMM_HI {
+ 0x0: decode REGIMM_LO {
+ format Branch {
+ 0x0: bltz({{ cond = (Rs.sw < 0); }});
+ 0x1: bgez({{ cond = (Rs.sw >= 0); }});
+ }
+
+ format BranchLikely {
+ 0x2: bltzl({{ cond = (Rs.sw < 0); }});
+ 0x3: bgezl({{ cond = (Rs.sw >= 0); }});
+ }
+ }
+
+ 0x1: decode REGIMM_LO {
+ format Trap {
+ 0x0: tgei( {{ cond = (Rs.sw >= INTIMM); }});
+ 0x1: tgeiu({{ cond = (Rs.uw >= INTIMM); }});
+ 0x2: tlti( {{ cond = (Rs.sw < INTIMM); }});
+ 0x3: tltiu({{ cond = (Rs.uw < INTIMM); }});
+ 0x4: teqi( {{ cond = (Rs.sw == INTIMM);}});
+ 0x6: tnei( {{ cond = (Rs.sw != INTIMM);}});
+ }
+ }
+
+ 0x2: decode REGIMM_LO {
+ format Branch {
+ 0x0: bltzal({{ cond = (Rs.sw < 0); }}, IsCall,IsReturn);
+ 0x1: bgezal({{ cond = (Rs.sw >= 0); }}, IsCall,IsReturn);
+ }
+
+ format BranchLikely {
+ 0x2: bltzall({{ cond = (Rs.sw < 0); }}, IsCall, IsReturn);
+ 0x3: bgezall({{ cond = (Rs.sw >= 0); }}, IsCall, IsReturn);
+ }
+ }
+
+ 0x3: decode REGIMM_LO {
+ format WarnUnimpl {
+ 0x7: synci();
+ }
+ }
+ }
+
+ format Jump {
+ 0x2: j({{ NNPC = (NPC & 0xF0000000) | (JMPTARG << 2);}});
+
+ 0x3: jal({{ NNPC = (NPC & 0xF0000000) | (JMPTARG << 2); }},IsCall,IsReturn);
+ }
+
+ format Branch {
+ 0x4: beq({{ cond = (Rs.sw == Rt.sw); }});
+ 0x5: bne({{ cond = (Rs.sw != Rt.sw); }});
+ 0x6: decode RT {
+ 0x0: blez({{ cond = (Rs.sw <= 0); }});
+ }
+
+ 0x7: decode RT {
+ 0x0: bgtz({{ cond = (Rs.sw > 0); }});
+ }
+ }
+ }
+
+ 0x1: decode OPCODE_LO {
+ format IntOp {
+ 0x0: addi({{ Rt.sw = Rs.sw + imm; /*Trap If Overflow*/}});
+ 0x1: addiu({{ Rt.sw = Rs.sw + imm;}});
+ 0x2: slti({{ Rt.sw = ( Rs.sw < imm) ? 1 : 0 }});
+ 0x3: sltiu({{ Rt.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}});
+ }
+ }
+ }
+
+ 0x2: decode OPCODE_LO {
+
+ //Table A-11 MIPS32 COP0 Encoding of rs Field
+ 0x0: decode RS_MSB {
+ 0x0: decode RS {
+ format System {
+ 0x0: mfc0({{
+ //uint64_t reg_num = Rd.uw;
+
+ Rt = xc->readMiscReg(RD << 5 | SEL);
+ }});
+
+ 0x4: mtc0({{
+ //uint64_t reg_num = Rd.uw;
+
+ xc->setMiscReg(RD << 5 | SEL,Rt);
+ }});
+
+ 0x8: mftr({{
+ //The contents of the coprocessor 0 register specified by the
+ //combination of rd and sel are loaded into general register
+ //rt. Note that not all coprocessor 0 registers support the
+ //sel field. In those instances, the sel field must be zero.
+
+ //MT Code Needed Here
+
+ }});
+
+ 0xC: mttr({{
+ //The contents of the coprocessor 0 register specified by the
+ //combination of rd and sel are loaded into general register
+ //rt. Note that not all coprocessor 0 registers support the
+ //sel field. In those instances, the sel field must be zero.
+
+ //MT Code Needed Here
+ }});
+
+
+ 0xA: rdpgpr({{
+ //Accessing Previous Shadow Set Register Number
+ //uint64_t prev = xc->readMiscReg(SRSCtl)/*[PSS]*/;
+ //uint64_t reg_num = Rt.uw;
+
+ //Rd = xc->regs.IntRegFile[prev];
+ //Rd = xc->shadowIntRegFile[prev][reg_num];
+ }});
+
+ 0xB: decode RD {
+
+ 0x0: decode SC {
+ 0x0: dvpe({{
+ Rt.sw = xc->readMiscReg(MVPControl);
+ xc->setMiscReg(MVPControl,0);
+ }});
+
+ 0x1: evpe({{
+ Rt.sw = xc->readMiscReg(MVPControl);
+ xc->setMiscReg(MVPControl,1);
+ }});
+ }
+
+ 0x1: decode SC {
+ 0x0: dmt({{
+ Rt.sw = xc->readMiscReg(VPEControl);
+ xc->setMiscReg(VPEControl,0);
+ }});
+
+ 0x1: emt({{
+ Rt.sw = xc->readMiscReg(VPEControl);
+ xc->setMiscReg(VPEControl,1);
+ }});
+ }
+
+ 0xC: decode SC {
+ 0x0: di({{
+ Rt.sw = xc->readMiscReg(Status);
+ xc->setMiscReg(Status,0);
+ }});
+
+ 0x1: ei({{
+ Rt.sw = xc->readMiscReg(Status);
+ xc->setMiscReg(Status,1);
+ }});
+ }
+ }
+
+ 0xE: wrpgpr({{
+ //Accessing Previous Shadow Set Register Number
+ //uint64_t prev = xc->readMiscReg(SRSCtl/*[PSS]*/);
+ //uint64_t reg_num = Rd.uw;
+
+ //xc->regs.IntRegFile[prev];
+ //xc->shadowIntRegFile[prev][reg_num] = Rt;
+ }});
+ }
+ }
+
+ //Table A-12 MIPS32 COP0 Encoding of Function Field When rs=CO
+ 0x1: decode FUNCTION {
+ format System {
+ 0x01: tlbr({{ }});
+ 0x02: tlbwi({{ }});
+ 0x06: tlbwr({{ }});
+ 0x08: tlbp({{ }});
+ }
+
+ format WarnUnimpl {
+ 0x18: eret();
+ 0x1F: deret();
+ 0x20: wait();
+ }
+ }
+ }
+
+ //Table A-13 MIPS32 COP1 Encoding of rs Field
+ 0x1: decode RS_MSB {
+
+ 0x0: decode RS_HI {
+ 0x0: decode RS_LO {
+ format FloatOp {
+ 0x0: mfc1 ({{ Rt.uw = Fs.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 = (getFPConditionCode(FCSR,CC) == 0); }});
+ 0x1: bc1t({{ cond = (getFPConditionCode(FCSR,CC) == 1); }});
+ }
+ }
+
+ 0x1: decode TF {
+ format BranchLikely {
+ 0x0: bc1fl({{ cond = (getFPConditionCode(FCSR,CC) == 0); }});
+ 0x1: bc1tl({{ cond = (getFPConditionCode(FCSR,CC) == 1); }});
+ }
+ }
+ }
+ }
+
+ 0x1: decode RS_HI {
+ 0x2: decode RS_LO {
+
+ //Table A-14 MIPS32 COP1 Encoding of Function Field When rs=S
+ //(( single-word ))
+ 0x0: decode FUNCTION_HI {
+ 0x0: decode FUNCTION_LO {
+ format FloatOp {
+ 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 FUNCTION_LO {
+ format Float64Op {
+ 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.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 FUNCTION_LO {
+ 0x1: decode MOVCF {
+ format FloatOp {
+ 0x0: movf_s({{if (getFPConditionCode(FCSR,CC) == 0) Fd = Fs;}});
+ 0x1: movt_s({{if (getFPConditionCode(FCSR,CC) == 1) 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);}});
+ }
+ }
+
+ 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;
+ }});
+ }
+ }
+
+ 0x6: decode FUNCTION_LO {
+ format FloatCompareOp {
+ 0x0: c_f_s({{ cond = 0; }});
+
+ 0x1: c_un_s({{
+ if (isnan(Fs.sf) || isnan(Ft.sf))
+ cond = 1;
+ else
+ cond = 0;
+ }});
+
+ 0x2: c_eq_s({{
+ if (isnan(Fs.sf) || isnan(Ft.sf))
+ cond = 0;
+ else
+ cond = (Fs.sf == Ft.sf);
+ }});
+
+ 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);
+ }});
+
+ 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 FUNCTION_HI {
+ 0x0: decode FUNCTION_LO {
+ format FloatOp {
+ 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 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.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 FUNCTION_LO {
+ 0x1: decode MOVCF {
+ format FloatOp {
+ 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: movz_d({{ if (Rt == 0) Fd.df = Fs.df; }});
+ 0x3: movn_d({{ if (Rt != 0) Fd.df = Fs.df; }});
+ }
+
+ format FloatOp {
+ 0x5: recip_d({{ Fd.df = 1 / Fs.df}});
+ 0x6: rsqrt_d({{ Fd.df = 1 / sqrt(Fs.df) }});
+ }
+ }
+
+ 0x4: decode FUNCTION_LO {
+ format FloatOp {
+ 0x0: cvt_s_d({{
+ Fd.uw = fpConvert(Fs.df, DOUBLE_TO_SINGLE);
+ }});
+
+ 0x4: cvt_w_d({{
+ Fd.uw = fpConvert(Fs.df, DOUBLE_TO_WORD);
+ }});
+
+ 0x5: cvt_l_d({{
+ 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 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);
+ }});
+ }
+
+ format Float64ConvertOp {
+ 0x26: cvt_ps_pw({{
+ Fd.ud = fpConvert(Fs.ud, WORD_TO_PS);
+ }});
+ }
+ }
+
+ //Table A-16 MIPS32 COP1 Encoding of Function Field When rs=L1
+ //Note: "1. Format type L is legal only if 64-bit floating point operations
+ //are enabled."
+ 0x5: decode FUNCTION_HI {
+ format 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);
+ }});
+
+ 0x26: cvt_ps_l({{
+ Fd.ud = fpConvert(Fs.ud, LONG_TO_PS);
+ }});
+ }
+ }
+
+ //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 FUNCTION_HI {
+ 0x0: decode FUNCTION_LO {
+ format Float64Op {
+ 0x0: add_ps({{
+ Fd1.sf = Fs1.sf + Ft2.sf;
+ Fd2.sf = Fs2.sf + Ft2.sf;
+ }});
+
+ 0x1: sub_ps({{
+ Fd1.sf = Fs1.sf - Ft2.sf;
+ Fd2.sf = Fs2.sf - Ft2.sf;
+ }});
+
+ 0x2: mul_ps({{
+ Fd1.sf = Fs1.sf * Ft2.sf;
+ Fd2.sf = Fs2.sf * Ft2.sf;
+ }});
+
+ 0x5: abs_ps({{
+ Fd1.sf = fabs(Fs1.sf);
+ Fd2.sf = fabs(Fs2.sf);
+ }});
+
+ 0x6: mov_ps({{
+ Fd1.sf = Fs1.sf;
+ Fd2.sf = Fs2.sf;
+ }});
+
+ 0x7: neg_ps({{
+ Fd1.sf = -1 * Fs1.sf;
+ Fd2.sf = -1 * Fs2.sf;
+ }});
+ }
+ }
+
+ 0x2: decode FUNCTION_LO {
+ 0x1: decode MOVCF {
+ format Float64Op {
+ 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 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 FUNCTION_LO {
+ 0x0: Float64Op::cvt_s_pu({{
+ Fd.uw = fpConvert(Fs2.uw, PU_TO_SINGLE);
+ }});
+ }
+
+ 0x5: decode FUNCTION_LO {
+ format Float64Op {
+ 0x0: cvt_s_pl({{
+ Fd.uw = fpConvert(Fs1.uw, PL_TO_SINGLE);
+ }});
+
+ 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);
+ }});
+ }
+ }
+ }
+ }
+ }
+ }
+
+ //Table A-19 MIPS32 COP2 Encoding of rs Field
+ 0x2: decode RS_MSB {
+ 0x0: decode RS_HI {
+ 0x0: decode RS_LO {
+ format WarnUnimpl {
+ 0x0: mfc2();
+ 0x2: cfc2();
+ 0x3: mfhc2();
+ 0x4: mtc2();
+ 0x6: ctc2();
+ 0x7: mftc2();
+ }
+ }
+
+ 0x1: decode ND {
+ 0x0: decode TF {
+ format WarnUnimpl {
+ 0x0: bc2f();
+ 0x1: bc2t();
+ }
+ }
+
+ 0x1: decode TF {
+ format WarnUnimpl {
+ 0x0: bc2fl();
+ 0x1: bc2tl();
+ }
+ }
+ }
+ }
+ }
+
+ //Table A-20 MIPS64 COP1X Encoding of Function Field 1
+ //Note: "COP1X instructions are legal only if 64-bit floating point
+ //operations are enabled."
+ 0x3: decode FUNCTION_HI {
+ 0x0: decode FUNCTION_LO {
+ format 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 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();
+ }
+
+ format FloatOp {
+ 0x3: WarnUnimpl::alnv_ps();
+
+ format BasicOp {
+ 0x4: decode FUNCTION_LO {
+ 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({{
+ 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 * Ft.sf) - Fr.sf; }});
+ 0x1: msub_d({{ Fd.df = (Fs.df * Ft.df) - Fr.df; }});
+ 0x6: msub_ps({{
+ 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 * Ft.sf) - Fr.sf; }});
+ 0x1: nmadd_d({{ Fd.df = (-1 * Fs.df * Ft.df) + Fr.df; }});
+ 0x6: nmadd_ps({{
+ 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 * Ft.sf) - Fr.sf; }});
+ 0x1: nmsub_d({{ Fd.df = (-1 * Fs.df * Ft.df) - Fr.df; }});
+ 0x6: nmsub_ps({{
+ Fd1.sf = -1 * ((Fs1.df * Ft1.df) - Fr1.df);
+ Fd2.sf = -1 * ((Fs2.df * Ft2.df) - Fr2.df);
+ }});
+ }
+ }
+ }
+ }
+
+ format BranchLikely {
+ 0x4: beql({{ cond = (Rs.sw == 0); }});
+ 0x5: bnel({{ cond = (Rs.sw != 0); }});
+ 0x6: blezl({{ cond = (Rs.sw <= 0); }});
+ 0x7: bgtzl({{ cond = (Rs.sw > 0); }});
+ }
+ }
+
+ 0x3: decode OPCODE_LO default FailUnimpl::reserved() {
+
+ //Table A-5 MIPS32 SPECIAL2 Encoding of Function Field
+ 0x4: decode FUNCTION_HI {
+
+ 0x0: decode FUNCTION_LO {
+ format IntOp {
+ 0x0: madd({{
+ int64_t temp1 = (int64_t) HI << 32 | LO;
+ temp1 = temp1 + (Rs.sw * Rt.sw);
+ HI = temp1<63:32>;
+ LO = temp1<31:0>;
+ }});
+
+ 0x1: maddu({{
+ int64_t temp1 = (int64_t) HI << 32 | LO;
+ temp1 = temp1 + (Rs.uw * Rt.uw);
+ HI = temp1<63:32>;
+ LO = temp1<31:0>;
+ }});
+
+ 0x2: mul({{ Rd.sw = Rs.sw * Rt.sw; }});
+
+ 0x4: msub({{
+ int64_t temp1 = (int64_t) HI << 32 | LO;
+ temp1 = temp1 - (Rs.sw * Rt.sw);
+ HI = temp1<63:32>;
+ LO = temp1<31:0>;
+ }});
+
+ 0x5: msubu({{
+ int64_t temp1 = (int64_t) HI << 32 | LO;
+ temp1 = temp1 - (Rs.uw * Rt.uw);
+ HI = temp1<63:32>;
+ LO = temp1<31:0>;
+ }});
+ }
+ }
+
+ 0x4: decode FUNCTION_LO {
+ format BasicOp {
+ 0x0: clz({{
+ int cnt = 0;
+ uint32_t mask = 0x80000000;
+ for (int i=0; i < 32; i++) {
+ if( (Rs & mask) == 0) {
+ cnt++;
+ } else {
+ break;
+ }
+ }
+ Rd.uw = cnt;
+ }});
+
+ 0x1: clo({{
+ int cnt = 0;
+ uint32_t mask = 0x80000000;
+ for (int i=0; i < 32; i++) {
+ if( (Rs & mask) != 0) {
+ cnt++;
+ } else {
+ break;
+ }
+ }
+ Rd.uw = cnt;
+ }});
+ }
+ }
+
+ 0x7: decode FUNCTION_LO {
+ 0x7: WarnUnimpl::sdbbp();
+ }
+ }
+
+ //Table A-6 MIPS32 SPECIAL3 Encoding of Function Field for Release 2 of the Architecture
+ 0x7: decode FUNCTION_HI {
+
+ 0x0: decode FUNCTION_LO {
+ format FailUnimpl {
+ 0x1: ext();
+ 0x4: ins();
+ }
+ }
+
+ 0x1: decode FUNCTION_LO {
+ format FailUnimpl {
+ 0x0: fork();
+ 0x1: yield();
+ }
+ }
+
+
+ //Table A-10 MIPS32 BSHFL Encoding of sa Field
+ 0x4: decode SA {
+
+ 0x02: FailUnimpl::wsbh();
+
+ format BasicOp {
+ 0x10: seb({{ Rd.sw = Rt.sw<7:0>}});
+ 0x18: seh({{ Rd.sw = Rt.sw<15:0>}});
+ }
+ }
+
+ 0x6: decode FUNCTION_LO {
+ 0x7: FailUnimpl::rdhwr();//{{ /*Rt = xc->hwRegs[RD];*/ }}
+ }
+ }
+ }
+
+ 0x4: decode OPCODE_LO default FailUnimpl::reserved() {
+ format LoadMemory {
+ 0x0: lb({{ Rt.sw = Mem.sb; }});
+ 0x1: lh({{ Rt.sw = Mem.sh; }});
+
+ 0x2: lwl({{
+ 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({{
+ 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; }});
+ }
+ }
+
+ 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({{
+ 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 {
+ 0x7: cache();
+ }
+
+ }
+
+ 0x6: decode OPCODE_LO default FailUnimpl::reserved() {
+ 0x0: LoadMemory::ll({{Rt.uw = Mem.uw}},mem_flags=LOCKED);
+
+ format LoadFloatMemory {
+ 0x1: lwc1({{ Ft.uw = Mem.uw; }});
+ 0x5: ldc1({{ Ft.ud = Mem.ud; }});
+ }
+ }
+
+
+ 0x7: decode OPCODE_LO default FailUnimpl::reserved() {
+ 0x0: StoreMemory::sc({{ Mem.uw = Rt.uw; Rt.uw = 1; }});
+
+ format StoreFloatMemory {
+ 0x1: swc1({{ Mem.uw = Ft.uw; }});
+ 0x5: sdc1({{ Mem.ud = Ft.ud; }});
+ }
+ }
+}
+
+
diff --git a/arch/mips/isa/formats/basic.isa b/src/arch/mips/isa/formats/basic.isa
index c02af7ddc..c02af7ddc 100644
--- a/arch/mips/isa/formats/basic.isa
+++ b/src/arch/mips/isa/formats/basic.isa
diff --git a/src/arch/mips/isa/formats/branch.isa b/src/arch/mips/isa/formats/branch.isa
new file mode 100644
index 000000000..8cfa37a20
--- /dev/null
+++ b/src/arch/mips/isa/formats/branch.isa
@@ -0,0 +1,324 @@
+// -*- mode:c++ -*-
+
+////////////////////////////////////////////////////////////////////
+//
+// Control transfer instructions
+//
+
+output header {{
+
+#include <iostream>
+ using namespace std;
+
+ /**
+ * Base class for instructions whose disassembly is not purely a
+ * function of the machine instruction (i.e., it depends on the
+ * PC). This class overrides the disassemble() method to check
+ * the PC and symbol table values before re-using a cached
+ * disassembly string. This is necessary for branches and jumps,
+ * where the disassembly string includes the target address (which
+ * may depend on the PC and/or symbol table).
+ */
+ class PCDependentDisassembly : public MipsStaticInst
+ {
+ protected:
+ /// Cached program counter from last disassembly
+ mutable Addr cachedPC;
+
+ /// Cached symbol table pointer from last disassembly
+ mutable const SymbolTable *cachedSymtab;
+
+ /// Constructor
+ PCDependentDisassembly(const char *mnem, MachInst _machInst,
+ OpClass __opClass)
+ : MipsStaticInst(mnem, _machInst, __opClass),
+ cachedPC(0), cachedSymtab(0)
+ {
+ }
+
+ const std::string &
+ disassemble(Addr pc, const SymbolTable *symtab) const;
+ };
+
+ /**
+ * Base class for branches (PC-relative control transfers),
+ * conditional or unconditional.
+ */
+ class Branch : public PCDependentDisassembly
+ {
+ protected:
+ /// target address (signed) Displacement .
+ int32_t disp;
+
+ /// Constructor.
+ Branch(const char *mnem, MachInst _machInst, OpClass __opClass)
+ : PCDependentDisassembly(mnem, _machInst, __opClass),
+ disp(OFFSET << 2)
+ {
+ //If Bit 17 is 1 then Sign Extend
+ if ( (disp & 0x00020000) > 0 ) {
+ disp |= 0xFFFE0000;
+ }
+ }
+
+ Addr branchTarget(Addr branchPC) const;
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+
+ /**
+ * Base class for branch likely branches (PC-relative control transfers),
+ */
+ class BranchLikely : public PCDependentDisassembly
+ {
+ protected:
+ /// target address (signed) Displacement .
+ int32_t disp;
+
+ /// Constructor.
+ BranchLikely(const char *mnem, MachInst _machInst, OpClass __opClass)
+ : PCDependentDisassembly(mnem, _machInst, __opClass),
+ disp(OFFSET << 2)
+ {
+
+ }
+
+ Addr branchTarget(Addr branchPC) const;
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+
+ /**
+ * Base class for jumps (register-indirect control transfers). In
+ * the Mips ISA, these are always unconditional.
+ */
+ class Jump : public PCDependentDisassembly
+ {
+ protected:
+
+ /// Displacement to target address (signed).
+ int32_t disp;
+
+ uint32_t target;
+
+ public:
+ /// Constructor
+ Jump(const char *mnem, MachInst _machInst, OpClass __opClass)
+ : PCDependentDisassembly(mnem, _machInst, __opClass),
+ disp(JMPTARG << 2)
+ {
+ }
+
+ Addr branchTarget(ExecContext *xc) const;
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+}};
+
+output decoder {{
+ Addr
+ Branch::branchTarget(Addr branchPC) const
+ {
+ return branchPC + 4 + disp;
+ }
+
+ Addr
+ BranchLikely::branchTarget(Addr branchPC) const
+ {
+ return branchPC + 4 + disp;
+ }
+
+ Addr
+ Jump::branchTarget(ExecContext *xc) const
+ {
+ Addr NPC = xc->readPC() + 4;
+ uint64_t Rb = xc->readIntReg(_srcRegIdx[0]);
+ return (Rb & ~3) | (NPC & 1);
+ }
+
+ const std::string &
+ PCDependentDisassembly::disassemble(Addr pc,
+ const SymbolTable *symtab) const
+ {
+ if (!cachedDisassembly ||
+ pc != cachedPC || symtab != cachedSymtab)
+ {
+ if (cachedDisassembly)
+ delete cachedDisassembly;
+
+ cachedDisassembly =
+ new std::string(generateDisassembly(pc, symtab));
+ cachedPC = pc;
+ cachedSymtab = symtab;
+ }
+
+ return *cachedDisassembly;
+ }
+
+ std::string
+ Branch::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+ {
+ std::stringstream ss;
+
+ ccprintf(ss, "%-10s ", mnemonic);
+
+ // There's only one register arg (RA), but it could be
+ // either a source (the condition for conditional
+ // branches) or a destination (the link reg for
+ // unconditional branches)
+ if (_numSrcRegs == 1) {
+ printReg(ss, _srcRegIdx[0]);
+ ss << ",";
+ } else if(_numSrcRegs == 2) {
+ printReg(ss, _srcRegIdx[0]);
+ ss << ",";
+ printReg(ss, _srcRegIdx[1]);
+ ss << ",";
+ }
+
+ Addr target = pc + 4 + disp;
+
+ std::string str;
+ if (symtab && symtab->findSymbol(target, str))
+ ss << str;
+ 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();
+ }
+
+ std::string
+ BranchLikely::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+ {
+ std::stringstream ss;
+
+ ccprintf(ss, "%-10s ", mnemonic);
+
+ // There's only one register arg (RA), but it could be
+ // either a source (the condition for conditional
+ // branches) or a destination (the link reg for
+ // unconditional branches)
+ if (_numSrcRegs > 0) {
+ printReg(ss, _srcRegIdx[0]);
+ ss << ",";
+ }
+ else if (_numDestRegs > 0) {
+ printReg(ss, _destRegIdx[0]);
+ ss << ",";
+ }
+
+ Addr target = pc + 4 + disp;
+
+ std::string str;
+ if (symtab && symtab->findSymbol(target, str))
+ ss << str;
+ else
+ ccprintf(ss, "0x%x", target);
+
+ return ss.str();
+ }
+
+ std::string
+ Jump::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+ {
+ std::stringstream ss;
+
+ ccprintf(ss, "%-10s ", mnemonic);
+
+ if ( mnemonic == "jal" ) {
+ Addr npc = pc + 4;
+ ccprintf(ss,"0x%x",(npc & 0xF0000000) | disp);
+ } else if (_numSrcRegs == 0) {
+ std::string str;
+ if (symtab && symtab->findSymbol(disp, str))
+ ss << str;
+ else
+ ccprintf(ss, "0x%x", disp);
+ } else if (_numSrcRegs == 1) {
+ printReg(ss, _srcRegIdx[0]);
+ } else if(_numSrcRegs == 2) {
+ printReg(ss, _srcRegIdx[0]);
+ ss << ",";
+ printReg(ss, _srcRegIdx[1]);
+ } else {
+ panic(">= 3 Source Registers!!!");
+ }
+
+ return ss.str();
+ }
+}};
+
+def format Branch(code,*flags) {{
+ #Add Link Code if Link instruction
+ strlen = len(name)
+ if name[strlen-2:] == 'al':
+ code += 'R31 = NNPC;\n'
+
+ #Condition code
+ code = 'bool cond;\n' + code
+ code += 'if (cond) {\n'
+ code += ' NNPC = NPC + disp;\n'
+ code += '} else {\n'
+ code += ' NNPC = NNPC;\n'
+ code += '} \n'
+
+ iop = InstObjParams(name, Name, 'Branch', CodeBlock(code),
+ ('IsDirectControl', 'IsCondControl'))
+
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ decode_block = BasicDecode.subst(iop)
+ exec_output = BasicExecute.subst(iop)
+}};
+
+
+def format BranchLikely(code,*flags) {{
+ #Add Link Code if Link instruction
+ strlen = len(name)
+ if name[strlen-3:] == 'all':
+ code += 'R31 = NNPC;\n'
+
+ #Condition code
+ code = 'bool cond;\n' + code
+ code += 'if (cond) {'
+ code += 'NNPC = NPC + disp;\n'
+ code += '} \n'
+
+
+ iop = InstObjParams(name, Name, 'Branch', CodeBlock(code),
+ ('IsDirectControl', 'IsCondControl','IsCondDelaySlot'))
+
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ decode_block = BasicDecode.subst(iop)
+ exec_output = BasicExecute.subst(iop)
+}};
+
+def format Jump(code,*flags) {{
+ #Add Link Code if Link instruction
+ strlen = len(name)
+ if strlen > 1 and name[1:] == 'al':
+ code = 'R31 = NNPC;\n' + code
+
+
+ iop = InstObjParams(name, Name, 'Jump', CodeBlock(code),\
+ ('IsIndirectControl', 'IsUncondControl'))
+
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ decode_block = BasicDecode.subst(iop)
+ exec_output = BasicExecute.subst(iop)
+}};
+
+
+
+
diff --git a/src/arch/mips/isa/formats/formats.isa b/src/arch/mips/isa/formats/formats.isa
new file mode 100644
index 000000000..7d493ffae
--- /dev/null
+++ b/src/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/src/arch/mips/isa/formats/fp.isa b/src/arch/mips/isa/formats/fp.isa
new file mode 100644
index 000000000..9f2c24755
--- /dev/null
+++ b/src/arch/mips/isa/formats/fp.isa
@@ -0,0 +1,109 @@
+// -*- mode:c++ -*-
+
+////////////////////////////////////////////////////////////////////
+//
+// Floating Point operate instructions
+//
+
+output header {{
+ /**
+ * Base class for FP operations.
+ */
+ class FPOp : public MipsStaticInst
+ {
+ protected:
+
+ /// Constructor
+ FPOp(const char *mnem, MachInst _machInst, OpClass __opClass) : MipsStaticInst(mnem, _machInst, __opClass)
+ {
+ }
+
+ std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+}};
+
+output decoder {{
+ std::string FPOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+ {
+ return "Disassembly of integer instruction\n";
+ }
+}};
+
+
+// Primary format for float operate instructions:
+def format FloatOp(code, *flags) {{
+ iop = InstObjParams(name, Name, 'MipsStaticInst', CodeBlock(code), flags)
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ decode_block = BasicDecode.subst(iop)
+ exec_output = BasicExecute.subst(iop)
+}};
+
+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)
+ decoder_output = BasicConstructor.subst(iop)
+ 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/src/arch/mips/isa/formats/int.isa b/src/arch/mips/isa/formats/int.isa
new file mode 100644
index 000000000..7d38b9ff5
--- /dev/null
+++ b/src/arch/mips/isa/formats/int.isa
@@ -0,0 +1,131 @@
+// -*- mode:c++ -*-
+
+////////////////////////////////////////////////////////////////////
+//
+// Integer operate instructions
+//
+
+//Outputs to decoder.hh
+output header {{
+#include <iostream>
+ using namespace std;
+ /**
+ * Base class for integer operations.
+ */
+ class IntOp : public MipsStaticInst
+ {
+ protected:
+
+ /// Constructor
+ IntOp(const char *mnem, MachInst _machInst, OpClass __opClass) :
+ MipsStaticInst(mnem, _machInst, __opClass)
+ {
+ }
+
+ std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+
+ class IntImmOp : public MipsStaticInst
+ {
+ protected:
+
+ int16_t imm;
+ int32_t sextImm;
+ uint32_t zextImm;
+
+ /// Constructor
+ IntImmOp(const char *mnem, MachInst _machInst, OpClass __opClass) :
+ MipsStaticInst(mnem, _machInst, __opClass),imm(INTIMM),
+ sextImm(INTIMM),zextImm(0x0000FFFF & INTIMM)
+ {
+ //If Bit 15 is 1 then Sign Extend
+ int32_t temp = sextImm & 0x00008000;
+ if (temp > 0 && mnemonic != "lui") {
+ sextImm |= 0xFFFF0000;
+ }
+ }
+
+ std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+
+
+ };
+
+}};
+
+//Outputs to decoder.cc
+output decoder {{
+ std::string IntOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+ {
+ std::stringstream ss;
+
+ ccprintf(ss, "%-10s ", mnemonic);
+
+ // just print the first dest... if there's a second one,
+ // it's generally implicit
+ if (_numDestRegs > 0) {
+ printReg(ss, _destRegIdx[0]);
+ ss << ",";
+ }
+
+ // just print the first two source regs... if there's
+ // a third one, it's a read-modify-write dest (Rc),
+ // e.g. for CMOVxx
+ if (_numSrcRegs > 0) {
+ printReg(ss, _srcRegIdx[0]);
+ }
+
+ if (_numSrcRegs > 1) {
+ ss << ",";
+ printReg(ss, _srcRegIdx[1]);
+ }
+
+ return ss.str();
+ }
+
+ std::string IntImmOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+ {
+ std::stringstream ss;
+
+ ccprintf(ss, "%-10s ", mnemonic);
+
+ if (_numDestRegs > 0) {
+ printReg(ss, _destRegIdx[0]);
+ }
+
+ ss << ",";
+
+ if (_numSrcRegs > 0) {
+ printReg(ss, _srcRegIdx[0]);
+ ss << ",";
+ }
+
+ if( mnemonic == "lui")
+ ccprintf(ss, "%08p ", sextImm);
+ else
+ ss << (int) sextImm;
+
+ return ss.str();
+ }
+
+}};
+
+//Used by decoder.isa
+def format IntOp(code, *opt_flags) {{
+ orig_code = code
+ cblk = CodeBlock(code)
+
+ # Figure out if we are creating a IntImmOp or a IntOp
+ # by looking at the instruction name
+ iop = InstObjParams(name, Name, 'IntOp', cblk, opt_flags)
+ strlen = len(name)
+ if name[strlen-1] == 'i' or name[strlen-2:] == 'iu':
+ iop = InstObjParams(name, Name, 'IntImmOp', cblk, opt_flags)
+
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ decode_block = OperateNopCheckDecode.subst(iop)
+ exec_output = BasicExecute.subst(iop)
+}};
+
+
+
diff --git a/src/arch/mips/isa/formats/mem.isa b/src/arch/mips/isa/formats/mem.isa
new file mode 100644
index 000000000..922cdb9a2
--- /dev/null
+++ b/src/arch/mips/isa/formats/mem.isa
@@ -0,0 +1,478 @@
+// -*- mode:c++ -*-
+
+// Copyright (c) 2003-2005 The Regents of The University of Michigan
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met: redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer;
+// redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution;
+// neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+////////////////////////////////////////////////////////////////////
+//
+// Memory-format instructions: LoadAddress, Load, Store
+//
+
+output header {{
+ /**
+ * Base class for general Mips memory-format instructions.
+ */
+ class Memory : public MipsStaticInst
+ {
+ protected:
+
+ /// Memory request flags. See mem_req_base.hh.
+ unsigned memAccessFlags;
+ /// Pointer to EAComp object.
+ const StaticInstPtr eaCompPtr;
+ /// Pointer to MemAcc object.
+ const StaticInstPtr memAccPtr;
+
+ /// Displacement for EA calculation (signed).
+ int32_t disp;
+
+ /// Constructor
+ Memory(const char *mnem, MachInst _machInst, OpClass __opClass,
+ StaticInstPtr _eaCompPtr = nullStaticInstPtr,
+ StaticInstPtr _memAccPtr = nullStaticInstPtr)
+ : MipsStaticInst(mnem, _machInst, __opClass),
+ memAccessFlags(0), eaCompPtr(_eaCompPtr), memAccPtr(_memAccPtr),
+ disp(OFFSET)
+ {
+ //If Bit 15 is 1 then Sign Extend
+ int32_t temp = disp & 0x00008000;
+
+ if (temp > 0) {
+ disp |= 0xFFFF0000;
+ }
+ }
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+
+ public:
+
+ const StaticInstPtr &eaCompInst() const { return eaCompPtr; }
+ const StaticInstPtr &memAccInst() const { return memAccPtr; }
+ };
+
+}};
+
+
+output decoder {{
+ std::string
+ Memory::generateDisassembly(Addr pc, const SymbolTable *symtab) const
+ {
+ return csprintf("%-10s %c%d,%d(r%d)", mnemonic,
+ flags[IsFloating] ? 'f' : 'r', RT, disp, RS);
+ }
+
+}};
+
+def format LoadAddress(code) {{
+ iop = InstObjParams(name, Name, 'MemoryDisp32', CodeBlock(code))
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ decode_block = BasicDecode.subst(iop)
+ exec_output = BasicExecute.subst(iop)
+}};
+
+
+def template LoadStoreDeclare {{
+ /**
+ * Static instruction class for "%(mnemonic)s".
+ */
+ class %(class_name)s : public %(base_class)s
+ {
+ protected:
+
+ /**
+ * "Fake" effective address computation class for "%(mnemonic)s".
+ */
+ class EAComp : public %(base_class)s
+ {
+ public:
+ /// Constructor
+ EAComp(MachInst machInst);
+
+ %(BasicExecDeclare)s
+ };
+
+ /**
+ * "Fake" memory access instruction class for "%(mnemonic)s".
+ */
+ class MemAcc : public %(base_class)s
+ {
+ public:
+ /// Constructor
+ MemAcc(MachInst machInst);
+
+ %(BasicExecDeclare)s
+ };
+
+ public:
+
+ /// Constructor.
+ %(class_name)s(MachInst machInst);
+
+ %(BasicExecDeclare)s
+
+ %(InitiateAccDeclare)s
+
+ %(CompleteAccDeclare)s
+ };
+}};
+
+
+def template InitiateAccDeclare {{
+ Fault initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const;
+}};
+
+
+def template CompleteAccDeclare {{
+ Fault completeAcc(uint8_t *, %(CPU_exec_context)s *, Trace::InstRecord *) const;
+}};
+
+
+def template LoadStoreConstructor {{
+ /** TODO: change op_class to AddrGenOp or something (requires
+ * creating new member of OpClass enum in op_class.hh, updating
+ * config files, etc.). */
+ inline %(class_name)s::EAComp::EAComp(MachInst machInst)
+ : %(base_class)s("%(mnemonic)s (EAComp)", machInst, IntAluOp)
+ {
+ %(ea_constructor)s;
+ }
+
+ inline %(class_name)s::MemAcc::MemAcc(MachInst machInst)
+ : %(base_class)s("%(mnemonic)s (MemAcc)", machInst, %(op_class)s)
+ {
+ %(memacc_constructor)s;
+ }
+
+ inline %(class_name)s::%(class_name)s(MachInst machInst)
+ : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
+ new EAComp(machInst), new MemAcc(machInst))
+ {
+ %(constructor)s;
+ }
+}};
+
+
+def template EACompExecute {{
+ Fault
+ %(class_name)s::EAComp::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ Addr EA;
+ Fault fault = NoFault;
+
+ %(fp_enable_check)s;
+ %(op_decl)s;
+ %(op_rd)s;
+ %(code)s;
+
+ if (fault == NoFault) {
+ %(op_wb)s;
+ xc->setEA(EA);
+ }
+
+ return fault;
+ }
+}};
+
+def template LoadMemAccExecute {{
+ Fault
+ %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ Addr EA;
+ Fault fault = NoFault;
+
+ %(fp_enable_check)s;
+ %(op_decl)s;
+ %(op_rd)s;
+ EA = xc->getEA();
+
+ if (fault == NoFault) {
+ fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags);
+ %(code)s;
+ }
+
+ if (fault == NoFault) {
+ %(op_wb)s;
+ }
+
+ return fault;
+ }
+}};
+
+
+def template LoadExecute {{
+ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ Addr EA;
+ Fault fault = NoFault;
+
+ %(fp_enable_check)s;
+ %(op_decl)s;
+ %(op_rd)s;
+ %(ea_code)s;
+
+ if (fault == NoFault) {
+ fault = xc->read(EA, (uint%(mem_acc_size)d_t&)Mem, memAccessFlags);
+ %(memacc_code)s;
+ }
+
+ if (fault == NoFault) {
+ %(op_wb)s;
+ }
+
+ return fault;
+ }
+}};
+
+
+def template LoadInitiateAcc {{
+ Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ Addr EA;
+ Fault fault = NoFault;
+
+ %(fp_enable_check)s;
+ %(op_src_decl)s;
+ %(op_rd)s;
+ %(ea_code)s;
+
+ if (fault == NoFault) {
+ fault = xc->read(EA, (uint%(mem_acc_size)d_t &)Mem, memAccessFlags);
+ }
+
+ return fault;
+ }
+}};
+
+
+def template LoadCompleteAcc {{
+ Fault %(class_name)s::completeAcc(uint8_t *data,
+ %(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ Fault fault = NoFault;
+
+ %(fp_enable_check)s;
+ %(op_decl)s;
+
+ memcpy(&Mem, data, sizeof(Mem));
+
+ if (fault == NoFault) {
+ %(memacc_code)s;
+ }
+
+ if (fault == NoFault) {
+ %(op_wb)s;
+ }
+
+ return fault;
+ }
+}};
+
+
+def template StoreMemAccExecute {{
+ Fault
+ %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ Addr EA;
+ Fault fault = NoFault;
+ uint64_t write_result = 0;
+
+ %(fp_enable_check)s;
+ %(op_decl)s;
+ %(op_rd)s;
+ EA = xc->getEA();
+
+ if (fault == NoFault) {
+ %(code)s;
+ }
+
+ if (fault == NoFault) {
+ fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
+ memAccessFlags, &write_result);
+ if (traceData) { traceData->setData(Mem); }
+ }
+
+ if (fault == NoFault) {
+ %(postacc_code)s;
+ }
+
+ if (fault == NoFault) {
+ %(op_wb)s;
+ }
+
+ return fault;
+ }
+}};
+
+
+def template StoreExecute {{
+ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ Addr EA;
+ Fault fault = NoFault;
+ uint64_t write_result = 0;
+
+ %(fp_enable_check)s;
+ %(op_decl)s;
+ %(op_rd)s;
+ %(ea_code)s;
+
+ if (fault == NoFault) {
+ %(memacc_code)s;
+ }
+
+ if (fault == NoFault) {
+ fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
+ memAccessFlags, &write_result);
+ if (traceData) { traceData->setData(Mem); }
+ }
+
+ if (fault == NoFault) {
+ %(postacc_code)s;
+ }
+
+ if (fault == NoFault) {
+ %(op_wb)s;
+ }
+
+ return fault;
+ }
+}};
+
+def template StoreInitiateAcc {{
+ Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ Addr EA;
+ Fault fault = NoFault;
+ uint64_t write_result = 0;
+
+ %(fp_enable_check)s;
+ %(op_decl)s;
+ %(op_rd)s;
+ %(ea_code)s;
+
+ if (fault == NoFault) {
+ %(memacc_code)s;
+ }
+
+ if (fault == NoFault) {
+ fault = xc->write((uint%(mem_acc_size)d_t&)Mem, EA,
+ memAccessFlags, &write_result);
+ if (traceData) { traceData->setData(Mem); }
+ }
+
+ return fault;
+ }
+}};
+
+
+def template StoreCompleteAcc {{
+ Fault %(class_name)s::completeAcc(uint8_t *data,
+ %(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ Fault fault = NoFault;
+ uint64_t write_result = 0;
+
+ %(fp_enable_check)s;
+ %(op_dest_decl)s;
+
+ memcpy(&write_result, data, sizeof(write_result));
+
+ if (fault == NoFault) {
+ %(postacc_code)s;
+ }
+
+ if (fault == NoFault) {
+ %(op_wb)s;
+ }
+
+ return fault;
+ }
+}};
+
+// load instructions use Rt as dest, so check for
+// Rt == 31 to detect nops
+def template LoadNopCheckDecode {{
+ {
+ MipsStaticInst *i = new %(class_name)s(machInst);
+ if (RT == 0) {
+ i = makeNop(i);
+ }
+ return i;
+ }
+}};
+
+def format LoadMemory(memacc_code, ea_code = {{ EA = Rs + disp; }},
+ mem_flags = [], inst_flags = []) {{
+ (header_output, decoder_output, decode_block, exec_output) = \
+ LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
+ decode_template = LoadNopCheckDecode,
+ exec_template_base = 'Load')
+}};
+
+
+def format StoreMemory(memacc_code, ea_code = {{ EA = Rs + disp; }},
+ mem_flags = [], inst_flags = []) {{
+ (header_output, decoder_output, decode_block, exec_output) = \
+ LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
+ exec_template_base = 'Store')
+}};
+
+//FP loads are offloaded to these formats for now ...
+def format 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 = BasicDecode,
+ exec_template_base = 'Load')
+}};
+
+
+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,
+ 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/src/arch/mips/isa/formats/noop.isa b/src/arch/mips/isa/formats/noop.isa
new file mode 100644
index 000000000..2aa4816e3
--- /dev/null
+++ b/src/arch/mips/isa/formats/noop.isa
@@ -0,0 +1,94 @@
+// -*- mode:c++ -*-
+
+////////////////////////////////////////////////////////////////////
+//
+// Nop
+//
+
+output header {{
+ /**
+ * Static instruction class for no-ops. This is a leaf class.
+ */
+ class Nop : public MipsStaticInst
+ {
+ /// Disassembly of original instruction.
+ const std::string originalDisassembly;
+
+ public:
+ /// Constructor
+ Nop(const std::string _originalDisassembly, MachInst _machInst)
+ : MipsStaticInst("nop", _machInst, No_OpClass),
+ originalDisassembly(_originalDisassembly)
+ {
+ flags[IsNop] = true;
+ }
+
+ ~Nop() { }
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+
+ %(BasicExecDeclare)s
+ };
+}};
+
+output decoder {{
+ std::string Nop::generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const
+ {
+#ifdef SS_COMPATIBLE_DISASSEMBLY
+ return originalDisassembly;
+#else
+ return csprintf("%-10s (%s)", "nop", originalDisassembly);
+#endif
+ }
+
+ /// Helper function for decoding nops. Substitute Nop object
+ /// for original inst passed in as arg (and delete latter).
+ inline
+ MipsStaticInst *
+ makeNop(MipsStaticInst *inst)
+ {
+ MipsStaticInst *nop = new Nop(inst->disassemble(0), inst->machInst);
+ delete inst;
+ return nop;
+ }
+}};
+
+output exec {{
+ Fault
+ Nop::execute(%(CPU_exec_context)s *, Trace::InstRecord *) const
+ {
+ return NoFault;
+ }
+}};
+
+// integer & FP operate instructions use RT as dest, so check for
+// RT == 0 to detect nops
+def template OperateNopCheckDecode {{
+ {
+ MipsStaticInst *i = new %(class_name)s(machInst);
+
+ //if (RD == 0) {
+ // i = makeNop(i);
+ //}
+
+ return i;
+ }
+}};
+
+
+// Like BasicOperate format, but generates NOP if RC/FC == 31
+def format BasicOperateWithNopCheck(code, *opt_args) {{
+ iop = InstObjParams(name, Name, 'MipsStaticInst', CodeBlock(code),
+ opt_args)
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ decode_block = OperateNopCheckDecode.subst(iop)
+ exec_output = BasicExecute.subst(iop)
+}};
+
+def format Nop() {{
+ decode_block = 'return new Nop(\"sll r0,r0,0\",machInst);\n'
+}};
+
diff --git a/arch/mips/isa/formats/tlbop.isa b/src/arch/mips/isa/formats/tlbop.isa
index f5e4076f2..f5e4076f2 100644
--- a/arch/mips/isa/formats/tlbop.isa
+++ b/src/arch/mips/isa/formats/tlbop.isa
diff --git a/arch/mips/isa/formats/trap.isa b/src/arch/mips/isa/formats/trap.isa
index 6884d4fa8..6884d4fa8 100644
--- a/arch/mips/isa/formats/trap.isa
+++ b/src/arch/mips/isa/formats/trap.isa
diff --git a/src/arch/mips/isa/formats/unimp.isa b/src/arch/mips/isa/formats/unimp.isa
new file mode 100644
index 000000000..ea0c5b15e
--- /dev/null
+++ b/src/arch/mips/isa/formats/unimp.isa
@@ -0,0 +1,171 @@
+// -*- mode:c++ -*-
+
+// Copyright (c) 2003-2005 The Regents of The University of Michigan
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met: redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer;
+// redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution;
+// neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+////////////////////////////////////////////////////////////////////
+//
+// Unimplemented instructions
+//
+
+output header {{
+ /**
+ * Static instruction class for unimplemented instructions that
+ * cause simulator termination. Note that these are recognized
+ * (legal) instructions that the simulator does not support; the
+ * 'Unknown' class is used for unrecognized/illegal instructions.
+ * This is a leaf class.
+ */
+ class FailUnimplemented : public MipsStaticInst
+ {
+ public:
+ /// Constructor
+ FailUnimplemented(const char *_mnemonic, MachInst _machInst)
+ : MipsStaticInst(_mnemonic, _machInst, No_OpClass)
+ {
+ // don't call execute() (which panics) if we're on a
+ // speculative path
+ flags[IsNonSpeculative] = true;
+ }
+
+ %(BasicExecDeclare)s
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+
+ /**
+ * Base class for unimplemented instructions that cause a warning
+ * to be printed (but do not terminate simulation). This
+ * implementation is a little screwy in that it will print a
+ * warning for each instance of a particular unimplemented machine
+ * instruction, not just for each unimplemented opcode. Should
+ * probably make the 'warned' flag a static member of the derived
+ * class.
+ */
+ class WarnUnimplemented : public MipsStaticInst
+ {
+ private:
+ /// Have we warned on this instruction yet?
+ mutable bool warned;
+
+ public:
+ /// Constructor
+ WarnUnimplemented(const char *_mnemonic, MachInst _machInst)
+ : MipsStaticInst(_mnemonic, _machInst, No_OpClass), warned(false)
+ {
+ // don't call execute() (which panics) if we're on a
+ // speculative path
+ flags[IsNonSpeculative] = true;
+ }
+
+ %(BasicExecDeclare)s
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+}};
+
+output decoder {{
+ std::string
+ FailUnimplemented::generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const
+ {
+ return csprintf("%-10s (unimplemented)", mnemonic);
+ }
+
+ std::string
+ WarnUnimplemented::generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const
+ {
+#ifdef SS_COMPATIBLE_DISASSEMBLY
+ return csprintf("%-10s", mnemonic);
+#else
+ return csprintf("%-10s (unimplemented)", mnemonic);
+#endif
+ }
+}};
+
+output exec {{
+ Fault
+ FailUnimplemented::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ panic("attempt to execute unimplemented instruction '%s' "
+ "(inst 0x%08x, opcode 0x%x, binary:%s)", mnemonic, machInst, OPCODE,
+ inst2string(machInst));
+ return new UnimplementedOpcodeFault;
+ }
+
+ Fault
+ WarnUnimplemented::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ if (!warned) {
+ warn("instruction '%s' unimplemented\n", mnemonic);
+ warned = true;
+ }
+
+ return NoFault;
+ }
+}};
+
+
+def format FailUnimpl() {{
+ iop = InstObjParams(name, 'FailUnimplemented')
+ decode_block = BasicDecodeWithMnemonic.subst(iop)
+}};
+
+def format WarnUnimpl() {{
+ iop = InstObjParams(name, 'WarnUnimplemented')
+ decode_block = BasicDecodeWithMnemonic.subst(iop)
+}};
+
+output header {{
+ /**
+ * Static instruction class for unknown (illegal) instructions.
+ * These cause simulator termination if they are executed in a
+ * non-speculative mode. This is a leaf class.
+ */
+ class Unknown : public MipsStaticInst
+ {
+ public:
+ /// Constructor
+ Unknown(MachInst _machInst)
+ : MipsStaticInst("unknown", _machInst, No_OpClass)
+ {
+ // don't call execute() (which panics) if we're on a
+ // speculative path
+ flags[IsNonSpeculative] = true;
+ }
+
+ %(BasicExecDeclare)s
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+ };
+}};
+
diff --git a/src/arch/mips/isa/formats/unknown.isa b/src/arch/mips/isa/formats/unknown.isa
new file mode 100644
index 000000000..6f88e630c
--- /dev/null
+++ b/src/arch/mips/isa/formats/unknown.isa
@@ -0,0 +1,79 @@
+// -*- mode:c++ -*-
+
+// Copyright (c) 2003-2005 The Regents of The University of Michigan
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met: redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer;
+// redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution;
+// neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+////////////////////////////////////////////////////////////////////
+//
+// Unknown instructions
+//
+
+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, binary:%s)",
+ "unknown", machInst, OPCODE, inst2string(machInst));
+ }
+}};
+
+output exec {{
+ Fault
+ Unknown::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ panic("attempt to execute unknown instruction "
+ "(inst 0x%08x, opcode 0x%x, binary: %s)", machInst, OPCODE, inst2string(machInst));
+ return new UnimplementedOpcodeFault;
+ }
+}};
+
+def format Unknown() {{
+ decode_block = 'return new Unknown(machInst);\n'
+}};
+
diff --git a/src/arch/mips/isa/formats/util.isa b/src/arch/mips/isa/formats/util.isa
new file mode 100644
index 000000000..615160931
--- /dev/null
+++ b/src/arch/mips/isa/formats/util.isa
@@ -0,0 +1,129 @@
+// -*- mode:c++ -*-
+
+let {{
+def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
+ postacc_code = '', base_class = 'Memory',
+ decode_template = BasicDecode, exec_template_base = ''):
+ # Make sure flags are in lists (convert to lists if not).
+ mem_flags = makeList(mem_flags)
+ inst_flags = makeList(inst_flags)
+
+ # add hook to get effective addresses into execution trace output.
+ ea_code += '\nif (traceData) { traceData->setAddr(EA); }\n'
+
+ # generate code block objects
+ ea_cblk = CodeBlock(ea_code)
+ memacc_cblk = CodeBlock(memacc_code)
+ postacc_cblk = CodeBlock(postacc_code)
+
+ # Some CPU models execute the memory operation as an atomic unit,
+ # while others want to separate them into an effective address
+ # computation and a memory access operation. As a result, we need
+ # to generate three StaticInst objects. Note that the latter two
+ # are nested inside the larger "atomic" one.
+
+ # generate InstObjParams for EAComp object
+ ea_iop = InstObjParams(name, Name, base_class, ea_cblk, inst_flags)
+
+ # generate InstObjParams for MemAcc object
+ memacc_iop = InstObjParams(name, Name, base_class, memacc_cblk, inst_flags)
+ # in the split execution model, the MemAcc portion is responsible
+ # for the post-access code.
+ memacc_iop.postacc_code = postacc_cblk.code
+
+ # generate InstObjParams for InitiateAcc, CompleteAcc object
+ # The code used depends on the template being used
+ if (exec_template_base == 'Load'):
+ initiateacc_cblk = CodeBlock(ea_code + memacc_code)
+ completeacc_cblk = CodeBlock(memacc_code + postacc_code)
+ elif (exec_template_base == 'Store'):
+ initiateacc_cblk = CodeBlock(ea_code + memacc_code)
+ completeacc_cblk = CodeBlock(postacc_code)
+ else:
+ initiateacc_cblk = ''
+ completeacc_cblk = ''
+
+ initiateacc_iop = InstObjParams(name, Name, base_class, initiateacc_cblk,
+ inst_flags)
+
+ completeacc_iop = InstObjParams(name, Name, base_class, completeacc_cblk,
+ inst_flags)
+
+ if (exec_template_base == 'Load'):
+ initiateacc_iop.ea_code = ea_cblk.code
+ initiateacc_iop.memacc_code = memacc_cblk.code
+ completeacc_iop.memacc_code = memacc_cblk.code
+ completeacc_iop.postacc_code = postacc_cblk.code
+ elif (exec_template_base == 'Store'):
+ initiateacc_iop.ea_code = ea_cblk.code
+ initiateacc_iop.memacc_code = memacc_cblk.code
+ completeacc_iop.postacc_code = postacc_cblk.code
+
+ # generate InstObjParams for unified execution
+ cblk = CodeBlock(ea_code + memacc_code + postacc_code)
+ iop = InstObjParams(name, Name, base_class, cblk, inst_flags)
+
+ iop.ea_constructor = ea_cblk.constructor
+ iop.ea_code = ea_cblk.code
+ iop.memacc_constructor = memacc_cblk.constructor
+ iop.memacc_code = memacc_cblk.code
+ iop.postacc_code = postacc_cblk.code
+
+ if mem_flags:
+ s = '\n\tmemAccessFlags = ' + string.join(mem_flags, '|') + ';'
+ iop.constructor += s
+ memacc_iop.constructor += s
+
+ # select templates
+ memAccExecTemplate = eval(exec_template_base + 'MemAccExecute')
+ fullExecTemplate = eval(exec_template_base + 'Execute')
+ initiateAccTemplate = eval(exec_template_base + 'InitiateAcc')
+ completeAccTemplate = eval(exec_template_base + 'CompleteAcc')
+
+ # (header_output, decoder_output, decode_block, exec_output)
+ return (LoadStoreDeclare.subst(iop), LoadStoreConstructor.subst(iop),
+ decode_template.subst(iop),
+ EACompExecute.subst(ea_iop)
+ + memAccExecTemplate.subst(memacc_iop)
+ + fullExecTemplate.subst(iop)
+ + initiateAccTemplate.subst(initiateacc_iop)
+ + completeAccTemplate.subst(completeacc_iop))
+}};
+
+
+output exec {{
+
+ using namespace MipsISA;
+
+ /// CLEAR ALL CPU INST/EXE HAZARDS
+ inline void
+ clear_exe_inst_hazards()
+ {
+ //CODE HERE
+ }
+
+
+ /// Check "FP enabled" machine status bit. Called when executing any FP
+ /// instruction in full-system mode.
+ /// @retval Full-system mode: NoFault if FP is enabled, FenFault
+ /// if not. Non-full-system mode: always returns NoFault.
+#if FULL_SYSTEM
+ inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc)
+ {
+ Fault fault = NoFault; // dummy... this ipr access should not fault
+ if (!Mips34k::ICSR_FPE(xc->readIpr(MipsISA::IPR_ICSR, fault))) {
+ fault = FloatEnableFault;
+ }
+ return fault;
+ }
+#else
+ inline Fault checkFpEnableFault(%(CPU_exec_context)s *xc)
+ {
+ return NoFault;
+ }
+#endif
+
+
+}};
+
+
diff --git a/src/arch/mips/isa/includes.isa b/src/arch/mips/isa/includes.isa
new file mode 100644
index 000000000..9c370fbe3
--- /dev/null
+++ b/src/arch/mips/isa/includes.isa
@@ -0,0 +1,48 @@
+////////////////////////////////////////////////////////////////////
+//
+// Output include file directives.
+//
+
+output header {{
+#include <sstream>
+#include <iostream>
+#include <iomanip>
+
+#include "cpu/static_inst.hh"
+#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>
+#endif
+
+#ifdef FULL_SYSTEM
+//#include "arch/alpha/pseudo_inst.hh"
+#endif
+#include "cpu/base.hh"
+#include "cpu/exetrace.hh"
+#include "sim/sim_exit.hh"
+
+using namespace MipsISA;
+}};
+
diff --git a/src/arch/mips/isa/main.isa b/src/arch/mips/isa/main.isa
new file mode 100644
index 000000000..e6f43c3e7
--- /dev/null
+++ b/src/arch/mips/isa/main.isa
@@ -0,0 +1,59 @@
+// -*- mode:c++ -*-
+
+// Copyright (c) 2003-2005 The Regents of The University of Michigan
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met: redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer;
+// redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution;
+// neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+////////////////////////////////////////////////////////////////////
+//
+// MIPS ISA description file.
+//
+////////////////////////////////////////////////////////////////////
+
+//Include the C++ include directives
+##include "includes.isa"
+
+////////////////////////////////////////////////////////////////////
+//
+// Namespace statement. Everything below this line will be in the
+// MipsISAInst namespace.
+//
+
+namespace MipsISA;
+
+//Include the bitfield definitions
+##include "bitfields.isa"
+
+//Include the operand_types and operand definitions
+##include "operands.isa"
+
+//Include the base class for mips instructions, and some support code
+##include "base.isa"
+
+//Include the definitions for the instruction formats
+##include "formats/formats.isa"
+
+//Include the decoder definition
+##include "decoder.isa"
diff --git a/src/arch/mips/isa/operands.isa b/src/arch/mips/isa/operands.isa
new file mode 100644
index 000000000..0f9c74b48
--- /dev/null
+++ b/src/arch/mips/isa/operands.isa
@@ -0,0 +1,61 @@
+def operand_types {{
+ 'sb' : ('signed int', 8),
+ 'ub' : ('unsigned int', 8),
+ 'sh' : ('signed int', 16),
+ 'uh' : ('unsigned int', 16),
+ 'sw' : ('signed int', 32),
+ 'uw' : ('unsigned int', 32),
+ 'sd' : ('signed int', 64),
+ 'ud' : ('unsigned int', 64),
+ 'sf' : ('float', 32),
+ 'df' : ('float', 64),
+ 'qf' : ('float', 128)
+}};
+
+def operands {{
+ #General Purpose Integer Reg Operands
+ 'Rd': ('IntReg', 'uw', 'RD', 'IsInteger', 1),
+ 'Rs': ('IntReg', 'uw', 'RS', 'IsInteger', 2),
+ 'Rt': ('IntReg', 'uw', 'RT', 'IsInteger', 3),
+
+ #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),
+
+ #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/src/arch/mips/isa_traits.cc b/src/arch/mips/isa_traits.cc
new file mode 100644
index 000000000..216a6e2ec
--- /dev/null
+++ b/src/arch/mips/isa_traits.cc
@@ -0,0 +1,229 @@
+/*
+ * Copyright (c) 2003-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "arch/mips/isa_traits.hh"
+#include "config/full_system.hh"
+#include "cpu/static_inst.hh"
+#include "sim/serialize.hh"
+#include "base/bitfield.hh"
+
+using namespace MipsISA;
+using namespace std;
+
+
+void
+MipsISA::copyRegs(ExecContext *src, ExecContext *dest)
+{
+ /*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);
+
+#if FULL_SYSTEM
+ copyIprs(xc);
+ #endif*/
+}
+
+void
+MipsISA::MiscRegFile::copyMiscRegs(ExecContext *xc)
+{
+ /*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*/
+}
+
+uint64_t
+MipsISA::fpConvert(double fp_val, ConvertType cvt_type)
+{
+
+ 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;
+
+ default:
+ panic("Invalid Floating Point Conversion Type (%d). See \"types.hh\" for List of Conversions\n",cvt_type);
+ return 0;
+ }
+}
+
+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;
+}
+
+double
+MipsISA::truncFP(double val)
+{
+ int trunc_val = (int) val;
+ return (double) trunc_val;
+}
+
+bool
+MipsISA::getFPConditionCode(uint32_t fcsr_reg, int cc)
+{
+ //uint32_t cc_bits = xc->readFloatReg(35);
+ return false;//regFile.floatRegfile.getConditionCode(cc);
+}
+
+uint32_t
+MipsISA::makeCCVector(uint32_t fcsr, int num, bool val)
+{
+ int shift = (num == 0) ? 22 : num + 23;
+
+ fcsr = fcsr | (val << shift);
+
+ return fcsr;
+}
+
+#if FULL_SYSTEM
+
+static inline Addr
+TruncPage(Addr addr)
+{ return addr & ~(MipsISA::PageBytes - 1); }
+
+static inline Addr
+RoundPage(Addr addr)
+{ return (addr + MipsISA::PageBytes - 1) & ~(MipsISA::PageBytes - 1); }
+#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)
+{
+ intRegFile.serialize(os);
+ //SERIALIZE_ARRAY(floatRegFile.q, NumFloatRegs);
+ //SERIALIZE_SCALAR(miscRegs.fpcr);
+ //SERIALIZE_SCALAR(miscRegs.uniq);
+ //SERIALIZE_SCALAR(miscRegs.lock_flag);
+ //SERIALIZE_SCALAR(miscRegs.lock_addr);
+ SERIALIZE_SCALAR(pc);
+ SERIALIZE_SCALAR(npc);
+ SERIALIZE_SCALAR(nnpc);
+#if FULL_SYSTEM
+ SERIALIZE_ARRAY(palregs, NumIntRegs);
+ SERIALIZE_ARRAY(ipr, NumInternalProcRegs);
+ SERIALIZE_SCALAR(intrflag);
+ SERIALIZE_SCALAR(pal_shadow);
+#endif
+}
+
+
+void
+RegFile::unserialize(Checkpoint *cp, const std::string &section)
+{
+ intRegFile.unserialize(cp, section);
+ //UNSERIALIZE_ARRAY(floatRegFile.q, NumFloatRegs);
+ //UNSERIALIZE_SCALAR(miscRegs.fpcr);
+ //UNSERIALIZE_SCALAR(miscRegs.uniq);
+ //UNSERIALIZE_SCALAR(miscRegs.lock_flag);
+ //UNSERIALIZE_SCALAR(miscRegs.lock_addr);
+ UNSERIALIZE_SCALAR(pc);
+ UNSERIALIZE_SCALAR(npc);
+ UNSERIALIZE_SCALAR(nnpc);
+#if FULL_SYSTEM
+ UNSERIALIZE_ARRAY(palregs, NumIntRegs);
+ UNSERIALIZE_ARRAY(ipr, NumInternalProcRegs);
+ UNSERIALIZE_SCALAR(intrflag);
+ UNSERIALIZE_SCALAR(pal_shadow);
+#endif
+}
+
+
+#if FULL_SYSTEM
+void
+PTE::serialize(std::ostream &os)
+{
+ SERIALIZE_SCALAR(tag);
+ SERIALIZE_SCALAR(ppn);
+ SERIALIZE_SCALAR(xre);
+ SERIALIZE_SCALAR(xwe);
+ SERIALIZE_SCALAR(asn);
+ SERIALIZE_SCALAR(asma);
+ SERIALIZE_SCALAR(fonr);
+ SERIALIZE_SCALAR(fonw);
+ SERIALIZE_SCALAR(valid);
+}
+
+
+void
+PTE::unserialize(Checkpoint *cp, const std::string &section)
+{
+ UNSERIALIZE_SCALAR(tag);
+ UNSERIALIZE_SCALAR(ppn);
+ UNSERIALIZE_SCALAR(xre);
+ UNSERIALIZE_SCALAR(xwe);
+ UNSERIALIZE_SCALAR(asn);
+ UNSERIALIZE_SCALAR(asma);
+ UNSERIALIZE_SCALAR(fonr);
+ UNSERIALIZE_SCALAR(fonw);
+ UNSERIALIZE_SCALAR(valid);
+}
+
+#endif //FULL_SYSTEM
diff --git a/src/arch/mips/isa_traits.hh b/src/arch/mips/isa_traits.hh
new file mode 100644
index 000000000..148c405df
--- /dev/null
+++ b/src/arch/mips/isa_traits.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_ISA_TRAITS_HH__
+#define __ARCH_MIPS_ISA_TRAITS_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"
+
+#include <vector>
+
+class FastCPU;
+class FullCPU;
+class Checkpoint;
+class ExecContext;
+
+namespace LittleEndianGuest {};
+
+#define TARGET_MIPS
+
+class StaticInst;
+class StaticInstPtr;
+
+namespace MIPS34K {
+int DTB_ASN_ASN(uint64_t reg);
+int ITB_ASN_ASN(uint64_t reg);
+};
+
+#if !FULL_SYSTEM
+class SyscallReturn {
+ public:
+ template <class T>
+ SyscallReturn(T v, bool s)
+ {
+ retval = (uint32_t)v;
+ success = s;
+ }
+
+ template <class T>
+ SyscallReturn(T v)
+ {
+ success = (v >= 0);
+ retval = (uint32_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 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());
+ }
+ }
+
+ StaticInstPtr decodeInst(ExtMachInst);
+
+ 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
+ }
+
+ /**
+ * 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;
+
+ void copyRegs(ExecContext *src, ExecContext *dest);
+
+ 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
+
+ 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
+
+ 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;
+ }
+
+};
+
+#if FULL_SYSTEM
+
+#include "arch/mips/mips34k.hh"
+
+#endif
+
+using namespace MipsISA;
+
+#endif // __ARCH_MIPS_ISA_TRAITS_HH__
diff --git a/src/arch/mips/linux/linux.cc b/src/arch/mips/linux/linux.cc
new file mode 100644
index 000000000..26e3dd479
--- /dev/null
+++ b/src/arch/mips/linux/linux.cc
@@ -0,0 +1,72 @@
+/*
+ * 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.
+ *
+ * Authors: Korey Sewell
+ */
+
+#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/src/arch/mips/linux/linux.hh b/src/arch/mips/linux/linux.hh
new file mode 100644
index 000000000..f85935bb9
--- /dev/null
+++ b/src/arch/mips/linux/linux.hh
@@ -0,0 +1,126 @@
+/*
+ * 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.
+ *
+ * Authors: Korey Sewell
+ */
+
+#ifndef __ARCH_MIPS_LINUX_LINUX_HH__
+#define __ARCH_MIPS_LINUX_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/src/arch/mips/linux/process.cc b/src/arch/mips/linux/process.cc
new file mode 100644
index 000000000..ffc5da2e1
--- /dev/null
+++ b/src/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/src/arch/mips/linux/process.hh b/src/arch/mips/linux/process.hh
new file mode 100644
index 000000000..68da3227b
--- /dev/null
+++ b/src/arch/mips/linux/process.hh
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2003-2004 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __MIPS_LINUX_PROCESS_HH__
+#define __MIPS_LINUX_PROCESS_HH__
+
+#include "arch/mips/process.hh"
+
+
+/// A process with emulated Mips/Linux syscalls.
+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);
+
+ virtual SyscallDesc* getDesc(int callnum);
+
+ /// The target system's hostname.
+ static const char *hostname;
+
+ /// Array of syscall descriptors, indexed by call number.
+ static SyscallDesc syscallDescs[];
+
+ const int Num_Syscall_Descs;
+};
+
+
+#endif // __MIPS_LINUX_PROCESS_HH__
diff --git a/src/arch/mips/process.cc b/src/arch/mips/process.cc
new file mode 100644
index 000000000..7831551be
--- /dev/null
+++ b/src/arch/mips/process.cc
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2003-2004 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "arch/mips/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;
+
+
+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)
+{
+ 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, system,
+ stdin_fd, stdout_fd, stderr_fd,
+ argv, envp);
+ break;
+
+ default:
+ fatal("Unknown/unsupported operating system.");
+ }
+
+ if (process == NULL)
+ fatal("Unknown error creating process object.");
+ return process;
+}
+
+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/src/arch/mips/process.hh b/src/arch/mips/process.hh
new file mode 100644
index 000000000..2a13dc955
--- /dev/null
+++ b/src/arch/mips/process.hh
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2003-2004 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __MIPS_PROCESS_HH__
+#define __MIPS_PROCESS_HH__
+
+#include <string>
+#include <vector>
+#include "sim/process.hh"
+
+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);
+
+};
+
+
+#endif // __MIPS_PROCESS_HH__
diff --git a/src/arch/mips/regfile/float_regfile.hh b/src/arch/mips/regfile/float_regfile.hh
new file mode 100644
index 000000000..15c6f97f4
--- /dev/null
+++ b/src/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/src/arch/mips/regfile/int_regfile.hh b/src/arch/mips/regfile/int_regfile.hh
new file mode 100644
index 000000000..3cd87734d
--- /dev/null
+++ b/src/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/src/arch/mips/regfile/misc_regfile.hh b/src/arch/mips/regfile/misc_regfile.hh
new file mode 100644
index 000000000..9f054e5f7
--- /dev/null
+++ b/src/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/src/arch/mips/regfile/regfile.hh b/src/arch/mips/regfile/regfile.hh
new file mode 100644
index 000000000..e77571b33
--- /dev/null
+++ b/src/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/stacktrace.hh b/src/arch/mips/stacktrace.hh
index 1d8d97a79..1d8d97a79 100644
--- a/arch/mips/stacktrace.hh
+++ b/src/arch/mips/stacktrace.hh
diff --git a/src/arch/mips/types.hh b/src/arch/mips/types.hh
new file mode 100644
index 000000000..4d5fb3456
--- /dev/null
+++ b/src/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/src/arch/mips/utility.hh b/src/arch/mips/utility.hh
new file mode 100644
index 000000000..5c7dc3ea4
--- /dev/null
+++ b/src/arch/mips/utility.hh
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ *
+ * Authors: Nathan Binkert
+ * Steve Reinhardt
+ */
+
+#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/src/arch/sparc/SConscript b/src/arch/sparc/SConscript
new file mode 100644
index 000000000..66435c239
--- /dev/null
+++ b/src/arch/sparc/SConscript
@@ -0,0 +1,80 @@
+# -*- mode:python -*-
+
+# Copyright (c) 2004-2005 The Regents of The University of Michigan
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met: redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer;
+# redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution;
+# neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import os
+import sys
+from os.path import isdir
+
+# Import build environment variable from SConstruct.
+Import('env')
+
+###################################################
+#
+# Define needed sources.
+#
+###################################################
+
+# Base sources used by all configurations.
+base_sources = Split('''
+ faults.cc
+ isa_traits.cc
+ ''')
+
+# Full-system sources
+full_system_sources = Split('''
+ vtophys.cc
+ ua2005.cc
+ ''')
+
+# Syscall emulation (non-full-system) sources
+syscall_emulation_sources = Split('''
+ linux/linux.cc
+ linux/process.cc
+ solaris/solaris.cc
+ solaris/process.cc
+ process.cc
+ ''')
+
+sources = base_sources
+
+if env['FULL_SYSTEM']:
+ sources += full_system_sources
+else:
+ sources += syscall_emulation_sources
+
+# Convert file names to SCons File objects. This takes care of the
+# path relative to the top of the directory tree.
+sources = [File(s) for s in sources]
+
+# Add in files generated by the ISA description.
+isa_desc_files = env.ISADesc('isa/main.isa')
+# Only non-header files need to be compiled.
+isa_desc_sources = [f for f in isa_desc_files if not f.path.endswith('.hh')]
+sources += isa_desc_sources
+
+Return('sources')
diff --git a/src/arch/sparc/faults.cc b/src/arch/sparc/faults.cc
new file mode 100644
index 000000000..67a89ab0e
--- /dev/null
+++ b/src/arch/sparc/faults.cc
@@ -0,0 +1,255 @@
+/*
+ * Copyright (c) 2003-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "arch/sparc/faults.hh"
+#include "cpu/exec_context.hh"
+#include "cpu/base.hh"
+#include "base/trace.hh"
+
+namespace SparcISA
+{
+
+FaultName InternalProcessorError::_name = "intprocerr";
+TrapType InternalProcessorError::_trapType = 0x029;
+FaultPriority InternalProcessorError::_priority = 4;
+FaultStat InternalProcessorError::_count;
+
+FaultName MemAddressNotAligned::_name = "unalign";
+TrapType MemAddressNotAligned::_trapType = 0x034;
+FaultPriority MemAddressNotAligned::_priority = 10;
+FaultStat MemAddressNotAligned::_count;
+
+FaultName PowerOnReset::_name = "pow_reset";
+TrapType PowerOnReset::_trapType = 0x001;
+FaultPriority PowerOnReset::_priority = 0;
+FaultStat PowerOnReset::_count;
+
+FaultName WatchDogReset::_name = "watch_dog_reset";
+TrapType WatchDogReset::_trapType = 0x002;
+FaultPriority WatchDogReset::_priority = 1;
+FaultStat WatchDogReset::_count;
+
+FaultName ExternallyInitiatedReset::_name = "extern_reset";
+TrapType ExternallyInitiatedReset::_trapType = 0x003;
+FaultPriority ExternallyInitiatedReset::_priority = 1;
+FaultStat ExternallyInitiatedReset::_count;
+
+FaultName SoftwareInitiatedReset::_name = "software_reset";
+TrapType SoftwareInitiatedReset::_trapType = 0x004;
+FaultPriority SoftwareInitiatedReset::_priority = 1;
+FaultStat SoftwareInitiatedReset::_count;
+
+FaultName REDStateException::_name = "red_counte";
+TrapType REDStateException::_trapType = 0x005;
+FaultPriority REDStateException::_priority = 1;
+FaultStat REDStateException::_count;
+
+FaultName InstructionAccessException::_name = "inst_access";
+TrapType InstructionAccessException::_trapType = 0x008;
+FaultPriority InstructionAccessException::_priority = 5;
+FaultStat InstructionAccessException::_count;
+
+FaultName InstructionAccessMMUMiss::_name = "inst_mmu";
+TrapType InstructionAccessMMUMiss::_trapType = 0x009;
+FaultPriority InstructionAccessMMUMiss::_priority = 2;
+FaultStat InstructionAccessMMUMiss::_count;
+
+FaultName InstructionAccessError::_name = "inst_error";
+TrapType InstructionAccessError::_trapType = 0x00A;
+FaultPriority InstructionAccessError::_priority = 3;
+FaultStat InstructionAccessError::_count;
+
+FaultName IllegalInstruction::_name = "illegal_inst";
+TrapType IllegalInstruction::_trapType = 0x010;
+FaultPriority IllegalInstruction::_priority = 7;
+FaultStat IllegalInstruction::_count;
+
+FaultName PrivilegedOpcode::_name = "priv_opcode";
+TrapType PrivilegedOpcode::_trapType = 0x011;
+FaultPriority PrivilegedOpcode::_priority = 6;
+FaultStat PrivilegedOpcode::_count;
+
+FaultName UnimplementedLDD::_name = "unimp_ldd";
+TrapType UnimplementedLDD::_trapType = 0x012;
+FaultPriority UnimplementedLDD::_priority = 6;
+FaultStat UnimplementedLDD::_count;
+
+FaultName UnimplementedSTD::_name = "unimp_std";
+TrapType UnimplementedSTD::_trapType = 0x013;
+FaultPriority UnimplementedSTD::_priority = 6;
+FaultStat UnimplementedSTD::_count;
+
+FaultName FpDisabled::_name = "fp_disabled";
+TrapType FpDisabled::_trapType = 0x020;
+FaultPriority FpDisabled::_priority = 8;
+FaultStat FpDisabled::_count;
+
+FaultName FpExceptionIEEE754::_name = "fp_754";
+TrapType FpExceptionIEEE754::_trapType = 0x021;
+FaultPriority FpExceptionIEEE754::_priority = 11;
+FaultStat FpExceptionIEEE754::_count;
+
+FaultName FpExceptionOther::_name = "fp_other";
+TrapType FpExceptionOther::_trapType = 0x022;
+FaultPriority FpExceptionOther::_priority = 11;
+FaultStat FpExceptionOther::_count;
+
+FaultName TagOverflow::_name = "tag_overflow";
+TrapType TagOverflow::_trapType = 0x023;
+FaultPriority TagOverflow::_priority = 14;
+FaultStat TagOverflow::_count;
+
+FaultName DivisionByZero::_name = "div_by_zero";
+TrapType DivisionByZero::_trapType = 0x028;
+FaultPriority DivisionByZero::_priority = 15;
+FaultStat DivisionByZero::_count;
+
+FaultName DataAccessException::_name = "data_access";
+TrapType DataAccessException::_trapType = 0x030;
+FaultPriority DataAccessException::_priority = 12;
+FaultStat DataAccessException::_count;
+
+FaultName DataAccessMMUMiss::_name = "data_mmu";
+TrapType DataAccessMMUMiss::_trapType = 0x031;
+FaultPriority DataAccessMMUMiss::_priority = 12;
+FaultStat DataAccessMMUMiss::_count;
+
+FaultName DataAccessError::_name = "data_error";
+TrapType DataAccessError::_trapType = 0x032;
+FaultPriority DataAccessError::_priority = 12;
+FaultStat DataAccessError::_count;
+
+FaultName DataAccessProtection::_name = "data_protection";
+TrapType DataAccessProtection::_trapType = 0x033;
+FaultPriority DataAccessProtection::_priority = 12;
+FaultStat DataAccessProtection::_count;
+
+FaultName LDDFMemAddressNotAligned::_name = "unalign_lddf";
+TrapType LDDFMemAddressNotAligned::_trapType = 0x035;
+FaultPriority LDDFMemAddressNotAligned::_priority = 10;
+FaultStat LDDFMemAddressNotAligned::_count;
+
+FaultName STDFMemAddressNotAligned::_name = "unalign_stdf";
+TrapType STDFMemAddressNotAligned::_trapType = 0x036;
+FaultPriority STDFMemAddressNotAligned::_priority = 10;
+FaultStat STDFMemAddressNotAligned::_count;
+
+FaultName PrivilegedAction::_name = "priv_action";
+TrapType PrivilegedAction::_trapType = 0x037;
+FaultPriority PrivilegedAction::_priority = 11;
+FaultStat PrivilegedAction::_count;
+
+FaultName LDQFMemAddressNotAligned::_name = "unalign_ldqf";
+TrapType LDQFMemAddressNotAligned::_trapType = 0x038;
+FaultPriority LDQFMemAddressNotAligned::_priority = 10;
+FaultStat LDQFMemAddressNotAligned::_count;
+
+FaultName STQFMemAddressNotAligned::_name = "unalign_stqf";
+TrapType STQFMemAddressNotAligned::_trapType = 0x039;
+FaultPriority STQFMemAddressNotAligned::_priority = 10;
+FaultStat STQFMemAddressNotAligned::_count;
+
+FaultName AsyncDataError::_name = "async_data";
+TrapType AsyncDataError::_trapType = 0x040;
+FaultPriority AsyncDataError::_priority = 2;
+FaultStat AsyncDataError::_count;
+
+FaultName CleanWindow::_name = "clean_win";
+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;
+
+FaultName SpillNNormal::_name = "spill_n_normal";
+TrapType SpillNNormal::_baseTrapType = 0x080;
+FaultPriority SpillNNormal::_priority = 9;
+FaultStat SpillNNormal::_count;
+
+FaultName SpillNOther::_name = "spill_n_other";
+TrapType SpillNOther::_baseTrapType = 0x0A0;
+FaultPriority SpillNOther::_priority = 9;
+FaultStat SpillNOther::_count;
+
+FaultName FillNNormal::_name = "fill_n_normal";
+TrapType FillNNormal::_baseTrapType = 0x0C0;
+FaultPriority FillNNormal::_priority = 9;
+FaultStat FillNNormal::_count;
+
+FaultName FillNOther::_name = "fill_n_other";
+TrapType FillNOther::_baseTrapType = 0x0E0;
+FaultPriority FillNOther::_priority = 9;
+FaultStat FillNOther::_count;
+
+FaultName TrapInstruction::_name = "trap_inst_n";
+TrapType TrapInstruction::_baseTrapType = 0x100;
+FaultPriority TrapInstruction::_priority = 16;
+FaultStat TrapInstruction::_count;
+
+#if FULL_SYSTEM
+
+void SparcFault::invoke(ExecContext * xc)
+{
+ FaultBase::invoke(xc);
+ countStat()++;
+
+ //Use the SPARC trap state machine
+ /*// exception restart address
+ if (setRestartAddress() || !xc->inPalMode())
+ xc->setMiscReg(AlphaISA::IPR_EXC_ADDR, xc->regs.pc);
+
+ if (skipFaultingInstruction()) {
+ // traps... skip faulting instruction.
+ xc->setMiscReg(AlphaISA::IPR_EXC_ADDR,
+ xc->readMiscReg(AlphaISA::IPR_EXC_ADDR) + 4);
+ }
+
+ if (!xc->inPalMode())
+ AlphaISA::swap_palshadow(&(xc->regs), true);
+
+ xc->regs.pc = xc->readMiscReg(AlphaISA::IPR_PAL_BASE) + vect();
+ xc->regs.npc = xc->regs.pc + sizeof(MachInst);*/
+}
+
+#endif
+
+#if !FULL_SYSTEM
+
+void TrapInstruction::invoke(ExecContext * xc)
+{
+ xc->syscall(syscall_num);
+}
+
+#endif
+
+} // namespace SparcISA
+
diff --git a/src/arch/sparc/faults.hh b/src/arch/sparc/faults.hh
new file mode 100644
index 000000000..e8fb8dfc5
--- /dev/null
+++ b/src/arch/sparc/faults.hh
@@ -0,0 +1,591 @@
+/*
+ * Copyright (c) 2003-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __ALPHA_FAULTS_HH__
+#define __ALPHA_FAULTS_HH__
+
+#include "sim/faults.hh"
+
+// The design of the "name" and "vect" functions is in sim/faults.hh
+
+namespace SparcISA
+{
+
+typedef const uint32_t TrapType;
+typedef const uint32_t FaultPriority;
+
+class SparcFault : public FaultBase
+{
+ public:
+#if FULL_SYSTEM
+ void invoke(ExecContext * xc);
+#endif
+ virtual TrapType trapType() = 0;
+ virtual FaultPriority priority() = 0;
+ virtual FaultStat & countStat() = 0;
+};
+
+class InternalProcessorError : public SparcFault
+{
+ private:
+ static FaultName _name;
+ static TrapType _trapType;
+ static FaultPriority _priority;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ TrapType trapType() {return _trapType;}
+ FaultPriority priority() {return _priority;}
+ FaultStat & countStat() {return _count;}
+ bool isMachineCheckFault() {return true;}
+};
+
+class MemAddressNotAligned : public SparcFault
+{
+ private:
+ static FaultName _name;
+ static TrapType _trapType;
+ static FaultPriority _priority;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ TrapType trapType() {return _trapType;}
+ FaultPriority priority() {return _priority;}
+ FaultStat & countStat() {return _count;}
+ bool isAlignmentFault() {return true;}
+};
+
+static inline Fault genMachineCheckFault()
+{
+ return new InternalProcessorError;
+}
+
+static inline Fault genAlignmentFault()
+{
+ return new MemAddressNotAligned;
+}
+
+class PowerOnReset : public SparcFault
+{
+ private:
+ static FaultName _name;
+ static TrapType _trapType;
+ static FaultPriority _priority;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ TrapType trapType() {return _trapType;}
+ FaultPriority priority() {return _priority;}
+ FaultStat & countStat() {return _count;}
+};
+
+class WatchDogReset : public SparcFault
+{
+ private:
+ static FaultName _name;
+ static TrapType _trapType;
+ static FaultPriority _priority;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ TrapType trapType() {return _trapType;}
+ FaultPriority priority() {return _priority;}
+ FaultStat & countStat() {return _count;}
+};
+
+class ExternallyInitiatedReset : public SparcFault
+{
+ private:
+ static FaultName _name;
+ static TrapType _trapType;
+ static FaultPriority _priority;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ TrapType trapType() {return _trapType;}
+ FaultPriority priority() {return _priority;}
+ FaultStat & countStat() {return _count;}
+};
+
+class SoftwareInitiatedReset : public SparcFault
+{
+ private:
+ static FaultName _name;
+ static TrapType _trapType;
+ static FaultPriority _priority;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ TrapType trapType() {return _trapType;}
+ FaultPriority priority() {return _priority;}
+ FaultStat & countStat() {return _count;}
+};
+
+class REDStateException : public SparcFault
+{
+ private:
+ static FaultName _name;
+ static TrapType _trapType;
+ static FaultPriority _priority;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ TrapType trapType() {return _trapType;}
+ FaultPriority priority() {return _priority;}
+ FaultStat & countStat() {return _count;}
+};
+
+class InstructionAccessException : public SparcFault
+{
+ private:
+ static FaultName _name;
+ static TrapType _trapType;
+ static FaultPriority _priority;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ TrapType trapType() {return _trapType;}
+ FaultPriority priority() {return _priority;}
+ FaultStat & countStat() {return _count;}
+};
+
+class InstructionAccessMMUMiss : public SparcFault
+{
+ private:
+ static FaultName _name;
+ static TrapType _trapType;
+ static FaultPriority _priority;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ TrapType trapType() {return _trapType;}
+ FaultPriority priority() {return _priority;}
+ FaultStat & countStat() {return _count;}
+};
+
+class InstructionAccessError : public SparcFault
+{
+ private:
+ static FaultName _name;
+ static TrapType _trapType;
+ static FaultPriority _priority;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ TrapType trapType() {return _trapType;}
+ FaultPriority priority() {return _priority;}
+ FaultStat & countStat() {return _count;}
+};
+
+class IllegalInstruction : public SparcFault
+{
+ private:
+ static FaultName _name;
+ static TrapType _trapType;
+ static FaultPriority _priority;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ TrapType trapType() {return _trapType;}
+ FaultPriority priority() {return _priority;}
+ FaultStat & countStat() {return _count;}
+};
+
+class PrivilegedOpcode : public SparcFault
+{
+ private:
+ static FaultName _name;
+ static TrapType _trapType;
+ static FaultPriority _priority;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ TrapType trapType() {return _trapType;}
+ FaultPriority priority() {return _priority;}
+ FaultStat & countStat() {return _count;}
+};
+
+class UnimplementedLDD : public SparcFault
+{
+ private:
+ static FaultName _name;
+ static TrapType _trapType;
+ static FaultPriority _priority;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ TrapType trapType() {return _trapType;}
+ FaultPriority priority() {return _priority;}
+ FaultStat & countStat() {return _count;}
+};
+
+class UnimplementedSTD : public SparcFault
+{
+ private:
+ static FaultName _name;
+ static TrapType _trapType;
+ static FaultPriority _priority;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ TrapType trapType() {return _trapType;}
+ FaultPriority priority() {return _priority;}
+ FaultStat & countStat() {return _count;}
+};
+
+class FpDisabled : public SparcFault
+{
+ private:
+ static FaultName _name;
+ static TrapType _trapType;
+ static FaultPriority _priority;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ TrapType trapType() {return _trapType;}
+ FaultPriority priority() {return _priority;}
+ FaultStat & countStat() {return _count;}
+};
+
+class FpExceptionIEEE754 : public SparcFault
+{
+ private:
+ static FaultName _name;
+ static TrapType _trapType;
+ static FaultPriority _priority;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ TrapType trapType() {return _trapType;}
+ FaultPriority priority() {return _priority;}
+ FaultStat & countStat() {return _count;}
+};
+
+class FpExceptionOther : public SparcFault
+{
+ private:
+ static FaultName _name;
+ static TrapType _trapType;
+ static FaultPriority _priority;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ TrapType trapType() {return _trapType;}
+ FaultPriority priority() {return _priority;}
+ FaultStat & countStat() {return _count;}
+};
+
+class TagOverflow : public SparcFault
+{
+ private:
+ static FaultName _name;
+ static TrapType _trapType;
+ static FaultPriority _priority;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ TrapType trapType() {return _trapType;}
+ FaultPriority priority() {return _priority;}
+ FaultStat & countStat() {return _count;}
+};
+
+class DivisionByZero : public SparcFault
+{
+ private:
+ static FaultName _name;
+ static TrapType _trapType;
+ static FaultPriority _priority;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ TrapType trapType() {return _trapType;}
+ FaultPriority priority() {return _priority;}
+ FaultStat & countStat() {return _count;}
+};
+
+class DataAccessException : public SparcFault
+{
+ private:
+ static FaultName _name;
+ static TrapType _trapType;
+ static FaultPriority _priority;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ TrapType trapType() {return _trapType;}
+ FaultPriority priority() {return _priority;}
+ FaultStat & countStat() {return _count;}
+};
+
+class DataAccessMMUMiss : public SparcFault
+{
+ private:
+ static FaultName _name;
+ static TrapType _trapType;
+ static FaultPriority _priority;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ TrapType trapType() {return _trapType;}
+ FaultPriority priority() {return _priority;}
+ FaultStat & countStat() {return _count;}
+};
+
+class DataAccessError : public SparcFault
+{
+ private:
+ static FaultName _name;
+ static TrapType _trapType;
+ static FaultPriority _priority;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ TrapType trapType() {return _trapType;}
+ FaultPriority priority() {return _priority;}
+ FaultStat & countStat() {return _count;}
+};
+
+class DataAccessProtection : public SparcFault
+{
+ private:
+ static FaultName _name;
+ static TrapType _trapType;
+ static FaultPriority _priority;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ TrapType trapType() {return _trapType;}
+ FaultPriority priority() {return _priority;}
+ FaultStat & countStat() {return _count;}
+};
+
+class LDDFMemAddressNotAligned : public SparcFault
+{
+ private:
+ static FaultName _name;
+ static TrapType _trapType;
+ static FaultPriority _priority;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ TrapType trapType() {return _trapType;}
+ FaultPriority priority() {return _priority;}
+ FaultStat & countStat() {return _count;}
+};
+
+class STDFMemAddressNotAligned : public SparcFault
+{
+ private:
+ static FaultName _name;
+ static TrapType _trapType;
+ static FaultPriority _priority;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ TrapType trapType() {return _trapType;}
+ FaultPriority priority() {return _priority;}
+ FaultStat & countStat() {return _count;}
+};
+
+class PrivilegedAction : public SparcFault
+{
+ private:
+ static FaultName _name;
+ static TrapType _trapType;
+ static FaultPriority _priority;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ TrapType trapType() {return _trapType;}
+ FaultPriority priority() {return _priority;}
+ FaultStat & countStat() {return _count;}
+};
+
+class LDQFMemAddressNotAligned : public SparcFault
+{
+ private:
+ static FaultName _name;
+ static TrapType _trapType;
+ static FaultPriority _priority;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ TrapType trapType() {return _trapType;}
+ FaultPriority priority() {return _priority;}
+ FaultStat & countStat() {return _count;}
+};
+
+class STQFMemAddressNotAligned : public SparcFault
+{
+ private:
+ static FaultName _name;
+ static TrapType _trapType;
+ static FaultPriority _priority;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ TrapType trapType() {return _trapType;}
+ FaultPriority priority() {return _priority;}
+ FaultStat & countStat() {return _count;}
+};
+
+class AsyncDataError : public SparcFault
+{
+ private:
+ static FaultName _name;
+ static TrapType _trapType;
+ static FaultPriority _priority;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ TrapType trapType() {return _trapType;}
+ FaultPriority priority() {return _priority;}
+ FaultStat & countStat() {return _count;}
+};
+
+class CleanWindow : public SparcFault
+{
+ private:
+ static FaultName _name;
+ static TrapType _trapType;
+ static FaultPriority _priority;
+ static FaultStat _count;
+ public:
+ FaultName name() {return _name;}
+ TrapType trapType() {return _trapType;}
+ FaultPriority priority() {return _priority;}
+ FaultStat & countStat() {return _count;}
+};
+
+class EnumeratedFault : public SparcFault
+{
+ protected:
+ uint32_t _n;
+ virtual TrapType baseTrapType() = 0;
+ public:
+ EnumeratedFault(uint32_t n) : SparcFault() {_n = n;}
+ TrapType trapType() {return baseTrapType() + _n;}
+};
+
+class InterruptLevelN : public EnumeratedFault
+{
+ private:
+ static FaultName _name;
+ static TrapType _baseTrapType;
+ static FaultStat _count;
+ TrapType baseTrapType() {return _baseTrapType;}
+ public:
+ InterruptLevelN(uint32_t n) : EnumeratedFault(n) {;}
+ FaultName name() {return _name;}
+ FaultPriority priority() {return 32 - _n;}
+ FaultStat & countStat() {return _count;}
+};
+
+class SpillNNormal : public EnumeratedFault
+{
+ private:
+ static FaultName _name;
+ static TrapType _baseTrapType;
+ static FaultPriority _priority;
+ static FaultStat _count;
+ TrapType baseTrapType() {return _baseTrapType;}
+ public:
+ SpillNNormal(uint32_t n) : EnumeratedFault(n) {;}
+ FaultName name() {return _name;}
+ FaultPriority priority() {return _priority;}
+ FaultStat & countStat() {return _count;}
+};
+
+class SpillNOther : public EnumeratedFault
+{
+ private:
+ static FaultName _name;
+ static TrapType _baseTrapType;
+ static FaultPriority _priority;
+ static FaultStat _count;
+ TrapType baseTrapType() {return _baseTrapType;}
+ public:
+ SpillNOther(uint32_t n) : EnumeratedFault(n) {;}
+ FaultName name() {return _name;}
+ FaultPriority priority() {return _priority;}
+ FaultStat & countStat() {return _count;}
+};
+
+class FillNNormal : public EnumeratedFault
+{
+ private:
+ static FaultName _name;
+ static TrapType _baseTrapType;
+ static FaultPriority _priority;
+ static FaultStat _count;
+ TrapType baseTrapType() {return _baseTrapType;}
+ public:
+ FillNNormal(uint32_t n) : EnumeratedFault(n) {;}
+ FaultName name() {return _name;}
+ FaultPriority priority() {return _priority;}
+ FaultStat & countStat() {return _count;}
+};
+
+class FillNOther : public EnumeratedFault
+{
+ private:
+ static FaultName _name;
+ static TrapType _baseTrapType;
+ static FaultPriority _priority;
+ static FaultStat _count;
+ TrapType baseTrapType() {return _baseTrapType;}
+ public:
+ FillNOther(uint32_t n) : EnumeratedFault(n) {;}
+ FaultName name() {return _name;}
+ FaultPriority priority() {return _priority;}
+ FaultStat & countStat() {return _count;}
+};
+
+class TrapInstruction : public EnumeratedFault
+{
+ private:
+ static FaultName _name;
+ static TrapType _baseTrapType;
+ static FaultPriority _priority;
+ static FaultStat _count;
+ uint64_t syscall_num;
+ TrapType baseTrapType() {return _baseTrapType;}
+ public:
+ TrapInstruction(uint32_t n, uint64_t syscall) :
+ EnumeratedFault(n), syscall_num(syscall) {;}
+ FaultName name() {return _name;}
+ FaultPriority priority() {return _priority;}
+ FaultStat & countStat() {return _count;}
+#if !FULL_SYSTEM
+ void invoke(ExecContext * xc);
+#endif
+};
+
+} // SparcISA namespace
+
+#endif // __FAULTS_HH__
diff --git a/src/arch/sparc/isa/base.isa b/src/arch/sparc/isa/base.isa
new file mode 100644
index 000000000..02f7cf61a
--- /dev/null
+++ b/src/arch/sparc/isa/base.isa
@@ -0,0 +1,252 @@
+// 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.
+//
+// Authors: Ali Saidi
+// Gabe Black
+// Steve Reinhardt
+
+////////////////////////////////////////////////////////////////////
+//
+// Base class for sparc instructions, and some support functions
+//
+
+output header {{
+
+ union CondCodes
+ {
+ struct
+ {
+ uint8_t c:1;
+ uint8_t v:1;
+ uint8_t z:1;
+ uint8_t n:1;
+ };
+ uint32_t bits;
+ };
+
+ enum CondTest
+ {
+ Always=0x8,
+ Never=0x0,
+ NotEqual=0x9,
+ Equal=0x1,
+ Greater=0xA,
+ LessOrEqual=0x2,
+ GreaterOrEqual=0xB,
+ Less=0x3,
+ GreaterUnsigned=0xC,
+ LessOrEqualUnsigned=0x4,
+ CarryClear=0xD,
+ CarrySet=0x5,
+ Positive=0xE,
+ Negative=0x6,
+ OverflowClear=0xF,
+ OverflowSet=0x7
+ };
+
+ extern char * CondTestAbbrev[];
+
+ /**
+ * Base class for all SPARC static instructions.
+ */
+ class SparcStaticInst : public StaticInst
+ {
+ protected:
+ // Constructor.
+ SparcStaticInst(const char *mnem,
+ MachInst _machInst, OpClass __opClass)
+ : StaticInst(mnem, _machInst, __opClass)
+ {
+ }
+
+ std::string generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const;
+
+ void printReg(std::ostream &os, int reg) const;
+ };
+
+ 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+)(?P<typeQual>\.\w+)?')
+ rOrImmMatch = matcher.search(code)
+ if (rOrImmMatch == None):
+ return (False, code, '', '', '')
+ rString = rOrImmMatch.group("rNum")
+ if (rOrImmMatch.group("typeQual") != None):
+ rString += rOrImmMatch.group("typeQual")
+ iString = rOrImmMatch.group("iNum")
+ orig_code = code
+ code = matcher.sub('Rs' + rString, 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;
+
+ printMnemonic(ss, mnemonic);
+
+ // just print the first two source regs... if there's
+ // a third one, it's a read-modify-write dest (Rc),
+ // e.g. for CMOVxx
+ if(_numSrcRegs > 0)
+ {
+ printReg(ss, _srcRegIdx[0]);
+ }
+ if(_numSrcRegs > 1)
+ {
+ ss << ",";
+ printReg(ss, _srcRegIdx[1]);
+ }
+
+ // just print the first dest... if there's a second one,
+ // it's generally implicit
+ if(_numDestRegs > 0)
+ {
+ if(_numSrcRegs > 0)
+ ss << ",";
+ printReg(ss, _destRegIdx[0]);
+ }
+
+ return ss.str();
+ }
+
+ bool passesCondition(uint32_t codes, uint32_t condition)
+ {
+ CondCodes condCodes;
+ condCodes.bits = codes;
+ switch(condition)
+ {
+ case Always:
+ return true;
+ case Never:
+ return false;
+ case NotEqual:
+ return !condCodes.z;
+ case Equal:
+ return condCodes.z;
+ case Greater:
+ return !(condCodes.z | (condCodes.n ^ condCodes.v));
+ case LessOrEqual:
+ return condCodes.z | (condCodes.n ^ condCodes.v);
+ case GreaterOrEqual:
+ return !(condCodes.n ^ condCodes.v);
+ case Less:
+ return (condCodes.n ^ condCodes.v);
+ case GreaterUnsigned:
+ return !(condCodes.c | condCodes.z);
+ case LessOrEqualUnsigned:
+ return (condCodes.c | condCodes.z);
+ case CarryClear:
+ return !condCodes.c;
+ case CarrySet:
+ return condCodes.c;
+ case Positive:
+ return !condCodes.n;
+ case Negative:
+ return condCodes.n;
+ case OverflowClear:
+ return !condCodes.v;
+ case OverflowSet:
+ return condCodes.v;
+ }
+ panic("Tried testing condition nonexistant "
+ "condition code %d", condition);
+ }
+}};
+
diff --git a/src/arch/sparc/isa/bitfields.isa b/src/arch/sparc/isa/bitfields.isa
new file mode 100644
index 000000000..27f52fa29
--- /dev/null
+++ b/src/arch/sparc/isa/bitfields.isa
@@ -0,0 +1,78 @@
+// 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.
+//
+// Authors: Ali Saidi
+// Gabe Black
+// Steve Reinhardt
+
+////////////////////////////////////////////////////////////////////
+//
+// Bitfield definitions.
+//
+
+// Bitfields are shared liberally between instruction formats, so they are
+// simply defined alphabetically
+
+def bitfield A <29>;
+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>;
+def bitfield D16HI <21:20>;
+def bitfield D16LO <13:0>;
+def bitfield DISP19 <18:0>;
+def bitfield DISP22 <21:0>;
+def bitfield DISP30 <29:0>;
+def bitfield FCN <29:26>;
+def bitfield I <13>;
+def bitfield IMM_ASI <12:5>;
+def bitfield IMM22 <21:0>;
+def bitfield MMASK <3:0>;
+def bitfield OP <31:30>;
+def bitfield OP2 <24:22>;
+def bitfield OP3 <24:19>;
+def bitfield OPF <13:5>;
+def bitfield OPF_CC <13:11>;
+def bitfield OPF_LOW5 <9:5>;
+def bitfield OPF_LOW6 <10:5>;
+def bitfield P <19>;
+def bitfield RCOND2 <27:25>;
+def bitfield RCOND3 <12:10>;
+def bitfield RCOND4 <12:10>;
+def bitfield RD <29:25>;
+def bitfield RS1 <18:14>;
+def bitfield RS2 <4:0>;
+def bitfield SHCNT32 <4:0>;
+def bitfield SHCNT64 <5:0>;
+def bitfield SIMM10 <9:0>;
+def bitfield SIMM11 <10:0>;
+def bitfield SIMM13 <12:0>;
+def bitfield SW_TRAP <7:0>;
+def bitfield X <12>;
diff --git a/src/arch/sparc/isa/decoder.isa b/src/arch/sparc/isa/decoder.isa
new file mode 100644
index 000000000..fa8832920
--- /dev/null
+++ b/src/arch/sparc/isa/decoder.isa
@@ -0,0 +1,669 @@
+// 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.
+//
+// Authors: Ali Saidi
+// Gabe Black
+// Steve Reinhardt
+
+////////////////////////////////////////////////////////////////////
+//
+// The actual decoder specification
+//
+
+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(Ccr<3:0>, COND2))
+ NNPC = xc->readPC() + disp;
+ else
+ handle_annul
+ }});
+ 0x2: bpccx({{
+ if(passesCondition(Ccr<7:4>, COND2))
+ NNPC = xc->readPC() + disp;
+ else
+ handle_annul
+ }});
+ }
+ }
+ 0x2: Branch22::bicc({{
+ if(passesCondition(Ccr<3:0>, 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 + Ccr<0:0>;}});
+ 0x09: mulx({{Rd = Rs1 * Rs2_or_imm13;}});
+ 0x0A: umul({{
+ Rd = Rs1.udw<31:0> * Rs2_or_imm13<31:0>;
+ Y = Rd<63:32>;
+ }});
+ 0x0B: smul({{
+ Rd.sdw = Rs1.sdw<31:0> * Rs2_or_imm13<31:0>;
+ Y = Rd.sdw;
+ }});
+ 0x0C: subc({{Rd.sdw = Rs1.sdw + (~Rs2_or_imm13) + 1 + Ccr<0:0>}});
+ 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
+ {
+ Rd.udw = ((Y << 32) | Rs1.udw<31:0>) / Rs2_or_imm13;
+ if(Rd.udw >> 32 != 0)
+ Rd.udw = 0xFFFFFFFF;
+ }
+ }});
+ 0x0F: sdiv({{
+ if(Rs2_or_imm13.sdw == 0)
+ fault = new DivisionByZero;
+ else
+ {
+ Rd.udw = ((int64_t)((Y << 32) | Rs1.sdw<31:0>)) / Rs2_or_imm13.sdw;
+ if(Rd.udw<63:31> != 0)
+ Rd.udw = 0x7FFFFFFF;
+ else if(Rd.udw<63:> && Rd.udw<62:31> != 0xFFFFFFFF)
+ Rd.udw = 0xFFFFFFFF80000000ULL;
+ }
+ }});
+ }
+ 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 = Ccr<0:0>;
+ 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;
+ Rd = resTemp = Rs1.udw<31:0> * Rs2_or_imm13.udw<31:0>;
+ Y = resTemp<63:32>;}},
+ {{0}},{{0}},{{0}},{{0}});
+ 0x1B: smulcc({{
+ int64_t resTemp;
+ Rd = resTemp = Rs1.sdw<31:0> * Rs2_or_imm13.sdw<31:0>;
+ Y = resTemp<63:32>;}},
+ {{0}},{{0}},{{0}},{{0}});
+ 0x1C: subccc({{
+ int64_t resTemp, val2 = Rs2_or_imm13;
+ int64_t carryin = Ccr<0:0>;
+ 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.udw == 0) fault = new DivisionByZero;
+ else Rd = Rs1.udw / Rs2_or_imm13.udw;}}
+ ,{{0}},{{0}},{{0}},{{0}});
+ 0x1E: udivcc({{
+ uint32_t resTemp, val2 = Rs2_or_imm13.udw;
+ int32_t overflow;
+ if(val2 == 0) fault = new DivisionByZero;
+ else
+ {
+ resTemp = (uint64_t)((Y << 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.sdw;
+ int32_t overflow, underflow;
+ if(val2 == 0) fault = new DivisionByZero;
+ else
+ {
+ Rd = resTemp = (int64_t)((Y << 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> |
+ ((Ccr<3:3>
+ ^ Ccr<1:1>) << 32);
+ if(!Y<0:>)
+ multiplicand = 0;
+ Rd = resTemp = multiplicand + multiplier;
+ Y = Y<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>);}});
+ }
+ // XXX might want a format rdipr thing here
+ 0x28: rdasr({{
+ Rd = xc->readMiscRegWithEffect(RS1 + AsrStart, fault);
+ }});
+ 0x29: rdhpr({{
+ // XXX Need to protect with format that traps non-priv/priv
+ // access
+ Rd = xc->readMiscRegWithEffect(RS1 + HprStart, fault);
+ }});
+ 0x2A: rdpr({{
+ // XXX Need to protect with format that traps non-priv
+ // access
+ Rd = xc->readMiscRegWithEffect(RS1 + PrStart, fault);
+ }});
+ 0x2B: BasicOperate::flushw({{
+ if(NWindows - 2 - Cansave == 0)
+ {
+ if(Otherwin)
+ fault = new SpillNOther(Wstate<5:3>);
+ else
+ fault = new SpillNNormal(Wstate<2:0>);
+ }
+ }});
+ 0x2C: decode MOVCC3
+ {
+ 0x0: Trap::movccfcc({{fault = new FpDisabled;}});
+ 0x1: decode CC
+ {
+ 0x0: movcci({{
+ if(passesCondition(Ccr<3:0>, COND4))
+ Rd = Rs2_or_imm11;
+ else
+ Rd = Rd;
+ }});
+ 0x2: movccx({{
+ if(passesCondition(Ccr<7:4>, COND4))
+ Rd = Rs2_or_imm11;
+ else
+ Rd = Rd;
+ }});
+ }
+ }
+ 0x2D: sdivx({{
+ if(Rs2_or_imm13.sdw == 0) fault = new DivisionByZero;
+ else Rd.sdw = Rs1.sdw / Rs2_or_imm13.sdw;
+ }});
+ 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.sdw == 0) ? Rs2_or_imm10 : Rd;}});
+ 0x2: movrle({{Rd = (Rs1.sdw <= 0) ? Rs2_or_imm10 : Rd;}});
+ 0x3: movrl({{Rd = (Rs1.sdw < 0) ? Rs2_or_imm10 : Rd;}});
+ 0x5: movrne({{Rd = (Rs1.sdw != 0) ? Rs2_or_imm10 : Rd;}});
+ 0x6: movrg({{Rd = (Rs1.sdw > 0) ? Rs2_or_imm10 : Rd;}});
+ 0x7: movrge({{Rd = (Rs1.sdw >= 0) ? Rs2_or_imm10 : Rd;}});
+ }
+ 0x30: wrasr({{
+ xc->setMiscRegWithEffect(RD + AsrStart, Rs1 ^ Rs2_or_imm13);
+ }});
+ 0x31: decode FCN {
+ 0x0: BasicOperate::saved({{/*Boogy Boogy*/}});
+ 0x1: BasicOperate::restored({{/*Boogy Boogy*/}});
+ }
+ 0x32: wrpr({{
+ // XXX Need to protect with format that traps non-priv
+ // access
+ xc->setMiscRegWithEffect(RD + PrStart, Rs1 ^ Rs2_or_imm13);
+ }});
+ 0x33: wrhpr({{
+ // XXX Need to protect with format that traps non-priv/priv
+ // access
+ xc->setMiscRegWithEffect(RD + HprStart, 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(Wstate<5:3>);
+ else
+ fault = new FillNNormal(Wstate<2:0>);
+ }
+ 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(Ccr<3:0>, 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
+ }
+ }});
+ 0x2: Trap::tccx({{
+ if(passesCondition(Ccr<7:4>, 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
+ }
+ }});
+ }
+ 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(Wstate<5:3>);
+ else
+ fault = new SpillNNormal(Wstate<2:0>);
+ Cwp = (Cwp + 2) % NWindows;
+ }
+ else if(Cleanwin - Canrestore == 0)
+ {
+ Cwp = (Cwp + 1) % NWindows;
+ fault = new CleanWindow;
+ }
+ 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(Wstate<5:3>);
+ else
+ fault = new FillNNormal(Wstate<2:0>);
+ }
+ 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 = Tstate<4:0>;
+ Pstate = Tstate<20:8>;
+ Asi = Tstate<31:24>;
+ Ccr = Tstate<39:32>;
+ Gl = Tstate<42:40>;
+ NPC = Tnpc;
+ NNPC = Tnpc + 4;
+ Tl = Tl - 1;
+ }});
+ 0x1: BasicOperate::retry({{
+ if(Tl == 0)
+ return new IllegalInstruction;
+ Cwp = Tstate<4:0>;
+ Pstate = Tstate<20:8>;
+ Asi = Tstate<31:24>;
+ Ccr = Tstate<39:32>;
+ Gl = Tstate<42:40>;
+ NPC = Tpc;
+ NNPC = Tnpc + 4;
+ 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/src/arch/sparc/isa/formats.isa b/src/arch/sparc/isa/formats.isa
new file mode 100644
index 000000000..17d68061b
--- /dev/null
+++ b/src/arch/sparc/isa/formats.isa
@@ -0,0 +1,28 @@
+//Include the basic format
+//Templates from this format are used later
+##include "formats/basic.isa"
+
+//Include the noop format
+##include "formats/nop.isa"
+
+//Include the integerOp and integerOpCc format
+##include "formats/integerop.isa"
+
+//Include the memory format
+##include "formats/mem.isa"
+
+//Include the compare and swap format
+##include "formats/cas.isa"
+
+//Include the trap format
+##include "formats/trap.isa"
+
+//Include the "unknown" format
+##include "formats/unknown.isa"
+
+//Include the priveleged mode format
+##include "formats/priv.isa"
+
+//Include the branch format
+##include "formats/branch.isa"
+
diff --git a/src/arch/sparc/isa/formats/basic.isa b/src/arch/sparc/isa/formats/basic.isa
new file mode 100644
index 000000000..60432cb6b
--- /dev/null
+++ b/src/arch/sparc/isa/formats/basic.isa
@@ -0,0 +1,97 @@
+// 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.
+//
+// Authors: Ali Saidi
+// Gabe Black
+// Steve Reinhardt
+
+// Declarations for execute() methods.
+def template BasicExecDeclare {{
+ Fault execute(%(CPU_exec_context)s *, Trace::InstRecord *) const;
+}};
+
+// Basic instruction class declaration template.
+def template BasicDeclare {{
+ /**
+ * Static instruction class for "%(mnemonic)s".
+ */
+ class %(class_name)s : public %(base_class)s
+ {
+ public:
+ // Constructor.
+ %(class_name)s(MachInst machInst);
+ %(BasicExecDeclare)s
+ };
+}};
+
+// Basic instruction class constructor template.
+def template BasicConstructor {{
+ inline %(class_name)s::%(class_name)s(MachInst machInst)
+ : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
+ {
+ %(constructor)s;
+ }
+}};
+
+// Basic instruction class execute method template.
+def template BasicExecute {{
+ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ Fault fault = NoFault;
+
+ %(fp_enable_check)s;
+ %(op_decl)s;
+ %(op_rd)s;
+ %(code)s;
+
+ if(fault == NoFault)
+ {
+ %(op_wb)s;
+ }
+ return fault;
+ }
+}};
+
+// Basic decode template.
+def template BasicDecode {{
+ return new %(class_name)s(machInst);
+}};
+
+// Basic decode template, passing mnemonic in as string arg to constructor.
+def template BasicDecodeWithMnemonic {{
+ return new %(class_name)s("%(mnemonic)s", machInst);
+}};
+
+// The most basic instruction format... used only for a few misc. insts
+def format BasicOperate(code, *flags) {{
+ iop = InstObjParams(name, Name, 'SparcStaticInst',
+ CodeBlock(code), flags)
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ decode_block = BasicDecode.subst(iop)
+ exec_output = BasicExecute.subst(iop)
+}};
diff --git a/src/arch/sparc/isa/formats/branch.isa b/src/arch/sparc/isa/formats/branch.isa
new file mode 100644
index 000000000..7d46ce739
--- /dev/null
+++ b/src/arch/sparc/isa/formats/branch.isa
@@ -0,0 +1,337 @@
+// 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.
+//
+// Authors: Gabe Black
+// Steve Reinhardt
+
+////////////////////////////////////////////////////////////////////
+//
+// Branch instructions
+//
+
+output header {{
+ /**
+ * Base class for branch operations.
+ */
+ class Branch : public SparcStaticInst
+ {
+ protected:
+ // Constructor
+ Branch(const char *mnem, MachInst _machInst, OpClass __opClass) :
+ SparcStaticInst(mnem, _machInst, __opClass)
+ {
+ }
+
+ std::string generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const;
+ };
+
+ /**
+ * 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::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
+ {
+ 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();
+ }
+}};
+
+def template BranchExecute {{
+ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ //Attempt to execute the instruction
+ Fault fault = NoFault;
+
+ %(op_decl)s;
+ %(op_rd)s;
+
+ NNPC = xc->readNextNPC();
+ %(code)s;
+
+ if(fault == NoFault)
+ {
+ //Write the resulting state to the execution context
+ %(op_wb)s;
+ }
+
+ return fault;
+ }
+}};
+
+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) {{
+ 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)
+ 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/src/arch/sparc/isa/formats/integerop.isa b/src/arch/sparc/isa/formats/integerop.isa
new file mode 100644
index 000000000..1894ce541
--- /dev/null
+++ b/src/arch/sparc/isa/formats/integerop.isa
@@ -0,0 +1,395 @@
+// 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.
+//
+// Authors: Ali Saidi
+// Gabe Black
+// Steve Reinhardt
+
+////////////////////////////////////////////////////////////////////
+//
+// Integer operate instructions
+//
+
+output header {{
+ /**
+ * Base class for integer operations.
+ */
+ class IntOp : public SparcStaticInst
+ {
+ protected:
+ // Constructor
+ 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 {{
+
+ bool IntOp::printPseudoOps(std::ostream &os, Addr pc,
+ const SymbolTable *symbab) const
+ {
+ 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;
+ }
+
+ bool IntOpImm::printPseudoOps(std::ostream &os, Addr pc,
+ const SymbolTable *symbab) const
+ {
+ 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)
+ {
+ 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;
+
+ 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 (_numDestRegs > 0)
+ {
+ if(_numSrcRegs > 0)
+ response << ", ";
+ printReg(response, _destRegIdx[0]);
+ }
+ }
+ return response.str();
+ }
+
+ 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)
+ {
+ response << ", ";
+ printReg(response, _destRegIdx[0]);
+ }
+ }
+ 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();
+ }
+}};
+
+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)
+ 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 = '''
+ uint8_t tmp_ccriccc;
+ uint8_t tmp_ccriccv;
+ uint8_t tmp_ccriccz;
+ uint8_t tmp_ccriccn;
+ uint8_t tmp_ccrxccc;
+ uint8_t tmp_ccrxccv;
+ uint8_t tmp_ccrxccz;
+ uint8_t tmp_ccrxccn;
+
+ tmp_ccriccn = (Rd >> 31) & 1;
+ tmp_ccriccz = ((Rd & 0xFFFFFFFF) == 0);
+ tmp_ccrxccn = (Rd >> 63) & 1;
+ tmp_ccrxccz = (Rd == 0);
+ tmp_ccriccv = %(ivValue)s & 1;
+ tmp_ccriccc = %(icValue)s & 1;
+ tmp_ccrxccv = %(xvValue)s & 1;
+ tmp_ccrxccc = %(xcValue)s & 1;
+
+ Ccr = tmp_ccriccc | tmp_ccriccv << 1 |
+ tmp_ccriccz << 2 | tmp_ccriccn << 3|
+ tmp_ccrxccc << 4 | tmp_ccrxccv << 5|
+ tmp_ccrxccz << 6| tmp_ccrxccn << 7;
+
+
+ DPRINTF(Sparc, "in = %%d\\n", (uint16_t)tmp_ccriccn);
+ DPRINTF(Sparc, "iz = %%d\\n", (uint16_t)tmp_ccriccz);
+ DPRINTF(Sparc, "xn = %%d\\n", (uint16_t)tmp_ccrxccn);
+ DPRINTF(Sparc, "xz = %%d\\n", (uint16_t)tmp_ccrxccz);
+ DPRINTF(Sparc, "iv = %%d\\n", (uint16_t)tmp_ccriccv);
+ DPRINTF(Sparc, "ic = %%d\\n", (uint16_t)tmp_ccriccc);
+ DPRINTF(Sparc, "xv = %%d\\n", (uint16_t)tmp_ccrxccv);
+ DPRINTF(Sparc, "xc = %%d\\n", (uint16_t)tmp_ccrxccc);
+ '''
+}};
+
+// Primary format for integer operate instructions:
+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/src/arch/sparc/isa/formats/mem.isa b/src/arch/sparc/isa/formats/mem.isa
new file mode 100644
index 000000000..12dae57e5
--- /dev/null
+++ b/src/arch/sparc/isa/formats/mem.isa
@@ -0,0 +1,171 @@
+////////////////////////////////////////////////////////////////////
+//
+// Mem instructions
+//
+
+output header {{
+ /**
+ * Base class for memory operations.
+ */
+ class Mem : public SparcStaticInst
+ {
+ protected:
+
+ // Constructor
+ Mem(const char *mnem, ExtMachInst _machInst, OpClass __opClass) :
+ SparcStaticInst(mnem, _machInst, __opClass)
+ {
+ }
+
+ 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::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
+ {
+ 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();
+ }
+}};
+
+def template MemExecute {{
+ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ Fault fault = NoFault;
+ Addr EA;
+ %(op_decl)s;
+ %(op_rd)s;
+ %(ea_code)s;
+ DPRINTF(Sparc, "The address is 0x%x\n", EA);
+ %(load)s;
+ %(code)s;
+ %(store)s;
+
+ if(fault == NoFault)
+ {
+ //Write the resulting state to the execution context
+ %(op_wb)s;
+ }
+
+ return fault;
+ }
+}};
+
+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 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/src/arch/sparc/isa/formats/nop.isa b/src/arch/sparc/isa/formats/nop.isa
new file mode 100644
index 000000000..37ef2e8d0
--- /dev/null
+++ b/src/arch/sparc/isa/formats/nop.isa
@@ -0,0 +1,98 @@
+// 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.
+//
+// Authors: Gabe Black
+// Steve Reinhardt
+
+////////////////////////////////////////////////////////////////////
+//
+// Nop instruction
+//
+
+// Per-cpu-model nop execute method.
+def template NopExec {{
+
+ Fault execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const
+ {
+ // Nothing to see here, move along
+ return NoFault;
+ }
+}};
+
+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. Interpolate via
+ // template so i gets expanded to a set of
+ // cpu-model-specific functions.
+ %(NopExec)s
+
+ 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/src/arch/sparc/isa/formats/priv.isa b/src/arch/sparc/isa/formats/priv.isa
new file mode 100644
index 000000000..7df59d736
--- /dev/null
+++ b/src/arch/sparc/isa/formats/priv.isa
@@ -0,0 +1,125 @@
+// 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.
+//
+// Authors: Ali Saidi
+// Gabe Black
+// Steve Reinhardt
+
+////////////////////////////////////////////////////////////////////
+//
+// 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 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;
+ };
+
+}};
+
+output decoder {{
+ std::string Priv::generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const
+ {
+ return "Privileged Instruction";
+ }
+}};
+
+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 = "((xc->readMiscReg(PrStart + MISCREG_PSTATE))<2:2>)"
+ (header_output, decoder_output,
+ exec_output, decode_block) = doPrivFormat(code,
+ checkCode, name, Name, opt_flags)
+}};
+
+
diff --git a/src/arch/sparc/isa/formats/trap.isa b/src/arch/sparc/isa/formats/trap.isa
new file mode 100644
index 000000000..04d467cfe
--- /dev/null
+++ b/src/arch/sparc/isa/formats/trap.isa
@@ -0,0 +1,93 @@
+// 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.
+//
+// Authors: Gabe Black
+// Steve Reinhardt
+
+////////////////////////////////////////////////////////////////////
+//
+// Trap instructions
+//
+
+output header {{
+ /**
+ * Base class for trap instructions,
+ * or instructions that always fault.
+ */
+ class Trap : public SparcStaticInst
+ {
+ protected:
+
+ // Constructor
+ 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;
+ };
+}};
+
+output decoder {{
+ std::string Trap::generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const
+ {
+ 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();
+ }
+}};
+
+def template TrapExecute {{
+ 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
+ return fault;
+ }
+}};
+
+def format Trap(code, *opt_flags) {{
+ orig_code = code
+ cblk = CodeBlock(code)
+ iop = InstObjParams(name, Name, 'Trap', cblk, opt_flags)
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ decode_block = BasicDecode.subst(iop)
+ exec_output = TrapExecute.subst(iop)
+}};
diff --git a/src/arch/sparc/isa/formats/unknown.isa b/src/arch/sparc/isa/formats/unknown.isa
new file mode 100644
index 000000000..8541d6a62
--- /dev/null
+++ b/src/arch/sparc/isa/formats/unknown.isa
@@ -0,0 +1,75 @@
+// 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.
+//
+// Authors: Gabe Black
+// Steve Reinhardt
+
+////////////////////////////////////////////////////////////////////
+//
+// 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/src/arch/sparc/isa/includes.isa b/src/arch/sparc/isa/includes.isa
new file mode 100644
index 000000000..762de243a
--- /dev/null
+++ b/src/arch/sparc/isa/includes.isa
@@ -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.
+//
+// Authors: Ali Saidi
+// Gabe Black
+// Steve Reinhardt
+
+////////////////////////////////////////////////////////////////////
+//
+// Output include file directives.
+//
+
+output header {{
+#include <sstream>
+#include <iostream>
+#include <iomanip>
+
+#include "cpu/static_inst.hh"
+#include "arch/sparc/faults.hh"
+#include "mem/request.hh" // some constructors use MemReq flags
+#include "arch/sparc/isa_traits.hh"
+#include "arch/sparc/regfile.hh"
+}};
+
+output decoder {{
+#include "base/cprintf.hh"
+#include "base/loader/symtab.hh"
+#include "cpu/exec_context.hh" // for Jump::branchTarget()
+
+#include <math.h>
+#if defined(linux)
+#include <fenv.h>
+#endif
+
+using namespace SparcISA;
+}};
+
+output exec {{
+#include <math.h>
+#if defined(linux)
+#include <fenv.h>
+#endif
+
+#ifdef FULL_SYSTEM
+//#include "sim/pseudo_inst.hh"
+#endif
+#include "cpu/base.hh"
+#include "cpu/exetrace.hh"
+#include "sim/sim_exit.hh"
+
+using namespace SparcISA;
+}};
+
diff --git a/src/arch/sparc/isa/main.isa b/src/arch/sparc/isa/main.isa
new file mode 100644
index 000000000..79be0e2a3
--- /dev/null
+++ b/src/arch/sparc/isa/main.isa
@@ -0,0 +1,59 @@
+// -*- mode:c++ -*-
+
+// Copyright (c) 2003-2005 The Regents of The University of Michigan
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met: redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer;
+// redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution;
+// neither the name of the copyright holders nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+////////////////////////////////////////////////////////////////////
+//
+// SPARC ISA description file.
+//
+////////////////////////////////////////////////////////////////////
+
+//Include the C++ include directives
+##include "includes.isa"
+
+////////////////////////////////////////////////////////////////////
+//
+// Namespace statement. Everything below this line will be in the
+// SparcISAInst namespace.
+//
+
+namespace SparcISA;
+
+//Include the bitfield definitions
+##include "bitfields.isa"
+
+//Include the operand_types and operand definitions
+##include "operands.isa"
+
+//Include the base class for sparc instructions, and some support code
+##include "base.isa"
+
+//Include the definitions for the instruction formats
+##include "formats.isa"
+
+//Include the decoder definition
+##include "decoder.isa"
diff --git a/src/arch/sparc/isa/operands.isa b/src/arch/sparc/isa/operands.isa
new file mode 100644
index 000000000..9e5c783e8
--- /dev/null
+++ b/src/arch/sparc/isa/operands.isa
@@ -0,0 +1,88 @@
+// 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.
+//
+// Authors: Ali Saidi
+// Gabe Black
+// Steve Reinhardt
+
+def operand_types {{
+ 'sb' : ('signed int', 8),
+ 'ub' : ('unsigned int', 8),
+ 'shw' : ('signed int', 16),
+ 'uhw' : ('unsigned int', 16),
+ 'sw' : ('signed int', 32),
+ 'uw' : ('unsigned int', 32),
+ 'sdw' : ('signed int', 64),
+ 'udw' : ('unsigned int', 64),
+ 'sf' : ('float', 32),
+ 'df' : ('float', 64),
+ 'qf' : ('float', 128)
+}};
+
+def operands {{
+ # Int regs default to unsigned, but code should not count on this.
+ # For clarity, descriptions that depend on unsigned behavior should
+ # explicitly specify '.uq'.
+ 'Rd': ('IntReg', 'udw', 'RD', 'IsInteger', 1),
+ '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', '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, 6),
+ 'R1': ('IntReg', 'udw', '1', None, 7),
+ 'R15': ('IntReg', 'udw', '15', 'IsInteger', 8),
+ 'R16': ('IntReg', 'udw', '16', None, 9),
+
+ # Control registers
+ 'Y': ('ControlReg', 'udw', 'MISCREG_Y', None, 12),
+ 'Ccr': ('ControlReg', 'udw', 'MISCREG_CCR', None, 17),
+ 'Asi': ('ControlReg', 'udw', 'MISCREG_ASI', None, 26),
+
+ 'Tpc': ('ControlReg', 'udw', 'MISCREG_TPC', None, 28),
+ 'Tnpc': ('ControlReg', 'udw', 'MISCREG_TNPC', None, 28),
+ 'Tstate': ('ControlReg', 'udw', 'MISCREG_TSTATE', None, 28),
+ 'Pstate': ('ControlReg', 'udw', 'MISCREG_PSTATE', None, 1),
+ 'Tl': ('ControlReg', 'udw', 'MISCREG_TL', None, 27),
+
+ 'Cwp': ('ControlReg', 'udw', 'MISCREG_CWP', None, 15),
+ 'Cansave': ('ControlReg', 'udw', 'MISCREG_CANSAVE', None, 34),
+ 'Canrestore': ('ControlReg', 'udw', 'MISCREG_CANRESTORE', None, 35),
+ 'Cleanwin': ('ControlReg', 'udw', 'MISCREG_CLEANWIN', None, 37),
+ 'Otherwin': ('ControlReg', 'udw', 'MISCREG_OTHERWIN', None, 36),
+ 'Wstate': ('ControlReg', 'udw', 'MISCREG_WSTATE', None, 38),
+ 'Gl': ('ControlReg', 'udw', 'MISCREG_GL', None, 12),
+
+ 'Fsr': ('ControlReg', 'udw', 'MISCREG_FSR', None, 47)
+
+}};
diff --git a/src/arch/sparc/isa_traits.hh b/src/arch/sparc/isa_traits.hh
new file mode 100644
index 000000000..3d55ff361
--- /dev/null
+++ b/src/arch/sparc/isa_traits.hh
@@ -0,0 +1,190 @@
+/*
+ * Copyright (c) 2003-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __ARCH_SPARC_ISA_TRAITS_HH__
+#define __ARCH_SPARC_ISA_TRAITS_HH__
+
+#include "base/misc.hh"
+#include "config/full_system.hh"
+#include "sim/host.hh"
+
+class ExecContext;
+class FastCPU;
+//class FullCPU;
+class Checkpoint;
+
+class StaticInst;
+class StaticInstPtr;
+
+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
+
+#if FULL_SYSTEM
+#include "arch/sparc/isa_fullsys_traits.hh"
+#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;
+
+ const int NumIntRegs = 32;
+ const int NumFloatRegs = 64;
+ const int NumMiscRegs = 32;
+
+ // semantically meaningful register indices
+ const int ZeroReg = 0; // architecturally meaningful
+ // the rest of these depend on the ABI
+ const int StackPointerReg = 14;
+ const int ReturnAddressReg = 31; // post call, precall is 15
+ const int ReturnValueReg = 8; // Post return, 24 is pre-return.
+ const int FramePointerReg = 30;
+ const int ArgumentReg0 = 8;
+ const int ArgumentReg1 = 9;
+ const int ArgumentReg2 = 10;
+ const int ArgumentReg3 = 11;
+ const int ArgumentReg4 = 12;
+ const int ArgumentReg5 = 13;
+ // Some OS syscall 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;
+
+ 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);
+
+ StaticInstPtr decodeInst(ExtMachInst);
+
+ // return a no-op instruction... used for instruction fetch faults
+ extern const MachInst NoopMachInst;
+}
+
+#include "arch/sparc/regfile.hh"
+
+namespace SparcISA
+{
+
+#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, clear XCC.C
+ regs->setMiscReg(MISCREG_CCR, regs->readMiscReg(MISCREG_CCR) & 0xEF);
+ regs->setIntReg(ReturnValueReg, return_value.value());
+ } else {
+ // got an error, set XCC.C
+ regs->setMiscReg(MISCREG_CCR, regs->readMiscReg(MISCREG_CCR) | 0x10);
+ regs->setIntReg(ReturnValueReg, return_value.value());
+ }
+ }
+#endif
+};
+
+#endif // __ARCH_SPARC_ISA_TRAITS_HH__
diff --git a/src/arch/sparc/linux/linux.cc b/src/arch/sparc/linux/linux.cc
new file mode 100644
index 000000000..c7ed29358
--- /dev/null
+++ b/src/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/src/arch/sparc/linux/linux.hh b/src/arch/sparc/linux/linux.hh
new file mode 100644
index 000000000..9cde5bb9c
--- /dev/null
+++ b/src/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 __ARCH_SPARC_LINUX_LINUX_HH__
+#define __ARCH_SPARC_LINUX_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/src/arch/sparc/linux/process.cc b/src/arch/sparc/linux/process.cc
new file mode 100644
index 000000000..71be6a83a
--- /dev/null
+++ b/src/arch/sparc/linux/process.cc
@@ -0,0 +1,407 @@
+/*
+ * 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/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 "sim/process.hh"
+#include "sim/syscall_emul.hh"
+
+using namespace std;
+using namespace SparcISA;
+
+
+/// Target uname() handler.
+static SyscallReturn
+unameFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+{
+ TypedBufferArg<Linux::utsname> name(xc->getSyscallArg(0));
+
+ strcpy(name->sysname, "Linux");
+ strcpy(name->nodename, "m5.eecs.umich.edu");
+ strcpy(name->release, "2.4.20");
+ strcpy(name->version, "#1 Mon Aug 18 11:32:15 EDT 2003");
+ strcpy(name->machine, "sparc");
+
+ name.copyOut(xc->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<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)
+ : 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 <= 284 entries because that is all there
+ // is space for.
+ assert(Num_Syscall_Descs <= 284);
+}
+
+
+
+SyscallDesc*
+SparcLinuxProcess::getDesc(int callnum)
+{
+ if (callnum < 0 || callnum > Num_Syscall_Descs)
+ return NULL;
+ return &syscallDescs[callnum];
+}
diff --git a/src/arch/sparc/linux/process.hh b/src/arch/sparc/linux/process.hh
new file mode 100644
index 000000000..23ce66d02
--- /dev/null
+++ b/src/arch/sparc/linux/process.hh
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2003-2004 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __SPARC_LINUX_PROCESS_HH__
+#define __SPARC_LINUX_PROCESS_HH__
+
+#include "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 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);
+
+ virtual SyscallDesc* getDesc(int callnum);
+
+ /// The target system's hostname.
+ static const char *hostname;
+
+ /// Array of syscall descriptors, indexed by call number.
+ static SyscallDesc syscallDescs[];
+
+ const int Num_Syscall_Descs;
+};
+
+SyscallReturn getresuidFunc(SyscallDesc *desc, int num,
+ Process *p, ExecContext *xc);
+
+} // namespace SparcISA
+#endif // __ALPHA_LINUX_PROCESS_HH__
diff --git a/src/arch/sparc/process.cc b/src/arch/sparc/process.cc
new file mode 100644
index 000000000..fe6692cc3
--- /dev/null
+++ b/src/arch/sparc/process.cc
@@ -0,0 +1,379 @@
+/*
+ * Copyright (c) 2003-2004 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "arch/sparc/isa_traits.hh"
+#include "arch/sparc/process.hh"
+#include "arch/sparc/linux/process.hh"
+#include "arch/sparc/solaris/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"
+
+using namespace std;
+using namespace SparcISA;
+
+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)
+{
+ 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 with arch %x does not match architecture %x.",
+ objFile->getArch(), ObjectFile::SPARC);
+ switch (objFile->getOpSys()) {
+ case ObjectFile::Linux:
+ process = new SparcLinuxProcess(nm, objFile, system,
+ stdin_fd, stdout_fd, stderr_fd,
+ argv, envp);
+ break;
+
+
+ case ObjectFile::Solaris:
+ process = new SparcSolarisProcess(nm, objFile, system,
+ stdin_fd, stdout_fd, stderr_fd,
+ argv, envp);
+ break;
+ default:
+ fatal("Unknown/unsupported operating system.");
+ }
+
+ if (process == NULL)
+ fatal("Unknown error creating process object.");
+ return process;
+}
+
+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, 0x02);
+
+ //Setup default FP state
+ execContexts[0]->setMiscReg(MISCREG_FSR, 0);
+
+ execContexts[0]->setMiscReg(MISCREG_TICK, 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/src/arch/sparc/process.hh b/src/arch/sparc/process.hh
new file mode 100644
index 000000000..c177f20a5
--- /dev/null
+++ b/src/arch/sparc/process.hh
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2003-2004 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __SPARC_PROCESS_HH__
+#define __SPARC_PROCESS_HH__
+
+#include <string>
+#include <vector>
+#include "sim/process.hh"
+
+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);
+
+ void argsInit(int intSize, int pageSize);
+
+};
+
+#endif // __SPARC_PROCESS_HH__
diff --git a/src/arch/sparc/regfile.hh b/src/arch/sparc/regfile.hh
new file mode 100644
index 000000000..5322ffb37
--- /dev/null
+++ b/src/arch/sparc/regfile.hh
@@ -0,0 +1,861 @@
+/*
+ * 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/exceptions.hh"
+#include "arch/sparc/faults.hh"
+#include "base/trace.hh"
+#include "sim/byteswap.hh"
+#include "cpu/cpuevent.hh"
+#include "sim/host.hh"
+
+class Checkpoint;
+
+namespace SparcISA
+{
+
+ typedef uint8_t RegIndex;
+
+ // MAXTL - maximum trap level
+ const int MaxPTL = 2;
+ const int MaxTL = 6;
+ const int MaxGL = 3;
+ const int MaxPGL = 2;
+
+ // NWINDOWS - number of register windows, can be 3 to 32
+ const int NWindows = 32;
+
+
+ const int AsrStart = 0;
+ const int PrStart = 32;
+ const int HprStart = 64;
+ const int MiscStart = 96;
+
+
+ const uint64_t Bit64 = 0x8000000000000000;
+
+ 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[MaxGL][RegsPerFrame];
+ IntReg regSegments[2 * NWindows][RegsPerFrame];
+
+ enum regFrame {Globals, Outputs, Locals, Inputs, NumFrames};
+
+ IntReg * regView[NumFrames];
+
+ static const int RegGlobalOffset = 0;
+ static const int FrameOffset = MaxGL * RegsPerFrame;
+ 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()
+ {
+ int x;
+ for (x = 0; x < MaxGL; x++)
+ memset(regGlobals[x], 0, sizeof(regGlobals[x]));
+ for(int x = 0; x < 2 * NWindows; x++)
+ bzero(regSegments[x], sizeof(regSegments[x]));
+ }
+
+ IntRegFile()
+ {
+ offset[Globals] = 0;
+ regView[Globals] = regGlobals[0];
+ 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 setGlobals(int gl)
+ {
+
+ DPRINTF(Sparc, "Now using %d globals", gl);
+
+ regView[Globals] = regGlobals[gl];
+ offset[Globals] = RegGlobalOffset + gl * RegsPerFrame;
+ }
+
+ 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
+ {
+ /** Ancillary State Registers */
+ MISCREG_Y = AsrStart + 0,
+ MISCREG_CCR = AsrStart + 2,
+ MISCREG_ASI = AsrStart + 3,
+ MISCREG_TICK = AsrStart + 4,
+ MISCREG_PC = AsrStart + 5,
+ MISCREG_FPRS = AsrStart + 6,
+ MISCREG_PCR = AsrStart + 16,
+ MISCREG_PIC = AsrStart + 17,
+ MISCREG_GSR = AsrStart + 19,
+ MISCREG_SOFTINT_SET = AsrStart + 20,
+ MISCREG_SOFTINT_CLR = AsrStart + 21,
+ MISCREG_SOFTINT = AsrStart + 22,
+ MISCREG_TICK_CMPR = AsrStart + 23,
+ MISCREG_STICK = AsrStart + 24,
+ MISCREG_STICK_CMPR = AsrStart + 25,
+
+ /** Privilged Registers */
+ MISCREG_TPC = PrStart + 0,
+ MISCREG_TNPC = PrStart + 1,
+ MISCREG_TSTATE = PrStart + 2,
+ MISCREG_TT = PrStart + 3,
+ MISCREG_PRIVTICK = PrStart + 4,
+ MISCREG_TBA = PrStart + 5,
+ MISCREG_PSTATE = PrStart + 6,
+ MISCREG_TL = PrStart + 7,
+ MISCREG_PIL = PrStart + 8,
+ MISCREG_CWP = PrStart + 9,
+ MISCREG_CANSAVE = PrStart + 10,
+ MISCREG_CANRESTORE = PrStart + 11,
+ MISCREG_CLEANWIN = PrStart + 12,
+ MISCREG_OTHERWIN = PrStart + 13,
+ MISCREG_WSTATE = PrStart + 14,
+ MISCREG_GL = PrStart + 16,
+
+ /** Hyper privileged registers */
+ MISCREG_HPSTATE = HprStart + 0,
+ MISCREG_HTSTATE = HprStart + 1,
+ MISCREG_HINTP = HprStart + 3,
+ MISCREG_HTBA = HprStart + 5,
+ MISCREG_HVER = HprStart + 6,
+ MISCREG_STRAND_STS_REG = HprStart + 16,
+ MISCREG_HSTICK_CMPR = HprStart + 31,
+
+ /** Floating Point Status Register */
+ MISCREG_FSR = MiscStart + 0
+
+ };
+
+ // The control registers, broken out into fields
+ class MiscRegFile
+ {
+ private:
+
+ /* ASR Registers */
+ 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;
+ };
+ 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
+ union {
+ uint64_t tick; // Hardware clock-tick counter
+ struct {
+ int64_t counter:63; // Clock-tick count
+ uint64_t npt:1; // Non-priveleged trap
+ } tickFields;
+ };
+ 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;
+ };
+ union {
+ uint64_t softint;
+ struct {
+ uint64_t tm:1;
+ uint64_t int_level:14;
+ uint64_t sm:1;
+ } softintFields;
+ };
+ union {
+ uint64_t tick_cmpr; // Hardware tick compare registers
+ struct {
+ uint64_t tick_cmpr:63; // Clock-tick count
+ uint64_t int_dis:1; // Non-priveleged trap
+ } tick_cmprFields;
+ };
+ union {
+ uint64_t stick; // Hardware clock-tick counter
+ struct {
+ int64_t :63; // Not used, storage in SparcSystem
+ uint64_t npt:1; // Non-priveleged trap
+ } stickFields;
+ };
+ union {
+ uint64_t stick_cmpr; // Hardware tick compare registers
+ struct {
+ uint64_t tick_cmpr:63; // Clock-tick count
+ uint64_t int_dis:1; // Non-priveleged trap
+ } stick_cmprFields;
+ };
+
+
+ /* Privileged Registers */
+ 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 :3; // Reserved bits
+ uint64_t pstate:13; // Process State
+ uint64_t :3; // Reserved bits
+ uint64_t asi:8; // Address Space Identifier
+ uint64_t ccr:8; // Condition Code Register
+ uint64_t gl:8; // Global level
+ } tstateFields[MaxTL];
+ };
+ uint16_t tt[MaxTL]; // Trap Type (Type of trap which occured
+ // on the previous level)
+ uint64_t tba; // Trap Base Address
+
+ union {
+ uint16_t pstate; // Process State Register
+ struct {
+ uint16_t :1; // reserved
+ 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 :1; // reserved2
+ uint16_t mm:2; // Memory Model
+ uint16_t tle:1; // Trap little-endian
+ uint16_t cle:1; // Current little-endian
+ } pstateFields;
+ };
+ uint8_t tl; // Trap Level
+ uint8_t pil; // Process Interrupt Register
+ uint8_t cwp; // Current Window Pointer
+ uint8_t cansave; // Savable windows
+ uint8_t canrestore; // Restorable windows
+ uint8_t cleanwin; // Clean windows
+ uint8_t otherwin; // Other 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;
+ };
+ uint8_t gl; // Global level register
+
+
+ /** Hyperprivileged Registers */
+ union {
+ uint64_t hpstate; // Hyperprivileged State Register
+ struct {
+ uint8_t tlz: 1;
+ uint8_t :1;
+ uint8_t hpriv:1;
+ uint8_t :2;
+ uint8_t red:1;
+ uint8_t :4;
+ uint8_t ibe:1;
+ uint8_t id:1;
+ } hpstateFields;
+ };
+
+ uint64_t htstate[MaxTL]; // Hyperprivileged Trap State Register
+ uint64_t hintp;
+ uint64_t htba; // Hyperprivileged Trap Base Address register
+ union {
+ uint64_t hstick_cmpr; // Hardware tick compare registers
+ struct {
+ uint64_t tick_cmpr:63; // Clock-tick count
+ uint64_t int_dis:1; // Non-priveleged trap
+ } hstick_cmprFields;
+ };
+
+ uint64_t strandStatusReg; // Per strand status register
+
+
+ /** Floating point misc registers. */
+ 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;
+ };
+
+ // These need to check the int_dis field and if 0 then
+ // set appropriate bit in softint and checkinterrutps on the cpu
+#if FULL_SYSTEM
+ /** Process a tick compare event and generate an interrupt on the cpu if
+ * appropriate. */
+ void processTickCompare(ExecContext *xc);
+ void processSTickCompare(ExecContext *xc);
+ void processHSTickCompare(ExecContext *xc);
+
+ typedef CpuEventWrapper<MiscRegFile,
+ &MiscRegFile::processTickCompare> TickCompareEvent;
+ TickCompareEvent *tickCompare;
+
+ typedef CpuEventWrapper<MiscRegFile,
+ &MiscRegFile::processSTickCompare> STickCompareEvent;
+ STickCompareEvent *sTickCompare;
+
+ typedef CpuEventWrapper<MiscRegFile,
+ &MiscRegFile::processHSTickCompare> HSTickCompareEvent;
+ HSTickCompareEvent *hSTickCompare;
+
+ /** Fullsystem only register version of ReadRegWithEffect() */
+ MiscReg readFSRegWithEffect(int miscReg, Fault &fault, ExecContext *xc);
+ /** Fullsystem only register version of SetRegWithEffect() */
+ Fault setFSRegWithEffect(int miscReg, const MiscReg &val,
+ ExecContext * xc);
+#endif
+ 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;
+ gl = MaxGL;
+
+ tickFields.counter = 0; //The TICK register is unreadable bya
+ tickFields.npt = 1; //The TICK register is unreadable by by !priv
+
+ softint = 0; // Clear all the soft interrupt bits
+ tick_cmprFields.int_dis = 1; // disable timer compare interrupts
+ tick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing
+ stickFields.npt = 1; //The TICK register is unreadable by by !priv
+ stick_cmprFields.int_dis = 1; // disable timer compare interrupts
+ stick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing
+
+
+ tt[tl] = power_on_reset;
+ pstate = 0; // fields 0 but pef
+ pstateFields.pef = 1;
+
+ hpstate = 0;
+ hpstateFields.red = 1;
+ hpstateFields.hpriv = 1;
+ hpstateFields.tlz = 0; // this is a guess
+
+ hintp = 0; // no interrupts pending
+ hstick_cmprFields.int_dis = 1; // disable timer compare interrupts
+ hstick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing
+
+#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();
+ }
+
+ /** read a value out of an either an SE or FS IPR. No checking is done
+ * about SE vs. FS as this is mostly used to copy the regfile. Thus more
+ * register are copied that are necessary for FS. However this prevents
+ * a bunch of ifdefs and is rarely called so is not performance
+ * criticial. */
+ MiscReg readReg(int miscReg);
+
+ /** Read a value from an IPR. Only the SE iprs are here and the rest
+ * are are readFSRegWithEffect (which is called by readRegWithEffect()).
+ * Checking is done for permission based on state bits in the miscreg
+ * file. */
+ MiscReg readRegWithEffect(int miscReg, Fault &fault, ExecContext *xc);
+
+ /** write a value into an either an SE or FS IPR. No checking is done
+ * about SE vs. FS as this is mostly used to copy the regfile. Thus more
+ * register are copied that are necessary for FS. However this prevents
+ * a bunch of ifdefs and is rarely called so is not performance
+ * criticial.*/
+ Fault setReg(int miscReg, const MiscReg &val);
+
+ /** Write a value into an IPR. Only the SE iprs are here and the rest
+ * are are setFSRegWithEffect (which is called by setRegWithEffect()).
+ * Checking is done for permission based on state bits in the miscreg
+ * file. */
+ 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);
+
+ bool isHyperPriv() { return hpstateFields.hpriv; }
+ bool isPriv() { return hpstateFields.hpriv || pstateFields.priv; }
+ bool isNonPriv() { return !isPriv(); }
+ };
+
+ 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
+ };
+ typedef int ContextVal;
+
+ void changeContext(ContextParam param, ContextVal val)
+ {
+ switch(param)
+ {
+ case CONTEXT_CWP:
+ intRegFile.setCWP(val);
+ break;
+ case CONTEXT_GLOBALS:
+ intRegFile.setGlobals(val);
+ 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);
+
+ int InterruptLevel(uint64_t softint);
+
+} // namespace SparcISA
+
+#endif
diff --git a/src/arch/sparc/solaris/process.cc b/src/arch/sparc/solaris/process.cc
new file mode 100644
index 000000000..95cdb0bd5
--- /dev/null
+++ b/src/arch/sparc/solaris/process.cc
@@ -0,0 +1,347 @@
+/*
+ * 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/isa_traits.hh"
+#include "arch/sparc/solaris/process.hh"
+#include "arch/sparc/regfile.hh"
+
+#include "base/trace.hh"
+#include "cpu/exec_context.hh"
+#include "kern/solaris/solaris.hh"
+
+#include "sim/process.hh"
+#include "sim/syscall_emul.hh"
+
+using namespace std;
+using namespace SparcISA;
+
+
+/// Target uname() handler.
+static SyscallReturn
+unameFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+{
+ TypedBufferArg<Solaris::utsname> name(xc->getSyscallArg(0));
+
+ strcpy(name->sysname, "SunOS");
+ strcpy(name->nodename, "m5.eecs.umich.edu");
+ strcpy(name->release, "5.9"); //?? do we want this or something newer?
+ strcpy(name->version, "Generic_118558-21");
+ strcpy(name->machine, "sun4u");
+
+ name.copyOut(xc->getMemPort());
+
+ return 0;
+}
+
+
+SyscallDesc SparcSolarisProcess::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<SparcSolaris>),
+ /* 6 */ SyscallDesc("close", closeFunc),
+ /* 7 */ SyscallDesc("wait", unimplementedFunc),
+ /* 8 */ SyscallDesc("creat", unimplementedFunc),
+ /* 9 */ SyscallDesc("link", unimplementedFunc),
+ /* 10 */ SyscallDesc("unlink", unlinkFunc),
+ /* 11 */ SyscallDesc("exec", unimplementedFunc),
+ /* 12 */ SyscallDesc("chdir", unimplementedFunc),
+ /* 13 */ SyscallDesc("time", unimplementedFunc),
+ /* 14 */ SyscallDesc("mknod", unimplementedFunc),
+ /* 15 */ SyscallDesc("chmod", chmodFunc<Solaris>),
+ /* 16 */ SyscallDesc("chown", chownFunc),
+ /* 17 */ SyscallDesc("brk", obreakFunc),
+ /* 18 */ SyscallDesc("stat", 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("pcsample", unimplementedFunc),
+ /* 27 */ SyscallDesc("alarm", unimplementedFunc),
+ /* 28 */ SyscallDesc("fstat", fstatFunc<SparcSolaris>),
+ /* 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("statfs", unimplementedFunc),
+ /* 36 */ SyscallDesc("sync", unimplementedFunc),
+ /* 37 */ SyscallDesc("kill", unimplementedFunc),
+ /* 38 */ SyscallDesc("fstatfs", unimplementedFunc),
+ /* 39 */ SyscallDesc("pgrpsys", unimplementedFunc),
+ /* 40 */ SyscallDesc("xenix", unimplementedFunc),
+ /* 41 */ SyscallDesc("dup", unimplementedFunc),
+ /* 42 */ SyscallDesc("pipe", pipePseudoFunc),
+ /* 43 */ SyscallDesc("times", unimplementedFunc),
+ /* 44 */ SyscallDesc("profil", unimplementedFunc),
+ /* 45 */ SyscallDesc("plock", unimplementedFunc),
+ /* 46 */ SyscallDesc("setgid", unimplementedFunc),
+ /* 47 */ SyscallDesc("getgid", getgidFunc),
+ /* 48 */ SyscallDesc("signal", unimplementedFunc),
+ /* 49 */ SyscallDesc("msgsys", unimplementedFunc),
+ /* 50 */ SyscallDesc("syssun", unimplementedFunc),
+ /* 51 */ SyscallDesc("acct", unimplementedFunc),
+ /* 52 */ SyscallDesc("shmsys", unimplementedFunc),
+ /* 53 */ SyscallDesc("semsys", unimplementedFunc),
+ /* 54 */ SyscallDesc("ioctl", unimplementedFunc),
+ /* 55 */ SyscallDesc("uadmin", unimplementedFunc),
+ /* 56 */ SyscallDesc("RESERVED", unimplementedFunc),
+ /* 57 */ SyscallDesc("utssys", unimplementedFunc),
+ /* 58 */ SyscallDesc("fdsync", unimplementedFunc),
+ /* 59 */ SyscallDesc("execve", unimplementedFunc),
+ /* 60 */ SyscallDesc("umask", unimplementedFunc),
+ /* 61 */ SyscallDesc("chroot", unimplementedFunc),
+ /* 62 */ SyscallDesc("fcntl", unimplementedFunc),
+ /* 63 */ SyscallDesc("ulimit", unimplementedFunc),
+ /* 64 */ SyscallDesc("reserved_64", unimplementedFunc),
+ /* 65 */ SyscallDesc("reserved_65", unimplementedFunc),
+ /* 66 */ SyscallDesc("reserved_66", unimplementedFunc),
+ /* 67 */ SyscallDesc("reserved_67", unimplementedFunc),
+ /* 68 */ SyscallDesc("reserved_68", unimplementedFunc),
+ /* 69 */ SyscallDesc("reserved_69", unimplementedFunc),
+ /* 70 */ SyscallDesc("tasksys", unimplementedFunc),
+ /* 71 */ SyscallDesc("acctctl", unimplementedFunc),
+ /* 72 */ SyscallDesc("reserved_72", unimplementedFunc),
+ /* 73 */ SyscallDesc("getpagesizes", unimplementedFunc),
+ /* 74 */ SyscallDesc("rctlsys", unimplementedFunc),
+ /* 75 */ SyscallDesc("issetugid", unimplementedFunc),
+ /* 76 */ SyscallDesc("fsat", unimplementedFunc),
+ /* 77 */ SyscallDesc("lwp_park", unimplementedFunc),
+ /* 78 */ SyscallDesc("sendfilev", unimplementedFunc),
+ /* 79 */ SyscallDesc("rmdir", unimplementedFunc),
+ /* 80 */ SyscallDesc("mkdir", unimplementedFunc),
+ /* 81 */ SyscallDesc("getdents", unimplementedFunc),
+ /* 82 */ SyscallDesc("reserved_82", unimplementedFunc),
+ /* 83 */ SyscallDesc("reserved_83", unimplementedFunc),
+ /* 84 */ SyscallDesc("sysfs", unimplementedFunc),
+ /* 85 */ SyscallDesc("getmsg", unimplementedFunc),
+ /* 86 */ SyscallDesc("putmsg", unimplementedFunc),
+ /* 87 */ SyscallDesc("poll", unimplementedFunc),
+ /* 88 */ SyscallDesc("lstat", unimplementedFunc),
+ /* 89 */ SyscallDesc("symlink", unimplementedFunc),
+ /* 90 */ SyscallDesc("readlink", unimplementedFunc),
+ /* 91 */ SyscallDesc("setgroups", unimplementedFunc),
+ /* 92 */ SyscallDesc("getgroups", unimplementedFunc),
+ /* 93 */ SyscallDesc("fchmod", unimplementedFunc),
+ /* 94 */ SyscallDesc("fchown", unimplementedFunc),
+ /* 95 */ SyscallDesc("sigprocmask", unimplementedFunc),
+ /* 96 */ SyscallDesc("sigsuspend", unimplementedFunc),
+ /* 97 */ SyscallDesc("sigaltstack", unimplementedFunc),
+ /* 98 */ SyscallDesc("sigaction", unimplementedFunc),
+ /* 99 */ SyscallDesc("sigpending", unimplementedFunc),
+ /* 100 */ SyscallDesc("context", unimplementedFunc),
+ /* 101 */ SyscallDesc("evsys", unimplementedFunc),
+ /* 102 */ SyscallDesc("evtrapret", unimplementedFunc),
+ /* 103 */ SyscallDesc("statvfs", unimplementedFunc),
+ /* 104 */ SyscallDesc("fstatvfs", unimplementedFunc),
+ /* 105 */ SyscallDesc("getloadavg", unimplementedFunc),
+ /* 106 */ SyscallDesc("nfssys", unimplementedFunc),
+ /* 107 */ SyscallDesc("waitsys", unimplementedFunc),
+ /* 108 */ SyscallDesc("sigsendsys", unimplementedFunc),
+ /* 109 */ SyscallDesc("hrtsys", unimplementedFunc),
+ /* 110 */ SyscallDesc("acancel", unimplementedFunc),
+ /* 111 */ SyscallDesc("async", unimplementedFunc),
+ /* 112 */ SyscallDesc("priocntlsys", unimplementedFunc),
+ /* 113 */ SyscallDesc("pathconf", unimplementedFunc),
+ /* 114 */ SyscallDesc("mincore", unimplementedFunc),
+ /* 115 */ SyscallDesc("mmap", mmapFunc<SparcSolaris>),
+ /* 116 */ SyscallDesc("mprotect", unimplementedFunc),
+ /* 117 */ SyscallDesc("munmap", munmapFunc),
+ /* 118 */ SyscallDesc("fpathconf", unimplementedFunc),
+ /* 119 */ SyscallDesc("vfork", unimplementedFunc),
+ /* 120 */ SyscallDesc("fchdir", unimplementedFunc),
+ /* 121 */ SyscallDesc("readv", unimplementedFunc),
+ /* 122 */ SyscallDesc("writev", unimplementedFunc),
+ /* 123 */ SyscallDesc("xstat", unimplementedFunc),
+ /* 124 */ SyscallDesc("lxstat", unimplementedFunc),
+ /* 125 */ SyscallDesc("fxstat", unimplementedFunc),
+ /* 126 */ SyscallDesc("xmknod", unimplementedFunc),
+ /* 127 */ SyscallDesc("clocal", unimplementedFunc),
+ /* 128 */ SyscallDesc("setrlimit", unimplementedFunc),
+ /* 129 */ SyscallDesc("getrlimit", unimplementedFunc),
+ /* 130 */ SyscallDesc("lchown", unimplementedFunc),
+ /* 131 */ SyscallDesc("memcntl", unimplementedFunc),
+ /* 132 */ SyscallDesc("getpmsg", unimplementedFunc),
+ /* 133 */ SyscallDesc("putpmsg", unimplementedFunc),
+ /* 134 */ SyscallDesc("rename", unimplementedFunc),
+ /* 135 */ SyscallDesc("uname", unameFunc),
+ /* 136 */ SyscallDesc("setegid", unimplementedFunc),
+ /* 137 */ SyscallDesc("sysconfig", unimplementedFunc),
+ /* 138 */ SyscallDesc("adjtime", unimplementedFunc),
+ /* 139 */ SyscallDesc("systeminfo", unimplementedFunc),
+ /* 140 */ SyscallDesc("reserved_140", unimplementedFunc),
+ /* 141 */ SyscallDesc("seteuid", unimplementedFunc),
+ /* 142 */ SyscallDesc("vtrace", unimplementedFunc),
+ /* 143 */ SyscallDesc("fork1", unimplementedFunc),
+ /* 144 */ SyscallDesc("sigtimedwait", unimplementedFunc),
+ /* 145 */ SyscallDesc("lwp_info", unimplementedFunc),
+ /* 146 */ SyscallDesc("yield", unimplementedFunc),
+ /* 147 */ SyscallDesc("lwp_sema_wait", unimplementedFunc),
+ /* 148 */ SyscallDesc("lwp_sema_post", unimplementedFunc),
+ /* 149 */ SyscallDesc("lwp_sema_trywait", unimplementedFunc),
+ /* 150 */ SyscallDesc("lwp_detach", unimplementedFunc),
+ /* 151 */ SyscallDesc("corectl", unimplementedFunc),
+ /* 152 */ SyscallDesc("modctl", unimplementedFunc),
+ /* 153 */ SyscallDesc("fchroot", unimplementedFunc),
+ /* 154 */ SyscallDesc("utimes", unimplementedFunc),
+ /* 155 */ SyscallDesc("vhangup", unimplementedFunc),
+ /* 156 */ SyscallDesc("gettimeofday", unimplementedFunc),
+ /* 157 */ SyscallDesc("getitimer", unimplementedFunc),
+ /* 158 */ SyscallDesc("setitimer", unimplementedFunc),
+ /* 159 */ SyscallDesc("lwp_create", unimplementedFunc),
+ /* 160 */ SyscallDesc("lwp_exit", unimplementedFunc),
+ /* 161 */ SyscallDesc("lwp_suspend", unimplementedFunc),
+ /* 162 */ SyscallDesc("lwp_continue", unimplementedFunc),
+ /* 163 */ SyscallDesc("lwp_kill", unimplementedFunc),
+ /* 164 */ SyscallDesc("lwp_self", unimplementedFunc),
+ /* 165 */ SyscallDesc("lwp_setprivate", unimplementedFunc),
+ /* 166 */ SyscallDesc("lwp_getprivate", unimplementedFunc),
+ /* 167 */ SyscallDesc("lwp_wait", unimplementedFunc),
+ /* 168 */ SyscallDesc("lwp_mutex_wakeup", unimplementedFunc),
+ /* 169 */ SyscallDesc("lwp_mutex_lock", unimplementedFunc),
+ /* 170 */ SyscallDesc("lwp_cond_wait", unimplementedFunc),
+ /* 171 */ SyscallDesc("lwp_cond_signal", unimplementedFunc),
+ /* 172 */ SyscallDesc("lwp_cond_broadcast", unimplementedFunc),
+ /* 173 */ SyscallDesc("pread", unimplementedFunc),
+ /* 174 */ SyscallDesc("pwrite", unimplementedFunc),
+ /* 175 */ SyscallDesc("llseek", unimplementedFunc),
+ /* 176 */ SyscallDesc("inst_sync", unimplementedFunc),
+ /* 177 */ SyscallDesc("srmlimitsys", unimplementedFunc),
+ /* 178 */ SyscallDesc("kaio", unimplementedFunc),
+ /* 179 */ SyscallDesc("cpc", unimplementedFunc),
+ /* 180 */ SyscallDesc("lgrpsys_meminfosys", unimplementedFunc),
+ /* 181 */ SyscallDesc("rusagesys", unimplementedFunc),
+ /* 182 */ SyscallDesc("reserved_182", unimplementedFunc),
+ /* 183 */ SyscallDesc("reserved_183", unimplementedFunc),
+ /* 184 */ SyscallDesc("tsolsys", unimplementedFunc),
+ /* 185 */ SyscallDesc("acl", unimplementedFunc),
+ /* 186 */ SyscallDesc("auditsys", unimplementedFunc),
+ /* 187 */ SyscallDesc("processor_bind", unimplementedFunc),
+ /* 188 */ SyscallDesc("processor_info", unimplementedFunc),
+ /* 189 */ SyscallDesc("p_online", unimplementedFunc),
+ /* 190 */ SyscallDesc("sigqueue", unimplementedFunc),
+ /* 191 */ SyscallDesc("clock_gettime", unimplementedFunc),
+ /* 192 */ SyscallDesc("clock_settime", unimplementedFunc),
+ /* 193 */ SyscallDesc("clock_getres", unimplementedFunc),
+ /* 194 */ SyscallDesc("timer_create", unimplementedFunc),
+ /* 195 */ SyscallDesc("timer_delete", unimplementedFunc),
+ /* 196 */ SyscallDesc("timer_settime", unimplementedFunc),
+ /* 197 */ SyscallDesc("timer_gettime", unimplementedFunc),
+ /* 198 */ SyscallDesc("timer_getoverrun", unimplementedFunc),
+ /* 199 */ SyscallDesc("nanosleep", unimplementedFunc),
+ /* 200 */ SyscallDesc("facl", unimplementedFunc),
+ /* 201 */ SyscallDesc("door", unimplementedFunc),
+ /* 202 */ SyscallDesc("setreuid", unimplementedFunc),
+ /* 203 */ SyscallDesc("setregid", unimplementedFunc),
+ /* 204 */ SyscallDesc("install_utrap", unimplementedFunc),
+ /* 205 */ SyscallDesc("signotify", unimplementedFunc),
+ /* 206 */ SyscallDesc("schedctl", unimplementedFunc),
+ /* 207 */ SyscallDesc("pset", unimplementedFunc),
+ /* 208 */ SyscallDesc("sparc_utrap_install", unimplementedFunc),
+ /* 209 */ SyscallDesc("resolvepath", unimplementedFunc),
+ /* 210 */ SyscallDesc("signotifywait", unimplementedFunc),
+ /* 211 */ SyscallDesc("lwp_sigredirect", unimplementedFunc),
+ /* 212 */ SyscallDesc("lwp_alarm", unimplementedFunc),
+ /* 213 */ SyscallDesc("getdents64", unimplementedFunc),
+ /* 214 */ SyscallDesc("mmap64", unimplementedFunc),
+ /* 215 */ SyscallDesc("stat64", unimplementedFunc),
+ /* 216 */ SyscallDesc("lstat64", unimplementedFunc),
+ /* 217 */ SyscallDesc("fstat64", unimplementedFunc),
+ /* 218 */ SyscallDesc("statvfs64", unimplementedFunc),
+ /* 219 */ SyscallDesc("fstatvfs64", unimplementedFunc),
+ /* 220 */ SyscallDesc("setrlimit64", unimplementedFunc),
+ /* 221 */ SyscallDesc("getrlimit64", unimplementedFunc),
+ /* 222 */ SyscallDesc("pread64", unimplementedFunc),
+ /* 223 */ SyscallDesc("pwrite64", unimplementedFunc),
+ /* 224 */ SyscallDesc("creat64", unimplementedFunc),
+ /* 225 */ SyscallDesc("open64", unimplementedFunc),
+ /* 226 */ SyscallDesc("rpcsys", unimplementedFunc),
+ /* 227 */ SyscallDesc("reserved_227", unimplementedFunc),
+ /* 228 */ SyscallDesc("reserved_228", unimplementedFunc),
+ /* 229 */ SyscallDesc("reserved_229", unimplementedFunc),
+ /* 230 */ SyscallDesc("so_socket", unimplementedFunc),
+ /* 231 */ SyscallDesc("so_socketpair", unimplementedFunc),
+ /* 232 */ SyscallDesc("bind", unimplementedFunc),
+ /* 233 */ SyscallDesc("listen", unimplementedFunc),
+ /* 234 */ SyscallDesc("accept", unimplementedFunc),
+ /* 235 */ SyscallDesc("connect", unimplementedFunc),
+ /* 236 */ SyscallDesc("shutdown", unimplementedFunc),
+ /* 237 */ SyscallDesc("recv", unimplementedFunc),
+ /* 238 */ SyscallDesc("recvfrom", unimplementedFunc),
+ /* 239 */ SyscallDesc("recvmsg", unimplementedFunc),
+ /* 240 */ SyscallDesc("send", unimplementedFunc),
+ /* 241 */ SyscallDesc("sendmsg", unimplementedFunc),
+ /* 242 */ SyscallDesc("sendto", unimplementedFunc),
+ /* 243 */ SyscallDesc("getpeername", unimplementedFunc),
+ /* 244 */ SyscallDesc("getsockname", unimplementedFunc),
+ /* 245 */ SyscallDesc("getsockopt", unimplementedFunc),
+ /* 246 */ SyscallDesc("setsockopt", unimplementedFunc),
+ /* 247 */ SyscallDesc("sockconfig", unimplementedFunc),
+ /* 248 */ SyscallDesc("ntp_gettime", unimplementedFunc),
+ /* 249 */ SyscallDesc("ntp_adjtime", unimplementedFunc),
+ /* 250 */ SyscallDesc("lwp_mutex_unlock", unimplementedFunc),
+ /* 251 */ SyscallDesc("lwp_mutex_trylock", unimplementedFunc),
+ /* 252 */ SyscallDesc("lwp_mutex_init", unimplementedFunc),
+ /* 253 */ SyscallDesc("cladm", unimplementedFunc),
+ /* 254 */ SyscallDesc("lwp_sigtimedwait", unimplementedFunc),
+ /* 255 */ SyscallDesc("umount2", unimplementedFunc)
+};
+
+SparcSolarisProcess::SparcSolarisProcess(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)
+ : 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 <= 284 entries because that is all there
+ // is space for.
+ assert(Num_Syscall_Descs <= 284);
+}
+
+
+
+SyscallDesc*
+SparcSolarisProcess::getDesc(int callnum)
+{
+ if (callnum < 0 || callnum > Num_Syscall_Descs)
+ return NULL;
+ return &syscallDescs[callnum];
+}
diff --git a/src/arch/sparc/solaris/process.hh b/src/arch/sparc/solaris/process.hh
new file mode 100644
index 000000000..24dffdaf0
--- /dev/null
+++ b/src/arch/sparc/solaris/process.hh
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2003-2004 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __SPARC_SOLARIS_PROCESS_HH__
+#define __SPARC_SOLARIS_PROCESS_HH__
+
+#include "arch/sparc/solaris/solaris.hh"
+#include "arch/sparc/process.hh"
+#include "sim/process.hh"
+
+namespace SparcISA {
+
+/// A process with emulated SPARC/Solaris syscalls.
+class SparcSolarisProcess : public SparcLiveProcess
+{
+ public:
+ /// Constructor.
+ SparcSolarisProcess(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);
+
+ virtual SyscallDesc* getDesc(int callnum);
+
+ /// The target system's hostname.
+ static const char *hostname;
+
+ /// Array of syscall descriptors, indexed by call number.
+ static SyscallDesc syscallDescs[];
+
+ const int Num_Syscall_Descs;
+};
+
+
+} // namespace SparcISA
+#endif // __ALPHA_SOLARIS_PROCESS_HH__
diff --git a/src/arch/sparc/solaris/solaris.cc b/src/arch/sparc/solaris/solaris.cc
new file mode 100644
index 000000000..a56f10740
--- /dev/null
+++ b/src/arch/sparc/solaris/solaris.cc
@@ -0,0 +1,74 @@
+/*
+ * 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/solaris/solaris.hh"
+
+// open(2) flags translation table
+OpenFlagTransTable SparcSolaris::openFlagTable[] = {
+#ifdef _MSC_VER
+ { SparcSolaris::TGT_O_RDONLY, _O_RDONLY },
+ { SparcSolaris::TGT_O_WRONLY, _O_WRONLY },
+ { SparcSolaris::TGT_O_RDWR, _O_RDWR },
+ { SparcSolaris::TGT_O_APPEND, _O_APPEND },
+ { SparcSolaris::TGT_O_CREAT, _O_CREAT },
+ { SparcSolaris::TGT_O_TRUNC, _O_TRUNC },
+ { SparcSolaris::TGT_O_EXCL, _O_EXCL },
+#ifdef _O_NONBLOCK
+ { SparcSolaris::TGT_O_NONBLOCK, _O_NONBLOCK },
+ { SparcSolaris::TGT_O_NDELAY , _O_NONBLOCK },
+#endif
+#ifdef _O_NOCTTY
+ { SparcSolaris::TGT_O_NOCTTY, _O_NOCTTY },
+#endif
+#ifdef _O_SYNC
+ { SparcSolaris::TGT_O_SYNC, _O_SYNC },
+ { SparcSolaris::TGT_O_DSYNC, _O_SYNC },
+ { SparcSolaris::TGT_O_RSYNC, _O_SYNC },
+#endif
+#else /* !_MSC_VER */
+ { SparcSolaris::TGT_O_RDONLY, O_RDONLY },
+ { SparcSolaris::TGT_O_WRONLY, O_WRONLY },
+ { SparcSolaris::TGT_O_RDWR, O_RDWR },
+ { SparcSolaris::TGT_O_APPEND, O_APPEND },
+ { SparcSolaris::TGT_O_CREAT, O_CREAT },
+ { SparcSolaris::TGT_O_TRUNC, O_TRUNC },
+ { SparcSolaris::TGT_O_EXCL, O_EXCL },
+ { SparcSolaris::TGT_O_NONBLOCK, O_NONBLOCK },
+ { SparcSolaris::TGT_O_NDELAY , O_NONBLOCK },
+ { SparcSolaris::TGT_O_NOCTTY, O_NOCTTY },
+#ifdef O_SYNC
+ { SparcSolaris::TGT_O_SYNC, O_SYNC },
+ { SparcSolaris::TGT_O_DSYNC, O_SYNC },
+ { SparcSolaris::TGT_O_RSYNC, O_SYNC },
+#endif
+#endif /* _MSC_VER */
+};
+
+const int SparcSolaris::NUM_OPEN_FLAGS =
+ (sizeof(SparcSolaris::openFlagTable)/sizeof(SparcSolaris::openFlagTable[0]));
+
diff --git a/src/arch/sparc/solaris/solaris.hh b/src/arch/sparc/solaris/solaris.hh
new file mode 100644
index 000000000..6833a2d6a
--- /dev/null
+++ b/src/arch/sparc/solaris/solaris.hh
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2003-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __ARCH_SPARC_SOLARIS_SOLARIS_HH__
+#define __ARCH_SPARC_SOLARIS_SOLARIS_HH__
+
+#include "kern/solaris/solaris.hh"
+
+class SparcSolaris : public Solaris
+{
+ 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_NDELAY = 0x00000004; //!< O_NONBLOCK
+ static const int TGT_O_APPEND = 0x00000008; //!< O_APPEND
+ static const int TGT_O_SYNC = 0x00000010; //!< O_SYNC
+ static const int TGT_O_DSYNC = 0x00000040; //!< O_SYNC
+ static const int TGT_O_RSYNC = 0x00008000; //!< O_SYNC
+ static const int TGT_O_NONBLOCK = 0x00000080; //!< O_NONBLOCK
+ static const int TGT_O_PRIV = 0x00001000; //??
+ static const int TGT_O_LARGEFILE = 0x00002000; //??
+ 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_XATTR = 0x00004000; //??
+
+ static const int NUM_OPEN_FLAGS;
+
+ static const unsigned TGT_MAP_ANONYMOUS = 0x100;
+};
+
+#endif
diff --git a/arch/sparc/stacktrace.hh b/src/arch/sparc/stacktrace.hh
index 1d8d97a79..1d8d97a79 100644
--- a/arch/sparc/stacktrace.hh
+++ b/src/arch/sparc/stacktrace.hh
diff --git a/src/arch/sparc/system.cc b/src/arch/sparc/system.cc
new file mode 100644
index 000000000..44413e339
--- /dev/null
+++ b/src/arch/sparc/system.cc
@@ -0,0 +1,201 @@
+/*
+ * 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), sysTick(0)
+
+{
+ 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/src/arch/sparc/system.hh b/src/arch/sparc/system.hh
new file mode 100644
index 000000000..a3eee7555
--- /dev/null
+++ b/src/arch/sparc/system.hh
@@ -0,0 +1,117 @@
+/*
+ * 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);
+
+ ~SparcSystem();
+
+ 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;
+
+ /** System Tick for syncronized tick across all cpus. */
+ Tick sysTick;
+
+ 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/src/arch/sparc/tlb.hh b/src/arch/sparc/tlb.hh
new file mode 100644
index 000000000..35ff08b43
--- /dev/null
+++ b/src/arch/sparc/tlb.hh
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ *
+ * Authors: Ali Saidi
+ */
+
+#ifndef __ARCH_SPARC_TLB_HH__
+#define __ARCH_SPARC_TLB_HH__
+
+
+#endif // __ARCH_SPARC_TLB_HH__
diff --git a/src/arch/sparc/ua2005.cc b/src/arch/sparc/ua2005.cc
new file mode 100644
index 000000000..680e94080
--- /dev/null
+++ b/src/arch/sparc/ua2005.cc
@@ -0,0 +1,222 @@
+/*
+ * 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.
+ */
+
+#include "arch/sparc/regfile.hh"
+
+Fault
+SparcISA::MiscRegFile::setFSRegWithEffect(int miscReg, const MiscReg &val,
+ ExecContext *xc)
+{
+ int64_t time;
+ SparcSystem *sys;
+ switch (miscReg) {
+ /** Full system only ASRs */
+ case MISCREG_SOFTINT:
+ if (isNonPriv())
+ return new PrivilegedOpcode;
+ // Check if we are going to interrupt because of something
+ int oldLevel = InterruptLevel(softint);
+ int newLevel = InterruptLevel(val);
+ setReg(miscReg, val);
+ if (newLevel > oldLevel)
+ ; // MUST DO SOMETHING HERE TO TELL CPU TO LOOK FOR INTERRUPTS XXX
+ //xc->getCpuPtr()->checkInterrupts = true;
+ return NoFault;
+
+ case MISCREG_SOFTINT_CLR:
+ return setRegWithEffect(miscReg, ~val & softint, xc);
+ case MISCREG_SOFTINT_SET:
+ return setRegWithEffect(miscReg, val | softint, xc);
+
+ case MISCREG_TICK_CMPR:
+ if (isNonPriv())
+ return new PrivilegedOpcode;
+ if (tickCompare == NULL)
+ tickCompare = new TickCompareEvent(this, xc);
+ setReg(miscReg, val);
+ if (tick_cmprFields.int_dis && tickCompare.scheduled())
+ tickCompare.deschedule();
+ time = tick_cmprFields.tick_cmpr - tickFields.counter;
+ if (!tick_cmprFields.int_dis && time > 0)
+ tickCompare.schedule(time * xc->getCpuPtr()->cycles(1));
+ return NoFault;
+
+ case MISCREG_STICK:
+ if (isNonPriv())
+ return new PrivilegedOpcode;
+ if (isPriv())
+ return new PrivilegedAction;
+ sys = dynamic_cast<SparcSystem*>(xc->getSystemPtr());
+ assert(sys != NULL);
+ sys->sysTick = curTick/Clock::Int::ns - val & ~Bit64;
+ stickFields.npt = val & Bit64 ? 1 : 0;
+ return NoFault;
+
+ case MISCREG_STICK_CMPR:
+ if (isNonPriv())
+ return new PrivilegedOpcode;
+ if (sTickCompare == NULL)
+ sTickCompare = new STickCompareEvent(this, xc);
+ sys = dynamic_cast<SparcSystem*>(xc->getSystemPtr());
+ assert(sys != NULL);
+ setReg(miscReg, val);
+ if (stick_cmprFields.int_dis && sTickCompare.scheduled())
+ sTickCompare.deschedule();
+ time = stick_cmprFields.tick_cmpr - sys->sysTick;
+ if (!stick_cmprFields.int_dis && time > 0)
+ sTickCompare.schedule(time * Clock::Int::ns);
+ return NoFault;
+
+ /** Fullsystem only Priv registers. */
+ case MISCREG_PIL:
+ if (FULL_SYSTEM) {
+ setReg(miscReg, val);
+ //xc->getCpuPtr()->checkInterrupts;
+ // MUST DO SOMETHING HERE TO TELL CPU TO LOOK FOR INTERRUPTS XXX
+ return NoFault;
+ } else
+ panic("PIL not implemented for syscall emulation\n");
+
+ /** Hyper privileged registers */
+ case MISCREG_HPSTATE:
+ case MISCREG_HINTP:
+ setReg(miscReg, val);
+ return NoFault;
+ case MISCREG_HTSTATE:
+ if (tl == 0)
+ return new IllegalInstruction;
+ setReg(miscReg, val);
+ return NoFault;
+
+ case MISCREG_HTBA:
+ // clear lower 7 bits on writes.
+ setReg(miscReg, val & ULL(~0x7FFF));
+ return NoFault;
+
+ case MISCREG_STRAND_STS_REG:
+ setReg(miscReg, strandStatusReg);
+ return NoFault;
+ case MISCREG_HSTICK_CMPR:
+ if (isNonPriv())
+ return new PrivilegedOpcode;
+ if (hSTickCompare == NULL)
+ hSTickCompare = new HSTickCompareEvent(this, xc);
+ sys = dynamic_cast<SparcSystem*>(xc->getSystemPtr());
+ assert(sys != NULL);
+ setReg(miscReg, val);
+ if (hstick_cmprFields.int_dis && hSTickCompare.scheduled())
+ hSTickCompare.deschedule();
+ int64_t time = hstick_cmprFields.tick_cmpr - sys->sysTick;
+ if (!hstick_cmprFields.int_dis && time > 0)
+ hSTickCompare.schedule(time * Clock::Int::ns);
+ return NoFault;
+ default:
+ return new IllegalInstruction;
+ }
+}
+
+MiscReg
+MiscRegFile::readFSRegWithEffect(int miscReg, Fault &fault, ExecContext * xc)
+{
+ switch (miscReg) {
+
+ /** Privileged registers. */
+ case MISCREG_SOFTINT:
+ if (isNonPriv()) {
+ fault = new PrivilegedOpcode;
+ return 0;
+ }
+ return readReg(miscReg);
+ case MISCREG_TICK_CMPR:
+ if (isNonPriv()) {
+ fault = new PrivilegedOpcode;
+ return 0;
+ }
+ return readReg(miscReg);
+ case MISCREG_STICK:
+ SparcSystem *sys;
+ if (stickFields.npt && !isNonPriv()) {
+ fault = new PrivilegedAction;
+ return 0;
+ }
+ sys = dynamic_cast<SparcSystem*>(xc->getSystemPtr());
+ assert(sys != NULL);
+ return curTick/Clock::Int::ns - sys->sysTick | stickFields.npt << 63;
+ case MISCREG_STICK_CMPR:
+ if (isNonPriv()) {
+ fault = new PrivilegedOpcode;
+ return 0;
+ }
+ return readReg(miscReg);
+
+
+ /** Hyper privileged registers */
+ case MISCREG_HPSTATE:
+ case MISCREG_HINTP:
+ return readReg(miscReg);
+ case MISCREG_HTSTATE:
+ if (tl == 0) {
+ fault = new IllegalInstruction;
+ return 0;
+ }
+ return readReg(miscReg);
+
+ case MISCREG_HTBA:
+ return readReg(miscReg) & ULL(~0x7FFF);
+ case MISCREG_HVER:
+ return NWindows | MaxTL << 8 | MaxGL << 16;
+ case MISCREG_STRAND_STS_REG:
+ return strandStatusReg;
+ case MISCREG_HSTICK_CMPR:
+ return hstick_cmpr;
+
+ default:
+ fault = new IllegalInstruction;
+ return 0;
+ }
+}
+
+void
+MiscRegFile::processTickCompare(ExecContext *xc)
+{
+ panic("tick compare not implemented\n");
+}
+
+void
+MiscRegFile::processSTickCompare(ExecContext *xc)
+{
+ panic("tick compare not implemented\n");
+}
+
+void
+MiscRegFile::processHSTickCompare(ExecContext *xc)
+{
+ panic("tick compare not implemented\n");
+}
+
+}; // namespace SparcISA
diff --git a/src/arch/sparc/utility.hh b/src/arch/sparc/utility.hh
new file mode 100644
index 000000000..1e67b3370
--- /dev/null
+++ b/src/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/src/arch/sparc/vtophys.cc b/src/arch/sparc/vtophys.cc
new file mode 100644
index 000000000..41e9b80a3
--- /dev/null
+++ b/src/arch/sparc/vtophys.cc
@@ -0,0 +1,162 @@
+/*
+ * 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 <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/vport.hh"
+
+using namespace std;
+using namespace AlphaISA;
+
+AlphaISA::PageTableEntry
+AlphaISA::kernel_pte_lookup(FunctionalPort *mem, Addr ptbr, AlphaISA::VAddr vaddr)
+{
+ Addr level1_pte = ptbr + vaddr.level1();
+ 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 = 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 = mem->read<uint64_t>(level3_pte);
+ if (!level3.valid()) {
+ DPRINTF(VtoPhys, "level 3 PTE not valid, va = %#x\n", vaddr);
+ return 0;
+ }
+ return level3;
+}
+
+Addr
+AlphaISA::vtophys(Addr vaddr)
+{
+ Addr paddr = 0;
+ if (AlphaISA::IsUSeg(vaddr))
+ DPRINTF(VtoPhys, "vtophys: invalid vaddr %#x", vaddr);
+ else if (AlphaISA::IsK0Seg(vaddr))
+ paddr = AlphaISA::K0Seg2Phys(vaddr);
+ else
+ panic("vtophys: ptbr is not set on virtual lookup");
+
+ DPRINTF(VtoPhys, "vtophys(%#x) -> %#x\n", vaddr, paddr);
+
+ return paddr;
+}
+
+Addr
+AlphaISA::vtophys(ExecContext *xc, Addr addr)
+{
+ AlphaISA::VAddr vaddr = addr;
+ Addr ptbr = xc->readMiscReg(AlphaISA::IPR_PALtemp20);
+ Addr paddr = 0;
+ //@todo Andrew couldn't remember why he commented some of this code
+ //so I put it back in. Perhaps something to do with gdb debugging?
+ if (AlphaISA::PcPAL(vaddr) && (vaddr < EV5::PalMax)) {
+ paddr = vaddr & ~ULL(1);
+ } else {
+ if (AlphaISA::IsK0Seg(vaddr)) {
+ paddr = AlphaISA::K0Seg2Phys(vaddr);
+ } else if (!ptbr) {
+ paddr = vaddr;
+ } else {
+ AlphaISA::PageTableEntry pte =
+ kernel_pte_lookup(xc->getPhysPort(), ptbr, vaddr);
+ if (pte.valid())
+ paddr = pte.paddr() | vaddr.offset();
+ }
+ }
+
+
+ DPRINTF(VtoPhys, "vtophys(%#x) -> %#x\n", vaddr, paddr);
+
+ return paddr;
+}
+
+
+void
+AlphaISA::CopyOut(ExecContext *xc, void *dest, Addr src, size_t cplen)
+{
+ uint8_t *dst = (uint8_t *)dest;
+ VirtualPort *vp = xc->getVirtPort(xc);
+
+ vp->readBlob(src, dst, cplen);
+
+ xc->delVirtPort(vp);
+
+}
+
+void
+AlphaISA::CopyIn(ExecContext *xc, Addr dest, void *source, size_t cplen)
+{
+ uint8_t *src = (uint8_t *)source;
+ VirtualPort *vp = xc->getVirtPort(xc);
+
+ vp->writeBlob(dest, src, cplen);
+
+ xc->delVirtPort(vp);
+}
+
+void
+AlphaISA::CopyStringOut(ExecContext *xc, char *dst, Addr vaddr, size_t maxlen)
+{
+ int len = 0;
+ VirtualPort *vp = xc->getVirtPort(xc);
+
+ do {
+ vp->readBlob(vaddr++, (uint8_t*)dst++, 1);
+ len++;
+ } while (len < maxlen && dst[len] != 0 );
+
+ xc->delVirtPort(vp);
+ dst[len] = 0;
+}
+
+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();
+ }
+ xc->delVirtPort(vp);
+}
diff --git a/src/arch/sparc/vtophys.hh b/src/arch/sparc/vtophys.hh
new file mode 100644
index 000000000..dcd8839e6
--- /dev/null
+++ b/src/arch/sparc/vtophys.hh
@@ -0,0 +1,52 @@
+/*
+ * 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_VTOPHYS_H__
+#define __ARCH_SPARC_VTOPHYS_H__
+
+#include "arch/sparc/isa_traits.hh"
+
+class ExecContext;
+class FunctionalPort;
+
+namespace SparcISA {
+
+PageTableEntry
+kernel_pte_lookup(FunctionalPort *mem, Addr ptbr, SparcISA::VAddr vaddr);
+
+Addr vtophys(Addr vaddr);
+Addr vtophys(ExecContext *xc, Addr vaddr);
+
+void CopyOut(ExecContext *xc, void *dst, Addr src, size_t len);
+void CopyIn(ExecContext *xc, Addr dst, void *src, size_t len);
+void CopyStringOut(ExecContext *xc, char *dst, Addr vaddr, size_t maxlen);
+void CopyStringIn(ExecContext *xc, char *src, Addr vaddr);
+
+};
+#endif // __ARCH_SPARC_VTOPHYS_H__
+
diff --git a/base/bitfield.hh b/src/base/bitfield.hh
index c59354c7d..c59354c7d 100644
--- a/base/bitfield.hh
+++ b/src/base/bitfield.hh
diff --git a/base/callback.hh b/src/base/callback.hh
index 7b3023505..7b3023505 100644
--- a/base/callback.hh
+++ b/src/base/callback.hh
diff --git a/src/base/chunk_generator.hh b/src/base/chunk_generator.hh
new file mode 100644
index 000000000..4f708bd4b
--- /dev/null
+++ b/src/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/circlebuf.cc b/src/base/circlebuf.cc
index 89bbfd822..89bbfd822 100644
--- a/base/circlebuf.cc
+++ b/src/base/circlebuf.cc
diff --git a/base/circlebuf.hh b/src/base/circlebuf.hh
index 8a64cb5f5..8a64cb5f5 100644
--- a/base/circlebuf.hh
+++ b/src/base/circlebuf.hh
diff --git a/base/compression/lzss_compression.cc b/src/base/compression/lzss_compression.cc
index 3ffdf7e95..3ffdf7e95 100644
--- a/base/compression/lzss_compression.cc
+++ b/src/base/compression/lzss_compression.cc
diff --git a/base/compression/lzss_compression.hh b/src/base/compression/lzss_compression.hh
index c136c6d60..c136c6d60 100644
--- a/base/compression/lzss_compression.hh
+++ b/src/base/compression/lzss_compression.hh
diff --git a/base/compression/null_compression.hh b/src/base/compression/null_compression.hh
index 5fbcf562b..5fbcf562b 100644
--- a/base/compression/null_compression.hh
+++ b/src/base/compression/null_compression.hh
diff --git a/base/cprintf.cc b/src/base/cprintf.cc
index cf332ebf2..cf332ebf2 100644
--- a/base/cprintf.cc
+++ b/src/base/cprintf.cc
diff --git a/src/base/cprintf.hh b/src/base/cprintf.hh
new file mode 100644
index 000000000..c468c375f
--- /dev/null
+++ b/src/base/cprintf.hh
@@ -0,0 +1,197 @@
+/*
+ * 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 __CPRINTF_HH__
+#define __CPRINTF_HH__
+
+#include <iostream>
+#include <list>
+#include <string>
+
+#include "base/cprintf_formats.hh"
+
+namespace cp {
+
+class ArgList
+{
+ private:
+ class Base
+ {
+ public:
+ virtual ~Base() {}
+ virtual void process(std::ostream &out, Format &fmt) = 0;
+ };
+
+ template <typename T>
+ class Node : public Base
+ {
+ public:
+ const T &data;
+
+ public:
+ Node(const T &d) : data(d) {}
+ virtual void process(std::ostream &out, Format &fmt) {
+ switch (fmt.format) {
+ case Format::character:
+ format_char(out, data, fmt);
+ break;
+
+ case Format::integer:
+ format_integer(out, data, fmt);
+ break;
+
+ case Format::floating:
+ format_float(out, data, fmt);
+ break;
+
+ case Format::string:
+ format_string(out, data, fmt);
+ break;
+
+ default:
+ out << "<bad format>";
+ break;
+ }
+ }
+ };
+
+ typedef std::list<Base *> list_t;
+
+ protected:
+ list_t objects;
+ std::ostream *stream;
+
+ public:
+ ArgList() : stream(&std::cout) {}
+ ~ArgList();
+
+ template<class T>
+ void append(const T &data) {
+ Base *obj = new ArgList::Node<T>(data);
+ objects.push_back(obj);
+ }
+
+ template<class T>
+ void prepend(const T &data) {
+ Base *obj = new ArgList::Node<T>(data);
+ objects.push_front(obj);
+ }
+
+ void dump(const std::string &format);
+ void dump(std::ostream &strm, const std::string &fmt)
+ { stream = &strm; dump(fmt); }
+
+ std::string dumpToString(const std::string &format);
+
+ friend ArgList &operator<<(std::ostream &str, ArgList &list);
+};
+
+template<class T>
+inline ArgList &
+operator,(ArgList &alist, const T &data)
+{
+ alist.append(data);
+ return alist;
+}
+
+class ArgListNull {
+};
+
+inline ArgList &
+operator,(ArgList &alist, ArgListNull)
+{ return alist; }
+
+//
+// cprintf(format, args, ...) prints to cout
+// (analogous to printf())
+//
+inline void
+__cprintf(const std::string &format, ArgList &args)
+{ args.dump(format); delete &args; }
+#define __cprintf__(format, args...) \
+ cp::__cprintf(format, (*(new cp::ArgList), args))
+#define cprintf(args...) \
+ __cprintf__(args, cp::ArgListNull())
+
+//
+// ccprintf(stream, format, args, ...) prints to the specified stream
+// (analogous to fprintf())
+//
+inline void
+__ccprintf(std::ostream &stream, const std::string &format, ArgList &args)
+{ args.dump(stream, format); delete &args; }
+#define __ccprintf__(stream, format, args...) \
+ cp::__ccprintf(stream, format, (*(new cp::ArgList), args))
+#define ccprintf(stream, args...) \
+ __ccprintf__(stream, args, cp::ArgListNull())
+
+//
+// csprintf(format, args, ...) returns a string
+// (roughly analogous to sprintf())
+//
+inline std::string
+__csprintf(const std::string &format, ArgList &args)
+{ std::string s = args.dumpToString(format); delete &args; return s; }
+#define __csprintf__(format, args...) \
+ cp::__csprintf(format, (*(new cp::ArgList), args))
+#define csprintf(args...) \
+ __csprintf__(args, cp::ArgListNull())
+
+template<class T>
+inline ArgList &
+operator<<(ArgList &list, const T &data)
+{
+ list.append(data);
+ return list;
+}
+
+inline ArgList &
+operator<<(std::ostream &str, ArgList &list)
+{
+ list.stream = &str;
+ return list;
+}
+
+class ArgListTemp
+{
+ private:
+ std::string format;
+ ArgList *args;
+
+ public:
+ ArgListTemp(const std::string &f) : format(f) { args = new ArgList; }
+ ~ArgListTemp() { args->dump(format); delete args; }
+
+ operator ArgList *() { return args; }
+};
+
+#define cformat(format) \
+ (*((cp::ArgList *)cp::ArgListTemp(format)))
+}
+
+#endif // __CPRINTF_HH__
diff --git a/src/base/cprintf_formats.hh b/src/base/cprintf_formats.hh
new file mode 100644
index 000000000..05a8723a4
--- /dev/null
+++ b/src/base/cprintf_formats.hh
@@ -0,0 +1,353 @@
+/*
+ * 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 __CPRINTF_FORMATS_HH__
+#define __CPRINTF_FORMATS_HH__
+
+#include <sstream>
+#include <ostream>
+
+namespace cp {
+
+struct Format
+{
+ bool alternate_form;
+ bool flush_left;
+ bool print_sign;
+ bool blank_space;
+ bool fill_zero;
+ bool uppercase;
+ enum { dec, hex, oct } base;
+ enum { none, string, integer, character, floating } format;
+ enum { best, fixed, scientific } float_format;
+ int precision;
+ int width;
+
+ Format() { clear(); }
+
+ void clear()
+ {
+ alternate_form = false;
+ flush_left = false;
+ print_sign = false;
+ blank_space = false;
+ fill_zero = false;
+ uppercase = false;
+ base = dec;
+ format = none;
+ precision = -1;
+ width = 0;
+ }
+};
+
+template <typename T>
+inline void
+_format_char(std::ostream &out, const T &data, Format &fmt)
+{
+ using namespace std;
+
+ out << data;
+}
+
+template <typename T>
+inline void
+_format_integer(std::ostream &out, const T &data, Format &fmt)
+{
+ using namespace std;
+
+ switch (fmt.base) {
+ case Format::hex:
+ out.setf(ios::hex, ios::basefield);
+ break;
+
+ case Format::oct:
+ out.setf(ios::oct, ios::basefield);
+ break;
+
+ case Format::dec:
+ out.setf(ios::dec, ios::basefield);
+ break;
+ }
+
+ if (fmt.alternate_form) {
+ if (!fmt.fill_zero)
+ out.setf(ios::showbase);
+ else {
+ switch (fmt.base) {
+ case Format::hex:
+ out << "0x";
+ fmt.width -= 2;
+ break;
+ case Format::oct:
+ out << "0";
+ fmt.width -= 1;
+ break;
+ case Format::dec:
+ break;
+ }
+ }
+ }
+
+ if (fmt.fill_zero)
+ out.fill('0');
+
+ if (fmt.width > 0)
+ out.width(fmt.width);
+
+ if (fmt.flush_left && !fmt.fill_zero)
+ out.setf(ios::left);
+
+ if (fmt.print_sign)
+ out.setf(ios::showpos);
+
+ if (fmt.uppercase)
+ out.setf(ios::uppercase);
+
+ out << data;
+}
+
+template <typename T>
+inline void
+_format_float(std::ostream &out, const T &data, Format &fmt)
+{
+ using namespace std;
+
+ switch (fmt.float_format) {
+ case Format::scientific:
+ if (fmt.precision != -1) {
+ if (fmt.width > 0)
+ out.width(fmt.width);
+
+ if (fmt.precision == 0)
+ fmt.precision = 1;
+ else
+ out.setf(ios::scientific);
+
+ out.precision(fmt.precision);
+ } else
+ if (fmt.width > 0)
+ out.width(fmt.width);
+
+ if (fmt.uppercase)
+ out.setf(ios::uppercase);
+ break;
+
+ case Format::fixed:
+ if (fmt.precision != -1) {
+ if (fmt.width > 0)
+ out.width(fmt.width);
+
+ out.setf(ios::fixed);
+ out.precision(fmt.precision);
+ } else
+ if (fmt.width > 0)
+ out.width(fmt.width);
+
+ break;
+
+ default:
+ if (fmt.precision != -1)
+ out.precision(fmt.precision);
+
+ if (fmt.width > 0)
+ out.width(fmt.width);
+
+ break;
+ }
+
+ out << data;
+}
+
+template <typename T>
+inline void
+_format_string(std::ostream &out, const T &data, Format &fmt)
+{
+ using namespace std;
+
+#if defined(__GNUC__) && (__GNUC__ < 3) || 1
+ if (fmt.width > 0) {
+ std::stringstream foo;
+ foo << data;
+ int flen = foo.str().size();
+
+ if (fmt.width > flen) {
+ char *spaces = new char[fmt.width - flen + 1];
+ memset(spaces, ' ', fmt.width - flen);
+ spaces[fmt.width - flen] = 0;
+
+ if (fmt.flush_left)
+ out << foo.str() << spaces;
+ else
+ out << spaces << foo.str();
+
+ delete [] spaces;
+ } else
+ out << data;
+ } else
+ out << data;
+#else
+ if (fmt.width > 0)
+ out.width(fmt.width);
+ if (fmt.flush_left)
+ out.setf(ios::left);
+
+ out << data;
+#endif
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// The code below controls the actual usage of formats for various types
+//
+
+//
+// character formats
+//
+template <typename T>
+inline void
+format_char(std::ostream &out, const T &data, Format &fmt)
+{ out << "<bad arg type for char format>"; }
+
+inline void
+format_char(std::ostream &out, char data, Format &fmt)
+{ _format_char(out, data, fmt); }
+
+inline void
+format_char(std::ostream &out, unsigned char data, Format &fmt)
+{ _format_char(out, data, fmt); }
+
+inline void
+format_char(std::ostream &out, signed char data, Format &fmt)
+{ _format_char(out, data, fmt); }
+
+inline void
+format_char(std::ostream &out, short data, Format &fmt)
+{ _format_char(out, (char)data, fmt); }
+
+inline void
+format_char(std::ostream &out, unsigned short data, Format &fmt)
+{ _format_char(out, (char)data, fmt); }
+
+inline void
+format_char(std::ostream &out, int data, Format &fmt)
+{ _format_char(out, (char)data, fmt); }
+
+inline void
+format_char(std::ostream &out, unsigned int data, Format &fmt)
+{ _format_char(out, (char)data, fmt); }
+
+inline void
+format_char(std::ostream &out, long data, Format &fmt)
+{ _format_char(out, (char)data, fmt); }
+
+inline void
+format_char(std::ostream &out, unsigned long data, Format &fmt)
+{ _format_char(out, (char)data, fmt); }
+
+inline void
+format_char(std::ostream &out, long long data, Format &fmt)
+{ _format_char(out, (char)data, fmt); }
+
+inline void
+format_char(std::ostream &out, unsigned long long data, Format &fmt)
+{ _format_char(out, (char)data, fmt); }
+
+//
+// integer formats
+//
+template <typename T>
+inline void
+format_integer(std::ostream &out, const T &data, Format &fmt)
+{ _format_integer(out, data, fmt); }
+inline void
+format_integer(std::ostream &out, char data, Format &fmt)
+{ _format_integer(out, data, fmt); }
+inline void
+format_integer(std::ostream &out, unsigned char data, Format &fmt)
+{ _format_integer(out, data, fmt); }
+inline void
+format_integer(std::ostream &out, signed char data, Format &fmt)
+{ _format_integer(out, data, fmt); }
+#if 0
+inline void
+format_integer(std::ostream &out, short data, Format &fmt)
+{ _format_integer(out, data, fmt); }
+inline void
+format_integer(std::ostream &out, unsigned short data, Format &fmt)
+{ _format_integer(out, data, fmt); }
+inline void
+format_integer(std::ostream &out, int data, Format &fmt)
+{ _format_integer(out, data, fmt); }
+inline void
+format_integer(std::ostream &out, unsigned int data, Format &fmt)
+{ _format_integer(out, data, fmt); }
+inline void
+format_integer(std::ostream &out, long data, Format &fmt)
+{ _format_integer(out, data, fmt); }
+inline void
+format_integer(std::ostream &out, unsigned long data, Format &fmt)
+{ _format_integer(out, data, fmt); }
+inline void
+format_integer(std::ostream &out, long long data, Format &fmt)
+{ _format_integer(out, data, fmt); }
+inline void
+format_integer(std::ostream &out, unsigned long long data, Format &fmt)
+{ _format_integer(out, data, fmt); }
+#endif
+
+//
+// floating point formats
+//
+template <typename T>
+inline void
+format_float(std::ostream &out, const T &data, Format &fmt)
+{ out << "<bad arg type for float format>"; }
+
+inline void
+format_float(std::ostream &out, float data, Format &fmt)
+{ _format_float(out, data, fmt); }
+
+inline void
+format_float(std::ostream &out, double data, Format &fmt)
+{ _format_float(out, data, fmt); }
+
+//
+// string formats
+//
+template <typename T>
+inline void
+format_string(std::ostream &out, const T &data, Format &fmt)
+{ _format_string(out, data, fmt); }
+
+inline void
+format_string(std::ostream &out, const std::stringstream &data, Format &fmt)
+{ _format_string(out, data.str(), fmt); }
+
+} // namespace cp
+
+#endif // __CPRINTF_FORMATS_HH__
diff --git a/src/base/crc.cc b/src/base/crc.cc
new file mode 100644
index 000000000..08f039577
--- /dev/null
+++ b/src/base/crc.cc
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 1988, 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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 "sim/host.hh"
+#include "base/crc.hh"
+
+#define ETHER_CRC_POLY_LE 0xedb88320
+#define ETHER_CRC_POLY_BE 0x04c11db6
+
+#if 0
+/*
+ * This is for reference. We have a table-driven version
+ * of the little-endian crc32 generator, which is faster
+ * than the double-loop.
+ */
+uint32_t
+crc32le(const uint8_t *buf, size_t len)
+{
+ uint32_t c, crc, carry;
+ size_t i, j;
+
+ crc = 0xffffffffU; /* initial value */
+
+ for (i = 0; i < len; i++) {
+ c = buf[i];
+ for (j = 0; j < 8; j++) {
+ carry = ((crc & 0x01) ? 1 : 0) ^ (c & 0x01);
+ crc >>= 1;
+ c >>= 1;
+ if (carry)
+ crc = (crc ^ ETHER_CRC_POLY_LE);
+ }
+ }
+
+ return (crc);
+}
+#else
+uint32_t
+crc32le(const uint8_t *buf, size_t len)
+{
+ static const uint32_t crctab[] = {
+ 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
+ 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
+ 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
+ 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
+ };
+ uint32_t crc;
+ int i;
+
+ crc = 0xffffffffU; /* initial value */
+
+ for (i = 0; i < len; i++) {
+ crc ^= buf[i];
+ crc = (crc >> 4) ^ crctab[crc & 0xf];
+ crc = (crc >> 4) ^ crctab[crc & 0xf];
+ }
+
+ return (crc);
+}
+#endif
+
+uint32_t
+crc32be(const uint8_t *buf, size_t len)
+{
+ uint32_t c, crc, carry;
+ size_t i, j;
+
+ crc = 0xffffffffU; /* initial value */
+
+ for (i = 0; i < len; i++) {
+ c = buf[i];
+ for (j = 0; j < 8; j++) {
+ carry = ((crc & 0x80000000U) ? 1 : 0) ^ (c & 0x01);
+ crc <<= 1;
+ c >>= 1;
+ if (carry)
+ crc = (crc ^ ETHER_CRC_POLY_BE) | carry;
+ }
+ }
+
+ return (crc);
+}
diff --git a/base/crc.hh b/src/base/crc.hh
index 6ede07748..6ede07748 100644
--- a/base/crc.hh
+++ b/src/base/crc.hh
diff --git a/base/date.cc b/src/base/date.cc
index ba7698c29..ba7698c29 100644
--- a/base/date.cc
+++ b/src/base/date.cc
diff --git a/base/dbl_list.hh b/src/base/dbl_list.hh
index 1d06ff576..1d06ff576 100644
--- a/base/dbl_list.hh
+++ b/src/base/dbl_list.hh
diff --git a/base/endian.hh b/src/base/endian.hh
index 499eb50c5..499eb50c5 100644
--- a/base/endian.hh
+++ b/src/base/endian.hh
diff --git a/base/fast_alloc.cc b/src/base/fast_alloc.cc
index 6504e07c2..6504e07c2 100644
--- a/base/fast_alloc.cc
+++ b/src/base/fast_alloc.cc
diff --git a/base/fast_alloc.hh b/src/base/fast_alloc.hh
index 54e35f8e0..54e35f8e0 100644
--- a/base/fast_alloc.hh
+++ b/src/base/fast_alloc.hh
diff --git a/base/fenv.hh b/src/base/fenv.hh
index 3234f5dd3..3234f5dd3 100644
--- a/base/fenv.hh
+++ b/src/base/fenv.hh
diff --git a/base/fifo_buffer.cc b/src/base/fifo_buffer.cc
index 85b306c25..85b306c25 100644
--- a/base/fifo_buffer.cc
+++ b/src/base/fifo_buffer.cc
diff --git a/base/fifo_buffer.hh b/src/base/fifo_buffer.hh
index 03ce057c7..03ce057c7 100644
--- a/base/fifo_buffer.hh
+++ b/src/base/fifo_buffer.hh
diff --git a/base/hashmap.hh b/src/base/hashmap.hh
index 712366829..712366829 100644
--- a/base/hashmap.hh
+++ b/src/base/hashmap.hh
diff --git a/src/base/hostinfo.cc b/src/base/hostinfo.cc
new file mode 100644
index 000000000..d42c96732
--- /dev/null
+++ b/src/base/hostinfo.cc
@@ -0,0 +1,85 @@
+/*
+ * 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 <ctype.h>
+#include <errno.h>
+#include <math.h>
+#include <unistd.h>
+
+#include <cstdlib>
+#include <cstring>
+#include <string>
+
+#include "base/misc.hh"
+#include "sim/host.hh"
+
+using namespace std;
+
+string
+__get_hostname()
+{
+ char host[256];
+ if (gethostname(host, sizeof host) == -1)
+ warn("could not get host name!");
+ return host;
+}
+
+string &
+hostname()
+{
+ static string hostname = __get_hostname();
+ return hostname;
+}
+
+uint64_t
+procInfo(char *filename, char *target)
+{
+ int done = 0;
+ char line[80];
+ char format[80];
+ long usage;
+
+ FILE *fp = fopen(filename, "r");
+
+ while (fp && !feof(fp) && !done) {
+ if (fgets(line, 80, fp)) {
+ if (strncmp(line, target, strlen(target)) == 0) {
+ snprintf(format, sizeof(format), "%s %%ld", target);
+ sscanf(line, format, &usage);
+
+ fclose(fp);
+ return usage ;
+ }
+ }
+ }
+
+ if (fp)
+ fclose(fp);
+
+ return 0;
+}
diff --git a/base/hostinfo.hh b/src/base/hostinfo.hh
index 21a6e5475..21a6e5475 100644
--- a/base/hostinfo.hh
+++ b/src/base/hostinfo.hh
diff --git a/base/hybrid_pred.cc b/src/base/hybrid_pred.cc
index 21cbdb0fd..21cbdb0fd 100644
--- a/base/hybrid_pred.cc
+++ b/src/base/hybrid_pred.cc
diff --git a/base/hybrid_pred.hh b/src/base/hybrid_pred.hh
index ea4a9d04c..ea4a9d04c 100644
--- a/base/hybrid_pred.hh
+++ b/src/base/hybrid_pred.hh
diff --git a/src/base/inet.cc b/src/base/inet.cc
new file mode 100644
index 000000000..f2665bd2b
--- /dev/null
+++ b/src/base/inet.cc
@@ -0,0 +1,207 @@
+/*
+ * 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 <sstream>
+#include <string>
+
+#include "base/cprintf.hh"
+#include "sim/host.hh"
+#include "base/inet.hh"
+
+using namespace std;
+namespace Net {
+
+EthAddr::EthAddr()
+{
+ memset(data, 0, ETH_ADDR_LEN);
+}
+
+EthAddr::EthAddr(const uint8_t ea[ETH_ADDR_LEN])
+{
+ *data = *ea;
+}
+
+EthAddr::EthAddr(const eth_addr &ea)
+{
+ *data = *ea.data;
+}
+
+EthAddr::EthAddr(const std::string &addr)
+{
+ parse(addr);
+}
+
+const EthAddr &
+EthAddr::operator=(const eth_addr &ea)
+{
+ *data = *ea.data;
+ return *this;
+}
+
+const EthAddr &
+EthAddr::operator=(const std::string &addr)
+{
+ parse(addr);
+ return *this;
+}
+
+void
+EthAddr::parse(const std::string &addr)
+{
+ // the hack below is to make sure that ETH_ADDR_LEN is 6 otherwise
+ // the sscanf function won't work.
+ int bytes[ETH_ADDR_LEN == 6 ? ETH_ADDR_LEN : -1];
+ if (sscanf(addr.c_str(), "%x:%x:%x:%x:%x:%x", &bytes[0], &bytes[1],
+ &bytes[2], &bytes[3], &bytes[4], &bytes[5]) != ETH_ADDR_LEN) {
+ memset(data, 0xff, ETH_ADDR_LEN);
+ return;
+ }
+
+ for (int i = 0; i < ETH_ADDR_LEN; ++i) {
+ if (bytes[i] & ~0xff) {
+ memset(data, 0xff, ETH_ADDR_LEN);
+ return;
+ }
+
+ data[i] = bytes[i];
+ }
+}
+
+string
+EthAddr::string() const
+{
+ stringstream stream;
+ stream << *this;
+ return stream.str();
+}
+
+bool
+operator==(const EthAddr &left, const EthAddr &right)
+{
+ return memcmp(left.bytes(), right.bytes(), ETH_ADDR_LEN);
+}
+
+ostream &
+operator<<(ostream &stream, const EthAddr &ea)
+{
+ const uint8_t *a = ea.addr();
+ ccprintf(stream, "%x:%x:%x:%x:%x:%x", a[0], a[1], a[2], a[3], a[4], a[5]);
+ return stream;
+}
+
+uint16_t
+cksum(const IpPtr &ptr)
+{
+ int sum = ip_cksum_add(ptr->bytes(), ptr->hlen(), 0);
+ return ip_cksum_carry(sum);
+}
+
+uint16_t
+__tu_cksum(const IpPtr &ip)
+{
+ int tcplen = ip->len() - ip->hlen();
+ int sum = ip_cksum_add(ip->payload(), tcplen, 0);
+ sum = ip_cksum_add(&ip->ip_src, 8, sum); // source and destination
+ sum += htons(ip->ip_p + tcplen);
+ return ip_cksum_carry(sum);
+}
+
+uint16_t
+cksum(const TcpPtr &tcp)
+{ return __tu_cksum(IpPtr(tcp.packet())); }
+
+uint16_t
+cksum(const UdpPtr &udp)
+{ return __tu_cksum(IpPtr(udp.packet())); }
+
+bool
+IpHdr::options(vector<const IpOpt *> &vec) const
+{
+ vec.clear();
+
+ const uint8_t *data = bytes() + sizeof(struct ip_hdr);
+ int all = hlen() - sizeof(struct ip_hdr);
+ while (all > 0) {
+ const IpOpt *opt = (const IpOpt *)data;
+ int len = opt->len();
+ if (all < len)
+ return false;
+
+ vec.push_back(opt);
+ all -= len;
+ data += len;
+ }
+
+ return true;
+}
+
+bool
+TcpHdr::options(vector<const TcpOpt *> &vec) const
+{
+ vec.clear();
+
+ const uint8_t *data = bytes() + sizeof(struct tcp_hdr);
+ int all = off() - sizeof(struct tcp_hdr);
+ while (all > 0) {
+ const TcpOpt *opt = (const TcpOpt *)data;
+ int len = opt->len();
+ if (all < len)
+ return false;
+
+ vec.push_back(opt);
+ all -= len;
+ data += len;
+ }
+
+ return true;
+}
+
+bool
+TcpOpt::sack(vector<SackRange> &vec) const
+{
+ vec.clear();
+
+ const uint8_t *data = bytes() + sizeof(struct tcp_hdr);
+ int all = len() - offsetof(tcp_opt, opt_data.sack);
+ while (all > 0) {
+ const uint16_t *sack = (const uint16_t *)data;
+ int len = sizeof(uint16_t) * 2;
+ if (all < len) {
+ vec.clear();
+ return false;
+ }
+
+ vec.push_back(RangeIn(ntohs(sack[0]), ntohs(sack[1])));
+ all -= len;
+ data += len;
+ }
+
+ return false;
+}
+
+/* namespace Net */ }
diff --git a/src/base/inet.hh b/src/base/inet.hh
new file mode 100644
index 000000000..e5d0473f9
--- /dev/null
+++ b/src/base/inet.hh
@@ -0,0 +1,407 @@
+/*
+ * 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 __BASE_INET_HH__
+#define __BASE_INET_HH__
+
+#include <iosfwd>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "base/range.hh"
+#include "dev/etherpkt.hh"
+#include "sim/host.hh"
+
+#include "dnet/os.h"
+#include "dnet/eth.h"
+#include "dnet/ip.h"
+#include "dnet/ip6.h"
+#include "dnet/addr.h"
+#include "dnet/arp.h"
+#include "dnet/icmp.h"
+#include "dnet/tcp.h"
+#include "dnet/udp.h"
+#include "dnet/intf.h"
+#include "dnet/route.h"
+#include "dnet/fw.h"
+#include "dnet/blob.h"
+#include "dnet/rand.h"
+
+namespace Net {
+
+/*
+ * Ethernet Stuff
+ */
+struct EthAddr : protected eth_addr
+{
+ protected:
+ void parse(const std::string &addr);
+
+ public:
+ EthAddr();
+ EthAddr(const uint8_t ea[ETH_ADDR_LEN]);
+ EthAddr(const eth_addr &ea);
+ EthAddr(const std::string &addr);
+ const EthAddr &operator=(const eth_addr &ea);
+ const EthAddr &operator=(const std::string &addr);
+
+ int size() const { return sizeof(eth_addr); }
+
+ const uint8_t *bytes() const { return &data[0]; }
+ uint8_t *bytes() { return &data[0]; }
+
+ const uint8_t *addr() const { return &data[0]; }
+ bool unicast() const { return data[0] == 0x00; }
+ bool multicast() const { return data[0] == 0x01; }
+ bool broadcast() const { return data[0] == 0xff; }
+ std::string string() const;
+
+ operator uint64_t() const
+ {
+ uint64_t reg = 0;
+ reg |= ((uint64_t)data[0]) << 40;
+ reg |= ((uint64_t)data[1]) << 32;
+ reg |= ((uint64_t)data[2]) << 24;
+ reg |= ((uint64_t)data[3]) << 16;
+ reg |= ((uint64_t)data[4]) << 8;
+ reg |= ((uint64_t)data[5]) << 0;
+ return reg;
+ }
+
+};
+
+std::ostream &operator<<(std::ostream &stream, const EthAddr &ea);
+bool operator==(const EthAddr &left, const EthAddr &right);
+
+struct EthHdr : public eth_hdr
+{
+ uint16_t type() const { return ntohs(eth_type); }
+ const EthAddr &src() const { return *(EthAddr *)&eth_src; }
+ const EthAddr &dst() const { return *(EthAddr *)&eth_dst; }
+
+ int size() const { return sizeof(eth_hdr); }
+
+ const uint8_t *bytes() const { return (const uint8_t *)this; }
+ const uint8_t *payload() const { return bytes() + size(); }
+ uint8_t *bytes() { return (uint8_t *)this; }
+ uint8_t *payload() { return bytes() + size(); }
+};
+
+class EthPtr
+{
+ protected:
+ friend class IpPtr;
+ EthPacketPtr p;
+
+ public:
+ EthPtr() {}
+ EthPtr(const EthPacketPtr &ptr) : p(ptr) { }
+
+ EthHdr *operator->() { return (EthHdr *)p->data; }
+ EthHdr &operator*() { return *(EthHdr *)p->data; }
+ operator EthHdr *() { return (EthHdr *)p->data; }
+
+ const EthHdr *operator->() const { return (const EthHdr *)p->data; }
+ const EthHdr &operator*() const { return *(const EthHdr *)p->data; }
+ operator const EthHdr *() const { return (const EthHdr *)p->data; }
+
+ const EthPtr &operator=(const EthPacketPtr &ptr) { p = ptr; return *this; }
+
+ const EthPacketPtr packet() const { return p; }
+ EthPacketPtr packet() { return p; }
+ bool operator!() const { return !p; }
+ operator bool() const { return p; }
+};
+
+/*
+ * IP Stuff
+ */
+struct IpOpt;
+struct IpHdr : public ip_hdr
+{
+ uint8_t version() const { return ip_v; }
+ uint8_t hlen() const { return ip_hl * 4; }
+ uint8_t tos() const { return ip_tos; }
+ uint16_t len() const { return ntohs(ip_len); }
+ uint16_t id() const { return ntohs(ip_id); }
+ uint16_t frag_flags() const { return ntohs(ip_off) >> 13; }
+ uint16_t frag_off() const { return ntohs(ip_off) & 0x1fff; }
+ uint8_t ttl() const { return ip_ttl; }
+ uint8_t proto() const { return ip_p; }
+ uint16_t sum() const { return ip_sum; }
+ uint32_t src() const { return ntohl(ip_src); }
+ uint32_t dst() const { return ntohl(ip_dst); }
+
+ void sum(uint16_t sum) { ip_sum = sum; }
+
+ bool options(std::vector<const IpOpt *> &vec) const;
+
+ int size() const { return hlen(); }
+ const uint8_t *bytes() const { return (const uint8_t *)this; }
+ const uint8_t *payload() const { return bytes() + size(); }
+ uint8_t *bytes() { return (uint8_t *)this; }
+ uint8_t *payload() { return bytes() + size(); }
+};
+
+class IpPtr
+{
+ protected:
+ friend class TcpPtr;
+ friend class UdpPtr;
+ 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 EthPacketPtr &ptr)
+ {
+ EthHdr *eth = (EthHdr *)ptr->data;
+ if (eth->type() == ETH_TYPE_IP)
+ p = ptr;
+ else
+ p = 0;
+ }
+
+ public:
+ IpPtr() {}
+ IpPtr(const EthPacketPtr &ptr) { set(ptr); }
+ IpPtr(const EthPtr &ptr) { set(ptr.p); }
+ IpPtr(const IpPtr &ptr) : p(ptr.p) { }
+
+ IpHdr *operator->() { return h(); }
+ IpHdr &operator*() { return *h(); }
+ operator IpHdr *() { return h(); }
+
+ const IpHdr *operator->() const { return h(); }
+ const IpHdr &operator*() const { return *h(); }
+ operator const IpHdr *() const { return h(); }
+
+ 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 EthPacketPtr packet() const { return p; }
+ EthPacketPtr packet() { return p; }
+ bool operator!() const { return !p; }
+ operator bool() const { return p; }
+ operator bool() { return p; }
+};
+
+uint16_t cksum(const IpPtr &ptr);
+
+struct IpOpt : public ip_opt
+{
+ uint8_t type() const { return opt_type; }
+ uint8_t typeNumber() const { return IP_OPT_NUMBER(opt_type); }
+ uint8_t typeClass() const { return IP_OPT_CLASS(opt_type); }
+ uint8_t typeCopied() const { return IP_OPT_COPIED(opt_type); }
+ uint8_t len() const { return IP_OPT_TYPEONLY(type()) ? 1 : opt_len; }
+
+ bool isNumber(int num) const { return typeNumber() == IP_OPT_NUMBER(num); }
+ bool isClass(int cls) const { return typeClass() == IP_OPT_CLASS(cls); }
+ bool isCopied(int cpy) const { return typeCopied() == IP_OPT_COPIED(cpy); }
+
+ const uint8_t *data() const { return opt_data.data8; }
+ void sec(ip_opt_data_sec &sec) const;
+ void lsrr(ip_opt_data_rr &rr) const;
+ void ssrr(ip_opt_data_rr &rr) const;
+ void ts(ip_opt_data_ts &ts) const;
+ uint16_t satid() const { return ntohs(opt_data.satid); }
+ uint16_t mtup() const { return ntohs(opt_data.mtu); }
+ uint16_t mtur() const { return ntohs(opt_data.mtu); }
+ void tr(ip_opt_data_tr &tr) const;
+ const uint32_t *addext() const { return &opt_data.addext[0]; }
+ uint16_t rtralt() const { return ntohs(opt_data.rtralt); }
+ void sdb(std::vector<uint32_t> &vec) const;
+};
+
+/*
+ * TCP Stuff
+ */
+struct TcpOpt;
+struct TcpHdr : public tcp_hdr
+{
+ uint16_t sport() const { return ntohs(th_sport); }
+ uint16_t dport() const { return ntohs(th_dport); }
+ uint32_t seq() const { return ntohl(th_seq); }
+ uint32_t ack() const { return ntohl(th_ack); }
+ uint8_t off() const { return th_off; }
+ uint8_t flags() const { return th_flags & 0x3f; }
+ uint16_t win() const { return ntohs(th_win); }
+ uint16_t sum() const { return th_sum; }
+ uint16_t urp() const { return ntohs(th_urp); }
+
+ void sum(uint16_t sum) { th_sum = sum; }
+
+ bool options(std::vector<const TcpOpt *> &vec) const;
+
+ int size() const { return off(); }
+ const uint8_t *bytes() const { return (const uint8_t *)this; }
+ const uint8_t *payload() const { return bytes() + size(); }
+ uint8_t *bytes() { return (uint8_t *)this; }
+ uint8_t *payload() { return bytes() + size(); }
+};
+
+class TcpPtr
+{
+ protected:
+ EthPacketPtr p;
+ int off;
+
+ const TcpHdr *h() const { return (const TcpHdr *)(p->data + off); }
+ TcpHdr *h() { return (TcpHdr *)(p->data + off); }
+
+ void set(const EthPacketPtr &ptr, int offset) { p = ptr; off = offset; }
+ void set(const IpPtr &ptr)
+ {
+ if (ptr->proto() == IP_PROTO_TCP)
+ set(ptr.p, sizeof(eth_hdr) + ptr->hlen());
+ else
+ set(0, 0);
+ }
+
+ public:
+ TcpPtr() {}
+ TcpPtr(const IpPtr &ptr) { set(ptr); }
+ TcpPtr(const TcpPtr &ptr) : p(ptr.p), off(ptr.off) {}
+
+ TcpHdr *operator->() { return h(); }
+ TcpHdr &operator*() { return *h(); }
+ operator TcpHdr *() { return h(); }
+
+ const TcpHdr *operator->() const { return h(); }
+ const TcpHdr &operator*() const { return *h(); }
+ operator const TcpHdr *() const { return h(); }
+
+ const TcpPtr &operator=(const IpPtr &i) { set(i); return *this; }
+ const TcpPtr &operator=(const TcpPtr &t) { set(t.p, t.off); return *this; }
+
+ const EthPacketPtr packet() const { return p; }
+ EthPacketPtr packet() { return p; }
+ bool operator!() const { return !p; }
+ operator bool() const { return p; }
+ operator bool() { return p; }
+};
+
+uint16_t cksum(const TcpPtr &ptr);
+
+typedef Range<uint16_t> SackRange;
+
+struct TcpOpt : public tcp_opt
+{
+ uint8_t type() const { return opt_type; }
+ uint8_t len() const { return TCP_OPT_TYPEONLY(type()) ? 1 : opt_len; }
+
+ bool isopt(int opt) const { return type() == opt; }
+
+ const uint8_t *data() const { return opt_data.data8; }
+
+ uint16_t mss() const { return ntohs(opt_data.mss); }
+ uint8_t wscale() const { return opt_data.wscale; }
+ bool sack(std::vector<SackRange> &vec) const;
+ uint32_t echo() const { return ntohl(opt_data.echo); }
+ uint32_t tsval() const { return ntohl(opt_data.timestamp[0]); }
+ uint32_t tsecr() const { return ntohl(opt_data.timestamp[1]); }
+ uint32_t cc() const { return ntohl(opt_data.cc); }
+ uint8_t cksum() const{ return opt_data.cksum; }
+ const uint8_t *md5() const { return opt_data.md5; }
+
+ int size() const { return len(); }
+ const uint8_t *bytes() const { return (const uint8_t *)this; }
+ const uint8_t *payload() const { return bytes() + size(); }
+ uint8_t *bytes() { return (uint8_t *)this; }
+ uint8_t *payload() { return bytes() + size(); }
+};
+
+/*
+ * UDP Stuff
+ */
+struct UdpHdr : public udp_hdr
+{
+ uint16_t sport() const { return ntohs(uh_sport); }
+ uint16_t dport() const { return ntohs(uh_dport); }
+ uint16_t len() const { return ntohs(uh_ulen); }
+ uint16_t sum() const { return uh_sum; }
+
+ void sum(uint16_t sum) { uh_sum = sum; }
+
+ int size() const { return sizeof(udp_hdr); }
+ const uint8_t *bytes() const { return (const uint8_t *)this; }
+ const uint8_t *payload() const { return bytes() + size(); }
+ uint8_t *bytes() { return (uint8_t *)this; }
+ uint8_t *payload() { return bytes() + size(); }
+};
+
+class UdpPtr
+{
+ protected:
+ EthPacketPtr p;
+ int off;
+
+ const UdpHdr *h() const { return (const UdpHdr *)(p->data + off); }
+ UdpHdr *h() { return (UdpHdr *)(p->data + off); }
+
+ void set(const EthPacketPtr &ptr, int offset) { p = ptr; off = offset; }
+ void set(const IpPtr &ptr)
+ {
+ if (ptr->proto() == IP_PROTO_UDP)
+ set(ptr.p, sizeof(eth_hdr) + ptr->hlen());
+ else
+ set(0, 0);
+ }
+
+ public:
+ UdpPtr() {}
+ UdpPtr(const IpPtr &ptr) { set(ptr); }
+ UdpPtr(const UdpPtr &ptr) : p(ptr.p), off(ptr.off) {}
+
+ UdpHdr *operator->() { return h(); }
+ UdpHdr &operator*() { return *h(); }
+ operator UdpHdr *() { return h(); }
+
+ const UdpHdr *operator->() const { return h(); }
+ const UdpHdr &operator*() const { return *h(); }
+ operator const UdpHdr *() const { return h(); }
+
+ const UdpPtr &operator=(const IpPtr &i) { set(i); return *this; }
+ const UdpPtr &operator=(const UdpPtr &t) { set(t.p, t.off); return *this; }
+
+ const EthPacketPtr packet() const { return p; }
+ EthPacketPtr packet() { return p; }
+ bool operator!() const { return !p; }
+ operator bool() const { return p; }
+ operator bool() { return p; }
+};
+
+uint16_t cksum(const UdpPtr &ptr);
+
+/* namespace Net */ }
+
+#endif // __BASE_INET_HH__
diff --git a/base/inifile.cc b/src/base/inifile.cc
index eb5a1335f..eb5a1335f 100644
--- a/base/inifile.cc
+++ b/src/base/inifile.cc
diff --git a/base/inifile.hh b/src/base/inifile.hh
index 3c6894978..3c6894978 100644
--- a/base/inifile.hh
+++ b/src/base/inifile.hh
diff --git a/base/intmath.cc b/src/base/intmath.cc
index f1c1651ba..f1c1651ba 100644
--- a/base/intmath.cc
+++ b/src/base/intmath.cc
diff --git a/src/base/intmath.hh b/src/base/intmath.hh
new file mode 100644
index 000000000..51baddb91
--- /dev/null
+++ b/src/base/intmath.hh
@@ -0,0 +1,230 @@
+/*
+ * Copyright (c) 2001, 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 __INTMATH_HH__
+#define __INTMATH_HH__
+
+#include <assert.h>
+
+#include "sim/host.hh"
+
+// Returns the prime number one less than n.
+int prevPrime(int n);
+
+// Determine if a number is prime
+template <class T>
+inline bool
+isPrime(T n)
+{
+ T i;
+
+ if (n == 2 || n == 3)
+ return true;
+
+ // Don't try every odd number to prove if it is a prime.
+ // Toggle between every 2nd and 4th number.
+ // (This is because every 6th odd number is divisible by 3.)
+ for (i = 5; i*i <= n; i += 6) {
+ if (((n % i) == 0 ) || ((n % (i + 2)) == 0) ) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+template <class T>
+inline T
+leastSigBit(T n)
+{
+ return n & ~(n - 1);
+}
+
+template <class T>
+inline bool
+isPowerOf2(T n)
+{
+ return n != 0 && leastSigBit(n) == n;
+}
+
+inline int
+floorLog2(unsigned x)
+{
+ assert(x > 0);
+
+ int y = 0;
+
+ if (x & 0xffff0000) { y += 16; x >>= 16; }
+ if (x & 0x0000ff00) { y += 8; x >>= 8; }
+ if (x & 0x000000f0) { y += 4; x >>= 4; }
+ if (x & 0x0000000c) { y += 2; x >>= 2; }
+ if (x & 0x00000002) { y += 1; }
+
+ return y;
+}
+
+inline int
+floorLog2(unsigned long x)
+{
+ assert(x > 0);
+
+ int y = 0;
+
+#if defined(__LP64__)
+ if (x & ULL(0xffffffff00000000)) { y += 32; x >>= 32; }
+#endif
+ if (x & 0xffff0000) { y += 16; x >>= 16; }
+ if (x & 0x0000ff00) { y += 8; x >>= 8; }
+ if (x & 0x000000f0) { y += 4; x >>= 4; }
+ if (x & 0x0000000c) { y += 2; x >>= 2; }
+ if (x & 0x00000002) { y += 1; }
+
+ return y;
+}
+
+inline int
+floorLog2(unsigned long long x)
+{
+ assert(x > 0);
+
+ int y = 0;
+
+ if (x & ULL(0xffffffff00000000)) { y += 32; x >>= 32; }
+ if (x & ULL(0x00000000ffff0000)) { y += 16; x >>= 16; }
+ if (x & ULL(0x000000000000ff00)) { y += 8; x >>= 8; }
+ if (x & ULL(0x00000000000000f0)) { y += 4; x >>= 4; }
+ if (x & ULL(0x000000000000000c)) { y += 2; x >>= 2; }
+ if (x & ULL(0x0000000000000002)) { y += 1; }
+
+ return y;
+}
+
+inline int
+floorLog2(int x)
+{
+ assert(x > 0);
+ return floorLog2((unsigned)x);
+}
+
+inline int
+floorLog2(long x)
+{
+ assert(x > 0);
+ return floorLog2((unsigned long)x);
+}
+
+inline int
+floorLog2(long long x)
+{
+ assert(x > 0);
+ return floorLog2((unsigned long long)x);
+}
+
+template <class T>
+inline int
+ceilLog2(T n)
+{
+ if (n == 1)
+ return 0;
+
+ return floorLog2(n - (T)1) + 1;
+}
+
+template <class T>
+inline T
+floorPow2(T n)
+{
+ return (T)1 << floorLog2(n);
+}
+
+template <class T>
+inline T
+ceilPow2(T n)
+{
+ return (T)1 << ceilLog2(n);
+}
+
+template <class T>
+inline T
+divCeil(T a, T b)
+{
+ return (a + b - 1) / b;
+}
+
+template <class T>
+inline T
+roundUp(T val, int align)
+{
+ T mask = (T)align - 1;
+ return (val + mask) & ~mask;
+}
+
+template <class T>
+inline T
+roundDown(T val, int align)
+{
+ T mask = (T)align - 1;
+ return val & ~mask;
+}
+
+inline bool
+isHex(char c)
+{
+ return c >= '0' && c <= '9' ||
+ c >= 'A' && c <= 'F' ||
+ c >= 'a' && c <= 'f';
+}
+
+inline bool
+isOct(char c)
+{
+ return c >= '0' && c <= '7';
+}
+
+inline bool
+isDec(char c)
+{
+ return c >= '0' && c <= '9';
+}
+
+inline int
+hex2Int(char c)
+{
+ if (c >= '0' && c <= '9')
+ return (c - '0');
+
+ if (c >= 'A' && c <= 'F')
+ return (c - 'A') + 10;
+
+ if (c >= 'a' && c <= 'f')
+ return (c - 'a') + 10;
+
+ return 0;
+}
+
+#endif // __INTMATH_HH__
diff --git a/base/kgdb.h b/src/base/kgdb.h
index 104244d0b..104244d0b 100644
--- a/base/kgdb.h
+++ b/src/base/kgdb.h
diff --git a/src/base/loader/aout_object.cc b/src/base/loader/aout_object.cc
new file mode 100644
index 000000000..564898ca3
--- /dev/null
+++ b/src/base/loader/aout_object.cc
@@ -0,0 +1,94 @@
+/*
+ * 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 <string>
+
+#include "base/loader/aout_object.hh"
+
+#include "base/loader/symtab.hh"
+
+#include "base/trace.hh" // for DPRINTF
+
+#include "base/loader/exec_aout.h"
+
+using namespace std;
+
+ObjectFile *
+AoutObject::tryFile(const string &fname, int fd, size_t len, uint8_t *data)
+{
+ if (!N_BADMAG(*(aout_exechdr *)data)) {
+ // right now this is only used for Alpha PAL code
+ return new AoutObject(fname, fd, len, data,
+ ObjectFile::Alpha, ObjectFile::UnknownOpSys);
+ }
+ else {
+ return NULL;
+ }
+}
+
+
+AoutObject::AoutObject(const string &_filename, int _fd,
+ size_t _len, uint8_t *_data,
+ Arch _arch, OpSys _opSys)
+ : ObjectFile(_filename, _fd, _len, _data, _arch, _opSys)
+{
+ execHdr = (aout_exechdr *)fileData;
+
+ entry = execHdr->entry;
+
+ 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,
+ bss.baseAddr, bss.size);
+}
+
+
+bool
+AoutObject::loadGlobalSymbols(SymbolTable *symtab)
+{
+ // a.out symbols not supported yet
+ return false;
+}
+
+bool
+AoutObject::loadLocalSymbols(SymbolTable *symtab)
+{
+ // a.out symbols not supported yet
+ return false;
+}
diff --git a/src/base/loader/aout_object.hh b/src/base/loader/aout_object.hh
new file mode 100644
index 000000000..aeb710427
--- /dev/null
+++ b/src/base/loader/aout_object.hh
@@ -0,0 +1,56 @@
+/*
+ * 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 __AOUT_OBJECT_HH__
+#define __AOUT_OBJECT_HH__
+
+#include "base/loader/object_file.hh"
+
+// forward decls: avoid including exec_aout.h here
+struct aout_exechdr;
+
+class AoutObject : public ObjectFile
+{
+ protected:
+ aout_exechdr *execHdr;
+
+ AoutObject(const std::string &_filename, int _fd,
+ size_t _len, uint8_t *_data,
+ Arch _arch, OpSys _opSys);
+
+ public:
+ virtual ~AoutObject() {}
+
+ virtual bool loadGlobalSymbols(SymbolTable *symtab);
+ virtual bool loadLocalSymbols(SymbolTable *symtab);
+
+ static ObjectFile *tryFile(const std::string &fname, int fd,
+ size_t len, uint8_t *data);
+};
+
+#endif // __AOUT_OBJECT_HH__
diff --git a/src/base/loader/coff_sym.h b/src/base/loader/coff_sym.h
new file mode 100644
index 000000000..4c6540395
--- /dev/null
+++ b/src/base/loader/coff_sym.h
@@ -0,0 +1,519 @@
+/*
+ * Copyright (c) 2003, 2005-2006 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Steve Reinhardt
+ */
+
+/*
+ * Taken from binutils-2.14.90.0.5 include/coff/sym.h
+ */
+
+/* Declarations of internal format of MIPS ECOFF symbols.
+ Originally contributed by MIPS Computer Systems and Third Eye Software.
+ Changes contributed by Cygnus Support are in the public domain.
+
+ This file is just aggregated with the files that make up the GNU
+ release; it is not considered part of GAS, GDB, or other GNU
+ programs. */
+
+/*
+ * |-----------------------------------------------------------|
+ * | Copyright (c) 1992, 1991, 1990 MIPS Computer Systems, Inc.|
+ * | MIPS Computer Systems, Inc. grants reproduction and use |
+ * | rights to all parties, PROVIDED that this comment is |
+ * | maintained in the copy. |
+ * |-----------------------------------------------------------|
+ */
+#ifndef _SYM_H
+#define _SYM_H
+
+/* (C) Copyright 1984 by Third Eye Software, Inc.
+ *
+ * Third Eye Software, Inc. grants reproduction and use rights to
+ * all parties, PROVIDED that this comment is maintained in the copy.
+ *
+ * Third Eye makes no claims about the applicability of this
+ * symbol table to a particular use.
+ */
+
+/*
+ * This file contains the definition of the Third Eye Symbol Table.
+ *
+ * Symbols are assumed to be in 'encounter order' - i.e. the order that
+ * the things they represent were encountered by the compiler/assembler/loader.
+ * EXCEPT for globals! These are assumed to be bunched together,
+ * probably right after the last 'normal' symbol. Globals ARE sorted
+ * in ascending order.
+ *
+ * -----------------------------------------------------------------------
+ * A brief word about Third Eye naming/use conventions:
+ *
+ * All arrays and index's are 0 based.
+ * All "ifooMax" values are the highest legal value PLUS ONE. This makes
+ * them good for allocating arrays, etc. All checks are "ifoo < ifooMax".
+ *
+ * "isym" Index into the SYMbol table.
+ * "ipd" Index into the Procedure Descriptor array.
+ * "ifd" Index into the File Descriptor array.
+ * "iss" Index into String Space.
+ * "cb" Count of Bytes.
+ * "rgPd" array whose domain is "0..ipdMax-1" and RanGe is PDR.
+ * "rgFd" array whose domain is "0..ifdMax-1" and RanGe is FDR.
+ */
+
+
+/*
+ * Symbolic Header (HDR) structure.
+ * As long as all the pointers are set correctly,
+ * we don't care WHAT order the various sections come out in!
+ *
+ * A file produced solely for the use of CDB will probably NOT have
+ * any instructions or data areas in it, as these are available
+ * in the original.
+ */
+
+typedef struct ecoff_symhdr {
+ coff_short magic; /* to verify validity of the table */
+ coff_short vstamp; /* version stamp */
+ coff_int ilineMax; /* number of line number entries */
+ coff_int idnMax; /* max index into dense number table */
+ coff_int ipdMax; /* number of procedures */
+ coff_int isymMax; /* number of local symbols */
+ coff_int ioptMax; /* max index into optimization symbol entries */
+ coff_int iauxMax; /* number of auxillary symbol entries */
+ coff_int issMax; /* max index into local strings */
+ coff_int issExtMax; /* max index into external strings */
+ coff_int ifdMax; /* number of file descriptor entries */
+ coff_int crfd; /* number of relative file descriptor entries */
+ coff_int iextMax; /* max index into external symbols */
+ coff_addr cbLine; /* number of bytes for line number entries */
+ coff_addr cbLineOffset; /* offset to start of line number entries*/
+ coff_addr cbDnOffset; /* offset to start dense number table */
+ coff_addr cbPdOffset; /* offset to procedure descriptor table */
+ coff_addr cbSymOffset; /* offset to start of local symbols*/
+ coff_addr cbOptOffset; /* offset to optimization symbol entries */
+ coff_addr cbAuxOffset; /* offset to start of auxillary symbol entries*/
+ coff_addr cbSsOffset; /* offset to start of local strings */
+ coff_addr cbSsExtOffset; /* offset to start of external strings */
+ coff_addr cbFdOffset; /* offset to file descriptor table */
+ coff_addr cbRfdOffset; /* offset to relative file descriptor table */
+ coff_addr cbExtOffset; /* offset to start of external symbol entries*/
+ /* If you add machine dependent fields, add them here */
+} HDRR, *pHDRR;
+#define cbHDRR sizeof(HDRR)
+#define hdrNil ((pHDRR)0)
+
+/*
+ * The FDR and PDR structures speed mapping of address <-> name.
+ * They are sorted in ascending memory order and are kept in
+ * memory by CDB at runtime.
+ */
+
+/*
+ * File Descriptor
+ *
+ * There is one of these for EVERY FILE, whether compiled with
+ * full debugging symbols or not. The name of a file should be
+ * the path name given to the compiler. This allows the user
+ * to simply specify the names of the directories where the COMPILES
+ * were done, and we will be able to find their files.
+ * A field whose comment starts with "R - " indicates that it will be
+ * setup at runtime.
+ */
+typedef struct ecoff_fdr {
+ coff_addr adr; /* memory address of beginning of file */
+ coff_addr cbLineOffset; /* byte offset from header for this file ln's */
+ coff_addr cbLine; /* size of lines for this file */
+ coff_addr cbSs; /* number of bytes in the ss */
+ coff_int rss; /* file name (of source, if known) */
+ coff_int issBase; /* file's string space */
+ coff_int isymBase; /* beginning of symbols */
+ coff_int csym; /* count file's of symbols */
+ coff_int ilineBase; /* file's line symbols */
+ coff_int cline; /* count of file's line symbols */
+ coff_int ioptBase; /* file's optimization entries */
+ coff_int copt; /* count of file's optimization entries */
+ coff_int ipdFirst; /* start of procedures for this file */
+ coff_int cpd; /* count of procedures for this file */
+ coff_int iauxBase; /* file's auxiliary entries */
+ coff_int caux; /* count of file's auxiliary entries */
+ coff_int rfdBase; /* index into the file indirect table */
+ coff_int crfd; /* count file indirect entries */
+ unsigned lang: 5; /* language for this file */
+ unsigned fMerge : 1; /* whether this file can be merged */
+ unsigned fReadin : 1; /* true if it was read in (not just created) */
+ unsigned fBigendian : 1;/* if set, was compiled on big endian machine */
+ /* aux's will be in compile host's sex */
+ unsigned glevel : 2; /* level this file was compiled with */
+ unsigned reserved : 22; /* reserved for future use */
+ coff_uint reserved2;
+} FDR, *pFDR;
+#define cbFDR sizeof(FDR)
+#define fdNil ((pFDR)0)
+#define ifdNil -1
+#define ifdTemp 0
+#define ilnNil -1
+
+
+/*
+ * Procedure Descriptor
+ *
+ * There is one of these for EVERY TEXT LABEL.
+ * If a procedure is in a file with full symbols, then isym
+ * will point to the PROC symbols, else it will point to the
+ * global symbol for the label.
+ */
+
+typedef struct pdr {
+ coff_addr adr; /* memory address of start of procedure */
+ coff_addr cbLineOffset; /* byte offset for this procedure from the fd base */
+ coff_int isym; /* start of local symbol entries */
+ coff_int iline; /* start of line number entries*/
+ coff_uint regmask; /* save register mask */
+ coff_int regoffset; /* save register offset */
+ coff_int iopt; /* start of optimization symbol entries*/
+ coff_uint fregmask; /* save floating point register mask */
+ coff_int fregoffset; /* save floating point register offset */
+ coff_int frameoffset; /* frame size */
+ coff_int lnLow; /* lowest line in the procedure */
+ coff_int lnHigh; /* highest line in the procedure */
+ /* These fields are new for 64 bit ECOFF. */
+ unsigned gp_prologue : 8; /* byte size of GP prologue */
+ unsigned gp_used : 1; /* true if the procedure uses GP */
+ unsigned reg_frame : 1; /* true if register frame procedure */
+ unsigned prof : 1; /* true if compiled with -pg */
+ unsigned reserved : 13; /* reserved: must be zero */
+ unsigned localoff : 8; /* offset of local variables from vfp */
+ coff_short framereg; /* frame pointer register */
+ coff_short pcreg; /* offset or reg of return pc */
+} PDR, *pPDR;
+#define cbPDR sizeof(PDR)
+#define pdNil ((pPDR) 0)
+#define ipdNil -1
+
+/*
+ * The structure of the runtime procedure descriptor created by the loader
+ * for use by the static exception system.
+ */
+/*
+ * If 0'd out because exception_info chokes Visual C++ and because there
+ * don't seem to be any references to this structure elsewhere in gdb.
+ */
+#if 0
+typedef struct runtime_pdr {
+ coff_addr adr; /* memory address of start of procedure */
+ coff_uint regmask; /* save register mask */
+ coff_int regoffset; /* save register offset */
+ coff_uint fregmask; /* save floating point register mask */
+ coff_int fregoffset; /* save floating point register offset */
+ coff_int frameoffset; /* frame size */
+ coff_ushort framereg; /* frame pointer register */
+ coff_ushort pcreg; /* offset or reg of return pc */
+ coff_int irpss; /* index into the runtime string table */
+ coff_uint reserved;
+ struct exception_info *exception_info;/* pointer to exception array */
+} RPDR, *pRPDR;
+#define cbRPDR sizeof(RPDR)
+#define rpdNil ((pRPDR) 0)
+#endif
+
+/*
+ * Line Numbers
+ *
+ * Line Numbers are segregated from the normal symbols because they
+ * are [1] smaller , [2] are of no interest to your
+ * average loader, and [3] are never needed in the middle of normal
+ * scanning and therefore slow things down.
+ *
+ * By definition, the first LINER for any given procedure will have
+ * the first line of a procedure and represent the first address.
+ */
+
+typedef coff_int LINER, *pLINER;
+#define lineNil ((pLINER)0)
+#define cbLINER sizeof(LINER)
+#define ilineNil -1
+
+
+
+/*
+ * The Symbol Structure (GFW, to those who Know!)
+ */
+
+typedef struct ecoff_sym {
+ coff_long value; /* value of symbol */
+ coff_int iss; /* index into String Space of name */
+ unsigned st : 6; /* symbol type */
+ unsigned sc : 5; /* storage class - text, data, etc */
+ unsigned reserved : 1; /* reserved */
+ unsigned index : 20; /* index into sym/aux table */
+} SYMR, *pSYMR;
+#define symNil ((pSYMR)0)
+#define cbSYMR sizeof(SYMR)
+#define isymNil -1
+#define indexNil 0xfffff
+#define issNil -1
+#define issNull 0
+
+
+/* The following converts a memory resident string to an iss.
+ * This hack is recognized in SbFIss, in sym.c of the debugger.
+ */
+#define IssFSb(sb) (0x80000000 | ((coff_ulong)(sb)))
+
+/* E X T E R N A L S Y M B O L R E C O R D
+ *
+ * Same as the SYMR except it contains file context to determine where
+ * the index is.
+ */
+typedef struct ecoff_extsym {
+ SYMR asym; /* symbol for the external */
+ unsigned jmptbl:1; /* symbol is a jump table entry for shlibs */
+ unsigned cobol_main:1; /* symbol is a cobol main procedure */
+ unsigned weakext:1; /* symbol is weak external */
+ unsigned reserved:29; /* reserved for future use */
+ coff_int ifd; /* where the iss and index fields point into */
+} EXTR, *pEXTR;
+#define extNil ((pEXTR)0)
+#define cbEXTR sizeof(EXTR)
+
+
+/* A U X I L L A R Y T Y P E I N F O R M A T I O N */
+
+/*
+ * Type Information Record
+ */
+typedef struct {
+ unsigned fBitfield : 1; /* set if bit width is specified */
+ unsigned continued : 1; /* indicates additional TQ info in next AUX */
+ unsigned bt : 6; /* basic type */
+ unsigned tq4 : 4;
+ unsigned tq5 : 4;
+ /* ---- 16 bit boundary ---- */
+ unsigned tq0 : 4;
+ unsigned tq1 : 4; /* 6 type qualifiers - tqPtr, etc. */
+ unsigned tq2 : 4;
+ unsigned tq3 : 4;
+} TIR, *pTIR;
+#define cbTIR sizeof(TIR)
+#define tiNil ((pTIR)0)
+#define itqMax 6
+
+/*
+ * Relative symbol record
+ *
+ * If the rfd field is 4095, the index field indexes into the global symbol
+ * table.
+ */
+
+typedef struct {
+ unsigned rfd : 12; /* index into the file indirect table */
+ unsigned index : 20; /* index int sym/aux/iss tables */
+} RNDXR, *pRNDXR;
+#define cbRNDXR sizeof(RNDXR)
+#define rndxNil ((pRNDXR)0)
+
+/* dense numbers or sometimes called block numbers are stored in this type,
+ * a rfd of 0xffffffff is an index into the global table.
+ */
+typedef struct {
+ coff_uint rfd; /* index into the file table */
+ coff_uint index; /* index int sym/aux/iss tables */
+} DNR, *pDNR;
+#define cbDNR sizeof(DNR)
+#define dnNil ((pDNR)0)
+
+
+
+/*
+ * Auxillary information occurs only if needed.
+ * It ALWAYS occurs in this order when present.
+
+ isymMac used by stProc only
+ TIR type info
+ TIR additional TQ info (if first TIR was not enough)
+ rndx if (bt == btStruct,btUnion,btEnum,btSet,btRange,
+ btTypedef):
+ rsym.index == iaux for btSet or btRange
+ else rsym.index == isym
+ dimLow btRange, btSet
+ dimMac btRange, btSet
+ rndx0 As many as there are tq arrays
+ dimLow0
+ dimHigh0
+ ...
+ rndxMax-1
+ dimLowMax-1
+ dimHighMax-1
+ width in bits if (bit field), width in bits.
+ */
+#define cAuxMax (6 + (idimMax*3))
+
+/* a union of all possible info in the AUX universe */
+typedef union {
+ TIR ti; /* type information record */
+ RNDXR rndx; /* relative index into symbol table */
+ coff_int dnLow; /* low dimension */
+ coff_int dnHigh; /* high dimension */
+ coff_int isym; /* symbol table index (end of proc) */
+ coff_int iss; /* index into string space (not used) */
+ coff_int width; /* width for non-default sized struc fields */
+ coff_int count; /* count of ranges for variant arm */
+} AUXU, *pAUXU;
+#define cbAUXU sizeof(AUXU)
+#define auxNil ((pAUXU)0)
+#define iauxNil -1
+
+
+/*
+ * Optimization symbols
+ *
+ * Optimization symbols contain some overlap information with the normal
+ * symbol table. In particular, the proc information
+ * is somewhat redundant but necessary to easily find the other information
+ * present.
+ *
+ * All of the offsets are relative to the beginning of the last otProc
+ */
+
+typedef struct {
+ unsigned ot: 8; /* optimization type */
+ unsigned value: 24; /* address where we are moving it to */
+ RNDXR rndx; /* points to a symbol or opt entry */
+ coff_ulong offset; /* relative offset this occured */
+} OPTR, *pOPTR;
+#define optNil ((pOPTR) 0)
+#define cbOPTR sizeof(OPTR)
+#define ioptNil -1
+
+/*
+ * File Indirect
+ *
+ * When a symbol is referenced across files the following procedure is used:
+ * 1) use the file index to get the File indirect entry.
+ * 2) use the file indirect entry to get the File descriptor.
+ * 3) add the sym index to the base of that file's sym table
+ *
+ */
+
+typedef coff_long RFDT, *pRFDT;
+#define cbRFDT sizeof(RFDT)
+#define rfdNil -1
+
+/*
+ * The file indirect table in the mips loader is known as an array of FITs.
+ * This is done to keep the code in the loader readable in the area where
+ * these tables are merged. Note this is only a name change.
+ */
+typedef coff_int FIT, *pFIT;
+#define cbFIT sizeof(FIT)
+#define ifiNil -1
+#define fiNil ((pFIT) 0)
+
+#ifdef _LANGUAGE_PASCAL
+#define ifdNil -1
+#define ilnNil -1
+#define ipdNil -1
+#define ilineNil -1
+#define isymNil -1
+#define indexNil 16#fffff
+#define issNil -1
+#define issNull 0
+#define itqMax 6
+#define iauxNil -1
+#define ioptNil -1
+#define rfdNil -1
+#define ifiNil -1
+#endif /* _LANGUAGE_PASCAL */
+
+
+/* Dense numbers
+ *
+ * Rather than use file index, symbol index pairs to represent symbols
+ * and globals, we use dense number so that they can be easily embeded
+ * in intermediate code and the programs that process them can
+ * use direct access tabls instead of hash table (which would be
+ * necesary otherwise because of the sparse name space caused by
+ * file index, symbol index pairs. Dense number are represented
+ * by RNDXRs.
+ */
+
+/*
+ * The following table defines the meaning of each SYM field as
+ * a function of the "st". (scD/B == scData OR scBss)
+ *
+ * Note: the value "isymMac" is used by symbols that have the concept
+ * of enclosing a block of related information. This value is the
+ * isym of the first symbol AFTER the end associated with the primary
+ * symbol. For example if a procedure was at isym==90 and had an
+ * isymMac==155, the associated end would be at isym==154, and the
+ * symbol at 155 would probably (although not necessarily) be the
+ * symbol for the next procedure. This allows rapid skipping over
+ * internal information of various sorts. "stEnd"s ALWAYS have the
+ * isym of the primary symbol that started the block.
+ *
+
+ST SC VALUE INDEX
+-------- ------ -------- ------
+stFile scText address isymMac
+stLabel scText address ---
+stGlobal scD/B address iaux
+stStatic scD/B address iaux
+stParam scAbs offset iaux
+stLocal scAbs offset iaux
+stProc scText address iaux (isymMac is first AUX)
+stStaticProc scText address iaux (isymMac is first AUX)
+
+stMember scNil ordinal --- (if member of enum)
+ (mipsread thinks the case below has a bit, not byte, offset.)
+stMember scNil byte offset iaux (if member of struct/union)
+stMember scBits bit offset iaux (bit field spec)
+
+stBlock scText address isymMac (text block)
+ (the code seems to think that rather than scNil, we see scInfo for
+ the two cases below.)
+stBlock scNil cb isymMac (struct/union member define)
+stBlock scNil cMembers isymMac (enum member define)
+
+ (New types added by SGI to simplify things:)
+stStruct scInfo cb isymMac (struct type define)
+stUnion scInfo cb isymMac (union type define)
+stEnum scInfo cMembers isymMac (enum type define)
+
+stEnd scText address isymStart
+stEnd scNil ------- isymStart (struct/union/enum)
+
+stTypedef scNil ------- iaux
+stRegReloc sc??? value old register number
+stForward sc??? new address isym to original symbol
+
+stConstant scInfo value --- (scalar)
+stConstant scInfo iss --- (complex, e.g. string)
+
+ *
+ */
+#endif
diff --git a/src/base/loader/coff_symconst.h b/src/base/loader/coff_symconst.h
new file mode 100644
index 000000000..f383c19e6
--- /dev/null
+++ b/src/base/loader/coff_symconst.h
@@ -0,0 +1,200 @@
+/*
+ * Copyright (c) 2003, 2005-2006 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Steve Reinhardt
+ */
+
+/*
+ * Taken from binutils-2.14.90.0.5 include/coff/symconst.h
+ */
+
+/* Declarations of constants for internal format of MIPS ECOFF symbols.
+ Originally contributed by MIPS Computer Systems and Third Eye Software.
+ Changes contributed by Cygnus Support are in the public domain.
+
+ This file is just aggregated with the files that make up the GNU
+ release; it is not considered part of GAS, GDB, or other GNU
+ programs. */
+
+/*
+ * |-----------------------------------------------------------|
+ * | Copyright (c) 1992, 1991, 1990 MIPS Computer Systems, Inc.|
+ * | MIPS Computer Systems, Inc. grants reproduction and use |
+ * | rights to all parties, PROVIDED that this comment is |
+ * | maintained in the copy. |
+ * |-----------------------------------------------------------|
+ */
+
+/* (C) Copyright 1984 by Third Eye Software, Inc.
+ *
+ * Third Eye Software, Inc. grants reproduction and use rights to
+ * all parties, PROVIDED that this comment is maintained in the copy.
+ *
+ * Third Eye makes no claims about the applicability of this
+ * symbol table to a particular use.
+ */
+
+/* glevels for field in FDR */
+#define GLEVEL_0 2
+#define GLEVEL_1 1
+#define GLEVEL_2 0 /* for upward compat reasons. */
+#define GLEVEL_3 3
+
+/* magic number fo symheader */
+#define magicSym 0x7009
+/* The Alpha uses this value instead, for some reason. */
+#define magicSym2 0x1992
+
+/* Language codes */
+#define langC 0
+#define langPascal 1
+#define langFortran 2
+#define langAssembler 3 /* one Assembley inst might map to many mach */
+#define langMachine 4
+#define langNil 5
+#define langAda 6
+#define langPl1 7
+#define langCobol 8
+#define langStdc 9 /* FIXME: Collides with SGI langCplusplus */
+#define langCplusplus 9 /* FIXME: Collides with langStdc */
+#define langCplusplusV2 10 /* SGI addition */
+#define langMax 11 /* maximun allowed 32 -- 5 bits */
+
+/* The following are value definitions for the fields in the SYMR */
+
+/*
+ * Storage Classes
+ */
+
+#define scNil 0
+#define scText 1 /* text symbol */
+#define scData 2 /* initialized data symbol */
+#define scBss 3 /* un-initialized data symbol */
+#define scRegister 4 /* value of symbol is register number */
+#define scAbs 5 /* value of symbol is absolute */
+#define scUndefined 6 /* who knows? */
+#define scCdbLocal 7 /* variable's value is IN se->va.?? */
+#define scBits 8 /* this is a bit field */
+#define scCdbSystem 9 /* variable's value is IN CDB's address space */
+#define scDbx 9 /* overlap dbx internal use */
+#define scRegImage 10 /* register value saved on stack */
+#define scInfo 11 /* symbol contains debugger information */
+#define scUserStruct 12 /* address in struct user for current process */
+#define scSData 13 /* load time only small data */
+#define scSBss 14 /* load time only small common */
+#define scRData 15 /* load time only read only data */
+#define scVar 16 /* Var parameter (fortran,pascal) */
+#define scCommon 17 /* common variable */
+#define scSCommon 18 /* small common */
+#define scVarRegister 19 /* Var parameter in a register */
+#define scVariant 20 /* Variant record */
+#define scSUndefined 21 /* small undefined(external) data */
+#define scInit 22 /* .init section symbol */
+#define scBasedVar 23 /* Fortran or PL/1 ptr based var */
+#define scXData 24 /* exception handling data */
+#define scPData 25 /* Procedure section */
+#define scFini 26 /* .fini section */
+#define scRConst 27 /* .rconst section */
+#define scMax 32
+
+
+/*
+ * Symbol Types
+ */
+
+#define stNil 0 /* Nuthin' special */
+#define stGlobal 1 /* external symbol */
+#define stStatic 2 /* static */
+#define stParam 3 /* procedure argument */
+#define stLocal 4 /* local variable */
+#define stLabel 5 /* label */
+#define stProc 6 /* " " Procedure */
+#define stBlock 7 /* beginnning of block */
+#define stEnd 8 /* end (of anything) */
+#define stMember 9 /* member (of anything - struct/union/enum */
+#define stTypedef 10 /* type definition */
+#define stFile 11 /* file name */
+#define stRegReloc 12 /* register relocation */
+#define stForward 13 /* forwarding address */
+#define stStaticProc 14 /* load time only static procs */
+#define stConstant 15 /* const */
+#define stStaParam 16 /* Fortran static parameters */
+ /* These new symbol types have been recently added to SGI machines. */
+#define stStruct 26 /* Beginning of block defining a struct type */
+#define stUnion 27 /* Beginning of block defining a union type */
+#define stEnum 28 /* Beginning of block defining an enum type */
+#define stIndirect 34 /* Indirect type specification */
+ /* Pseudo-symbols - internal to debugger */
+#define stStr 60 /* string */
+#define stNumber 61 /* pure number (ie. 4 NOR 2+2) */
+#define stExpr 62 /* 2+2 vs. 4 */
+#define stType 63 /* post-coersion SER */
+#define stMax 64
+
+/* definitions for fields in TIR */
+
+/* type qualifiers for ti.tq0 -> ti.(itqMax-1) */
+#define tqNil 0 /* bt is what you see */
+#define tqPtr 1 /* pointer */
+#define tqProc 2 /* procedure */
+#define tqArray 3 /* duh */
+#define tqFar 4 /* longer addressing - 8086/8 land */
+#define tqVol 5 /* volatile */
+#define tqConst 6 /* const */
+#define tqMax 8
+
+/* basic types as seen in ti.bt */
+#define btNil 0 /* undefined (also, enum members) */
+#define btAdr 1 /* address - integer same size as pointer */
+#define btChar 2 /* character */
+#define btUChar 3 /* unsigned character */
+#define btShort 4 /* short */
+#define btUShort 5 /* unsigned short */
+#define btInt 6 /* int */
+#define btUInt 7 /* unsigned int */
+#define btLong 8 /* long */
+#define btULong 9 /* unsigned long */
+#define btFloat 10 /* float (real) */
+#define btDouble 11 /* Double (real) */
+#define btStruct 12 /* Structure (Record) */
+#define btUnion 13 /* Union (variant) */
+#define btEnum 14 /* Enumerated */
+#define btTypedef 15 /* defined via a typedef, isymRef points */
+#define btRange 16 /* subrange of int */
+#define btSet 17 /* pascal sets */
+#define btComplex 18 /* fortran complex */
+#define btDComplex 19 /* fortran double complex */
+#define btIndirect 20 /* forward or unnamed typedef */
+#define btFixedDec 21 /* Fixed Decimal */
+#define btFloatDec 22 /* Float Decimal */
+#define btString 23 /* Varying Length Character String */
+#define btBit 24 /* Aligned Bit String */
+#define btPicture 25 /* Picture */
+#define btVoid 26 /* void */
+#define btLongLong 27 /* long long */
+#define btULongLong 28 /* unsigned long long */
+#define btMax 64
diff --git a/src/base/loader/ecoff_object.cc b/src/base/loader/ecoff_object.cc
new file mode 100644
index 000000000..80917ee9c
--- /dev/null
+++ b/src/base/loader/ecoff_object.cc
@@ -0,0 +1,153 @@
+/*
+ * 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 <string>
+
+#include "base/loader/ecoff_object.hh"
+#include "base/misc.hh"
+#include "base/loader/symtab.hh"
+
+#include "base/trace.hh" // for DPRINTF
+
+#include "base/loader/exec_ecoff.h"
+#include "base/loader/coff_sym.h"
+#include "base/loader/coff_symconst.h"
+
+using namespace std;
+
+ObjectFile *
+EcoffObject::tryFile(const string &fname, int fd, size_t len, uint8_t *data)
+{
+ if (((ecoff_filehdr *)data)->f_magic == ECOFF_MAGIC_ALPHA) {
+ // it's Alpha ECOFF
+ return new EcoffObject(fname, fd, len, data,
+ ObjectFile::Alpha, ObjectFile::Tru64);
+ }
+ else {
+ return NULL;
+ }
+}
+
+
+EcoffObject::EcoffObject(const string &_filename, int _fd,
+ size_t _len, uint8_t *_data,
+ Arch _arch, OpSys _opSys)
+ : ObjectFile(_filename, _fd, _len, _data, _arch, _opSys)
+{
+ execHdr = (ecoff_exechdr *)fileData;
+ fileHdr = &(execHdr->f);
+ aoutHdr = &(execHdr->a);
+
+ entry = aoutHdr->entry;
+
+ 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,
+ bss.baseAddr, bss.size);
+}
+
+
+bool
+EcoffObject::loadGlobalSymbols(SymbolTable *symtab)
+{
+ if (!symtab)
+ return false;
+
+ if (fileHdr->f_magic != ECOFF_MAGIC_ALPHA) {
+ warn("loadGlobalSymbols: wrong magic on %s\n", filename);
+ return false;
+ }
+
+ ecoff_symhdr *syms = (ecoff_symhdr *)(fileData + fileHdr->f_symptr);
+ if (syms->magic != magicSym2) {
+ warn("loadGlobalSymbols: bad symbol header magic on %s\n", filename);
+ return false;
+ }
+
+ ecoff_extsym *ext_syms = (ecoff_extsym *)(fileData + syms->cbExtOffset);
+
+ char *ext_strings = (char *)(fileData + syms->cbSsExtOffset);
+ for (int i = 0; i < syms->iextMax; i++) {
+ ecoff_sym *entry = &(ext_syms[i].asym);
+ if (entry->iss != -1)
+ symtab->insert(entry->value, ext_strings + entry->iss);
+ }
+
+ return true;
+}
+
+bool
+EcoffObject::loadLocalSymbols(SymbolTable *symtab)
+{
+ if (!symtab)
+ return false;
+
+ if (fileHdr->f_magic != ECOFF_MAGIC_ALPHA) {
+ warn("loadGlobalSymbols: wrong magic on %s\n", filename);
+ return false;
+ }
+
+ ecoff_symhdr *syms = (ecoff_symhdr *)(fileData + fileHdr->f_symptr);
+ if (syms->magic != magicSym2) {
+ warn("loadGlobalSymbols: bad symbol header magic on %s\n", filename);
+ return false;
+ }
+
+ ecoff_sym *local_syms = (ecoff_sym *)(fileData + syms->cbSymOffset);
+ char *local_strings = (char *)(fileData + syms->cbSsOffset);
+ ecoff_fdr *fdesc = (ecoff_fdr *)(fileData + syms->cbFdOffset);
+
+ for (int i = 0; i < syms->ifdMax; i++) {
+ ecoff_sym *entry = (ecoff_sym *)(local_syms + fdesc[i].isymBase);
+ char *strings = (char *)(local_strings + fdesc[i].issBase);
+ for (int j = 0; j < fdesc[i].csym; j++) {
+ if (entry[j].st == stGlobal || entry[j].st == stProc)
+ if (entry[j].iss != -1)
+ symtab->insert(entry[j].value, strings + entry[j].iss);
+ }
+ }
+
+ for (int i = 0; i < syms->isymMax; i++) {
+ ecoff_sym *entry = &(local_syms[i]);
+ if (entry->st == stProc)
+ symtab->insert(entry->value, local_strings + entry->iss);
+ }
+
+ return true;
+}
diff --git a/src/base/loader/ecoff_object.hh b/src/base/loader/ecoff_object.hh
new file mode 100644
index 000000000..603c70bec
--- /dev/null
+++ b/src/base/loader/ecoff_object.hh
@@ -0,0 +1,60 @@
+/*
+ * 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 __ECOFF_OBJECT_HH__
+#define __ECOFF_OBJECT_HH__
+
+#include "base/loader/object_file.hh"
+
+// forward decls: avoid including exec_ecoff.h here
+struct ecoff_exechdr;
+struct ecoff_filehdr;
+struct ecoff_aouthdr;
+
+class EcoffObject : public ObjectFile
+{
+ protected:
+ ecoff_exechdr *execHdr;
+ ecoff_filehdr *fileHdr;
+ ecoff_aouthdr *aoutHdr;
+
+ EcoffObject(const std::string &_filename, int _fd,
+ size_t _len, uint8_t *_data,
+ Arch _arch, OpSys _opSys);
+
+ public:
+ virtual ~EcoffObject() {}
+
+ virtual bool loadGlobalSymbols(SymbolTable *symtab);
+ virtual bool loadLocalSymbols(SymbolTable *symtab);
+
+ static ObjectFile *tryFile(const std::string &fname, int fd,
+ size_t len, uint8_t *data);
+};
+
+#endif // __ECOFF_OBJECT_HH__
diff --git a/src/base/loader/elf_object.cc b/src/base/loader/elf_object.cc
new file mode 100644
index 000000000..79601e9d1
--- /dev/null
+++ b/src/base/loader/elf_object.cc
@@ -0,0 +1,309 @@
+/*
+ * 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 <string>
+
+// Because of the -Wundef flag we have to do this
+#define __LIBELF_INTERNAL__ 0
+#define __LIBELF_NEED_LINK_H 0
+#define __LIBELF_SYMBOL_VERSIONS 0
+
+#include "gelf.h"
+
+#include "base/loader/elf_object.hh"
+#include "base/misc.hh"
+
+#include "base/loader/symtab.hh"
+
+#include "base/trace.hh" // for DPRINTF
+
+#include "sim/byteswap.hh"
+
+
+using namespace std;
+
+ObjectFile *
+ElfObject::tryFile(const string &fname, int fd, size_t len, uint8_t *data)
+{
+ Elf *elf;
+ GElf_Ehdr ehdr;
+ Arch arch = UnknownArch;
+ OpSys opSys = UnknownOpSys;
+
+ // check that header matches library version
+ if (elf_version(EV_CURRENT) == EV_NONE)
+ panic("wrong elf version number!");
+
+ // get a pointer to elf structure
+ elf = elf_memory((char*)data,len);
+ // will only fail if fd is invalid
+ assert(elf != NULL);
+
+ // Check that we actually have a elf file
+ if (gelf_getehdr(elf, &ehdr) ==0) {
+ DPRINTFR(Loader, "Not ELF\n");
+ elf_end(elf);
+ return NULL;
+ } else {
+ //Detect the architecture
+ //Since we don't know how to check for alpha right now, we'll
+ //just assume if it wasn't something else and it's 64 bit, that's
+ //what it must be.
+ if (ehdr.e_machine == EM_SPARC64 ||
+ ehdr.e_machine == EM_SPARC ||
+ ehdr.e_machine == EM_SPARCV9) {
+ arch = ObjectFile::SPARC;
+ } else if (ehdr.e_machine == EM_MIPS
+ && ehdr.e_ident[EI_CLASS] == ELFCLASS32) {
+ arch = ObjectFile::Mips;
+ } else if (ehdr.e_ident[EI_CLASS] == ELFCLASS64) {
+ arch = ObjectFile::Alpha;
+ } else {
+ warn("Unknown architecture: %d\n", ehdr.e_machine);
+ arch = ObjectFile::UnknownArch;
+ }
+
+ //Detect the operating system
+ switch (ehdr.e_ident[EI_OSABI])
+ {
+
+ case ELFOSABI_LINUX:
+ opSys = ObjectFile::Linux;
+ break;
+ case ELFOSABI_SOLARIS:
+ opSys = ObjectFile::Solaris;
+ break;
+ case ELFOSABI_TRU64:
+ opSys = ObjectFile::Tru64;
+ break;
+ default:
+ opSys = ObjectFile::UnknownOpSys;
+ }
+
+ //take a look at the .note.ABI section
+ //It can let us know what's what.
+ if (opSys == ObjectFile::UnknownOpSys) {
+ Elf_Scn *section;
+ GElf_Shdr shdr;
+ Elf_Data *data;
+ uint32_t osAbi;;
+ int secIdx = 1;
+
+ // Get the first section
+ section = elf_getscn(elf, secIdx);
+
+ // While there are no more sections
+ while (section != NULL && opSys == ObjectFile::UnknownOpSys) {
+ gelf_getshdr(section, &shdr);
+ if (shdr.sh_type == SHT_NOTE && !strcmp(".note.ABI-tag",
+ elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name))) {
+ // we have found a ABI note section
+ // Check the 5th 32bit word for OS 0 == linux, 1 == hurd,
+ // 2 == solaris, 3 == freebsd
+ data = elf_rawdata(section, NULL);
+ assert(data->d_buf);
+ if(ehdr.e_ident[EI_DATA] == ELFDATA2LSB)
+ osAbi = htole(((uint32_t*)data->d_buf)[4]);
+ else
+ osAbi = htobe(((uint32_t*)data->d_buf)[4]);
+
+ switch(osAbi) {
+ case 0:
+ opSys = ObjectFile::Linux;
+ break;
+ case 2:
+ opSys = ObjectFile::Solaris;
+ break;
+ }
+ } // if section found
+ if (!strcmp(".SUNW_version", elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name)))
+ opSys = ObjectFile::Solaris;
+ if (!strcmp(".stab.index", elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name)))
+ opSys = ObjectFile::Solaris;
+
+ section = elf_getscn(elf, ++secIdx);
+ } // while sections
+ }
+
+ elf_end(elf);
+ return new ElfObject(fname, fd, len, data, arch, opSys);
+ }
+}
+
+
+ElfObject::ElfObject(const string &_filename, int _fd,
+ size_t _len, uint8_t *_data,
+ Arch _arch, OpSys _opSys)
+ : ObjectFile(_filename, _fd, _len, _data, _arch, _opSys)
+
+{
+ Elf *elf;
+ GElf_Ehdr ehdr;
+
+ // check that header matches library version
+ if (elf_version(EV_CURRENT) == EV_NONE)
+ panic("wrong elf version number!");
+
+ // get a pointer to elf structure
+ elf = elf_memory((char*)fileData,len);
+ // will only fail if fd is invalid
+ assert(elf != NULL);
+
+ // Check that we actually have a elf file
+ if (gelf_getehdr(elf, &ehdr) ==0) {
+ panic("Not ELF, shouldn't be here");
+ }
+
+ entry = ehdr.e_entry;
+
+
+ // initialize segment sizes to 0 in case they're not present
+ text.size = data.size = bss.size = 0;
+
+ for (int i = 0; i < ehdr.e_phnum; ++i) {
+ GElf_Phdr phdr;
+ if (gelf_getphdr(elf, i, &phdr) == 0) {
+ panic("gelf_getphdr failed for section %d", i);
+ }
+
+ // for now we don't care about non-loadable segments
+ if (!(phdr.p_type & PT_LOAD))
+ continue;
+
+ // the headers don't explicitly distinguish text from data,
+ // but empirically the text segment comes first.
+ if (text.size == 0) { // haven't seen text segment yet
+ text.baseAddr = phdr.p_vaddr;
+ text.size = phdr.p_filesz;
+ 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;
+ bss.fileImage = NULL;
+ } else if (data.size == 0) { // have text, this must be data
+ data.baseAddr = phdr.p_vaddr;
+ data.size = phdr.p_filesz;
+ 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).
+ if (phdr.p_memsz - phdr.p_filesz > 0 && bss.size != 0) {
+ warn("Two implied bss segments in file!\n");
+ }
+ 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);
+ }
+ }
+
+ // should have found at least one loadable segment
+ assert(text.size != 0);
+
+ DPRINTFR(Loader, "text: 0x%x %d\ndata: 0x%x %d\nbss: 0x%x %d\n",
+ text.baseAddr, text.size, data.baseAddr, data.size,
+ bss.baseAddr, bss.size);
+
+ elf_end(elf);
+
+ // We will actually read the sections when we need to load them
+}
+
+
+bool
+ElfObject::loadSomeSymbols(SymbolTable *symtab, int binding)
+{
+ Elf *elf;
+ int sec_idx = 1; // there is a 0 but it is nothing, go figure
+ Elf_Scn *section;
+ GElf_Shdr shdr;
+ Elf_Data *data;
+ int count, ii;
+ bool found = false;
+ GElf_Sym sym;
+
+ if (!symtab)
+ return false;
+
+ // check that header matches library version
+ if (elf_version(EV_CURRENT) == EV_NONE)
+ panic("wrong elf version number!");
+
+ // get a pointer to elf structure
+ elf = elf_memory((char*)fileData,len);
+
+ assert(elf != NULL);
+
+ // Get the first section
+ section = elf_getscn(elf, sec_idx);
+
+ // While there are no more sections
+ while (section != NULL) {
+ gelf_getshdr(section, &shdr);
+
+ if (shdr.sh_type == SHT_SYMTAB) {
+ found = true;
+ data = elf_getdata(section, NULL);
+ count = shdr.sh_size / shdr.sh_entsize;
+ DPRINTF(Loader, "Found Symbol Table, %d symbols present\n", count);
+
+ // loop through all the symbols, only loading global ones
+ for (ii = 0; ii < count; ++ii) {
+ gelf_getsym(data, ii, &sym);
+ if (GELF_ST_BIND(sym.st_info) == binding) {
+ symtab->insert(sym.st_value,
+ elf_strptr(elf, shdr.sh_link, sym.st_name));
+ }
+ }
+ }
+ ++sec_idx;
+ section = elf_getscn(elf, sec_idx);
+ }
+
+ elf_end(elf);
+
+ return found;
+}
+
+bool
+ElfObject::loadGlobalSymbols(SymbolTable *symtab)
+{
+ return loadSomeSymbols(symtab, STB_GLOBAL);
+}
+
+bool
+ElfObject::loadLocalSymbols(SymbolTable *symtab)
+{
+ return loadSomeSymbols(symtab, STB_LOCAL);
+}
diff --git a/src/base/loader/elf_object.hh b/src/base/loader/elf_object.hh
new file mode 100644
index 000000000..72c265edd
--- /dev/null
+++ b/src/base/loader/elf_object.hh
@@ -0,0 +1,55 @@
+/*
+ * 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 __ELF_OBJECT_HH__
+#define __ELF_OBJECT_HH__
+
+#include "base/loader/object_file.hh"
+
+class ElfObject : public ObjectFile
+{
+ protected:
+
+ /// Helper functions for loadGlobalSymbols() and loadLocalSymbols().
+ bool loadSomeSymbols(SymbolTable *symtab, int binding);
+
+ ElfObject(const std::string &_filename, int _fd,
+ size_t _len, uint8_t *_data,
+ Arch _arch, OpSys _opSys);
+
+ public:
+ virtual ~ElfObject() {}
+
+ virtual bool loadGlobalSymbols(SymbolTable *symtab);
+ virtual bool loadLocalSymbols(SymbolTable *symtab);
+
+ static ObjectFile *tryFile(const std::string &fname, int fd,
+ size_t len, uint8_t *data);
+};
+
+#endif // __ELF_OBJECT_HH__
diff --git a/base/loader/exec_aout.h b/src/base/loader/exec_aout.h
index eed44baee..eed44baee 100644
--- a/base/loader/exec_aout.h
+++ b/src/base/loader/exec_aout.h
diff --git a/base/loader/exec_ecoff.h b/src/base/loader/exec_ecoff.h
index 555589806..555589806 100644
--- a/base/loader/exec_ecoff.h
+++ b/src/base/loader/exec_ecoff.h
diff --git a/src/base/loader/object_file.cc b/src/base/loader/object_file.cc
new file mode 100644
index 000000000..c6dfced1d
--- /dev/null
+++ b/src/base/loader/object_file.cc
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2002-2004 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <list>
+#include <string>
+
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include "base/cprintf.hh"
+#include "base/loader/object_file.hh"
+#include "base/loader/symtab.hh"
+
+#include "base/loader/ecoff_object.hh"
+#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,
+ size_t _len, uint8_t *_data,
+ Arch _arch, OpSys _opSys)
+ : filename(_filename), descriptor(_fd), fileData(_data), len(_len),
+ arch(_arch), opSys(_opSys)
+{
+}
+
+
+ObjectFile::~ObjectFile()
+{
+ close();
+}
+
+
+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()
+{
+ if (descriptor >= 0) {
+ ::close(descriptor);
+ descriptor = -1;
+ }
+
+ if (fileData) {
+ ::munmap(fileData, len);
+ fileData = NULL;
+ }
+}
+
+
+ObjectFile *
+createObjectFile(const string &fname)
+{
+ // open the file
+ int fd = open(fname.c_str(), O_RDONLY);
+ if (fd < 0) {
+ return NULL;
+ }
+
+ // find the length of the file by seeking to the end
+ size_t len = (size_t)lseek(fd, 0, SEEK_END);
+
+ // mmap the whole shebang
+ uint8_t *fileData =
+ (uint8_t *)mmap(NULL, len, PROT_READ, MAP_SHARED, fd, 0);
+ if (fileData == MAP_FAILED) {
+ close(fd);
+ return NULL;
+ }
+
+ ObjectFile *fileObj = NULL;
+
+ // figure out what we have here
+ if ((fileObj = EcoffObject::tryFile(fname, fd, len, fileData)) != NULL) {
+ return fileObj;
+ }
+
+ if ((fileObj = AoutObject::tryFile(fname, fd, len, fileData)) != NULL) {
+ return fileObj;
+ }
+
+ if ((fileObj = ElfObject::tryFile(fname, fd, len, fileData)) != NULL) {
+ return fileObj;
+ }
+
+ // don't know what it is
+ close(fd);
+ munmap(fileData, len);
+ return NULL;
+}
diff --git a/src/base/loader/object_file.hh b/src/base/loader/object_file.hh
new file mode 100644
index 000000000..b43989cb5
--- /dev/null
+++ b/src/base/loader/object_file.hh
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2002-2004 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __OBJECT_FILE_HH__
+#define __OBJECT_FILE_HH__
+
+#include <limits>
+#include <string>
+
+#include "sim/host.hh" // for Addr
+
+class Port;
+class SymbolTable;
+
+class ObjectFile
+{
+ public:
+
+ enum Arch {
+ UnknownArch,
+ Alpha,
+ SPARC,
+ Mips
+ };
+
+ enum OpSys {
+ UnknownOpSys,
+ Tru64,
+ Linux,
+ Solaris
+ };
+
+ protected:
+ const std::string filename;
+ int descriptor;
+ uint8_t *fileData;
+ size_t len;
+
+ Arch arch;
+ OpSys opSys;
+
+ ObjectFile(const std::string &_filename, int _fd,
+ size_t _len, uint8_t *_data,
+ Arch _arch, OpSys _opSys);
+
+ public:
+ virtual ~ObjectFile();
+
+ void close();
+
+ virtual bool loadSections(Port *memPort, Addr addrMask =
+ std::numeric_limits<Addr>::max());
+ virtual bool loadGlobalSymbols(SymbolTable *symtab) = 0;
+ virtual bool loadLocalSymbols(SymbolTable *symtab) = 0;
+
+ Arch getArch() const { return arch; }
+ OpSys getOpSys() const { return opSys; }
+
+ protected:
+
+ struct Section {
+ Addr baseAddr;
+ uint8_t *fileImage;
+ size_t size;
+ };
+
+ Addr entry;
+ Addr globalPtr;
+
+ Section text;
+ 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; }
+ Addr dataBase() const { return data.baseAddr; }
+ Addr bssBase() const { return bss.baseAddr; }
+
+ size_t textSize() const { return text.size; }
+ size_t dataSize() const { return data.size; }
+ size_t bssSize() const { return bss.size; }
+};
+
+ObjectFile *createObjectFile(const std::string &fname);
+
+
+#endif // __OBJECT_FILE_HH__
diff --git a/base/loader/symtab.cc b/src/base/loader/symtab.cc
index 25f54f9bf..25f54f9bf 100644
--- a/base/loader/symtab.cc
+++ b/src/base/loader/symtab.cc
diff --git a/src/base/loader/symtab.hh b/src/base/loader/symtab.hh
new file mode 100644
index 000000000..931fd2cc2
--- /dev/null
+++ b/src/base/loader/symtab.hh
@@ -0,0 +1,173 @@
+/*
+ * 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 __SYMTAB_HH__
+#define __SYMTAB_HH__
+
+#include <iosfwd>
+#include <map>
+
+#include "sim/host.hh" // for Addr
+
+class Checkpoint;
+class SymbolTable
+{
+ public:
+ typedef std::map<Addr, std::string> ATable;
+ typedef std::map<std::string, Addr> STable;
+
+ private:
+ ATable addrTable;
+ STable symbolTable;
+
+ private:
+ bool
+ upperBound(Addr addr, ATable::const_iterator &iter) const
+ {
+ // find first key *larger* than desired address
+ iter = addrTable.upper_bound(addr);
+
+ // if very first key is larger, we're out of luck
+ if (iter == addrTable.begin())
+ return false;
+
+ return true;
+ }
+
+ public:
+ SymbolTable() {}
+ SymbolTable(const std::string &file) { load(file); }
+ ~SymbolTable() {}
+
+ void clear();
+ bool insert(Addr address, std::string symbol);
+ bool load(const std::string &file);
+
+ const ATable &getAddrTable() const { return addrTable; }
+ const STable &getSymbolTable() const { return symbolTable; }
+
+ public:
+ void serialize(const std::string &base, std::ostream &os);
+ void unserialize(const std::string &base, Checkpoint *cp,
+ const std::string &section);
+
+ public:
+ bool
+ findSymbol(Addr address, std::string &symbol) const
+ {
+ ATable::const_iterator i = addrTable.find(address);
+ if (i == addrTable.end())
+ return false;
+
+ symbol = (*i).second;
+ return true;
+ }
+
+ bool
+ findAddress(const std::string &symbol, Addr &address) const
+ {
+ STable::const_iterator i = symbolTable.find(symbol);
+ if (i == symbolTable.end())
+ return false;
+
+ address = (*i).second;
+ return true;
+ }
+
+ /// Find the nearest symbol equal to or less than the supplied
+ /// address (e.g., the label for the enclosing function).
+ /// @param address The address to look up.
+ /// @param symbol Return reference for symbol string.
+ /// @param sym_address Return reference for symbol address.
+ /// @param next_sym_address Address of following symbol (for
+ /// determining valid range of symbol).
+ /// @retval True if a symbol was found.
+ bool
+ findNearestSymbol(Addr addr, std::string &symbol, Addr &symaddr,
+ Addr &nextaddr) const
+ {
+ ATable::const_iterator i;
+ if (!upperBound(addr, i))
+ return false;
+
+ nextaddr = i->first;
+ --i;
+ symaddr = i->first;
+ symbol = i->second;
+ return true;
+ }
+
+ /// Overload for findNearestSymbol() for callers who don't care
+ /// about next_sym_address.
+ bool
+ findNearestSymbol(Addr addr, std::string &symbol, Addr &symaddr) const
+ {
+ ATable::const_iterator i;
+ if (!upperBound(addr, i))
+ return false;
+
+ --i;
+ symaddr = i->first;
+ symbol = i->second;
+ return true;
+ }
+
+
+ bool
+ findNearestAddr(Addr addr, Addr &symaddr, Addr &nextaddr) const
+ {
+ ATable::const_iterator i;
+ if (!upperBound(addr, i))
+ return false;
+
+ nextaddr = i->first;
+ --i;
+ symaddr = i->first;
+ return true;
+ }
+
+ bool
+ findNearestAddr(Addr addr, Addr &symaddr) const
+ {
+ ATable::const_iterator i;
+ if (!upperBound(addr, i))
+ return false;
+
+ --i;
+ symaddr = i->first;
+ return true;
+ }
+};
+
+/// Global unified debugging symbol table (for target). Conceptually
+/// there should be one of these per System object for full system,
+/// and per Process object for non-full-system, but so far one big
+/// global one has worked well enough.
+extern SymbolTable *debugSymbolTable;
+
+#endif // __SYMTAB_HH__
diff --git a/base/match.cc b/src/base/match.cc
index 4f1f49b57..4f1f49b57 100644
--- a/base/match.cc
+++ b/src/base/match.cc
diff --git a/base/match.hh b/src/base/match.hh
index 1b0a083a7..1b0a083a7 100644
--- a/base/match.hh
+++ b/src/base/match.hh
diff --git a/base/misc.cc b/src/base/misc.cc
index f3c86827b..f3c86827b 100644
--- a/base/misc.cc
+++ b/src/base/misc.cc
diff --git a/base/misc.hh b/src/base/misc.hh
index 9255c69c6..9255c69c6 100644
--- a/base/misc.hh
+++ b/src/base/misc.hh
diff --git a/base/mod_num.hh b/src/base/mod_num.hh
index fabbb56a9..fabbb56a9 100644
--- a/base/mod_num.hh
+++ b/src/base/mod_num.hh
diff --git a/base/mysql.cc b/src/base/mysql.cc
index c8d6e933a..c8d6e933a 100644
--- a/base/mysql.cc
+++ b/src/base/mysql.cc
diff --git a/base/mysql.hh b/src/base/mysql.hh
index ae28a9dfb..ae28a9dfb 100644
--- a/base/mysql.hh
+++ b/src/base/mysql.hh
diff --git a/base/output.cc b/src/base/output.cc
index 2b1733f21..2b1733f21 100644
--- a/base/output.cc
+++ b/src/base/output.cc
diff --git a/base/output.hh b/src/base/output.hh
index 3bbe73e3b..3bbe73e3b 100644
--- a/base/output.hh
+++ b/src/base/output.hh
diff --git a/base/pollevent.cc b/src/base/pollevent.cc
index 99044fc09..99044fc09 100644
--- a/base/pollevent.cc
+++ b/src/base/pollevent.cc
diff --git a/base/pollevent.hh b/src/base/pollevent.hh
index d39931797..d39931797 100644
--- a/base/pollevent.hh
+++ b/src/base/pollevent.hh
diff --git a/base/predictor.hh b/src/base/predictor.hh
index 37aa29989..37aa29989 100644
--- a/base/predictor.hh
+++ b/src/base/predictor.hh
diff --git a/base/random.cc b/src/base/random.cc
index 4aac14101..4aac14101 100644
--- a/base/random.cc
+++ b/src/base/random.cc
diff --git a/base/random.hh b/src/base/random.hh
index def7a4bce..def7a4bce 100644
--- a/base/random.hh
+++ b/src/base/random.hh
diff --git a/base/range.cc b/src/base/range.cc
index a4e50fc4f..a4e50fc4f 100644
--- a/base/range.cc
+++ b/src/base/range.cc
diff --git a/base/range.hh b/src/base/range.hh
index 4e3e0fd6e..4e3e0fd6e 100644
--- a/base/range.hh
+++ b/src/base/range.hh
diff --git a/base/refcnt.hh b/src/base/refcnt.hh
index de589f7c5..de589f7c5 100644
--- a/base/refcnt.hh
+++ b/src/base/refcnt.hh
diff --git a/src/base/remote_gdb.cc b/src/base/remote_gdb.cc
new file mode 100644
index 000000000..41d0c1471
--- /dev/null
+++ b/src/base/remote_gdb.cc
@@ -0,0 +1,1175 @@
+/*
+ * 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.
+ */
+
+/*
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Lawrence Berkeley Laboratories.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ * @(#)kgdb_stub.c 8.4 (Berkeley) 1/12/94
+ */
+
+/*-
+ * Copyright (c) 2001 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+/*
+ * $NetBSD: kgdb_stub.c,v 1.8 2001/07/07 22:58:00 wdk Exp $
+ *
+ * Taken from NetBSD
+ *
+ * "Stub" to allow remote cpu to debug over a serial line using gdb.
+ */
+
+#include <sys/signal.h>
+
+#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/physical.hh"
+#include "mem/port.hh"
+#include "sim/system.hh"
+
+using namespace std;
+using namespace TheISA;
+
+#ifndef NDEBUG
+vector<RemoteGDB *> debuggers;
+int current_debugger = -1;
+
+void
+debugger()
+{
+ if (current_debugger >= 0 && current_debugger < debuggers.size()) {
+ RemoteGDB *gdb = debuggers[current_debugger];
+ if (!gdb->isattached())
+ gdb->listener->accept();
+ if (gdb->isattached())
+ gdb->trap(ALPHA_KENTRY_IF);
+ }
+}
+#endif
+
+///////////////////////////////////////////////////////////
+//
+//
+//
+
+GDBListener::Event::Event(GDBListener *l, int fd, int e)
+ : PollEvent(fd, e), listener(l)
+{}
+
+void
+GDBListener::Event::process(int revent)
+{
+ listener->accept();
+}
+
+GDBListener::GDBListener(RemoteGDB *g, int p)
+ : event(NULL), gdb(g), port(p)
+{
+ assert(!gdb->listener);
+ gdb->listener = this;
+}
+
+GDBListener::~GDBListener()
+{
+ if (event)
+ delete event;
+}
+
+string
+GDBListener::name()
+{
+ return gdb->name() + ".listener";
+}
+
+void
+GDBListener::listen()
+{
+ while (!listener.listen(port, true)) {
+ DPRINTF(GDBMisc, "Can't bind port %d\n", port);
+ port++;
+ }
+
+ event = new Event(this, listener.getfd(), POLLIN);
+ pollQueue.schedule(event);
+
+#ifndef NDEBUG
+ gdb->number = debuggers.size();
+ debuggers.push_back(gdb);
+#endif
+
+#ifndef NDEBUG
+ ccprintf(cerr, "%d: %s: listening for remote gdb #%d on port %d\n",
+ curTick, name(), gdb->number, port);
+#else
+ ccprintf(cerr, "%d: %s: listening for remote gdb on port %d\n",
+ curTick, name(), port);
+#endif
+}
+
+void
+GDBListener::accept()
+{
+ if (!listener.islistening())
+ panic("GDBListener::accept(): cannot accept if we're not listening!");
+
+ int sfd = listener.accept(true);
+
+ if (sfd != -1) {
+ if (gdb->isattached())
+ close(sfd);
+ else
+ gdb->attach(sfd);
+ }
+}
+
+///////////////////////////////////////////////////////////
+//
+//
+//
+int digit2i(char);
+char i2digit(int);
+void mem2hex(void *, const void *, int);
+const char *hex2mem(void *, const char *, int);
+Addr hex2i(const char **);
+
+RemoteGDB::Event::Event(RemoteGDB *g, int fd, int e)
+ : PollEvent(fd, e), gdb(g)
+{}
+
+void
+RemoteGDB::Event::process(int revent)
+{
+ if (revent & POLLIN)
+ gdb->trap(ALPHA_KENTRY_IF);
+ else if (revent & POLLNVAL)
+ gdb->detach();
+}
+
+RemoteGDB::RemoteGDB(System *_system, ExecContext *c)
+ : event(NULL), listener(NULL), number(-1), fd(-1),
+ active(false), attached(false),
+ system(_system), pmem(_system->physmem), context(c)
+{
+ memset(gdbregs, 0, sizeof(gdbregs));
+}
+
+RemoteGDB::~RemoteGDB()
+{
+ if (event)
+ delete event;
+}
+
+string
+RemoteGDB::name()
+{
+ return system->name() + ".remote_gdb";
+}
+
+bool
+RemoteGDB::isattached()
+{ return attached; }
+
+void
+RemoteGDB::attach(int f)
+{
+ fd = f;
+
+ event = new Event(this, fd, POLLIN);
+ pollQueue.schedule(event);
+
+ attached = true;
+ DPRINTFN("remote gdb attached\n");
+}
+
+void
+RemoteGDB::detach()
+{
+ attached = false;
+ close(fd);
+ fd = -1;
+
+ pollQueue.remove(event);
+ DPRINTFN("remote gdb detached\n");
+}
+
+const char *
+gdb_command(char cmd)
+{
+ switch (cmd) {
+ case KGDB_SIGNAL: return "KGDB_SIGNAL";
+ case KGDB_SET_BAUD: return "KGDB_SET_BAUD";
+ case KGDB_SET_BREAK: return "KGDB_SET_BREAK";
+ case KGDB_CONT: return "KGDB_CONT";
+ case KGDB_ASYNC_CONT: return "KGDB_ASYNC_CONT";
+ case KGDB_DEBUG: return "KGDB_DEBUG";
+ case KGDB_DETACH: return "KGDB_DETACH";
+ case KGDB_REG_R: return "KGDB_REG_R";
+ case KGDB_REG_W: return "KGDB_REG_W";
+ case KGDB_SET_THREAD: return "KGDB_SET_THREAD";
+ case KGDB_CYCLE_STEP: return "KGDB_CYCLE_STEP";
+ case KGDB_SIG_CYCLE_STEP: return "KGDB_SIG_CYCLE_STEP";
+ case KGDB_KILL: return "KGDB_KILL";
+ case KGDB_MEM_W: return "KGDB_MEM_W";
+ case KGDB_MEM_R: return "KGDB_MEM_R";
+ case KGDB_SET_REG: return "KGDB_SET_REG";
+ case KGDB_READ_REG: return "KGDB_READ_REG";
+ case KGDB_QUERY_VAR: return "KGDB_QUERY_VAR";
+ case KGDB_SET_VAR: return "KGDB_SET_VAR";
+ case KGDB_RESET: return "KGDB_RESET";
+ case KGDB_STEP: return "KGDB_STEP";
+ case KGDB_ASYNC_STEP: return "KGDB_ASYNC_STEP";
+ case KGDB_THREAD_ALIVE: return "KGDB_THREAD_ALIVE";
+ case KGDB_TARGET_EXIT: return "KGDB_TARGET_EXIT";
+ case KGDB_BINARY_DLOAD: return "KGDB_BINARY_DLOAD";
+ case KGDB_CLR_HW_BKPT: return "KGDB_CLR_HW_BKPT";
+ case KGDB_SET_HW_BKPT: return "KGDB_SET_HW_BKPT";
+ case KGDB_START: return "KGDB_START";
+ case KGDB_END: return "KGDB_END";
+ case KGDB_GOODP: return "KGDB_GOODP";
+ case KGDB_BADP: return "KGDB_BADP";
+ default: return "KGDB_UNKNOWN";
+ }
+}
+
+///////////////////////////////////////////////////////////
+// RemoteGDB::acc
+//
+// Determine if the mapping at va..(va+len) is valid.
+//
+bool
+RemoteGDB::acc(Addr va, size_t len)
+{
+ Addr last_va;
+
+ va = TheISA::TruncPage(va);
+ last_va = TheISA::RoundPage(va + len);
+
+ do {
+ if (TheISA::IsK0Seg(va)) {
+ if (va < (TheISA::K0SegBase + pmem->size())) {
+ DPRINTF(GDBAcc, "acc: Mapping is valid K0SEG <= "
+ "%#x < K0SEG + size\n", va);
+ return true;
+ } else {
+ DPRINTF(GDBAcc, "acc: Mapping invalid %#x > K0SEG + size\n",
+ va);
+ return false;
+ }
+ }
+
+ /**
+ * This code says that all accesses to palcode (instruction and data)
+ * are valid since there isn't a va->pa mapping because palcode is
+ * accessed physically. At some point this should probably be cleaned up
+ * but there is no easy way to do it.
+ */
+
+ if (AlphaISA::PcPAL(va) || va < 0x10000)
+ return true;
+
+ Addr ptbr = context->readMiscReg(AlphaISA::IPR_PALtemp20);
+ 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;
+ }
+ va += TheISA::PageBytes;
+ } while (va < last_va);
+
+ DPRINTF(GDBAcc, "acc: %#x mapping is valid\n", va);
+ return true;
+}
+
+///////////////////////////////////////////////////////////
+// RemoteGDB::signal
+//
+// Translate a trap number into a Unix-compatible signal number.
+// (GDB only understands Unix signal numbers.)
+//
+int
+RemoteGDB::signal(int type)
+{
+ switch (type) {
+ case ALPHA_KENTRY_INT:
+ return (SIGTRAP);
+
+ case ALPHA_KENTRY_UNA:
+ return (SIGBUS);
+
+ case ALPHA_KENTRY_ARITH:
+ return (SIGFPE);
+
+ case ALPHA_KENTRY_IF:
+ return (SIGILL);
+
+ case ALPHA_KENTRY_MM:
+ return (SIGSEGV);
+
+ default:
+ panic("unknown signal type");
+ return 0;
+ }
+}
+
+///////////////////////////////////////////////////////////
+// RemoteGDB::getregs
+//
+// Translate the kernel debugger register format into
+// the GDB register format.
+void
+RemoteGDB::getregs()
+{
+ memset(gdbregs, 0, sizeof(gdbregs));
+
+ gdbregs[KGDB_REG_PC] = context->readPC();
+
+ // @todo: Currently this is very Alpha specific.
+ if (AlphaISA::PcPAL(gdbregs[KGDB_REG_PC])) {
+ for (int i = 0; i < TheISA::NumIntArchRegs; ++i) {
+ gdbregs[i] = context->readIntReg(AlphaISA::reg_redir[i]);
+ }
+ } else {
+ for (int i = 0; i < TheISA::NumIntArchRegs; ++i) {
+ gdbregs[i] = context->readIntReg(i);
+ }
+ }
+
+#ifdef KGDB_FP_REGS
+ for (int i = 0; i < TheISA::NumFloatArchRegs; ++i) {
+ gdbregs[i + KGDB_REG_F0] = context->readFloatRegBits(i);
+ }
+#endif
+}
+
+///////////////////////////////////////////////////////////
+// RemoteGDB::setregs
+//
+// Translate the GDB register format into the kernel
+// debugger register format.
+//
+void
+RemoteGDB::setregs()
+{
+ // @todo: Currently this is very Alpha specific.
+ if (AlphaISA::PcPAL(gdbregs[KGDB_REG_PC])) {
+ for (int i = 0; i < TheISA::NumIntArchRegs; ++i) {
+ context->setIntReg(AlphaISA::reg_redir[i], gdbregs[i]);
+ }
+ } else {
+ for (int i = 0; i < TheISA::NumIntArchRegs; ++i) {
+ context->setIntReg(i, gdbregs[i]);
+ }
+ }
+
+#ifdef KGDB_FP_REGS
+ for (int i = 0; i < TheISA::NumFloatArchRegs; ++i) {
+ context->setFloatRegBits(i, gdbregs[i + KGDB_REG_F0]);
+ }
+#endif
+ context->setPC(gdbregs[KGDB_REG_PC]);
+}
+
+void
+RemoteGDB::setTempBreakpoint(TempBreakpoint &bkpt, Addr addr)
+{
+ DPRINTF(GDBMisc, "setTempBreakpoint: addr=%#x\n", addr);
+
+ bkpt.address = addr;
+ insertHardBreak(addr, 4);
+}
+
+void
+RemoteGDB::clearTempBreakpoint(TempBreakpoint &bkpt)
+{
+ DPRINTF(GDBMisc, "setTempBreakpoint: addr=%#x\n",
+ bkpt.address);
+
+
+ removeHardBreak(bkpt.address, 4);
+ bkpt.address = 0;
+}
+
+void
+RemoteGDB::clearSingleStep()
+{
+ DPRINTF(GDBMisc, "clearSingleStep bt_addr=%#x nt_addr=%#x\n",
+ takenBkpt.address, notTakenBkpt.address);
+
+ if (takenBkpt.address != 0)
+ clearTempBreakpoint(takenBkpt);
+
+ if (notTakenBkpt.address != 0)
+ clearTempBreakpoint(notTakenBkpt);
+}
+
+void
+RemoteGDB::setSingleStep()
+{
+ Addr pc = context->readPC();
+ Addr npc, bpc;
+ bool set_bt = false;
+
+ npc = pc + sizeof(MachInst);
+
+ // User was stopped at pc, e.g. the instruction at pc was not
+ // executed.
+ MachInst inst = read<MachInst>(pc);
+ StaticInstPtr si(inst);
+ if (si->hasBranchTarget(pc, context, bpc)) {
+ // Don't bother setting a breakpoint on the taken branch if it
+ // is the same as the next pc
+ if (bpc != npc)
+ set_bt = true;
+ }
+
+ DPRINTF(GDBMisc, "setSingleStep bt_addr=%#x nt_addr=%#x\n",
+ takenBkpt.address, notTakenBkpt.address);
+
+ setTempBreakpoint(notTakenBkpt, npc);
+
+ if (set_bt)
+ setTempBreakpoint(takenBkpt, bpc);
+}
+
+/////////////////////////
+//
+//
+
+uint8_t
+RemoteGDB::getbyte()
+{
+ uint8_t b;
+ ::read(fd, &b, 1);
+ return b;
+}
+
+void
+RemoteGDB::putbyte(uint8_t b)
+{
+ ::write(fd, &b, 1);
+}
+
+// Send a packet to gdb
+void
+RemoteGDB::send(const char *bp)
+{
+ const char *p;
+ uint8_t csum, c;
+
+ DPRINTF(GDBSend, "send: %s\n", bp);
+
+ do {
+ p = bp;
+ putbyte(KGDB_START);
+ for (csum = 0; (c = *p); p++) {
+ putbyte(c);
+ csum += c;
+ }
+ putbyte(KGDB_END);
+ putbyte(i2digit(csum >> 4));
+ putbyte(i2digit(csum));
+ } while ((c = getbyte() & 0x7f) == KGDB_BADP);
+}
+
+// Receive a packet from gdb
+int
+RemoteGDB::recv(char *bp, int maxlen)
+{
+ char *p;
+ int c, csum;
+ int len;
+
+ do {
+ p = bp;
+ csum = len = 0;
+ while ((c = getbyte()) != KGDB_START)
+ ;
+
+ while ((c = getbyte()) != KGDB_END && len < maxlen) {
+ c &= 0x7f;
+ csum += c;
+ *p++ = c;
+ len++;
+ }
+ csum &= 0xff;
+ *p = '\0';
+
+ if (len >= maxlen) {
+ putbyte(KGDB_BADP);
+ continue;
+ }
+
+ csum -= digit2i(getbyte()) * 16;
+ csum -= digit2i(getbyte());
+
+ if (csum == 0) {
+ putbyte(KGDB_GOODP);
+ // Sequence present?
+ if (bp[2] == ':') {
+ putbyte(bp[0]);
+ putbyte(bp[1]);
+ len -= 3;
+ bcopy(bp + 3, bp, len);
+ }
+ break;
+ }
+ putbyte(KGDB_BADP);
+ } while (1);
+
+ DPRINTF(GDBRecv, "recv: %s: %s\n", gdb_command(*bp), bp);
+
+ return (len);
+}
+
+// Read bytes from kernel address space for debugger.
+bool
+RemoteGDB::read(Addr vaddr, size_t size, char *data)
+{
+ static Addr lastaddr = 0;
+ static size_t lastsize = 0;
+
+ if (vaddr < 10) {
+ DPRINTF(GDBRead, "read: reading memory location zero!\n");
+ vaddr = lastaddr + lastsize;
+ }
+
+ DPRINTF(GDBRead, "read: addr=%#x, size=%d", vaddr, size);
+
+ context->getVirtPort(context)->readBlob(vaddr, (uint8_t*)data, size);
+
+#if TRACING_ON
+ if (DTRACE(GDBRead)) {
+ if (DTRACE(GDBExtra)) {
+ char buf[1024];
+ mem2hex(buf, data, size);
+ DPRINTFNR(": %s\n", buf);
+ } else
+ DPRINTFNR("\n");
+ }
+#endif
+
+ return true;
+}
+
+// Write bytes to kernel address space for debugger.
+bool
+RemoteGDB::write(Addr vaddr, size_t size, const char *data)
+{
+ static Addr lastaddr = 0;
+ static size_t lastsize = 0;
+
+ if (vaddr < 10) {
+ DPRINTF(GDBWrite, "write: writing memory location zero!\n");
+ vaddr = lastaddr + lastsize;
+ }
+
+ if (DTRACE(GDBWrite)) {
+ DPRINTFN("write: addr=%#x, size=%d", vaddr, size);
+ if (DTRACE(GDBExtra)) {
+ char buf[1024];
+ mem2hex(buf, data, size);
+ DPRINTFNR(": %s\n", buf);
+ } else
+ DPRINTFNR("\n");
+ }
+
+ context->getVirtPort(context)->writeBlob(vaddr, (uint8_t*)data, size);
+
+#ifdef IMB
+ alpha_pal_imb();
+#endif
+
+ return true;
+}
+
+
+PCEventQueue *RemoteGDB::getPcEventQueue()
+{
+ return &system->pcEventQueue;
+}
+
+
+RemoteGDB::HardBreakpoint::HardBreakpoint(RemoteGDB *_gdb, Addr pc)
+ : PCEvent(_gdb->getPcEventQueue(), "HardBreakpoint Event", pc),
+ gdb(_gdb), refcount(0)
+{
+ DPRINTF(GDBMisc, "creating hardware breakpoint at %#x\n", evpc);
+}
+
+void
+RemoteGDB::HardBreakpoint::process(ExecContext *xc)
+{
+ DPRINTF(GDBMisc, "handling hardware breakpoint at %#x\n", pc());
+
+ if (xc == gdb->context)
+ gdb->trap(ALPHA_KENTRY_INT);
+}
+
+bool
+RemoteGDB::insertSoftBreak(Addr addr, size_t len)
+{
+ if (len != sizeof(MachInst))
+ panic("invalid length\n");
+
+ return insertHardBreak(addr, len);
+}
+
+bool
+RemoteGDB::removeSoftBreak(Addr addr, size_t len)
+{
+ if (len != sizeof(MachInst))
+ panic("invalid length\n");
+
+ return removeHardBreak(addr, len);
+}
+
+bool
+RemoteGDB::insertHardBreak(Addr addr, size_t len)
+{
+ if (len != sizeof(MachInst))
+ panic("invalid length\n");
+
+ DPRINTF(GDBMisc, "inserting hardware breakpoint at %#x\n", addr);
+
+ HardBreakpoint *&bkpt = hardBreakMap[addr];
+ if (bkpt == 0)
+ bkpt = new HardBreakpoint(this, addr);
+
+ bkpt->refcount++;
+
+ return true;
+}
+
+bool
+RemoteGDB::removeHardBreak(Addr addr, size_t len)
+{
+ if (len != sizeof(MachInst))
+ panic("invalid length\n");
+
+ DPRINTF(GDBMisc, "removing hardware breakpoint at %#x\n", addr);
+
+ break_iter_t i = hardBreakMap.find(addr);
+ if (i == hardBreakMap.end())
+ return false;
+
+ HardBreakpoint *hbp = (*i).second;
+ if (--hbp->refcount == 0) {
+ delete hbp;
+ hardBreakMap.erase(i);
+ }
+
+ return true;
+}
+
+const char *
+break_type(char c)
+{
+ switch(c) {
+ case '0': return "software breakpoint";
+ case '1': return "hardware breakpoint";
+ case '2': return "write watchpoint";
+ case '3': return "read watchpoint";
+ case '4': return "access watchpoint";
+ default: return "unknown breakpoint/watchpoint";
+ }
+}
+
+// This function does all command processing for interfacing to a
+// remote gdb. Note that the error codes are ignored by gdb at
+// present, but might eventually become meaningful. (XXX) It might
+// makes sense to use POSIX errno values, because that is what the
+// gdb/remote.c functions want to return.
+bool
+RemoteGDB::trap(int type)
+{
+ uint64_t val;
+ size_t datalen, len;
+ char data[KGDB_BUFLEN + 1];
+ char buffer[sizeof(gdbregs) * 2 + 256];
+ char temp[KGDB_BUFLEN];
+ const char *p;
+ char command, subcmd;
+ string var;
+ bool ret;
+
+ if (!attached)
+ return false;
+
+ DPRINTF(GDBMisc, "trap: PC=%#x NPC=%#x\n",
+ context->readPC(), context->readNextPC());
+
+ clearSingleStep();
+
+ /*
+ * The first entry to this function is normally through
+ * a breakpoint trap in kgdb_connect(), in which case we
+ * must advance past the breakpoint because gdb will not.
+ *
+ * On the first entry here, we expect that gdb is not yet
+ * listening to us, so just enter the interaction loop.
+ * After the debugger is "active" (connected) it will be
+ * waiting for a "signaled" message from us.
+ */
+ if (!active)
+ active = true;
+ else
+ // Tell remote host that an exception has occurred.
+ snprintf((char *)buffer, sizeof(buffer), "S%02x", signal(type));
+ send(buffer);
+
+ // Stick frame regs into our reg cache.
+ getregs();
+
+ for (;;) {
+ datalen = recv(data, sizeof(data));
+ data[sizeof(data) - 1] = 0; // Sentinel
+ command = data[0];
+ subcmd = 0;
+ p = data + 1;
+ switch (command) {
+
+ case KGDB_SIGNAL:
+ // if this command came from a running gdb, answer it --
+ // the other guy has no way of knowing if we're in or out
+ // of this loop when he issues a "remote-signal".
+ snprintf((char *)buffer, sizeof(buffer), "S%02x", signal(type));
+ send(buffer);
+ continue;
+
+ case KGDB_REG_R:
+ if (2 * sizeof(gdbregs) > sizeof(buffer))
+ panic("buffer too small");
+
+ mem2hex(buffer, gdbregs, sizeof(gdbregs));
+ send(buffer);
+ continue;
+
+ case KGDB_REG_W:
+ p = hex2mem(gdbregs, p, sizeof(gdbregs));
+ if (p == NULL || *p != '\0')
+ send("E01");
+ else {
+ setregs();
+ send("OK");
+ }
+ continue;
+
+#if 0
+ case KGDB_SET_REG:
+ val = hex2i(&p);
+ if (*p++ != '=') {
+ send("E01");
+ continue;
+ }
+ if (val < 0 && val >= KGDB_NUMREGS) {
+ send("E01");
+ continue;
+ }
+
+ gdbregs[val] = hex2i(&p);
+ setregs();
+ send("OK");
+
+ continue;
+#endif
+
+ case KGDB_MEM_R:
+ val = hex2i(&p);
+ if (*p++ != ',') {
+ send("E02");
+ continue;
+ }
+ len = hex2i(&p);
+ if (*p != '\0') {
+ send("E03");
+ continue;
+ }
+ if (len > sizeof(buffer)) {
+ send("E04");
+ continue;
+ }
+ if (!acc(val, len)) {
+ send("E05");
+ continue;
+ }
+
+ if (read(val, (size_t)len, (char *)buffer)) {
+ mem2hex(temp, buffer, len);
+ send(temp);
+ } else {
+ send("E05");
+ }
+ continue;
+
+ case KGDB_MEM_W:
+ val = hex2i(&p);
+ if (*p++ != ',') {
+ send("E06");
+ continue;
+ }
+ len = hex2i(&p);
+ if (*p++ != ':') {
+ send("E07");
+ continue;
+ }
+ if (len > datalen - (p - data)) {
+ send("E08");
+ continue;
+ }
+ p = hex2mem(buffer, p, sizeof(buffer));
+ if (p == NULL) {
+ send("E09");
+ continue;
+ }
+ if (!acc(val, len)) {
+ send("E0A");
+ continue;
+ }
+ if (write(val, (size_t)len, (char *)buffer))
+ send("OK");
+ else
+ send("E0B");
+ continue;
+
+ case KGDB_SET_THREAD:
+ subcmd = *p++;
+ val = hex2i(&p);
+ if (val == 0)
+ send("OK");
+ else
+ send("E01");
+ continue;
+
+ case KGDB_DETACH:
+ case KGDB_KILL:
+ active = false;
+ clearSingleStep();
+ detach();
+ goto out;
+
+ case KGDB_ASYNC_CONT:
+ subcmd = hex2i(&p);
+ if (*p++ == ';') {
+ val = hex2i(&p);
+ context->setPC(val);
+ context->setNextPC(val + sizeof(MachInst));
+ }
+ clearSingleStep();
+ goto out;
+
+ case KGDB_CONT:
+ if (p - data < datalen) {
+ val = hex2i(&p);
+ context->setPC(val);
+ context->setNextPC(val + sizeof(MachInst));
+ }
+ clearSingleStep();
+ goto out;
+
+ case KGDB_ASYNC_STEP:
+ subcmd = hex2i(&p);
+ if (*p++ == ';') {
+ val = hex2i(&p);
+ context->setPC(val);
+ context->setNextPC(val + sizeof(MachInst));
+ }
+ setSingleStep();
+ goto out;
+
+ case KGDB_STEP:
+ if (p - data < datalen) {
+ val = hex2i(&p);
+ context->setPC(val);
+ context->setNextPC(val + sizeof(MachInst));
+ }
+ setSingleStep();
+ goto out;
+
+ case KGDB_CLR_HW_BKPT:
+ subcmd = *p++;
+ if (*p++ != ',') send("E0D");
+ val = hex2i(&p);
+ if (*p++ != ',') send("E0D");
+ len = hex2i(&p);
+
+ DPRINTF(GDBMisc, "clear %s, addr=%#x, len=%d\n",
+ break_type(subcmd), val, len);
+
+ ret = false;
+
+ switch (subcmd) {
+ case '0': // software breakpoint
+ ret = removeSoftBreak(val, len);
+ break;
+
+ case '1': // hardware breakpoint
+ ret = removeHardBreak(val, len);
+ break;
+
+ case '2': // write watchpoint
+ case '3': // read watchpoint
+ case '4': // access watchpoint
+ default: // unknown
+ send("");
+ break;
+ }
+
+ send(ret ? "OK" : "E0C");
+ continue;
+
+ case KGDB_SET_HW_BKPT:
+ subcmd = *p++;
+ if (*p++ != ',') send("E0D");
+ val = hex2i(&p);
+ if (*p++ != ',') send("E0D");
+ len = hex2i(&p);
+
+ DPRINTF(GDBMisc, "set %s, addr=%#x, len=%d\n",
+ break_type(subcmd), val, len);
+
+ ret = false;
+
+ switch (subcmd) {
+ case '0': // software breakpoint
+ ret = insertSoftBreak(val, len);
+ break;
+
+ case '1': // hardware breakpoint
+ ret = insertHardBreak(val, len);
+ break;
+
+ case '2': // write watchpoint
+ case '3': // read watchpoint
+ case '4': // access watchpoint
+ default: // unknown
+ send("");
+ break;
+ }
+
+ send(ret ? "OK" : "E0C");
+ continue;
+
+ case KGDB_QUERY_VAR:
+ var = string(p, datalen - 1);
+ if (var == "C")
+ send("QC0");
+ else
+ send("");
+ continue;
+
+ case KGDB_SET_BAUD:
+ case KGDB_SET_BREAK:
+ case KGDB_DEBUG:
+ case KGDB_CYCLE_STEP:
+ case KGDB_SIG_CYCLE_STEP:
+ case KGDB_READ_REG:
+ case KGDB_SET_VAR:
+ case KGDB_RESET:
+ case KGDB_THREAD_ALIVE:
+ case KGDB_TARGET_EXIT:
+ case KGDB_BINARY_DLOAD:
+ // Unsupported command
+ DPRINTF(GDBMisc, "Unsupported command: %s\n",
+ gdb_command(command));
+ DDUMP(GDBMisc, (uint8_t *)data, datalen);
+ send("");
+ continue;
+
+ default:
+ // Unknown command.
+ DPRINTF(GDBMisc, "Unknown command: %c(%#x)\n",
+ command, command);
+ send("");
+ continue;
+
+
+ }
+ }
+
+ out:
+ return true;
+}
+
+// Convert a hex digit into an integer.
+// This returns -1 if the argument passed is no valid hex digit.
+int
+digit2i(char c)
+{
+ if (c >= '0' && c <= '9')
+ return (c - '0');
+ else if (c >= 'a' && c <= 'f')
+ return (c - 'a' + 10);
+ else if (c >= 'A' && c <= 'F')
+
+ return (c - 'A' + 10);
+ else
+ return (-1);
+}
+
+// Convert the low 4 bits of an integer into an hex digit.
+char
+i2digit(int n)
+{
+ return ("0123456789abcdef"[n & 0x0f]);
+}
+
+// Convert a byte array into an hex string.
+void
+mem2hex(void *vdst, const void *vsrc, int len)
+{
+ char *dst = (char *)vdst;
+ const char *src = (const char *)vsrc;
+
+ while (len--) {
+ *dst++ = i2digit(*src >> 4);
+ *dst++ = i2digit(*src++);
+ }
+ *dst = '\0';
+}
+
+// Convert an hex string into a byte array.
+// This returns a pointer to the character following the last valid
+// hex digit. If the string ends in the middle of a byte, NULL is
+// returned.
+const char *
+hex2mem(void *vdst, const char *src, int maxlen)
+{
+ char *dst = (char *)vdst;
+ int msb, lsb;
+
+ while (*src && maxlen--) {
+ msb = digit2i(*src++);
+ if (msb < 0)
+ return (src - 1);
+ lsb = digit2i(*src++);
+ if (lsb < 0)
+ return (NULL);
+ *dst++ = (msb << 4) | lsb;
+ }
+ return (src);
+}
+
+// Convert an hex string into an integer.
+// This returns a pointer to the character following the last valid
+// hex digit.
+Addr
+hex2i(const char **srcp)
+{
+ const char *src = *srcp;
+ Addr r = 0;
+ int nibble;
+
+ while ((nibble = digit2i(*src)) >= 0) {
+ r *= 16;
+ r += nibble;
+ src++;
+ }
+ *srcp = src;
+ return (r);
+}
+
diff --git a/base/remote_gdb.hh b/src/base/remote_gdb.hh
index b7abf5116..b7abf5116 100644
--- a/base/remote_gdb.hh
+++ b/src/base/remote_gdb.hh
diff --git a/base/res_list.hh b/src/base/res_list.hh
index 960ed108e..960ed108e 100644
--- a/base/res_list.hh
+++ b/src/base/res_list.hh
diff --git a/base/sat_counter.cc b/src/base/sat_counter.cc
index 7920f6c81..7920f6c81 100644
--- a/base/sat_counter.cc
+++ b/src/base/sat_counter.cc
diff --git a/base/sat_counter.hh b/src/base/sat_counter.hh
index d7be17b6f..d7be17b6f 100644
--- a/base/sat_counter.hh
+++ b/src/base/sat_counter.hh
diff --git a/base/sched_list.hh b/src/base/sched_list.hh
index f794e3514..f794e3514 100644
--- a/base/sched_list.hh
+++ b/src/base/sched_list.hh
diff --git a/base/socket.cc b/src/base/socket.cc
index 45a60e7e3..45a60e7e3 100644
--- a/base/socket.cc
+++ b/src/base/socket.cc
diff --git a/base/socket.hh b/src/base/socket.hh
index 848405c09..848405c09 100644
--- a/base/socket.hh
+++ b/src/base/socket.hh
diff --git a/src/base/statistics.cc b/src/base/statistics.cc
new file mode 100644
index 000000000..20de46347
--- /dev/null
+++ b/src/base/statistics.cc
@@ -0,0 +1,356 @@
+/*
+ * 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 <iomanip>
+#include <fstream>
+#include <list>
+#include <map>
+#include <string>
+
+#include "base/callback.hh"
+#include "base/cprintf.hh"
+#include "base/hostinfo.hh"
+#include "base/misc.hh"
+#include "base/statistics.hh"
+#include "base/str.hh"
+#include "base/time.hh"
+#include "base/trace.hh"
+#include "base/stats/statdb.hh"
+#include "config/stats_binning.hh"
+
+using namespace std;
+
+namespace Stats {
+
+StatData *
+DataAccess::find() const
+{
+ return Database::find(const_cast<void *>((const void *)this));
+}
+
+const StatData *
+getStatData(const void *stat)
+{
+ return Database::find(const_cast<void *>(stat));
+}
+
+void
+DataAccess::map(StatData *data)
+{
+ Database::regStat(this, data);
+}
+
+StatData *
+DataAccess::statData()
+{
+ StatData *ptr = find();
+ assert(ptr);
+ return ptr;
+}
+
+const StatData *
+DataAccess::statData() const
+{
+ const StatData *ptr = find();
+ assert(ptr);
+ return ptr;
+}
+
+void
+DataAccess::setInit()
+{
+ statData()->flags |= init;
+}
+
+void
+DataAccess::setPrint()
+{
+ Database::regPrint(this);
+}
+
+StatData::StatData()
+ : flags(none), precision(-1), prereq(0)
+{
+ static int count = 0;
+ id = count++;
+}
+
+StatData::~StatData()
+{
+}
+
+bool
+StatData::less(StatData *stat1, StatData *stat2)
+{
+ const string &name1 = stat1->name;
+ const string &name2 = stat2->name;
+
+ vector<string> v1;
+ vector<string> v2;
+
+ tokenize(v1, name1, '.');
+ tokenize(v2, name2, '.');
+
+ int last = min(v1.size(), v2.size()) - 1;
+ for (int i = 0; i < last; ++i)
+ if (v1[i] != v2[i])
+ return v1[i] < v2[i];
+
+ // Special compare for last element.
+ if (v1[last] == v2[last])
+ return v1.size() < v2.size();
+ else
+ return v1[last] < v2[last];
+
+ return false;
+}
+
+bool
+StatData::baseCheck() const
+{
+ if (!(flags & init)) {
+#ifdef DEBUG
+ cprintf("this is stat number %d\n", id);
+#endif
+ panic("Not all stats have been initialized");
+ return false;
+ }
+
+ if ((flags & print) && name.empty()) {
+ panic("all printable stats must be named");
+ return false;
+ }
+
+ return true;
+}
+
+
+void
+FormulaBase::result(VResult &vec) const
+{
+ if (root)
+ vec = root->result();
+}
+
+Result
+FormulaBase::total() const
+{
+ return root ? root->total() : 0.0;
+}
+
+size_t
+FormulaBase::size() const
+{
+ if (!root)
+ return 0;
+ else
+ return root->size();
+}
+
+bool
+FormulaBase::binned() const
+{
+ return root && root->binned();
+}
+
+void
+FormulaBase::reset()
+{
+}
+
+bool
+FormulaBase::zero() const
+{
+ VResult vec;
+ result(vec);
+ for (int i = 0; i < vec.size(); ++i)
+ if (vec[i] != 0.0)
+ return false;
+ return true;
+}
+
+void
+FormulaBase::update(StatData *)
+{
+}
+
+string
+FormulaBase::str() const
+{
+ return root ? root->str() : "";
+}
+
+Formula::Formula()
+{
+ setInit();
+}
+
+Formula::Formula(Temp r)
+{
+ root = r;
+ assert(size());
+}
+
+const Formula &
+Formula::operator=(Temp r)
+{
+ assert(!root && "Can't change formulas");
+ root = r;
+ assert(size());
+ return *this;
+}
+
+const Formula &
+Formula::operator+=(Temp r)
+{
+ if (root)
+ root = NodePtr(new BinaryNode<std::plus<Result> >(root, r));
+ else
+ root = r;
+ assert(size());
+ return *this;
+}
+
+MainBin::MainBin(const string &name)
+ : _name(name), mem(NULL), memsize(-1)
+{
+ Database::regBin(this, name);
+}
+
+MainBin::~MainBin()
+{
+ if (mem)
+ delete [] mem;
+}
+
+char *
+MainBin::memory(off_t off)
+{
+ if (memsize == -1)
+ memsize = ceilPow2((size_t) offset());
+
+ if (!mem) {
+ mem = new char[memsize];
+ memset(mem, 0, memsize);
+ }
+
+ assert(offset() <= size());
+ return mem + off;
+}
+
+void
+check()
+{
+ typedef Database::stat_list_t::iterator iter_t;
+
+ iter_t i, end = Database::stats().end();
+ for (i = Database::stats().begin(); i != end; ++i) {
+ StatData *data = *i;
+ assert(data);
+ if (!data->check() || !data->baseCheck())
+ panic("stat check failed for %s\n", data->name);
+ }
+
+ int j = 0;
+ for (i = Database::stats().begin(); i != end; ++i) {
+ StatData *data = *i;
+ if (!(data->flags & print))
+ data->name = "__Stat" + to_string(j++);
+ }
+
+ Database::stats().sort(StatData::less);
+
+#if STATS_BINNING
+ if (MainBin::curBin() == NULL) {
+ static MainBin mainBin("main bin");
+ mainBin.activate();
+ }
+#endif
+
+ if (i == end)
+ return;
+
+ iter_t last = i;
+ ++i;
+
+ for (i = Database::stats().begin(); i != end; ++i) {
+ if ((*i)->name == (*last)->name)
+ panic("same name used twice! name=%s\n", (*i)->name);
+
+ last = i;
+ }
+}
+
+CallbackQueue resetQueue;
+
+void
+reset()
+{
+ // reset non-binned stats
+ Database::stat_list_t::iterator i = Database::stats().begin();
+ Database::stat_list_t::iterator end = Database::stats().end();
+ while (i != end) {
+ StatData *data = *i;
+ if (!data->binned())
+ data->reset();
+ ++i;
+ }
+
+ // save the bin so we can go back to where we were
+ MainBin *orig = MainBin::curBin();
+
+ // reset binned stats
+ Database::bin_list_t::iterator bi = Database::bins().begin();
+ Database::bin_list_t::iterator be = Database::bins().end();
+ while (bi != be) {
+ MainBin *bin = *bi;
+ bin->activate();
+
+ i = Database::stats().begin();
+ while (i != end) {
+ StatData *data = *i;
+ if (data->binned())
+ data->reset();
+ ++i;
+ }
+ ++bi;
+ }
+
+ // restore bin
+ MainBin::curBin() = orig;
+
+ resetQueue.process();
+}
+
+void
+registerResetCallback(Callback *cb)
+{
+ resetQueue.add(cb);
+}
+
+/* namespace Stats */ }
diff --git a/src/base/statistics.hh b/src/base/statistics.hh
new file mode 100644
index 000000000..dd507c091
--- /dev/null
+++ b/src/base/statistics.hh
@@ -0,0 +1,2896 @@
+/*
+ * 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.
+ */
+
+/** @file
+ * Declaration of Statistics objects.
+ */
+
+/**
+* @todo
+*
+* Generalized N-dimensinal vector
+* documentation
+* key stats
+* interval stats
+* -- these both can use the same function that prints out a
+* specific set of stats
+* VectorStandardDeviation totals
+* Document Namespaces
+*/
+#ifndef __BASE_STATISTICS_HH__
+#define __BASE_STATISTICS_HH__
+
+#include <algorithm>
+#include <cassert>
+#include <cmath>
+#include <functional>
+#include <iosfwd>
+#include <string>
+#include <vector>
+
+#include "base/cprintf.hh"
+#include "base/intmath.hh"
+#include "base/refcnt.hh"
+#include "base/str.hh"
+#include "base/stats/bin.hh"
+#include "base/stats/flags.hh"
+#include "base/stats/visit.hh"
+#include "base/stats/types.hh"
+#include "config/stats_binning.hh"
+#include "sim/host.hh"
+
+class Callback;
+
+/** The current simulated cycle. */
+extern Tick curTick;
+
+/* A namespace for all of the Statistics */
+namespace Stats {
+
+/* Contains the statistic implementation details */
+//////////////////////////////////////////////////////////////////////
+//
+// Statistics Framework Base classes
+//
+//////////////////////////////////////////////////////////////////////
+struct StatData
+{
+ /** The name of the stat. */
+ std::string name;
+ /** The description of the stat. */
+ std::string desc;
+ /** The formatting flags. */
+ StatFlags flags;
+ /** The display precision. */
+ int precision;
+ /** A pointer to a prerequisite Stat. */
+ const StatData *prereq;
+ /**
+ * A unique stat ID for each stat in the simulator.
+ * Can be used externally for lookups as well as for debugging.
+ */
+ int id;
+
+ StatData();
+ virtual ~StatData();
+
+ /**
+ * @return true if the stat is binned.
+ */
+ virtual bool binned() const = 0;
+
+ /**
+ * Reset the corresponding stat to the default state.
+ */
+ virtual void reset() = 0;
+
+ /**
+ * @return true if this stat has a value and satisfies its
+ * requirement as a prereq
+ */
+ virtual bool zero() const = 0;
+
+ /**
+ * Check that this stat has been set up properly and is ready for
+ * use
+ * @return true for success
+ */
+ virtual bool check() const = 0;
+ bool baseCheck() const;
+
+ /**
+ * Visitor entry for outputing statistics data
+ */
+ virtual void visit(Visit &visitor) = 0;
+
+ /**
+ * Checks if the first stat's name is alphabetically less than the second.
+ * This function breaks names up at periods and considers each subname
+ * separately.
+ * @param stat1 The first stat.
+ * @param stat2 The second stat.
+ * @return stat1's name is alphabetically before stat2's
+ */
+ static bool less(StatData *stat1, StatData *stat2);
+};
+
+class ScalarData : public StatData
+{
+ public:
+ virtual Counter value() const = 0;
+ virtual Result result() const = 0;
+ virtual Result total() const = 0;
+ virtual void visit(Visit &visitor) { visitor.visit(*this); }
+};
+
+template <class Stat>
+class ScalarStatData : public ScalarData
+{
+ protected:
+ Stat &s;
+
+ public:
+ ScalarStatData(Stat &stat) : s(stat) {}
+
+ virtual bool binned() const { return s.binned(); }
+ virtual bool check() const { return s.check(); }
+ virtual Counter value() const { return s.value(); }
+ virtual Result result() const { return s.result(); }
+ virtual Result total() const { return s.total(); }
+ virtual void reset() { s.reset(); }
+ virtual bool zero() const { return s.zero(); }
+};
+
+struct VectorData : public StatData
+{
+ /** Names and descriptions of subfields. */
+ mutable std::vector<std::string> subnames;
+ mutable std::vector<std::string> subdescs;
+
+ virtual size_t size() const = 0;
+ virtual const VCounter &value() const = 0;
+ virtual const VResult &result() const = 0;
+ virtual Result total() const = 0;
+ void update()
+ {
+ if (!subnames.empty()) {
+ int s = size();
+ if (subnames.size() < s)
+ subnames.resize(s);
+
+ if (subdescs.size() < s)
+ subdescs.resize(s);
+ }
+ }
+};
+
+template <class Stat>
+class VectorStatData : public VectorData
+{
+ protected:
+ Stat &s;
+ mutable VCounter cvec;
+ mutable VResult rvec;
+
+ public:
+ VectorStatData(Stat &stat) : s(stat) {}
+
+ virtual bool binned() const { return s.binned(); }
+ virtual bool check() const { return s.check(); }
+ virtual bool zero() const { return s.zero(); }
+ virtual void reset() { s.reset(); }
+
+ virtual size_t size() const { return s.size(); }
+ virtual VCounter &value() const
+ {
+ s.value(cvec);
+ return cvec;
+ }
+ virtual const VResult &result() const
+ {
+ s.result(rvec);
+ return rvec;
+ }
+ virtual Result total() const { return s.total(); }
+ virtual void visit(Visit &visitor)
+ {
+ update();
+ s.update(this);
+ visitor.visit(*this);
+ }
+};
+
+struct DistDataData
+{
+ Counter min_val;
+ Counter max_val;
+ Counter underflow;
+ Counter overflow;
+ VCounter cvec;
+ Counter sum;
+ Counter squares;
+ Counter samples;
+
+ Counter min;
+ Counter max;
+ Counter bucket_size;
+ int size;
+ bool fancy;
+};
+
+struct DistData : public StatData
+{
+ /** Local storage for the entry values, used for printing. */
+ DistDataData data;
+};
+
+template <class Stat>
+class DistStatData : public DistData
+{
+ protected:
+ Stat &s;
+
+ public:
+ DistStatData(Stat &stat) : s(stat) {}
+
+ virtual bool binned() const { return s.binned(); }
+ virtual bool check() const { return s.check(); }
+ virtual void reset() { s.reset(); }
+ virtual bool zero() const { return s.zero(); }
+ virtual void visit(Visit &visitor)
+ {
+ s.update(this);
+ visitor.visit(*this);
+ }
+};
+
+struct VectorDistData : public StatData
+{
+ std::vector<DistDataData> data;
+
+ /** Names and descriptions of subfields. */
+ mutable std::vector<std::string> subnames;
+ mutable std::vector<std::string> subdescs;
+
+ /** Local storage for the entry values, used for printing. */
+ mutable VResult rvec;
+
+ virtual size_t size() const = 0;
+ void update()
+ {
+ int s = size();
+ if (subnames.size() < s)
+ subnames.resize(s);
+
+ if (subdescs.size() < s)
+ subdescs.resize(s);
+ }
+};
+
+template <class Stat>
+class VectorDistStatData : public VectorDistData
+{
+ protected:
+ Stat &s;
+ typedef typename Stat::bin_t bin_t;
+
+ public:
+ VectorDistStatData(Stat &stat) : s(stat) {}
+
+ virtual bool binned() const { return bin_t::binned; }
+ virtual bool check() const { return s.check(); }
+ virtual void reset() { s.reset(); }
+ virtual size_t size() const { return s.size(); }
+ virtual bool zero() const { return s.zero(); }
+ virtual void visit(Visit &visitor)
+ {
+ update();
+ s.update(this);
+ visitor.visit(*this);
+ }
+};
+
+struct Vector2dData : public StatData
+{
+ /** Names and descriptions of subfields. */
+ std::vector<std::string> subnames;
+ std::vector<std::string> subdescs;
+ std::vector<std::string> y_subnames;
+
+ /** Local storage for the entry values, used for printing. */
+ mutable VCounter cvec;
+ mutable int x;
+ mutable int y;
+
+ void update()
+ {
+ if (subnames.size() < x)
+ subnames.resize(x);
+ }
+};
+
+template <class Stat>
+class Vector2dStatData : public Vector2dData
+{
+ protected:
+ Stat &s;
+ typedef typename Stat::bin_t bin_t;
+
+ public:
+ Vector2dStatData(Stat &stat) : s(stat) {}
+
+ virtual bool binned() const { return bin_t::binned; }
+ virtual bool check() const { return s.check(); }
+ virtual void reset() { s.reset(); }
+ virtual bool zero() const { return s.zero(); }
+ virtual void visit(Visit &visitor)
+ {
+ update();
+ s.update(this);
+ visitor.visit(*this);
+ }
+};
+
+
+class DataAccess
+{
+ protected:
+ StatData *find() const;
+ void map(StatData *data);
+
+ StatData *statData();
+ const StatData *statData() const;
+
+ void setInit();
+ void setPrint();
+};
+
+template <class Parent, class Child, template <class> class Data>
+class Wrap : public Child
+{
+ protected:
+ Parent &self() { return *reinterpret_cast<Parent *>(this); }
+
+ protected:
+ Data<Child> *statData()
+ {
+ StatData *__data = DataAccess::statData();
+ Data<Child> *ptr = dynamic_cast<Data<Child> *>(__data);
+ assert(ptr);
+ return ptr;
+ }
+
+ public:
+ const Data<Child> *statData() const
+ {
+ const StatData *__data = DataAccess::statData();
+ const Data<Child> *ptr = dynamic_cast<const Data<Child> *>(__data);
+ assert(ptr);
+ return ptr;
+ }
+
+ protected:
+ /**
+ * Copy constructor, copies are not allowed.
+ */
+ Wrap(const Wrap &stat);
+ /**
+ * Can't copy stats.
+ */
+ void operator=(const Wrap &);
+
+ public:
+ Wrap()
+ {
+ map(new Data<Child>(*this));
+ }
+
+ /**
+ * Set the name and marks this stat to print at the end of simulation.
+ * @param name The new name.
+ * @return A reference to this stat.
+ */
+ Parent &name(const std::string &_name)
+ {
+ Data<Child> *data = this->statData();
+ data->name = _name;
+ this->setPrint();
+ return this->self();
+ }
+
+ /**
+ * Set the description and marks this stat to print at the end of
+ * simulation.
+ * @param desc The new description.
+ * @return A reference to this stat.
+ */
+ Parent &desc(const std::string &_desc)
+ {
+ this->statData()->desc = _desc;
+ return this->self();
+ }
+
+ /**
+ * Set the precision and marks this stat to print at the end of simulation.
+ * @param p The new precision
+ * @return A reference to this stat.
+ */
+ Parent &precision(int _precision)
+ {
+ this->statData()->precision = _precision;
+ return this->self();
+ }
+
+ /**
+ * Set the flags and marks this stat to print at the end of simulation.
+ * @param f The new flags.
+ * @return A reference to this stat.
+ */
+ Parent &flags(StatFlags _flags)
+ {
+ this->statData()->flags |= _flags;
+ return this->self();
+ }
+
+ /**
+ * Set the prerequisite stat and marks this stat to print at the end of
+ * simulation.
+ * @param prereq The prerequisite stat.
+ * @return A reference to this stat.
+ */
+ template <class Stat>
+ Parent &prereq(const Stat &prereq)
+ {
+ this->statData()->prereq = prereq.statData();
+ return this->self();
+ }
+};
+
+template <class Parent, class Child, template <class Child> class Data>
+class WrapVec : public Wrap<Parent, Child, Data>
+{
+ public:
+ // The following functions are specific to vectors. If you use them
+ // in a non vector context, you will get a nice compiler error!
+
+ /**
+ * Set the subfield name for the given index, and marks this stat to print
+ * at the end of simulation.
+ * @param index The subfield index.
+ * @param name The new name of the subfield.
+ * @return A reference to this stat.
+ */
+ Parent &subname(int index, const std::string &name)
+ {
+ std::vector<std::string> &subn = this->statData()->subnames;
+ if (subn.size() <= index)
+ subn.resize(index + 1);
+ subn[index] = name;
+ return this->self();
+ }
+
+ /**
+ * Set the subfield description for the given index and marks this stat to
+ * print at the end of simulation.
+ * @param index The subfield index.
+ * @param desc The new description of the subfield
+ * @return A reference to this stat.
+ */
+ Parent &subdesc(int index, const std::string &desc)
+ {
+ std::vector<std::string> &subd = this->statData()->subdescs;
+ if (subd.size() <= index)
+ subd.resize(index + 1);
+ subd[index] = desc;
+
+ return this->self();
+ }
+
+};
+
+template <class Parent, class Child, template <class Child> class Data>
+class WrapVec2d : public WrapVec<Parent, Child, Data>
+{
+ public:
+ /**
+ * @warning This makes the assumption that if you're gonna subnames a 2d
+ * vector, you're subnaming across all y
+ */
+ Parent &ysubnames(const char **names)
+ {
+ Data<Child> *data = this->statData();
+ data->y_subnames.resize(this->y);
+ for (int i = 0; i < this->y; ++i)
+ data->y_subnames[i] = names[i];
+ return this->self();
+ }
+ Parent &ysubname(int index, const std::string subname)
+ {
+ Data<Child> *data = this->statData();
+ assert(index < this->y);
+ data->y_subnames.resize(this->y);
+ data->y_subnames[index] = subname.c_str();
+ return this->self();
+ }
+};
+
+//////////////////////////////////////////////////////////////////////
+//
+// Simple Statistics
+//
+//////////////////////////////////////////////////////////////////////
+
+/**
+ * Templatized storage and interface for a simple scalar stat.
+ */
+struct StatStor
+{
+ public:
+ /** The paramaters for this storage type, none for a scalar. */
+ struct Params { };
+
+ private:
+ /** The statistic value. */
+ Counter data;
+
+ public:
+ /**
+ * Builds this storage element and calls the base constructor of the
+ * datatype.
+ */
+ StatStor(const Params &) : data(Counter()) {}
+
+ /**
+ * The the stat to the given value.
+ * @param val The new value.
+ * @param p The paramters of this storage type.
+ */
+ void set(Counter val, const Params &p) { data = val; }
+ /**
+ * Increment the stat by the given value.
+ * @param val The new value.
+ * @param p The paramters of this storage type.
+ */
+ void inc(Counter val, const Params &p) { data += val; }
+ /**
+ * Decrement the stat by the given value.
+ * @param val The new value.
+ * @param p The paramters of this storage type.
+ */
+ void dec(Counter val, const Params &p) { data -= val; }
+ /**
+ * Return the value of this stat as its base type.
+ * @param p The params of this storage type.
+ * @return The value of this stat.
+ */
+ Counter value(const Params &p) const { return data; }
+ /**
+ * Return the value of this stat as a result type.
+ * @param p The parameters of this storage type.
+ * @return The value of this stat.
+ */
+ Result result(const Params &p) const { return (Result)data; }
+ /**
+ * Reset stat value to default
+ */
+ void reset() { data = Counter(); }
+
+ /**
+ * @return true if zero value
+ */
+ bool zero() const { return data == Counter(); }
+};
+
+/**
+ * Templatized storage and interface to a per-cycle average stat. This keeps
+ * a current count and updates a total (count * cycles) when this count
+ * changes. This allows the quick calculation of a per cycle count of the item
+ * being watched. This is good for keeping track of residencies in structures
+ * among other things.
+ * @todo add lateny to the stat and fix binning.
+ */
+struct AvgStor
+{
+ public:
+ /** The paramaters for this storage type */
+ struct Params
+ {
+ /**
+ * The current count. We stash this here because the current
+ * value is not a binned value.
+ */
+ Counter current;
+ };
+
+ private:
+ /** The total count for all cycles. */
+ mutable Result total;
+ /** The cycle that current last changed. */
+ mutable Tick last;
+
+ public:
+ /**
+ * Build and initializes this stat storage.
+ */
+ AvgStor(Params &p) : total(0), last(0) { p.current = Counter(); }
+
+ /**
+ * Set the current count to the one provided, update the total and last
+ * set values.
+ * @param val The new count.
+ * @param p The parameters for this storage.
+ */
+ void set(Counter val, Params &p) {
+ total += p.current * (curTick - last);
+ last = curTick;
+ p.current = val;
+ }
+
+ /**
+ * Increment the current count by the provided value, calls set.
+ * @param val The amount to increment.
+ * @param p The parameters for this storage.
+ */
+ void inc(Counter val, Params &p) { set(p.current + val, p); }
+
+ /**
+ * Deccrement the current count by the provided value, calls set.
+ * @param val The amount to decrement.
+ * @param p The parameters for this storage.
+ */
+ void dec(Counter val, Params &p) { set(p.current - val, p); }
+
+ /**
+ * Return the current count.
+ * @param p The parameters for this storage.
+ * @return The current count.
+ */
+ Counter value(const Params &p) const { return p.current; }
+
+ /**
+ * Return the current average.
+ * @param p The parameters for this storage.
+ * @return The current average.
+ */
+ Result result(const Params &p) const
+ {
+ total += p.current * (curTick - last);
+ last = curTick;
+ return (Result)(total + p.current) / (Result)(curTick + 1);
+ }
+
+ /**
+ * Reset stat value to default
+ */
+ void reset()
+ {
+ total = 0;
+ last = curTick;
+ }
+
+ /**
+ * @return true if zero value
+ */
+ bool zero() const { return total == 0.0; }
+};
+
+/**
+ * Implementation of a scalar stat. The type of stat is determined by the
+ * Storage template. The storage for this stat is held within the Bin class.
+ * This allows for breaking down statistics across multiple bins easily.
+ */
+template <class Storage, class Bin>
+class ScalarBase : public DataAccess
+{
+ public:
+ /** Define the params of the storage class. */
+ typedef typename Storage::Params params_t;
+ /** Define the bin type. */
+ typedef typename Bin::template Bin<Storage> bin_t;
+
+ protected:
+ /** The bin of this stat. */
+ bin_t bin;
+ /** The parameters for this stat. */
+ params_t params;
+
+ protected:
+ /**
+ * Retrieve the storage from the bin.
+ * @return The storage object for this stat.
+ */
+ Storage *data() { return bin.data(params); }
+ /**
+ * Retrieve a const pointer to the storage from the bin.
+ * @return A const pointer to the storage object for this stat.
+ */
+ const Storage *data() const
+ {
+ bin_t *_bin = const_cast<bin_t *>(&bin);
+ params_t *_params = const_cast<params_t *>(&params);
+ return _bin->data(*_params);
+ }
+
+ public:
+ /**
+ * Return the current value of this stat as its base type.
+ * @return The current value.
+ */
+ Counter value() const { return data()->value(params); }
+
+ public:
+ /**
+ * Create and initialize this stat, register it with the database.
+ */
+ ScalarBase()
+ {
+ bin.init(params);
+ }
+
+ public:
+ // Common operators for stats
+ /**
+ * Increment the stat by 1. This calls the associated storage object inc
+ * function.
+ */
+ void operator++() { data()->inc(1, params); }
+ /**
+ * Decrement the stat by 1. This calls the associated storage object dec
+ * function.
+ */
+ void operator--() { data()->dec(1, params); }
+
+ /** Increment the stat by 1. */
+ void operator++(int) { ++*this; }
+ /** Decrement the stat by 1. */
+ void operator--(int) { --*this; }
+
+ /**
+ * Set the data value to the given value. This calls the associated storage
+ * object set function.
+ * @param v The new value.
+ */
+ template <typename U>
+ void operator=(const U &v) { data()->set(v, params); }
+
+ /**
+ * Increment the stat by the given value. This calls the associated
+ * storage object inc function.
+ * @param v The value to add.
+ */
+ template <typename U>
+ void operator+=(const U &v) { data()->inc(v, params); }
+
+ /**
+ * Decrement the stat by the given value. This calls the associated
+ * storage object dec function.
+ * @param v The value to substract.
+ */
+ template <typename U>
+ void operator-=(const U &v) { data()->dec(v, params); }
+
+ /**
+ * Return the number of elements, always 1 for a scalar.
+ * @return 1.
+ */
+ size_t size() const { return 1; }
+ /**
+ * Return true if stat is binned.
+ *@return True is stat is binned.
+ */
+ bool binned() const { return bin_t::binned; }
+
+ bool check() const { return bin.initialized(); }
+
+ /**
+ * Reset stat value to default
+ */
+ void reset() { bin.reset(); }
+
+ Counter value() { return data()->value(params); }
+
+ Result result() { return data()->result(params); }
+
+ Result total() { return result(); }
+
+ bool zero() { return result() == 0.0; }
+
+};
+
+class ProxyData : public ScalarData
+{
+ public:
+ virtual void visit(Visit &visitor) { visitor.visit(*this); }
+ virtual bool binned() const { return false; }
+ virtual std::string str() const { return to_string(value()); }
+ virtual size_t size() const { return 1; }
+ virtual bool zero() const { return value() == 0; }
+ virtual bool check() const { return true; }
+ virtual void reset() { }
+};
+
+template <class T>
+class ValueProxy : public ProxyData
+{
+ private:
+ T *scalar;
+
+ public:
+ ValueProxy(T &val) : scalar(&val) {}
+ virtual Counter value() const { return *scalar; }
+ virtual Result result() const { return *scalar; }
+ virtual Result total() const { return *scalar; }
+};
+
+template <class T>
+class FunctorProxy : public ProxyData
+{
+ private:
+ T *functor;
+
+ public:
+ FunctorProxy(T &func) : functor(&func) {}
+ virtual Counter value() const { return (*functor)(); }
+ virtual Result result() const { return (*functor)(); }
+ virtual Result total() const { return (*functor)(); }
+};
+
+class ValueBase : public DataAccess
+{
+ private:
+ ProxyData *proxy;
+
+ public:
+ ValueBase() : proxy(NULL) { }
+ ~ValueBase() { if (proxy) delete proxy; }
+
+ template <class T>
+ void scalar(T &value)
+ {
+ proxy = new ValueProxy<T>(value);
+ setInit();
+ }
+
+ template <class T>
+ void functor(T &func)
+ {
+ proxy = new FunctorProxy<T>(func);
+ setInit();
+ }
+
+ Counter value() { return proxy->value(); }
+ Result result() const { return proxy->result(); }
+ Result total() const { return proxy->total(); };
+ size_t size() const { return proxy->size(); }
+
+ bool binned() const { return proxy->binned(); }
+ std::string str() const { return proxy->str(); }
+ bool zero() const { return proxy->zero(); }
+ bool check() const { return proxy != NULL; }
+ void reset() { }
+};
+
+//////////////////////////////////////////////////////////////////////
+//
+// Vector Statistics
+//
+//////////////////////////////////////////////////////////////////////
+template <class Storage, class Bin>
+class ScalarProxy;
+
+/**
+ * Implementation of a vector of stats. The type of stat is determined by the
+ * Storage class. @sa ScalarBase
+ */
+template <class Storage, class Bin>
+class VectorBase : public DataAccess
+{
+ public:
+ /** Define the params of the storage class. */
+ typedef typename Storage::Params params_t;
+ /** Define the bin type. */
+ typedef typename Bin::template VectorBin<Storage> bin_t;
+
+ protected:
+ /** The bin of this stat. */
+ bin_t bin;
+ /** The parameters for this stat. */
+ params_t params;
+
+ protected:
+ /**
+ * Retrieve the storage from the bin for the given index.
+ * @param index The vector index to access.
+ * @return The storage object at the given index.
+ */
+ Storage *data(int index) { return bin.data(index, params); }
+ /**
+ * Retrieve a const pointer to the storage from the bin
+ * for the given index.
+ * @param index The vector index to access.
+ * @return A const pointer to the storage object at the given index.
+ */
+ const Storage *data(int index) const
+ {
+ bin_t *_bin = const_cast<bin_t *>(&bin);
+ params_t *_params = const_cast<params_t *>(&params);
+ return _bin->data(index, *_params);
+ }
+
+ public:
+ void value(VCounter &vec) const
+ {
+ vec.resize(size());
+ for (int i = 0; i < size(); ++i)
+ vec[i] = data(i)->value(params);
+ }
+
+ /**
+ * Copy the values to a local vector and return a reference to it.
+ * @return A reference to a vector of the stat values.
+ */
+ void result(VResult &vec) const
+ {
+ vec.resize(size());
+ for (int i = 0; i < size(); ++i)
+ vec[i] = data(i)->result(params);
+ }
+
+ /**
+ * @return True is stat is binned.
+ */
+ bool binned() const { return bin_t::binned; }
+
+ /**
+ * Return a total of all entries in this vector.
+ * @return The total of all vector entries.
+ */
+ Result total() const {
+ Result total = 0.0;
+ for (int i = 0; i < size(); ++i)
+ total += data(i)->result(params);
+ return total;
+ }
+
+ /**
+ * @return the number of elements in this vector.
+ */
+ size_t size() const { return bin.size(); }
+
+ bool zero() const
+ {
+ for (int i = 0; i < size(); ++i)
+ if (data(i)->zero())
+ return true;
+ return false;
+ }
+
+ bool check() const { return bin.initialized(); }
+ void reset() { bin.reset(); }
+
+ public:
+ VectorBase() {}
+
+ /** Friend this class with the associated scalar proxy. */
+ friend class ScalarProxy<Storage, Bin>;
+
+ /**
+ * Return a reference (ScalarProxy) to the stat at the given index.
+ * @param index The vector index to access.
+ * @return A reference of the stat.
+ */
+ ScalarProxy<Storage, Bin> operator[](int index);
+
+ void update(StatData *data) {}
+};
+
+const StatData * getStatData(const void *stat);
+
+/**
+ * A proxy class to access the stat at a given index in a VectorBase stat.
+ * Behaves like a ScalarBase.
+ */
+template <class Storage, class Bin>
+class ScalarProxy
+{
+ public:
+ /** Define the params of the storage class. */
+ typedef typename Storage::Params params_t;
+ /** Define the bin type. */
+ typedef typename Bin::template VectorBin<Storage> bin_t;
+
+ private:
+ /** Pointer to the bin in the parent VectorBase. */
+ bin_t *bin;
+ /** Pointer to the params in the parent VectorBase. */
+ params_t *params;
+ /** The index to access in the parent VectorBase. */
+ int index;
+ /** Keep a pointer to the original stat so was can get data */
+ void *stat;
+
+ protected:
+ /**
+ * Retrieve the storage from the bin.
+ * @return The storage from the bin for this stat.
+ */
+ Storage *data() { return bin->data(index, *params); }
+ /**
+ * Retrieve a const pointer to the storage from the bin.
+ * @return A const pointer to the storage for this stat.
+ */
+ const Storage *data() const
+ {
+ bin_t *_bin = const_cast<bin_t *>(bin);
+ params_t *_params = const_cast<params_t *>(params);
+ return _bin->data(index, *_params);
+ }
+
+ public:
+ /**
+ * Return the current value of this stat as its base type.
+ * @return The current value.
+ */
+ Counter value() const { return data()->value(*params); }
+
+ /**
+ * Return the current value of this statas a result type.
+ * @return The current value.
+ */
+ Result result() const { return data()->result(*params); }
+
+ public:
+ /**
+ * Create and initialize this proxy, do not register it with the database.
+ * @param b The bin to use.
+ * @param p The params to use.
+ * @param i The index to access.
+ */
+ ScalarProxy(bin_t &b, params_t &p, int i, void *s)
+ : bin(&b), params(&p), index(i), stat(s) {}
+ /**
+ * Create a copy of the provided ScalarProxy.
+ * @param sp The proxy to copy.
+ */
+ ScalarProxy(const ScalarProxy &sp)
+ : bin(sp.bin), params(sp.params), index(sp.index), stat(sp.stat) {}
+ /**
+ * Set this proxy equal to the provided one.
+ * @param sp The proxy to copy.
+ * @return A reference to this proxy.
+ */
+ const ScalarProxy &operator=(const ScalarProxy &sp) {
+ bin = sp.bin;
+ params = sp.params;
+ index = sp.index;
+ stat = sp.stat;
+ return *this;
+ }
+
+ public:
+ // Common operators for stats
+ /**
+ * Increment the stat by 1. This calls the associated storage object inc
+ * function.
+ */
+ void operator++() { data()->inc(1, *params); }
+ /**
+ * Decrement the stat by 1. This calls the associated storage object dec
+ * function.
+ */
+ void operator--() { data()->dec(1, *params); }
+
+ /** Increment the stat by 1. */
+ void operator++(int) { ++*this; }
+ /** Decrement the stat by 1. */
+ void operator--(int) { --*this; }
+
+ /**
+ * Set the data value to the given value. This calls the associated storage
+ * object set function.
+ * @param v The new value.
+ */
+ template <typename U>
+ void operator=(const U &v) { data()->set(v, *params); }
+
+ /**
+ * Increment the stat by the given value. This calls the associated
+ * storage object inc function.
+ * @param v The value to add.
+ */
+ template <typename U>
+ void operator+=(const U &v) { data()->inc(v, *params); }
+
+ /**
+ * Decrement the stat by the given value. This calls the associated
+ * storage object dec function.
+ * @param v The value to substract.
+ */
+ template <typename U>
+ void operator-=(const U &v) { data()->dec(v, *params); }
+
+ /**
+ * Return the number of elements, always 1 for a scalar.
+ * @return 1.
+ */
+ size_t size() const { return 1; }
+
+ /**
+ * Return true if stat is binned.
+ *@return false since Proxies aren't printed/binned
+ */
+ bool binned() const { return false; }
+
+ /**
+ * This stat has no state. Nothing to reset
+ */
+ void reset() { }
+
+ public:
+ const StatData *statData() const { return getStatData(stat); }
+ std::string str() const
+ {
+ return csprintf("%s[%d]", this->statData()->name, index);
+
+ }
+};
+
+template <class Storage, class Bin>
+inline ScalarProxy<Storage, Bin>
+VectorBase<Storage, Bin>::operator[](int index)
+{
+ assert (index >= 0 && index < size());
+ return ScalarProxy<Storage, Bin>(bin, params, index, this);
+}
+
+template <class Storage, class Bin>
+class VectorProxy;
+
+template <class Storage, class Bin>
+class Vector2dBase : public DataAccess
+{
+ public:
+ typedef typename Storage::Params params_t;
+ typedef typename Bin::template VectorBin<Storage> bin_t;
+
+ protected:
+ size_t x;
+ size_t y;
+ bin_t bin;
+ params_t params;
+
+ protected:
+ Storage *data(int index) { return bin.data(index, params); }
+ const Storage *data(int index) const
+ {
+ bin_t *_bin = const_cast<bin_t *>(&bin);
+ params_t *_params = const_cast<params_t *>(&params);
+ return _bin->data(index, *_params);
+ }
+
+ public:
+ Vector2dBase() {}
+
+ void update(Vector2dData *data)
+ {
+ int size = this->size();
+ data->cvec.resize(size);
+ for (int i = 0; i < size; ++i)
+ data->cvec[i] = this->data(i)->value(params);
+ }
+
+ std::string ysubname(int i) const { return (*this->y_subnames)[i]; }
+
+ friend class VectorProxy<Storage, Bin>;
+ VectorProxy<Storage, Bin> operator[](int index);
+
+ size_t size() const { return bin.size(); }
+ bool zero() const { return data(0)->value(params) == 0.0; }
+
+ /**
+ * Reset stat value to default
+ */
+ void reset() { bin.reset(); }
+
+ bool check() { return bin.initialized(); }
+};
+
+template <class Storage, class Bin>
+class VectorProxy
+{
+ public:
+ typedef typename Storage::Params params_t;
+ typedef typename Bin::template VectorBin<Storage> bin_t;
+
+ private:
+ bin_t *bin;
+ params_t *params;
+ int offset;
+ int len;
+ void *stat;
+
+ private:
+ mutable VResult *vec;
+
+ Storage *data(int index) {
+ assert(index < len);
+ return bin->data(offset + index, *params);
+ }
+
+ const Storage *data(int index) const {
+ bin_t *_bin = const_cast<bin_t *>(bin);
+ params_t *_params = const_cast<params_t *>(params);
+ return _bin->data(offset + index, *_params);
+ }
+
+ public:
+ const VResult &result() const {
+ if (vec)
+ vec->resize(size());
+ else
+ vec = new VResult(size());
+
+ for (int i = 0; i < size(); ++i)
+ (*vec)[i] = data(i)->result(*params);
+
+ return *vec;
+ }
+
+ Result total() const {
+ Result total = 0.0;
+ for (int i = 0; i < size(); ++i)
+ total += data(i)->result(*params);
+ return total;
+ }
+
+ public:
+ VectorProxy(bin_t &b, params_t &p, int o, int l, void *s)
+ : bin(&b), params(&p), offset(o), len(l), stat(s), vec(NULL)
+ {
+ }
+
+ VectorProxy(const VectorProxy &sp)
+ : bin(sp.bin), params(sp.params), offset(sp.offset), len(sp.len),
+ stat(sp.stat), vec(NULL)
+ {
+ }
+
+ ~VectorProxy()
+ {
+ if (vec)
+ delete vec;
+ }
+
+ const VectorProxy &operator=(const VectorProxy &sp)
+ {
+ bin = sp.bin;
+ params = sp.params;
+ offset = sp.offset;
+ len = sp.len;
+ stat = sp.stat;
+ if (vec)
+ delete vec;
+ vec = NULL;
+ return *this;
+ }
+
+ ScalarProxy<Storage, Bin> operator[](int index)
+ {
+ assert (index >= 0 && index < size());
+ return ScalarProxy<Storage, Bin>(*bin, *params, offset + index, stat);
+ }
+
+ size_t size() const { return len; }
+
+ /**
+ * Return true if stat is binned.
+ *@return false since Proxies aren't printed/binned
+ */
+ bool binned() const { return false; }
+
+ /**
+ * This stat has no state. Nothing to reset.
+ */
+ void reset() { }
+};
+
+template <class Storage, class Bin>
+inline VectorProxy<Storage, Bin>
+Vector2dBase<Storage, Bin>::operator[](int index)
+{
+ int offset = index * y;
+ assert (index >= 0 && offset < size());
+ return VectorProxy<Storage, Bin>(bin, params, offset, y, this);
+}
+
+//////////////////////////////////////////////////////////////////////
+//
+// Non formula statistics
+//
+//////////////////////////////////////////////////////////////////////
+
+/**
+ * Templatized storage and interface for a distrbution stat.
+ */
+struct DistStor
+{
+ public:
+ /** The parameters for a distribution stat. */
+ struct Params
+ {
+ /** The minimum value to track. */
+ Counter min;
+ /** The maximum value to track. */
+ Counter max;
+ /** The number of entries in each bucket. */
+ Counter bucket_size;
+ /** The number of buckets. Equal to (max-min)/bucket_size. */
+ int size;
+ };
+ enum { fancy = false };
+
+ private:
+ /** The smallest value sampled. */
+ Counter min_val;
+ /** The largest value sampled. */
+ Counter max_val;
+ /** The number of values sampled less than min. */
+ Counter underflow;
+ /** The number of values sampled more than max. */
+ Counter overflow;
+ /** The current sum. */
+ Counter sum;
+ /** The sum of squares. */
+ Counter squares;
+ /** The number of samples. */
+ Counter samples;
+ /** Counter for each bucket. */
+ VCounter cvec;
+
+ public:
+ /**
+ * Construct this storage with the supplied params.
+ * @param params The parameters.
+ */
+ DistStor(const Params &params)
+ : min_val(INT_MAX), max_val(INT_MIN), underflow(Counter()),
+ overflow(Counter()), sum(Counter()), squares(Counter()),
+ samples(Counter()), cvec(params.size)
+ {
+ reset();
+ }
+
+ /**
+ * Add a value to the distribution for the given number of times.
+ * @param val The value to add.
+ * @param number The number of times to add the value.
+ * @param params The paramters of the distribution.
+ */
+ void sample(Counter val, int number, const Params &params)
+ {
+ if (val < params.min)
+ underflow += number;
+ else if (val > params.max)
+ overflow += number;
+ else {
+ int index = (int)floor((val - params.min) / params.bucket_size);
+ assert(index < size(params));
+ cvec[index] += number;
+ }
+
+ if (val < min_val)
+ min_val = val;
+
+ if (val > max_val)
+ max_val = val;
+
+ Counter sample = val * number;
+ sum += sample;
+ squares += sample * sample;
+ samples += number;
+ }
+
+ /**
+ * Return the number of buckets in this distribution.
+ * @return the number of buckets.
+ * @todo Is it faster to return the size from the parameters?
+ */
+ size_t size(const Params &) const { return cvec.size(); }
+
+ /**
+ * Returns true if any calls to sample have been made.
+ * @param params The paramters of the distribution.
+ * @return True if any values have been sampled.
+ */
+ bool zero(const Params &params) const
+ {
+ return samples == Counter();
+ }
+
+ void update(DistDataData *data, const Params &params)
+ {
+ data->min = params.min;
+ data->max = params.max;
+ data->bucket_size = params.bucket_size;
+ data->size = params.size;
+
+ data->min_val = (min_val == INT_MAX) ? 0 : min_val;
+ data->max_val = (max_val == INT_MIN) ? 0 : max_val;
+ data->underflow = underflow;
+ data->overflow = overflow;
+ data->cvec.resize(params.size);
+ for (int i = 0; i < params.size; ++i)
+ data->cvec[i] = cvec[i];
+
+ data->sum = sum;
+ data->squares = squares;
+ data->samples = samples;
+ }
+
+ /**
+ * Reset stat value to default
+ */
+ void reset()
+ {
+ min_val = INT_MAX;
+ max_val = INT_MIN;
+ underflow = 0;
+ overflow = 0;
+
+ int size = cvec.size();
+ for (int i = 0; i < size; ++i)
+ cvec[i] = Counter();
+
+ sum = Counter();
+ squares = Counter();
+ samples = Counter();
+ }
+};
+
+/**
+ * Templatized storage and interface for a distribution that calculates mean
+ * and variance.
+ */
+struct FancyStor
+{
+ public:
+ /**
+ * No paramters for this storage.
+ */
+ struct Params {};
+ enum { fancy = true };
+
+ private:
+ /** The current sum. */
+ Counter sum;
+ /** The sum of squares. */
+ Counter squares;
+ /** The number of samples. */
+ Counter samples;
+
+ public:
+ /**
+ * Create and initialize this storage.
+ */
+ FancyStor(const Params &)
+ : sum(Counter()), squares(Counter()), samples(Counter())
+ { }
+
+ /**
+ * Add a value the given number of times to this running average.
+ * Update the running sum and sum of squares, increment the number of
+ * values seen by the given number.
+ * @param val The value to add.
+ * @param number The number of times to add the value.
+ * @param p The parameters of this stat.
+ */
+ void sample(Counter val, int number, const Params &p)
+ {
+ Counter value = val * number;
+ sum += value;
+ squares += value * value;
+ samples += number;
+ }
+
+ void update(DistDataData *data, const Params &params)
+ {
+ data->sum = sum;
+ data->squares = squares;
+ data->samples = samples;
+ }
+
+ /**
+ * Return the number of entries in this stat, 1
+ * @return 1.
+ */
+ size_t size(const Params &) const { return 1; }
+
+ /**
+ * Return true if no samples have been added.
+ * @return True if no samples have been added.
+ */
+ bool zero(const Params &) const { return samples == Counter(); }
+
+ /**
+ * Reset stat value to default
+ */
+ void reset()
+ {
+ sum = Counter();
+ squares = Counter();
+ samples = Counter();
+ }
+};
+
+/**
+ * Templatized storage for distribution that calculates per cycle mean and
+ * variance.
+ */
+struct AvgFancy
+{
+ public:
+ /** No parameters for this storage. */
+ struct Params {};
+ enum { fancy = true };
+
+ private:
+ /** Current total. */
+ Counter sum;
+ /** Current sum of squares. */
+ Counter squares;
+
+ public:
+ /**
+ * Create and initialize this storage.
+ */
+ AvgFancy(const Params &) : sum(Counter()), squares(Counter()) {}
+
+ /**
+ * Add a value to the distribution for the given number of times.
+ * Update the running sum and sum of squares.
+ * @param val The value to add.
+ * @param number The number of times to add the value.
+ * @param p The paramters of the distribution.
+ */
+ void sample(Counter val, int number, const Params &p)
+ {
+ Counter value = val * number;
+ sum += value;
+ squares += value * value;
+ }
+
+ void update(DistDataData *data, const Params &params)
+ {
+ data->sum = sum;
+ data->squares = squares;
+ data->samples = curTick;
+ }
+
+ /**
+ * Return the number of entries, in this case 1.
+ * @return 1.
+ */
+ size_t size(const Params &params) const { return 1; }
+ /**
+ * Return true if no samples have been added.
+ * @return True if the sum is zero.
+ */
+ bool zero(const Params &params) const { return sum == Counter(); }
+ /**
+ * Reset stat value to default
+ */
+ void reset()
+ {
+ sum = Counter();
+ squares = Counter();
+ }
+};
+
+/**
+ * Implementation of a distribution stat. The type of distribution is
+ * determined by the Storage template. @sa ScalarBase
+ */
+template <class Storage, class Bin>
+class DistBase : public DataAccess
+{
+ public:
+ /** Define the params of the storage class. */
+ typedef typename Storage::Params params_t;
+ /** Define the bin type. */
+ typedef typename Bin::template Bin<Storage> bin_t;
+
+ protected:
+ /** The bin of this stat. */
+ bin_t bin;
+ /** The parameters for this stat. */
+ params_t params;
+
+ protected:
+ /**
+ * Retrieve the storage from the bin.
+ * @return The storage object for this stat.
+ */
+ Storage *data() { return bin.data(params); }
+ /**
+ * Retrieve a const pointer to the storage from the bin.
+ * @return A const pointer to the storage object for this stat.
+ */
+ const Storage *data() const
+ {
+ bin_t *_bin = const_cast<bin_t *>(&bin);
+ params_t *_params = const_cast<params_t *>(&params);
+ return _bin->data(*_params);
+ }
+
+ public:
+ DistBase() { }
+
+ /**
+ * Add a value to the distribtion n times. Calls sample on the storage
+ * class.
+ * @param v The value to add.
+ * @param n The number of times to add it, defaults to 1.
+ */
+ template <typename U>
+ void sample(const U &v, int n = 1) { data()->sample(v, n, params); }
+
+ /**
+ * Return the number of entries in this stat.
+ * @return The number of entries.
+ */
+ size_t size() const { return data()->size(params); }
+ /**
+ * Return true if no samples have been added.
+ * @return True if there haven't been any samples.
+ */
+ bool zero() const { return data()->zero(params); }
+
+ void update(DistData *base)
+ {
+ base->data.fancy = Storage::fancy;
+ data()->update(&(base->data), params);
+ }
+ /**
+ * @return True is stat is binned.
+ */
+ bool binned() const { return bin_t::binned; }
+ /**
+ * Reset stat value to default
+ */
+ void reset()
+ {
+ bin.reset();
+ }
+
+ bool check() { return bin.initialized(); }
+};
+
+template <class Storage, class Bin>
+class DistProxy;
+
+template <class Storage, class Bin>
+class VectorDistBase : public DataAccess
+{
+ public:
+ typedef typename Storage::Params params_t;
+ typedef typename Bin::template VectorBin<Storage> bin_t;
+
+ protected:
+ bin_t bin;
+ params_t params;
+
+ protected:
+ Storage *data(int index) { return bin.data(index, params); }
+ const Storage *data(int index) const
+ {
+ bin_t *_bin = const_cast<bin_t *>(&bin);
+ params_t *_params = const_cast<params_t *>(&params);
+ return _bin->data(index, *_params);
+ }
+
+ public:
+ VectorDistBase() {}
+
+ friend class DistProxy<Storage, Bin>;
+ DistProxy<Storage, Bin> operator[](int index);
+ const DistProxy<Storage, Bin> operator[](int index) const;
+
+ size_t size() const { return bin.size(); }
+ bool zero() const { return false; }
+ /**
+ * Return true if stat is binned.
+ *@return True is stat is binned.
+ */
+ bool binned() const { return bin_t::binned; }
+ /**
+ * Reset stat value to default
+ */
+ void reset() { bin.reset(); }
+
+ bool check() { return bin.initialized(); }
+ void update(VectorDistData *base)
+ {
+ int size = this->size();
+ base->data.resize(size);
+ for (int i = 0; i < size; ++i) {
+ base->data[i].fancy = Storage::fancy;
+ data(i)->update(&(base->data[i]), params);
+ }
+ }
+};
+
+template <class Storage, class Bin>
+class DistProxy
+{
+ public:
+ typedef typename Storage::Params params_t;
+ typedef typename Bin::template Bin<Storage> bin_t;
+ typedef VectorDistBase<Storage, Bin> base_t;
+
+ private:
+ union {
+ base_t *stat;
+ const base_t *cstat;
+ };
+ int index;
+
+ protected:
+ Storage *data() { return stat->data(index); }
+ const Storage *data() const { return cstat->data(index); }
+
+ public:
+ DistProxy(const VectorDistBase<Storage, Bin> &s, int i)
+ : cstat(&s), index(i) {}
+ DistProxy(const DistProxy &sp)
+ : cstat(sp.cstat), index(sp.index) {}
+ const DistProxy &operator=(const DistProxy &sp) {
+ cstat = sp.cstat; index = sp.index; return *this;
+ }
+
+ public:
+ template <typename U>
+ void sample(const U &v, int n = 1) { data()->sample(v, n, cstat->params); }
+
+ size_t size() const { return 1; }
+ bool zero() const { return data()->zero(cstat->params); }
+ /**
+ * Return true if stat is binned.
+ *@return false since Proxies are not binned/printed.
+ */
+ bool binned() const { return false; }
+ /**
+ * Proxy has no state. Nothing to reset.
+ */
+ void reset() { }
+};
+
+template <class Storage, class Bin>
+inline DistProxy<Storage, Bin>
+VectorDistBase<Storage, Bin>::operator[](int index)
+{
+ assert (index >= 0 && index < size());
+ return DistProxy<Storage, Bin>(*this, index);
+}
+
+template <class Storage, class Bin>
+inline const DistProxy<Storage, Bin>
+VectorDistBase<Storage, Bin>::operator[](int index) const
+{
+ assert (index >= 0 && index < size());
+ return DistProxy<Storage, Bin>(*this, index);
+}
+
+#if 0
+template <class Storage, class Bin>
+Result
+VectorDistBase<Storage, Bin>::total(int index) const
+{
+ int total = 0;
+ for (int i=0; i < x_size(); ++i) {
+ total += data(i)->result(*params);
+ }
+}
+#endif
+
+//////////////////////////////////////////////////////////////////////
+//
+// Formula Details
+//
+//////////////////////////////////////////////////////////////////////
+
+/**
+ * Base class for formula statistic node. These nodes are used to build a tree
+ * that represents the formula.
+ */
+class Node : public RefCounted
+{
+ public:
+ /**
+ * Return the number of nodes in the subtree starting at this node.
+ * @return the number of nodes in this subtree.
+ */
+ virtual size_t size() const = 0;
+ /**
+ * Return the result vector of this subtree.
+ * @return The result vector of this subtree.
+ */
+ virtual const VResult &result() const = 0;
+ /**
+ * Return the total of the result vector.
+ * @return The total of the result vector.
+ */
+ virtual Result total() const = 0;
+ /**
+ * Return true if stat is binned.
+ *@return True is stat is binned.
+ */
+ virtual bool binned() const = 0;
+
+ /**
+ *
+ */
+ virtual std::string str() const = 0;
+};
+
+/** Reference counting pointer to a function Node. */
+typedef RefCountingPtr<Node> NodePtr;
+
+class ScalarStatNode : public Node
+{
+ private:
+ const ScalarData *data;
+ mutable VResult vresult;
+
+ public:
+ ScalarStatNode(const ScalarData *d) : data(d), vresult(1) {}
+ virtual const VResult &result() const
+ {
+ vresult[0] = data->result();
+ return vresult;
+ }
+ virtual Result total() const { return data->result(); };
+
+ virtual size_t size() const { return 1; }
+ /**
+ * Return true if stat is binned.
+ *@return True is stat is binned.
+ */
+ virtual bool binned() const { return data->binned(); }
+
+ /**
+ *
+ */
+ virtual std::string str() const { return data->name; }
+};
+
+template <class Storage, class Bin>
+class ScalarProxyNode : public Node
+{
+ private:
+ const ScalarProxy<Storage, Bin> proxy;
+ mutable VResult vresult;
+
+ public:
+ ScalarProxyNode(const ScalarProxy<Storage, Bin> &p)
+ : proxy(p), vresult(1) { }
+ virtual const VResult &result() const
+ {
+ vresult[0] = proxy.result();
+ return vresult;
+ }
+ virtual Result total() const { return proxy.result(); };
+
+ virtual size_t size() const { return 1; }
+ /**
+ * Return true if stat is binned.
+ *@return True is stat is binned.
+ */
+ virtual bool binned() const { return proxy.binned(); }
+
+ /**
+ *
+ */
+ virtual std::string str() const { return proxy.str(); }
+};
+
+class VectorStatNode : public Node
+{
+ private:
+ const VectorData *data;
+
+ public:
+ VectorStatNode(const VectorData *d) : data(d) { }
+ virtual const VResult &result() const { return data->result(); }
+ virtual Result total() const { return data->total(); };
+
+ virtual size_t size() const { return data->size(); }
+ /**
+ * Return true if stat is binned.
+ *@return True is stat is binned.
+ */
+ virtual bool binned() const { return data->binned(); }
+
+ virtual std::string str() const { return data->name; }
+};
+
+template <class T>
+class ConstNode : public Node
+{
+ private:
+ VResult vresult;
+
+ public:
+ ConstNode(T s) : vresult(1, (Result)s) {}
+ const VResult &result() const { return vresult; }
+ virtual Result total() const { return vresult[0]; };
+ virtual size_t size() const { return 1; }
+
+ /**
+ * Return true if stat is binned.
+ *@return False since constants aren't binned.
+ */
+ virtual bool binned() const { return false; }
+
+ virtual std::string str() const { return to_string(vresult[0]); }
+};
+
+template <class Op>
+struct OpString;
+
+template<>
+struct OpString<std::plus<Result> >
+{
+ static std::string str() { return "+"; }
+};
+
+template<>
+struct OpString<std::minus<Result> >
+{
+ static std::string str() { return "-"; }
+};
+
+template<>
+struct OpString<std::multiplies<Result> >
+{
+ static std::string str() { return "*"; }
+};
+
+template<>
+struct OpString<std::divides<Result> >
+{
+ static std::string str() { return "/"; }
+};
+
+template<>
+struct OpString<std::modulus<Result> >
+{
+ static std::string str() { return "%"; }
+};
+
+template<>
+struct OpString<std::negate<Result> >
+{
+ static std::string str() { return "-"; }
+};
+
+template <class Op>
+class UnaryNode : public Node
+{
+ public:
+ NodePtr l;
+ mutable VResult vresult;
+
+ public:
+ UnaryNode(NodePtr &p) : l(p) {}
+
+ const VResult &result() const
+ {
+ const VResult &lvec = l->result();
+ int size = lvec.size();
+
+ assert(size > 0);
+
+ vresult.resize(size);
+ Op op;
+ for (int i = 0; i < size; ++i)
+ vresult[i] = op(lvec[i]);
+
+ return vresult;
+ }
+
+ Result total() const {
+ Op op;
+ return op(l->total());
+ }
+
+ virtual size_t size() const { return l->size(); }
+ /**
+ * Return true if child of node is binned.
+ *@return True if child of node is binned.
+ */
+ virtual bool binned() const { return l->binned(); }
+
+ virtual std::string str() const
+ {
+ return OpString<Op>::str() + l->str();
+ }
+};
+
+template <class Op>
+class BinaryNode : public Node
+{
+ public:
+ NodePtr l;
+ NodePtr r;
+ mutable VResult vresult;
+
+ public:
+ BinaryNode(NodePtr &a, NodePtr &b) : l(a), r(b) {}
+
+ const VResult &result() const
+ {
+ Op op;
+ const VResult &lvec = l->result();
+ const VResult &rvec = r->result();
+
+ assert(lvec.size() > 0 && rvec.size() > 0);
+
+ if (lvec.size() == 1 && rvec.size() == 1) {
+ vresult.resize(1);
+ vresult[0] = op(lvec[0], rvec[0]);
+ } else if (lvec.size() == 1) {
+ int size = rvec.size();
+ vresult.resize(size);
+ for (int i = 0; i < size; ++i)
+ vresult[i] = op(lvec[0], rvec[i]);
+ } else if (rvec.size() == 1) {
+ int size = lvec.size();
+ vresult.resize(size);
+ for (int i = 0; i < size; ++i)
+ vresult[i] = op(lvec[i], rvec[0]);
+ } else if (rvec.size() == lvec.size()) {
+ int size = rvec.size();
+ vresult.resize(size);
+ for (int i = 0; i < size; ++i)
+ vresult[i] = op(lvec[i], rvec[i]);
+ }
+
+ return vresult;
+ }
+
+ Result total() const {
+ Op op;
+ return op(l->total(), r->total());
+ }
+
+ virtual size_t size() const {
+ int ls = l->size();
+ int rs = r->size();
+ if (ls == 1)
+ return rs;
+ else if (rs == 1)
+ return ls;
+ else {
+ assert(ls == rs && "Node vector sizes are not equal");
+ return ls;
+ }
+ }
+ /**
+ * Return true if any children of node are binned
+ *@return True if either child of node is binned.
+ */
+ virtual bool binned() const { return (l->binned() || r->binned()); }
+
+ virtual std::string str() const
+ {
+ return csprintf("(%s %s %s)", l->str(), OpString<Op>::str(), r->str());
+ }
+};
+
+template <class Op>
+class SumNode : public Node
+{
+ public:
+ NodePtr l;
+ mutable VResult vresult;
+
+ public:
+ SumNode(NodePtr &p) : l(p), vresult(1) {}
+
+ const VResult &result() const
+ {
+ const VResult &lvec = l->result();
+ int size = lvec.size();
+ assert(size > 0);
+
+ vresult[0] = 0.0;
+
+ Op op;
+ for (int i = 0; i < size; ++i)
+ vresult[0] = op(vresult[0], lvec[i]);
+
+ return vresult;
+ }
+
+ Result total() const
+ {
+ const VResult &lvec = l->result();
+ int size = lvec.size();
+ assert(size > 0);
+
+ Result vresult = 0.0;
+
+ Op op;
+ for (int i = 0; i < size; ++i)
+ vresult = op(vresult, lvec[i]);
+
+ return vresult;
+ }
+
+ virtual size_t size() const { return 1; }
+ /**
+ * Return true if child of node is binned.
+ *@return True if child of node is binned.
+ */
+ virtual bool binned() const { return l->binned(); }
+
+ virtual std::string str() const
+ {
+ return csprintf("total(%s)", l->str());
+ }
+};
+
+
+//////////////////////////////////////////////////////////////////////
+//
+// Visible Statistics Types
+//
+//////////////////////////////////////////////////////////////////////
+/**
+ * @defgroup VisibleStats "Statistic Types"
+ * These are the statistics that are used in the simulator. By default these
+ * store counters and don't use binning, but are templatized to accept any type
+ * and any Bin class.
+ * @{
+ */
+
+/**
+ * This is an easy way to assign all your stats to be binned or not
+ * binned. If the typedef is NoBin, nothing is binned. If it is
+ * MainBin, then all stats are binned under that Bin.
+ */
+#if STATS_BINNING
+typedef MainBin DefaultBin;
+#else
+typedef NoBin DefaultBin;
+#endif
+
+/**
+ * This is a simple scalar statistic, like a counter.
+ * @sa Stat, ScalarBase, StatStor
+ */
+template <class Bin = DefaultBin>
+class Scalar
+ : public Wrap<Scalar<Bin>,
+ ScalarBase<StatStor, Bin>,
+ ScalarStatData>
+{
+ public:
+ /** The base implementation. */
+ typedef ScalarBase<StatStor, Bin> Base;
+
+ Scalar()
+ {
+ this->setInit();
+ }
+
+ /**
+ * Sets the stat equal to the given value. Calls the base implementation
+ * of operator=
+ * @param v The new value.
+ */
+ template <typename U>
+ void operator=(const U &v) { Base::operator=(v); }
+};
+
+class Value
+ : public Wrap<Value,
+ ValueBase,
+ ScalarStatData>
+{
+ public:
+ /** The base implementation. */
+ typedef ValueBase Base;
+
+ template <class T>
+ Value &scalar(T &value)
+ {
+ Base::scalar(value);
+ return *this;
+ }
+
+ template <class T>
+ Value &functor(T &func)
+ {
+ Base::functor(func);
+ return *this;
+ }
+};
+
+/**
+ * A stat that calculates the per cycle average of a value.
+ * @sa Stat, ScalarBase, AvgStor
+ */
+template <class Bin = DefaultBin>
+class Average
+ : public Wrap<Average<Bin>,
+ ScalarBase<AvgStor, Bin>,
+ ScalarStatData>
+{
+ public:
+ /** The base implementation. */
+ typedef ScalarBase<AvgStor, Bin> Base;
+
+ Average()
+ {
+ this->setInit();
+ }
+
+ /**
+ * Sets the stat equal to the given value. Calls the base implementation
+ * of operator=
+ * @param v The new value.
+ */
+ template <typename U>
+ void operator=(const U &v) { Base::operator=(v); }
+};
+
+/**
+ * A vector of scalar stats.
+ * @sa Stat, VectorBase, StatStor
+ */
+template <class Bin = DefaultBin>
+class Vector
+ : public WrapVec<Vector<Bin>,
+ VectorBase<StatStor, Bin>,
+ VectorStatData>
+{
+ public:
+ /** The base implementation. */
+ typedef ScalarBase<StatStor, Bin> Base;
+
+ /**
+ * Set this vector to have the given size.
+ * @param size The new size.
+ * @return A reference to this stat.
+ */
+ Vector &init(size_t size) {
+ this->bin.init(size, this->params);
+ this->setInit();
+
+ return *this;
+ }
+};
+
+/**
+ * A vector of Average stats.
+ * @sa Stat, VectorBase, AvgStor
+ */
+template <class Bin = DefaultBin>
+class AverageVector
+ : public WrapVec<AverageVector<Bin>,
+ VectorBase<AvgStor, Bin>,
+ VectorStatData>
+{
+ public:
+ /**
+ * Set this vector to have the given size.
+ * @param size The new size.
+ * @return A reference to this stat.
+ */
+ AverageVector &init(size_t size) {
+ this->bin.init(size, this->params);
+ this->setInit();
+
+ return *this;
+ }
+};
+
+/**
+ * A 2-Dimensional vecto of scalar stats.
+ * @sa Stat, Vector2dBase, StatStor
+ */
+template <class Bin = DefaultBin>
+class Vector2d
+ : public WrapVec2d<Vector2d<Bin>,
+ Vector2dBase<StatStor, Bin>,
+ Vector2dStatData>
+{
+ public:
+ Vector2d &init(size_t _x, size_t _y) {
+ this->statData()->x = this->x = _x;
+ this->statData()->y = this->y = _y;
+ this->bin.init(this->x * this->y, this->params);
+ this->setInit();
+
+ return *this;
+ }
+};
+
+/**
+ * A simple distribution stat.
+ * @sa Stat, DistBase, DistStor
+ */
+template <class Bin = DefaultBin>
+class Distribution
+ : public Wrap<Distribution<Bin>,
+ DistBase<DistStor, Bin>,
+ DistStatData>
+{
+ public:
+ /** Base implementation. */
+ typedef DistBase<DistStor, Bin> Base;
+ /** The Parameter type. */
+ typedef typename DistStor::Params Params;
+
+ public:
+ /**
+ * Set the parameters of this distribution. @sa DistStor::Params
+ * @param min The minimum value of the distribution.
+ * @param max The maximum value of the distribution.
+ * @param bkt The number of values in each bucket.
+ * @return A reference to this distribution.
+ */
+ Distribution &init(Counter min, Counter max, Counter bkt) {
+ this->params.min = min;
+ this->params.max = max;
+ this->params.bucket_size = bkt;
+ this->params.size = (int)rint((max - min) / bkt + 1.0);
+ this->bin.init(this->params);
+ this->setInit();
+
+ return *this;
+ }
+};
+
+/**
+ * Calculates the mean and variance of all the samples.
+ * @sa Stat, DistBase, FancyStor
+ */
+template <class Bin = DefaultBin>
+class StandardDeviation
+ : public Wrap<StandardDeviation<Bin>,
+ DistBase<FancyStor, Bin>,
+ DistStatData>
+{
+ public:
+ /** The base implementation */
+ typedef DistBase<DistStor, Bin> Base;
+ /** The parameter type. */
+ typedef typename DistStor::Params Params;
+
+ public:
+ /**
+ * Construct and initialize this distribution.
+ */
+ StandardDeviation() {
+ this->bin.init(this->params);
+ this->setInit();
+ }
+};
+
+/**
+ * Calculates the per cycle mean and variance of the samples.
+ * @sa Stat, DistBase, AvgFancy
+ */
+template <class Bin = DefaultBin>
+class AverageDeviation
+ : public Wrap<AverageDeviation<Bin>,
+ DistBase<AvgFancy, Bin>,
+ DistStatData>
+{
+ public:
+ /** The base implementation */
+ typedef DistBase<DistStor, Bin> Base;
+ /** The parameter type. */
+ typedef typename DistStor::Params Params;
+
+ public:
+ /**
+ * Construct and initialize this distribution.
+ */
+ AverageDeviation()
+ {
+ this->bin.init(this->params);
+ this->setInit();
+ }
+};
+
+/**
+ * A vector of distributions.
+ * @sa Stat, VectorDistBase, DistStor
+ */
+template <class Bin = DefaultBin>
+class VectorDistribution
+ : public WrapVec<VectorDistribution<Bin>,
+ VectorDistBase<DistStor, Bin>,
+ VectorDistStatData>
+{
+ public:
+ /** The base implementation */
+ typedef VectorDistBase<DistStor, Bin> Base;
+ /** The parameter type. */
+ typedef typename DistStor::Params Params;
+
+ public:
+ /**
+ * Initialize storage and parameters for this distribution.
+ * @param size The size of the vector (the number of distributions).
+ * @param min The minimum value of the distribution.
+ * @param max The maximum value of the distribution.
+ * @param bkt The number of values in each bucket.
+ * @return A reference to this distribution.
+ */
+ VectorDistribution &init(int size, Counter min, Counter max, Counter bkt) {
+ this->params.min = min;
+ this->params.max = max;
+ this->params.bucket_size = bkt;
+ this->params.size = (int)rint((max - min) / bkt + 1.0);
+ this->bin.init(size, this->params);
+ this->setInit();
+
+ return *this;
+ }
+};
+
+/**
+ * This is a vector of StandardDeviation stats.
+ * @sa Stat, VectorDistBase, FancyStor
+ */
+template <class Bin = DefaultBin>
+class VectorStandardDeviation
+ : public WrapVec<VectorStandardDeviation<Bin>,
+ VectorDistBase<FancyStor, Bin>,
+ VectorDistStatData>
+{
+ public:
+ /** The base implementation */
+ typedef VectorDistBase<FancyStor, Bin> Base;
+ /** The parameter type. */
+ typedef typename DistStor::Params Params;
+
+ public:
+ /**
+ * Initialize storage for this distribution.
+ * @param size The size of the vector.
+ * @return A reference to this distribution.
+ */
+ VectorStandardDeviation &init(int size) {
+ this->bin.init(size, this->params);
+ this->setInit();
+
+ return *this;
+ }
+};
+
+/**
+ * This is a vector of AverageDeviation stats.
+ * @sa Stat, VectorDistBase, AvgFancy
+ */
+template <class Bin = DefaultBin>
+class VectorAverageDeviation
+ : public WrapVec<VectorAverageDeviation<Bin>,
+ VectorDistBase<AvgFancy, Bin>,
+ VectorDistStatData>
+{
+ public:
+ /** The base implementation */
+ typedef VectorDistBase<AvgFancy, Bin> Base;
+ /** The parameter type. */
+ typedef typename DistStor::Params Params;
+
+ public:
+ /**
+ * Initialize storage for this distribution.
+ * @param size The size of the vector.
+ * @return A reference to this distribution.
+ */
+ VectorAverageDeviation &init(int size) {
+ this->bin.init(size, this->params);
+ this->setInit();
+
+ return *this;
+ }
+};
+
+/**
+ * A formula for statistics that is calculated when printed. A formula is
+ * stored as a tree of Nodes that represent the equation to calculate.
+ * @sa Stat, ScalarStat, VectorStat, Node, Temp
+ */
+class FormulaBase : public DataAccess
+{
+ protected:
+ /** The root of the tree which represents the Formula */
+ NodePtr root;
+ friend class Temp;
+
+ public:
+ /**
+ * Return the result of the Fomula in a vector. If there were no Vector
+ * components to the Formula, then the vector is size 1. If there were,
+ * like x/y with x being a vector of size 3, then the result returned will
+ * be x[0]/y, x[1]/y, x[2]/y, respectively.
+ * @return The result vector.
+ */
+ void result(VResult &vec) const;
+
+ /**
+ * Return the total Formula result. If there is a Vector
+ * component to this Formula, then this is the result of the
+ * Formula if the formula is applied after summing all the
+ * components of the Vector. For example, if Formula is x/y where
+ * x is size 3, then total() will return (x[1]+x[2]+x[3])/y. If
+ * there is no Vector component, total() returns the same value as
+ * the first entry in the VResult val() returns.
+ * @return The total of the result vector.
+ */
+ Result total() const;
+
+ /**
+ * Return the number of elements in the tree.
+ */
+ size_t size() const;
+
+ /**
+ * Return true if Formula is binned. i.e. any of its children
+ * nodes are binned
+ * @return True if Formula is binned.
+ */
+ bool binned() const;
+
+ bool check() const { return true; }
+
+ /**
+ * Formulas don't need to be reset
+ */
+ void reset();
+
+ /**
+ *
+ */
+ bool zero() const;
+
+ /**
+ *
+ */
+ void update(StatData *);
+
+ std::string str() const;
+};
+
+class FormulaData : public VectorData
+{
+ public:
+ virtual std::string str() const = 0;
+ virtual bool check() const { return true; }
+};
+
+template <class Stat>
+class FormulaStatData : public FormulaData
+{
+ protected:
+ Stat &s;
+ mutable VResult vec;
+ mutable VCounter cvec;
+
+ public:
+ FormulaStatData(Stat &stat) : s(stat) {}
+
+ virtual bool binned() const { return s.binned(); }
+ virtual bool zero() const { return s.zero(); }
+ virtual void reset() { s.reset(); }
+
+ virtual size_t size() const { return s.size(); }
+ virtual const VResult &result() const
+ {
+ s.result(vec);
+ return vec;
+ }
+ virtual Result total() const { return s.total(); }
+ virtual VCounter &value() const { return cvec; }
+ virtual void visit(Visit &visitor)
+ {
+ update();
+ s.update(this);
+ visitor.visit(*this);
+ }
+ virtual std::string str() const { return s.str(); }
+};
+
+class Temp;
+class Formula
+ : public WrapVec<Formula,
+ FormulaBase,
+ FormulaStatData>
+{
+ public:
+ /**
+ * Create and initialize thie formula, and register it with the database.
+ */
+ Formula();
+
+ /**
+ * Create a formula with the given root node, register it with the
+ * database.
+ * @param r The root of the expression tree.
+ */
+ Formula(Temp r);
+
+ /**
+ * Set an unitialized Formula to the given root.
+ * @param r The root of the expression tree.
+ * @return a reference to this formula.
+ */
+ const Formula &operator=(Temp r);
+
+ /**
+ * Add the given tree to the existing one.
+ * @param r The root of the expression tree.
+ * @return a reference to this formula.
+ */
+ const Formula &operator+=(Temp r);
+};
+
+class FormulaNode : public Node
+{
+ private:
+ const Formula &formula;
+ mutable VResult vec;
+
+ public:
+ FormulaNode(const Formula &f) : formula(f) {}
+
+ virtual size_t size() const { return formula.size(); }
+ virtual const VResult &result() const { formula.result(vec); return vec; }
+ virtual Result total() const { return formula.total(); }
+ virtual bool binned() const { return formula.binned(); }
+
+ virtual std::string str() const { return formula.str(); }
+};
+
+/**
+ * Helper class to construct formula node trees.
+ */
+class Temp
+{
+ protected:
+ /**
+ * Pointer to a Node object.
+ */
+ NodePtr node;
+
+ public:
+ /**
+ * Copy the given pointer to this class.
+ * @param n A pointer to a Node object to copy.
+ */
+ Temp(NodePtr n) : node(n) { }
+
+ /**
+ * Return the node pointer.
+ * @return the node pointer.
+ */
+ operator NodePtr&() { return node;}
+
+ public:
+ /**
+ * Create a new ScalarStatNode.
+ * @param s The ScalarStat to place in a node.
+ */
+ template <class Bin>
+ Temp(const Scalar<Bin> &s)
+ : node(new ScalarStatNode(s.statData())) { }
+
+ /**
+ * Create a new ScalarStatNode.
+ * @param s The ScalarStat to place in a node.
+ */
+ Temp(const Value &s)
+ : node(new ScalarStatNode(s.statData())) { }
+
+ /**
+ * Create a new ScalarStatNode.
+ * @param s The ScalarStat to place in a node.
+ */
+ template <class Bin>
+ Temp(const Average<Bin> &s)
+ : node(new ScalarStatNode(s.statData())) { }
+
+ /**
+ * Create a new VectorStatNode.
+ * @param s The VectorStat to place in a node.
+ */
+ template <class Bin>
+ Temp(const Vector<Bin> &s)
+ : node(new VectorStatNode(s.statData())) { }
+
+ /**
+ *
+ */
+ Temp(const Formula &f)
+ : node(new FormulaNode(f)) { }
+
+ /**
+ * Create a new ScalarProxyNode.
+ * @param p The ScalarProxy to place in a node.
+ */
+ template <class Storage, class Bin>
+ Temp(const ScalarProxy<Storage, Bin> &p)
+ : node(new ScalarProxyNode<Storage, Bin>(p)) { }
+
+ /**
+ * Create a ConstNode
+ * @param value The value of the const node.
+ */
+ Temp(signed char value)
+ : node(new ConstNode<signed char>(value)) {}
+
+ /**
+ * Create a ConstNode
+ * @param value The value of the const node.
+ */
+ Temp(unsigned char value)
+ : node(new ConstNode<unsigned char>(value)) {}
+
+ /**
+ * Create a ConstNode
+ * @param value The value of the const node.
+ */
+ Temp(signed short value)
+ : node(new ConstNode<signed short>(value)) {}
+
+ /**
+ * Create a ConstNode
+ * @param value The value of the const node.
+ */
+ Temp(unsigned short value)
+ : node(new ConstNode<unsigned short>(value)) {}
+
+ /**
+ * Create a ConstNode
+ * @param value The value of the const node.
+ */
+ Temp(signed int value)
+ : node(new ConstNode<signed int>(value)) {}
+
+ /**
+ * Create a ConstNode
+ * @param value The value of the const node.
+ */
+ Temp(unsigned int value)
+ : node(new ConstNode<unsigned int>(value)) {}
+
+ /**
+ * Create a ConstNode
+ * @param value The value of the const node.
+ */
+ Temp(signed long value)
+ : node(new ConstNode<signed long>(value)) {}
+
+ /**
+ * Create a ConstNode
+ * @param value The value of the const node.
+ */
+ Temp(unsigned long value)
+ : node(new ConstNode<unsigned long>(value)) {}
+
+ /**
+ * Create a ConstNode
+ * @param value The value of the const node.
+ */
+ Temp(signed long long value)
+ : node(new ConstNode<signed long long>(value)) {}
+
+ /**
+ * Create a ConstNode
+ * @param value The value of the const node.
+ */
+ Temp(unsigned long long value)
+ : node(new ConstNode<unsigned long long>(value)) {}
+
+ /**
+ * Create a ConstNode
+ * @param value The value of the const node.
+ */
+ Temp(float value)
+ : node(new ConstNode<float>(value)) {}
+
+ /**
+ * Create a ConstNode
+ * @param value The value of the const node.
+ */
+ Temp(double value)
+ : node(new ConstNode<double>(value)) {}
+};
+
+
+/**
+ * @}
+ */
+
+void check();
+void reset();
+void registerResetCallback(Callback *cb);
+
+inline Temp
+operator+(Temp l, Temp r)
+{
+ return NodePtr(new BinaryNode<std::plus<Result> >(l, r));
+}
+
+inline Temp
+operator-(Temp l, Temp r)
+{
+ return NodePtr(new BinaryNode<std::minus<Result> >(l, r));
+}
+
+inline Temp
+operator*(Temp l, Temp r)
+{
+ return NodePtr(new BinaryNode<std::multiplies<Result> >(l, r));
+}
+
+inline Temp
+operator/(Temp l, Temp r)
+{
+ return NodePtr(new BinaryNode<std::divides<Result> >(l, r));
+}
+
+inline Temp
+operator-(Temp l)
+{
+ return NodePtr(new UnaryNode<std::negate<Result> >(l));
+}
+
+template <typename T>
+inline Temp
+constant(T val)
+{
+ return NodePtr(new ConstNode<T>(val));
+}
+
+inline Temp
+sum(Temp val)
+{
+ return NodePtr(new SumNode<std::plus<Result> >(val));
+}
+
+/* namespace Stats */ }
+
+#endif // __BASE_STATISTICS_HH__
diff --git a/base/stats/events.cc b/src/base/stats/events.cc
index 3191aec13..3191aec13 100644
--- a/base/stats/events.cc
+++ b/src/base/stats/events.cc
diff --git a/base/stats/events.hh b/src/base/stats/events.hh
index 2a23240b4..2a23240b4 100644
--- a/base/stats/events.hh
+++ b/src/base/stats/events.hh
diff --git a/base/stats/flags.hh b/src/base/stats/flags.hh
index 00db95bc1..00db95bc1 100644
--- a/base/stats/flags.hh
+++ b/src/base/stats/flags.hh
diff --git a/base/stats/mysql.cc b/src/base/stats/mysql.cc
index 6d12b4fc1..6d12b4fc1 100644
--- a/base/stats/mysql.cc
+++ b/src/base/stats/mysql.cc
diff --git a/base/stats/mysql.hh b/src/base/stats/mysql.hh
index 25ea22b97..25ea22b97 100644
--- a/base/stats/mysql.hh
+++ b/src/base/stats/mysql.hh
diff --git a/base/stats/mysql_run.hh b/src/base/stats/mysql_run.hh
index d8dcb7594..d8dcb7594 100644
--- a/base/stats/mysql_run.hh
+++ b/src/base/stats/mysql_run.hh
diff --git a/base/stats/output.hh b/src/base/stats/output.hh
index ee6b38d63..ee6b38d63 100644
--- a/base/stats/output.hh
+++ b/src/base/stats/output.hh
diff --git a/base/stats/statdb.cc b/src/base/stats/statdb.cc
index a6b00ab8a..a6b00ab8a 100644
--- a/base/stats/statdb.cc
+++ b/src/base/stats/statdb.cc
diff --git a/base/stats/statdb.hh b/src/base/stats/statdb.hh
index eb56d8fac..eb56d8fac 100644
--- a/base/stats/statdb.hh
+++ b/src/base/stats/statdb.hh
diff --git a/src/base/stats/text.cc b/src/base/stats/text.cc
new file mode 100644
index 000000000..300737c60
--- /dev/null
+++ b/src/base/stats/text.cc
@@ -0,0 +1,736 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if defined(__APPLE__)
+#define _GLIBCPP_USE_C99 1
+#endif
+
+#include <iostream>
+#include <sstream>
+#include <fstream>
+#include <string>
+
+#include "base/misc.hh"
+#include "base/statistics.hh"
+#include "base/stats/statdb.hh"
+#include "base/stats/text.hh"
+#include "base/stats/visit.hh"
+
+using namespace std;
+
+#ifndef NAN
+float __nan();
+/** Define Not a number. */
+#define NAN (__nan())
+/** Need to define __nan() */
+#define __M5_NAN
+#endif
+
+#ifdef __M5_NAN
+float
+__nan()
+{
+ union {
+ uint32_t ui;
+ float f;
+ } nan;
+
+ nan.ui = 0x7fc00000;
+ return nan.f;
+}
+#endif
+
+namespace Stats {
+
+Text::Text()
+ : mystream(false), stream(NULL), compat(false), descriptions(false)
+{
+}
+
+Text::Text(std::ostream &stream)
+ : mystream(false), stream(NULL), compat(false), descriptions(false)
+{
+ open(stream);
+}
+
+Text::Text(const std::string &file)
+ : mystream(false), stream(NULL), compat(false), descriptions(false)
+{
+ open(file);
+}
+
+
+Text::~Text()
+{
+ if (mystream) {
+ assert(stream);
+ delete stream;
+ }
+}
+
+void
+Text::open(std::ostream &_stream)
+{
+ if (stream)
+ panic("stream already set!");
+
+ mystream = false;
+ stream = &_stream;
+ assert(valid());
+}
+
+void
+Text::open(const std::string &file)
+{
+ if (stream)
+ panic("stream already set!");
+
+ mystream = true;
+ stream = new ofstream(file.c_str(), ios::trunc);
+ assert(valid());
+}
+
+bool
+Text::valid() const
+{
+ return stream != NULL;
+}
+
+void
+Text::output()
+{
+ using namespace Database;
+
+ ccprintf(*stream, "\n---------- Begin Simulation Statistics ----------\n");
+ if (bins().empty() || bins().size() == 1) {
+ stat_list_t::const_iterator i, end = stats().end();
+ for (i = stats().begin(); i != end; ++i)
+ (*i)->visit(*this);
+ } else {
+ ccprintf(*stream, "PRINTING BINNED STATS\n");
+ bin_list_t::iterator i, end = bins().end();
+ for (i = bins().begin(); i != end; ++i) {
+ MainBin *bin = *i;
+ bin->activate();
+ ccprintf(*stream,"---%s Bin------------\n", bin->name());
+ stat_list_t::const_iterator i, end = stats().end();
+ for (i = stats().begin(); i != end; ++i)
+ (*i)->visit(*this);
+ ccprintf(*stream, "---------------------------------\n");
+ }
+ }
+ ccprintf(*stream, "\n---------- End Simulation Statistics ----------\n");
+ stream->flush();
+}
+
+bool
+Text::noOutput(const StatData &data)
+{
+ if (!(data.flags & print))
+ return true;
+
+ if (data.prereq && data.prereq->zero())
+ return true;
+
+ return false;
+}
+
+string
+ValueToString(Result value, int precision, bool compat)
+{
+ stringstream val;
+
+ if (!isnan(value)) {
+ if (precision != -1)
+ val.precision(precision);
+ else if (value == rint(value))
+ val.precision(0);
+
+ val.unsetf(ios::showpoint);
+ val.setf(ios::fixed);
+ val << value;
+ } else {
+ val << (compat ? "<err: div-0>" : "no value");
+ }
+
+ return val.str();
+}
+
+struct ScalarPrint
+{
+ Result value;
+ string name;
+ string desc;
+ StatFlags flags;
+ bool compat;
+ bool descriptions;
+ int precision;
+ Result pdf;
+ Result cdf;
+
+ void operator()(ostream &stream) const;
+};
+
+void
+ScalarPrint::operator()(ostream &stream) const
+{
+ if (flags & nozero && value == 0.0 ||
+ flags & nonan && isnan(value))
+ return;
+
+ stringstream pdfstr, cdfstr;
+
+ if (!isnan(pdf))
+ ccprintf(pdfstr, "%.2f%%", pdf * 100.0);
+
+ if (!isnan(cdf))
+ ccprintf(cdfstr, "%.2f%%", cdf * 100.0);
+
+ if (compat && flags & __substat) {
+ ccprintf(stream, "%32s %12s %10s %10s", name,
+ ValueToString(value, precision, compat), pdfstr, cdfstr);
+ } else {
+ ccprintf(stream, "%-40s %12s %10s %10s", name,
+ ValueToString(value, precision, compat), pdfstr, cdfstr);
+ }
+
+ if (descriptions) {
+ if (!desc.empty())
+ ccprintf(stream, " # %s", desc);
+ }
+ stream << endl;
+}
+
+struct VectorPrint
+{
+ string name;
+ string desc;
+ vector<string> subnames;
+ vector<string> subdescs;
+ StatFlags flags;
+ bool compat;
+ bool descriptions;
+ int precision;
+ VResult vec;
+ Result total;
+
+ void operator()(ostream &stream) const;
+};
+
+void
+VectorPrint::operator()(std::ostream &stream) const
+{
+ int _size = vec.size();
+ Result _total = 0.0;
+
+ if (flags & (pdf | cdf)) {
+ for (int i = 0; i < _size; ++i) {
+ _total += vec[i];
+ }
+ }
+
+ string base = name + (compat ? "_" : "::");
+
+ ScalarPrint print;
+ print.name = name;
+ print.desc = desc;
+ print.precision = precision;
+ print.descriptions = descriptions;
+ print.flags = flags;
+ print.pdf = NAN;
+ print.cdf = NAN;
+
+ bool havesub = !subnames.empty();
+
+ if (_size == 1) {
+ print.value = vec[0];
+ print(stream);
+ } else if (!compat) {
+ for (int i = 0; i < _size; ++i) {
+ if (havesub && (i >= subnames.size() || subnames[i].empty()))
+ continue;
+
+ print.name = base + (havesub ? subnames[i] : to_string(i));
+ print.desc = subdescs.empty() ? desc : subdescs[i];
+ print.value = vec[i];
+
+ if (_total && (flags & pdf)) {
+ print.pdf = vec[i] / _total;
+ print.cdf += print.pdf;
+ }
+
+ print(stream);
+ }
+
+ if (flags & ::Stats::total) {
+ print.name = base + "total";
+ print.desc = desc;
+ print.value = total;
+ print(stream);
+ }
+ } else {
+ if (flags & ::Stats::total) {
+ print.value = total;
+ print(stream);
+ }
+
+ Result _pdf = 0.0;
+ Result _cdf = 0.0;
+ if (flags & dist) {
+ ccprintf(stream, "%s.start_dist\n", name);
+ for (int i = 0; i < _size; ++i) {
+ print.name = havesub ? subnames[i] : to_string(i);
+ print.desc = subdescs.empty() ? desc : subdescs[i];
+ print.flags |= __substat;
+ print.value = vec[i];
+
+ if (_total) {
+ _pdf = vec[i] / _total;
+ _cdf += _pdf;
+ }
+
+ if (flags & pdf)
+ print.pdf = _pdf;
+ if (flags & cdf)
+ print.cdf = _cdf;
+
+ print(stream);
+ }
+ ccprintf(stream, "%s.end_dist\n", name);
+ } else {
+ for (int i = 0; i < _size; ++i) {
+ if (havesub && subnames[i].empty())
+ continue;
+
+ print.name = base;
+ print.name += havesub ? subnames[i] : to_string(i);
+ print.desc = subdescs.empty() ? desc : subdescs[i];
+ print.value = vec[i];
+
+ if (_total) {
+ _pdf = vec[i] / _total;
+ _cdf += _pdf;
+ } else {
+ _pdf = _cdf = NAN;
+ }
+
+ if (flags & pdf) {
+ print.pdf = _pdf;
+ print.cdf = _cdf;
+ }
+
+ print(stream);
+ }
+ }
+ }
+}
+
+struct DistPrint
+{
+ string name;
+ string desc;
+ StatFlags flags;
+ bool compat;
+ bool descriptions;
+ int precision;
+
+ Result min_val;
+ Result max_val;
+ Result underflow;
+ Result overflow;
+ VResult vec;
+ Result sum;
+ Result squares;
+ Result samples;
+
+ Counter min;
+ Counter max;
+ Counter bucket_size;
+ int size;
+ bool fancy;
+
+ void operator()(ostream &stream) const;
+};
+
+void
+DistPrint::operator()(ostream &stream) const
+{
+ if (fancy) {
+ ScalarPrint print;
+ string base = name + (compat ? "_" : "::");
+
+ print.precision = precision;
+ print.flags = flags;
+ print.compat = compat;
+ print.descriptions = descriptions;
+ print.desc = desc;
+ print.pdf = NAN;
+ print.cdf = NAN;
+
+ print.name = base + "mean";
+ print.value = samples ? sum / samples : NAN;
+ print(stream);
+
+ print.name = base + "stdev";
+ print.value = samples ? sqrt((samples * squares - sum * sum) /
+ (samples * (samples - 1.0))) : NAN;
+ print(stream);
+
+ print.name = "**Ignore: " + base + "TOT";
+ print.value = samples;
+ print(stream);
+ return;
+ }
+
+ assert(size == vec.size());
+
+ Result total = 0.0;
+
+ total += underflow;
+ for (int i = 0; i < size; ++i)
+ total += vec[i];
+ total += overflow;
+
+ string base = name + (compat ? "." : "::");
+
+ ScalarPrint print;
+ print.desc = compat ? "" : desc;
+ print.flags = flags;
+ print.compat = compat;
+ print.descriptions = descriptions;
+ print.precision = precision;
+ print.pdf = NAN;
+ print.cdf = NAN;
+
+ if (compat) {
+ ccprintf(stream, "%-42s", base + "start_dist");
+ if (descriptions && !desc.empty())
+ ccprintf(stream, " # %s", desc);
+ stream << endl;
+ }
+
+ print.name = base + "samples";
+ print.value = samples;
+ print(stream);
+
+ print.name = base + "min_value";
+ print.value = min_val;
+ print(stream);
+
+ if (!compat || underflow > 0.0) {
+ print.name = base + "underflows";
+ print.value = underflow;
+ if (!compat && total) {
+ print.pdf = underflow / total;
+ print.cdf += print.pdf;
+ }
+ print(stream);
+ }
+
+
+ if (!compat) {
+ for (int i = 0; i < size; ++i) {
+ stringstream namestr;
+ namestr << name;
+
+ Counter low = i * bucket_size + min;
+ Counter high = ::min(low + bucket_size, max);
+ namestr << low;
+ if (low < high)
+ namestr << "-" << high;
+
+ print.name = namestr.str();
+ print.value = vec[i];
+ if (total) {
+ print.pdf = vec[i] / total;
+ print.cdf += print.pdf;
+ }
+ print(stream);
+ }
+
+ } else {
+ Counter _min;
+ Result _pdf;
+ Result _cdf = 0.0;
+
+ print.flags = flags | __substat;
+
+ for (int i = 0; i < size; ++i) {
+ if (flags & nozero && vec[i] == 0.0 ||
+ flags & nonan && isnan(vec[i]))
+ continue;
+
+ _min = i * bucket_size + min;
+ _pdf = vec[i] / total * 100.0;
+ _cdf += _pdf;
+
+
+ print.name = ValueToString(_min, 0, compat);
+ print.value = vec[i];
+ print.pdf = (flags & pdf) ? _pdf : NAN;
+ print.cdf = (flags & cdf) ? _cdf : NAN;
+ print(stream);
+ }
+
+ print.flags = flags;
+ }
+
+ if (!compat || overflow > 0.0) {
+ print.name = base + "overflows";
+ print.value = overflow;
+ if (!compat && total) {
+ print.pdf = overflow / total;
+ print.cdf += print.pdf;
+ } else {
+ print.pdf = NAN;
+ print.cdf = NAN;
+ }
+ print(stream);
+ }
+
+ print.pdf = NAN;
+ print.cdf = NAN;
+
+ if (!compat) {
+ print.name = base + "total";
+ print.value = total;
+ print(stream);
+ }
+
+ print.name = base + "max_value";
+ print.value = max_val;
+ print(stream);
+
+ if (!compat && samples != 0) {
+ print.name = base + "mean";
+ print.value = sum / samples;
+ print(stream);
+
+ print.name = base + "stdev";
+ print.value = sqrt((samples * squares - sum * sum) /
+ (samples * (samples - 1.0)));
+ print(stream);
+ }
+
+ if (compat)
+ ccprintf(stream, "%send_dist\n\n", base);
+}
+
+void
+Text::visit(const ScalarData &data)
+{
+ if (noOutput(data))
+ return;
+
+ ScalarPrint print;
+ print.value = data.result();
+ print.name = data.name;
+ print.desc = data.desc;
+ print.flags = data.flags;
+ print.compat = compat;
+ print.descriptions = descriptions;
+ print.precision = data.precision;
+ print.pdf = NAN;
+ print.cdf = NAN;
+
+ print(*stream);
+}
+
+void
+Text::visit(const VectorData &data)
+{
+ if (noOutput(data))
+ return;
+
+ int size = data.size();
+ VectorPrint print;
+
+ print.name = data.name;
+ print.desc = data.desc;
+ print.flags = data.flags;
+ print.compat = compat;
+ print.descriptions = descriptions;
+ print.precision = data.precision;
+ print.vec = data.result();
+ print.total = data.total();
+
+ if (!data.subnames.empty()) {
+ for (int i = 0; i < size; ++i) {
+ if (!data.subnames[i].empty()) {
+ print.subnames = data.subnames;
+ print.subnames.resize(size);
+ for (int i = 0; i < size; ++i) {
+ if (!data.subnames[i].empty() &&
+ !data.subdescs[i].empty()) {
+ print.subdescs = data.subdescs;
+ print.subdescs.resize(size);
+ break;
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ print(*stream);
+}
+
+void
+Text::visit(const Vector2dData &data)
+{
+ if (noOutput(data))
+ return;
+
+ bool havesub = false;
+ VectorPrint print;
+
+ print.subnames = data.y_subnames;
+ print.flags = data.flags;
+ print.compat = compat;
+ print.descriptions = descriptions;
+ print.precision = data.precision;
+
+ if (!data.subnames.empty()) {
+ for (int i = 0; i < data.x; ++i)
+ if (!data.subnames[i].empty())
+ havesub = true;
+ }
+
+ VResult tot_vec(data.y);
+ Result super_total = 0.0;
+ for (int i = 0; i < data.x; ++i) {
+ if (havesub && (i >= data.subnames.size() || data.subnames[i].empty()))
+ continue;
+
+ int iy = i * data.y;
+ VResult yvec(data.y);
+
+ Result total = 0.0;
+ for (int j = 0; j < data.y; ++j) {
+ yvec[j] = data.cvec[iy + j];
+ tot_vec[j] += yvec[j];
+ total += yvec[j];
+ super_total += yvec[j];
+ }
+
+ print.name = data.name + "_" + (havesub ? data.subnames[i] : to_string(i));
+ print.desc = data.desc;
+ print.vec = yvec;
+ print.total = total;
+ print(*stream);
+ }
+
+ if ((data.flags & ::Stats::total) && (data.x > 1)) {
+ print.name = data.name;
+ print.desc = data.desc;
+ print.vec = tot_vec;
+ print.total = super_total;
+ print(*stream);
+ }
+}
+
+void
+Text::visit(const DistData &data)
+{
+ if (noOutput(data))
+ return;
+
+ DistPrint print;
+
+ print.name = data.name;
+ print.desc = data.desc;
+ print.flags = data.flags;
+ print.compat = compat;
+ print.descriptions = descriptions;
+ print.precision = data.precision;
+
+ print.min_val = data.data.min_val;
+ print.max_val = data.data.max_val;
+ print.underflow = data.data.underflow;
+ print.overflow = data.data.overflow;
+ print.vec.resize(data.data.cvec.size());
+ for (int i = 0; i < print.vec.size(); ++i)
+ print.vec[i] = (Result)data.data.cvec[i];
+ print.sum = data.data.sum;
+ print.squares = data.data.squares;
+ print.samples = data.data.samples;
+
+ print.min = data.data.min;
+ print.max = data.data.max;
+ print.bucket_size = data.data.bucket_size;
+ print.size = data.data.size;
+ print.fancy = data.data.fancy;
+
+ print(*stream);
+}
+
+void
+Text::visit(const VectorDistData &data)
+{
+ if (noOutput(data))
+ return;
+
+ for (int i = 0; i < data.size(); ++i) {
+ DistPrint print;
+
+ print.name = data.name +
+ (data.subnames[i].empty() ? ("_" + to_string(i)) : data.subnames[i]);
+ print.desc = data.subdescs[i].empty() ? data.desc : data.subdescs[i];
+ print.flags = data.flags;
+ print.compat = compat;
+ print.descriptions = descriptions;
+ print.precision = data.precision;
+
+ print.min_val = data.data[i].min_val;
+ print.max_val = data.data[i].max_val;
+ print.underflow = data.data[i].underflow;
+ print.overflow = data.data[i].overflow;
+ print.vec.resize(data.data[i].cvec.size());
+ for (int j = 0; j < print.vec.size(); ++j)
+ print.vec[j] = (Result)data.data[i].cvec[j];
+ print.sum = data.data[i].sum;
+ print.squares = data.data[i].squares;
+ print.samples = data.data[i].samples;
+
+ print.min = data.data[i].min;
+ print.max = data.data[i].max;
+ print.bucket_size = data.data[i].bucket_size;
+ print.size = data.data[i].size;
+ print.fancy = data.data[i].fancy;
+
+ print(*stream);
+ }
+}
+
+void
+Text::visit(const FormulaData &data)
+{
+ visit((const VectorData &)data);
+}
+
+/* namespace Stats */ }
diff --git a/base/stats/text.hh b/src/base/stats/text.hh
index 125cb79fa..125cb79fa 100644
--- a/base/stats/text.hh
+++ b/src/base/stats/text.hh
diff --git a/base/stats/types.hh b/src/base/stats/types.hh
index 57f1564a5..57f1564a5 100644
--- a/base/stats/types.hh
+++ b/src/base/stats/types.hh
diff --git a/base/stats/visit.cc b/src/base/stats/visit.cc
index dd4d49502..dd4d49502 100644
--- a/base/stats/visit.cc
+++ b/src/base/stats/visit.cc
diff --git a/base/stats/visit.hh b/src/base/stats/visit.hh
index c0593c670..c0593c670 100644
--- a/base/stats/visit.hh
+++ b/src/base/stats/visit.hh
diff --git a/base/str.cc b/src/base/str.cc
index 5f7f50286..5f7f50286 100644
--- a/base/str.cc
+++ b/src/base/str.cc
diff --git a/base/str.hh b/src/base/str.hh
index 79e33a1be..79e33a1be 100644
--- a/base/str.hh
+++ b/src/base/str.hh
diff --git a/base/time.cc b/src/base/time.cc
index 5827c9a85..5827c9a85 100644
--- a/base/time.cc
+++ b/src/base/time.cc
diff --git a/base/time.hh b/src/base/time.hh
index 5731e3029..5731e3029 100644
--- a/base/time.hh
+++ b/src/base/time.hh
diff --git a/base/timebuf.hh b/src/base/timebuf.hh
index f6b5b2781..f6b5b2781 100644
--- a/base/timebuf.hh
+++ b/src/base/timebuf.hh
diff --git a/base/trace.cc b/src/base/trace.cc
index 90db7f045..90db7f045 100644
--- a/base/trace.cc
+++ b/src/base/trace.cc
diff --git a/base/trace.hh b/src/base/trace.hh
index 5e14f1bff..5e14f1bff 100644
--- a/base/trace.hh
+++ b/src/base/trace.hh
diff --git a/src/base/traceflags.py b/src/base/traceflags.py
new file mode 100644
index 000000000..9797e4cb7
--- /dev/null
+++ b/src/base/traceflags.py
@@ -0,0 +1,289 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2004-2005 The Regents of The University of Michigan
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met: redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer;
+# redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution;
+# neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#
+# This file generates the header and source files for the flags
+# that control the tracing facility.
+#
+
+import sys
+
+if len(sys.argv) != 2:
+ print "%s: Need argument (basename of cc/hh files)" % sys.argv[0]
+ sys.exit(1)
+
+hhfilename = sys.argv[1] + '.hh'
+ccfilename = sys.argv[1] + '.cc'
+
+#
+# The list of trace flags that can be used to condition DPRINTFs etc.
+# To define a new flag, simply add it to this list.
+#
+baseFlags = [
+ 'AlphaConsole',
+ 'BADADDR',
+ 'BPredRAS',
+ 'Bus',
+ 'BusAddrRanges',
+ 'BusBridge',
+ 'Cache',
+ 'Chains',
+ 'Clock',
+ 'Commit',
+ 'CommitRate',
+ 'Config',
+ 'Console',
+ 'ConsolePoll',
+ 'ConsoleVerbose',
+ 'Context',
+ 'Cycle',
+ 'DMA',
+ 'DMAReadVerbose',
+ 'DMAWriteVerbose',
+ 'DebugPrintf',
+ 'Decode',
+ 'DiskImage',
+ 'DiskImageRead',
+ 'DiskImageWrite',
+ 'DynInst',
+ 'Ethernet',
+ 'EthernetCksum',
+ 'EthernetDMA',
+ 'EthernetData',
+ 'EthernetDesc',
+ 'EthernetIntr',
+ 'EthernetPIO',
+ 'EthernetSM',
+ 'Event',
+ 'Fault',
+ 'Fetch',
+ 'Flow',
+ 'FreeList',
+ 'FullCPU',
+ 'GDBAcc',
+ 'GDBExtra',
+ 'GDBMisc',
+ 'GDBRead',
+ 'GDBRecv',
+ 'GDBSend',
+ 'GDBWrite',
+ 'HWPrefetch',
+ 'IEW',
+ 'IIC',
+ 'IICMore',
+ 'IPI',
+ 'IQ',
+ 'ISP',
+ 'IdeCtrl',
+ 'IdeDisk',
+ 'InstExec',
+ 'Interrupt',
+ 'LSQ',
+ 'LSQUnit',
+ 'Loader',
+ 'MC146818',
+ 'MMU',
+ 'MSHR',
+ 'Mbox',
+ 'MemDepUnit',
+ 'OzoneCPU',
+ 'FE',
+ 'IBE',
+ 'BE',
+ 'OzoneLSQ',
+ ]
+
+#
+# "Compound" flags correspond to a set of base flags. These exist
+# solely for convenience in setting them via the command line: if a
+# compound flag is specified, all of the corresponding base flags are
+# set. Compound flags cannot be used directly in DPRINTFs etc.
+# To define a new compound flag, add a new entry to this hash
+# following the existing examples.
+#
+compoundFlagMap = {
+ 'GDBAll' : [ 'GDBMisc', 'GDBAcc', 'GDBRead', 'GDBWrite', 'GDBSend', 'GDBRecv', 'GDBExtra' ],
+ 'ScsiAll' : [ 'ScsiDisk', 'ScsiCtrl', 'ScsiNone' ],
+ 'DiskImageAll' : [ 'DiskImage', 'DiskImageRead', 'DiskImageWrite' ],
+ 'EthernetAll' : [ 'Ethernet', 'EthernetPIO', 'EthernetDMA', 'EthernetData' , 'EthernetDesc', 'EthernetIntr', 'EthernetSM', 'EthernetCksum' ],
+ 'EthernetNoData' : [ 'Ethernet', 'EthernetPIO', 'EthernetDesc', 'EthernetIntr', 'EthernetSM', 'EthernetCksum' ],
+ 'IdeAll' : [ 'IdeCtrl', 'IdeDisk' ],
+ 'FullCPUAll' : [ 'Fetch', 'Decode', 'Rename', 'IEW', 'Commit', 'IQ', 'ROB', 'FreeList', 'RenameMap', 'LSQ', 'LSQUnit', 'StoreSet', 'MemDepUnit', 'DynInst', 'FullCPU', 'Activity','Scoreboard','Writeback'],
+ 'OzoneCPUAll' : [ 'BE', 'FE', 'IBE', 'OzoneLSQ', 'OzoneCPU']
+}
+
+#############################################################
+#
+# Everything below this point generates the appropriate C++
+# declarations and definitions for the trace flags. If you are simply
+# adding or modifying flag definitions, you should not have to change
+# anything below.
+#
+
+import sys
+
+# extract just the compound flag names into a list
+compoundFlags = []
+compoundFlags.extend(compoundFlagMap.keys())
+compoundFlags.sort()
+
+#
+# First generate the header file. This defines the Flag enum
+# and some extern declarations for the .cc file.
+#
+try:
+ hhfile = file(hhfilename, 'w')
+except IOError, e:
+ sys.exit("can't open %s: %s" % (hhfilename, e))
+
+# file header boilerplate
+print >>hhfile, '''
+/*
+ * DO NOT EDIT THIS FILE!
+ *
+ * Automatically generated from traceflags.py
+ */
+
+#ifndef __BASE_TRACE_FLAGS_HH__
+#define __BASE_TRACE_FLAGS_HH__
+
+namespace Trace {
+
+enum Flags {
+''',
+
+# Generate the enum. Base flags come first, then compound flags.
+idx = 0
+for flag in baseFlags:
+ print >>hhfile, ' %s = %d,' % (flag, idx)
+ idx += 1
+
+numBaseFlags = idx
+print >>hhfile, ' NumFlags = %d,' % idx
+
+# put a comment in here to separate base from compound flags
+print >>hhfile, '''
+ // The remaining enum values are *not* valid indices for Trace::flags.
+ // They are "compound" flags, which correspond to sets of base
+ // flags, and are used only by TraceParamContext::setFlags().
+''',
+
+for flag in compoundFlags:
+ print >>hhfile, ' %s = %d,' % (flag, idx)
+ idx += 1
+
+numCompoundFlags = idx - numBaseFlags
+print >>hhfile, ' NumCompoundFlags = %d' % numCompoundFlags
+
+# trailer boilerplate
+print >>hhfile, '''\
+}; // enum Flags
+
+// Array of strings for SimpleEnumParam
+extern const char *flagStrings[];
+extern const int numFlagStrings;
+
+// Array of arraay pointers: for each compound flag, gives the list of
+// base flags to set. Inidividual flag arrays are terminated by -1.
+extern const Flags *compoundFlags[];
+
+/* namespace Trace */ }
+
+#endif // __BASE_TRACE_FLAGS_HH__
+''',
+
+hhfile.close()
+
+#
+#
+# Print out .cc file with array definitions.
+#
+#
+try:
+ ccfile = file(ccfilename, 'w')
+except OSError, e:
+ sys.exit("can't open %s: %s" % (ccfilename, e))
+
+# file header
+print >>ccfile, '''
+/*
+ * DO NOT EDIT THIS FILE!
+ *
+ * Automatically generated from traceflags.pl.
+ */
+
+#include "base/traceflags.hh"
+
+using namespace Trace;
+
+const char *Trace::flagStrings[] =
+{
+''',
+
+# The string array is used by SimpleEnumParam to map the strings
+# provided by the user to enum values.
+for flag in baseFlags:
+ print >>ccfile, ' "%s",' % flag
+
+for flag in compoundFlags:
+ print >>ccfile, ' "%s",' % flag
+
+print >>ccfile, '};\n'
+
+numFlagStrings = len(baseFlags) + len(compoundFlags);
+
+print >>ccfile, 'const int Trace::numFlagStrings = %d;' % numFlagStrings
+print >>ccfile
+
+#
+# Now define the individual compound flag arrays. There is an array
+# for each compound flag listing the component base flags.
+#
+
+for flag in compoundFlags:
+ flags = compoundFlagMap[flag]
+ flags.append('(Flags)-1')
+ print >>ccfile, 'static const Flags %sMap[] =' % flag
+ print >>ccfile, '{ %s };' % (', '.join(flags))
+ print >>ccfile
+
+#
+# Finally the compoundFlags[] array maps the compound flags
+# to their individual arrays/
+#
+print >>ccfile, 'const Flags *Trace::compoundFlags[] ='
+print >>ccfile, '{'
+
+for flag in compoundFlags:
+ print >>ccfile, ' %sMap,' % flag
+
+# file trailer
+print >>ccfile, '};'
+
+ccfile.close()
+
diff --git a/base/userinfo.cc b/src/base/userinfo.cc
index 15bd72224..15bd72224 100644
--- a/base/userinfo.cc
+++ b/src/base/userinfo.cc
diff --git a/base/userinfo.hh b/src/base/userinfo.hh
index d8ebd443c..d8ebd443c 100644
--- a/base/userinfo.hh
+++ b/src/base/userinfo.hh
diff --git a/src/cpu/SConscript b/src/cpu/SConscript
new file mode 100644
index 000000000..a4cbe2aa6
--- /dev/null
+++ b/src/cpu/SConscript
@@ -0,0 +1,179 @@
+# -*- mode:python -*-
+
+# Copyright (c) 2006 The Regents of The University of Michigan
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met: redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer;
+# redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution;
+# neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import os
+import os.path
+
+# Import build environment variable from SConstruct.
+Import('env')
+
+#################################################################
+#
+# Generate StaticInst execute() method signatures.
+#
+# There must be one signature for each CPU model compiled in.
+# Since the set of compiled-in models is flexible, we generate a
+# header containing the appropriate set of signatures on the fly.
+#
+#################################################################
+
+# CPU model-specific data is contained in cpu_models.py
+# Convert to SCons File node to get path handling
+models_db = File('cpu_models.py')
+# slurp in contents of file
+execfile(models_db.srcnode().abspath)
+
+# Template for execute() signature.
+exec_sig_template = '''
+virtual Fault execute(%s *xc, Trace::InstRecord *traceData) const = 0;
+virtual Fault initiateAcc(%s *xc, Trace::InstRecord *traceData) const
+{ panic("initiateAcc not defined!"); };
+virtual Fault completeAcc(Packet *pkt, %s *xc,
+ Trace::InstRecord *traceData) const
+{ panic("completeAcc not defined!"); };
+'''
+
+mem_ini_sig_template = '''
+virtual Fault initiateAcc(%s *xc, Trace::InstRecord *traceData) const { panic("Not defined!"); };
+'''
+
+mem_comp_sig_template = '''
+virtual Fault completeAcc(uint8_t *data, %s *xc, Trace::InstRecord *traceData) const { panic("Not defined!"); return NoFault; };
+'''
+
+# Generate header.
+def gen_cpu_exec_signatures(target, source, env):
+ f = open(str(target[0]), 'w')
+ print >> f, '''
+#ifndef __CPU_STATIC_INST_EXEC_SIGS_HH__
+#define __CPU_STATIC_INST_EXEC_SIGS_HH__
+'''
+ for cpu in env['CPU_MODELS']:
+ xc_type = CpuModel.dict[cpu].strings['CPU_exec_context']
+ print >> f, exec_sig_template % (xc_type, xc_type, xc_type)
+ print >> f, '''
+#endif // __CPU_STATIC_INST_EXEC_SIGS_HH__
+'''
+
+# Generate string that gets printed when header is rebuilt
+def gen_sigs_string(target, source, env):
+ return "Generating static_inst_exec_sigs.hh: " \
+ + ', '.join(env['CPU_MODELS'])
+
+# Add command to generate header to environment.
+env.Command('static_inst_exec_sigs.hh', models_db,
+ Action(gen_cpu_exec_signatures, gen_sigs_string,
+ varlist = ['CPU_MODELS']))
+
+#################################################################
+#
+# Include CPU-model-specific files based on set of models
+# specified in CPU_MODELS build option.
+#
+#################################################################
+
+sources = []
+
+need_simple_base = False
+if 'AtomicSimpleCPU' in env['CPU_MODELS']:
+ need_simple_base = True
+ sources += Split('simple/atomic.cc')
+
+if 'TimingSimpleCPU' in env['CPU_MODELS']:
+ need_simple_base = True
+ sources += Split('simple/timing.cc')
+
+if need_simple_base:
+ sources += Split('simple/base.cc')
+
+if 'FastCPU' in env['CPU_MODELS']:
+ sources += Split('fast/cpu.cc')
+
+if 'AlphaFullCPU' in env['CPU_MODELS']:
+ sources += Split('''
+ o3/2bit_local_pred.cc
+ o3/alpha_dyn_inst.cc
+ o3/alpha_cpu.cc
+ o3/alpha_cpu_builder.cc
+ o3/bpred_unit.cc
+ o3/btb.cc
+ o3/commit.cc
+ o3/decode.cc
+ o3/fetch.cc
+ o3/free_list.cc
+ o3/fu_pool.cc
+ o3/cpu.cc
+ o3/iew.cc
+ o3/inst_queue.cc
+ o3/lsq_unit.cc
+ o3/lsq.cc
+ o3/mem_dep_unit.cc
+ o3/ras.cc
+ o3/rename.cc
+ o3/rename_map.cc
+ o3/rob.cc
+ o3/scoreboard.cc
+ o3/store_set.cc
+ o3/tournament_pred.cc
+ ''')
+
+if 'OzoneSimpleCPU' in env['CPU_MODELS']:
+ sources += Split('''
+ ozone/cpu.cc
+ ozone/cpu_builder.cc
+ ozone/dyn_inst.cc
+ ozone/front_end.cc
+ ozone/inorder_back_end.cc
+ ozone/inst_queue.cc
+ ozone/rename_table.cc
+ ''')
+
+if 'OzoneCPU' in env['CPU_MODELS']:
+ sources += Split('''
+ ozone/back_end.cc
+ ozone/lsq_unit.cc
+ ozone/lw_back_end.cc
+ ozone/lw_lsq.cc
+ ''')
+
+if 'CheckerCPU' in env['CPU_MODELS']:
+ sources += Split('''
+ checker/cpu.cc
+ checker/cpu_builder.cc
+ checker/o3_cpu_builder.cc
+ ''')
+
+# FullCPU sources are included from m5/SConscript since they're not
+# below this point in the file hierarchy.
+
+# Convert file names to SCons File objects. This takes care of the
+# path relative to the top of the directory tree.
+sources = [File(s) for s in sources]
+
+Return('sources')
+
diff --git a/src/cpu/base.cc b/src/cpu/base.cc
new file mode 100644
index 000000000..8641d987d
--- /dev/null
+++ b/src/cpu/base.cc
@@ -0,0 +1,381 @@
+/*
+ * 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 <iostream>
+#include <string>
+#include <sstream>
+
+#include "base/cprintf.hh"
+#include "base/loader/symtab.hh"
+#include "base/misc.hh"
+#include "base/output.hh"
+#include "cpu/base.hh"
+#include "cpu/cpuevent.hh"
+#include "cpu/exec_context.hh"
+#include "cpu/profile.hh"
+#include "cpu/sampler/sampler.hh"
+#include "sim/param.hh"
+#include "sim/process.hh"
+#include "sim/sim_events.hh"
+#include "sim/system.hh"
+
+#include "base/trace.hh"
+
+using namespace std;
+
+vector<BaseCPU *> BaseCPU::cpuList;
+
+// This variable reflects the max number of threads in any CPU. Be
+// careful to only use it once all the CPUs that you care about have
+// been initialized
+int maxThreadsPerCPU = 1;
+
+#if FULL_SYSTEM
+BaseCPU::BaseCPU(Params *p)
+ : SimObject(p->name), clock(p->clock), checkInterrupts(true),
+ params(p), number_of_threads(p->numberOfThreads), system(p->system)
+#else
+BaseCPU::BaseCPU(Params *p)
+ : SimObject(p->name), clock(p->clock), params(p),
+ number_of_threads(p->numberOfThreads), system(p->system)
+#endif
+{
+ DPRINTF(FullCPU, "BaseCPU: Creating object, mem address %#x.\n", this);
+
+ // add self to global list of CPUs
+ cpuList.push_back(this);
+
+ DPRINTF(FullCPU, "BaseCPU: CPU added to cpuList, mem address %#x.\n",
+ this);
+
+ if (number_of_threads > maxThreadsPerCPU)
+ maxThreadsPerCPU = number_of_threads;
+
+ // allocate per-thread instruction-based event queues
+ comInstEventQueue = new EventQueue *[number_of_threads];
+ for (int i = 0; i < number_of_threads; ++i)
+ comInstEventQueue[i] = new EventQueue("instruction-based event queue");
+
+ //
+ // set up instruction-count-based termination events, if any
+ //
+ if (p->max_insts_any_thread != 0)
+ for (int i = 0; i < number_of_threads; ++i)
+ new SimExitEvent(comInstEventQueue[i], p->max_insts_any_thread,
+ "a thread reached the max instruction count");
+
+ if (p->max_insts_all_threads != 0) {
+ // allocate & initialize shared downcounter: each event will
+ // decrement this when triggered; simulation will terminate
+ // when counter reaches 0
+ int *counter = new int;
+ *counter = number_of_threads;
+ for (int i = 0; i < number_of_threads; ++i)
+ new CountedExitEvent(comInstEventQueue[i],
+ "all threads reached the max instruction count",
+ p->max_insts_all_threads, *counter);
+ }
+
+ // allocate per-thread load-based event queues
+ comLoadEventQueue = new EventQueue *[number_of_threads];
+ for (int i = 0; i < number_of_threads; ++i)
+ comLoadEventQueue[i] = new EventQueue("load-based event queue");
+
+ //
+ // set up instruction-count-based termination events, if any
+ //
+ if (p->max_loads_any_thread != 0)
+ for (int i = 0; i < number_of_threads; ++i)
+ new SimExitEvent(comLoadEventQueue[i], p->max_loads_any_thread,
+ "a thread reached the max load count");
+
+ if (p->max_loads_all_threads != 0) {
+ // allocate & initialize shared downcounter: each event will
+ // decrement this when triggered; simulation will terminate
+ // when counter reaches 0
+ int *counter = new int;
+ *counter = number_of_threads;
+ for (int i = 0; i < number_of_threads; ++i)
+ new CountedExitEvent(comLoadEventQueue[i],
+ "all threads reached the max load count",
+ p->max_loads_all_threads, *counter);
+ }
+
+#if FULL_SYSTEM
+ memset(interrupts, 0, sizeof(interrupts));
+ intstatus = 0;
+#endif
+
+ functionTracingEnabled = false;
+ if (p->functionTrace) {
+ functionTraceStream = simout.find(csprintf("ftrace.%s", name()));
+ currentFunctionStart = currentFunctionEnd = 0;
+ functionEntryTick = p->functionTraceStart;
+
+ if (p->functionTraceStart == 0) {
+ functionTracingEnabled = true;
+ } else {
+ Event *e =
+ new EventWrapper<BaseCPU, &BaseCPU::enableFunctionTrace>(this,
+ true);
+ e->schedule(p->functionTraceStart);
+ }
+ }
+#if FULL_SYSTEM
+ profileEvent = NULL;
+ if (params->profile)
+ profileEvent = new ProfileEvent(this, params->profile);
+#endif
+
+}
+
+BaseCPU::Params::Params()
+{
+#if FULL_SYSTEM
+ profile = false;
+#endif
+ checker = NULL;
+}
+
+void
+BaseCPU::enableFunctionTrace()
+{
+ functionTracingEnabled = true;
+}
+
+BaseCPU::~BaseCPU()
+{
+}
+
+void
+BaseCPU::init()
+{
+ if (!params->deferRegistration)
+ registerExecContexts();
+}
+
+void
+BaseCPU::startup()
+{
+#if FULL_SYSTEM
+ if (!params->deferRegistration && profileEvent)
+ profileEvent->schedule(curTick);
+#endif
+}
+
+
+void
+BaseCPU::regStats()
+{
+ using namespace Stats;
+
+ numCycles
+ .name(name() + ".numCycles")
+ .desc("number of cpu cycles simulated")
+ ;
+
+ int size = execContexts.size();
+ if (size > 1) {
+ for (int i = 0; i < size; ++i) {
+ stringstream namestr;
+ ccprintf(namestr, "%s.ctx%d", name(), i);
+ execContexts[i]->regStats(namestr.str());
+ }
+ } else if (size == 1)
+ execContexts[0]->regStats(name());
+
+#if FULL_SYSTEM
+#endif
+}
+
+
+void
+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)
+ id += i;
+
+ xc->setCpuId(system->registerExecContext(xc, id));
+#else
+ xc->setCpuId(xc->getProcessPtr()->registerExecContext(xc));
+#endif
+ }
+ }
+}
+
+
+void
+BaseCPU::switchOut(Sampler *sampler)
+{
+ panic("This CPU doesn't support sampling!");
+}
+
+void
+BaseCPU::takeOverFrom(BaseCPU *oldCPU)
+{
+ assert(execContexts.size() == oldCPU->execContexts.size());
+
+ for (int i = 0; i < execContexts.size(); ++i) {
+ ExecContext *newXC = execContexts[i];
+ ExecContext *oldXC = oldCPU->execContexts[i];
+
+ newXC->takeOverFrom(oldXC);
+
+ CpuEvent::replaceExecContext(oldXC, newXC);
+
+ assert(newXC->readCpuId() == oldXC->readCpuId());
+#if FULL_SYSTEM
+ system->replaceExecContext(newXC, newXC->readCpuId());
+#else
+ assert(newXC->getProcessPtr() == oldXC->getProcessPtr());
+ newXC->getProcessPtr()->replaceExecContext(newXC, newXC->readCpuId());
+#endif
+ }
+
+#if FULL_SYSTEM
+ for (int i = 0; i < TheISA::NumInterruptLevels; ++i)
+ interrupts[i] = oldCPU->interrupts[i];
+ intstatus = oldCPU->intstatus;
+
+ for (int i = 0; i < execContexts.size(); ++i)
+ execContexts[i]->profileClear();
+
+ if (profileEvent)
+ profileEvent->schedule(curTick);
+#endif
+}
+
+
+#if FULL_SYSTEM
+BaseCPU::ProfileEvent::ProfileEvent(BaseCPU *_cpu, int _interval)
+ : Event(&mainEventQueue), cpu(_cpu), interval(_interval)
+{ }
+
+void
+BaseCPU::ProfileEvent::process()
+{
+ for (int i = 0, size = cpu->execContexts.size(); i < size; ++i) {
+ ExecContext *xc = cpu->execContexts[i];
+ xc->profileSample();
+ }
+
+ schedule(curTick + interval);
+}
+
+void
+BaseCPU::post_interrupt(int int_num, int index)
+{
+ DPRINTF(Interrupt, "Interrupt %d:%d posted\n", int_num, index);
+
+ if (int_num < 0 || int_num >= TheISA::NumInterruptLevels)
+ panic("int_num out of bounds\n");
+
+ if (index < 0 || index >= sizeof(uint64_t) * 8)
+ panic("int_num out of bounds\n");
+
+ checkInterrupts = true;
+ interrupts[int_num] |= 1 << index;
+ intstatus |= (ULL(1) << int_num);
+}
+
+void
+BaseCPU::clear_interrupt(int int_num, int index)
+{
+ DPRINTF(Interrupt, "Interrupt %d:%d cleared\n", int_num, index);
+
+ if (int_num < 0 || int_num >= TheISA::NumInterruptLevels)
+ panic("int_num out of bounds\n");
+
+ if (index < 0 || index >= sizeof(uint64_t) * 8)
+ panic("int_num out of bounds\n");
+
+ interrupts[int_num] &= ~(1 << index);
+ if (interrupts[int_num] == 0)
+ intstatus &= ~(ULL(1) << int_num);
+}
+
+void
+BaseCPU::clear_interrupts()
+{
+ DPRINTF(Interrupt, "Interrupts all cleared\n");
+
+ memset(interrupts, 0, sizeof(interrupts));
+ intstatus = 0;
+}
+
+
+void
+BaseCPU::serialize(std::ostream &os)
+{
+ SERIALIZE_ARRAY(interrupts, TheISA::NumInterruptLevels);
+ SERIALIZE_SCALAR(intstatus);
+}
+
+void
+BaseCPU::unserialize(Checkpoint *cp, const std::string &section)
+{
+ UNSERIALIZE_ARRAY(interrupts, TheISA::NumInterruptLevels);
+ UNSERIALIZE_SCALAR(intstatus);
+}
+
+#endif // FULL_SYSTEM
+
+void
+BaseCPU::traceFunctionsInternal(Addr pc)
+{
+ if (!debugSymbolTable)
+ return;
+
+ // if pc enters different function, print new function symbol and
+ // update saved range. Otherwise do nothing.
+ if (pc < currentFunctionStart || pc >= currentFunctionEnd) {
+ string sym_str;
+ bool found = debugSymbolTable->findNearestSymbol(pc, sym_str,
+ currentFunctionStart,
+ currentFunctionEnd);
+
+ if (!found) {
+ // no symbol found: use addr as label
+ sym_str = csprintf("0x%x", pc);
+ currentFunctionStart = pc;
+ currentFunctionEnd = pc + 1;
+ }
+
+ ccprintf(*functionTraceStream, " (%d)\n%d: %s",
+ curTick - functionEntryTick, curTick, sym_str);
+ functionEntryTick = curTick;
+ }
+}
+
+
+DEFINE_SIM_OBJECT_CLASS_NAME("BaseCPU", BaseCPU)
diff --git a/src/cpu/base.hh b/src/cpu/base.hh
new file mode 100644
index 000000000..f14ace750
--- /dev/null
+++ b/src/cpu/base.hh
@@ -0,0 +1,238 @@
+/*
+ * 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 __CPU_BASE_HH__
+#define __CPU_BASE_HH__
+
+#include <vector>
+
+#include "base/statistics.hh"
+#include "config/full_system.hh"
+#include "cpu/sampler/sampler.hh"
+#include "sim/eventq.hh"
+#include "sim/sim_object.hh"
+#include "arch/isa_traits.hh"
+
+class BranchPred;
+class CheckerCPU;
+class ExecContext;
+class System;
+
+class BaseCPU : public SimObject
+{
+ protected:
+ // CPU's clock period in terms of the number of ticks of curTime.
+ Tick clock;
+
+ public:
+ inline Tick frequency() const { return Clock::Frequency / clock; }
+ inline Tick cycles(int numCycles) const { return clock * numCycles; }
+ inline Tick curCycle() const { return curTick / clock; }
+
+#if FULL_SYSTEM
+ protected:
+ uint64_t interrupts[TheISA::NumInterruptLevels];
+ uint64_t intstatus;
+
+ public:
+ virtual void post_interrupt(int int_num, int index);
+ virtual void clear_interrupt(int int_num, int index);
+ virtual void clear_interrupts();
+ bool checkInterrupts;
+
+ bool check_interrupt(int int_num) const {
+ if (int_num > TheISA::NumInterruptLevels)
+ panic("int_num out of bounds\n");
+
+ return interrupts[int_num] != 0;
+ }
+
+ bool check_interrupts() const { return intstatus != 0; }
+ uint64_t intr_status() const { return intstatus; }
+
+ class ProfileEvent : public Event
+ {
+ private:
+ BaseCPU *cpu;
+ int interval;
+
+ public:
+ ProfileEvent(BaseCPU *cpu, int interval);
+ void process();
+ };
+ ProfileEvent *profileEvent;
+#endif
+
+ protected:
+ std::vector<ExecContext *> execContexts;
+
+ public:
+
+ /// Notify the CPU that the indicated context is now active. The
+ /// delay parameter indicates the number of ticks to wait before
+ /// executing (typically 0 or 1).
+ virtual void activateContext(int thread_num, int delay) {}
+
+ /// Notify the CPU that the indicated context is now suspended.
+ virtual void suspendContext(int thread_num) {}
+
+ /// Notify the CPU that the indicated context is now deallocated.
+ virtual void deallocateContext(int thread_num) {}
+
+ /// Notify the CPU that the indicated context is now halted.
+ virtual void haltContext(int thread_num) {}
+
+ public:
+ struct Params
+ {
+ std::string name;
+ int numberOfThreads;
+ bool deferRegistration;
+ Counter max_insts_any_thread;
+ Counter max_insts_all_threads;
+ Counter max_loads_any_thread;
+ Counter max_loads_all_threads;
+ Tick clock;
+ bool functionTrace;
+ Tick functionTraceStart;
+ System *system;
+#if FULL_SYSTEM
+ int cpu_id;
+ Tick profile;
+#endif
+ BaseCPU *checker;
+
+ Params();
+ };
+
+ const Params *params;
+
+ BaseCPU(Params *params);
+ virtual ~BaseCPU();
+
+ virtual void init();
+ virtual void startup();
+ virtual void regStats();
+
+ virtual void activateWhenReady(int tid) {};
+
+ void registerExecContexts();
+
+ /// Prepare for another CPU to take over execution. When it is
+ /// is ready (drained pipe) it signals the sampler.
+ virtual void switchOut(Sampler *);
+
+ /// Take over execution from the given CPU. Used for warm-up and
+ /// sampling.
+ virtual void takeOverFrom(BaseCPU *);
+
+ /**
+ * Number of threads we're actually simulating (<= SMT_MAX_THREADS).
+ * This is a constant for the duration of the simulation.
+ */
+ int number_of_threads;
+
+ /**
+ * Vector of per-thread instruction-based event queues. Used for
+ * scheduling events based on number of instructions committed by
+ * a particular thread.
+ */
+ EventQueue **comInstEventQueue;
+
+ /**
+ * Vector of per-thread load-based event queues. Used for
+ * scheduling events based on number of loads committed by
+ *a particular thread.
+ */
+ EventQueue **comLoadEventQueue;
+
+ System *system;
+
+#if FULL_SYSTEM
+ /**
+ * Serialize this object to the given output stream.
+ * @param os The stream to serialize to.
+ */
+ virtual void serialize(std::ostream &os);
+
+ /**
+ * Reconstruct the state of this object from a checkpoint.
+ * @param cp The checkpoint use.
+ * @param section The section name of this object
+ */
+ virtual void unserialize(Checkpoint *cp, const std::string &section);
+
+#endif
+
+ /**
+ * Return pointer to CPU's branch predictor (NULL if none).
+ * @return Branch predictor pointer.
+ */
+ virtual BranchPred *getBranchPred() { return NULL; };
+
+ virtual Counter totalInstructions() const { return 0; }
+
+ // Function tracing
+ private:
+ bool functionTracingEnabled;
+ std::ostream *functionTraceStream;
+ Addr currentFunctionStart;
+ Addr currentFunctionEnd;
+ Tick functionEntryTick;
+ void enableFunctionTrace();
+ void traceFunctionsInternal(Addr pc);
+
+ protected:
+ void traceFunctions(Addr pc)
+ {
+ if (functionTracingEnabled)
+ traceFunctionsInternal(pc);
+ }
+
+ private:
+ static std::vector<BaseCPU *> cpuList; //!< Static global cpu list
+
+ public:
+ static int numSimulatedCPUs() { return cpuList.size(); }
+ static Counter numSimulatedInstructions()
+ {
+ Counter total = 0;
+
+ int size = cpuList.size();
+ for (int i = 0; i < size; ++i)
+ total += cpuList[i]->totalInstructions();
+
+ return total;
+ }
+
+ public:
+ // Number of CPU cycles simulated
+ Stats::Scalar<> numCycles;
+};
+
+#endif // __CPU_BASE_HH__
diff --git a/cpu/base_dyn_inst.cc b/src/cpu/base_dyn_inst.cc
index 7ab760ae3..7ab760ae3 100644
--- a/cpu/base_dyn_inst.cc
+++ b/src/cpu/base_dyn_inst.cc
diff --git a/cpu/base_dyn_inst.hh b/src/cpu/base_dyn_inst.hh
index 388ea4a8d..388ea4a8d 100644
--- a/cpu/base_dyn_inst.hh
+++ b/src/cpu/base_dyn_inst.hh
diff --git a/src/cpu/cpu_exec_context.cc b/src/cpu/cpu_exec_context.cc
new file mode 100644
index 000000000..7c2b32a93
--- /dev/null
+++ b/src/cpu/cpu_exec_context.cc
@@ -0,0 +1,340 @@
+/*
+ * Copyright (c) 2001-2006 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <string>
+
+#include "arch/isa_traits.hh"
+#include "cpu/base.hh"
+#include "cpu/cpu_exec_context.hh"
+#include "cpu/exec_context.hh"
+
+#if FULL_SYSTEM
+#include "base/callback.hh"
+#include "base/cprintf.hh"
+#include "base/output.hh"
+#include "base/trace.hh"
+#include "cpu/profile.hh"
+#include "cpu/quiesce_event.hh"
+#include "kern/kernel_stats.hh"
+#include "sim/serialize.hh"
+#include "sim/sim_exit.hh"
+#include "arch/stacktrace.hh"
+#else
+#include "sim/process.hh"
+#include "sim/system.hh"
+#include "mem/translating_port.hh"
+#endif
+
+using namespace std;
+
+// constructor
+#if FULL_SYSTEM
+CPUExecContext::CPUExecContext(BaseCPU *_cpu, int _thread_num, System *_sys,
+ AlphaITB *_itb, AlphaDTB *_dtb,
+ bool use_kernel_stats)
+ : _status(ExecContext::Unallocated), cpu(_cpu), thread_num(_thread_num),
+ cpu_id(-1), lastActivate(0), lastSuspend(0), system(_sys), itb(_itb),
+ dtb(_dtb), profile(NULL), func_exe_inst(0), storeCondFailures(0)
+
+{
+ proxy = new ProxyExecContext<CPUExecContext>(this);
+
+ quiesceEvent = new EndQuiesceEvent(proxy);
+
+ regs.clear();
+
+ if (cpu->params->profile) {
+ profile = new FunctionProfile(system->kernelSymtab);
+ Callback *cb =
+ new MakeCallback<CPUExecContext,
+ &CPUExecContext::dumpFuncProfile>(this);
+ registerExitCallback(cb);
+ }
+
+ // let's fill with a dummy node for now so we don't get a segfault
+ // on the first cycle when there's no node available.
+ static ProfileNode dummyNode;
+ profileNode = &dummyNode;
+ profilePC = 3;
+
+
+ if (use_kernel_stats) {
+ kernelStats = new Kernel::Statistics(system);
+ } else {
+ kernelStats = NULL;
+ }
+ Port *mem_port;
+ physPort = new FunctionalPort(csprintf("%s-%d-funcport",
+ cpu->name(), thread_num));
+ mem_port = system->physmem->getPort("functional");
+ mem_port->setPeer(physPort);
+ physPort->setPeer(mem_port);
+
+ virtPort = new VirtualPort(csprintf("%s-%d-vport",
+ cpu->name(), thread_num));
+ 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, MemObject* memobj)
+ : _status(ExecContext::Unallocated),
+ cpu(_cpu), thread_num(_thread_num), cpu_id(-1), lastActivate(0),
+ lastSuspend(0), process(_process), asid(_asid),
+ func_exe_inst(0), storeCondFailures(0)
+{
+ /* Use this port to for syscall emulation writes to memory. */
+ Port *mem_port;
+ port = new TranslatingPort(csprintf("%s-%d-funcport",
+ cpu->name(), thread_num),
+ 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), asid(-1),
+ func_exe_inst(0), storeCondFailures(0)
+{
+ regs = *regFile;
+ proxy = new ProxyExecContext<CPUExecContext>(this);
+}
+
+#endif
+
+CPUExecContext::~CPUExecContext()
+{
+ delete proxy;
+}
+
+#if FULL_SYSTEM
+void
+CPUExecContext::dumpFuncProfile()
+{
+ std::ostream *os = simout.create(csprintf("profile.%s.dat", cpu->name()));
+ profile->dump(proxy, *os);
+}
+
+void
+CPUExecContext::profileClear()
+{
+ if (profile)
+ profile->clear();
+}
+
+void
+CPUExecContext::profileSample()
+{
+ if (profile)
+ profile->sample(profileNode, profilePC);
+}
+
+#endif
+
+void
+CPUExecContext::takeOverFrom(ExecContext *oldContext)
+{
+ // some things should already be set up
+#if FULL_SYSTEM
+ assert(system == oldContext->getSystemPtr());
+#else
+ assert(process == oldContext->getProcessPtr());
+#endif
+
+ // copy over functional state
+ _status = oldContext->status();
+ copyArchRegs(oldContext);
+ cpu_id = oldContext->readCpuId();
+#if !FULL_SYSTEM
+ func_exe_inst = oldContext->readFuncExeInst();
+#else
+ EndQuiesceEvent *quiesce = oldContext->getQuiesceEvent();
+ if (quiesce) {
+ // Point the quiesce event's XC at this XC so that it wakes up
+ // the proper CPU.
+ quiesce->xc = proxy;
+ }
+ if (quiesceEvent) {
+ quiesceEvent->xc = proxy;
+ }
+#endif
+
+ storeCondFailures = 0;
+
+ oldContext->setStatus(ExecContext::Unallocated);
+}
+
+void
+CPUExecContext::serialize(ostream &os)
+{
+ SERIALIZE_ENUM(_status);
+ regs.serialize(os);
+ // thread_num and cpu_id are deterministic from the config
+ SERIALIZE_SCALAR(func_exe_inst);
+ SERIALIZE_SCALAR(inst);
+
+#if FULL_SYSTEM
+ Tick quiesceEndTick = 0;
+ if (quiesceEvent->scheduled())
+ quiesceEndTick = quiesceEvent->when();
+ SERIALIZE_SCALAR(quiesceEndTick);
+ if (kernelStats)
+ kernelStats->serialize(os);
+#endif
+}
+
+
+void
+CPUExecContext::unserialize(Checkpoint *cp, const std::string &section)
+{
+ UNSERIALIZE_ENUM(_status);
+ regs.unserialize(cp, section);
+ // thread_num and cpu_id are deterministic from the config
+ UNSERIALIZE_SCALAR(func_exe_inst);
+ UNSERIALIZE_SCALAR(inst);
+
+#if FULL_SYSTEM
+ Tick quiesceEndTick;
+ UNSERIALIZE_SCALAR(quiesceEndTick);
+ if (quiesceEndTick)
+ quiesceEvent->schedule(quiesceEndTick);
+ if (kernelStats)
+ kernelStats->unserialize(cp, section);
+#endif
+}
+
+
+void
+CPUExecContext::activate(int delay)
+{
+ if (status() == ExecContext::Active)
+ return;
+
+ lastActivate = curTick;
+
+ if (status() == ExecContext::Unallocated) {
+ cpu->activateWhenReady(thread_num);
+ return;
+ }
+
+ _status = ExecContext::Active;
+
+ // status() == Suspended
+ cpu->activateContext(thread_num, delay);
+}
+
+void
+CPUExecContext::suspend()
+{
+ if (status() == ExecContext::Suspended)
+ return;
+
+ lastActivate = curTick;
+ lastSuspend = curTick;
+/*
+#if FULL_SYSTEM
+ // Don't change the status from active if there are pending interrupts
+ if (cpu->check_interrupts()) {
+ assert(status() == ExecContext::Active);
+ return;
+ }
+#endif
+*/
+ _status = ExecContext::Suspended;
+ cpu->suspendContext(thread_num);
+}
+
+void
+CPUExecContext::deallocate()
+{
+ if (status() == ExecContext::Unallocated)
+ return;
+
+ _status = ExecContext::Unallocated;
+ cpu->deallocateContext(thread_num);
+}
+
+void
+CPUExecContext::halt()
+{
+ if (status() == ExecContext::Halted)
+ return;
+
+ _status = ExecContext::Halted;
+ cpu->haltContext(thread_num);
+}
+
+
+void
+CPUExecContext::regStats(const string &name)
+{
+#if FULL_SYSTEM
+ if (kernelStats)
+ kernelStats->regStats(name + ".kern");
+#endif
+}
+
+void
+CPUExecContext::copyArchRegs(ExecContext *xc)
+{
+ TheISA::copyRegs(xc, proxy);
+}
+
+#if FULL_SYSTEM
+VirtualPort*
+CPUExecContext::getVirtPort(ExecContext *xc)
+{
+ if (!xc)
+ return virtPort;
+
+ VirtualPort *vp;
+ Port *mem_port;
+
+ vp = new VirtualPort("xc-vport", 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/src/cpu/cpu_exec_context.hh b/src/cpu/cpu_exec_context.hh
new file mode 100644
index 000000000..61e6550af
--- /dev/null
+++ b/src/cpu/cpu_exec_context.hh
@@ -0,0 +1,540 @@
+/*
+ * Copyright (c) 2001-2006 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __CPU_CPU_EXEC_CONTEXT_HH__
+#define __CPU_CPU_EXEC_CONTEXT_HH__
+
+#include "arch/isa_traits.hh"
+#include "config/full_system.hh"
+#include "cpu/exec_context.hh"
+#include "mem/physical.hh"
+#include "mem/request.hh"
+#include "sim/byteswap.hh"
+#include "sim/eventq.hh"
+#include "sim/host.hh"
+#include "sim/serialize.hh"
+
+class BaseCPU;
+
+#if FULL_SYSTEM
+
+#include "sim/system.hh"
+#include "arch/tlb.hh"
+
+class FunctionProfile;
+class ProfileNode;
+class FunctionalPort;
+class PhysicalPort;
+
+
+namespace Kernel {
+ class Statistics;
+};
+
+#else // !FULL_SYSTEM
+
+#include "sim/process.hh"
+#include "mem/page_table.hh"
+class TranslatingPort;
+
+
+#endif // FULL_SYSTEM
+
+//
+// The CPUExecContext object represents a functional context for
+// instruction execution. It incorporates everything required for
+// architecture-level functional simulation of a single thread.
+//
+
+class CPUExecContext
+{
+ protected:
+ typedef TheISA::RegFile RegFile;
+ typedef TheISA::MachInst MachInst;
+ typedef TheISA::MiscRegFile MiscRegFile;
+ typedef TheISA::MiscReg MiscReg;
+ typedef TheISA::FloatReg FloatReg;
+ typedef TheISA::FloatRegBits FloatRegBits;
+ public:
+ typedef ExecContext::Status Status;
+
+ private:
+ Status _status;
+
+ public:
+ Status status() const { return _status; }
+
+ void setStatus(Status newStatus) { _status = newStatus; }
+
+ /// Set the status to Active. Optional delay indicates number of
+ /// cycles to wait before beginning execution.
+ void activate(int delay = 1);
+
+ /// Set the status to Suspended.
+ void suspend();
+
+ /// Set the status to Unallocated.
+ void deallocate();
+
+ /// Set the status to Halted.
+ void halt();
+
+ protected:
+ RegFile regs; // correct-path register context
+
+ public:
+ // pointer to CPU associated with this context
+ BaseCPU *cpu;
+
+ ProxyExecContext<CPUExecContext> *proxy;
+
+ // Current instruction
+ MachInst inst;
+
+ // Index of hardware thread context on the CPU that this represents.
+ int thread_num;
+
+ // ID of this context w.r.t. the System or Process object to which
+ // it belongs. For full-system mode, this is the system CPU ID.
+ int cpu_id;
+
+ Tick lastActivate;
+ Tick lastSuspend;
+
+ System *system;
+
+
+#if FULL_SYSTEM
+ AlphaITB *itb;
+ AlphaDTB *dtb;
+
+ /** 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;
+ Addr profilePC;
+ void dumpFuncProfile();
+
+ EndQuiesceEvent *quiesceEvent;
+
+ EndQuiesceEvent *getQuiesceEvent() { return quiesceEvent; }
+
+ Tick readLastActivate() { return lastActivate; }
+
+ Tick readLastSuspend() { return lastSuspend; }
+
+ void profileClear();
+
+ void profileSample();
+
+ Kernel::Statistics *getKernelStats() { return kernelStats; }
+
+ Kernel::Statistics *kernelStats;
+#else
+ /// Port that syscalls can use to access memory (provides translation step).
+ TranslatingPort *port;
+
+ Process *process;
+
+ // Address space ID. Note that this is used for TIMING cache
+ // simulation only; all functional memory accesses should use
+ // one of the FunctionalMemory pointers above.
+ short asid;
+
+#endif
+
+ /**
+ * Temporary storage to pass the source address from copy_load to
+ * copy_store.
+ * @todo Remove this temporary when we have a better way to do it.
+ */
+ Addr copySrcAddr;
+ /**
+ * Temp storage for the physical source address of a copy.
+ * @todo Remove this temporary when we have a better way to do it.
+ */
+ Addr copySrcPhysAddr;
+
+
+ /*
+ * number of executed instructions, for matching with syscall trace
+ * points in EIO files.
+ */
+ Counter func_exe_inst;
+
+ //
+ // Count failed store conditionals so we can warn of apparent
+ // application deadlock situations.
+ unsigned storeCondFailures;
+
+ // constructor: initialize context from given process structure
+#if FULL_SYSTEM
+ CPUExecContext(BaseCPU *_cpu, int _thread_num, System *_system,
+ AlphaITB *_itb, AlphaDTB *_dtb,
+ bool use_kernel_stats = true);
+#else
+ 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);
+#endif
+ virtual ~CPUExecContext();
+
+ virtual void takeOverFrom(ExecContext *oldContext);
+
+ void regStats(const std::string &name);
+
+ void serialize(std::ostream &os);
+ void unserialize(Checkpoint *cp, const std::string &section);
+
+ BaseCPU *getCpuPtr() { return cpu; }
+
+ ExecContext *getProxy() { return proxy; }
+
+ int getThreadNum() { return thread_num; }
+
+#if FULL_SYSTEM
+ System *getSystemPtr() { return system; }
+
+ AlphaITB *getITBPtr() { return itb; }
+
+ AlphaDTB *getDTBPtr() { return dtb; }
+
+ int getInstAsid() { return regs.instAsid(); }
+ int getDataAsid() { return regs.dataAsid(); }
+
+ Fault translateInstReq(RequestPtr &req)
+ {
+ return itb->translate(req, proxy);
+ }
+
+ Fault translateDataReadReq(RequestPtr &req)
+ {
+ return dtb->translate(req, proxy, false);
+ }
+
+ Fault translateDataWriteReq(RequestPtr &req)
+ {
+ return dtb->translate(req, proxy, true);
+ }
+
+ FunctionalPort *getPhysPort() { return physPort; }
+
+ /** 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);
+
+ void delVirtPort(VirtualPort *vp);
+
+#else
+ TranslatingPort *getMemPort() { return port; }
+
+ Process *getProcessPtr() { return process; }
+
+ int getInstAsid() { return asid; }
+ int getDataAsid() { return asid; }
+
+ Fault translateInstReq(RequestPtr &req)
+ {
+ return process->pTable->translate(req);
+ }
+
+ Fault translateDataReadReq(RequestPtr &req)
+ {
+ return process->pTable->translate(req);
+ }
+
+ Fault translateDataWriteReq(RequestPtr &req)
+ {
+ return process->pTable->translate(req);
+ }
+
+#endif
+
+/*
+ template <class T>
+ Fault read(RequestPtr &req, T &data)
+ {
+#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);
+ }
+#endif
+
+ Fault error;
+ error = mem->prot_read(req->paddr, data, req->size);
+ data = LittleEndianGuest::gtoh(data);
+ return error;
+ }
+
+ template <class T>
+ Fault write(RequestPtr &req, T &data)
+ {
+#if FULL_SYSTEM && THE_ISA == ALPHA_ISA
+ ExecContext *xc;
+
+ // If this is a store conditional, act appropriately
+ if (req->flags & LOCKED) {
+ xc = req->xc;
+
+ if (req->flags & UNCACHEABLE) {
+ // Don't update result register (see stq_c in isa_desc)
+ req->result = 2;
+ xc->setStCondFailures(0);//Needed? [RGD]
+ } else {
+ bool lock_flag = xc->readMiscReg(TheISA::Lock_Flag_DepTag);
+ Addr lock_addr = xc->readMiscReg(TheISA::Lock_Addr_DepTag);
+ req->result = lock_flag;
+ if (!lock_flag ||
+ ((lock_addr & ~0xf) != (req->paddr & ~0xf))) {
+ xc->setMiscReg(TheISA::Lock_Flag_DepTag, false);
+ xc->setStCondFailures(xc->readStCondFailures() + 1);
+ if (((xc->readStCondFailures()) % 100000) == 0) {
+ std::cerr << "Warning: "
+ << xc->readStCondFailures()
+ << " consecutive store conditional failures "
+ << "on cpu " << req->xc->readCpuId()
+ << std::endl;
+ }
+ return NoFault;
+ }
+ else xc->setStCondFailures(0);
+ }
+ }
+
+ // Need to clear any locked flags on other proccessors for
+ // this address. Only do this for succsful Store Conditionals
+ // and all other stores (WH64?). Unsuccessful Store
+ // Conditionals would have returned above, and wouldn't fall
+ // through.
+ for (int i = 0; i < system->execContexts.size(); i++){
+ xc = system->execContexts[i];
+ if ((xc->readMiscReg(TheISA::Lock_Addr_DepTag) & ~0xf) ==
+ (req->paddr & ~0xf)) {
+ xc->setMiscReg(TheISA::Lock_Flag_DepTag, false);
+ }
+ }
+
+#endif
+ return mem->prot_write(req->paddr, (T)htog(data), req->size);
+ }
+*/
+ virtual bool misspeculating();
+
+
+ MachInst getInst() { return inst; }
+
+ void setInst(MachInst new_inst)
+ {
+ inst = new_inst;
+ }
+
+ Fault instRead(RequestPtr &req)
+ {
+ panic("instRead not implemented");
+ // return funcPhysMem->read(req, inst);
+ return NoFault;
+ }
+
+ void setCpuId(int id) { cpu_id = id; }
+
+ int readCpuId() { return cpu_id; }
+
+ void copyArchRegs(ExecContext *xc);
+
+ //
+ // New accessors for new decoder.
+ //
+ uint64_t readIntReg(int reg_idx)
+ {
+ return regs.readIntReg(reg_idx);
+ }
+
+ FloatReg readFloatReg(int reg_idx, int width)
+ {
+ return regs.readFloatReg(reg_idx, width);
+ }
+
+ FloatReg readFloatReg(int reg_idx)
+ {
+ return regs.readFloatReg(reg_idx);
+ }
+
+ FloatRegBits readFloatRegBits(int reg_idx, int width)
+ {
+ 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.setIntReg(reg_idx, val);
+ }
+
+ void setFloatReg(int reg_idx, FloatReg val, int width)
+ {
+ regs.setFloatReg(reg_idx, val, width);
+ }
+
+ void setFloatReg(int reg_idx, FloatReg val)
+ {
+ regs.setFloatReg(reg_idx, val);
+ }
+
+ void setFloatRegBits(int reg_idx, FloatRegBits val, int width)
+ {
+ regs.setFloatRegBits(reg_idx, val, width);
+ }
+
+ void setFloatRegBits(int reg_idx, FloatRegBits val)
+ {
+ regs.setFloatRegBits(reg_idx, val);
+ }
+
+ uint64_t readPC()
+ {
+ return regs.readPC();
+ }
+
+ void setPC(uint64_t val)
+ {
+ regs.setPC(val);
+ }
+
+ uint64_t readNextPC()
+ {
+ return regs.readNextPC();
+ }
+
+ void setNextPC(uint64_t val)
+ {
+ regs.setNextPC(val);
+ }
+
+ uint64_t readNextNPC()
+ {
+ return regs.readNextNPC();
+ }
+
+ void setNextNPC(uint64_t val)
+ {
+ regs.setNextNPC(val);
+ }
+
+
+ MiscReg readMiscReg(int misc_reg)
+ {
+ return regs.readMiscReg(misc_reg);
+ }
+
+ MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault)
+ {
+ return regs.readMiscRegWithEffect(misc_reg, fault, proxy);
+ }
+
+ Fault setMiscReg(int misc_reg, const MiscReg &val)
+ {
+ return regs.setMiscReg(misc_reg, val);
+ }
+
+ Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val)
+ {
+ return regs.setMiscRegWithEffect(misc_reg, val, proxy);
+ }
+
+ unsigned readStCondFailures() { return storeCondFailures; }
+
+ void setStCondFailures(unsigned sc_failures)
+ { storeCondFailures = sc_failures; }
+
+ 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.readPC()); }
+ bool simPalCheck(int palFunc);
+#endif
+
+#if !FULL_SYSTEM
+ TheISA::IntReg getSyscallArg(int i)
+ {
+ return regs.readIntReg(TheISA::ArgumentReg0 + i);
+ }
+
+ // used to shift args for indirect syscall
+ void setSyscallArg(int i, TheISA::IntReg val)
+ {
+ regs.setIntReg(TheISA::ArgumentReg0 + i, val);
+ }
+
+ void setSyscallReturn(SyscallReturn return_value)
+ {
+ TheISA::setSyscallReturn(return_value, &regs);
+ }
+
+ void syscall(int64_t callnum)
+ {
+ 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);
+ }
+};
+
+
+// for non-speculative execution context, spec_mode is always false
+inline bool
+CPUExecContext::misspeculating()
+{
+ return false;
+}
+
+#endif // __CPU_CPU_EXEC_CONTEXT_HH__
diff --git a/src/cpu/cpu_models.py b/src/cpu/cpu_models.py
new file mode 100644
index 000000000..c3de03948
--- /dev/null
+++ b/src/cpu/cpu_models.py
@@ -0,0 +1,80 @@
+# Copyright (c) 2003-2006 The Regents of The University of Michigan
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met: redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer;
+# redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution;
+# neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+################
+# CpuModel class
+#
+# The CpuModel class encapsulates everything the ISA parser needs to
+# know about a particular CPU model.
+
+class CpuModel:
+ # Dict of available CPU model objects. Accessible as CpuModel.dict.
+ dict = {}
+
+ # Constructor. Automatically adds models to CpuModel.dict.
+ def __init__(self, name, filename, includes, strings):
+ self.name = name
+ self.filename = filename # filename for output exec code
+ self.includes = includes # include files needed in exec file
+ # The 'strings' dict holds all the per-CPU symbols we can
+ # substitute into templates etc.
+ self.strings = strings
+ # Add self to dict
+ CpuModel.dict[name] = self
+
+
+#
+# Define CPU models.
+#
+# Parameters are:
+# - name of model
+# - filename for generated ISA execution file
+# - includes needed for generated ISA execution file
+# - substitution strings for ISA description templates
+#
+
+CpuModel('AtomicSimpleCPU', 'atomic_simple_cpu_exec.cc',
+ '#include "cpu/simple/atomic.hh"',
+ { 'CPU_exec_context': 'AtomicSimpleCPU' })
+CpuModel('TimingSimpleCPU', 'timing_simple_cpu_exec.cc',
+ '#include "cpu/simple/timing.hh"',
+ { 'CPU_exec_context': 'TimingSimpleCPU' })
+CpuModel('FullCPU', 'full_cpu_exec.cc',
+ '#include "encumbered/cpu/full/dyn_inst.hh"',
+ { 'CPU_exec_context': 'DynInst' })
+CpuModel('AlphaFullCPU', 'alpha_o3_exec.cc',
+ '#include "cpu/o3/alpha_dyn_inst.hh"',
+ { 'CPU_exec_context': 'AlphaDynInst<AlphaSimpleImpl>' })
+CpuModel('OzoneSimpleCPU', 'ozone_simple_exec.cc',
+ '#include "cpu/ozone/dyn_inst.hh"',
+ { 'CPU_exec_context': 'OzoneDynInst<SimpleImpl>' })
+CpuModel('OzoneCPU', 'ozone_exec.cc',
+ '#include "cpu/ozone/dyn_inst.hh"',
+ { 'CPU_exec_context': 'OzoneDynInst<OzoneImpl>' })
+CpuModel('CheckerCPU', 'checker_cpu_exec.cc',
+ '#include "cpu/checker/cpu.hh"',
+ { 'CPU_exec_context': 'CheckerCPU' })
+
diff --git a/src/cpu/cpuevent.cc b/src/cpu/cpuevent.cc
new file mode 100644
index 000000000..ae1dd7fa3
--- /dev/null
+++ b/src/cpu/cpuevent.cc
@@ -0,0 +1,61 @@
+/*
+ * 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.
+ *
+ * Authors: Ali Saidi
+ */
+
+#include "cpu/cpuevent.hh"
+
+/** Static list of all CpuEvent objects so we can modify their execution
+ * contexts as needed. */
+CpuEvent::CpuEventList CpuEvent::cpuEventList;
+
+CpuEvent::~CpuEvent()
+{
+ CpuEventList::iterator i;
+
+ // delete the event from the global list
+ for (i = cpuEventList.begin(); i != cpuEventList.end(); ) {
+ if (*i == this)
+ i = cpuEventList.erase(i);
+ else
+ i++;
+ }
+}
+
+void
+CpuEvent::replaceExecContext(ExecContext *oldXc, ExecContext *newXc)
+{
+ CpuEventList::iterator i;
+
+ // Update any events that have the old execution context with the new exec
+ // context
+ for (i = cpuEventList.begin(); i != cpuEventList.end(); i++) {
+ if ((*i)->xc == oldXc)
+ (*i)->xc = newXc;
+ }
+}
diff --git a/src/cpu/cpuevent.hh b/src/cpu/cpuevent.hh
new file mode 100644
index 000000000..10359b121
--- /dev/null
+++ b/src/cpu/cpuevent.hh
@@ -0,0 +1,88 @@
+/*
+ * 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.
+ *
+ * Authors: Ali Saidi
+ */
+
+#ifndef __CPU_CPUEVENT_HH__
+#define __CPU_CPUEVENT_HH__
+
+#include <vector>
+#include "sim/eventq.hh"
+
+class ExecContext;
+
+/** This class creates a global list of events than need a pointer to an
+ * execution context. When a switchover takes place the events can be migrated
+ * to the new execution context, otherwise you could have a wake timer interrupt
+ * go off on a switched out cpu or other unfortunate events. This object MUST be
+ * dynamically allocated to avoid it being deleted after a cpu switch happens.
+ * */
+class CpuEvent : public Event
+{
+ private:
+ /** type of global list of cpu events. */
+ typedef std::vector<CpuEvent *> CpuEventList;
+
+ /** Static list of cpu events that is searched every time a cpu switch
+ * happens. */
+ static CpuEventList cpuEventList;
+
+ /** The execution context that is switched to the new cpus. */
+ ExecContext *xc;
+
+ public:
+ CpuEvent(EventQueue *q, ExecContext *_xc, Priority p = Default_Pri)
+ : Event(q, p), xc(_xc)
+ { cpuEventList.push_back(this); }
+
+ /** delete the cpu event from the global list. */
+ ~CpuEvent();
+
+ /** Update all events switching old xc to new xc.
+ * @param oldXc the old exeuction context we are switching from
+ * @param newXc the new execution context we are switching to.
+ */
+ static void replaceExecContext(ExecContext *oldXc, ExecContext *newXc);
+};
+
+template <class T, void (T::* F)(ExecContext *xc)>
+class CpuEventWrapper : public CpuEvent
+{
+ private:
+ T *object;
+
+ public:
+ CpuEventWrapper(T *obj, ExecContext *_xc, EventQueue *q = &mainEventQueue,
+ Priority p = Default_Pri)
+ : CpuEvent(q, _xc, p), object(obj)
+ { }
+ void process() { (object->*F)(xc); }
+};
+
+#endif // __CPU_CPUEVENT_HH__
+
diff --git a/src/cpu/exec_context.hh b/src/cpu/exec_context.hh
new file mode 100644
index 000000000..5b601bb30
--- /dev/null
+++ b/src/cpu/exec_context.hh
@@ -0,0 +1,417 @@
+/*
+ * 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.
+ */
+
+#ifndef __CPU_EXEC_CONTEXT_HH__
+#define __CPU_EXEC_CONTEXT_HH__
+
+#include "config/full_system.hh"
+#include "mem/request.hh"
+#include "sim/faults.hh"
+#include "sim/host.hh"
+#include "sim/serialize.hh"
+#include "sim/byteswap.hh"
+
+// @todo: Figure out a more architecture independent way to obtain the ITB and
+// DTB pointers.
+class AlphaDTB;
+class AlphaITB;
+class BaseCPU;
+class EndQuiesceEvent;
+class Event;
+class TranslatingPort;
+class FunctionalPort;
+class VirtualPort;
+class Process;
+class System;
+namespace Kernel {
+ class Statistics;
+};
+
+class ExecContext
+{
+ protected:
+ 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:
+ enum Status
+ {
+ /// Initialized but not running yet. All CPUs start in
+ /// this state, but most transition to Active on cycle 1.
+ /// In MP or SMT systems, non-primary contexts will stay
+ /// in this state until a thread is assigned to them.
+ Unallocated,
+
+ /// Running. Instructions should be executed only when
+ /// the context is in this state.
+ Active,
+
+ /// Temporarily inactive. Entered while waiting for
+ /// synchronization, etc.
+ Suspended,
+
+ /// Permanently shut down. Entered when target executes
+ /// m5exit pseudo-instruction. When all contexts enter
+ /// this state, the simulation will terminate.
+ Halted
+ };
+
+ virtual ~ExecContext() { };
+
+ virtual BaseCPU *getCpuPtr() = 0;
+
+ virtual void setCpuId(int id) = 0;
+
+ virtual int readCpuId() = 0;
+
+#if FULL_SYSTEM
+ virtual System *getSystemPtr() = 0;
+
+ virtual AlphaITB *getITBPtr() = 0;
+
+ virtual AlphaDTB * getDTBPtr() = 0;
+
+ virtual Kernel::Statistics *getKernelStats() = 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
+
+ virtual Status status() const = 0;
+
+ virtual void setStatus(Status new_status) = 0;
+
+ /// Set the status to Active. Optional delay indicates number of
+ /// cycles to wait before beginning execution.
+ virtual void activate(int delay = 1) = 0;
+
+ /// Set the status to Suspended.
+ virtual void suspend() = 0;
+
+ /// Set the status to Unallocated.
+ virtual void deallocate() = 0;
+
+ /// Set the status to Halted.
+ virtual void halt() = 0;
+
+#if FULL_SYSTEM
+ virtual void dumpFuncProfile() = 0;
+#endif
+
+ virtual void takeOverFrom(ExecContext *old_context) = 0;
+
+ virtual void regStats(const std::string &name) = 0;
+
+ virtual void serialize(std::ostream &os) = 0;
+ virtual void unserialize(Checkpoint *cp, const std::string &section) = 0;
+
+#if FULL_SYSTEM
+ virtual EndQuiesceEvent *getQuiesceEvent() = 0;
+
+ // Not necessarily the best location for these...
+ // Having an extra function just to read these is obnoxious
+ virtual Tick readLastActivate() = 0;
+ virtual Tick readLastSuspend() = 0;
+
+ virtual void profileClear() = 0;
+ virtual void profileSample() = 0;
+#endif
+
+ virtual int getThreadNum() = 0;
+
+ // Also somewhat obnoxious. Really only used for the TLB fault.
+ // However, may be quite useful in SPARC.
+ virtual TheISA::MachInst getInst() = 0;
+
+ virtual void copyArchRegs(ExecContext *xc) = 0;
+
+ virtual void clearArchRegs() = 0;
+
+ //
+ // New accessors for new decoder.
+ //
+ virtual uint64_t readIntReg(int reg_idx) = 0;
+
+ virtual FloatReg readFloatReg(int reg_idx, int width) = 0;
+
+ virtual FloatReg readFloatReg(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 setFloatReg(int reg_idx, FloatReg val, int width) = 0;
+
+ virtual void setFloatReg(int reg_idx, FloatReg val) = 0;
+
+ virtual void setFloatRegBits(int reg_idx, FloatRegBits val) = 0;
+
+ virtual void setFloatRegBits(int reg_idx, FloatRegBits val, int width) = 0;
+
+ virtual uint64_t readPC() = 0;
+
+ virtual void setPC(uint64_t val) = 0;
+
+ virtual uint64_t readNextPC() = 0;
+
+ virtual void setNextPC(uint64_t val) = 0;
+
+ virtual 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;
+
+ virtual Fault setMiscReg(int misc_reg, const MiscReg &val) = 0;
+
+ virtual Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val) = 0;
+
+ // Also not necessarily the best location for these two. Hopefully will go
+ // away once we decide upon where st cond failures goes.
+ virtual unsigned readStCondFailures() = 0;
+
+ virtual void setStCondFailures(unsigned sc_failures) = 0;
+
+#if FULL_SYSTEM
+ virtual bool inPalMode() = 0;
+#endif
+
+ // Only really makes sense for old CPU model. Still could be useful though.
+ virtual bool misspeculating() = 0;
+
+#if !FULL_SYSTEM
+ virtual IntReg getSyscallArg(int i) = 0;
+
+ // used to shift args for indirect syscall
+ virtual void setSyscallArg(int i, IntReg val) = 0;
+
+ virtual void setSyscallReturn(SyscallReturn return_value) = 0;
+
+
+ // Same with st cond failures.
+ virtual Counter readFuncExeInst() = 0;
+#endif
+
+ virtual void changeRegFileContext(RegFile::ContextParam param,
+ RegFile::ContextVal val) = 0;
+};
+
+template <class XC>
+class ProxyExecContext : public ExecContext
+{
+ public:
+ ProxyExecContext(XC *actual_xc)
+ { actualXC = actual_xc; }
+
+ private:
+ XC *actualXC;
+
+ public:
+
+ BaseCPU *getCpuPtr() { return actualXC->getCpuPtr(); }
+
+ void setCpuId(int id) { actualXC->setCpuId(id); }
+
+ int readCpuId() { return actualXC->readCpuId(); }
+
+#if FULL_SYSTEM
+ System *getSystemPtr() { return actualXC->getSystemPtr(); }
+
+ AlphaITB *getITBPtr() { return actualXC->getITBPtr(); }
+
+ AlphaDTB *getDTBPtr() { return actualXC->getDTBPtr(); }
+
+ Kernel::Statistics *getKernelStats() { return actualXC->getKernelStats(); }
+
+ 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
+
+ Status status() const { return actualXC->status(); }
+
+ void setStatus(Status new_status) { actualXC->setStatus(new_status); }
+
+ /// Set the status to Active. Optional delay indicates number of
+ /// cycles to wait before beginning execution.
+ void activate(int delay = 1) { actualXC->activate(delay); }
+
+ /// Set the status to Suspended.
+ void suspend() { actualXC->suspend(); }
+
+ /// Set the status to Unallocated.
+ void deallocate() { actualXC->deallocate(); }
+
+ /// Set the status to Halted.
+ void halt() { actualXC->halt(); }
+
+#if FULL_SYSTEM
+ void dumpFuncProfile() { actualXC->dumpFuncProfile(); }
+#endif
+
+ void takeOverFrom(ExecContext *oldContext)
+ { actualXC->takeOverFrom(oldContext); }
+
+ void regStats(const std::string &name) { actualXC->regStats(name); }
+
+ void serialize(std::ostream &os) { actualXC->serialize(os); }
+ void unserialize(Checkpoint *cp, const std::string &section)
+ { actualXC->unserialize(cp, section); }
+
+#if FULL_SYSTEM
+ EndQuiesceEvent *getQuiesceEvent() { return actualXC->getQuiesceEvent(); }
+
+ Tick readLastActivate() { return actualXC->readLastActivate(); }
+ Tick readLastSuspend() { return actualXC->readLastSuspend(); }
+
+ void profileClear() { return actualXC->profileClear(); }
+ void profileSample() { return actualXC->profileSample(); }
+#endif
+
+ int getThreadNum() { return actualXC->getThreadNum(); }
+
+ // @todo: Do I need this?
+ MachInst getInst() { return actualXC->getInst(); }
+
+ // @todo: Do I need this?
+ void copyArchRegs(ExecContext *xc) { actualXC->copyArchRegs(xc); }
+
+ void clearArchRegs() { actualXC->clearArchRegs(); }
+
+ //
+ // New accessors for new decoder.
+ //
+ uint64_t readIntReg(int reg_idx)
+ { return actualXC->readIntReg(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); }
+
+ FloatRegBits readFloatRegBits(int reg_idx, int width)
+ { return actualXC->readFloatRegBits(reg_idx, width); }
+
+ FloatRegBits readFloatRegBits(int reg_idx)
+ { return actualXC->readFloatRegBits(reg_idx); }
+
+ void setIntReg(int reg_idx, uint64_t val)
+ { actualXC->setIntReg(reg_idx, val); }
+
+ void setFloatReg(int reg_idx, FloatReg val, int width)
+ { actualXC->setFloatReg(reg_idx, val, width); }
+
+ void setFloatReg(int reg_idx, FloatReg val)
+ { actualXC->setFloatReg(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(); }
+
+ void setPC(uint64_t val) { actualXC->setPC(val); }
+
+ uint64_t readNextPC() { return actualXC->readNextPC(); }
+
+ 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); }
+
+ MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault)
+ { return actualXC->readMiscRegWithEffect(misc_reg, fault); }
+
+ Fault setMiscReg(int misc_reg, const MiscReg &val)
+ { return actualXC->setMiscReg(misc_reg, val); }
+
+ Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val)
+ { return actualXC->setMiscRegWithEffect(misc_reg, val); }
+
+ unsigned readStCondFailures()
+ { return actualXC->readStCondFailures(); }
+
+ void setStCondFailures(unsigned sc_failures)
+ { actualXC->setStCondFailures(sc_failures); }
+#if FULL_SYSTEM
+ bool inPalMode() { return actualXC->inPalMode(); }
+#endif
+
+ // @todo: Fix this!
+ bool misspeculating() { return actualXC->misspeculating(); }
+
+#if !FULL_SYSTEM
+ IntReg getSyscallArg(int i) { return actualXC->getSyscallArg(i); }
+
+ // used to shift args for indirect syscall
+ void setSyscallArg(int i, IntReg val)
+ { actualXC->setSyscallArg(i, val); }
+
+ void setSyscallReturn(SyscallReturn return_value)
+ { actualXC->setSyscallReturn(return_value); }
+
+
+ Counter readFuncExeInst() { return actualXC->readFuncExeInst(); }
+#endif
+
+ void changeRegFileContext(RegFile::ContextParam param,
+ RegFile::ContextVal val)
+ {
+ actualXC->changeRegFileContext(param, val);
+ }
+};
+
+#endif
diff --git a/src/cpu/exetrace.cc b/src/cpu/exetrace.cc
new file mode 100644
index 000000000..5ec05ea72
--- /dev/null
+++ b/src/cpu/exetrace.cc
@@ -0,0 +1,230 @@
+/*
+ * 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 <fstream>
+#include <iomanip>
+
+#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;
+
+
+////////////////////////////////////////////////////////////////////////
+//
+// Methods for the InstRecord object
+//
+
+
+void
+Trace::InstRecord::dump(ostream &outs)
+{
+ if (flags[INTEL_FORMAT]) {
+#if FULL_SYSTEM
+ bool is_trace_system = (cpu->system->name() == trace_system);
+#else
+ bool is_trace_system = true;
+#endif
+ if (is_trace_system) {
+ ccprintf(outs, "%7d ) ", cycle);
+ outs << "0x" << hex << PC << ":\t";
+ if (staticInst->isLoad()) {
+ outs << "<RD 0x" << hex << addr;
+ outs << ">";
+ } else if (staticInst->isStore()) {
+ outs << "<WR 0x" << hex << addr;
+ outs << ">";
+ }
+ outs << endl;
+ }
+ } else {
+ if (flags[PRINT_CYCLE])
+ ccprintf(outs, "%7d: ", cycle);
+
+ outs << cpu->name() << " ";
+
+ if (flags[TRACE_MISSPEC])
+ outs << (misspeculating ? "-" : "+") << " ";
+
+ if (flags[PRINT_THREAD_NUM])
+ outs << "T" << thread << " : ";
+
+
+ std::string sym_str;
+ Addr sym_addr;
+ if (debugSymbolTable
+ && debugSymbolTable->findNearestSymbol(PC, sym_str, sym_addr)
+ && flags[PC_SYMBOL]) {
+ if (PC != sym_addr)
+ sym_str += csprintf("+%d", PC - sym_addr);
+ outs << "@" << sym_str << " : ";
+ }
+ else {
+ outs << "0x" << hex << PC << " : ";
+ }
+
+ //
+ // Print decoded instruction
+ //
+
+#if defined(__GNUC__) && (__GNUC__ < 3)
+ // There's a bug in gcc 2.x library that prevents setw()
+ // from working properly on strings
+ string mc(staticInst->disassemble(PC, debugSymbolTable));
+ while (mc.length() < 26)
+ mc += " ";
+ outs << mc;
+#else
+ outs << setw(26) << left << staticInst->disassemble(PC, debugSymbolTable);
+#endif
+
+ outs << " : ";
+
+ if (flags[PRINT_OP_CLASS]) {
+ outs << opClassStrings[staticInst->opClass()] << " : ";
+ }
+
+ if (flags[PRINT_RESULT_DATA] && data_status != DataInvalid) {
+ outs << " D=";
+#if 0
+ if (data_status == DataDouble)
+ ccprintf(outs, "%f", data.as_double);
+ else
+ ccprintf(outs, "%#018x", data.as_int);
+#else
+ ccprintf(outs, "%#018x", data.as_int);
+#endif
+ }
+
+ if (flags[PRINT_EFF_ADDR] && addr_valid)
+ outs << " A=0x" << hex << addr;
+
+ if (flags[PRINT_INT_REGS] && regs_valid) {
+ for (int i = 0; i < TheISA::NumIntRegs;)
+ for (int j = i + 1; i <= j; i++)
+ ccprintf(outs, "r%02d = %#018x%s", i,
+ iregs->regs.readReg(i),
+ ((i == j) ? "\n" : " "));
+ outs << "\n";
+ }
+
+ if (flags[PRINT_FETCH_SEQ] && fetch_seq_valid)
+ outs << " FetchSeq=" << dec << fetch_seq;
+
+ if (flags[PRINT_CP_SEQ] && cp_seq_valid)
+ outs << " CPSeq=" << dec << cp_seq;
+
+ //
+ // End of line...
+ //
+ outs << endl;
+ }
+}
+
+
+vector<bool> Trace::InstRecord::flags(NUM_BITS);
+string Trace::InstRecord::trace_system;
+
+////////////////////////////////////////////////////////////////////////
+//
+// Parameter space for per-cycle execution address tracing options.
+// Derive from ParamContext so we can override checkParams() function.
+//
+class ExecutionTraceParamContext : public ParamContext
+{
+ public:
+ ExecutionTraceParamContext(const string &_iniSection)
+ : ParamContext(_iniSection)
+ {
+ }
+
+ void checkParams(); // defined at bottom of file
+};
+
+ExecutionTraceParamContext exeTraceParams("exetrace");
+
+Param<bool> exe_trace_spec(&exeTraceParams, "speculative",
+ "capture speculative instructions", true);
+
+Param<bool> exe_trace_print_cycle(&exeTraceParams, "print_cycle",
+ "print cycle number", true);
+Param<bool> exe_trace_print_opclass(&exeTraceParams, "print_opclass",
+ "print op class", true);
+Param<bool> exe_trace_print_thread(&exeTraceParams, "print_thread",
+ "print thread number", true);
+Param<bool> exe_trace_print_effaddr(&exeTraceParams, "print_effaddr",
+ "print effective address", true);
+Param<bool> exe_trace_print_data(&exeTraceParams, "print_data",
+ "print result data", true);
+Param<bool> exe_trace_print_iregs(&exeTraceParams, "print_iregs",
+ "print all integer regs", false);
+Param<bool> exe_trace_print_fetchseq(&exeTraceParams, "print_fetchseq",
+ "print fetch sequence number", false);
+Param<bool> exe_trace_print_cp_seq(&exeTraceParams, "print_cpseq",
+ "print correct-path sequence number", false);
+Param<bool> exe_trace_pc_symbol(&exeTraceParams, "pc_symbol",
+ "Use symbols for the PC if available", true);
+Param<bool> exe_trace_intel_format(&exeTraceParams, "intel_format",
+ "print trace in intel compatible format", false);
+Param<string> exe_trace_system(&exeTraceParams, "trace_system",
+ "print trace of which system (client or server)",
+ "client");
+
+
+//
+// Helper function for ExecutionTraceParamContext::checkParams() just
+// to get us into the InstRecord namespace
+//
+void
+Trace::InstRecord::setParams()
+{
+ flags[TRACE_MISSPEC] = exe_trace_spec;
+
+ flags[PRINT_CYCLE] = exe_trace_print_cycle;
+ flags[PRINT_OP_CLASS] = exe_trace_print_opclass;
+ flags[PRINT_THREAD_NUM] = exe_trace_print_thread;
+ flags[PRINT_RESULT_DATA] = exe_trace_print_effaddr;
+ flags[PRINT_EFF_ADDR] = exe_trace_print_data;
+ flags[PRINT_INT_REGS] = exe_trace_print_iregs;
+ flags[PRINT_FETCH_SEQ] = exe_trace_print_fetchseq;
+ flags[PRINT_CP_SEQ] = exe_trace_print_cp_seq;
+ flags[PC_SYMBOL] = exe_trace_pc_symbol;
+ flags[INTEL_FORMAT] = exe_trace_intel_format;
+ trace_system = exe_trace_system;
+}
+
+void
+ExecutionTraceParamContext::checkParams()
+{
+ Trace::InstRecord::setParams();
+}
+
diff --git a/src/cpu/exetrace.hh b/src/cpu/exetrace.hh
new file mode 100644
index 000000000..7b86a9344
--- /dev/null
+++ b/src/cpu/exetrace.hh
@@ -0,0 +1,189 @@
+/*
+ * 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 __EXETRACE_HH__
+#define __EXETRACE_HH__
+
+#include <fstream>
+#include <vector>
+
+#include "sim/host.hh"
+#include "cpu/inst_seq.hh" // for InstSeqNum
+#include "base/trace.hh"
+#include "cpu/exec_context.hh"
+#include "cpu/static_inst.hh"
+
+class BaseCPU;
+
+
+namespace Trace {
+
+class InstRecord : public Record
+{
+ protected:
+ typedef TheISA::IntRegFile IntRegFile;
+
+ // The following fields are initialized by the constructor and
+ // thus guaranteed to be valid.
+ BaseCPU *cpu;
+ // need to make this ref-counted so it doesn't go away before we
+ // dump the record
+ StaticInstPtr staticInst;
+ Addr PC;
+ bool misspeculating;
+ unsigned thread;
+
+ // The remaining fields are only valid for particular instruction
+ // types (e.g, addresses for memory ops) or when particular
+ // options are enabled (e.g., tracing full register contents).
+ // Each data field has an associated valid flag to indicate
+ // whether the data field is valid.
+ Addr addr;
+ bool addr_valid;
+
+ union {
+ uint64_t as_int;
+ double as_double;
+ } data;
+ enum {
+ DataInvalid = 0,
+ DataInt8 = 1, // set to equal number of bytes
+ DataInt16 = 2,
+ DataInt32 = 4,
+ DataInt64 = 8,
+ DataDouble = 3
+ } data_status;
+
+ InstSeqNum fetch_seq;
+ bool fetch_seq_valid;
+
+ InstSeqNum cp_seq;
+ bool cp_seq_valid;
+
+ struct iRegFile {
+ IntRegFile regs;
+ };
+ iRegFile *iregs;
+ bool regs_valid;
+
+ public:
+ InstRecord(Tick _cycle, BaseCPU *_cpu,
+ const StaticInstPtr &_staticInst,
+ Addr _pc, bool spec, int _thread)
+ : Record(_cycle), cpu(_cpu), staticInst(_staticInst), PC(_pc),
+ misspeculating(spec), thread(_thread)
+ {
+ data_status = DataInvalid;
+ addr_valid = false;
+ regs_valid = false;
+
+ fetch_seq_valid = false;
+ cp_seq_valid = false;
+ }
+
+ virtual ~InstRecord() { }
+
+ virtual void dump(std::ostream &outs);
+
+ void setAddr(Addr a) { addr = a; addr_valid = true; }
+
+ void setData(uint64_t d) { data.as_int = d; data_status = DataInt64; }
+ void setData(uint32_t d) { data.as_int = d; data_status = DataInt32; }
+ void setData(uint16_t d) { data.as_int = d; data_status = DataInt16; }
+ void setData(uint8_t d) { data.as_int = d; data_status = DataInt8; }
+
+ void setData(int64_t d) { setData((uint64_t)d); }
+ void setData(int32_t d) { setData((uint32_t)d); }
+ void setData(int16_t d) { setData((uint16_t)d); }
+ void setData(int8_t d) { setData((uint8_t)d); }
+
+ void setData(double d) { data.as_double = d; data_status = DataDouble; }
+
+ void setFetchSeq(InstSeqNum seq)
+ { fetch_seq = seq; fetch_seq_valid = true; }
+
+ void setCPSeq(InstSeqNum seq)
+ { cp_seq = seq; cp_seq_valid = true; }
+
+ void setRegs(const IntRegFile &regs);
+
+ void finalize() { theLog.append(this); }
+
+ enum InstExecFlagBits {
+ TRACE_MISSPEC = 0,
+ PRINT_CYCLE,
+ PRINT_OP_CLASS,
+ PRINT_THREAD_NUM,
+ PRINT_RESULT_DATA,
+ PRINT_EFF_ADDR,
+ PRINT_INT_REGS,
+ PRINT_FETCH_SEQ,
+ PRINT_CP_SEQ,
+ PC_SYMBOL,
+ INTEL_FORMAT,
+ NUM_BITS
+ };
+
+ static std::vector<bool> flags;
+ static std::string trace_system;
+
+ static void setParams();
+
+ static bool traceMisspec() { return flags[TRACE_MISSPEC]; }
+};
+
+
+inline void
+InstRecord::setRegs(const IntRegFile &regs)
+{
+ if (!iregs)
+ iregs = new iRegFile;
+
+ memcpy(&iregs->regs, &regs, sizeof(IntRegFile));
+ regs_valid = true;
+}
+
+inline
+InstRecord *
+getInstRecord(Tick cycle, ExecContext *xc, BaseCPU *cpu,
+ const StaticInstPtr staticInst,
+ Addr pc, int thread = 0)
+{
+ if (DTRACE(InstExec) &&
+ (InstRecord::traceMisspec() || !xc->misspeculating())) {
+ return new InstRecord(cycle, cpu, staticInst, pc,
+ xc->misspeculating(), thread);
+ }
+
+ return NULL;
+}
+
+
+}
+
+#endif // __EXETRACE_HH__
diff --git a/cpu/inst_seq.hh b/src/cpu/inst_seq.hh
index 356d19df0..356d19df0 100644
--- a/cpu/inst_seq.hh
+++ b/src/cpu/inst_seq.hh
diff --git a/cpu/intr_control.cc b/src/cpu/intr_control.cc
index 43e7f654c..43e7f654c 100644
--- a/cpu/intr_control.cc
+++ b/src/cpu/intr_control.cc
diff --git a/cpu/intr_control.hh b/src/cpu/intr_control.hh
index 5ec4e14cb..5ec4e14cb 100644
--- a/cpu/intr_control.hh
+++ b/src/cpu/intr_control.hh
diff --git a/src/cpu/memtest/memtest.cc b/src/cpu/memtest/memtest.cc
new file mode 100644
index 000000000..54def1012
--- /dev/null
+++ b/src/cpu/memtest/memtest.cc
@@ -0,0 +1,440 @@
+/*
+ * 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.
+ */
+
+// FIX ME: make trackBlkAddr use blocksize from actual cache, not hard coded
+
+#include <iomanip>
+#include <set>
+#include <string>
+#include <vector>
+
+#include "base/misc.hh"
+#include "base/statistics.hh"
+#include "cpu/cpu_exec_context.hh"
+#include "cpu/memtest/memtest.hh"
+#include "mem/cache/base_cache.hh"
+#include "sim/builder.hh"
+#include "sim/sim_events.hh"
+#include "sim/stats.hh"
+
+using namespace std;
+using namespace TheISA;
+
+int TESTER_ALLOCATOR=0;
+
+MemTest::MemTest(const string &name,
+ MemInterface *_cache_interface,
+ FunctionalMemory *main_mem,
+ FunctionalMemory *check_mem,
+ unsigned _memorySize,
+ unsigned _percentReads,
+ unsigned _percentCopies,
+ unsigned _percentUncacheable,
+ unsigned _progressInterval,
+ unsigned _percentSourceUnaligned,
+ unsigned _percentDestUnaligned,
+ Addr _traceAddr,
+ Counter _max_loads)
+ : SimObject(name),
+ tickEvent(this),
+ cacheInterface(_cache_interface),
+ mainMem(main_mem),
+ checkMem(check_mem),
+ size(_memorySize),
+ percentReads(_percentReads),
+ percentCopies(_percentCopies),
+ percentUncacheable(_percentUncacheable),
+ progressInterval(_progressInterval),
+ nextProgressMessage(_progressInterval),
+ percentSourceUnaligned(_percentSourceUnaligned),
+ percentDestUnaligned(percentDestUnaligned),
+ maxLoads(_max_loads)
+{
+ vector<string> cmd;
+ cmd.push_back("/bin/ls");
+ vector<string> null_vec;
+ cpuXC = new CPUExecContext(NULL, 0, mainMem, 0);
+
+ blockSize = cacheInterface->getBlockSize();
+ blockAddrMask = blockSize - 1;
+ traceBlockAddr = blockAddr(_traceAddr);
+
+ //setup data storage with interesting values
+ uint8_t *data1 = new uint8_t[size];
+ uint8_t *data2 = new uint8_t[size];
+ uint8_t *data3 = new uint8_t[size];
+ memset(data1, 1, size);
+ memset(data2, 2, size);
+ memset(data3, 3, size);
+ curTick = 0;
+
+ baseAddr1 = 0x100000;
+ baseAddr2 = 0x400000;
+ uncacheAddr = 0x800000;
+
+ // set up intial memory contents here
+ mainMem->prot_write(baseAddr1, data1, size);
+ checkMem->prot_write(baseAddr1, data1, size);
+ mainMem->prot_write(baseAddr2, data2, size);
+ checkMem->prot_write(baseAddr2, data2, size);
+ mainMem->prot_write(uncacheAddr, data3, size);
+ checkMem->prot_write(uncacheAddr, data3, size);
+
+ delete [] data1;
+ delete [] data2;
+ delete [] data3;
+
+ // set up counters
+ noResponseCycles = 0;
+ numReads = 0;
+ tickEvent.schedule(0);
+
+ id = TESTER_ALLOCATOR++;
+}
+
+static void
+printData(ostream &os, uint8_t *data, int nbytes)
+{
+ os << hex << setfill('0');
+ // assume little-endian: print bytes from highest address to lowest
+ for (uint8_t *dp = data + nbytes - 1; dp >= data; --dp) {
+ os << setw(2) << (unsigned)*dp;
+ }
+ os << dec;
+}
+
+void
+MemTest::completeRequest(MemReqPtr &req, uint8_t *data)
+{
+ //Remove the address from the list of outstanding
+ std::set<unsigned>::iterator removeAddr = outstandingAddrs.find(req->paddr);
+ assert(removeAddr != outstandingAddrs.end());
+ outstandingAddrs.erase(removeAddr);
+
+ switch (req->cmd) {
+ case Read:
+ if (memcmp(req->data, data, req->size) != 0) {
+ cerr << name() << ": on read of 0x" << hex << req->paddr
+ << " (0x" << hex << blockAddr(req->paddr) << ")"
+ << "@ cycle " << dec << curTick
+ << ", cache returns 0x";
+ printData(cerr, req->data, req->size);
+ cerr << ", expected 0x";
+ printData(cerr, data, req->size);
+ cerr << endl;
+ fatal("");
+ }
+
+ numReads++;
+ numReadsStat++;
+
+ if (numReads == nextProgressMessage) {
+ ccprintf(cerr, "%s: completed %d read accesses @%d\n",
+ name(), numReads, curTick);
+ nextProgressMessage += progressInterval;
+ }
+
+ if (numReads >= maxLoads)
+ SimExit(curTick, "Maximum number of loads reached!");
+ break;
+
+ case Write:
+ numWritesStat++;
+ break;
+
+ case Copy:
+ //Also remove dest from outstanding list
+ removeAddr = outstandingAddrs.find(req->dest);
+ assert(removeAddr != outstandingAddrs.end());
+ outstandingAddrs.erase(removeAddr);
+ numCopiesStat++;
+ break;
+
+ default:
+ panic("invalid command");
+ }
+
+ if (blockAddr(req->paddr) == traceBlockAddr) {
+ cerr << name() << ": completed "
+ << (req->cmd.isWrite() ? "write" : "read")
+ << " access of "
+ << dec << req->size << " bytes at address 0x"
+ << hex << req->paddr
+ << " (0x" << hex << blockAddr(req->paddr) << ")"
+ << ", value = 0x";
+ printData(cerr, req->data, req->size);
+ cerr << " @ cycle " << dec << curTick;
+
+ cerr << endl;
+ }
+
+ noResponseCycles = 0;
+ delete [] data;
+}
+
+
+void
+MemTest::regStats()
+{
+ using namespace Stats;
+
+
+ numReadsStat
+ .name(name() + ".num_reads")
+ .desc("number of read accesses completed")
+ ;
+
+ numWritesStat
+ .name(name() + ".num_writes")
+ .desc("number of write accesses completed")
+ ;
+
+ numCopiesStat
+ .name(name() + ".num_copies")
+ .desc("number of copy accesses completed")
+ ;
+}
+
+void
+MemTest::tick()
+{
+ if (!tickEvent.scheduled())
+ tickEvent.schedule(curTick + cycles(1));
+
+ if (++noResponseCycles >= 500000) {
+ cerr << name() << ": deadlocked at cycle " << curTick << endl;
+ fatal("");
+ }
+
+ if (cacheInterface->isBlocked()) {
+ return;
+ }
+
+ //make new request
+ unsigned cmd = random() % 100;
+ unsigned offset = random() % size;
+ unsigned base = random() % 2;
+ uint64_t data = random();
+ unsigned access_size = random() % 4;
+ unsigned cacheable = random() % 100;
+
+ //If we aren't doing copies, use id as offset, and do a false sharing
+ //mem tester
+ if (percentCopies == 0) {
+ //We can eliminate the lower bits of the offset, and then use the id
+ //to offset within the blks
+ offset &= ~63; //Not the low order bits
+ offset += id;
+ access_size = 0;
+ }
+
+ MemReqPtr req = new MemReq();
+
+ if (cacheable < percentUncacheable) {
+ req->flags |= UNCACHEABLE;
+ req->paddr = uncacheAddr + offset;
+ } else {
+ req->paddr = ((base) ? baseAddr1 : baseAddr2) + offset;
+ }
+ // bool probe = (random() % 2 == 1) && !req->isUncacheable();
+ bool probe = false;
+
+ req->size = 1 << access_size;
+ req->data = new uint8_t[req->size];
+ req->paddr &= ~(req->size - 1);
+ req->time = curTick;
+ req->xc = cpuXC->getProxy();
+
+ if (cmd < percentReads) {
+ // read
+
+ //For now we only allow one outstanding request per addreess per tester
+ //This means we assume CPU does write forwarding to reads that alias something
+ //in the cpu store buffer.
+ if (outstandingAddrs.find(req->paddr) != outstandingAddrs.end()) return;
+ else outstandingAddrs.insert(req->paddr);
+
+ req->cmd = Read;
+ uint8_t *result = new uint8_t[8];
+ checkMem->access(Read, req->paddr, result, req->size);
+ if (blockAddr(req->paddr) == traceBlockAddr) {
+ cerr << name()
+ << ": initiating read "
+ << ((probe) ? "probe of " : "access of ")
+ << dec << req->size << " bytes from addr 0x"
+ << hex << req->paddr
+ << " (0x" << hex << blockAddr(req->paddr) << ")"
+ << " at cycle "
+ << dec << curTick << endl;
+ }
+ if (probe) {
+ cacheInterface->probeAndUpdate(req);
+ completeRequest(req, result);
+ } else {
+ req->completionEvent = new MemCompleteEvent(req, result, this);
+ cacheInterface->access(req);
+ }
+ } else if (cmd < (100 - percentCopies)){
+ // write
+
+ //For now we only allow one outstanding request per addreess per tester
+ //This means we assume CPU does write forwarding to reads that alias something
+ //in the cpu store buffer.
+ if (outstandingAddrs.find(req->paddr) != outstandingAddrs.end()) return;
+ else outstandingAddrs.insert(req->paddr);
+
+ req->cmd = Write;
+ memcpy(req->data, &data, req->size);
+ checkMem->access(Write, req->paddr, req->data, req->size);
+ if (blockAddr(req->paddr) == traceBlockAddr) {
+ cerr << name() << ": initiating write "
+ << ((probe)?"probe of ":"access of ")
+ << dec << req->size << " bytes (value = 0x";
+ printData(cerr, req->data, req->size);
+ cerr << ") to addr 0x"
+ << hex << req->paddr
+ << " (0x" << hex << blockAddr(req->paddr) << ")"
+ << " at cycle "
+ << dec << curTick << endl;
+ }
+ if (probe) {
+ cacheInterface->probeAndUpdate(req);
+ completeRequest(req, NULL);
+ } else {
+ req->completionEvent = new MemCompleteEvent(req, NULL, this);
+ cacheInterface->access(req);
+ }
+ } else {
+ // copy
+ unsigned source_align = random() % 100;
+ unsigned dest_align = random() % 100;
+ unsigned offset2 = random() % size;
+
+ Addr source = ((base) ? baseAddr1 : baseAddr2) + offset;
+ Addr dest = ((base) ? baseAddr2 : baseAddr1) + offset2;
+ if (outstandingAddrs.find(source) != outstandingAddrs.end()) return;
+ else outstandingAddrs.insert(source);
+ if (outstandingAddrs.find(dest) != outstandingAddrs.end()) return;
+ else outstandingAddrs.insert(dest);
+
+ if (source_align >= percentSourceUnaligned) {
+ source = blockAddr(source);
+ }
+ if (dest_align >= percentDestUnaligned) {
+ dest = blockAddr(dest);
+ }
+ req->cmd = Copy;
+ req->flags &= ~UNCACHEABLE;
+ req->paddr = source;
+ req->dest = dest;
+ delete [] req->data;
+ req->data = new uint8_t[blockSize];
+ req->size = blockSize;
+ if (source == traceBlockAddr || dest == traceBlockAddr) {
+ cerr << name()
+ << ": initiating copy of "
+ << dec << req->size << " bytes from addr 0x"
+ << hex << source
+ << " (0x" << hex << blockAddr(source) << ")"
+ << " to addr 0x"
+ << hex << dest
+ << " (0x" << hex << blockAddr(dest) << ")"
+ << " at cycle "
+ << dec << curTick << endl;
+ }
+ cacheInterface->access(req);
+ uint8_t result[blockSize];
+ checkMem->access(Read, source, &result, blockSize);
+ checkMem->access(Write, dest, &result, blockSize);
+ }
+}
+
+
+void
+MemCompleteEvent::process()
+{
+ tester->completeRequest(req, data);
+ delete this;
+}
+
+
+const char *
+MemCompleteEvent::description()
+{
+ return "memory access completion";
+}
+
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(MemTest)
+
+ SimObjectParam<BaseCache *> cache;
+ SimObjectParam<FunctionalMemory *> main_mem;
+ SimObjectParam<FunctionalMemory *> check_mem;
+ Param<unsigned> memory_size;
+ Param<unsigned> percent_reads;
+ Param<unsigned> percent_copies;
+ Param<unsigned> percent_uncacheable;
+ Param<unsigned> progress_interval;
+ Param<unsigned> percent_source_unaligned;
+ Param<unsigned> percent_dest_unaligned;
+ Param<Addr> trace_addr;
+ Param<Counter> max_loads;
+
+END_DECLARE_SIM_OBJECT_PARAMS(MemTest)
+
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(MemTest)
+
+ INIT_PARAM(cache, "L1 cache"),
+ INIT_PARAM(main_mem, "hierarchical memory"),
+ INIT_PARAM(check_mem, "check memory"),
+ INIT_PARAM(memory_size, "memory size"),
+ INIT_PARAM(percent_reads, "target read percentage"),
+ INIT_PARAM(percent_copies, "target copy percentage"),
+ INIT_PARAM(percent_uncacheable, "target uncacheable percentage"),
+ INIT_PARAM(progress_interval, "progress report interval (in accesses)"),
+ INIT_PARAM(percent_source_unaligned,
+ "percent of copy source address that are unaligned"),
+ INIT_PARAM(percent_dest_unaligned,
+ "percent of copy dest address that are unaligned"),
+ INIT_PARAM(trace_addr, "address to trace"),
+ INIT_PARAM(max_loads, "terminate when we have reached this load count")
+
+END_INIT_SIM_OBJECT_PARAMS(MemTest)
+
+
+CREATE_SIM_OBJECT(MemTest)
+{
+ return new MemTest(getInstanceName(), cache->getInterface(), main_mem,
+ check_mem, memory_size, percent_reads, percent_copies,
+ percent_uncacheable, progress_interval,
+ percent_source_unaligned, percent_dest_unaligned,
+ trace_addr, max_loads);
+}
+
+REGISTER_SIM_OBJECT("MemTest", MemTest)
diff --git a/cpu/memtest/memtest.hh b/src/cpu/memtest/memtest.hh
index cdb40a26a..cdb40a26a 100644
--- a/cpu/memtest/memtest.hh
+++ b/src/cpu/memtest/memtest.hh
diff --git a/cpu/o3/2bit_local_pred.cc b/src/cpu/o3/2bit_local_pred.cc
index c3fb2fdb8..c3fb2fdb8 100644
--- a/cpu/o3/2bit_local_pred.cc
+++ b/src/cpu/o3/2bit_local_pred.cc
diff --git a/cpu/o3/2bit_local_pred.hh b/src/cpu/o3/2bit_local_pred.hh
index cd65978ca..cd65978ca 100644
--- a/cpu/o3/2bit_local_pred.hh
+++ b/src/cpu/o3/2bit_local_pred.hh
diff --git a/cpu/o3/alpha_cpu.cc b/src/cpu/o3/alpha_cpu.cc
index 7bc90dae6..7bc90dae6 100644
--- a/cpu/o3/alpha_cpu.cc
+++ b/src/cpu/o3/alpha_cpu.cc
diff --git a/src/cpu/o3/alpha_cpu.hh b/src/cpu/o3/alpha_cpu.hh
new file mode 100644
index 000000000..1bab0703e
--- /dev/null
+++ b/src/cpu/o3/alpha_cpu.hh
@@ -0,0 +1,430 @@
+/*
+ * Copyright (c) 2004-2006 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __CPU_O3_ALPHA_FULL_CPU_HH__
+#define __CPU_O3_ALPHA_FULL_CPU_HH__
+
+#include "arch/isa_traits.hh"
+#include "cpu/exec_context.hh"
+#include "cpu/o3/cpu.hh"
+#include "sim/byteswap.hh"
+
+class EndQuiesceEvent;
+namespace Kernel {
+ class Statistics;
+};
+
+template <class Impl>
+class AlphaFullCPU : public FullO3CPU<Impl>
+{
+ protected:
+ typedef TheISA::IntReg IntReg;
+ typedef TheISA::MiscReg MiscReg;
+ typedef TheISA::RegFile RegFile;
+ typedef TheISA::MiscRegFile MiscRegFile;
+
+ public:
+ typedef O3ThreadState<Impl> ImplState;
+ typedef O3ThreadState<Impl> Thread;
+ typedef typename Impl::Params Params;
+
+ /** Constructs an AlphaFullCPU with the given parameters. */
+ AlphaFullCPU(Params *params);
+
+ class AlphaXC : public ExecContext
+ {
+ public:
+ AlphaFullCPU<Impl> *cpu;
+
+ O3ThreadState<Impl> *thread;
+
+ virtual BaseCPU *getCpuPtr() { return cpu; }
+
+ virtual void setCpuId(int id) { cpu->cpu_id = id; }
+
+ virtual int readCpuId() { return cpu->cpu_id; }
+
+ virtual FunctionalMemory *getMemPtr() { return thread->mem; }
+
+#if FULL_SYSTEM
+ virtual System *getSystemPtr() { return cpu->system; }
+
+ virtual PhysicalMemory *getPhysMemPtr() { return cpu->physmem; }
+
+ virtual AlphaITB *getITBPtr() { return cpu->itb; }
+
+ virtual AlphaDTB * getDTBPtr() { return cpu->dtb; }
+
+ virtual Kernel::Statistics *getKernelStats()
+ { return thread->kernelStats; }
+#else
+ virtual Process *getProcessPtr() { return thread->process; }
+#endif
+
+ virtual Status status() const { return thread->status(); }
+
+ virtual void setStatus(Status new_status)
+ { thread->setStatus(new_status); }
+
+ /// Set the status to Active. Optional delay indicates number of
+ /// cycles to wait before beginning execution.
+ virtual void activate(int delay = 1);
+
+ /// Set the status to Suspended.
+ virtual void suspend();
+
+ /// Set the status to Unallocated.
+ virtual void deallocate();
+
+ /// Set the status to Halted.
+ virtual void halt();
+
+#if FULL_SYSTEM
+ virtual void dumpFuncProfile();
+#endif
+
+ virtual void takeOverFrom(ExecContext *old_context);
+
+ virtual void regStats(const std::string &name);
+
+ virtual void serialize(std::ostream &os);
+ virtual void unserialize(Checkpoint *cp, const std::string &section);
+
+#if FULL_SYSTEM
+ virtual EndQuiesceEvent *getQuiesceEvent();
+
+ virtual Tick readLastActivate();
+ virtual Tick readLastSuspend();
+
+ virtual void profileClear();
+ virtual void profileSample();
+#endif
+
+ virtual int getThreadNum() { return thread->tid; }
+
+ virtual TheISA::MachInst getInst();
+
+ virtual void copyArchRegs(ExecContext *xc);
+
+ virtual void clearArchRegs();
+
+ virtual uint64_t readIntReg(int reg_idx);
+
+ virtual float readFloatRegSingle(int reg_idx);
+
+ virtual double readFloatRegDouble(int reg_idx);
+
+ virtual uint64_t readFloatRegInt(int reg_idx);
+
+ virtual void setIntReg(int reg_idx, uint64_t val);
+
+ virtual void setFloatRegSingle(int reg_idx, float val);
+
+ virtual void setFloatRegDouble(int reg_idx, double val);
+
+ virtual void setFloatRegInt(int reg_idx, uint64_t val);
+
+ virtual uint64_t readPC()
+ { return cpu->readPC(thread->tid); }
+
+ virtual void setPC(uint64_t val);
+
+ virtual uint64_t readNextPC()
+ { return cpu->readNextPC(thread->tid); }
+
+ virtual void setNextPC(uint64_t val);
+
+ virtual MiscReg readMiscReg(int misc_reg)
+ { return cpu->readMiscReg(misc_reg, thread->tid); }
+
+ virtual MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault)
+ { return cpu->readMiscRegWithEffect(misc_reg, fault, thread->tid); }
+
+ virtual Fault setMiscReg(int misc_reg, const MiscReg &val);
+
+ virtual Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val);
+
+ // @todo: Figure out where these store cond failures should go.
+ virtual unsigned readStCondFailures()
+ { return thread->storeCondFailures; }
+
+ virtual void setStCondFailures(unsigned sc_failures)
+ { thread->storeCondFailures = sc_failures; }
+
+#if FULL_SYSTEM
+ virtual bool inPalMode()
+ { return TheISA::PcPAL(cpu->readPC(thread->tid)); }
+#endif
+
+ // Only really makes sense for old CPU model. Lots of code
+ // outside the CPU still checks this function, so it will
+ // always return false to keep everything working.
+ virtual bool misspeculating() { return false; }
+
+#if !FULL_SYSTEM
+ virtual IntReg getSyscallArg(int i);
+
+ virtual void setSyscallArg(int i, IntReg val);
+
+ virtual void setSyscallReturn(SyscallReturn return_value);
+
+ virtual void syscall() { return cpu->syscall(thread->tid); }
+
+ virtual Counter readFuncExeInst() { return thread->funcExeInst; }
+#endif
+ };
+
+#if FULL_SYSTEM
+ /** ITB pointer. */
+ AlphaITB *itb;
+ /** DTB pointer. */
+ AlphaDTB *dtb;
+#endif
+
+ /** Registers statistics. */
+ void regStats();
+
+#if FULL_SYSTEM
+ /** Translates instruction requestion. */
+ Fault translateInstReq(MemReqPtr &req)
+ {
+ return itb->translate(req);
+ }
+
+ /** Translates data read request. */
+ Fault translateDataReadReq(MemReqPtr &req)
+ {
+ return dtb->translate(req, false);
+ }
+
+ /** Translates data write request. */
+ Fault translateDataWriteReq(MemReqPtr &req)
+ {
+ return dtb->translate(req, true);
+ }
+
+#else
+ 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;
+ }
+
+ /** Translates instruction requestion in syscall emulation mode. */
+ Fault translateInstReq(MemReqPtr &req)
+ {
+ return dummyTranslation(req);
+ }
+
+ /** Translates data read request in syscall emulation mode. */
+ Fault translateDataReadReq(MemReqPtr &req)
+ {
+ return dummyTranslation(req);
+ }
+
+ /** Translates data write request in syscall emulation mode. */
+ Fault translateDataWriteReq(MemReqPtr &req)
+ {
+ return dummyTranslation(req);
+ }
+
+#endif
+ MiscReg readMiscReg(int misc_reg, unsigned tid);
+
+ MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault, unsigned tid);
+
+ Fault setMiscReg(int misc_reg, const MiscReg &val, unsigned tid);
+
+ Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val, unsigned tid);
+
+ void squashFromXC(unsigned tid);
+
+#if FULL_SYSTEM
+ void post_interrupt(int int_num, int index);
+
+ int readIntrFlag();
+ /** Sets the interrupt flags. */
+ void setIntrFlag(int val);
+ /** HW return from error interrupt. */
+ Fault hwrei(unsigned tid);
+ /** Returns if a specific PC is a PAL mode PC. */
+ bool inPalMode(uint64_t PC)
+ { return AlphaISA::PcPAL(PC); }
+
+ /** Traps to handle given fault. */
+ void trap(Fault fault, unsigned tid);
+ bool simPalCheck(int palFunc, unsigned tid);
+
+ /** Processes any interrupts. */
+ void processInterrupts();
+
+ /** Halts the CPU. */
+ void halt() { panic("Halt not implemented!\n"); }
+#endif
+
+
+#if !FULL_SYSTEM
+ /** Executes a syscall.
+ * @todo: Determine if this needs to be virtual.
+ */
+ void syscall(int thread_num);
+ /** Gets a syscall argument. */
+ IntReg getSyscallArg(int i, int tid);
+
+ /** Used to shift args for indirect syscall. */
+ void setSyscallArg(int i, IntReg val, int tid);
+
+ /** Sets the return value of a syscall. */
+ void setSyscallReturn(SyscallReturn return_value, int tid);
+#endif
+
+ /** Read from memory function. */
+ template <class T>
+ Fault read(MemReqPtr &req, T &data)
+ {
+#if 0
+#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);
+ }
+#endif
+#endif
+ Fault error;
+
+#if FULL_SYSTEM
+ // @todo: Fix this LL/SC hack.
+ if (req->flags & LOCKED) {
+ lockAddr = req->paddr;
+ lockFlag = true;
+ }
+#endif
+
+ error = this->mem->read(req, data);
+ data = gtoh(data);
+ return error;
+ }
+
+ /** CPU read function, forwards read to LSQ. */
+ template <class T>
+ Fault read(MemReqPtr &req, T &data, int load_idx)
+ {
+ return this->iew.ldstQueue.read(req, data, load_idx);
+ }
+
+ /** Write to memory function. */
+ template <class T>
+ Fault write(MemReqPtr &req, T &data)
+ {
+#if 0
+#if FULL_SYSTEM && THE_ISA == ALPHA_ISA
+ ExecContext *xc;
+
+ // If this is a store conditional, act appropriately
+ if (req->flags & LOCKED) {
+ xc = req->xc;
+
+ if (req->flags & UNCACHEABLE) {
+ // Don't update result register (see stq_c in isa_desc)
+ req->result = 2;
+ xc->setStCondFailures(0);//Needed? [RGD]
+ } else {
+ bool lock_flag = xc->readMiscReg(TheISA::Lock_Flag_DepTag);
+ Addr lock_addr = xc->readMiscReg(TheISA::Lock_Addr_DepTag);
+ req->result = lock_flag;
+ if (!lock_flag ||
+ ((lock_addr & ~0xf) != (req->paddr & ~0xf))) {
+ xc->setMiscReg(TheISA::Lock_Flag_DepTag, false);
+ xc->setStCondFailures(xc->readStCondFailures() + 1);
+ if (((xc->readStCondFailures()) % 100000) == 0) {
+ std::cerr << "Warning: "
+ << xc->readStCondFailures()
+ << " consecutive store conditional failures "
+ << "on cpu " << req->xc->readCpuId()
+ << std::endl;
+ }
+ return NoFault;
+ }
+ else xc->setStCondFailures(0);
+ }
+ }
+
+ // Need to clear any locked flags on other proccessors for
+ // this address. Only do this for succsful Store Conditionals
+ // and all other stores (WH64?). Unsuccessful Store
+ // Conditionals would have returned above, and wouldn't fall
+ // through.
+ for (int i = 0; i < this->system->execContexts.size(); i++){
+ xc = this->system->execContexts[i];
+ if ((xc->readMiscReg(TheISA::Lock_Addr_DepTag) & ~0xf) ==
+ (req->paddr & ~0xf)) {
+ xc->setMiscReg(TheISA::Lock_Flag_DepTag, false);
+ }
+ }
+
+#endif
+#endif
+
+#if FULL_SYSTEM
+ // @todo: Fix this LL/SC hack.
+ if (req->flags & LOCKED) {
+ if (req->flags & UNCACHEABLE) {
+ req->result = 2;
+ } else {
+ if (this->lockFlag) {
+ req->result = 1;
+ } else {
+ req->result = 0;
+ return NoFault;
+ }
+ }
+ }
+#endif
+
+ return this->mem->write(req, (T)htog(data));
+ }
+
+ /** CPU write function, forwards write to LSQ. */
+ template <class T>
+ Fault write(MemReqPtr &req, T &data, int store_idx)
+ {
+ return this->iew.ldstQueue.write(req, data, store_idx);
+ }
+
+ Addr lockAddr;
+
+ bool lockFlag;
+};
+
+#endif // __CPU_O3_ALPHA_FULL_CPU_HH__
diff --git a/cpu/o3/alpha_cpu_builder.cc b/src/cpu/o3/alpha_cpu_builder.cc
index b0d812edc..b0d812edc 100644
--- a/cpu/o3/alpha_cpu_builder.cc
+++ b/src/cpu/o3/alpha_cpu_builder.cc
diff --git a/src/cpu/o3/alpha_cpu_impl.hh b/src/cpu/o3/alpha_cpu_impl.hh
new file mode 100644
index 000000000..f7f0a3842
--- /dev/null
+++ b/src/cpu/o3/alpha_cpu_impl.hh
@@ -0,0 +1,775 @@
+/*
+ * Copyright (c) 2004-2006 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "arch/alpha/faults.hh"
+#include "base/cprintf.hh"
+#include "base/statistics.hh"
+#include "base/timebuf.hh"
+#include "cpu/checker/exec_context.hh"
+#include "mem/mem_interface.hh"
+#include "sim/sim_events.hh"
+#include "sim/stats.hh"
+
+#include "cpu/o3/alpha_cpu.hh"
+#include "cpu/o3/alpha_params.hh"
+#include "cpu/o3/comm.hh"
+#include "cpu/o3/thread_state.hh"
+
+#if FULL_SYSTEM
+#include "arch/alpha/osfpal.hh"
+#include "arch/isa_traits.hh"
+#include "cpu/quiesce_event.hh"
+#include "kern/kernel_stats.hh"
+#endif
+
+using namespace TheISA;
+
+template <class Impl>
+AlphaFullCPU<Impl>::AlphaFullCPU(Params *params)
+#if FULL_SYSTEM
+ : FullO3CPU<Impl>(params), itb(params->itb), dtb(params->dtb)
+#else
+ : FullO3CPU<Impl>(params)
+#endif
+{
+ DPRINTF(FullCPU, "AlphaFullCPU: Creating AlphaFullCPU object.\n");
+
+ this->thread.resize(this->numThreads);
+
+ for (int i = 0; i < this->numThreads; ++i) {
+#if FULL_SYSTEM
+ assert(this->numThreads == 1);
+ this->thread[i] = new Thread(this, 0, params->mem);
+ this->thread[i]->setStatus(ExecContext::Suspended);
+#else
+ if (i < params->workload.size()) {
+ DPRINTF(FullCPU, "FullCPU: Workload[%i]'s starting PC is %#x, "
+ "process is %#x",
+ i, params->workload[i]->prog_entry, this->thread[i]);
+ this->thread[i] = new Thread(this, i, params->workload[i], i);
+ assert(params->workload[i]->getMemory() != NULL);
+
+ this->thread[i]->setStatus(ExecContext::Suspended);
+ //usedTids[i] = true;
+ //threadMap[i] = i;
+ } else {
+ //Allocate Empty execution context so M5 can use later
+ //when scheduling threads to CPU
+ Process* dummy_proc = NULL;
+
+ this->thread[i] = new Thread(this, i, dummy_proc, i);
+ //usedTids[i] = false;
+ }
+#endif // !FULL_SYSTEM
+
+ this->thread[i]->numInst = 0;
+
+ ExecContext *xc_proxy;
+
+ AlphaXC *alpha_xc_proxy = new AlphaXC;
+
+ if (params->checker) {
+ xc_proxy = new CheckerExecContext<AlphaXC>(alpha_xc_proxy, this->checker);
+ } else {
+ xc_proxy = alpha_xc_proxy;
+ }
+
+ alpha_xc_proxy->cpu = this;
+ alpha_xc_proxy->thread = this->thread[i];
+
+#if FULL_SYSTEM
+ this->thread[i]->quiesceEvent =
+ new EndQuiesceEvent(xc_proxy);
+ this->thread[i]->lastActivate = 0;
+ this->thread[i]->lastSuspend = 0;
+#endif
+ this->thread[i]->xcProxy = xc_proxy;
+
+ this->execContexts.push_back(xc_proxy);
+ }
+
+
+ for (int i=0; i < this->numThreads; i++) {
+ this->thread[i]->funcExeInst = 0;
+ }
+
+ // Sets CPU pointers. These must be set at this level because the CPU
+ // pointers are defined to be the highest level of CPU class.
+ this->fetch.setCPU(this);
+ this->decode.setCPU(this);
+ this->rename.setCPU(this);
+ this->iew.setCPU(this);
+ this->commit.setCPU(this);
+
+ this->rob.setCPU(this);
+ this->regFile.setCPU(this);
+
+ lockAddr = 0;
+ lockFlag = false;
+}
+
+template <class Impl>
+void
+AlphaFullCPU<Impl>::regStats()
+{
+ // Register stats for everything that has stats.
+ this->fullCPURegStats();
+ this->fetch.regStats();
+ this->decode.regStats();
+ this->rename.regStats();
+ this->iew.regStats();
+ this->commit.regStats();
+}
+
+#if FULL_SYSTEM
+template <class Impl>
+void
+AlphaFullCPU<Impl>::AlphaXC::dumpFuncProfile()
+{
+ // Currently not supported
+}
+#endif
+
+template <class Impl>
+void
+AlphaFullCPU<Impl>::AlphaXC::takeOverFrom(ExecContext *old_context)
+{
+ // some things should already be set up
+ assert(getMemPtr() == old_context->getMemPtr());
+#if FULL_SYSTEM
+ assert(getSystemPtr() == old_context->getSystemPtr());
+#else
+ assert(getProcessPtr() == old_context->getProcessPtr());
+#endif
+
+ // copy over functional state
+ setStatus(old_context->status());
+ copyArchRegs(old_context);
+ setCpuId(old_context->readCpuId());
+#if !FULL_SYSTEM
+ thread->funcExeInst = old_context->readFuncExeInst();
+#else
+ EndQuiesceEvent *other_quiesce = old_context->getQuiesceEvent();
+ if (other_quiesce) {
+ // Point the quiesce event's XC at this XC so that it wakes up
+ // the proper CPU.
+ other_quiesce->xc = this;
+ }
+ if (thread->quiesceEvent) {
+ thread->quiesceEvent->xc = this;
+ }
+
+ // Transfer kernel stats from one CPU to the other.
+ thread->kernelStats = old_context->getKernelStats();
+// storeCondFailures = 0;
+ cpu->lockFlag = false;
+#endif
+
+ old_context->setStatus(ExecContext::Unallocated);
+
+ thread->inSyscall = false;
+ thread->trapPending = false;
+}
+
+template <class Impl>
+void
+AlphaFullCPU<Impl>::AlphaXC::activate(int delay)
+{
+ DPRINTF(FullCPU, "Calling activate on AlphaXC\n");
+
+ if (thread->status() == ExecContext::Active)
+ return;
+
+#if FULL_SYSTEM
+ thread->lastActivate = curTick;
+#endif
+
+ if (thread->status() == ExecContext::Unallocated) {
+ cpu->activateWhenReady(thread->tid);
+ return;
+ }
+
+ thread->setStatus(ExecContext::Active);
+
+ // status() == Suspended
+ cpu->activateContext(thread->tid, delay);
+}
+
+template <class Impl>
+void
+AlphaFullCPU<Impl>::AlphaXC::suspend()
+{
+ DPRINTF(FullCPU, "Calling suspend on AlphaXC\n");
+
+ if (thread->status() == ExecContext::Suspended)
+ return;
+
+#if FULL_SYSTEM
+ thread->lastActivate = curTick;
+ thread->lastSuspend = curTick;
+#endif
+/*
+#if FULL_SYSTEM
+ // Don't change the status from active if there are pending interrupts
+ if (cpu->check_interrupts()) {
+ assert(status() == ExecContext::Active);
+ return;
+ }
+#endif
+*/
+ thread->setStatus(ExecContext::Suspended);
+ cpu->suspendContext(thread->tid);
+}
+
+template <class Impl>
+void
+AlphaFullCPU<Impl>::AlphaXC::deallocate()
+{
+ DPRINTF(FullCPU, "Calling deallocate on AlphaXC\n");
+
+ if (thread->status() == ExecContext::Unallocated)
+ return;
+
+ thread->setStatus(ExecContext::Unallocated);
+ cpu->deallocateContext(thread->tid);
+}
+
+template <class Impl>
+void
+AlphaFullCPU<Impl>::AlphaXC::halt()
+{
+ DPRINTF(FullCPU, "Calling halt on AlphaXC\n");
+
+ if (thread->status() == ExecContext::Halted)
+ return;
+
+ thread->setStatus(ExecContext::Halted);
+ cpu->haltContext(thread->tid);
+}
+
+template <class Impl>
+void
+AlphaFullCPU<Impl>::AlphaXC::regStats(const std::string &name)
+{
+#if FULL_SYSTEM
+ thread->kernelStats = new Kernel::Statistics(cpu->system);
+ thread->kernelStats->regStats(name + ".kern");
+#endif
+}
+
+template <class Impl>
+void
+AlphaFullCPU<Impl>::AlphaXC::serialize(std::ostream &os)
+{
+#if FULL_SYSTEM
+ if (thread->kernelStats)
+ thread->kernelStats->serialize(os);
+#endif
+
+}
+
+template <class Impl>
+void
+AlphaFullCPU<Impl>::AlphaXC::unserialize(Checkpoint *cp, const std::string &section)
+{
+#if FULL_SYSTEM
+ if (thread->kernelStats)
+ thread->kernelStats->unserialize(cp, section);
+#endif
+
+}
+
+#if FULL_SYSTEM
+template <class Impl>
+EndQuiesceEvent *
+AlphaFullCPU<Impl>::AlphaXC::getQuiesceEvent()
+{
+ return thread->quiesceEvent;
+}
+
+template <class Impl>
+Tick
+AlphaFullCPU<Impl>::AlphaXC::readLastActivate()
+{
+ return thread->lastActivate;
+}
+
+template <class Impl>
+Tick
+AlphaFullCPU<Impl>::AlphaXC::readLastSuspend()
+{
+ return thread->lastSuspend;
+}
+
+template <class Impl>
+void
+AlphaFullCPU<Impl>::AlphaXC::profileClear()
+{}
+
+template <class Impl>
+void
+AlphaFullCPU<Impl>::AlphaXC::profileSample()
+{}
+#endif
+
+template <class Impl>
+TheISA::MachInst
+AlphaFullCPU<Impl>::AlphaXC:: getInst()
+{
+ return thread->inst;
+}
+
+template <class Impl>
+void
+AlphaFullCPU<Impl>::AlphaXC::copyArchRegs(ExecContext *xc)
+{
+ // This function will mess things up unless the ROB is empty and
+ // there are no instructions in the pipeline.
+ unsigned tid = thread->tid;
+ PhysRegIndex renamed_reg;
+
+ // First loop through the integer registers.
+ for (int i = 0; i < AlphaISA::NumIntRegs; ++i) {
+ renamed_reg = cpu->renameMap[tid].lookup(i);
+
+ DPRINTF(FullCPU, "FullCPU: Copying over register %i, had data %lli, "
+ "now has data %lli.\n",
+ renamed_reg, cpu->readIntReg(renamed_reg),
+ xc->readIntReg(i));
+
+ cpu->setIntReg(renamed_reg, xc->readIntReg(i));
+ }
+
+ // Then loop through the floating point registers.
+ for (int i = 0; i < AlphaISA::NumFloatRegs; ++i)
+ {
+ renamed_reg = this->renameMap.lookup(i + AlphaISA::FP_Base_DepTag);
+ this->cpuXC->setFloatRegBits(i,
+ this->regFile.readFloatRegBits(renamed_reg));
+ }
+
+ // Copy the misc regs.
+ cpu->regFile.miscRegs[tid].copyMiscRegs(xc);
+
+ // Then finally set the PC and the next PC.
+ cpu->setPC(xc->readPC(), tid);
+ cpu->setNextPC(xc->readNextPC(), tid);
+#if !FULL_SYSTEM
+ this->thread->funcExeInst = xc->readFuncExeInst();
+#endif
+}
+
+template <class Impl>
+void
+AlphaFullCPU<Impl>::AlphaXC::clearArchRegs()
+{}
+
+template <class Impl>
+uint64_t
+AlphaFullCPU<Impl>::AlphaXC::readIntReg(int reg_idx)
+{
+ DPRINTF(Fault, "Reading int register through the XC!\n");
+ return cpu->readArchIntReg(reg_idx, thread->tid);
+}
+
+template <class Impl>
+float
+AlphaFullCPU<Impl>::AlphaXC::readFloatRegSingle(int reg_idx)
+{
+ DPRINTF(Fault, "Reading float register through the XC!\n");
+ return cpu->readArchFloatRegSingle(reg_idx, thread->tid);
+}
+
+template <class Impl>
+double
+AlphaFullCPU<Impl>::AlphaXC::readFloatRegDouble(int reg_idx)
+{
+ DPRINTF(Fault, "Reading float register through the XC!\n");
+ return cpu->readArchFloatRegDouble(reg_idx, thread->tid);
+}
+
+template <class Impl>
+uint64_t
+AlphaFullCPU<Impl>::AlphaXC::readFloatRegInt(int reg_idx)
+{
+ DPRINTF(Fault, "Reading floatint register through the XC!\n");
+ return cpu->readArchFloatRegInt(reg_idx, thread->tid);
+}
+
+template <class Impl>
+void
+AlphaFullCPU<Impl>::AlphaXC::setIntReg(int reg_idx, uint64_t val)
+{
+ DPRINTF(Fault, "Setting int register through the XC!\n");
+ cpu->setArchIntReg(reg_idx, val, thread->tid);
+
+ if (!thread->trapPending && !thread->inSyscall) {
+ cpu->squashFromXC(thread->tid);
+ }
+}
+
+template <class Impl>
+void
+AlphaFullCPU<Impl>::AlphaXC::setFloatRegSingle(int reg_idx, float val)
+{
+ DPRINTF(Fault, "Setting float register through the XC!\n");
+ cpu->setArchFloatRegSingle(reg_idx, val, thread->tid);
+
+ if (!thread->trapPending && !thread->inSyscall) {
+ cpu->squashFromXC(thread->tid);
+ }
+}
+
+template <class Impl>
+void
+AlphaFullCPU<Impl>::AlphaXC::setFloatRegDouble(int reg_idx, double val)
+{
+ DPRINTF(Fault, "Setting float register through the XC!\n");
+ cpu->setArchFloatRegDouble(reg_idx, val, thread->tid);
+
+ if (!thread->trapPending && !thread->inSyscall) {
+ cpu->squashFromXC(thread->tid);
+ }
+}
+
+template <class Impl>
+void
+AlphaFullCPU<Impl>::AlphaXC::setFloatRegInt(int reg_idx, uint64_t val)
+{
+ DPRINTF(Fault, "Setting floatint register through the XC!\n");
+ cpu->setArchFloatRegInt(reg_idx, val, thread->tid);
+
+ if (!thread->trapPending && !thread->inSyscall) {
+ cpu->squashFromXC(thread->tid);
+ }
+}
+
+template <class Impl>
+void
+AlphaFullCPU<Impl>::AlphaXC::setPC(uint64_t val)
+{
+ cpu->setPC(val, thread->tid);
+
+ if (!thread->trapPending && !thread->inSyscall) {
+ cpu->squashFromXC(thread->tid);
+ }
+}
+
+template <class Impl>
+void
+AlphaFullCPU<Impl>::AlphaXC::setNextPC(uint64_t val)
+{
+ cpu->setNextPC(val, thread->tid);
+
+ if (!thread->trapPending && !thread->inSyscall) {
+ cpu->squashFromXC(thread->tid);
+ }
+}
+
+template <class Impl>
+Fault
+AlphaFullCPU<Impl>::AlphaXC::setMiscReg(int misc_reg, const MiscReg &val)
+{
+ DPRINTF(Fault, "Setting misc register through the XC!\n");
+
+ Fault ret_fault = cpu->setMiscReg(misc_reg, val, thread->tid);
+
+ if (!thread->trapPending && !thread->inSyscall) {
+ cpu->squashFromXC(thread->tid);
+ }
+
+ return ret_fault;
+}
+
+template <class Impl>
+Fault
+AlphaFullCPU<Impl>::AlphaXC::setMiscRegWithEffect(int misc_reg, const MiscReg &val)
+{
+ DPRINTF(Fault, "Setting misc register through the XC!\n");
+
+ Fault ret_fault = cpu->setMiscRegWithEffect(misc_reg, val, thread->tid);
+
+ if (!thread->trapPending && !thread->inSyscall) {
+ cpu->squashFromXC(thread->tid);
+ }
+
+ return ret_fault;
+}
+
+#if !FULL_SYSTEM
+
+template <class Impl>
+TheISA::IntReg
+AlphaFullCPU<Impl>::AlphaXC::getSyscallArg(int i)
+{
+ return cpu->getSyscallArg(i, thread->tid);
+}
+
+template <class Impl>
+void
+AlphaFullCPU<Impl>::AlphaXC::setSyscallArg(int i, IntReg val)
+{
+ cpu->setSyscallArg(i, val, thread->tid);
+}
+
+template <class Impl>
+void
+AlphaFullCPU<Impl>::AlphaXC::setSyscallReturn(SyscallReturn return_value)
+{
+ cpu->setSyscallReturn(return_value, thread->tid);
+}
+
+#endif // FULL_SYSTEM
+
+template <class Impl>
+MiscReg
+AlphaFullCPU<Impl>::readMiscReg(int misc_reg, unsigned tid)
+{
+ return this->regFile.readMiscReg(misc_reg, tid);
+}
+
+template <class Impl>
+MiscReg
+AlphaFullCPU<Impl>::readMiscRegWithEffect(int misc_reg, Fault &fault,
+ unsigned tid)
+{
+ return this->regFile.readMiscRegWithEffect(misc_reg, fault, tid);
+}
+
+template <class Impl>
+Fault
+AlphaFullCPU<Impl>::setMiscReg(int misc_reg, const MiscReg &val, unsigned tid)
+{
+ return this->regFile.setMiscReg(misc_reg, val, tid);
+}
+
+template <class Impl>
+Fault
+AlphaFullCPU<Impl>::setMiscRegWithEffect(int misc_reg, const MiscReg &val,
+ unsigned tid)
+{
+ return this->regFile.setMiscRegWithEffect(misc_reg, val, tid);
+}
+
+template <class Impl>
+void
+AlphaFullCPU<Impl>::squashFromXC(unsigned tid)
+{
+ this->thread[tid]->inSyscall = true;
+ this->commit.generateXCEvent(tid);
+}
+
+#if FULL_SYSTEM
+
+template <class Impl>
+void
+AlphaFullCPU<Impl>::post_interrupt(int int_num, int index)
+{
+ BaseCPU::post_interrupt(int_num, index);
+
+ if (this->thread[0]->status() == ExecContext::Suspended) {
+ DPRINTF(IPI,"Suspended Processor awoke\n");
+// xcProxies[0]->activate();
+ this->execContexts[0]->activate();
+ }
+}
+
+template <class Impl>
+int
+AlphaFullCPU<Impl>::readIntrFlag()
+{
+ return this->regFile.readIntrFlag();
+}
+
+template <class Impl>
+void
+AlphaFullCPU<Impl>::setIntrFlag(int val)
+{
+ this->regFile.setIntrFlag(val);
+}
+
+template <class Impl>
+Fault
+AlphaFullCPU<Impl>::hwrei(unsigned tid)
+{
+ // Need to clear the lock flag upon returning from an interrupt.
+ this->lockFlag = false;
+
+ this->thread[tid]->kernelStats->hwrei();
+
+ this->checkInterrupts = true;
+
+ // FIXME: XXX check for interrupts? XXX
+ return NoFault;
+}
+
+template <class Impl>
+bool
+AlphaFullCPU<Impl>::simPalCheck(int palFunc, unsigned tid)
+{
+ if (this->thread[tid]->kernelStats)
+ this->thread[tid]->kernelStats->callpal(palFunc,
+ this->execContexts[tid]);
+
+ switch (palFunc) {
+ case PAL::halt:
+ halt();
+ if (--System::numSystemsRunning == 0)
+ new SimExitEvent("all cpus halted");
+ break;
+
+ case PAL::bpt:
+ case PAL::bugchk:
+ if (this->system->breakpoint())
+ return false;
+ break;
+ }
+
+ return true;
+}
+
+template <class Impl>
+void
+AlphaFullCPU<Impl>::trap(Fault fault, unsigned tid)
+{
+ fault->invoke(this->execContexts[tid]);
+}
+
+template <class Impl>
+void
+AlphaFullCPU<Impl>::processInterrupts()
+{
+ // Check for interrupts here. For now can copy the code that
+ // exists within isa_fullsys_traits.hh. Also assume that thread 0
+ // is the one that handles the interrupts.
+ // @todo: Possibly consolidate the interrupt checking code.
+ // @todo: Allow other threads to handle interrupts.
+
+ // Check if there are any outstanding interrupts
+ //Handle the interrupts
+ int ipl = 0;
+ int summary = 0;
+
+ this->checkInterrupts = false;
+
+ if (this->readMiscReg(IPR_ASTRR, 0))
+ panic("asynchronous traps not implemented\n");
+
+ if (this->readMiscReg(IPR_SIRR, 0)) {
+ for (int i = INTLEVEL_SOFTWARE_MIN;
+ i < INTLEVEL_SOFTWARE_MAX; i++) {
+ if (this->readMiscReg(IPR_SIRR, 0) & (ULL(1) << i)) {
+ // See table 4-19 of the 21164 hardware reference
+ ipl = (i - INTLEVEL_SOFTWARE_MIN) + 1;
+ summary |= (ULL(1) << i);
+ }
+ }
+ }
+
+ uint64_t interrupts = this->intr_status();
+
+ if (interrupts) {
+ for (int i = INTLEVEL_EXTERNAL_MIN;
+ i < INTLEVEL_EXTERNAL_MAX; i++) {
+ if (interrupts & (ULL(1) << i)) {
+ // See table 4-19 of the 21164 hardware reference
+ ipl = i;
+ summary |= (ULL(1) << i);
+ }
+ }
+ }
+
+ if (ipl && ipl > this->readMiscReg(IPR_IPLR, 0)) {
+ this->setMiscReg(IPR_ISR, summary, 0);
+ this->setMiscReg(IPR_INTID, ipl, 0);
+ if (this->checker) {
+ this->checker->cpuXCBase()->setMiscReg(IPR_ISR, summary);
+ this->checker->cpuXCBase()->setMiscReg(IPR_INTID, ipl);
+ }
+ this->trap(Fault(new InterruptFault), 0);
+ DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n",
+ this->readMiscReg(IPR_IPLR, 0), ipl, summary);
+ }
+}
+
+#endif // FULL_SYSTEM
+
+#if !FULL_SYSTEM
+
+template <class Impl>
+void
+AlphaFullCPU<Impl>::syscall(int tid)
+{
+ DPRINTF(FullCPU, "AlphaFullCPU: [tid:%i] Executing syscall().\n\n", tid);
+
+ DPRINTF(Activity,"Activity: syscall() called.\n");
+
+ // Temporarily increase this by one to account for the syscall
+ // instruction.
+ ++(this->thread[tid]->funcExeInst);
+
+ // Execute the actual syscall.
+ this->thread[tid]->syscall();
+
+ // Decrease funcExeInst by one as the normal commit will handle
+ // incrementing it.
+ --(this->thread[tid]->funcExeInst);
+}
+
+template <class Impl>
+TheISA::IntReg
+AlphaFullCPU<Impl>::getSyscallArg(int i, int tid)
+{
+ return this->readArchIntReg(AlphaISA::ArgumentReg0 + i, tid);
+}
+
+template <class Impl>
+void
+AlphaFullCPU<Impl>::setSyscallArg(int i, IntReg val, int tid)
+{
+ this->setArchIntReg(AlphaISA::ArgumentReg0 + i, val, tid);
+}
+
+template <class Impl>
+void
+AlphaFullCPU<Impl>::setSyscallReturn(SyscallReturn return_value, int tid)
+{
+ // check for error condition. Alpha syscall convention is to
+ // indicate success/failure in reg a3 (r19) and put the
+ // return value itself in the standard return value reg (v0).
+ if (return_value.successful()) {
+ // no error
+ this->setArchIntReg(SyscallSuccessReg, 0, tid);
+ this->setArchIntReg(ReturnValueReg, return_value.value(), tid);
+ } else {
+ // got an error, return details
+ this->setArchIntReg(SyscallSuccessReg, (IntReg) -1, tid);
+ this->setArchIntReg(ReturnValueReg, -return_value.value(), tid);
+ }
+}
+#endif
diff --git a/cpu/o3/alpha_dyn_inst.cc b/src/cpu/o3/alpha_dyn_inst.cc
index 72ac77d95..72ac77d95 100644
--- a/cpu/o3/alpha_dyn_inst.cc
+++ b/src/cpu/o3/alpha_dyn_inst.cc
diff --git a/src/cpu/o3/alpha_dyn_inst.hh b/src/cpu/o3/alpha_dyn_inst.hh
new file mode 100644
index 000000000..b03c8c337
--- /dev/null
+++ b/src/cpu/o3/alpha_dyn_inst.hh
@@ -0,0 +1,280 @@
+/*
+ * Copyright (c) 2004-2006 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __CPU_O3_ALPHA_DYN_INST_HH__
+#define __CPU_O3_ALPHA_DYN_INST_HH__
+
+#include "cpu/base_dyn_inst.hh"
+#include "cpu/inst_seq.hh"
+#include "cpu/o3/alpha_cpu.hh"
+#include "cpu/o3/alpha_impl.hh"
+
+/**
+ * Mostly implementation & ISA specific AlphaDynInst. As with most
+ * other classes in the new CPU model, it is templated on the Impl to
+ * allow for passing in of all types, such as the CPU type and the ISA
+ * type. The AlphaDynInst serves as the primary interface to the CPU
+ * for instructions that are executing.
+ */
+template <class Impl>
+class AlphaDynInst : public BaseDynInst<Impl>
+{
+ public:
+ /** Typedef for the CPU. */
+ typedef typename Impl::FullCPU FullCPU;
+
+ /** Binary machine instruction type. */
+ typedef TheISA::MachInst MachInst;
+ /** Extended machine instruction type. */
+ typedef TheISA::ExtMachInst ExtMachInst;
+ /** Logical register index type. */
+ typedef TheISA::RegIndex RegIndex;
+ /** Integer register index type. */
+ typedef TheISA::IntReg IntReg;
+ /** Misc register index type. */
+ typedef TheISA::MiscReg MiscReg;
+
+ enum {
+ MaxInstSrcRegs = TheISA::MaxInstSrcRegs, //< Max source regs
+ MaxInstDestRegs = TheISA::MaxInstDestRegs, //< Max dest regs
+ };
+
+ public:
+ /** BaseDynInst constructor given a binary instruction. */
+ AlphaDynInst(ExtMachInst inst, Addr PC, Addr Pred_PC, InstSeqNum seq_num,
+ FullCPU *cpu);
+
+ /** BaseDynInst constructor given a static inst pointer. */
+ AlphaDynInst(StaticInstPtr &_staticInst);
+
+ /** Executes the instruction.*/
+ Fault execute();
+
+ /** Initiates the access. Only valid for memory operations. */
+ Fault initiateAcc();
+
+ /** Completes the access. Only valid for memory operations. */
+ Fault completeAcc();
+
+ private:
+ /** Initializes variables. */
+ void initVars();
+
+ public:
+ MiscReg readMiscReg(int misc_reg)
+ {
+ return this->cpu->readMiscReg(misc_reg, this->threadNumber);
+ }
+
+ MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault)
+ {
+ return this->cpu->readMiscRegWithEffect(misc_reg, fault,
+ this->threadNumber);
+ }
+
+ Fault setMiscReg(int misc_reg, const MiscReg &val)
+ {
+ this->instResult.integer = val;
+ return this->cpu->setMiscReg(misc_reg, val, this->threadNumber);
+ }
+
+ Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val)
+ {
+ return this->cpu->setMiscRegWithEffect(misc_reg, val,
+ this->threadNumber);
+ }
+
+#if FULL_SYSTEM
+ /** Calls hardware return from error interrupt. */
+ Fault hwrei();
+ /** Reads interrupt flag. */
+ int readIntrFlag();
+ /** Sets interrupt flag. */
+ void setIntrFlag(int val);
+ /** Checks if system is in PAL mode. */
+ bool inPalMode();
+ /** Traps to handle specified fault. */
+ void trap(Fault fault);
+ bool simPalCheck(int palFunc);
+#else
+ /** Calls a syscall. */
+ void syscall();
+#endif
+
+ private:
+ /** Physical register index of the destination registers of this
+ * instruction.
+ */
+ PhysRegIndex _destRegIdx[MaxInstDestRegs];
+
+ /** Physical register index of the source registers of this
+ * instruction.
+ */
+ PhysRegIndex _srcRegIdx[MaxInstSrcRegs];
+
+ /** Physical register index of the previous producers of the
+ * architected destinations.
+ */
+ PhysRegIndex _prevDestRegIdx[MaxInstDestRegs];
+
+ public:
+
+ // The register accessor methods provide the index of the
+ // instruction's operand (e.g., 0 or 1), not the architectural
+ // register index, to simplify the implementation of register
+ // renaming. We find the architectural register index by indexing
+ // into the instruction's own operand index table. Note that a
+ // raw pointer to the StaticInst is provided instead of a
+ // ref-counted StaticInstPtr to redice overhead. This is fine as
+ // long as these methods don't copy the pointer into any long-term
+ // storage (which is pretty hard to imagine they would have reason
+ // to do).
+
+ uint64_t readIntReg(const StaticInst *si, int idx)
+ {
+ return this->cpu->readIntReg(_srcRegIdx[idx]);
+ }
+
+ FloatReg readFloatReg(const StaticInst *si, int idx, int width)
+ {
+ return this->cpu->readFloatReg(_srcRegIdx[idx], width);
+ }
+
+ FloatReg readFloatReg(const StaticInst *si, int idx)
+ {
+ return this->cpu->readFloatReg(_srcRegIdx[idx]);
+ }
+
+ FloatRegBits readFloatRegBits(const StaticInst *si, int idx, int width)
+ {
+ 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
+ * registers.
+ */
+ void setIntReg(const StaticInst *si, int idx, uint64_t val)
+ {
+ this->cpu->setIntReg(_destRegIdx[idx], val);
+ BaseDynInst<Impl>::setIntReg(si, idx, val);
+ }
+
+ void setFloatReg(const StaticInst *si, int idx, FloatReg val, int width)
+ {
+ this->cpu->setFloatReg(_destRegIdx[idx], val, width);
+ BaseDynInst<Impl>::setFloatRegSingle(si, idx, val);
+ }
+
+ void setFloatReg(const StaticInst *si, int idx, FloatReg val)
+ {
+ this->cpu->setFloatReg(_destRegIdx[idx], val);
+ BaseDynInst<Impl>::setFloatRegDouble(si, idx, 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->setFloatRegBits(_destRegIdx[idx], val);
+ BaseDynInst<Impl>::setFloatRegInt(si, idx, val);
+ }
+
+ /** Returns the physical register index of the i'th destination
+ * register.
+ */
+ PhysRegIndex renamedDestRegIdx(int idx) const
+ {
+ return _destRegIdx[idx];
+ }
+
+ /** Returns the physical register index of the i'th source register. */
+ PhysRegIndex renamedSrcRegIdx(int idx) const
+ {
+ return _srcRegIdx[idx];
+ }
+
+ /** Returns the physical register index of the previous physical register
+ * that remapped to the same logical register index.
+ */
+ PhysRegIndex prevDestRegIdx(int idx) const
+ {
+ return _prevDestRegIdx[idx];
+ }
+
+ /** Renames a destination register to a physical register. Also records
+ * the previous physical register that the logical register mapped to.
+ */
+ void renameDestReg(int idx,
+ PhysRegIndex renamed_dest,
+ PhysRegIndex previous_rename)
+ {
+ _destRegIdx[idx] = renamed_dest;
+ _prevDestRegIdx[idx] = previous_rename;
+ }
+
+ /** Renames a source logical register to the physical register which
+ * has/will produce that logical register's result.
+ * @todo: add in whether or not the source register is ready.
+ */
+ void renameSrcReg(int idx, PhysRegIndex renamed_src)
+ {
+ _srcRegIdx[idx] = renamed_src;
+ }
+
+ public:
+ /** Calculates EA part of a memory instruction. Currently unused,
+ * though it may be useful in the future if we want to split
+ * memory operations into EA calculation and memory access parts.
+ */
+ Fault calcEA()
+ {
+ return this->staticInst->eaCompInst()->execute(this, this->traceData);
+ }
+
+ /** Does the memory access part of a memory instruction. Currently unused,
+ * though it may be useful in the future if we want to split
+ * memory operations into EA calculation and memory access parts.
+ */
+ Fault memAccess()
+ {
+ return this->staticInst->memAccInst()->execute(this, this->traceData);
+ }
+};
+
+#endif // __CPU_O3_ALPHA_DYN_INST_HH__
+
diff --git a/cpu/o3/alpha_dyn_inst_impl.hh b/src/cpu/o3/alpha_dyn_inst_impl.hh
index 541d5ab82..541d5ab82 100644
--- a/cpu/o3/alpha_dyn_inst_impl.hh
+++ b/src/cpu/o3/alpha_dyn_inst_impl.hh
diff --git a/cpu/o3/alpha_impl.hh b/src/cpu/o3/alpha_impl.hh
index f404bd3ec..f404bd3ec 100644
--- a/cpu/o3/alpha_impl.hh
+++ b/src/cpu/o3/alpha_impl.hh
diff --git a/cpu/o3/alpha_params.hh b/src/cpu/o3/alpha_params.hh
index e3acf2c05..e3acf2c05 100644
--- a/cpu/o3/alpha_params.hh
+++ b/src/cpu/o3/alpha_params.hh
diff --git a/cpu/o3/bpred_unit.cc b/src/cpu/o3/bpred_unit.cc
index 92344111f..92344111f 100644
--- a/cpu/o3/bpred_unit.cc
+++ b/src/cpu/o3/bpred_unit.cc
diff --git a/cpu/o3/bpred_unit.hh b/src/cpu/o3/bpred_unit.hh
index b7814b2e9..b7814b2e9 100644
--- a/cpu/o3/bpred_unit.hh
+++ b/src/cpu/o3/bpred_unit.hh
diff --git a/cpu/o3/bpred_unit_impl.hh b/src/cpu/o3/bpred_unit_impl.hh
index c37df606b..c37df606b 100644
--- a/cpu/o3/bpred_unit_impl.hh
+++ b/src/cpu/o3/bpred_unit_impl.hh
diff --git a/cpu/o3/btb.cc b/src/cpu/o3/btb.cc
index e5f69043a..e5f69043a 100644
--- a/cpu/o3/btb.cc
+++ b/src/cpu/o3/btb.cc
diff --git a/cpu/o3/btb.hh b/src/cpu/o3/btb.hh
index b9ff42573..b9ff42573 100644
--- a/cpu/o3/btb.hh
+++ b/src/cpu/o3/btb.hh
diff --git a/cpu/o3/comm.hh b/src/cpu/o3/comm.hh
index c36c58d3d..c36c58d3d 100644
--- a/cpu/o3/comm.hh
+++ b/src/cpu/o3/comm.hh
diff --git a/cpu/o3/commit.cc b/src/cpu/o3/commit.cc
index fe5e9c1de..fe5e9c1de 100644
--- a/cpu/o3/commit.cc
+++ b/src/cpu/o3/commit.cc
diff --git a/cpu/o3/commit.hh b/src/cpu/o3/commit.hh
index 66abf8dc6..66abf8dc6 100644
--- a/cpu/o3/commit.hh
+++ b/src/cpu/o3/commit.hh
diff --git a/cpu/o3/commit_impl.hh b/src/cpu/o3/commit_impl.hh
index 346a8bc1c..346a8bc1c 100644
--- a/cpu/o3/commit_impl.hh
+++ b/src/cpu/o3/commit_impl.hh
diff --git a/src/cpu/o3/cpu.cc b/src/cpu/o3/cpu.cc
new file mode 100644
index 000000000..ed02a845b
--- /dev/null
+++ b/src/cpu/o3/cpu.cc
@@ -0,0 +1,1196 @@
+/*
+ * Copyright (c) 2004-2006 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config/full_system.hh"
+
+#if FULL_SYSTEM
+#include "sim/system.hh"
+#else
+#include "sim/process.hh"
+#endif
+
+#include "cpu/activity.hh"
+#include "cpu/checker/cpu.hh"
+#include "cpu/cpu_exec_context.hh"
+#include "cpu/exec_context.hh"
+#include "cpu/o3/alpha_dyn_inst.hh"
+#include "cpu/o3/alpha_impl.hh"
+#include "cpu/o3/cpu.hh"
+
+#include "sim/root.hh"
+#include "sim/stat_control.hh"
+
+using namespace std;
+
+BaseFullCPU::BaseFullCPU(Params *params)
+ : BaseCPU(params), cpu_id(0)
+{
+}
+
+void
+BaseFullCPU::regStats()
+{
+ BaseCPU::regStats();
+}
+
+template <class Impl>
+FullO3CPU<Impl>::TickEvent::TickEvent(FullO3CPU<Impl> *c)
+ : Event(&mainEventQueue, CPU_Tick_Pri), cpu(c)
+{
+}
+
+template <class Impl>
+void
+FullO3CPU<Impl>::TickEvent::process()
+{
+ cpu->tick();
+}
+
+template <class Impl>
+const char *
+FullO3CPU<Impl>::TickEvent::description()
+{
+ return "FullO3CPU tick event";
+}
+
+template <class Impl>
+FullO3CPU<Impl>::FullO3CPU(Params *params)
+ : BaseFullCPU(params),
+ tickEvent(this),
+ removeInstsThisCycle(false),
+ fetch(params),
+ decode(params),
+ rename(params),
+ iew(params),
+ commit(params),
+
+ regFile(params->numPhysIntRegs, params->numPhysFloatRegs),
+
+ freeList(params->numberOfThreads,//number of activeThreads
+ TheISA::NumIntRegs, params->numPhysIntRegs,
+ TheISA::NumFloatRegs, params->numPhysFloatRegs),
+
+ rob(params->numROBEntries, params->squashWidth,
+ params->smtROBPolicy, params->smtROBThreshold,
+ params->numberOfThreads),
+
+ scoreboard(params->numberOfThreads,//number of activeThreads
+ TheISA::NumIntRegs, params->numPhysIntRegs,
+ TheISA::NumFloatRegs, params->numPhysFloatRegs,
+ TheISA::NumMiscRegs * number_of_threads,
+ TheISA::ZeroReg),
+
+ // For now just have these time buffers be pretty big.
+ // @todo: Make these time buffer sizes parameters or derived
+ // from latencies
+ timeBuffer(5, 5),
+ fetchQueue(5, 5),
+ decodeQueue(5, 5),
+ renameQueue(5, 5),
+ iewQueue(5, 5),
+ activityRec(NumStages, 10, params->activity),
+
+ globalSeqNum(1),
+
+#if FULL_SYSTEM
+ system(params->system),
+ memCtrl(system->memctrl),
+ physmem(system->physmem),
+ mem(params->mem),
+#else
+// pTable(params->pTable),
+ mem(params->workload[0]->getMemory()),
+#endif // FULL_SYSTEM
+ switchCount(0),
+ icacheInterface(params->icacheInterface),
+ dcacheInterface(params->dcacheInterface),
+ deferRegistration(params->deferRegistration),
+ numThreads(number_of_threads)
+{
+ _status = Idle;
+
+ if (params->checker) {
+ BaseCPU *temp_checker = params->checker;
+ checker = dynamic_cast<Checker<DynInstPtr> *>(temp_checker);
+ checker->setMemory(mem);
+#if FULL_SYSTEM
+ checker->setSystem(params->system);
+#endif
+ } else {
+ checker = NULL;
+ }
+
+#if !FULL_SYSTEM
+ thread.resize(number_of_threads);
+ tids.resize(number_of_threads);
+#endif
+
+ // The stages also need their CPU pointer setup. However this
+ // must be done at the upper level CPU because they have pointers
+ // to the upper level CPU, and not this FullO3CPU.
+
+ // Set up Pointers to the activeThreads list for each stage
+ fetch.setActiveThreads(&activeThreads);
+ decode.setActiveThreads(&activeThreads);
+ rename.setActiveThreads(&activeThreads);
+ iew.setActiveThreads(&activeThreads);
+ commit.setActiveThreads(&activeThreads);
+
+ // Give each of the stages the time buffer they will use.
+ fetch.setTimeBuffer(&timeBuffer);
+ decode.setTimeBuffer(&timeBuffer);
+ rename.setTimeBuffer(&timeBuffer);
+ iew.setTimeBuffer(&timeBuffer);
+ commit.setTimeBuffer(&timeBuffer);
+
+ // Also setup each of the stages' queues.
+ fetch.setFetchQueue(&fetchQueue);
+ decode.setFetchQueue(&fetchQueue);
+ commit.setFetchQueue(&fetchQueue);
+ decode.setDecodeQueue(&decodeQueue);
+ rename.setDecodeQueue(&decodeQueue);
+ rename.setRenameQueue(&renameQueue);
+ iew.setRenameQueue(&renameQueue);
+ iew.setIEWQueue(&iewQueue);
+ commit.setIEWQueue(&iewQueue);
+ commit.setRenameQueue(&renameQueue);
+
+ commit.setFetchStage(&fetch);
+ commit.setIEWStage(&iew);
+ rename.setIEWStage(&iew);
+ rename.setCommitStage(&commit);
+
+#if !FULL_SYSTEM
+ int active_threads = params->workload.size();
+#else
+ int active_threads = 1;
+#endif
+
+ //Make Sure That this a Valid Architeture
+ assert(params->numPhysIntRegs >= numThreads * TheISA::NumIntRegs);
+ assert(params->numPhysFloatRegs >= numThreads * TheISA::NumFloatRegs);
+
+ rename.setScoreboard(&scoreboard);
+ iew.setScoreboard(&scoreboard);
+
+ // Setup the rename map for whichever stages need it.
+ PhysRegIndex lreg_idx = 0;
+ PhysRegIndex freg_idx = params->numPhysIntRegs; //Index to 1 after int regs
+
+ for (int tid=0; tid < numThreads; tid++) {
+ bool bindRegs = (tid <= active_threads - 1);
+
+ commitRenameMap[tid].init(TheISA::NumIntRegs,
+ params->numPhysIntRegs,
+ lreg_idx, //Index for Logical. Regs
+
+ TheISA::NumFloatRegs,
+ params->numPhysFloatRegs,
+ freg_idx, //Index for Float Regs
+
+ TheISA::NumMiscRegs,
+
+ TheISA::ZeroReg,
+ TheISA::ZeroReg,
+
+ tid,
+ false);
+
+ renameMap[tid].init(TheISA::NumIntRegs,
+ params->numPhysIntRegs,
+ lreg_idx, //Index for Logical. Regs
+
+ TheISA::NumFloatRegs,
+ params->numPhysFloatRegs,
+ freg_idx, //Index for Float Regs
+
+ TheISA::NumMiscRegs,
+
+ TheISA::ZeroReg,
+ TheISA::ZeroReg,
+
+ tid,
+ bindRegs);
+ }
+
+ rename.setRenameMap(renameMap);
+ commit.setRenameMap(commitRenameMap);
+
+ // Give renameMap & rename stage access to the freeList;
+ for (int i=0; i < numThreads; i++) {
+ renameMap[i].setFreeList(&freeList);
+ }
+ rename.setFreeList(&freeList);
+
+ // Setup the page table for whichever stages need it.
+#if !FULL_SYSTEM
+// fetch.setPageTable(pTable);
+// iew.setPageTable(pTable);
+#endif
+
+ // Setup the ROB for whichever stages need it.
+ commit.setROB(&rob);
+
+ lastRunningCycle = curTick;
+
+ contextSwitch = false;
+}
+
+template <class Impl>
+FullO3CPU<Impl>::~FullO3CPU()
+{
+}
+
+template <class Impl>
+void
+FullO3CPU<Impl>::fullCPURegStats()
+{
+ BaseFullCPU::regStats();
+
+ // Register any of the FullCPU's stats here.
+ timesIdled
+ .name(name() + ".timesIdled")
+ .desc("Number of times that the entire CPU went into an idle state and"
+ " unscheduled itself")
+ .prereq(timesIdled);
+
+ idleCycles
+ .name(name() + ".idleCycles")
+ .desc("Total number of cycles that the CPU has spent unscheduled due "
+ "to idling")
+ .prereq(idleCycles);
+
+ // Number of Instructions simulated
+ // --------------------------------
+ // Should probably be in Base CPU but need templated
+ // MaxThreads so put in here instead
+ committedInsts
+ .init(numThreads)
+ .name(name() + ".committedInsts")
+ .desc("Number of Instructions Simulated");
+
+ totalCommittedInsts
+ .name(name() + ".committedInsts_total")
+ .desc("Number of Instructions Simulated");
+
+ cpi
+ .name(name() + ".cpi")
+ .desc("CPI: Cycles Per Instruction")
+ .precision(6);
+ cpi = simTicks / committedInsts;
+
+ totalCpi
+ .name(name() + ".cpi_total")
+ .desc("CPI: Total CPI of All Threads")
+ .precision(6);
+ totalCpi = simTicks / totalCommittedInsts;
+
+ ipc
+ .name(name() + ".ipc")
+ .desc("IPC: Instructions Per Cycle")
+ .precision(6);
+ ipc = committedInsts / simTicks;
+
+ totalIpc
+ .name(name() + ".ipc_total")
+ .desc("IPC: Total IPC of All Threads")
+ .precision(6);
+ totalIpc = totalCommittedInsts / simTicks;
+
+}
+
+template <class Impl>
+void
+FullO3CPU<Impl>::tick()
+{
+ DPRINTF(FullCPU, "\n\nFullCPU: Ticking main, FullO3CPU.\n");
+
+ ++numCycles;
+
+// activity = false;
+
+ //Tick each of the stages
+ fetch.tick();
+
+ decode.tick();
+
+ rename.tick();
+
+ iew.tick();
+
+ commit.tick();
+
+#if !FULL_SYSTEM
+ doContextSwitch();
+#endif
+
+ // Now advance the time buffers
+ timeBuffer.advance();
+
+ fetchQueue.advance();
+ decodeQueue.advance();
+ renameQueue.advance();
+ iewQueue.advance();
+
+ activityRec.advance();
+
+ if (removeInstsThisCycle) {
+ cleanUpRemovedInsts();
+ }
+
+ if (!tickEvent.scheduled()) {
+ if (_status == SwitchedOut) {
+ // increment stat
+ lastRunningCycle = curTick;
+ } else if (!activityRec.active()) {
+ lastRunningCycle = curTick;
+ timesIdled++;
+ } else {
+ tickEvent.schedule(curTick + cycles(1));
+ }
+ }
+
+#if !FULL_SYSTEM
+ updateThreadPriority();
+#endif
+
+}
+
+template <class Impl>
+void
+FullO3CPU<Impl>::init()
+{
+ if (!deferRegistration) {
+ registerExecContexts();
+ }
+
+ // Set inSyscall so that the CPU doesn't squash when initially
+ // setting up registers.
+ for (int i = 0; i < number_of_threads; ++i)
+ thread[i]->inSyscall = true;
+
+ for (int tid=0; tid < number_of_threads; tid++) {
+#if FULL_SYSTEM
+ ExecContext *src_xc = execContexts[tid];
+#else
+ ExecContext *src_xc = thread[tid]->getXCProxy();
+#endif
+ // Threads start in the Suspended State
+ if (src_xc->status() != ExecContext::Suspended) {
+ continue;
+ }
+
+#if FULL_SYSTEM
+ TheISA::initCPU(src_xc, src_xc->readCpuId());
+#endif
+ }
+
+ // Clear inSyscall.
+ for (int i = 0; i < number_of_threads; ++i)
+ thread[i]->inSyscall = false;
+
+ // Initialize stages.
+ fetch.initStage();
+ iew.initStage();
+ rename.initStage();
+ commit.initStage();
+
+ commit.setThreads(thread);
+}
+
+template <class Impl>
+void
+FullO3CPU<Impl>::insertThread(unsigned tid)
+{
+ DPRINTF(FullCPU,"[tid:%i] Initializing thread data");
+ // Will change now that the PC and thread state is internal to the CPU
+ // and not in the CPUExecContext.
+#if 0
+#if FULL_SYSTEM
+ ExecContext *src_xc = system->execContexts[tid];
+#else
+ CPUExecContext *src_xc = thread[tid];
+#endif
+
+ //Bind Int Regs to Rename Map
+ for (int ireg = 0; ireg < TheISA::NumIntRegs; ireg++) {
+ PhysRegIndex phys_reg = freeList.getIntReg();
+
+ renameMap[tid].setEntry(ireg,phys_reg);
+ scoreboard.setReg(phys_reg);
+ }
+
+ //Bind Float Regs to Rename Map
+ for (int freg = 0; freg < TheISA::NumFloatRegs; freg++) {
+ PhysRegIndex phys_reg = freeList.getFloatReg();
+
+ renameMap[tid].setEntry(freg,phys_reg);
+ scoreboard.setReg(phys_reg);
+ }
+
+ //Copy Thread Data Into RegFile
+ this->copyFromXC(tid);
+
+ //Set PC/NPC
+ regFile.pc[tid] = src_xc->readPC();
+ regFile.npc[tid] = src_xc->readNextPC();
+
+ src_xc->setStatus(ExecContext::Active);
+
+ activateContext(tid,1);
+
+ //Reset ROB/IQ/LSQ Entries
+ commit.rob->resetEntries();
+ iew.resetEntries();
+#endif
+}
+
+template <class Impl>
+void
+FullO3CPU<Impl>::removeThread(unsigned tid)
+{
+ DPRINTF(FullCPU,"[tid:%i] Removing thread data");
+#if 0
+ //Unbind Int Regs from Rename Map
+ for (int ireg = 0; ireg < TheISA::NumIntRegs; ireg++) {
+ PhysRegIndex phys_reg = renameMap[tid].lookup(ireg);
+
+ scoreboard.unsetReg(phys_reg);
+ freeList.addReg(phys_reg);
+ }
+
+ //Unbind Float Regs from Rename Map
+ for (int freg = 0; freg < TheISA::NumFloatRegs; freg++) {
+ PhysRegIndex phys_reg = renameMap[tid].lookup(freg);
+
+ scoreboard.unsetReg(phys_reg);
+ freeList.addReg(phys_reg);
+ }
+
+ //Copy Thread Data From RegFile
+ /* Fix Me:
+ * Do we really need to do this if we are removing a thread
+ * in the sense that it's finished (exiting)? If the thread is just
+ * being suspended we might...
+ */
+// this->copyToXC(tid);
+
+ //Squash Throughout Pipeline
+ fetch.squash(0,tid);
+ decode.squash(tid);
+ rename.squash(tid);
+
+ assert(iew.ldstQueue.getCount(tid) == 0);
+
+ //Reset ROB/IQ/LSQ Entries
+ if (activeThreads.size() >= 1) {
+ commit.rob->resetEntries();
+ iew.resetEntries();
+ }
+#endif
+}
+
+
+template <class Impl>
+void
+FullO3CPU<Impl>::activateWhenReady(int tid)
+{
+ DPRINTF(FullCPU,"[tid:%i]: Checking if resources are available for incoming"
+ "(e.g. PhysRegs/ROB/IQ/LSQ) \n",
+ tid);
+
+ bool ready = true;
+
+ if (freeList.numFreeIntRegs() >= TheISA::NumIntRegs) {
+ DPRINTF(FullCPU,"[tid:%i] Suspending thread due to not enough "
+ "Phys. Int. Regs.\n",
+ tid);
+ ready = false;
+ } else if (freeList.numFreeFloatRegs() >= TheISA::NumFloatRegs) {
+ DPRINTF(FullCPU,"[tid:%i] Suspending thread due to not enough "
+ "Phys. Float. Regs.\n",
+ tid);
+ ready = false;
+ } else if (commit.rob->numFreeEntries() >=
+ commit.rob->entryAmount(activeThreads.size() + 1)) {
+ DPRINTF(FullCPU,"[tid:%i] Suspending thread due to not enough "
+ "ROB entries.\n",
+ tid);
+ ready = false;
+ } else if (iew.instQueue.numFreeEntries() >=
+ iew.instQueue.entryAmount(activeThreads.size() + 1)) {
+ DPRINTF(FullCPU,"[tid:%i] Suspending thread due to not enough "
+ "IQ entries.\n",
+ tid);
+ ready = false;
+ } else if (iew.ldstQueue.numFreeEntries() >=
+ iew.ldstQueue.entryAmount(activeThreads.size() + 1)) {
+ DPRINTF(FullCPU,"[tid:%i] Suspending thread due to not enough "
+ "LSQ entries.\n",
+ tid);
+ ready = false;
+ }
+
+ if (ready) {
+ insertThread(tid);
+
+ contextSwitch = false;
+
+ cpuWaitList.remove(tid);
+ } else {
+ suspendContext(tid);
+
+ //blocks fetch
+ contextSwitch = true;
+
+ //do waitlist
+ cpuWaitList.push_back(tid);
+ }
+}
+
+template <class Impl>
+void
+FullO3CPU<Impl>::activateContext(int tid, int delay)
+{
+ // Needs to set each stage to running as well.
+ list<unsigned>::iterator isActive = find(
+ activeThreads.begin(), activeThreads.end(), tid);
+
+ if (isActive == activeThreads.end()) {
+ //May Need to Re-code this if the delay variable is the
+ //delay needed for thread to activate
+ DPRINTF(FullCPU, "Adding Thread %i to active threads list\n",
+ tid);
+
+ activeThreads.push_back(tid);
+ }
+
+ assert(_status == Idle || _status == SwitchedOut);
+
+ scheduleTickEvent(delay);
+
+ // Be sure to signal that there's some activity so the CPU doesn't
+ // deschedule itself.
+ activityRec.activity();
+ fetch.wakeFromQuiesce();
+
+ _status = Running;
+}
+
+template <class Impl>
+void
+FullO3CPU<Impl>::suspendContext(int tid)
+{
+ DPRINTF(FullCPU,"[tid: %i]: Suspended ...\n", tid);
+ unscheduleTickEvent();
+ _status = Idle;
+/*
+ //Remove From Active List, if Active
+ list<unsigned>::iterator isActive = find(
+ activeThreads.begin(), activeThreads.end(), tid);
+
+ if (isActive != activeThreads.end()) {
+ DPRINTF(FullCPU,"[tid:%i]: Removing from active threads list\n",
+ tid);
+ activeThreads.erase(isActive);
+ }
+*/
+}
+
+template <class Impl>
+void
+FullO3CPU<Impl>::deallocateContext(int tid)
+{
+ DPRINTF(FullCPU,"[tid:%i]: Deallocating ...", tid);
+/*
+ //Remove From Active List, if Active
+ list<unsigned>::iterator isActive = find(
+ activeThreads.begin(), activeThreads.end(), tid);
+
+ if (isActive != activeThreads.end()) {
+ DPRINTF(FullCPU,"[tid:%i]: Removing from active threads list\n",
+ tid);
+ activeThreads.erase(isActive);
+
+ removeThread(tid);
+ }
+*/
+}
+
+template <class Impl>
+void
+FullO3CPU<Impl>::haltContext(int tid)
+{
+ DPRINTF(FullCPU,"[tid:%i]: Halted ...", tid);
+/*
+ //Remove From Active List, if Active
+ list<unsigned>::iterator isActive = find(
+ activeThreads.begin(), activeThreads.end(), tid);
+
+ if (isActive != activeThreads.end()) {
+ DPRINTF(FullCPU,"[tid:%i]: Removing from active threads list\n",
+ tid);
+ activeThreads.erase(isActive);
+
+ removeThread(tid);
+ }
+*/
+}
+
+template <class Impl>
+void
+FullO3CPU<Impl>::switchOut(Sampler *_sampler)
+{
+ sampler = _sampler;
+ switchCount = 0;
+ fetch.switchOut();
+ decode.switchOut();
+ rename.switchOut();
+ iew.switchOut();
+ commit.switchOut();
+
+ // Wake the CPU and record activity so everything can drain out if
+ // the CPU is currently idle.
+ wakeCPU();
+ activityRec.activity();
+}
+
+template <class Impl>
+void
+FullO3CPU<Impl>::signalSwitched()
+{
+ if (++switchCount == NumStages) {
+ fetch.doSwitchOut();
+ rename.doSwitchOut();
+ commit.doSwitchOut();
+ instList.clear();
+ while (!removeList.empty()) {
+ removeList.pop();
+ }
+
+ if (checker)
+ checker->switchOut(sampler);
+
+ if (tickEvent.scheduled())
+ tickEvent.squash();
+ sampler->signalSwitched();
+ _status = SwitchedOut;
+ }
+ assert(switchCount <= 5);
+}
+
+template <class Impl>
+void
+FullO3CPU<Impl>::takeOverFrom(BaseCPU *oldCPU)
+{
+ // Flush out any old data from the time buffers.
+ for (int i = 0; i < 10; ++i) {
+ timeBuffer.advance();
+ fetchQueue.advance();
+ decodeQueue.advance();
+ renameQueue.advance();
+ iewQueue.advance();
+ }
+
+ activityRec.reset();
+
+ BaseCPU::takeOverFrom(oldCPU);
+
+ fetch.takeOverFrom();
+ decode.takeOverFrom();
+ rename.takeOverFrom();
+ iew.takeOverFrom();
+ commit.takeOverFrom();
+
+ assert(!tickEvent.scheduled());
+
+ // @todo: Figure out how to properly select the tid to put onto
+ // the active threads list.
+ int tid = 0;
+
+ list<unsigned>::iterator isActive = find(
+ activeThreads.begin(), activeThreads.end(), tid);
+
+ if (isActive == activeThreads.end()) {
+ //May Need to Re-code this if the delay variable is the delay
+ //needed for thread to activate
+ DPRINTF(FullCPU, "Adding Thread %i to active threads list\n",
+ tid);
+
+ activeThreads.push_back(tid);
+ }
+
+ // Set all statuses to active, schedule the CPU's tick event.
+ // @todo: Fix up statuses so this is handled properly
+ for (int i = 0; i < execContexts.size(); ++i) {
+ ExecContext *xc = execContexts[i];
+ if (xc->status() == ExecContext::Active && _status != Running) {
+ _status = Running;
+ tickEvent.schedule(curTick);
+ }
+ }
+ if (!tickEvent.scheduled())
+ tickEvent.schedule(curTick);
+}
+
+template <class Impl>
+uint64_t
+FullO3CPU<Impl>::readIntReg(int reg_idx)
+{
+ return regFile.readIntReg(reg_idx);
+}
+
+template <class Impl>
+FloatReg
+FullO3CPU<Impl>::readFloatReg(int reg_idx, int width)
+{
+ return regFile.readFloatReg(reg_idx, width);
+}
+
+template <class Impl>
+FloatReg
+FullO3CPU<Impl>::readFloatReg(int reg_idx)
+{
+ return regFile.readFloatReg(reg_idx);
+}
+
+template <class Impl>
+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.readFloatRegBits(reg_idx);
+}
+
+template <class Impl>
+void
+FullO3CPU<Impl>::setIntReg(int reg_idx, uint64_t val)
+{
+ regFile.setIntReg(reg_idx, val);
+}
+
+template <class Impl>
+void
+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.setFloatReg(reg_idx, val);
+}
+
+template <class Impl>
+void
+FullO3CPU<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val, int width)
+{
+ regFile.setFloatRegBits(reg_idx, val, width);
+}
+
+template <class Impl>
+void
+FullO3CPU<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val)
+{
+ regFile.setFloatRegBits(reg_idx, val);
+}
+
+template <class Impl>
+uint64_t
+FullO3CPU<Impl>::readArchIntReg(int reg_idx, unsigned tid)
+{
+ PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx);
+
+ return regFile.readIntReg(phys_reg);
+}
+
+template <class Impl>
+float
+FullO3CPU<Impl>::readArchFloatRegSingle(int reg_idx, unsigned tid)
+{
+ int idx = reg_idx + TheISA::FP_Base_DepTag;
+ PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx);
+
+ return regFile.readFloatRegSingle(phys_reg);
+}
+
+template <class Impl>
+double
+FullO3CPU<Impl>::readArchFloatRegDouble(int reg_idx, unsigned tid)
+{
+ int idx = reg_idx + TheISA::FP_Base_DepTag;
+ PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx);
+
+ return regFile.readFloatRegDouble(phys_reg);
+}
+
+template <class Impl>
+uint64_t
+FullO3CPU<Impl>::readArchFloatRegInt(int reg_idx, unsigned tid)
+{
+ int idx = reg_idx + TheISA::FP_Base_DepTag;
+ PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx);
+
+ return regFile.readFloatRegInt(phys_reg);
+}
+
+template <class Impl>
+void
+FullO3CPU<Impl>::setArchIntReg(int reg_idx, uint64_t val, unsigned tid)
+{
+ PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx);
+
+ regFile.setIntReg(phys_reg, val);
+}
+
+template <class Impl>
+void
+FullO3CPU<Impl>::setArchFloatRegSingle(int reg_idx, float val, unsigned tid)
+{
+ PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx);
+
+ regFile.setFloatRegSingle(phys_reg, val);
+}
+
+template <class Impl>
+void
+FullO3CPU<Impl>::setArchFloatRegDouble(int reg_idx, double val, unsigned tid)
+{
+ PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx);
+
+ regFile.setFloatRegDouble(phys_reg, val);
+}
+
+template <class Impl>
+void
+FullO3CPU<Impl>::setArchFloatRegInt(int reg_idx, uint64_t val, unsigned tid)
+{
+ PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx);
+
+ regFile.setFloatRegInt(phys_reg, val);
+}
+
+template <class Impl>
+uint64_t
+FullO3CPU<Impl>::readPC(unsigned tid)
+{
+ return commit.readPC(tid);
+}
+
+template <class Impl>
+void
+FullO3CPU<Impl>::setPC(Addr new_PC,unsigned tid)
+{
+ commit.setPC(new_PC, tid);
+}
+
+template <class Impl>
+uint64_t
+FullO3CPU<Impl>::readNextPC(unsigned tid)
+{
+ return commit.readNextPC(tid);
+}
+
+template <class Impl>
+void
+FullO3CPU<Impl>::setNextPC(uint64_t val,unsigned tid)
+{
+ commit.setNextPC(val, tid);
+}
+
+template <class Impl>
+typename FullO3CPU<Impl>::ListIt
+FullO3CPU<Impl>::addInst(DynInstPtr &inst)
+{
+ instList.push_back(inst);
+
+ return --(instList.end());
+}
+
+template <class Impl>
+void
+FullO3CPU<Impl>::instDone(unsigned tid)
+{
+ // Keep an instruction count.
+ thread[tid]->numInst++;
+ thread[tid]->numInsts++;
+ committedInsts[tid]++;
+ totalCommittedInsts++;
+
+ // Check for instruction-count-based events.
+ comInstEventQueue[tid]->serviceEvents(thread[tid]->numInst);
+}
+
+template <class Impl>
+void
+FullO3CPU<Impl>::addToRemoveList(DynInstPtr &inst)
+{
+ removeInstsThisCycle = true;
+
+ removeList.push(inst->getInstListIt());
+}
+
+template <class Impl>
+void
+FullO3CPU<Impl>::removeFrontInst(DynInstPtr &inst)
+{
+ DPRINTF(FullCPU, "FullCPU: Removing committed instruction [tid:%i] PC %#x "
+ "[sn:%lli]\n",
+ inst->threadNumber, inst->readPC(), inst->seqNum);
+
+ removeInstsThisCycle = true;
+
+ // Remove the front instruction.
+ removeList.push(inst->getInstListIt());
+}
+
+template <class Impl>
+void
+FullO3CPU<Impl>::removeInstsNotInROB(unsigned tid)
+{
+ DPRINTF(FullCPU, "FullCPU: Thread %i: Deleting instructions from instruction"
+ " list.\n", tid);
+
+ ListIt end_it;
+
+ bool rob_empty = false;
+
+ if (instList.empty()) {
+ return;
+ } else if (rob.isEmpty(/*tid*/)) {
+ DPRINTF(FullCPU, "FullCPU: ROB is empty, squashing all insts.\n");
+ end_it = instList.begin();
+ rob_empty = true;
+ } else {
+ end_it = (rob.readTailInst(tid))->getInstListIt();
+ DPRINTF(FullCPU, "FullCPU: ROB is not empty, squashing insts not in ROB.\n");
+ }
+
+ removeInstsThisCycle = true;
+
+ ListIt inst_it = instList.end();
+
+ inst_it--;
+
+ // Walk through the instruction list, removing any instructions
+ // that were inserted after the given instruction iterator, end_it.
+ while (inst_it != end_it) {
+ assert(!instList.empty());
+
+ squashInstIt(inst_it, tid);
+
+ inst_it--;
+ }
+
+ // If the ROB was empty, then we actually need to remove the first
+ // instruction as well.
+ if (rob_empty) {
+ squashInstIt(inst_it, tid);
+ }
+}
+
+template <class Impl>
+void
+FullO3CPU<Impl>::removeInstsUntil(const InstSeqNum &seq_num,
+ unsigned tid)
+{
+ assert(!instList.empty());
+
+ removeInstsThisCycle = true;
+
+ ListIt inst_iter = instList.end();
+
+ inst_iter--;
+
+ DPRINTF(FullCPU, "FullCPU: Deleting instructions from instruction "
+ "list that are from [tid:%i] and above [sn:%lli] (end=%lli).\n",
+ tid, seq_num, (*inst_iter)->seqNum);
+
+ while ((*inst_iter)->seqNum > seq_num) {
+
+ bool break_loop = (inst_iter == instList.begin());
+
+ squashInstIt(inst_iter, tid);
+
+ inst_iter--;
+
+ if (break_loop)
+ break;
+ }
+}
+
+template <class Impl>
+inline void
+FullO3CPU<Impl>::squashInstIt(const ListIt &instIt, const unsigned &tid)
+{
+ if ((*instIt)->threadNumber == tid) {
+ DPRINTF(FullCPU, "FullCPU: Squashing instruction, "
+ "[tid:%i] [sn:%lli] PC %#x\n",
+ (*instIt)->threadNumber,
+ (*instIt)->seqNum,
+ (*instIt)->readPC());
+
+ // Mark it as squashed.
+ (*instIt)->setSquashed();
+
+ // @todo: Formulate a consistent method for deleting
+ // instructions from the instruction list
+ // Remove the instruction from the list.
+ removeList.push(instIt);
+ }
+}
+
+template <class Impl>
+void
+FullO3CPU<Impl>::cleanUpRemovedInsts()
+{
+ while (!removeList.empty()) {
+ DPRINTF(FullCPU, "FullCPU: Removing instruction, "
+ "[tid:%i] [sn:%lli] PC %#x\n",
+ (*removeList.front())->threadNumber,
+ (*removeList.front())->seqNum,
+ (*removeList.front())->readPC());
+
+ instList.erase(removeList.front());
+
+ removeList.pop();
+ }
+
+ removeInstsThisCycle = false;
+}
+/*
+template <class Impl>
+void
+FullO3CPU<Impl>::removeAllInsts()
+{
+ instList.clear();
+}
+*/
+template <class Impl>
+void
+FullO3CPU<Impl>::dumpInsts()
+{
+ int num = 0;
+
+ ListIt inst_list_it = instList.begin();
+
+ cprintf("Dumping Instruction List\n");
+
+ while (inst_list_it != instList.end()) {
+ cprintf("Instruction:%i\nPC:%#x\n[tid:%i]\n[sn:%lli]\nIssued:%i\n"
+ "Squashed:%i\n\n",
+ num, (*inst_list_it)->readPC(), (*inst_list_it)->threadNumber,
+ (*inst_list_it)->seqNum, (*inst_list_it)->isIssued(),
+ (*inst_list_it)->isSquashed());
+ inst_list_it++;
+ ++num;
+ }
+}
+/*
+template <class Impl>
+void
+FullO3CPU<Impl>::wakeDependents(DynInstPtr &inst)
+{
+ iew.wakeDependents(inst);
+}
+*/
+template <class Impl>
+void
+FullO3CPU<Impl>::wakeCPU()
+{
+ if (activityRec.active() || tickEvent.scheduled()) {
+ DPRINTF(Activity, "CPU already running.\n");
+ return;
+ }
+
+ DPRINTF(Activity, "Waking up CPU\n");
+
+ idleCycles += (curTick - 1) - lastRunningCycle;
+
+ tickEvent.schedule(curTick);
+}
+
+template <class Impl>
+int
+FullO3CPU<Impl>::getFreeTid()
+{
+ for (int i=0; i < numThreads; i++) {
+ if (!tids[i]) {
+ tids[i] = true;
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+template <class Impl>
+void
+FullO3CPU<Impl>::doContextSwitch()
+{
+ if (contextSwitch) {
+
+ //ADD CODE TO DEACTIVE THREAD HERE (???)
+
+ for (int tid=0; tid < cpuWaitList.size(); tid++) {
+ activateWhenReady(tid);
+ }
+
+ if (cpuWaitList.size() == 0)
+ contextSwitch = true;
+ }
+}
+
+template <class Impl>
+void
+FullO3CPU<Impl>::updateThreadPriority()
+{
+ if (activeThreads.size() > 1)
+ {
+ //DEFAULT TO ROUND ROBIN SCHEME
+ //e.g. Move highest priority to end of thread list
+ list<unsigned>::iterator list_begin = activeThreads.begin();
+ list<unsigned>::iterator list_end = activeThreads.end();
+
+ unsigned high_thread = *list_begin;
+
+ activeThreads.erase(list_begin);
+
+ activeThreads.push_back(high_thread);
+ }
+}
+
+// Forward declaration of FullO3CPU.
+template class FullO3CPU<AlphaSimpleImpl>;
diff --git a/src/cpu/o3/cpu.hh b/src/cpu/o3/cpu.hh
new file mode 100644
index 000000000..bed95ad54
--- /dev/null
+++ b/src/cpu/o3/cpu.hh
@@ -0,0 +1,525 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __CPU_O3_CPU_HH__
+#define __CPU_O3_CPU_HH__
+
+#include <iostream>
+#include <list>
+#include <queue>
+#include <set>
+#include <vector>
+
+#include "base/statistics.hh"
+#include "base/timebuf.hh"
+#include "config/full_system.hh"
+#include "cpu/activity.hh"
+#include "cpu/base.hh"
+#include "cpu/cpu_exec_context.hh"
+#include "cpu/o3/comm.hh"
+#include "cpu/o3/cpu_policy.hh"
+#include "cpu/o3/scoreboard.hh"
+#include "cpu/o3/thread_state.hh"
+#include "sim/process.hh"
+
+template <class>
+class Checker;
+class ExecContext;
+class MemInterface;
+class Process;
+
+class BaseFullCPU : public BaseCPU
+{
+ //Stuff that's pretty ISA independent will go here.
+ public:
+ typedef BaseCPU::Params Params;
+
+ BaseFullCPU(Params *params);
+
+ void regStats();
+
+ protected:
+ int cpu_id;
+};
+
+template <class Impl>
+class FullO3CPU : public BaseFullCPU
+{
+ public:
+ // Typedefs from the Impl here.
+ typedef typename Impl::CPUPol CPUPolicy;
+ typedef typename Impl::Params Params;
+ typedef typename Impl::DynInstPtr DynInstPtr;
+
+ typedef O3ThreadState<Impl> Thread;
+
+ typedef typename std::list<DynInstPtr>::iterator ListIt;
+
+ public:
+ enum Status {
+ Running,
+ Idle,
+ Halted,
+ Blocked,
+ SwitchedOut
+ };
+
+ /** Overall CPU status. */
+ Status _status;
+
+ private:
+ class TickEvent : public Event
+ {
+ private:
+ /** Pointer to the CPU. */
+ FullO3CPU<Impl> *cpu;
+
+ public:
+ /** Constructs a tick event. */
+ TickEvent(FullO3CPU<Impl> *c);
+
+ /** Processes a tick event, calling tick() on the CPU. */
+ void process();
+ /** Returns the description of the tick event. */
+ const char *description();
+ };
+
+ /** The tick event used for scheduling CPU ticks. */
+ TickEvent tickEvent;
+
+ /** Schedule tick event, regardless of its current state. */
+ void scheduleTickEvent(int delay)
+ {
+ if (tickEvent.squashed())
+ tickEvent.reschedule(curTick + cycles(delay));
+ else if (!tickEvent.scheduled())
+ tickEvent.schedule(curTick + cycles(delay));
+ }
+
+ /** Unschedule tick event, regardless of its current state. */
+ void unscheduleTickEvent()
+ {
+ if (tickEvent.scheduled())
+ tickEvent.squash();
+ }
+
+ public:
+ /** Constructs a CPU with the given parameters. */
+ FullO3CPU(Params *params);
+ /** Destructor. */
+ ~FullO3CPU();
+
+ /** Registers statistics. */
+ void fullCPURegStats();
+
+ /** Ticks CPU, calling tick() on each stage, and checking the overall
+ * activity to see if the CPU should deschedule itself.
+ */
+ void tick();
+
+ /** Initialize the CPU */
+ void init();
+
+ /** Setup CPU to insert a thread's context */
+ void insertThread(unsigned tid);
+
+ /** Remove all of a thread's context from CPU */
+ void removeThread(unsigned tid);
+
+ /** Count the Total Instructions Committed in the CPU. */
+ virtual Counter totalInstructions() const
+ {
+ Counter total(0);
+
+ for (int i=0; i < thread.size(); i++)
+ total += thread[i]->numInst;
+
+ return total;
+ }
+
+ /** Add Thread to Active Threads List. */
+ void activateContext(int tid, int delay);
+
+ /** Remove Thread from Active Threads List */
+ void suspendContext(int tid);
+
+ /** Remove Thread from Active Threads List &&
+ * Remove Thread Context from CPU.
+ */
+ void deallocateContext(int tid);
+
+ /** Remove Thread from Active Threads List &&
+ * Remove Thread Context from CPU.
+ */
+ void haltContext(int tid);
+
+ /** Activate a Thread When CPU Resources are Available. */
+ void activateWhenReady(int tid);
+
+ /** Add or Remove a Thread Context in the CPU. */
+ void doContextSwitch();
+
+ /** Update The Order In Which We Process Threads. */
+ void updateThreadPriority();
+
+ /** Executes a syscall on this cycle.
+ * ---------------------------------------
+ * Note: this is a virtual function. CPU-Specific
+ * functionality defined in derived classes
+ */
+ virtual void syscall(int tid) { panic("Unimplemented!"); }
+
+ /** Check if there are any system calls pending. */
+ void checkSyscalls();
+
+ /** Switches out this CPU.
+ */
+ void switchOut(Sampler *sampler);
+
+ void signalSwitched();
+
+ /** Takes over from another CPU.
+ */
+ void takeOverFrom(BaseCPU *oldCPU);
+
+ /** Get the current instruction sequence number, and increment it. */
+ InstSeqNum getAndIncrementInstSeq()
+ { return globalSeqNum++; }
+
+#if FULL_SYSTEM
+ /** Check if this address is a valid instruction address. */
+ bool validInstAddr(Addr addr) { return true; }
+
+ /** Check if this address is a valid data address. */
+ bool validDataAddr(Addr addr) { return true; }
+
+ /** Get instruction asid. */
+ int getInstAsid(unsigned tid)
+ { return regFile.miscRegs[tid].getInstAsid(); }
+
+ /** Get data asid. */
+ int getDataAsid(unsigned tid)
+ { return regFile.miscRegs[tid].getDataAsid(); }
+#else
+ /** Check if this address is a valid instruction address. */
+ bool validInstAddr(Addr addr,unsigned tid)
+ { return thread[tid]->validInstAddr(addr); }
+
+ /** Check if this address is a valid data address. */
+ bool validDataAddr(Addr addr,unsigned tid)
+ { return thread[tid]->validDataAddr(addr); }
+
+ /** Get instruction asid. */
+ int getInstAsid(unsigned tid)
+ { return thread[tid]->asid; }
+
+ /** Get data asid. */
+ int getDataAsid(unsigned tid)
+ { return thread[tid]->asid; }
+
+#endif
+
+ //
+ // New accessors for new decoder.
+ //
+ uint64_t readIntReg(int reg_idx);
+
+ FloatReg readFloatReg(int reg_idx);
+
+ FloatReg readFloatReg(int reg_idx, int width);
+
+ FloatRegBits readFloatRegBits(int reg_idx);
+
+ FloatRegBits readFloatRegBits(int reg_idx, int width);
+
+ void setIntReg(int reg_idx, uint64_t val);
+
+ void setFloatReg(int reg_idx, FloatReg val, int width);
+
+ void setFloatReg(int reg_idx, FloatReg val, int width);
+
+ void setFloatRegBits(int reg_idx, FloatRegBits val);
+
+ void setFloatRegBits(int reg_idx, FloatRegBits val);
+
+ uint64_t readArchIntReg(int reg_idx, unsigned tid);
+
+ float readArchFloatRegSingle(int reg_idx, unsigned tid);
+
+ double readArchFloatRegDouble(int reg_idx, unsigned tid);
+
+ uint64_t readArchFloatRegInt(int reg_idx, unsigned tid);
+
+ void setArchIntReg(int reg_idx, uint64_t val, unsigned tid);
+
+ void setArchFloatRegSingle(int reg_idx, float val, unsigned tid);
+
+ void setArchFloatRegDouble(int reg_idx, double val, unsigned tid);
+
+ void setArchFloatRegInt(int reg_idx, uint64_t val, unsigned tid);
+
+ uint64_t readPC(unsigned tid);
+
+ void setPC(Addr new_PC,unsigned tid);
+
+ uint64_t readNextPC(unsigned tid);
+
+ void setNextPC(uint64_t val,unsigned tid);
+
+ /** Function to add instruction onto the head of the list of the
+ * instructions. Used when new instructions are fetched.
+ */
+ ListIt addInst(DynInstPtr &inst);
+
+ /** Function to tell the CPU that an instruction has completed. */
+ void instDone(unsigned tid);
+
+ /** Add Instructions to the CPU Remove List*/
+ void addToRemoveList(DynInstPtr &inst);
+
+ /** Remove an instruction from the front end of the list. There's
+ * no restriction on location of the instruction.
+ */
+ void removeFrontInst(DynInstPtr &inst);
+
+ /** Remove all instructions that are not currently in the ROB. */
+ void removeInstsNotInROB(unsigned tid);
+
+ /** Remove all instructions younger than the given sequence number. */
+ void removeInstsUntil(const InstSeqNum &seq_num,unsigned tid);
+
+ inline void squashInstIt(const ListIt &instIt, const unsigned &tid);
+
+ void cleanUpRemovedInsts();
+
+ /** Remove all instructions from the list. */
+// void removeAllInsts();
+
+ void dumpInsts();
+
+ /** Basically a wrapper function so that instructions executed at
+ * commit can tell the instruction queue that they have
+ * completed. Eventually this hack should be removed.
+ */
+// void wakeDependents(DynInstPtr &inst);
+
+ public:
+ /** List of all the instructions in flight. */
+ std::list<DynInstPtr> instList;
+
+ /** List of all the instructions that will be removed at the end of this
+ * cycle.
+ */
+ std::queue<ListIt> removeList;
+
+#ifdef DEBUG
+ std::set<InstSeqNum> snList;
+#endif
+
+ /** Records if instructions need to be removed this cycle due to
+ * being retired or squashed.
+ */
+ bool removeInstsThisCycle;
+
+ protected:
+ /** The fetch stage. */
+ typename CPUPolicy::Fetch fetch;
+
+ /** The decode stage. */
+ typename CPUPolicy::Decode decode;
+
+ /** The dispatch stage. */
+ typename CPUPolicy::Rename rename;
+
+ /** The issue/execute/writeback stages. */
+ typename CPUPolicy::IEW iew;
+
+ /** The commit stage. */
+ typename CPUPolicy::Commit commit;
+
+ /** The register file. */
+ typename CPUPolicy::RegFile regFile;
+
+ /** The free list. */
+ typename CPUPolicy::FreeList freeList;
+
+ /** The rename map. */
+ typename CPUPolicy::RenameMap renameMap[Impl::MaxThreads];
+
+ /** The commit rename map. */
+ typename CPUPolicy::RenameMap commitRenameMap[Impl::MaxThreads];
+
+ /** The re-order buffer. */
+ typename CPUPolicy::ROB rob;
+
+ /** Active Threads List */
+ std::list<unsigned> activeThreads;
+
+ /** Integer Register Scoreboard */
+ Scoreboard scoreboard;
+
+ public:
+ /** Enum to give each stage a specific index, so when calling
+ * activateStage() or deactivateStage(), they can specify which stage
+ * is being activated/deactivated.
+ */
+ enum StageIdx {
+ FetchIdx,
+ DecodeIdx,
+ RenameIdx,
+ IEWIdx,
+ CommitIdx,
+ NumStages };
+
+ /** Typedefs from the Impl to get the structs that each of the
+ * time buffers should use.
+ */
+ typedef typename CPUPolicy::TimeStruct TimeStruct;
+
+ typedef typename CPUPolicy::FetchStruct FetchStruct;
+
+ typedef typename CPUPolicy::DecodeStruct DecodeStruct;
+
+ typedef typename CPUPolicy::RenameStruct RenameStruct;
+
+ typedef typename CPUPolicy::IEWStruct IEWStruct;
+
+ /** The main time buffer to do backwards communication. */
+ TimeBuffer<TimeStruct> timeBuffer;
+
+ /** The fetch stage's instruction queue. */
+ TimeBuffer<FetchStruct> fetchQueue;
+
+ /** The decode stage's instruction queue. */
+ TimeBuffer<DecodeStruct> decodeQueue;
+
+ /** The rename stage's instruction queue. */
+ TimeBuffer<RenameStruct> renameQueue;
+
+ /** The IEW stage's instruction queue. */
+ TimeBuffer<IEWStruct> iewQueue;
+
+ public:
+ ActivityRecorder activityRec;
+
+ void activityThisCycle() { activityRec.activity(); }
+
+ void activateStage(const StageIdx idx)
+ { activityRec.activateStage(idx); }
+
+ void deactivateStage(const StageIdx idx)
+ { activityRec.deactivateStage(idx); }
+
+ /** Wakes the CPU, rescheduling the CPU if it's not already active. */
+ void wakeCPU();
+
+ /** Gets a free thread id. Use if thread ids change across system. */
+ int getFreeTid();
+
+ public:
+ /** Temporary function to get pointer to exec context. */
+ ExecContext *xcBase(unsigned tid)
+ {
+ return thread[tid]->getXCProxy();
+ }
+
+ /** The global sequence number counter. */
+ InstSeqNum globalSeqNum;
+
+ Checker<DynInstPtr> *checker;
+
+#if FULL_SYSTEM
+ /** Pointer to the system. */
+ System *system;
+
+ /** Pointer to the memory controller. */
+ MemoryController *memCtrl;
+ /** Pointer to physical memory. */
+ PhysicalMemory *physmem;
+#endif
+
+ /** Pointer to memory. */
+ FunctionalMemory *mem;
+
+ Sampler *sampler;
+
+ int switchCount;
+
+ // List of all ExecContexts.
+ std::vector<Thread *> thread;
+
+#if 0
+ /** Page table pointer. */
+ PageTable *pTable;
+#endif
+
+ /** Pointer to the icache interface. */
+ MemInterface *icacheInterface;
+ /** Pointer to the dcache interface. */
+ MemInterface *dcacheInterface;
+
+ /** Whether or not the CPU should defer its registration. */
+ bool deferRegistration;
+
+ /** Is there a context switch pending? */
+ bool contextSwitch;
+
+ /** Threads Scheduled to Enter CPU */
+ std::list<int> cpuWaitList;
+
+ /** The cycle that the CPU was last running, used for statistics. */
+ Tick lastRunningCycle;
+
+ /** Number of Threads CPU can process */
+ unsigned numThreads;
+
+ /** Mapping for system thread id to cpu id */
+ std::map<unsigned,unsigned> threadMap;
+
+ /** Available thread ids in the cpu*/
+ std::vector<unsigned> tids;
+
+ /** Stat for total number of times the CPU is descheduled. */
+ Stats::Scalar<> timesIdled;
+ /** Stat for total number of cycles the CPU spends descheduled. */
+ Stats::Scalar<> idleCycles;
+ /** Stat for the number of committed instructions per thread. */
+ Stats::Vector<> committedInsts;
+ /** Stat for the total number of committed instructions. */
+ Stats::Scalar<> totalCommittedInsts;
+ /** Stat for the CPI per thread. */
+ Stats::Formula cpi;
+ /** Stat for the total CPI. */
+ Stats::Formula totalCpi;
+ /** Stat for the IPC per thread. */
+ Stats::Formula ipc;
+ /** Stat for the total IPC. */
+ Stats::Formula totalIpc;
+};
+
+#endif // __CPU_O3_CPU_HH__
diff --git a/cpu/o3/cpu_policy.hh b/src/cpu/o3/cpu_policy.hh
index 52227013e..52227013e 100644
--- a/cpu/o3/cpu_policy.hh
+++ b/src/cpu/o3/cpu_policy.hh
diff --git a/cpu/o3/decode.cc b/src/cpu/o3/decode.cc
index b14fbb7a3..b14fbb7a3 100644
--- a/cpu/o3/decode.cc
+++ b/src/cpu/o3/decode.cc
diff --git a/cpu/o3/decode.hh b/src/cpu/o3/decode.hh
index 3035b3387..3035b3387 100644
--- a/cpu/o3/decode.hh
+++ b/src/cpu/o3/decode.hh
diff --git a/cpu/o3/decode_impl.hh b/src/cpu/o3/decode_impl.hh
index 2ed7ec6fc..2ed7ec6fc 100644
--- a/cpu/o3/decode_impl.hh
+++ b/src/cpu/o3/decode_impl.hh
diff --git a/cpu/o3/fetch.cc b/src/cpu/o3/fetch.cc
index 7959416be..7959416be 100644
--- a/cpu/o3/fetch.cc
+++ b/src/cpu/o3/fetch.cc
diff --git a/cpu/o3/fetch.hh b/src/cpu/o3/fetch.hh
index 3fcfdc3a1..3fcfdc3a1 100644
--- a/cpu/o3/fetch.hh
+++ b/src/cpu/o3/fetch.hh
diff --git a/cpu/o3/fetch_impl.hh b/src/cpu/o3/fetch_impl.hh
index 1c5e508f6..1c5e508f6 100644
--- a/cpu/o3/fetch_impl.hh
+++ b/src/cpu/o3/fetch_impl.hh
diff --git a/cpu/o3/free_list.cc b/src/cpu/o3/free_list.cc
index bd0f4f034..bd0f4f034 100644
--- a/cpu/o3/free_list.cc
+++ b/src/cpu/o3/free_list.cc
diff --git a/cpu/o3/free_list.hh b/src/cpu/o3/free_list.hh
index 29e84cd44..29e84cd44 100644
--- a/cpu/o3/free_list.hh
+++ b/src/cpu/o3/free_list.hh
diff --git a/cpu/o3/iew.cc b/src/cpu/o3/iew.cc
index 90d035f71..90d035f71 100644
--- a/cpu/o3/iew.cc
+++ b/src/cpu/o3/iew.cc
diff --git a/cpu/o3/iew.hh b/src/cpu/o3/iew.hh
index 935320628..935320628 100644
--- a/cpu/o3/iew.hh
+++ b/src/cpu/o3/iew.hh
diff --git a/cpu/o3/iew_impl.hh b/src/cpu/o3/iew_impl.hh
index b0137d7fc..b0137d7fc 100644
--- a/cpu/o3/iew_impl.hh
+++ b/src/cpu/o3/iew_impl.hh
diff --git a/cpu/o3/inst_queue.cc b/src/cpu/o3/inst_queue.cc
index 95ae2b699..95ae2b699 100644
--- a/cpu/o3/inst_queue.cc
+++ b/src/cpu/o3/inst_queue.cc
diff --git a/cpu/o3/inst_queue.hh b/src/cpu/o3/inst_queue.hh
index 518de73d9..518de73d9 100644
--- a/cpu/o3/inst_queue.hh
+++ b/src/cpu/o3/inst_queue.hh
diff --git a/cpu/o3/inst_queue_impl.hh b/src/cpu/o3/inst_queue_impl.hh
index f1dc4e01f..f1dc4e01f 100644
--- a/cpu/o3/inst_queue_impl.hh
+++ b/src/cpu/o3/inst_queue_impl.hh
diff --git a/cpu/o3/mem_dep_unit.cc b/src/cpu/o3/mem_dep_unit.cc
index ccdd1a515..ccdd1a515 100644
--- a/cpu/o3/mem_dep_unit.cc
+++ b/src/cpu/o3/mem_dep_unit.cc
diff --git a/cpu/o3/mem_dep_unit.hh b/src/cpu/o3/mem_dep_unit.hh
index acbe08ec2..acbe08ec2 100644
--- a/cpu/o3/mem_dep_unit.hh
+++ b/src/cpu/o3/mem_dep_unit.hh
diff --git a/cpu/o3/mem_dep_unit_impl.hh b/src/cpu/o3/mem_dep_unit_impl.hh
index 8b195baab..8b195baab 100644
--- a/cpu/o3/mem_dep_unit_impl.hh
+++ b/src/cpu/o3/mem_dep_unit_impl.hh
diff --git a/cpu/o3/ras.cc b/src/cpu/o3/ras.cc
index 0b3ea4918..0b3ea4918 100644
--- a/cpu/o3/ras.cc
+++ b/src/cpu/o3/ras.cc
diff --git a/cpu/o3/ras.hh b/src/cpu/o3/ras.hh
index 27e7c2df4..27e7c2df4 100644
--- a/cpu/o3/ras.hh
+++ b/src/cpu/o3/ras.hh
diff --git a/src/cpu/o3/regfile.hh b/src/cpu/o3/regfile.hh
new file mode 100644
index 000000000..3350903db
--- /dev/null
+++ b/src/cpu/o3/regfile.hh
@@ -0,0 +1,289 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __CPU_O3_REGFILE_HH__
+#define __CPU_O3_REGFILE_HH__
+
+#include "arch/isa_traits.hh"
+#include "arch/faults.hh"
+#include "base/trace.hh"
+#include "config/full_system.hh"
+#include "cpu/o3/comm.hh"
+
+#if FULL_SYSTEM
+#include "kern/kernel_stats.hh"
+
+#endif
+
+#include <vector>
+
+/**
+ * Simple physical register file class.
+ * This really only depends on the ISA, and not the Impl. Things that are
+ * in the ifdef FULL_SYSTEM are pretty dependent on the ISA, and probably
+ * should go in the AlphaFullCPU.
+ */
+template <class Impl>
+class PhysRegFile
+{
+ protected:
+ typedef TheISA::IntReg IntReg;
+ typedef TheISA::FloatReg FloatReg;
+ typedef TheISA::MiscRegFile MiscRegFile;
+ typedef TheISA::MiscReg MiscReg;
+ // Note that most of the definitions of the IntReg, FloatReg, etc. exist
+ // within the Impl/ISA class and not within this PhysRegFile class.
+
+ // Will make these registers public for now, but they probably should
+ // be private eventually with some accessor functions.
+ public:
+ typedef typename Impl::FullCPU FullCPU;
+
+ /**
+ * Constructs a physical register file with the specified amount of
+ * integer and floating point registers.
+ */
+ PhysRegFile(unsigned _numPhysicalIntRegs,
+ unsigned _numPhysicalFloatRegs);
+
+ //Everything below should be pretty well identical to the normal
+ //register file that exists within AlphaISA class.
+ //The duplication is unfortunate but it's better than having
+ //different ways to access certain registers.
+
+ //Add these in later when everything else is in place
+// void serialize(std::ostream &os);
+// void unserialize(Checkpoint *cp, const std::string &section);
+
+ /** Reads an integer register. */
+ uint64_t readIntReg(PhysRegIndex reg_idx)
+ {
+ assert(reg_idx < numPhysicalIntRegs);
+
+ DPRINTF(IEW, "RegFile: Access to int register %i, has data "
+ "%i\n", int(reg_idx), intRegFile[reg_idx]);
+ return intRegFile[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);
+
+ FloatReg floatReg = floatRegFile.readReg(reg_idx, width);
+
+ DPRINTF(IEW, "RegFile: Access to %d byte float register %i, has "
+ "data %8.8d\n", int(reg_idx), (double)floatReg);
+
+ return floatReg;
+ }
+
+ /** Reads a floating point register (double precision). */
+ FloatReg readFloatReg(PhysRegIndex reg_idx)
+ {
+ // Remove the base Float reg dependency.
+ reg_idx = reg_idx - numPhysicalIntRegs;
+
+ assert(reg_idx < numPhysicalFloatRegs + numPhysicalIntRegs);
+
+ 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 floatReg;
+ }
+
+ /** Reads a floating point register as an integer. */
+ FloatRegBits readFloatRegBits(PhysRegIndex reg_idx, int width)
+ {
+ // Remove the base Float reg dependency.
+ reg_idx = reg_idx - numPhysicalIntRegs;
+
+ assert(reg_idx < numPhysicalFloatRegs + numPhysicalIntRegs);
+
+ 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 floatRegBits;
+ }
+
+ /** Sets an integer register to the given value. */
+ void setIntReg(PhysRegIndex reg_idx, uint64_t val)
+ {
+ assert(reg_idx < numPhysicalIntRegs);
+
+ DPRINTF(IEW, "RegFile: Setting int register %i to %lli\n",
+ int(reg_idx), val);
+
+ if (reg_idx != TheISA::ZeroReg)
+ intRegFile[reg_idx] = val;
+ }
+
+ /** Sets a single precision floating point register to the given value. */
+ 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.8d\n",
+ int(reg_idx), (double)val);
+
+ if (reg_idx != TheISA::ZeroReg)
+ floatRegFile.setReg(reg_idx, val, width);
+ }
+
+ /** Sets a double precision floating point register to the given value. */
+ 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.8d\n",
+ int(reg_idx), (double)val);
+
+ if (reg_idx != TheISA::ZeroReg)
+ floatRegFile.setReg(reg_idx, val);
+ }
+
+ /** Sets a floating point register to the given integer value. */
+ void setFloatRegBits(PhysRegIndex reg_idx, FloatRegBits 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 %lli\n",
+ 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);
+ }
+
+ MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault,
+ unsigned thread_id)
+ {
+ return miscRegs[thread_id].readRegWithEffect(misc_reg, fault,
+ cpu->xcBase(thread_id));
+ }
+
+ Fault setMiscReg(int misc_reg, const MiscReg &val, unsigned thread_id)
+ {
+ return miscRegs[thread_id].setReg(misc_reg, val);
+ }
+
+ Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val,
+ unsigned thread_id)
+ {
+ return miscRegs[thread_id].setRegWithEffect(misc_reg, val,
+ cpu->xcBase(thread_id));
+ }
+
+#if FULL_SYSTEM
+ int readIntrFlag() { return intrflag; }
+ /** Sets an interrupt flag. */
+ void setIntrFlag(int val) { intrflag = val; }
+#endif
+
+ public:
+ /** (signed) integer register file. */
+ std::vector<IntReg> intRegFile;
+
+ /** Floating point register file. */
+ std::vector<FloatReg> floatRegFile;
+
+ /** Miscellaneous register file. */
+ MiscRegFile miscRegs[Impl::MaxThreads];
+
+#if FULL_SYSTEM
+ private:
+ int intrflag; // interrupt flag
+#endif
+
+ private:
+ /** CPU pointer. */
+ FullCPU *cpu;
+
+ public:
+ /** Sets the CPU pointer. */
+ void setCPU(FullCPU *cpu_ptr) { cpu = cpu_ptr; }
+
+ /** Number of physical integer registers. */
+ unsigned numPhysicalIntRegs;
+ /** Number of physical floating point registers. */
+ unsigned numPhysicalFloatRegs;
+};
+
+template <class Impl>
+PhysRegFile<Impl>::PhysRegFile(unsigned _numPhysicalIntRegs,
+ unsigned _numPhysicalFloatRegs)
+ : numPhysicalIntRegs(_numPhysicalIntRegs),
+ numPhysicalFloatRegs(_numPhysicalFloatRegs)
+{
+ intRegFile.resize(numPhysicalIntRegs);
+ floatRegFile.resize(numPhysicalFloatRegs);
+
+ //memset(intRegFile, 0, sizeof(*intRegFile));
+ //memset(floatRegFile, 0, sizeof(*floatRegFile));
+}
+
+#endif
diff --git a/cpu/o3/rename.cc b/src/cpu/o3/rename.cc
index 4dc3bf6b2..4dc3bf6b2 100644
--- a/cpu/o3/rename.cc
+++ b/src/cpu/o3/rename.cc
diff --git a/cpu/o3/rename.hh b/src/cpu/o3/rename.hh
index 3f1a27bb5..3f1a27bb5 100644
--- a/cpu/o3/rename.hh
+++ b/src/cpu/o3/rename.hh
diff --git a/cpu/o3/rename_impl.hh b/src/cpu/o3/rename_impl.hh
index b4f1077d1..b4f1077d1 100644
--- a/cpu/o3/rename_impl.hh
+++ b/src/cpu/o3/rename_impl.hh
diff --git a/cpu/o3/rename_map.cc b/src/cpu/o3/rename_map.cc
index fc59058a1..fc59058a1 100644
--- a/cpu/o3/rename_map.cc
+++ b/src/cpu/o3/rename_map.cc
diff --git a/cpu/o3/rename_map.hh b/src/cpu/o3/rename_map.hh
index d7e49ae83..d7e49ae83 100644
--- a/cpu/o3/rename_map.hh
+++ b/src/cpu/o3/rename_map.hh
diff --git a/cpu/o3/rob.cc b/src/cpu/o3/rob.cc
index c10f782fd..c10f782fd 100644
--- a/cpu/o3/rob.cc
+++ b/src/cpu/o3/rob.cc
diff --git a/cpu/o3/rob.hh b/src/cpu/o3/rob.hh
index e05eebe5a..e05eebe5a 100644
--- a/cpu/o3/rob.hh
+++ b/src/cpu/o3/rob.hh
diff --git a/cpu/o3/rob_impl.hh b/src/cpu/o3/rob_impl.hh
index 25e0c80fd..25e0c80fd 100644
--- a/cpu/o3/rob_impl.hh
+++ b/src/cpu/o3/rob_impl.hh
diff --git a/src/cpu/o3/sat_counter.cc b/src/cpu/o3/sat_counter.cc
new file mode 100644
index 000000000..b481b4ad2
--- /dev/null
+++ b/src/cpu/o3/sat_counter.cc
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "base/misc.hh"
+#include "cpu/o3/sat_counter.hh"
+
+SatCounter::SatCounter()
+ : initialVal(0), counter(0)
+{
+}
+
+SatCounter::SatCounter(unsigned bits)
+ : initialVal(0), maxVal((1 << bits) - 1), counter(0)
+{
+}
+
+SatCounter::SatCounter(unsigned bits, uint8_t initial_val)
+ : initialVal(initialVal), maxVal((1 << bits) - 1), counter(initial_val)
+{
+ // Check to make sure initial value doesn't exceed the max counter value.
+ if (initial_val > maxVal) {
+ fatal("BP: Initial counter value exceeds max size.");
+ }
+}
+
+void
+SatCounter::setBits(unsigned bits)
+{
+ maxVal = (1 << bits) - 1;
+}
diff --git a/cpu/o3/sat_counter.hh b/src/cpu/o3/sat_counter.hh
index d01fd93ce..d01fd93ce 100644
--- a/cpu/o3/sat_counter.hh
+++ b/src/cpu/o3/sat_counter.hh
diff --git a/cpu/o3/store_set.cc b/src/cpu/o3/store_set.cc
index 0c957c8c7..0c957c8c7 100644
--- a/cpu/o3/store_set.cc
+++ b/src/cpu/o3/store_set.cc
diff --git a/cpu/o3/store_set.hh b/src/cpu/o3/store_set.hh
index 7189db3ab..7189db3ab 100644
--- a/cpu/o3/store_set.hh
+++ b/src/cpu/o3/store_set.hh
diff --git a/cpu/o3/tournament_pred.cc b/src/cpu/o3/tournament_pred.cc
index 89da7b9f5..89da7b9f5 100644
--- a/cpu/o3/tournament_pred.cc
+++ b/src/cpu/o3/tournament_pred.cc
diff --git a/cpu/o3/tournament_pred.hh b/src/cpu/o3/tournament_pred.hh
index 7b600aa53..7b600aa53 100644
--- a/cpu/o3/tournament_pred.hh
+++ b/src/cpu/o3/tournament_pred.hh
diff --git a/src/cpu/op_class.cc b/src/cpu/op_class.cc
new file mode 100644
index 000000000..00136ded5
--- /dev/null
+++ b/src/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/src/cpu/op_class.hh b/src/cpu/op_class.hh
new file mode 100644
index 000000000..cdb40a0fb
--- /dev/null
+++ b/src/cpu/op_class.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 __CPU__OP_CLASS_HH__
+#define __CPU__OP_CLASS_HH__
+
+/**
+ * @file
+ * Definition of operation classes.
+ */
+
+/**
+ * Instruction operation classes. These classes are used for
+ * assigning instructions to functional units.
+ */
+enum OpClass {
+ 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 op_class.cc.
+ */
+extern const char *opClassStrings[];
+
+#endif // __CPU__OP_CLASS_HH__
diff --git a/cpu/ozone/cpu.cc b/src/cpu/ozone/cpu.cc
index d2ea0164c..d2ea0164c 100644
--- a/cpu/ozone/cpu.cc
+++ b/src/cpu/ozone/cpu.cc
diff --git a/cpu/ozone/cpu.hh b/src/cpu/ozone/cpu.hh
index 5af2b02b2..5af2b02b2 100644
--- a/cpu/ozone/cpu.hh
+++ b/src/cpu/ozone/cpu.hh
diff --git a/cpu/ozone/cpu_impl.hh b/src/cpu/ozone/cpu_impl.hh
index 5675da3a8..5675da3a8 100644
--- a/cpu/ozone/cpu_impl.hh
+++ b/src/cpu/ozone/cpu_impl.hh
diff --git a/cpu/ozone/ea_list.cc b/src/cpu/ozone/ea_list.cc
index 6114a0ca1..6114a0ca1 100644
--- a/cpu/ozone/ea_list.cc
+++ b/src/cpu/ozone/ea_list.cc
diff --git a/cpu/ozone/ea_list.hh b/src/cpu/ozone/ea_list.hh
index c0eee4bb8..c0eee4bb8 100644
--- a/cpu/ozone/ea_list.hh
+++ b/src/cpu/ozone/ea_list.hh
diff --git a/cpu/pc_event.cc b/src/cpu/pc_event.cc
index 050bf1a88..050bf1a88 100644
--- a/cpu/pc_event.cc
+++ b/src/cpu/pc_event.cc
diff --git a/src/cpu/pc_event.hh b/src/cpu/pc_event.hh
new file mode 100644
index 000000000..32b7f3ef5
--- /dev/null
+++ b/src/cpu/pc_event.hh
@@ -0,0 +1,140 @@
+/*
+ * 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 __PC_EVENT_HH__
+#define __PC_EVENT_HH__
+
+#include <vector>
+
+#include "base/misc.hh"
+
+class ExecContext;
+class PCEventQueue;
+
+class PCEvent
+{
+ protected:
+ std::string description;
+ PCEventQueue *queue;
+ Addr evpc;
+
+ public:
+ PCEvent(PCEventQueue *q, const std::string &desc, Addr pc);
+
+ virtual ~PCEvent() { if (queue) remove(); }
+
+ // for DPRINTF
+ virtual const std::string name() const { return description; }
+
+ std::string descr() const { return description; }
+ Addr pc() const { return evpc; }
+
+ bool remove();
+ virtual void process(ExecContext *xc) = 0;
+};
+
+class PCEventQueue
+{
+ protected:
+ typedef PCEvent * record_t;
+ class MapCompare {
+ public:
+ bool operator()(const record_t &l, const record_t &r) const {
+ return l->pc() < r->pc();
+ }
+ bool operator()(const record_t &l, Addr pc) const {
+ return l->pc() < pc;
+ }
+ bool operator()(Addr pc, const record_t &r) const {
+ return pc < r->pc();
+ }
+ };
+ typedef std::vector<record_t> map_t;
+
+ public:
+ typedef map_t::iterator iterator;
+ typedef map_t::const_iterator const_iterator;
+
+ protected:
+ typedef std::pair<iterator, iterator> range_t;
+ typedef std::pair<const_iterator, const_iterator> const_range_t;
+
+ protected:
+ map_t pc_map;
+
+ bool doService(ExecContext *xc);
+
+ public:
+ PCEventQueue();
+ ~PCEventQueue();
+
+ bool remove(PCEvent *event);
+ bool schedule(PCEvent *event);
+ bool service(ExecContext *xc)
+ {
+ if (pc_map.empty())
+ return false;
+
+ return doService(xc);
+ }
+
+ range_t equal_range(Addr pc);
+ range_t equal_range(PCEvent *event) { return equal_range(event->pc()); }
+
+ void dump() const;
+};
+
+
+inline
+PCEvent::PCEvent(PCEventQueue *q, const std::string &desc, Addr pc)
+ : description(desc), queue(q), evpc(pc)
+{
+ queue->schedule(this);
+}
+
+inline bool
+PCEvent::remove()
+{
+ if (!queue)
+ panic("cannot remove an uninitialized event;");
+
+ return queue->remove(this);
+}
+
+class BreakPCEvent : public PCEvent
+{
+ protected:
+ bool remove;
+
+ public:
+ BreakPCEvent(PCEventQueue *q, const std::string &desc, Addr addr,
+ bool del = false);
+ virtual void process(ExecContext *xc);
+};
+
+#endif // __PC_EVENT_HH__
diff --git a/cpu/profile.cc b/src/cpu/profile.cc
index fe3458b61..fe3458b61 100644
--- a/cpu/profile.cc
+++ b/src/cpu/profile.cc
diff --git a/cpu/profile.hh b/src/cpu/profile.hh
index d55c9eec9..d55c9eec9 100644
--- a/cpu/profile.hh
+++ b/src/cpu/profile.hh
diff --git a/src/cpu/simple/atomic.cc b/src/cpu/simple/atomic.cc
new file mode 100644
index 000000000..3cad6e43f
--- /dev/null
+++ b/src/cpu/simple/atomic.cc
@@ -0,0 +1,546 @@
+/*
+ * Copyright (c) 2002-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "arch/utility.hh"
+#include "cpu/exetrace.hh"
+#include "cpu/simple/atomic.hh"
+#include "mem/packet_impl.hh"
+#include "sim/builder.hh"
+
+using namespace std;
+using namespace TheISA;
+
+AtomicSimpleCPU::TickEvent::TickEvent(AtomicSimpleCPU *c)
+ : Event(&mainEventQueue, CPU_Tick_Pri), cpu(c)
+{
+}
+
+
+void
+AtomicSimpleCPU::TickEvent::process()
+{
+ cpu->tick();
+}
+
+const char *
+AtomicSimpleCPU::TickEvent::description()
+{
+ return "AtomicSimpleCPU tick event";
+}
+
+
+void
+AtomicSimpleCPU::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) {
+ ExecContext *xc = execContexts[i];
+
+ // initialize CPU, including PC
+ TheISA::initCPU(xc, xc->readCpuId());
+ }
+#endif
+}
+
+bool
+AtomicSimpleCPU::CpuPort::recvTiming(Packet *pkt)
+{
+ panic("AtomicSimpleCPU doesn't expect recvAtomic callback!");
+ return true;
+}
+
+Tick
+AtomicSimpleCPU::CpuPort::recvAtomic(Packet *pkt)
+{
+ panic("AtomicSimpleCPU doesn't expect recvAtomic callback!");
+ return curTick;
+}
+
+void
+AtomicSimpleCPU::CpuPort::recvFunctional(Packet *pkt)
+{
+ panic("AtomicSimpleCPU doesn't expect recvFunctional callback!");
+}
+
+void
+AtomicSimpleCPU::CpuPort::recvStatusChange(Status status)
+{
+ if (status == RangeChange)
+ return;
+
+ panic("AtomicSimpleCPU doesn't expect recvStatusChange callback!");
+}
+
+Packet *
+AtomicSimpleCPU::CpuPort::recvRetry()
+{
+ panic("AtomicSimpleCPU doesn't expect recvRetry callback!");
+ return NULL;
+}
+
+
+AtomicSimpleCPU::AtomicSimpleCPU(Params *p)
+ : BaseSimpleCPU(p), tickEvent(this),
+ width(p->width), simulate_stalls(p->simulate_stalls),
+ icachePort(name() + "-iport", this), dcachePort(name() + "-iport", this)
+{
+ _status = Idle;
+
+ 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_req, Packet::ReadReq, Packet::Broadcast);
+ ifetch_pkt->dataStatic(&inst);
+
+ 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_req, Packet::ReadReq,
+ Packet::Broadcast);
+ data_read_pkt->dataStatic(&dataReg);
+
+ 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_req, Packet::WriteReq,
+ Packet::Broadcast);
+}
+
+
+AtomicSimpleCPU::~AtomicSimpleCPU()
+{
+}
+
+void
+AtomicSimpleCPU::serialize(ostream &os)
+{
+ BaseSimpleCPU::serialize(os);
+ SERIALIZE_ENUM(_status);
+ nameOut(os, csprintf("%s.tickEvent", name()));
+ tickEvent.serialize(os);
+}
+
+void
+AtomicSimpleCPU::unserialize(Checkpoint *cp, const string &section)
+{
+ BaseSimpleCPU::unserialize(cp, section);
+ UNSERIALIZE_ENUM(_status);
+ tickEvent.unserialize(cp, csprintf("%s.tickEvent", section));
+}
+
+void
+AtomicSimpleCPU::switchOut(Sampler *s)
+{
+ sampler = s;
+ if (status() == Running) {
+ _status = SwitchedOut;
+
+ tickEvent.squash();
+ }
+ sampler->signalSwitched();
+}
+
+
+void
+AtomicSimpleCPU::takeOverFrom(BaseCPU *oldCPU)
+{
+ BaseCPU::takeOverFrom(oldCPU);
+
+ assert(!tickEvent.scheduled());
+
+ // if any of this CPU's ExecContexts are active, mark the CPU as
+ // running and schedule its tick event.
+ for (int i = 0; i < execContexts.size(); ++i) {
+ ExecContext *xc = execContexts[i];
+ if (xc->status() == ExecContext::Active && _status != Running) {
+ _status = Running;
+ tickEvent.schedule(curTick);
+ break;
+ }
+ }
+}
+
+
+void
+AtomicSimpleCPU::activateContext(int thread_num, int delay)
+{
+ assert(thread_num == 0);
+ assert(cpuXC);
+
+ assert(_status == Idle);
+ assert(!tickEvent.scheduled());
+
+ notIdleFraction++;
+ tickEvent.schedule(curTick + cycles(delay));
+ _status = Running;
+}
+
+
+void
+AtomicSimpleCPU::suspendContext(int thread_num)
+{
+ assert(thread_num == 0);
+ assert(cpuXC);
+
+ assert(_status == Running);
+
+ // tick event may not be scheduled if this gets called from inside
+ // an instruction's execution, e.g. "quiesce"
+ if (tickEvent.scheduled())
+ tickEvent.deschedule();
+
+ notIdleFraction--;
+ _status = Idle;
+}
+
+
+template <class T>
+Fault
+AtomicSimpleCPU::read(Addr addr, T &data, unsigned flags)
+{
+ data_read_req->setVaddr(addr);
+ data_read_req->setSize(sizeof(T));
+ data_read_req->setFlags(flags);
+ data_read_req->setTime(curTick);
+
+ if (traceData) {
+ traceData->setAddr(addr);
+ }
+
+ // translate to physical address
+ Fault fault = cpuXC->translateDataReadReq(data_read_req);
+
+ // Now do the access.
+ if (fault == NoFault) {
+ data_read_pkt->reset();
+ data_read_pkt->reinitFromRequest();
+
+ dcache_complete = dcachePort.sendAtomic(data_read_pkt);
+ dcache_access = true;
+
+ assert(data_read_pkt->result == Packet::Success);
+ data = data_read_pkt->get<T>();
+
+ }
+
+ // 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;
+}
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+template
+Fault
+AtomicSimpleCPU::read(Addr addr, uint64_t &data, unsigned flags);
+
+template
+Fault
+AtomicSimpleCPU::read(Addr addr, uint32_t &data, unsigned flags);
+
+template
+Fault
+AtomicSimpleCPU::read(Addr addr, uint16_t &data, unsigned flags);
+
+template
+Fault
+AtomicSimpleCPU::read(Addr addr, uint8_t &data, unsigned flags);
+
+#endif //DOXYGEN_SHOULD_SKIP_THIS
+
+template<>
+Fault
+AtomicSimpleCPU::read(Addr addr, double &data, unsigned flags)
+{
+ return read(addr, *(uint64_t*)&data, flags);
+}
+
+template<>
+Fault
+AtomicSimpleCPU::read(Addr addr, float &data, unsigned flags)
+{
+ return read(addr, *(uint32_t*)&data, flags);
+}
+
+
+template<>
+Fault
+AtomicSimpleCPU::read(Addr addr, int32_t &data, unsigned flags)
+{
+ return read(addr, (uint32_t&)data, flags);
+}
+
+
+template <class T>
+Fault
+AtomicSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
+{
+ data_write_req->setVaddr(addr);
+ data_write_req->setTime(curTick);
+ data_write_req->setSize(sizeof(T));
+ data_write_req->setFlags(flags);
+
+ if (traceData) {
+ traceData->setAddr(addr);
+ }
+
+ // translate to physical address
+ Fault fault = cpuXC->translateDataWriteReq(data_write_req);
+
+ // Now do the access.
+ if (fault == NoFault) {
+ data_write_pkt->reset();
+ data = htog(data);
+ data_write_pkt->dataStatic(&data);
+ data_write_pkt->reinitFromRequest();
+
+ dcache_complete = dcachePort.sendAtomic(data_write_pkt);
+ dcache_access = true;
+
+ assert(data_write_pkt->result == Packet::Success);
+
+ if (res && data_write_req->getFlags() & LOCKED) {
+ *res = data_write_req->getScResult();
+ }
+ }
+
+ // 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");
+
+ // 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;
+}
+
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+template
+Fault
+AtomicSimpleCPU::write(uint64_t data, Addr addr,
+ unsigned flags, uint64_t *res);
+
+template
+Fault
+AtomicSimpleCPU::write(uint32_t data, Addr addr,
+ unsigned flags, uint64_t *res);
+
+template
+Fault
+AtomicSimpleCPU::write(uint16_t data, Addr addr,
+ unsigned flags, uint64_t *res);
+
+template
+Fault
+AtomicSimpleCPU::write(uint8_t data, Addr addr,
+ unsigned flags, uint64_t *res);
+
+#endif //DOXYGEN_SHOULD_SKIP_THIS
+
+template<>
+Fault
+AtomicSimpleCPU::write(double data, Addr addr, unsigned flags, uint64_t *res)
+{
+ return write(*(uint64_t*)&data, addr, flags, res);
+}
+
+template<>
+Fault
+AtomicSimpleCPU::write(float data, Addr addr, unsigned flags, uint64_t *res)
+{
+ return write(*(uint32_t*)&data, addr, flags, res);
+}
+
+
+template<>
+Fault
+AtomicSimpleCPU::write(int32_t data, Addr addr, unsigned flags, uint64_t *res)
+{
+ return write((uint32_t)data, addr, flags, res);
+}
+
+
+void
+AtomicSimpleCPU::tick()
+{
+ Tick latency = cycles(1); // instruction takes one cycle by default
+
+ for (int i = 0; i < width; ++i) {
+ numCycles++;
+
+ checkForInterrupts();
+
+ ifetch_req->resetMin();
+ ifetch_pkt->reset();
+ Fault fault = setupFetchPacket(ifetch_pkt);
+
+ if (fault == NoFault) {
+ Tick icache_complete = icachePort.sendAtomic(ifetch_pkt);
+ // ifetch_req is initialized to read the instruction directly
+ // into the CPU object's inst field.
+
+ dcache_access = false; // assume no dcache access
+ preExecute();
+ fault = curStaticInst->execute(this, traceData);
+ postExecute();
+
+ if (simulate_stalls) {
+ // This calculation assumes that the icache and dcache
+ // access latencies are always a multiple of the CPU's
+ // cycle time. If not, the next tick event may get
+ // scheduled at a non-integer multiple of the CPU
+ // cycle time.
+ Tick icache_stall = icache_complete - curTick - cycles(1);
+ Tick dcache_stall =
+ dcache_access ? dcache_complete - curTick - cycles(1) : 0;
+ latency += icache_stall + dcache_stall;
+ }
+
+ }
+
+ advancePC(fault);
+ }
+
+ if (_status != Idle)
+ tickEvent.schedule(curTick + latency);
+}
+
+
+////////////////////////////////////////////////////////////////////////
+//
+// AtomicSimpleCPU Simulation Object
+//
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(AtomicSimpleCPU)
+
+ Param<Counter> max_insts_any_thread;
+ 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<System *> system;
+ Param<int> cpu_id;
+ Param<Tick> profile;
+#else
+ SimObjectParam<Process *> workload;
+#endif // FULL_SYSTEM
+
+ Param<int> clock;
+
+ Param<bool> defer_registration;
+ Param<int> width;
+ Param<bool> function_trace;
+ Param<Tick> function_trace_start;
+ Param<bool> simulate_stalls;
+
+END_DECLARE_SIM_OBJECT_PARAMS(AtomicSimpleCPU)
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(AtomicSimpleCPU)
+
+ INIT_PARAM(max_insts_any_thread,
+ "terminate when any thread reaches this inst count"),
+ INIT_PARAM(max_insts_all_threads,
+ "terminate when all threads have reached this inst count"),
+ INIT_PARAM(max_loads_any_thread,
+ "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(system, "system object"),
+ INIT_PARAM(cpu_id, "processor ID"),
+ INIT_PARAM(profile, ""),
+#else
+ INIT_PARAM(workload, "processes to run"),
+#endif // FULL_SYSTEM
+
+ INIT_PARAM(clock, "clock speed"),
+ INIT_PARAM(defer_registration, "defer system registration (for sampling)"),
+ INIT_PARAM(width, "cpu width"),
+ INIT_PARAM(function_trace, "Enable function trace"),
+ INIT_PARAM(function_trace_start, "Cycle to start function trace"),
+ INIT_PARAM(simulate_stalls, "Simulate cache stall cycles")
+
+END_INIT_SIM_OBJECT_PARAMS(AtomicSimpleCPU)
+
+
+CREATE_SIM_OBJECT(AtomicSimpleCPU)
+{
+ AtomicSimpleCPU::Params *params = new AtomicSimpleCPU::Params();
+ params->name = getInstanceName();
+ params->numberOfThreads = 1;
+ params->max_insts_any_thread = max_insts_any_thread;
+ params->max_insts_all_threads = max_insts_all_threads;
+ params->max_loads_any_thread = max_loads_any_thread;
+ params->max_loads_all_threads = max_loads_all_threads;
+ params->deferRegistration = defer_registration;
+ params->clock = clock;
+ params->functionTrace = function_trace;
+ params->functionTraceStart = function_trace_start;
+ params->width = width;
+ params->simulate_stalls = simulate_stalls;
+ params->mem = mem;
+
+#if FULL_SYSTEM
+ params->itb = itb;
+ params->dtb = dtb;
+ params->system = system;
+ params->cpu_id = cpu_id;
+ params->profile = profile;
+#else
+ params->process = workload;
+#endif
+
+ AtomicSimpleCPU *cpu = new AtomicSimpleCPU(params);
+ return cpu;
+}
+
+REGISTER_SIM_OBJECT("AtomicSimpleCPU", AtomicSimpleCPU)
+
diff --git a/src/cpu/simple/atomic.hh b/src/cpu/simple/atomic.hh
new file mode 100644
index 000000000..ab3a3e8ef
--- /dev/null
+++ b/src/cpu/simple/atomic.hh
@@ -0,0 +1,139 @@
+/*
+ * 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 __CPU_SIMPLE_ATOMIC_HH__
+#define __CPU_SIMPLE_ATOMIC_HH__
+
+#include "cpu/simple/base.hh"
+
+class AtomicSimpleCPU : public BaseSimpleCPU
+{
+ public:
+
+ struct Params : public BaseSimpleCPU::Params {
+ int width;
+ bool simulate_stalls;
+ };
+
+ AtomicSimpleCPU(Params *params);
+ virtual ~AtomicSimpleCPU();
+
+ virtual void init();
+
+ public:
+ //
+ enum Status {
+ Running,
+ Idle,
+ SwitchedOut
+ };
+
+ protected:
+ Status _status;
+
+ Status status() const { return _status; }
+
+ private:
+
+ struct TickEvent : public Event
+ {
+ AtomicSimpleCPU *cpu;
+
+ TickEvent(AtomicSimpleCPU *c);
+ void process();
+ const char *description();
+ };
+
+ TickEvent tickEvent;
+
+ const int width;
+ const bool simulate_stalls;
+
+ // main simulation loop (one cycle)
+ void tick();
+
+ class CpuPort : public Port
+ {
+
+ AtomicSimpleCPU *cpu;
+
+ public:
+
+ CpuPort(const std::string &_name, AtomicSimpleCPU *_cpu)
+ : Port(_name), 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(); }
+ };
+
+ CpuPort icachePort;
+ CpuPort dcachePort;
+
+ Request *ifetch_req;
+ Packet *ifetch_pkt;
+ Request *data_read_req;
+ Packet *data_read_pkt;
+ Request *data_write_req;
+ Packet *data_write_pkt;
+
+ bool dcache_access;
+ Tick dcache_complete;
+
+ public:
+
+ virtual void serialize(std::ostream &os);
+ virtual void unserialize(Checkpoint *cp, const std::string &section);
+
+ void switchOut(Sampler *s);
+ void takeOverFrom(BaseCPU *oldCPU);
+
+ virtual void activateContext(int thread_num, int delay);
+ virtual void suspendContext(int thread_num);
+
+ template <class T>
+ Fault read(Addr addr, T &data, unsigned flags);
+
+ template <class T>
+ Fault write(T data, Addr addr, unsigned flags, uint64_t *res);
+};
+
+#endif // __CPU_SIMPLE_ATOMIC_HH__
diff --git a/src/cpu/simple/base.cc b/src/cpu/simple/base.cc
new file mode 100644
index 000000000..18f170449
--- /dev/null
+++ b/src/cpu/simple/base.cc
@@ -0,0 +1,482 @@
+/*
+ * Copyright (c) 2002-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "arch/utility.hh"
+#include "base/cprintf.hh"
+#include "base/inifile.hh"
+#include "base/loader/symtab.hh"
+#include "base/misc.hh"
+#include "base/pollevent.hh"
+#include "base/range.hh"
+#include "base/stats/events.hh"
+#include "base/trace.hh"
+#include "cpu/base.hh"
+#include "cpu/cpu_exec_context.hh"
+#include "cpu/exec_context.hh"
+#include "cpu/exetrace.hh"
+#include "cpu/profile.hh"
+#include "cpu/sampler/sampler.hh"
+#include "cpu/simple/base.hh"
+#include "cpu/smt.hh"
+#include "cpu/static_inst.hh"
+#include "kern/kernel_stats.hh"
+#include "mem/packet_impl.hh"
+#include "sim/byteswap.hh"
+#include "sim/builder.hh"
+#include "sim/debug.hh"
+#include "sim/host.hh"
+#include "sim/sim_events.hh"
+#include "sim/sim_object.hh"
+#include "sim/stats.hh"
+
+#if FULL_SYSTEM
+#include "base/remote_gdb.hh"
+#include "sim/system.hh"
+#include "arch/tlb.hh"
+#include "arch/stacktrace.hh"
+#include "arch/vtophys.hh"
+#else // !FULL_SYSTEM
+#include "mem/mem_object.hh"
+#endif // FULL_SYSTEM
+
+using namespace std;
+using namespace TheISA;
+
+BaseSimpleCPU::BaseSimpleCPU(Params *p)
+ : BaseCPU(p), mem(p->mem), cpuXC(NULL)
+{
+#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, mem);
+#endif // !FULL_SYSTEM
+
+ xcProxy = cpuXC->getProxy();
+
+ numInst = 0;
+ startNumInst = 0;
+ numLoad = 0;
+ startNumLoad = 0;
+ lastIcacheStall = 0;
+ lastDcacheStall = 0;
+
+ execContexts.push_back(xcProxy);
+}
+
+BaseSimpleCPU::~BaseSimpleCPU()
+{
+}
+
+void
+BaseSimpleCPU::deallocateContext(int thread_num)
+{
+ // for now, these are equivalent
+ suspendContext(thread_num);
+}
+
+
+void
+BaseSimpleCPU::haltContext(int thread_num)
+{
+ // for now, these are equivalent
+ suspendContext(thread_num);
+}
+
+
+void
+BaseSimpleCPU::regStats()
+{
+ using namespace Stats;
+
+ BaseCPU::regStats();
+
+ numInsts
+ .name(name() + ".num_insts")
+ .desc("Number of instructions executed")
+ ;
+
+ numMemRefs
+ .name(name() + ".num_refs")
+ .desc("Number of memory references")
+ ;
+
+ notIdleFraction
+ .name(name() + ".not_idle_fraction")
+ .desc("Percentage of non-idle cycles")
+ ;
+
+ idleFraction
+ .name(name() + ".idle_fraction")
+ .desc("Percentage of idle cycles")
+ ;
+
+ icacheStallCycles
+ .name(name() + ".icache_stall_cycles")
+ .desc("ICache total stall cycles")
+ .prereq(icacheStallCycles)
+ ;
+
+ dcacheStallCycles
+ .name(name() + ".dcache_stall_cycles")
+ .desc("DCache total stall cycles")
+ .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;
+}
+
+void
+BaseSimpleCPU::resetStats()
+{
+ startNumInst = numInst;
+ // notIdleFraction = (_status != Idle);
+}
+
+void
+BaseSimpleCPU::serialize(ostream &os)
+{
+ BaseCPU::serialize(os);
+ SERIALIZE_SCALAR(inst);
+ nameOut(os, csprintf("%s.xc", name()));
+ cpuXC->serialize(os);
+}
+
+void
+BaseSimpleCPU::unserialize(Checkpoint *cp, const string &section)
+{
+ BaseCPU::unserialize(cp, section);
+ UNSERIALIZE_SCALAR(inst);
+ cpuXC->unserialize(cp, csprintf("%s.xc", section));
+}
+
+void
+change_thread_state(int thread_number, int activate, int priority)
+{
+}
+
+Fault
+BaseSimpleCPU::copySrcTranslate(Addr src)
+{
+#if 0
+ static bool no_warn = true;
+ int blk_size = (dcacheInterface) ? dcacheInterface->getBlockSize() : 64;
+ // Only support block sizes of 64 atm.
+ assert(blk_size == 64);
+ int offset = src & (blk_size - 1);
+
+ // Make sure block doesn't span page
+ if (no_warn &&
+ (src & PageMask) != ((src + blk_size) & PageMask) &&
+ (src >> 40) != 0xfffffc) {
+ warn("Copied block source spans pages %x.", src);
+ no_warn = false;
+ }
+
+ memReq->reset(src & ~(blk_size - 1), blk_size);
+
+ // translate to physical address
+ Fault fault = cpuXC->translateDataReadReq(req);
+
+ if (fault == NoFault) {
+ cpuXC->copySrcAddr = src;
+ cpuXC->copySrcPhysAddr = memReq->paddr + offset;
+ } else {
+ assert(!fault->isAlignmentFault());
+
+ cpuXC->copySrcAddr = 0;
+ cpuXC->copySrcPhysAddr = 0;
+ }
+ return fault;
+#else
+ return NoFault;
+#endif
+}
+
+Fault
+BaseSimpleCPU::copy(Addr dest)
+{
+#if 0
+ static bool no_warn = true;
+ int blk_size = (dcacheInterface) ? dcacheInterface->getBlockSize() : 64;
+ // Only support block sizes of 64 atm.
+ assert(blk_size == 64);
+ uint8_t data[blk_size];
+ //assert(cpuXC->copySrcAddr);
+ int offset = dest & (blk_size - 1);
+
+ // Make sure block doesn't span page
+ if (no_warn &&
+ (dest & PageMask) != ((dest + blk_size) & PageMask) &&
+ (dest >> 40) != 0xfffffc) {
+ no_warn = false;
+ warn("Copied block destination spans pages %x. ", dest);
+ }
+
+ memReq->reset(dest & ~(blk_size -1), blk_size);
+ // translate to physical address
+ Fault fault = cpuXC->translateDataWriteReq(req);
+
+ if (fault == NoFault) {
+ Addr dest_addr = memReq->paddr + offset;
+ // Need to read straight from memory since we have more than 8 bytes.
+ memReq->paddr = cpuXC->copySrcPhysAddr;
+ cpuXC->mem->read(memReq, data);
+ memReq->paddr = dest_addr;
+ cpuXC->mem->write(memReq, data);
+ if (dcacheInterface) {
+ memReq->cmd = Copy;
+ memReq->completionEvent = NULL;
+ memReq->paddr = cpuXC->copySrcPhysAddr;
+ memReq->dest = dest_addr;
+ memReq->size = 64;
+ memReq->time = curTick;
+ memReq->flags &= ~INST_READ;
+ dcacheInterface->access(memReq);
+ }
+ }
+ else
+ assert(!fault->isAlignmentFault());
+
+ return fault;
+#else
+ panic("copy not implemented");
+ return NoFault;
+#endif
+}
+
+#if FULL_SYSTEM
+Addr
+BaseSimpleCPU::dbg_vtophys(Addr addr)
+{
+ return vtophys(xcProxy, addr);
+}
+#endif // FULL_SYSTEM
+
+#if FULL_SYSTEM
+void
+BaseSimpleCPU::post_interrupt(int int_num, int index)
+{
+ BaseCPU::post_interrupt(int_num, index);
+
+ if (cpuXC->status() == ExecContext::Suspended) {
+ DPRINTF(IPI,"Suspended Processor awoke\n");
+ cpuXC->activate();
+ }
+}
+#endif // FULL_SYSTEM
+
+void
+BaseSimpleCPU::checkForInterrupts()
+{
+#if FULL_SYSTEM
+ if (checkInterrupts && check_interrupts() && !cpuXC->inPalMode()) {
+ int ipl = 0;
+ int summary = 0;
+ checkInterrupts = false;
+
+ if (cpuXC->readMiscReg(IPR_SIRR)) {
+ for (int i = INTLEVEL_SOFTWARE_MIN;
+ i < INTLEVEL_SOFTWARE_MAX; i++) {
+ if (cpuXC->readMiscReg(IPR_SIRR) & (ULL(1) << i)) {
+ // See table 4-19 of 21164 hardware reference
+ ipl = (i - INTLEVEL_SOFTWARE_MIN) + 1;
+ summary |= (ULL(1) << i);
+ }
+ }
+ }
+
+ uint64_t interrupts = cpuXC->cpu->intr_status();
+ for (int i = INTLEVEL_EXTERNAL_MIN;
+ i < INTLEVEL_EXTERNAL_MAX; i++) {
+ if (interrupts & (ULL(1) << i)) {
+ // See table 4-19 of 21164 hardware reference
+ ipl = i;
+ summary |= (ULL(1) << i);
+ }
+ }
+
+ if (cpuXC->readMiscReg(IPR_ASTRR))
+ panic("asynchronous traps not implemented\n");
+
+ if (ipl && ipl > cpuXC->readMiscReg(IPR_IPLR)) {
+ cpuXC->setMiscReg(IPR_ISR, summary);
+ cpuXC->setMiscReg(IPR_INTID, ipl);
+
+ Fault(new InterruptFault)->invoke(xcProxy);
+
+ DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n",
+ cpuXC->readMiscReg(IPR_IPLR), ipl, summary);
+ }
+ }
+#endif
+}
+
+
+Fault
+BaseSimpleCPU::setupFetchPacket(Packet *ifetch_pkt)
+{
+ // 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());
+
+ Request *ifetch_req = ifetch_pkt->req;
+ ifetch_req->setVaddr(cpuXC->readPC() & ~3);
+ ifetch_req->setTime(curTick);
+#if FULL_SYSTEM
+ ifetch_req->setFlags((cpuXC->readPC() & 1) ? PHYSICAL : 0);
+#else
+ ifetch_req->setFlags(0);
+#endif
+
+ Fault fault = cpuXC->translateInstReq(ifetch_req);
+
+ if (fault == NoFault) {
+ ifetch_pkt->reinitFromRequest();
+ }
+
+ return fault;
+}
+
+
+void
+BaseSimpleCPU::preExecute()
+{
+ // maintain $r0 semantics
+ cpuXC->setIntReg(ZeroReg, 0);
+#if THE_ISA == ALPHA_ISA
+ cpuXC->setFloatReg(ZeroReg, 0.0);
+#endif // ALPHA_ISA
+
+ // keep an instruction count
+ numInst++;
+ numInsts++;
+
+ cpuXC->func_exe_inst++;
+
+ // check for instruction-count-based events
+ comInstEventQueue[0]->serviceEvents(numInst);
+
+ // decode the instruction
+ inst = gtoh(inst);
+ curStaticInst = StaticInst::decode(makeExtMI(inst, cpuXC->readPC()));
+
+ 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
+}
+
+void
+BaseSimpleCPU::postExecute()
+{
+#if FULL_SYSTEM
+ if (system->kernelBinning->fnbin) {
+ assert(kernelStats);
+ system->kernelBinning->execute(xcProxy, inst);
+ }
+
+ if (cpuXC->profile) {
+ bool usermode =
+ (cpuXC->readMiscReg(AlphaISA::IPR_DTB_CM) & 0x18) != 0;
+ cpuXC->profilePC = usermode ? 1 : cpuXC->readPC();
+ ProfileNode *node = cpuXC->profile->consume(xcProxy, inst);
+ if (node)
+ cpuXC->profileNode = node;
+ }
+#endif
+
+ if (curStaticInst->isMemRef()) {
+ numMemRefs++;
+ }
+
+ if (curStaticInst->isLoad()) {
+ ++numLoad;
+ comLoadEventQueue[0]->serviceEvents(numLoad);
+ }
+
+ traceFunctions(cpuXC->readPC());
+
+ if (traceData) {
+ traceData->finalize();
+ }
+}
+
+
+void
+BaseSimpleCPU::advancePC(Fault fault)
+{
+ if (fault != NoFault) {
+#if FULL_SYSTEM
+ fault->invoke(xcProxy);
+#else // !FULL_SYSTEM
+ fatal("fault (%s) detected @ PC %08p", fault->name(), cpuXC->readPC());
+#endif // FULL_SYSTEM
+ }
+ else {
+ // go to the next instruction
+ cpuXC->setPC(cpuXC->readNextPC());
+#if THE_ISA == ALPHA_ISA
+ cpuXC->setNextPC(cpuXC->readNextPC() + sizeof(MachInst));
+#else
+ cpuXC->setNextPC(cpuXC->readNextNPC());
+ cpuXC->setNextNPC(cpuXC->readNextNPC() + sizeof(MachInst));
+#endif
+
+ }
+
+#if FULL_SYSTEM
+ Addr oldpc;
+ do {
+ oldpc = cpuXC->readPC();
+ system->pcEventQueue.service(xcProxy);
+ } while (oldpc != cpuXC->readPC());
+#endif
+}
+
diff --git a/src/cpu/simple/base.hh b/src/cpu/simple/base.hh
new file mode 100644
index 000000000..4c0e6f3c7
--- /dev/null
+++ b/src/cpu/simple/base.hh
@@ -0,0 +1,316 @@
+/*
+ * 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 __CPU_SIMPLE_BASE_HH__
+#define __CPU_SIMPLE_BASE_HH__
+
+#include "base/statistics.hh"
+#include "config/full_system.hh"
+#include "cpu/base.hh"
+#include "cpu/cpu_exec_context.hh"
+#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
+#if FULL_SYSTEM
+class Processor;
+class AlphaITB;
+class AlphaDTB;
+class MemObject;
+
+class RemoteGDB;
+class GDBListener;
+
+#else
+
+class Process;
+
+#endif // FULL_SYSTEM
+
+class ExecContext;
+class Checkpoint;
+
+namespace Trace {
+ class InstRecord;
+}
+
+
+class BaseSimpleCPU : public BaseCPU
+{
+ protected:
+ typedef TheISA::MachInst MachInst;
+ typedef TheISA::MiscReg MiscReg;
+ typedef TheISA::FloatReg FloatReg;
+ typedef TheISA::FloatRegBits FloatRegBits;
+
+ MemObject *mem;
+
+ protected:
+ Trace::InstRecord *traceData;
+
+ public:
+ void post_interrupt(int int_num, int index);
+
+ void zero_fill_64(Addr addr) {
+ static int warned = 0;
+ if (!warned) {
+ warn ("WH64 is not implemented");
+ warned = 1;
+ }
+ };
+
+ public:
+ struct Params : public BaseCPU::Params
+ {
+ MemObject *mem;
+#if FULL_SYSTEM
+ AlphaITB *itb;
+ AlphaDTB *dtb;
+#else
+ Process *process;
+#endif
+ };
+ BaseSimpleCPU(Params *params);
+ virtual ~BaseSimpleCPU();
+
+ public:
+ // execution context
+ CPUExecContext *cpuXC;
+
+ ExecContext *xcProxy;
+
+#if FULL_SYSTEM
+ Addr dbg_vtophys(Addr addr);
+
+ bool interval_stats;
+#endif
+
+ // current instruction
+ MachInst inst;
+
+ // Static data storage
+ TheISA::IntReg dataReg;
+
+ // Pointer to the sampler that is telling us to switchover.
+ // Used to signal the completion of the pipe drain and schedule
+ // the next switchover
+ Sampler *sampler;
+
+ StaticInstPtr curStaticInst;
+
+ void checkForInterrupts();
+ Fault setupFetchPacket(Packet *ifetch_pkt);
+ void preExecute();
+ void postExecute();
+ void advancePC(Fault fault);
+
+ virtual void deallocateContext(int thread_num);
+ virtual void haltContext(int thread_num);
+
+ // statistics
+ virtual void regStats();
+ virtual void resetStats();
+
+ // number of simulated instructions
+ Counter numInst;
+ Counter startNumInst;
+ Stats::Scalar<> numInsts;
+
+ virtual Counter totalInstructions() const
+ {
+ return numInst - startNumInst;
+ }
+
+ // number of simulated memory references
+ Stats::Scalar<> numMemRefs;
+
+ // number of simulated loads
+ Counter numLoad;
+ Counter startNumLoad;
+
+ // number of idle cycles
+ Stats::Average<> notIdleFraction;
+ Stats::Formula idleFraction;
+
+ // number of cycles stalled for I-cache responses
+ Stats::Scalar<> icacheStallCycles;
+ Counter lastIcacheStall;
+
+ // 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;
+
+ // number of cycles stalled for D-cache retries
+ Stats::Scalar<> dcacheRetryCycles;
+ Counter lastDcacheRetry;
+
+ virtual void serialize(std::ostream &os);
+ virtual void unserialize(Checkpoint *cp, const std::string &section);
+
+ // These functions are only used in CPU models that split
+ // effective address computation from the actual memory access.
+ void setEA(Addr EA) { panic("BaseSimpleCPU::setEA() not implemented\n"); }
+ Addr getEA() { panic("BaseSimpleCPU::getEA() not implemented\n"); }
+
+ void prefetch(Addr addr, unsigned flags)
+ {
+ // need to do this...
+ }
+
+ void writeHint(Addr addr, int size, unsigned flags)
+ {
+ // need to do this...
+ }
+
+ Fault copySrcTranslate(Addr src);
+
+ Fault copy(Addr dest);
+
+ // The register accessor methods provide the index of the
+ // instruction's operand (e.g., 0 or 1), not the architectural
+ // register index, to simplify the implementation of register
+ // renaming. We find the architectural register index by indexing
+ // into the instruction's own operand index table. Note that a
+ // raw pointer to the StaticInst is provided instead of a
+ // ref-counted StaticInstPtr to redice overhead. This is fine as
+ // long as these methods don't copy the pointer into any long-term
+ // storage (which is pretty hard to imagine they would have reason
+ // to do).
+
+ uint64_t readIntReg(const StaticInst *si, int idx)
+ {
+ return cpuXC->readIntReg(si->srcRegIdx(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->readFloatReg(reg_idx);
+ }
+
+ FloatRegBits readFloatRegBits(const StaticInst *si, int idx, int width)
+ {
+ int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
+ return cpuXC->readFloatRegBits(reg_idx, width);
+ }
+
+ FloatRegBits readFloatRegBits(const StaticInst *si, int idx)
+ {
+ int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
+ return cpuXC->readFloatRegBits(reg_idx);
+ }
+
+ void setIntReg(const StaticInst *si, int idx, uint64_t val)
+ {
+ cpuXC->setIntReg(si->destRegIdx(idx), val);
+ }
+
+ void setFloatReg(const StaticInst *si, int idx, FloatReg val, int width)
+ {
+ int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
+ cpuXC->setFloatReg(reg_idx, val, width);
+ }
+
+ void setFloatReg(const StaticInst *si, int idx, FloatReg val)
+ {
+ int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
+ cpuXC->setFloatReg(reg_idx, val);
+ }
+
+ void setFloatRegBits(const StaticInst *si, int idx,
+ FloatRegBits val, int width)
+ {
+ int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
+ 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)
+ {
+ return cpuXC->readMiscReg(misc_reg);
+ }
+
+ MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault)
+ {
+ return cpuXC->readMiscRegWithEffect(misc_reg, fault);
+ }
+
+ Fault setMiscReg(int misc_reg, const MiscReg &val)
+ {
+ return cpuXC->setMiscReg(misc_reg, val);
+ }
+
+ Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val)
+ {
+ return cpuXC->setMiscRegWithEffect(misc_reg, val);
+ }
+
+#if FULL_SYSTEM
+ Fault hwrei() { return cpuXC->hwrei(); }
+ int readIntrFlag() { return cpuXC->readIntrFlag(); }
+ void setIntrFlag(int val) { cpuXC->setIntrFlag(val); }
+ bool inPalMode() { return cpuXC->inPalMode(); }
+ void ev5_trap(Fault fault) { fault->invoke(xcProxy); }
+ bool simPalCheck(int palFunc) { return cpuXC->simPalCheck(palFunc); }
+#else
+ void syscall(int64_t callnum) { cpuXC->syscall(callnum); }
+#endif
+
+ bool misspeculating() { return cpuXC->misspeculating(); }
+ ExecContext *xcBase() { return xcProxy; }
+};
+
+#endif // __CPU_SIMPLE_BASE_HH__
diff --git a/src/cpu/simple/timing.cc b/src/cpu/simple/timing.cc
new file mode 100644
index 000000000..7cdcdafa1
--- /dev/null
+++ b/src/cpu/simple/timing.cc
@@ -0,0 +1,570 @@
+/*
+ * Copyright (c) 2002-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "arch/utility.hh"
+#include "cpu/exetrace.hh"
+#include "cpu/simple/timing.hh"
+#include "mem/packet_impl.hh"
+#include "sim/builder.hh"
+
+using namespace std;
+using namespace TheISA;
+
+
+void
+TimingSimpleCPU::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) {
+ ExecContext *xc = execContexts[i];
+
+ // initialize CPU, including PC
+ TheISA::initCPU(xc, xc->readCpuId());
+ }
+#endif
+}
+
+Tick
+TimingSimpleCPU::CpuPort::recvAtomic(Packet *pkt)
+{
+ panic("TimingSimpleCPU doesn't expect recvAtomic callback!");
+ return curTick;
+}
+
+void
+TimingSimpleCPU::CpuPort::recvFunctional(Packet *pkt)
+{
+ panic("TimingSimpleCPU doesn't expect recvFunctional callback!");
+}
+
+void
+TimingSimpleCPU::CpuPort::recvStatusChange(Status status)
+{
+ if (status == RangeChange)
+ return;
+
+ panic("TimingSimpleCPU doesn't expect recvStatusChange callback!");
+}
+
+TimingSimpleCPU::TimingSimpleCPU(Params *p)
+ : BaseSimpleCPU(p), icachePort(this), dcachePort(this)
+{
+ _status = Idle;
+ ifetch_pkt = dcache_pkt = NULL;
+}
+
+
+TimingSimpleCPU::~TimingSimpleCPU()
+{
+}
+
+void
+TimingSimpleCPU::serialize(ostream &os)
+{
+ BaseSimpleCPU::serialize(os);
+ SERIALIZE_ENUM(_status);
+}
+
+void
+TimingSimpleCPU::unserialize(Checkpoint *cp, const string &section)
+{
+ BaseSimpleCPU::unserialize(cp, section);
+ UNSERIALIZE_ENUM(_status);
+}
+
+void
+TimingSimpleCPU::switchOut(Sampler *s)
+{
+ sampler = s;
+ if (status() == Running) {
+ _status = SwitchedOut;
+ }
+ sampler->signalSwitched();
+}
+
+
+void
+TimingSimpleCPU::takeOverFrom(BaseCPU *oldCPU)
+{
+ BaseCPU::takeOverFrom(oldCPU);
+
+ // if any of this CPU's ExecContexts are active, mark the CPU as
+ // running and schedule its tick event.
+ for (int i = 0; i < execContexts.size(); ++i) {
+ ExecContext *xc = execContexts[i];
+ if (xc->status() == ExecContext::Active && _status != Running) {
+ _status = Running;
+ break;
+ }
+ }
+}
+
+
+void
+TimingSimpleCPU::activateContext(int thread_num, int delay)
+{
+ assert(thread_num == 0);
+ assert(cpuXC);
+
+ assert(_status == Idle);
+
+ notIdleFraction++;
+ _status = Running;
+ // kick things off by initiating the fetch of the next instruction
+ Event *e =
+ new EventWrapper<TimingSimpleCPU, &TimingSimpleCPU::fetch>(this, true);
+ e->schedule(curTick + cycles(delay));
+}
+
+
+void
+TimingSimpleCPU::suspendContext(int thread_num)
+{
+ assert(thread_num == 0);
+ assert(cpuXC);
+
+ assert(_status == Running);
+
+ // just change status to Idle... if status != Running,
+ // completeInst() will not initiate fetch of next instruction.
+
+ notIdleFraction--;
+ _status = Idle;
+}
+
+
+template <class T>
+Fault
+TimingSimpleCPU::read(Addr addr, T &data, unsigned flags)
+{
+ Request *data_read_req = new Request(true);
+
+ data_read_req->setVaddr(addr);
+ data_read_req->setSize(sizeof(T));
+ data_read_req->setFlags(flags);
+ data_read_req->setTime(curTick);
+
+ if (traceData) {
+ traceData->setAddr(data_read_req->getVaddr());
+ }
+
+ // translate to physical address
+ Fault fault = cpuXC->translateDataReadReq(data_read_req);
+
+ // Now do the access.
+ if (fault == NoFault) {
+ Packet *data_read_pkt =
+ new Packet(data_read_req, Packet::ReadReq, Packet::Broadcast);
+ data_read_pkt->dataDynamic<T>(new T);
+
+ if (!dcachePort.sendTiming(data_read_pkt)) {
+ _status = DcacheRetry;
+ dcache_pkt = data_read_pkt;
+ } else {
+ _status = DcacheWaitResponse;
+ dcache_pkt = NULL;
+ }
+ }
+
+ // 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;
+}
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+template
+Fault
+TimingSimpleCPU::read(Addr addr, uint64_t &data, unsigned flags);
+
+template
+Fault
+TimingSimpleCPU::read(Addr addr, uint32_t &data, unsigned flags);
+
+template
+Fault
+TimingSimpleCPU::read(Addr addr, uint16_t &data, unsigned flags);
+
+template
+Fault
+TimingSimpleCPU::read(Addr addr, uint8_t &data, unsigned flags);
+
+#endif //DOXYGEN_SHOULD_SKIP_THIS
+
+template<>
+Fault
+TimingSimpleCPU::read(Addr addr, double &data, unsigned flags)
+{
+ return read(addr, *(uint64_t*)&data, flags);
+}
+
+template<>
+Fault
+TimingSimpleCPU::read(Addr addr, float &data, unsigned flags)
+{
+ return read(addr, *(uint32_t*)&data, flags);
+}
+
+
+template<>
+Fault
+TimingSimpleCPU::read(Addr addr, int32_t &data, unsigned flags)
+{
+ return read(addr, (uint32_t&)data, flags);
+}
+
+
+template <class T>
+Fault
+TimingSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
+{
+ Request *data_write_req = new Request(true);
+ 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(data_write_req);
+ // Now do the access.
+ if (fault == NoFault) {
+ Packet *data_write_pkt =
+ new Packet(data_write_req, Packet::WriteReq, Packet::Broadcast);
+ data_write_pkt->allocate();
+ data_write_pkt->set(data);
+
+ if (!dcachePort.sendTiming(data_write_pkt)) {
+ _status = DcacheRetry;
+ dcache_pkt = data_write_pkt;
+ } else {
+ _status = DcacheWaitResponse;
+ dcache_pkt = NULL;
+ }
+ }
+
+ // 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");
+
+ // 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;
+}
+
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+template
+Fault
+TimingSimpleCPU::write(uint64_t data, Addr addr,
+ unsigned flags, uint64_t *res);
+
+template
+Fault
+TimingSimpleCPU::write(uint32_t data, Addr addr,
+ unsigned flags, uint64_t *res);
+
+template
+Fault
+TimingSimpleCPU::write(uint16_t data, Addr addr,
+ unsigned flags, uint64_t *res);
+
+template
+Fault
+TimingSimpleCPU::write(uint8_t data, Addr addr,
+ unsigned flags, uint64_t *res);
+
+#endif //DOXYGEN_SHOULD_SKIP_THIS
+
+template<>
+Fault
+TimingSimpleCPU::write(double data, Addr addr, unsigned flags, uint64_t *res)
+{
+ return write(*(uint64_t*)&data, addr, flags, res);
+}
+
+template<>
+Fault
+TimingSimpleCPU::write(float data, Addr addr, unsigned flags, uint64_t *res)
+{
+ return write(*(uint32_t*)&data, addr, flags, res);
+}
+
+
+template<>
+Fault
+TimingSimpleCPU::write(int32_t data, Addr addr, unsigned flags, uint64_t *res)
+{
+ return write((uint32_t)data, addr, flags, res);
+}
+
+
+void
+TimingSimpleCPU::fetch()
+{
+ checkForInterrupts();
+
+ Request *ifetch_req = new Request(true);
+ ifetch_req->setSize(sizeof(MachInst));
+
+ ifetch_pkt = new Packet(ifetch_req, Packet::ReadReq, Packet::Broadcast);
+ ifetch_pkt->dataStatic(&inst);
+
+ Fault fault = setupFetchPacket(ifetch_pkt);
+ if (fault == NoFault) {
+ if (!icachePort.sendTiming(ifetch_pkt)) {
+ // Need to wait for retry
+ _status = IcacheRetry;
+ } else {
+ // Need to wait for cache to respond
+ _status = IcacheWaitResponse;
+ // ownership of packet transferred to memory system
+ ifetch_pkt = NULL;
+ }
+ } else {
+ // fetch fault: advance directly to next instruction (fault handler)
+ advanceInst(fault);
+ }
+}
+
+
+void
+TimingSimpleCPU::advanceInst(Fault fault)
+{
+ advancePC(fault);
+
+ if (_status == Running) {
+ // kick off fetch of next instruction... callback from icache
+ // response will cause that instruction to be executed,
+ // keeping the CPU running.
+ fetch();
+ }
+}
+
+
+void
+TimingSimpleCPU::completeIfetch(Packet *pkt)
+{
+ // received a response from the icache: execute the received
+ // instruction
+ assert(pkt->result == Packet::Success);
+ assert(_status == IcacheWaitResponse);
+ _status = Running;
+
+ delete pkt->req;
+ delete pkt;
+
+ preExecute();
+ if (curStaticInst->isMemRef() && !curStaticInst->isDataPrefetch()) {
+ // load or store: just send to dcache
+ Fault fault = curStaticInst->initiateAcc(this, traceData);
+ if (fault == NoFault) {
+ // successfully initiated access: instruction will
+ // complete in dcache response callback
+ assert(_status == DcacheWaitResponse);
+ } else {
+ // fault: complete now to invoke fault handler
+ postExecute();
+ advanceInst(fault);
+ }
+ } else {
+ // non-memory instruction: execute completely now
+ Fault fault = curStaticInst->execute(this, traceData);
+ postExecute();
+ advanceInst(fault);
+ }
+}
+
+
+bool
+TimingSimpleCPU::IcachePort::recvTiming(Packet *pkt)
+{
+ cpu->completeIfetch(pkt);
+ return true;
+}
+
+Packet *
+TimingSimpleCPU::IcachePort::recvRetry()
+{
+ // we shouldn't get a retry unless we have a packet that we're
+ // waiting to transmit
+ assert(cpu->ifetch_pkt != NULL);
+ assert(cpu->_status == IcacheRetry);
+ cpu->_status = IcacheWaitResponse;
+ Packet *tmp = cpu->ifetch_pkt;
+ cpu->ifetch_pkt = NULL;
+ return tmp;
+}
+
+void
+TimingSimpleCPU::completeDataAccess(Packet *pkt)
+{
+ // received a response from the dcache: complete the load or store
+ // instruction
+ assert(pkt->result == Packet::Success);
+ assert(_status == DcacheWaitResponse);
+ _status = Running;
+
+ Fault fault = curStaticInst->completeAcc(pkt, this, traceData);
+
+ delete pkt->req;
+ delete pkt;
+
+ postExecute();
+ advanceInst(fault);
+}
+
+
+
+bool
+TimingSimpleCPU::DcachePort::recvTiming(Packet *pkt)
+{
+ cpu->completeDataAccess(pkt);
+ return true;
+}
+
+Packet *
+TimingSimpleCPU::DcachePort::recvRetry()
+{
+ // we shouldn't get a retry unless we have a packet that we're
+ // waiting to transmit
+ assert(cpu->dcache_pkt != NULL);
+ assert(cpu->_status == DcacheRetry);
+ cpu->_status = DcacheWaitResponse;
+ Packet *tmp = cpu->dcache_pkt;
+ cpu->dcache_pkt = NULL;
+ return tmp;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+//
+// TimingSimpleCPU Simulation Object
+//
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(TimingSimpleCPU)
+
+ Param<Counter> max_insts_any_thread;
+ 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<System *> system;
+ Param<int> cpu_id;
+ Param<Tick> profile;
+#else
+ SimObjectParam<Process *> workload;
+#endif // FULL_SYSTEM
+
+ Param<int> clock;
+
+ Param<bool> defer_registration;
+ Param<int> width;
+ Param<bool> function_trace;
+ Param<Tick> function_trace_start;
+ Param<bool> simulate_stalls;
+
+END_DECLARE_SIM_OBJECT_PARAMS(TimingSimpleCPU)
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(TimingSimpleCPU)
+
+ INIT_PARAM(max_insts_any_thread,
+ "terminate when any thread reaches this inst count"),
+ INIT_PARAM(max_insts_all_threads,
+ "terminate when all threads have reached this inst count"),
+ INIT_PARAM(max_loads_any_thread,
+ "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(system, "system object"),
+ INIT_PARAM(cpu_id, "processor ID"),
+ INIT_PARAM(profile, ""),
+#else
+ INIT_PARAM(workload, "processes to run"),
+#endif // FULL_SYSTEM
+
+ INIT_PARAM(clock, "clock speed"),
+ INIT_PARAM(defer_registration, "defer system registration (for sampling)"),
+ INIT_PARAM(width, "cpu width"),
+ INIT_PARAM(function_trace, "Enable function trace"),
+ INIT_PARAM(function_trace_start, "Cycle to start function trace"),
+ INIT_PARAM(simulate_stalls, "Simulate cache stall cycles")
+
+END_INIT_SIM_OBJECT_PARAMS(TimingSimpleCPU)
+
+
+CREATE_SIM_OBJECT(TimingSimpleCPU)
+{
+ TimingSimpleCPU::Params *params = new TimingSimpleCPU::Params();
+ params->name = getInstanceName();
+ params->numberOfThreads = 1;
+ params->max_insts_any_thread = max_insts_any_thread;
+ params->max_insts_all_threads = max_insts_all_threads;
+ params->max_loads_any_thread = max_loads_any_thread;
+ params->max_loads_all_threads = max_loads_all_threads;
+ params->deferRegistration = defer_registration;
+ params->clock = clock;
+ params->functionTrace = function_trace;
+ params->functionTraceStart = function_trace_start;
+ params->mem = mem;
+
+#if FULL_SYSTEM
+ params->itb = itb;
+ params->dtb = dtb;
+ params->system = system;
+ params->cpu_id = cpu_id;
+ params->profile = profile;
+#else
+ params->process = workload;
+#endif
+
+ TimingSimpleCPU *cpu = new TimingSimpleCPU(params);
+ return cpu;
+}
+
+REGISTER_SIM_OBJECT("TimingSimpleCPU", TimingSimpleCPU)
+
diff --git a/src/cpu/simple/timing.hh b/src/cpu/simple/timing.hh
new file mode 100644
index 000000000..b46631d5a
--- /dev/null
+++ b/src/cpu/simple/timing.hh
@@ -0,0 +1,150 @@
+/*
+ * 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 __CPU_SIMPLE_TIMING_HH__
+#define __CPU_SIMPLE_TIMING_HH__
+
+#include "cpu/simple/base.hh"
+
+class TimingSimpleCPU : public BaseSimpleCPU
+{
+ public:
+
+ struct Params : public BaseSimpleCPU::Params {
+ };
+
+ TimingSimpleCPU(Params *params);
+ virtual ~TimingSimpleCPU();
+
+ virtual void init();
+
+ public:
+ //
+ enum Status {
+ Idle,
+ Running,
+ IcacheRetry,
+ IcacheWaitResponse,
+ IcacheWaitSwitch,
+ DcacheRetry,
+ DcacheWaitResponse,
+ DcacheWaitSwitch,
+ SwitchedOut
+ };
+
+ protected:
+ Status _status;
+
+ Status status() const { return _status; }
+
+ private:
+
+ class CpuPort : public Port
+ {
+ protected:
+ TimingSimpleCPU *cpu;
+
+ public:
+
+ CpuPort(const std::string &_name, TimingSimpleCPU *_cpu)
+ : Port(_name), cpu(_cpu)
+ { }
+
+ protected:
+
+ virtual Tick recvAtomic(Packet *pkt);
+
+ virtual void recvFunctional(Packet *pkt);
+
+ virtual void recvStatusChange(Status status);
+
+ virtual void getDeviceAddressRanges(AddrRangeList &resp,
+ AddrRangeList &snoop)
+ { resp.clear(); snoop.clear(); }
+ };
+
+ class IcachePort : public CpuPort
+ {
+ public:
+
+ IcachePort(TimingSimpleCPU *_cpu)
+ : CpuPort(_cpu->name() + "-iport", _cpu)
+ { }
+
+ protected:
+
+ virtual bool recvTiming(Packet *pkt);
+
+ virtual Packet *recvRetry();
+ };
+
+ class DcachePort : public CpuPort
+ {
+ public:
+
+ DcachePort(TimingSimpleCPU *_cpu)
+ : CpuPort(_cpu->name() + "-dport", _cpu)
+ { }
+
+ protected:
+
+ virtual bool recvTiming(Packet *pkt);
+
+ virtual Packet *recvRetry();
+ };
+
+ IcachePort icachePort;
+ DcachePort dcachePort;
+
+ Packet *ifetch_pkt;
+ Packet *dcache_pkt;
+
+ public:
+
+ virtual void serialize(std::ostream &os);
+ virtual void unserialize(Checkpoint *cp, const std::string &section);
+
+ void switchOut(Sampler *s);
+ void takeOverFrom(BaseCPU *oldCPU);
+
+ virtual void activateContext(int thread_num, int delay);
+ virtual void suspendContext(int thread_num);
+
+ template <class T>
+ Fault read(Addr addr, T &data, unsigned flags);
+
+ template <class T>
+ Fault write(T data, Addr addr, unsigned flags, uint64_t *res);
+
+ void fetch();
+ void completeIfetch(Packet *);
+ void completeDataAccess(Packet *);
+ void advanceInst(Fault fault);
+};
+
+#endif // __CPU_SIMPLE_TIMING_HH__
diff --git a/cpu/smt.hh b/src/cpu/smt.hh
index 9c52abf95..9c52abf95 100644
--- a/cpu/smt.hh
+++ b/src/cpu/smt.hh
diff --git a/cpu/static_inst.cc b/src/cpu/static_inst.cc
index c307dc6fc..c307dc6fc 100644
--- a/cpu/static_inst.cc
+++ b/src/cpu/static_inst.cc
diff --git a/src/cpu/static_inst.hh b/src/cpu/static_inst.hh
new file mode 100644
index 000000000..803b7a09b
--- /dev/null
+++ b/src/cpu/static_inst.hh
@@ -0,0 +1,490 @@
+/*
+ * 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 __CPU_STATIC_INST_HH__
+#define __CPU_STATIC_INST_HH__
+
+#include <bitset>
+#include <string>
+
+#include "base/hashmap.hh"
+#include "base/misc.hh"
+#include "base/refcnt.hh"
+#include "cpu/op_class.hh"
+#include "sim/host.hh"
+#include "arch/isa_traits.hh"
+
+// forward declarations
+struct AlphaSimpleImpl;
+struct OzoneImpl;
+struct SimpleImpl;
+class ExecContext;
+class DynInst;
+class Packet;
+
+template <class Impl>
+class AlphaDynInst;
+
+template <class Impl>
+class OzoneDynInst;
+
+class CheckerCPU;
+class FastCPU;
+class AtomicSimpleCPU;
+class TimingSimpleCPU;
+class InorderCPU;
+class SymbolTable;
+
+namespace Trace {
+ class InstRecord;
+}
+
+/**
+ * Base, ISA-independent static instruction class.
+ *
+ * The main component of this class is the vector of flags and the
+ * associated methods for reading them. Any object that can rely
+ * solely on these flags can process instructions without being
+ * recompiled for multiple ISAs.
+ */
+class StaticInstBase : public RefCounted
+{
+ protected:
+
+ /// Set of boolean static instruction properties.
+ ///
+ /// Notes:
+ /// - The IsInteger and IsFloating flags are based on the class of
+ /// registers accessed by the instruction. Although most
+ /// instructions will have exactly one of these two flags set, it
+ /// is possible for an instruction to have neither (e.g., direct
+ /// unconditional branches, memory barriers) or both (e.g., an
+ /// FP/int conversion).
+ /// - If IsMemRef is set, then exactly one of IsLoad or IsStore
+ /// will be set.
+ /// - If IsControl is set, then exactly one of IsDirectControl or
+ /// IsIndirect Control will be set, and exactly one of
+ /// IsCondControl or IsUncondControl will be set.
+ /// - IsSerializing, IsMemBarrier, and IsWriteBarrier are
+ /// implemented as flags since in the current model there's no
+ /// other way for instructions to inject behavior into the
+ /// pipeline outside of fetch. Once we go to an exec-in-exec CPU
+ /// model we should be able to get rid of these flags and
+ /// implement this behavior via the execute() methods.
+ ///
+ enum Flags {
+ IsNop, ///< Is a no-op (no effect at all).
+
+ IsInteger, ///< References integer regs.
+ IsFloating, ///< References FP regs.
+
+ IsMemRef, ///< References memory (load, store, or prefetch).
+ IsLoad, ///< Reads from memory (load or prefetch).
+ IsStore, ///< Writes to memory.
+ IsStoreConditional, ///< Store conditional instruction.
+ IsInstPrefetch, ///< Instruction-cache prefetch.
+ IsDataPrefetch, ///< Data-cache prefetch.
+ IsCopy, ///< Fast Cache block copy
+
+ IsControl, ///< Control transfer instruction.
+ IsDirectControl, ///< PC relative control transfer.
+ IsIndirectControl, ///< Register indirect control transfer.
+ IsCondControl, ///< Conditional control transfer.
+ IsUncondControl, ///< Unconditional control transfer.
+ IsCall, ///< Subroutine call.
+ IsReturn, ///< Subroutine return.
+
+ IsCondDelaySlot,///< Conditional Delay-Slot Instruction
+
+ IsThreadSync, ///< Thread synchronization operation.
+
+ IsSerializing, ///< Serializes pipeline: won't execute until all
+ /// older instructions have committed.
+ IsSerializeBefore,
+ IsSerializeAfter,
+ IsMemBarrier, ///< Is a memory barrier
+ IsWriteBarrier, ///< Is a write barrier
+
+ IsNonSpeculative, ///< Should not be executed speculatively
+ IsQuiesce, ///< Is a quiesce instruction
+
+ IsIprAccess, ///< Accesses IPRs
+ IsUnverifiable, ///< Can't be verified by a checker
+
+ NumFlags
+ };
+
+ /// Flag values for this instruction.
+ std::bitset<NumFlags> flags;
+
+ /// See opClass().
+ OpClass _opClass;
+
+ /// See numSrcRegs().
+ int8_t _numSrcRegs;
+
+ /// See numDestRegs().
+ int8_t _numDestRegs;
+
+ /// The following are used to track physical register usage
+ /// for machines with separate int & FP reg files.
+ //@{
+ int8_t _numFPDestRegs;
+ int8_t _numIntDestRegs;
+ //@}
+
+ /// Constructor.
+ /// It's important to initialize everything here to a sane
+ /// default, since the decoder generally only overrides
+ /// the fields that are meaningful for the particular
+ /// instruction.
+ StaticInstBase(OpClass __opClass)
+ : _opClass(__opClass), _numSrcRegs(0), _numDestRegs(0),
+ _numFPDestRegs(0), _numIntDestRegs(0)
+ {
+ }
+
+ public:
+
+ /// @name Register information.
+ /// The sum of numFPDestRegs() and numIntDestRegs() equals
+ /// numDestRegs(). The former two functions are used to track
+ /// physical register usage for machines with separate int & FP
+ /// reg files.
+ //@{
+ /// Number of source registers.
+ int8_t numSrcRegs() const { return _numSrcRegs; }
+ /// Number of destination registers.
+ int8_t numDestRegs() const { return _numDestRegs; }
+ /// Number of floating-point destination regs.
+ int8_t numFPDestRegs() const { return _numFPDestRegs; }
+ /// Number of integer destination regs.
+ int8_t numIntDestRegs() const { return _numIntDestRegs; }
+ //@}
+
+ /// @name Flag accessors.
+ /// These functions are used to access the values of the various
+ /// instruction property flags. See StaticInstBase::Flags for descriptions
+ /// of the individual flags.
+ //@{
+
+ bool isNop() const { return flags[IsNop]; }
+
+ bool isMemRef() const { return flags[IsMemRef]; }
+ bool isLoad() const { return flags[IsLoad]; }
+ bool isStore() const { return flags[IsStore]; }
+ bool isStoreConditional() const { return flags[IsStoreConditional]; }
+ bool isInstPrefetch() const { return flags[IsInstPrefetch]; }
+ bool isDataPrefetch() const { return flags[IsDataPrefetch]; }
+ bool isCopy() const { return flags[IsCopy];}
+
+ bool isInteger() const { return flags[IsInteger]; }
+ bool isFloating() const { return flags[IsFloating]; }
+
+ bool isControl() const { return flags[IsControl]; }
+ bool isCall() const { return flags[IsCall]; }
+ bool isReturn() const { return flags[IsReturn]; }
+ bool isDirectCtrl() const { return flags[IsDirectControl]; }
+ bool isIndirectCtrl() const { return flags[IsIndirectControl]; }
+ bool isCondCtrl() const { return flags[IsCondControl]; }
+ bool isUncondCtrl() const { return flags[IsUncondControl]; }
+
+ bool isThreadSync() const { return flags[IsThreadSync]; }
+ bool isSerializing() const { return flags[IsSerializing] ||
+ flags[IsSerializeBefore] ||
+ flags[IsSerializeAfter]; }
+ bool isSerializeBefore() const { return flags[IsSerializeBefore]; }
+ bool isSerializeAfter() const { return flags[IsSerializeAfter]; }
+ bool isMemBarrier() const { return flags[IsMemBarrier]; }
+ bool isWriteBarrier() const { return flags[IsWriteBarrier]; }
+ bool isNonSpeculative() const { return flags[IsNonSpeculative]; }
+ bool isQuiesce() const { return flags[IsQuiesce]; }
+ bool isIprAccess() const { return flags[IsIprAccess]; }
+ bool isUnverifiable() const { return flags[IsUnverifiable]; }
+ //@}
+
+ /// Operation class. Used to select appropriate function unit in issue.
+ OpClass opClass() const { return _opClass; }
+};
+
+
+// forward declaration
+class StaticInstPtr;
+
+/**
+ * Generic yet ISA-dependent static instruction class.
+ *
+ * This class builds on StaticInstBase, defining fields and interfaces
+ * that are generic across all ISAs but that differ in details
+ * according to the specific ISA being used.
+ */
+class StaticInst : public StaticInstBase
+{
+ public:
+
+ /// Binary machine instruction type.
+ typedef TheISA::MachInst MachInst;
+ /// Binary extended machine instruction type.
+ typedef TheISA::ExtMachInst ExtMachInst;
+ /// Logical register index type.
+ typedef TheISA::RegIndex RegIndex;
+
+ enum {
+ MaxInstSrcRegs = TheISA::MaxInstSrcRegs, //< Max source regs
+ MaxInstDestRegs = TheISA::MaxInstDestRegs, //< Max dest regs
+ };
+
+
+ /// Return logical index (architectural reg num) of i'th destination reg.
+ /// Only the entries from 0 through numDestRegs()-1 are valid.
+ RegIndex destRegIdx(int i) const { return _destRegIdx[i]; }
+
+ /// Return logical index (architectural reg num) of i'th source reg.
+ /// Only the entries from 0 through numSrcRegs()-1 are valid.
+ RegIndex srcRegIdx(int i) const { return _srcRegIdx[i]; }
+
+ /// Pointer to a statically allocated "null" instruction object.
+ /// Used to give eaCompInst() and memAccInst() something to return
+ /// when called on non-memory instructions.
+ static StaticInstPtr nullStaticInstPtr;
+
+ /**
+ * Memory references only: returns "fake" instruction representing
+ * the effective address part of the memory operation. Used to
+ * obtain the dependence info (numSrcRegs and srcRegIdx[]) for
+ * just the EA computation.
+ */
+ virtual const
+ StaticInstPtr &eaCompInst() const { return nullStaticInstPtr; }
+
+ /**
+ * Memory references only: returns "fake" instruction representing
+ * the memory access part of the memory operation. Used to
+ * obtain the dependence info (numSrcRegs and srcRegIdx[]) for
+ * just the memory access (not the EA computation).
+ */
+ virtual const
+ StaticInstPtr &memAccInst() const { return nullStaticInstPtr; }
+
+ /// The binary machine instruction.
+ const ExtMachInst machInst;
+
+ protected:
+
+ /// See destRegIdx().
+ RegIndex _destRegIdx[MaxInstDestRegs];
+ /// See srcRegIdx().
+ RegIndex _srcRegIdx[MaxInstSrcRegs];
+
+ /**
+ * Base mnemonic (e.g., "add"). Used by generateDisassembly()
+ * methods. Also useful to readily identify instructions from
+ * within the debugger when #cachedDisassembly has not been
+ * initialized.
+ */
+ const char *mnemonic;
+
+ /**
+ * String representation of disassembly (lazily evaluated via
+ * disassemble()).
+ */
+ mutable std::string *cachedDisassembly;
+
+ /**
+ * Internal function to generate disassembly string.
+ */
+ virtual std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const = 0;
+
+ /// Constructor.
+ StaticInst(const char *_mnemonic, ExtMachInst _machInst, OpClass __opClass)
+ : StaticInstBase(__opClass),
+ machInst(_machInst), mnemonic(_mnemonic), cachedDisassembly(0)
+ {
+ }
+
+ public:
+
+ virtual ~StaticInst()
+ {
+ if (cachedDisassembly)
+ delete cachedDisassembly;
+ }
+
+/**
+ * The execute() signatures are auto-generated by scons based on the
+ * set of CPU models we are compiling in today.
+ */
+#include "cpu/static_inst_exec_sigs.hh"
+
+ /**
+ * Return the target address for a PC-relative branch.
+ * Invalid if not a PC-relative branch (i.e. isDirectCtrl()
+ * should be true).
+ */
+ virtual Addr branchTarget(Addr branchPC) const
+ {
+ panic("StaticInst::branchTarget() called on instruction "
+ "that is not a PC-relative branch.");
+ }
+
+ /**
+ * Return the target address for an indirect branch (jump). The
+ * register value is read from the supplied execution context, so
+ * the result is valid only if the execution context is about to
+ * execute the branch in question. Invalid if not an indirect
+ * branch (i.e. isIndirectCtrl() should be true).
+ */
+ virtual Addr branchTarget(ExecContext *xc) const
+ {
+ panic("StaticInst::branchTarget() called on instruction "
+ "that is not an indirect branch.");
+ }
+
+ /**
+ * Return true if the instruction is a control transfer, and if so,
+ * return the target address as well.
+ */
+ bool hasBranchTarget(Addr pc, ExecContext *xc, Addr &tgt) const;
+
+ /**
+ * Return string representation of disassembled instruction.
+ * The default version of this function will call the internal
+ * virtual generateDisassembly() function to get the string,
+ * then cache it in #cachedDisassembly. If the disassembly
+ * should not be cached, this function should be overridden directly.
+ */
+ virtual const std::string &disassemble(Addr pc,
+ const SymbolTable *symtab = 0) const
+ {
+ if (!cachedDisassembly)
+ cachedDisassembly =
+ new std::string(generateDisassembly(pc, symtab));
+
+ return *cachedDisassembly;
+ }
+
+ /// Decoded instruction cache type.
+ /// For now we're using a generic hash_map; this seems to work
+ /// pretty well.
+ typedef m5::hash_map<ExtMachInst, StaticInstPtr> DecodeCache;
+
+ /// A cache of decoded instruction objects.
+ static DecodeCache decodeCache;
+
+ /**
+ * Dump some basic stats on the decode cache hash map.
+ * Only gets called if DECODE_CACHE_HASH_STATS is defined.
+ */
+ static void dumpDecodeCacheStats();
+
+ /// Decode a machine instruction.
+ /// @param mach_inst The binary instruction to decode.
+ /// @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;
+
+/// Reference-counted pointer to a StaticInst object.
+/// This type should be used instead of "StaticInst *" so that
+/// StaticInst objects can be properly reference-counted.
+class StaticInstPtr : public RefCountingPtr<StaticInst>
+{
+ public:
+ /// Constructor.
+ StaticInstPtr()
+ : RefCountingPtr<StaticInst>()
+ {
+ }
+
+ /// Conversion from "StaticInst *".
+ StaticInstPtr(StaticInst *p)
+ : RefCountingPtr<StaticInst>(p)
+ {
+ }
+
+ /// Copy constructor.
+ StaticInstPtr(const StaticInstPtr &r)
+ : RefCountingPtr<StaticInst>(r)
+ {
+ }
+
+ /// Construct directly from machine instruction.
+ /// Calls StaticInst::decode().
+ StaticInstPtr(TheISA::ExtMachInst mach_inst)
+ : RefCountingPtr<StaticInst>(StaticInst::decode(mach_inst))
+ {
+ }
+
+ /// Convert to pointer to StaticInstBase class.
+ operator const StaticInstBasePtr()
+ {
+ return this->get();
+ }
+};
+
+inline StaticInstPtr
+StaticInst::decode(StaticInst::ExtMachInst mach_inst)
+{
+#ifdef DECODE_CACHE_HASH_STATS
+ // Simple stats on decode hash_map. Turns out the default
+ // hash function is as good as anything I could come up with.
+ const int dump_every_n = 10000000;
+ static int decodes_til_dump = dump_every_n;
+
+ if (--decodes_til_dump == 0) {
+ dumpDecodeCacheStats();
+ decodes_til_dump = dump_every_n;
+ }
+#endif
+
+ DecodeCache::iterator iter = decodeCache.find(mach_inst);
+ if (iter != decodeCache.end()) {
+ return iter->second;
+ }
+
+ StaticInstPtr si = TheISA::decodeInst(mach_inst);
+ decodeCache[mach_inst] = si;
+ return si;
+}
+
+#endif // __CPU_STATIC_INST_HH__
diff --git a/cpu/trace/opt_cpu.cc b/src/cpu/trace/opt_cpu.cc
index 6cd23b0dd..6cd23b0dd 100644
--- a/cpu/trace/opt_cpu.cc
+++ b/src/cpu/trace/opt_cpu.cc
diff --git a/cpu/trace/opt_cpu.hh b/src/cpu/trace/opt_cpu.hh
index f81691733..f81691733 100644
--- a/cpu/trace/opt_cpu.hh
+++ b/src/cpu/trace/opt_cpu.hh
diff --git a/cpu/trace/reader/ibm_reader.cc b/src/cpu/trace/reader/ibm_reader.cc
index 420101b63..420101b63 100644
--- a/cpu/trace/reader/ibm_reader.cc
+++ b/src/cpu/trace/reader/ibm_reader.cc
diff --git a/cpu/trace/reader/ibm_reader.hh b/src/cpu/trace/reader/ibm_reader.hh
index ce29206a2..ce29206a2 100644
--- a/cpu/trace/reader/ibm_reader.hh
+++ b/src/cpu/trace/reader/ibm_reader.hh
diff --git a/cpu/trace/reader/itx_reader.cc b/src/cpu/trace/reader/itx_reader.cc
index 39ba27393..39ba27393 100644
--- a/cpu/trace/reader/itx_reader.cc
+++ b/src/cpu/trace/reader/itx_reader.cc
diff --git a/cpu/trace/reader/itx_reader.hh b/src/cpu/trace/reader/itx_reader.hh
index a16a08085..a16a08085 100644
--- a/cpu/trace/reader/itx_reader.hh
+++ b/src/cpu/trace/reader/itx_reader.hh
diff --git a/cpu/trace/reader/m5_reader.cc b/src/cpu/trace/reader/m5_reader.cc
index ce44672f2..ce44672f2 100644
--- a/cpu/trace/reader/m5_reader.cc
+++ b/src/cpu/trace/reader/m5_reader.cc
diff --git a/cpu/trace/reader/m5_reader.hh b/src/cpu/trace/reader/m5_reader.hh
index 974a83ffa..974a83ffa 100644
--- a/cpu/trace/reader/m5_reader.hh
+++ b/src/cpu/trace/reader/m5_reader.hh
diff --git a/cpu/trace/reader/mem_trace_reader.cc b/src/cpu/trace/reader/mem_trace_reader.cc
index 769f0be27..769f0be27 100644
--- a/cpu/trace/reader/mem_trace_reader.cc
+++ b/src/cpu/trace/reader/mem_trace_reader.cc
diff --git a/cpu/trace/reader/mem_trace_reader.hh b/src/cpu/trace/reader/mem_trace_reader.hh
index b433cdbdd..b433cdbdd 100644
--- a/cpu/trace/reader/mem_trace_reader.hh
+++ b/src/cpu/trace/reader/mem_trace_reader.hh
diff --git a/cpu/trace/trace_cpu.cc b/src/cpu/trace/trace_cpu.cc
index 20d0a567f..20d0a567f 100644
--- a/cpu/trace/trace_cpu.cc
+++ b/src/cpu/trace/trace_cpu.cc
diff --git a/cpu/trace/trace_cpu.hh b/src/cpu/trace/trace_cpu.hh
index 69ca35321..69ca35321 100644
--- a/cpu/trace/trace_cpu.hh
+++ b/src/cpu/trace/trace_cpu.hh
diff --git a/dev/alpha_access.h b/src/dev/alpha_access.h
index 5a1df6f39..5a1df6f39 100644
--- a/dev/alpha_access.h
+++ b/src/dev/alpha_access.h
diff --git a/src/dev/alpha_console.cc b/src/dev/alpha_console.cc
new file mode 100644
index 000000000..0b4bb048c
--- /dev/null
+++ b/src/dev/alpha_console.cc
@@ -0,0 +1,344 @@
+/*
+ * 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
+ * Alpha Console Definition
+ */
+
+#include <cstddef>
+#include <string>
+
+#include "arch/alpha/system.hh"
+#include "base/inifile.hh"
+#include "base/str.hh"
+#include "base/trace.hh"
+#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 "mem/physical.hh"
+#include "sim/builder.hh"
+#include "sim/sim_object.hh"
+
+using namespace std;
+using namespace AlphaISA;
+
+AlphaConsole::AlphaConsole(Params *p)
+ : BasicPioDevice(p), disk(p->disk),
+ console(params()->cons), system(params()->alpha_sys), cpu(params()->cpu)
+{
+
+ pioSize = sizeof(struct AlphaAccess);
+
+ alphaAccess = new Access();
+ alphaAccess->last_offset = pioSize - 1;
+
+ alphaAccess->version = ALPHA_ACCESS_VERSION;
+ alphaAccess->diskUnit = 1;
+
+ alphaAccess->diskCount = 0;
+ alphaAccess->diskPAddr = 0;
+ alphaAccess->diskBlock = 0;
+ alphaAccess->diskOperation = 0;
+ alphaAccess->outputChar = 0;
+ alphaAccess->inputChar = 0;
+ bzero(alphaAccess->cpuStack, sizeof(alphaAccess->cpuStack));
+
+}
+
+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 = params()->platform->intrFrequency();
+}
+
+Tick
+AlphaConsole::read(Packet *pkt)
+{
+
+ /** 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 == Packet::Unknown);
+ assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
+
+ pkt->time += pioDelay;
+ Addr daddr = pkt->getAddr() - pioAddr;
+
+ pkt->allocate();
+
+ switch (pkt->getSize())
+ {
+ case sizeof(uint32_t):
+ switch (daddr)
+ {
+ case offsetof(AlphaAccess, last_offset):
+ pkt->set(alphaAccess->last_offset);
+ break;
+ case offsetof(AlphaAccess, version):
+ pkt->set(alphaAccess->version);
+ break;
+ case offsetof(AlphaAccess, numCPUs):
+ pkt->set(alphaAccess->numCPUs);
+ break;
+ case offsetof(AlphaAccess, intrClockFrequency):
+ pkt->set(alphaAccess->intrClockFrequency);
+ break;
+ default:
+ /* Old console code read in everyting as a 32bit int
+ * we now break that for better error checking.
+ */
+ pkt->result = Packet::BadAddress;
+ }
+ DPRINTF(AlphaConsole, "read: offset=%#x val=%#x\n", daddr,
+ pkt->get<uint32_t>());
+ break;
+ case sizeof(uint64_t):
+ switch (daddr)
+ {
+ case offsetof(AlphaAccess, inputChar):
+ pkt->set(console->console_in());
+ break;
+ case offsetof(AlphaAccess, cpuClock):
+ pkt->set(alphaAccess->cpuClock);
+ break;
+ case offsetof(AlphaAccess, mem_size):
+ pkt->set(alphaAccess->mem_size);
+ break;
+ case offsetof(AlphaAccess, kernStart):
+ pkt->set(alphaAccess->kernStart);
+ break;
+ case offsetof(AlphaAccess, kernEnd):
+ pkt->set(alphaAccess->kernEnd);
+ break;
+ case offsetof(AlphaAccess, entryPoint):
+ pkt->set(alphaAccess->entryPoint);
+ break;
+ case offsetof(AlphaAccess, diskUnit):
+ pkt->set(alphaAccess->diskUnit);
+ break;
+ case offsetof(AlphaAccess, diskCount):
+ pkt->set(alphaAccess->diskCount);
+ break;
+ case offsetof(AlphaAccess, diskPAddr):
+ pkt->set(alphaAccess->diskPAddr);
+ break;
+ case offsetof(AlphaAccess, diskBlock):
+ pkt->set(alphaAccess->diskBlock);
+ break;
+ case offsetof(AlphaAccess, diskOperation):
+ pkt->set(alphaAccess->diskOperation);
+ break;
+ case offsetof(AlphaAccess, outputChar):
+ pkt->set(alphaAccess->outputChar);
+ break;
+ default:
+ int cpunum = (daddr - offsetof(AlphaAccess, cpuStack)) /
+ sizeof(alphaAccess->cpuStack[0]);
+
+ if (cpunum >= 0 && cpunum < 64)
+ 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:
+ pkt->result = Packet::BadAddress;
+ }
+ if (pkt->result == Packet::Unknown)
+ pkt->result = Packet::Success;
+ return pioDelay;
+}
+
+Tick
+AlphaConsole::write(Packet *pkt)
+{
+ pkt->time += pioDelay;
+
+ assert(pkt->result == Packet::Unknown);
+ assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
+ Addr daddr = pkt->getAddr() - pioAddr;
+
+ uint64_t val = pkt->get<uint64_t>();
+ assert(pkt->getSize() == sizeof(uint64_t));
+
+ switch (daddr) {
+ case offsetof(AlphaAccess, diskUnit):
+ alphaAccess->diskUnit = val;
+ break;
+
+ case offsetof(AlphaAccess, diskCount):
+ alphaAccess->diskCount = val;
+ break;
+
+ case offsetof(AlphaAccess, diskPAddr):
+ alphaAccess->diskPAddr = val;
+ break;
+
+ case offsetof(AlphaAccess, diskBlock):
+ alphaAccess->diskBlock = val;
+ break;
+
+ case offsetof(AlphaAccess, diskOperation):
+ if (val == 0x13)
+ disk->read(alphaAccess->diskPAddr, alphaAccess->diskBlock,
+ alphaAccess->diskCount);
+ else
+ panic("Invalid disk operation!");
+
+ break;
+
+ case offsetof(AlphaAccess, outputChar):
+ console->out((char)(val & 0xff));
+ break;
+
+ default:
+ int cpunum = (daddr - offsetof(AlphaAccess, cpuStack)) /
+ sizeof(alphaAccess->cpuStack[0]);
+ warn("%d: Trying to launch CPU number %d!", curTick, cpunum);
+ assert(val > 0 && "Must not access primary cpu");
+ if (cpunum >= 0 && cpunum < 64)
+ alphaAccess->cpuStack[cpunum] = val;
+ else
+ panic("Unknown 64bit access, %#x\n", daddr);
+ }
+
+ pkt->result = Packet::Success;
+
+ return pioDelay;
+}
+
+void
+AlphaConsole::Access::serialize(ostream &os)
+{
+ SERIALIZE_SCALAR(last_offset);
+ SERIALIZE_SCALAR(version);
+ SERIALIZE_SCALAR(numCPUs);
+ SERIALIZE_SCALAR(mem_size);
+ SERIALIZE_SCALAR(cpuClock);
+ SERIALIZE_SCALAR(intrClockFrequency);
+ SERIALIZE_SCALAR(kernStart);
+ SERIALIZE_SCALAR(kernEnd);
+ SERIALIZE_SCALAR(entryPoint);
+ SERIALIZE_SCALAR(diskUnit);
+ SERIALIZE_SCALAR(diskCount);
+ SERIALIZE_SCALAR(diskPAddr);
+ SERIALIZE_SCALAR(diskBlock);
+ SERIALIZE_SCALAR(diskOperation);
+ SERIALIZE_SCALAR(outputChar);
+ SERIALIZE_SCALAR(inputChar);
+ SERIALIZE_ARRAY(cpuStack,64);
+}
+
+void
+AlphaConsole::Access::unserialize(Checkpoint *cp, const std::string &section)
+{
+ UNSERIALIZE_SCALAR(last_offset);
+ UNSERIALIZE_SCALAR(version);
+ UNSERIALIZE_SCALAR(numCPUs);
+ UNSERIALIZE_SCALAR(mem_size);
+ UNSERIALIZE_SCALAR(cpuClock);
+ UNSERIALIZE_SCALAR(intrClockFrequency);
+ UNSERIALIZE_SCALAR(kernStart);
+ UNSERIALIZE_SCALAR(kernEnd);
+ UNSERIALIZE_SCALAR(entryPoint);
+ UNSERIALIZE_SCALAR(diskUnit);
+ UNSERIALIZE_SCALAR(diskCount);
+ UNSERIALIZE_SCALAR(diskPAddr);
+ UNSERIALIZE_SCALAR(diskBlock);
+ UNSERIALIZE_SCALAR(diskOperation);
+ UNSERIALIZE_SCALAR(outputChar);
+ UNSERIALIZE_SCALAR(inputChar);
+ UNSERIALIZE_ARRAY(cpuStack, 64);
+}
+
+void
+AlphaConsole::serialize(ostream &os)
+{
+ alphaAccess->serialize(os);
+}
+
+void
+AlphaConsole::unserialize(Checkpoint *cp, const std::string &section)
+{
+ alphaAccess->unserialize(cp, section);
+}
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaConsole)
+
+ SimObjectParam<SimConsole *> sim_console;
+ SimObjectParam<SimpleDisk *> disk;
+ Param<Addr> pio_addr;
+ SimObjectParam<AlphaSystem *> system;
+ SimObjectParam<BaseCPU *> cpu;
+ SimObjectParam<Platform *> platform;
+ Param<Tick> pio_latency;
+
+END_DECLARE_SIM_OBJECT_PARAMS(AlphaConsole)
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(AlphaConsole)
+
+ INIT_PARAM(sim_console, "The Simulator Console"),
+ INIT_PARAM(disk, "Simple Disk"),
+ INIT_PARAM(pio_addr, "Device Address"),
+ INIT_PARAM(system, "system object"),
+ INIT_PARAM(cpu, "Processor"),
+ INIT_PARAM(platform, "platform"),
+ INIT_PARAM_DFLT(pio_latency, "Programmed IO latency", 1000)
+
+END_INIT_SIM_OBJECT_PARAMS(AlphaConsole)
+
+CREATE_SIM_OBJECT(AlphaConsole)
+{
+ 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/src/dev/alpha_console.hh b/src/dev/alpha_console.hh
new file mode 100644
index 000000000..34d21e15c
--- /dev/null
+++ b/src/dev/alpha_console.hh
@@ -0,0 +1,129 @@
+/*
+ * 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
+ * System Console Interface
+ */
+
+#ifndef __ALPHA_CONSOLE_HH__
+#define __ALPHA_CONSOLE_HH__
+
+#include "base/range.hh"
+#include "dev/alpha_access.h"
+#include "dev/io_device.hh"
+#include "sim/host.hh"
+#include "sim/sim_object.hh"
+
+class BaseCPU;
+class SimConsole;
+class AlphaSystem;
+class SimpleDisk;
+
+/**
+ * Memory mapped interface to the system console. This device
+ * represents a shared data region between the OS Kernel and the
+ * System Console.
+ *
+ * The system console is a small standalone program that is initially
+ * run when the system boots. It contains the necessary code to
+ * access the boot disk, to read/write from the console, and to pass
+ * boot parameters to the kernel.
+ *
+ * This version of the system console is very different from the one
+ * that would be found in a real system. Many of the functions use
+ * some sort of backdoor to get their job done. For example, reading
+ * from the boot device on a real system would require a minimal
+ * device driver to access the disk controller, but since we have a
+ * simulator here, we are able to bypass the disk controller and
+ * access the disk image directly. There are also some things like
+ * reading the kernel off the disk image into memory that are normally
+ * taken care of by the console that are now taken care of by the
+ * simulator.
+ *
+ * These shortcuts are acceptable since the system console is
+ * primarily used doing boot before the kernel has loaded its device
+ * drivers.
+ */
+class AlphaConsole : public BasicPioDevice
+{
+ protected:
+ struct Access : public AlphaAccess
+ {
+ void serialize(std::ostream &os);
+ void unserialize(Checkpoint *cp, const std::string &section);
+ };
+
+ union {
+ Access *alphaAccess;
+ uint8_t *consoleData;
+ };
+
+ /** the disk must be accessed from the console */
+ SimpleDisk *disk;
+
+ /** the system console (the terminal) is accessable from the console */
+ SimConsole *console;
+
+ /** a pointer to the system we are running in */
+ AlphaSystem *system;
+
+ /** a pointer to the CPU boot cpu */
+ BaseCPU *cpu;
+
+ 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(Params *p);
+
+ virtual void startup();
+
+ /**
+ * memory mapped reads and writes
+ */
+ 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);
+};
+
+#endif // __ALPHA_CONSOLE_HH__
diff --git a/src/dev/baddev.cc b/src/dev/baddev.cc
new file mode 100644
index 000000000..66fbd8a86
--- /dev/null
+++ b/src/dev/baddev.cc
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file
+ * BadDevice implemenation
+ */
+
+#include <deque>
+#include <string>
+#include <vector>
+
+#include "base/trace.hh"
+#include "dev/baddev.hh"
+#include "dev/platform.hh"
+#include "mem/port.hh"
+#include "sim/builder.hh"
+#include "sim/system.hh"
+
+using namespace std;
+using namespace TheISA;
+
+BadDevice::BadDevice(Params *p)
+ : BasicPioDevice(p), devname(p->device_name)
+{
+ pioSize = 0xf;
+}
+
+Tick
+BadDevice::read(Packet *pkt)
+{
+ panic("Device %s not imlpmented\n", devname);
+}
+
+Tick
+BadDevice::write(Packet *pkt)
+{
+ 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;
+ Param<Tick> pio_latency;
+
+END_DECLARE_SIM_OBJECT_PARAMS(BadDevice)
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(BadDevice)
+
+ 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)
+{
+ 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/src/dev/baddev.hh b/src/dev/baddev.hh
new file mode 100644
index 000000000..35ae0382a
--- /dev/null
+++ b/src/dev/baddev.hh
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file
+ * This devices just panics when touched. For example if you have a
+ * kernel that touches the frame buffer which isn't allowed.
+ */
+
+#ifndef __DEV_BADDEV_HH__
+#define __DEV_BADDEV_HH__
+
+#include "base/range.hh"
+#include "dev/io_device.hh"
+
+
+/**
+ * BadDevice
+ * This device just panics when accessed. It is supposed to warn
+ * the user that the kernel they are running has unsupported
+ * options (i.e. frame buffer)
+ */
+class BadDevice : public BasicPioDevice
+{
+ private:
+ 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 p object parameters
+ * @param a base address of the write
+ */
+ BadDevice(Params *p);
+
+ virtual Tick read(Packet *pkt);
+ virtual Tick write(Packet *pkt);
+};
+
+#endif // __DEV_BADDEV_HH__
diff --git a/src/dev/disk_image.cc b/src/dev/disk_image.cc
new file mode 100644
index 000000000..185a8b083
--- /dev/null
+++ b/src/dev/disk_image.cc
@@ -0,0 +1,470 @@
+/*
+ * 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
+ * Disk Image Definitions
+ */
+
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include <cstring>
+#include <fstream>
+#include <string>
+
+#include "base/callback.hh"
+#include "base/misc.hh"
+#include "base/trace.hh"
+#include "dev/disk_image.hh"
+#include "sim/builder.hh"
+#include "sim/sim_exit.hh"
+#include "sim/byteswap.hh"
+
+using namespace std;
+
+////////////////////////////////////////////////////////////////////////
+//
+// Raw Disk image
+//
+RawDiskImage::RawDiskImage(const string &name, const string &filename,
+ bool rd_only)
+ : DiskImage(name), disk_size(0)
+{ open(filename, rd_only); }
+
+RawDiskImage::~RawDiskImage()
+{ close(); }
+
+void
+RawDiskImage::open(const string &filename, bool rd_only)
+{
+ if (!filename.empty()) {
+ initialized = true;
+ readonly = rd_only;
+ file = filename;
+
+ ios::openmode mode = ios::in | ios::binary;
+ if (!readonly)
+ mode |= ios::out;
+ stream.open(file.c_str(), mode);
+ if (!stream.is_open())
+ panic("Error opening %s", filename);
+ }
+}
+
+void
+RawDiskImage::close()
+{
+ stream.close();
+}
+
+off_t
+RawDiskImage::size() const
+{
+ if (disk_size == 0) {
+ if (!stream.is_open())
+ panic("file not open!\n");
+ stream.seekg(0, ios::end);
+ disk_size = stream.tellg();
+ }
+
+ return disk_size / SectorSize;
+}
+
+off_t
+RawDiskImage::read(uint8_t *data, off_t offset) const
+{
+ if (!initialized)
+ panic("RawDiskImage not initialized");
+
+ if (!stream.is_open())
+ panic("file not open!\n");
+
+ if (stream.seekg(offset * SectorSize, ios::beg) < 0)
+ panic("Could not seek to location in file");
+
+ streampos pos = stream.tellg();
+ stream.read((char *)data, SectorSize);
+
+ DPRINTF(DiskImageRead, "read: offset=%d\n", (uint64_t)offset);
+ DDUMP(DiskImageRead, data, SectorSize);
+
+ return stream.tellg() - pos;
+}
+
+off_t
+RawDiskImage::write(const uint8_t *data, off_t offset)
+{
+ if (!initialized)
+ panic("RawDiskImage not initialized");
+
+ if (readonly)
+ panic("Cannot write to a read only disk image");
+
+ if (!stream.is_open())
+ panic("file not open!\n");
+
+ if (stream.seekp(offset * SectorSize, ios::beg) < 0)
+ panic("Could not seek to location in file");
+
+ DPRINTF(DiskImageWrite, "write: offset=%d\n", (uint64_t)offset);
+ DDUMP(DiskImageWrite, data, SectorSize);
+
+ streampos pos = stream.tellp();
+ stream.write((const char *)data, SectorSize);
+ return stream.tellp() - pos;
+}
+
+DEFINE_SIM_OBJECT_CLASS_NAME("DiskImage", DiskImage)
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(RawDiskImage)
+
+ Param<string> image_file;
+ Param<bool> read_only;
+
+END_DECLARE_SIM_OBJECT_PARAMS(RawDiskImage)
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(RawDiskImage)
+
+ INIT_PARAM(image_file, "disk image file"),
+ INIT_PARAM_DFLT(read_only, "read only image", false)
+
+END_INIT_SIM_OBJECT_PARAMS(RawDiskImage)
+
+
+CREATE_SIM_OBJECT(RawDiskImage)
+{
+ return new RawDiskImage(getInstanceName(), image_file, read_only);
+}
+
+REGISTER_SIM_OBJECT("RawDiskImage", RawDiskImage)
+
+////////////////////////////////////////////////////////////////////////
+//
+// Copy on Write Disk image
+//
+const int CowDiskImage::VersionMajor = 1;
+const int CowDiskImage::VersionMinor = 0;
+
+CowDiskImage::CowDiskImage(const string &name, DiskImage *kid, int hash_size)
+ : DiskImage(name), child(kid), table(NULL)
+{ init(hash_size); }
+
+class CowDiskCallback : public Callback
+{
+ private:
+ CowDiskImage *image;
+
+ public:
+ CowDiskCallback(CowDiskImage *i) : image(i) {}
+ void process() { image->save(); delete this; }
+};
+
+CowDiskImage::CowDiskImage(const string &name, DiskImage *kid, int hash_size,
+ const string &file, bool read_only)
+ : DiskImage(name), filename(file), child(kid), table(NULL)
+{
+ if (!open(filename)) {
+ assert(!read_only && "why have a non-existent read only file?");
+ init(hash_size);
+ }
+
+ if (!read_only)
+ registerExitCallback(new CowDiskCallback(this));
+}
+
+CowDiskImage::~CowDiskImage()
+{
+ SectorTable::iterator i = table->begin();
+ SectorTable::iterator end = table->end();
+
+ while (i != end) {
+ delete (*i).second;
+ ++i;
+ }
+}
+
+void
+SafeRead(ifstream &stream, void *data, int count)
+{
+ stream.read((char *)data, count);
+ if (!stream.is_open())
+ panic("file not open");
+
+ if (stream.eof())
+ panic("premature end-of-file");
+
+ if (stream.bad() || stream.fail())
+ panic("error reading cowdisk image");
+}
+
+template<class T>
+void
+SafeRead(ifstream &stream, T &data)
+{
+ SafeRead(stream, &data, sizeof(data));
+}
+
+template<class T>
+void
+SafeReadSwap(ifstream &stream, T &data)
+{
+ SafeRead(stream, &data, sizeof(data));
+ data = letoh(data); //is this the proper byte order conversion?
+}
+
+bool
+CowDiskImage::open(const string &file)
+{
+ ifstream stream(file.c_str());
+ if (!stream.is_open())
+ return false;
+
+ if (stream.fail() || stream.bad())
+ panic("Error opening %s", file);
+
+ uint64_t magic;
+ SafeRead(stream, magic);
+
+ if (memcmp(&magic, "COWDISK!", sizeof(magic)) != 0)
+ panic("Could not open %s: Invalid magic", file);
+
+ uint32_t major, minor;
+ SafeReadSwap(stream, major);
+ SafeReadSwap(stream, minor);
+
+ if (major != VersionMajor && minor != VersionMinor)
+ panic("Could not open %s: invalid version %d.%d != %d.%d",
+ file, major, minor, VersionMajor, VersionMinor);
+
+ uint64_t sector_count;
+ SafeReadSwap(stream, sector_count);
+ table = new SectorTable(sector_count);
+
+
+ for (uint64_t i = 0; i < sector_count; i++) {
+ uint64_t offset;
+ SafeReadSwap(stream, offset);
+
+ Sector *sector = new Sector;
+ SafeRead(stream, sector, sizeof(Sector));
+
+ assert(table->find(offset) == table->end());
+ (*table)[offset] = sector;
+ }
+
+ stream.close();
+
+ initialized = true;
+ return true;
+}
+
+void
+CowDiskImage::init(int hash_size)
+{
+ table = new SectorTable(hash_size);
+
+ initialized = true;
+}
+
+void
+SafeWrite(ofstream &stream, const void *data, int count)
+{
+ stream.write((const char *)data, count);
+ if (!stream.is_open())
+ panic("file not open");
+
+ if (stream.eof())
+ panic("premature end-of-file");
+
+ if (stream.bad() || stream.fail())
+ panic("error reading cowdisk image");
+}
+
+template<class T>
+void
+SafeWrite(ofstream &stream, const T &data)
+{
+ SafeWrite(stream, &data, sizeof(data));
+}
+
+template<class T>
+void
+SafeWriteSwap(ofstream &stream, const T &data)
+{
+ T swappeddata = letoh(data); //is this the proper byte order conversion?
+ SafeWrite(stream, &swappeddata, sizeof(data));
+}
+void
+CowDiskImage::save()
+{
+ save(filename);
+}
+
+void
+CowDiskImage::save(const string &file)
+{
+ if (!initialized)
+ panic("RawDiskImage not initialized");
+
+ ofstream stream(file.c_str());
+ if (!stream.is_open() || stream.fail() || stream.bad())
+ panic("Error opening %s", file);
+
+ uint64_t magic;
+ memcpy(&magic, "COWDISK!", sizeof(magic));
+ SafeWrite(stream, magic);
+
+ SafeWriteSwap(stream, (uint32_t)VersionMajor);
+ SafeWriteSwap(stream, (uint32_t)VersionMinor);
+ SafeWriteSwap(stream, (uint64_t)table->size());
+
+ uint64_t size = table->size();
+ SectorTable::iterator iter = table->begin();
+ SectorTable::iterator end = table->end();
+
+ for (uint64_t i = 0; i < size; i++) {
+ if (iter == end)
+ panic("Incorrect Table Size during save of COW disk image");
+
+ SafeWriteSwap(stream, (uint64_t)(*iter).first);
+ SafeWrite(stream, (*iter).second->data, sizeof(Sector));
+ ++iter;
+ }
+
+ stream.close();
+}
+
+void
+CowDiskImage::writeback()
+{
+ SectorTable::iterator i = table->begin();
+ SectorTable::iterator end = table->end();
+
+ while (i != end) {
+ child->write((*i).second->data, (*i).first);
+ ++i;
+ }
+}
+
+off_t
+CowDiskImage::size() const
+{ return child->size(); }
+
+off_t
+CowDiskImage::read(uint8_t *data, off_t offset) const
+{
+ if (!initialized)
+ panic("CowDiskImage not initialized");
+
+ if (offset > size())
+ panic("access out of bounds");
+
+ SectorTable::const_iterator i = table->find(offset);
+ if (i == table->end())
+ return child->read(data, offset);
+ else {
+ memcpy(data, (*i).second->data, SectorSize);
+ DPRINTF(DiskImageRead, "read: offset=%d\n", (uint64_t)offset);
+ DDUMP(DiskImageRead, data, SectorSize);
+ return SectorSize;
+ }
+}
+
+off_t
+CowDiskImage::write(const uint8_t *data, off_t offset)
+{
+ if (!initialized)
+ panic("RawDiskImage not initialized");
+
+ if (offset > size())
+ panic("access out of bounds");
+
+ SectorTable::iterator i = table->find(offset);
+ if (i == table->end()) {
+ Sector *sector = new Sector;
+ memcpy(sector, data, SectorSize);
+ table->insert(make_pair(offset, sector));
+ } else {
+ memcpy((*i).second->data, data, SectorSize);
+ }
+
+ DPRINTF(DiskImageWrite, "write: offset=%d\n", (uint64_t)offset);
+ DDUMP(DiskImageWrite, data, SectorSize);
+
+ return SectorSize;
+}
+
+void
+CowDiskImage::serialize(ostream &os)
+{
+ string cowFilename = name() + ".cow";
+ SERIALIZE_SCALAR(cowFilename);
+ save(Checkpoint::dir() + "/" + cowFilename);
+}
+
+void
+CowDiskImage::unserialize(Checkpoint *cp, const string &section)
+{
+ string cowFilename;
+ UNSERIALIZE_SCALAR(cowFilename);
+ cowFilename = cp->cptDir + "/" + cowFilename;
+ open(cowFilename);
+}
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(CowDiskImage)
+
+ SimObjectParam<DiskImage *> child;
+ Param<string> image_file;
+ Param<int> table_size;
+ Param<bool> read_only;
+
+END_DECLARE_SIM_OBJECT_PARAMS(CowDiskImage)
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(CowDiskImage)
+
+ INIT_PARAM(child, "child image"),
+ INIT_PARAM_DFLT(image_file, "disk image file", ""),
+ INIT_PARAM_DFLT(table_size, "initial table size", 65536),
+ INIT_PARAM_DFLT(read_only, "don't write back to the copy-on-write file",
+ true)
+
+END_INIT_SIM_OBJECT_PARAMS(CowDiskImage)
+
+
+CREATE_SIM_OBJECT(CowDiskImage)
+{
+ if (((string)image_file).empty())
+ return new CowDiskImage(getInstanceName(), child, table_size);
+ else
+ return new CowDiskImage(getInstanceName(), child, table_size,
+ image_file, read_only);
+}
+
+REGISTER_SIM_OBJECT("CowDiskImage", CowDiskImage)
diff --git a/dev/disk_image.hh b/src/dev/disk_image.hh
index 648aa20c6..648aa20c6 100644
--- a/dev/disk_image.hh
+++ b/src/dev/disk_image.hh
diff --git a/src/dev/etherbus.cc b/src/dev/etherbus.cc
new file mode 100644
index 000000000..906e324d3
--- /dev/null
+++ b/src/dev/etherbus.cc
@@ -0,0 +1,125 @@
+/*
+ * 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
+ * Device module for modelling an ethernet hub
+ */
+
+#include <cmath>
+#include <deque>
+#include <string>
+#include <vector>
+
+#include "base/trace.hh"
+#include "dev/etherbus.hh"
+#include "dev/etherdump.hh"
+#include "dev/etherint.hh"
+#include "dev/etherpkt.hh"
+#include "sim/builder.hh"
+#include "sim/root.hh"
+
+using namespace std;
+
+EtherBus::EtherBus(const string &name, double speed, bool loop,
+ EtherDump *packet_dump)
+ : SimObject(name), ticksPerByte(speed), loopback(loop),
+ event(&mainEventQueue, this), sender(0), dump(packet_dump)
+{
+}
+
+void
+EtherBus::txDone()
+{
+ devlist_t::iterator i = devlist.begin();
+ devlist_t::iterator end = devlist.end();
+
+ DPRINTF(Ethernet, "ethernet packet received: length=%d\n", packet->length);
+ DDUMP(EthernetData, packet->data, packet->length);
+
+ while (i != end) {
+ if (loopback || *i != sender)
+ (*i)->sendPacket(packet);
+ ++i;
+ }
+
+ sender->sendDone();
+
+ if (dump)
+ dump->dump(packet);
+
+ sender = 0;
+ packet = 0;
+}
+
+void
+EtherBus::reg(EtherInt *dev)
+{ devlist.push_back(dev); }
+
+bool
+EtherBus::send(EtherInt *sndr, EthPacketPtr &pkt)
+{
+ if (busy()) {
+ DPRINTF(Ethernet, "ethernet packet not sent, bus busy\n", curTick);
+ return false;
+ }
+
+ DPRINTF(Ethernet, "ethernet packet sent: length=%d\n", pkt->length);
+ DDUMP(EthernetData, pkt->data, pkt->length);
+
+ packet = pkt;
+ sender = sndr;
+ int delay = (int)ceil(((double)pkt->length * ticksPerByte) + 1.0);
+ DPRINTF(Ethernet, "scheduling packet: delay=%d, (rate=%f)\n",
+ delay, ticksPerByte);
+ event.schedule(curTick + delay);
+
+ return true;
+}
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(EtherBus)
+
+ Param<bool> loopback;
+ Param<double> speed;
+ SimObjectParam<EtherDump *> packet_dump;
+
+END_DECLARE_SIM_OBJECT_PARAMS(EtherBus)
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(EtherBus)
+
+ INIT_PARAM(loopback, "send the packet back to the sending interface"),
+ INIT_PARAM(speed, "bus speed in ticks per byte"),
+ INIT_PARAM(packet_dump, "object to dump network packets to")
+
+END_INIT_SIM_OBJECT_PARAMS(EtherBus)
+
+CREATE_SIM_OBJECT(EtherBus)
+{
+ return new EtherBus(getInstanceName(), speed, loopback, packet_dump);
+}
+
+REGISTER_SIM_OBJECT("EtherBus", EtherBus)
diff --git a/src/dev/etherbus.hh b/src/dev/etherbus.hh
new file mode 100644
index 000000000..4a364abd8
--- /dev/null
+++ b/src/dev/etherbus.hh
@@ -0,0 +1,79 @@
+/*
+ * 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
+ * Device module for modelling an ethernet hub
+ */
+
+#ifndef __ETHERBUS_H__
+#define __ETHERBUS_H__
+
+#include "sim/eventq.hh"
+#include "dev/etherpkt.hh"
+#include "sim/sim_object.hh"
+
+class EtherDump;
+class EtherInt;
+class EtherBus : public SimObject
+{
+ protected:
+ typedef std::list<EtherInt *> devlist_t;
+ devlist_t devlist;
+ double ticksPerByte;
+ bool loopback;
+
+ protected:
+ class DoneEvent : public Event
+ {
+ protected:
+ EtherBus *bus;
+
+ public:
+ DoneEvent(EventQueue *q, EtherBus *b)
+ : Event(q), bus(b) {}
+ virtual void process() { bus->txDone(); }
+ virtual const char *description() { return "ethernet bus completion"; }
+ };
+
+ DoneEvent event;
+ EthPacketPtr packet;
+ EtherInt *sender;
+ EtherDump *dump;
+
+ public:
+ EtherBus(const std::string &name, double speed, bool loopback,
+ EtherDump *dump);
+ virtual ~EtherBus() {}
+
+ void txDone();
+ void reg(EtherInt *dev);
+ bool busy() const { return (bool)packet; }
+ bool send(EtherInt *sender, EthPacketPtr &packet);
+};
+
+#endif // __ETHERBUS_H__
diff --git a/src/dev/etherdump.cc b/src/dev/etherdump.cc
new file mode 100644
index 000000000..cb5f0b70e
--- /dev/null
+++ b/src/dev/etherdump.cc
@@ -0,0 +1,136 @@
+/*
+ * 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
+ * Simple object for creating a simple pcap style packet trace
+ */
+
+#include <sys/time.h>
+
+#include <algorithm>
+#include <string>
+
+#include "base/misc.hh"
+#include "base/output.hh"
+#include "dev/etherdump.hh"
+#include "sim/builder.hh"
+#include "sim/root.hh"
+
+using std::string;
+
+EtherDump::EtherDump(const string &name, const string &file, int max)
+ : SimObject(name), stream(file.c_str()), maxlen(max)
+{
+}
+
+#define DLT_EN10MB 1 // Ethernet (10Mb)
+#define TCPDUMP_MAGIC 0xa1b2c3d4
+#define PCAP_VERSION_MAJOR 2
+#define PCAP_VERSION_MINOR 4
+
+struct pcap_file_header {
+ uint32_t magic;
+ uint16_t version_major;
+ uint16_t version_minor;
+ int32_t thiszone; // gmt to local correction
+ uint32_t sigfigs; // accuracy of timestamps
+ uint32_t snaplen; // max length saved portion of each pkt
+ uint32_t linktype; // data link type (DLT_*)
+};
+
+struct pcap_pkthdr {
+ uint32_t seconds;
+ uint32_t microseconds;
+ uint32_t caplen; // length of portion present
+ uint32_t len; // length this packet (off wire)
+};
+
+void
+EtherDump::init()
+{
+ curtime = time(NULL);
+ struct pcap_file_header hdr;
+ hdr.magic = TCPDUMP_MAGIC;
+ hdr.version_major = PCAP_VERSION_MAJOR;
+ hdr.version_minor = PCAP_VERSION_MINOR;
+
+ hdr.thiszone = -5 * 3600;
+ hdr.snaplen = 1500;
+ hdr.sigfigs = 0;
+ hdr.linktype = DLT_EN10MB;
+
+ stream.write(reinterpret_cast<char *>(&hdr), sizeof(hdr));
+
+ /*
+ * output an empty packet with the current time so that we know
+ * when the simulation began. This allows us to correlate packets
+ * to sim_cycles.
+ */
+ pcap_pkthdr pkthdr;
+ pkthdr.seconds = curtime;
+ pkthdr.microseconds = 0;
+ pkthdr.caplen = 0;
+ pkthdr.len = 0;
+ stream.write(reinterpret_cast<char *>(&pkthdr), sizeof(pkthdr));
+
+ stream.flush();
+}
+
+void
+EtherDump::dumpPacket(EthPacketPtr &packet)
+{
+ pcap_pkthdr pkthdr;
+ pkthdr.seconds = curtime + (curTick / Clock::Int::s);
+ pkthdr.microseconds = (curTick / Clock::Int::us) % ULL(1000000);
+ pkthdr.caplen = std::min(packet->length, maxlen);
+ pkthdr.len = packet->length;
+ stream.write(reinterpret_cast<char *>(&pkthdr), sizeof(pkthdr));
+ stream.write(reinterpret_cast<char *>(packet->data), pkthdr.caplen);
+ stream.flush();
+}
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(EtherDump)
+
+ Param<string> file;
+ Param<int> maxlen;
+
+END_DECLARE_SIM_OBJECT_PARAMS(EtherDump)
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(EtherDump)
+
+ INIT_PARAM(file, "file to dump packets to"),
+ INIT_PARAM(maxlen, "max portion of packet data to dump")
+
+END_INIT_SIM_OBJECT_PARAMS(EtherDump)
+
+CREATE_SIM_OBJECT(EtherDump)
+{
+ return new EtherDump(getInstanceName(), simout.resolve(file), maxlen);
+}
+
+REGISTER_SIM_OBJECT("EtherDump", EtherDump)
diff --git a/src/dev/etherdump.hh b/src/dev/etherdump.hh
new file mode 100644
index 000000000..8bba073fe
--- /dev/null
+++ b/src/dev/etherdump.hh
@@ -0,0 +1,59 @@
+/*
+ * 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
+ * Simple object for creating a simple pcap style packet trace
+ */
+
+#ifndef __ETHERDUMP_H__
+#define __ETHERDUMP_H__
+
+#include <fstream>
+#include "dev/etherpkt.hh"
+#include "sim/sim_object.hh"
+
+/*
+ * Simple object for creating a simple pcap style packet trace
+ */
+class EtherDump : public SimObject
+{
+ private:
+ std::ofstream stream;
+ const int maxlen;
+ void dumpPacket(EthPacketPtr &packet);
+ void init();
+
+ Tick curtime;
+
+ public:
+ EtherDump(const std::string &name, const std::string &file, int max);
+
+ inline void dump(EthPacketPtr &pkt) { dumpPacket(pkt); }
+};
+
+#endif // __ETHERDUMP_H__
diff --git a/dev/etherint.cc b/src/dev/etherint.cc
index 8fb047373..8fb047373 100644
--- a/dev/etherint.cc
+++ b/src/dev/etherint.cc
diff --git a/src/dev/etherint.hh b/src/dev/etherint.hh
new file mode 100644
index 000000000..1f641fadb
--- /dev/null
+++ b/src/dev/etherint.hh
@@ -0,0 +1,66 @@
+/*
+ * 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
+ * Class representing the actual interface between two ethernet
+ * components.
+ */
+
+#ifndef __DEV_ETHERINT_HH__
+#define __DEV_ETHERINT_HH__
+
+#include <string>
+
+#include "dev/etherpkt.hh"
+#include "sim/sim_object.hh"
+
+/*
+ * Class representing the actual interface between two ethernet
+ * components. These components are intended to attach to another
+ * ethernet interface on one side and whatever device on the other.
+ */
+class EtherInt : public SimObject
+{
+ protected:
+ EtherInt *peer;
+
+ public:
+ EtherInt(const std::string &name) : SimObject(name), peer(NULL) {}
+ virtual ~EtherInt() {}
+
+ void setPeer(EtherInt *p);
+
+ void recvDone() { peer->sendDone(); }
+ virtual void sendDone() = 0;
+
+ bool sendPacket(EthPacketPtr packet)
+ { return peer ? peer->recvPacket(packet) : true; }
+ virtual bool recvPacket(EthPacketPtr packet) = 0;
+};
+
+#endif // __DEV_ETHERINT_HH__
diff --git a/src/dev/etherlink.cc b/src/dev/etherlink.cc
new file mode 100644
index 000000000..5b6531c2e
--- /dev/null
+++ b/src/dev/etherlink.cc
@@ -0,0 +1,300 @@
+/*
+ * 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
+ * Device module for modelling a fixed bandwidth full duplex ethernet link
+ */
+
+#include <cmath>
+#include <deque>
+#include <string>
+#include <vector>
+
+#include "base/random.hh"
+#include "base/trace.hh"
+#include "dev/etherdump.hh"
+#include "dev/etherint.hh"
+#include "dev/etherlink.hh"
+#include "dev/etherpkt.hh"
+#include "sim/builder.hh"
+#include "sim/serialize.hh"
+#include "sim/system.hh"
+#include "sim/root.hh"
+
+using namespace std;
+
+EtherLink::EtherLink(const string &name, EtherInt *peer0, EtherInt *peer1,
+ double rate, Tick delay, Tick delayVar, EtherDump *dump)
+ : SimObject(name)
+{
+ link[0] = new Link(name + ".link0", this, 0, rate, delay, delayVar, dump);
+ link[1] = new Link(name + ".link1", this, 1, rate, delay, delayVar, dump);
+
+ interface[0] = new Interface(name + ".int0", link[0], link[1]);
+ interface[1] = new Interface(name + ".int1", link[1], link[0]);
+
+ interface[0]->setPeer(peer0);
+ peer0->setPeer(interface[0]);
+ interface[1]->setPeer(peer1);
+ peer1->setPeer(interface[1]);
+}
+
+EtherLink::~EtherLink()
+{
+ delete link[0];
+ delete link[1];
+
+ delete interface[0];
+ delete interface[1];
+}
+
+EtherLink::Interface::Interface(const string &name, Link *tx, Link *rx)
+ : EtherInt(name), txlink(tx)
+{
+ tx->setTxInt(this);
+ rx->setRxInt(this);
+}
+
+EtherLink::Link::Link(const string &name, EtherLink *p, int num,
+ double rate, Tick delay, Tick delay_var, EtherDump *d)
+ : objName(name), parent(p), number(num), txint(NULL), rxint(NULL),
+ ticksPerByte(rate), linkDelay(delay), delayVar(delay_var), dump(d),
+ doneEvent(this)
+{ }
+
+void
+EtherLink::serialize(ostream &os)
+{
+ link[0]->serialize("link0", os);
+ link[1]->serialize("link1", os);
+}
+
+void
+EtherLink::unserialize(Checkpoint *cp, const string &section)
+{
+ link[0]->unserialize("link0", cp, section);
+ link[1]->unserialize("link1", cp, section);
+}
+
+void
+EtherLink::Link::txComplete(EthPacketPtr packet)
+{
+ DPRINTF(Ethernet, "packet received: len=%d\n", packet->length);
+ DDUMP(EthernetData, packet->data, packet->length);
+ rxint->sendPacket(packet);
+}
+
+class LinkDelayEvent : public Event
+{
+ protected:
+ EtherLink::Link *link;
+ EthPacketPtr packet;
+
+ public:
+ // non-scheduling version for createForUnserialize()
+ LinkDelayEvent();
+ LinkDelayEvent(EtherLink::Link *link, EthPacketPtr pkt, Tick when);
+
+ void process();
+
+ virtual void serialize(ostream &os);
+ virtual void unserialize(Checkpoint *cp, const string &section);
+ static Serializable *createForUnserialize(Checkpoint *cp,
+ const string &section);
+};
+
+void
+EtherLink::Link::txDone()
+{
+ if (dump)
+ dump->dump(packet);
+
+ if (linkDelay > 0) {
+ DPRINTF(Ethernet, "packet delayed: delay=%d\n", linkDelay);
+ new LinkDelayEvent(this, packet, curTick + linkDelay);
+ } else {
+ txComplete(packet);
+ }
+
+ packet = 0;
+ assert(!busy());
+
+ txint->sendDone();
+}
+
+bool
+EtherLink::Link::transmit(EthPacketPtr pkt)
+{
+ if (busy()) {
+ DPRINTF(Ethernet, "packet not sent, link busy\n");
+ return false;
+ }
+
+ DPRINTF(Ethernet, "packet sent: len=%d\n", pkt->length);
+ DDUMP(EthernetData, pkt->data, pkt->length);
+
+ packet = pkt;
+ Tick delay = (Tick)ceil(((double)pkt->length * ticksPerByte) + 1.0);
+ if (delayVar != 0) {
+ Random<Tick> var;
+ delay += var.uniform(0, delayVar);
+ }
+ DPRINTF(Ethernet, "scheduling packet: delay=%d, (rate=%f)\n",
+ delay, ticksPerByte);
+ doneEvent.schedule(curTick + delay);
+
+ return true;
+}
+
+void
+EtherLink::Link::serialize(const string &base, ostream &os)
+{
+ bool packet_exists = packet;
+ paramOut(os, base + ".packet_exists", packet_exists);
+ if (packet_exists)
+ packet->serialize(base + ".packet", os);
+
+ bool event_scheduled = doneEvent.scheduled();
+ paramOut(os, base + ".event_scheduled", event_scheduled);
+ if (event_scheduled) {
+ Tick event_time = doneEvent.when();
+ paramOut(os, base + ".event_time", event_time);
+ }
+
+}
+
+void
+EtherLink::Link::unserialize(const string &base, Checkpoint *cp,
+ const string &section)
+{
+ bool packet_exists;
+ paramIn(cp, section, base + ".packet_exists", packet_exists);
+ if (packet_exists) {
+ packet = new EthPacketData(16384);
+ packet->unserialize(base + ".packet", cp, section);
+ }
+
+ bool event_scheduled;
+ paramIn(cp, section, base + ".event_scheduled", event_scheduled);
+ if (event_scheduled) {
+ Tick event_time;
+ paramIn(cp, section, base + ".event_time", event_time);
+ doneEvent.schedule(event_time);
+ }
+}
+
+LinkDelayEvent::LinkDelayEvent()
+ : Event(&mainEventQueue), link(NULL)
+{
+ setFlags(AutoSerialize);
+ setFlags(AutoDelete);
+}
+
+LinkDelayEvent::LinkDelayEvent(EtherLink::Link *l, EthPacketPtr p, Tick when)
+ : Event(&mainEventQueue), link(l), packet(p)
+{
+ setFlags(AutoSerialize);
+ setFlags(AutoDelete);
+ schedule(when);
+}
+
+void
+LinkDelayEvent::process()
+{
+ link->txComplete(packet);
+}
+
+void
+LinkDelayEvent::serialize(ostream &os)
+{
+ paramOut(os, "type", string("LinkDelayEvent"));
+ Event::serialize(os);
+
+ EtherLink *parent = link->parent;
+ bool number = link->number;
+ SERIALIZE_OBJPTR(parent);
+ SERIALIZE_SCALAR(number);
+
+ packet->serialize("packet", os);
+}
+
+
+void
+LinkDelayEvent::unserialize(Checkpoint *cp, const string &section)
+{
+ Event::unserialize(cp, section);
+
+ EtherLink *parent;
+ bool number;
+ UNSERIALIZE_OBJPTR(parent);
+ UNSERIALIZE_SCALAR(number);
+
+ link = parent->link[number];
+
+ packet = new EthPacketData(16384);
+ packet->unserialize("packet", cp, section);
+}
+
+
+Serializable *
+LinkDelayEvent::createForUnserialize(Checkpoint *cp, const string &section)
+{
+ return new LinkDelayEvent();
+}
+
+REGISTER_SERIALIZEABLE("LinkDelayEvent", LinkDelayEvent)
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(EtherLink)
+
+ SimObjectParam<EtherInt *> int1;
+ SimObjectParam<EtherInt *> int2;
+ Param<double> speed;
+ Param<Tick> delay;
+ Param<Tick> delay_var;
+ SimObjectParam<EtherDump *> dump;
+
+END_DECLARE_SIM_OBJECT_PARAMS(EtherLink)
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(EtherLink)
+
+ INIT_PARAM(int1, "interface 1"),
+ INIT_PARAM(int2, "interface 2"),
+ INIT_PARAM(speed, "link speed in bits per second"),
+ INIT_PARAM(delay, "transmit delay of packets in us"),
+ INIT_PARAM(delay_var, "Difference in amount of time to traverse wire"),
+ INIT_PARAM(dump, "object to dump network packets to")
+
+END_INIT_SIM_OBJECT_PARAMS(EtherLink)
+
+CREATE_SIM_OBJECT(EtherLink)
+{
+ return new EtherLink(getInstanceName(), int1, int2, speed, delay, delay_var,
+ dump);
+}
+
+REGISTER_SIM_OBJECT("EtherLink", EtherLink)
diff --git a/src/dev/etherlink.hh b/src/dev/etherlink.hh
new file mode 100644
index 000000000..570444e1b
--- /dev/null
+++ b/src/dev/etherlink.hh
@@ -0,0 +1,130 @@
+/*
+ * 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
+ * Device module for modelling a fixed bandwidth full duplex ethernet link
+ */
+
+#ifndef __DEV_ETHERLINK_HH__
+#define __DEV_ETHERLINK_HH__
+
+#include "dev/etherint.hh"
+#include "dev/etherpkt.hh"
+#include "sim/eventq.hh"
+#include "sim/host.hh"
+#include "sim/sim_object.hh"
+
+class EtherDump;
+class Checkpoint;
+/*
+ * Model for a fixed bandwidth full duplex ethernet link
+ */
+class EtherLink : public SimObject
+{
+ protected:
+ class Interface;
+
+ friend class LinkDelayEvent;
+ /*
+ * Model for a single uni-directional link
+ */
+ class Link
+ {
+ protected:
+ std::string objName;
+
+ EtherLink *parent;
+ int number;
+
+ Interface *txint;
+ Interface *rxint;
+
+ double ticksPerByte;
+ Tick linkDelay;
+ Tick delayVar;
+ EtherDump *dump;
+
+ protected:
+ /*
+ * Transfer is complete
+ */
+ EthPacketPtr packet;
+ void txDone();
+ typedef EventWrapper<Link, &Link::txDone> DoneEvent;
+ friend void DoneEvent::process();
+ DoneEvent doneEvent;
+
+ friend class LinkDelayEvent;
+ void txComplete(EthPacketPtr packet);
+
+ public:
+ Link(const std::string &name, EtherLink *p, int num,
+ double rate, Tick delay, Tick delay_var, EtherDump *dump);
+ ~Link() {}
+
+ const std::string name() const { return objName; }
+
+ bool busy() const { return (bool)packet; }
+ bool transmit(EthPacketPtr packet);
+
+ void setTxInt(Interface *i) { assert(!txint); txint = i; }
+ void setRxInt(Interface *i) { assert(!rxint); rxint = i; }
+
+ void serialize(const std::string &base, std::ostream &os);
+ void unserialize(const std::string &base, Checkpoint *cp,
+ const std::string &section);
+ };
+
+ /*
+ * Interface at each end of the link
+ */
+ class Interface : public EtherInt
+ {
+ private:
+ Link *txlink;
+
+ public:
+ Interface(const std::string &name, Link *txlink, Link *rxlink);
+ bool recvPacket(EthPacketPtr packet) { return txlink->transmit(packet); }
+ void sendDone() { peer->sendDone(); }
+ };
+
+ Link *link[2];
+ EtherInt *interface[2];
+
+ public:
+ EtherLink(const std::string &name, EtherInt *peer0, EtherInt *peer1,
+ double rate, Tick delay, Tick delayVar, EtherDump *dump);
+ virtual ~EtherLink();
+
+ virtual void serialize(std::ostream &os);
+ virtual void unserialize(Checkpoint *cp, const std::string &section);
+
+};
+
+#endif // __ETHERLINK_HH__
diff --git a/src/dev/etherpkt.cc b/src/dev/etherpkt.cc
new file mode 100644
index 000000000..85e18e981
--- /dev/null
+++ b/src/dev/etherpkt.cc
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <iostream>
+
+#include "base/misc.hh"
+#include "dev/etherpkt.hh"
+#include "sim/serialize.hh"
+
+using namespace std;
+
+void
+EthPacketData::serialize(const string &base, ostream &os)
+{
+ paramOut(os, base + ".length", length);
+ paramOut(os, base + ".slack", slack);
+ arrayParamOut(os, base + ".data", data, length);
+}
+
+void
+EthPacketData::unserialize(const string &base, Checkpoint *cp,
+ const string &section)
+{
+ paramIn(cp, section, base + ".length", length);
+ paramIn(cp, section, base + ".slack", slack);
+ if (length)
+ arrayParamIn(cp, section, base + ".data", data, length);
+}
diff --git a/src/dev/etherpkt.hh b/src/dev/etherpkt.hh
new file mode 100644
index 000000000..01741b3d5
--- /dev/null
+++ b/src/dev/etherpkt.hh
@@ -0,0 +1,84 @@
+/*
+ * 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
+ * Reference counted class containing ethernet packet data
+ */
+
+#ifndef __ETHERPKT_HH__
+#define __ETHERPKT_HH__
+
+#include <iosfwd>
+#include <memory>
+#include <assert.h>
+
+#include "base/refcnt.hh"
+#include "sim/host.hh"
+
+/*
+ * Reference counted class containing ethernet packet data
+ */
+class Checkpoint;
+class EthPacketData : public RefCounted
+{
+ public:
+ /*
+ * Pointer to packet data will be deleted
+ */
+ uint8_t *data;
+
+ /*
+ * Length of the current packet
+ */
+ int length;
+
+ /*
+ * Extra space taken up by the packet in whatever data structure
+ * it is in.
+ *
+ * NOTE: This can only be use by *one* data structure at a time!
+ */
+ int slack;
+
+ public:
+ EthPacketData() : data(NULL), length(0), slack(0) { }
+ explicit EthPacketData(size_t size)
+ : data(new uint8_t[size]), length(0), slack(0) { }
+ EthPacketData(std::auto_ptr<uint8_t> d, int l, int s = 0)
+ : data(d.release()), length(l), slack(s) { }
+ ~EthPacketData() { if (data) delete [] data; }
+
+ public:
+ void serialize(const std::string &base, std::ostream &os);
+ void unserialize(const std::string &base, Checkpoint *cp,
+ const std::string &section);
+};
+
+typedef RefCountingPtr<EthPacketData> EthPacketPtr;
+
+#endif // __ETHERPKT_HH__
diff --git a/src/dev/ethertap.cc b/src/dev/ethertap.cc
new file mode 100644
index 000000000..b5abb1d62
--- /dev/null
+++ b/src/dev/ethertap.cc
@@ -0,0 +1,345 @@
+/*
+ * 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.
+ */
+
+/* @file
+ * Interface to connect a simulated ethernet device to the real world
+ */
+
+#if defined(__OpenBSD__) || defined(__APPLE__)
+#include <sys/param.h>
+#endif
+#include <netinet/in.h>
+
+#include <unistd.h>
+
+#include <deque>
+#include <string>
+
+#include "base/misc.hh"
+#include "base/pollevent.hh"
+#include "base/socket.hh"
+#include "base/trace.hh"
+#include "dev/etherdump.hh"
+#include "dev/etherint.hh"
+#include "dev/etherpkt.hh"
+#include "dev/ethertap.hh"
+#include "sim/builder.hh"
+
+using namespace std;
+
+/**
+ */
+class TapListener
+{
+ protected:
+ /**
+ */
+ class Event : public PollEvent
+ {
+ protected:
+ TapListener *listener;
+
+ public:
+ Event(TapListener *l, int fd, int e)
+ : PollEvent(fd, e), listener(l) {}
+
+ virtual void process(int revent) { listener->accept(); }
+ };
+
+ friend class Event;
+ Event *event;
+
+ protected:
+ ListenSocket listener;
+ EtherTap *tap;
+ int port;
+
+ public:
+ TapListener(EtherTap *t, int p)
+ : event(NULL), tap(t), port(p) {}
+ ~TapListener() { if (event) delete event; }
+
+ void accept();
+ void listen();
+};
+
+void
+TapListener::listen()
+{
+ while (!listener.listen(port, true)) {
+ DPRINTF(Ethernet, "TapListener(listen): Can't bind port %d\n", port);
+ port++;
+ }
+
+ ccprintf(cerr, "Listening for tap connection on port %d\n", port);
+ event = new Event(this, listener.getfd(), POLLIN|POLLERR);
+ pollQueue.schedule(event);
+}
+
+void
+TapListener::accept()
+{
+ if (!listener.islistening())
+ panic("TapListener(accept): cannot accept if we're not listening!");
+
+ int sfd = listener.accept(true);
+ if (sfd != -1)
+ tap->attach(sfd);
+}
+
+/**
+ */
+class TapEvent : public PollEvent
+{
+ protected:
+ EtherTap *tap;
+
+ public:
+ TapEvent(EtherTap *_tap, int fd, int e)
+ : PollEvent(fd, e), tap(_tap) {}
+ virtual void process(int revent) { tap->process(revent); }
+};
+
+EtherTap::EtherTap(const string &name, EtherDump *d, int port, int bufsz)
+ : EtherInt(name), event(NULL), socket(-1), buflen(bufsz), dump(d),
+ txEvent(this)
+{
+ buffer = new char[buflen];
+ listener = new TapListener(this, port);
+ listener->listen();
+}
+
+EtherTap::~EtherTap()
+{
+ if (event)
+ delete event;
+ if (buffer)
+ delete [] buffer;
+
+ delete listener;
+}
+
+void
+EtherTap::attach(int fd)
+{
+ if (socket != -1)
+ close(fd);
+
+ buffer_offset = 0;
+ data_len = 0;
+ socket = fd;
+ DPRINTF(Ethernet, "EtherTap attached\n");
+ event = new TapEvent(this, socket, POLLIN|POLLERR);
+ pollQueue.schedule(event);
+}
+
+void
+EtherTap::detach()
+{
+ DPRINTF(Ethernet, "EtherTap detached\n");
+ delete event;
+ event = 0;
+ close(socket);
+ socket = -1;
+}
+
+bool
+EtherTap::recvPacket(EthPacketPtr packet)
+{
+ if (dump)
+ dump->dump(packet);
+
+ DPRINTF(Ethernet, "EtherTap output len=%d\n", packet->length);
+ DDUMP(EthernetData, packet->data, packet->length);
+ u_int32_t len = htonl(packet->length);
+ write(socket, &len, sizeof(len));
+ write(socket, packet->data, packet->length);
+
+ recvDone();
+
+ return true;
+}
+
+void
+EtherTap::sendDone()
+{}
+
+void
+EtherTap::process(int revent)
+{
+ if (revent & POLLERR) {
+ detach();
+ return;
+ }
+
+ char *data = buffer + sizeof(u_int32_t);
+ if (!(revent & POLLIN))
+ return;
+
+ if (buffer_offset < data_len + sizeof(u_int32_t)) {
+ int len = read(socket, buffer + buffer_offset, buflen - buffer_offset);
+ if (len == 0) {
+ detach();
+ return;
+ }
+
+ buffer_offset += len;
+
+ if (data_len == 0)
+ data_len = ntohl(*(u_int32_t *)buffer);
+
+ DPRINTF(Ethernet, "Received data from peer: len=%d buffer_offset=%d "
+ "data_len=%d\n", len, buffer_offset, data_len);
+ }
+
+ while (data_len != 0 && buffer_offset >= data_len + sizeof(u_int32_t)) {
+ EthPacketPtr packet;
+ packet = new EthPacketData(data_len);
+ packet->length = data_len;
+ memcpy(packet->data, data, data_len);
+
+ buffer_offset -= data_len + sizeof(u_int32_t);
+ assert(buffer_offset >= 0);
+ if (buffer_offset > 0) {
+ memmove(buffer, data + data_len, buffer_offset);
+ data_len = ntohl(*(u_int32_t *)buffer);
+ } else
+ data_len = 0;
+
+ DPRINTF(Ethernet, "EtherTap input len=%d\n", packet->length);
+ DDUMP(EthernetData, packet->data, packet->length);
+ if (!sendPacket(packet)) {
+ DPRINTF(Ethernet, "bus busy...buffer for retransmission\n");
+ packetBuffer.push(packet);
+ if (!txEvent.scheduled())
+ txEvent.schedule(curTick + retryTime);
+ } else if (dump) {
+ dump->dump(packet);
+ }
+ }
+}
+
+void
+EtherTap::retransmit()
+{
+ if (packetBuffer.empty())
+ return;
+
+ EthPacketPtr packet = packetBuffer.front();
+ if (sendPacket(packet)) {
+ if (dump)
+ dump->dump(packet);
+ DPRINTF(Ethernet, "EtherTap retransmit\n");
+ packetBuffer.front() = NULL;
+ packetBuffer.pop();
+ }
+
+ if (!packetBuffer.empty() && !txEvent.scheduled())
+ txEvent.schedule(curTick + retryTime);
+}
+
+//=====================================================================
+
+void
+EtherTap::serialize(ostream &os)
+{
+ SERIALIZE_SCALAR(socket);
+ SERIALIZE_SCALAR(buflen);
+ uint8_t *buffer = (uint8_t *)this->buffer;
+ SERIALIZE_ARRAY(buffer, buflen);
+ SERIALIZE_SCALAR(buffer_offset);
+ SERIALIZE_SCALAR(data_len);
+
+ bool tapevent_present = false;
+ if (event) {
+ tapevent_present = true;
+ SERIALIZE_SCALAR(tapevent_present);
+ event->serialize(os);
+ }
+ else {
+ SERIALIZE_SCALAR(tapevent_present);
+ }
+}
+
+void
+EtherTap::unserialize(Checkpoint *cp, const std::string &section)
+{
+ UNSERIALIZE_SCALAR(socket);
+ UNSERIALIZE_SCALAR(buflen);
+ uint8_t *buffer = (uint8_t *)this->buffer;
+ UNSERIALIZE_ARRAY(buffer, buflen);
+ UNSERIALIZE_SCALAR(buffer_offset);
+ UNSERIALIZE_SCALAR(data_len);
+
+ bool tapevent_present;
+ UNSERIALIZE_SCALAR(tapevent_present);
+ if (tapevent_present) {
+ event = new TapEvent(this, socket, POLLIN|POLLERR);
+
+ event->unserialize(cp,section);
+
+ if (event->queued()) {
+ pollQueue.schedule(event);
+ }
+ }
+}
+
+//=====================================================================
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(EtherTap)
+
+ SimObjectParam<EtherInt *> peer;
+ SimObjectParam<EtherDump *> dump;
+ Param<unsigned> port;
+ Param<unsigned> bufsz;
+
+END_DECLARE_SIM_OBJECT_PARAMS(EtherTap)
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(EtherTap)
+
+ INIT_PARAM_DFLT(peer, "peer interface", NULL),
+ INIT_PARAM_DFLT(dump, "object to dump network packets to", NULL),
+ INIT_PARAM_DFLT(port, "tap port", 3500),
+ INIT_PARAM_DFLT(bufsz, "tap buffer size", 10000)
+
+END_INIT_SIM_OBJECT_PARAMS(EtherTap)
+
+
+CREATE_SIM_OBJECT(EtherTap)
+{
+ EtherTap *tap = new EtherTap(getInstanceName(), dump, port, bufsz);
+
+ if (peer) {
+ tap->setPeer(peer);
+ peer->setPeer(tap);
+ }
+
+ return tap;
+}
+
+REGISTER_SIM_OBJECT("EtherTap", EtherTap)
diff --git a/src/dev/ethertap.hh b/src/dev/ethertap.hh
new file mode 100644
index 000000000..40ce6af0b
--- /dev/null
+++ b/src/dev/ethertap.hh
@@ -0,0 +1,107 @@
+/*
+ * 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.
+ */
+
+/* @file
+ * Interface to connect a simulated ethernet device to the real world
+ */
+
+#ifndef __ETHERTAP_HH__
+#define __ETHERTAP_HH__
+
+#include <queue>
+#include <string>
+
+#include "dev/etherint.hh"
+#include "dev/etherpkt.hh"
+#include "sim/eventq.hh"
+#include "base/pollevent.hh"
+#include "sim/sim_object.hh"
+
+class TapEvent;
+class TapListener;
+
+/*
+ * Interface to connect a simulated ethernet device to the real world
+ */
+class EtherTap : public EtherInt
+{
+ protected:
+ friend class TapEvent;
+ TapEvent *event;
+
+ protected:
+ friend class TapListener;
+ TapListener *listener;
+ int socket;
+ char *buffer;
+ int buflen;
+ int32_t buffer_offset;
+ int32_t data_len;
+
+ EtherDump *dump;
+
+ void attach(int fd);
+ void detach();
+
+ protected:
+ std::string device;
+ std::queue<EthPacketPtr> packetBuffer;
+
+ void process(int revent);
+ void enqueue(EthPacketData *packet);
+ void retransmit();
+
+ /*
+ */
+ class TxEvent : public Event
+ {
+ protected:
+ EtherTap *tap;
+
+ public:
+ TxEvent(EtherTap *_tap)
+ : Event(&mainEventQueue), tap(_tap) {}
+ void process() { tap->retransmit(); }
+ virtual const char *description() { return "retransmit event"; }
+ };
+
+ friend class TxEvent;
+ TxEvent txEvent;
+
+ public:
+ EtherTap(const std::string &name, EtherDump *dump, int port, int bufsz);
+ virtual ~EtherTap();
+
+ virtual bool recvPacket(EthPacketPtr packet);
+ virtual void sendDone();
+
+ virtual void serialize(std::ostream &os);
+ virtual void unserialize(Checkpoint *cp, const std::string &section);
+};
+
+#endif // __ETHERTAP_HH__
diff --git a/dev/ide_atareg.h b/src/dev/ide_atareg.h
index 5320529c8..5320529c8 100644
--- a/dev/ide_atareg.h
+++ b/src/dev/ide_atareg.h
diff --git a/src/dev/ide_ctrl.cc b/src/dev/ide_ctrl.cc
new file mode 100644
index 000000000..eb03d5db8
--- /dev/null
+++ b/src/dev/ide_ctrl.cc
@@ -0,0 +1,814 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <cstddef>
+#include <cstdlib>
+#include <string>
+#include <vector>
+
+#include "base/trace.hh"
+#include "cpu/intr_control.hh"
+#include "dev/ide_ctrl.hh"
+#include "dev/ide_disk.hh"
+#include "dev/pciconfigall.hh"
+#include "dev/pcireg.h"
+#include "dev/platform.hh"
+#include "mem/packet.hh"
+#include "sim/builder.hh"
+#include "sim/sim_object.hh"
+#include "sim/byteswap.hh"
+
+using namespace std;
+
+////
+// Initialization and destruction
+////
+
+IdeController::IdeController(Params *p)
+ : PciDev(p)
+{
+ // initialize the PIO interface addresses
+ pri_cmd_addr = 0;
+ pri_cmd_size = BARSize[0];
+
+ pri_ctrl_addr = 0;
+ pri_ctrl_size = BARSize[1];
+
+ sec_cmd_addr = 0;
+ sec_cmd_size = BARSize[2];
+
+ sec_ctrl_addr = 0;
+ sec_ctrl_size = BARSize[3];
+
+ // initialize the bus master interface (BMI) address to be configured
+ // via PCI
+ bmi_addr = 0;
+ bmi_size = BARSize[4];
+
+ // zero out all of the registers
+ memset(bmi_regs.data, 0, sizeof(bmi_regs));
+ memset(config_regs.data, 0, sizeof(config_regs.data));
+
+ // setup initial values
+ // enable both channels
+ config_regs.idetim0 = htole((uint16_t)IDETIM_DECODE_EN);
+ config_regs.idetim1 = htole((uint16_t)IDETIM_DECODE_EN);
+ bmi_regs.bmis0 = DMA1CAP | DMA0CAP;
+ bmi_regs.bmis1 = DMA1CAP | DMA0CAP;
+
+ // reset all internal variables
+ io_enabled = false;
+ bm_enabled = false;
+ memset(cmd_in_progress, 0, sizeof(cmd_in_progress));
+
+ // setup the disks attached to controller
+ memset(disks, 0, sizeof(disks));
+ dev[0] = 0;
+ dev[1] = 0;
+
+ if (params()->disks.size() > 3)
+ panic("IDE controllers support a maximum of 4 devices attached!\n");
+
+ for (int i = 0; i < params()->disks.size(); i++) {
+ disks[i] = params()->disks[i];
+ disks[i]->setController(this);
+ }
+}
+
+IdeController::~IdeController()
+{
+ for (int i = 0; i < 4; i++)
+ if (disks[i])
+ delete disks[i];
+}
+
+////
+// Utility functions
+///
+
+void
+IdeController::parseAddr(const Addr &addr, Addr &offset, IdeChannel &channel,
+ IdeRegType &reg_type)
+{
+ offset = addr;
+
+ if (addr >= pri_cmd_addr && addr < (pri_cmd_addr + pri_cmd_size)) {
+ offset -= pri_cmd_addr;
+ reg_type = COMMAND_BLOCK;
+ channel = PRIMARY;
+ } else if (addr >= pri_ctrl_addr &&
+ addr < (pri_ctrl_addr + pri_ctrl_size)) {
+ offset -= pri_ctrl_addr;
+ reg_type = CONTROL_BLOCK;
+ channel = PRIMARY;
+ } else if (addr >= sec_cmd_addr &&
+ addr < (sec_cmd_addr + sec_cmd_size)) {
+ offset -= sec_cmd_addr;
+ reg_type = COMMAND_BLOCK;
+ channel = SECONDARY;
+ } else if (addr >= sec_ctrl_addr &&
+ addr < (sec_ctrl_addr + sec_ctrl_size)) {
+ offset -= sec_ctrl_addr;
+ reg_type = CONTROL_BLOCK;
+ channel = SECONDARY;
+ } else if (addr >= bmi_addr && addr < (bmi_addr + bmi_size)) {
+ offset -= bmi_addr;
+ reg_type = BMI_BLOCK;
+ channel = (offset < BMIC1) ? PRIMARY : SECONDARY;
+ } else {
+ panic("IDE controller access to invalid address: %#x\n", addr);
+ }
+}
+
+int
+IdeController::getDisk(IdeChannel channel)
+{
+ int disk = 0;
+ uint8_t *devBit = &dev[0];
+
+ if (channel == SECONDARY) {
+ disk += 2;
+ devBit = &dev[1];
+ }
+
+ disk += *devBit;
+
+ assert(*devBit == 0 || *devBit == 1);
+
+ return disk;
+}
+
+int
+IdeController::getDisk(IdeDisk *diskPtr)
+{
+ for (int i = 0; i < 4; i++) {
+ if ((long)diskPtr == (long)disks[i])
+ return i;
+ }
+ return -1;
+}
+
+bool
+IdeController::isDiskSelected(IdeDisk *diskPtr)
+{
+ for (int i = 0; i < 4; i++) {
+ if ((long)diskPtr == (long)disks[i]) {
+ // is disk is on primary or secondary channel
+ int channel = i/2;
+ // is disk the master or slave
+ int devID = i%2;
+
+ return (dev[channel] == devID);
+ }
+ }
+ panic("Unable to find disk by pointer!!\n");
+}
+
+////
+// Command completion
+////
+
+void
+IdeController::setDmaComplete(IdeDisk *disk)
+{
+ int diskNum = getDisk(disk);
+
+ if (diskNum < 0)
+ panic("Unable to find disk based on pointer %#x\n", disk);
+
+ if (diskNum < 2) {
+ // clear the start/stop bit in the command register
+ bmi_regs.bmic0 &= ~SSBM;
+ // clear the bus master active bit in the status register
+ bmi_regs.bmis0 &= ~BMIDEA;
+ // set the interrupt bit
+ bmi_regs.bmis0 |= IDEINTS;
+ } else {
+ // clear the start/stop bit in the command register
+ bmi_regs.bmic1 &= ~SSBM;
+ // clear the bus master active bit in the status register
+ bmi_regs.bmis1 &= ~BMIDEA;
+ // set the interrupt bit
+ bmi_regs.bmis1 |= IDEINTS;
+ }
+}
+
+
+////
+// Read and write handling
+////
+
+void
+IdeController::readConfig(int offset, uint8_t *data)
+{
+ if (offset < PCI_DEVICE_SPECIFIC) {
+ PciDev::readConfig(offset, data);
+ } else if (offset >= IDE_CTRL_CONF_START &&
+ (offset + 1) <= IDE_CTRL_CONF_END) {
+
+ switch (offset) {
+ case IDE_CTRL_CONF_DEV_TIMING:
+ *data = config_regs.sidetim;
+ break;
+ case IDE_CTRL_CONF_UDMA_CNTRL:
+ *data = config_regs.udmactl;
+ break;
+ 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 for size 1 at offset: %#x!\n",
+ offset);
+ }
+
+ } else {
+ panic("Read of unimplemented PCI config. register: %x\n", offset);
+ }
+ 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 IDE_CTRL_CONF_SEC_TIMING:
+ *data = config_regs.idetim1;
+ break;
+ 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 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::readConfig(int offset, uint32_t *data)
+{
+ if (offset < PCI_DEVICE_SPECIFIC) {
+ 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 + 1) <= IDE_CTRL_CONF_END) {
+
+ switch (offset) {
+ case IDE_CTRL_CONF_DEV_TIMING:
+ config_regs.sidetim = data;
+ break;
+ case IDE_CTRL_CONF_UDMA_CNTRL:
+ config_regs.udmactl = data;
+ break;
+ 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 for size 1 offset: %#x!\n",
+ offset);
+ }
+
+ } else {
+ 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);
+}
+
+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 IDE_CTRL_CONF_SEC_TIMING:
+ config_regs.idetim1 = data;
+ break;
+ 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 for size 2 offset: %#x!\n",
+ offset);
+ }
+
+ } 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
+ io_enabled = false;
+
+ if (letoh(config.command) & PCI_CMD_BME)
+ bm_enabled = true;
+ else
+ bm_enabled = false;
+ }
+
+}
+
+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)
+ pri_cmd_addr = BARAddrs[0];
+ break;
+
+ case PCI0_BASE_ADDR1:
+ if (BARAddrs[1] != 0)
+ pri_ctrl_addr = BARAddrs[1];
+ break;
+
+ case PCI0_BASE_ADDR2:
+ if (BARAddrs[2] != 0)
+ sec_cmd_addr = BARAddrs[2];
+ break;
+
+ case PCI0_BASE_ADDR3:
+ if (BARAddrs[3] != 0)
+ sec_ctrl_addr = BARAddrs[3];
+ break;
+
+ case PCI0_BASE_ADDR4:
+ if (BARAddrs[4] != 0)
+ bmi_addr = BARAddrs[4];
+ break;
+ }
+}
+
+Tick
+IdeController::read(Packet *pkt)
+{
+ Addr offset;
+ IdeChannel channel;
+ IdeRegType reg_type;
+ int disk;
+
+ pkt->time += pioDelay;
+ pkt->allocate();
+ if (pkt->getSize() != 1 && pkt->getSize() != 2 && pkt->getSize() !=4)
+ panic("Bad IDE read size: %d\n", pkt->getSize());
+
+ parseAddr(pkt->getAddr(), offset, channel, reg_type);
+
+ if (!io_enabled) {
+ pkt->result = Packet::Success;
+ return pioDelay;
+ }
+
+ switch (reg_type) {
+ case BMI_BLOCK:
+ switch (pkt->getSize()) {
+ case sizeof(uint8_t):
+ pkt->set(bmi_regs.data[offset]);
+ break;
+ case sizeof(uint16_t):
+ pkt->set(*(uint16_t*)&bmi_regs.data[offset]);
+ break;
+ case sizeof(uint32_t):
+ pkt->set(*(uint32_t*)&bmi_regs.data[offset]);
+ break;
+ default:
+ panic("IDE read of BMI reg invalid size: %#x\n", pkt->getSize());
+ }
+ break;
+
+ case COMMAND_BLOCK:
+ case CONTROL_BLOCK:
+ disk = getDisk(channel);
+
+ if (disks[disk] == NULL) {
+ pkt->set<uint8_t>(0);
+ break;
+ }
+
+ switch (offset) {
+ case DATA_OFFSET:
+ switch (pkt->getSize()) {
+ case sizeof(uint16_t):
+ disks[disk]->read(offset, reg_type, pkt->getPtr<uint8_t>());
+ break;
+
+ case sizeof(uint32_t):
+ 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", pkt->getSize());
+ }
+ break;
+ default:
+ if (pkt->getSize() == 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", pkt->getSize());
+ }
+ break;
+ default:
+ panic("IDE controller read of unknown register block type!\n");
+ }
+ if (pkt->getSize() == 1)
+ DPRINTF(IdeCtrl, "read from offset: %#x size: %#x data: %#x\n",
+ offset, pkt->getSize(), (uint32_t)pkt->get<uint8_t>());
+ else if (pkt->getSize() == 2)
+ DPRINTF(IdeCtrl, "read from offset: %#x size: %#x data: %#x\n",
+ offset, pkt->getSize(), pkt->get<uint16_t>());
+ else
+ DPRINTF(IdeCtrl, "read from offset: %#x size: %#x data: %#x\n",
+ offset, pkt->getSize(), pkt->get<uint32_t>());
+
+ pkt->result = Packet::Success;
+ return pioDelay;
+}
+
+Tick
+IdeController::write(Packet *pkt)
+{
+ Addr offset;
+ IdeChannel channel;
+ IdeRegType reg_type;
+ int disk;
+ uint8_t oldVal, newVal;
+
+ pkt->time += pioDelay;
+
+ parseAddr(pkt->getAddr(), offset, channel, reg_type);
+
+ if (!io_enabled) {
+ pkt->result = Packet::Success;
+ DPRINTF(IdeCtrl, "io not enabled\n");
+ return pioDelay;
+ }
+
+ switch (reg_type) {
+ case BMI_BLOCK:
+ if (!bm_enabled) {
+ pkt->result = Packet::Success;
+ return pioDelay;
+ }
+
+ switch (offset) {
+ // Bus master IDE command register
+ case BMIC1:
+ case BMIC0:
+ if (pkt->getSize() != sizeof(uint8_t))
+ panic("Invalid BMIC write size: %x\n", pkt->getSize());
+
+ // select the current disk based on DEV bit
+ disk = getDisk(channel);
+
+ oldVal = bmi_regs.chan[channel].bmic;
+ newVal = pkt->get<uint8_t>();
+
+ // if a DMA transfer is in progress, R/W control cannot change
+ if (oldVal & SSBM) {
+ if ((oldVal & RWCON) ^ (newVal & RWCON)) {
+ (oldVal & RWCON) ? newVal |= RWCON : newVal &= ~RWCON;
+ }
+ }
+
+ // see if the start/stop bit is being changed
+ if ((oldVal & SSBM) ^ (newVal & SSBM)) {
+ if (oldVal & SSBM) {
+ // stopping DMA transfer
+ DPRINTF(IdeCtrl, "Stopping DMA transfer\n");
+
+ // clear the BMIDEA bit
+ bmi_regs.chan[channel].bmis =
+ bmi_regs.chan[channel].bmis & ~BMIDEA;
+
+ if (disks[disk] == NULL)
+ panic("DMA stop for disk %d which does not exist\n",
+ disk);
+
+ // inform the disk of the DMA transfer abort
+ disks[disk]->abortDma();
+ } else {
+ // starting DMA transfer
+ DPRINTF(IdeCtrl, "Starting DMA transfer\n");
+
+ // set the BMIDEA bit
+ bmi_regs.chan[channel].bmis =
+ bmi_regs.chan[channel].bmis | BMIDEA;
+
+ if (disks[disk] == NULL)
+ panic("DMA start for disk %d which does not exist\n",
+ disk);
+
+ // inform the disk of the DMA transfer start
+ disks[disk]->startDma(letoh(bmi_regs.chan[channel].bmidtp));
+ }
+ }
+
+ // update the register value
+ bmi_regs.chan[channel].bmic = newVal;
+ break;
+
+ // Bus master IDE status register
+ case BMIS0:
+ case BMIS1:
+ if (pkt->getSize() != sizeof(uint8_t))
+ panic("Invalid BMIS write size: %x\n", pkt->getSize());
+
+ oldVal = bmi_regs.chan[channel].bmis;
+ newVal = pkt->get<uint8_t>();
+
+ // the BMIDEA bit is RO
+ newVal |= (oldVal & BMIDEA);
+
+ // to reset (set 0) IDEINTS and IDEDMAE, write 1 to each
+ if ((oldVal & IDEINTS) && (newVal & IDEINTS))
+ newVal &= ~IDEINTS; // clear the interrupt?
+ else
+ (oldVal & IDEINTS) ? newVal |= IDEINTS : newVal &= ~IDEINTS;
+
+ if ((oldVal & IDEDMAE) && (newVal & IDEDMAE))
+ newVal &= ~IDEDMAE;
+ else
+ (oldVal & IDEDMAE) ? newVal |= IDEDMAE : newVal &= ~IDEDMAE;
+
+ bmi_regs.chan[channel].bmis = newVal;
+ break;
+
+ // Bus master IDE descriptor table pointer register
+ case BMIDTP0:
+ case BMIDTP1:
+ {
+ if (pkt->getSize() != sizeof(uint32_t))
+ panic("Invalid BMIDTP write size: %x\n", pkt->getSize());
+
+ bmi_regs.chan[channel].bmidtp = htole(pkt->get<uint32_t>() & ~0x3);
+ }
+ break;
+
+ default:
+ if (pkt->getSize() != sizeof(uint8_t) &&
+ pkt->getSize() != sizeof(uint16_t) &&
+ pkt->getSize() != sizeof(uint32_t))
+ panic("IDE controller write of invalid write size: %x\n",
+ pkt->getSize());
+
+ // do a default copy of data into the registers
+ memcpy(&bmi_regs.data[offset], pkt->getPtr<uint8_t>(), pkt->getSize());
+ }
+ break;
+ case COMMAND_BLOCK:
+ if (offset == IDE_SELECT_OFFSET) {
+ uint8_t *devBit = &dev[channel];
+ *devBit = (letoh(pkt->get<uint8_t>()) & IDE_SELECT_DEV_BIT) ? 1 : 0;
+ }
+ // fall-through ok!
+ case CONTROL_BLOCK:
+ disk = getDisk(channel);
+
+ if (disks[disk] == NULL)
+ break;
+
+ switch (offset) {
+ case DATA_OFFSET:
+ switch (pkt->getSize()) {
+ case sizeof(uint16_t):
+ disks[disk]->write(offset, reg_type, pkt->getPtr<uint8_t>());
+ break;
+
+ case sizeof(uint32_t):
+ 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", pkt->getSize());
+ }
+ break;
+ default:
+ if (pkt->getSize() == 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", pkt->getSize());
+ }
+ break;
+ default:
+ panic("IDE controller write of unknown register block type!\n");
+ }
+
+ if (pkt->getSize() == 1)
+ DPRINTF(IdeCtrl, "write to offset: %#x size: %#x data: %#x\n",
+ offset, pkt->getSize(), (uint32_t)pkt->get<uint8_t>());
+ else if (pkt->getSize() == 2)
+ DPRINTF(IdeCtrl, "write to offset: %#x size: %#x data: %#x\n",
+ offset, pkt->getSize(), pkt->get<uint16_t>());
+ else
+ DPRINTF(IdeCtrl, "write to offset: %#x size: %#x data: %#x\n",
+ offset, pkt->getSize(), pkt->get<uint32_t>());
+
+
+ pkt->result = Packet::Success;
+ return pioDelay;
+}
+
+////
+// Serialization
+////
+
+void
+IdeController::serialize(std::ostream &os)
+{
+ // Serialize the PciDev base class
+ PciDev::serialize(os);
+
+ // Serialize register addresses and sizes
+ SERIALIZE_SCALAR(pri_cmd_addr);
+ SERIALIZE_SCALAR(pri_cmd_size);
+ SERIALIZE_SCALAR(pri_ctrl_addr);
+ SERIALIZE_SCALAR(pri_ctrl_size);
+ SERIALIZE_SCALAR(sec_cmd_addr);
+ SERIALIZE_SCALAR(sec_cmd_size);
+ SERIALIZE_SCALAR(sec_ctrl_addr);
+ SERIALIZE_SCALAR(sec_ctrl_size);
+ SERIALIZE_SCALAR(bmi_addr);
+ SERIALIZE_SCALAR(bmi_size);
+
+ // Serialize registers
+ SERIALIZE_ARRAY(bmi_regs.data,
+ sizeof(bmi_regs.data) / sizeof(bmi_regs.data[0]));
+ SERIALIZE_ARRAY(dev, sizeof(dev) / sizeof(dev[0]));
+ SERIALIZE_ARRAY(config_regs.data,
+ sizeof(config_regs.data) / sizeof(config_regs.data[0]));
+
+ // Serialize internal state
+ SERIALIZE_SCALAR(io_enabled);
+ SERIALIZE_SCALAR(bm_enabled);
+ SERIALIZE_ARRAY(cmd_in_progress,
+ sizeof(cmd_in_progress) / sizeof(cmd_in_progress[0]));
+}
+
+void
+IdeController::unserialize(Checkpoint *cp, const std::string &section)
+{
+ // Unserialize the PciDev base class
+ PciDev::unserialize(cp, section);
+
+ // Unserialize register addresses and sizes
+ UNSERIALIZE_SCALAR(pri_cmd_addr);
+ UNSERIALIZE_SCALAR(pri_cmd_size);
+ UNSERIALIZE_SCALAR(pri_ctrl_addr);
+ UNSERIALIZE_SCALAR(pri_ctrl_size);
+ UNSERIALIZE_SCALAR(sec_cmd_addr);
+ UNSERIALIZE_SCALAR(sec_cmd_size);
+ UNSERIALIZE_SCALAR(sec_ctrl_addr);
+ UNSERIALIZE_SCALAR(sec_ctrl_size);
+ UNSERIALIZE_SCALAR(bmi_addr);
+ UNSERIALIZE_SCALAR(bmi_size);
+
+ // Unserialize registers
+ UNSERIALIZE_ARRAY(bmi_regs.data,
+ sizeof(bmi_regs.data) / sizeof(bmi_regs.data[0]));
+ UNSERIALIZE_ARRAY(dev, sizeof(dev) / sizeof(dev[0]));
+ UNSERIALIZE_ARRAY(config_regs.data,
+ sizeof(config_regs.data) / sizeof(config_regs.data[0]));
+
+ // Unserialize internal state
+ UNSERIALIZE_SCALAR(io_enabled);
+ UNSERIALIZE_SCALAR(bm_enabled);
+ UNSERIALIZE_ARRAY(cmd_in_progress,
+ sizeof(cmd_in_progress) / sizeof(cmd_in_progress[0]));
+ pioPort->sendStatusChange(Port::RangeChange);
+}
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(IdeController)
+
+ SimObjectParam<System *> system;
+ SimObjectParam<Platform *> platform;
+ SimObjectParam<PciConfigAll *> configspace;
+ SimObjectParam<PciConfigData *> configdata;
+ Param<uint32_t> pci_bus;
+ Param<uint32_t> pci_dev;
+ Param<uint32_t> pci_func;
+ Param<Tick> pio_latency;
+ SimObjectVectorParam<IdeDisk *> disks;
+
+END_DECLARE_SIM_OBJECT_PARAMS(IdeController)
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(IdeController)
+
+ INIT_PARAM(system, "System pointer"),
+ INIT_PARAM(platform, "Platform pointer"),
+ INIT_PARAM(configspace, "PCI Configspace"),
+ INIT_PARAM(configdata, "PCI Config data"),
+ 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(disks, "IDE disks attached to this controller")
+
+END_INIT_SIM_OBJECT_PARAMS(IdeController)
+
+CREATE_SIM_OBJECT(IdeController)
+{
+ IdeController::Params *params = new IdeController::Params;
+ params->name = getInstanceName();
+ params->platform = platform;
+ params->system = system;
+ params->configSpace = configspace;
+ params->configData = configdata;
+ params->busNum = pci_bus;
+ params->deviceNum = pci_dev;
+ params->functionNum = pci_func;
+ params->pio_delay = pio_latency;
+ params->disks = disks;
+ return new IdeController(params);
+}
+
+REGISTER_SIM_OBJECT("IdeController", IdeController)
+
+#endif //DOXYGEN_SHOULD_SKIP_THIS
diff --git a/src/dev/ide_ctrl.hh b/src/dev/ide_ctrl.hh
new file mode 100644
index 000000000..dda2cbb66
--- /dev/null
+++ b/src/dev/ide_ctrl.hh
@@ -0,0 +1,241 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file
+ * Simple PCI IDE controller with bus mastering capability and UDMA
+ * modeled after controller in the Intel PIIX4 chip
+ */
+
+#ifndef __IDE_CTRL_HH__
+#define __IDE_CTRL_HH__
+
+#include "dev/pcidev.hh"
+#include "dev/pcireg.h"
+#include "dev/io_device.hh"
+
+#define BMIC0 0x0 // Bus master IDE command register
+#define BMIS0 0x2 // Bus master IDE status register
+#define BMIDTP0 0x4 // Bus master IDE descriptor table pointer register
+#define BMIC1 0x8 // Bus master IDE command register
+#define BMIS1 0xa // Bus master IDE status register
+#define BMIDTP1 0xc // Bus master IDE descriptor table pointer register
+
+// Bus master IDE command register bit fields
+#define RWCON 0x08 // Bus master read/write control
+#define SSBM 0x01 // Start/stop bus master
+
+// Bus master IDE status register bit fields
+#define DMA1CAP 0x40 // Drive 1 DMA capable
+#define DMA0CAP 0x20 // Drive 0 DMA capable
+#define IDEINTS 0x04 // IDE Interrupt Status
+#define IDEDMAE 0x02 // IDE DMA error
+#define BMIDEA 0x01 // Bus master IDE active
+
+// IDE Command byte fields
+#define IDE_SELECT_OFFSET (6)
+#define IDE_SELECT_DEV_BIT 0x10
+
+#define IDE_FEATURE_OFFSET IDE_ERROR_OFFSET
+#define IDE_COMMAND_OFFSET IDE_STATUS_OFFSET
+
+// IDE Timing Register bit fields
+#define IDETIM_DECODE_EN 0x8000
+
+// PCI device specific register byte offsets
+#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,
+ CONTROL_BLOCK,
+ BMI_BLOCK
+};
+
+class IdeDisk;
+class IntrControl;
+class PciConfigAll;
+class Platform;
+
+/**
+ * Device model for an Intel PIIX4 IDE controller
+ */
+
+class IdeController : public PciDev
+{
+ friend class IdeDisk;
+
+ enum IdeChannel {
+ PRIMARY = 0,
+ SECONDARY = 1
+ };
+
+ private:
+ /** Primary command block registers */
+ Addr pri_cmd_addr;
+ Addr pri_cmd_size;
+ /** Primary control block registers */
+ Addr pri_ctrl_addr;
+ Addr pri_ctrl_size;
+ /** Secondary command block registers */
+ Addr sec_cmd_addr;
+ Addr sec_cmd_size;
+ /** Secondary control block registers */
+ Addr sec_ctrl_addr;
+ Addr sec_ctrl_size;
+ /** Bus master interface (BMI) registers */
+ Addr bmi_addr;
+ Addr bmi_size;
+
+ private:
+ /** Registers used for bus master interface */
+ union {
+ uint8_t data[16];
+
+ struct {
+ uint8_t bmic0;
+ uint8_t reserved_0;
+ uint8_t bmis0;
+ uint8_t reserved_1;
+ uint32_t bmidtp0;
+ uint8_t bmic1;
+ uint8_t reserved_2;
+ uint8_t bmis1;
+ uint8_t reserved_3;
+ uint32_t bmidtp1;
+ };
+
+ struct {
+ uint8_t bmic;
+ uint8_t reserved_4;
+ uint8_t bmis;
+ uint8_t reserved_5;
+ uint32_t bmidtp;
+ } chan[2];
+
+ } bmi_regs;
+ /** Shadows of the device select bit */
+ uint8_t dev[2];
+ /** Registers used in device specific PCI configuration */
+ union {
+ uint8_t data[22];
+
+ struct {
+ uint16_t idetim0;
+ uint16_t idetim1;
+ uint8_t sidetim;
+ uint8_t reserved_0[3];
+ uint8_t udmactl;
+ uint8_t reserved_1;
+ uint16_t udmatim;
+ uint8_t reserved_2[8];
+ uint16_t ideconfig;
+ };
+ } config_regs;
+
+ // Internal management variables
+ bool io_enabled;
+ bool bm_enabled;
+ bool cmd_in_progress[4];
+
+ private:
+ /** IDE disks connected to controller */
+ IdeDisk *disks[4];
+
+ private:
+ /** Parse the access address to pass on to device */
+ void parseAddr(const Addr &addr, Addr &offset, IdeChannel &channel,
+ IdeRegType &reg_type);
+
+ /** Select the disk based on the channel and device bit */
+ int getDisk(IdeChannel channel);
+
+ /** Select the disk based on a pointer */
+ int getDisk(IdeDisk *diskPtr);
+
+ public:
+ /** See if a disk is selected based on its pointer */
+ bool isDiskSelected(IdeDisk *diskPtr);
+
+ public:
+ struct Params : public PciDev::Params
+ {
+ /** Array of disk objects */
+ std::vector<IdeDisk *> disks;
+ };
+ const Params *params() const { return (const Params *)_params; }
+
+ public:
+ IdeController(Params *p);
+ ~IdeController();
+
+ 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 pkt Packet describing what is to be read
+ * @return The amount of time to complete this request
+ */
+ virtual Tick read(Packet *pkt);
+
+ /**
+ * 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 Tick write(Packet *pkt);
+
+ /**
+ * Serialize this object to the given output stream.
+ * @param os The stream to serialize to.
+ */
+ virtual void serialize(std::ostream &os);
+
+ /**
+ * Reconstruct the state of this object from a checkpoint.
+ * @param cp The checkpoint use.
+ * @param section The section name of this object
+ */
+ virtual void unserialize(Checkpoint *cp, const std::string &section);
+
+};
+#endif // __IDE_CTRL_HH_
diff --git a/src/dev/ide_disk.cc b/src/dev/ide_disk.cc
new file mode 100644
index 000000000..909f35c60
--- /dev/null
+++ b/src/dev/ide_disk.cc
@@ -0,0 +1,1146 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file
+ * Device model implementation for an IDE disk
+ */
+
+#include <cerrno>
+#include <cstring>
+#include <deque>
+#include <string>
+
+#include "base/chunk_generator.hh"
+#include "base/cprintf.hh" // csprintf
+#include "base/trace.hh"
+#include "dev/disk_image.hh"
+#include "dev/ide_disk.hh"
+#include "dev/ide_ctrl.hh"
+#include "dev/tsunami.hh"
+#include "dev/tsunami_pchip.hh"
+#include "sim/builder.hh"
+#include "sim/sim_object.hh"
+#include "sim/root.hh"
+#include "arch/isa_traits.hh"
+
+using namespace std;
+using namespace TheISA;
+
+IdeDisk::IdeDisk(const string &name, DiskImage *img,
+ int id, Tick delay)
+ : 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
+ reset(id);
+
+ // fill out the drive ID structure
+ memset(&driveID, 0, sizeof(struct ataparams));
+
+ // Calculate LBA and C/H/S values
+ uint16_t cylinders;
+ uint8_t heads;
+ uint8_t sectors;
+
+ uint32_t lba_size = image->size();
+ if (lba_size >= 16383*16*63) {
+ cylinders = 16383;
+ heads = 16;
+ sectors = 63;
+ } else {
+ if (lba_size >= 63)
+ sectors = 63;
+ else
+ sectors = lba_size;
+
+ if ((lba_size / sectors) >= 16)
+ heads = 16;
+ else
+ heads = (lba_size / sectors);
+
+ cylinders = lba_size / (heads * sectors);
+ }
+
+ // Setup the model name
+ strncpy((char *)driveID.atap_model, "5MI EDD si k",
+ sizeof(driveID.atap_model));
+ // Set the maximum multisector transfer size
+ driveID.atap_multi = MAX_MULTSECT;
+ // IORDY supported, IORDY disabled, LBA enabled, DMA enabled
+ driveID.atap_capabilities1 = 0x7;
+ // UDMA support, EIDE support
+ driveID.atap_extensions = 0x6;
+ // Setup default C/H/S settings
+ driveID.atap_cylinders = cylinders;
+ driveID.atap_sectors = sectors;
+ driveID.atap_heads = heads;
+ // Setup the current multisector transfer size
+ driveID.atap_curmulti = MAX_MULTSECT;
+ driveID.atap_curmulti_valid = 0x1;
+ // Number of sectors on disk
+ driveID.atap_capacity = lba_size;
+ // Multiword DMA mode 2 and below supported
+ driveID.atap_dmamode_supp = 0x400;
+ // Set PIO mode 4 and 3 supported
+ driveID.atap_piomode_supp = 0x3;
+ // Set DMA mode 4 and below supported
+ driveID.atap_udmamode_supp = 0x1f;
+ // Statically set hardware config word
+ driveID.atap_hwreset_res = 0x4001;
+
+ //arbitrary for now...
+ driveID.atap_ata_major = WDC_VER_ATA7;
+}
+
+IdeDisk::~IdeDisk()
+{
+ // destroy the data buffer
+ delete [] dataBuffer;
+}
+
+void
+IdeDisk::reset(int id)
+{
+ // initialize the data buffer and shadow registers
+ dataBuffer = new uint8_t[MAX_DMA_SIZE];
+
+ memset(dataBuffer, 0, MAX_DMA_SIZE);
+ memset(&cmdReg, 0, sizeof(CommandReg_t));
+ memset(&curPrd.entry, 0, sizeof(PrdEntry_t));
+
+ curPrdAddr = 0;
+ curSector = 0;
+ cmdBytes = 0;
+ cmdBytesLeft = 0;
+ drqBytesLeft = 0;
+ dmaRead = false;
+ intrPending = false;
+
+ // set the device state to idle
+ dmaState = Dma_Idle;
+
+ if (id == DEV0) {
+ devState = Device_Idle_S;
+ devID = DEV0;
+ } else if (id == DEV1) {
+ devState = Device_Idle_NS;
+ devID = DEV1;
+ } else {
+ panic("Invalid device ID: %#x\n", id);
+ }
+
+ // set the device ready bit
+ status = STATUS_DRDY_BIT;
+
+ /* The error register must be set to 0x1 on start-up to
+ indicate that no diagnostic error was detected */
+ cmdReg.error = 0x1;
+}
+
+////
+// Utility functions
+////
+
+bool
+IdeDisk::isDEVSelect()
+{
+ return ctrl->isDiskSelected(this);
+}
+
+Addr
+IdeDisk::pciToDma(Addr pciAddr)
+{
+ if (ctrl)
+ return ctrl->plat->pciToDma(pciAddr);
+ else
+ panic("Access to unset controller!\n");
+}
+
+////
+// Device registers read/write
+////
+
+void
+IdeDisk::read(const Addr &offset, IdeRegType reg_type, uint8_t *data)
+{
+ DevAction_t action = ACT_NONE;
+
+ switch (reg_type) {
+ case COMMAND_BLOCK:
+ switch (offset) {
+ // Data transfers occur two bytes at a time
+ case DATA_OFFSET:
+ *(uint16_t*)data = cmdReg.data;
+ action = ACT_DATA_READ_SHORT;
+ break;
+ case ERROR_OFFSET:
+ *data = cmdReg.error;
+ break;
+ case NSECTOR_OFFSET:
+ *data = cmdReg.sec_count;
+ break;
+ case SECTOR_OFFSET:
+ *data = cmdReg.sec_num;
+ break;
+ case LCYL_OFFSET:
+ *data = cmdReg.cyl_low;
+ break;
+ case HCYL_OFFSET:
+ *data = cmdReg.cyl_high;
+ break;
+ case DRIVE_OFFSET:
+ *data = cmdReg.drive;
+ break;
+ case STATUS_OFFSET:
+ *data = status;
+ action = ACT_STAT_READ;
+ break;
+ default:
+ panic("Invalid IDE command register offset: %#x\n", offset);
+ }
+ break;
+ case CONTROL_BLOCK:
+ if (offset == ALTSTAT_OFFSET)
+ *data = status;
+ else
+ panic("Invalid IDE control register offset: %#x\n", offset);
+ break;
+ 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);
+}
+
+void
+IdeDisk::write(const Addr &offset, IdeRegType reg_type, const uint8_t *data)
+{
+ DevAction_t action = ACT_NONE;
+
+ switch (reg_type) {
+ case COMMAND_BLOCK:
+ switch (offset) {
+ case DATA_OFFSET:
+ cmdReg.data = *(uint16_t*)data;
+ action = ACT_DATA_WRITE_SHORT;
+ break;
+ case FEATURES_OFFSET:
+ break;
+ case NSECTOR_OFFSET:
+ cmdReg.sec_count = *data;
+ break;
+ case SECTOR_OFFSET:
+ cmdReg.sec_num = *data;
+ break;
+ case LCYL_OFFSET:
+ cmdReg.cyl_low = *data;
+ break;
+ case HCYL_OFFSET:
+ cmdReg.cyl_high = *data;
+ break;
+ case DRIVE_OFFSET:
+ cmdReg.drive = *data;
+ action = ACT_SELECT_WRITE;
+ break;
+ case COMMAND_OFFSET:
+ cmdReg.command = *data;
+ action = ACT_CMD_WRITE;
+ break;
+ default:
+ panic("Invalid IDE command register offset: %#x\n", offset);
+ }
+ break;
+ case CONTROL_BLOCK:
+ if (offset == CONTROL_OFFSET) {
+ if (*data & CONTROL_RST_BIT) {
+ // force the device into the reset state
+ devState = Device_Srst;
+ action = ACT_SRST_SET;
+ } else if (devState == Device_Srst && !(*data & CONTROL_RST_BIT))
+ action = ACT_SRST_CLEAR;
+
+ nIENBit = (*data & CONTROL_IEN_BIT) ? true : false;
+ }
+ else
+ panic("Invalid IDE control register offset: %#x\n", offset);
+ break;
+ default:
+ 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);
+}
+
+////
+// Perform DMA transactions
+////
+
+void
+IdeDisk::doDmaTransfer()
+{
+ if (dmaState != Dma_Transfer || devState != Transfer_Data_Dma)
+ panic("Inconsistent DMA transfer state: dmaState = %d devState = %d\n",
+ dmaState, devState);
+
+ 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()
+{
+ DPRINTF(IdeDisk,
+ "PRD: baseAddr:%#x (%#x) byteCount:%d (%d) eot:%#x sector:%d\n",
+ curPrd.getBaseAddr(), pciToDma(curPrd.getBaseAddr()),
+ curPrd.getByteCount(), (cmdBytesLeft/SectorSize),
+ curPrd.getEOT(), curSector);
+
+ // the prd pointer has already been translated, so just do an increment
+ curPrdAddr = curPrdAddr + sizeof(PrdEntry_t);
+
+ if (dmaRead)
+ doDmaDataRead();
+ else
+ doDmaDataWrite();
+}
+
+void
+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);
+
+ dmaReadWaitEvent.schedule(curTick + totalDiskDelay);
+}
+
+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()
+{
+
+ 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());
+ dmaReadBytes += dmaReadCG->size();
+ dmaReadTxs++;
+ if (dmaReadCG->size() == TheISA::PageBytes)
+ dmaReadFullPages++;
+ dmaReadCG->next();
+ } else {
+ assert(dmaReadCG->done());
+ delete dmaReadCG;
+ dmaReadCG = NULL;
+ dmaReadDone();
+ }
+}
+
+void
+IdeDisk::dmaReadDone()
+{
+
+ uint32_t bytesWritten = 0;
+
+
+ // write the data to the disk image
+ for (bytesWritten = 0; bytesWritten < curPrd.getByteCount();
+ bytesWritten += SectorSize) {
+
+ cmdBytesLeft -= SectorSize;
+ writeDisk(curSector++, (uint8_t *)(dataBuffer + bytesWritten));
+ }
+
+ // check for the EOT
+ if (curPrd.getEOT()) {
+ assert(cmdBytesLeft == 0);
+ dmaState = Dma_Idle;
+ updateState(ACT_DMA_DONE);
+ } else {
+ doDmaTransfer();
+ }
+}
+
+void
+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);
+
+ 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;
+ }
+
+ dmaWriteWaitEvent.schedule(curTick + totalDiskDelay);
+}
+
+void
+IdeDisk::doDmaWrite()
+{
+
+ 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());
+ dmaWriteBytes += dmaWriteCG->size();
+ dmaWriteTxs++;
+ if (dmaWriteCG->size() == TheISA::PageBytes)
+ dmaWriteFullPages++;
+ dmaWriteCG->next();
+ } else {
+ assert(dmaWriteCG->done());
+ delete dmaWriteCG;
+ dmaWriteCG = NULL;
+ dmaWriteDone();
+ }
+}
+
+void
+IdeDisk::dmaWriteDone()
+{
+ // check for the EOT
+ if (curPrd.getEOT()) {
+ assert(cmdBytesLeft == 0);
+ dmaState = Dma_Idle;
+ updateState(ACT_DMA_DONE);
+ } else {
+ doDmaTransfer();
+ }
+}
+
+////
+// Disk utility routines
+///
+
+void
+IdeDisk::readDisk(uint32_t sector, uint8_t *data)
+{
+ uint32_t bytesRead = image->read(data, sector);
+
+ if (bytesRead != SectorSize)
+ panic("Can't read from %s. Only %d of %d read. errno=%d\n",
+ name(), bytesRead, SectorSize, errno);
+}
+
+void
+IdeDisk::writeDisk(uint32_t sector, uint8_t *data)
+{
+ uint32_t bytesWritten = image->write(data, sector);
+
+ if (bytesWritten != SectorSize)
+ panic("Can't write to %s. Only %d of %d written. errno=%d\n",
+ name(), bytesWritten, SectorSize, errno);
+}
+
+////
+// Setup and handle commands
+////
+
+void
+IdeDisk::startDma(const uint32_t &prdTableBase)
+{
+ if (dmaState != Dma_Start)
+ panic("Inconsistent DMA state, should be in Dma_Start!\n");
+
+ if (devState != Transfer_Data_Dma)
+ panic("Inconsistent device state for DMA start!\n");
+
+ // PRD base address is given by bits 31:2
+ curPrdAddr = pciToDma((Addr)(prdTableBase & ~ULL(0x3)));
+
+ dmaState = Dma_Transfer;
+
+ // schedule dma transfer (doDmaTransfer)
+ dmaTransferEvent.schedule(curTick + 1);
+}
+
+void
+IdeDisk::abortDma()
+{
+ if (dmaState == Dma_Idle)
+ panic("Inconsistent DMA state, should be Start or Transfer!");
+
+ if (devState != Transfer_Data_Dma && devState != Prepare_Data_Dma)
+ panic("Inconsistent device state, should be Transfer or Prepare!\n");
+
+ updateState(ACT_CMD_ERROR);
+}
+
+void
+IdeDisk::startCommand()
+{
+ DevAction_t action = ACT_NONE;
+ uint32_t size = 0;
+ dmaRead = false;
+
+ // Decode commands
+ switch (cmdReg.command) {
+ // Supported non-data commands
+ case WDSF_READ_NATIVE_MAX:
+ size = image->size() - 1;
+ cmdReg.sec_num = (size & 0xff);
+ cmdReg.cyl_low = ((size & 0xff00) >> 8);
+ cmdReg.cyl_high = ((size & 0xff0000) >> 16);
+ cmdReg.head = ((size & 0xf000000) >> 24);
+
+ devState = Command_Execution;
+ action = ACT_CMD_COMPLETE;
+ break;
+
+ case WDCC_RECAL:
+ case WDCC_IDP:
+ case WDCC_STANDBY_IMMED:
+ case WDCC_FLUSHCACHE:
+ case WDSF_VERIFY:
+ case WDSF_SEEK:
+ case SET_FEATURES:
+ case WDCC_SETMULTI:
+ devState = Command_Execution;
+ action = ACT_CMD_COMPLETE;
+ break;
+
+ // Supported PIO data-in commands
+ case WDCC_IDENTIFY:
+ cmdBytes = cmdBytesLeft = sizeof(struct ataparams);
+ devState = Prepare_Data_In;
+ action = ACT_DATA_READY;
+ break;
+
+ case WDCC_READMULTI:
+ case WDCC_READ:
+ if (!(cmdReg.drive & DRIVE_LBA_BIT))
+ panic("Attempt to perform CHS access, only supports LBA\n");
+
+ if (cmdReg.sec_count == 0)
+ cmdBytes = cmdBytesLeft = (256 * SectorSize);
+ else
+ cmdBytes = cmdBytesLeft = (cmdReg.sec_count * SectorSize);
+
+ curSector = getLBABase();
+
+ /** @todo make this a scheduled event to simulate disk delay */
+ devState = Prepare_Data_In;
+ action = ACT_DATA_READY;
+ break;
+
+ // Supported PIO data-out commands
+ case WDCC_WRITEMULTI:
+ case WDCC_WRITE:
+ if (!(cmdReg.drive & DRIVE_LBA_BIT))
+ panic("Attempt to perform CHS access, only supports LBA\n");
+
+ if (cmdReg.sec_count == 0)
+ cmdBytes = cmdBytesLeft = (256 * SectorSize);
+ else
+ cmdBytes = cmdBytesLeft = (cmdReg.sec_count * SectorSize);
+
+ curSector = getLBABase();
+
+ devState = Prepare_Data_Out;
+ action = ACT_DATA_READY;
+ break;
+
+ // Supported DMA commands
+ case WDCC_WRITEDMA:
+ dmaRead = true; // a write to the disk is a DMA read from memory
+ case WDCC_READDMA:
+ if (!(cmdReg.drive & DRIVE_LBA_BIT))
+ panic("Attempt to perform CHS access, only supports LBA\n");
+
+ if (cmdReg.sec_count == 0)
+ cmdBytes = cmdBytesLeft = (256 * SectorSize);
+ else
+ cmdBytes = cmdBytesLeft = (cmdReg.sec_count * SectorSize);
+
+ curSector = getLBABase();
+
+ devState = Prepare_Data_Dma;
+ action = ACT_DMA_READY;
+ break;
+
+ default:
+ panic("Unsupported ATA command: %#x\n", cmdReg.command);
+ }
+
+ if (action != ACT_NONE) {
+ // set the BSY bit
+ status |= STATUS_BSY_BIT;
+ // clear the DRQ bit
+ status &= ~STATUS_DRQ_BIT;
+ // clear the DF bit
+ status &= ~STATUS_DF_BIT;
+
+ updateState(action);
+ }
+}
+
+////
+// Handle setting and clearing interrupts
+////
+
+void
+IdeDisk::intrPost()
+{
+ DPRINTF(IdeDisk, "Posting Interrupt\n");
+ if (intrPending)
+ panic("Attempt to post an interrupt with one pending\n");
+
+ intrPending = true;
+
+ // talk to controller to set interrupt
+ if (ctrl) {
+ ctrl->bmi_regs.bmis0 |= IDEINTS;
+ ctrl->intrPost();
+ }
+}
+
+void
+IdeDisk::intrClear()
+{
+ DPRINTF(IdeDisk, "Clearing Interrupt\n");
+ if (!intrPending)
+ panic("Attempt to clear a non-pending interrupt\n");
+
+ intrPending = false;
+
+ // talk to controller to clear interrupt
+ if (ctrl)
+ ctrl->intrClear();
+}
+
+////
+// Manage the device internal state machine
+////
+
+void
+IdeDisk::updateState(DevAction_t action)
+{
+ switch (devState) {
+ case Device_Srst:
+ if (action == ACT_SRST_SET) {
+ // set the BSY bit
+ status |= STATUS_BSY_BIT;
+ } else if (action == ACT_SRST_CLEAR) {
+ // clear the BSY bit
+ status &= ~STATUS_BSY_BIT;
+
+ // reset the device state
+ reset(devID);
+ }
+ break;
+
+ case Device_Idle_S:
+ if (action == ACT_SELECT_WRITE && !isDEVSelect()) {
+ devState = Device_Idle_NS;
+ } else if (action == ACT_CMD_WRITE) {
+ startCommand();
+ }
+
+ break;
+
+ case Device_Idle_SI:
+ if (action == ACT_SELECT_WRITE && !isDEVSelect()) {
+ devState = Device_Idle_NS;
+ intrClear();
+ } else if (action == ACT_STAT_READ || isIENSet()) {
+ devState = Device_Idle_S;
+ intrClear();
+ } else if (action == ACT_CMD_WRITE) {
+ intrClear();
+ startCommand();
+ }
+
+ break;
+
+ case Device_Idle_NS:
+ if (action == ACT_SELECT_WRITE && isDEVSelect()) {
+ if (!isIENSet() && intrPending) {
+ devState = Device_Idle_SI;
+ intrPost();
+ }
+ if (isIENSet() || !intrPending) {
+ devState = Device_Idle_S;
+ }
+ }
+ break;
+
+ case Command_Execution:
+ if (action == ACT_CMD_COMPLETE) {
+ // clear the BSY bit
+ setComplete();
+
+ if (!isIENSet()) {
+ devState = Device_Idle_SI;
+ intrPost();
+ } else {
+ devState = Device_Idle_S;
+ }
+ }
+ break;
+
+ case Prepare_Data_In:
+ if (action == ACT_CMD_ERROR) {
+ // clear the BSY bit
+ setComplete();
+
+ if (!isIENSet()) {
+ devState = Device_Idle_SI;
+ intrPost();
+ } else {
+ devState = Device_Idle_S;
+ }
+ } else if (action == ACT_DATA_READY) {
+ // clear the BSY bit
+ status &= ~STATUS_BSY_BIT;
+ // set the DRQ bit
+ status |= STATUS_DRQ_BIT;
+
+ // copy the data into the data buffer
+ if (cmdReg.command == WDCC_IDENTIFY) {
+ // Reset the drqBytes for this block
+ drqBytesLeft = sizeof(struct ataparams);
+
+ memcpy((void *)dataBuffer, (void *)&driveID,
+ sizeof(struct ataparams));
+ } else {
+ // Reset the drqBytes for this block
+ drqBytesLeft = SectorSize;
+
+ readDisk(curSector++, dataBuffer);
+ }
+
+ // put the first two bytes into the data register
+ memcpy((void *)&cmdReg.data, (void *)dataBuffer,
+ sizeof(uint16_t));
+
+ if (!isIENSet()) {
+ devState = Data_Ready_INTRQ_In;
+ intrPost();
+ } else {
+ devState = Transfer_Data_In;
+ }
+ }
+ break;
+
+ case Data_Ready_INTRQ_In:
+ if (action == ACT_STAT_READ) {
+ devState = Transfer_Data_In;
+ intrClear();
+ }
+ break;
+
+ case Transfer_Data_In:
+ if (action == ACT_DATA_READ_BYTE || action == ACT_DATA_READ_SHORT) {
+ if (action == ACT_DATA_READ_BYTE) {
+ panic("DEBUG: READING DATA ONE BYTE AT A TIME!\n");
+ } else {
+ drqBytesLeft -= 2;
+ cmdBytesLeft -= 2;
+
+ // copy next short into data registers
+ if (drqBytesLeft)
+ memcpy((void *)&cmdReg.data,
+ (void *)&dataBuffer[SectorSize - drqBytesLeft],
+ sizeof(uint16_t));
+ }
+
+ if (drqBytesLeft == 0) {
+ if (cmdBytesLeft == 0) {
+ // Clear the BSY bit
+ setComplete();
+ devState = Device_Idle_S;
+ } else {
+ devState = Prepare_Data_In;
+ // set the BSY_BIT
+ status |= STATUS_BSY_BIT;
+ // clear the DRQ_BIT
+ status &= ~STATUS_DRQ_BIT;
+
+ /** @todo change this to a scheduled event to simulate
+ disk delay */
+ updateState(ACT_DATA_READY);
+ }
+ }
+ }
+ break;
+
+ case Prepare_Data_Out:
+ if (action == ACT_CMD_ERROR || cmdBytesLeft == 0) {
+ // clear the BSY bit
+ setComplete();
+
+ if (!isIENSet()) {
+ devState = Device_Idle_SI;
+ intrPost();
+ } else {
+ devState = Device_Idle_S;
+ }
+ } else if (action == ACT_DATA_READY && cmdBytesLeft != 0) {
+ // clear the BSY bit
+ status &= ~STATUS_BSY_BIT;
+ // set the DRQ bit
+ status |= STATUS_DRQ_BIT;
+
+ // clear the data buffer to get it ready for writes
+ memset(dataBuffer, 0, MAX_DMA_SIZE);
+
+ // reset the drqBytes for this block
+ drqBytesLeft = SectorSize;
+
+ if (cmdBytesLeft == cmdBytes || isIENSet()) {
+ devState = Transfer_Data_Out;
+ } else {
+ devState = Data_Ready_INTRQ_Out;
+ intrPost();
+ }
+ }
+ break;
+
+ case Data_Ready_INTRQ_Out:
+ if (action == ACT_STAT_READ) {
+ devState = Transfer_Data_Out;
+ intrClear();
+ }
+ break;
+
+ case Transfer_Data_Out:
+ if (action == ACT_DATA_WRITE_BYTE ||
+ action == ACT_DATA_WRITE_SHORT) {
+
+ if (action == ACT_DATA_READ_BYTE) {
+ panic("DEBUG: WRITING DATA ONE BYTE AT A TIME!\n");
+ } else {
+ // copy the latest short into the data buffer
+ memcpy((void *)&dataBuffer[SectorSize - drqBytesLeft],
+ (void *)&cmdReg.data,
+ sizeof(uint16_t));
+
+ drqBytesLeft -= 2;
+ cmdBytesLeft -= 2;
+ }
+
+ if (drqBytesLeft == 0) {
+ // copy the block to the disk
+ writeDisk(curSector++, dataBuffer);
+
+ // set the BSY bit
+ status |= STATUS_BSY_BIT;
+ // set the seek bit
+ status |= STATUS_SEEK_BIT;
+ // clear the DRQ bit
+ status &= ~STATUS_DRQ_BIT;
+
+ devState = Prepare_Data_Out;
+
+ /** @todo change this to a scheduled event to simulate
+ disk delay */
+ updateState(ACT_DATA_READY);
+ }
+ }
+ break;
+
+ case Prepare_Data_Dma:
+ if (action == ACT_CMD_ERROR) {
+ // clear the BSY bit
+ setComplete();
+
+ if (!isIENSet()) {
+ devState = Device_Idle_SI;
+ intrPost();
+ } else {
+ devState = Device_Idle_S;
+ }
+ } else if (action == ACT_DMA_READY) {
+ // clear the BSY bit
+ status &= ~STATUS_BSY_BIT;
+ // set the DRQ bit
+ status |= STATUS_DRQ_BIT;
+
+ devState = Transfer_Data_Dma;
+
+ if (dmaState != Dma_Idle)
+ panic("Inconsistent DMA state, should be Dma_Idle\n");
+
+ dmaState = Dma_Start;
+ // wait for the write to the DMA start bit
+ }
+ break;
+
+ case Transfer_Data_Dma:
+ if (action == ACT_CMD_ERROR || action == ACT_DMA_DONE) {
+ // clear the BSY bit
+ setComplete();
+ // set the seek bit
+ status |= STATUS_SEEK_BIT;
+ // clear the controller state for DMA transfer
+ ctrl->setDmaComplete(this);
+
+ if (!isIENSet()) {
+ devState = Device_Idle_SI;
+ intrPost();
+ } else {
+ devState = Device_Idle_S;
+ }
+ }
+ break;
+
+ default:
+ panic("Unknown IDE device state: %#x\n", devState);
+ }
+}
+
+void
+IdeDisk::serialize(ostream &os)
+{
+ // Check all outstanding events to see if they are scheduled
+ // these are all mutually exclusive
+ Tick reschedule = 0;
+ Events_t event = None;
+
+ int eventCount = 0;
+
+ if (dmaTransferEvent.scheduled()) {
+ reschedule = dmaTransferEvent.when();
+ event = Transfer;
+ eventCount++;
+ }
+ if (dmaReadWaitEvent.scheduled()) {
+ reschedule = dmaReadWaitEvent.when();
+ event = ReadWait;
+ eventCount++;
+ }
+ if (dmaWriteWaitEvent.scheduled()) {
+ reschedule = dmaWriteWaitEvent.when();
+ event = WriteWait;
+ eventCount++;
+ }
+ if (dmaPrdReadEvent.scheduled()) {
+ reschedule = dmaPrdReadEvent.when();
+ event = PrdRead;
+ eventCount++;
+ }
+ if (dmaReadEvent.scheduled()) {
+ reschedule = dmaReadEvent.when();
+ event = DmaRead;
+ eventCount++;
+ }
+ if (dmaWriteEvent.scheduled()) {
+ reschedule = dmaWriteEvent.when();
+ event = DmaWrite;
+ eventCount++;
+ }
+
+ assert(eventCount <= 1);
+
+ SERIALIZE_SCALAR(reschedule);
+ SERIALIZE_ENUM(event);
+
+ // Serialize device registers
+ SERIALIZE_SCALAR(cmdReg.data);
+ SERIALIZE_SCALAR(cmdReg.sec_count);
+ SERIALIZE_SCALAR(cmdReg.sec_num);
+ SERIALIZE_SCALAR(cmdReg.cyl_low);
+ SERIALIZE_SCALAR(cmdReg.cyl_high);
+ SERIALIZE_SCALAR(cmdReg.drive);
+ SERIALIZE_SCALAR(cmdReg.command);
+ SERIALIZE_SCALAR(status);
+ SERIALIZE_SCALAR(nIENBit);
+ SERIALIZE_SCALAR(devID);
+
+ // Serialize the PRD related information
+ SERIALIZE_SCALAR(curPrd.entry.baseAddr);
+ SERIALIZE_SCALAR(curPrd.entry.byteCount);
+ 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(intrPending);
+ SERIALIZE_ENUM(devState);
+ SERIALIZE_ENUM(dmaState);
+ SERIALIZE_ARRAY(dataBuffer, MAX_DMA_SIZE);
+}
+
+void
+IdeDisk::unserialize(Checkpoint *cp, const string &section)
+{
+ // Reschedule events that were outstanding
+ // these are all mutually exclusive
+ Tick reschedule = 0;
+ Events_t event = None;
+
+ UNSERIALIZE_SCALAR(reschedule);
+ UNSERIALIZE_ENUM(event);
+
+ switch (event) {
+ case None : break;
+ case Transfer : dmaTransferEvent.schedule(reschedule); break;
+ case ReadWait : dmaReadWaitEvent.schedule(reschedule); break;
+ case WriteWait : dmaWriteWaitEvent.schedule(reschedule); break;
+ case PrdRead : dmaPrdReadEvent.schedule(reschedule); break;
+ case DmaRead : dmaReadEvent.schedule(reschedule); break;
+ case DmaWrite : dmaWriteEvent.schedule(reschedule); break;
+ }
+
+ // Unserialize device registers
+ UNSERIALIZE_SCALAR(cmdReg.data);
+ UNSERIALIZE_SCALAR(cmdReg.sec_count);
+ UNSERIALIZE_SCALAR(cmdReg.sec_num);
+ UNSERIALIZE_SCALAR(cmdReg.cyl_low);
+ UNSERIALIZE_SCALAR(cmdReg.cyl_high);
+ UNSERIALIZE_SCALAR(cmdReg.drive);
+ UNSERIALIZE_SCALAR(cmdReg.command);
+ UNSERIALIZE_SCALAR(status);
+ UNSERIALIZE_SCALAR(nIENBit);
+ UNSERIALIZE_SCALAR(devID);
+
+ // Unserialize the PRD related information
+ UNSERIALIZE_SCALAR(curPrd.entry.baseAddr);
+ UNSERIALIZE_SCALAR(curPrd.entry.byteCount);
+ 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(intrPending);
+ UNSERIALIZE_ENUM(devState);
+ UNSERIALIZE_ENUM(dmaState);
+ UNSERIALIZE_ARRAY(dataBuffer, MAX_DMA_SIZE);
+}
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+enum DriveID { master, slave };
+static const char *DriveID_strings[] = { "master", "slave" };
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(IdeDisk)
+
+ SimObjectParam<DiskImage *> image;
+ SimpleEnumParam<DriveID> driveID;
+ Param<int> delay;
+
+END_DECLARE_SIM_OBJECT_PARAMS(IdeDisk)
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(IdeDisk)
+
+ INIT_PARAM(image, "Disk image"),
+ INIT_ENUM_PARAM(driveID, "Drive ID (0=master 1=slave)", DriveID_strings),
+ INIT_PARAM_DFLT(delay, "Fixed disk delay in microseconds", 1)
+
+END_INIT_SIM_OBJECT_PARAMS(IdeDisk)
+
+
+CREATE_SIM_OBJECT(IdeDisk)
+{
+ return new IdeDisk(getInstanceName(), image, driveID, delay);
+}
+
+REGISTER_SIM_OBJECT("IdeDisk", IdeDisk)
+
+#endif //DOXYGEN_SHOULD_SKIP_THIS
diff --git a/src/dev/ide_disk.hh b/src/dev/ide_disk.hh
new file mode 100644
index 000000000..5379e5e73
--- /dev/null
+++ b/src/dev/ide_disk.hh
@@ -0,0 +1,367 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file
+ * Device model for an IDE disk
+ */
+
+#ifndef __IDE_DISK_HH__
+#define __IDE_DISK_HH__
+
+#include "base/statistics.hh"
+#include "dev/disk_image.hh"
+#include "dev/ide_atareg.h"
+#include "dev/ide_ctrl.hh"
+#include "dev/ide_wdcreg.h"
+#include "dev/io_device.hh"
+#include "sim/eventq.hh"
+
+#define DMA_BACKOFF_PERIOD 200
+
+#define MAX_DMA_SIZE (131072) // 128K
+#define MAX_MULTSECT (128)
+
+#define PRD_BASE_MASK 0xfffffffe
+#define PRD_COUNT_MASK 0xfffe
+#define PRD_EOT_MASK 0x8000
+
+typedef struct PrdEntry {
+ uint32_t baseAddr;
+ uint16_t byteCount;
+ uint16_t endOfTable;
+} PrdEntry_t;
+
+class PrdTableEntry {
+ public:
+ PrdEntry_t entry;
+
+ uint32_t getBaseAddr()
+ {
+ return (entry.baseAddr & PRD_BASE_MASK);
+ }
+
+ uint32_t getByteCount()
+ {
+ return ((entry.byteCount == 0) ? MAX_DMA_SIZE :
+ (entry.byteCount & PRD_COUNT_MASK));
+ }
+
+ uint16_t getEOT()
+ {
+ return (entry.endOfTable & PRD_EOT_MASK);
+ }
+};
+
+#define DATA_OFFSET (0)
+#define ERROR_OFFSET (1)
+#define FEATURES_OFFSET (1)
+#define NSECTOR_OFFSET (2)
+#define SECTOR_OFFSET (3)
+#define LCYL_OFFSET (4)
+#define HCYL_OFFSET (5)
+#define SELECT_OFFSET (6)
+#define DRIVE_OFFSET (6)
+#define STATUS_OFFSET (7)
+#define COMMAND_OFFSET (7)
+
+#define CONTROL_OFFSET (2)
+#define ALTSTAT_OFFSET (2)
+
+#define SELECT_DEV_BIT 0x10
+#define CONTROL_RST_BIT 0x04
+#define CONTROL_IEN_BIT 0x02
+#define STATUS_BSY_BIT 0x80
+#define STATUS_DRDY_BIT 0x40
+#define STATUS_DRQ_BIT 0x08
+#define STATUS_SEEK_BIT 0x10
+#define STATUS_DF_BIT 0x20
+#define DRIVE_LBA_BIT 0x40
+
+#define DEV0 (0)
+#define DEV1 (1)
+
+typedef struct CommandReg {
+ uint16_t data;
+ uint8_t error;
+ uint8_t sec_count;
+ uint8_t sec_num;
+ uint8_t cyl_low;
+ uint8_t cyl_high;
+ union {
+ uint8_t drive;
+ uint8_t head;
+ };
+ uint8_t command;
+} CommandReg_t;
+
+typedef enum Events {
+ None = 0,
+ Transfer,
+ ReadWait,
+ WriteWait,
+ PrdRead,
+ DmaRead,
+ DmaWrite
+} Events_t;
+
+typedef enum DevAction {
+ ACT_NONE = 0,
+ ACT_CMD_WRITE,
+ ACT_CMD_COMPLETE,
+ ACT_CMD_ERROR,
+ ACT_SELECT_WRITE,
+ ACT_STAT_READ,
+ ACT_DATA_READY,
+ ACT_DATA_READ_BYTE,
+ ACT_DATA_READ_SHORT,
+ ACT_DATA_WRITE_BYTE,
+ ACT_DATA_WRITE_SHORT,
+ ACT_DMA_READY,
+ ACT_DMA_DONE,
+ ACT_SRST_SET,
+ ACT_SRST_CLEAR
+} DevAction_t;
+
+typedef enum DevState {
+ // Device idle
+ Device_Idle_S = 0,
+ Device_Idle_SI,
+ Device_Idle_NS,
+
+ // Software reset
+ Device_Srst,
+
+ // Non-data commands
+ Command_Execution,
+
+ // PIO data-in (data to host)
+ Prepare_Data_In,
+ Data_Ready_INTRQ_In,
+ Transfer_Data_In,
+
+ // PIO data-out (data from host)
+ Prepare_Data_Out,
+ Data_Ready_INTRQ_Out,
+ Transfer_Data_Out,
+
+ // DMA protocol
+ Prepare_Data_Dma,
+ Transfer_Data_Dma
+} DevState_t;
+
+typedef enum DmaState {
+ Dma_Idle = 0,
+ Dma_Start,
+ Dma_Transfer
+} DmaState_t;
+
+class PhysicalMemory;
+class IdeController;
+
+/**
+ * IDE Disk device model
+ */
+class IdeDisk : public SimObject
+{
+ protected:
+ /** The IDE controller for this disk. */
+ IdeController *ctrl;
+ /** The image that contains the data of this disk. */
+ DiskImage *image;
+
+ protected:
+ /** The disk delay in microseconds. */
+ int diskDelay;
+
+ private:
+ /** Drive identification structure for this disk */
+ struct ataparams driveID;
+ /** Data buffer for transfers */
+ uint8_t *dataBuffer;
+ /** Number of bytes in command data transfer */
+ uint32_t cmdBytes;
+ /** Number of bytes left in command data transfer */
+ uint32_t cmdBytesLeft;
+ /** Number of bytes left in DRQ block */
+ uint32_t drqBytesLeft;
+ /** Current sector in access */
+ uint32_t curSector;
+ /** Command block registers */
+ CommandReg_t cmdReg;
+ /** Status register */
+ uint8_t status;
+ /** Interrupt enable bit */
+ bool nIENBit;
+ /** Device state */
+ DevState_t devState;
+ /** Dma state */
+ DmaState_t dmaState;
+ /** Dma transaction is a read */
+ bool dmaRead;
+ /** PRD table base address */
+ uint32_t curPrdAddr;
+ /** PRD entry */
+ PrdTableEntry curPrd;
+ /** Device ID (master=0/slave=1) */
+ int devID;
+ /** Interrupt pending */
+ bool intrPending;
+
+ Stats::Scalar<> dmaReadFullPages;
+ Stats::Scalar<> dmaReadBytes;
+ Stats::Scalar<> dmaReadTxs;
+ Stats::Scalar<> dmaWriteFullPages;
+ Stats::Scalar<> dmaWriteBytes;
+ Stats::Scalar<> dmaWriteTxs;
+
+ public:
+ /**
+ * Create and initialize this Disk.
+ * @param name The name of this disk.
+ * @param img The disk image of this disk.
+ * @param id The disk ID (master=0/slave=1)
+ * @param disk_delay The disk delay in milliseconds
+ */
+ IdeDisk(const std::string &name, DiskImage *img, int id, Tick disk_delay);
+
+ /**
+ * Delete the data buffer.
+ */
+ ~IdeDisk();
+
+ /**
+ * Reset the device state
+ */
+ void reset(int id);
+
+ /**
+ * Register Statistics
+ */
+ void regStats();
+
+ /**
+ * Set the controller for this device
+ * @param c The IDE controller
+ */
+ void setController(IdeController *c) {
+ if (ctrl) panic("Cannot change the controller once set!\n");
+ ctrl = c;
+ }
+
+ // Device register read/write
+ void read(const Addr &offset, IdeRegType regtype, uint8_t *data);
+ void write(const Addr &offset, IdeRegType regtype, const uint8_t *data);
+
+ // Start/abort functions
+ void startDma(const uint32_t &prdTableBase);
+ void abortDma();
+
+ private:
+ void startCommand();
+
+ // Interrupt management
+ void intrPost();
+ void intrClear();
+
+ // DMA stuff
+ void doDmaTransfer();
+ 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;
+
+ void dmaPrdReadDone();
+ friend class EventWrapper<IdeDisk, &IdeDisk::dmaPrdReadDone>;
+ EventWrapper<IdeDisk, &IdeDisk::dmaPrdReadDone> dmaPrdReadEvent;
+
+ void dmaReadDone();
+ friend class EventWrapper<IdeDisk, &IdeDisk::dmaReadDone>;
+ EventWrapper<IdeDisk, &IdeDisk::dmaReadDone> dmaReadEvent;
+
+ void dmaWriteDone();
+ friend class EventWrapper<IdeDisk, &IdeDisk::dmaWriteDone>;
+ EventWrapper<IdeDisk, &IdeDisk::dmaWriteDone> dmaWriteEvent;
+
+ // Disk image read/write
+ void readDisk(uint32_t sector, uint8_t *data);
+ void writeDisk(uint32_t sector, uint8_t *data);
+
+ // State machine management
+ void updateState(DevAction_t action);
+
+ // Utility functions
+ bool isBSYSet() { return (status & STATUS_BSY_BIT); }
+ bool isIENSet() { return nIENBit; }
+ bool isDEVSelect();
+
+ void setComplete()
+ {
+ // clear out the status byte
+ status = 0;
+ // set the DRDY bit
+ status |= STATUS_DRDY_BIT;
+ // set the SEEK bit
+ status |= STATUS_SEEK_BIT;
+ }
+
+ uint32_t getLBABase()
+ {
+ return (Addr)(((cmdReg.head & 0xf) << 24) | (cmdReg.cyl_high << 16) |
+ (cmdReg.cyl_low << 8) | (cmdReg.sec_num));
+ }
+
+ inline Addr pciToDma(Addr pciAddr);
+
+ /**
+ * Serialize this object to the given output stream.
+ * @param os The stream to serialize to.
+ */
+ void serialize(std::ostream &os);
+
+ /**
+ * Reconstruct the state of this object from a checkpoint.
+ * @param cp The checkpoint to use.
+ * @param section The section name describing this object.
+ */
+ void unserialize(Checkpoint *cp, const std::string &section);
+};
+
+
+#endif // __IDE_DISK_HH__
diff --git a/dev/ide_wdcreg.h b/src/dev/ide_wdcreg.h
index ed7475ec8..ed7475ec8 100644
--- a/dev/ide_wdcreg.h
+++ b/src/dev/ide_wdcreg.h
diff --git a/src/dev/io_device.cc b/src/dev/io_device.cc
new file mode 100644
index 000000000..87fdbb765
--- /dev/null
+++ b/src/dev/io_device.cc
@@ -0,0 +1,225 @@
+/*
+ * 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.
+ */
+
+#include "dev/io_device.hh"
+#include "sim/builder.hh"
+
+
+PioPort::PioPort(PioDevice *dev, Platform *p)
+ : Port(dev->name() + "-pioport"), 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))
+ return;
+
+ port->transmitList.push_back(packet);
+}
+
+
+bool
+PioPort::recvTiming(Packet *pkt)
+{
+ device->recvAtomic(pkt);
+ // turn packet around to go back to requester
+ pkt->makeTimingResponse();
+ sendTiming(pkt, pkt->time - pkt->req->getTime());
+ return true;
+}
+
+PioDevice::~PioDevice()
+{
+ if (pioPort)
+ delete pioPort;
+}
+
+void
+PioDevice::init()
+{
+ if (!pioPort)
+ panic("Pio port not connected to anything!");
+ pioPort->sendStatusChange(Port::RangeChange);
+}
+
+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)
+ : Port(dev->name() + "-dmaport"), device(dev), platform(p), pendingCount(0)
+{ }
+
+bool
+DmaPort::recvTiming(Packet *pkt)
+{
+ if (pkt->senderState) {
+ DmaReqState *state;
+ state = dynamic_cast<DmaReqState*>(pkt->senderState);
+ state->completionEvent->schedule(pkt->time - pkt->req->getTime());
+ delete pkt->req;
+ delete pkt;
+ } else {
+ delete pkt->req;
+ delete pkt;
+ }
+
+ return Packet::Success;
+}
+
+DmaDevice::DmaDevice(Params *p)
+ : PioDevice(p), dmaPort(NULL)
+{ }
+
+void
+DmaPort::SendEvent::process()
+{
+ if (port->Port::sendTiming(packet))
+ return;
+
+ port->transmitList.push_back(packet);
+}
+
+Packet *
+DmaPort::recvRetry()
+{
+ Packet* pkt = transmitList.front();
+ transmitList.pop_front();
+ return pkt;
+}
+
+
+void
+DmaPort::dmaAction(Packet::Command cmd, Addr addr, int size, Event *event,
+ uint8_t *data)
+{
+ assert(event);
+
+ int prevSize = 0;
+
+ for (ChunkGenerator gen(addr, size, peerBlockSize());
+ !gen.done(); gen.next()) {
+ Request *req = new Request(false);
+ req->setPaddr(gen.addr());
+ req->setSize(gen.size());
+ req->setTime(curTick);
+ Packet *pkt = new Packet(req, cmd, Packet::Broadcast);
+
+ // Increment the data pointer on a write
+ if (data)
+ pkt->dataStatic(data + prevSize) ;
+
+ prevSize += gen.size();
+
+ // Set the last bit of the dma as the final packet for this dma
+ // and set it's completion event.
+ if (prevSize == size) {
+ pkt->senderState = new DmaReqState(event, true);
+ }
+ assert(pendingCount >= 0);
+ pendingCount++;
+ sendDma(pkt);
+ }
+}
+
+
+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))
+ transmitList.push_back(&packet);
+ } else if (state == Atomic) {*/
+ sendAtomic(pkt);
+ if (pkt->senderState) {
+ DmaReqState *state = dynamic_cast<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 (dmaPort)
+ delete dmaPort;
+}
+
+
diff --git a/src/dev/io_device.hh b/src/dev/io_device.hh
new file mode 100644
index 000000000..74730ad92
--- /dev/null
+++ b/src/dev/io_device.hh
@@ -0,0 +1,335 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __DEV_IO_DEVICE_HH__
+#define __DEV_IO_DEVICE_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 Platform;
+class PioDevice;
+class DmaDevice;
+class System;
+
+/**
+ * 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), port(p), 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 : public Packet::SenderState
+{
+ 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;
+
+ /** 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:
+ DmaPort(DmaDevice *dev, Platform *p);
+
+ void dmaAction(Packet::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->isRead() ? 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:
+ DmaPort *dmaPort;
+
+ public:
+ DmaDevice(Params *p);
+ virtual ~DmaDevice();
+
+ void dmaWrite(Addr addr, int size, Event *event, uint8_t *data)
+ { dmaPort->dmaAction(Packet::WriteReq, addr, size, event, data) ; }
+
+ void dmaRead(Addr addr, int size, Event *event, uint8_t *data = NULL)
+ { dmaPort->dmaAction(Packet::ReadReq, 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/src/dev/isa_fake.cc b/src/dev/isa_fake.cc
new file mode 100644
index 000000000..c303ffc30
--- /dev/null
+++ b/src/dev/isa_fake.cc
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file
+ * Isa Fake Device implementation
+ */
+
+#include <deque>
+#include <string>
+#include <vector>
+
+#include "base/trace.hh"
+#include "dev/isa_fake.hh"
+#include "mem/packet.hh"
+#include "sim/builder.hh"
+#include "sim/system.hh"
+
+using namespace std;
+
+IsaFake::IsaFake(Params *p)
+ : BasicPioDevice(p)
+{
+ pioSize = p->pio_size;
+}
+
+Tick
+IsaFake::read(Packet *pkt)
+{
+ assert(pkt->result == Packet::Unknown);
+ assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
+
+ pkt->time += pioDelay;
+
+ DPRINTF(Tsunami, "read va=%#x size=%d\n", pkt->getAddr(), pkt->getSize());
+
+ switch (pkt->getSize()) {
+ pkt->set(0xFFFFFFFFFFFFFFFFULL);
+ break;
+ case sizeof(uint32_t):
+ pkt->set((uint32_t)0xFFFFFFFF);
+ break;
+ case sizeof(uint16_t):
+ pkt->set((uint16_t)0xFFFF);
+ break;
+ case sizeof(uint8_t):
+ pkt->set((uint8_t)0xFF);
+ break;
+ default:
+ panic("invalid access size(?) for PCI configspace!\n");
+ }
+ pkt->result = Packet::Success;
+ return pioDelay;
+}
+
+Tick
+IsaFake::write(Packet *pkt)
+{
+ pkt->time += pioDelay;
+ DPRINTF(Tsunami, "write - va=%#x size=%d \n", pkt->getAddr(), pkt->getSize());
+ pkt->result = Packet::Success;
+ return pioDelay;
+}
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(IsaFake)
+
+ Param<Addr> pio_addr;
+ Param<Tick> pio_latency;
+ Param<Addr> pio_size;
+ SimObjectParam<Platform *> platform;
+ SimObjectParam<System *> system;
+
+END_DECLARE_SIM_OBJECT_PARAMS(IsaFake)
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(IsaFake)
+
+ 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)
+{
+ 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/src/dev/isa_fake.hh b/src/dev/isa_fake.hh
new file mode 100644
index 000000000..65d44f6a5
--- /dev/null
+++ b/src/dev/isa_fake.hh
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file
+ * Declaration of a fake device.
+ */
+
+#ifndef __ISA_FAKE_HH__
+#define __ISA_FAKE_HH__
+
+#include "dev/tsunami.hh"
+#include "base/range.hh"
+#include "dev/io_device.hh"
+
+/**
+ * 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 BasicPioDevice
+{
+ 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 p params structure
+ */
+ IsaFake(Params *p);
+
+ /**
+ * This read always returns -1.
+ * @param req The memory request.
+ * @param data Where to put the data.
+ */
+ virtual Tick read(Packet *pkt);
+
+ /**
+ * All writes are simply ignored.
+ * @param req The memory request.
+ * @param data the data to not write.
+ */
+ virtual Tick write(Packet *pkt);
+};
+
+#endif // __TSUNAMI_FAKE_HH__
diff --git a/src/dev/ns_gige.cc b/src/dev/ns_gige.cc
new file mode 100644
index 000000000..963675847
--- /dev/null
+++ b/src/dev/ns_gige.cc
@@ -0,0 +1,2914 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file
+ * Device module for modelling the National Semiconductor
+ * DP83820 ethernet controller. Does not support priority queueing
+ */
+#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/packet.hh"
+#include "sim/builder.hh"
+#include "sim/debug.hh"
+#include "sim/host.hh"
+#include "sim/stats.hh"
+#include "sim/system.hh"
+
+const char *NsRxStateStrings[] =
+{
+ "rxIdle",
+ "rxDescRefr",
+ "rxDescRead",
+ "rxFifoBlock",
+ "rxFragWrite",
+ "rxDescWrite",
+ "rxAdvance"
+};
+
+const char *NsTxStateStrings[] =
+{
+ "txIdle",
+ "txDescRefr",
+ "txDescRead",
+ "txFifoBlock",
+ "txFragRead",
+ "txDescWrite",
+ "txAdvance"
+};
+
+const char *NsDmaState[] =
+{
+ "dmaIdle",
+ "dmaReading",
+ "dmaWriting",
+ "dmaReadWaiting",
+ "dmaWriteWaiting"
+};
+
+using namespace std;
+using namespace Net;
+using namespace TheISA;
+
+///////////////////////////////////////////////////////////////////////
+//
+// NSGigE PCI Device
+//
+NSGigE::NSGigE(Params *p)
+ : PciDev(p), ioEnable(false),
+ txFifo(p->tx_fifo_size), rxFifo(p->rx_fifo_size),
+ txPacket(0), rxPacket(0), txPacketBufPtr(NULL), rxPacketBufPtr(NULL),
+ txXferLen(0), rxXferLen(0), clock(p->clock),
+ txState(txIdle), txEnable(false), CTDD(false),
+ txFragPtr(0), txDescCnt(0), txDmaState(dmaIdle), rxState(rxIdle),
+ rxEnable(false), CRDD(false), rxPktBytes(0),
+ rxFragPtr(0), rxDescCnt(0), rxDmaState(dmaIdle), extstsEnable(false),
+ eepromState(eepromStart), rxDmaReadEvent(this), rxDmaWriteEvent(this),
+ txDmaReadEvent(this), txDmaWriteEvent(this),
+ dmaDescFree(p->dma_desc_free), dmaDataFree(p->dma_data_free),
+ txDelay(p->tx_delay), rxDelay(p->rx_delay),
+ rxKickTick(0), rxKickEvent(this), txKickTick(0), txKickEvent(this),
+ txEvent(this), rxFilterEnable(p->rx_filter), acceptBroadcast(false),
+ acceptMulticast(false), acceptUnicast(false),
+ acceptPerfect(false), acceptArp(false), multicastHashEnable(false),
+ intrTick(0), cpuPendingIntr(false),
+ intrEvent(0), interface(0)
+{
+
+ intrDelay = p->intr_delay;
+ dmaReadDelay = p->dma_read_delay;
+ dmaWriteDelay = p->dma_write_delay;
+ dmaReadFactor = p->dma_read_factor;
+ dmaWriteFactor = p->dma_write_factor;
+
+ regsReset();
+ memcpy(&rom.perfectMatch, p->eaddr.bytes(), ETH_ADDR_LEN);
+
+ memset(&rxDesc32, 0, sizeof(rxDesc32));
+ memset(&txDesc32, 0, sizeof(txDesc32));
+ memset(&rxDesc64, 0, sizeof(rxDesc64));
+ memset(&txDesc64, 0, sizeof(txDesc64));
+}
+
+NSGigE::~NSGigE()
+{}
+
+void
+NSGigE::regStats()
+{
+ txBytes
+ .name(name() + ".txBytes")
+ .desc("Bytes Transmitted")
+ .prereq(txBytes)
+ ;
+
+ rxBytes
+ .name(name() + ".rxBytes")
+ .desc("Bytes Received")
+ .prereq(rxBytes)
+ ;
+
+ txPackets
+ .name(name() + ".txPackets")
+ .desc("Number of Packets Transmitted")
+ .prereq(txBytes)
+ ;
+
+ rxPackets
+ .name(name() + ".rxPackets")
+ .desc("Number of Packets Received")
+ .prereq(rxBytes)
+ ;
+
+ txIpChecksums
+ .name(name() + ".txIpChecksums")
+ .desc("Number of tx IP Checksums done by device")
+ .precision(0)
+ .prereq(txBytes)
+ ;
+
+ rxIpChecksums
+ .name(name() + ".rxIpChecksums")
+ .desc("Number of rx IP Checksums done by device")
+ .precision(0)
+ .prereq(rxBytes)
+ ;
+
+ txTcpChecksums
+ .name(name() + ".txTcpChecksums")
+ .desc("Number of tx TCP Checksums done by device")
+ .precision(0)
+ .prereq(txBytes)
+ ;
+
+ rxTcpChecksums
+ .name(name() + ".rxTcpChecksums")
+ .desc("Number of rx TCP Checksums done by device")
+ .precision(0)
+ .prereq(rxBytes)
+ ;
+
+ txUdpChecksums
+ .name(name() + ".txUdpChecksums")
+ .desc("Number of tx UDP Checksums done by device")
+ .precision(0)
+ .prereq(txBytes)
+ ;
+
+ rxUdpChecksums
+ .name(name() + ".rxUdpChecksums")
+ .desc("Number of rx UDP Checksums done by device")
+ .precision(0)
+ .prereq(rxBytes)
+ ;
+
+ descDmaReads
+ .name(name() + ".descDMAReads")
+ .desc("Number of descriptors the device read w/ DMA")
+ .precision(0)
+ ;
+
+ descDmaWrites
+ .name(name() + ".descDMAWrites")
+ .desc("Number of descriptors the device wrote w/ DMA")
+ .precision(0)
+ ;
+
+ descDmaRdBytes
+ .name(name() + ".descDmaReadBytes")
+ .desc("number of descriptor bytes read w/ DMA")
+ .precision(0)
+ ;
+
+ descDmaWrBytes
+ .name(name() + ".descDmaWriteBytes")
+ .desc("number of descriptor bytes write w/ DMA")
+ .precision(0)
+ ;
+
+ txBandwidth
+ .name(name() + ".txBandwidth")
+ .desc("Transmit Bandwidth (bits/s)")
+ .precision(0)
+ .prereq(txBytes)
+ ;
+
+ rxBandwidth
+ .name(name() + ".rxBandwidth")
+ .desc("Receive Bandwidth (bits/s)")
+ .precision(0)
+ .prereq(rxBytes)
+ ;
+
+ totBandwidth
+ .name(name() + ".totBandwidth")
+ .desc("Total Bandwidth (bits/s)")
+ .precision(0)
+ .prereq(totBytes)
+ ;
+
+ totPackets
+ .name(name() + ".totPackets")
+ .desc("Total Packets")
+ .precision(0)
+ .prereq(totBytes)
+ ;
+
+ totBytes
+ .name(name() + ".totBytes")
+ .desc("Total Bytes")
+ .precision(0)
+ .prereq(totBytes)
+ ;
+
+ totPacketRate
+ .name(name() + ".totPPS")
+ .desc("Total Tranmission Rate (packets/s)")
+ .precision(0)
+ .prereq(totBytes)
+ ;
+
+ txPacketRate
+ .name(name() + ".txPPS")
+ .desc("Packet Tranmission Rate (packets/s)")
+ .precision(0)
+ .prereq(txBytes)
+ ;
+
+ rxPacketRate
+ .name(name() + ".rxPPS")
+ .desc("Packet Reception Rate (packets/s)")
+ .precision(0)
+ .prereq(rxBytes)
+ ;
+
+ postedSwi
+ .name(name() + ".postedSwi")
+ .desc("number of software interrupts posted to CPU")
+ .precision(0)
+ ;
+
+ totalSwi
+ .name(name() + ".totalSwi")
+ .desc("total number of Swi written to ISR")
+ .precision(0)
+ ;
+
+ coalescedSwi
+ .name(name() + ".coalescedSwi")
+ .desc("average number of Swi's coalesced into each post")
+ .precision(0)
+ ;
+
+ postedRxIdle
+ .name(name() + ".postedRxIdle")
+ .desc("number of rxIdle interrupts posted to CPU")
+ .precision(0)
+ ;
+
+ totalRxIdle
+ .name(name() + ".totalRxIdle")
+ .desc("total number of RxIdle written to ISR")
+ .precision(0)
+ ;
+
+ coalescedRxIdle
+ .name(name() + ".coalescedRxIdle")
+ .desc("average number of RxIdle's coalesced into each post")
+ .precision(0)
+ ;
+
+ postedRxOk
+ .name(name() + ".postedRxOk")
+ .desc("number of RxOk interrupts posted to CPU")
+ .precision(0)
+ ;
+
+ totalRxOk
+ .name(name() + ".totalRxOk")
+ .desc("total number of RxOk written to ISR")
+ .precision(0)
+ ;
+
+ coalescedRxOk
+ .name(name() + ".coalescedRxOk")
+ .desc("average number of RxOk's coalesced into each post")
+ .precision(0)
+ ;
+
+ postedRxDesc
+ .name(name() + ".postedRxDesc")
+ .desc("number of RxDesc interrupts posted to CPU")
+ .precision(0)
+ ;
+
+ totalRxDesc
+ .name(name() + ".totalRxDesc")
+ .desc("total number of RxDesc written to ISR")
+ .precision(0)
+ ;
+
+ coalescedRxDesc
+ .name(name() + ".coalescedRxDesc")
+ .desc("average number of RxDesc's coalesced into each post")
+ .precision(0)
+ ;
+
+ postedTxOk
+ .name(name() + ".postedTxOk")
+ .desc("number of TxOk interrupts posted to CPU")
+ .precision(0)
+ ;
+
+ totalTxOk
+ .name(name() + ".totalTxOk")
+ .desc("total number of TxOk written to ISR")
+ .precision(0)
+ ;
+
+ coalescedTxOk
+ .name(name() + ".coalescedTxOk")
+ .desc("average number of TxOk's coalesced into each post")
+ .precision(0)
+ ;
+
+ postedTxIdle
+ .name(name() + ".postedTxIdle")
+ .desc("number of TxIdle interrupts posted to CPU")
+ .precision(0)
+ ;
+
+ totalTxIdle
+ .name(name() + ".totalTxIdle")
+ .desc("total number of TxIdle written to ISR")
+ .precision(0)
+ ;
+
+ coalescedTxIdle
+ .name(name() + ".coalescedTxIdle")
+ .desc("average number of TxIdle's coalesced into each post")
+ .precision(0)
+ ;
+
+ postedTxDesc
+ .name(name() + ".postedTxDesc")
+ .desc("number of TxDesc interrupts posted to CPU")
+ .precision(0)
+ ;
+
+ totalTxDesc
+ .name(name() + ".totalTxDesc")
+ .desc("total number of TxDesc written to ISR")
+ .precision(0)
+ ;
+
+ coalescedTxDesc
+ .name(name() + ".coalescedTxDesc")
+ .desc("average number of TxDesc's coalesced into each post")
+ .precision(0)
+ ;
+
+ postedRxOrn
+ .name(name() + ".postedRxOrn")
+ .desc("number of RxOrn posted to CPU")
+ .precision(0)
+ ;
+
+ totalRxOrn
+ .name(name() + ".totalRxOrn")
+ .desc("total number of RxOrn written to ISR")
+ .precision(0)
+ ;
+
+ coalescedRxOrn
+ .name(name() + ".coalescedRxOrn")
+ .desc("average number of RxOrn's coalesced into each post")
+ .precision(0)
+ ;
+
+ coalescedTotal
+ .name(name() + ".coalescedTotal")
+ .desc("average number of interrupts coalesced into each post")
+ .precision(0)
+ ;
+
+ postedInterrupts
+ .name(name() + ".postedInterrupts")
+ .desc("number of posts to CPU")
+ .precision(0)
+ ;
+
+ droppedPackets
+ .name(name() + ".droppedPackets")
+ .desc("number of packets dropped")
+ .precision(0)
+ ;
+
+ coalescedSwi = totalSwi / postedInterrupts;
+ coalescedRxIdle = totalRxIdle / postedInterrupts;
+ coalescedRxOk = totalRxOk / postedInterrupts;
+ coalescedRxDesc = totalRxDesc / postedInterrupts;
+ coalescedTxOk = totalTxOk / postedInterrupts;
+ coalescedTxIdle = totalTxIdle / postedInterrupts;
+ coalescedTxDesc = totalTxDesc / postedInterrupts;
+ coalescedRxOrn = totalRxOrn / postedInterrupts;
+
+ coalescedTotal = (totalSwi + totalRxIdle + totalRxOk + totalRxDesc +
+ totalTxOk + totalTxIdle + totalTxDesc +
+ totalRxOrn) / postedInterrupts;
+
+ txBandwidth = txBytes * Stats::constant(8) / simSeconds;
+ rxBandwidth = rxBytes * Stats::constant(8) / simSeconds;
+ totBandwidth = txBandwidth + rxBandwidth;
+ totBytes = txBytes + rxBytes;
+ totPackets = txPackets + rxPackets;
+
+ txPacketRate = txPackets / simSeconds;
+ rxPacketRate = rxPackets / simSeconds;
+}
+
+
+/**
+ * This is to write to the PCI general configuration registers
+ */
+void
+NSGigE::writeConfig(int offset, const uint16_t data)
+{
+ if (offset < PCI_DEVICE_SPECIFIC)
+ PciDev::writeConfig(offset, data);
+ else
+ panic("Device specific PCI config space not implemented!\n");
+
+ 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
+ // need to properly implement it
+ case PCI_COMMAND:
+ if (config.data[offset] & PCI_CMD_IOSE)
+ ioEnable = true;
+ else
+ ioEnable = false;
+ break;
+ }
+}
+
+/**
+ * This reads the device registers, which are detailed in the NS83820
+ * spec sheet
+ */
+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 = pkt->getAddr() & 0xfff;
+ DPRINTF(EthernetPIO, "read da=%#x pa=%#x size=%d\n",
+ daddr, pkt->getAddr(), pkt->getSize());
+
+
+ // there are some reserved registers, you can see ns_gige_reg.h and
+ // the spec sheet for details
+ if (daddr > LAST && daddr <= RESERVED) {
+ panic("Accessing reserved register");
+ } else if (daddr > RESERVED && daddr <= 0x3FC) {
+ if (pkt->getSize() == sizeof(uint8_t))
+ readConfig(daddr & 0xff, pkt->getPtr<uint8_t>());
+ if (pkt->getSize() == sizeof(uint16_t))
+ readConfig(daddr & 0xff, pkt->getPtr<uint16_t>());
+ if (pkt->getSize() == sizeof(uint32_t))
+ readConfig(daddr & 0xff, pkt->getPtr<uint32_t>());
+ pkt->result = Packet::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
+ pkt->set<uint32_t>(0);
+ pkt->result = Packet::Success;
+ return pioDelay;
+ } else if (daddr > 0x3FC)
+ panic("Something is messed up!\n");
+
+ assert(pkt->getSize() == sizeof(uint32_t));
+ uint32_t &reg = *pkt->getPtr<uint32_t>();
+ 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;
+
+ case CFGR:
+ reg = regs.config;
+ break;
+
+ case MEAR:
+ reg = regs.mear;
+ break;
+
+ case PTSCR:
+ reg = regs.ptscr;
+ break;
+
+ case ISR:
+ reg = regs.isr;
+ devIntrClear(ISR_ALL);
+ break;
+
+ case IMR:
+ reg = regs.imr;
+ break;
+
+ case IER:
+ reg = regs.ier;
+ break;
+
+ case IHR:
+ reg = regs.ihr;
+ break;
+
+ case TXDP:
+ reg = regs.txdp;
+ break;
+
+ case TXDP_HI:
+ reg = regs.txdp_hi;
+ break;
+
+ case TX_CFG:
+ reg = regs.txcfg;
+ break;
+
+ case GPIOR:
+ reg = regs.gpior;
+ break;
+
+ case RXDP:
+ reg = regs.rxdp;
+ break;
+
+ case RXDP_HI:
+ reg = regs.rxdp_hi;
+ break;
+
+ case RX_CFG:
+ reg = regs.rxcfg;
+ break;
+
+ case PQCR:
+ reg = regs.pqcr;
+ 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;
+
+ 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;
+ }
+
+ panic("reading RFDR for something other than pattern"
+ " matching or hashing! %#x\n", rfaddr);
+ }
+ break;
+
+ case SRR:
+ reg = regs.srr;
+ break;
+
+ case MIBC:
+ reg = regs.mibc;
+ reg &= ~(MIBC_MIBS | MIBC_ACLR);
+ break;
+
+ case VRCR:
+ reg = regs.vrcr;
+ break;
+
+ case VTCR:
+ reg = regs.vtcr;
+ break;
+
+ case VDR:
+ reg = regs.vdr;
+ break;
+
+ case CCSR:
+ reg = regs.ccsr;
+ break;
+
+ case TBICR:
+ reg = regs.tbicr;
+ break;
+
+ case TBISR:
+ reg = regs.tbisr;
+ break;
+
+ case TANAR:
+ reg = regs.tanar;
+ break;
+
+ case TANLPAR:
+ reg = regs.tanlpar;
+ break;
+
+ case TANER:
+ reg = regs.taner;
+ break;
+
+ case TESR:
+ reg = regs.tesr;
+ 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;
+
+ default:
+ panic("reading unimplemented register: addr=%#x", daddr);
+ }
+
+ DPRINTF(EthernetPIO, "read from %#x: data=%d data=%#x\n",
+ daddr, reg, reg);
+
+ pkt->result = Packet::Success;
+ return pioDelay;
+}
+
+Tick
+NSGigE::write(Packet *pkt)
+{
+ assert(ioEnable);
+
+ Addr daddr = pkt->getAddr() & 0xfff;
+ DPRINTF(EthernetPIO, "write da=%#x pa=%#x size=%d\n",
+ daddr, pkt->getAddr(), pkt->getSize());
+
+ pkt->time += pioDelay;
+
+ if (daddr > LAST && daddr <= RESERVED) {
+ panic("Accessing reserved register");
+ } else if (daddr > RESERVED && daddr <= 0x3FC) {
+ if (pkt->getSize() == sizeof(uint8_t))
+ writeConfig(daddr & 0xff, pkt->get<uint8_t>());
+ if (pkt->getSize() == sizeof(uint16_t))
+ writeConfig(daddr & 0xff, pkt->get<uint16_t>());
+ if (pkt->getSize() == sizeof(uint32_t))
+ writeConfig(daddr & 0xff, pkt->get<uint32_t>());
+ pkt->result = Packet::Success;
+ return pioDelay;
+ } else if (daddr > 0x3FC)
+ panic("Something is messed up!\n");
+
+ if (pkt->getSize() == sizeof(uint32_t)) {
+ uint32_t reg = pkt->get<uint32_t>();
+ uint16_t rfaddr;
+
+ DPRINTF(EthernetPIO, "write data=%d data=%#x\n", reg, reg);
+
+ switch (daddr) {
+ case CR:
+ regs.command = reg;
+ if (reg & CR_TXD) {
+ txEnable = false;
+ } else if (reg & CR_TXE) {
+ txEnable = true;
+
+ // the kernel is enabling the transmit machine
+ if (txState == txIdle)
+ txKick();
+ }
+
+ if (reg & CR_RXD) {
+ rxEnable = false;
+ } else if (reg & CR_RXE) {
+ rxEnable = true;
+
+ if (rxState == rxIdle)
+ rxKick();
+ }
+
+ if (reg & CR_TXR)
+ txReset();
+
+ if (reg & CR_RXR)
+ rxReset();
+
+ if (reg & CR_SWI)
+ devIntrPost(ISR_SWI);
+
+ if (reg & CR_RST) {
+ txReset();
+ rxReset();
+
+ regsReset();
+ }
+ break;
+
+ case CFGR:
+ if (reg & CFGR_LNKSTS ||
+ reg & CFGR_SPDSTS ||
+ reg & CFGR_DUPSTS ||
+ reg & CFGR_RESERVED ||
+ reg & CFGR_T64ADDR ||
+ reg & CFGR_PCI64_DET)
+
+ // First clear all writable bits
+ regs.config &= CFGR_LNKSTS | CFGR_SPDSTS | CFGR_DUPSTS |
+ CFGR_RESERVED | CFGR_T64ADDR |
+ CFGR_PCI64_DET;
+ // Now set the appropriate writable bits
+ regs.config |= reg & ~(CFGR_LNKSTS | CFGR_SPDSTS | CFGR_DUPSTS |
+ CFGR_RESERVED | CFGR_T64ADDR |
+ CFGR_PCI64_DET);
+
+// all these #if 0's are because i don't THINK the kernel needs to
+// have these implemented. if there is a problem relating to one of
+// these, you may need to add functionality in.
+ if (reg & CFGR_TBI_EN) ;
+ if (reg & CFGR_MODE_1000) ;
+
+ if (reg & CFGR_AUTO_1000)
+ panic("CFGR_AUTO_1000 not implemented!\n");
+
+ if (reg & CFGR_PINT_DUPSTS ||
+ reg & CFGR_PINT_LNKSTS ||
+ reg & CFGR_PINT_SPDSTS)
+ ;
+
+ if (reg & CFGR_TMRTEST) ;
+ if (reg & CFGR_MRM_DIS) ;
+ if (reg & CFGR_MWI_DIS) ;
+
+ if (reg & CFGR_T64ADDR) ;
+ // panic("CFGR_T64ADDR is read only register!\n");
+
+ if (reg & CFGR_PCI64_DET)
+ panic("CFGR_PCI64_DET is read only register!\n");
+
+ if (reg & CFGR_DATA64_EN) ;
+ if (reg & CFGR_M64ADDR) ;
+ if (reg & CFGR_PHY_RST) ;
+ if (reg & CFGR_PHY_DIS) ;
+
+ if (reg & CFGR_EXTSTS_EN)
+ extstsEnable = true;
+ else
+ extstsEnable = false;
+
+ if (reg & CFGR_REQALG) ;
+ if (reg & CFGR_SB) ;
+ if (reg & CFGR_POW) ;
+ if (reg & CFGR_EXD) ;
+ if (reg & CFGR_PESEL) ;
+ if (reg & CFGR_BROM_DIS) ;
+ if (reg & CFGR_EXT_125) ;
+ if (reg & CFGR_BEM) ;
+ break;
+
+ case MEAR:
+ // Clear writable bits
+ regs.mear &= MEAR_EEDO;
+ // Set appropriate writable bits
+ regs.mear |= reg & ~MEAR_EEDO;
+
+ // FreeBSD uses the EEPROM to read PMATCH (for the MAC address)
+ // even though it could get it through RFDR
+ if (reg & MEAR_EESEL) {
+ // Rising edge of clock
+ if (reg & MEAR_EECLK && !eepromClk)
+ eepromKick();
+ }
+ else {
+ eepromState = eepromStart;
+ regs.mear &= ~MEAR_EEDI;
+ }
+
+ eepromClk = reg & MEAR_EECLK;
+
+ // since phy is completely faked, MEAR_MD* don't matter
+ if (reg & MEAR_MDIO) ;
+ if (reg & MEAR_MDDIR) ;
+ if (reg & MEAR_MDC) ;
+ break;
+
+ case PTSCR:
+ regs.ptscr = reg & ~(PTSCR_RBIST_RDONLY);
+ // these control BISTs for various parts of chip - we
+ // don't care or do just fake that the BIST is done
+ if (reg & PTSCR_RBIST_EN)
+ regs.ptscr |= PTSCR_RBIST_DONE;
+ if (reg & PTSCR_EEBIST_EN)
+ regs.ptscr &= ~PTSCR_EEBIST_EN;
+ if (reg & PTSCR_EELOAD_EN)
+ regs.ptscr &= ~PTSCR_EELOAD_EN;
+ break;
+
+ case ISR: /* writing to the ISR has no effect */
+ panic("ISR is a read only register!\n");
+
+ case IMR:
+ regs.imr = reg;
+ devIntrChangeMask();
+ break;
+
+ case IER:
+ regs.ier = reg;
+ break;
+
+ case IHR:
+ regs.ihr = reg;
+ /* not going to implement real interrupt holdoff */
+ break;
+
+ case TXDP:
+ regs.txdp = (reg & 0xFFFFFFFC);
+ assert(txState == txIdle);
+ CTDD = false;
+ break;
+
+ case TXDP_HI:
+ regs.txdp_hi = reg;
+ break;
+
+ case TX_CFG:
+ regs.txcfg = reg;
+#if 0
+ if (reg & TX_CFG_CSI) ;
+ if (reg & TX_CFG_HBI) ;
+ if (reg & TX_CFG_MLB) ;
+ if (reg & TX_CFG_ATP) ;
+ if (reg & TX_CFG_ECRETRY) {
+ /*
+ * this could easily be implemented, but considering
+ * the network is just a fake pipe, wouldn't make
+ * sense to do this
+ */
+ }
+
+ if (reg & TX_CFG_BRST_DIS) ;
+#endif
+
+#if 0
+ /* we handle our own DMA, ignore the kernel's exhortations */
+ if (reg & TX_CFG_MXDMA) ;
+#endif
+
+ // also, we currently don't care about fill/drain
+ // thresholds though this may change in the future with
+ // more realistic networks or a driver which changes it
+ // according to feedback
+
+ break;
+
+ case GPIOR:
+ // Only write writable bits
+ regs.gpior &= GPIOR_UNUSED | GPIOR_GP5_IN | GPIOR_GP4_IN
+ | GPIOR_GP3_IN | GPIOR_GP2_IN | GPIOR_GP1_IN;
+ regs.gpior |= reg & ~(GPIOR_UNUSED | GPIOR_GP5_IN | GPIOR_GP4_IN
+ | GPIOR_GP3_IN | GPIOR_GP2_IN | GPIOR_GP1_IN);
+ /* these just control general purpose i/o pins, don't matter */
+ break;
+
+ case RXDP:
+ regs.rxdp = reg;
+ CRDD = false;
+ break;
+
+ case RXDP_HI:
+ regs.rxdp_hi = reg;
+ break;
+
+ case RX_CFG:
+ regs.rxcfg = reg;
+#if 0
+ if (reg & RX_CFG_AEP) ;
+ if (reg & RX_CFG_ARP) ;
+ if (reg & RX_CFG_STRIPCRC) ;
+ if (reg & RX_CFG_RX_RD) ;
+ if (reg & RX_CFG_ALP) ;
+ if (reg & RX_CFG_AIRL) ;
+
+ /* we handle our own DMA, ignore what kernel says about it */
+ if (reg & RX_CFG_MXDMA) ;
+
+ //also, we currently don't care about fill/drain thresholds
+ //though this may change in the future with more realistic
+ //networks or a driver which changes it according to feedback
+ if (reg & (RX_CFG_DRTH | RX_CFG_DRTH0)) ;
+#endif
+ break;
+
+ case PQCR:
+ /* there is no priority queueing used in the linux 2.6 driver */
+ regs.pqcr = reg;
+ break;
+
+ case WCSR:
+ /* not going to implement wake on LAN */
+ regs.wcsr = reg;
+ break;
+
+ case PCR:
+ /* not going to implement pause control */
+ regs.pcr = reg;
+ break;
+
+ case RFCR:
+ regs.rfcr = reg;
+
+ rxFilterEnable = (reg & RFCR_RFEN) ? true : false;
+ acceptBroadcast = (reg & RFCR_AAB) ? true : false;
+ acceptMulticast = (reg & RFCR_AAM) ? true : false;
+ acceptUnicast = (reg & RFCR_AAU) ? true : false;
+ acceptPerfect = (reg & RFCR_APM) ? true : false;
+ acceptArp = (reg & RFCR_AARP) ? true : false;
+ multicastHashEnable = (reg & RFCR_MHEN) ? true : false;
+
+#if 0
+ if (reg & RFCR_APAT)
+ panic("RFCR_APAT not implemented!\n");
+#endif
+ if (reg & RFCR_UHEN)
+ panic("Unicast hash filtering not used by drivers!\n");
+
+ if (reg & RFCR_ULM)
+ panic("RFCR_ULM not implemented!\n");
+
+ break;
+
+ case RFDR:
+ rfaddr = (uint16_t)(regs.rfcr & RFCR_RFADDR);
+ switch (rfaddr) {
+ case 0x000:
+ rom.perfectMatch[0] = (uint8_t)reg;
+ rom.perfectMatch[1] = (uint8_t)(reg >> 8);
+ break;
+ case 0x002:
+ rom.perfectMatch[2] = (uint8_t)reg;
+ rom.perfectMatch[3] = (uint8_t)(reg >> 8);
+ break;
+ case 0x004:
+ rom.perfectMatch[4] = (uint8_t)reg;
+ rom.perfectMatch[5] = (uint8_t)(reg >> 8);
+ break;
+ default:
+
+ if (rfaddr >= FHASH_ADDR &&
+ rfaddr < FHASH_ADDR + FHASH_SIZE) {
+
+ // Only word-aligned writes supported
+ if (rfaddr % 2)
+ panic("unaligned write to filter hash table!");
+
+ rom.filterHash[rfaddr - FHASH_ADDR] = (uint8_t)reg;
+ rom.filterHash[rfaddr - FHASH_ADDR + 1]
+ = (uint8_t)(reg >> 8);
+ break;
+ }
+ panic("writing RFDR for something other than pattern matching\
+ or hashing! %#x\n", rfaddr);
+ }
+
+ case BRAR:
+ regs.brar = reg;
+ break;
+
+ case BRDR:
+ panic("the driver never uses BRDR, something is wrong!\n");
+
+ case SRR:
+ panic("SRR is read only register!\n");
+
+ case MIBC:
+ panic("the driver never uses MIBC, something is wrong!\n");
+
+ case VRCR:
+ regs.vrcr = reg;
+ break;
+
+ case VTCR:
+ regs.vtcr = reg;
+ break;
+
+ case VDR:
+ panic("the driver never uses VDR, something is wrong!\n");
+
+ case CCSR:
+ /* not going to implement clockrun stuff */
+ regs.ccsr = reg;
+ break;
+
+ case TBICR:
+ regs.tbicr = reg;
+ if (reg & TBICR_MR_LOOPBACK)
+ panic("TBICR_MR_LOOPBACK never used, something wrong!\n");
+
+ if (reg & TBICR_MR_AN_ENABLE) {
+ regs.tanlpar = regs.tanar;
+ regs.tbisr |= (TBISR_MR_AN_COMPLETE | TBISR_MR_LINK_STATUS);
+ }
+
+#if 0
+ if (reg & TBICR_MR_RESTART_AN) ;
+#endif
+
+ break;
+
+ case TBISR:
+ panic("TBISR is read only register!\n");
+
+ case TANAR:
+ // Only write the writable bits
+ regs.tanar &= TANAR_RF1 | TANAR_RF2 | TANAR_UNUSED;
+ regs.tanar |= reg & ~(TANAR_RF1 | TANAR_RF2 | TANAR_UNUSED);
+
+ // Pause capability unimplemented
+#if 0
+ if (reg & TANAR_PS2) ;
+ if (reg & TANAR_PS1) ;
+#endif
+
+ break;
+
+ case TANLPAR:
+ panic("this should only be written to by the fake phy!\n");
+
+ case TANER:
+ panic("TANER is read only register!\n");
+
+ case TESR:
+ regs.tesr = reg;
+ break;
+
+ default:
+ panic("invalid register access daddr=%#x", daddr);
+ }
+ } else {
+ panic("Invalid Request Size");
+ }
+ pkt->result = Packet::Success;
+ return pioDelay;
+}
+
+void
+NSGigE::devIntrPost(uint32_t interrupts)
+{
+ if (interrupts & ISR_RESERVE)
+ panic("Cannot set a reserved interrupt");
+
+ if (interrupts & ISR_NOIMPL)
+ warn("interrupt not implemented %#x\n", interrupts);
+
+ interrupts &= ISR_IMPL;
+ regs.isr |= interrupts;
+
+ if (interrupts & regs.imr) {
+ if (interrupts & ISR_SWI) {
+ totalSwi++;
+ }
+ if (interrupts & ISR_RXIDLE) {
+ totalRxIdle++;
+ }
+ if (interrupts & ISR_RXOK) {
+ totalRxOk++;
+ }
+ if (interrupts & ISR_RXDESC) {
+ totalRxDesc++;
+ }
+ if (interrupts & ISR_TXOK) {
+ totalTxOk++;
+ }
+ if (interrupts & ISR_TXIDLE) {
+ totalTxIdle++;
+ }
+ if (interrupts & ISR_TXDESC) {
+ totalTxDesc++;
+ }
+ if (interrupts & ISR_RXORN) {
+ totalRxOrn++;
+ }
+ }
+
+ DPRINTF(EthernetIntr,
+ "interrupt written to ISR: intr=%#x isr=%#x imr=%#x\n",
+ interrupts, regs.isr, regs.imr);
+
+ if ((regs.isr & regs.imr)) {
+ Tick when = curTick;
+ if ((regs.isr & regs.imr & ISR_NODELAY) == 0)
+ when += intrDelay;
+ cpuIntrPost(when);
+ }
+}
+
+/* writing this interrupt counting stats inside this means that this function
+ is now limited to being used to clear all interrupts upon the kernel
+ reading isr and servicing. just telling you in case you were thinking
+ of expanding use.
+*/
+void
+NSGigE::devIntrClear(uint32_t interrupts)
+{
+ if (interrupts & ISR_RESERVE)
+ panic("Cannot clear a reserved interrupt");
+
+ if (regs.isr & regs.imr & ISR_SWI) {
+ postedSwi++;
+ }
+ if (regs.isr & regs.imr & ISR_RXIDLE) {
+ postedRxIdle++;
+ }
+ if (regs.isr & regs.imr & ISR_RXOK) {
+ postedRxOk++;
+ }
+ if (regs.isr & regs.imr & ISR_RXDESC) {
+ postedRxDesc++;
+ }
+ if (regs.isr & regs.imr & ISR_TXOK) {
+ postedTxOk++;
+ }
+ if (regs.isr & regs.imr & ISR_TXIDLE) {
+ postedTxIdle++;
+ }
+ if (regs.isr & regs.imr & ISR_TXDESC) {
+ postedTxDesc++;
+ }
+ if (regs.isr & regs.imr & ISR_RXORN) {
+ postedRxOrn++;
+ }
+
+ if (regs.isr & regs.imr & ISR_IMPL)
+ postedInterrupts++;
+
+ interrupts &= ~ISR_NOIMPL;
+ regs.isr &= ~interrupts;
+
+ DPRINTF(EthernetIntr,
+ "interrupt cleared from ISR: intr=%x isr=%x imr=%x\n",
+ interrupts, regs.isr, regs.imr);
+
+ if (!(regs.isr & regs.imr))
+ cpuIntrClear();
+}
+
+void
+NSGigE::devIntrChangeMask()
+{
+ DPRINTF(EthernetIntr, "interrupt mask changed: isr=%x imr=%x masked=%x\n",
+ regs.isr, regs.imr, regs.isr & regs.imr);
+
+ if (regs.isr & regs.imr)
+ cpuIntrPost(curTick);
+ else
+ cpuIntrClear();
+}
+
+void
+NSGigE::cpuIntrPost(Tick when)
+{
+ // If the interrupt you want to post is later than an interrupt
+ // already scheduled, just let it post in the coming one and don't
+ // schedule another.
+ // HOWEVER, must be sure that the scheduled intrTick is in the
+ // future (this was formerly the source of a bug)
+ /**
+ * @todo this warning should be removed and the intrTick code should
+ * be fixed.
+ */
+ assert(when >= curTick);
+ assert(intrTick >= curTick || intrTick == 0);
+ if (when > intrTick && intrTick != 0) {
+ DPRINTF(EthernetIntr, "don't need to schedule event...intrTick=%d\n",
+ intrTick);
+ return;
+ }
+
+ intrTick = when;
+ if (intrTick < curTick) {
+ debug_break();
+ intrTick = curTick;
+ }
+
+ DPRINTF(EthernetIntr, "going to schedule an interrupt for intrTick=%d\n",
+ intrTick);
+
+ if (intrEvent)
+ intrEvent->squash();
+ intrEvent = new IntrEvent(this, true);
+ intrEvent->schedule(intrTick);
+}
+
+void
+NSGigE::cpuInterrupt()
+{
+ assert(intrTick == curTick);
+
+ // Whether or not there's a pending interrupt, we don't care about
+ // it anymore
+ intrEvent = 0;
+ intrTick = 0;
+
+ // Don't send an interrupt if there's already one
+ if (cpuPendingIntr) {
+ DPRINTF(EthernetIntr,
+ "would send an interrupt now, but there's already pending\n");
+ } else {
+ // Send interrupt
+ cpuPendingIntr = true;
+
+ DPRINTF(EthernetIntr, "posting interrupt\n");
+ intrPost();
+ }
+}
+
+void
+NSGigE::cpuIntrClear()
+{
+ if (!cpuPendingIntr)
+ return;
+
+ if (intrEvent) {
+ intrEvent->squash();
+ intrEvent = 0;
+ }
+
+ intrTick = 0;
+
+ cpuPendingIntr = false;
+
+ DPRINTF(EthernetIntr, "clearing interrupt\n");
+ intrClear();
+}
+
+bool
+NSGigE::cpuIntrPending() const
+{ return cpuPendingIntr; }
+
+void
+NSGigE::txReset()
+{
+
+ DPRINTF(Ethernet, "transmit reset\n");
+
+ CTDD = false;
+ txEnable = false;;
+ txFragPtr = 0;
+ assert(txDescCnt == 0);
+ txFifo.clear();
+ txState = txIdle;
+ assert(txDmaState == dmaIdle);
+}
+
+void
+NSGigE::rxReset()
+{
+ DPRINTF(Ethernet, "receive reset\n");
+
+ CRDD = false;
+ assert(rxPktBytes == 0);
+ rxEnable = false;
+ rxFragPtr = 0;
+ assert(rxDescCnt == 0);
+ assert(rxDmaState == dmaIdle);
+ rxFifo.clear();
+ rxState = rxIdle;
+}
+
+void
+NSGigE::regsReset()
+{
+ memset(&regs, 0, sizeof(regs));
+ regs.config = (CFGR_LNKSTS | CFGR_TBI_EN | CFGR_MODE_1000);
+ regs.mear = 0x12;
+ regs.txcfg = 0x120; // set drain threshold to 1024 bytes and
+ // fill threshold to 32 bytes
+ regs.rxcfg = 0x4; // set drain threshold to 16 bytes
+ regs.srr = 0x0103; // set the silicon revision to rev B or 0x103
+ regs.mibc = MIBC_FRZ;
+ regs.vdr = 0x81; // set the vlan tag type to 802.1q
+ regs.tesr = 0xc000; // TBI capable of both full and half duplex
+ regs.brar = 0xffffffff;
+
+ extstsEnable = false;
+ acceptBroadcast = false;
+ acceptMulticast = false;
+ acceptUnicast = false;
+ acceptPerfect = false;
+ acceptArp = false;
+}
+
+bool
+NSGigE::doRxDmaRead()
+{
+ assert(rxDmaState == dmaIdle || rxDmaState == dmaReadWaiting);
+ rxDmaState = dmaReading;
+
+ if (dmaPending())
+ rxDmaState = dmaReadWaiting;
+ else
+ dmaRead(rxDmaAddr, rxDmaLen, &rxDmaReadEvent, (uint8_t*)rxDmaData);
+
+ return true;
+}
+
+void
+NSGigE::rxDmaReadDone()
+{
+ assert(rxDmaState == dmaReading);
+ 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)
+ txKick();
+
+ rxKick();
+}
+
+bool
+NSGigE::doRxDmaWrite()
+{
+ assert(rxDmaState == dmaIdle || rxDmaState == dmaWriteWaiting);
+ rxDmaState = dmaWriting;
+
+ if (dmaPending())
+ rxDmaState = dmaWriteWaiting;
+ else
+ dmaWrite(rxDmaAddr, rxDmaLen, &rxDmaWriteEvent, (uint8_t*)rxDmaData);
+ return true;
+}
+
+void
+NSGigE::rxDmaWriteDone()
+{
+ assert(rxDmaState == dmaWriting);
+ 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)
+ txKick();
+
+ rxKick();
+}
+
+void
+NSGigE::rxKick()
+{
+ bool is64bit = (bool)(regs.config & CFGR_M64ADDR);
+
+ DPRINTF(EthernetSM,
+ "receive kick rxState=%s (rxBuf.size=%d) %d-bit\n",
+ NsRxStateStrings[rxState], rxFifo.size(), is64bit ? 64 : 32);
+
+ Addr link, bufptr;
+ uint32_t &cmdsts = is64bit ? rxDesc64.cmdsts : rxDesc32.cmdsts;
+ uint32_t &extsts = is64bit ? rxDesc64.extsts : rxDesc32.extsts;
+
+ next:
+ if (clock) {
+ if (rxKickTick > curTick) {
+ DPRINTF(EthernetSM, "receive kick exiting, can't run till %d\n",
+ rxKickTick);
+
+ goto exit;
+ }
+
+ // Go to the next state machine clock tick.
+ rxKickTick = curTick + cycles(1);
+ }
+
+ switch(rxDmaState) {
+ case dmaReadWaiting:
+ if (doRxDmaRead())
+ goto exit;
+ break;
+ case dmaWriteWaiting:
+ if (doRxDmaWrite())
+ goto exit;
+ break;
+ default:
+ break;
+ }
+
+ link = is64bit ? (Addr)rxDesc64.link : (Addr)rxDesc32.link;
+ bufptr = is64bit ? (Addr)rxDesc64.bufptr : (Addr)rxDesc32.bufptr;
+
+ // see state machine from spec for details
+ // the way this works is, if you finish work on one state and can
+ // go directly to another, you do that through jumping to the
+ // label "next". however, if you have intermediate work, like DMA
+ // so that you can't go to the next state yet, you go to exit and
+ // exit the loop. however, when the DMA is done it will trigger
+ // an event and come back to this loop.
+ switch (rxState) {
+ case rxIdle:
+ if (!rxEnable) {
+ DPRINTF(EthernetSM, "Receive Disabled! Nothing to do.\n");
+ goto exit;
+ }
+
+ if (CRDD) {
+ rxState = rxDescRefr;
+
+ rxDmaAddr = regs.rxdp & 0x3fffffff;
+ rxDmaData =
+ is64bit ? (void *)&rxDesc64.link : (void *)&rxDesc32.link;
+ rxDmaLen = is64bit ? sizeof(rxDesc64.link) : sizeof(rxDesc32.link);
+ rxDmaFree = dmaDescFree;
+
+ descDmaReads++;
+ descDmaRdBytes += rxDmaLen;
+
+ if (doRxDmaRead())
+ goto exit;
+ } else {
+ rxState = rxDescRead;
+
+ rxDmaAddr = regs.rxdp & 0x3fffffff;
+ rxDmaData = is64bit ? (void *)&rxDesc64 : (void *)&rxDesc32;
+ rxDmaLen = is64bit ? sizeof(rxDesc64) : sizeof(rxDesc32);
+ rxDmaFree = dmaDescFree;
+
+ descDmaReads++;
+ descDmaRdBytes += rxDmaLen;
+
+ if (doRxDmaRead())
+ goto exit;
+ }
+ break;
+
+ case rxDescRefr:
+ if (rxDmaState != dmaIdle)
+ goto exit;
+
+ rxState = rxAdvance;
+ break;
+
+ case rxDescRead:
+ if (rxDmaState != dmaIdle)
+ goto exit;
+
+ DPRINTF(EthernetDesc, "rxDesc: addr=%08x read descriptor\n",
+ regs.rxdp & 0x3fffffff);
+ DPRINTF(EthernetDesc,
+ "rxDesc: link=%#x bufptr=%#x cmdsts=%08x extsts=%08x\n",
+ link, bufptr, cmdsts, extsts);
+
+ if (cmdsts & CMDSTS_OWN) {
+ devIntrPost(ISR_RXIDLE);
+ rxState = rxIdle;
+ goto exit;
+ } else {
+ rxState = rxFifoBlock;
+ rxFragPtr = bufptr;
+ rxDescCnt = cmdsts & CMDSTS_LEN_MASK;
+ }
+ break;
+
+ case rxFifoBlock:
+ if (!rxPacket) {
+ /**
+ * @todo in reality, we should be able to start processing
+ * the packet as it arrives, and not have to wait for the
+ * full packet ot be in the receive fifo.
+ */
+ if (rxFifo.empty())
+ goto exit;
+
+ DPRINTF(EthernetSM, "****processing receive of new packet****\n");
+
+ // If we don't have a packet, grab a new one from the fifo.
+ rxPacket = rxFifo.front();
+ rxPktBytes = rxPacket->length;
+ rxPacketBufPtr = rxPacket->data;
+
+#if TRACING_ON
+ if (DTRACE(Ethernet)) {
+ IpPtr ip(rxPacket);
+ if (ip) {
+ DPRINTF(Ethernet, "ID is %d\n", ip->id());
+ TcpPtr tcp(ip);
+ if (tcp) {
+ DPRINTF(Ethernet,
+ "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n",
+ tcp->sport(), tcp->dport(), tcp->seq(),
+ tcp->ack());
+ }
+ }
+ }
+#endif
+
+ // sanity check - i think the driver behaves like this
+ assert(rxDescCnt >= rxPktBytes);
+ rxFifo.pop();
+ }
+
+
+ // dont' need the && rxDescCnt > 0 if driver sanity check
+ // above holds
+ if (rxPktBytes > 0) {
+ rxState = rxFragWrite;
+ // don't need min<>(rxPktBytes,rxDescCnt) if above sanity
+ // check holds
+ rxXferLen = rxPktBytes;
+
+ rxDmaAddr = rxFragPtr & 0x3fffffff;
+ rxDmaData = rxPacketBufPtr;
+ rxDmaLen = rxXferLen;
+ rxDmaFree = dmaDataFree;
+
+ if (doRxDmaWrite())
+ goto exit;
+
+ } else {
+ rxState = rxDescWrite;
+
+ //if (rxPktBytes == 0) { /* packet is done */
+ assert(rxPktBytes == 0);
+ DPRINTF(EthernetSM, "done with receiving packet\n");
+
+ cmdsts |= CMDSTS_OWN;
+ cmdsts &= ~CMDSTS_MORE;
+ cmdsts |= CMDSTS_OK;
+ cmdsts &= 0xffff0000;
+ cmdsts += rxPacket->length; //i.e. set CMDSTS_SIZE
+
+#if 0
+ /*
+ * all the driver uses these are for its own stats keeping
+ * which we don't care about, aren't necessary for
+ * functionality and doing this would just slow us down.
+ * if they end up using this in a later version for
+ * functional purposes, just undef
+ */
+ if (rxFilterEnable) {
+ cmdsts &= ~CMDSTS_DEST_MASK;
+ const EthAddr &dst = rxFifoFront()->dst();
+ if (dst->unicast())
+ cmdsts |= CMDSTS_DEST_SELF;
+ if (dst->multicast())
+ cmdsts |= CMDSTS_DEST_MULTI;
+ if (dst->broadcast())
+ cmdsts |= CMDSTS_DEST_MASK;
+ }
+#endif
+
+ IpPtr ip(rxPacket);
+ if (extstsEnable && ip) {
+ extsts |= EXTSTS_IPPKT;
+ rxIpChecksums++;
+ if (cksum(ip) != 0) {
+ DPRINTF(EthernetCksum, "Rx IP Checksum Error\n");
+ extsts |= EXTSTS_IPERR;
+ }
+ TcpPtr tcp(ip);
+ UdpPtr udp(ip);
+ if (tcp) {
+ extsts |= EXTSTS_TCPPKT;
+ rxTcpChecksums++;
+ if (cksum(tcp) != 0) {
+ DPRINTF(EthernetCksum, "Rx TCP Checksum Error\n");
+ extsts |= EXTSTS_TCPERR;
+
+ }
+ } else if (udp) {
+ extsts |= EXTSTS_UDPPKT;
+ rxUdpChecksums++;
+ if (cksum(udp) != 0) {
+ DPRINTF(EthernetCksum, "Rx UDP Checksum Error\n");
+ extsts |= EXTSTS_UDPERR;
+ }
+ }
+ }
+ rxPacket = 0;
+
+ /*
+ * the driver seems to always receive into desc buffers
+ * of size 1514, so you never have a pkt that is split
+ * into multiple descriptors on the receive side, so
+ * i don't implement that case, hence the assert above.
+ */
+
+ DPRINTF(EthernetDesc,
+ "rxDesc: addr=%08x writeback cmdsts extsts\n",
+ regs.rxdp & 0x3fffffff);
+ DPRINTF(EthernetDesc,
+ "rxDesc: link=%#x bufptr=%#x cmdsts=%08x extsts=%08x\n",
+ link, bufptr, cmdsts, extsts);
+
+ rxDmaAddr = regs.rxdp & 0x3fffffff;
+ rxDmaData = &cmdsts;
+ if (is64bit) {
+ rxDmaAddr += offsetof(ns_desc64, cmdsts);
+ rxDmaLen = sizeof(rxDesc64.cmdsts) + sizeof(rxDesc64.extsts);
+ } else {
+ rxDmaAddr += offsetof(ns_desc32, cmdsts);
+ rxDmaLen = sizeof(rxDesc32.cmdsts) + sizeof(rxDesc32.extsts);
+ }
+ rxDmaFree = dmaDescFree;
+
+ descDmaWrites++;
+ descDmaWrBytes += rxDmaLen;
+
+ if (doRxDmaWrite())
+ goto exit;
+ }
+ break;
+
+ case rxFragWrite:
+ if (rxDmaState != dmaIdle)
+ goto exit;
+
+ rxPacketBufPtr += rxXferLen;
+ rxFragPtr += rxXferLen;
+ rxPktBytes -= rxXferLen;
+
+ rxState = rxFifoBlock;
+ break;
+
+ case rxDescWrite:
+ if (rxDmaState != dmaIdle)
+ goto exit;
+
+ assert(cmdsts & CMDSTS_OWN);
+
+ assert(rxPacket == 0);
+ devIntrPost(ISR_RXOK);
+
+ if (cmdsts & CMDSTS_INTR)
+ devIntrPost(ISR_RXDESC);
+
+ if (!rxEnable) {
+ DPRINTF(EthernetSM, "Halting the RX state machine\n");
+ rxState = rxIdle;
+ goto exit;
+ } else
+ rxState = rxAdvance;
+ break;
+
+ case rxAdvance:
+ if (link == 0) {
+ devIntrPost(ISR_RXIDLE);
+ rxState = rxIdle;
+ CRDD = true;
+ goto exit;
+ } else {
+ if (rxDmaState != dmaIdle)
+ goto exit;
+ rxState = rxDescRead;
+ regs.rxdp = link;
+ CRDD = false;
+
+ rxDmaAddr = regs.rxdp & 0x3fffffff;
+ rxDmaData = is64bit ? (void *)&rxDesc64 : (void *)&rxDesc32;
+ rxDmaLen = is64bit ? sizeof(rxDesc64) : sizeof(rxDesc32);
+ rxDmaFree = dmaDescFree;
+
+ if (doRxDmaRead())
+ goto exit;
+ }
+ break;
+
+ default:
+ panic("Invalid rxState!");
+ }
+
+ DPRINTF(EthernetSM, "entering next rxState=%s\n",
+ NsRxStateStrings[rxState]);
+ goto next;
+
+ exit:
+ /**
+ * @todo do we want to schedule a future kick?
+ */
+ DPRINTF(EthernetSM, "rx state machine exited rxState=%s\n",
+ NsRxStateStrings[rxState]);
+
+ if (clock && !rxKickEvent.scheduled())
+ rxKickEvent.schedule(rxKickTick);
+}
+
+void
+NSGigE::transmit()
+{
+ if (txFifo.empty()) {
+ DPRINTF(Ethernet, "nothing to transmit\n");
+ return;
+ }
+
+ DPRINTF(Ethernet, "Attempt Pkt Transmit: txFifo length=%d\n",
+ txFifo.size());
+ if (interface->sendPacket(txFifo.front())) {
+#if TRACING_ON
+ if (DTRACE(Ethernet)) {
+ IpPtr ip(txFifo.front());
+ if (ip) {
+ DPRINTF(Ethernet, "ID is %d\n", ip->id());
+ TcpPtr tcp(ip);
+ if (tcp) {
+ DPRINTF(Ethernet,
+ "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n",
+ tcp->sport(), tcp->dport(), tcp->seq(),
+ tcp->ack());
+ }
+ }
+ }
+#endif
+
+ DDUMP(EthernetData, txFifo.front()->data, txFifo.front()->length);
+ txBytes += txFifo.front()->length;
+ txPackets++;
+
+ DPRINTF(Ethernet, "Successful Xmit! now txFifoAvail is %d\n",
+ txFifo.avail());
+ txFifo.pop();
+
+ /*
+ * normally do a writeback of the descriptor here, and ONLY
+ * after that is done, send this interrupt. but since our
+ * stuff never actually fails, just do this interrupt here,
+ * otherwise the code has to stray from this nice format.
+ * besides, it's functionally the same.
+ */
+ devIntrPost(ISR_TXOK);
+ }
+
+ if (!txFifo.empty() && !txEvent.scheduled()) {
+ DPRINTF(Ethernet, "reschedule transmit\n");
+ txEvent.schedule(curTick + retryTime);
+ }
+}
+
+bool
+NSGigE::doTxDmaRead()
+{
+ assert(txDmaState == dmaIdle || txDmaState == dmaReadWaiting);
+ txDmaState = dmaReading;
+
+ if (dmaPending())
+ txDmaState = dmaReadWaiting;
+ else
+ dmaRead(txDmaAddr, txDmaLen, &txDmaReadEvent, (uint8_t*)txDmaData);
+
+ return true;
+}
+
+void
+NSGigE::txDmaReadDone()
+{
+ assert(txDmaState == dmaReading);
+ 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)
+ rxKick();
+
+ txKick();
+}
+
+bool
+NSGigE::doTxDmaWrite()
+{
+ assert(txDmaState == dmaIdle || txDmaState == dmaWriteWaiting);
+ txDmaState = dmaWriting;
+
+ if (dmaPending())
+ txDmaState = dmaWriteWaiting;
+ else
+ dmaWrite(txDmaAddr, txDmaLen, &txDmaWriteEvent, (uint8_t*)txDmaData);
+ return true;
+}
+
+void
+NSGigE::txDmaWriteDone()
+{
+ assert(txDmaState == dmaWriting);
+ 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)
+ rxKick();
+
+ txKick();
+}
+
+void
+NSGigE::txKick()
+{
+ bool is64bit = (bool)(regs.config & CFGR_M64ADDR);
+
+ DPRINTF(EthernetSM, "transmit kick txState=%s %d-bit\n",
+ NsTxStateStrings[txState], is64bit ? 64 : 32);
+
+ Addr link, bufptr;
+ uint32_t &cmdsts = is64bit ? txDesc64.cmdsts : txDesc32.cmdsts;
+ uint32_t &extsts = is64bit ? txDesc64.extsts : txDesc32.extsts;
+
+ next:
+ if (clock) {
+ if (txKickTick > curTick) {
+ DPRINTF(EthernetSM, "transmit kick exiting, can't run till %d\n",
+ txKickTick);
+ goto exit;
+ }
+
+ // Go to the next state machine clock tick.
+ txKickTick = curTick + cycles(1);
+ }
+
+ switch(txDmaState) {
+ case dmaReadWaiting:
+ if (doTxDmaRead())
+ goto exit;
+ break;
+ case dmaWriteWaiting:
+ if (doTxDmaWrite())
+ goto exit;
+ break;
+ default:
+ break;
+ }
+
+ link = is64bit ? (Addr)txDesc64.link : (Addr)txDesc32.link;
+ bufptr = is64bit ? (Addr)txDesc64.bufptr : (Addr)txDesc32.bufptr;
+ switch (txState) {
+ case txIdle:
+ if (!txEnable) {
+ DPRINTF(EthernetSM, "Transmit disabled. Nothing to do.\n");
+ goto exit;
+ }
+
+ if (CTDD) {
+ txState = txDescRefr;
+
+ txDmaAddr = regs.txdp & 0x3fffffff;
+ txDmaData =
+ is64bit ? (void *)&txDesc64.link : (void *)&txDesc32.link;
+ txDmaLen = is64bit ? sizeof(txDesc64.link) : sizeof(txDesc32.link);
+ txDmaFree = dmaDescFree;
+
+ descDmaReads++;
+ descDmaRdBytes += txDmaLen;
+
+ if (doTxDmaRead())
+ goto exit;
+
+ } else {
+ txState = txDescRead;
+
+ txDmaAddr = regs.txdp & 0x3fffffff;
+ txDmaData = is64bit ? (void *)&txDesc64 : (void *)&txDesc32;
+ txDmaLen = is64bit ? sizeof(txDesc64) : sizeof(txDesc32);
+ txDmaFree = dmaDescFree;
+
+ descDmaReads++;
+ descDmaRdBytes += txDmaLen;
+
+ if (doTxDmaRead())
+ goto exit;
+ }
+ break;
+
+ case txDescRefr:
+ if (txDmaState != dmaIdle)
+ goto exit;
+
+ txState = txAdvance;
+ break;
+
+ case txDescRead:
+ if (txDmaState != dmaIdle)
+ goto exit;
+
+ DPRINTF(EthernetDesc, "txDesc: addr=%08x read descriptor\n",
+ regs.txdp & 0x3fffffff);
+ DPRINTF(EthernetDesc,
+ "txDesc: link=%#x bufptr=%#x cmdsts=%#08x extsts=%#08x\n",
+ link, bufptr, cmdsts, extsts);
+
+ if (cmdsts & CMDSTS_OWN) {
+ txState = txFifoBlock;
+ txFragPtr = bufptr;
+ txDescCnt = cmdsts & CMDSTS_LEN_MASK;
+ } else {
+ devIntrPost(ISR_TXIDLE);
+ txState = txIdle;
+ goto exit;
+ }
+ break;
+
+ case txFifoBlock:
+ if (!txPacket) {
+ DPRINTF(EthernetSM, "****starting the tx of a new packet****\n");
+ txPacket = new EthPacketData(16384);
+ txPacketBufPtr = txPacket->data;
+ }
+
+ if (txDescCnt == 0) {
+ DPRINTF(EthernetSM, "the txDescCnt == 0, done with descriptor\n");
+ if (cmdsts & CMDSTS_MORE) {
+ DPRINTF(EthernetSM, "there are more descriptors to come\n");
+ txState = txDescWrite;
+
+ cmdsts &= ~CMDSTS_OWN;
+
+ txDmaAddr = regs.txdp & 0x3fffffff;
+ txDmaData = &cmdsts;
+ if (is64bit) {
+ txDmaAddr += offsetof(ns_desc64, cmdsts);
+ txDmaLen = sizeof(txDesc64.cmdsts);
+ } else {
+ txDmaAddr += offsetof(ns_desc32, cmdsts);
+ txDmaLen = sizeof(txDesc32.cmdsts);
+ }
+ txDmaFree = dmaDescFree;
+
+ if (doTxDmaWrite())
+ goto exit;
+
+ } else { /* this packet is totally done */
+ DPRINTF(EthernetSM, "This packet is done, let's wrap it up\n");
+ /* deal with the the packet that just finished */
+ if ((regs.vtcr & VTCR_PPCHK) && extstsEnable) {
+ IpPtr ip(txPacket);
+ if (extsts & EXTSTS_UDPPKT) {
+ UdpPtr udp(ip);
+ udp->sum(0);
+ udp->sum(cksum(udp));
+ txUdpChecksums++;
+ } else if (extsts & EXTSTS_TCPPKT) {
+ TcpPtr tcp(ip);
+ tcp->sum(0);
+ tcp->sum(cksum(tcp));
+ txTcpChecksums++;
+ }
+ if (extsts & EXTSTS_IPPKT) {
+ ip->sum(0);
+ ip->sum(cksum(ip));
+ txIpChecksums++;
+ }
+ }
+
+ txPacket->length = txPacketBufPtr - txPacket->data;
+ // this is just because the receive can't handle a
+ // packet bigger want to make sure
+ if (txPacket->length > 1514)
+ panic("transmit packet too large, %s > 1514\n",
+ txPacket->length);
+
+#ifndef NDEBUG
+ bool success =
+#endif
+ txFifo.push(txPacket);
+ assert(success);
+
+ /*
+ * this following section is not tqo spec, but
+ * functionally shouldn't be any different. normally,
+ * the chip will wait til the transmit has occurred
+ * before writing back the descriptor because it has
+ * to wait to see that it was successfully transmitted
+ * to decide whether to set CMDSTS_OK or not.
+ * however, in the simulator since it is always
+ * successfully transmitted, and writing it exactly to
+ * spec would complicate the code, we just do it here
+ */
+
+ cmdsts &= ~CMDSTS_OWN;
+ cmdsts |= CMDSTS_OK;
+
+ DPRINTF(EthernetDesc,
+ "txDesc writeback: cmdsts=%08x extsts=%08x\n",
+ cmdsts, extsts);
+
+ txDmaFree = dmaDescFree;
+ txDmaAddr = regs.txdp & 0x3fffffff;
+ txDmaData = &cmdsts;
+ if (is64bit) {
+ txDmaAddr += offsetof(ns_desc64, cmdsts);
+ txDmaLen =
+ sizeof(txDesc64.cmdsts) + sizeof(txDesc64.extsts);
+ } else {
+ txDmaAddr += offsetof(ns_desc32, cmdsts);
+ txDmaLen =
+ sizeof(txDesc32.cmdsts) + sizeof(txDesc32.extsts);
+ }
+
+ descDmaWrites++;
+ descDmaWrBytes += txDmaLen;
+
+ transmit();
+ txPacket = 0;
+
+ if (!txEnable) {
+ DPRINTF(EthernetSM, "halting TX state machine\n");
+ txState = txIdle;
+ goto exit;
+ } else
+ txState = txAdvance;
+
+ if (doTxDmaWrite())
+ goto exit;
+ }
+ } else {
+ DPRINTF(EthernetSM, "this descriptor isn't done yet\n");
+ if (!txFifo.full()) {
+ txState = txFragRead;
+
+ /*
+ * The number of bytes transferred is either whatever
+ * is left in the descriptor (txDescCnt), or if there
+ * is not enough room in the fifo, just whatever room
+ * is left in the fifo
+ */
+ txXferLen = min<uint32_t>(txDescCnt, txFifo.avail());
+
+ txDmaAddr = txFragPtr & 0x3fffffff;
+ txDmaData = txPacketBufPtr;
+ txDmaLen = txXferLen;
+ txDmaFree = dmaDataFree;
+
+ if (doTxDmaRead())
+ goto exit;
+ } else {
+ txState = txFifoBlock;
+ transmit();
+
+ goto exit;
+ }
+
+ }
+ break;
+
+ case txFragRead:
+ if (txDmaState != dmaIdle)
+ goto exit;
+
+ txPacketBufPtr += txXferLen;
+ txFragPtr += txXferLen;
+ txDescCnt -= txXferLen;
+ txFifo.reserve(txXferLen);
+
+ txState = txFifoBlock;
+ break;
+
+ case txDescWrite:
+ if (txDmaState != dmaIdle)
+ goto exit;
+
+ if (cmdsts & CMDSTS_INTR)
+ devIntrPost(ISR_TXDESC);
+
+ if (!txEnable) {
+ DPRINTF(EthernetSM, "halting TX state machine\n");
+ txState = txIdle;
+ goto exit;
+ } else
+ txState = txAdvance;
+ break;
+
+ case txAdvance:
+ if (link == 0) {
+ devIntrPost(ISR_TXIDLE);
+ txState = txIdle;
+ goto exit;
+ } else {
+ if (txDmaState != dmaIdle)
+ goto exit;
+ txState = txDescRead;
+ regs.txdp = link;
+ CTDD = false;
+
+ txDmaAddr = link & 0x3fffffff;
+ txDmaData = is64bit ? (void *)&txDesc64 : (void *)&txDesc32;
+ txDmaLen = is64bit ? sizeof(txDesc64) : sizeof(txDesc32);
+ txDmaFree = dmaDescFree;
+
+ if (doTxDmaRead())
+ goto exit;
+ }
+ break;
+
+ default:
+ panic("invalid state");
+ }
+
+ DPRINTF(EthernetSM, "entering next txState=%s\n",
+ NsTxStateStrings[txState]);
+ goto next;
+
+ exit:
+ /**
+ * @todo do we want to schedule a future kick?
+ */
+ DPRINTF(EthernetSM, "tx state machine exited txState=%s\n",
+ NsTxStateStrings[txState]);
+
+ if (clock && !txKickEvent.scheduled())
+ txKickEvent.schedule(txKickTick);
+}
+
+/**
+ * Advance the EEPROM state machine
+ * Called on rising edge of EEPROM clock bit in MEAR
+ */
+void
+NSGigE::eepromKick()
+{
+ switch (eepromState) {
+
+ case eepromStart:
+
+ // Wait for start bit
+ if (regs.mear & MEAR_EEDI) {
+ // Set up to get 2 opcode bits
+ eepromState = eepromGetOpcode;
+ eepromBitsToRx = 2;
+ eepromOpcode = 0;
+ }
+ break;
+
+ case eepromGetOpcode:
+ eepromOpcode <<= 1;
+ eepromOpcode += (regs.mear & MEAR_EEDI) ? 1 : 0;
+ --eepromBitsToRx;
+
+ // Done getting opcode
+ if (eepromBitsToRx == 0) {
+ if (eepromOpcode != EEPROM_READ)
+ panic("only EEPROM reads are implemented!");
+
+ // Set up to get address
+ eepromState = eepromGetAddress;
+ eepromBitsToRx = 6;
+ eepromAddress = 0;
+ }
+ break;
+
+ case eepromGetAddress:
+ eepromAddress <<= 1;
+ eepromAddress += (regs.mear & MEAR_EEDI) ? 1 : 0;
+ --eepromBitsToRx;
+
+ // Done getting address
+ if (eepromBitsToRx == 0) {
+
+ if (eepromAddress >= EEPROM_SIZE)
+ panic("EEPROM read access out of range!");
+
+ switch (eepromAddress) {
+
+ case EEPROM_PMATCH2_ADDR:
+ eepromData = rom.perfectMatch[5];
+ eepromData <<= 8;
+ eepromData += rom.perfectMatch[4];
+ break;
+
+ case EEPROM_PMATCH1_ADDR:
+ eepromData = rom.perfectMatch[3];
+ eepromData <<= 8;
+ eepromData += rom.perfectMatch[2];
+ break;
+
+ case EEPROM_PMATCH0_ADDR:
+ eepromData = rom.perfectMatch[1];
+ eepromData <<= 8;
+ eepromData += rom.perfectMatch[0];
+ break;
+
+ default:
+ panic("FreeBSD driver only uses EEPROM to read PMATCH!");
+ }
+ // Set up to read data
+ eepromState = eepromRead;
+ eepromBitsToRx = 16;
+
+ // Clear data in bit
+ regs.mear &= ~MEAR_EEDI;
+ }
+ break;
+
+ case eepromRead:
+ // Clear Data Out bit
+ regs.mear &= ~MEAR_EEDO;
+ // Set bit to value of current EEPROM bit
+ regs.mear |= (eepromData & 0x8000) ? MEAR_EEDO : 0x0;
+
+ eepromData <<= 1;
+ --eepromBitsToRx;
+
+ // All done
+ if (eepromBitsToRx == 0) {
+ eepromState = eepromStart;
+ }
+ break;
+
+ default:
+ panic("invalid EEPROM state");
+ }
+
+}
+
+void
+NSGigE::transferDone()
+{
+ if (txFifo.empty()) {
+ DPRINTF(Ethernet, "transfer complete: txFifo empty...nothing to do\n");
+ return;
+ }
+
+ DPRINTF(Ethernet, "transfer complete: data in txFifo...schedule xmit\n");
+
+ if (txEvent.scheduled())
+ txEvent.reschedule(curTick + cycles(1));
+ else
+ txEvent.schedule(curTick + cycles(1));
+}
+
+bool
+NSGigE::rxFilter(const EthPacketPtr &packet)
+{
+ EthPtr eth = packet;
+ bool drop = true;
+ string type;
+
+ const EthAddr &dst = eth->dst();
+ if (dst.unicast()) {
+ // If we're accepting all unicast addresses
+ if (acceptUnicast)
+ drop = false;
+
+ // If we make a perfect match
+ if (acceptPerfect && dst == rom.perfectMatch)
+ drop = false;
+
+ if (acceptArp && eth->type() == ETH_TYPE_ARP)
+ drop = false;
+
+ } else if (dst.broadcast()) {
+ // if we're accepting broadcasts
+ if (acceptBroadcast)
+ drop = false;
+
+ } else if (dst.multicast()) {
+ // if we're accepting all multicasts
+ if (acceptMulticast)
+ drop = false;
+
+ // Multicast hashing faked - all packets accepted
+ if (multicastHashEnable)
+ drop = false;
+ }
+
+ if (drop) {
+ DPRINTF(Ethernet, "rxFilter drop\n");
+ DDUMP(EthernetData, packet->data, packet->length);
+ }
+
+ return drop;
+}
+
+bool
+NSGigE::recvPacket(EthPacketPtr packet)
+{
+ rxBytes += packet->length;
+ rxPackets++;
+
+ DPRINTF(Ethernet, "Receiving packet from wire, rxFifoAvail=%d\n",
+ rxFifo.avail());
+
+ if (!rxEnable) {
+ DPRINTF(Ethernet, "receive disabled...packet dropped\n");
+ return true;
+ }
+
+ if (!rxFilterEnable) {
+ DPRINTF(Ethernet,
+ "receive packet filtering disabled . . . packet dropped\n");
+ return true;
+ }
+
+ if (rxFilter(packet)) {
+ DPRINTF(Ethernet, "packet filtered...dropped\n");
+ return true;
+ }
+
+ if (rxFifo.avail() < packet->length) {
+#if TRACING_ON
+ IpPtr ip(packet);
+ TcpPtr tcp(ip);
+ if (ip) {
+ DPRINTF(Ethernet,
+ "packet won't fit in receive buffer...pkt ID %d dropped\n",
+ ip->id());
+ if (tcp) {
+ DPRINTF(Ethernet, "Seq=%d\n", tcp->seq());
+ }
+ }
+#endif
+ droppedPackets++;
+ devIntrPost(ISR_RXORN);
+ return false;
+ }
+
+ rxFifo.push(packet);
+
+ rxKick();
+ return true;
+}
+
+//=====================================================================
+//
+//
+void
+NSGigE::serialize(ostream &os)
+{
+ // Serialize the PciDev base class
+ PciDev::serialize(os);
+
+ /*
+ * Finalize any DMA events now.
+ */
+ // @todo will mem system save pending dma?
+
+ /*
+ * Serialize the device registers
+ */
+ SERIALIZE_SCALAR(regs.command);
+ SERIALIZE_SCALAR(regs.config);
+ SERIALIZE_SCALAR(regs.mear);
+ SERIALIZE_SCALAR(regs.ptscr);
+ SERIALIZE_SCALAR(regs.isr);
+ SERIALIZE_SCALAR(regs.imr);
+ SERIALIZE_SCALAR(regs.ier);
+ SERIALIZE_SCALAR(regs.ihr);
+ SERIALIZE_SCALAR(regs.txdp);
+ SERIALIZE_SCALAR(regs.txdp_hi);
+ SERIALIZE_SCALAR(regs.txcfg);
+ SERIALIZE_SCALAR(regs.gpior);
+ SERIALIZE_SCALAR(regs.rxdp);
+ SERIALIZE_SCALAR(regs.rxdp_hi);
+ SERIALIZE_SCALAR(regs.rxcfg);
+ SERIALIZE_SCALAR(regs.pqcr);
+ SERIALIZE_SCALAR(regs.wcsr);
+ SERIALIZE_SCALAR(regs.pcr);
+ SERIALIZE_SCALAR(regs.rfcr);
+ SERIALIZE_SCALAR(regs.rfdr);
+ SERIALIZE_SCALAR(regs.brar);
+ SERIALIZE_SCALAR(regs.brdr);
+ SERIALIZE_SCALAR(regs.srr);
+ SERIALIZE_SCALAR(regs.mibc);
+ SERIALIZE_SCALAR(regs.vrcr);
+ SERIALIZE_SCALAR(regs.vtcr);
+ SERIALIZE_SCALAR(regs.vdr);
+ SERIALIZE_SCALAR(regs.ccsr);
+ SERIALIZE_SCALAR(regs.tbicr);
+ SERIALIZE_SCALAR(regs.tbisr);
+ SERIALIZE_SCALAR(regs.tanar);
+ SERIALIZE_SCALAR(regs.tanlpar);
+ SERIALIZE_SCALAR(regs.taner);
+ SERIALIZE_SCALAR(regs.tesr);
+
+ SERIALIZE_ARRAY(rom.perfectMatch, ETH_ADDR_LEN);
+ SERIALIZE_ARRAY(rom.filterHash, FHASH_SIZE);
+
+ SERIALIZE_SCALAR(ioEnable);
+
+ /*
+ * Serialize the data Fifos
+ */
+ rxFifo.serialize("rxFifo", os);
+ txFifo.serialize("txFifo", os);
+
+ /*
+ * Serialize the various helper variables
+ */
+ bool txPacketExists = txPacket;
+ SERIALIZE_SCALAR(txPacketExists);
+ if (txPacketExists) {
+ txPacket->length = txPacketBufPtr - txPacket->data;
+ txPacket->serialize("txPacket", os);
+ uint32_t txPktBufPtr = (uint32_t) (txPacketBufPtr - txPacket->data);
+ SERIALIZE_SCALAR(txPktBufPtr);
+ }
+
+ bool rxPacketExists = rxPacket;
+ SERIALIZE_SCALAR(rxPacketExists);
+ if (rxPacketExists) {
+ rxPacket->serialize("rxPacket", os);
+ uint32_t rxPktBufPtr = (uint32_t) (rxPacketBufPtr - rxPacket->data);
+ SERIALIZE_SCALAR(rxPktBufPtr);
+ }
+
+ SERIALIZE_SCALAR(txXferLen);
+ SERIALIZE_SCALAR(rxXferLen);
+
+ /*
+ * Serialize Cached Descriptors
+ */
+ SERIALIZE_SCALAR(rxDesc64.link);
+ SERIALIZE_SCALAR(rxDesc64.bufptr);
+ SERIALIZE_SCALAR(rxDesc64.cmdsts);
+ SERIALIZE_SCALAR(rxDesc64.extsts);
+ SERIALIZE_SCALAR(txDesc64.link);
+ SERIALIZE_SCALAR(txDesc64.bufptr);
+ SERIALIZE_SCALAR(txDesc64.cmdsts);
+ SERIALIZE_SCALAR(txDesc64.extsts);
+ SERIALIZE_SCALAR(rxDesc32.link);
+ SERIALIZE_SCALAR(rxDesc32.bufptr);
+ SERIALIZE_SCALAR(rxDesc32.cmdsts);
+ SERIALIZE_SCALAR(rxDesc32.extsts);
+ SERIALIZE_SCALAR(txDesc32.link);
+ SERIALIZE_SCALAR(txDesc32.bufptr);
+ SERIALIZE_SCALAR(txDesc32.cmdsts);
+ SERIALIZE_SCALAR(txDesc32.extsts);
+ SERIALIZE_SCALAR(extstsEnable);
+
+ /*
+ * Serialize tx state machine
+ */
+ int txState = this->txState;
+ SERIALIZE_SCALAR(txState);
+ SERIALIZE_SCALAR(txEnable);
+ SERIALIZE_SCALAR(CTDD);
+ SERIALIZE_SCALAR(txFragPtr);
+ SERIALIZE_SCALAR(txDescCnt);
+ int txDmaState = this->txDmaState;
+ SERIALIZE_SCALAR(txDmaState);
+ SERIALIZE_SCALAR(txKickTick);
+
+ /*
+ * Serialize rx state machine
+ */
+ int rxState = this->rxState;
+ SERIALIZE_SCALAR(rxState);
+ SERIALIZE_SCALAR(rxEnable);
+ SERIALIZE_SCALAR(CRDD);
+ SERIALIZE_SCALAR(rxPktBytes);
+ SERIALIZE_SCALAR(rxFragPtr);
+ SERIALIZE_SCALAR(rxDescCnt);
+ int rxDmaState = this->rxDmaState;
+ SERIALIZE_SCALAR(rxDmaState);
+ SERIALIZE_SCALAR(rxKickTick);
+
+ /*
+ * Serialize EEPROM state machine
+ */
+ int eepromState = this->eepromState;
+ SERIALIZE_SCALAR(eepromState);
+ SERIALIZE_SCALAR(eepromClk);
+ SERIALIZE_SCALAR(eepromBitsToRx);
+ SERIALIZE_SCALAR(eepromOpcode);
+ SERIALIZE_SCALAR(eepromAddress);
+ SERIALIZE_SCALAR(eepromData);
+
+ /*
+ * If there's a pending transmit, store the time so we can
+ * reschedule it later
+ */
+ Tick transmitTick = txEvent.scheduled() ? txEvent.when() - curTick : 0;
+ SERIALIZE_SCALAR(transmitTick);
+
+ /*
+ * receive address filter settings
+ */
+ SERIALIZE_SCALAR(rxFilterEnable);
+ SERIALIZE_SCALAR(acceptBroadcast);
+ SERIALIZE_SCALAR(acceptMulticast);
+ SERIALIZE_SCALAR(acceptUnicast);
+ SERIALIZE_SCALAR(acceptPerfect);
+ SERIALIZE_SCALAR(acceptArp);
+ SERIALIZE_SCALAR(multicastHashEnable);
+
+ /*
+ * Keep track of pending interrupt status.
+ */
+ SERIALIZE_SCALAR(intrTick);
+ SERIALIZE_SCALAR(cpuPendingIntr);
+ Tick intrEventTick = 0;
+ if (intrEvent)
+ intrEventTick = intrEvent->when();
+ SERIALIZE_SCALAR(intrEventTick);
+
+}
+
+void
+NSGigE::unserialize(Checkpoint *cp, const std::string &section)
+{
+ // Unserialize the PciDev base class
+ PciDev::unserialize(cp, section);
+
+ UNSERIALIZE_SCALAR(regs.command);
+ UNSERIALIZE_SCALAR(regs.config);
+ UNSERIALIZE_SCALAR(regs.mear);
+ UNSERIALIZE_SCALAR(regs.ptscr);
+ UNSERIALIZE_SCALAR(regs.isr);
+ UNSERIALIZE_SCALAR(regs.imr);
+ UNSERIALIZE_SCALAR(regs.ier);
+ UNSERIALIZE_SCALAR(regs.ihr);
+ UNSERIALIZE_SCALAR(regs.txdp);
+ UNSERIALIZE_SCALAR(regs.txdp_hi);
+ UNSERIALIZE_SCALAR(regs.txcfg);
+ UNSERIALIZE_SCALAR(regs.gpior);
+ UNSERIALIZE_SCALAR(regs.rxdp);
+ UNSERIALIZE_SCALAR(regs.rxdp_hi);
+ UNSERIALIZE_SCALAR(regs.rxcfg);
+ UNSERIALIZE_SCALAR(regs.pqcr);
+ UNSERIALIZE_SCALAR(regs.wcsr);
+ UNSERIALIZE_SCALAR(regs.pcr);
+ UNSERIALIZE_SCALAR(regs.rfcr);
+ UNSERIALIZE_SCALAR(regs.rfdr);
+ UNSERIALIZE_SCALAR(regs.brar);
+ UNSERIALIZE_SCALAR(regs.brdr);
+ UNSERIALIZE_SCALAR(regs.srr);
+ UNSERIALIZE_SCALAR(regs.mibc);
+ UNSERIALIZE_SCALAR(regs.vrcr);
+ UNSERIALIZE_SCALAR(regs.vtcr);
+ UNSERIALIZE_SCALAR(regs.vdr);
+ UNSERIALIZE_SCALAR(regs.ccsr);
+ UNSERIALIZE_SCALAR(regs.tbicr);
+ UNSERIALIZE_SCALAR(regs.tbisr);
+ UNSERIALIZE_SCALAR(regs.tanar);
+ UNSERIALIZE_SCALAR(regs.tanlpar);
+ UNSERIALIZE_SCALAR(regs.taner);
+ UNSERIALIZE_SCALAR(regs.tesr);
+
+ UNSERIALIZE_ARRAY(rom.perfectMatch, ETH_ADDR_LEN);
+ UNSERIALIZE_ARRAY(rom.filterHash, FHASH_SIZE);
+
+ UNSERIALIZE_SCALAR(ioEnable);
+
+ /*
+ * unserialize the data fifos
+ */
+ rxFifo.unserialize("rxFifo", cp, section);
+ txFifo.unserialize("txFifo", cp, section);
+
+ /*
+ * unserialize the various helper variables
+ */
+ bool txPacketExists;
+ UNSERIALIZE_SCALAR(txPacketExists);
+ if (txPacketExists) {
+ txPacket = new EthPacketData(16384);
+ txPacket->unserialize("txPacket", cp, section);
+ uint32_t txPktBufPtr;
+ UNSERIALIZE_SCALAR(txPktBufPtr);
+ txPacketBufPtr = (uint8_t *) txPacket->data + txPktBufPtr;
+ } else
+ txPacket = 0;
+
+ bool rxPacketExists;
+ UNSERIALIZE_SCALAR(rxPacketExists);
+ rxPacket = 0;
+ if (rxPacketExists) {
+ rxPacket = new EthPacketData(16384);
+ rxPacket->unserialize("rxPacket", cp, section);
+ uint32_t rxPktBufPtr;
+ UNSERIALIZE_SCALAR(rxPktBufPtr);
+ rxPacketBufPtr = (uint8_t *) rxPacket->data + rxPktBufPtr;
+ } else
+ rxPacket = 0;
+
+ UNSERIALIZE_SCALAR(txXferLen);
+ UNSERIALIZE_SCALAR(rxXferLen);
+
+ /*
+ * Unserialize Cached Descriptors
+ */
+ UNSERIALIZE_SCALAR(rxDesc64.link);
+ UNSERIALIZE_SCALAR(rxDesc64.bufptr);
+ UNSERIALIZE_SCALAR(rxDesc64.cmdsts);
+ UNSERIALIZE_SCALAR(rxDesc64.extsts);
+ UNSERIALIZE_SCALAR(txDesc64.link);
+ UNSERIALIZE_SCALAR(txDesc64.bufptr);
+ UNSERIALIZE_SCALAR(txDesc64.cmdsts);
+ UNSERIALIZE_SCALAR(txDesc64.extsts);
+ UNSERIALIZE_SCALAR(rxDesc32.link);
+ UNSERIALIZE_SCALAR(rxDesc32.bufptr);
+ UNSERIALIZE_SCALAR(rxDesc32.cmdsts);
+ UNSERIALIZE_SCALAR(rxDesc32.extsts);
+ UNSERIALIZE_SCALAR(txDesc32.link);
+ UNSERIALIZE_SCALAR(txDesc32.bufptr);
+ UNSERIALIZE_SCALAR(txDesc32.cmdsts);
+ UNSERIALIZE_SCALAR(txDesc32.extsts);
+ UNSERIALIZE_SCALAR(extstsEnable);
+
+ /*
+ * unserialize tx state machine
+ */
+ int txState;
+ UNSERIALIZE_SCALAR(txState);
+ this->txState = (TxState) txState;
+ UNSERIALIZE_SCALAR(txEnable);
+ UNSERIALIZE_SCALAR(CTDD);
+ UNSERIALIZE_SCALAR(txFragPtr);
+ UNSERIALIZE_SCALAR(txDescCnt);
+ int txDmaState;
+ UNSERIALIZE_SCALAR(txDmaState);
+ this->txDmaState = (DmaState) txDmaState;
+ UNSERIALIZE_SCALAR(txKickTick);
+ if (txKickTick)
+ txKickEvent.schedule(txKickTick);
+
+ /*
+ * unserialize rx state machine
+ */
+ int rxState;
+ UNSERIALIZE_SCALAR(rxState);
+ this->rxState = (RxState) rxState;
+ UNSERIALIZE_SCALAR(rxEnable);
+ UNSERIALIZE_SCALAR(CRDD);
+ UNSERIALIZE_SCALAR(rxPktBytes);
+ UNSERIALIZE_SCALAR(rxFragPtr);
+ UNSERIALIZE_SCALAR(rxDescCnt);
+ int rxDmaState;
+ UNSERIALIZE_SCALAR(rxDmaState);
+ this->rxDmaState = (DmaState) rxDmaState;
+ UNSERIALIZE_SCALAR(rxKickTick);
+ if (rxKickTick)
+ rxKickEvent.schedule(rxKickTick);
+
+ /*
+ * Unserialize EEPROM state machine
+ */
+ int eepromState;
+ UNSERIALIZE_SCALAR(eepromState);
+ this->eepromState = (EEPROMState) eepromState;
+ UNSERIALIZE_SCALAR(eepromClk);
+ UNSERIALIZE_SCALAR(eepromBitsToRx);
+ UNSERIALIZE_SCALAR(eepromOpcode);
+ UNSERIALIZE_SCALAR(eepromAddress);
+ UNSERIALIZE_SCALAR(eepromData);
+
+ /*
+ * If there's a pending transmit, reschedule it now
+ */
+ Tick transmitTick;
+ UNSERIALIZE_SCALAR(transmitTick);
+ if (transmitTick)
+ txEvent.schedule(curTick + transmitTick);
+
+ /*
+ * unserialize receive address filter settings
+ */
+ UNSERIALIZE_SCALAR(rxFilterEnable);
+ UNSERIALIZE_SCALAR(acceptBroadcast);
+ UNSERIALIZE_SCALAR(acceptMulticast);
+ UNSERIALIZE_SCALAR(acceptUnicast);
+ UNSERIALIZE_SCALAR(acceptPerfect);
+ UNSERIALIZE_SCALAR(acceptArp);
+ UNSERIALIZE_SCALAR(multicastHashEnable);
+
+ /*
+ * Keep track of pending interrupt status.
+ */
+ UNSERIALIZE_SCALAR(intrTick);
+ UNSERIALIZE_SCALAR(cpuPendingIntr);
+ Tick intrEventTick;
+ UNSERIALIZE_SCALAR(intrEventTick);
+ if (intrEventTick) {
+ intrEvent = new IntrEvent(this, true);
+ intrEvent->schedule(intrEventTick);
+ }
+}
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigEInt)
+
+ SimObjectParam<EtherInt *> peer;
+ SimObjectParam<NSGigE *> device;
+
+END_DECLARE_SIM_OBJECT_PARAMS(NSGigEInt)
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigEInt)
+
+ INIT_PARAM_DFLT(peer, "peer interface", NULL),
+ INIT_PARAM(device, "Ethernet device of this interface")
+
+END_INIT_SIM_OBJECT_PARAMS(NSGigEInt)
+
+CREATE_SIM_OBJECT(NSGigEInt)
+{
+ NSGigEInt *dev_int = new NSGigEInt(getInstanceName(), device);
+
+ EtherInt *p = (EtherInt *)peer;
+ if (p) {
+ dev_int->setPeer(p);
+ p->setPeer(dev_int);
+ }
+
+ return dev_int;
+}
+
+REGISTER_SIM_OBJECT("NSGigEInt", NSGigEInt)
+
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigE)
+
+ SimObjectParam<System *> system;
+ SimObjectParam<Platform *> platform;
+ SimObjectParam<PciConfigAll *> configspace;
+ SimObjectParam<PciConfigData *> configdata;
+ Param<uint32_t> pci_bus;
+ Param<uint32_t> pci_dev;
+ Param<uint32_t> pci_func;
+ Param<Tick> pio_latency;
+
+ Param<Tick> clock;
+ Param<bool> dma_desc_free;
+ Param<bool> dma_data_free;
+ Param<Tick> dma_read_delay;
+ Param<Tick> dma_write_delay;
+ Param<Tick> dma_read_factor;
+ Param<Tick> dma_write_factor;
+ Param<bool> dma_no_allocate;
+ Param<Tick> intr_delay;
+
+ Param<Tick> rx_delay;
+ Param<Tick> tx_delay;
+ Param<uint32_t> rx_fifo_size;
+ Param<uint32_t> tx_fifo_size;
+
+ Param<bool> rx_filter;
+ Param<string> hardware_address;
+ Param<bool> rx_thread;
+ Param<bool> tx_thread;
+ Param<bool> rss;
+
+END_DECLARE_SIM_OBJECT_PARAMS(NSGigE)
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigE)
+
+ INIT_PARAM(system, "System pointer"),
+ INIT_PARAM(platform, "Platform pointer"),
+ INIT_PARAM(configspace, "PCI Configspace"),
+ INIT_PARAM(configdata, "PCI Config data"),
+ 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(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"),
+ INIT_PARAM(dma_write_delay, "fixed delay for dma writes"),
+ 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(intr_delay, "Interrupt Delay in microseconds"),
+
+ INIT_PARAM(rx_delay, "Receive Delay"),
+ INIT_PARAM(tx_delay, "Transmit Delay"),
+ INIT_PARAM(rx_fifo_size, "max size in bytes of rxFifo"),
+ INIT_PARAM(tx_fifo_size, "max size in bytes of txFifo"),
+
+ INIT_PARAM(rx_filter, "Enable Receive Filter"),
+ INIT_PARAM(hardware_address, "Ethernet Hardware Address"),
+ INIT_PARAM(rx_thread, ""),
+ INIT_PARAM(tx_thread, ""),
+ INIT_PARAM(rss, "")
+
+END_INIT_SIM_OBJECT_PARAMS(NSGigE)
+
+
+CREATE_SIM_OBJECT(NSGigE)
+{
+ NSGigE::Params *params = new NSGigE::Params;
+
+ params->name = getInstanceName();
+ params->platform = platform;
+ params->system = system;
+ params->configSpace = configspace;
+ params->configData = configdata;
+ params->busNum = pci_bus;
+ params->deviceNum = pci_dev;
+ params->functionNum = pci_func;
+ params->pio_delay = pio_latency;
+
+ params->clock = clock;
+ params->dma_desc_free = dma_desc_free;
+ params->dma_data_free = dma_data_free;
+ params->dma_read_delay = dma_read_delay;
+ params->dma_write_delay = dma_write_delay;
+ params->dma_read_factor = dma_read_factor;
+ params->dma_write_factor = dma_write_factor;
+ params->dma_no_allocate = dma_no_allocate;
+ params->pio_delay = pio_latency;
+ params->intr_delay = intr_delay;
+
+ params->rx_delay = rx_delay;
+ params->tx_delay = tx_delay;
+ params->rx_fifo_size = rx_fifo_size;
+ params->tx_fifo_size = tx_fifo_size;
+
+ params->rx_filter = rx_filter;
+ params->eaddr = hardware_address;
+ params->rx_thread = rx_thread;
+ params->tx_thread = tx_thread;
+ params->rss = rss;
+
+ return new NSGigE(params);
+}
+
+REGISTER_SIM_OBJECT("NSGigE", NSGigE)
diff --git a/src/dev/ns_gige.hh b/src/dev/ns_gige.hh
new file mode 100644
index 000000000..51520fd00
--- /dev/null
+++ b/src/dev/ns_gige.hh
@@ -0,0 +1,463 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file
+ * Device module for modelling the National Semiconductor
+ * DP83820 ethernet controller
+ */
+
+#ifndef __DEV_NS_GIGE_HH__
+#define __DEV_NS_GIGE_HH__
+
+#include "base/inet.hh"
+#include "base/statistics.hh"
+#include "dev/etherint.hh"
+#include "dev/etherpkt.hh"
+#include "dev/io_device.hh"
+#include "dev/ns_gige_reg.h"
+#include "dev/pcidev.hh"
+#include "dev/pktfifo.hh"
+#include "sim/eventq.hh"
+
+// Hash filtering constants
+const uint16_t FHASH_ADDR = 0x100;
+const uint16_t FHASH_SIZE = 0x100;
+
+// EEPROM constants
+const uint8_t EEPROM_READ = 0x2;
+const uint8_t EEPROM_SIZE = 64; // Size in words of NSC93C46 EEPROM
+const uint8_t EEPROM_PMATCH2_ADDR = 0xA; // EEPROM Address of PMATCH word 2
+const uint8_t EEPROM_PMATCH1_ADDR = 0xB; // EEPROM Address of PMATCH word 1
+const uint8_t EEPROM_PMATCH0_ADDR = 0xC; // EEPROM Address of PMATCH word 0
+
+/**
+ * Ethernet device registers
+ */
+struct dp_regs {
+ uint32_t command;
+ uint32_t config;
+ uint32_t mear;
+ uint32_t ptscr;
+ uint32_t isr;
+ uint32_t imr;
+ uint32_t ier;
+ uint32_t ihr;
+ uint32_t txdp;
+ uint32_t txdp_hi;
+ uint32_t txcfg;
+ uint32_t gpior;
+ uint32_t rxdp;
+ uint32_t rxdp_hi;
+ uint32_t rxcfg;
+ uint32_t pqcr;
+ uint32_t wcsr;
+ uint32_t pcr;
+ uint32_t rfcr;
+ uint32_t rfdr;
+ uint32_t brar;
+ uint32_t brdr;
+ uint32_t srr;
+ uint32_t mibc;
+ uint32_t vrcr;
+ uint32_t vtcr;
+ uint32_t vdr;
+ uint32_t ccsr;
+ uint32_t tbicr;
+ uint32_t tbisr;
+ uint32_t tanar;
+ uint32_t tanlpar;
+ uint32_t taner;
+ uint32_t tesr;
+};
+
+struct dp_rom {
+ /**
+ * for perfect match memory.
+ * the linux driver doesn't use any other ROM
+ */
+ uint8_t perfectMatch[ETH_ADDR_LEN];
+
+ /**
+ * for hash table memory.
+ * used by the freebsd driver
+ */
+ uint8_t filterHash[FHASH_SIZE];
+};
+
+class NSGigEInt;
+class Packet;
+class PciConfigAll;
+
+/**
+ * NS DP83820 Ethernet device model
+ */
+class NSGigE : public PciDev
+{
+ public:
+ /** Transmit State Machine states */
+ enum TxState
+ {
+ txIdle,
+ txDescRefr,
+ txDescRead,
+ txFifoBlock,
+ txFragRead,
+ txDescWrite,
+ txAdvance
+ };
+
+ /** Receive State Machine States */
+ enum RxState
+ {
+ rxIdle,
+ rxDescRefr,
+ rxDescRead,
+ rxFifoBlock,
+ rxFragWrite,
+ rxDescWrite,
+ rxAdvance
+ };
+
+ enum DmaState
+ {
+ dmaIdle,
+ dmaReading,
+ dmaWriting,
+ dmaReadWaiting,
+ dmaWriteWaiting
+ };
+
+ /** EEPROM State Machine States */
+ enum EEPROMState
+ {
+ eepromStart,
+ eepromGetOpcode,
+ eepromGetAddress,
+ eepromRead
+ };
+
+ protected:
+ /** device register file */
+ dp_regs regs;
+ dp_rom rom;
+
+ /** pci settings */
+ bool ioEnable;
+#if 0
+ bool memEnable;
+ bool bmEnable;
+#endif
+
+ /*** BASIC STRUCTURES FOR TX/RX ***/
+ /* Data FIFOs */
+ PacketFifo txFifo;
+ PacketFifo rxFifo;
+
+ /** various helper vars */
+ EthPacketPtr txPacket;
+ EthPacketPtr rxPacket;
+ uint8_t *txPacketBufPtr;
+ uint8_t *rxPacketBufPtr;
+ uint32_t txXferLen;
+ uint32_t rxXferLen;
+ bool rxDmaFree;
+ bool txDmaFree;
+
+ /** DescCaches */
+ ns_desc32 txDesc32;
+ ns_desc32 rxDesc32;
+ ns_desc64 txDesc64;
+ ns_desc64 rxDesc64;
+
+ /* state machine cycle time */
+ Tick clock;
+ inline Tick cycles(int numCycles) const { return numCycles * clock; }
+
+ /* tx State Machine */
+ TxState txState;
+ bool txEnable;
+
+ /** Current Transmit Descriptor Done */
+ bool CTDD;
+ /** halt the tx state machine after next packet */
+ bool txHalt;
+ /** ptr to the next byte in the current fragment */
+ Addr txFragPtr;
+ /** count of bytes remaining in the current descriptor */
+ uint32_t txDescCnt;
+ DmaState txDmaState;
+
+ /** rx State Machine */
+ RxState rxState;
+ bool rxEnable;
+
+ /** Current Receive Descriptor Done */
+ bool CRDD;
+ /** num of bytes in the current packet being drained from rxDataFifo */
+ uint32_t rxPktBytes;
+ /** halt the rx state machine after current packet */
+ bool rxHalt;
+ /** ptr to the next byte in current fragment */
+ Addr rxFragPtr;
+ /** count of bytes remaining in the current descriptor */
+ uint32_t rxDescCnt;
+ DmaState rxDmaState;
+
+ bool extstsEnable;
+
+ /** EEPROM State Machine */
+ EEPROMState eepromState;
+ bool eepromClk;
+ uint8_t eepromBitsToRx;
+ uint8_t eepromOpcode;
+ uint8_t eepromAddress;
+ uint16_t eepromData;
+
+ protected:
+ Tick dmaReadDelay;
+ Tick dmaWriteDelay;
+
+ Tick dmaReadFactor;
+ Tick dmaWriteFactor;
+
+ void *rxDmaData;
+ Addr rxDmaAddr;
+ int rxDmaLen;
+ bool doRxDmaRead();
+ bool doRxDmaWrite();
+
+ void *txDmaData;
+ Addr txDmaAddr;
+ int txDmaLen;
+ bool doTxDmaRead();
+ bool doTxDmaWrite();
+
+ void rxDmaReadDone();
+ friend class EventWrapper<NSGigE, &NSGigE::rxDmaReadDone>;
+ EventWrapper<NSGigE, &NSGigE::rxDmaReadDone> rxDmaReadEvent;
+
+ void rxDmaWriteDone();
+ friend class EventWrapper<NSGigE, &NSGigE::rxDmaWriteDone>;
+ EventWrapper<NSGigE, &NSGigE::rxDmaWriteDone> rxDmaWriteEvent;
+
+ void txDmaReadDone();
+ friend class EventWrapper<NSGigE, &NSGigE::txDmaReadDone>;
+ EventWrapper<NSGigE, &NSGigE::txDmaReadDone> txDmaReadEvent;
+
+ void txDmaWriteDone();
+ friend class EventWrapper<NSGigE, &NSGigE::txDmaWriteDone>;
+ EventWrapper<NSGigE, &NSGigE::txDmaWriteDone> txDmaWriteEvent;
+
+ bool dmaDescFree;
+ bool dmaDataFree;
+
+ protected:
+ Tick txDelay;
+ Tick rxDelay;
+
+ void txReset();
+ void rxReset();
+ void regsReset();
+
+ void rxKick();
+ Tick rxKickTick;
+ typedef EventWrapper<NSGigE, &NSGigE::rxKick> RxKickEvent;
+ friend void RxKickEvent::process();
+ RxKickEvent rxKickEvent;
+
+ void txKick();
+ Tick txKickTick;
+ typedef EventWrapper<NSGigE, &NSGigE::txKick> TxKickEvent;
+ friend void TxKickEvent::process();
+ TxKickEvent txKickEvent;
+
+ void eepromKick();
+
+ /**
+ * Retransmit event
+ */
+ void transmit();
+ void txEventTransmit()
+ {
+ transmit();
+ if (txState == txFifoBlock)
+ txKick();
+ }
+ typedef EventWrapper<NSGigE, &NSGigE::txEventTransmit> TxEvent;
+ friend void TxEvent::process();
+ TxEvent txEvent;
+
+ void txDump() const;
+ void rxDump() const;
+
+ /**
+ * receive address filter
+ */
+ bool rxFilterEnable;
+ bool rxFilter(const EthPacketPtr &packet);
+ bool acceptBroadcast;
+ bool acceptMulticast;
+ bool acceptUnicast;
+ bool acceptPerfect;
+ bool acceptArp;
+ bool multicastHashEnable;
+
+ /**
+ * Interrupt management
+ */
+ void devIntrPost(uint32_t interrupts);
+ void devIntrClear(uint32_t interrupts);
+ void devIntrChangeMask();
+
+ Tick intrDelay;
+ Tick intrTick;
+ bool cpuPendingIntr;
+ void cpuIntrPost(Tick when);
+ void cpuInterrupt();
+ void cpuIntrClear();
+
+ typedef EventWrapper<NSGigE, &NSGigE::cpuInterrupt> IntrEvent;
+ friend void IntrEvent::process();
+ IntrEvent *intrEvent;
+ NSGigEInt *interface;
+
+ public:
+ struct Params : public PciDev::Params
+ {
+ Tick clock;
+ Tick intr_delay;
+ Tick tx_delay;
+ Tick rx_delay;
+ bool dma_desc_free;
+ bool dma_data_free;
+ Tick dma_read_delay;
+ Tick dma_write_delay;
+ Tick dma_read_factor;
+ Tick dma_write_factor;
+ bool rx_filter;
+ Net::EthAddr eaddr;
+ uint32_t tx_fifo_size;
+ uint32_t rx_fifo_size;
+ bool rx_thread;
+ bool tx_thread;
+ bool rss;
+ bool dma_no_allocate;
+ };
+
+ NSGigE(Params *params);
+ ~NSGigE();
+ const Params *params() const { return (const Params *)_params; }
+
+ virtual void writeConfig(int offset, const uint16_t data);
+
+ virtual Tick read(Packet *pkt);
+ virtual Tick write(Packet *pkt);
+
+ bool cpuIntrPending() const;
+ void cpuIntrAck() { cpuIntrClear(); }
+
+ bool recvPacket(EthPacketPtr packet);
+ void transferDone();
+
+ void setInterface(NSGigEInt *i) { assert(!interface); interface = i; }
+
+ virtual void serialize(std::ostream &os);
+ virtual void unserialize(Checkpoint *cp, const std::string &section);
+
+ public:
+ void regStats();
+
+ private:
+ Stats::Scalar<> txBytes;
+ Stats::Scalar<> rxBytes;
+ Stats::Scalar<> txPackets;
+ Stats::Scalar<> rxPackets;
+ Stats::Scalar<> txIpChecksums;
+ Stats::Scalar<> rxIpChecksums;
+ Stats::Scalar<> txTcpChecksums;
+ Stats::Scalar<> rxTcpChecksums;
+ Stats::Scalar<> txUdpChecksums;
+ Stats::Scalar<> rxUdpChecksums;
+ Stats::Scalar<> descDmaReads;
+ Stats::Scalar<> descDmaWrites;
+ Stats::Scalar<> descDmaRdBytes;
+ Stats::Scalar<> descDmaWrBytes;
+ Stats::Formula totBandwidth;
+ Stats::Formula totPackets;
+ Stats::Formula totBytes;
+ Stats::Formula totPacketRate;
+ Stats::Formula txBandwidth;
+ Stats::Formula rxBandwidth;
+ Stats::Formula txPacketRate;
+ Stats::Formula rxPacketRate;
+ Stats::Scalar<> postedSwi;
+ Stats::Formula coalescedSwi;
+ Stats::Scalar<> totalSwi;
+ Stats::Scalar<> postedRxIdle;
+ Stats::Formula coalescedRxIdle;
+ Stats::Scalar<> totalRxIdle;
+ Stats::Scalar<> postedRxOk;
+ Stats::Formula coalescedRxOk;
+ Stats::Scalar<> totalRxOk;
+ Stats::Scalar<> postedRxDesc;
+ Stats::Formula coalescedRxDesc;
+ Stats::Scalar<> totalRxDesc;
+ Stats::Scalar<> postedTxOk;
+ Stats::Formula coalescedTxOk;
+ Stats::Scalar<> totalTxOk;
+ Stats::Scalar<> postedTxIdle;
+ Stats::Formula coalescedTxIdle;
+ Stats::Scalar<> totalTxIdle;
+ Stats::Scalar<> postedTxDesc;
+ Stats::Formula coalescedTxDesc;
+ Stats::Scalar<> totalTxDesc;
+ Stats::Scalar<> postedRxOrn;
+ Stats::Formula coalescedRxOrn;
+ Stats::Scalar<> totalRxOrn;
+ Stats::Formula coalescedTotal;
+ Stats::Scalar<> postedInterrupts;
+ Stats::Scalar<> droppedPackets;
+};
+
+/*
+ * Ethernet Interface for an Ethernet Device
+ */
+class NSGigEInt : public EtherInt
+{
+ private:
+ NSGigE *dev;
+
+ public:
+ NSGigEInt(const std::string &name, NSGigE *d)
+ : EtherInt(name), dev(d) { dev->setInterface(this); }
+
+ virtual bool recvPacket(EthPacketPtr pkt) { return dev->recvPacket(pkt); }
+ virtual void sendDone() { dev->transferDone(); }
+};
+
+#endif // __DEV_NS_GIGE_HH__
diff --git a/dev/ns_gige_reg.h b/src/dev/ns_gige_reg.h
index 5f6fa2cc5..5f6fa2cc5 100644
--- a/dev/ns_gige_reg.h
+++ b/src/dev/ns_gige_reg.h
diff --git a/src/dev/pciconfigall.cc b/src/dev/pciconfigall.cc
new file mode 100644
index 000000000..14a28e86d
--- /dev/null
+++ b/src/dev/pciconfigall.cc
@@ -0,0 +1,224 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* @file
+ * PCI Configspace implementation
+ */
+
+#include <deque>
+#include <string>
+#include <vector>
+#include <bitset>
+
+#include "base/trace.hh"
+#include "dev/pciconfigall.hh"
+#include "dev/pcidev.hh"
+#include "dev/pcireg.h"
+#include "dev/platform.hh"
+#include "mem/packet.hh"
+#include "sim/builder.hh"
+#include "sim/system.hh"
+
+using namespace std;
+
+PciConfigAll::PciConfigAll(Params *p)
+ : BasicPioDevice(p)
+{
+ pioSize = 0xffffff;
+
+ // 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++)
+ for(int y=0; y < MAX_PCI_FUNC; y++)
+ devices[x][y] = NULL;
+}
+
+// If two interrupts share the same line largely bad things will happen.
+// Since we don't track how many times an interrupt was set and correspondingly
+// cleared two devices on the same interrupt line and assert and deassert each
+// others interrupt "line". Interrupts will not work correctly.
+void
+PciConfigAll::startup()
+{
+ bitset<256> intLines;
+ PciDev *tempDev;
+ uint8_t intline;
+
+ for (int x = 0; x < MAX_PCI_DEV; x++) {
+ for (int y = 0; y < MAX_PCI_FUNC; y++) {
+ if (devices[x][y] != NULL) {
+ tempDev = devices[x][y];
+ intline = tempDev->interruptLine();
+ if (intLines.test(intline))
+ warn("Interrupt line %#X is used multiple times"
+ "(You probably want to fix this).\n", (uint32_t)intline);
+ else
+ intLines.set(intline);
+ } // devices != NULL
+ } // PCI_FUNC
+ } // PCI_DEV
+
+}
+
+Tick
+PciConfigAll::read(Packet *pkt)
+{
+ assert(pkt->result == Packet::Unknown);
+ assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
+
+ Addr daddr = pkt->getAddr() - pioAddr;
+ int device = (daddr >> 11) & 0x1F;
+ int func = (daddr >> 8) & 0x7;
+ int reg = daddr & 0xFF;
+
+ pkt->time += pioDelay;
+ pkt->allocate();
+
+ DPRINTF(PciConfigAll, "read va=%#x da=%#x size=%d\n", pkt->getAddr(), daddr,
+ pkt->getSize());
+
+ switch (pkt->getSize()) {
+ 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");
+ }
+ pkt->result = Packet::Success;
+ return pioDelay;
+}
+
+Tick
+PciConfigAll::write(Packet *pkt)
+{
+ pkt->time += pioDelay;
+
+ assert(pkt->result == Packet::Unknown);
+ assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
+ assert(pkt->getSize() == sizeof(uint8_t) || pkt->getSize() == sizeof(uint16_t) ||
+ pkt->getSize() == sizeof(uint32_t));
+ Addr daddr = pkt->getAddr() - pioAddr;
+
+ int device = (daddr >> 11) & 0x1F;
+ int func = (daddr >> 8) & 0x7;
+ int reg = daddr & 0xFF;
+
+ if (devices[device][func] == NULL)
+ panic("Attempting to write to config space on non-existant device\n");
+
+ DPRINTF(PciConfigAll, "write - va=%#x size=%d data=%#x\n",
+ pkt->getAddr(), pkt->getSize(), pkt->get<uint32_t>());
+
+ switch (pkt->getSize()) {
+ 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");
+ }
+ pkt->result = Packet::Success;
+ return pioDelay;
+}
+
+void
+PciConfigAll::serialize(std::ostream &os)
+{
+ /*
+ * There is no state associated with this object that requires
+ * serialization. The only real state are the device pointers
+ * which are all setup by the constructor of the PciDev class
+ */
+}
+
+void
+PciConfigAll::unserialize(Checkpoint *cp, const std::string &section)
+{
+ /*
+ * There is no state associated with this object that requires
+ * serialization. The only real state are the device pointers
+ * which are all setup by the constructor of the PciDev class
+ */
+}
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(PciConfigAll)
+
+ Param<Addr> pio_addr;
+ Param<Tick> pio_latency;
+ SimObjectParam<Platform *> platform;
+ SimObjectParam<System *> system;
+
+END_DECLARE_SIM_OBJECT_PARAMS(PciConfigAll)
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(PciConfigAll)
+
+ 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)
+{
+ 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)
+
+#endif // DOXYGEN_SHOULD_SKIP_THIS
diff --git a/src/dev/pciconfigall.hh b/src/dev/pciconfigall.hh
new file mode 100644
index 000000000..df4eae448
--- /dev/null
+++ b/src/dev/pciconfigall.hh
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * @file
+ * PCI Config space implementation.
+ */
+
+#ifndef __PCICONFIGALL_HH__
+#define __PCICONFIGALL_HH__
+
+#include "dev/pcireg.h"
+#include "base/range.hh"
+#include "dev/io_device.hh"
+
+
+static const uint32_t MAX_PCI_DEV = 32;
+static const uint32_t MAX_PCI_FUNC = 8;
+
+class PciDev;
+
+/**
+ * PCI Config Space
+ * All of PCI config space needs to return -1 on Tsunami, except
+ * the devices that exist. This device maps the entire bus config
+ * space and passes the requests on to TsunamiPCIDev devices as
+ * appropriate.
+ */
+class PciConfigAll : public BasicPioDevice
+{
+ private:
+ /**
+ * Pointers to all the devices that are registered with this
+ * particular config space.
+ */
+ PciDev* devices[MAX_PCI_DEV][MAX_PCI_FUNC];
+
+ public:
+ /**
+ * Constructor for PCIConfigAll
+ * @param p parameters structure
+ */
+ PciConfigAll(Params *p);
+
+ /**
+ * Check if a device exists.
+ * @param pcidev PCI device to check
+ * @param pcifunc PCI function to check
+ * @return true if device exists, false otherwise
+ */
+ bool deviceExists(uint32_t pcidev, uint32_t pcifunc)
+ { return devices[pcidev][pcifunc] != NULL ? true : false; }
+
+ /**
+ * Registers a device with the config space object.
+ * @param pcidev PCI device to register
+ * @param pcifunc PCI function to register
+ * @param device device to register
+ */
+ void registerDevice(uint8_t pcidev, uint8_t pcifunc, PciDev *device)
+ { devices[pcidev][pcifunc] = device; }
+
+ /**
+ * 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 pkt Contains the address of the field to read.
+ * @return Amount of time to do the read
+ */
+ virtual Tick read(Packet *pkt);
+
+ /**
+ * Write to PCI config spcae. If the device does not exit the simulator
+ * panics. If it does it is passed on the PciDev::WriteConfig (or the virtual
+ * function that overrides it).
+ * @param req Contains the address to write to.
+ * @param data The data to write.
+ * @return The fault condition of the access.
+ */
+
+ virtual Tick write(Packet *pkt);
+
+ /**
+ * Start up function to check if more than one person is using an interrupt line
+ * and print a warning if such a case exists
+ */
+ virtual void startup();
+
+ /**
+ * Serialize this object to the given output stream.
+ * @param os The stream to serialize to.
+ */
+ virtual void serialize(std::ostream &os);
+
+ /**
+ * Reconstruct the state of this object from a checkpoint.
+ * @param cp The checkpoint use.
+ * @param section The section name of this object
+ */
+ virtual void unserialize(Checkpoint *cp, const std::string &section);
+};
+
+#endif // __PCICONFIGALL_HH__
diff --git a/src/dev/pcidev.cc b/src/dev/pcidev.cc
new file mode 100644
index 000000000..76392ccfe
--- /dev/null
+++ b/src/dev/pcidev.cc
@@ -0,0 +1,386 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* @file
+ * A single PCI device configuration space entry.
+ */
+
+#include <list>
+#include <string>
+#include <vector>
+
+#include "base/inifile.hh"
+#include "base/misc.hh"
+#include "base/str.hh" // for to_number
+#include "base/trace.hh"
+#include "dev/pciconfigall.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"
+
+using namespace std;
+
+PciDev::PciDev(Params *p)
+ : DmaDevice(p), plat(p->platform), configData(p->configData),
+ pioDelay(p->pio_delay)
+{
+ // copy the config data from the PciConfigData object
+ if (configData) {
+ memcpy(config.data, configData->config.data, sizeof(config.data));
+ memcpy(BARSize, configData->BARSize, sizeof(BARSize));
+ memcpy(BARAddrs, configData->BARAddrs, sizeof(BARAddrs));
+ } else
+ panic("NULL pointer to configuration data");
+
+ // Setup pointer in config space to point to this entry
+ if (p->configSpace->deviceExists(p->deviceNum, p->functionNum))
+ panic("Two PCI devices occuping same dev: %#x func: %#x",
+ p->deviceNum, p->functionNum);
+ else
+ p->configSpace->registerDevice(p->deviceNum, p->functionNum, this);
+}
+
+void
+PciDev::readConfig(int offset, uint8_t *data)
+{
+ if (offset >= PCI_DEVICE_SPECIFIC)
+ panic("Device specific PCI config space not implemented!\n");
+
+ *data = config.data[offset];
+
+ DPRINTF(PCIDEV,
+ "read device: %#x function: %#x register: %#x 1 bytes: data: %#x\n",
+ params()->deviceNum, params()->functionNum, offset, *data);
+}
+
+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]));
+}
+
+void
+PciDev::readConfig(int offset, uint16_t *data)
+{
+ if (offset >= PCI_DEVICE_SPECIFIC)
+ panic("Device specific PCI config space not implemented!\n");
+
+ *data = *(uint16_t*)&config.data[offset];
+
+ DPRINTF(PCIDEV,
+ "read device: %#x function: %#x register: %#x 2 bytes: data: %#x\n",
+ params()->deviceNum, params()->functionNum, offset, *data);
+}
+
+void
+PciDev::readConfig(int offset, uint32_t *data)
+{
+ if (offset >= PCI_DEVICE_SPECIFIC)
+ panic("Device specific PCI config space not implemented!\n");
+
+ *data = *(uint32_t*)&config.data[offset];
+
+ DPRINTF(PCIDEV,
+ "read device: %#x function: %#x register: %#x 4 bytes: data: %#x\n",
+ params()->deviceNum, params()->functionNum, offset, *data);
+}
+
+
+void
+PciDev::writeConfig(int offset, const uint8_t data)
+{
+ if (offset >= PCI_DEVICE_SPECIFIC)
+ panic("Device specific PCI config space not implemented!\n");
+
+ 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;
+ /* 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");
+ }
+}
+
+void
+PciDev::writeConfig(int offset, const uint16_t data)
+{
+ if (offset >= PCI_DEVICE_SPECIFIC)
+ panic("Device specific PCI config space not implemented!\n");
+
+ DPRINTF(PCIDEV,
+ "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");
+ }
+}
+
+
+void
+PciDev::writeConfig(int offset, const uint32_t data)
+{
+ if (offset >= PCI_DEVICE_SPECIFIC)
+ panic("Device specific PCI config space not implemented!\n");
+
+ 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;
+ }
+
+ // 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(
+ (~(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;
+
+ pioPort->sendStatusChange(Port::RangeChange);
+ }
+ }
+ 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:
+ DPRINTF(PCIDEV, "Writing to a read only register");
+ }
+}
+
+void
+PciDev::serialize(ostream &os)
+{
+ SERIALIZE_ARRAY(BARSize, sizeof(BARSize) / sizeof(BARSize[0]));
+ SERIALIZE_ARRAY(BARAddrs, sizeof(BARAddrs) / sizeof(BARAddrs[0]));
+ SERIALIZE_ARRAY(config.data, sizeof(config.data) / sizeof(config.data[0]));
+}
+
+void
+PciDev::unserialize(Checkpoint *cp, const std::string &section)
+{
+ UNSERIALIZE_ARRAY(BARSize, sizeof(BARSize) / sizeof(BARSize[0]));
+ UNSERIALIZE_ARRAY(BARAddrs, sizeof(BARAddrs) / sizeof(BARAddrs[0]));
+ UNSERIALIZE_ARRAY(config.data,
+ sizeof(config.data) / sizeof(config.data[0]));
+}
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(PciConfigData)
+
+ Param<uint16_t> VendorID;
+ Param<uint16_t> DeviceID;
+ Param<uint16_t> Command;
+ Param<uint16_t> Status;
+ Param<uint8_t> Revision;
+ Param<uint8_t> ProgIF;
+ Param<uint8_t> SubClassCode;
+ Param<uint8_t> ClassCode;
+ Param<uint8_t> CacheLineSize;
+ Param<uint8_t> LatencyTimer;
+ Param<uint8_t> HeaderType;
+ Param<uint8_t> BIST;
+ Param<uint32_t> BAR0;
+ Param<uint32_t> BAR1;
+ Param<uint32_t> BAR2;
+ Param<uint32_t> BAR3;
+ Param<uint32_t> BAR4;
+ Param<uint32_t> BAR5;
+ Param<uint32_t> CardbusCIS;
+ Param<uint16_t> SubsystemVendorID;
+ Param<uint16_t> SubsystemID;
+ Param<uint32_t> ExpansionROM;
+ Param<uint8_t> InterruptLine;
+ Param<uint8_t> InterruptPin;
+ Param<uint8_t> MinimumGrant;
+ Param<uint8_t> MaximumLatency;
+ Param<uint32_t> BAR0Size;
+ Param<uint32_t> BAR1Size;
+ Param<uint32_t> BAR2Size;
+ Param<uint32_t> BAR3Size;
+ Param<uint32_t> BAR4Size;
+ Param<uint32_t> BAR5Size;
+
+END_DECLARE_SIM_OBJECT_PARAMS(PciConfigData)
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(PciConfigData)
+
+ INIT_PARAM(VendorID, "Vendor ID"),
+ INIT_PARAM(DeviceID, "Device ID"),
+ INIT_PARAM_DFLT(Command, "Command Register", 0x00),
+ INIT_PARAM_DFLT(Status, "Status Register", 0x00),
+ INIT_PARAM_DFLT(Revision, "Device Revision", 0x00),
+ INIT_PARAM_DFLT(ProgIF, "Programming Interface", 0x00),
+ INIT_PARAM(SubClassCode, "Sub-Class Code"),
+ INIT_PARAM(ClassCode, "Class Code"),
+ INIT_PARAM_DFLT(CacheLineSize, "System Cacheline Size", 0x00),
+ INIT_PARAM_DFLT(LatencyTimer, "PCI Latency Timer", 0x00),
+ INIT_PARAM_DFLT(HeaderType, "PCI Header Type", 0x00),
+ INIT_PARAM_DFLT(BIST, "Built In Self Test", 0x00),
+ INIT_PARAM_DFLT(BAR0, "Base Address Register 0", 0x00),
+ INIT_PARAM_DFLT(BAR1, "Base Address Register 1", 0x00),
+ INIT_PARAM_DFLT(BAR2, "Base Address Register 2", 0x00),
+ INIT_PARAM_DFLT(BAR3, "Base Address Register 3", 0x00),
+ INIT_PARAM_DFLT(BAR4, "Base Address Register 4", 0x00),
+ INIT_PARAM_DFLT(BAR5, "Base Address Register 5", 0x00),
+ INIT_PARAM_DFLT(CardbusCIS, "Cardbus Card Information Structure", 0x00),
+ INIT_PARAM_DFLT(SubsystemVendorID, "Subsystem Vendor ID", 0x00),
+ INIT_PARAM_DFLT(SubsystemID, "Subsystem ID", 0x00),
+ INIT_PARAM_DFLT(ExpansionROM, "Expansion ROM Base Address Register", 0x00),
+ INIT_PARAM(InterruptLine, "Interrupt Line Register"),
+ INIT_PARAM(InterruptPin, "Interrupt Pin Register"),
+ INIT_PARAM_DFLT(MinimumGrant, "Minimum Grant", 0x00),
+ INIT_PARAM_DFLT(MaximumLatency, "Maximum Latency", 0x00),
+ INIT_PARAM_DFLT(BAR0Size, "Base Address Register 0 Size", 0x00),
+ INIT_PARAM_DFLT(BAR1Size, "Base Address Register 1 Size", 0x00),
+ INIT_PARAM_DFLT(BAR2Size, "Base Address Register 2 Size", 0x00),
+ INIT_PARAM_DFLT(BAR3Size, "Base Address Register 3 Size", 0x00),
+ INIT_PARAM_DFLT(BAR4Size, "Base Address Register 4 Size", 0x00),
+ INIT_PARAM_DFLT(BAR5Size, "Base Address Register 5 Size", 0x00)
+
+END_INIT_SIM_OBJECT_PARAMS(PciConfigData)
+
+CREATE_SIM_OBJECT(PciConfigData)
+{
+ PciConfigData *data = new PciConfigData(getInstanceName());
+
+ data->config.vendor = htole(VendorID);
+ data->config.device = htole(DeviceID);
+ data->config.command = htole(Command);
+ data->config.status = htole(Status);
+ data->config.revision = htole(Revision);
+ data->config.progIF = htole(ProgIF);
+ data->config.subClassCode = htole(SubClassCode);
+ data->config.classCode = htole(ClassCode);
+ data->config.cacheLineSize = htole(CacheLineSize);
+ data->config.latencyTimer = htole(LatencyTimer);
+ data->config.headerType = htole(HeaderType);
+ data->config.bist = htole(BIST);
+
+ data->config.baseAddr0 = htole(BAR0);
+ data->config.baseAddr1 = htole(BAR1);
+ data->config.baseAddr2 = htole(BAR2);
+ data->config.baseAddr3 = htole(BAR3);
+ data->config.baseAddr4 = htole(BAR4);
+ data->config.baseAddr5 = htole(BAR5);
+ data->config.cardbusCIS = htole(CardbusCIS);
+ data->config.subsystemVendorID = htole(SubsystemVendorID);
+ data->config.subsystemID = htole(SubsystemVendorID);
+ data->config.expansionROM = htole(ExpansionROM);
+ data->config.interruptLine = htole(InterruptLine);
+ data->config.interruptPin = htole(InterruptPin);
+ data->config.minimumGrant = htole(MinimumGrant);
+ data->config.maximumLatency = htole(MaximumLatency);
+
+ data->BARSize[0] = BAR0Size;
+ data->BARSize[1] = BAR1Size;
+ data->BARSize[2] = BAR2Size;
+ data->BARSize[3] = BAR3Size;
+ data->BARSize[4] = BAR4Size;
+ data->BARSize[5] = BAR5Size;
+
+ return data;
+}
+
+REGISTER_SIM_OBJECT("PciConfigData", PciConfigData)
+
+#endif // DOXYGEN_SHOULD_SKIP_THIS
diff --git a/src/dev/pcidev.hh b/src/dev/pcidev.hh
new file mode 100644
index 000000000..fc4773908
--- /dev/null
+++ b/src/dev/pcidev.hh
@@ -0,0 +1,230 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* @file
+ * Interface for devices using PCI configuration
+ */
+
+#ifndef __DEV_PCIDEV_HH__
+#define __DEV_PCIDEV_HH__
+
+#include "dev/io_device.hh"
+#include "dev/pcireg.h"
+#include "dev/platform.hh"
+
+#define BAR_IO_MASK 0x3
+#define BAR_MEM_MASK 0xF
+#define BAR_IO_SPACE_BIT 0x1
+#define BAR_IO_SPACE(x) ((x) & BAR_IO_SPACE_BIT)
+#define BAR_NUMBER(x) (((x) - PCI0_BASE_ADDR0) >> 0x2);
+
+class PciConfigAll;
+
+
+/**
+ * This class encapulates the first 64 bytes of a singles PCI
+ * devices config space that in configured by the configuration file.
+ */
+class PciConfigData : public SimObject
+{
+ public:
+ /**
+ * Constructor to initialize the devices config space to 0.
+ */
+ PciConfigData(const std::string &name)
+ : SimObject(name)
+ {
+ memset(config.data, 0, sizeof(config.data));
+ memset(BARAddrs, 0, sizeof(BARAddrs));
+ memset(BARSize, 0, sizeof(BARSize));
+ }
+
+ /** The first 64 bytes */
+ PCIConfig config;
+
+ /** The size of the BARs */
+ uint32_t BARSize[6];
+
+ /** The addresses of the BARs */
+ Addr BARAddrs[6];
+};
+
+/**
+ * PCI device, base implemnation is only config space.
+ * Each device is connected to a PCIConfigSpace device
+ * which returns -1 for everything but the pcidevs that
+ * register with it. This object registers with the PCIConfig space
+ * object.
+ */
+class PciDev : public DmaDevice
+{
+ public:
+ struct Params : public ::PioDevice::Params
+ {
+ /**
+ * A pointer to the configspace all object that calls us when
+ * a read comes to this particular device/function.
+ */
+ PciConfigAll *configSpace;
+
+ /**
+ * A pointer to the object that contains the first 64 bytes of
+ * config space
+ */
+ PciConfigData *configData;
+
+ /** The bus number we are on */
+ uint32_t busNum;
+
+ /** The device number we have */
+ uint32_t deviceNum;
+
+ /** The function number */
+ uint32_t functionNum;
+
+ /** The latency for pio accesses. */
+ Tick pio_delay;
+ };
+
+ public:
+ const Params *params() const { return (const Params *)_params; }
+
+ protected:
+ /** The current config space. Unlike the PciConfigData this is
+ * updated during simulation while continues to reflect what was
+ * in the config file.
+ */
+ PCIConfig config;
+
+ /** The size of the BARs */
+ uint32_t BARSize[6];
+
+ /** The current address mapping of the BARs */
+ Addr BARAddrs[6];
+
+ bool
+ isBAR(Addr addr, int bar) const
+ {
+ assert(bar >= 0 && bar < 6);
+ return BARAddrs[bar] <= addr && addr < BARAddrs[bar] + BARSize[bar];
+ }
+
+ int
+ getBAR(Addr addr)
+ {
+ for (int i = 0; i <= 5; ++i)
+ if (isBAR(addr, i))
+ return i;
+
+ return -1;
+ }
+
+ bool
+ getBAR(Addr paddr, Addr &daddr, int &bar)
+ {
+ int b = getBAR(paddr);
+ if (b < 0)
+ return false;
+
+ daddr = paddr - BARAddrs[b];
+ bar = b;
+ return true;
+ }
+
+ protected:
+ Platform *plat;
+ PciConfigData *configData;
+ Tick pioDelay;
+
+ public:
+ Addr pciToDma(Addr pciAddr) const
+ { return plat->pciToDma(pciAddr); }
+
+ void
+ intrPost()
+ { plat->postPciInt(configData->config.interruptLine); }
+
+ void
+ intrClear()
+ { plat->clearPciInt(configData->config.interruptLine); }
+
+ uint8_t
+ interruptLine()
+ { return configData->config.interruptLine; }
+
+ /** 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
+ * a PciConfigAll object.
+ */
+ PciDev(Params *params);
+
+ /**
+ * 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
+ * for normal operations that it does not need to override.
+ * @param offset the offset into config space
+ * @param size the size of the write
+ * @param data the data to write
+ */
+ 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);
+
+
+ /**
+ * Read from 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
+ * for normal operations that it does not need to override.
+ * @param offset the offset into config space
+ * @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, 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.
+ * @param os The stream to serialize to.
+ */
+ virtual void serialize(std::ostream &os);
+
+ /**
+ * Reconstruct the state of this object from a checkpoint.
+ * @param cp The checkpoint use.
+ * @param section The section name of this object
+ */
+ virtual void unserialize(Checkpoint *cp, const std::string &section);
+};
+#endif // __DEV_PCIDEV_HH__
diff --git a/dev/pcireg.h b/src/dev/pcireg.h
index 9d2737c20..9d2737c20 100644
--- a/dev/pcireg.h
+++ b/src/dev/pcireg.h
diff --git a/dev/pitreg.h b/src/dev/pitreg.h
index 5fe1cf03f..5fe1cf03f 100644
--- a/dev/pitreg.h
+++ b/src/dev/pitreg.h
diff --git a/src/dev/pktfifo.cc b/src/dev/pktfifo.cc
new file mode 100644
index 000000000..922a66912
--- /dev/null
+++ b/src/dev/pktfifo.cc
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "base/misc.hh"
+#include "dev/pktfifo.hh"
+
+using namespace std;
+
+bool
+PacketFifo::copyout(void *dest, int offset, int len)
+{
+ char *data = (char *)dest;
+ if (offset + len >= size())
+ return false;
+
+ list<EthPacketPtr>::iterator p = fifo.begin();
+ list<EthPacketPtr>::iterator end = fifo.end();
+ while (len > 0) {
+ while (offset >= (*p)->length) {
+ offset -= (*p)->length;
+ ++p;
+ }
+
+ if (p == end)
+ panic("invalid fifo");
+
+ int size = min((*p)->length - offset, len);
+ memcpy(data, (*p)->data, size);
+ offset = 0;
+ len -= size;
+ data += size;
+ ++p;
+ }
+
+ return true;
+}
+
+
+void
+PacketFifo::serialize(const string &base, ostream &os)
+{
+ paramOut(os, base + ".size", _size);
+ paramOut(os, base + ".maxsize", _maxsize);
+ paramOut(os, base + ".reserved", _reserved);
+ paramOut(os, base + ".packets", fifo.size());
+
+ int i = 0;
+ 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;
+ ++i;
+ }
+}
+
+void
+PacketFifo::unserialize(const string &base, Checkpoint *cp,
+ const string &section)
+{
+ paramIn(cp, section, base + ".size", _size);
+// paramIn(cp, section, base + ".maxsize", _maxsize);
+ paramIn(cp, section, base + ".reserved", _reserved);
+ int fifosize;
+ paramIn(cp, section, base + ".packets", fifosize);
+
+ fifo.clear();
+
+ for (int i = 0; i < fifosize; ++i) {
+ EthPacketPtr p = new EthPacketData(16384);
+ p->unserialize(csprintf("%s.packet%d", base, i), cp, section);
+ fifo.push_back(p);
+ }
+}
diff --git a/src/dev/pktfifo.hh b/src/dev/pktfifo.hh
new file mode 100644
index 000000000..336da22d8
--- /dev/null
+++ b/src/dev/pktfifo.hh
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __DEV_PKTFIFO_HH__
+#define __DEV_PKTFIFO_HH__
+
+#include <iosfwd>
+#include <list>
+#include <string>
+
+#include "dev/etherpkt.hh"
+#include "sim/serialize.hh"
+
+class Checkpoint;
+class PacketFifo
+{
+ public:
+ typedef std::list<EthPacketPtr> fifo_list;
+ typedef fifo_list::iterator iterator;
+
+ protected:
+ std::list<EthPacketPtr> fifo;
+ int _maxsize;
+ int _size;
+ int _reserved;
+
+ public:
+ explicit PacketFifo(int max) : _maxsize(max), _size(0), _reserved(0) {}
+ virtual ~PacketFifo() {}
+
+ int packets() const { return fifo.size(); }
+ int maxsize() const { return _maxsize; }
+ int size() const { return _size; }
+ int reserved() const { return _reserved; }
+ int avail() const { return _maxsize - _size - _reserved; }
+ bool empty() const { return size() <= 0; }
+ bool full() const { return avail() <= 0; }
+
+ int reserve(int len = 0)
+ {
+ _reserved += len;
+ assert(avail() >= 0);
+ return _reserved;
+ }
+
+ iterator begin() { return fifo.begin(); }
+ iterator end() { return fifo.end(); }
+
+ EthPacketPtr front() { return fifo.front(); }
+
+ bool push(EthPacketPtr ptr)
+ {
+ assert(ptr->length);
+ assert(_reserved <= ptr->length);
+ assert(ptr->slack == 0);
+ if (avail() < ptr->length - _reserved)
+ return false;
+
+ _size += ptr->length;
+ fifo.push_back(ptr);
+ _reserved = 0;
+ return true;
+ }
+
+ void pop()
+ {
+ if (empty())
+ return;
+
+ EthPacketPtr &packet = fifo.front();
+ _size -= packet->length;
+ _size -= packet->slack;
+ packet->slack = 0;
+ packet = NULL;
+ fifo.pop_front();
+ }
+
+ void clear()
+ {
+ for (iterator i = begin(); i != end(); ++i)
+ (*i)->slack = 0;
+ fifo.clear();
+ _size = 0;
+ _reserved = 0;
+ }
+
+ void remove(iterator i)
+ {
+ EthPacketPtr &packet = *i;
+ if (i != fifo.begin()) {
+ iterator prev = i;
+ --prev;
+ assert(prev != fifo.end());
+ (*prev)->slack += packet->length;
+ } else {
+ _size -= packet->length;
+ _size -= packet->slack;
+ }
+
+ packet->slack = 0;
+ packet = NULL;
+ fifo.erase(i);
+ }
+
+ bool copyout(void *dest, int offset, int len);
+
+ int countPacketsBefore(iterator end)
+ {
+ iterator i = fifo.begin();
+ int count = 0;
+
+ while (i != end) {
+ ++count;
+ ++i;
+ }
+
+ return count;
+ }
+
+ int countPacketsAfter(iterator i)
+ {
+ iterator end = fifo.end();
+ int count = 0;
+
+ while (i != end) {
+ ++count;
+ ++i;
+ }
+
+ return count;
+ }
+
+
+/**
+ * Serialization stuff
+ */
+ public:
+ void serialize(const std::string &base, std::ostream &os);
+ void unserialize(const std::string &base,
+ Checkpoint *cp, const std::string &section);
+};
+
+#endif // __DEV_PKTFIFO_HH__
diff --git a/src/dev/platform.cc b/src/dev/platform.cc
new file mode 100644
index 000000000..9d10e0828
--- /dev/null
+++ b/src/dev/platform.cc
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "dev/platform.hh"
+#include "sim/builder.hh"
+#include "sim/sim_exit.hh"
+
+using namespace std;
+using namespace TheISA;
+
+Platform::Platform(const string &name, IntrControl *intctrl)
+ : SimObject(name), intrctrl(intctrl)
+{
+}
+
+Platform::~Platform()
+{
+}
+
+void
+Platform::postPciInt(int line)
+{
+ panic("No PCI interrupt support in platform.");
+}
+
+void
+Platform::clearPciInt(int line)
+{
+ panic("No PCI interrupt support in platform.");
+}
+
+Addr
+Platform::pciToDma(Addr pciAddr) const
+{
+ panic("No PCI dma support in platform.");
+}
+
+DEFINE_SIM_OBJECT_CLASS_NAME("Platform", Platform)
+
diff --git a/src/dev/platform.hh b/src/dev/platform.hh
new file mode 100644
index 000000000..f149ca2fb
--- /dev/null
+++ b/src/dev/platform.hh
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * Generic interface for platforms
+ */
+
+#ifndef __DEV_PLATFORM_HH__
+#define __DEV_PLATFORM_HH__
+
+#include "sim/sim_object.hh"
+#include "arch/isa_traits.hh"
+
+class PciConfigAll;
+class IntrControl;
+class SimConsole;
+class Uart;
+class System;
+
+class Platform : public SimObject
+{
+ public:
+ /** Pointer to the interrupt controller */
+ IntrControl *intrctrl;
+
+ /** Pointer to the PCI configuration space */
+ PciConfigAll *pciconfig;
+
+ /** 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);
+ 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;
+ virtual void postPciInt(int line);
+ virtual void clearPciInt(int line);
+ virtual Addr pciToDma(Addr pciAddr) const;
+};
+
+#endif // __DEV_PLATFORM_HH__
diff --git a/dev/rtcreg.h b/src/dev/rtcreg.h
index 5025a0e95..5025a0e95 100644
--- a/dev/rtcreg.h
+++ b/src/dev/rtcreg.h
diff --git a/src/dev/simconsole.cc b/src/dev/simconsole.cc
new file mode 100644
index 000000000..e33fa18b5
--- /dev/null
+++ b/src/dev/simconsole.cc
@@ -0,0 +1,413 @@
+/*
+ * 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
+ * Implements the user interface to a serial console
+ */
+
+#include <sys/ioctl.h>
+#include <sys/termios.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <poll.h>
+#include <unistd.h>
+
+#include <iostream>
+#include <fstream>
+#include <sstream>
+#include <string>
+
+#include "base/misc.hh"
+#include "base/output.hh"
+#include "base/socket.hh"
+#include "base/trace.hh"
+#include "dev/platform.hh"
+#include "dev/simconsole.hh"
+#include "dev/uart.hh"
+#include "sim/builder.hh"
+
+using namespace std;
+
+////////////////////////////////////////////////////////////////////////
+//
+//
+
+SimConsole::Event::Event(SimConsole *c, int fd, int e)
+ : PollEvent(fd, e), cons(c)
+{
+}
+
+void
+SimConsole::Event::process(int revent)
+{
+ if (revent & POLLIN)
+ cons->data();
+ else if (revent & POLLNVAL)
+ cons->detach();
+}
+
+SimConsole::SimConsole(const string &name, ostream *os, int num)
+ : SimObject(name), event(NULL), number(num), in_fd(-1), out_fd(-1),
+ listener(NULL), txbuf(16384), rxbuf(16384), outfile(os)
+#if TRACING_ON == 1
+ , linebuf(16384)
+#endif
+{
+ if (outfile)
+ outfile->setf(ios::unitbuf);
+}
+
+SimConsole::~SimConsole()
+{
+ close();
+}
+
+void
+SimConsole::close()
+{
+ if (in_fd != -1)
+ ::close(in_fd);
+
+ if (out_fd != in_fd && out_fd != -1)
+ ::close(out_fd);
+}
+
+void
+SimConsole::attach(int in, int out, ConsoleListener *l)
+{
+ in_fd = in;
+ out_fd = out;
+ listener = l;
+
+ event = new Event(this, in, POLLIN);
+ pollQueue.schedule(event);
+
+ stringstream stream;
+ ccprintf(stream, "==== m5 slave console: Console %d ====", number);
+
+ // we need an actual carriage return followed by a newline for the
+ // terminal
+ stream << "\r\n";
+
+ write((const uint8_t *)stream.str().c_str(), stream.str().size());
+
+
+ DPRINTFN("attach console %d\n", number);
+
+ txbuf.readall(out);
+}
+
+void
+SimConsole::detach()
+{
+ close();
+ in_fd = -1;
+ out_fd = -1;
+
+ pollQueue.remove(event);
+
+ if (listener) {
+ listener->add(this);
+ listener = NULL;
+ }
+
+ DPRINTFN("detach console %d\n", number);
+}
+
+void
+SimConsole::data()
+{
+ uint8_t buf[1024];
+ int len;
+
+ len = read(buf, sizeof(buf));
+ if (len) {
+ rxbuf.write((char *)buf, len);
+ // Inform the UART there is data available
+ uart->dataAvailable();
+ }
+}
+
+size_t
+SimConsole::read(uint8_t *buf, size_t len)
+{
+ if (in_fd < 0)
+ panic("Console not properly attached.\n");
+
+ size_t ret;
+ do {
+ ret = ::read(in_fd, buf, len);
+ } while (ret == -1 && errno == EINTR);
+
+
+ if (ret < 0)
+ DPRINTFN("Read failed.\n");
+
+ if (ret <= 0) {
+ detach();
+ return 0;
+ }
+
+ return ret;
+}
+
+// Console output.
+size_t
+SimConsole::write(const uint8_t *buf, size_t len)
+{
+ if (out_fd < 0)
+ panic("Console not properly attached.\n");
+
+ size_t ret;
+ for (;;) {
+ ret = ::write(out_fd, buf, len);
+
+ if (ret >= 0)
+ break;
+
+ if (errno != EINTR)
+ detach();
+ }
+
+ return ret;
+}
+
+#define MORE_PENDING (ULL(1) << 61)
+#define RECEIVE_SUCCESS (ULL(0) << 62)
+#define RECEIVE_NONE (ULL(2) << 62)
+#define RECEIVE_ERROR (ULL(3) << 62)
+
+uint8_t
+SimConsole::in()
+{
+ bool empty;
+ uint8_t c;
+
+ empty = rxbuf.empty();
+ assert(!empty);
+ rxbuf.read((char *)&c, 1);
+ empty = rxbuf.empty();
+
+
+ DPRINTF(ConsoleVerbose, "in: \'%c\' %#02x more: %d\n",
+ isprint(c) ? c : ' ', c, !empty);
+
+ return c;
+}
+
+uint64_t
+SimConsole::console_in()
+{
+ uint64_t value;
+
+ if (dataAvailable()) {
+ value = RECEIVE_SUCCESS | in();
+ if (!rxbuf.empty())
+ value |= MORE_PENDING;
+ } else {
+ value = RECEIVE_NONE;
+ }
+
+ DPRINTF(ConsoleVerbose, "console_in: return: %#x\n", value);
+
+ return value;
+}
+
+void
+SimConsole::out(char c)
+{
+#if TRACING_ON == 1
+ if (DTRACE(Console)) {
+ static char last = '\0';
+
+ if (c != '\n' && c != '\r' ||
+ last != '\n' && last != '\r') {
+ if (c == '\n' || c == '\r') {
+ int size = linebuf.size();
+ char *buffer = new char[size + 1];
+ linebuf.read(buffer, size);
+ buffer[size] = '\0';
+ DPRINTF(Console, "%s\n", buffer);
+ delete [] buffer;
+ } else {
+ linebuf.write(c);
+ }
+ }
+
+ last = c;
+ }
+#endif
+
+ txbuf.write(c);
+
+ if (out_fd >= 0)
+ write(c);
+
+ if (outfile)
+ outfile->write(&c, 1);
+
+ DPRINTF(ConsoleVerbose, "out: \'%c\' %#02x\n",
+ isprint(c) ? c : ' ', (int)c);
+
+}
+
+
+void
+SimConsole::serialize(ostream &os)
+{
+}
+
+void
+SimConsole::unserialize(Checkpoint *cp, const std::string &section)
+{
+}
+
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(SimConsole)
+
+ SimObjectParam<ConsoleListener *> listener;
+ SimObjectParam<IntrControl *> intr_control;
+ Param<string> output;
+ Param<bool> append_name;
+ Param<int> number;
+
+END_DECLARE_SIM_OBJECT_PARAMS(SimConsole)
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(SimConsole)
+
+ INIT_PARAM(listener, "console listener"),
+ INIT_PARAM(intr_control, "interrupt controller"),
+ INIT_PARAM(output, "file to dump output to"),
+ INIT_PARAM_DFLT(append_name, "append name() to filename", true),
+ INIT_PARAM_DFLT(number, "console number", 0)
+
+END_INIT_SIM_OBJECT_PARAMS(SimConsole)
+
+CREATE_SIM_OBJECT(SimConsole)
+{
+ string filename = output;
+ ostream *stream = NULL;
+
+ if (!filename.empty()) {
+ if (append_name)
+ filename += "." + getInstanceName();
+ stream = simout.find(filename);
+ }
+
+ SimConsole *console = new SimConsole(getInstanceName(), stream, number);
+ ((ConsoleListener *)listener)->add(console);
+
+ return console;
+}
+
+REGISTER_SIM_OBJECT("SimConsole", SimConsole)
+
+////////////////////////////////////////////////////////////////////////
+//
+//
+
+ConsoleListener::ConsoleListener(const string &name)
+ : SimObject(name), event(NULL)
+{}
+
+ConsoleListener::~ConsoleListener()
+{
+ if (event)
+ delete event;
+}
+
+void
+ConsoleListener::Event::process(int revent)
+{
+ listener->accept();
+}
+
+///////////////////////////////////////////////////////////////////////
+// socket creation and console attach
+//
+
+void
+ConsoleListener::listen(int port)
+{
+ while (!listener.listen(port, true)) {
+ DPRINTF(Console,
+ ": can't bind address console port %d inuse PID %d\n",
+ port, getpid());
+ port++;
+ }
+
+ ccprintf(cerr, "Listening for console connection on port %d\n", port);
+
+ event = new Event(this, listener.getfd(), POLLIN);
+ pollQueue.schedule(event);
+}
+
+void
+ConsoleListener::add(SimConsole *cons)
+{ ConsoleList.push_back(cons);}
+
+void
+ConsoleListener::accept()
+{
+ if (!listener.islistening())
+ panic("%s: cannot accept a connection if not listening!", name());
+
+ int sfd = listener.accept(true);
+ if (sfd != -1) {
+ iter_t i = ConsoleList.begin();
+ iter_t end = ConsoleList.end();
+ if (i == end) {
+ close(sfd);
+ } else {
+ (*i)->attach(sfd, this);
+ i = ConsoleList.erase(i);
+ }
+ }
+}
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(ConsoleListener)
+
+ Param<int> port;
+
+END_DECLARE_SIM_OBJECT_PARAMS(ConsoleListener)
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(ConsoleListener)
+
+ INIT_PARAM_DFLT(port, "listen port", 3456)
+
+END_INIT_SIM_OBJECT_PARAMS(ConsoleListener)
+
+CREATE_SIM_OBJECT(ConsoleListener)
+{
+ ConsoleListener *listener = new ConsoleListener(getInstanceName());
+ listener->listen(port);
+
+ return listener;
+}
+
+REGISTER_SIM_OBJECT("ConsoleListener", ConsoleListener)
diff --git a/src/dev/simconsole.hh b/src/dev/simconsole.hh
new file mode 100644
index 000000000..64d1f6717
--- /dev/null
+++ b/src/dev/simconsole.hh
@@ -0,0 +1,165 @@
+/*
+ * 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
+ * User Console Interface
+ */
+
+#ifndef __CONSOLE_HH__
+#define __CONSOLE_HH__
+
+#include <iostream>
+
+#include "base/circlebuf.hh"
+#include "cpu/intr_control.hh"
+#include "base/pollevent.hh"
+#include "base/socket.hh"
+#include "sim/sim_object.hh"
+
+class ConsoleListener;
+class Uart;
+
+class SimConsole : public SimObject
+{
+ public:
+ Uart *uart;
+
+ protected:
+ class Event : public PollEvent
+ {
+ protected:
+ SimConsole *cons;
+
+ public:
+ Event(SimConsole *c, int fd, int e);
+ void process(int revent);
+ };
+
+ friend class Event;
+ Event *event;
+
+ protected:
+ int number;
+ int in_fd;
+ int out_fd;
+ ConsoleListener *listener;
+
+ public:
+ SimConsole(const std::string &name, std::ostream *os, int num);
+ ~SimConsole();
+
+ protected:
+ CircleBuf txbuf;
+ CircleBuf rxbuf;
+ std::ostream *outfile;
+#if TRACING_ON == 1
+ CircleBuf linebuf;
+#endif
+
+ public:
+ ///////////////////////
+ // Terminal Interface
+
+ void attach(int fd, ConsoleListener *l = NULL) { attach(fd, fd, l); }
+ void attach(int in, int out, ConsoleListener *l = NULL);
+ void detach();
+
+ void data();
+
+ void close();
+ void read(uint8_t &c) { read(&c, 1); }
+ size_t read(uint8_t *buf, size_t len);
+ void write(uint8_t c) { write(&c, 1); }
+ size_t write(const uint8_t *buf, size_t len);
+
+ public:
+ /////////////////
+ // OS interface
+
+ // Get a character from the console.
+ uint8_t in();
+
+ // get a character from the console in the console specific format
+ // corresponds to GETC:
+ // retval<63:61>
+ // 000: success: character received
+ // 001: success: character received, more pending
+ // 100: failure: no character ready
+ // 110: failure: character received with error
+ // 111: failure: character received with error, more pending
+ // retval<31:0>
+ // character read from console
+ //
+ // Interrupts are cleared when the buffer is empty.
+ uint64_t console_in();
+
+ // Send a character to the console
+ void out(char c);
+
+ //Ask the console if data is available
+ bool dataAvailable() { return !rxbuf.empty(); }
+
+ virtual void serialize(std::ostream &os);
+ virtual void unserialize(Checkpoint *cp, const std::string &section);
+};
+
+class ConsoleListener : public SimObject
+{
+ protected:
+ class Event : public PollEvent
+ {
+ protected:
+ ConsoleListener *listener;
+
+ public:
+ Event(ConsoleListener *l, int fd, int e)
+ : PollEvent(fd, e), listener(l) {}
+ void process(int revent);
+ };
+
+ friend class Event;
+ Event *event;
+
+ typedef std::list<SimConsole *> list_t;
+ typedef list_t::iterator iter_t;
+ list_t ConsoleList;
+
+ protected:
+ ListenSocket listener;
+
+ public:
+ ConsoleListener(const std::string &name);
+ ~ConsoleListener();
+
+ void add(SimConsole *cons);
+
+ void accept();
+ void listen(int port);
+};
+
+#endif // __CONSOLE_HH__
diff --git a/src/dev/simple_disk.cc b/src/dev/simple_disk.cc
new file mode 100644
index 000000000..9eee4668c
--- /dev/null
+++ b/src/dev/simple_disk.cc
@@ -0,0 +1,111 @@
+/*
+ * 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
+ * Simple disk interface for the system console
+ */
+
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <cstring>
+#include <string>
+
+#include "base/misc.hh"
+#include "base/trace.hh"
+#include "dev/disk_image.hh"
+#include "dev/simple_disk.hh"
+#include "mem/port.hh"
+#include "sim/builder.hh"
+#include "sim/system.hh"
+
+using namespace std;
+
+SimpleDisk::SimpleDisk(const string &name, System *sys, DiskImage *img)
+ : SimObject(name), system(sys), image(img)
+{}
+
+SimpleDisk::~SimpleDisk()
+{}
+
+
+void
+SimpleDisk::read(Addr addr, baddr_t block, int count) const
+{
+ uint8_t *data = new uint8_t[SectorSize * count];
+
+ if (count & (SectorSize - 1))
+ panic("Not reading a multiple of a sector (count = %d)", count);
+
+ 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
+SimpleDisk::write(Addr addr, baddr_t block, int count)
+{
+ panic("unimplemented!\n");
+
+#if 0
+ uint8_t *data = physmem->dma_addr(addr, count);
+ if (!data)
+ panic("dma out of range! write addr=%#x count=%d\n", addr, count);
+
+ image->write(data, block, count);
+#endif
+}
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(SimpleDisk)
+
+ SimObjectParam<System *> system;
+ SimObjectParam<DiskImage *> disk;
+
+END_DECLARE_SIM_OBJECT_PARAMS(SimpleDisk)
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(SimpleDisk)
+
+ INIT_PARAM(system, "System pointer"),
+ INIT_PARAM(disk, "Disk Image")
+
+END_INIT_SIM_OBJECT_PARAMS(SimpleDisk)
+
+CREATE_SIM_OBJECT(SimpleDisk)
+{
+ return new SimpleDisk(getInstanceName(), system, disk);
+}
+
+REGISTER_SIM_OBJECT("SimpleDisk", SimpleDisk)
diff --git a/src/dev/simple_disk.hh b/src/dev/simple_disk.hh
new file mode 100644
index 000000000..19967f208
--- /dev/null
+++ b/src/dev/simple_disk.hh
@@ -0,0 +1,62 @@
+/*
+ * 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
+ * Simple disk interface for the system console
+ */
+
+#ifndef __DEV_SIMPLE_DISK_HH__
+#define __DEV_SIMPLE_DISK_HH__
+
+#include "sim/sim_object.hh"
+#include "arch/isa_traits.hh"
+
+class DiskImage;
+class System;
+
+/*
+ * Trivial interface to a disk image used by the System Console
+ */
+class SimpleDisk : public SimObject
+{
+ public:
+ typedef uint64_t baddr_t;
+
+ protected:
+ System *system;
+ DiskImage *image;
+
+ public:
+ SimpleDisk(const std::string &name, System *sys, DiskImage *img);
+ ~SimpleDisk();
+
+ void read(Addr addr, baddr_t block, int count) const;
+ void write(Addr addr, baddr_t block, int count);
+};
+
+#endif // __DEV_SIMPLE_DISK_HH__
diff --git a/src/dev/sinic.cc b/src/dev/sinic.cc
new file mode 100644
index 000000000..31fbc49aa
--- /dev/null
+++ b/src/dev/sinic.cc
@@ -0,0 +1,1756 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <deque>
+#include <limits>
+#include <string>
+
+#include "base/inet.hh"
+#include "cpu/exec_context.hh"
+#include "cpu/intr_control.hh"
+#include "dev/etherlink.hh"
+#include "dev/sinic.hh"
+#include "dev/pciconfigall.hh"
+#include "mem/packet.hh"
+#include "sim/builder.hh"
+#include "sim/debug.hh"
+#include "sim/eventq.hh"
+#include "sim/host.hh"
+#include "sim/stats.hh"
+#include "arch/vtophys.hh"
+
+using namespace Net;
+using namespace TheISA;
+
+namespace Sinic {
+
+const char *RxStateStrings[] =
+{
+ "rxIdle",
+ "rxFifoBlock",
+ "rxBeginCopy",
+ "rxCopy",
+ "rxCopyDone"
+};
+
+const char *TxStateStrings[] =
+{
+ "txIdle",
+ "txFifoBlock",
+ "txBeginCopy",
+ "txCopy",
+ "txCopyDone"
+};
+
+
+///////////////////////////////////////////////////////////////////////
+//
+// Sinic PCI Device
+//
+Base::Base(Params *p)
+ : PciDev(p), rxEnable(false), txEnable(false), clock(p->clock),
+ intrDelay(p->intr_delay), intrTick(0), cpuIntrEnable(false),
+ cpuPendingIntr(false), intrEvent(0), interface(NULL)
+{
+}
+
+Device::Device(Params *p)
+ : Base(p), 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),
+ dmaWriteDelay(p->dma_write_delay), dmaWriteFactor(p->dma_write_factor)
+{
+ reset();
+
+}
+
+Device::~Device()
+{}
+
+void
+Device::regStats()
+{
+ rxBytes
+ .name(name() + ".rxBytes")
+ .desc("Bytes Received")
+ .prereq(rxBytes)
+ ;
+
+ rxBandwidth
+ .name(name() + ".rxBandwidth")
+ .desc("Receive Bandwidth (bits/s)")
+ .precision(0)
+ .prereq(rxBytes)
+ ;
+
+ rxPackets
+ .name(name() + ".rxPackets")
+ .desc("Number of Packets Received")
+ .prereq(rxBytes)
+ ;
+
+ rxPacketRate
+ .name(name() + ".rxPPS")
+ .desc("Packet Reception Rate (packets/s)")
+ .precision(0)
+ .prereq(rxBytes)
+ ;
+
+ rxIpPackets
+ .name(name() + ".rxIpPackets")
+ .desc("Number of IP Packets Received")
+ .prereq(rxBytes)
+ ;
+
+ rxTcpPackets
+ .name(name() + ".rxTcpPackets")
+ .desc("Number of Packets Received")
+ .prereq(rxBytes)
+ ;
+
+ rxUdpPackets
+ .name(name() + ".rxUdpPackets")
+ .desc("Number of UDP Packets Received")
+ .prereq(rxBytes)
+ ;
+
+ rxIpChecksums
+ .name(name() + ".rxIpChecksums")
+ .desc("Number of rx IP Checksums done by device")
+ .precision(0)
+ .prereq(rxBytes)
+ ;
+
+ rxTcpChecksums
+ .name(name() + ".rxTcpChecksums")
+ .desc("Number of rx TCP Checksums done by device")
+ .precision(0)
+ .prereq(rxBytes)
+ ;
+
+ rxUdpChecksums
+ .name(name() + ".rxUdpChecksums")
+ .desc("Number of rx UDP Checksums done by device")
+ .precision(0)
+ .prereq(rxBytes)
+ ;
+
+ totBandwidth
+ .name(name() + ".totBandwidth")
+ .desc("Total Bandwidth (bits/s)")
+ .precision(0)
+ .prereq(totBytes)
+ ;
+
+ totPackets
+ .name(name() + ".totPackets")
+ .desc("Total Packets")
+ .precision(0)
+ .prereq(totBytes)
+ ;
+
+ totBytes
+ .name(name() + ".totBytes")
+ .desc("Total Bytes")
+ .precision(0)
+ .prereq(totBytes)
+ ;
+
+ totPacketRate
+ .name(name() + ".totPPS")
+ .desc("Total Tranmission Rate (packets/s)")
+ .precision(0)
+ .prereq(totBytes)
+ ;
+
+ txBytes
+ .name(name() + ".txBytes")
+ .desc("Bytes Transmitted")
+ .prereq(txBytes)
+ ;
+
+ txBandwidth
+ .name(name() + ".txBandwidth")
+ .desc("Transmit Bandwidth (bits/s)")
+ .precision(0)
+ .prereq(txBytes)
+ ;
+
+ txPackets
+ .name(name() + ".txPackets")
+ .desc("Number of Packets Transmitted")
+ .prereq(txBytes)
+ ;
+
+ txPacketRate
+ .name(name() + ".txPPS")
+ .desc("Packet Tranmission Rate (packets/s)")
+ .precision(0)
+ .prereq(txBytes)
+ ;
+
+ txIpPackets
+ .name(name() + ".txIpPackets")
+ .desc("Number of IP Packets Transmitted")
+ .prereq(txBytes)
+ ;
+
+ txTcpPackets
+ .name(name() + ".txTcpPackets")
+ .desc("Number of TCP Packets Transmitted")
+ .prereq(txBytes)
+ ;
+
+ txUdpPackets
+ .name(name() + ".txUdpPackets")
+ .desc("Number of Packets Transmitted")
+ .prereq(txBytes)
+ ;
+
+ txIpChecksums
+ .name(name() + ".txIpChecksums")
+ .desc("Number of tx IP Checksums done by device")
+ .precision(0)
+ .prereq(txBytes)
+ ;
+
+ txTcpChecksums
+ .name(name() + ".txTcpChecksums")
+ .desc("Number of tx TCP Checksums done by device")
+ .precision(0)
+ .prereq(txBytes)
+ ;
+
+ txUdpChecksums
+ .name(name() + ".txUdpChecksums")
+ .desc("Number of tx UDP Checksums done by device")
+ .precision(0)
+ .prereq(txBytes)
+ ;
+
+ txBandwidth = txBytes * Stats::constant(8) / simSeconds;
+ rxBandwidth = rxBytes * Stats::constant(8) / simSeconds;
+ totBandwidth = txBandwidth + rxBandwidth;
+ totBytes = txBytes + rxBytes;
+ totPackets = txPackets + rxPackets;
+ txPacketRate = txPackets / simSeconds;
+ rxPacketRate = rxPackets / simSeconds;
+}
+
+void
+Device::prepareIO(int cpu, int index)
+{
+ int size = virtualRegs.size();
+ if (index > size)
+ panic("Trying to access a vnic that doesn't exist %d > %d\n",
+ index, size);
+}
+
+void
+Device::prepareRead(int cpu, int index)
+{
+ using namespace Regs;
+ prepareIO(cpu, index);
+
+ VirtualReg &vnic = virtualRegs[index];
+
+ // update rx registers
+ uint64_t rxdone = vnic.RxDone;
+ rxdone = set_RxDone_Packets(rxdone, rxFifo.countPacketsAfter(rxFifoPtr));
+ rxdone = set_RxDone_Empty(rxdone, rxFifo.empty());
+ rxdone = set_RxDone_High(rxdone, rxFifo.size() > regs.RxFifoMark);
+ rxdone = set_RxDone_NotHigh(rxdone, rxLow);
+ regs.RxData = vnic.RxData;
+ regs.RxDone = rxdone;
+ regs.RxWait = rxdone;
+
+ // update tx regsiters
+ uint64_t txdone = vnic.TxDone;
+ txdone = set_TxDone_Packets(txdone, txFifo.packets());
+ txdone = set_TxDone_Full(txdone, txFifo.avail() < regs.TxMaxCopy);
+ txdone = set_TxDone_Low(txdone, txFifo.size() < regs.TxFifoMark);
+ regs.TxData = vnic.TxData;
+ regs.TxDone = txdone;
+ regs.TxWait = txdone;
+}
+
+void
+Device::prepareWrite(int cpu, int index)
+{
+ prepareIO(cpu, index);
+}
+
+/**
+ * I/O read of device register
+ */
+Tick
+Device::read(Packet *pkt)
+{
+ assert(config.command & PCI_CMD_MSE);
+ assert(pkt->getAddr() >= BARAddrs[0] && pkt->getSize() < BARSize[0]);
+
+ int cpu = pkt->req->getCpuNum();
+ Addr daddr = pkt->getAddr() - 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 size=%d",
+ cpu, index, daddr, pkt->getAddr(), pkt->getSize());
+
+ const Regs::Info &info = regInfo(raddr);
+ if (!info.read)
+ panic("read %s (write only): "
+ "cpu=%d vnic=%d da=%#x pa=%#x size=%d",
+ info.name, cpu, index, daddr, pkt->getAddr(), pkt->getSize());
+
+ panic("read %s (invalid size): "
+ "cpu=%d vnic=%d da=%#x pa=%#x size=%d",
+ info.name, cpu, index, daddr, pkt->getAddr(), pkt->getSize());
+
+ prepareRead(cpu, index);
+
+ uint64_t value = 0;
+ if (pkt->getSize() == 4) {
+ uint32_t reg = regData32(raddr);
+ pkt->set(reg);
+ value = reg;
+ }
+
+ if (pkt->getSize() == 8) {
+ uint64_t reg = regData64(raddr);
+ pkt->set(reg);
+ value = reg;
+ }
+
+ DPRINTF(EthernetPIO,
+ "read %s: cpu=%d vnic=%d da=%#x pa=%#x size=%d val=%#x\n",
+ info.name, cpu, index, daddr, pkt->getAddr(), pkt->getSize(), value);
+
+ // reading the interrupt status register has the side effect of
+ // clearing it
+ if (raddr == Regs::IntrStatus)
+ devIntrClear();
+
+ return pioDelay;
+}
+
+/**
+ * IPR read of device register
+
+ Fault
+Device::iprRead(Addr daddr, int cpu, uint64_t &result)
+{
+ if (!regValid(daddr))
+ panic("invalid address: da=%#x", daddr);
+
+ const Regs::Info &info = regInfo(daddr);
+ if (!info.read)
+ panic("reading %s (write only): cpu=%d da=%#x", info.name, cpu, daddr);
+
+ DPRINTF(EthernetPIO, "IPR read %s: cpu=%d da=%#x\n",
+ info.name, cpu, daddr);
+
+ prepareRead(cpu, 0);
+
+ if (info.size == 4)
+ result = regData32(daddr);
+
+ if (info.size == 8)
+ result = regData64(daddr);
+
+ DPRINTF(EthernetPIO, "IPR read %s: cpu=%s da=%#x val=%#x\n",
+ info.name, cpu, result);
+
+ return NoFault;
+}
+*/
+/**
+ * I/O write of device register
+ */
+Tick
+Device::write(Packet *pkt)
+{
+ assert(config.command & PCI_CMD_MSE);
+ assert(pkt->getAddr() >= BARAddrs[0] && pkt->getSize() < BARSize[0]);
+
+ int cpu = pkt->req->getCpuNum();
+ Addr daddr = pkt->getAddr() - BARAddrs[0];
+ Addr index = daddr >> Regs::VirtualShift;
+ Addr raddr = daddr & Regs::VirtualMask;
+
+ pkt->time += pioDelay;
+
+ if (!regValid(raddr))
+ panic("invalid register: cpu=%d, da=%#x pa=%#x size=%d",
+ cpu, daddr, pkt->getAddr(), pkt->getSize());
+
+ const Regs::Info &info = regInfo(raddr);
+ if (!info.write)
+ panic("write %s (read only): "
+ "cpu=%d vnic=%d da=%#x pa=%#x size=%d",
+ info.name, cpu, index, daddr, pkt->getAddr(), pkt->getSize());
+
+ if (pkt->getSize() != info.size)
+ panic("write %s (invalid size): "
+ "cpu=%d vnic=%d da=%#x pa=%#x size=%d",
+ info.name, cpu, index, daddr, pkt->getAddr(), pkt->getSize());
+
+ VirtualReg &vnic = virtualRegs[index];
+
+ DPRINTF(EthernetPIO,
+ "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->getAddr(), pkt->getSize());
+
+ prepareWrite(cpu, index);
+
+ switch (raddr) {
+ case Regs::Config:
+ changeConfig(pkt->get<uint32_t>());
+ break;
+
+ case Regs::Command:
+ command(pkt->get<uint32_t>());
+ break;
+
+ case Regs::IntrStatus:
+ devIntrClear(regs.IntrStatus & pkt->get<uint32_t>());
+ break;
+
+ case Regs::IntrMask:
+ devIntrChangeMask(pkt->get<uint32_t>());
+ break;
+
+ case Regs::RxData:
+ if (Regs::get_RxDone_Busy(vnic.RxDone))
+ panic("receive machine busy with another request! rxState=%s",
+ RxStateStrings[rxState]);
+
+ vnic.rxUnique = rxUnique++;
+ vnic.RxDone = Regs::RxDone_Busy;
+ vnic.RxData = pkt->get<uint64_t>();
+
+ if (Regs::get_RxData_Vaddr(pkt->get<uint64_t>())) {
+ panic("vtophys not implemented in newmem");
+/* Addr vaddr = Regs::get_RxData_Addr(reg64);
+ Addr paddr = vtophys(req->xc, vaddr);
+ DPRINTF(EthernetPIO, "write RxData vnic %d (rxunique %d): "
+ "vaddr=%#x, paddr=%#x\n",
+ index, vnic.rxUnique, vaddr, paddr);
+
+ vnic.RxData = Regs::set_RxData_Addr(vnic.RxData, paddr);*/
+ } else {
+ DPRINTF(EthernetPIO, "write RxData vnic %d (rxunique %d)\n",
+ index, vnic.rxUnique);
+ }
+
+ if (vnic.rxPacket == rxFifo.end()) {
+ DPRINTF(EthernetPIO, "request new packet...appending to rxList\n");
+ rxList.push_back(index);
+ } else {
+ DPRINTF(EthernetPIO, "packet exists...appending to rxBusy\n");
+ rxBusy.push_back(index);
+ }
+
+ if (rxEnable && (rxState == rxIdle || rxState == rxFifoBlock)) {
+ rxState = rxFifoBlock;
+ rxKick();
+ }
+ break;
+
+ case Regs::TxData:
+ if (Regs::get_TxDone_Busy(vnic.TxDone))
+ panic("transmit machine busy with another request! txState=%s",
+ TxStateStrings[txState]);
+
+ vnic.txUnique = txUnique++;
+ vnic.TxDone = Regs::TxDone_Busy;
+
+ 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);*/
+ } else {
+ DPRINTF(EthernetPIO, "write TxData vnic %d (rxunique %d)\n",
+ index, vnic.txUnique);
+ }
+
+ if (txList.empty() || txList.front() != index)
+ txList.push_back(index);
+ if (txEnable && txState == txIdle && txList.front() == index) {
+ txState = txFifoBlock;
+ txKick();
+ }
+ break;
+ }
+
+ return pioDelay;
+}
+
+void
+Device::devIntrPost(uint32_t interrupts)
+{
+ if ((interrupts & Regs::Intr_Res))
+ panic("Cannot set a reserved interrupt");
+
+ regs.IntrStatus |= interrupts;
+
+ DPRINTF(EthernetIntr,
+ "interrupt written to intStatus: intr=%#x status=%#x mask=%#x\n",
+ interrupts, regs.IntrStatus, regs.IntrMask);
+
+ interrupts = regs.IntrStatus & regs.IntrMask;
+
+ // Intr_RxHigh is special, we only signal it if we've emptied the fifo
+ // and then filled it above the high watermark
+ if (rxEmpty)
+ rxEmpty = false;
+ else
+ interrupts &= ~Regs::Intr_RxHigh;
+
+ // Intr_TxLow is special, we only signal it if we've filled up the fifo
+ // and then dropped below the low watermark
+ if (txFull)
+ txFull = false;
+ else
+ interrupts &= ~Regs::Intr_TxLow;
+
+ if (interrupts) {
+ Tick when = curTick;
+ if ((interrupts & Regs::Intr_NoDelay) == 0)
+ when += intrDelay;
+ cpuIntrPost(when);
+ }
+}
+
+void
+Device::devIntrClear(uint32_t interrupts)
+{
+ if ((interrupts & Regs::Intr_Res))
+ panic("Cannot clear a reserved interrupt");
+
+ regs.IntrStatus &= ~interrupts;
+
+ DPRINTF(EthernetIntr,
+ "interrupt cleared from intStatus: intr=%x status=%x mask=%x\n",
+ interrupts, regs.IntrStatus, regs.IntrMask);
+
+ if (!(regs.IntrStatus & regs.IntrMask))
+ cpuIntrClear();
+}
+
+void
+Device::devIntrChangeMask(uint32_t newmask)
+{
+ if (regs.IntrMask == newmask)
+ return;
+
+ regs.IntrMask = newmask;
+
+ DPRINTF(EthernetIntr,
+ "interrupt mask changed: intStatus=%x intMask=%x masked=%x\n",
+ regs.IntrStatus, regs.IntrMask, regs.IntrStatus & regs.IntrMask);
+
+ if (regs.IntrStatus & regs.IntrMask)
+ cpuIntrPost(curTick);
+ else
+ cpuIntrClear();
+}
+
+void
+Base::cpuIntrPost(Tick when)
+{
+ // If the interrupt you want to post is later than an interrupt
+ // already scheduled, just let it post in the coming one and don't
+ // schedule another.
+ // HOWEVER, must be sure that the scheduled intrTick is in the
+ // future (this was formerly the source of a bug)
+ /**
+ * @todo this warning should be removed and the intrTick code should
+ * be fixed.
+ */
+ assert(when >= curTick);
+ assert(intrTick >= curTick || intrTick == 0);
+ if (!cpuIntrEnable) {
+ DPRINTF(EthernetIntr, "interrupts not enabled.\n",
+ intrTick);
+ return;
+ }
+
+ if (when > intrTick && intrTick != 0) {
+ DPRINTF(EthernetIntr, "don't need to schedule event...intrTick=%d\n",
+ intrTick);
+ return;
+ }
+
+ intrTick = when;
+ if (intrTick < curTick) {
+ debug_break();
+ intrTick = curTick;
+ }
+
+ DPRINTF(EthernetIntr, "going to schedule an interrupt for intrTick=%d\n",
+ intrTick);
+
+ if (intrEvent)
+ intrEvent->squash();
+ intrEvent = new IntrEvent(this, true);
+ intrEvent->schedule(intrTick);
+}
+
+void
+Base::cpuInterrupt()
+{
+ assert(intrTick == curTick);
+
+ // Whether or not there's a pending interrupt, we don't care about
+ // it anymore
+ intrEvent = 0;
+ intrTick = 0;
+
+ // Don't send an interrupt if there's already one
+ if (cpuPendingIntr) {
+ DPRINTF(EthernetIntr,
+ "would send an interrupt now, but there's already pending\n");
+ } else {
+ // Send interrupt
+ cpuPendingIntr = true;
+
+ DPRINTF(EthernetIntr, "posting interrupt\n");
+ intrPost();
+ }
+}
+
+void
+Base::cpuIntrClear()
+{
+ if (!cpuPendingIntr)
+ return;
+
+ if (intrEvent) {
+ intrEvent->squash();
+ intrEvent = 0;
+ }
+
+ intrTick = 0;
+
+ cpuPendingIntr = false;
+
+ DPRINTF(EthernetIntr, "clearing cchip interrupt\n");
+ intrClear();
+}
+
+bool
+Base::cpuIntrPending() const
+{ return cpuPendingIntr; }
+
+void
+Device::changeConfig(uint32_t newconf)
+{
+ uint32_t changed = regs.Config ^ newconf;
+ if (!changed)
+ return;
+
+ regs.Config = newconf;
+
+ if ((changed & Regs::Config_IntEn)) {
+ cpuIntrEnable = regs.Config & Regs::Config_IntEn;
+ if (cpuIntrEnable) {
+ if (regs.IntrStatus & regs.IntrMask)
+ cpuIntrPost(curTick);
+ } else {
+ cpuIntrClear();
+ }
+ }
+
+ if ((changed & Regs::Config_TxEn)) {
+ txEnable = regs.Config & Regs::Config_TxEn;
+ if (txEnable)
+ txKick();
+ }
+
+ if ((changed & Regs::Config_RxEn)) {
+ rxEnable = regs.Config & Regs::Config_RxEn;
+ if (rxEnable)
+ rxKick();
+ }
+}
+
+void
+Device::command(uint32_t command)
+{
+ if (command & Regs::Command_Intr)
+ devIntrPost(Regs::Intr_Soft);
+
+ if (command & Regs::Command_Reset)
+ reset();
+}
+
+void
+Device::reset()
+{
+ using namespace Regs;
+
+ memset(&regs, 0, sizeof(regs));
+
+ regs.Config = 0;
+ if (params()->rx_thread)
+ regs.Config |= Config_RxThread;
+ if (params()->tx_thread)
+ regs.Config |= Config_TxThread;
+ if (params()->rss)
+ regs.Config |= Config_RSS;
+ if (params()->zero_copy)
+ regs.Config |= Config_ZeroCopy;
+ if (params()->delay_copy)
+ regs.Config |= Config_DelayCopy;
+ if (params()->virtual_addr)
+ regs.Config |= Config_Vaddr;
+
+ if (params()->delay_copy && params()->zero_copy)
+ panic("Can't delay copy and zero copy");
+
+ regs.IntrMask = Intr_Soft | Intr_RxHigh | Intr_RxPacket | Intr_TxLow;
+ regs.RxMaxCopy = params()->rx_max_copy;
+ regs.TxMaxCopy = params()->tx_max_copy;
+ regs.RxMaxIntr = params()->rx_max_intr;
+ regs.VirtualCount = params()->virtual_count;
+ regs.RxFifoSize = params()->rx_fifo_size;
+ regs.TxFifoSize = params()->tx_fifo_size;
+ regs.RxFifoMark = params()->rx_fifo_threshold;
+ regs.TxFifoMark = params()->tx_fifo_threshold;
+ regs.HwAddr = params()->eaddr;
+
+ rxList.clear();
+ rxBusy.clear();
+ rxActive = -1;
+ txList.clear();
+
+ rxState = rxIdle;
+ txState = txIdle;
+
+ rxFifo.clear();
+ rxFifoPtr = rxFifo.end();
+ txFifo.clear();
+ rxEmpty = false;
+ rxLow = true;
+ txFull = false;
+
+ int size = virtualRegs.size();
+ virtualRegs.clear();
+ virtualRegs.resize(size);
+ for (int i = 0; i < size; ++i)
+ virtualRegs[i].rxPacket = rxFifo.end();
+}
+
+void
+Device::rxDmaDone()
+{
+ assert(rxState == rxCopy);
+ rxState = rxCopyDone;
+ DPRINTF(EthernetDMA, "end rx dma write paddr=%#x len=%d\n",
+ rxDmaAddr, rxDmaLen);
+ DDUMP(EthernetData, rxDmaData, rxDmaLen);
+
+ // If the transmit state machine has a pending DMA, let it go first
+ if (txState == txBeginCopy)
+ txKick();
+
+ rxKick();
+}
+
+void
+Device::rxKick()
+{
+ VirtualReg *vnic = NULL;
+
+ DPRINTF(EthernetSM, "rxKick: rxState=%s (rxFifo.size=%d)\n",
+ RxStateStrings[rxState], rxFifo.size());
+
+ if (rxKickTick > curTick) {
+ DPRINTF(EthernetSM, "rxKick: exiting, can't run till %d\n",
+ rxKickTick);
+ return;
+ }
+
+ next:
+ if (rxState == rxIdle)
+ goto exit;
+
+ if (rxActive == -1) {
+ if (rxState != rxFifoBlock)
+ panic("no active vnic while in state %s", RxStateStrings[rxState]);
+
+ DPRINTF(EthernetSM, "processing rxState=%s\n",
+ RxStateStrings[rxState]);
+ } else {
+ vnic = &virtualRegs[rxActive];
+ DPRINTF(EthernetSM,
+ "processing rxState=%s for vnic %d (rxunique %d)\n",
+ RxStateStrings[rxState], rxActive, vnic->rxUnique);
+ }
+
+ switch (rxState) {
+ case rxFifoBlock:
+ if (DTRACE(EthernetSM)) {
+ PacketFifo::iterator end = rxFifo.end();
+ int size = virtualRegs.size();
+ for (int i = 0; i < size; ++i) {
+ VirtualReg *vn = &virtualRegs[i];
+ if (vn->rxPacket != end &&
+ !Regs::get_RxDone_Busy(vn->RxDone)) {
+ DPRINTF(EthernetSM,
+ "vnic %d (rxunique %d), has outstanding packet %d\n",
+ i, vn->rxUnique,
+ rxFifo.countPacketsBefore(vn->rxPacket));
+ }
+ }
+ }
+
+ if (!rxBusy.empty()) {
+ rxActive = rxBusy.front();
+ rxBusy.pop_front();
+ vnic = &virtualRegs[rxActive];
+
+ if (vnic->rxPacket == rxFifo.end())
+ panic("continuing vnic without packet\n");
+
+ DPRINTF(EthernetSM,
+ "continue processing for vnic %d (rxunique %d)\n",
+ rxActive, vnic->rxUnique);
+
+ rxState = rxBeginCopy;
+
+ break;
+ }
+
+ if (rxFifoPtr == rxFifo.end()) {
+ DPRINTF(EthernetSM, "receive waiting for data. Nothing to do.\n");
+ goto exit;
+ }
+
+ if (rxList.empty())
+ panic("Not idle, but nothing to do!");
+
+ assert(!rxFifo.empty());
+
+ rxActive = rxList.front();
+ rxList.pop_front();
+ vnic = &virtualRegs[rxActive];
+
+ DPRINTF(EthernetSM,
+ "processing new packet for vnic %d (rxunique %d)\n",
+ rxActive, vnic->rxUnique);
+
+ // Grab a new packet from the fifo.
+ vnic->rxPacket = rxFifoPtr++;
+ vnic->rxPacketOffset = 0;
+ vnic->rxPacketBytes = (*vnic->rxPacket)->length;
+ assert(vnic->rxPacketBytes);
+
+ vnic->rxDoneData = 0;
+ /* scope for variables */ {
+ IpPtr ip(*vnic->rxPacket);
+ if (ip) {
+ DPRINTF(Ethernet, "ID is %d\n", ip->id());
+ vnic->rxDoneData |= Regs::RxDone_IpPacket;
+ rxIpChecksums++;
+ if (cksum(ip) != 0) {
+ DPRINTF(EthernetCksum, "Rx IP Checksum Error\n");
+ vnic->rxDoneData |= Regs::RxDone_IpError;
+ }
+ TcpPtr tcp(ip);
+ UdpPtr udp(ip);
+ if (tcp) {
+ DPRINTF(Ethernet,
+ "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n",
+ tcp->sport(), tcp->dport(), tcp->seq(),
+ tcp->ack());
+ vnic->rxDoneData |= Regs::RxDone_TcpPacket;
+ rxTcpChecksums++;
+ if (cksum(tcp) != 0) {
+ DPRINTF(EthernetCksum, "Rx TCP Checksum Error\n");
+ vnic->rxDoneData |= Regs::RxDone_TcpError;
+ }
+ } else if (udp) {
+ vnic->rxDoneData |= Regs::RxDone_UdpPacket;
+ rxUdpChecksums++;
+ if (cksum(udp) != 0) {
+ DPRINTF(EthernetCksum, "Rx UDP Checksum Error\n");
+ vnic->rxDoneData |= Regs::RxDone_UdpError;
+ }
+ }
+ }
+ }
+ rxState = rxBeginCopy;
+ break;
+
+ case rxBeginCopy:
+ if (dmaPending())
+ goto exit;
+
+ 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;
+ }
+
+
+ dmaWrite(rxDmaAddr, rxDmaLen, &rxDmaEvent, rxDmaData);
+ break;
+
+ case rxCopy:
+ DPRINTF(EthernetSM, "receive machine still copying\n");
+ goto exit;
+
+ case rxCopyDone:
+ vnic->RxDone = vnic->rxDoneData;
+ vnic->RxDone |= Regs::RxDone_Complete;
+
+ if (vnic->rxPacketBytes == rxDmaLen) {
+ // Packet is complete. Indicate how many bytes were copied
+ vnic->RxDone = Regs::set_RxDone_CopyLen(vnic->RxDone, rxDmaLen);
+
+ DPRINTF(EthernetSM,
+ "rxKick: packet complete on vnic %d (rxunique %d)\n",
+ rxActive, vnic->rxUnique);
+ rxFifo.remove(vnic->rxPacket);
+ vnic->rxPacket = rxFifo.end();
+ } else {
+ vnic->rxPacketBytes -= rxDmaLen;
+ vnic->rxPacketOffset += rxDmaLen;
+ vnic->RxDone |= Regs::RxDone_More;
+ vnic->RxDone = Regs::set_RxDone_CopyLen(vnic->RxDone,
+ vnic->rxPacketBytes);
+ DPRINTF(EthernetSM,
+ "rxKick: packet not complete on vnic %d (rxunique %d): "
+ "%d bytes left\n",
+ rxActive, vnic->rxUnique, vnic->rxPacketBytes);
+ }
+
+ rxActive = -1;
+ rxState = rxBusy.empty() && rxList.empty() ? rxIdle : rxFifoBlock;
+
+ if (rxFifo.empty()) {
+ devIntrPost(Regs::Intr_RxEmpty);
+ rxEmpty = true;
+ }
+
+ if (rxFifo.size() < params()->rx_fifo_low_mark)
+ rxLow = true;
+
+ if (rxFifo.size() > params()->rx_fifo_threshold)
+ rxLow = false;
+
+ devIntrPost(Regs::Intr_RxDMA);
+ break;
+
+ default:
+ panic("Invalid rxState!");
+ }
+
+ DPRINTF(EthernetSM, "entering next rxState=%s\n",
+ RxStateStrings[rxState]);
+
+ goto next;
+
+ exit:
+ /**
+ * @todo do we want to schedule a future kick?
+ */
+ DPRINTF(EthernetSM, "rx state machine exited rxState=%s\n",
+ RxStateStrings[rxState]);
+}
+
+void
+Device::txDmaDone()
+{
+ assert(txState == txCopy);
+ txState = txCopyDone;
+ DPRINTF(EthernetDMA, "tx dma read paddr=%#x len=%d\n",
+ txDmaAddr, txDmaLen);
+ DDUMP(EthernetData, txDmaData, txDmaLen);
+
+ // If the receive state machine has a pending DMA, let it go first
+ if (rxState == rxBeginCopy)
+ rxKick();
+
+ txKick();
+}
+
+void
+Device::transmit()
+{
+ if (txFifo.empty()) {
+ DPRINTF(Ethernet, "nothing to transmit\n");
+ return;
+ }
+
+ uint32_t interrupts;
+ EthPacketPtr packet = txFifo.front();
+ if (!interface->sendPacket(packet)) {
+ DPRINTF(Ethernet, "Packet Transmit: failed txFifo available %d\n",
+ txFifo.avail());
+ goto reschedule;
+ }
+
+ txFifo.pop();
+#if TRACING_ON
+ if (DTRACE(Ethernet)) {
+ IpPtr ip(packet);
+ if (ip) {
+ DPRINTF(Ethernet, "ID is %d\n", ip->id());
+ TcpPtr tcp(ip);
+ if (tcp) {
+ DPRINTF(Ethernet,
+ "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n",
+ tcp->sport(), tcp->dport(), tcp->seq(),
+ tcp->ack());
+ }
+ }
+ }
+#endif
+
+ DDUMP(EthernetData, packet->data, packet->length);
+ txBytes += packet->length;
+ txPackets++;
+
+ DPRINTF(Ethernet, "Packet Transmit: successful txFifo Available %d\n",
+ txFifo.avail());
+
+ interrupts = Regs::Intr_TxPacket;
+ if (txFifo.size() < regs.TxFifoMark)
+ interrupts |= Regs::Intr_TxLow;
+ devIntrPost(interrupts);
+
+ reschedule:
+ if (!txFifo.empty() && !txEvent.scheduled()) {
+ DPRINTF(Ethernet, "reschedule transmit\n");
+ txEvent.schedule(curTick + retryTime);
+ }
+}
+
+void
+Device::txKick()
+{
+ VirtualReg *vnic;
+ DPRINTF(EthernetSM, "txKick: txState=%s (txFifo.size=%d)\n",
+ TxStateStrings[txState], txFifo.size());
+
+ if (txKickTick > curTick) {
+ DPRINTF(EthernetSM, "txKick: exiting, can't run till %d\n",
+ txKickTick);
+ return;
+ }
+
+ next:
+ if (txState == txIdle)
+ goto exit;
+
+ assert(!txList.empty());
+ vnic = &virtualRegs[txList.front()];
+
+ switch (txState) {
+ case txFifoBlock:
+ assert(Regs::get_TxDone_Busy(vnic->TxDone));
+ if (!txPacket) {
+ // Grab a new packet from the fifo.
+ txPacket = new EthPacketData(16384);
+ txPacketOffset = 0;
+ }
+
+ if (txFifo.avail() - txPacket->length <
+ Regs::get_TxData_Len(vnic->TxData)) {
+ DPRINTF(EthernetSM, "transmit fifo full. Nothing to do.\n");
+ goto exit;
+ }
+
+ txState = txBeginCopy;
+ break;
+
+ case txBeginCopy:
+ if (dmaPending())
+ goto exit;
+
+ txDmaAddr = params()->platform->pciToDma(
+ Regs::get_TxData_Addr(vnic->TxData));
+ txDmaLen = Regs::get_TxData_Len(vnic->TxData);
+ txDmaData = txPacket->data + txPacketOffset;
+ txState = txCopy;
+
+ dmaRead(txDmaAddr, txDmaLen, &txDmaEvent, txDmaData);
+ break;
+
+ case txCopy:
+ DPRINTF(EthernetSM, "transmit machine still copying\n");
+ goto exit;
+
+ case txCopyDone:
+ vnic->TxDone = txDmaLen | Regs::TxDone_Complete;
+ txPacket->length += txDmaLen;
+ if ((vnic->TxData & Regs::TxData_More)) {
+ txPacketOffset += txDmaLen;
+ txState = txIdle;
+ devIntrPost(Regs::Intr_TxDMA);
+ break;
+ }
+
+ assert(txPacket->length <= txFifo.avail());
+ if ((vnic->TxData & Regs::TxData_Checksum)) {
+ IpPtr ip(txPacket);
+ if (ip) {
+ TcpPtr tcp(ip);
+ if (tcp) {
+ tcp->sum(0);
+ tcp->sum(cksum(tcp));
+ txTcpChecksums++;
+ }
+
+ UdpPtr udp(ip);
+ if (udp) {
+ udp->sum(0);
+ udp->sum(cksum(udp));
+ txUdpChecksums++;
+ }
+
+ ip->sum(0);
+ ip->sum(cksum(ip));
+ txIpChecksums++;
+ }
+ }
+
+ txFifo.push(txPacket);
+ if (txFifo.avail() < regs.TxMaxCopy) {
+ devIntrPost(Regs::Intr_TxFull);
+ txFull = true;
+ }
+ txPacket = 0;
+ transmit();
+ txList.pop_front();
+ txState = txList.empty() ? txIdle : txFifoBlock;
+ devIntrPost(Regs::Intr_TxDMA);
+ break;
+
+ default:
+ panic("Invalid txState!");
+ }
+
+ DPRINTF(EthernetSM, "entering next txState=%s\n",
+ TxStateStrings[txState]);
+
+ goto next;
+
+ exit:
+ /**
+ * @todo do we want to schedule a future kick?
+ */
+ DPRINTF(EthernetSM, "tx state machine exited txState=%s\n",
+ TxStateStrings[txState]);
+}
+
+void
+Device::transferDone()
+{
+ if (txFifo.empty()) {
+ DPRINTF(Ethernet, "transfer complete: txFifo empty...nothing to do\n");
+ return;
+ }
+
+ DPRINTF(Ethernet, "transfer complete: data in txFifo...schedule xmit\n");
+
+ if (txEvent.scheduled())
+ txEvent.reschedule(curTick + cycles(1));
+ else
+ txEvent.schedule(curTick + cycles(1));
+}
+
+bool
+Device::rxFilter(const EthPacketPtr &packet)
+{
+ if (!Regs::get_Config_Filter(regs.Config))
+ return false;
+
+ panic("receive filter not implemented\n");
+ bool drop = true;
+
+#if 0
+ string type;
+
+ EthHdr *eth = packet->eth();
+ if (eth->unicast()) {
+ // If we're accepting all unicast addresses
+ if (acceptUnicast)
+ drop = false;
+
+ // If we make a perfect match
+ if (acceptPerfect && params->eaddr == eth.dst())
+ drop = false;
+
+ if (acceptArp && eth->type() == ETH_TYPE_ARP)
+ drop = false;
+
+ } else if (eth->broadcast()) {
+ // if we're accepting broadcasts
+ if (acceptBroadcast)
+ drop = false;
+
+ } else if (eth->multicast()) {
+ // if we're accepting all multicasts
+ if (acceptMulticast)
+ drop = false;
+
+ }
+
+ if (drop) {
+ DPRINTF(Ethernet, "rxFilter drop\n");
+ DDUMP(EthernetData, packet->data, packet->length);
+ }
+#endif
+ return drop;
+}
+
+bool
+Device::recvPacket(EthPacketPtr packet)
+{
+ rxBytes += packet->length;
+ rxPackets++;
+
+ DPRINTF(Ethernet, "Receiving packet from wire, rxFifo Available is %d\n",
+ rxFifo.avail());
+
+ if (!rxEnable) {
+ DPRINTF(Ethernet, "receive disabled...packet dropped\n");
+ return true;
+ }
+
+ if (rxFilter(packet)) {
+ DPRINTF(Ethernet, "packet filtered...dropped\n");
+ return true;
+ }
+
+ if (rxFifo.size() >= regs.RxFifoMark)
+ devIntrPost(Regs::Intr_RxHigh);
+
+ if (!rxFifo.push(packet)) {
+ DPRINTF(Ethernet,
+ "packet will not fit in receive buffer...packet dropped\n");
+ return false;
+ }
+
+ // If we were at the last element, back up one ot go to the new
+ // last element of the list.
+ if (rxFifoPtr == rxFifo.end())
+ --rxFifoPtr;
+
+ devIntrPost(Regs::Intr_RxPacket);
+ rxKick();
+ return true;
+}
+
+//=====================================================================
+//
+//
+void
+Base::serialize(std::ostream &os)
+{
+ // Serialize the PciDev base class
+ PciDev::serialize(os);
+
+ SERIALIZE_SCALAR(rxEnable);
+ SERIALIZE_SCALAR(txEnable);
+ SERIALIZE_SCALAR(cpuIntrEnable);
+
+ /*
+ * Keep track of pending interrupt status.
+ */
+ SERIALIZE_SCALAR(intrTick);
+ SERIALIZE_SCALAR(cpuPendingIntr);
+ Tick intrEventTick = 0;
+ if (intrEvent)
+ intrEventTick = intrEvent->when();
+ SERIALIZE_SCALAR(intrEventTick);
+}
+
+void
+Base::unserialize(Checkpoint *cp, const std::string &section)
+{
+ // Unserialize the PciDev base class
+ PciDev::unserialize(cp, section);
+
+ UNSERIALIZE_SCALAR(rxEnable);
+ UNSERIALIZE_SCALAR(txEnable);
+ UNSERIALIZE_SCALAR(cpuIntrEnable);
+
+ /*
+ * Keep track of pending interrupt status.
+ */
+ UNSERIALIZE_SCALAR(intrTick);
+ UNSERIALIZE_SCALAR(cpuPendingIntr);
+ Tick intrEventTick;
+ UNSERIALIZE_SCALAR(intrEventTick);
+ if (intrEventTick) {
+ intrEvent = new IntrEvent(this, true);
+ intrEvent->schedule(intrEventTick);
+ }
+}
+
+void
+Device::serialize(std::ostream &os)
+{
+ int count;
+
+ // Serialize the PciDev base class
+ Base::serialize(os);
+
+ if (rxState == rxCopy)
+ panic("can't serialize with an in flight dma request rxState=%s",
+ RxStateStrings[rxState]);
+
+ if (txState == txCopy)
+ panic("can't serialize with an in flight dma request txState=%s",
+ TxStateStrings[txState]);
+
+ /*
+ * Serialize the device registers
+ */
+ SERIALIZE_SCALAR(regs.Config);
+ SERIALIZE_SCALAR(regs.IntrStatus);
+ SERIALIZE_SCALAR(regs.IntrMask);
+ SERIALIZE_SCALAR(regs.RxMaxCopy);
+ SERIALIZE_SCALAR(regs.TxMaxCopy);
+ SERIALIZE_SCALAR(regs.RxMaxIntr);
+ SERIALIZE_SCALAR(regs.VirtualCount);
+ SERIALIZE_SCALAR(regs.RxData);
+ SERIALIZE_SCALAR(regs.RxDone);
+ SERIALIZE_SCALAR(regs.TxData);
+ SERIALIZE_SCALAR(regs.TxDone);
+
+ /*
+ * Serialize the virtual nic state
+ */
+ int virtualRegsSize = virtualRegs.size();
+ SERIALIZE_SCALAR(virtualRegsSize);
+ for (int i = 0; i < virtualRegsSize; ++i) {
+ VirtualReg *vnic = &virtualRegs[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);
+ paramOut(os, reg + ".TxDone", vnic->TxDone);
+
+ bool rxPacketExists = vnic->rxPacket != rxFifo.end();
+ paramOut(os, reg + ".rxPacketExists", rxPacketExists);
+ if (rxPacketExists) {
+ int rxPacket = 0;
+ PacketFifo::iterator i = rxFifo.begin();
+ while (i != vnic->rxPacket) {
+ assert(i != rxFifo.end());
+ ++i;
+ ++rxPacket;
+ }
+
+ paramOut(os, reg + ".rxPacket", rxPacket);
+ paramOut(os, reg + ".rxPacketOffset", vnic->rxPacketOffset);
+ paramOut(os, reg + ".rxPacketBytes", vnic->rxPacketBytes);
+ }
+ paramOut(os, reg + ".rxDoneData", vnic->rxDoneData);
+ }
+
+ int rxFifoPtr = rxFifo.countPacketsBefore(this->rxFifoPtr);
+ SERIALIZE_SCALAR(rxFifoPtr);
+
+ SERIALIZE_SCALAR(rxActive);
+
+ VirtualList::iterator i, end;
+ for (count = 0, i = rxList.begin(), end = rxList.end(); i != end; ++i)
+ paramOut(os, csprintf("rxList%d", count++), *i);
+ int rxListSize = count;
+ SERIALIZE_SCALAR(rxListSize);
+
+ for (count = 0, i = rxBusy.begin(), end = rxBusy.end(); i != end; ++i)
+ paramOut(os, csprintf("rxBusy%d", count++), *i);
+ int rxBusySize = count;
+ SERIALIZE_SCALAR(rxBusySize);
+
+ for (count = 0, i = txList.begin(), end = txList.end(); i != end; ++i)
+ paramOut(os, csprintf("txList%d", count++), *i);
+ int txListSize = count;
+ SERIALIZE_SCALAR(txListSize);
+
+ /*
+ * Serialize rx state machine
+ */
+ int rxState = this->rxState;
+ SERIALIZE_SCALAR(rxState);
+ SERIALIZE_SCALAR(rxEmpty);
+ SERIALIZE_SCALAR(rxLow);
+ rxFifo.serialize("rxFifo", os);
+
+ /*
+ * Serialize tx state machine
+ */
+ int txState = this->txState;
+ SERIALIZE_SCALAR(txState);
+ SERIALIZE_SCALAR(txFull);
+ txFifo.serialize("txFifo", os);
+ bool txPacketExists = txPacket;
+ SERIALIZE_SCALAR(txPacketExists);
+ if (txPacketExists) {
+ txPacket->serialize("txPacket", os);
+ SERIALIZE_SCALAR(txPacketOffset);
+ SERIALIZE_SCALAR(txPacketBytes);
+ }
+
+ /*
+ * If there's a pending transmit, store the time so we can
+ * reschedule it later
+ */
+ Tick transmitTick = txEvent.scheduled() ? txEvent.when() - curTick : 0;
+ SERIALIZE_SCALAR(transmitTick);
+}
+
+void
+Device::unserialize(Checkpoint *cp, const std::string &section)
+{
+ // Unserialize the PciDev base class
+ Base::unserialize(cp, section);
+
+ /*
+ * Unserialize the device registers
+ */
+ UNSERIALIZE_SCALAR(regs.Config);
+ UNSERIALIZE_SCALAR(regs.IntrStatus);
+ UNSERIALIZE_SCALAR(regs.IntrMask);
+ UNSERIALIZE_SCALAR(regs.RxMaxCopy);
+ UNSERIALIZE_SCALAR(regs.TxMaxCopy);
+ UNSERIALIZE_SCALAR(regs.RxMaxIntr);
+ UNSERIALIZE_SCALAR(regs.VirtualCount);
+ UNSERIALIZE_SCALAR(regs.RxData);
+ UNSERIALIZE_SCALAR(regs.RxDone);
+ UNSERIALIZE_SCALAR(regs.TxData);
+ UNSERIALIZE_SCALAR(regs.TxDone);
+
+ UNSERIALIZE_SCALAR(rxActive);
+
+ int rxListSize;
+ UNSERIALIZE_SCALAR(rxListSize);
+ rxList.clear();
+ for (int i = 0; i < rxListSize; ++i) {
+ int value;
+ paramIn(cp, section, csprintf("rxList%d", i), value);
+ rxList.push_back(value);
+ }
+
+ int rxBusySize;
+ UNSERIALIZE_SCALAR(rxBusySize);
+ rxBusy.clear();
+ for (int i = 0; i < rxBusySize; ++i) {
+ int value;
+ paramIn(cp, section, csprintf("rxBusy%d", i), value);
+ rxBusy.push_back(value);
+ }
+
+ int txListSize;
+ UNSERIALIZE_SCALAR(txListSize);
+ txList.clear();
+ for (int i = 0; i < txListSize; ++i) {
+ int value;
+ paramIn(cp, section, csprintf("txList%d", i), value);
+ txList.push_back(value);
+ }
+
+ /*
+ * Unserialize rx state machine
+ */
+ int rxState;
+ UNSERIALIZE_SCALAR(rxState);
+ UNSERIALIZE_SCALAR(rxEmpty);
+ UNSERIALIZE_SCALAR(rxLow);
+ this->rxState = (RxState) rxState;
+ rxFifo.unserialize("rxFifo", cp, section);
+
+ int rxFifoPtr;
+ UNSERIALIZE_SCALAR(rxFifoPtr);
+ this->rxFifoPtr = rxFifo.begin();
+ for (int i = 0; i < rxFifoPtr; ++i)
+ ++this->rxFifoPtr;
+
+ /*
+ * Unserialize tx state machine
+ */
+ int txState;
+ UNSERIALIZE_SCALAR(txState);
+ UNSERIALIZE_SCALAR(txFull);
+ this->txState = (TxState) txState;
+ txFifo.unserialize("txFifo", cp, section);
+ bool txPacketExists;
+ UNSERIALIZE_SCALAR(txPacketExists);
+ txPacket = 0;
+ if (txPacketExists) {
+ txPacket = new EthPacketData(16384);
+ txPacket->unserialize("txPacket", cp, section);
+ UNSERIALIZE_SCALAR(txPacketOffset);
+ UNSERIALIZE_SCALAR(txPacketBytes);
+ }
+
+ /*
+ * unserialize the virtual nic registers/state
+ *
+ * this must be done after the unserialization of the rxFifo
+ * because the packet iterators depend on the fifo being populated
+ */
+ int virtualRegsSize;
+ UNSERIALIZE_SCALAR(virtualRegsSize);
+ virtualRegs.clear();
+ virtualRegs.resize(virtualRegsSize);
+ for (int i = 0; i < virtualRegsSize; ++i) {
+ VirtualReg *vnic = &virtualRegs[i];
+ std::string reg = csprintf("vnic%d", i);
+
+ paramIn(cp, section, reg + ".RxData", vnic->RxData);
+ paramIn(cp, section, reg + ".RxDone", vnic->RxDone);
+ paramIn(cp, section, reg + ".TxData", vnic->TxData);
+ paramIn(cp, section, reg + ".TxDone", vnic->TxDone);
+
+ vnic->rxUnique = rxUnique++;
+ vnic->txUnique = txUnique++;
+
+ bool rxPacketExists;
+ paramIn(cp, section, reg + ".rxPacketExists", rxPacketExists);
+ if (rxPacketExists) {
+ int rxPacket;
+ paramIn(cp, section, reg + ".rxPacket", rxPacket);
+ vnic->rxPacket = rxFifo.begin();
+ while (rxPacket--)
+ ++vnic->rxPacket;
+
+ paramIn(cp, section, reg + ".rxPacketOffset",
+ vnic->rxPacketOffset);
+ paramIn(cp, section, reg + ".rxPacketBytes", vnic->rxPacketBytes);
+ } else {
+ vnic->rxPacket = rxFifo.end();
+ }
+ paramIn(cp, section, reg + ".rxDoneData", vnic->rxDoneData);
+ }
+
+ /*
+ * If there's a pending transmit, reschedule it now
+ */
+ Tick transmitTick;
+ UNSERIALIZE_SCALAR(transmitTick);
+ if (transmitTick)
+ txEvent.schedule(curTick + transmitTick);
+
+ pioPort->sendStatusChange(Port::RangeChange);
+
+}
+
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(Interface)
+
+ SimObjectParam<EtherInt *> peer;
+ SimObjectParam<Device *> device;
+
+END_DECLARE_SIM_OBJECT_PARAMS(Interface)
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(Interface)
+
+ INIT_PARAM_DFLT(peer, "peer interface", NULL),
+ INIT_PARAM(device, "Ethernet device of this interface")
+
+END_INIT_SIM_OBJECT_PARAMS(Interface)
+
+CREATE_SIM_OBJECT(Interface)
+{
+ Interface *dev_int = new Interface(getInstanceName(), device);
+
+ EtherInt *p = (EtherInt *)peer;
+ if (p) {
+ dev_int->setPeer(p);
+ p->setPeer(dev_int);
+ }
+
+ return dev_int;
+}
+
+REGISTER_SIM_OBJECT("SinicInt", Interface)
+
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(Device)
+
+
+ SimObjectParam<System *> system;
+ SimObjectParam<Platform *> platform;
+ SimObjectParam<PciConfigAll *> configspace;
+ SimObjectParam<PciConfigData *> configdata;
+ Param<uint32_t> pci_bus;
+ Param<uint32_t> pci_dev;
+ Param<uint32_t> pci_func;
+ Param<Tick> pio_latency;
+ Param<Tick> intr_delay;
+
+ Param<Tick> clock;
+ Param<Tick> dma_read_delay;
+ Param<Tick> dma_read_factor;
+ Param<Tick> dma_write_delay;
+ Param<Tick> dma_write_factor;
+
+ Param<Tick> rx_delay;
+ Param<Tick> tx_delay;
+ Param<uint32_t> rx_max_copy;
+ Param<uint32_t> tx_max_copy;
+ Param<uint32_t> rx_max_intr;
+ Param<uint32_t> rx_fifo_size;
+ Param<uint32_t> tx_fifo_size;
+ Param<uint32_t> rx_fifo_threshold;
+ Param<uint32_t> rx_fifo_low_mark;
+ Param<uint32_t> tx_fifo_high_mark;
+ Param<uint32_t> tx_fifo_threshold;
+
+ Param<bool> rx_filter;
+ Param<std::string> hardware_address;
+ Param<bool> rx_thread;
+ Param<bool> tx_thread;
+ Param<bool> rss;
+ Param<uint32_t> virtual_count;
+ Param<bool> zero_copy;
+ Param<bool> delay_copy;
+ Param<bool> virtual_addr;
+
+END_DECLARE_SIM_OBJECT_PARAMS(Device)
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(Device)
+
+
+ INIT_PARAM(system, "System pointer"),
+ INIT_PARAM(platform, "Platform pointer"),
+ INIT_PARAM(configspace, "PCI Configspace"),
+ INIT_PARAM(configdata, "PCI Config data"),
+ 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(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(rx_delay, "Receive Delay"),
+ INIT_PARAM(tx_delay, "Transmit Delay"),
+ INIT_PARAM(rx_max_copy, "rx max copy"),
+ INIT_PARAM(tx_max_copy, "rx max copy"),
+ INIT_PARAM(rx_max_intr, "rx max intr"),
+ INIT_PARAM(rx_fifo_size, "max size in bytes of rxFifo"),
+ INIT_PARAM(tx_fifo_size, "max size in bytes of txFifo"),
+ INIT_PARAM(rx_fifo_threshold, "max size in bytes of rxFifo"),
+ INIT_PARAM(rx_fifo_low_mark, "max size in bytes of rxFifo"),
+ INIT_PARAM(tx_fifo_high_mark, "max size in bytes of txFifo"),
+ INIT_PARAM(tx_fifo_threshold, "max size in bytes of txFifo"),
+
+ INIT_PARAM(rx_filter, "Enable Receive Filter"),
+ INIT_PARAM(hardware_address, "Ethernet Hardware Address"),
+ INIT_PARAM(rx_thread, ""),
+ INIT_PARAM(tx_thread, ""),
+ INIT_PARAM(rss, ""),
+ INIT_PARAM(virtual_count, ""),
+ INIT_PARAM(zero_copy, ""),
+ INIT_PARAM(delay_copy, ""),
+ INIT_PARAM(virtual_addr, "")
+
+END_INIT_SIM_OBJECT_PARAMS(Device)
+
+
+CREATE_SIM_OBJECT(Device)
+{
+ Device::Params *params = new Device::Params;
+ params->name = getInstanceName();
+ params->platform = platform;
+ params->system = system;
+ params->configSpace = configspace;
+ params->configData = configdata;
+ 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->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->tx_delay = tx_delay;
+ params->rx_delay = rx_delay;
+ params->rx_max_copy = rx_max_copy;
+ params->tx_max_copy = tx_max_copy;
+ params->rx_max_intr = rx_max_intr;
+ params->rx_fifo_size = rx_fifo_size;
+ params->tx_fifo_size = tx_fifo_size;
+ params->rx_fifo_threshold = rx_fifo_threshold;
+ params->rx_fifo_low_mark = rx_fifo_low_mark;
+ params->tx_fifo_high_mark = tx_fifo_high_mark;
+ params->tx_fifo_threshold = tx_fifo_threshold;
+
+ params->rx_filter = rx_filter;
+ params->eaddr = hardware_address;
+ params->rx_thread = rx_thread;
+ params->tx_thread = tx_thread;
+ params->rss = rss;
+ params->virtual_count = virtual_count;
+ params->zero_copy = zero_copy;
+ params->delay_copy = delay_copy;
+ params->virtual_addr = virtual_addr;
+
+ return new Device(params);
+}
+
+REGISTER_SIM_OBJECT("Sinic", Device)
+
+/* namespace Sinic */ }
diff --git a/src/dev/sinic.hh b/src/dev/sinic.hh
new file mode 100644
index 000000000..1bb4c77e0
--- /dev/null
+++ b/src/dev/sinic.hh
@@ -0,0 +1,371 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __DEV_SINIC_HH__
+#define __DEV_SINIC_HH__
+
+#include "base/inet.hh"
+#include "base/statistics.hh"
+#include "dev/etherint.hh"
+#include "dev/etherpkt.hh"
+#include "dev/io_device.hh"
+#include "dev/pcidev.hh"
+#include "dev/pktfifo.hh"
+#include "dev/sinicreg.hh"
+#include "sim/eventq.hh"
+
+namespace Sinic {
+
+class Interface;
+class Base : public PciDev
+{
+ protected:
+ bool rxEnable;
+ bool txEnable;
+ Tick clock;
+ inline Tick cycles(int numCycles) const { return numCycles * clock; }
+
+ protected:
+ Tick intrDelay;
+ Tick intrTick;
+ bool cpuIntrEnable;
+ bool cpuPendingIntr;
+ void cpuIntrPost(Tick when);
+ void cpuInterrupt();
+ void cpuIntrClear();
+
+ typedef EventWrapper<Base, &Base::cpuInterrupt> IntrEvent;
+ friend void IntrEvent::process();
+ IntrEvent *intrEvent;
+ Interface *interface;
+
+ bool cpuIntrPending() const;
+ void cpuIntrAck() { cpuIntrClear(); }
+
+/**
+ * Serialization stuff
+ */
+ public:
+ virtual void serialize(std::ostream &os);
+ virtual void unserialize(Checkpoint *cp, const std::string &section);
+
+/**
+ * Construction/Destruction/Parameters
+ */
+ public:
+ struct Params : public PciDev::Params
+ {
+ Tick clock;
+ Tick intr_delay;
+ };
+
+ Base(Params *p);
+};
+
+class Device : public Base
+{
+ protected:
+ /** Receive State Machine States */
+ enum RxState {
+ rxIdle,
+ rxFifoBlock,
+ rxBeginCopy,
+ rxCopy,
+ rxCopyDone
+ };
+
+ /** Transmit State Machine states */
+ enum TxState {
+ txIdle,
+ txFifoBlock,
+ txBeginCopy,
+ txCopy,
+ txCopyDone
+ };
+
+ /** device register file */
+ struct {
+ uint32_t Config; // 0x00
+ uint32_t Command; // 0x04
+ uint32_t IntrStatus; // 0x08
+ uint32_t IntrMask; // 0x0c
+ uint32_t RxMaxCopy; // 0x10
+ uint32_t TxMaxCopy; // 0x14
+ uint32_t RxMaxIntr; // 0x18
+ uint32_t VirtualCount; // 0x1c
+ uint32_t RxFifoSize; // 0x20
+ uint32_t TxFifoSize; // 0x24
+ uint32_t RxFifoMark; // 0x28
+ uint32_t TxFifoMark; // 0x2c
+ uint64_t RxData; // 0x30
+ uint64_t RxDone; // 0x38
+ uint64_t RxWait; // 0x40
+ uint64_t TxData; // 0x48
+ uint64_t TxDone; // 0x50
+ uint64_t TxWait; // 0x58
+ uint64_t HwAddr; // 0x60
+ } regs;
+
+ struct VirtualReg {
+ uint64_t RxData;
+ uint64_t RxDone;
+ uint64_t TxData;
+ uint64_t TxDone;
+
+ PacketFifo::iterator rxPacket;
+ int rxPacketOffset;
+ int rxPacketBytes;
+ uint64_t rxDoneData;
+
+ Counter rxUnique;
+ Counter txUnique;
+
+ VirtualReg()
+ : RxData(0), RxDone(0), TxData(0), TxDone(0),
+ rxPacketOffset(0), rxPacketBytes(0), rxDoneData(0)
+ { }
+ };
+ typedef std::vector<VirtualReg> VirtualRegs;
+ typedef std::list<int> VirtualList;
+ Counter rxUnique;
+ Counter txUnique;
+ VirtualRegs virtualRegs;
+ VirtualList rxList;
+ VirtualList rxBusy;
+ int rxActive;
+ VirtualList txList;
+
+ uint8_t &regData8(Addr daddr) { return *((uint8_t *)&regs + daddr); }
+ uint32_t &regData32(Addr daddr) { return *(uint32_t *)&regData8(daddr); }
+ uint64_t &regData64(Addr daddr) { return *(uint64_t *)&regData8(daddr); }
+
+ protected:
+ RxState rxState;
+ PacketFifo rxFifo;
+ PacketFifo::iterator rxFifoPtr;
+ bool rxEmpty;
+ bool rxLow;
+ Addr rxDmaAddr;
+ uint8_t *rxDmaData;
+ int rxDmaLen;
+
+ TxState txState;
+ PacketFifo txFifo;
+ bool txFull;
+ EthPacketPtr txPacket;
+ int txPacketOffset;
+ int txPacketBytes;
+ Addr txDmaAddr;
+ uint8_t *txDmaData;
+ int txDmaLen;
+
+ protected:
+ void reset();
+
+ void rxKick();
+ Tick rxKickTick;
+ typedef EventWrapper<Device, &Device::rxKick> RxKickEvent;
+ friend void RxKickEvent::process();
+
+ void txKick();
+ Tick txKickTick;
+ typedef EventWrapper<Device, &Device::txKick> TxKickEvent;
+ friend void TxKickEvent::process();
+
+ /**
+ * Retransmit event
+ */
+ void transmit();
+ void txEventTransmit()
+ {
+ transmit();
+ if (txState == txFifoBlock)
+ txKick();
+ }
+ typedef EventWrapper<Device, &Device::txEventTransmit> TxEvent;
+ friend void TxEvent::process();
+ TxEvent txEvent;
+
+ void txDump() const;
+ void rxDump() const;
+
+ /**
+ * receive address filter
+ */
+ bool rxFilter(const EthPacketPtr &packet);
+
+/**
+ * device configuration
+ */
+ void changeConfig(uint32_t newconfig);
+ void command(uint32_t command);
+
+/**
+ * device ethernet interface
+ */
+ public:
+ bool recvPacket(EthPacketPtr packet);
+ void transferDone();
+ void setInterface(Interface *i) { assert(!interface); interface = i; }
+
+/**
+ * DMA parameters
+ */
+ protected:
+ void rxDmaDone();
+ friend class EventWrapper<Device, &Device::rxDmaDone>;
+ EventWrapper<Device, &Device::rxDmaDone> rxDmaEvent;
+
+ void txDmaDone();
+ friend class EventWrapper<Device, &Device::txDmaDone>;
+ EventWrapper<Device, &Device::txDmaDone> txDmaEvent;
+
+ Tick dmaReadDelay;
+ Tick dmaReadFactor;
+ Tick dmaWriteDelay;
+ Tick dmaWriteFactor;
+
+/**
+ * Interrupt management
+ */
+ protected:
+ void devIntrPost(uint32_t interrupts);
+ void devIntrClear(uint32_t interrupts = Regs::Intr_All);
+ void devIntrChangeMask(uint32_t newmask);
+
+/**
+ * Memory Interface
+ */
+ public:
+ 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);
+
+/**
+ * Statistics
+ */
+ private:
+ Stats::Scalar<> rxBytes;
+ Stats::Formula rxBandwidth;
+ Stats::Scalar<> rxPackets;
+ Stats::Formula rxPacketRate;
+ Stats::Scalar<> rxIpPackets;
+ Stats::Scalar<> rxTcpPackets;
+ Stats::Scalar<> rxUdpPackets;
+ Stats::Scalar<> rxIpChecksums;
+ Stats::Scalar<> rxTcpChecksums;
+ Stats::Scalar<> rxUdpChecksums;
+
+ Stats::Scalar<> txBytes;
+ Stats::Formula txBandwidth;
+ Stats::Formula totBandwidth;
+ Stats::Formula totPackets;
+ Stats::Formula totBytes;
+ Stats::Formula totPacketRate;
+ Stats::Scalar<> txPackets;
+ Stats::Formula txPacketRate;
+ Stats::Scalar<> txIpPackets;
+ Stats::Scalar<> txTcpPackets;
+ Stats::Scalar<> txUdpPackets;
+ Stats::Scalar<> txIpChecksums;
+ Stats::Scalar<> txTcpChecksums;
+ Stats::Scalar<> txUdpChecksums;
+
+ public:
+ virtual void regStats();
+
+/**
+ * Serialization stuff
+ */
+ public:
+ virtual void serialize(std::ostream &os);
+ virtual void unserialize(Checkpoint *cp, const std::string &section);
+
+/**
+ * Construction/Destruction/Parameters
+ */
+ public:
+ struct Params : public Base::Params
+ {
+ Tick tx_delay;
+ Tick rx_delay;
+ bool rx_filter;
+ Net::EthAddr eaddr;
+ uint32_t rx_max_copy;
+ uint32_t tx_max_copy;
+ uint32_t rx_max_intr;
+ uint32_t rx_fifo_size;
+ uint32_t tx_fifo_size;
+ uint32_t rx_fifo_threshold;
+ uint32_t rx_fifo_low_mark;
+ uint32_t tx_fifo_high_mark;
+ uint32_t tx_fifo_threshold;
+ Tick dma_read_delay;
+ Tick dma_read_factor;
+ Tick dma_write_delay;
+ Tick dma_write_factor;
+ bool rx_thread;
+ bool tx_thread;
+ bool rss;
+ uint32_t virtual_count;
+ bool zero_copy;
+ bool delay_copy;
+ bool virtual_addr;
+ };
+
+ protected:
+ const Params *params() const { return (const Params *)_params; }
+
+ public:
+ Device(Params *params);
+ ~Device();
+};
+
+/*
+ * Ethernet Interface for an Ethernet Device
+ */
+class Interface : public EtherInt
+{
+ private:
+ Device *dev;
+
+ public:
+ Interface(const std::string &name, Device *d)
+ : EtherInt(name), dev(d) { dev->setInterface(this); }
+
+ virtual bool recvPacket(EthPacketPtr pkt) { return dev->recvPacket(pkt); }
+ virtual void sendDone() { dev->transferDone(); }
+};
+
+/* namespace Sinic */ }
+
+#endif // __DEV_SINIC_HH__
diff --git a/dev/sinicreg.hh b/src/dev/sinicreg.hh
index d41eb5b16..d41eb5b16 100644
--- a/dev/sinicreg.hh
+++ b/src/dev/sinicreg.hh
diff --git a/src/dev/tsunami.cc b/src/dev/tsunami.cc
new file mode 100644
index 000000000..ed011531d
--- /dev/null
+++ b/src/dev/tsunami.cc
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file
+ * Implementation of Tsunami platform.
+ */
+
+#include <deque>
+#include <string>
+#include <vector>
+
+#include "cpu/intr_control.hh"
+#include "dev/simconsole.hh"
+#include "dev/tsunami_cchip.hh"
+#include "dev/tsunami_pchip.hh"
+#include "dev/tsunami_io.hh"
+#include "dev/tsunami.hh"
+#include "sim/builder.hh"
+#include "sim/system.hh"
+
+using namespace std;
+//Should this be AlphaISA?
+using namespace TheISA;
+
+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;
+
+ for (int i = 0; i < Tsunami::Max_CPUs; i++)
+ intr_sum_type[i] = 0;
+}
+
+Tick
+Tsunami::intrFrequency()
+{
+ return io->frequency();
+}
+
+void
+Tsunami::postConsoleInt()
+{
+ io->postPIC(0x10);
+}
+
+void
+Tsunami::clearConsoleInt()
+{
+ io->clearPIC(0x10);
+}
+
+void
+Tsunami::postPciInt(int line)
+{
+ cchip->postDRIR(line);
+}
+
+void
+Tsunami::clearPciInt(int line)
+{
+ cchip->clearDRIR(line);
+}
+
+Addr
+Tsunami::pciToDma(Addr pciAddr) const
+{
+ return pchip->translatePciToDma(pciAddr);
+}
+
+void
+Tsunami::serialize(std::ostream &os)
+{
+ SERIALIZE_ARRAY(intr_sum_type, Tsunami::Max_CPUs);
+}
+
+void
+Tsunami::unserialize(Checkpoint *cp, const std::string &section)
+{
+ UNSERIALIZE_ARRAY(intr_sum_type, Tsunami::Max_CPUs);
+}
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(Tsunami)
+
+ SimObjectParam<System *> system;
+ SimObjectParam<IntrControl *> intrctrl;
+
+END_DECLARE_SIM_OBJECT_PARAMS(Tsunami)
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(Tsunami)
+
+ INIT_PARAM(system, "system"),
+ INIT_PARAM(intrctrl, "interrupt controller")
+
+END_INIT_SIM_OBJECT_PARAMS(Tsunami)
+
+CREATE_SIM_OBJECT(Tsunami)
+{
+ return new Tsunami(getInstanceName(), system, intrctrl);
+}
+
+REGISTER_SIM_OBJECT("Tsunami", Tsunami)
diff --git a/src/dev/tsunami.hh b/src/dev/tsunami.hh
new file mode 100644
index 000000000..668c82674
--- /dev/null
+++ b/src/dev/tsunami.hh
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * Declaration of top level class for the Tsunami chipset. This class just
+ * retains pointers to all its children so the children can communicate.
+ */
+
+#ifndef __DEV_TSUNAMI_HH__
+#define __DEV_TSUNAMI_HH__
+
+#include "dev/platform.hh"
+
+class IdeController;
+class TsunamiCChip;
+class TsunamiPChip;
+class TsunamiIO;
+class System;
+
+/**
+ * Top level class for Tsunami Chipset emulation.
+ * This structure just contains pointers to all the
+ * children so the children can commnicate to do the
+ * read work
+ */
+
+class Tsunami : public Platform
+{
+ public:
+ /** Max number of CPUs in a Tsunami */
+ static const int Max_CPUs = 64;
+
+ /** Pointer to the system */
+ System *system;
+
+ /** Pointer to the TsunamiIO device which has the RTC */
+ TsunamiIO *io;
+
+ /** Pointer to the Tsunami CChip.
+ * The chip contains some configuration information and
+ * all the interrupt mask and status registers
+ */
+ TsunamiCChip *cchip;
+
+ /** Pointer to the Tsunami PChip.
+ * The pchip is the interface to the PCI bus, in our case
+ * it does not have to do much.
+ */
+ TsunamiPChip *pchip;
+
+ int intr_sum_type[Tsunami::Max_CPUs];
+ int ipi_pending[Tsunami::Max_CPUs];
+
+ public:
+ /**
+ * Constructor for the Tsunami Class.
+ * @param name name of the object
+ * @param intrctrl pointer to the interrupt controller
+ */
+ Tsunami(const std::string &name, System *s, IntrControl *intctrl);
+
+ /**
+ * Return the interrupting frequency to AlphaAccess
+ * @return frequency of RTC interrupts
+ */
+ virtual Tick intrFrequency();
+
+ /**
+ * Cause the cpu to post a serial interrupt to the CPU.
+ */
+ virtual void postConsoleInt();
+
+ /**
+ * Clear a posted CPU interrupt (id=55)
+ */
+ virtual void clearConsoleInt();
+
+ /**
+ * Cause the chipset to post a cpi interrupt to the CPU.
+ */
+ virtual void postPciInt(int line);
+
+ /**
+ * Clear a posted PCI->CPU interrupt
+ */
+ virtual void clearPciInt(int line);
+
+ virtual Addr pciToDma(Addr pciAddr) const;
+
+ /**
+ * Serialize this object to the given output stream.
+ * @param os The stream to serialize to.
+ */
+ virtual void serialize(std::ostream &os);
+
+ /**
+ * Reconstruct the state of this object from a checkpoint.
+ * @param cp The checkpoint use.
+ * @param section The section name of this object
+ */
+ virtual void unserialize(Checkpoint *cp, const std::string &section);
+};
+
+#endif // __DEV_TSUNAMI_HH__
diff --git a/src/dev/tsunami_cchip.cc b/src/dev/tsunami_cchip.cc
new file mode 100644
index 000000000..146321b9f
--- /dev/null
+++ b/src/dev/tsunami_cchip.cc
@@ -0,0 +1,554 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file
+ * Emulation of the Tsunami CChip CSRs
+ */
+
+#include <deque>
+#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/port.hh"
+#include "cpu/exec_context.hh"
+#include "cpu/intr_control.hh"
+#include "sim/builder.hh"
+#include "sim/system.hh"
+
+using namespace std;
+//Should this be AlphaISA?
+using namespace TheISA;
+
+TsunamiCChip::TsunamiCChip(Params *p)
+ : BasicPioDevice(p), tsunami(p->tsunami)
+{
+ pioSize = 0xfffffff;
+
+ drir = 0;
+ ipint = 0;
+ itint = 0;
+
+ for (int x = 0; x < Tsunami::Max_CPUs; x++)
+ {
+ dim[x] = 0;
+ dir[x] = 0;
+ }
+
+ //Put back pointer in tsunami
+ tsunami->cchip = this;
+}
+
+Tick
+TsunamiCChip::read(Packet *pkt)
+{
+ DPRINTF(Tsunami, "read va=%#x size=%d\n", pkt->getAddr(), pkt->getSize());
+
+ assert(pkt->result == Packet::Unknown);
+ assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
+
+ pkt->time += pioDelay;
+ Addr regnum = (pkt->getAddr() - pioAddr) >> 6;
+ Addr daddr = (pkt->getAddr() - pioAddr);
+
+ pkt->allocate();
+ switch (pkt->getSize()) {
+
+ case sizeof(uint64_t):
+ if (daddr & TSDEV_CC_BDIMS)
+ {
+ pkt->set(dim[(daddr >> 4) & 0x3F]);
+ break;
+ }
+
+ if (daddr & TSDEV_CC_BDIRS)
+ {
+ pkt->set(dir[(daddr >> 4) & 0x3F]);
+ break;
+ }
+
+ switch(regnum) {
+ case TSDEV_CC_CSR:
+ pkt->set(0x0);
+ break;
+ case TSDEV_CC_MTR:
+ panic("TSDEV_CC_MTR not implemeted\n");
+ break;
+ case TSDEV_CC_MISC:
+ 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:
+ pkt->set(0);
+ break;
+ case TSDEV_CC_DIM0:
+ pkt->set(dim[0]);
+ break;
+ case TSDEV_CC_DIM1:
+ pkt->set(dim[1]);
+ break;
+ case TSDEV_CC_DIM2:
+ pkt->set(dim[2]);
+ break;
+ case TSDEV_CC_DIM3:
+ pkt->set(dim[3]);
+ break;
+ case TSDEV_CC_DIR0:
+ pkt->set(dir[0]);
+ break;
+ case TSDEV_CC_DIR1:
+ pkt->set(dir[1]);
+ break;
+ case TSDEV_CC_DIR2:
+ pkt->set(dir[2]);
+ break;
+ case TSDEV_CC_DIR3:
+ pkt->set(dir[3]);
+ break;
+ case TSDEV_CC_DRIR:
+ pkt->set(drir);
+ break;
+ case TSDEV_CC_PRBEN:
+ panic("TSDEV_CC_PRBEN not implemented\n");
+ break;
+ case TSDEV_CC_IIC0:
+ case TSDEV_CC_IIC1:
+ case TSDEV_CC_IIC2:
+ case TSDEV_CC_IIC3:
+ panic("TSDEV_CC_IICx not implemented\n");
+ break;
+ case TSDEV_CC_MPR0:
+ case TSDEV_CC_MPR1:
+ case TSDEV_CC_MPR2:
+ case TSDEV_CC_MPR3:
+ panic("TSDEV_CC_MPRx not implemented\n");
+ break;
+ case TSDEV_CC_IPIR:
+ pkt->set(ipint);
+ break;
+ case TSDEV_CC_ITIR:
+ pkt->set(itint);
+ break;
+ default:
+ panic("default in cchip read reached, accessing 0x%x\n");
+ } // uint64_t
+
+ break;
+ case sizeof(uint32_t):
+ case sizeof(uint16_t):
+ case sizeof(uint8_t):
+ default:
+ panic("invalid access size(?) for tsunami register!\n");
+ }
+ DPRINTF(Tsunami, "Tsunami CChip: read regnum=%#x size=%d data=%lld\n",
+ regnum, pkt->getSize(), pkt->get<uint64_t>());
+
+ pkt->result = Packet::Success;
+ return pioDelay;
+}
+
+Tick
+TsunamiCChip::write(Packet *pkt)
+{
+ pkt->time += pioDelay;
+
+
+ assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
+ Addr daddr = pkt->getAddr() - pioAddr;
+ Addr regnum = (pkt->getAddr() - pioAddr) >> 6 ;
+
+
+ assert(pkt->getSize() == sizeof(uint64_t));
+
+ DPRINTF(Tsunami, "write - addr=%#x value=%#x\n", pkt->getAddr(), pkt->get<uint64_t>());
+
+ bool supportedWrite = false;
+
+
+ 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);
+
+ }
+
+
+ }
+ }
+ } 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 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;
+ }
+
+ //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;
+ }
+
+ // 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);
+
+ }
+
+
+ }
+ }
+ 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 = Packet::Success;
+ return pioDelay;
+}
+
+void
+TsunamiCChip::clearIPI(uint64_t ipintr)
+{
+ int numcpus = tsunami->intrctrl->cpu->system->execContexts.size();
+ assert(numcpus <= Tsunami::Max_CPUs);
+
+ if (ipintr) {
+ for (int cpunum=0; cpunum < numcpus; cpunum++) {
+ // Check each cpu bit
+ uint64_t cpumask = ULL(1) << cpunum;
+ if (ipintr & cpumask) {
+ // Check if there is a pending ipi
+ if (ipint & cpumask) {
+ ipint &= ~cpumask;
+ tsunami->intrctrl->clear(cpunum, TheISA::INTLEVEL_IRQ3, 0);
+ DPRINTF(IPI, "clear IPI IPI cpu=%d\n", cpunum);
+ }
+ else
+ warn("clear IPI for CPU=%d, but NO IPI\n", cpunum);
+ }
+ }
+ }
+ else
+ panic("Big IPI Clear, but not processors indicated\n");
+}
+
+void
+TsunamiCChip::clearITI(uint64_t itintr)
+{
+ int numcpus = tsunami->intrctrl->cpu->system->execContexts.size();
+ assert(numcpus <= Tsunami::Max_CPUs);
+
+ if (itintr) {
+ for (int i=0; i < numcpus; i++) {
+ uint64_t cpumask = ULL(1) << i;
+ if (itintr & cpumask & itint) {
+ tsunami->intrctrl->clear(i, TheISA::INTLEVEL_IRQ2, 0);
+ itint &= ~cpumask;
+ DPRINTF(Tsunami, "clearing rtc interrupt to cpu=%d\n", i);
+ }
+ }
+ }
+ else
+ panic("Big ITI Clear, but not processors indicated\n");
+}
+
+void
+TsunamiCChip::reqIPI(uint64_t ipreq)
+{
+ int numcpus = tsunami->intrctrl->cpu->system->execContexts.size();
+ assert(numcpus <= Tsunami::Max_CPUs);
+
+ if (ipreq) {
+ for (int cpunum=0; cpunum < numcpus; cpunum++) {
+ // Check each cpu bit
+ uint64_t cpumask = ULL(1) << cpunum;
+ if (ipreq & cpumask) {
+ // Check if there is already an ipi (bits 8:11)
+ if (!(ipint & cpumask)) {
+ ipint |= cpumask;
+ tsunami->intrctrl->post(cpunum, TheISA::INTLEVEL_IRQ3, 0);
+ DPRINTF(IPI, "send IPI cpu=%d\n", cpunum);
+ }
+ else
+ warn("post IPI for CPU=%d, but IPI already\n", cpunum);
+ }
+ }
+ }
+ else
+ panic("Big IPI Request, but not processors indicated\n");
+}
+
+
+void
+TsunamiCChip::postRTC()
+{
+ int size = tsunami->intrctrl->cpu->system->execContexts.size();
+ assert(size <= Tsunami::Max_CPUs);
+
+ 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);
+ }
+ }
+
+}
+
+void
+TsunamiCChip::postDRIR(uint32_t interrupt)
+{
+ uint64_t bitvector = ULL(1) << interrupt;
+ uint64_t size = tsunami->intrctrl->cpu->system->execContexts.size();
+ assert(size <= Tsunami::Max_CPUs);
+ drir |= bitvector;
+
+ 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,"
+ "interrupt %d\n",i, interrupt);
+ }
+ }
+}
+
+void
+TsunamiCChip::clearDRIR(uint32_t interrupt)
+{
+ uint64_t bitvector = ULL(1) << interrupt;
+ uint64_t size = tsunami->intrctrl->cpu->system->execContexts.size();
+ assert(size <= Tsunami::Max_CPUs);
+
+ if (drir & bitvector)
+ {
+ 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,"
+ "interrupt %d\n",i, interrupt);
+
+ }
+ dir[i] = dim[i] & drir;
+ }
+ }
+ else
+ DPRINTF(Tsunami, "Spurrious clear? interrupt %d\n", interrupt);
+}
+
+
+void
+TsunamiCChip::serialize(std::ostream &os)
+{
+ SERIALIZE_ARRAY(dim, Tsunami::Max_CPUs);
+ SERIALIZE_ARRAY(dir, Tsunami::Max_CPUs);
+ SERIALIZE_SCALAR(ipint);
+ SERIALIZE_SCALAR(itint);
+ SERIALIZE_SCALAR(drir);
+}
+
+void
+TsunamiCChip::unserialize(Checkpoint *cp, const std::string &section)
+{
+ UNSERIALIZE_ARRAY(dim, Tsunami::Max_CPUs);
+ UNSERIALIZE_ARRAY(dir, Tsunami::Max_CPUs);
+ UNSERIALIZE_SCALAR(ipint);
+ UNSERIALIZE_SCALAR(itint);
+ UNSERIALIZE_SCALAR(drir);
+}
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiCChip)
+
+ Param<Addr> pio_addr;
+ Param<Tick> pio_latency;
+ SimObjectParam<Platform *> platform;
+ SimObjectParam<System *> system;
+ SimObjectParam<Tsunami *> tsunami;
+
+END_DECLARE_SIM_OBJECT_PARAMS(TsunamiCChip)
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiCChip)
+
+ 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)
+{
+ 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/src/dev/tsunami_cchip.hh b/src/dev/tsunami_cchip.hh
new file mode 100644
index 000000000..3dde0131e
--- /dev/null
+++ b/src/dev/tsunami_cchip.hh
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file
+ * Emulation of the Tsunami CChip CSRs
+ */
+
+#ifndef __TSUNAMI_CCHIP_HH__
+#define __TSUNAMI_CCHIP_HH__
+
+#include "dev/tsunami.hh"
+#include "base/range.hh"
+#include "dev/io_device.hh"
+
+
+/**
+ * Tsunami CChip CSR Emulation. This device includes all the interrupt
+ * handling code for the chipset.
+ */
+class TsunamiCChip : public BasicPioDevice
+{
+ protected:
+ /**
+ * pointer to the tsunami object.
+ * This is our access to all the other tsunami
+ * devices.
+ */
+ Tsunami *tsunami;
+
+ /**
+ * The dims are device interrupt mask registers.
+ * One exists for each CPU, the DRIR X DIM = DIR
+ */
+ uint64_t dim[Tsunami::Max_CPUs];
+
+ /**
+ * The dirs are device interrupt registers.
+ * One exists for each CPU, the DRIR X DIM = DIR
+ */
+ uint64_t dir[Tsunami::Max_CPUs];
+
+ /**
+ * This register contains bits for each PCI interrupt
+ * that can occur.
+ */
+ uint64_t drir;
+
+ /** Indicator of which CPUs have an IPI interrupt */
+ uint64_t ipint;
+
+ /** Indicator of which CPUs have an RTC interrupt */
+ 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 p params struct
+ */
+ TsunamiCChip(Params *p);
+
+ virtual Tick read(Packet *pkt);
+
+ virtual Tick write(Packet *pkt);
+
+ /**
+ * post an RTC interrupt to the CPU
+ */
+ void postRTC();
+
+ /**
+ * post an interrupt to the CPU.
+ * @param interrupt the interrupt number to post (0-64)
+ */
+ void postDRIR(uint32_t interrupt);
+
+ /**
+ * clear an interrupt previously posted to the CPU.
+ * @param interrupt the interrupt number to post (0-64)
+ */
+ void clearDRIR(uint32_t interrupt);
+
+ /**
+ * post an ipi interrupt to the CPU.
+ * @param ipintr the cpu number to clear(bitvector)
+ */
+ void clearIPI(uint64_t ipintr);
+
+ /**
+ * clear a timer interrupt previously posted to the CPU.
+ * @param itintr the cpu number to clear(bitvector)
+ */
+ void clearITI(uint64_t itintr);
+
+ /**
+ * request an interrupt be posted to the CPU.
+ * @param ipreq the cpu number to interrupt(bitvector)
+ */
+ void reqIPI(uint64_t ipreq);
+
+
+ /**
+ * Serialize this object to the given output stream.
+ * @param os The stream to serialize to.
+ */
+ virtual void serialize(std::ostream &os);
+
+ /**
+ * Reconstruct the state of this object from a checkpoint.
+ * @param cp The checkpoint use.
+ * @param section The section name of this object
+ */
+ virtual void unserialize(Checkpoint *cp, const std::string &section);
+
+};
+
+#endif // __TSUNAMI_CCHIP_HH__
diff --git a/src/dev/tsunami_io.cc b/src/dev/tsunami_io.cc
new file mode 100644
index 000000000..729a61cf7
--- /dev/null
+++ b/src/dev/tsunami_io.cc
@@ -0,0 +1,685 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file
+ * Tsunami I/O including PIC, PIT, RTC, DMA
+ */
+
+#include <sys/time.h>
+
+#include <deque>
+#include <string>
+#include <vector>
+
+#include "base/trace.hh"
+#include "dev/pitreg.h"
+#include "dev/rtcreg.h"
+#include "dev/tsunami_cchip.hh"
+#include "dev/tsunami.hh"
+#include "dev/tsunami_io.hh"
+#include "dev/tsunamireg.h"
+#include "mem/port.hh"
+#include "sim/builder.hh"
+#include "sim/system.hh"
+
+using namespace std;
+//Should this be AlphaISA?
+using namespace TheISA;
+
+TsunamiIO::RTC::RTC(const string &name, Tsunami* t, Tick i)
+ : _name(name), event(t, i), addr(0)
+{
+ memset(clock_data, 0, sizeof(clock_data));
+ stat_regA = RTCA_32768HZ | RTCA_1024HZ;
+ stat_regB = RTCB_PRDC_IE |RTCB_BIN | RTCB_24HR;
+}
+
+void
+TsunamiIO::RTC::set_time(time_t t)
+{
+ struct tm tm;
+ gmtime_r(&t, &tm);
+
+ sec = tm.tm_sec;
+ min = tm.tm_min;
+ hour = tm.tm_hour;
+ wday = tm.tm_wday + 1;
+ mday = tm.tm_mday;
+ mon = tm.tm_mon + 1;
+ year = tm.tm_year;
+
+ DPRINTFN("Real-time clock set to %s", asctime(&tm));
+}
+
+void
+TsunamiIO::RTC::writeAddr(const uint8_t 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)
+{
+ if (addr < RTC_STAT_REGA)
+ clock_data[addr] = data;
+ else {
+ switch (addr) {
+ case RTC_STAT_REGA:
+ if (data != (RTCA_32768HZ | RTCA_1024HZ))
+ panic("Unimplemented RTC register A value write!\n");
+ stat_regA = data;
+ break;
+ case RTC_STAT_REGB:
+ 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 (!event.scheduled())
+ event.scheduleIntr();
+ } else {
+ if (event.scheduled())
+ event.deschedule();
+ }
+ stat_regB = data;
+ break;
+ case RTC_STAT_REGC:
+ case RTC_STAT_REGD:
+ panic("RTC status registers C and D are not implemented.\n");
+ break;
+ }
+ }
+}
+
+uint8_t
+TsunamiIO::RTC::readData()
+{
+ if (addr < RTC_STAT_REGA)
+ return clock_data[addr];
+ else {
+ switch (addr) {
+ case RTC_STAT_REGA:
+ // toggle UIP bit for linux
+ stat_regA ^= RTCA_UIP;
+ return stat_regA;
+ break;
+ case RTC_STAT_REGB:
+ return stat_regB;
+ break;
+ case RTC_STAT_REGC:
+ case RTC_STAT_REGD:
+ return 0x00;
+ break;
+ default:
+ panic("Shouldn't be here");
+ }
+ }
+}
+
+void
+TsunamiIO::RTC::serialize(const string &base, ostream &os)
+{
+ paramOut(os, base + ".addr", addr);
+ arrayParamOut(os, base + ".clock_data", clock_data, sizeof(clock_data));
+ paramOut(os, base + ".stat_regA", stat_regA);
+ paramOut(os, base + ".stat_regB", stat_regB);
+}
+
+void
+TsunamiIO::RTC::unserialize(const string &base, Checkpoint *cp,
+ const string &section)
+{
+ paramIn(cp, section, base + ".addr", addr);
+ arrayParamIn(cp, section, base + ".clock_data", clock_data,
+ sizeof(clock_data));
+ paramIn(cp, section, base + ".stat_regA", stat_regA);
+ paramIn(cp, section, base + ".stat_regB", stat_regB);
+
+ // We're not unserializing the event here, but we need to
+ // rescehedule the event since curTick was moved forward by the
+ // checkpoint
+ event.reschedule(curTick + event.interval);
+}
+
+TsunamiIO::RTC::RTCEvent::RTCEvent(Tsunami*t, Tick i)
+ : Event(&mainEventQueue), tsunami(t), interval(i)
+{
+ DPRINTF(MC146818, "RTC Event Initilizing\n");
+ schedule(curTick + interval);
+}
+
+void
+TsunamiIO::RTC::RTCEvent::scheduleIntr()
+{
+ schedule(curTick + interval);
+}
+
+void
+TsunamiIO::RTC::RTCEvent::process()
+{
+ DPRINTF(MC146818, "RTC Timer Interrupt\n");
+ schedule(curTick + interval);
+ //Actually interrupt the processor here
+ tsunami->cchip->postRTC();
+}
+
+const char *
+TsunamiIO::RTC::RTCEvent::description()
+{
+ return "tsunami RTC interrupt";
+}
+
+TsunamiIO::PITimer::PITimer(const string &name)
+ : _name(name), counter0(name + ".counter0"), counter1(name + ".counter1"),
+ counter2(name + ".counter2")
+{
+ counter[0] = &counter0;
+ counter[1] = &counter0;
+ counter[2] = &counter0;
+}
+
+void
+TsunamiIO::PITimer::writeControl(const uint8_t data)
+{
+ int rw;
+ int sel;
+
+ sel = GET_CTRL_SEL(data);
+
+ if (sel == PIT_READ_BACK)
+ panic("PITimer Read-Back Command is not implemented.\n");
+
+ 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));
+ }
+}
+
+void
+TsunamiIO::PITimer::serialize(const string &base, ostream &os)
+{
+ // serialize the counters
+ counter0.serialize(base + ".counter0", os);
+ counter1.serialize(base + ".counter1", os);
+ counter2.serialize(base + ".counter2", os);
+}
+
+void
+TsunamiIO::PITimer::unserialize(const string &base, Checkpoint *cp,
+ const string &section)
+{
+ // unserialze the counters
+ counter0.unserialize(base + ".counter0", cp, section);
+ counter1.unserialize(base + ".counter1", cp, section);
+ counter2.unserialize(base + ".counter2", cp, section);
+}
+
+TsunamiIO::PITimer::Counter::Counter(const string &name)
+ : _name(name), event(this), count(0), latched_count(0), period(0),
+ mode(0), output_high(false), latch_on(false), read_byte(LSB),
+ write_byte(LSB)
+{
+
+}
+
+void
+TsunamiIO::PITimer::Counter::latchCount()
+{
+ // behave like a real latch
+ if(!latch_on) {
+ latch_on = true;
+ read_byte = LSB;
+ latched_count = count;
+ }
+}
+
+uint8_t
+TsunamiIO::PITimer::Counter::read()
+{
+ if (latch_on) {
+ switch (read_byte) {
+ case LSB:
+ read_byte = MSB;
+ return (uint8_t)latched_count;
+ break;
+ case MSB:
+ read_byte = LSB;
+ latch_on = false;
+ return latched_count >> 8;
+ break;
+ default:
+ panic("Shouldn't be here");
+ }
+ } else {
+ switch (read_byte) {
+ case LSB:
+ read_byte = MSB;
+ return (uint8_t)count;
+ break;
+ case MSB:
+ read_byte = LSB;
+ return count >> 8;
+ break;
+ default:
+ panic("Shouldn't be here");
+ }
+ }
+}
+
+void
+TsunamiIO::PITimer::Counter::write(const uint8_t data)
+{
+ switch (write_byte) {
+ case LSB:
+ count = (count & 0xFF00) | data;
+
+ if (event.scheduled())
+ event.deschedule();
+ output_high = false;
+ write_byte = MSB;
+ break;
+
+ case MSB:
+ count = (count & 0x00FF) | (data << 8);
+ period = count;
+
+ if (period > 0) {
+ DPRINTF(Tsunami, "Timer set to curTick + %d\n",
+ count * event.interval);
+ event.schedule(curTick + count * event.interval);
+ }
+ write_byte = LSB;
+ break;
+ }
+}
+
+void
+TsunamiIO::PITimer::Counter::setRW(int rw_val)
+{
+ if (rw_val != PIT_RW_16BIT)
+ panic("Only LSB/MSB read/write is implemented.\n");
+}
+
+void
+TsunamiIO::PITimer::Counter::setMode(int mode_val)
+{
+ if(mode_val != PIT_MODE_INTTC && mode_val != PIT_MODE_RATEGEN &&
+ mode_val != PIT_MODE_SQWAVE)
+ panic("PIT mode %#x is not implemented: \n", mode_val);
+
+ mode = mode_val;
+}
+
+void
+TsunamiIO::PITimer::Counter::setBCD(int bcd_val)
+{
+ if (bcd_val != PIT_BCD_FALSE)
+ panic("PITimer does not implement BCD counts.\n");
+}
+
+bool
+TsunamiIO::PITimer::Counter::outputHigh()
+{
+ return output_high;
+}
+
+void
+TsunamiIO::PITimer::Counter::serialize(const string &base, ostream &os)
+{
+ paramOut(os, base + ".count", count);
+ paramOut(os, base + ".latched_count", latched_count);
+ paramOut(os, base + ".period", period);
+ paramOut(os, base + ".mode", mode);
+ paramOut(os, base + ".output_high", output_high);
+ paramOut(os, base + ".latch_on", latch_on);
+ paramOut(os, base + ".read_byte", read_byte);
+ paramOut(os, base + ".write_byte", write_byte);
+
+ Tick event_tick = 0;
+ if (event.scheduled())
+ event_tick = event.when();
+ paramOut(os, base + ".event_tick", event_tick);
+}
+
+void
+TsunamiIO::PITimer::Counter::unserialize(const string &base, Checkpoint *cp,
+ const string &section)
+{
+ paramIn(cp, section, base + ".count", count);
+ paramIn(cp, section, base + ".latched_count", latched_count);
+ paramIn(cp, section, base + ".period", period);
+ paramIn(cp, section, base + ".mode", mode);
+ paramIn(cp, section, base + ".output_high", output_high);
+ paramIn(cp, section, base + ".latch_on", latch_on);
+ paramIn(cp, section, base + ".read_byte", read_byte);
+ paramIn(cp, section, base + ".write_byte", write_byte);
+
+ Tick event_tick;
+ paramIn(cp, section, base + ".event_tick", event_tick);
+ if (event_tick)
+ event.schedule(event_tick);
+}
+
+TsunamiIO::PITimer::Counter::CounterEvent::CounterEvent(Counter* c_ptr)
+ : Event(&mainEventQueue)
+{
+ interval = (Tick)(Clock::Float::s / 1193180.0);
+ counter = c_ptr;
+}
+
+void
+TsunamiIO::PITimer::Counter::CounterEvent::process()
+{
+ DPRINTF(Tsunami, "Timer Interrupt\n");
+ switch (counter->mode) {
+ case PIT_MODE_INTTC:
+ counter->output_high = true;
+ case PIT_MODE_RATEGEN:
+ case PIT_MODE_SQWAVE:
+ break;
+ default:
+ panic("Unimplemented PITimer mode.\n");
+ }
+}
+
+const char *
+TsunamiIO::PITimer::Counter::CounterEvent::description()
+{
+ return "tsunami 8254 Interval timer";
+}
+
+TsunamiIO::TsunamiIO(Params *p)
+ : BasicPioDevice(p), tsunami(p->tsunami), pitimer(p->name + "pitimer"),
+ rtc(p->name + ".rtc", p->tsunami, p->frequency)
+{
+ pioSize = 0xff;
+
+ // set the back pointer from tsunami to myself
+ tsunami->io = this;
+
+ timerData = 0;
+ rtc.set_time(p->init_time == 0 ? time(NULL) : p->init_time);
+ picr = 0;
+ picInterrupting = false;
+}
+
+Tick
+TsunamiIO::frequency() const
+{
+ return Clock::Frequency / params()->frequency;
+}
+
+Tick
+TsunamiIO::read(Packet *pkt)
+{
+ assert(pkt->result == Packet::Unknown);
+ assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
+
+ pkt->time += pioDelay;
+ Addr daddr = pkt->getAddr() - pioAddr;
+
+ DPRINTF(Tsunami, "io read va=%#x size=%d IOPorrt=%#x\n", pkt->getAddr(),
+ pkt->getSize(), daddr);
+
+ pkt->allocate();
+
+ if (pkt->getSize() == sizeof(uint8_t)) {
+ switch(daddr) {
+ // PIC1 mask read
+ case TSDEV_PIC1_MASK:
+ pkt->set(~mask1);
+ break;
+ case TSDEV_PIC2_MASK:
+ 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
+ pkt->set(picr);
+ break;
+ case TSDEV_PIC2_ISR:
+ // PIC2 not implemnted... just return 0
+ pkt->set(0x00);
+ break;
+ case TSDEV_TMR0_DATA:
+ pkt->set(pitimer.counter0.read());
+ break;
+ case TSDEV_TMR1_DATA:
+ pkt->set(pitimer.counter1.read());
+ break;
+ case TSDEV_TMR2_DATA:
+ pkt->set(pitimer.counter2.read());
+ break;
+ case TSDEV_RTC_DATA:
+ pkt->set(rtc.readData());
+ break;
+ case TSDEV_CTRL_PORTB:
+ if (pitimer.counter2.outputHigh())
+ pkt->set(PORTB_SPKR_HIGH);
+ else
+ pkt->set(0x00);
+ break;
+ default:
+ panic("I/O Read - va%#x size %d\n", pkt->getAddr(), pkt->getSize());
+ }
+ } else if (pkt->getSize() == 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->getAddr(), pkt->getSize());
+ } else {
+ panic("I/O Read - invalid size - va %#x size %d\n", pkt->getAddr(), pkt->getSize());
+ }
+ pkt->result = Packet::Success;
+ return pioDelay;
+}
+
+Tick
+TsunamiIO::write(Packet *pkt)
+{
+ pkt->time += pioDelay;
+
+ assert(pkt->result == Packet::Unknown);
+ assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
+ Addr daddr = pkt->getAddr() - pioAddr;
+
+ DPRINTF(Tsunami, "io write - va=%#x size=%d IOPort=%#x Data=%#x\n",
+ pkt->getAddr(), pkt->getSize(), pkt->getAddr() & 0xfff, (uint32_t)pkt->get<uint8_t>());
+
+ assert(pkt->getSize() == sizeof(uint8_t));
+
+ 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");
+ }
+ 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 - va%#x size %d data %#x\n", pkt->getAddr(), pkt->getSize(), pkt->get<uint8_t>());
+ }
+
+ pkt->result = Packet::Success;
+ return pioDelay;
+}
+
+void
+TsunamiIO::postPIC(uint8_t bitvector)
+{
+ //PIC2 Is not implemented, because nothing of interest there
+ picr |= bitvector;
+ if (picr & mask1) {
+ tsunami->cchip->postDRIR(55);
+ DPRINTF(Tsunami, "posting pic interrupt to cchip\n");
+ }
+}
+
+void
+TsunamiIO::clearPIC(uint8_t bitvector)
+{
+ //PIC2 Is not implemented, because nothing of interest there
+ picr &= ~bitvector;
+ if (!(picr & mask1)) {
+ tsunami->cchip->clearDRIR(55);
+ DPRINTF(Tsunami, "clearing pic interrupt to cchip\n");
+ }
+}
+
+void
+TsunamiIO::serialize(ostream &os)
+{
+ SERIALIZE_SCALAR(timerData);
+ SERIALIZE_SCALAR(mask1);
+ SERIALIZE_SCALAR(mask2);
+ SERIALIZE_SCALAR(mode1);
+ SERIALIZE_SCALAR(mode2);
+ SERIALIZE_SCALAR(picr);
+ SERIALIZE_SCALAR(picInterrupting);
+
+ // Serialize the timers
+ pitimer.serialize("pitimer", os);
+ rtc.serialize("rtc", os);
+}
+
+void
+TsunamiIO::unserialize(Checkpoint *cp, const string &section)
+{
+ UNSERIALIZE_SCALAR(timerData);
+ UNSERIALIZE_SCALAR(mask1);
+ UNSERIALIZE_SCALAR(mask2);
+ UNSERIALIZE_SCALAR(mode1);
+ UNSERIALIZE_SCALAR(mode2);
+ UNSERIALIZE_SCALAR(picr);
+ UNSERIALIZE_SCALAR(picInterrupting);
+
+ // Unserialize the timers
+ pitimer.unserialize("pitimer", cp, section);
+ rtc.unserialize("rtc", cp, section);
+}
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiIO)
+
+ Param<Addr> pio_addr;
+ Param<Tick> pio_latency;
+ 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(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(tsunami, "Tsunami")
+
+END_INIT_SIM_OBJECT_PARAMS(TsunamiIO)
+
+CREATE_SIM_OBJECT(TsunamiIO)
+{
+ 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/src/dev/tsunami_io.hh b/src/dev/tsunami_io.hh
new file mode 100644
index 000000000..71ca0d98f
--- /dev/null
+++ b/src/dev/tsunami_io.hh
@@ -0,0 +1,351 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file
+ * Tsunami I/O Space mapping including RTC/timer interrupts
+ */
+
+#ifndef __DEV_TSUNAMI_IO_HH__
+#define __DEV_TSUNAMI_IO_HH__
+
+#include "dev/io_device.hh"
+#include "base/range.hh"
+#include "dev/tsunami.hh"
+#include "sim/eventq.hh"
+
+/**
+ * Tsunami I/O device is a catch all for all the south bridge stuff we care
+ * to implement.
+ */
+class TsunamiIO : public BasicPioDevice
+{
+ private:
+ struct tm tm;
+
+ protected:
+ /** Real-Time Clock (MC146818) */
+ class RTC
+ {
+ private:
+ /** Event for RTC periodic interrupt */
+ struct RTCEvent : public Event
+ {
+ /** A pointer back to tsunami to create interrupt the processor. */
+ Tsunami* tsunami;
+ Tick interval;
+
+ RTCEvent(Tsunami* t, Tick i);
+
+ /** Schedule the RTC periodic interrupt */
+ void scheduleIntr();
+
+ /** Event process to occur at interrupt*/
+ virtual void process();
+
+ /** Event description */
+ virtual const char *description();
+ };
+
+ private:
+ std::string _name;
+ const std::string &name() const { return _name; }
+
+ /** RTC periodic interrupt event */
+ RTCEvent event;
+
+ /** Current RTC register address/index */
+ int addr;
+
+ /** Data for real-time clock function */
+ union {
+ uint8_t clock_data[10];
+
+ struct {
+ uint8_t sec;
+ uint8_t sec_alrm;
+ uint8_t min;
+ uint8_t min_alrm;
+ uint8_t hour;
+ uint8_t hour_alrm;
+ uint8_t wday;
+ uint8_t mday;
+ uint8_t mon;
+ uint8_t year;
+ };
+ };
+
+ /** RTC status register A */
+ uint8_t stat_regA;
+
+ /** RTC status register B */
+ uint8_t stat_regB;
+
+ public:
+ RTC(const std::string &name, Tsunami* t, Tick i);
+
+ /** Set the initial RTC time/date */
+ void set_time(time_t t);
+
+ /** RTC address port: write address of RTC RAM data to access */
+ void writeAddr(const uint8_t data);
+
+ /** RTC write data */
+ void writeData(const uint8_t data);
+
+ /** RTC read data */
+ uint8_t readData();
+
+ /**
+ * Serialize this object to the given output stream.
+ * @param os The stream to serialize to.
+ */
+ void serialize(const std::string &base, std::ostream &os);
+
+ /**
+ * Reconstruct the state of this object from a checkpoint.
+ * @param cp The checkpoint use.
+ * @param section The section name of this object
+ */
+ void unserialize(const std::string &base, Checkpoint *cp,
+ const std::string &section);
+ };
+
+ /** Programmable Interval Timer (Intel 8254) */
+ class PITimer
+ {
+ /** Counter element for PIT */
+ class Counter
+ {
+ /** Event for counter interrupt */
+ class CounterEvent : public Event
+ {
+ private:
+ /** Pointer back to Counter */
+ Counter* counter;
+ Tick interval;
+
+ public:
+ CounterEvent(Counter*);
+
+ /** Event process */
+ virtual void process();
+
+ /** Event description */
+ virtual const char *description();
+
+ friend class Counter;
+ };
+
+ private:
+ std::string _name;
+ const std::string &name() const { return _name; }
+
+ CounterEvent event;
+
+ /** Current count value */
+ uint16_t count;
+
+ /** Latched count */
+ uint16_t latched_count;
+
+ /** Interrupt period */
+ uint16_t period;
+
+ /** Current mode of operation */
+ uint8_t mode;
+
+ /** Output goes high when the counter reaches zero */
+ bool output_high;
+
+ /** State of the count latch */
+ bool latch_on;
+
+ /** Set of values for read_byte and write_byte */
+ enum {LSB, MSB};
+
+ /** Determine which byte of a 16-bit count value to read/write */
+ uint8_t read_byte, write_byte;
+
+ public:
+ Counter(const std::string &name);
+
+ /** Latch the current count (if one is not already latched) */
+ void latchCount();
+
+ /** Set the read/write mode */
+ void setRW(int rw_val);
+
+ /** Set operational mode */
+ void setMode(int mode_val);
+
+ /** Set count encoding */
+ void setBCD(int bcd_val);
+
+ /** Read a count byte */
+ uint8_t read();
+
+ /** Write a count byte */
+ void write(const uint8_t data);
+
+ /** Is the output high? */
+ bool outputHigh();
+
+ /**
+ * Serialize this object to the given output stream.
+ * @param os The stream to serialize to.
+ */
+ void serialize(const std::string &base, std::ostream &os);
+
+ /**
+ * Reconstruct the state of this object from a checkpoint.
+ * @param cp The checkpoint use.
+ * @param section The section name of this object
+ */
+ void unserialize(const std::string &base, Checkpoint *cp,
+ const std::string &section);
+ };
+
+ private:
+ std::string _name;
+ const std::string &name() const { return _name; }
+
+ /** PIT has three seperate counters */
+ Counter *counter[3];
+
+ public:
+ /** Public way to access individual counters (avoid array accesses) */
+ Counter counter0;
+ Counter counter1;
+ Counter counter2;
+
+ PITimer(const std::string &name);
+
+ /** Write control word */
+ void writeControl(const uint8_t data);
+
+ /**
+ * Serialize this object to the given output stream.
+ * @param os The stream to serialize to.
+ */
+ void serialize(const std::string &base, std::ostream &os);
+
+ /**
+ * Reconstruct the state of this object from a checkpoint.
+ * @param cp The checkpoint use.
+ * @param section The section name of this object
+ */
+ void unserialize(const std::string &base, Checkpoint *cp,
+ const std::string &section);
+ };
+
+ /** Mask of the PIC1 */
+ uint8_t mask1;
+
+ /** Mask of the PIC2 */
+ uint8_t mask2;
+
+ /** Mode of PIC1. Not used for anything */
+ uint8_t mode1;
+
+ /** Mode of PIC2. Not used for anything */
+ uint8_t mode2;
+
+ /** Raw PIC interrupt register before masking */
+ uint8_t picr; //Raw PIC interrput register
+
+ /** Is the pic interrupting right now or not. */
+ bool picInterrupting;
+
+ /** A pointer to the Tsunami device which be belong to */
+ Tsunami *tsunami;
+
+ /** Intel 8253 Periodic Interval Timer */
+ PITimer pitimer;
+
+ RTC rtc;
+
+ /** The interval is set via two writes to the PIT.
+ * This variable contains a flag as to how many writes have happened, and
+ * the time so far.
+ */
+ uint16_t timerData;
+
+ public:
+ /**
+ * Return the freqency of the RTC
+ * @return interrupt rate of the RTC
+ */
+ 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 p pointer to Params struct
+ */
+ TsunamiIO(Params *p);
+
+ virtual Tick read(Packet *pkt);
+ virtual Tick write(Packet *pkt);
+
+ /**
+ * Post an PIC interrupt to the CPU via the CChip
+ * @param bitvector interrupt to post.
+ */
+ void postPIC(uint8_t bitvector);
+
+ /**
+ * Clear a posted interrupt
+ * @param bitvector interrupt to clear
+ */
+ void clearPIC(uint8_t bitvector);
+
+ /**
+ * Serialize this object to the given output stream.
+ * @param os The stream to serialize to.
+ */
+ virtual void serialize(std::ostream &os);
+
+ /**
+ * Reconstruct the state of this object from a checkpoint.
+ * @param cp The checkpoint use.
+ * @param section The section name of this object
+ */
+ virtual void unserialize(Checkpoint *cp, const std::string &section);
+
+};
+
+#endif // __DEV_TSUNAMI_IO_HH__
diff --git a/src/dev/tsunami_pchip.cc b/src/dev/tsunami_pchip.cc
new file mode 100644
index 000000000..c430ca0a0
--- /dev/null
+++ b/src/dev/tsunami_pchip.cc
@@ -0,0 +1,358 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file
+ * Tsunami PChip (pci)
+ */
+
+#include <deque>
+#include <string>
+#include <vector>
+
+#include "base/trace.hh"
+#include "dev/tsunami_pchip.hh"
+#include "dev/tsunamireg.h"
+#include "dev/tsunami.hh"
+#include "mem/packet.hh"
+#include "sim/builder.hh"
+#include "sim/system.hh"
+
+using namespace std;
+//Should this be AlphaISA?
+using namespace TheISA;
+
+TsunamiPChip::TsunamiPChip(Params *p)
+: BasicPioDevice(p)
+{
+ pioSize = 0xfff;
+
+ for (int i = 0; i < 4; i++) {
+ wsba[i] = 0;
+ wsm[i] = 0;
+ tba[i] = 0;
+ }
+
+ // initialize pchip control register
+ pctl = (ULL(0x1) << 20) | (ULL(0x1) << 32) | (ULL(0x2) << 36);
+
+ //Set back pointer in tsunami
+ p->tsunami->pchip = this;
+}
+
+Tick
+TsunamiPChip::read(Packet *pkt)
+{
+ assert(pkt->result == Packet::Unknown);
+ assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
+
+
+ pkt->time += pioDelay;
+ pkt->allocate();
+ Addr daddr = (pkt->getAddr() - pioAddr) >> 6;;
+ assert(pkt->getSize() == sizeof(uint64_t));
+
+
+ DPRINTF(Tsunami, "read va=%#x size=%d\n", pkt->getAddr(), pkt->getSize());
+
+ 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("Default in PChip Read reached reading 0x%x\n", daddr);
+ }
+ pkt->result = Packet::Success;
+ return pioDelay;
+
+}
+
+Tick
+TsunamiPChip::write(Packet *pkt)
+{
+ pkt->time += pioDelay;
+
+ assert(pkt->result == Packet::Unknown);
+ assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
+ Addr daddr = (pkt->getAddr() - pioAddr) >> 6;
+
+ assert(pkt->getSize() == sizeof(uint64_t));
+
+ DPRINTF(Tsunami, "write - va=%#x size=%d \n", pkt->getAddr(), pkt->getSize());
+
+ 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 = Packet::Success;
+ return pioDelay;
+}
+
+#define DMA_ADDR_MASK ULL(0x3ffffffff)
+
+Addr
+TsunamiPChip::translatePciToDma(Addr busAddr)
+{
+ // compare the address to the window base registers
+ uint64_t tbaMask = 0;
+ uint64_t baMask = 0;
+
+ uint64_t windowMask = 0;
+ uint64_t windowBase = 0;
+
+ uint64_t pteEntry = 0;
+
+ Addr pteAddr;
+ Addr dmaAddr;
+
+#if 0
+ DPRINTF(IdeDisk, "Translation for bus address: %#x\n", busAddr);
+ for (int i = 0; i < 4; i++) {
+ DPRINTF(IdeDisk, "(%d) base:%#x mask:%#x\n",
+ i, wsba[i], wsm[i]);
+
+ windowBase = wsba[i];
+ windowMask = ~wsm[i] & (ULL(0xfff) << 20);
+
+ if ((busAddr & windowMask) == (windowBase & windowMask)) {
+ DPRINTF(IdeDisk, "Would have matched %d (wb:%#x wm:%#x --> ba&wm:%#x wb&wm:%#x)\n",
+ i, windowBase, windowMask, (busAddr & windowMask),
+ (windowBase & windowMask));
+ }
+ }
+#endif
+
+ for (int i = 0; i < 4; i++) {
+
+ windowBase = wsba[i];
+ windowMask = ~wsm[i] & (ULL(0xfff) << 20);
+
+ if ((busAddr & windowMask) == (windowBase & windowMask)) {
+
+ if (wsba[i] & 0x1) { // see if enabled
+ if (wsba[i] & 0x2) { // see if SG bit is set
+ /** @todo
+ This currently is faked by just doing a direct
+ read from memory, however, to be realistic, this
+ needs to actually do a bus transaction. The process
+ is explained in the tsunami documentation on page
+ 10-12 and basically munges the address to look up a
+ PTE from a table in memory and then uses that mapping
+ to create an address for the SG page
+ */
+
+ tbaMask = ~(((wsm[i] & (ULL(0xfff) << 20)) >> 10) | ULL(0x3ff));
+ baMask = (wsm[i] & (ULL(0xfff) << 20)) | (ULL(0x7f) << 13);
+ pteAddr = (tba[i] & tbaMask) | ((busAddr & baMask) >> 10);
+
+ pioPort->readBlob(pteAddr, (uint8_t*)&pteEntry, sizeof(uint64_t));
+
+ dmaAddr = ((pteEntry & ~ULL(0x1)) << 12) | (busAddr & ULL(0x1fff));
+
+ } else {
+ baMask = (wsm[i] & (ULL(0xfff) << 20)) | ULL(0xfffff);
+ tbaMask = ~baMask;
+ dmaAddr = (tba[i] & tbaMask) | (busAddr & baMask);
+ }
+
+ return (dmaAddr & DMA_ADDR_MASK);
+ }
+ }
+ }
+
+ // if no match was found, then return the original address
+ return busAddr;
+}
+
+void
+TsunamiPChip::serialize(std::ostream &os)
+{
+ SERIALIZE_SCALAR(pctl);
+ SERIALIZE_ARRAY(wsba, 4);
+ SERIALIZE_ARRAY(wsm, 4);
+ SERIALIZE_ARRAY(tba, 4);
+}
+
+void
+TsunamiPChip::unserialize(Checkpoint *cp, const std::string &section)
+{
+ UNSERIALIZE_SCALAR(pctl);
+ UNSERIALIZE_ARRAY(wsba, 4);
+ UNSERIALIZE_ARRAY(wsm, 4);
+ UNSERIALIZE_ARRAY(tba, 4);
+}
+
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiPChip)
+
+ Param<Addr> pio_addr;
+ Param<Tick> pio_latency;
+ SimObjectParam<Platform *> platform;
+ SimObjectParam<System *> system;
+ SimObjectParam<Tsunami *> tsunami;
+
+END_DECLARE_SIM_OBJECT_PARAMS(TsunamiPChip)
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiPChip)
+
+ 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)
+{
+ 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/src/dev/tsunami_pchip.hh b/src/dev/tsunami_pchip.hh
new file mode 100644
index 000000000..bb84339c9
--- /dev/null
+++ b/src/dev/tsunami_pchip.hh
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file
+ * Tsunami PCI interface CSRs
+ */
+
+#ifndef __TSUNAMI_PCHIP_HH__
+#define __TSUNAMI_PCHIP_HH__
+
+#include "dev/tsunami.hh"
+#include "base/range.hh"
+#include "dev/io_device.hh"
+
+/**
+ * A very simple implementation of the Tsunami PCI interface chips.
+ */
+class TsunamiPChip : public BasicPioDevice
+{
+ protected:
+ /** Pchip control register */
+ uint64_t pctl;
+
+ /** Window Base addresses */
+ uint64_t wsba[4];
+
+ /** Window masks */
+ uint64_t wsm[4];
+
+ /** Translated Base Addresses */
+ 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 p pointer to the parameters struct
+ */
+ TsunamiPChip(Params *p);
+
+ /**
+ * Translate a PCI bus address to a memory address for DMA.
+ * @todo Andrew says this needs to be fixed. What's wrong with it?
+ * @param busAddr PCI address to translate.
+ * @return memory system address
+ */
+ Addr translatePciToDma(Addr busAddr);
+
+ virtual Tick read(Packet *pkt);
+ virtual Tick write(Packet *pkt);
+
+ /**
+ * Serialize this object to the given output stream.
+ * @param os The stream to serialize to.
+ */
+ virtual void serialize(std::ostream &os);
+
+ /**
+ * Reconstruct the state of this object from a checkpoint.
+ * @param cp The checkpoint use.
+ * @param section The section name of this object
+ */
+ virtual void unserialize(Checkpoint *cp, const std::string &section);
+};
+
+#endif // __TSUNAMI_PCHIP_HH__
diff --git a/dev/tsunamireg.h b/src/dev/tsunamireg.h
index a10259900..a10259900 100644
--- a/dev/tsunamireg.h
+++ b/src/dev/tsunamireg.h
diff --git a/src/dev/uart.cc b/src/dev/uart.cc
new file mode 100644
index 000000000..4a9f2b505
--- /dev/null
+++ b/src/dev/uart.cc
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file
+ * Implements a base class for UARTs
+ */
+
+#include "dev/simconsole.hh"
+#include "dev/uart.hh"
+#include "dev/platform.hh"
+#include "sim/builder.hh"
+
+using namespace std;
+
+Uart::Uart(Params *p)
+ : BasicPioDevice(p), platform(p->platform), cons(p->cons)
+{
+
+ status = 0;
+
+ // set back pointers
+ cons->uart = this;
+ platform->uart = this;
+}
+
+DEFINE_SIM_OBJECT_CLASS_NAME("Uart", Uart)
+
diff --git a/src/dev/uart.hh b/src/dev/uart.hh
new file mode 100644
index 000000000..2dd15d9b8
--- /dev/null
+++ b/src/dev/uart.hh
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file
+ * Base class for UART
+ */
+
+#ifndef __UART_HH__
+#define __UART_HH__
+
+#include "base/range.hh"
+#include "dev/io_device.hh"
+
+class SimConsole;
+class Platform;
+
+const int RX_INT = 0x1;
+const int TX_INT = 0x2;
+
+
+class Uart : public BasicPioDevice
+{
+
+ protected:
+ int status;
+ Platform *platform;
+ SimConsole *cons;
+
+ public:
+ struct Params : public BasicPioDevice::Params
+ {
+ SimConsole *cons;
+ };
+
+ Uart(Params *p);
+
+ /**
+ * Inform the uart that there is data available.
+ */
+ virtual void dataAvailable() = 0;
+
+
+ /**
+ * Return if we have an interrupt pending
+ * @return interrupt status
+ */
+ bool intStatus() { return status ? true : false; }
+
+ protected:
+ const Params *params() const {return (const Params *)_params; }
+
+};
+
+#endif // __UART_HH__
diff --git a/src/dev/uart8250.cc b/src/dev/uart8250.cc
new file mode 100644
index 000000000..8a5a1f1cd
--- /dev/null
+++ b/src/dev/uart8250.cc
@@ -0,0 +1,366 @@
+/*
+ * Copyright (c) 2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file
+ * Implements a 8250 UART
+ */
+
+#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 "sim/builder.hh"
+
+using namespace std;
+using namespace TheISA;
+
+Uart8250::IntrEvent::IntrEvent(Uart8250 *u, int bit)
+ : Event(&mainEventQueue), uart(u)
+{
+ DPRINTF(Uart, "UART Interrupt Event Initilizing\n");
+ intrBit = bit;
+}
+
+const char *
+Uart8250::IntrEvent::description()
+{
+ return "uart interrupt delay event";
+}
+
+void
+Uart8250::IntrEvent::process()
+{
+ if (intrBit & uart->IER) {
+ DPRINTF(Uart, "UART InterEvent, interrupting\n");
+ uart->platform->postConsoleInt();
+ uart->status |= intrBit;
+ }
+ else
+ DPRINTF(Uart, "UART InterEvent, not interrupting\n");
+
+}
+
+/* The linux serial driver (8250.c about line 1182) loops reading from
+ * the device until the device reports it has no more data to
+ * read. After a maximum of 255 iterations the code prints "serial8250
+ * too much work for irq X," and breaks out of the loop. Since the
+ * simulated system is so much slower than the actual system, if a
+ * user is typing on the keyboard it is very easy for them to provide
+ * input at a fast enough rate to not allow the loop to exit and thus
+ * the error to be printed. This magic number provides a delay between
+ * the time the UART receives a character to send to the simulated
+ * system and the time it actually notifies the system it has a
+ * character to send to alleviate this problem. --Ali
+ */
+void
+Uart8250::IntrEvent::scheduleIntr()
+{
+ static const Tick interval = (Tick)((Clock::Float::s / 2e9) * 450);
+ DPRINTF(Uart, "Scheduling IER interrupt for %#x, at cycle %lld\n", intrBit,
+ curTick + interval);
+ if (!scheduled())
+ schedule(curTick + interval);
+ else
+ reschedule(curTick + interval);
+}
+
+
+Uart8250::Uart8250(Params *p)
+ : Uart(p), txIntrEvent(this, TX_INT), rxIntrEvent(this, RX_INT)
+{
+ pioSize = 8;
+
+ IER = 0;
+ DLAB = 0;
+ LCR = 0;
+ MCR = 0;
+}
+
+Tick
+Uart8250::read(Packet *pkt)
+{
+ assert(pkt->result == Packet::Unknown);
+ assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
+ assert(pkt->getSize() == 1);
+
+ pkt->time += pioDelay;
+ Addr daddr = pkt->getAddr() - pioAddr;
+ pkt->allocate();
+
+ DPRINTF(Uart, " read register %#x\n", daddr);
+
+ switch (daddr) {
+ case 0x0:
+ if (!(LCR & 0x80)) { // read byte
+ if (cons->dataAvailable())
+ pkt->set(cons->in());
+ else {
+ pkt->set((uint8_t)0);
+ // A limited amount of these are ok.
+ DPRINTF(Uart, "empty read of RX register\n");
+ }
+ status &= ~RX_INT;
+ platform->clearConsoleInt();
+
+ if (cons->dataAvailable() && (IER & UART_IER_RDI))
+ rxIntrEvent.scheduleIntr();
+ } else { // dll divisor latch
+ ;
+ }
+ break;
+ case 0x1:
+ if (!(LCR & 0x80)) { // Intr Enable Register(IER)
+ pkt->set(IER);
+ } else { // DLM divisor latch MSB
+ ;
+ }
+ break;
+ case 0x2: // Intr Identification Register (IIR)
+ DPRINTF(Uart, "IIR Read, status = %#x\n", (uint32_t)status);
+
+ if (status & RX_INT) /* Rx data interrupt has a higher priority */
+ pkt->set(IIR_RXID);
+ else if (status & TX_INT)
+ pkt->set(IIR_TXID);
+ else
+ pkt->set(IIR_NOPEND);
+
+ //Tx interrupts are cleared on IIR reads
+ status &= ~TX_INT;
+ break;
+ case 0x3: // Line Control Register (LCR)
+ pkt->set(LCR);
+ break;
+ case 0x4: // Modem Control Register (MCR)
+ break;
+ case 0x5: // Line Status Register (LSR)
+ uint8_t lsr;
+ lsr = 0;
+ // check if there are any bytes to be read
+ if (cons->dataAvailable())
+ lsr = UART_LSR_DR;
+ lsr |= UART_LSR_TEMT | UART_LSR_THRE;
+ pkt->set(lsr);
+ break;
+ case 0x6: // Modem Status Register (MSR)
+ pkt->set((uint8_t)0);
+ break;
+ case 0x7: // Scratch Register (SCR)
+ 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;
+ }
+/* uint32_t d32 = *data;
+ DPRINTF(Uart, "Register read to register %#x returned %#x\n", daddr, d32);
+*/
+ pkt->result = Packet::Success;
+ return pioDelay;
+}
+
+Tick
+Uart8250::write(Packet *pkt)
+{
+
+ assert(pkt->result == Packet::Unknown);
+ assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
+ assert(pkt->getSize() == 1);
+
+ pkt->time += pioDelay;
+ Addr daddr = pkt->getAddr() - 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(pkt->get<uint8_t>());
+ platform->clearConsoleInt();
+ status &= ~TX_INT;
+ if (UART_IER_THRI & IER)
+ txIntrEvent.scheduleIntr();
+ } else { // dll divisor latch
+ ;
+ }
+ break;
+ case 0x1:
+ if (!(LCR & 0x80)) { // Intr Enable Register(IER)
+ IER = pkt->get<uint8_t>();
+ if (UART_IER_THRI & IER)
+ {
+ DPRINTF(Uart, "IER: IER_THRI set, scheduling TX intrrupt\n");
+ txIntrEvent.scheduleIntr();
+ }
+ else
+ {
+ DPRINTF(Uart, "IER: IER_THRI cleared, descheduling TX intrrupt\n");
+ if (txIntrEvent.scheduled())
+ txIntrEvent.deschedule();
+ if (status & TX_INT)
+ platform->clearConsoleInt();
+ status &= ~TX_INT;
+ }
+
+ if ((UART_IER_RDI & IER) && cons->dataAvailable()) {
+ DPRINTF(Uart, "IER: IER_RDI set, scheduling RX intrrupt\n");
+ rxIntrEvent.scheduleIntr();
+ } else {
+ DPRINTF(Uart, "IER: IER_RDI cleared, descheduling RX intrrupt\n");
+ if (rxIntrEvent.scheduled())
+ rxIntrEvent.deschedule();
+ if (status & RX_INT)
+ platform->clearConsoleInt();
+ status &= ~RX_INT;
+ }
+ } else { // DLM divisor latch MSB
+ ;
+ }
+ break;
+ case 0x2: // FIFO Control Register (FCR)
+ break;
+ case 0x3: // Line Control Register (LCR)
+ LCR = pkt->get<uint8_t>();
+ break;
+ case 0x4: // Modem Control Register (MCR)
+ if (pkt->get<uint8_t>() == (UART_MCR_LOOP | 0x0A))
+ MCR = 0x9A;
+ break;
+ case 0x7: // Scratch Register (SCR)
+ // We are emulating a 8250 so we don't have a scratch reg
+ break;
+ default:
+ panic("Tried to access a UART port that doesn't exist\n");
+ break;
+ }
+ pkt->result = Packet::Success;
+ return pioDelay;
+}
+
+void
+Uart8250::dataAvailable()
+{
+ // if the kernel wants an interrupt when we have data
+ if (IER & UART_IER_RDI)
+ {
+ platform->postConsoleInt();
+ status |= RX_INT;
+ }
+
+}
+
+void
+Uart8250::addressRanges(AddrRangeList &range_list)
+{
+ assert(pioSize != 0);
+ range_list.clear();
+ range_list.push_back(RangeSize(pioAddr, pioSize));
+}
+
+
+
+void
+Uart8250::serialize(ostream &os)
+{
+ SERIALIZE_SCALAR(status);
+ SERIALIZE_SCALAR(IER);
+ SERIALIZE_SCALAR(DLAB);
+ SERIALIZE_SCALAR(LCR);
+ SERIALIZE_SCALAR(MCR);
+ Tick rxintrwhen;
+ if (rxIntrEvent.scheduled())
+ rxintrwhen = rxIntrEvent.when();
+ else
+ rxintrwhen = 0;
+ Tick txintrwhen;
+ if (txIntrEvent.scheduled())
+ txintrwhen = txIntrEvent.when();
+ else
+ txintrwhen = 0;
+ SERIALIZE_SCALAR(rxintrwhen);
+ SERIALIZE_SCALAR(txintrwhen);
+}
+
+void
+Uart8250::unserialize(Checkpoint *cp, const std::string &section)
+{
+ UNSERIALIZE_SCALAR(status);
+ UNSERIALIZE_SCALAR(IER);
+ UNSERIALIZE_SCALAR(DLAB);
+ UNSERIALIZE_SCALAR(LCR);
+ UNSERIALIZE_SCALAR(MCR);
+ Tick rxintrwhen;
+ Tick txintrwhen;
+ UNSERIALIZE_SCALAR(rxintrwhen);
+ UNSERIALIZE_SCALAR(txintrwhen);
+ if (rxintrwhen != 0)
+ rxIntrEvent.schedule(rxintrwhen);
+ if (txintrwhen != 0)
+ txIntrEvent.schedule(txintrwhen);
+}
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(Uart8250)
+
+ Param<Addr> pio_addr;
+ Param<Tick> pio_latency;
+ SimObjectParam<Platform *> platform;
+ SimObjectParam<SimConsole *> sim_console;
+ SimObjectParam<System *> system;
+
+END_DECLARE_SIM_OBJECT_PARAMS(Uart8250)
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(Uart8250)
+
+ 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)
+{
+ 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/src/dev/uart8250.hh b/src/dev/uart8250.hh
new file mode 100644
index 000000000..4b7c2f1e4
--- /dev/null
+++ b/src/dev/uart8250.hh
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file
+ * Defines a 8250 UART
+ */
+
+#ifndef __DEV_UART8250_HH__
+#define __DEV_UART8250_HH__
+
+#include "dev/tsunamireg.h"
+#include "base/range.hh"
+#include "dev/io_device.hh"
+#include "dev/uart.hh"
+
+
+/* UART8250 Interrupt ID Register
+ * bit 0 Interrupt Pending 0 = true, 1 = false
+ * bit 2:1 ID of highest priority interrupt
+ * bit 7:3 zeroes
+ */
+const uint8_t IIR_NOPEND = 0x1;
+
+// Interrupt IDs
+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 Platform;
+
+class Uart8250 : public Uart
+{
+
+
+ protected:
+ uint8_t IER, DLAB, LCR, MCR;
+
+ class IntrEvent : public Event
+ {
+ protected:
+ Uart8250 *uart;
+ int intrBit;
+ public:
+ IntrEvent(Uart8250 *u, int bit);
+ virtual void process();
+ virtual const char *description();
+ void scheduleIntr();
+ };
+
+ IntrEvent txIntrEvent;
+ IntrEvent rxIntrEvent;
+
+ public:
+ Uart8250(Params *p);
+
+ virtual Tick read(Packet *pkt);
+ virtual Tick write(Packet *pkt);
+ virtual void addressRanges(AddrRangeList &range_list);
+
+
+ /**
+ * Inform the uart that there is data available.
+ */
+ virtual void dataAvailable();
+
+
+ /**
+ * Return if we have an interrupt pending
+ * @return interrupt status
+ */
+ virtual bool intStatus() { return status ? true : false; }
+
+ virtual void serialize(std::ostream &os);
+ virtual void unserialize(Checkpoint *cp, const std::string &section);
+
+};
+
+#endif // __TSUNAMI_UART_HH__
diff --git a/kern/kernel_stats.cc b/src/kern/kernel_stats.cc
index b85d88145..b85d88145 100644
--- a/kern/kernel_stats.cc
+++ b/src/kern/kernel_stats.cc
diff --git a/kern/kernel_stats.hh b/src/kern/kernel_stats.hh
index 16ec721d0..16ec721d0 100644
--- a/kern/kernel_stats.hh
+++ b/src/kern/kernel_stats.hh
diff --git a/src/kern/linux/events.cc b/src/kern/linux/events.cc
new file mode 100644
index 000000000..b688e9dd0
--- /dev/null
+++ b/src/kern/linux/events.cc
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2004-2006 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "arch/arguments.hh"
+#include "base/trace.hh"
+#include "cpu/exec_context.hh"
+#include "kern/linux/events.hh"
+#include "kern/linux/printk.hh"
+#include "kern/system_events.hh"
+#include "sim/system.hh"
+
+
+namespace Linux {
+
+void
+DebugPrintkEvent::process(ExecContext *xc)
+{
+ if (DTRACE(DebugPrintf)) {
+ if (!raw) {
+ StringWrap name(xc->getSystemPtr()->name() + ".dprintk");
+ DPRINTFN("");
+ }
+
+ AlphaISA::AlphaArguments args(xc);
+ Printk(args);
+ SkipFuncEvent::process(xc);
+ }
+}
+
+} // namespace linux
diff --git a/kern/linux/events.hh b/src/kern/linux/events.hh
index 95c268976..95c268976 100644
--- a/kern/linux/events.hh
+++ b/src/kern/linux/events.hh
diff --git a/src/kern/linux/linux.hh b/src/kern/linux/linux.hh
new file mode 100644
index 000000000..63e0dd5ca
--- /dev/null
+++ b/src/kern/linux/linux.hh
@@ -0,0 +1,283 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __LINUX_HH__
+#define __LINUX_HH__
+#include "config/full_system.hh"
+
+#if FULL_SYSTEM
+
+class Linux {};
+
+#else //!FULL_SYSTEM
+
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h> // for host open() flags
+#include <string.h> // for memset()
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "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
+/// syscall interface.
+///
+class Linux {
+
+ public:
+
+ //@{
+ /// Basic Linux types.
+ typedef uint64_t size_t;
+ typedef uint64_t off_t;
+ typedef int64_t time_t;
+ typedef uint32_t uid_t;
+ typedef uint32_t gid_t;
+ //@}
+
+#if BSD_HOST
+ typedef struct stat hst_stat;
+ typedef struct stat hst_stat64;
+#else
+ typedef struct stat hst_stat ;
+ typedef struct stat64 hst_stat64;
+#endif
+
+ /// Stat buffer. Note that we can't call it 'stat' since that
+ /// gets #defined to something else on some systems.
+ struct tgt_stat {
+ uint32_t st_dev; //!< device
+ uint32_t st_ino; //!< inode
+ uint32_t st_mode; //!< mode
+ uint32_t st_nlink; //!< link count
+ uint32_t st_uid; //!< owner's user ID
+ uint32_t st_gid; //!< owner's group ID
+ uint32_t st_rdev; //!< device number
+ int32_t _pad1; //!< for alignment
+ int64_t st_size; //!< file size in bytes
+ uint64_t st_atimeX; //!< time of last access
+ uint64_t st_mtimeX; //!< time of last modification
+ uint64_t st_ctimeX; //!< time of last status change
+ uint32_t st_blksize; //!< optimal I/O block size
+ int32_t st_blocks; //!< number of blocks allocated
+ uint32_t st_flags; //!< flags
+ uint32_t st_gen; //!< unknown
+ };
+
+ // same for stat64
+ struct tgt_stat64 {
+ uint64_t st_dev;
+ uint64_t st_ino;
+ uint64_t st_rdev;
+ int64_t st_size;
+ uint64_t st_blocks;
+
+ uint32_t st_mode;
+ uint32_t st_uid;
+ uint32_t st_gid;
+ uint32_t st_blksize;
+ uint32_t st_nlink;
+ uint32_t __pad0;
+
+ uint64_t tgt_st_atime;
+ uint64_t st_atime_nsec;
+ uint64_t tgt_st_mtime;
+ uint64_t st_mtime_nsec;
+ uint64_t tgt_st_ctime;
+ uint64_t st_ctime_nsec;
+ int64_t ___unused[3];
+ };
+
+ /// Length of strings in struct utsname (plus 1 for null char).
+ static const int _SYS_NMLN = 65;
+
+ /// Interface struct for uname().
+ struct utsname {
+ char sysname[_SYS_NMLN]; //!< System name.
+ char nodename[_SYS_NMLN]; //!< Node name.
+ char release[_SYS_NMLN]; //!< OS release.
+ char version[_SYS_NMLN]; //!< OS version.
+ char machine[_SYS_NMLN]; //!< Machine type.
+ };
+
+ /// Limit struct for getrlimit/setrlimit.
+ struct rlimit {
+ uint64_t rlim_cur; //!< soft limit
+ uint64_t rlim_max; //!< hard limit
+ };
+
+ /// For gettimeofday().
+ struct timeval {
+ int64_t tv_sec; //!< seconds
+ int64_t tv_usec; //!< microseconds
+ };
+
+ // For writev/readv
+ struct tgt_iovec {
+ uint64_t iov_base; // void *
+ uint64_t iov_len;
+ };
+
+
+ /// For getrusage().
+ struct rusage {
+ struct timeval ru_utime; //!< user time used
+ struct timeval ru_stime; //!< system time used
+ int64_t ru_maxrss; //!< max rss
+ int64_t ru_ixrss; //!< integral shared memory size
+ int64_t ru_idrss; //!< integral unshared data "
+ int64_t ru_isrss; //!< integral unshared stack "
+ int64_t ru_minflt; //!< page reclaims - total vmfaults
+ int64_t ru_majflt; //!< page faults
+ int64_t ru_nswap; //!< swaps
+ int64_t ru_inblock; //!< block input operations
+ int64_t ru_oublock; //!< block output operations
+ int64_t ru_msgsnd; //!< messages sent
+ int64_t ru_msgrcv; //!< messages received
+ int64_t ru_nsignals; //!< signals received
+ int64_t ru_nvcsw; //!< voluntary context switches
+ int64_t ru_nivcsw; //!< involuntary "
+ };
+
+ /// Helper function to convert a host stat buffer to a target stat
+ /// buffer. Also copies the target buffer out to the simulated
+ /// memory space. Used by stat(), fstat(), and lstat().
+#if !BSD_HOST
+ static void
+ copyOutStatBuf(TranslatingPort *mem, Addr addr, hst_stat *host)
+ {
+ using namespace TheISA;
+
+ TypedBufferArg<Linux::tgt_stat> tgt(addr);
+
+ tgt->st_dev = htog(host->st_dev);
+ tgt->st_ino = htog(host->st_ino);
+ tgt->st_mode = htog(host->st_mode);
+ tgt->st_nlink = htog(host->st_nlink);
+ tgt->st_uid = htog(host->st_uid);
+ tgt->st_gid = htog(host->st_gid);
+ tgt->st_rdev = htog(host->st_rdev);
+ tgt->st_size = htog(host->st_size);
+ tgt->st_atimeX = htog(host->st_atime);
+ tgt->st_mtimeX = htog(host->st_mtime);
+ tgt->st_ctimeX = htog(host->st_ctime);
+ tgt->st_blksize = htog(host->st_blksize);
+ tgt->st_blocks = htog(host->st_blocks);
+
+ tgt.copyOut(mem);
+ }
+#else
+ // Third version for bsd systems which no longer have any support for
+ // the old stat() call and stat() is actually a stat64()
+ static void
+ copyOutStatBuf(TranslatingPort *mem, Addr addr, hst_stat64 *host)
+ {
+ using namespace TheISA;
+
+ TypedBufferArg<Linux::tgt_stat> tgt(addr);
+
+ tgt->st_dev = htog(host->st_dev);
+ tgt->st_ino = htog(host->st_ino);
+ tgt->st_mode = htog(host->st_mode);
+ tgt->st_nlink = htog(host->st_nlink);
+ tgt->st_uid = htog(host->st_uid);
+ tgt->st_gid = htog(host->st_gid);
+ tgt->st_rdev = htog(host->st_rdev);
+ tgt->st_size = htog(host->st_size);
+ tgt->st_atimeX = htog(host->st_atime);
+ tgt->st_mtimeX = htog(host->st_mtime);
+ tgt->st_ctimeX = htog(host->st_ctime);
+ tgt->st_blksize = htog(host->st_blksize);
+ tgt->st_blocks = htog(host->st_blocks);
+
+ tgt.copyOut(mem);
+ }
+#endif
+
+
+ // Same for stat64
+ static void
+ copyOutStat64Buf(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
+ // that the stdout is interactive vs. a file
+ // this makes it work on non-linux systems
+ if (fd == 1)
+ tgt->st_dev = htog((uint64_t)0xA);
+ else
+ tgt->st_dev = htog((uint64_t)host->st_dev);
+ // XXX What about STAT64_HAS_BROKEN_ST_INO ???
+ tgt->st_ino = htog((uint64_t)host->st_ino);
+ if (fd == 1)
+ tgt->st_rdev = htog((uint64_t)0x880d);
+ else
+ tgt->st_rdev = htog((uint64_t)host->st_rdev);
+ tgt->st_size = htog((int64_t)host->st_size);
+ tgt->st_blocks = htog((uint64_t)host->st_blocks);
+
+ if (fd == 1)
+ tgt->st_mode = htog((uint32_t)0x2190);
+ else
+ tgt->st_mode = htog((uint32_t)host->st_mode);
+ tgt->st_uid = htog((uint32_t)host->st_uid);
+ tgt->st_gid = htog((uint32_t)host->st_gid);
+ tgt->st_blksize = htog((uint32_t)host->st_blksize);
+ tgt->st_nlink = htog((uint32_t)host->st_nlink);
+ tgt->tgt_st_atime = htog((uint64_t)host->st_atime);
+ tgt->tgt_st_mtime = htog((uint64_t)host->st_mtime);
+ tgt->tgt_st_ctime = htog((uint64_t)host->st_ctime);
+#if defined(STAT_HAVE_NSEC)
+ tgt->st_atime_nsec = htog(host->st_atime_nsec);
+ tgt->st_mtime_nsec = htog(host->st_mtime_nsec);
+ tgt->st_ctime_nsec = htog(host->st_ctime_nsec);
+#else
+ tgt->st_atime_nsec = 0;
+ tgt->st_mtime_nsec = 0;
+ tgt->st_ctime_nsec = 0;
+#endif
+
+ tgt.copyOut(mem);
+ }
+
+}; // class Linux
+
+
+#endif // FULL_SYSTEM
+
+#endif // __LINUX_HH__
diff --git a/kern/linux/linux_syscalls.cc b/src/kern/linux/linux_syscalls.cc
index c85b6d28f..c85b6d28f 100644
--- a/kern/linux/linux_syscalls.cc
+++ b/src/kern/linux/linux_syscalls.cc
diff --git a/kern/linux/linux_syscalls.hh b/src/kern/linux/linux_syscalls.hh
index 7f2a08ea9..7f2a08ea9 100644
--- a/kern/linux/linux_syscalls.hh
+++ b/src/kern/linux/linux_syscalls.hh
diff --git a/src/kern/linux/printk.cc b/src/kern/linux/printk.cc
new file mode 100644
index 000000000..918b8dabe
--- /dev/null
+++ b/src/kern/linux/printk.cc
@@ -0,0 +1,261 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include <algorithm>
+
+#include "base/trace.hh"
+#include "arch/arguments.hh"
+
+using namespace std;
+
+
+void
+Printk(AlphaISA::AlphaArguments args)
+{
+ char *p = (char *)args++;
+
+ ios::fmtflags saved_flags = DebugOut().flags();
+ char old_fill = DebugOut().fill();
+ int old_precision = DebugOut().precision();
+
+ while (*p) {
+ switch (*p) {
+ case '%': {
+ bool more = true;
+ bool islong = false;
+ bool leftjustify = false;
+ bool format = false;
+ bool zero = false;
+ int width = 0;
+ while (more && *++p) {
+ switch (*p) {
+ case 'l':
+ case 'L':
+ islong = true;
+ break;
+ case '-':
+ leftjustify = true;
+ break;
+ case '#':
+ format = true;
+ break;
+ case '0':
+ if (width)
+ width *= 10;
+ else
+ zero = true;
+ break;
+ default:
+ if (*p >= '1' && *p <= '9')
+ width = 10 * width + *p - '0';
+ else
+ more = false;
+ break;
+ }
+ }
+
+ bool hexnum = false;
+ bool octal = false;
+ bool sign = false;
+ switch (*p) {
+ case 'X':
+ case 'x':
+ hexnum = true;
+ break;
+ case 'O':
+ case 'o':
+ octal = true;
+ break;
+ case 'D':
+ case 'd':
+ sign = true;
+ break;
+ case 'P':
+ format = true;
+ case 'p':
+ hexnum = true;
+ break;
+ }
+
+ switch (*p) {
+ case 'D':
+ case 'd':
+ case 'U':
+ case 'u':
+ case 'X':
+ case 'x':
+ case 'O':
+ case 'o':
+ case 'P':
+ case 'p': {
+ if (hexnum)
+ DebugOut() << hex;
+
+ if (octal)
+ DebugOut() << oct;
+
+ if (format) {
+ if (!zero)
+ DebugOut().setf(ios::showbase);
+ else {
+ if (hexnum) {
+ DebugOut() << "0x";
+ width -= 2;
+ } else if (octal) {
+ DebugOut() << "0";
+ width -= 1;
+ }
+ }
+ }
+
+ if (zero)
+ DebugOut().fill('0');
+
+ if (width > 0)
+ DebugOut().width(width);
+
+ if (leftjustify && !zero)
+ DebugOut().setf(ios::left);
+
+ if (sign) {
+ if (islong)
+ DebugOut() << (int64_t)args;
+ else
+ DebugOut() << (int32_t)args;
+ } else {
+ if (islong)
+ DebugOut() << (uint64_t)args;
+ else
+ DebugOut() << (uint32_t)args;
+ }
+
+ if (zero)
+ DebugOut().fill(' ');
+
+ if (width > 0)
+ DebugOut().width(0);
+
+ DebugOut() << dec;
+
+ ++args;
+ }
+ break;
+
+ case 's': {
+ char *s = (char *)args;
+ if (!s)
+ s = "<NULL>";
+
+ if (width > 0)
+ DebugOut().width(width);
+ if (leftjustify)
+ DebugOut().setf(ios::left);
+
+ DebugOut() << s;
+ ++args;
+ }
+ break;
+ case 'C':
+ case 'c': {
+ uint64_t mask = (*p == 'C') ? 0xffL : 0x7fL;
+ uint64_t num;
+ int width;
+
+ if (islong) {
+ num = (uint64_t)args;
+ width = sizeof(uint64_t);
+ } else {
+ num = (uint32_t)args;
+ width = sizeof(uint32_t);
+ }
+
+ while (width-- > 0) {
+ char c = (char)(num & mask);
+ if (c)
+ DebugOut() << c;
+ num >>= 8;
+ }
+
+ ++args;
+ }
+ break;
+ case 'b': {
+ uint64_t n = (uint64_t)args++;
+ char *s = (char *)args++;
+ DebugOut() << s << ": " << n;
+ }
+ break;
+ case 'n':
+ case 'N': {
+ args += 2;
+#if 0
+ uint64_t n = (uint64_t)args++;
+ struct reg_values *rv = (struct reg_values *)args++;
+#endif
+ }
+ break;
+ case 'r':
+ case 'R': {
+ args += 2;
+#if 0
+ uint64_t n = (uint64_t)args++;
+ struct reg_desc *rd = (struct reg_desc *)args++;
+#endif
+ }
+ break;
+ case '%':
+ DebugOut() << '%';
+ break;
+ }
+ ++p;
+ }
+ break;
+ case '\n':
+ DebugOut() << endl;
+ ++p;
+ break;
+ case '\r':
+ ++p;
+ if (*p != '\n')
+ DebugOut() << endl;
+ break;
+
+ default: {
+ size_t len = strcspn(p, "%\n\r\0");
+ DebugOut().write(p, len);
+ p += len;
+ }
+ }
+ }
+
+ DebugOut().flags(saved_flags);
+ DebugOut().fill(old_fill);
+ DebugOut().precision(old_precision);
+}
+
diff --git a/src/kern/linux/printk.hh b/src/kern/linux/printk.hh
new file mode 100644
index 000000000..b88c40f5e
--- /dev/null
+++ b/src/kern/linux/printk.hh
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __PRINTK_HH__
+#define __PRINTK_HH__
+
+class AlphaISA::AlphaArguments;
+
+void Printk(AlphaISA::AlphaArguments args);
+
+#endif // __PRINTK_HH__
diff --git a/kern/linux/sched.hh b/src/kern/linux/sched.hh
index a11fa590d..a11fa590d 100644
--- a/kern/linux/sched.hh
+++ b/src/kern/linux/sched.hh
diff --git a/src/kern/solaris/solaris.hh b/src/kern/solaris/solaris.hh
new file mode 100644
index 000000000..e2b61d613
--- /dev/null
+++ b/src/kern/solaris/solaris.hh
@@ -0,0 +1,304 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __SOLARIS_HH__
+#define __SOLARIS_HH__
+#include "config/full_system.hh"
+
+#if FULL_SYSTEM
+
+class Solaris {};
+
+#else //!FULL_SYSTEM
+
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h> // for host open() flags
+#include <string.h> // for memset()
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "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 Solaris
+/// syscall interface.
+///
+class Solaris {
+
+ public:
+
+ //@{
+ /// Basic Solaris types.
+ typedef uint64_t size_t;
+ typedef uint64_t off_t;
+ typedef int64_t time_t;
+ typedef int32_t uid_t;
+ typedef int32_t gid_t;
+ typedef uint64_t rlim_t;
+ typedef uint64_t ino_t;
+ typedef uint64_t dev_t;
+ typedef uint32_t mode_t;
+ typedef uint32_t nlink_t;
+ //@}
+
+#if BSD_HOST
+ typedef struct stat hst_stat;
+ typedef struct stat hst_stat64;
+#else
+ typedef struct stat hst_stat ;
+ typedef struct stat64 hst_stat64;
+#endif
+ struct tgt_timespec {
+ int64_t tv_sec;
+ int64_t tv_nsec;
+ };
+
+ /// Stat buffer. Note that we can't call it 'stat' since that
+ /// gets #defined to something else on some systems.
+ struct tgt_stat {
+ uint64_t st_dev; //!< device
+ uint64_t st_ino; //!< inode
+ uint32_t st_mode; //!< mode
+ uint32_t st_nlink; //!< link count
+ int32_t st_uid; //!< owner's user ID
+ int32_t st_gid; //!< owner's group ID
+ uint64_t st_rdev; //!< device number
+ int64_t st_size; //!< file size in bytes
+ struct tgt_timespec st_atimeX; //!< time of last access
+ struct tgt_timespec st_mtimeX; //!< time of last modification
+ struct tgt_timespec st_ctimeX; //!< time of last status change
+ int32_t st_blksize; //!< optimal I/O block size
+ int64_t st_blocks; //!< number of blocks allocated
+ char st_fstype[16];
+ };
+
+ // same for stat64
+ struct tgt_stat64 {
+ uint64_t st_dev; //!< device
+ uint64_t st_ino; //!< inode
+ uint32_t st_mode; //!< mode
+ uint32_t st_nlink; //!< link count
+ int32_t st_uid; //!< owner's user ID
+ int32_t st_gid; //!< owner's group ID
+ uint64_t st_rdev; //!< device number
+ int64_t st_size; //!< file size in bytes
+ struct tgt_timespec st_atimeX; //!< time of last access
+ struct tgt_timespec st_mtimeX; //!< time of last modification
+ struct tgt_timespec st_ctimeX; //!< time of last status change
+ int32_t st_blksize; //!< optimal I/O block size
+ int64_t st_blocks; //!< number of blocks allocated
+ char st_fstype[16];
+ };
+
+ /// Length of strings in struct utsname (plus 1 for null char).
+ static const int _SYS_NMLN = 257;
+
+ /// Interface struct for uname().
+ struct utsname {
+ char sysname[_SYS_NMLN]; //!< System name.
+ char nodename[_SYS_NMLN]; //!< Node name.
+ char release[_SYS_NMLN]; //!< OS release.
+ char version[_SYS_NMLN]; //!< OS version.
+ char machine[_SYS_NMLN]; //!< Machine type.
+ };
+
+ /// Limit struct for getrlimit/setrlimit.
+ struct rlimit {
+ uint64_t rlim_cur; //!< soft limit
+ uint64_t rlim_max; //!< hard limit
+ };
+
+ /// For gettimeofday().
+ struct timeval {
+ int64_t tv_sec; //!< seconds
+ int64_t tv_usec; //!< microseconds
+ };
+
+ // For writev/readv
+ struct tgt_iovec {
+ uint64_t iov_base; // void *
+ uint64_t iov_len;
+ };
+
+
+ /// For getrusage().
+ struct rusage {
+ struct timeval ru_utime; //!< user time used
+ struct timeval ru_stime; //!< system time used
+ int64_t ru_maxrss; //!< max rss
+ int64_t ru_ixrss; //!< integral shared memory size
+ int64_t ru_idrss; //!< integral unshared data "
+ int64_t ru_isrss; //!< integral unshared stack "
+ int64_t ru_minflt; //!< page reclaims - total vmfaults
+ int64_t ru_majflt; //!< page faults
+ int64_t ru_nswap; //!< swaps
+ int64_t ru_inblock; //!< block input operations
+ int64_t ru_oublock; //!< block output operations
+ int64_t ru_msgsnd; //!< messages sent
+ int64_t ru_msgrcv; //!< messages received
+ int64_t ru_nsignals; //!< signals received
+ int64_t ru_nvcsw; //!< voluntary context switches
+ int64_t ru_nivcsw; //!< involuntary "
+ };
+
+ /// Helper function to convert a host stat buffer to a target stat
+ /// buffer. Also copies the target buffer out to the simulated
+ /// memory space. Used by stat(), fstat(), and lstat().
+#if !BSD_HOST
+ static void
+ copyOutStatBuf(TranslatingPort *mem, Addr addr, hst_stat *host)
+ {
+ using namespace TheISA;
+
+ TypedBufferArg<Solaris::tgt_stat> tgt(addr);
+
+ tgt->st_dev = htog(host->st_dev);
+ tgt->st_ino = htog(host->st_ino);
+ tgt->st_mode = htog(host->st_mode);
+ tgt->st_nlink = htog(host->st_nlink);
+ tgt->st_uid = htog(host->st_uid);
+ tgt->st_gid = htog(host->st_gid);
+ tgt->st_rdev = htog(host->st_rdev);
+ tgt->st_size = htog(host->st_size);
+ tgt->st_atimeX.tv_sec = htog((uint64_t)host->st_atime);
+ tgt->st_mtimeX.tv_sec = htog((uint64_t)host->st_mtime);
+ tgt->st_ctimeX.tv_sec = htog((uint64_t)host->st_ctime);
+#if defined(STAT_HAVE_NSEC)
+ tgt->st_atimeX.tv_nsec = htog(host->st_atime_nsec);
+ tgt->st_mtimeX.tv_nsec = htog(host->st_mtime_nsec);
+ tgt->st_ctimeX.tv_nsec = htog(host->st_ctime_nsec);
+#else
+ tgt->st_atimeX.tv_nsec = 0;
+ tgt->st_mtimeX.tv_nsec = 0;
+ tgt->st_ctimeX.tv_nsec = 0;
+#endif
+ tgt->st_blksize = htog(host->st_blksize);
+ tgt->st_blocks = htog(host->st_blocks);
+ strncpy(tgt->st_fstype, "????", 16);
+
+ tgt.copyOut(mem);
+ }
+#else
+ // Third version for bsd systems which no longer have any support for
+ // the old stat() call and stat() is actually a stat64()
+ static void
+ copyOutStatBuf(TranslatingPort *mem, Addr addr, hst_stat64 *host)
+ {
+ using namespace TheISA;
+
+ TypedBufferArg<Solaris::tgt_stat> tgt(addr);
+
+ tgt->st_dev = htog(host->st_dev);
+ tgt->st_ino = htog(host->st_ino);
+ tgt->st_mode = htog(host->st_mode);
+ tgt->st_nlink = htog(host->st_nlink);
+ tgt->st_uid = htog(host->st_uid);
+ tgt->st_gid = htog(host->st_gid);
+ tgt->st_rdev = htog(host->st_rdev);
+ tgt->st_size = htog(host->st_size);
+ tgt->st_atimeX.tv_sec = htog((uint64_t)host->st_atime);
+ tgt->st_mtimeX.tv_sec = htog((uint64_t)host->st_mtime);
+ tgt->st_ctimeX.tv_sec = htog((uint64_t)host->st_ctime);
+#if defined(STAT_HAVE_NSEC)
+ tgt->st_atimeX.tv_nsec = htog(host->st_atime_nsec);
+ tgt->st_mtimeX.tv_nsec = htog(host->st_mtime_nsec);
+ tgt->st_ctimeX.tv_nsec = htog(host->st_ctime_nsec);
+#else
+ tgt->st_atimeX.tv_nsec = 0;
+ tgt->st_mtimeX.tv_nsec = 0;
+ tgt->st_ctimeX.tv_nsec = 0;
+#endif
+ tgt->st_blksize = htog(host->st_blksize);
+ tgt->st_blocks = htog(host->st_blocks);
+ strncpy(tgt->st_fstype, "????", 16);
+
+ tgt.copyOut(mem);
+ }
+#endif
+
+
+ // Same for stat64
+ static void
+ copyOutStat64Buf(TranslatingPort *mem, int fd, Addr addr, hst_stat64 *host)
+ {
+ using namespace TheISA;
+
+ TypedBufferArg<Solaris::tgt_stat64> tgt(addr);
+
+ // fd == 1 checks are because libc does some checks
+ // that the stdout is interactive vs. a file
+ // this makes it work on non-solaris systems
+ if (fd == 1)
+ tgt->st_dev = htog((uint64_t)0xA);
+ else
+ tgt->st_dev = htog((uint64_t)host->st_dev);
+ // XXX What about STAT64_HAS_BROKEN_ST_INO ???
+ tgt->st_ino = htog((uint64_t)host->st_ino);
+ if (fd == 1)
+ tgt->st_rdev = htog((uint64_t)0x880d);
+ else
+ tgt->st_rdev = htog((uint64_t)host->st_rdev);
+ tgt->st_size = htog((int64_t)host->st_size);
+ tgt->st_blocks = htog((uint64_t)host->st_blocks);
+
+ if (fd == 1)
+ tgt->st_mode = htog((uint32_t)0x2190);
+ else
+ tgt->st_mode = htog((uint32_t)host->st_mode);
+ tgt->st_uid = htog((uint32_t)host->st_uid);
+ tgt->st_gid = htog((uint32_t)host->st_gid);
+ tgt->st_blksize = htog((uint32_t)host->st_blksize);
+ tgt->st_nlink = htog((uint32_t)host->st_nlink);
+ tgt->st_atimeX.tv_sec = htog((uint64_t)host->st_atime);
+ tgt->st_mtimeX.tv_sec = htog((uint64_t)host->st_mtime);
+ tgt->st_ctimeX.tv_sec = htog((uint64_t)host->st_ctime);
+#if defined(STAT_HAVE_NSEC)
+ tgt->st_atimeX.tv_nsec = htog(host->st_atime_nsec);
+ tgt->st_mtimeX.tv_nsec = htog(host->st_mtime_nsec);
+ tgt->st_ctimeX.tv_nsec = htog(host->st_ctime_nsec);
+#else
+ tgt->st_atimeX.tv_nsec = 0;
+ tgt->st_mtimeX.tv_nsec = 0;
+ tgt->st_ctimeX.tv_nsec = 0;
+#endif
+
+ tgt.copyOut(mem);
+ }
+
+}; // class Solaris
+
+
+#endif // FULL_SYSTEM
+
+#endif // __SOLARIS_HH__
diff --git a/src/kern/system_events.cc b/src/kern/system_events.cc
new file mode 100644
index 000000000..f3b1bf91d
--- /dev/null
+++ b/src/kern/system_events.cc
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#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;
+
+void
+SkipFuncEvent::process(ExecContext *xc)
+{
+ Addr newpc = xc->readIntReg(ReturnAddressReg);
+
+ DPRINTF(PCEvent, "skipping %s: pc=%x, newpc=%x\n", description,
+ xc->readPC(), newpc);
+
+ xc->setPC(newpc);
+ xc->setNextPC(xc->readPC() + sizeof(TheISA::MachInst));
+/*
+ BranchPred *bp = xc->getCpuPtr()->getBranchPred();
+ if (bp != NULL) {
+ bp->popRAS(xc->getThreadNum());
+ }
+*/
+}
+
+
+FnEvent::FnEvent(PCEventQueue *q, const std::string &desc, Addr addr,
+ Stats::MainBin *bin)
+ : PCEvent(q, desc, addr), _name(desc), mybin(bin)
+{
+}
+
+void
+FnEvent::process(ExecContext *xc)
+{
+ if (xc->misspeculating())
+ return;
+
+ xc->getSystemPtr()->kernelBinning->call(xc, mybin);
+}
+
+void
+IdleStartEvent::process(ExecContext *xc)
+{
+ if (xc->getKernelStats())
+ xc->getKernelStats()->setIdleProcess(
+ xc->readMiscReg(AlphaISA::IPR_PALtemp23), xc);
+ remove();
+}
+
+void
+InterruptStartEvent::process(ExecContext *xc)
+{
+ if (xc->getKernelStats())
+ xc->getKernelStats()->mode(Kernel::interrupt, xc);
+}
+
+void
+InterruptEndEvent::process(ExecContext *xc)
+{
+ // We go back to kernel, if we are user, inside the rti
+ // pal code we will get switched to user because of the ICM write
+ if (xc->getKernelStats())
+ xc->getKernelStats()->mode(Kernel::kernel, xc);
+}
diff --git a/kern/system_events.hh b/src/kern/system_events.hh
index 246140a09..246140a09 100644
--- a/kern/system_events.hh
+++ b/src/kern/system_events.hh
diff --git a/kern/tru64/dump_mbuf.cc b/src/kern/tru64/dump_mbuf.cc
index c3c37531a..c3c37531a 100644
--- a/kern/tru64/dump_mbuf.cc
+++ b/src/kern/tru64/dump_mbuf.cc
diff --git a/src/kern/tru64/dump_mbuf.hh b/src/kern/tru64/dump_mbuf.hh
new file mode 100644
index 000000000..9e1698ff1
--- /dev/null
+++ b/src/kern/tru64/dump_mbuf.hh
@@ -0,0 +1,38 @@
+/*
+ * 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 __DUMP_MBUF_HH__
+#define __DUMP_MBUF_HH__
+
+#include "arch/arguments.hh"
+
+namespace tru64 {
+ void DumpMbuf(AlphaISA::AlphaArguments args);
+}
+
+#endif // __DUMP_MBUF_HH__
diff --git a/kern/tru64/mbuf.hh b/src/kern/tru64/mbuf.hh
index 93424858f..93424858f 100644
--- a/kern/tru64/mbuf.hh
+++ b/src/kern/tru64/mbuf.hh
diff --git a/src/kern/tru64/printf.cc b/src/kern/tru64/printf.cc
new file mode 100644
index 000000000..319d36673
--- /dev/null
+++ b/src/kern/tru64/printf.cc
@@ -0,0 +1,266 @@
+/*
+ * 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 <sys/types.h>
+#include <algorithm>
+
+#include "base/cprintf.hh"
+#include "base/trace.hh"
+#include "sim/host.hh"
+#include "arch/arguments.hh"
+#include "arch/vtophys.hh"
+
+using namespace std;
+
+namespace tru64 {
+
+void
+Printf(AlphaISA::AlphaArguments args)
+{
+ char *p = (char *)args++;
+
+ ios::fmtflags saved_flags = DebugOut().flags();
+ char old_fill = DebugOut().fill();
+ int old_precision = DebugOut().precision();
+
+ while (*p) {
+ switch (*p) {
+ case '%': {
+ bool more = true;
+ bool islong = false;
+ bool leftjustify = false;
+ bool format = false;
+ bool zero = false;
+ int width = 0;
+ while (more && *++p) {
+ switch (*p) {
+ case 'l':
+ case 'L':
+ islong = true;
+ break;
+ case '-':
+ leftjustify = true;
+ break;
+ case '#':
+ format = true;
+ break;
+ case '0':
+ if (width)
+ width *= 10;
+ else
+ zero = true;
+ break;
+ default:
+ if (*p >= '1' && *p <= '9')
+ width = 10 * width + *p - '0';
+ else
+ more = false;
+ break;
+ }
+ }
+
+ bool hexnum = false;
+ bool octal = false;
+ bool sign = false;
+ switch (*p) {
+ case 'X':
+ case 'x':
+ hexnum = true;
+ break;
+ case 'O':
+ case 'o':
+ octal = true;
+ break;
+ case 'D':
+ case 'd':
+ sign = true;
+ break;
+ case 'P':
+ format = true;
+ case 'p':
+ hexnum = true;
+ break;
+ }
+
+ switch (*p) {
+ case 'D':
+ case 'd':
+ case 'U':
+ case 'u':
+ case 'X':
+ case 'x':
+ case 'O':
+ case 'o':
+ case 'P':
+ case 'p': {
+ if (hexnum)
+ DebugOut() << hex;
+
+ if (octal)
+ DebugOut() << oct;
+
+ if (format) {
+ if (!zero)
+ DebugOut().setf(ios::showbase);
+ else {
+ if (hexnum) {
+ DebugOut() << "0x";
+ width -= 2;
+ } else if (octal) {
+ DebugOut() << "0";
+ width -= 1;
+ }
+ }
+ }
+
+ if (zero)
+ DebugOut().fill('0');
+
+ if (width > 0)
+ DebugOut().width(width);
+
+ if (leftjustify && !zero)
+ DebugOut().setf(ios::left);
+
+ if (sign) {
+ if (islong)
+ DebugOut() << (int64_t)args;
+ else
+ DebugOut() << (int32_t)args;
+ } else {
+ if (islong)
+ DebugOut() << (uint64_t)args;
+ else
+ DebugOut() << (uint32_t)args;
+ }
+
+ if (zero)
+ DebugOut().fill(' ');
+
+ if (width > 0)
+ DebugOut().width(0);
+
+ DebugOut() << dec;
+
+ ++args;
+ }
+ break;
+
+ case 's': {
+ char *s = (char *)args;
+ if (!s)
+ s = "<NULL>";
+
+ if (width > 0)
+ DebugOut().width(width);
+ if (leftjustify)
+ DebugOut().setf(ios::left);
+
+ DebugOut() << s;
+ ++args;
+ }
+ break;
+ case 'C':
+ case 'c': {
+ uint64_t mask = (*p == 'C') ? 0xffL : 0x7fL;
+ uint64_t num;
+ int width;
+
+ if (islong) {
+ num = (uint64_t)args;
+ width = sizeof(uint64_t);
+ } else {
+ num = (uint32_t)args;
+ width = sizeof(uint32_t);
+ }
+
+ while (width-- > 0) {
+ char c = (char)(num & mask);
+ if (c)
+ DebugOut() << c;
+ num >>= 8;
+ }
+
+ ++args;
+ }
+ break;
+ case 'b': {
+ uint64_t n = (uint64_t)args++;
+ char *s = (char *)args++;
+ DebugOut() << s << ": " << n;
+ }
+ break;
+ case 'n':
+ case 'N': {
+ args += 2;
+#if 0
+ uint64_t n = (uint64_t)args++;
+ struct reg_values *rv = (struct reg_values *)args++;
+#endif
+ }
+ break;
+ case 'r':
+ case 'R': {
+ args += 2;
+#if 0
+ uint64_t n = (uint64_t)args++;
+ struct reg_desc *rd = (struct reg_desc *)args++;
+#endif
+ }
+ break;
+ case '%':
+ DebugOut() << '%';
+ break;
+ }
+ ++p;
+ }
+ break;
+ case '\n':
+ DebugOut() << endl;
+ ++p;
+ break;
+ case '\r':
+ ++p;
+ if (*p != '\n')
+ DebugOut() << endl;
+ break;
+
+ default: {
+ size_t len = strcspn(p, "%\n\r\0");
+ DebugOut().write(p, len);
+ p += len;
+ }
+ }
+ }
+
+ DebugOut().flags(saved_flags);
+ DebugOut().fill(old_fill);
+ DebugOut().precision(old_precision);
+}
+
+} // namespace Tru64
diff --git a/src/kern/tru64/printf.hh b/src/kern/tru64/printf.hh
new file mode 100644
index 000000000..61236e83a
--- /dev/null
+++ b/src/kern/tru64/printf.hh
@@ -0,0 +1,38 @@
+/*
+ * 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 __PRINTF_HH__
+#define __PRINTF_HH__
+
+#include "arch/arguments.hh"
+
+namespace tru64 {
+ void Printf(AlphaISA::AlphaArguments args);
+}
+
+#endif // __PRINTF_HH__
diff --git a/src/kern/tru64/tru64.hh b/src/kern/tru64/tru64.hh
new file mode 100644
index 000000000..fff91f8ca
--- /dev/null
+++ b/src/kern/tru64/tru64.hh
@@ -0,0 +1,1240 @@
+/*
+ * 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 __TRU64_HH__
+#define __TRU64_HH__
+#include "config/full_system.hh"
+
+#if FULL_SYSTEM
+
+class Tru64 {};
+
+#else //!FULL_SYSTEM
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#if defined(__OpenBSD__) || defined(__APPLE__) || defined(__FreeBSD__)
+#include <sys/param.h>
+#include <sys/mount.h>
+#else
+#include <sys/statfs.h>
+#endif
+
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h> // for memset()
+#include <unistd.h>
+
+#include "cpu/base.hh"
+#include "sim/root.hh"
+#include "sim/syscall_emul.hh"
+
+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
+/// syscall interface.
+///
+class Tru64 {
+
+ public:
+
+ //@{
+ /// Basic Tru64 types.
+ typedef uint64_t size_t;
+ typedef uint64_t off_t;
+ typedef uint16_t nlink_t;
+ typedef int32_t dev_t;
+ typedef uint32_t uid_t;
+ typedef uint32_t gid_t;
+ typedef uint32_t time_t;
+ typedef uint32_t mode_t;
+ typedef uint32_t ino_t;
+ typedef struct { int val[2]; } quad;
+ typedef quad fsid_t;
+ //@}
+
+ /// Stat buffer. Note that Tru64 v5.0+ use a new "F64" stat
+ /// structure, and a new set of syscall numbers for stat calls.
+ /// On some hosts (notably Linux) define st_atime, st_mtime, and
+ /// st_ctime as macros, so we append an X to get around this.
+ struct F64_stat {
+ dev_t st_dev; //!< st_dev
+ int32_t st_retired1; //!< st_retired1
+ mode_t st_mode; //!< st_mode
+ nlink_t st_nlink; //!< st_nlink
+ uint16_t st_nlink_reserved; //!< st_nlink_reserved
+ uid_t st_uid; //!< st_uid
+ gid_t st_gid; //!< st_gid
+ dev_t st_rdev; //!< st_rdev
+ dev_t st_ldev; //!< st_ldev
+ off_t st_size; //!< st_size
+ time_t st_retired2; //!< st_retired2
+ int32_t st_uatime; //!< st_uatime
+ time_t st_retired3; //!< st_retired3
+ int32_t st_umtime; //!< st_umtime
+ time_t st_retired4; //!< st_retired4
+ int32_t st_uctime; //!< st_uctime
+ int32_t st_retired5; //!< st_retired5
+ int32_t st_retired6; //!< st_retired6
+ uint32_t st_flags; //!< st_flags
+ uint32_t st_gen; //!< st_gen
+ uint64_t st_spare[4]; //!< st_spare[4]
+ ino_t st_ino; //!< st_ino
+ int32_t st_ino_reserved; //!< st_ino_reserved
+ time_t st_atimeX; //!< st_atime
+ int32_t st_atime_reserved; //!< st_atime_reserved
+ time_t st_mtimeX; //!< st_mtime
+ int32_t st_mtime_reserved; //!< st_mtime_reserved
+ time_t st_ctimeX; //!< st_ctime
+ int32_t st_ctime_reserved; //!< st_ctime_reserved
+ uint64_t st_blksize; //!< st_blksize
+ uint64_t st_blocks; //!< st_blocks
+ };
+
+
+ /// Old Tru64 v4.x stat struct.
+ /// Tru64 maintains backwards compatibility with v4.x by
+ /// implementing another set of stat functions using the old
+ /// structure definition and binding them to the old syscall
+ /// numbers.
+
+ struct pre_F64_stat {
+ dev_t st_dev;
+ ino_t st_ino;
+ mode_t st_mode;
+ nlink_t st_nlink;
+ uid_t st_uid __attribute__ ((aligned(sizeof(uid_t))));
+ gid_t st_gid;
+ dev_t st_rdev;
+ off_t st_size __attribute__ ((aligned(sizeof(off_t))));
+ time_t st_atimeX;
+ int32_t st_uatime;
+ time_t st_mtimeX;
+ int32_t st_umtime;
+ time_t st_ctimeX;
+ int32_t st_uctime;
+ uint32_t st_blksize;
+ int32_t st_blocks;
+ uint32_t st_flags;
+ uint32_t st_gen;
+ };
+
+ /// For statfs().
+ struct F64_statfs {
+ int16_t f_type;
+ int16_t f_flags;
+ int32_t f_retired1;
+ int32_t f_retired2;
+ int32_t f_retired3;
+ int32_t f_retired4;
+ int32_t f_retired5;
+ int32_t f_retired6;
+ int32_t f_retired7;
+ fsid_t f_fsid;
+ int32_t f_spare[9];
+ char f_retired8[90];
+ char f_retired9[90];
+ uint64_t dummy[10]; // was union mount_info mount_info;
+ uint64_t f_flags2;
+ int64_t f_spare2[14];
+ int64_t f_fsize;
+ int64_t f_bsize;
+ int64_t f_blocks;
+ int64_t f_bfree;
+ int64_t f_bavail;
+ int64_t f_files;
+ int64_t f_ffree;
+ char f_mntonname[1024];
+ char f_mntfromname[1024];
+ };
+
+ /// For old Tru64 v4.x statfs()
+ struct pre_F64_statfs {
+ int16_t f_type;
+ int16_t f_flags;
+ int32_t f_fsize;
+ int32_t f_bsize;
+ int32_t f_blocks;
+ int32_t f_bfree;
+ int32_t f_bavail;
+ int32_t f_files;
+ int32_t f_ffree;
+ fsid_t f_fsid;
+ int32_t f_spare[9];
+ char f_mntonname[90];
+ char f_mntfromname[90];
+ uint64_t dummy[10]; // was union mount_info mount_info;
+ };
+
+ /// For getdirentries().
+ struct dirent
+ {
+ ino_t d_ino; //!< file number of entry
+ uint16_t d_reclen; //!< length of this record
+ uint16_t d_namlen; //!< length of string in d_name
+ char d_name[256]; //!< dummy name length
+ };
+
+
+ /// Length of strings in struct utsname (plus 1 for null char).
+ static const int _SYS_NMLN = 32;
+
+ /// Interface struct for uname().
+ struct utsname {
+ char sysname[_SYS_NMLN]; //!< System name.
+ char nodename[_SYS_NMLN]; //!< Node name.
+ char release[_SYS_NMLN]; //!< OS release.
+ char version[_SYS_NMLN]; //!< OS version.
+ char machine[_SYS_NMLN]; //!< Machine type.
+ };
+
+ /// Limit struct for getrlimit/setrlimit.
+ struct rlimit {
+ uint64_t rlim_cur; //!< soft limit
+ uint64_t rlim_max; //!< hard limit
+ };
+
+
+ /// For getsysinfo() GSI_CPU_INFO option.
+ struct cpu_info {
+ uint32_t current_cpu; //!< current_cpu
+ uint32_t cpus_in_box; //!< cpus_in_box
+ uint32_t cpu_type; //!< cpu_type
+ uint32_t ncpus; //!< ncpus
+ uint64_t cpus_present; //!< cpus_present
+ uint64_t cpus_running; //!< cpus_running
+ uint64_t cpu_binding; //!< cpu_binding
+ uint64_t cpu_ex_binding; //!< cpu_ex_binding
+ uint32_t mhz; //!< mhz
+ uint32_t unused[3]; //!< future expansion
+ };
+
+ /// For gettimeofday.
+ struct timeval {
+ uint32_t tv_sec; //!< seconds
+ uint32_t tv_usec; //!< microseconds
+ };
+
+ /// For getrusage().
+ struct rusage {
+ struct timeval ru_utime; //!< user time used
+ struct timeval ru_stime; //!< system time used
+ uint64_t ru_maxrss; //!< ru_maxrss
+ uint64_t ru_ixrss; //!< integral shared memory size
+ uint64_t ru_idrss; //!< integral unshared data "
+ uint64_t ru_isrss; //!< integral unshared stack "
+ uint64_t ru_minflt; //!< page reclaims - total vmfaults
+ uint64_t ru_majflt; //!< page faults
+ uint64_t ru_nswap; //!< swaps
+ uint64_t ru_inblock; //!< block input operations
+ uint64_t ru_oublock; //!< block output operations
+ uint64_t ru_msgsnd; //!< messages sent
+ uint64_t ru_msgrcv; //!< messages received
+ uint64_t ru_nsignals; //!< signals received
+ uint64_t ru_nvcsw; //!< voluntary context switches
+ uint64_t ru_nivcsw; //!< involuntary "
+ };
+
+ /// For sigreturn().
+ struct sigcontext {
+ int64_t sc_onstack; //!< sigstack state to restore
+ int64_t sc_mask; //!< signal mask to restore
+ int64_t sc_pc; //!< pc at time of signal
+ int64_t sc_ps; //!< psl to retore
+ int64_t sc_regs[32]; //!< processor regs 0 to 31
+ int64_t sc_ownedfp; //!< fp has been used
+ int64_t sc_fpregs[32]; //!< fp regs 0 to 31
+ uint64_t sc_fpcr; //!< floating point control reg
+ uint64_t sc_fp_control; //!< software fpcr
+ int64_t sc_reserved1; //!< reserved for kernel
+ uint32_t sc_kreserved1; //!< reserved for kernel
+ uint32_t sc_kreserved2; //!< reserved for kernel
+ size_t sc_ssize; //!< stack size
+ caddr_t sc_sbase; //!< stack start
+ uint64_t sc_traparg_a0; //!< a0 argument to trap on exc
+ uint64_t sc_traparg_a1; //!< a1 argument to trap on exc
+ uint64_t sc_traparg_a2; //!< a2 argument to trap on exc
+ uint64_t sc_fp_trap_pc; //!< imprecise pc
+ uint64_t sc_fp_trigger_sum; //!< Exception summary at trigg
+ uint64_t sc_fp_trigger_inst; //!< Instruction at trigger pc
+ };
+
+
+
+ /// For table().
+ struct tbl_sysinfo {
+ uint64_t si_user; //!< User time
+ uint64_t si_nice; //!< Nice time
+ uint64_t si_sys; //!< System time
+ uint64_t si_idle; //!< Idle time
+ uint64_t si_hz; //!< hz
+ uint64_t si_phz; //!< phz
+ uint64_t si_boottime; //!< Boot time in seconds
+ uint64_t wait; //!< Wait time
+ uint32_t si_max_procs; //!< rpb->rpb_numprocs
+ uint32_t pad; //!< padding
+ };
+
+
+ /// For stack_create.
+ struct vm_stack {
+ // was void *
+ Addr address; //!< address hint
+ size_t rsize; //!< red zone size
+ size_t ysize; //!< yellow zone size
+ size_t gsize; //!< green zone size
+ size_t swap; //!< amount of swap to reserve
+ size_t incr; //!< growth increment
+ uint64_t align; //!< address alignment
+ uint64_t flags; //!< MAP_FIXED etc.
+ // was struct memalloc_attr *
+ Addr attr; //!< allocation policy
+ uint64_t reserved; //!< reserved
+ };
+
+ /// Return values for nxm calls.
+ enum {
+ KERN_NOT_RECEIVER = 7,
+ KERN_NOT_IN_SET = 12
+ };
+
+ /// For nxm_task_init.
+ static const int NXM_TASK_INIT_VP = 2; //!< initial thread is VP
+
+ /// Task attribute structure.
+ struct nxm_task_attr {
+ int64_t nxm_callback; //!< nxm_callback
+ unsigned int nxm_version; //!< nxm_version
+ unsigned short nxm_uniq_offset; //!< nxm_uniq_offset
+ unsigned short flags; //!< flags
+ int nxm_quantum; //!< nxm_quantum
+ int pad1; //!< pad1
+ int64_t pad2; //!< pad2
+ };
+
+ /// Signal set.
+ typedef uint64_t sigset_t;
+
+ /// Thread state shared between user & kernel.
+ struct ushared_state {
+ sigset_t sigmask; //!< thread signal mask
+ sigset_t sig; //!< thread pending mask
+ // struct nxm_pth_state *
+ Addr pth_id; //!< out-of-line state
+ int flags; //!< shared flags
+#define US_SIGSTACK 0x1 // thread called sigaltstack
+#define US_ONSTACK 0x2 // thread is running on altstack
+#define US_PROFILE 0x4 // thread called profil
+#define US_SYSCALL 0x8 // thread in syscall
+#define US_TRAP 0x10 // thread has trapped
+#define US_YELLOW 0x20 // thread has mellowed yellow
+#define US_YZONE 0x40 // thread has zoned out
+#define US_FP_OWNED 0x80 // thread used floating point
+
+ int cancel_state; //!< thread's cancelation state
+#define US_CANCEL 0x1 // cancel pending
+#define US_NOCANCEL 0X2 // synch cancel disabled
+#define US_SYS_NOCANCEL 0x4 // syscall cancel disabled
+#define US_ASYNC_NOCANCEL 0x8 // asynch cancel disabled
+#define US_CANCEL_BITS (US_NOCANCEL|US_SYS_NOCANCEL|US_ASYNC_NOCANCEL)
+#define US_CANCEL_MASK (US_CANCEL|US_NOCANCEL|US_SYS_NOCANCEL| \
+ US_ASYNC_NOCANCEL)
+
+ // These are semi-shared. They are always visible to
+ // the kernel but are never context-switched by the library.
+
+ int nxm_ssig; //!< scheduler's synchronous signals
+ int reserved1; //!< reserved1
+ int64_t nxm_active; //!< scheduler active
+ int64_t reserved2; //!< reserved2
+ };
+
+ struct nxm_sched_state {
+ struct ushared_state nxm_u; //!< state own by user thread
+ unsigned int nxm_bits; //!< scheduler state / slot
+ int nxm_quantum; //!< quantum count-down value
+ int nxm_set_quantum; //!< quantum reset value
+ int nxm_sysevent; //!< syscall state
+ // struct nxm_upcall *
+ Addr nxm_uc_ret; //!< stack ptr of null thread
+ // void *
+ Addr nxm_tid; //!< scheduler's thread id
+ int64_t nxm_va; //!< page fault address
+ // struct nxm_pth_state *
+ Addr nxm_pthid; //!< id of null thread
+ uint64_t nxm_bound_pcs_count; //!< bound PCS thread count
+ int64_t pad[2]; //!< pad
+ };
+
+ /// nxm_shared.
+ struct nxm_shared {
+ int64_t nxm_callback; //!< address of upcall routine
+ unsigned int nxm_version; //!< version number
+ unsigned short nxm_uniq_offset; //!< correction factor for TEB
+ unsigned short pad1; //!< pad1
+ int64_t space[2]; //!< future growth
+ struct nxm_sched_state nxm_ss[1]; //!< array of shared areas
+ };
+
+ /// nxm_slot_state_t.
+ enum nxm_slot_state_t {
+ NXM_SLOT_AVAIL,
+ NXM_SLOT_BOUND,
+ NXM_SLOT_UNBOUND,
+ NXM_SLOT_EMPTY
+ };
+
+ /// nxm_config_info
+ struct nxm_config_info {
+ int nxm_nslots_per_rad; //!< max number of VP slots per RAD
+ int nxm_nrads; //!< max number of RADs
+ // nxm_slot_state_t *
+ Addr nxm_slot_state; //!< per-VP slot state
+ // struct nxm_shared *
+ Addr nxm_rad[1]; //!< per-RAD shared areas
+ };
+
+ /// For nxm_thread_create.
+ enum nxm_thread_type {
+ NXM_TYPE_SCS = 0,
+ NXM_TYPE_VP = 1,
+ NXM_TYPE_MANAGER = 2
+ };
+
+ /// Thread attributes.
+ struct nxm_thread_attr {
+ int version; //!< version
+ int type; //!< type
+ int cancel_flags; //!< cancel_flags
+ int priority; //!< priority
+ int policy; //!< policy
+ int signal_type; //!< signal_type
+ // void *
+ Addr pthid; //!< pthid
+ sigset_t sigmask; //!< sigmask
+ /// Initial register values.
+ struct {
+ uint64_t pc; //!< pc
+ uint64_t sp; //!< sp
+ uint64_t a0; //!< a0
+ } registers;
+ uint64_t pad2[2]; //!< pad2
+ };
+
+ /// Helper function to convert a host stat buffer to a target stat
+ /// buffer. Also copies the target buffer out to the simulated
+ /// memory space. Used by stat(), fstat(), and lstat().
+ template <class T>
+ static void
+ copyOutStatBuf(TranslatingPort *mem, Addr addr, global_stat *host)
+ {
+ using namespace TheISA;
+
+ TypedBufferArg<T> tgt(addr);
+
+ tgt->st_dev = htog(host->st_dev);
+ tgt->st_ino = htog(host->st_ino);
+ tgt->st_mode = htog(host->st_mode);
+ tgt->st_nlink = htog(host->st_nlink);
+ tgt->st_uid = htog(host->st_uid);
+ tgt->st_gid = htog(host->st_gid);
+ tgt->st_rdev = htog(host->st_rdev);
+ tgt->st_size = htog(host->st_size);
+ tgt->st_atimeX = htog(host->st_atime);
+ tgt->st_mtimeX = htog(host->st_mtime);
+ tgt->st_ctimeX = htog(host->st_ctime);
+ tgt->st_blksize = htog(host->st_blksize);
+ tgt->st_blocks = htog(host->st_blocks);
+
+ tgt.copyOut(mem);
+ }
+
+ /// Helper function to convert a host statfs buffer to a target statfs
+ /// buffer. Also copies the target buffer out to the simulated
+ /// memory space. Used by statfs() and fstatfs().
+ template <class T>
+ static void
+ copyOutStatfsBuf(TranslatingPort *mem, Addr addr, global_statfs *host)
+ {
+ using namespace TheISA;
+
+ TypedBufferArg<T> tgt(addr);
+
+#if defined(__OpenBSD__) || defined(__APPLE__) || defined(__FreeBSD__)
+ tgt->f_type = 0;
+#else
+ tgt->f_type = htog(host->f_type);
+#endif
+ tgt->f_bsize = htog(host->f_bsize);
+ tgt->f_blocks = htog(host->f_blocks);
+ tgt->f_bfree = htog(host->f_bfree);
+ tgt->f_bavail = htog(host->f_bavail);
+ tgt->f_files = htog(host->f_files);
+ tgt->f_ffree = htog(host->f_ffree);
+
+ // Is this as string normally?
+ memcpy(&tgt->f_fsid, &host->f_fsid, sizeof(host->f_fsid));
+
+ tgt.copyOut(mem);
+ }
+
+ class F64 {
+ public:
+ static void copyOutStatBuf(TranslatingPort *mem, Addr addr,
+ global_stat *host)
+ {
+ Tru64::copyOutStatBuf<Tru64::F64_stat>(mem, addr, host);
+ }
+
+ static void copyOutStatfsBuf(TranslatingPort *mem, Addr addr,
+ global_statfs *host)
+ {
+ Tru64::copyOutStatfsBuf<Tru64::F64_statfs>(mem, addr, host);
+ }
+ };
+
+ class PreF64 {
+ public:
+ static void copyOutStatBuf(TranslatingPort *mem, Addr addr,
+ global_stat *host)
+ {
+ Tru64::copyOutStatBuf<Tru64::pre_F64_stat>(mem, addr, host);
+ }
+
+ static void copyOutStatfsBuf(TranslatingPort *mem, Addr addr,
+ global_statfs *host)
+ {
+ Tru64::copyOutStatfsBuf<Tru64::pre_F64_statfs>(mem, addr, host);
+ }
+ };
+
+ /// Helper function to convert a host stat buffer to an old pre-F64
+ /// (4.x) target stat buffer. Also copies the target buffer out to
+ /// the simulated memory space. Used by pre_F64_stat(),
+ /// pre_F64_fstat(), and pre_F64_lstat().
+ static void
+ copyOutPreF64StatBuf(TranslatingPort *mem, Addr addr, struct stat *host)
+ {
+ using namespace TheISA;
+
+ TypedBufferArg<Tru64::pre_F64_stat> tgt(addr);
+
+ tgt->st_dev = htog(host->st_dev);
+ tgt->st_ino = htog(host->st_ino);
+ tgt->st_mode = htog(host->st_mode);
+ tgt->st_nlink = htog(host->st_nlink);
+ tgt->st_uid = htog(host->st_uid);
+ tgt->st_gid = htog(host->st_gid);
+ tgt->st_rdev = htog(host->st_rdev);
+ tgt->st_size = htog(host->st_size);
+ tgt->st_atimeX = htog(host->st_atime);
+ tgt->st_mtimeX = htog(host->st_mtime);
+ tgt->st_ctimeX = htog(host->st_ctime);
+ tgt->st_blksize = htog(host->st_blksize);
+ tgt->st_blocks = htog(host->st_blocks);
+
+ tgt.copyOut(mem);
+ }
+
+
+ /// The target system's hostname.
+ static const char *hostname;
+
+
+ /// Target getdirentries() handler.
+ static SyscallReturn
+ getdirentriesFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+ {
+ using namespace TheISA;
+
+#ifdef __CYGWIN__
+ panic("getdirent not implemented on cygwin!");
+#else
+ int fd = process->sim_fd(xc->getSyscallArg(0));
+ Addr tgt_buf = xc->getSyscallArg(1);
+ int tgt_nbytes = xc->getSyscallArg(2);
+ Addr tgt_basep = xc->getSyscallArg(3);
+
+ char * const host_buf = new char[tgt_nbytes];
+
+ // just pass basep through uninterpreted.
+ TypedBufferArg<int64_t> basep(tgt_basep);
+ basep.copyIn(xc->getMemPort());
+ long host_basep = (off_t)htog((int64_t)*basep);
+ int host_result = getdirentries(fd, host_buf, tgt_nbytes, &host_basep);
+
+ // check for error
+ if (host_result < 0) {
+ delete [] host_buf;
+ return -errno;
+ }
+
+ // no error: copy results back to target space
+ Addr tgt_buf_ptr = tgt_buf;
+ char *host_buf_ptr = host_buf;
+ char *host_buf_end = host_buf + host_result;
+ while (host_buf_ptr < host_buf_end) {
+ global_dirent *host_dp = (global_dirent *)host_buf_ptr;
+ int namelen = strlen(host_dp->d_name);
+
+ // Actual size includes padded string rounded up for alignment.
+ // Subtract 256 for dummy char array in Tru64::dirent definition.
+ // Add 1 to namelen for terminating null char.
+ int tgt_bufsize = sizeof(Tru64::dirent) - 256 + roundUp(namelen+1, 8);
+ TypedBufferArg<Tru64::dirent> tgt_dp(tgt_buf_ptr, tgt_bufsize);
+ tgt_dp->d_ino = host_dp->d_ino;
+ tgt_dp->d_reclen = tgt_bufsize;
+ tgt_dp->d_namlen = namelen;
+ strcpy(tgt_dp->d_name, host_dp->d_name);
+ tgt_dp.copyOut(xc->getMemPort());
+
+ tgt_buf_ptr += tgt_bufsize;
+ host_buf_ptr += host_dp->d_reclen;
+ }
+
+ delete [] host_buf;
+
+ *basep = htog((int64_t)host_basep);
+ basep.copyOut(xc->getMemPort());
+
+ return tgt_buf_ptr - tgt_buf;
+#endif
+ }
+
+ /// Target sigreturn() handler.
+ static SyscallReturn
+ 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->getMemPort());
+
+ // Restore state from sigcontext structure.
+ // Note that we'll advance PC <- NPC before the end of the cycle,
+ // so we need to restore the desired PC into NPC.
+ // The current regs->pc will get clobbered.
+ xc->setNextPC(htog(sc->sc_pc));
+
+ for (int i = 0; i < 31; ++i) {
+ xc->setIntReg(i, htog(sc->sc_regs[i]));
+ xc->setFloatRegBits(i, htog(sc->sc_fpregs[i]));
+ }
+
+ xc->setMiscReg(TheISA::Fpcr_DepTag, htog(sc->sc_fpcr));
+
+ return 0;
+ }
+
+
+ //
+ // Mach syscalls -- identified by negated syscall numbers
+ //
+
+ /// Create a stack region for a thread.
+ static SyscallReturn
+ stack_createFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+ {
+ using namespace TheISA;
+
+ TypedBufferArg<Tru64::vm_stack> argp(xc->getSyscallArg(0));
+
+ argp.copyIn(xc->getMemPort());
+
+ // if the user chose an address, just let them have it. Otherwise
+ // pick one for them.
+ if (htog(argp->address) == 0) {
+ argp->address = htog(process->next_thread_stack_base);
+ int stack_size = (htog(argp->rsize) + htog(argp->ysize) +
+ htog(argp->gsize));
+ process->next_thread_stack_base -= stack_size;
+ argp.copyOut(xc->getMemPort());
+ }
+
+ return 0;
+ }
+
+ /// NXM library version stamp.
+ static
+ const int NXM_LIB_VERSION = 301003;
+
+ /// This call sets up the interface between the user and kernel
+ /// schedulers by creating a shared-memory region. The shared memory
+ /// region has several structs, some global, some per-RAD, some per-VP.
+ static SyscallReturn
+ nxm_task_initFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+ {
+ 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->getMemPort());
+
+ if (gtoh(attrp->nxm_version) != NXM_LIB_VERSION) {
+ cerr << "nxm_task_init: thread library version mismatch! "
+ << "got " << attrp->nxm_version
+ << ", expected " << NXM_LIB_VERSION << endl;
+ abort();
+ }
+
+ if (gtoh(attrp->flags) != Tru64::NXM_TASK_INIT_VP) {
+ cerr << "nxm_task_init: bad flag value " << attrp->flags
+ << " (expected " << Tru64::NXM_TASK_INIT_VP << ")" << endl;
+ abort();
+ }
+
+ const Addr base_addr = 0x12000; // was 0x3f0000000LL;
+ Addr cur_addr = base_addr; // next addresses to use
+ // first comes the config_info struct
+ Addr config_addr = cur_addr;
+ cur_addr += sizeof(Tru64::nxm_config_info);
+ // next comes the per-cpu state vector
+ Addr slot_state_addr = cur_addr;
+ int slot_state_size =
+ process->numCpus() * sizeof(Tru64::nxm_slot_state_t);
+ cur_addr += slot_state_size;
+ // now the per-RAD state struct (we only support one RAD)
+ cur_addr = 0x14000; // bump up addr for alignment
+ Addr rad_state_addr = cur_addr;
+ int rad_state_size =
+ (sizeof(Tru64::nxm_shared)
+ + (process->numCpus()-1) * sizeof(Tru64::nxm_sched_state));
+ cur_addr += rad_state_size;
+
+ // now initialize a config_info struct and copy it out to user space
+ TypedBufferArg<Tru64::nxm_config_info> config(config_addr);
+
+ config->nxm_nslots_per_rad = htog(process->numCpus());
+ config->nxm_nrads = htog(1); // only one RAD in our system!
+ config->nxm_slot_state = htog(slot_state_addr);
+ config->nxm_rad[0] = htog(rad_state_addr);
+
+ config.copyOut(xc->getMemPort());
+
+ // initialize the slot_state array and copy it out
+ TypedBufferArg<Tru64::nxm_slot_state_t> slot_state(slot_state_addr,
+ slot_state_size);
+ for (int i = 0; i < process->numCpus(); ++i) {
+ // CPU 0 is bound to the calling process; all others are available
+ // XXX this code should have an endian conversion, but I don't think
+ // it works anyway
+ slot_state[i] =
+ (i == 0) ? Tru64::NXM_SLOT_BOUND : Tru64::NXM_SLOT_AVAIL;
+ }
+
+ slot_state.copyOut(xc->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
+ // the end.
+ TypedBufferArg<Tru64::nxm_shared> rad_state(rad_state_addr,
+ rad_state_size);
+
+ rad_state->nxm_callback = attrp->nxm_callback;
+ rad_state->nxm_version = attrp->nxm_version;
+ rad_state->nxm_uniq_offset = attrp->nxm_uniq_offset;
+ for (int i = 0; i < process->numCpus(); ++i) {
+ Tru64::nxm_sched_state *ssp = &rad_state->nxm_ss[i];
+ ssp->nxm_u.sigmask = htog(0);
+ ssp->nxm_u.sig = htog(0);
+ ssp->nxm_u.flags = htog(0);
+ ssp->nxm_u.cancel_state = htog(0);
+ ssp->nxm_u.nxm_ssig = 0;
+ ssp->nxm_bits = htog(0);
+ ssp->nxm_quantum = attrp->nxm_quantum;
+ ssp->nxm_set_quantum = attrp->nxm_quantum;
+ ssp->nxm_sysevent = htog(0);
+
+ if (i == 0) {
+ uint64_t uniq = xc->readMiscReg(TheISA::Uniq_DepTag);
+ ssp->nxm_u.pth_id = htog(uniq + gtoh(attrp->nxm_uniq_offset));
+ ssp->nxm_u.nxm_active = htog(uniq | 1);
+ }
+ else {
+ ssp->nxm_u.pth_id = htog(0);
+ ssp->nxm_u.nxm_active = htog(0);
+ }
+ }
+
+ rad_state.copyOut(xc->getMemPort());
+
+ //
+ // copy pointer to shared config area out to user
+ //
+ *configptr_ptr = htog(config_addr);
+ configptr_ptr.copyOut(xc->getMemPort());
+
+ // Register this as a valid address range with the process
+ process->nxm_start = base_addr;
+ process->nxm_end = cur_addr;
+
+ return 0;
+ }
+
+ /// Initialize execution context.
+ static void
+ init_exec_context(ExecContext *ec,
+ Tru64::nxm_thread_attr *attrp, uint64_t uniq_val)
+ {
+ using namespace TheISA;
+
+ ec->clearArchRegs();
+
+ ec->setIntReg(TheISA::ArgumentReg0, gtoh(attrp->registers.a0));
+ ec->setIntReg(27/*t12*/, gtoh(attrp->registers.pc));
+ ec->setIntReg(TheISA::StackPointerReg, gtoh(attrp->registers.sp));
+ ec->setMiscReg(TheISA::Uniq_DepTag, uniq_val);
+
+ ec->setPC(gtoh(attrp->registers.pc));
+ ec->setNextPC(gtoh(attrp->registers.pc) + sizeof(TheISA::MachInst));
+
+ ec->activate();
+ }
+
+ /// Create thread.
+ static SyscallReturn
+ nxm_thread_createFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+ {
+ 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->getMemPort());
+
+ if (gtoh(attrp->version) != NXM_LIB_VERSION) {
+ cerr << "nxm_thread_create: thread library version mismatch! "
+ << "got " << attrp->version
+ << ", expected " << NXM_LIB_VERSION << endl;
+ abort();
+ }
+
+ if (thread_index < 0 | thread_index > process->numCpus()) {
+ cerr << "nxm_thread_create: bad thread index " << thread_index
+ << endl;
+ abort();
+ }
+
+ // On a real machine, the per-RAD shared structure is in
+ // shared memory, so both the user and kernel can get at it.
+ // We don't have that luxury, so we just copy it in and then
+ // back out again.
+ int rad_state_size =
+ (sizeof(Tru64::nxm_shared) +
+ (process->numCpus()-1) * sizeof(Tru64::nxm_sched_state));
+
+ TypedBufferArg<Tru64::nxm_shared> rad_state(0x14000,
+ rad_state_size);
+ rad_state.copyIn(xc->getMemPort());
+
+ uint64_t uniq_val = gtoh(attrp->pthid) - gtoh(rad_state->nxm_uniq_offset);
+
+ if (gtoh(attrp->type) == Tru64::NXM_TYPE_MANAGER) {
+ // DEC pthreads seems to always create one of these (in
+ // addition to N application threads), but we don't use it,
+ // so don't bother creating it.
+
+ // This is supposed to be a port number. Make something up.
+ *kidp = htog(99);
+ kidp.copyOut(xc->getMemPort());
+
+ return 0;
+ } else if (gtoh(attrp->type) == Tru64::NXM_TYPE_VP) {
+ // A real "virtual processor" kernel thread. Need to fork
+ // this thread on another CPU.
+ Tru64::nxm_sched_state *ssp = &rad_state->nxm_ss[thread_index];
+
+ if (gtoh(ssp->nxm_u.nxm_active) != 0)
+ return (int) Tru64::KERN_NOT_RECEIVER;
+
+ ssp->nxm_u.pth_id = attrp->pthid;
+ ssp->nxm_u.nxm_active = htog(uniq_val | 1);
+
+ rad_state.copyOut(xc->getMemPort());
+
+ Addr slot_state_addr = 0x12000 + sizeof(Tru64::nxm_config_info);
+ int slot_state_size =
+ process->numCpus() * sizeof(Tru64::nxm_slot_state_t);
+
+ TypedBufferArg<Tru64::nxm_slot_state_t>
+ slot_state(slot_state_addr,
+ slot_state_size);
+
+ slot_state.copyIn(xc->getMemPort());
+
+ if (slot_state[thread_index] != Tru64::NXM_SLOT_AVAIL) {
+ cerr << "nxm_thread_createFunc: requested VP slot "
+ << thread_index << " not available!" << endl;
+ fatal("");
+ }
+
+ // XXX This should have an endian conversion but I think this code
+ // doesn't work anyway
+ slot_state[thread_index] = Tru64::NXM_SLOT_BOUND;
+
+ slot_state.copyOut(xc->getMemPort());
+
+ // Find a free simulator execution context.
+ for (int i = 0; i < process->numCpus(); ++i) {
+ ExecContext *xc = process->execContexts[i];
+
+ if (xc->status() == ExecContext::Suspended) {
+ // inactive context... grab it
+ init_exec_context(xc, attrp, uniq_val);
+
+ // This is supposed to be a port number, but we'll try
+ // and get away with just sticking the thread index
+ // here.
+ *kidp = htog(thread_index);
+ kidp.copyOut(xc->getMemPort());
+
+ return 0;
+ }
+ }
+
+ // fell out of loop... no available inactive context
+ cerr << "nxm_thread_create: no idle contexts available." << endl;
+ abort();
+ } else {
+ cerr << "nxm_thread_create: can't handle thread type "
+ << attrp->type << endl;
+ abort();
+ }
+
+ return 0;
+ }
+
+ /// Thread idle call (like yield()).
+ static SyscallReturn
+ nxm_idleFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+ {
+ return 0;
+ }
+
+ /// Block thread.
+ static SyscallReturn
+ nxm_thread_blockFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+ {
+ using namespace std;
+
+ uint64_t tid = xc->getSyscallArg(0);
+ uint64_t secs = xc->getSyscallArg(1);
+ uint64_t flags = xc->getSyscallArg(2);
+ uint64_t action = xc->getSyscallArg(3);
+ uint64_t usecs = xc->getSyscallArg(4);
+
+ cout << xc->getCpuPtr()->name() << ": nxm_thread_block " << tid << " "
+ << secs << " " << flags << " " << action << " " << usecs << endl;
+
+ return 0;
+ }
+
+ /// block.
+ static SyscallReturn
+ nxm_blockFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+ {
+ using namespace std;
+
+ Addr uaddr = xc->getSyscallArg(0);
+ uint64_t val = xc->getSyscallArg(1);
+ uint64_t secs = xc->getSyscallArg(2);
+ uint64_t usecs = xc->getSyscallArg(3);
+ uint64_t flags = xc->getSyscallArg(4);
+
+ BaseCPU *cpu = xc->getCpuPtr();
+
+ cout << cpu->name() << ": nxm_block "
+ << hex << uaddr << dec << " " << val
+ << " " << secs << " " << usecs
+ << " " << flags << endl;
+
+ return 0;
+ }
+
+ /// Unblock thread.
+ static SyscallReturn
+ nxm_unblockFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+ {
+ using namespace std;
+
+ Addr uaddr = xc->getSyscallArg(0);
+
+ cout << xc->getCpuPtr()->name() << ": nxm_unblock "
+ << hex << uaddr << dec << endl;
+
+ return 0;
+ }
+
+ /// Switch thread priority.
+ static SyscallReturn
+ swtch_priFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+ {
+ // Attempts to switch to another runnable thread (if there is
+ // one). Returns false if there are no other threads to run
+ // (i.e., the thread can reasonably spin-wait) or true if there
+ // are other threads.
+ //
+ // Since we assume at most one "kernel" thread per CPU, it's
+ // always safe to return false here.
+ return 0; //false;
+ }
+
+
+ /// Activate exec context waiting on a channel. Just activate one
+ /// by default.
+ static int
+ activate_waiting_context(Addr uaddr, Process *process,
+ bool activate_all = false)
+ {
+ using namespace std;
+
+ int num_activated = 0;
+
+ list<Process::WaitRec>::iterator i = process->waitList.begin();
+ list<Process::WaitRec>::iterator end = process->waitList.end();
+
+ while (i != end && (num_activated == 0 || activate_all)) {
+ if (i->waitChan == uaddr) {
+ // found waiting process: make it active
+ ExecContext *newCtx = i->waitingContext;
+ assert(newCtx->status() == ExecContext::Suspended);
+ newCtx->activate();
+
+ // get rid of this record
+ i = process->waitList.erase(i);
+
+ ++num_activated;
+ } else {
+ ++i;
+ }
+ }
+
+ return num_activated;
+ }
+
+ /// M5 hacked-up lock acquire.
+ static void
+ m5_lock_mutex(Addr uaddr, Process *process, ExecContext *xc)
+ {
+ using namespace TheISA;
+
+ TypedBufferArg<uint64_t> lockp(uaddr);
+
+ lockp.copyIn(xc->getMemPort());
+
+ if (gtoh(*lockp) == 0) {
+ // lock is free: grab it
+ *lockp = htog(1);
+ lockp.copyOut(xc->getMemPort());
+ } else {
+ // lock is busy: disable until free
+ process->waitList.push_back(Process::WaitRec(uaddr, xc));
+ xc->suspend();
+ }
+ }
+
+ /// M5 unlock call.
+ static void
+ m5_unlock_mutex(Addr uaddr, Process *process, ExecContext *xc)
+ {
+ TypedBufferArg<uint64_t> lockp(uaddr);
+
+ lockp.copyIn(xc->getMemPort());
+ assert(*lockp != 0);
+
+ // Check for a process waiting on the lock.
+ int num_waiting = activate_waiting_context(uaddr, process);
+
+ // clear lock field if no waiting context is taking over the lock
+ if (num_waiting == 0) {
+ *lockp = 0;
+ lockp.copyOut(xc->getMemPort());
+ }
+ }
+
+ /// Lock acquire syscall handler.
+ static SyscallReturn
+ m5_mutex_lockFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+ {
+ Addr uaddr = xc->getSyscallArg(0);
+
+ m5_lock_mutex(uaddr, process, xc);
+
+ // Return 0 since we will always return to the user with the lock
+ // acquired. We will just keep the context inactive until that is
+ // true.
+ return 0;
+ }
+
+ /// Try lock (non-blocking).
+ static SyscallReturn
+ m5_mutex_trylockFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+ {
+ using namespace TheISA;
+
+ Addr uaddr = xc->getSyscallArg(0);
+ TypedBufferArg<uint64_t> lockp(uaddr);
+
+ lockp.copyIn(xc->getMemPort());
+
+ if (gtoh(*lockp) == 0) {
+ // lock is free: grab it
+ *lockp = htog(1);
+ lockp.copyOut(xc->getMemPort());
+ return 0;
+ } else {
+ return 1;
+ }
+ }
+
+ /// Unlock syscall handler.
+ static SyscallReturn
+ m5_mutex_unlockFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+ {
+ Addr uaddr = xc->getSyscallArg(0);
+
+ m5_unlock_mutex(uaddr, process, xc);
+
+ return 0;
+ }
+
+ /// Signal ocndition.
+ static SyscallReturn
+ m5_cond_signalFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+ {
+ Addr cond_addr = xc->getSyscallArg(0);
+
+ // Wake up one process waiting on the condition variable.
+ activate_waiting_context(cond_addr, process);
+
+ return 0;
+ }
+
+ /// Wake up all processes waiting on the condition variable.
+ static SyscallReturn
+ m5_cond_broadcastFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+ {
+ Addr cond_addr = xc->getSyscallArg(0);
+
+ activate_waiting_context(cond_addr, process, true);
+
+ return 0;
+ }
+
+ /// Wait on a condition.
+ static SyscallReturn
+ m5_cond_waitFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+ {
+ 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->getMemPort());
+ assert(gtoh(*lockp) != 0);
+
+ m5_unlock_mutex(lock_addr, process, xc);
+
+ process->waitList.push_back(Process::WaitRec(cond_addr, xc));
+ xc->suspend();
+
+ return 0;
+ }
+
+ /// Thread exit.
+ static SyscallReturn
+ m5_thread_exitFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+ {
+ assert(xc->status() == ExecContext::Active);
+ xc->deallocate();
+
+ return 0;
+ }
+
+ /// Indirect syscall invocation (call #0).
+ static SyscallReturn
+ indirectSyscallFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+ {
+ int new_callnum = xc->getSyscallArg(0);
+ LiveProcess *lp = dynamic_cast<LiveProcess*>(process);
+ assert(lp);
+
+ for (int i = 0; i < 5; ++i)
+ xc->setSyscallArg(i, xc->getSyscallArg(i+1));
+
+
+ SyscallDesc *new_desc = lp->getDesc(new_callnum);
+ if (desc == NULL)
+ fatal("Syscall %d out of range", callnum);
+
+ new_desc->doSyscall(new_callnum, process, xc);
+
+ return 0;
+ }
+
+}; // class Tru64
+
+
+#endif // FULL_SYSTEM
+
+#endif // __TRU64_HH__
diff --git a/src/kern/tru64/tru64_events.cc b/src/kern/tru64/tru64_events.cc
new file mode 100644
index 000000000..69fc5c55d
--- /dev/null
+++ b/src/kern/tru64/tru64_events.cc
@@ -0,0 +1,105 @@
+/*
+ * 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/exec_context.hh"
+#include "cpu/base.hh"
+#include "kern/system_events.hh"
+#include "kern/tru64/tru64_events.hh"
+#include "kern/tru64/dump_mbuf.hh"
+#include "kern/tru64/printf.hh"
+#include "arch/alpha/ev5.hh"
+#include "arch/arguments.hh"
+#include "arch/isa_traits.hh"
+#include "sim/system.hh"
+
+using namespace TheISA;
+
+//void SkipFuncEvent::process(ExecContext *xc);
+
+void
+BadAddrEvent::process(ExecContext *xc)
+{
+ // The following gross hack is the equivalent function to the
+ // annotation for vmunix::badaddr in:
+ // simos/simulation/apps/tcl/osf/tlaser.tcl
+
+ uint64_t a0 = xc->readIntReg(ArgumentReg0);
+
+ 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);
+ SkipFuncEvent::process(xc);
+ }
+ else
+ DPRINTF(BADADDR, "badaddr arg=%#x good\n", a0);
+}
+
+void
+PrintfEvent::process(ExecContext *xc)
+{
+ if (DTRACE(Printf)) {
+ DebugOut() << curTick << ": " << xc->getCpuPtr()->name() << ": ";
+
+ AlphaArguments args(xc);
+ tru64::Printf(args);
+ }
+}
+
+void
+DebugPrintfEvent::process(ExecContext *xc)
+{
+ if (DTRACE(DebugPrintf)) {
+ if (!raw)
+ DebugOut() << curTick << ": " << xc->getCpuPtr()->name() << ": ";
+
+ AlphaArguments args(xc);
+ tru64::Printf(args);
+ }
+}
+
+void
+DumpMbufEvent::process(ExecContext *xc)
+{
+ if (DTRACE(DebugPrintf)) {
+ AlphaArguments args(xc);
+ tru64::DumpMbuf(args);
+ }
+}
diff --git a/kern/tru64/tru64_events.hh b/src/kern/tru64/tru64_events.hh
index 9b5bcfea2..9b5bcfea2 100644
--- a/kern/tru64/tru64_events.hh
+++ b/src/kern/tru64/tru64_events.hh
diff --git a/kern/tru64/tru64_syscalls.cc b/src/kern/tru64/tru64_syscalls.cc
index 8aa57dbaa..8aa57dbaa 100644
--- a/kern/tru64/tru64_syscalls.cc
+++ b/src/kern/tru64/tru64_syscalls.cc
diff --git a/kern/tru64/tru64_syscalls.hh b/src/kern/tru64/tru64_syscalls.hh
index 69fa9101c..69fa9101c 100644
--- a/kern/tru64/tru64_syscalls.hh
+++ b/src/kern/tru64/tru64_syscalls.hh
diff --git a/src/mem/bridge.cc b/src/mem/bridge.cc
new file mode 100644
index 000000000..736e8dc81
--- /dev/null
+++ b/src/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 <algorithm>
+
+#include "base/trace.hh"
+#include "mem/bridge.hh"
+#include "sim/builder.hh"
+
+Bridge::BridgePort::BridgePort(const std::string &_name,
+ Bridge *_bridge, BridgePort *_otherPort,
+ int _delay, int _queueLimit)
+ : Port(_name), bridge(_bridge), otherPort(_otherPort),
+ delay(_delay), outstandingResponses(0),
+ queueLimit(_queueLimit), sendEvent(this)
+{
+}
+
+Bridge::Bridge(const std::string &n, int qsa, int qsb,
+ Tick _delay, int write_ack)
+ : MemObject(n),
+ portA(n + "-portA", this, &portB, _delay, qsa),
+ portB(n + "-portB", this, &portA, _delay, qsa),
+ ackWrites(write_ack)
+{
+}
+
+Port *
+Bridge::getPort(const std::string &if_name)
+{
+ BridgePort *port;
+
+ if (if_name == "side_a")
+ port = &portA;
+ else if (if_name == "side_b")
+ port = &portB;
+ else
+ return NULL;
+
+ if (port->getPeer() != NULL)
+ panic("bridge side %s already connected to.", if_name);
+ return port;
+}
+
+
+void
+Bridge::init()
+{
+ // Make sure that both sides are connected to.
+ if (portA.getPeer() == NULL || portB.getPeer() == NULL)
+ panic("Both ports of bus bridge are not connected to a bus.\n");
+}
+
+
+/** Function called by the port when the bus is receiving a Timing
+ * transaction.*/
+bool
+Bridge::BridgePort::recvTiming(Packet *pkt)
+{
+ DPRINTF(BusBridge, "recvTiming: src %d dest %d addr 0x%x\n",
+ pkt->getSrc(), pkt->getDest(), pkt->getAddr());
+
+ if (pkt->isResponse()) {
+ // This is a response for a request we forwarded earlier. The
+ // corresponding PacketBuffer should be stored in the packet's
+ // senderState field.
+ PacketBuffer *buf = dynamic_cast<PacketBuffer*>(pkt->senderState);
+ assert(buf != NULL);
+ // set up new packet dest & senderState based on values saved
+ // from original request
+ buf->fixResponse(pkt);
+ DPRINTF(BusBridge, " is response, new dest %d\n", pkt->getDest());
+ delete buf;
+ }
+
+ return otherPort->queueForSendTiming(pkt);
+}
+
+
+bool
+Bridge::BridgePort::queueForSendTiming(Packet *pkt)
+{
+ if (queueFull())
+ return false;
+
+ Tick readyTime = curTick + delay;
+ PacketBuffer *buf = new PacketBuffer(pkt, readyTime);
+
+ // If we're about to put this packet at the head of the queue, we
+ // need to schedule an event to do the transmit. Otherwise there
+ // should already be an event scheduled for sending the head
+ // packet.
+ if (sendQueue.empty()) {
+ sendEvent.schedule(readyTime);
+ }
+
+ sendQueue.push_back(buf);
+
+ // Did we just become blocked? If yes, let other side know.
+ if (queueFull())
+ otherPort->sendStatusChange(Port::Blocked);
+
+ return true;
+}
+
+
+void
+Bridge::BridgePort::finishSend(PacketBuffer *buf)
+{
+ if (buf->expectResponse) {
+ // Must wait for response. We just need to count outstanding
+ // responses (in case we want to cap them); PacketBuffer
+ // pointer will be recovered on response.
+ ++outstandingResponses;
+ DPRINTF(BusBridge, " successful: awaiting response (%d)\n",
+ outstandingResponses);
+ } else {
+ // no response expected... deallocate packet buffer now.
+ DPRINTF(BusBridge, " successful: no response expected\n");
+ delete buf;
+ }
+
+ // If there are more packets to send, schedule event to try again.
+ if (!sendQueue.empty()) {
+ buf = sendQueue.front();
+ sendEvent.schedule(std::max(buf->ready, curTick + 1));
+ }
+}
+
+
+void
+Bridge::BridgePort::trySend()
+{
+ assert(!sendQueue.empty());
+
+ PacketBuffer *buf = sendQueue.front();
+
+ assert(buf->ready <= curTick);
+
+ Packet *pkt = buf->pkt;
+
+ DPRINTF(BusBridge, "trySend: origSrc %d dest %d addr 0x%x\n",
+ buf->origSrc, pkt->getDest(), pkt->getAddr());
+
+ if (sendTiming(pkt)) {
+ // send successful
+ sendQueue.pop_front();
+ buf->pkt = NULL; // we no longer own packet, so it's not safe to look at it
+ finishSend(buf);
+ } else {
+ DPRINTF(BusBridge, " unsuccessful\n");
+ }
+}
+
+
+Packet *
+Bridge::BridgePort::recvRetry()
+{
+ PacketBuffer *buf = sendQueue.front();
+ Packet *pkt = buf->pkt;
+ finishSend(buf);
+ return pkt;
+}
+
+/** Function called by the port when the bus is receiving a Atomic
+ * transaction.*/
+Tick
+Bridge::BridgePort::recvAtomic(Packet *pkt)
+{
+ return otherPort->sendAtomic(pkt) + delay;
+}
+
+/** Function called by the port when the bus is receiving a Functional
+ * transaction.*/
+void
+Bridge::BridgePort::recvFunctional(Packet *pkt)
+{
+ std::list<PacketBuffer*>::iterator i;
+ bool pktContinue = true;
+
+ for (i = sendQueue.begin(); i != sendQueue.end(); ++i) {
+ if (pkt->intersect((*i)->pkt)) {
+ pktContinue &= fixPacket(pkt, (*i)->pkt);
+ }
+ }
+
+ if (pktContinue) {
+ otherPort->sendFunctional(pkt);
+ }
+}
+
+/** Function called by the port when the bus is receiving a status change.*/
+void
+Bridge::BridgePort::recvStatusChange(Port::Status status)
+{
+ if (status == Port::Blocked || status == Port::Unblocked)
+ return;
+
+ otherPort->sendStatusChange(status);
+}
+
+void
+Bridge::BridgePort::getDeviceAddressRanges(AddrRangeList &resp,
+ AddrRangeList &snoop)
+{
+ otherPort->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/src/mem/bridge.hh b/src/mem/bridge.hh
new file mode 100644
index 000000000..8a5cbf92a
--- /dev/null
+++ b/src/mem/bridge.hh
@@ -0,0 +1,184 @@
+/*
+ * 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
+{
+ protected:
+ /** 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 bridge to which this port belongs. */
+ Bridge *bridge;
+
+ /**
+ * Pointer to the port on the other side of the bridge
+ * (connected to the other bus).
+ */
+ BridgePort *otherPort;
+
+ /** Minimum delay though this bridge. */
+ Tick delay;
+
+ class PacketBuffer : public Packet::SenderState {
+
+ public:
+ Tick ready;
+ Packet *pkt;
+ Packet::SenderState *origSenderState;
+ short origSrc;
+ bool expectResponse;
+
+ PacketBuffer(Packet *_pkt, Tick t)
+ : ready(t), pkt(_pkt),
+ origSenderState(_pkt->senderState), origSrc(_pkt->getSrc()),
+ expectResponse(_pkt->needsResponse())
+ {
+ pkt->senderState = this;
+ }
+
+ void fixResponse(Packet *pkt)
+ {
+ assert(pkt->senderState == this);
+ pkt->setDest(origSrc);
+ pkt->senderState = origSenderState;
+ }
+ };
+
+ /**
+ * Outbound packet queue. Packets are held in this queue for a
+ * specified delay to model the processing delay of the
+ * bridge.
+ */
+ std::list<PacketBuffer*> sendQueue;
+
+ int outstandingResponses;
+
+ /** Max queue size for outbound packets */
+ int queueLimit;
+
+ /**
+ * Is this side blocked from accepting outbound packets?
+ */
+ bool queueFull() { return (sendQueue.size() == queueLimit); }
+
+ bool queueForSendTiming(Packet *pkt);
+
+ void finishSend(PacketBuffer *buf);
+
+ /**
+ * Handle send event, scheduled when the packet at the head of
+ * the outbound queue is ready to transmit (for timing
+ * accesses only).
+ */
+ void trySend();
+
+ class SendEvent : public Event
+ {
+ BridgePort *port;
+
+ public:
+ SendEvent(BridgePort *p)
+ : Event(&mainEventQueue), port(p) {}
+
+ virtual void process() { port->trySend(); }
+
+ virtual const char *description() { return "bridge send event"; }
+ };
+
+ SendEvent sendEvent;
+
+ public:
+
+ /** Constructor for the BusPort.*/
+ BridgePort(const std::string &_name,
+ Bridge *_bridge, BridgePort *_otherPort,
+ int _delay, int _queueLimit);
+
+ protected:
+
+ /** When receiving a timing request from the peer port,
+ pass it to the bridge. */
+ virtual bool recvTiming(Packet *pkt);
+
+ /** When receiving a retry request from the peer port,
+ pass it to the bridge. */
+ virtual Packet* recvRetry();
+
+ /** When receiving a Atomic requestfrom the peer port,
+ pass it to the bridge. */
+ virtual Tick recvAtomic(Packet *pkt);
+
+ /** When receiving a Functional request from the peer port,
+ pass it to the bridge. */
+ virtual void recvFunctional(Packet *pkt);
+
+ /** When receiving a status changefrom the peer port,
+ pass it to the bridge. */
+ virtual void recvStatusChange(Status status);
+
+ /** When receiving a address range request the peer port,
+ pass it to the bridge. */
+ virtual void getDeviceAddressRanges(AddrRangeList &resp,
+ AddrRangeList &snoop);
+ };
+
+ BridgePort portA, portB;
+
+ /** 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);
+
+ virtual void init();
+
+ Bridge(const std::string &n, int qsa, int qsb, Tick _delay, int write_ack);
+};
+
+#endif //__MEM_BUS_HH__
diff --git a/src/mem/bus.cc b/src/mem/bus.cc
new file mode 100644
index 000000000..cfc99a64f
--- /dev/null
+++ b/src/mem/bus.cc
@@ -0,0 +1,206 @@
+/*
+ * 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"
+
+Port *
+Bus::getPort(const std::string &if_name)
+{
+ // if_name ignored? forced to be empty?
+ int id = interfaces.size();
+ BusPort *bp = new BusPort(csprintf("%s-p%d", name(), id), this, id);
+ interfaces.push_back(bp);
+ return bp;
+}
+
+/** 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 receiving a Timing
+ * transaction.*/
+bool
+Bus::recvTiming(Packet *pkt)
+{
+ Port *port;
+ DPRINTF(Bus, "recvTiming: packet src %d dest %d addr 0x%x cmd %s\n",
+ pkt->getSrc(), pkt->getDest(), pkt->getAddr(), pkt->cmdString());
+
+ short dest = pkt->getDest();
+ if (dest == Packet::Broadcast) {
+ port = findPort(pkt->getAddr(), pkt->getSrc());
+ } else {
+ assert(dest >= 0 && dest < interfaces.size());
+ assert(dest != pkt->getSrc()); // catch infinite loops
+ port = interfaces[dest];
+ }
+ return port->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 0x%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 receiving a Atomic
+ * transaction.*/
+Tick
+Bus::recvAtomic(Packet *pkt)
+{
+ DPRINTF(Bus, "recvAtomic: packet src %d dest %d addr 0x%x cmd %s\n",
+ pkt->getSrc(), pkt->getDest(), pkt->getAddr(), pkt->cmdString());
+ assert(pkt->getDest() == Packet::Broadcast);
+ return findPort(pkt->getAddr(), pkt->getSrc())->sendAtomic(pkt);
+}
+
+/** Function called by the port when the bus is receiving a Functional
+ * transaction.*/
+void
+Bus::recvFunctional(Packet *pkt)
+{
+ DPRINTF(Bus, "recvFunctional: packet src %d dest %d addr 0x%x cmd %s\n",
+ pkt->getSrc(), pkt->getDest(), pkt->getAddr(), pkt->cmdString());
+ assert(pkt->getDest() == Packet::Broadcast);
+ findPort(pkt->getAddr(), pkt->getSrc())->sendFunctional(pkt);
+}
+
+/** Function called by the port when the bus is receiving a status change.*/
+void
+Bus::recvStatusChange(Port::Status status, int id)
+{
+ assert(status == Port::RangeChange &&
+ "The other statuses need to be implemented.");
+
+ DPRINTF(BusAddrRanges, "received RangeChange from device id %d\n", id);
+
+ 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(BusAddrRanges, "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(BusAddrRanges, "received address range request, returning:\n");
+ for (portIter = portList.begin(); portIter != portList.end(); portIter++) {
+ if (portIter->portId != id) {
+ resp.push_back(portIter->range);
+ DPRINTF(BusAddrRanges, " -- %#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/src/mem/bus.hh b/src/mem/bus.hh
new file mode 100644
index 000000000..5eeb07904
--- /dev/null
+++ b/src/mem/bus.hh
@@ -0,0 +1,158 @@
+/*
+ * 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);
+
+ /** Function called by the port when the bus is recieving a Atomic
+ transaction.*/
+ Tick recvAtomic(Packet *pkt);
+
+ /** Function called by the port when the bus is recieving a Functional
+ transaction.*/
+ void recvFunctional(Packet *pkt);
+
+ /** 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 *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(const std::string &_name, Bus *_bus, int _id)
+ : Port(_name), 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)
+ { pkt->setSrc(id); return bus->recvTiming(pkt); }
+
+ /** When reciving a Atomic requestfrom the peer port (at id),
+ pass it to the bus. */
+ virtual Tick recvAtomic(Packet *pkt)
+ { pkt->setSrc(id); return bus->recvAtomic(pkt); }
+
+ /** When reciving a Functional requestfrom the peer port (at id),
+ pass it to the bus. */
+ virtual void recvFunctional(Packet *pkt)
+ { pkt->setSrc(id); bus->recvFunctional(pkt); }
+
+ /** 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);
+
+ virtual void init();
+
+ Bus(const std::string &n, int bus_id)
+ : MemObject(n), busId(bus_id) {}
+
+};
+
+#endif //__MEM_BUS_HH__
diff --git a/mem/cache/prefetch/tagged_prefetcher_impl.hh b/src/mem/cache/prefetch/tagged_prefetcher_impl.hh
index 6c27256a9..6c27256a9 100644
--- a/mem/cache/prefetch/tagged_prefetcher_impl.hh
+++ b/src/mem/cache/prefetch/tagged_prefetcher_impl.hh
diff --git a/mem/config/prefetch.hh b/src/mem/config/prefetch.hh
index 03eb570f0..03eb570f0 100644
--- a/mem/config/prefetch.hh
+++ b/src/mem/config/prefetch.hh
diff --git a/src/mem/mem_object.cc b/src/mem/mem_object.cc
new file mode 100644
index 000000000..f579a0727
--- /dev/null
+++ b/src/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/src/mem/mem_object.hh b/src/mem/mem_object.hh
new file mode 100644
index 000000000..58930eccc
--- /dev/null
+++ b/src/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/src/mem/packet.cc b/src/mem/packet.cc
new file mode 100644
index 000000000..3b415d77f
--- /dev/null
+++ b/src/mem/packet.cc
@@ -0,0 +1,118 @@
+/*
+ * 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"
+
+static const std::string ReadReqString("ReadReq");
+static const std::string WriteReqString("WriteReq");
+static const std::string WriteReqNoAckString("WriteReqNoAck");
+static const std::string ReadRespString("ReadResp");
+static const std::string WriteRespString("WriteResp");
+static const std::string OtherCmdString("<other>");
+
+const std::string &
+Packet::cmdString() const
+{
+ switch (cmd) {
+ case ReadReq: return ReadReqString;
+ case WriteReq: return WriteReqString;
+ case WriteReqNoAck: return WriteReqNoAckString;
+ case ReadResp: return ReadRespString;
+ case WriteResp: return WriteRespString;
+ default: return OtherCmdString;
+ }
+}
+
+/** 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[getSize()];
+}
+
+/** Do the packet modify the same addresses. */
+bool
+Packet::intersect(Packet *p)
+{
+ Addr s1 = getAddr();
+ Addr e1 = getAddr() + getSize();
+ Addr s2 = p->getAddr();
+ Addr e2 = p->getAddr() + p->getSize();
+
+ 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/src/mem/packet.hh b/src/mem/packet.hh
new file mode 100644
index 000000000..83f52ede5
--- /dev/null
+++ b/src/mem/packet.hh
@@ -0,0 +1,256 @@
+/*
+ * 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;
+
+/**
+ * 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.
+ */
+class 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;
+
+
+ /** The address of the request, could be virtual or physical (depending on
+ cache configurations). */
+ Addr addr;
+
+ /** 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;
+
+ bool addrValid;
+ bool sizeValid;
+ bool srcValid;
+
+ public:
+
+ static const short Broadcast = -1;
+
+ /** A pointer to the overall request. */
+ RequestPtr req;
+
+ class CoherenceState {
+ public:
+ virtual ~CoherenceState() {}
+ };
+
+ /** A virtual base opaque structure used to hold
+ coherence status messages. */
+ CoherenceState *coherence; // virtual base opaque,
+ // assert(dynamic_cast<Foo>) etc.
+
+ class SenderState {
+ public:
+ virtual ~SenderState() {}
+ };
+
+ /** A virtual base opaque structure used to hold the senders state. */
+ SenderState *senderState; // virtual base opaque,
+ // assert(dynamic_cast<Foo>) etc.
+
+ private:
+ /** List of command attributes. */
+ enum CommandAttribute
+ {
+ IsRead = 1 << 0,
+ IsWrite = 1 << 1,
+ IsPrefetch = 1 << 2,
+ IsInvalidate = 1 << 3,
+ IsRequest = 1 << 4,
+ IsResponse = 1 << 5,
+ NeedsResponse = 1 << 6,
+ };
+
+ public:
+ /** List of all commands associated with a packet. */
+ enum Command
+ {
+ ReadReq = IsRead | IsRequest | NeedsResponse,
+ WriteReq = IsWrite | IsRequest | NeedsResponse,
+ WriteReqNoAck = IsWrite | IsRequest,
+ ReadResp = IsRead | IsResponse,
+ WriteResp = IsWrite | IsResponse
+ };
+
+ const std::string &cmdString() const;
+
+ /** The command of the transaction. */
+ Command cmd;
+
+ bool isRead() { return (cmd & IsRead) != 0; }
+ bool isRequest() { return (cmd & IsRequest) != 0; }
+ bool isResponse() { return (cmd & IsResponse) != 0; }
+ bool needsResponse() { return (cmd & NeedsResponse) != 0; }
+
+ void makeTimingResponse() {
+ assert(needsResponse());
+ int icmd = (int)cmd;
+ icmd &= ~(IsRequest | NeedsResponse);
+ icmd |= IsResponse;
+ cmd = (Command)icmd;
+ dest = src;
+ srcValid = false;
+ }
+
+ /** The time this request was responded to. Used to calculate latencies. */
+ Tick time;
+
+ /** The result of a particular packets request. */
+ enum Result
+ {
+ Success,
+ BadAddress,
+ Unknown
+ };
+
+ /** The result of the packet transaction. */
+ Result result;
+
+ /** Accessor function that returns the source index of the packet. */
+ short getSrc() const { assert(srcValid); return src; }
+ void setSrc(short _src) { src = _src; srcValid = true; }
+
+ /** Accessor function that returns the destination index of
+ the packet. */
+ short getDest() const { return dest; }
+ void setDest(short _dest) { dest = _dest; }
+
+ Addr getAddr() const { assert(addrValid); return addr; }
+ void setAddr(Addr _addr) { addr = _addr; addrValid = true; }
+
+ int getSize() const { assert(sizeValid); return size; }
+ void setSize(int _size) { size = _size; sizeValid = true; }
+
+
+ Packet(Request *_req, Command _cmd, short _dest)
+ : data(NULL), staticData(false), dynamicData(false), arrayData(false),
+ addr(_req->paddr), size(_req->size), dest(_dest),
+ addrValid(_req->validPaddr), sizeValid(_req->validSize),
+ srcValid(false),
+ req(_req), coherence(NULL), senderState(NULL), cmd(_cmd),
+ time(curTick), result(Unknown)
+ {
+ }
+
+ ~Packet()
+ { deleteData(); }
+
+
+ /** Minimally reset a packet so something like simple cpu can reuse it. */
+ void reset();
+
+ void reinitFromRequest() {
+ if (req->validPaddr) setAddr(req->paddr);
+ if (req->validSize) setSize(req->size);
+ }
+
+ /** 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/src/mem/page_table.cc b/src/mem/page_table.cc
new file mode 100644
index 000000000..c4e1ea193
--- /dev/null
+++ b/src/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/src/mem/page_table.hh b/src/mem/page_table.hh
new file mode 100644
index 000000000..26248261a
--- /dev/null
+++ b/src/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/src/mem/physical.cc b/src/mem/physical.cc
new file mode 100644
index 000000000..26dbef0cd
--- /dev/null
+++ b/src/mem/physical.cc
@@ -0,0 +1,377 @@
+/*
+ * 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 <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);
+
+ // turn packet around to go back to requester
+ pkt->makeTimingResponse();
+ 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->getAddr() + pkt->getSize() < pmem_size);
+
+ switch (pkt->cmd) {
+ case Packet::ReadReq:
+ memcpy(pkt->getPtr<uint8_t>(),
+ pmem_addr + pkt->getAddr() - base_addr,
+ pkt->getSize());
+ break;
+ case Packet::WriteReq:
+ memcpy(pmem_addr + pkt->getAddr() - base_addr,
+ pkt->getPtr<uint8_t>(),
+ pkt->getSize());
+ // temporary hack: will need to add real LL/SC implementation
+ // for cacheless systems later.
+ if (pkt->req->getFlags() & LOCKED) {
+ pkt->req->setScResult(1);
+ }
+ break;
+ default:
+ panic("unimplemented");
+ }
+
+ pkt->result = Packet::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(name() + "-port", this);
+ return port;
+ } else if (if_name == "functional") {
+ /* special port for functional writes at startup. */
+ return new MemoryPort(name() + "-funcport", this);
+ } else {
+ panic("PhysicalMemory::getPort: unknown port %s requested", if_name);
+ }
+}
+
+void
+PhysicalMemory::recvStatusChange(Port::Status status)
+{
+}
+
+PhysicalMemory::MemoryPort::MemoryPort(const std::string &_name,
+ PhysicalMemory *_memory)
+ : Port(_name), 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/src/mem/physical.hh b/src/mem/physical.hh
new file mode 100644
index 000000000..2ced79045
--- /dev/null
+++ b/src/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(const std::string &_name, 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/src/mem/port.cc b/src/mem/port.cc
new file mode 100644
index 000000000..651cb739a
--- /dev/null
+++ b/src/mem/port.cc
@@ -0,0 +1,84 @@
+/*
+ * 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 "base/trace.hh"
+#include "mem/packet_impl.hh"
+#include "mem/port.hh"
+
+void
+Port::setPeer(Port *port)
+{
+ DPRINTF(Config, "setting peer to %s\n", port->name());
+ peer = port;
+}
+
+void
+Port::blobHelper(Addr addr, uint8_t *p, int size, Packet::Command cmd)
+{
+ Request req(false);
+ Packet pkt(&req, cmd, Packet::Broadcast);
+
+ for (ChunkGenerator gen(addr, size, peerBlockSize());
+ !gen.done(); gen.next()) {
+ req.setPaddr(gen.addr());
+ req.setSize(gen.size());
+ pkt.reinitFromRequest();
+ pkt.dataStatic(p);
+ sendFunctional(&pkt);
+ p += gen.size();
+ }
+}
+
+void
+Port::writeBlob(Addr addr, uint8_t *p, int size)
+{
+ blobHelper(addr, p, size, Packet::WriteReq);
+}
+
+void
+Port::readBlob(Addr addr, uint8_t *p, int size)
+{
+ blobHelper(addr, p, size, Packet::ReadReq);
+}
+
+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, Packet::WriteReq);
+
+ delete [] buf;
+}
diff --git a/src/mem/port.hh b/src/mem/port.hh
new file mode 100644
index 000000000..f9103865e
--- /dev/null
+++ b/src/mem/port.hh
@@ -0,0 +1,270 @@
+/*
+ * 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
+{
+ private:
+
+ /** Descriptive name (for DPRINTF output) */
+ const std::string portName;
+
+ public:
+
+ /**
+ * Constructor.
+ *
+ * @param _name Port name for DPRINTF output. Should include name
+ * of memory system object to which the port belongs.
+ */
+ Port(const std::string &_name)
+ : portName(_name)
+ { }
+
+ /** Return port name (for DPRINTF). */
+ const std::string &name() const { return portName; }
+
+ 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);
+
+ /** 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, Packet::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:
+ FunctionalPort(const std::string &_name)
+ : Port(_name)
+ {}
+
+ 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/src/mem/request.hh b/src/mem/request.hh
new file mode 100644
index 000000000..10550e859
--- /dev/null
+++ b/src/mem/request.hh
@@ -0,0 +1,201 @@
+/*
+ * 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;
+
+//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);
+
+ friend class Packet;
+};
+
+#endif // __MEM_REQUEST_HH__
diff --git a/src/mem/translating_port.cc b/src/mem/translating_port.cc
new file mode 100644
index 000000000..ee4d277b6
--- /dev/null
+++ b/src/mem/translating_port.cc
@@ -0,0 +1,187 @@
+/*
+ * 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(const std::string &_name,
+ PageTable *p_table, bool alloc)
+ : FunctionalPort(_name), 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/src/mem/translating_port.hh b/src/mem/translating_port.hh
new file mode 100644
index 000000000..d078158a3
--- /dev/null
+++ b/src/mem/translating_port.hh
@@ -0,0 +1,61 @@
+/*
+ * 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;
+
+ public:
+ TranslatingPort(const std::string &_name,
+ PageTable *p_table, bool alloc = false);
+ virtual ~TranslatingPort();
+
+ 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/src/mem/vport.cc b/src/mem/vport.cc
new file mode 100644
index 000000000..cc569acf3
--- /dev/null
+++ b/src/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/src/mem/vport.hh b/src/mem/vport.hh
new file mode 100644
index 000000000..0f3b1f09e
--- /dev/null
+++ b/src/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(const std::string &_name, ExecContext *_xc = NULL)
+ : FunctionalPort(_name), 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/src/python/SConscript b/src/python/SConscript
new file mode 100644
index 000000000..4407e403d
--- /dev/null
+++ b/src/python/SConscript
@@ -0,0 +1,207 @@
+# -*- mode:python -*-
+
+# Copyright (c) 2004-2005 The Regents of The University of Michigan
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met: redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer;
+# redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution;
+# neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import os, os.path, re, sys
+
+Import('env')
+
+import scons_helper
+
+def WriteEmbeddedPyFile(target, source, path, name, ext, filename):
+ if isinstance(source, str):
+ source = file(source, 'r')
+
+ if isinstance(target, str):
+ target = file(target, 'w')
+
+ print >>target, "AddModule(%s, %s, %s, %s, '''\\" % \
+ (`path`, `name`, `ext`, `filename`)
+
+ for line in source:
+ line = line
+ # escape existing backslashes
+ line = line.replace('\\', '\\\\')
+ # escape existing triple quotes
+ line = line.replace("'''", r"\'\'\'")
+
+ print >>target, line,
+
+ print >>target, "''')"
+ print >>target
+
+def WriteCFile(target, source, name):
+ if isinstance(source, str):
+ source = file(source, 'r')
+
+ if isinstance(target, str):
+ target = file(target, 'w')
+
+ print >>target, 'const char %s_string[] = {' % name
+
+ count = 0
+ from array import array
+ try:
+ while True:
+ foo = array('B')
+ foo.fromfile(source, 10000)
+ l = [ str(i) for i in foo.tolist() ]
+ count += len(l)
+ for i in xrange(0,9999,20):
+ print >>target, ','.join(l[i:i+20]) + ','
+ except EOFError:
+ l = [ str(i) for i in foo.tolist() ]
+ count += len(l)
+ for i in xrange(0,len(l),20):
+ print >>target, ','.join(l[i:i+20]) + ','
+ print >>target, ','.join(l[i:]) + ','
+
+ print >>target, '};'
+ print >>target, 'const int %s_length = %d;' % (name, count)
+ print >>target
+
+def splitpath(path):
+ dir,file = os.path.split(path)
+ path = []
+ assert(file)
+ while dir:
+ dir,base = os.path.split(dir)
+ path.insert(0, base)
+ return path, file
+
+def MakeEmbeddedPyFile(target, source, env):
+ target = file(str(target[0]), 'w')
+
+ tree = {}
+ for src in source:
+ src = str(src)
+ path,pyfile = splitpath(src)
+ node = tree
+ for dir in path:
+ if not node.has_key(dir):
+ node[dir] = { }
+ node = node[dir]
+
+ name,ext = pyfile.split('.')
+ if name == '__init__':
+ node['.hasinit'] = True
+ node[pyfile] = (src,name,ext,src)
+
+ done = False
+ while not done:
+ done = True
+ for name,entry in tree.items():
+ if not isinstance(entry, dict): continue
+ if entry.has_key('.hasinit'): continue
+
+ done = False
+ del tree[name]
+ for key,val in entry.iteritems():
+ if tree.has_key(key):
+ raise NameError, \
+ "dir already has %s can't add it again" % key
+ tree[key] = val
+
+ files = []
+ def populate(node, path = []):
+ names = node.keys()
+ names.sort()
+ for name in names:
+ if name == '.hasinit':
+ continue
+
+ entry = node[name]
+ if isinstance(entry, dict):
+ if not entry.has_key('.hasinit'):
+ raise NameError, 'package directory missing __init__.py'
+ populate(entry, path + [ name ])
+ else:
+ pyfile,name,ext,filename = entry
+ files.append((pyfile, path, name, ext, filename))
+ populate(tree)
+
+ for pyfile, path, name, ext, filename in files:
+ WriteEmbeddedPyFile(target, pyfile, path, name, ext, filename)
+
+def MakeDefinesPyFile(target, source, env):
+ f = file(str(target[0]), 'w')
+ print >>f, "import __main__"
+ print >>f, "__main__.m5_build_env = ",
+ print >>f, source[0]
+ f.close()
+
+CFileCounter = 0
+def MakePythonCFile(target, source, env):
+ global CFileCounter
+ target = file(str(target[0]), 'w')
+
+ print >>target, '''\
+#include "base/embedfile.hh"
+
+namespace {
+'''
+ for src in source:
+ src = str(src)
+ fname = os.path.basename(src)
+ name = 'embedded_file%d' % CFileCounter
+ CFileCounter += 1
+ WriteCFile(target, src, name)
+ print >>target, '''\
+EmbedMap %(name)s("%(fname)s",
+ %(name)s_string, %(name)s_length);
+
+''' % locals()
+ print >>target, '''\
+
+/* namespace */ }
+'''
+
+# base list of .py files to embed
+embedded_py_files = [ os.path.join(env['ROOT'], 'util/pbs/jobfile.py') ]
+# add all .py files in python/m5
+objpath = os.path.join(env['SRCDIR'], 'python', 'm5')
+for root, dirs, files in os.walk(objpath, topdown=True):
+ for i,dir in enumerate(dirs):
+ if dir == 'SCCS':
+ del dirs[i]
+ break
+
+ assert(root.startswith(objpath))
+ for f in files:
+ if f.endswith('.py'):
+ embedded_py_files.append(os.path.join(root, f))
+
+embedfile_hh = os.path.join(env['SRCDIR'], 'base/embedfile.hh')
+
+optionDict = dict([(opt, env[opt]) for opt in env.ExportOptions])
+env.Command('defines.py', Value(optionDict), MakeDefinesPyFile)
+
+env.Command('embedded_py.py', embedded_py_files, MakeEmbeddedPyFile)
+env.Depends('embedded_py.cc', embedfile_hh)
+env.Command('embedded_py.cc',
+ ['string_importer.py', 'defines.py', 'embedded_py.py'],
+ MakePythonCFile)
diff --git a/python/m5/__init__.py b/src/python/m5/__init__.py
index 9bb68a090..9bb68a090 100644
--- a/python/m5/__init__.py
+++ b/src/python/m5/__init__.py
diff --git a/python/m5/config.py b/src/python/m5/config.py
index 1e25e0d09..1e25e0d09 100644
--- a/python/m5/config.py
+++ b/src/python/m5/config.py
diff --git a/python/m5/convert.py b/src/python/m5/convert.py
index 73181e985..73181e985 100644
--- a/python/m5/convert.py
+++ b/src/python/m5/convert.py
diff --git a/python/m5/multidict.py b/src/python/m5/multidict.py
index fd40ebbbd..fd40ebbbd 100644
--- a/python/m5/multidict.py
+++ b/src/python/m5/multidict.py
diff --git a/src/python/m5/objects/AlphaConsole.py b/src/python/m5/objects/AlphaConsole.py
new file mode 100644
index 000000000..68e6089ab
--- /dev/null
+++ b/src/python/m5/objects/AlphaConsole.py
@@ -0,0 +1,9 @@
+from m5 import *
+from Device import BasicPioDevice
+
+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.AlphaSystem(Parent.any, "system object")
diff --git a/python/m5/objects/AlphaFullCPU.py b/src/python/m5/objects/AlphaFullCPU.py
index d719bf783..d719bf783 100644
--- a/python/m5/objects/AlphaFullCPU.py
+++ b/src/python/m5/objects/AlphaFullCPU.py
diff --git a/python/m5/objects/AlphaTLB.py b/src/python/m5/objects/AlphaTLB.py
index 5edf8e13d..5edf8e13d 100644
--- a/python/m5/objects/AlphaTLB.py
+++ b/src/python/m5/objects/AlphaTLB.py
diff --git a/src/python/m5/objects/BadDevice.py b/src/python/m5/objects/BadDevice.py
new file mode 100644
index 000000000..9cb9a8f03
--- /dev/null
+++ b/src/python/m5/objects/BadDevice.py
@@ -0,0 +1,6 @@
+from m5 import *
+from Device import BasicPioDevice
+
+class BadDevice(BasicPioDevice):
+ type = 'BadDevice'
+ devicename = Param.String("Name of device to error on")
diff --git a/src/python/m5/objects/BaseCPU.py b/src/python/m5/objects/BaseCPU.py
new file mode 100644
index 000000000..49cb2a8f3
--- /dev/null
+++ b/src/python/m5/objects/BaseCPU.py
@@ -0,0 +1,27 @@
+from m5 import *
+class BaseCPU(SimObject):
+ type = 'BaseCPU'
+ abstract = True
+ mem = Param.MemObject("memory")
+
+ if build_env['FULL_SYSTEM']:
+ dtb = Param.AlphaDTB("Data TLB")
+ itb = Param.AlphaITB("Instruction TLB")
+ system = Param.System(Parent.any, "system object")
+ cpu_id = Param.Int(-1, "CPU identifier")
+ else:
+ workload = VectorParam.Process("processes to run")
+
+ max_insts_all_threads = Param.Counter(0,
+ "terminate when all threads have reached this inst count")
+ max_insts_any_thread = Param.Counter(0,
+ "terminate when any thread reaches this inst count")
+ max_loads_all_threads = Param.Counter(0,
+ "terminate when all threads have reached this load count")
+ max_loads_any_thread = Param.Counter(0,
+ "terminate when any thread reaches this load count")
+
+ defer_registration = Param.Bool(False,
+ "defer registration with system (for sampling)")
+
+ clock = Param.Clock(Parent.clock, "clock speed")
diff --git a/python/m5/objects/BaseCache.py b/src/python/m5/objects/BaseCache.py
index 79d21572a..79d21572a 100644
--- a/python/m5/objects/BaseCache.py
+++ b/src/python/m5/objects/BaseCache.py
diff --git a/src/python/m5/objects/Bridge.py b/src/python/m5/objects/Bridge.py
new file mode 100644
index 000000000..ada715ce9
--- /dev/null
+++ b/src/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/src/python/m5/objects/Bus.py b/src/python/m5/objects/Bus.py
new file mode 100644
index 000000000..8c5397281
--- /dev/null
+++ b/src/python/m5/objects/Bus.py
@@ -0,0 +1,6 @@
+from m5 import *
+from MemObject import MemObject
+
+class Bus(MemObject):
+ type = 'Bus'
+ bus_id = Param.Int(0, "blah")
diff --git a/python/m5/objects/CoherenceProtocol.py b/src/python/m5/objects/CoherenceProtocol.py
index 7013000d6..7013000d6 100644
--- a/python/m5/objects/CoherenceProtocol.py
+++ b/src/python/m5/objects/CoherenceProtocol.py
diff --git a/src/python/m5/objects/Device.py b/src/python/m5/objects/Device.py
new file mode 100644
index 000000000..2a71bbc65
--- /dev/null
+++ b/src/python/m5/objects/Device.py
@@ -0,0 +1,18 @@
+from m5 import *
+from MemObject import MemObject
+
+class PioDevice(MemObject):
+ type = 'PioDevice'
+ abstract = True
+ platform = Param.Platform(Parent.any, "Platform this device is part of")
+ system = Param.System(Parent.any, "System this device is part of")
+
+class BasicPioDevice(PioDevice):
+ type = 'BasicPioDevice'
+ abstract = True
+ pio_addr = Param.Addr("Device Address")
+ pio_latency = Param.Tick(1, "Programmed IO latency in simticks")
+
+class DmaDevice(PioDevice):
+ type = 'DmaDevice'
+ abstract = True
diff --git a/python/m5/objects/DiskImage.py b/src/python/m5/objects/DiskImage.py
index 0d55e9329..0d55e9329 100644
--- a/python/m5/objects/DiskImage.py
+++ b/src/python/m5/objects/DiskImage.py
diff --git a/src/python/m5/objects/Ethernet.py b/src/python/m5/objects/Ethernet.py
new file mode 100644
index 000000000..4286c71c8
--- /dev/null
+++ b/src/python/m5/objects/Ethernet.py
@@ -0,0 +1,115 @@
+from m5 import *
+from Device import DmaDevice
+from Pci import PciDevice
+
+class EtherInt(SimObject):
+ type = 'EtherInt'
+ abstract = True
+ peer = Param.EtherInt(NULL, "peer interface")
+
+class EtherLink(SimObject):
+ type = 'EtherLink'
+ int1 = Param.EtherInt("interface 1")
+ int2 = Param.EtherInt("interface 2")
+ delay = Param.Latency('0us', "packet transmit delay")
+ delay_var = Param.Latency('0ns', "packet transmit delay variability")
+ speed = Param.NetworkBandwidth('1Gbps', "link speed")
+ dump = Param.EtherDump(NULL, "dump object")
+
+class EtherBus(SimObject):
+ type = 'EtherBus'
+ loopback = Param.Bool(True, "send packet back to the sending interface")
+ dump = Param.EtherDump(NULL, "dump object")
+ speed = Param.NetworkBandwidth('100Mbps', "bus speed in bits per second")
+
+class EtherTap(EtherInt):
+ type = 'EtherTap'
+ bufsz = Param.Int(10000, "tap buffer size")
+ dump = Param.EtherDump(NULL, "dump object")
+ port = Param.UInt16(3500, "tap port")
+
+class EtherDump(SimObject):
+ type = 'EtherDump'
+ file = Param.String("dump file")
+ maxlen = Param.Int(96, "max portion of packet data to dump")
+
+if build_env['ALPHA_TLASER']:
+
+ class EtherDev(DmaDevice):
+ type = 'EtherDev'
+ hardware_address = Param.EthernetAddr(NextEthernetAddr,
+ "Ethernet Hardware Address")
+
+ dma_data_free = Param.Bool(False, "DMA of Data is free")
+ dma_desc_free = Param.Bool(False, "DMA of Descriptors is free")
+ 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_filter = Param.Bool(True, "Enable Receive Filter")
+ rx_delay = Param.Latency('1us', "Receive Delay")
+ tx_delay = Param.Latency('1us', "Transmit Delay")
+
+ intr_delay = Param.Latency('0us', "Interrupt Delay")
+ payload_bus = Param.Bus(NULL, "The IO Bus to attach to for payload")
+ physmem = Param.PhysicalMemory(Parent.any, "Physical Memory")
+ tlaser = Param.Turbolaser(Parent.any, "Turbolaser")
+
+ class EtherDevInt(EtherInt):
+ type = 'EtherDevInt'
+ device = Param.EtherDev("Ethernet device of this interface")
+
+class EtherDevBase(PciDevice):
+ hardware_address = Param.EthernetAddr(NextEthernetAddr,
+ "Ethernet Hardware Address")
+
+ clock = Param.Clock('0ns', "State machine processor frequency")
+
+ 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")
+
+ rx_delay = Param.Latency('1us', "Receive Delay")
+ tx_delay = Param.Latency('1us', "Transmit Delay")
+ rx_fifo_size = Param.MemorySize('512kB', "max size of rx fifo")
+ tx_fifo_size = Param.MemorySize('512kB', "max size of tx fifo")
+
+ rx_filter = Param.Bool(True, "Enable Receive Filter")
+ intr_delay = Param.Latency('10us', "Interrupt propagation delay")
+ rx_thread = Param.Bool(False, "dedicated kernel thread for transmit")
+ tx_thread = Param.Bool(False, "dedicated kernel threads for receive")
+ rss = Param.Bool(False, "Receive Side Scaling")
+
+class NSGigE(EtherDevBase):
+ type = 'NSGigE'
+
+ 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):
+ type = 'NSGigEInt'
+ device = Param.NSGigE("Ethernet device of this interface")
+
+class Sinic(EtherDevBase):
+ type = 'Sinic'
+
+ rx_max_copy = Param.MemorySize('1514B', "rx max copy")
+ tx_max_copy = Param.MemorySize('16kB', "tx max copy")
+ rx_max_intr = Param.UInt32(10, "max rx packets per interrupt")
+ rx_fifo_threshold = Param.MemorySize('384kB', "rx fifo high threshold")
+ rx_fifo_low_mark = Param.MemorySize('128kB', "rx fifo low threshold")
+ tx_fifo_high_mark = Param.MemorySize('384kB', "tx fifo high threshold")
+ tx_fifo_threshold = Param.MemorySize('128kB', "tx fifo low threshold")
+ virtual_count = Param.UInt32(1, "Virtualized SINIC")
+ zero_copy = Param.Bool(False, "Zero copy receive")
+ delay_copy = Param.Bool(False, "Delayed copy transmit")
+ virtual_addr = Param.Bool(False, "Virtual addressing")
+
+class SinicInt(EtherInt):
+ type = 'SinicInt'
+ device = Param.Sinic("Ethernet device of this interface")
diff --git a/src/python/m5/objects/Ide.py b/src/python/m5/objects/Ide.py
new file mode 100644
index 000000000..2403e6d36
--- /dev/null
+++ b/src/python/m5/objects/Ide.py
@@ -0,0 +1,14 @@
+from m5 import *
+from Pci import PciDevice
+
+class IdeID(Enum): vals = ['master', 'slave']
+
+class IdeDisk(SimObject):
+ type = 'IdeDisk'
+ delay = Param.Latency('1us', "Fixed disk delay in microseconds")
+ driveID = Param.IdeID('master', "Drive ID")
+ image = Param.DiskImage("Disk image")
+
+class IdeController(PciDevice):
+ type = 'IdeController'
+ disks = VectorParam.IdeDisk("IDE disks attached to this controller")
diff --git a/python/m5/objects/IntrControl.py b/src/python/m5/objects/IntrControl.py
index 66c82c182..66c82c182 100644
--- a/python/m5/objects/IntrControl.py
+++ b/src/python/m5/objects/IntrControl.py
diff --git a/src/python/m5/objects/MemObject.py b/src/python/m5/objects/MemObject.py
new file mode 100644
index 000000000..4d68243e6
--- /dev/null
+++ b/src/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/MemTest.py b/src/python/m5/objects/MemTest.py
index 34299faf0..34299faf0 100644
--- a/python/m5/objects/MemTest.py
+++ b/src/python/m5/objects/MemTest.py
diff --git a/src/python/m5/objects/Pci.py b/src/python/m5/objects/Pci.py
new file mode 100644
index 000000000..85cefcd44
--- /dev/null
+++ b/src/python/m5/objects/Pci.py
@@ -0,0 +1,55 @@
+from m5 import *
+from Device import BasicPioDevice, DmaDevice
+
+class PciConfigData(SimObject):
+ type = 'PciConfigData'
+ VendorID = Param.UInt16("Vendor ID")
+ DeviceID = Param.UInt16("Device ID")
+ Command = Param.UInt16(0, "Command")
+ Status = Param.UInt16(0, "Status")
+ Revision = Param.UInt8(0, "Device")
+ ProgIF = Param.UInt8(0, "Programming Interface")
+ SubClassCode = Param.UInt8(0, "Sub-Class Code")
+ ClassCode = Param.UInt8(0, "Class Code")
+ CacheLineSize = Param.UInt8(0, "System Cacheline Size")
+ LatencyTimer = Param.UInt8(0, "PCI Latency Timer")
+ HeaderType = Param.UInt8(0, "PCI Header Type")
+ BIST = Param.UInt8(0, "Built In Self Test")
+
+ BAR0 = Param.UInt32(0x00, "Base Address Register 0")
+ BAR1 = Param.UInt32(0x00, "Base Address Register 1")
+ BAR2 = Param.UInt32(0x00, "Base Address Register 2")
+ BAR3 = Param.UInt32(0x00, "Base Address Register 3")
+ BAR4 = Param.UInt32(0x00, "Base Address Register 4")
+ BAR5 = Param.UInt32(0x00, "Base Address Register 5")
+ BAR0Size = Param.MemorySize32('0B', "Base Address Register 0 Size")
+ BAR1Size = Param.MemorySize32('0B', "Base Address Register 1 Size")
+ BAR2Size = Param.MemorySize32('0B', "Base Address Register 2 Size")
+ BAR3Size = Param.MemorySize32('0B', "Base Address Register 3 Size")
+ BAR4Size = Param.MemorySize32('0B', "Base Address Register 4 Size")
+ BAR5Size = Param.MemorySize32('0B', "Base Address Register 5 Size")
+
+ CardbusCIS = Param.UInt32(0x00, "Cardbus Card Information Structure")
+ SubsystemID = Param.UInt16(0x00, "Subsystem ID")
+ SubsystemVendorID = Param.UInt16(0x00, "Subsystem Vendor ID")
+ ExpansionROM = Param.UInt32(0x00, "Expansion ROM Base Address")
+ InterruptLine = Param.UInt8(0x00, "Interrupt Line")
+ InterruptPin = Param.UInt8(0x00, "Interrupt Pin")
+ MaximumLatency = Param.UInt8(0x00, "Maximum Latency")
+ MinimumGrant = Param.UInt8(0x00, "Minimum Grant")
+
+class PciConfigAll(BasicPioDevice):
+ type = 'PciConfigAll'
+
+class PciDevice(DmaDevice):
+ type = 'PciDevice'
+ abstract = True
+ 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")
+
+class PciFake(PciDevice):
+ type = 'PciFake'
diff --git a/src/python/m5/objects/PhysicalMemory.py b/src/python/m5/objects/PhysicalMemory.py
new file mode 100644
index 000000000..c59910093
--- /dev/null
+++ b/src/python/m5/objects/PhysicalMemory.py
@@ -0,0 +1,8 @@
+from m5 import *
+from MemObject import *
+
+class PhysicalMemory(MemObject):
+ type = 'PhysicalMemory'
+ range = Param.AddrRange("Device Address")
+ file = Param.String('', "memory mapped file")
+ latency = Param.Latency(Parent.clock, "latency of an access")
diff --git a/python/m5/objects/Platform.py b/src/python/m5/objects/Platform.py
index 4da0ffab4..4da0ffab4 100644
--- a/python/m5/objects/Platform.py
+++ b/src/python/m5/objects/Platform.py
diff --git a/src/python/m5/objects/Process.py b/src/python/m5/objects/Process.py
new file mode 100644
index 000000000..60b00229e
--- /dev/null
+++ b/src/python/m5/objects/Process.py
@@ -0,0 +1,27 @@
+from m5 import *
+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'
+ executable = Param.String('', "executable (overrides cmd[0] if set)")
+ cmd = VectorParam.String("command line (executable plus arguments)")
+ 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)")
+ file = Param.String("EIO trace file name")
diff --git a/python/m5/objects/Repl.py b/src/python/m5/objects/Repl.py
index afd256082..afd256082 100644
--- a/python/m5/objects/Repl.py
+++ b/src/python/m5/objects/Repl.py
diff --git a/src/python/m5/objects/Root.py b/src/python/m5/objects/Root.py
new file mode 100644
index 000000000..205a93c76
--- /dev/null
+++ b/src/python/m5/objects/Root.py
@@ -0,0 +1,23 @@
+from m5 import *
+from Serialize import Serialize
+from Statistics import Statistics
+from Trace import Trace
+from ExeTrace import ExecutionTrace
+from Debug import Debug
+
+class Root(SimObject):
+ type = 'Root'
+ clock = Param.RootClock('200MHz', "tick frequency")
+ max_tick = Param.Tick('0', "maximum simulation ticks (0 = infinite)")
+ progress_interval = Param.Tick('0',
+ "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")
+# stats = Param.Statistics(Statistics(), "statistics object")
+# trace = Param.Trace(Trace(), "trace object")
+# serialize = Param.Serialize(Serialize(), "checkpoint generation options")
+ stats = Statistics()
+ trace = Trace()
+ exetrace = ExecutionTrace()
+ serialize = Serialize()
+ debug = Debug()
diff --git a/python/m5/objects/SimConsole.py b/src/python/m5/objects/SimConsole.py
index df3061908..df3061908 100644
--- a/python/m5/objects/SimConsole.py
+++ b/src/python/m5/objects/SimConsole.py
diff --git a/src/python/m5/objects/SimpleDisk.py b/src/python/m5/objects/SimpleDisk.py
new file mode 100644
index 000000000..e34155ace
--- /dev/null
+++ b/src/python/m5/objects/SimpleDisk.py
@@ -0,0 +1,5 @@
+from m5 import *
+class SimpleDisk(SimObject):
+ type = 'SimpleDisk'
+ disk = Param.DiskImage("Disk Image")
+ system = Param.System(Parent.any, "Sysetm Pointer")
diff --git a/src/python/m5/objects/System.py b/src/python/m5/objects/System.py
new file mode 100644
index 000000000..622b5a870
--- /dev/null
+++ b/src/python/m5/objects/System.py
@@ -0,0 +1,21 @@
+from m5 import *
+
+class System(SimObject):
+ type = 'System'
+ physmem = Param.PhysicalMemory(Parent.any, "phsyical memory")
+ 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")
+ system_type = Param.UInt64("Type of system we are emulating")
+ system_rev = Param.UInt64("Revision of system we are emulating")
diff --git a/src/python/m5/objects/Tsunami.py b/src/python/m5/objects/Tsunami.py
new file mode 100644
index 000000000..27ea0bce8
--- /dev/null
+++ b/src/python/m5/objects/Tsunami.py
@@ -0,0 +1,27 @@
+from m5 import *
+from Device import BasicPioDevice
+from Platform import Platform
+
+class Tsunami(Platform):
+ type = 'Tsunami'
+# pciconfig = Param.PciConfigAll("PCI configuration")
+ system = Param.System(Parent.any, "system")
+
+class TsunamiCChip(BasicPioDevice):
+ type = 'TsunamiCChip'
+ tsunami = Param.Tsunami(Parent.any, "Tsunami")
+
+class IsaFake(BasicPioDevice):
+ type = 'IsaFake'
+ pio_size = Param.Addr(0x8, "Size of address range")
+
+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(BasicPioDevice):
+ type = 'TsunamiPChip'
+ tsunami = Param.Tsunami(Parent.any, "Tsunami")
diff --git a/src/python/m5/objects/Uart.py b/src/python/m5/objects/Uart.py
new file mode 100644
index 000000000..54754aeb9
--- /dev/null
+++ b/src/python/m5/objects/Uart.py
@@ -0,0 +1,15 @@
+from m5 import *
+from Device import BasicPioDevice
+
+class Uart(BasicPioDevice):
+ type = 'Uart'
+ abstract = True
+ sim_console = Param.SimConsole(Parent.any, "The console")
+
+class Uart8250(Uart):
+ type = 'Uart8250'
+
+if build_env['ALPHA_TLASER']:
+ class Uart8530(Uart):
+ type = 'Uart8530'
+
diff --git a/python/m5/smartdict.py b/src/python/m5/smartdict.py
index cd38d7326..cd38d7326 100644
--- a/python/m5/smartdict.py
+++ b/src/python/m5/smartdict.py
diff --git a/sim/async.hh b/src/sim/async.hh
index e0190a133..e0190a133 100644
--- a/sim/async.hh
+++ b/src/sim/async.hh
diff --git a/sim/builder.cc b/src/sim/builder.cc
index 7dc118985..7dc118985 100644
--- a/sim/builder.cc
+++ b/src/sim/builder.cc
diff --git a/sim/builder.hh b/src/sim/builder.hh
index b32e00e76..b32e00e76 100644
--- a/sim/builder.hh
+++ b/src/sim/builder.hh
diff --git a/src/sim/byteswap.hh b/src/sim/byteswap.hh
new file mode 100644
index 000000000..a8c5da9d7
--- /dev/null
+++ b/src/sim/byteswap.hh
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2004 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+//The purpose of this file is to provide endainness conversion utility
+//functions. Depending on the endianness of the guest system, either
+//the LittleEndianGuest or BigEndianGuest namespace is used.
+
+#ifndef __SIM_BYTE_SWAP_HH__
+#define __SIM_BYTE_SWAP_HH__
+
+#include "sim/host.hh"
+
+// This lets us figure out what the byte order of the host system is
+#if defined(linux)
+#include <endian.h>
+// 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
+
+//These functions actually perform the swapping for parameters
+//of various bit lengths
+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 |
+ ((uint64_t)(x) & 0xff000000ULL) << 8 |
+ ((uint64_t)(x) & 0xff00000000ULL) >> 8 |
+ ((uint64_t)(x) & 0xff0000000000ULL) >> 24 |
+ ((uint64_t)(x) & 0xff000000000000ULL) >> 40 |
+ ((uint64_t)(x) & 0xff00000000000000ULL) >> 56) ;
+#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
+//for different data types.
+static inline uint64_t swap_byte(uint64_t x) {return swap_byte64(x);}
+static inline int64_t swap_byte(int64_t x) {return swap_byte64((uint64_t)x);}
+static inline uint32_t swap_byte(uint32_t x) {return swap_byte32(x);}
+static inline int32_t swap_byte(int32_t x) {return swap_byte32((uint32_t)x);}
+//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);}
+#endif
+static inline uint16_t swap_byte(uint16_t x) {return swap_byte32(x);}
+static inline int16_t swap_byte(int16_t x) {return swap_byte16((uint16_t)x);}
+static inline uint8_t swap_byte(uint8_t x) {return x;}
+static inline int8_t swap_byte(int8_t x) {return x;}
+static inline double swap_byte(double x) {return swap_byte64((uint64_t)x);}
+static inline float swap_byte(float x) {return swap_byte32((uint32_t)x);}
+
+//The conversion functions with fixed endianness on both ends don't need to
+//be in a namespace
+template <typename T> static inline T betole(T value) {return swap_byte(value);}
+template <typename T> static inline T letobe(T value) {return swap_byte(value);}
+
+//For conversions not involving the guest system, we can define the functions
+//conditionally based on the BYTE_ORDER macro and outside of the namespaces
+#if BYTE_ORDER == BIG_ENDIAN
+template <typename T> static inline T htole(T value) {return swap_byte(value);}
+template <typename T> static inline T letoh(T value) {return swap_byte(value);}
+template <typename T> static inline T htobe(T value) {return value;}
+template <typename T> static inline T betoh(T value) {return value;}
+#elif BYTE_ORDER == LITTLE_ENDIAN
+template <typename T> static inline T htole(T value) {return value;}
+template <typename T> static inline T letoh(T value) {return value;}
+template <typename T> static inline T htobe(T value) {return swap_byte(value);}
+template <typename T> static inline T betoh(T value) {return swap_byte(value);}
+#else
+ #error Invalid Endianess
+#endif
+
+namespace BigEndianGuest
+{
+ template <typename T>
+ static inline T gtole(T value) {return betole(value);}
+ template <typename T>
+ static inline T letog(T value) {return letobe(value);}
+ template <typename T>
+ static inline T gtobe(T value) {return value;}
+ template <typename T>
+ static inline T betog(T value) {return value;}
+ template <typename T>
+ static inline T htog(T value) {return htobe(value);}
+ template <typename T>
+ static inline T gtoh(T value) {return betoh(value);}
+}
+
+namespace LittleEndianGuest
+{
+ template <typename T>
+ static inline T gtole(T value) {return value;}
+ template <typename T>
+ static inline T letog(T value) {return value;}
+ template <typename T>
+ static inline T gtobe(T value) {return letobe(value);}
+ template <typename T>
+ static inline T betog(T value) {return betole(value);}
+ template <typename T>
+ static inline T htog(T value) {return htole(value);}
+ template <typename T>
+ static inline T gtoh(T value) {return letoh(value);}
+}
+#endif // __SIM_BYTE_SWAP_HH__
diff --git a/sim/debug.cc b/src/sim/debug.cc
index 09e5346a8..09e5346a8 100644
--- a/sim/debug.cc
+++ b/src/sim/debug.cc
diff --git a/sim/debug.hh b/src/sim/debug.hh
index 75b261d80..75b261d80 100644
--- a/sim/debug.hh
+++ b/src/sim/debug.hh
diff --git a/src/sim/eventq.cc b/src/sim/eventq.cc
new file mode 100644
index 000000000..4bfd6face
--- /dev/null
+++ b/src/sim/eventq.cc
@@ -0,0 +1,258 @@
+/*
+ * Copyright (c) 2000-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 <assert.h>
+
+#include <iostream>
+#include <string>
+#include <vector>
+
+#include "cpu/smt.hh"
+#include "base/misc.hh"
+
+#include "sim/eventq.hh"
+#include "base/trace.hh"
+#include "sim/root.hh"
+
+using namespace std;
+
+//
+// Main Event Queue
+//
+// Events on this queue are processed at the *beginning* of each
+// cycle, before the pipeline simulation is performed.
+//
+EventQueue mainEventQueue("MainEventQueue");
+
+void
+EventQueue::insert(Event *event)
+{
+ if (head == NULL || event->when() < head->when() ||
+ (event->when() == head->when() &&
+ event->priority() <= head->priority())) {
+ event->next = head;
+ head = event;
+ } else {
+ Event *prev = head;
+ Event *curr = head->next;
+
+ while (curr) {
+ if (event->when() <= curr->when() &&
+ (event->when() < curr->when() ||
+ event->priority() <= curr->priority()))
+ break;
+
+ prev = curr;
+ curr = curr->next;
+ }
+
+ event->next = curr;
+ prev->next = event;
+ }
+}
+
+void
+EventQueue::remove(Event *event)
+{
+ if (head == NULL)
+ return;
+
+ if (head == event){
+ head = event->next;
+ return;
+ }
+
+ Event *prev = head;
+ Event *curr = head->next;
+ while (curr && curr != event) {
+ prev = curr;
+ curr = curr->next;
+ }
+
+ if (curr == event)
+ prev->next = curr->next;
+}
+
+void
+EventQueue::serviceOne()
+{
+ Event *event = head;
+ event->clearFlags(Event::Scheduled);
+ head = event->next;
+
+ // handle action
+ if (!event->squashed())
+ event->process();
+ else
+ event->clearFlags(Event::Squashed);
+
+ if (event->getFlags(Event::AutoDelete) && !event->scheduled())
+ delete event;
+}
+
+
+void
+Event::serialize(std::ostream &os)
+{
+ SERIALIZE_SCALAR(_when);
+ SERIALIZE_SCALAR(_priority);
+ SERIALIZE_ENUM(_flags);
+}
+
+
+void
+Event::unserialize(Checkpoint *cp, const string &section)
+{
+ if (scheduled())
+ deschedule();
+
+ UNSERIALIZE_SCALAR(_when);
+ UNSERIALIZE_SCALAR(_priority);
+
+ // need to see if original event was in a scheduled, unsquashed
+ // state, but don't want to restore those flags in the current
+ // object itself (since they aren't immediately true)
+ UNSERIALIZE_ENUM(_flags);
+ bool wasScheduled = (_flags & Scheduled) && !(_flags & Squashed);
+ _flags &= ~(Squashed | Scheduled);
+
+ if (wasScheduled) {
+ DPRINTF(Config, "rescheduling at %d\n", _when);
+ schedule(_when);
+ }
+}
+
+void
+EventQueue::serialize(ostream &os)
+{
+ std::list<Event *> eventPtrs;
+
+ int numEvents = 0;
+ Event *event = head;
+ while (event) {
+ if (event->getFlags(Event::AutoSerialize)) {
+ eventPtrs.push_back(event);
+ paramOut(os, csprintf("event%d", numEvents++), event->name());
+ }
+ event = event->next;
+ }
+
+ SERIALIZE_SCALAR(numEvents);
+
+ for (std::list<Event *>::iterator it=eventPtrs.begin();
+ it != eventPtrs.end(); ++it) {
+ (*it)->nameOut(os);
+ (*it)->serialize(os);
+ }
+}
+
+void
+EventQueue::unserialize(Checkpoint *cp, const std::string &section)
+{
+ int numEvents;
+ UNSERIALIZE_SCALAR(numEvents);
+
+ std::string eventName;
+ for (int i = 0; i < numEvents; i++) {
+ // get the pointer value associated with the event
+ paramIn(cp, section, csprintf("event%d", i), eventName);
+
+ // create the event based on its pointer value
+ Serializable::create(cp, eventName);
+ }
+}
+
+void
+EventQueue::dump()
+{
+ cprintf("============================================================\n");
+ cprintf("EventQueue Dump (cycle %d)\n", curTick);
+ cprintf("------------------------------------------------------------\n");
+
+ if (empty())
+ cprintf("<No Events>\n");
+ else {
+ Event *event = head;
+ while (event) {
+ event->dump();
+ event = event->next;
+ }
+ }
+
+ cprintf("============================================================\n");
+}
+
+extern "C"
+void
+dumpMainQueue()
+{
+ mainEventQueue.dump();
+}
+
+
+const char *
+Event::description()
+{
+ return "generic";
+}
+
+#if TRACING_ON
+void
+Event::trace(const char *action)
+{
+ // This DPRINTF is unconditional because calls to this function
+ // are protected by an 'if (DTRACE(Event))' in the inlined Event
+ // methods.
+ //
+ // This is just a default implementation for derived classes where
+ // it's not worth doing anything special. If you want to put a
+ // more informative message in the trace, override this method on
+ // the particular subclass where you have the information that
+ // needs to be printed.
+ DPRINTFN("%s event %s @ %d\n", description(), action, when());
+}
+#endif
+
+void
+Event::dump()
+{
+ cprintf("Event (%s)\n", description());
+ cprintf("Flags: %#x\n", _flags);
+#if TRACING_ON
+ cprintf("Created: %d\n", when_created);
+#endif
+ if (scheduled()) {
+#if TRACING_ON
+ cprintf("Scheduled at %d\n", when_scheduled);
+#endif
+ cprintf("Scheduled for %d, priority %d\n", when(), _priority);
+ }
+ else {
+ cprintf("Not Scheduled\n");
+ }
+}
diff --git a/sim/eventq.hh b/src/sim/eventq.hh
index 5fc73bb53..5fc73bb53 100644
--- a/sim/eventq.hh
+++ b/src/sim/eventq.hh
diff --git a/src/sim/faults.cc b/src/sim/faults.cc
new file mode 100644
index 000000000..cb095f852
--- /dev/null
+++ b/src/sim/faults.cc
@@ -0,0 +1,52 @@
+/*
+ * 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 "base/misc.hh"
+#include "sim/faults.hh"
+#include "cpu/exec_context.hh"
+#include "cpu/base.hh"
+
+#if !FULL_SYSTEM
+void FaultBase::invoke(ExecContext * xc)
+{
+ fatal("fault (%s) detected @ PC 0x%08p", name(), xc->readPC());
+}
+#else
+void FaultBase::invoke(ExecContext * xc)
+{
+ DPRINTF(Fault, "Fault %s at PC: %#x\n", name(), xc->readPC());
+ xc->getCpuPtr()->recordEvent(csprintf("Fault %s", name()));
+
+ assert(!xc->misspeculating());
+}
+#endif
+
+void UnimpFault::invoke(ExecContext * xc)
+{
+ panic("Unimpfault: %s\n", panicStr.c_str());
+}
diff --git a/src/sim/faults.hh b/src/sim/faults.hh
new file mode 100644
index 000000000..9b3bc9103
--- /dev/null
+++ b/src/sim/faults.hh
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2003-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __FAULTS_HH__
+#define __FAULTS_HH__
+
+#include "base/refcnt.hh"
+#include "sim/stats.hh"
+#include "config/full_system.hh"
+
+class ExecContext;
+class FaultBase;
+typedef RefCountingPtr<FaultBase> Fault;
+
+typedef const char * FaultName;
+typedef Stats::Scalar<> FaultStat;
+
+// Each class has it's name statically define in _name,
+// and has a virtual function to access it's name.
+// The function is necessary because otherwise, all objects
+// which are being accessed cast as a FaultBase * (namely
+// all faults returned using the Fault type) will use the
+// generic FaultBase name.
+
+class FaultBase : public RefCounted
+{
+ public:
+ virtual FaultName name() = 0;
+#if FULL_SYSTEM
+ virtual void invoke(ExecContext * xc);
+#else
+ virtual void invoke(ExecContext * xc);
+#endif
+// template<typename T>
+// bool isA() {return dynamic_cast<T *>(this);}
+ virtual bool isMachineCheckFault() {return false;}
+ virtual bool isAlignmentFault() {return false;}
+};
+
+FaultBase * const NoFault = 0;
+
+class UnimpFault : public FaultBase
+{
+ private:
+ std::string panicStr;
+ public:
+ UnimpFault(std::string _str)
+ : panicStr(_str)
+ { }
+
+ FaultName name() {return "Unimplemented simulator feature";}
+ void invoke(ExecContext * xc);
+};
+
+#endif // __FAULTS_HH__
diff --git a/src/sim/host.hh b/src/sim/host.hh
new file mode 100644
index 000000000..48c977331
--- /dev/null
+++ b/src/sim/host.hh
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2003-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * Defines host-dependent types:
+ * Counter, Tick, and (indirectly) {int,uint}{8,16,32,64}_t.
+ */
+
+#ifndef __HOST_HH__
+#define __HOST_HH__
+
+#include <inttypes.h>
+
+/** uint64_t constant */
+#define ULL(N) ((uint64_t)N##ULL)
+/** int64_t constant */
+#define LL(N) (((int64_t)N##LL)
+
+/** Statistics counter type. Not much excuse for not using a 64-bit
+ * integer here, but if you're desperate and only run short
+ * simulations you could make this 32 bits.
+ */
+typedef int64_t Counter;
+
+/**
+ * Clock cycle count type.
+ * @note using an unsigned breaks the cache.
+ */
+typedef int64_t Tick;
+
+/**
+ * Address type
+ * This will probably be moved somewhere else in the near future.
+ * This should be at least as big as the biggest address width in use
+ * in the system, which will probably be 64 bits.
+ */
+typedef uint64_t Addr;
+
+const Addr MaxAddr = (Addr)-1;
+
+#endif // __HOST_H__
diff --git a/src/sim/main.cc b/src/sim/main.cc
new file mode 100644
index 000000000..aecc171ed
--- /dev/null
+++ b/src/sim/main.cc
@@ -0,0 +1,433 @@
+/*
+ * Copyright (c) 2000-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 sim/main.cc
+///
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <libgen.h>
+#include <stdlib.h>
+#include <signal.h>
+
+#include <list>
+#include <string>
+#include <vector>
+
+#include "base/copyright.hh"
+#include "base/embedfile.hh"
+#include "base/inifile.hh"
+#include "base/misc.hh"
+#include "base/output.hh"
+#include "base/pollevent.hh"
+#include "base/statistics.hh"
+#include "base/str.hh"
+#include "base/time.hh"
+#include "cpu/base.hh"
+#include "cpu/smt.hh"
+#include "python/pyconfig.hh"
+#include "sim/async.hh"
+#include "sim/builder.hh"
+#include "sim/configfile.hh"
+#include "sim/host.hh"
+#include "sim/sim_events.hh"
+#include "sim/sim_exit.hh"
+#include "sim/sim_object.hh"
+#include "sim/stat_control.hh"
+#include "sim/stats.hh"
+#include "sim/root.hh"
+
+using namespace std;
+
+// See async.h.
+volatile bool async_event = false;
+volatile bool async_dump = false;
+volatile bool async_dumpreset = false;
+volatile bool async_exit = false;
+volatile bool async_io = false;
+volatile bool async_alarm = false;
+
+/// Stats signal handler.
+void
+dumpStatsHandler(int sigtype)
+{
+ async_event = true;
+ async_dump = true;
+}
+
+void
+dumprstStatsHandler(int sigtype)
+{
+ async_event = true;
+ async_dumpreset = true;
+}
+
+/// Exit signal handler.
+void
+exitNowHandler(int sigtype)
+{
+ async_event = true;
+ async_exit = true;
+}
+
+/// Abort signal handler.
+void
+abortHandler(int sigtype)
+{
+ cerr << "Program aborted at cycle " << curTick << endl;
+
+#if TRACING_ON
+ // dump trace buffer, if there is one
+ Trace::theLog.dump(cerr);
+#endif
+}
+
+/// Simulator executable name
+char *myProgName = "";
+
+/// Show brief help message.
+void
+showBriefHelp(ostream &out)
+{
+ char *prog = basename(myProgName);
+
+ ccprintf(out, "Usage:\n");
+ ccprintf(out,
+"%s [-d <dir>] [-E <var>[=<val>]] [-I <dir>] [-P <python>]\n"
+" [--<var>=<val>] <config file>\n"
+"\n"
+" -d set the output directory to <dir>\n"
+" -E set the environment variable <var> to <val> (or 'True')\n"
+" -I add the directory <dir> to python's path\n"
+" -P execute <python> directly in the configuration\n"
+" --var=val set the python variable <var> to '<val>'\n"
+" <configfile> config file name (ends in .py)\n\n",
+ prog);
+
+ ccprintf(out, "%s -X\n -X extract embedded files\n\n", prog);
+ ccprintf(out, "%s -h\n -h print short help\n\n", prog);
+}
+
+/// Print welcome message.
+void
+sayHello(ostream &out)
+{
+ extern const char *compileDate; // from date.cc
+
+ ccprintf(out, "M5 Simulator System\n");
+ // display copyright
+ ccprintf(out, "%s\n", briefCopyright);
+ ccprintf(out, "M5 compiled on %d\n", compileDate);
+
+ char *host = getenv("HOSTNAME");
+ if (!host)
+ host = getenv("HOST");
+
+ if (host)
+ ccprintf(out, "M5 executing on %s\n", host);
+
+ ccprintf(out, "M5 simulation started %s\n", Time::start);
+}
+
+///
+/// Echo the command line for posterity in such a way that it can be
+/// used to rerun the same simulation (given the same .ini files).
+///
+void
+echoCommandLine(int argc, char **argv, ostream &out)
+{
+ out << "command line: " << argv[0];
+ for (int i = 1; i < argc; i++) {
+ string arg(argv[i]);
+
+ out << ' ';
+
+ // If the arg contains spaces, we need to quote it.
+ // The rest of this is overkill to make it look purty.
+
+ // print dashes first outside quotes
+ int non_dash_pos = arg.find_first_not_of("-");
+ out << arg.substr(0, non_dash_pos); // print dashes
+ string body = arg.substr(non_dash_pos); // the rest
+
+ // if it's an assignment, handle the lhs & rhs separately
+ int eq_pos = body.find("=");
+ if (eq_pos == string::npos) {
+ out << quote(body);
+ }
+ else {
+ string lhs(body.substr(0, eq_pos));
+ string rhs(body.substr(eq_pos + 1));
+
+ out << quote(lhs) << "=" << quote(rhs);
+ }
+ }
+ out << endl << endl;
+}
+
+char *
+getOptionString(int &index, int argc, char **argv)
+{
+ char *option = argv[index] + 2;
+ if (*option != '\0')
+ return option;
+
+ // We didn't find an argument, it must be in the next variable.
+ if (++index >= argc)
+ panic("option string for option '%s' not found", argv[index - 1]);
+
+ return argv[index];
+}
+
+int
+main(int argc, char **argv)
+{
+ // Save off program name
+ myProgName = argv[0];
+
+ signal(SIGFPE, SIG_IGN); // may occur on misspeculated paths
+ signal(SIGTRAP, SIG_IGN);
+ signal(SIGUSR1, dumpStatsHandler); // dump intermediate stats
+ signal(SIGUSR2, dumprstStatsHandler); // dump and reset stats
+ signal(SIGINT, exitNowHandler); // dump final stats and exit
+ signal(SIGABRT, abortHandler);
+
+ bool configfile_found = false;
+ PythonConfig pyconfig;
+ string outdir;
+
+ if (argc < 2) {
+ showBriefHelp(cerr);
+ exit(1);
+ }
+
+ sayHello(cerr);
+
+ // Parse command-line options.
+ // Since most of the complex options are handled through the
+ // config database, we don't mess with getopts, and just parse
+ // manually.
+ for (int i = 1; i < argc; ++i) {
+ char *arg_str = argv[i];
+
+ // if arg starts with '--', parse as a special python option
+ // of the format --<python var>=<string value>, if the arg
+ // starts with '-', it should be a simulator option with a
+ // format similar to getopt. In any other case, treat the
+ // option as a configuration file name and load it.
+ if (arg_str[0] == '-' && arg_str[1] == '-') {
+ string str = &arg_str[2];
+ string var, val;
+
+ if (!split_first(str, var, val, '='))
+ panic("Could not parse configuration argument '%s'\n"
+ "Expecting --<variable>=<value>\n", arg_str);
+
+ pyconfig.setVariable(var, val);
+ } else if (arg_str[0] == '-') {
+ char *option;
+ string var, val;
+
+ // switch on second char
+ switch (arg_str[1]) {
+ case 'd':
+ outdir = getOptionString(i, argc, argv);
+ break;
+
+ case 'h':
+ showBriefHelp(cerr);
+ exit(1);
+
+ case 'E':
+ option = getOptionString(i, argc, argv);
+ if (!split_first(option, var, val, '='))
+ val = "True";
+
+ if (setenv(var.c_str(), val.c_str(), true) == -1)
+ panic("setenv: %s\n", strerror(errno));
+ break;
+
+ case 'I':
+ option = getOptionString(i, argc, argv);
+ pyconfig.addPath(option);
+ break;
+
+ case 'P':
+ option = getOptionString(i, argc, argv);
+ pyconfig.writeLine(option);
+ break;
+
+ case 'X': {
+ list<EmbedFile> lst;
+ EmbedMap::all(lst);
+ list<EmbedFile>::iterator i = lst.begin();
+ list<EmbedFile>::iterator end = lst.end();
+
+ while (i != end) {
+ cprintf("Embedded File: %s\n", i->name);
+ cout.write(i->data, i->length);
+ ++i;
+ }
+
+ return 0;
+ }
+
+ default:
+ showBriefHelp(cerr);
+ panic("invalid argument '%s'\n", arg_str);
+ }
+ } else {
+ string file(arg_str);
+ string base, ext;
+
+ if (!split_last(file, base, ext, '.') || ext != "py")
+ panic("Config file '%s' must end in '.py'\n", file);
+
+ pyconfig.load(file);
+ configfile_found = true;
+ }
+ }
+
+ if (outdir.empty()) {
+ char *env = getenv("OUTPUT_DIR");
+ outdir = env ? env : ".";
+ }
+
+ simout.setDirectory(outdir);
+
+ char *env = getenv("CONFIG_OUTPUT");
+ if (!env)
+ env = "config.out";
+ configStream = simout.find(env);
+
+ if (!configfile_found)
+ panic("no configuration file specified!");
+
+ // The configuration database is now complete; start processing it.
+ IniFile inifile;
+ if (!pyconfig.output(inifile))
+ panic("Error processing python code");
+
+ // Initialize statistics database
+ Stats::InitSimStats();
+
+ // Now process the configuration hierarchy and create the SimObjects.
+ ConfigHierarchy configHierarchy(inifile);
+ configHierarchy.build();
+ configHierarchy.createSimObjects();
+
+ // Parse and check all non-config-hierarchy parameters.
+ ParamContext::parseAllContexts(inifile);
+ ParamContext::checkAllContexts();
+
+ // Print hello message to stats file if it's actually a file. If
+ // it's not (i.e. it's cout or cerr) then we already did it above.
+ if (simout.isFile(*outputStream))
+ sayHello(*outputStream);
+
+ // Echo command line and all parameter settings to stats file as well.
+ 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();
+
+ // Restore checkpointed state, if any.
+ configHierarchy.unserializeSimObjects();
+
+ // Done processing the configuration database.
+ // Check for unreferenced entries.
+ if (inifile.printUnreferenced())
+ panic("unreferenced sections/entries in the intermediate ini file");
+
+ SimObject::regAllStats();
+
+ // uncomment the following to get PC-based execution-time profile
+#ifdef DO_PROFILE
+ init_profile((char *)&_init, (char *)&_fini);
+#endif
+
+ // Check to make sure that the stats package is properly initialized
+ Stats::check();
+
+ // Reset to put the stats in a consistent state.
+ Stats::reset();
+
+ warn("Entering event queue. Starting simulation...\n");
+ SimStartup();
+ while (!mainEventQueue.empty()) {
+ assert(curTick <= mainEventQueue.nextTick() &&
+ "event scheduled in the past");
+
+ // forward current cycle to the time of the first event on the
+ // queue
+ curTick = mainEventQueue.nextTick();
+ mainEventQueue.serviceOne();
+
+ if (async_event) {
+ async_event = false;
+ if (async_dump) {
+ async_dump = false;
+
+ using namespace Stats;
+ SetupEvent(Dump, curTick);
+ }
+
+ if (async_dumpreset) {
+ async_dumpreset = false;
+
+ using namespace Stats;
+ SetupEvent(Dump | Reset, curTick);
+ }
+
+ if (async_exit) {
+ async_exit = false;
+ new SimExitEvent("User requested STOP");
+ }
+
+ if (async_io || async_alarm) {
+ async_io = false;
+ async_alarm = false;
+ pollQueue.service();
+ }
+ }
+ }
+
+ // This should never happen... every conceivable way for the
+ // simulation to terminate (hit max cycles/insts, signal,
+ // simulated system halts/exits) generates an exit event, so we
+ // should never run out of events on the queue.
+ exitNow("no events on event loop! All CPUs must be idle.", 1);
+
+ return 0;
+}
diff --git a/src/sim/param.cc b/src/sim/param.cc
new file mode 100644
index 000000000..8998d7d77
--- /dev/null
+++ b/src/sim/param.cc
@@ -0,0 +1,793 @@
+/*
+ * 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 <algorithm>
+#include <cassert>
+#include <list>
+#include <string>
+#include <vector>
+
+#include "base/inifile.hh"
+#include "base/misc.hh"
+#include "base/range.hh"
+#include "base/str.hh"
+#include "base/trace.hh"
+#include "sim/config_node.hh"
+#include "sim/configfile.hh"
+#include "sim/param.hh"
+#include "sim/sim_object.hh"
+
+using namespace std;
+
+
+////////////////////////////////////////////////////////////////////////
+//
+// BaseParam member definitions
+//
+////////////////////////////////////////////////////////////////////////
+
+void
+BaseParam::die(const string &err) const
+{
+ context->printErrorProlog(cerr);
+ cerr << " parameter '" << name << "': "
+ << err << endl;
+ abort();
+}
+
+
+////////////////////////////////////////////////////////////////////////
+//
+// Param<T> and VectorParam<T> member definitions
+//
+// We implement parsing & displaying values for various parameter
+// types T using a set of overloaded functions:
+//
+// - parseParam(string s, T &value) parses s into value
+// - showParam(ostream &os, T &value) displays value on os
+//
+// By making these independent functions, we can reuse the same code
+// for type T in both Param<T> and VectorParam<T>.
+//
+// For enum types, the parseParam function requires additional
+// arguments, in which case we must specialize the Param<T>::parse and
+// VectorParam<T>::parse calls as well.
+//
+// Type-specific instances come first, followed by more generic
+// templated versions and their instantiations.
+//
+////////////////////////////////////////////////////////////////////////
+
+//
+// The base implementations use to_number for parsing and '<<' for
+// displaying, suitable for integer types.
+//
+template <class T>
+bool
+parseParam(const string &s, T &value)
+{
+ return to_number(s, value);
+}
+
+template <class T>
+void
+showParam(ostream &os, T const &value)
+{
+ os << value;
+}
+
+//
+// Template specializations:
+// - char (8-bit integer)
+// - floating-point types
+// - bool
+// - string
+//
+
+// Treat 8-bit ints (chars) as ints on output, not as chars
+template <>
+void
+showParam(ostream &os, const char &value)
+{
+ os << (int)value;
+}
+
+
+template <>
+void
+showParam(ostream &os, const unsigned char &value)
+{
+ os << (unsigned int)value;
+}
+
+
+// Use sscanf() for FP types as to_number() only handles integers
+template <>
+bool
+parseParam(const string &s, float &value)
+{
+ return (sscanf(s.c_str(), "%f", &value) == 1);
+}
+
+template <>
+bool
+parseParam(const string &s, double &value)
+{
+ return (sscanf(s.c_str(), "%lf", &value) == 1);
+}
+
+// Be flexible about what we take for bool
+template <>
+bool
+parseParam(const string &s, bool &value)
+{
+ const string &ls = to_lower(s);
+
+ if (ls == "true" || ls == "t" || ls == "yes" || ls == "y" || ls == "1") {
+ value = true;
+ return true;
+ }
+
+ if (ls == "false" || ls == "f" || ls == "no" || ls == "n" || ls == "0") {
+ value = false;
+ return true;
+ }
+
+ return false;
+}
+
+// Display bools as strings
+template <>
+void
+showParam(ostream &os, const bool &value)
+{
+ os << (value ? "true" : "false");
+}
+
+
+// String requires no processing to speak of
+template <>
+bool
+parseParam(const string &s, string &value)
+{
+ value = s;
+ return true;
+}
+
+template <>
+bool
+parseParam(const string &s, Range<uint32_t> &value)
+{
+ value = s;
+ return value.valid();
+}
+
+template <>
+bool
+parseParam(const string &s, Range<uint64_t> &value)
+{
+ value = s;
+ return value.valid();
+}
+
+//
+// End of parseParam/showParam definitions. Now we move on to
+// incorporate them into the Param/VectorParam parse() and showValue()
+// methods.
+//
+
+// These definitions for Param<T>::parse and VectorParam<T>::parse
+// work for any type for which parseParam() takes only two arguments
+// (i.e., all the fundamental types like int, bool, etc.), thanks to
+// overloading.
+template <class T>
+void
+Param<T>::parse(const string &s)
+{
+ if (parseParam(s, value)) {
+ wasSet = true;
+ }
+ else {
+ string err("could not parse \"");
+
+ err += s;
+ err += "\"";
+
+ die(err);
+ }
+}
+
+template <class T>
+void
+VectorParam<T>::parse(const string &s)
+{
+ if (s.empty()) {
+ wasSet = true;
+ return;
+ }
+
+ vector<string> tokens;
+
+ tokenize(tokens, s, ' ');
+
+ value.resize(tokens.size());
+
+ for (int i = 0; i < tokens.size(); i++) {
+ // need to parse into local variable to handle vector<bool>,
+ // for which operator[] returns a special reference class
+ // that's not the same as 'bool&', (since it's a packed
+ // vector)
+ T scalar_value;
+ if (!parseParam(tokens[i], scalar_value)) {
+ string err("could not parse \"");
+
+ err += s;
+ err += "\"";
+
+ die(err);
+ }
+
+ // assign parsed value to vector
+ value[i] = scalar_value;
+ }
+
+ wasSet = true;
+}
+
+// These definitions for Param<T>::showValue() and
+// VectorParam<T>::showValue() work for any type where showParam()
+// takes only two arguments (i.e., everything but the SimpleEnum and
+// MappedEnum classes).
+template <class T>
+void
+Param<T>::showValue(ostream &os) const
+{
+ showParam(os, value);
+}
+
+template <class T>
+void
+VectorParam<T>::showValue(ostream &os) const
+{
+ for (int i = 0; i < value.size(); i++) {
+ if (i != 0) {
+ os << " ";
+ }
+ showParam(os, value[i]);
+ }
+}
+
+
+#ifdef INSURE_BUILD
+#define INSTANTIATE_PARAM_TEMPLATES(type, typestr) \
+void Param<type>::showType(ostream &os) const { os << typestr; } \
+void VectorParam<type>::showType(ostream &os) const { \
+ os << "vector of " << typestr; \
+} \
+template Param<type>; \
+template VectorParam<type>;
+
+#else
+// instantiate all four methods (parse/show, scalar/vector) for basic
+// types that can use the above templates
+#define INSTANTIATE_PARAM_TEMPLATES(type, typestr) \
+template bool parseParam<type>(const string &s, type &value); \
+template void showParam<type>(ostream &os, type const &value); \
+template void Param<type>::parse(const string &); \
+template void VectorParam<type>::parse(const string &); \
+template void Param<type>::showValue(ostream &) const; \
+template void VectorParam<type>::showValue(ostream &) const; \
+template <> void Param<type>::showType(ostream &os) const { os << typestr; } \
+template <> void VectorParam<type>::showType(ostream &os) const { \
+ os << "vector of " << typestr; \
+}
+#endif
+
+INSTANTIATE_PARAM_TEMPLATES(unsigned long long, "ull")
+INSTANTIATE_PARAM_TEMPLATES(signed long long, "sll")
+INSTANTIATE_PARAM_TEMPLATES(unsigned long, "uns long")
+INSTANTIATE_PARAM_TEMPLATES(signed long, "long")
+INSTANTIATE_PARAM_TEMPLATES(unsigned int, "uns")
+INSTANTIATE_PARAM_TEMPLATES(signed int, "int")
+INSTANTIATE_PARAM_TEMPLATES(unsigned short, "uns short")
+INSTANTIATE_PARAM_TEMPLATES(signed short, "short")
+INSTANTIATE_PARAM_TEMPLATES(unsigned char, "uns char")
+INSTANTIATE_PARAM_TEMPLATES(signed char, "char")
+
+INSTANTIATE_PARAM_TEMPLATES(float, "float")
+INSTANTIATE_PARAM_TEMPLATES(double, "double")
+
+INSTANTIATE_PARAM_TEMPLATES(bool, "bool")
+INSTANTIATE_PARAM_TEMPLATES(string, "string")
+
+INSTANTIATE_PARAM_TEMPLATES(Range<uint64_t>, "uint64 range")
+INSTANTIATE_PARAM_TEMPLATES(Range<uint32_t>, "uint32 range")
+
+#undef INSTANTIATE_PARAM_TEMPLATES
+
+//
+// SimpleEnumParam & MappedEnumParam must specialize their parse(),
+// showValue(), and showType() methods.
+//
+
+//
+// SimpleEnumParam & SimpleEnumVectorParam
+//
+bool
+parseEnumParam(const char *const *map, const int num_values,
+ const string &s, int &value)
+{
+ for (int i = 0; i < num_values; ++i) {
+ if (s == map[i]) {
+ value = i;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void
+showEnumParam(ostream &os,
+ const char *const *map, const int num_values,
+ int value)
+{
+ assert(0 <= value && value < num_values);
+ os << map[value];
+}
+
+void
+showEnumType(ostream &os,
+ const char *const *map, const int num_values)
+{
+ os << "{" << map[0];
+ for (int i = 1; i < num_values; ++i)
+ os << "," << map[i];
+
+ os << "}";
+}
+
+
+//
+// MappedEnumParam & MappedEnumVectorParam
+//
+bool
+parseEnumParam(const EnumParamMap *map, const int num_values,
+ const string &s, int &value)
+{
+ for (int i = 0; i < num_values; ++i) {
+ if (s == map[i].name) {
+ value = map[i].value;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void
+showEnumParam(ostream &os,
+ const EnumParamMap *map, const int num_values,
+ int value)
+{
+ for (int i = 0; i < num_values; ++i) {
+ if (value == map[i].value) {
+ os << map[i].name;
+ return;
+ }
+ }
+
+ // if we can't find a reverse mapping just print the int value
+ os << value;
+}
+
+void
+showEnumType(ostream &os,
+ const EnumParamMap *map, const int num_values)
+{
+ os << "{" << map[0].name;
+ for (int i = 1; i < num_values; ++i)
+ os << "," << map[i].name;
+
+ os << "}";
+}
+
+
+template <class Map>
+void
+EnumParam<Map>::parse(const string &s)
+{
+ if (parseEnumParam(map, num_values, s, value)) {
+ wasSet = true;
+ } else {
+ string err("no match for enum string \"");
+
+ err += s;
+ err += "\"";
+
+ die(err);
+ }
+}
+
+template <class Map>
+void
+EnumVectorParam<Map>::parse(const string &s)
+{
+ vector<string> tokens;
+
+ if (s.empty()) {
+ wasSet = true;
+ return;
+ }
+
+ tokenize(tokens, s, ' ');
+
+ value.resize(tokens.size());
+
+ for (int i = 0; i < tokens.size(); i++) {
+ if (!parseEnumParam(map, num_values, tokens[i], value[i])) {
+ string err("no match for enum string \"");
+
+ err += s;
+ err += "\"";
+
+ die(err);
+ }
+ }
+
+ wasSet = true;
+}
+
+template <class Map>
+void
+EnumParam<Map>::showValue(ostream &os) const
+{
+ showEnumParam(os, map, num_values, value);
+}
+
+template <class Map>
+void
+EnumVectorParam<Map>::showValue(ostream &os) const
+{
+ for (int i = 0; i < value.size(); i++) {
+ if (i != 0) {
+ os << " ";
+ }
+ showEnumParam(os, map, num_values, value[i]);
+ }
+}
+
+template <class Map>
+void
+EnumParam<Map>::showType(ostream &os) const
+{
+ showEnumType(os, map, num_values);
+}
+
+template <class Map>
+void
+EnumVectorParam<Map>::showType(ostream &os) const
+{
+ os << "vector of";
+ showEnumType(os, map, num_values);
+}
+
+template class EnumParam<const char *>;
+template class EnumVectorParam<const char *>;
+
+template class EnumParam<EnumParamMap>;
+template class EnumVectorParam<EnumParamMap>;
+
+////////////////////////////////////////////////////////////////////////
+//
+// SimObjectBaseParam methods
+//
+////////////////////////////////////////////////////////////////////////
+
+bool
+parseSimObjectParam(ParamContext *context, const string &s, SimObject *&value)
+{
+ SimObject *obj;
+
+ if (to_lower(s) == "null") {
+ // explicitly set to null by user; assume that's OK
+ obj = NULL;
+ }
+ else {
+ obj = context->resolveSimObject(s);
+
+ if (obj == NULL)
+ return false;
+ }
+
+ value = obj;
+ return true;
+}
+
+
+void
+SimObjectBaseParam::showValue(ostream &os, SimObject *value) const
+{
+ os << (value ? value->name() : "null");
+}
+
+void
+SimObjectBaseParam::parse(const string &s, SimObject *&value)
+{
+ if (parseSimObjectParam(context, s, value)) {
+ wasSet = true;
+ }
+ else {
+ string err("could not resolve object name \"");
+
+ err += s;
+ err += "\"";
+
+ die(err);
+ }
+}
+
+void
+SimObjectBaseParam::parse(const string &s, vector<SimObject *>&value)
+{
+ vector<string> tokens;
+
+ tokenize(tokens, s, ' ');
+
+ value.resize(tokens.size());
+
+ for (int i = 0; i < tokens.size(); i++) {
+ if (!parseSimObjectParam(context, tokens[i], value[i])) {
+ string err("could not resolve object name \"");
+
+ err += s;
+ err += "\"";
+
+ die(err);
+ }
+ }
+
+ wasSet = true;
+}
+
+////////////////////////////////////////////////////////////////////////
+//
+// ParamContext member definitions
+//
+////////////////////////////////////////////////////////////////////////
+
+list<ParamContext *> *ParamContext::ctxList = NULL;
+
+ParamContext::ParamContext(const string &_iniSection, InitPhase _initPhase)
+ : iniFilePtr(NULL), // initialized on call to parseParams()
+ iniSection(_iniSection), paramList(NULL),
+ initPhase(_initPhase)
+{
+ // Put this context on global list for initialization
+ if (initPhase != NoAutoInit) {
+ if (ctxList == NULL)
+ ctxList = new list<ParamContext *>();
+
+ // keep list sorted by ascending initPhase values
+ list<ParamContext *>::iterator i = ctxList->begin();
+ list<ParamContext *>::iterator end = ctxList->end();
+ for (; i != end; ++i) {
+ if (initPhase <= (*i)->initPhase) {
+ // found where we want to insert
+ break;
+ }
+ }
+ // (fall through case: insert at end)
+ ctxList->insert(i, this);
+ }
+}
+
+
+void
+ParamContext::addParam(BaseParam *param)
+{
+ getParamList()->push_back(param);
+}
+
+
+void
+ParamContext::parseParams(IniFile &iniFile)
+{
+ iniFilePtr = &iniFile; // set object member
+
+ ParamList::iterator i;
+
+ for (i = getParamList()->begin(); i != getParamList()->end(); ++i) {
+ string string_value;
+
+ if (iniFile.find(iniSection, (*i)->name, string_value))
+ (*i)->parse(string_value);
+ }
+}
+
+
+// Check parameter values for validity & consistency. Default
+// implementation is no-op; derive subclass & override to add
+// actual functionality here.
+void
+ParamContext::checkParams()
+{
+ // nada
+}
+
+
+// Clean up context-related objects at end of execution. Default
+// implementation is no-op; derive subclass & override to add actual
+// functionality here.
+void
+ParamContext::cleanup()
+{
+ // nada
+}
+
+
+void
+ParamContext::describeParams(ostream &os)
+{
+ ParamList::iterator i;
+
+ for (i = getParamList()->begin(); i != getParamList()->end(); ++i) {
+ BaseParam *p = *i;
+
+ os << p->name << " (";
+ p->showType(os);
+ os << "): " << p->description << "\n";
+ }
+}
+
+
+
+void
+ParamContext::showParams(ostream &os)
+{
+ ParamList::iterator i;
+
+ for (i = getParamList()->begin(); i != getParamList()->end(); ++i) {
+ BaseParam *p = *i;
+
+ if (p->isValid()) {
+ os << p->name << "=";
+ p->showValue(os);
+ os << endl;
+ }
+ else {
+ os << "// "<< p->name << " not specified" << endl;
+ }
+ }
+}
+
+
+void
+ParamContext::printErrorProlog(ostream &os)
+{
+ os << "Parameter error in section [" << iniSection << "]: " << endl;
+}
+
+//
+// Resolve an object name to a SimObject pointer. The object will be
+// created as a side-effect if necessary. If the name contains a
+// colon (e.g., "iq:IQ"), then the object is local (invisible to
+// outside this context). If there is no colon, the name needs to be
+// resolved through the configuration hierarchy (only possible for
+// SimObjectBuilder objects, which return non-NULL for configNode()).
+//
+SimObject *
+ParamContext::resolveSimObject(const string &name)
+{
+ ConfigNode *n = getConfigNode();
+ return n ? n->resolveSimObject(name) : NULL;
+}
+
+
+//
+// static method: call parseParams() on all registered contexts
+//
+void
+ParamContext::parseAllContexts(IniFile &iniFile)
+{
+ list<ParamContext *>::iterator iter;
+
+ for (iter = ctxList->begin(); iter != ctxList->end(); ++iter) {
+ ParamContext *pc = *iter;
+
+ pc->parseParams(iniFile);
+ }
+}
+
+
+//
+// static method: call checkParams() on all registered contexts
+//
+void
+ParamContext::checkAllContexts()
+{
+ list<ParamContext *>::iterator iter;
+
+ for (iter = ctxList->begin(); iter != ctxList->end(); ++iter) {
+ ParamContext *pc = *iter;
+
+ pc->checkParams();
+ }
+}
+
+
+//
+// static method: call showParams() on all registered contexts
+//
+void
+ParamContext::showAllContexts(ostream &os)
+{
+ list<ParamContext *>::iterator iter;
+
+ for (iter = ctxList->begin(); iter != ctxList->end(); ++iter) {
+ ParamContext *pc = *iter;
+
+ os << "[" << pc->iniSection << "]" << endl;
+ pc->showParams(os);
+ os << endl;
+ }
+}
+
+
+//
+// static method: call cleanup() on all registered contexts
+//
+void
+ParamContext::cleanupAllContexts()
+{
+ list<ParamContext *>::iterator iter;
+
+ for (iter = ctxList->begin(); iter != ctxList->end(); ++iter) {
+ ParamContext *pc = *iter;
+
+ pc->cleanup();
+ }
+}
+
+
+//
+// static method: call describeParams() on all registered contexts
+//
+void
+ParamContext::describeAllContexts(ostream &os)
+{
+ list<ParamContext *>::iterator iter;
+
+ for (iter = ctxList->begin(); iter != ctxList->end(); ++iter) {
+ ParamContext *pc = *iter;
+
+ os << "[" << pc->iniSection << "]\n";
+ pc->describeParams(os);
+ os << endl;
+ }
+}
diff --git a/sim/param.hh b/src/sim/param.hh
index 4a1b8bda1..4a1b8bda1 100644
--- a/sim/param.hh
+++ b/src/sim/param.hh
diff --git a/src/sim/process.cc b/src/sim/process.cc
new file mode 100644
index 000000000..1da525093
--- /dev/null
+++ b/src/sim/process.cc
@@ -0,0 +1,361 @@
+/*
+ * 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 <unistd.h>
+#include <fcntl.h>
+
+#include <string>
+
+#include "base/intmath.hh"
+#include "base/loader/object_file.hh"
+#include "base/loader/symtab.hh"
+#include "base/statistics.hh"
+#include "config/full_system.hh"
+#include "cpu/exec_context.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 "sim/system.hh"
+
+using namespace std;
+using namespace TheISA;
+
+//
+// The purpose of this code is to fake the loader & syscall mechanism
+// when there's no OS: thus there's no resone to use it in FULL_SYSTEM
+// mode when we do have an OS
+//
+#if FULL_SYSTEM
+#error "process.cc not compatible with FULL_SYSTEM"
+#endif
+
+// current number of allocated processes
+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), system(_system)
+{
+ // initialize first 3 fds (stdin, stdout, stderr)
+ fd_map[STDIN_FILENO] = stdin_fd;
+ fd_map[STDOUT_FILENO] = stdout_fd;
+ fd_map[STDERR_FILENO] = stderr_fd;
+
+ // mark remaining fds as free
+ for (int i = 3; i <= MAX_FD; ++i) {
+ fd_map[i] = -1;
+ }
+
+ 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()
+{
+ using namespace Stats;
+
+ num_syscalls
+ .name(name() + ".PROG:num_syscalls")
+ .desc("Number of system calls")
+ ;
+}
+
+//
+// static helper functions
+//
+int
+Process::openInputFile(const string &filename)
+{
+ int fd = open(filename.c_str(), O_RDONLY);
+
+ if (fd == -1) {
+ perror(NULL);
+ cerr << "unable to open \"" << filename << "\" for reading\n";
+ fatal("can't open input file");
+ }
+
+ return fd;
+}
+
+
+int
+Process::openOutputFile(const string &filename)
+{
+ int fd = open(filename.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0774);
+
+ if (fd == -1) {
+ perror(NULL);
+ cerr << "unable to open \"" << filename << "\" for writing\n";
+ fatal("can't open output file");
+ }
+
+ return fd;
+}
+
+
+int
+Process::registerExecContext(ExecContext *xc)
+{
+ // add to list
+ int myIndex = execContexts.size();
+ execContexts.push_back(xc);
+
+ // return CPU number to caller
+ return myIndex;
+}
+
+void
+Process::startup()
+{
+ if (execContexts.empty())
+ 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("process init port", pTable, true);
+ mem_port->setPeer(initVirtMem);
+ initVirtMem->setPeer(mem_port);
+}
+
+void
+Process::replaceExecContext(ExecContext *xc, int xcIndex)
+{
+ if (xcIndex >= execContexts.size()) {
+ panic("replaceExecContext: bad xcIndex, %d >= %d\n",
+ xcIndex, execContexts.size());
+ }
+
+ execContexts[xcIndex] = xc;
+}
+
+// map simulator fd sim_fd to target fd tgt_fd
+void
+Process::dup_fd(int sim_fd, int tgt_fd)
+{
+ if (tgt_fd < 0 || tgt_fd > MAX_FD)
+ panic("Process::dup_fd tried to dup past MAX_FD (%d)", tgt_fd);
+
+ fd_map[tgt_fd] = sim_fd;
+}
+
+
+// generate new target fd for sim_fd
+int
+Process::alloc_fd(int sim_fd)
+{
+ // in case open() returns an error, don't allocate a new fd
+ if (sim_fd == -1)
+ return -1;
+
+ // find first free target fd
+ for (int free_fd = 0; free_fd < MAX_FD; ++free_fd) {
+ if (fd_map[free_fd] == -1) {
+ fd_map[free_fd] = sim_fd;
+ return free_fd;
+ }
+ }
+
+ panic("Process::alloc_fd: out of file descriptors!");
+}
+
+
+// free target fd (e.g., after close)
+void
+Process::free_fd(int tgt_fd)
+{
+ if (fd_map[tgt_fd] == -1)
+ warn("Process::free_fd: request to free unused fd %d", tgt_fd);
+
+ fd_map[tgt_fd] = -1;
+}
+
+
+// look up simulator fd for given target fd
+int
+Process::sim_fd(int tgt_fd)
+{
+ if (tgt_fd > MAX_FD)
+ return -1;
+
+ return fd_map[tgt_fd];
+}
+
+
+
+//
+// need to declare these here since there is no concrete Process type
+// that can be constructed (i.e., no REGISTER_SIM_OBJECT() macro call,
+// which is where these get declared for concrete types).
+//
+DEFINE_SIM_OBJECT_CLASS_NAME("Process", Process)
+
+
+////////////////////////////////////////////////////////////////////////
+//
+// LiveProcess member definitions
+//
+////////////////////////////////////////////////////////////////////////
+
+
+void
+copyStringArray(vector<string> &strings, Addr array_ptr, Addr data_ptr,
+ TranslatingPort* memPort)
+{
+ Addr data_ptr_swap;
+ for (int i = 0; i < strings.size(); ++i) {
+ data_ptr_swap = htog(data_ptr);
+ 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;
+
+ memPort->writeBlob(array_ptr, (uint8_t*)&data_ptr, sizeof(Addr));
+}
+
+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, _system, stdin_fd, stdout_fd, stderr_fd),
+ objFile(_objFile), argv(_argv), envp(_envp)
+{
+ prog_fname = argv[0];
+
+ // load up symbols, if any... these may be used for debugging or
+ // profiling.
+ if (!debugSymbolTable) {
+ debugSymbolTable = new SymbolTable();
+ if (!objFile->loadGlobalSymbols(debugSymbolTable) ||
+ !objFile->loadLocalSymbols(debugSymbolTable)) {
+ // didn't load any symbols
+ delete debugSymbolTable;
+ debugSymbolTable = NULL;
+ }
+ }
+}
+
+void
+LiveProcess::argsInit(int intSize, int pageSize)
+{
+ Process::startup();
+
+ // load object file into target memory
+ objFile->loadSections(initVirtMem);
+
+ // Calculate how much space we need for arg & env arrays.
+ 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;
+ }
+ int env_data_size = 0;
+ for (int i = 0; i < envp.size(); ++i) {
+ env_data_size += envp[i].size() + 1;
+ }
+
+ int space_needed =
+ argv_array_size + envp_array_size + arg_data_size + env_data_size;
+ // for SimpleScalar compatibility
+ if (space_needed < 16384)
+ space_needed = 16384;
+
+ // set bottom of stack
+ stack_min = stack_base - space_needed;
+ // align it
+ 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 + 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();
+ 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(int64_t callnum, ExecContext *xc)
+{
+ num_syscalls++;
+
+ SyscallDesc *desc = getDesc(callnum);
+ if (desc == NULL)
+ fatal("Syscall %d out of range", callnum);
+
+ desc->doSyscall(callnum, this, xc);
+}
+
+DEFINE_SIM_OBJECT_CLASS_NAME("LiveProcess", LiveProcess);
diff --git a/src/sim/process.hh b/src/sim/process.hh
new file mode 100644
index 000000000..807bf330f
--- /dev/null
+++ b/src/sim/process.hh
@@ -0,0 +1,192 @@
+/*
+ * 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 __PROCESS_HH__
+#define __PROCESS_HH__
+
+//
+// The purpose of this code is to fake the loader & syscall mechanism
+// when there's no OS: thus there's no reason to use it in FULL_SYSTEM
+// mode when we do have an OS.
+//
+#include "config/full_system.hh"
+
+#if !FULL_SYSTEM
+
+#include <vector>
+
+#include "base/statistics.hh"
+#include "sim/sim_object.hh"
+
+class CPUExecContext;
+class ExecContext;
+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
+{
+ 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.
+ bool initialContextLoaded;
+
+ // execution contexts associated with this process
+ std::vector<ExecContext *> execContexts;
+
+ // number of CPUs (esxec contexts, really) assigned to this process.
+ unsigned int numCpus() { return execContexts.size(); }
+
+ // record of blocked context
+ struct WaitRec
+ {
+ Addr waitChan;
+ ExecContext *waitingContext;
+
+ WaitRec(Addr chan, ExecContext *ctx)
+ : waitChan(chan), waitingContext(ctx)
+ { }
+ };
+
+ // list of all blocked contexts
+ std::list<WaitRec> waitList;
+
+ Addr brk_point; // top of the data segment
+
+ Addr stack_base; // stack segment base (highest address)
+ unsigned stack_size; // initial stack size
+ Addr stack_min; // lowest address accessed on the stack
+
+ // addr to use for next stack region (for multithreaded apps)
+ Addr next_thread_stack_base;
+
+ // Base of region for mmaps (when user doesn't specify an address).
+ Addr mmap_start;
+ Addr mmap_end;
+
+ // Base of region for nxm data
+ Addr nxm_start;
+ Addr nxm_end;
+
+ std::string prog_fname; // file name
+
+ Stats::Scalar<> num_syscalls; // number of syscalls executed
+
+
+ protected:
+ // constructor
+ Process(const std::string &nm,
+ System *_system,
+ int stdin_fd, // initial I/O descriptors
+ int stdout_fd,
+ int stderr_fd);
+
+ // post initialization startup
+ virtual void startup();
+
+ protected:
+ /// Memory object for initialization (image loading)
+ TranslatingPort *initVirtMem;
+
+ public:
+ PageTable *pTable;
+
+ private:
+ // file descriptor remapping support
+ static const int MAX_FD = 256; // max legal fd value
+ int fd_map[MAX_FD+1];
+
+ public:
+ // static helper functions to generate file descriptors for constructor
+ static int openInputFile(const std::string &filename);
+ static int openOutputFile(const std::string &filename);
+
+ // override of virtual SimObject method: register statistics
+ virtual void regStats();
+
+ // register an execution context for this process.
+ // returns xc's cpu number (index into execContexts[])
+ int registerExecContext(ExecContext *xc);
+
+
+ void replaceExecContext(ExecContext *xc, int xcIndex);
+
+ // map simulator fd sim_fd to target fd tgt_fd
+ void dup_fd(int sim_fd, int tgt_fd);
+
+ // generate new target fd for sim_fd
+ int alloc_fd(int sim_fd);
+
+ // free target fd (e.g., after close)
+ void free_fd(int tgt_fd);
+
+ // look up simulator fd for given target fd
+ int sim_fd(int tgt_fd);
+
+ virtual void syscall(int64_t callnum, ExecContext *xc) = 0;
+};
+
+//
+// "Live" process with system calls redirected to host system
+//
+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,
+ System *_system, int stdin_fd, int stdout_fd, int stderr_fd,
+ std::vector<std::string> &argv,
+ std::vector<std::string> &envp);
+
+ virtual void argsInit(int intSize, int pageSize);
+
+ public:
+ virtual void syscall(int64_t callnum, ExecContext *xc);
+
+ virtual SyscallDesc* getDesc(int callnum) = 0;
+};
+
+
+#endif // !FULL_SYSTEM
+
+#endif // __PROCESS_HH__
diff --git a/src/sim/pseudo_inst.cc b/src/sim/pseudo_inst.cc
new file mode 100644
index 000000000..12c076c08
--- /dev/null
+++ b/src/sim/pseudo_inst.cc
@@ -0,0 +1,290 @@
+/*
+ * Copyright (c) 2003-2006 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <string>
+
+#include "sim/pseudo_inst.hh"
+#include "arch/vtophys.hh"
+#include "cpu/base.hh"
+#include "cpu/sampler/sampler.hh"
+#include "cpu/exec_context.hh"
+#include "cpu/quiesce_event.hh"
+#include "kern/kernel_stats.hh"
+#include "sim/param.hh"
+#include "sim/serialize.hh"
+#include "sim/sim_exit.hh"
+#include "sim/stat_control.hh"
+#include "sim/stats.hh"
+#include "sim/system.hh"
+#include "sim/debug.hh"
+#include "sim/vptr.hh"
+
+using namespace std;
+
+extern Sampler *SampCPU;
+
+using namespace Stats;
+using namespace TheISA;
+
+namespace AlphaPseudo
+{
+ bool doStatisticsInsts;
+ bool doCheckpointInsts;
+ bool doQuiesce;
+
+ void
+ arm(ExecContext *xc)
+ {
+ if (xc->getKernelStats())
+ xc->getKernelStats()->arm();
+ }
+
+ void
+ quiesce(ExecContext *xc)
+ {
+ if (!doQuiesce)
+ return;
+
+ xc->suspend();
+ if (xc->getKernelStats())
+ xc->getKernelStats()->quiesce();
+ }
+
+ void
+ quiesceNs(ExecContext *xc, uint64_t ns)
+ {
+ if (!doQuiesce || ns == 0)
+ return;
+
+ EndQuiesceEvent *quiesceEvent = xc->getQuiesceEvent();
+
+ if (quiesceEvent->scheduled())
+ quiesceEvent->reschedule(curTick + Clock::Int::ns * ns);
+ else
+ quiesceEvent->schedule(curTick + Clock::Int::ns * ns);
+
+ xc->suspend();
+ if (xc->getKernelStats())
+ xc->getKernelStats()->quiesce();
+ }
+
+ void
+ quiesceCycles(ExecContext *xc, uint64_t cycles)
+ {
+ if (!doQuiesce || cycles == 0)
+ return;
+
+ EndQuiesceEvent *quiesceEvent = xc->getQuiesceEvent();
+
+ if (quiesceEvent->scheduled())
+ quiesceEvent->reschedule(curTick +
+ xc->getCpuPtr()->cycles(cycles));
+ else
+ quiesceEvent->schedule(curTick +
+ xc->getCpuPtr()->cycles(cycles));
+
+ xc->suspend();
+ if (xc->getKernelStats())
+ xc->getKernelStats()->quiesce();
+ }
+
+ uint64_t
+ quiesceTime(ExecContext *xc)
+ {
+ return (xc->readLastActivate() - xc->readLastSuspend()) / Clock::Int::ns;
+ }
+
+ void
+ ivlb(ExecContext *xc)
+ {
+ if (xc->getKernelStats())
+ xc->getKernelStats()->ivlb();
+ }
+
+ void
+ ivle(ExecContext *xc)
+ {
+ }
+
+ void
+ m5exit_old(ExecContext *xc)
+ {
+ SimExit(curTick, "m5_exit_old instruction encountered");
+ }
+
+ void
+ m5exit(ExecContext *xc, Tick delay)
+ {
+ Tick when = curTick + delay * Clock::Int::ns;
+ SimExit(when, "m5_exit instruction encountered");
+ }
+
+ void
+ resetstats(ExecContext *xc, Tick delay, Tick period)
+ {
+ if (!doStatisticsInsts)
+ return;
+
+
+ Tick when = curTick + delay * Clock::Int::ns;
+ Tick repeat = period * Clock::Int::ns;
+
+ using namespace Stats;
+ SetupEvent(Reset, when, repeat);
+ }
+
+ void
+ dumpstats(ExecContext *xc, Tick delay, Tick period)
+ {
+ if (!doStatisticsInsts)
+ return;
+
+
+ Tick when = curTick + delay * Clock::Int::ns;
+ Tick repeat = period * Clock::Int::ns;
+
+ using namespace Stats;
+ SetupEvent(Dump, when, repeat);
+ }
+
+ void
+ addsymbol(ExecContext *xc, Addr addr, Addr symbolAddr)
+ {
+ char symb[100];
+ CopyStringOut(xc, symb, symbolAddr, 100);
+ std::string symbol(symb);
+
+ DPRINTF(Loader, "Loaded symbol: %s @ %#llx\n", symbol, addr);
+
+ xc->getSystemPtr()->kernelSymtab->insert(addr,symbol);
+ }
+
+ void
+ dumpresetstats(ExecContext *xc, Tick delay, Tick period)
+ {
+ if (!doStatisticsInsts)
+ return;
+
+
+ Tick when = curTick + delay * Clock::Int::ns;
+ Tick repeat = period * Clock::Int::ns;
+
+ using namespace Stats;
+ SetupEvent(Dump|Reset, when, repeat);
+ }
+
+ void
+ m5checkpoint(ExecContext *xc, Tick delay, Tick period)
+ {
+ if (!doCheckpointInsts)
+ return;
+
+
+ Tick when = curTick + delay * Clock::Int::ns;
+ Tick repeat = period * Clock::Int::ns;
+
+ Checkpoint::setup(when, repeat);
+ }
+
+ uint64_t
+ readfile(ExecContext *xc, Addr vaddr, uint64_t len, uint64_t offset)
+ {
+ const string &file = xc->getCpuPtr()->system->params()->readfile;
+ if (file.empty()) {
+ return ULL(0);
+ }
+
+ uint64_t result = 0;
+
+ int fd = ::open(file.c_str(), O_RDONLY, 0);
+ if (fd < 0)
+ panic("could not open file %s\n", file);
+
+ if (::lseek(fd, offset, SEEK_SET) < 0)
+ panic("could not seek: %s", strerror(errno));
+
+ char *buf = new char[len];
+ char *p = buf;
+ while (len > 0) {
+ int bytes = ::read(fd, p, len);
+ if (bytes <= 0)
+ break;
+
+ p += bytes;
+ result += bytes;
+ len -= bytes;
+ }
+
+ close(fd);
+ CopyIn(xc, vaddr, buf, result);
+ delete [] buf;
+ return result;
+ }
+
+ class Context : public ParamContext
+ {
+ public:
+ Context(const string &section) : ParamContext(section) {}
+ void checkParams();
+ };
+
+ Context context("pseudo_inst");
+
+ Param<bool> __quiesce(&context, "quiesce",
+ "enable quiesce instructions",
+ true);
+ Param<bool> __statistics(&context, "statistics",
+ "enable statistics pseudo instructions",
+ true);
+ Param<bool> __checkpoint(&context, "checkpoint",
+ "enable checkpoint pseudo instructions",
+ true);
+
+ void
+ Context::checkParams()
+ {
+ doQuiesce = __quiesce;
+ doStatisticsInsts = __statistics;
+ doCheckpointInsts = __checkpoint;
+ }
+
+ void debugbreak(ExecContext *xc)
+ {
+ debug_break();
+ }
+
+ void switchcpu(ExecContext *xc)
+ {
+ if (SampCPU)
+ SampCPU->switchCPUs();
+ }
+}
diff --git a/sim/pseudo_inst.hh b/src/sim/pseudo_inst.hh
index 4dd427c99..4dd427c99 100644
--- a/sim/pseudo_inst.hh
+++ b/src/sim/pseudo_inst.hh
diff --git a/sim/root.cc b/src/sim/root.cc
index 6348ec104..6348ec104 100644
--- a/sim/root.cc
+++ b/src/sim/root.cc
diff --git a/sim/serialize.cc b/src/sim/serialize.cc
index c4ef124bb..c4ef124bb 100644
--- a/sim/serialize.cc
+++ b/src/sim/serialize.cc
diff --git a/sim/serialize.hh b/src/sim/serialize.hh
index d8f5f8fc5..d8f5f8fc5 100644
--- a/sim/serialize.hh
+++ b/src/sim/serialize.hh
diff --git a/sim/sim_events.cc b/src/sim/sim_events.cc
index c2bdca9df..c2bdca9df 100644
--- a/sim/sim_events.cc
+++ b/src/sim/sim_events.cc
diff --git a/sim/sim_events.hh b/src/sim/sim_events.hh
index c93914457..c93914457 100644
--- a/sim/sim_events.hh
+++ b/src/sim/sim_events.hh
diff --git a/sim/sim_exit.hh b/src/sim/sim_exit.hh
index f14256933..f14256933 100644
--- a/sim/sim_exit.hh
+++ b/src/sim/sim_exit.hh
diff --git a/src/sim/sim_object.cc b/src/sim/sim_object.cc
new file mode 100644
index 000000000..17d58ba4f
--- /dev/null
+++ b/src/sim/sim_object.cc
@@ -0,0 +1,258 @@
+/*
+ * 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 <assert.h>
+
+#include "base/callback.hh"
+#include "base/inifile.hh"
+#include "base/match.hh"
+#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"
+#include "sim/stats.hh"
+#include "sim/param.hh"
+
+using namespace std;
+
+
+////////////////////////////////////////////////////////////////////////
+//
+// SimObject member definitions
+//
+////////////////////////////////////////////////////////////////////////
+
+//
+// static list of all SimObjects, used for initialization etc.
+//
+SimObject::SimObjectList SimObject::simObjectList;
+
+namespace Stats {
+ extern ObjectMatch event_ignore;
+}
+
+//
+// SimObject constructor: used to maintain static simObjectList
+//
+SimObject::SimObject(Params *p)
+ : _params(p)
+{
+#ifdef DEBUG
+ doDebugBreak = false;
+#endif
+
+ doRecordEvent = !Stats::event_ignore.match(name());
+ simObjectList.push_back(this);
+}
+
+//
+// SimObject constructor: used to maintain static simObjectList
+//
+SimObject::SimObject(const string &_name)
+ : _params(new Params)
+{
+ _params->name = _name;
+#ifdef DEBUG
+ doDebugBreak = false;
+#endif
+
+ doRecordEvent = !Stats::event_ignore.match(name());
+ simObjectList.push_back(this);
+}
+
+void
+SimObject::connect()
+{
+}
+
+void
+SimObject::init()
+{
+}
+
+//
+// no default statistics, so nothing to do in base implementation
+//
+void
+SimObject::regStats()
+{
+}
+
+void
+SimObject::regFormulas()
+{
+}
+
+void
+SimObject::resetStats()
+{
+}
+
+//
+// static function:
+// call regStats() on all SimObjects and then regFormulas() on all
+// SimObjects.
+//
+struct SimObjectResetCB : public Callback
+{
+ virtual void process() { SimObject::resetAllStats(); }
+};
+
+namespace {
+ static SimObjectResetCB StatResetCB;
+}
+
+void
+SimObject::regAllStats()
+{
+ SimObjectList::iterator i;
+ SimObjectList::iterator end = simObjectList.end();
+
+ /**
+ * @todo change cprintfs to DPRINTFs
+ */
+ for (i = simObjectList.begin(); i != end; ++i) {
+#ifdef STAT_DEBUG
+ cprintf("registering stats for %s\n", (*i)->name());
+#endif
+ (*i)->regStats();
+ }
+
+ for (i = simObjectList.begin(); i != end; ++i) {
+#ifdef STAT_DEBUG
+ cprintf("registering formulas for %s\n", (*i)->name());
+#endif
+ (*i)->regFormulas();
+ }
+
+ Stats::registerResetCallback(&StatResetCB);
+}
+
+//
+// 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
+SimObject::initAll()
+{
+ SimObjectList::iterator i = simObjectList.begin();
+ SimObjectList::iterator end = simObjectList.end();
+
+ for (; i != end; ++i) {
+ SimObject *obj = *i;
+ obj->init();
+ }
+}
+
+//
+// static function: call resetStats() on all SimObjects.
+//
+void
+SimObject::resetAllStats()
+{
+ SimObjectList::iterator i = simObjectList.begin();
+ SimObjectList::iterator end = simObjectList.end();
+
+ for (; i != end; ++i) {
+ SimObject *obj = *i;
+ obj->resetStats();
+ }
+}
+
+//
+// static function: serialize all SimObjects.
+//
+void
+SimObject::serializeAll(ostream &os)
+{
+ SimObjectList::reverse_iterator ri = simObjectList.rbegin();
+ SimObjectList::reverse_iterator rend = simObjectList.rend();
+
+ for (; ri != rend; ++ri) {
+ SimObject *obj = *ri;
+ obj->nameOut(os);
+ obj->serialize(os);
+ }
+}
+
+#ifdef DEBUG
+//
+// static function: flag which objects should have the debugger break
+//
+void
+SimObject::debugObjectBreak(const string &objs)
+{
+ SimObjectList::const_iterator i = simObjectList.begin();
+ SimObjectList::const_iterator end = simObjectList.end();
+
+ ObjectMatch match(objs);
+ for (; i != end; ++i) {
+ SimObject *obj = *i;
+ obj->doDebugBreak = match.match(obj->name());
+ }
+}
+
+extern "C"
+void
+debugObjectBreak(const char *objs)
+{
+ SimObject::debugObjectBreak(string(objs));
+}
+#endif
+
+void
+SimObject::recordEvent(const std::string &stat)
+{
+ if (doRecordEvent)
+ Stats::recordEvent(stat);
+}
+
+void
+SimObject::drain(Serializer *serializer)
+{
+ serializer->signalDrained();
+}
+
+DEFINE_SIM_OBJECT_CLASS_NAME("SimObject", SimObject)
diff --git a/src/sim/sim_object.hh b/src/sim/sim_object.hh
new file mode 100644
index 000000000..76aba7ea1
--- /dev/null
+++ b/src/sim/sim_object.hh
@@ -0,0 +1,119 @@
+/*
+ * 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
+ * User Console Definitions
+ */
+
+#ifndef __SIM_OBJECT_HH__
+#define __SIM_OBJECT_HH__
+
+#include <map>
+#include <list>
+#include <vector>
+#include <iostream>
+
+#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
+ * config file (CPUs, caches, etc.).
+ */
+class SimObject : public Serializable, protected StartupCallback
+{
+ public:
+ struct Params {
+ std::string name;
+ };
+
+ protected:
+ Params *_params;
+
+ public:
+ const Params *params() const { return _params; }
+
+ private:
+ friend class Serializer;
+
+ typedef std::vector<SimObject *> SimObjectList;
+
+ // list of all instantiated simulation objects
+ static SimObjectList simObjectList;
+
+ public:
+ SimObject(Params *_params);
+ SimObject(const std::string &_name);
+
+ virtual ~SimObject() {}
+
+ virtual const std::string name() const { return params()->name; }
+
+ // 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();
+ virtual void regFormulas();
+ virtual void resetStats();
+
+ // static: call reg_stats on all SimObjects
+ static void regAllStats();
+
+ // static: call resetStats on all SimObjects
+ static void resetAllStats();
+
+ // 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;
+ static void debugObjectBreak(const std::string &objs);
+#endif
+
+ public:
+ bool doRecordEvent;
+ void recordEvent(const std::string &stat);
+};
+
+#endif // __SIM_OBJECT_HH__
diff --git a/sim/startup.cc b/src/sim/startup.cc
index 683e6c746..683e6c746 100644
--- a/sim/startup.cc
+++ b/src/sim/startup.cc
diff --git a/sim/startup.hh b/src/sim/startup.hh
index 3c9b654f1..3c9b654f1 100644
--- a/sim/startup.hh
+++ b/src/sim/startup.hh
diff --git a/sim/stat_control.cc b/src/sim/stat_control.cc
index 85c405b7f..85c405b7f 100644
--- a/sim/stat_control.cc
+++ b/src/sim/stat_control.cc
diff --git a/sim/stat_control.hh b/src/sim/stat_control.hh
index a22ce76af..a22ce76af 100644
--- a/sim/stat_control.hh
+++ b/src/sim/stat_control.hh
diff --git a/sim/stats.hh b/src/sim/stats.hh
index 8e97d041f..8e97d041f 100644
--- a/sim/stats.hh
+++ b/src/sim/stats.hh
diff --git a/src/sim/syscall_emul.cc b/src/sim/syscall_emul.cc
new file mode 100644
index 000000000..ed0da628e
--- /dev/null
+++ b/src/sim/syscall_emul.cc
@@ -0,0 +1,454 @@
+/*
+ * 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 <fcntl.h>
+#include <unistd.h>
+
+#include <string>
+#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"
+
+using namespace std;
+using namespace TheISA;
+
+void
+SyscallDesc::doSyscall(int callnum, Process *process, ExecContext *xc)
+{
+ 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, "%d: %s: syscall %s returns %d\n",
+ curTick,xc->getCpuPtr()->name(), name, retval.value());
+
+ if (!(flags & SyscallDesc::SuppressReturnValue))
+ xc->setSyscallReturn(retval);
+}
+
+
+SyscallReturn
+unimplementedFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+{
+ fatal("syscall %s (#%d) unimplemented.", desc->name, callnum);
+
+ return 1;
+}
+
+
+SyscallReturn
+ignoreFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+{
+ warn("ignoring syscall %s(%d, %d, ...)", desc->name,
+ xc->getSyscallArg(0), xc->getSyscallArg(1));
+
+ return 0;
+}
+
+
+SyscallReturn
+exitFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+{
+ new SimExitEvent("target called exit()", xc->getSyscallArg(0) & 0xff);
+
+ return 1;
+}
+
+
+SyscallReturn
+getpagesizeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
+{
+ return (int)VMPageSize;
+}
+
+
+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) {
+ 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;
+}
+
+
+SyscallReturn
+closeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
+{
+ int target_fd = xc->getSyscallArg(0);
+ int status = close(p->sim_fd(target_fd));
+ if (status >= 0)
+ p->free_fd(target_fd);
+ return status;
+}
+
+
+SyscallReturn
+readFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
+{
+ int fd = p->sim_fd(xc->getSyscallArg(0));
+ int nbytes = xc->getSyscallArg(2);
+ BufferArg bufArg(xc->getSyscallArg(1), nbytes);
+
+ int bytes_read = read(fd, bufArg.bufferPtr(), nbytes);
+
+ if (bytes_read != -1)
+ bufArg.copyOut(xc->getMemPort());
+
+ return bytes_read;
+}
+
+SyscallReturn
+writeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
+{
+ int fd = p->sim_fd(xc->getSyscallArg(0));
+ int nbytes = xc->getSyscallArg(2);
+ BufferArg bufArg(xc->getSyscallArg(1), nbytes);
+
+ bufArg.copyIn(xc->getMemPort());
+
+ int bytes_written = write(fd, bufArg.bufferPtr(), nbytes);
+
+ fsync(fd);
+
+ return bytes_written;
+}
+
+
+SyscallReturn
+lseekFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
+{
+ int fd = p->sim_fd(xc->getSyscallArg(0));
+ uint64_t offs = xc->getSyscallArg(1);
+ int whence = xc->getSyscallArg(2);
+
+ off_t result = lseek(fd, offs, whence);
+
+ return (result == (off_t)-1) ? -errno : result;
+}
+
+
+SyscallReturn
+munmapFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
+{
+ // given that we don't really implement mmap, munmap is really easy
+ return 0;
+}
+
+
+const char *hostname = "m5.eecs.umich.edu";
+
+SyscallReturn
+gethostnameFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
+{
+ int name_len = xc->getSyscallArg(1);
+ BufferArg name(xc->getSyscallArg(0), name_len);
+
+ strncpy((char *)name.bufferPtr(), hostname, name_len);
+
+ name.copyOut(xc->getMemPort());
+
+ return 0;
+}
+
+SyscallReturn
+unlinkFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
+{
+ string path;
+
+ if (!xc->getMemPort()->tryReadString(path, xc->getSyscallArg(0)))
+ return (TheISA::IntReg)-EFAULT;
+
+ int result = unlink(path.c_str());
+ return (result == -1) ? -errno : result;
+}
+
+SyscallReturn
+renameFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
+{
+ string old_name;
+
+ if (!xc->getMemPort()->tryReadString(old_name, xc->getSyscallArg(0)))
+ return -EFAULT;
+
+ string new_name;
+
+ if (!xc->getMemPort()->tryReadString(new_name, xc->getSyscallArg(1)))
+ return -EFAULT;
+
+ int64_t result = rename(old_name.c_str(), new_name.c_str());
+ return (result == -1) ? -errno : result;
+}
+
+SyscallReturn
+truncateFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
+{
+ string path;
+
+ if (!xc->getMemPort()->tryReadString(path, xc->getSyscallArg(0)))
+ return -EFAULT;
+
+ off_t length = xc->getSyscallArg(1);
+
+ int result = truncate(path.c_str(), length);
+ return (result == -1) ? -errno : result;
+}
+
+SyscallReturn
+ftruncateFunc(SyscallDesc *desc, int num, Process *process, ExecContext *xc)
+{
+ int fd = process->sim_fd(xc->getSyscallArg(0));
+
+ if (fd < 0)
+ return -EBADF;
+
+ off_t length = xc->getSyscallArg(1);
+
+ int result = ftruncate(fd, length);
+ return (result == -1) ? -errno : result;
+}
+
+SyscallReturn
+chownFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
+{
+ string path;
+
+ if (!xc->getMemPort()->tryReadString(path, xc->getSyscallArg(0)))
+ return -EFAULT;
+
+ /* XXX endianess */
+ uint32_t owner = xc->getSyscallArg(1);
+ uid_t hostOwner = owner;
+ uint32_t group = xc->getSyscallArg(2);
+ gid_t hostGroup = group;
+
+ int result = chown(path.c_str(), hostOwner, hostGroup);
+ return (result == -1) ? -errno : result;
+}
+
+SyscallReturn
+fchownFunc(SyscallDesc *desc, int num, Process *process, ExecContext *xc)
+{
+ int fd = process->sim_fd(xc->getSyscallArg(0));
+
+ if (fd < 0)
+ return -EBADF;
+
+ /* XXX endianess */
+ uint32_t owner = xc->getSyscallArg(1);
+ uid_t hostOwner = owner;
+ uint32_t group = xc->getSyscallArg(2);
+ gid_t hostGroup = group;
+
+ int result = fchown(fd, hostOwner, hostGroup);
+ return (result == -1) ? -errno : result;
+}
+
+
+SyscallReturn
+fcntlFunc(SyscallDesc *desc, int num, Process *process,
+ ExecContext *xc)
+{
+ int fd = xc->getSyscallArg(0);
+
+ if (fd < 0 || process->sim_fd(fd) < 0)
+ return -EBADF;
+
+ int cmd = xc->getSyscallArg(1);
+ switch (cmd) {
+ case 0: // F_DUPFD
+ // if we really wanted to support this, we'd need to do it
+ // in the target fd space.
+ warn("fcntl(%d, F_DUPFD) not supported, error returned\n", fd);
+ return -EMFILE;
+
+ case 1: // F_GETFD (get close-on-exec flag)
+ case 2: // F_SETFD (set close-on-exec flag)
+ return 0;
+
+ case 3: // F_GETFL (get file flags)
+ case 4: // F_SETFL (set file flags)
+ // not sure if this is totally valid, but we'll pass it through
+ // to the underlying OS
+ warn("fcntl(%d, %d) passed through to host\n", fd, cmd);
+ return fcntl(process->sim_fd(fd), cmd);
+ // return 0;
+
+ case 7: // F_GETLK (get lock)
+ case 8: // F_SETLK (set lock)
+ case 9: // F_SETLKW (set lock and wait)
+ // don't mess with file locking... just act like it's OK
+ warn("File lock call (fcntl(%d, %d)) ignored.\n", fd, cmd);
+ return 0;
+
+ default:
+ warn("Unknown fcntl command %d\n", cmd);
+ return 0;
+ }
+}
+
+SyscallReturn
+pipePseudoFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+{
+ int fds[2], sim_fds[2];
+ int pipe_retval = pipe(fds);
+
+ if (pipe_retval < 0) {
+ // error
+ return pipe_retval;
+ }
+
+ sim_fds[0] = process->alloc_fd(fds[0]);
+ sim_fds[1] = process->alloc_fd(fds[1]);
+
+ // Alpha Linux convention for pipe() is that fd[0] is returned as
+ // the return value of the function, and fd[1] is returned in r20.
+ xc->setIntReg(SyscallPseudoReturnReg, sim_fds[1]);
+ return sim_fds[0];
+}
+
+
+SyscallReturn
+getpidPseudoFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+{
+ // Make up a PID. There's no interprocess communication in
+ // fake_syscall mode, so there's no way for a process to know it's
+ // not getting a unique value.
+
+ xc->setIntReg(SyscallPseudoReturnReg, 99);
+ return 100;
+}
+
+
+SyscallReturn
+getuidPseudoFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+{
+ // Make up a UID and EUID... it shouldn't matter, and we want the
+ // simulation to be deterministic.
+
+ // EUID goes in r20.
+ xc->setIntReg(SyscallPseudoReturnReg, 100); //EUID
+ return 100; // UID
+}
+
+
+SyscallReturn
+getgidPseudoFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+{
+ // Get current group ID. EGID goes in r20.
+ xc->setIntReg(SyscallPseudoReturnReg, 100); //EGID
+ return 100;
+}
+
+
+SyscallReturn
+setuidFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+{
+ // can't fathom why a benchmark would call this.
+ warn("Ignoring call to setuid(%d)\n", xc->getSyscallArg(0));
+ return 0;
+}
+
+SyscallReturn
+getpidFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+{
+ // Make up a PID. There's no interprocess communication in
+ // fake_syscall mode, so there's no way for a process to know it's
+ // not getting a unique value.
+
+ xc->setIntReg(SyscallPseudoReturnReg, 99); //PID
+ return 100;
+}
+
+SyscallReturn
+getppidFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+{
+ return 99;
+}
+
+SyscallReturn
+getuidFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+{
+ return 100; // UID
+}
+
+SyscallReturn
+geteuidFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+{
+ return 100; // UID
+}
+
+SyscallReturn
+getgidFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+{
+ return 100;
+}
+
+SyscallReturn
+getegidFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+{
+ return 100;
+}
+
+
diff --git a/src/sim/syscall_emul.hh b/src/sim/syscall_emul.hh
new file mode 100644
index 000000000..00f016410
--- /dev/null
+++ b/src/sim/syscall_emul.hh
@@ -0,0 +1,849 @@
+/*
+ * 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 __SIM_SYSCALL_EMUL_HH__
+#define __SIM_SYSCALL_EMUL_HH__
+
+#define BSD_HOST (defined(__APPLE__) || defined(__OpenBSD__) || \
+ defined(__FreeBSD__))
+
+///
+/// @file syscall_emul.hh
+///
+/// This file defines objects used to emulate syscalls from the target
+/// application on the host machine.
+
+#include <errno.h>
+#include <string>
+#ifdef __CYGWIN32__
+#include <sys/fcntl.h> // for O_BINARY
+#endif
+#include <sys/uio.h>
+
+#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"
+
+///
+/// System call descriptor.
+///
+class SyscallDesc {
+
+ public:
+
+ /// Typedef for target syscall handler functions.
+ typedef SyscallReturn (*FuncPtr)(SyscallDesc *, int num,
+ Process *, ExecContext *);
+
+ const char *name; //!< Syscall name (e.g., "open").
+ FuncPtr funcPtr; //!< Pointer to emulation function.
+ int flags; //!< Flags (see Flags enum).
+
+ /// Flag values for controlling syscall behavior.
+ enum Flags {
+ /// Don't set return regs according to funcPtr return value.
+ /// Used for syscalls with non-standard return conventions
+ /// that explicitly set the ExecContext regs (e.g.,
+ /// sigreturn).
+ SuppressReturnValue = 1
+ };
+
+ /// Constructor.
+ SyscallDesc(const char *_name, FuncPtr _funcPtr, int _flags = 0)
+ : name(_name), funcPtr(_funcPtr), flags(_flags)
+ {
+ }
+
+ /// Emulate the syscall. Public interface for calling through funcPtr.
+ void doSyscall(int callnum, Process *proc, ExecContext *xc);
+};
+
+
+class BaseBufferArg {
+
+ public:
+
+ BaseBufferArg(Addr _addr, int _size) : addr(_addr), size(_size)
+ {
+ bufPtr = new uint8_t[size];
+ // clear out buffer: in case we only partially populate this,
+ // and then do a copyOut(), we want to make sure we don't
+ // introduce any random junk into the simulated address space
+ memset(bufPtr, 0, size);
+ }
+
+ virtual ~BaseBufferArg() { delete [] bufPtr; }
+
+ //
+ // copy data into simulator space (read from target memory)
+ //
+ virtual bool copyIn(TranslatingPort *memport)
+ {
+ 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(TranslatingPort *memport)
+ {
+ memport->writeBlob(addr, bufPtr, size);
+ return true; // no EFAULT detection for now
+ }
+
+ protected:
+ Addr addr;
+ int size;
+ uint8_t *bufPtr;
+};
+
+
+class BufferArg : public BaseBufferArg
+{
+ public:
+ BufferArg(Addr _addr, int _size) : BaseBufferArg(_addr, _size) { }
+ void *bufferPtr() { return bufPtr; }
+};
+
+template <class T>
+class TypedBufferArg : public BaseBufferArg
+{
+ public:
+ // user can optionally specify a specific number of bytes to
+ // allocate to deal with those structs that have variable-size
+ // arrays at the end
+ TypedBufferArg(Addr _addr, int _size = sizeof(T))
+ : BaseBufferArg(_addr, _size)
+ { }
+
+ // type case
+ operator T*() { return (T *)bufPtr; }
+
+ // dereference operators
+ T &operator*() { return *((T *)bufPtr); }
+ T* operator->() { return (T *)bufPtr; }
+ T &operator[](int i) { return ((T *)bufPtr)[i]; }
+};
+
+//////////////////////////////////////////////////////////////////////
+//
+// The following emulation functions are generic enough that they
+// don't need to be recompiled for different emulated OS's. They are
+// defined in sim/syscall_emul.cc.
+//
+//////////////////////////////////////////////////////////////////////
+
+
+/// Handler for unimplemented syscalls that we haven't thought about.
+SyscallReturn unimplementedFunc(SyscallDesc *desc, int num,
+ Process *p, ExecContext *xc);
+
+/// Handler for unimplemented syscalls that we never intend to
+/// implement (signal handling, etc.) and should not affect the correct
+/// behavior of the program. Print a warning only if the appropriate
+/// trace flag is enabled. Return success to the target program.
+SyscallReturn ignoreFunc(SyscallDesc *desc, int num,
+ Process *p, ExecContext *xc);
+
+/// Target exit() handler: terminate simulation.
+SyscallReturn exitFunc(SyscallDesc *desc, int num,
+ Process *p, ExecContext *xc);
+
+/// Target getpagesize() handler.
+SyscallReturn getpagesizeFunc(SyscallDesc *desc, int num,
+ Process *p, ExecContext *xc);
+
+/// Target obreak() handler: set brk address.
+SyscallReturn obreakFunc(SyscallDesc *desc, int num,
+ Process *p, ExecContext *xc);
+
+/// Target close() handler.
+SyscallReturn closeFunc(SyscallDesc *desc, int num,
+ Process *p, ExecContext *xc);
+
+/// Target read() handler.
+SyscallReturn readFunc(SyscallDesc *desc, int num,
+ Process *p, ExecContext *xc);
+
+/// Target write() handler.
+SyscallReturn writeFunc(SyscallDesc *desc, int num,
+ Process *p, ExecContext *xc);
+
+/// Target lseek() handler.
+SyscallReturn lseekFunc(SyscallDesc *desc, int num,
+ Process *p, ExecContext *xc);
+
+/// Target munmap() handler.
+SyscallReturn munmapFunc(SyscallDesc *desc, int num,
+ Process *p, ExecContext *xc);
+
+/// Target gethostname() handler.
+SyscallReturn gethostnameFunc(SyscallDesc *desc, int num,
+ Process *p, ExecContext *xc);
+
+/// Target unlink() handler.
+SyscallReturn unlinkFunc(SyscallDesc *desc, int num,
+ Process *p, ExecContext *xc);
+
+/// Target rename() handler.
+SyscallReturn renameFunc(SyscallDesc *desc, int num,
+ Process *p, ExecContext *xc);
+
+
+/// Target truncate() handler.
+SyscallReturn truncateFunc(SyscallDesc *desc, int num,
+ Process *p, ExecContext *xc);
+
+
+/// Target ftruncate() handler.
+SyscallReturn ftruncateFunc(SyscallDesc *desc, int num,
+ Process *p, ExecContext *xc);
+
+
+/// Target chown() handler.
+SyscallReturn chownFunc(SyscallDesc *desc, int num,
+ Process *p, ExecContext *xc);
+
+
+/// Target fchown() handler.
+SyscallReturn fchownFunc(SyscallDesc *desc, int num,
+ Process *p, ExecContext *xc);
+
+/// Target fnctl() handler.
+SyscallReturn fcntlFunc(SyscallDesc *desc, int num,
+ Process *process, ExecContext *xc);
+
+/// Target setuid() handler.
+SyscallReturn setuidFunc(SyscallDesc *desc, int num,
+ Process *p, ExecContext *xc);
+
+/// Target getpid() handler.
+SyscallReturn getpidFunc(SyscallDesc *desc, int num,
+ Process *p, ExecContext *xc);
+
+/// Target getuid() handler.
+SyscallReturn getuidFunc(SyscallDesc *desc, int num,
+ Process *p, ExecContext *xc);
+
+/// Target getgid() handler.
+SyscallReturn getgidFunc(SyscallDesc *desc, int num,
+ Process *p, ExecContext *xc);
+
+/// Target getppid() handler.
+SyscallReturn getppidFunc(SyscallDesc *desc, int num,
+ Process *p, ExecContext *xc);
+
+/// Target geteuid() handler.
+SyscallReturn geteuidFunc(SyscallDesc *desc, int num,
+ Process *p, ExecContext *xc);
+
+/// Target getegid() handler.
+SyscallReturn getegidFunc(SyscallDesc *desc, int num,
+ Process *p, ExecContext *xc);
+
+
+
+/// Pseudo Funcs - These functions use a different return convension,
+/// returning a second value in a register other than the normal return register
+SyscallReturn pipePseudoFunc(SyscallDesc *desc, int num,
+ Process *process, ExecContext *xc);
+
+/// Target getpidPseudo() handler.
+SyscallReturn getpidPseudoFunc(SyscallDesc *desc, int num,
+ Process *p, ExecContext *xc);
+
+/// Target getuidPseudo() handler.
+SyscallReturn getuidPseudoFunc(SyscallDesc *desc, int num,
+ Process *p, ExecContext *xc);
+
+/// Target getgidPseudo() handler.
+SyscallReturn getgidPseudoFunc(SyscallDesc *desc, int num,
+ Process *p, ExecContext *xc);
+
+
+/// This struct is used to build an target-OS-dependent table that
+/// maps the target's open() flags to the host open() flags.
+struct OpenFlagTransTable {
+ int tgtFlag; //!< Target system flag value.
+ int hostFlag; //!< Corresponding host system flag value.
+};
+
+
+
+/// A readable name for 1,000,000, for converting microseconds to seconds.
+const int one_million = 1000000;
+
+/// Approximate seconds since the epoch (1/1/1970). About a billion,
+/// by my reckoning. We want to keep this a constant (not use the
+/// real-world time) to keep simulations repeatable.
+const unsigned seconds_since_epoch = 1000000000;
+
+/// Helper function to convert current elapsed time to seconds and
+/// microseconds.
+template <class T1, class T2>
+void
+getElapsedTime(T1 &sec, T2 &usec)
+{
+ int elapsed_usecs = curTick / Clock::Int::us;
+ sec = elapsed_usecs / one_million;
+ usec = elapsed_usecs % one_million;
+}
+
+//////////////////////////////////////////////////////////////////////
+//
+// The following emulation functions are generic, but need to be
+// templated to account for differences in types, constants, etc.
+//
+//////////////////////////////////////////////////////////////////////
+
+/// Target ioctl() handler. For the most part, programs call ioctl()
+/// only to find out if their stdout is a tty, to determine whether to
+/// do line or block buffering.
+template <class OS>
+SyscallReturn
+ioctlFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+{
+ int fd = xc->getSyscallArg(0);
+ unsigned req = xc->getSyscallArg(1);
+
+ DPRINTF(SyscallVerbose, "ioctl(%d, 0x%x, ...)\n", fd, req);
+
+ if (fd < 0 || process->sim_fd(fd) < 0) {
+ // doesn't map to any simulator fd: not a valid target fd
+ return -EBADF;
+ }
+
+ switch (req) {
+ case OS::TIOCISATTY:
+ case OS::TIOCGETP:
+ case OS::TIOCSETP:
+ case OS::TIOCSETN:
+ case OS::TIOCSETC:
+ case OS::TIOCGETC:
+ case OS::TIOCGETS:
+ case OS::TIOCGETA:
+ return -ENOTTY;
+
+ default:
+ fatal("Unsupported ioctl call: ioctl(%d, 0x%x, ...) @ 0x%llx\n",
+ fd, req, xc->readPC());
+ }
+}
+
+/// Target open() handler.
+template <class OS>
+SyscallReturn
+openFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+{
+ std::string path;
+
+ if (!xc->getMemPort()->tryReadString(path, xc->getSyscallArg(0)))
+ return -EFAULT;
+
+ if (path == "/dev/sysdev0") {
+ // This is a memory-mapped high-resolution timer device on Alpha.
+ // We don't support it, so just punt.
+ warn("Ignoring open(%s, ...)\n", path);
+ return -ENOENT;
+ }
+
+ int tgtFlags = xc->getSyscallArg(1);
+ int mode = xc->getSyscallArg(2);
+ int hostFlags = 0;
+
+ // translate open flags
+ for (int i = 0; i < OS::NUM_OPEN_FLAGS; i++) {
+ if (tgtFlags & OS::openFlagTable[i].tgtFlag) {
+ tgtFlags &= ~OS::openFlagTable[i].tgtFlag;
+ hostFlags |= OS::openFlagTable[i].hostFlag;
+ }
+ }
+
+ // any target flags left?
+ if (tgtFlags != 0)
+ warn("Syscall: open: cannot decode flags 0x%x", tgtFlags);
+
+#ifdef __CYGWIN32__
+ hostFlags |= O_BINARY;
+#endif
+
+ DPRINTF(SyscallVerbose, "opening file %s\n", path.c_str());
+
+ // open the file
+ int fd = open(path.c_str(), hostFlags, mode);
+
+ return (fd == -1) ? -errno : process->alloc_fd(fd);
+}
+
+
+/// Target chmod() handler.
+template <class OS>
+SyscallReturn
+chmodFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+{
+ std::string path;
+
+ if (!xc->getMemPort()->tryReadString(path, xc->getSyscallArg(0)))
+ return -EFAULT;
+
+ uint32_t mode = xc->getSyscallArg(1);
+ mode_t hostMode = 0;
+
+ // XXX translate mode flags via OS::something???
+ hostMode = mode;
+
+ // do the chmod
+ int result = chmod(path.c_str(), hostMode);
+ if (result < 0)
+ return -errno;
+
+ return 0;
+}
+
+
+/// Target fchmod() handler.
+template <class OS>
+SyscallReturn
+fchmodFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+{
+ int fd = xc->getSyscallArg(0);
+ if (fd < 0 || process->sim_fd(fd) < 0) {
+ // doesn't map to any simulator fd: not a valid target fd
+ return -EBADF;
+ }
+
+ uint32_t mode = xc->getSyscallArg(1);
+ mode_t hostMode = 0;
+
+ // XXX translate mode flags via OS::someting???
+ hostMode = mode;
+
+ // do the fchmod
+ int result = fchmod(process->sim_fd(fd), hostMode);
+ if (result < 0)
+ return -errno;
+
+ return 0;
+}
+
+
+/// Target stat() handler.
+template <class OS>
+SyscallReturn
+statFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+{
+ std::string path;
+
+ if (!xc->getMemPort()->tryReadString(path, xc->getSyscallArg(0)))
+ return -EFAULT;
+
+ struct stat hostBuf;
+ int result = stat(path.c_str(), &hostBuf);
+
+ if (result < 0)
+ return -errno;
+
+ OS::copyOutStatBuf(xc->getMemPort(), xc->getSyscallArg(1), &hostBuf);
+
+ return 0;
+}
+
+
+/// Target fstat64() handler.
+template <class OS>
+SyscallReturn
+fstat64Func(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+{
+ int fd = xc->getSyscallArg(0);
+ if (fd < 0 || process->sim_fd(fd) < 0) {
+ // doesn't map to any simulator fd: not a valid target fd
+ return -EBADF;
+ }
+
+#if BSD_HOST
+ struct stat hostBuf;
+ int result = fstat(process->sim_fd(fd), &hostBuf);
+#else
+ struct stat64 hostBuf;
+ int result = fstat64(process->sim_fd(fd), &hostBuf);
+#endif
+
+ if (result < 0)
+ return -errno;
+
+ OS::copyOutStat64Buf(xc->getMemPort(), fd, xc->getSyscallArg(1), &hostBuf);
+
+ return 0;
+}
+
+
+/// Target lstat() handler.
+template <class OS>
+SyscallReturn
+lstatFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+{
+ std::string path;
+
+ if (!xc->getMemPort()->tryReadString(path, xc->getSyscallArg(0)))
+ return -EFAULT;
+
+ struct stat hostBuf;
+ int result = lstat(path.c_str(), &hostBuf);
+
+ if (result < 0)
+ return -errno;
+
+ OS::copyOutStatBuf(xc->getMemPort(), xc->getSyscallArg(1), &hostBuf);
+
+ return 0;
+}
+
+/// Target lstat64() handler.
+template <class OS>
+SyscallReturn
+lstat64Func(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+{
+ std::string path;
+
+ if (!xc->getMemPort()->tryReadString(path, xc->getSyscallArg(0)))
+ return -EFAULT;
+
+#if BSD_HOST
+ struct stat hostBuf;
+ int result = lstat(path.c_str(), &hostBuf);
+#else
+ struct stat64 hostBuf;
+ int result = lstat64(path.c_str(), &hostBuf);
+#endif
+
+ if (result < 0)
+ return -errno;
+
+ OS::copyOutStat64Buf(xc->getMemPort(), -1, xc->getSyscallArg(1), &hostBuf);
+
+ return 0;
+}
+
+/// Target fstat() handler.
+template <class OS>
+SyscallReturn
+fstatFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+{
+ int fd = process->sim_fd(xc->getSyscallArg(0));
+
+ DPRINTF(SyscallVerbose, "fstat(%d, ...)\n", fd);
+
+ if (fd < 0)
+ return -EBADF;
+
+ struct stat hostBuf;
+ int result = fstat(fd, &hostBuf);
+
+ if (result < 0)
+ return -errno;
+
+ OS::copyOutStatBuf(xc->getMemPort(), xc->getSyscallArg(1), &hostBuf);
+
+ return 0;
+}
+
+
+/// Target statfs() handler.
+template <class OS>
+SyscallReturn
+statfsFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+{
+ std::string path;
+
+ if (!xc->getMemPort()->tryReadString(path, xc->getSyscallArg(0)))
+ return -EFAULT;
+
+ struct statfs hostBuf;
+ int result = statfs(path.c_str(), &hostBuf);
+
+ if (result < 0)
+ return -errno;
+
+ OS::copyOutStatfsBuf(xc->getMemPort(), xc->getSyscallArg(1), &hostBuf);
+
+ return 0;
+}
+
+
+/// Target fstatfs() handler.
+template <class OS>
+SyscallReturn
+fstatfsFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+{
+ int fd = process->sim_fd(xc->getSyscallArg(0));
+
+ if (fd < 0)
+ return -EBADF;
+
+ struct statfs hostBuf;
+ int result = fstatfs(fd, &hostBuf);
+
+ if (result < 0)
+ return -errno;
+
+ OS::copyOutStatfsBuf(xc->getMemPort(), xc->getSyscallArg(1), &hostBuf);
+
+ return 0;
+}
+
+
+/// Target writev() handler.
+template <class OS>
+SyscallReturn
+writevFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+{
+ int fd = xc->getSyscallArg(0);
+ if (fd < 0 || process->sim_fd(fd) < 0) {
+ // doesn't map to any simulator fd: not a valid target fd
+ 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;
+
+ 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];
+ 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);
+
+ for (int i = 0; i < count; ++i)
+ {
+ delete [] (char *)hiov[i].iov_base;
+ }
+
+ if (result < 0)
+ return -errno;
+
+ return 0;
+}
+
+
+/// Target mmap() handler.
+///
+/// We don't really handle mmap(). If the target is mmaping an
+/// anonymous region or /dev/zero, we can get away with doing basically
+/// nothing (since memory is initialized to zero and the simulator
+/// doesn't really check addresses anyway). Always print a warning,
+/// since this could be seriously broken if we're not mapping
+/// /dev/zero.
+//
+/// Someday we should explicitly check for /dev/zero in open, flag the
+/// file descriptor, and fail (or implement!) a non-anonymous mmap to
+/// anything else.
+template <class OS>
+SyscallReturn
+mmapFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
+{
+ Addr start = xc->getSyscallArg(0);
+ uint64_t length = xc->getSyscallArg(1);
+ // int prot = xc->getSyscallArg(2);
+ int flags = xc->getSyscallArg(3);
+ // int fd = p->sim_fd(xc->getSyscallArg(4));
+ // int offset = xc->getSyscallArg(5);
+
+ 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));
+ }
+
+ return start;
+}
+
+/// Target getrlimit() handler.
+template <class OS>
+SyscallReturn
+getrlimitFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+{
+ unsigned resource = xc->getSyscallArg(0);
+ TypedBufferArg<typename OS::rlimit> rlp(xc->getSyscallArg(1));
+
+ switch (resource) {
+ case OS::TGT_RLIMIT_STACK:
+ // max stack size in bytes: make up a number (2MB for now)
+ rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024;
+ rlp->rlim_cur = htog(rlp->rlim_cur);
+ rlp->rlim_max = htog(rlp->rlim_max);
+ break;
+
+ default:
+ std::cerr << "getrlimitFunc: unimplemented resource " << resource
+ << std::endl;
+ abort();
+ break;
+ }
+
+ rlp.copyOut(xc->getMemPort());
+ return 0;
+}
+
+/// Target gettimeofday() handler.
+template <class OS>
+SyscallReturn
+gettimeofdayFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+{
+ TypedBufferArg<typename OS::timeval> tp(xc->getSyscallArg(0));
+
+ getElapsedTime(tp->tv_sec, tp->tv_usec);
+ tp->tv_sec += seconds_since_epoch;
+ tp->tv_sec = htog(tp->tv_sec);
+ tp->tv_usec = htog(tp->tv_usec);
+
+ tp.copyOut(xc->getMemPort());
+
+ return 0;
+}
+
+
+/// Target utimes() handler.
+template <class OS>
+SyscallReturn
+utimesFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+{
+ std::string path;
+
+ if (!xc->getMemPort()->tryReadString(path, xc->getSyscallArg(0)))
+ return -EFAULT;
+
+ TypedBufferArg<typename OS::timeval [2]> tp(xc->getSyscallArg(1));
+ tp.copyIn(xc->getMemPort());
+
+ struct timeval hostTimeval[2];
+ for (int i = 0; i < 2; ++i)
+ {
+ hostTimeval[i].tv_sec = gtoh((*tp)[i].tv_sec);
+ hostTimeval[i].tv_usec = gtoh((*tp)[i].tv_usec);
+ }
+ int result = utimes(path.c_str(), hostTimeval);
+
+ if (result < 0)
+ return -errno;
+
+ return 0;
+}
+/// Target getrusage() function.
+template <class OS>
+SyscallReturn
+getrusageFunc(SyscallDesc *desc, int callnum, Process *process,
+ ExecContext *xc)
+{
+ int who = xc->getSyscallArg(0); // THREAD, SELF, or CHILDREN
+ TypedBufferArg<typename OS::rusage> rup(xc->getSyscallArg(1));
+
+ if (who != OS::TGT_RUSAGE_SELF) {
+ // don't really handle THREAD or CHILDREN, but just warn and
+ // plow ahead
+ warn("getrusage() only supports RUSAGE_SELF. Parameter %d ignored.",
+ who);
+ }
+
+ getElapsedTime(rup->ru_utime.tv_sec, rup->ru_utime.tv_usec);
+ rup->ru_utime.tv_sec = htog(rup->ru_utime.tv_sec);
+ rup->ru_utime.tv_usec = htog(rup->ru_utime.tv_usec);
+
+ rup->ru_stime.tv_sec = 0;
+ rup->ru_stime.tv_usec = 0;
+ rup->ru_maxrss = 0;
+ rup->ru_ixrss = 0;
+ rup->ru_idrss = 0;
+ rup->ru_isrss = 0;
+ rup->ru_minflt = 0;
+ rup->ru_majflt = 0;
+ rup->ru_nswap = 0;
+ rup->ru_inblock = 0;
+ rup->ru_oublock = 0;
+ rup->ru_msgsnd = 0;
+ rup->ru_msgrcv = 0;
+ rup->ru_nsignals = 0;
+ rup->ru_nvcsw = 0;
+ rup->ru_nivcsw = 0;
+
+ rup.copyOut(xc->getMemPort());
+
+ return 0;
+}
+
+
+
+
+#endif // __SIM_SYSCALL_EMUL_HH__
diff --git a/src/sim/system.cc b/src/sim/system.cc
new file mode 100644
index 000000000..89f39491e
--- /dev/null
+++ b/src/sim/system.cc
@@ -0,0 +1,267 @@
+#include "arch/isa_traits.hh"
+#include "base/loader/object_file.hh"
+#include "base/loader/symtab.hh"
+#include "base/trace.hh"
+#include "cpu/exec_context.hh"
+#include "mem/mem_object.hh"
+#include "mem/physical.hh"
+#include "sim/builder.hh"
+#include "sim/byteswap.hh"
+#include "sim/system.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;
+
+vector<System *> System::systemList;
+
+int System::numSystemsRunning = 0;
+
+System::System(Params *p)
+ : SimObject(p->name), physmem(p->physmem), numcpus(0),
+#if FULL_SYSTEM
+ init_param(p->init_param),
+ functionalPort(p->name + "-fport"),
+ virtPort(p->name + "-vport"),
+#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
+ */
+ // Load kernel code
+ kernel = createObjectFile(params()->kernel_path);
+ if (kernel == NULL)
+ fatal("Could not load kernel file %s", params()->kernel_path);
+
+ // Load program sections into memory
+ kernel->loadSections(&functionalPort, LoadAddrMask);
+
+ // setup entry points
+ kernelStart = kernel->textBase();
+ kernelEnd = kernel->bssBase() + kernel->bssSize();
+ kernelEntry = kernel->entryPoint();
+
+ // load symbols
+ if (!kernel->loadGlobalSymbols(kernelSymtab))
+ panic("could not load kernel symbols\n");
+
+ if (!kernel->loadLocalSymbols(kernelSymtab))
+ panic("could not load kernel local symbols\n");
+
+ if (!kernel->loadGlobalSymbols(debugSymbolTable))
+ panic("could not load kernel symbols\n");
+
+ if (!kernel->loadLocalSymbols(debugSymbolTable))
+ panic("could not load kernel local symbols\n");
+
+ DPRINTF(Loader, "Kernel start = %#x\n", kernelStart);
+ DPRINTF(Loader, "Kernel end = %#x\n", kernelEnd);
+ DPRINTF(Loader, "Kernel entry = %#x\n", kernelEntry);
+ DPRINTF(Loader, "Kernel loaded...\n");
+
+ kernelBinning = new Kernel::Binning(this);
+#endif // FULL_SYSTEM
+
+ // increment the number of running systms
+ numSystemsRunning++;
+}
+
+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)
+{
+ if (id == -1) {
+ for (id = 0; id < execContexts.size(); id++) {
+ if (!execContexts[id])
+ break;
+ }
+ }
+
+ if (execContexts.size() <= id)
+ execContexts.resize(id + 1);
+
+ if (execContexts[id])
+ panic("Cannot have two CPUs with the same id (%d)\n", id);
+
+ execContexts[id] = xc;
+ numcpus++;
+
+#if FULL_SYSTEM
+ RemoteGDB *rgdb = new RemoteGDB(this, xc);
+ GDBListener *gdbl = new GDBListener(rgdb, 7000 + id);
+ gdbl->listen();
+ /**
+ * Uncommenting this line waits for a remote debugger to connect
+ * to the simulator before continuing.
+ */
+ if (rgdb_wait != -1 && rgdb_wait == id)
+ gdbl->accept();
+
+ if (remoteGDB.size() <= id) {
+ remoteGDB.resize(id + 1);
+ }
+
+ remoteGDB[id] = rgdb;
+#endif // FULL_SYSTEM
+
+ return id;
+}
+
+void
+System::startup()
+{
+ int i;
+ for (i = 0; i < execContexts.size(); i++)
+ execContexts[i]->activate(0);
+}
+
+void
+System::replaceExecContext(ExecContext *xc, int id)
+{
+ if (id >= execContexts.size()) {
+ panic("replaceExecContext: bad id, %d >= %d\n",
+ id, execContexts.size());
+ }
+
+ 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
+System::printSystems()
+{
+ vector<System *>::iterator i = systemList.begin();
+ vector<System *>::iterator end = systemList.end();
+ for (; i != end; ++i) {
+ System *sys = *i;
+ cerr << "System " << sys->name() << ": " << hex << sys << endl;
+ }
+}
+
+extern "C"
+void
+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/src/sim/system.hh b/src/sim/system.hh
new file mode 100644
index 000000000..7e21bd587
--- /dev/null
+++ b/src/sim/system.hh
@@ -0,0 +1,229 @@
+/*
+ * 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 __SYSTEM_HH__
+#define __SYSTEM_HH__
+
+#include <string>
+#include <vector>
+
+#include "base/loader/symtab.hh"
+#include "base/misc.hh"
+#include "base/statistics.hh"
+#include "cpu/pc_event.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 ObjectFile;
+class PhysicalMemory;
+
+#if FULL_SYSTEM
+class Platform;
+class GDBListener;
+class RemoteGDB;
+namespace Kernel { class Binning; }
+#endif
+
+class System : public SimObject
+{
+ public:
+ PhysicalMemory *physmem;
+ PCEventQueue pcEventQueue;
+
+ std::vector<ExecContext *> execContexts;
+ int numcpus;
+
+ int getNumCPUs()
+ {
+ if (numcpus != execContexts.size())
+ panic("cpu array not fully populated!");
+
+ 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;
+
+ /** Object pointer for the kernel code */
+ ObjectFile *kernel;
+
+ /** Begining of kernel code */
+ Addr kernelStart;
+
+ /** End of kernel code */
+ Addr kernelEnd;
+
+ /** Entry point in the kernel to start at */
+ Addr kernelEntry;
+
+ 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
+ * system.cc for details.
+ */
+ virtual Addr fixFuncEventAddr(Addr addr) = 0;
+
+ /**
+ * Add a function-based event to the given function, to be looked
+ * up in the specified symbol table.
+ */
+ template <class T>
+ T *System::addFuncEvent(SymbolTable *symtab, const char *lbl)
+ {
+ Addr addr = 0; // initialize only to avoid compiler warning
+
+ if (symtab->findAddress(lbl, addr)) {
+ T *ev = new T(&pcEventQueue, lbl, fixFuncEventAddr(addr));
+ return ev;
+ }
+
+ return NULL;
+ }
+
+ /** Add a function-based event to kernel code. */
+ template <class T>
+ T *System::addKernelFuncEvent(const char *lbl)
+ {
+ 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;
+ 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;
+ bool bin_int;
+
+ std::string kernel_path;
+ std::string readfile;
+#endif
+ };
+
+ protected:
+ Params *_params;
+
+ public:
+ System(Params *p);
+ ~System();
+
+ void startup();
+
+ 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
+ */
+ Addr getKernelStart() const { return kernelStart; }
+
+ /**
+ * Returns the addess the kernel ends at.
+ * @return address the kernel ends at
+ */
+ Addr getKernelEnd() const { return kernelEnd; }
+
+ /**
+ * Returns the addess the entry point to the kernel code.
+ * @return entry point of the kernel code
+ */
+ Addr getKernelEntry() const { return kernelEntry; }
+
+#else
+
+ Addr new_page();
+
+#endif // FULL_SYSTEM
+
+ int registerExecContext(ExecContext *xc, int xcIndex);
+ void replaceExecContext(ExecContext *xc, int xcIndex);
+
+ void regStats();
+ void serialize(std::ostream &os);
+ void unserialize(Checkpoint *cp, const std::string &section);
+
+ public:
+ ////////////////////////////////////////////
+ //
+ // STATIC GLOBAL SYSTEM LIST
+ //
+ ////////////////////////////////////////////
+
+ static std::vector<System *> systemList;
+ static int numSystemsRunning;
+
+ static void printSystems();
+
+
+};
+
+#endif // __SYSTEM_HH__
diff --git a/src/sim/vptr.hh b/src/sim/vptr.hh
new file mode 100644
index 000000000..cc57e63f0
--- /dev/null
+++ b/src/sim/vptr.hh
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __ARCH_ALPHA_VPTR_HH__
+#define __ARCH_ALPHA_VPTR_HH__
+
+#include "arch/vtophys.hh"
+#include "arch/isa_traits.hh"
+
+class ExecContext;
+
+template <class T>
+class VPtr
+{
+ public:
+ typedef T Type;
+
+ private:
+ ExecContext *xc;
+ Addr ptr;
+
+ public:
+ ExecContext *GetXC() const { return xc; }
+ Addr GetPointer() const { return ptr; }
+
+ public:
+ explicit VPtr(ExecContext *_xc, Addr p = 0) : xc(_xc), ptr(p) { }
+ template <class U>
+ VPtr(const VPtr<U> &vp) : xc(vp.GetXC()), ptr(vp.GetPointer()) {}
+ ~VPtr() {}
+
+ bool operator!() const
+ {
+ return ptr == 0;
+ }
+
+ VPtr<T> operator+(int offset)
+ {
+ VPtr<T> ptr(*this);
+ ptr += offset;
+
+ return ptr;
+ }
+
+ const VPtr<T> &operator+=(int offset)
+ {
+ ptr += offset;
+ assert((ptr & (TheISA::PageBytes - 1)) + sizeof(T)
+ < TheISA::PageBytes);
+
+ return *this;
+ }
+
+ const VPtr<T> &operator=(Addr p)
+ {
+ assert((p & (TheISA::PageBytes - 1)) + sizeof(T)
+ < TheISA::PageBytes);
+ ptr = p;
+
+ return *this;
+ }
+
+ template <class U>
+ const VPtr<T> &operator=(const VPtr<U> &vp)
+ {
+ xc = vp.GetXC();
+ ptr = vp.GetPointer();
+
+ return *this;
+ }
+
+ operator T *()
+ {
+ panic("Needs to be rewritten\n");
+/* void *addr = vtomem(xc, ptr, sizeof(T));
+ return (T *)addr;
+ */
+ }
+
+ T *operator->()
+ {
+ panic("Needs to be rewritten\n");
+/* void *addr = vtomem(xc, ptr, sizeof(T));
+ return (T *)addr;
+ */
+ }
+
+ T &operator*()
+ {
+ panic("Needs to be rewritten\n");
+/* void *addr = vtomem(xc, ptr, sizeof(T));
+ return *(T *)addr;
+ */
+ }
+};
+
+#endif // __ARCH_ALPHA_VPTR_HH__
diff --git a/src/unittest/Makefile b/src/unittest/Makefile
new file mode 100644
index 000000000..1f0584066
--- /dev/null
+++ b/src/unittest/Makefile
@@ -0,0 +1,98 @@
+# 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.
+#
+# Authors: Nathan Binkert
+# Steve Reinhardt
+
+CC?= gcc
+CXX?= g++
+PYTHON?=/usr/bin/env python
+
+CURDIR?= $(shell /bin/pwd)
+SRCDIR?= $(CURDIR)/..
+
+CCFLAGS= -g -O0 -MMD -I. -I$(SRCDIR) -I- -DTRACING_ON=0
+MYSQL= -I/usr/include/mysql -L/usr/lib/mysql -lmysqlclient
+
+VPATH=$(SRCDIR):$(CURDIR)
+
+default:
+ @echo "You must specify a target"
+
+base/traceflags.cc base/traceflags.hh: $(SRCDIR)/base/traceflags.py
+ mkdir -p base; \
+ cd base; \
+ $(PYTHON) $<
+
+bitvectest: test/bitvectest.cc
+ $(CXX) $(CCFLAGS) -o $@ $^
+
+circletest: test/circletest.cc base/circlebuf.cc
+ $(CXX) $(CCFLAGS) -o $@ $^
+
+cprintftest: test/cprintftest.cc base/cprintf.cc
+ $(CXX) $(CCFLAGS) -o $@ $^
+
+initest: test/initest.cc base/str.cc base/inifile.cc base/cprintf.cc
+ $(CXX) $(CCFLAGS) -o $@ $^
+
+lrutest: test/lru_test.cc
+ $(CXX) $(CCFLAGS) -o $@ $^
+
+nmtest: test/nmtest.cc base/output.cc base/hostinfo.cc base/cprintf.cc base/misc.cc base/loader/object_file.cc base/loader/symtab.cc base/misc.cc base/str.cc base/loader/aout_object.cc base/loader/ecoff_object.cc base/loader/elf_object.cc
+ $(CXX) $(CCFLAGS) -I/n/ziff/z/binkertn/build/work/ALPHA_FS -lelf -o $@ $^
+
+offtest: test/offtest.cc
+ $(CXX) $(CCFLAGS) -o $@ $^
+
+rangetest: test/rangetest.cc base/range.cc base/str.cc
+ $(CXX) $(CCFLAGS) -o $@ $^
+
+STATTEST+= base/cprintf.cc base/hostinfo.cc base/misc.cc base/mysql.cc
+STATTEST+= base/python.cc base/str.cc base/time.cc
+STATTEST+= base/statistics.cc base/stats/mysql.cc base/stats/python.cc
+STATTEST+= base/stats/statdb.cc base/stats/text.cc base/stats/visit.cc
+STATTEST+= test/stattest.cc
+stattest: $(STATTEST)
+ $(CXX) $(CCFLAGS) $(MYSQL) -o $@ $^
+
+strnumtest: test/strnumtest.cc base/str.cc
+ $(CXX) $(CCFLAGS) -o $@ $^
+
+symtest: test/symtest.cc base/misc.cc base/symtab.cc base/str.cc
+ $(CXX) $(CCFLAGS) -o $@ $^
+
+tokentest: test/tokentest.cc base/str.cc
+ $(CXX) $(CCFLAGS) -o $@ $^
+
+TRACE+=test/tracetest.cc base/trace.cc base/trace_flags.cc base/cprintf.cc
+TRACE+=base/str.cc base/misc.cc
+tracetest: $(TRACE)
+ $(CXX) $(CCFLAGS) -o $@ $^
+
+clean:
+ @rm -rf *test *~ .#* *.core core base
+.PHONY: clean
diff --git a/test/bitvectest.cc b/src/unittest/bitvectest.cc
index 1b8c332f5..1b8c332f5 100644
--- a/test/bitvectest.cc
+++ b/src/unittest/bitvectest.cc
diff --git a/test/circletest.cc b/src/unittest/circletest.cc
index bb15f8c64..bb15f8c64 100644
--- a/test/circletest.cc
+++ b/src/unittest/circletest.cc
diff --git a/src/unittest/cprintftest.cc b/src/unittest/cprintftest.cc
new file mode 100644
index 000000000..361f84028
--- /dev/null
+++ b/src/unittest/cprintftest.cc
@@ -0,0 +1,163 @@
+/*
+ * 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 <iostream>
+#include <list>
+#include <string>
+#include <sstream>
+
+#include "base/cprintf.hh"
+
+using namespace std;
+
+int
+main()
+{
+ char foo[9];
+ cprintf("%s\n", foo);
+
+ cprintf("%shits%%s + %smisses%%s\n", "test", "test");
+ cprintf("%%s%-10s %c he went home \'\"%d %#o %#x %1.5f %1.2E\n",
+ "hello", 'A', 1, 0xff, 0xfffffffffffffULL, 3.141592653589, 1.1e10);
+
+ cout << cformat("%s %#x %s\n") << "hello" << 0 << "foo 0\n";
+ cerr << cformat("%s %#x\n") << "hello" << 1 << "foo 1\n";
+
+ cprintf("another test\n");
+
+ stringstream buffer;
+ ccprintf(buffer, "%-10s %c he home \'\"%d %#o %#x %1.5f %1.2E\n",
+ "hello", 'A', 1, 0xff, 0xfffffffffffffULL, 3.14159265, 1.1e10);
+
+ double f = 314159.26535897932384;
+
+ #define ctest(x, y) printf(x, y); cprintf(x, y); cprintf("\n");
+ ctest("%1.8f\n", f);
+ ctest("%2.8f\n", f);
+ ctest("%3.8f\n", f);
+ ctest("%4.8f\n", f);
+ ctest("%5.8f\n", f);
+ ctest("%6.8f\n", f);
+ ctest("%12.8f\n", f);
+ ctest("%1000.8f\n", f);
+ ctest("%1.0f\n", f);
+ ctest("%1.1f\n", f);
+ ctest("%1.2f\n", f);
+ ctest("%1.3f\n", f);
+ ctest("%1.4f\n", f);
+ ctest("%1.5f\n", f);
+ ctest("%1.6f\n", f);
+ ctest("%1.7f\n", f);
+ ctest("%1.8f\n", f);
+ ctest("%1.9f\n", f);
+ ctest("%1.10f\n", f);
+ ctest("%1.11f\n", f);
+ ctest("%1.12f\n", f);
+ ctest("%1.13f\n", f);
+ ctest("%1.14f\n", f);
+ ctest("%1.15f\n", f);
+ ctest("%1.16f\n", f);
+ ctest("%1.17f\n", f);
+ ctest("%1.18f\n", f);
+
+ cout << "foo\n";
+
+ f = 0.00000026535897932384;
+ ctest("%1.8f\n", f);
+ ctest("%2.8f\n", f);
+ ctest("%3.8f\n", f);
+ ctest("%4.8f\n", f);
+ ctest("%5.8f\n", f);
+ ctest("%6.8f\n", f);
+ ctest("%12.8f\n", f);
+ ctest("%1.0f\n", f);
+ ctest("%1.1f\n", f);
+ ctest("%1.2f\n", f);
+ ctest("%1.3f\n", f);
+ ctest("%1.4f\n", f);
+ ctest("%1.5f\n", f);
+ ctest("%1.6f\n", f);
+ ctest("%1.7f\n", f);
+ ctest("%1.8f\n", f);
+ ctest("%1.9f\n", f);
+ ctest("%1.10f\n", f);
+ ctest("%1.11f\n", f);
+ ctest("%1.12f\n", f);
+ ctest("%1.13f\n", f);
+ ctest("%1.14f\n", f);
+ ctest("%1.15f\n", f);
+ ctest("%1.16f\n", f);
+ ctest("%1.17f\n", f);
+ ctest("%1.18f\n", f);
+
+ f = 0.00000026535897932384;
+ ctest("%1.8e\n", f);
+ ctest("%2.8e\n", f);
+ ctest("%3.8e\n", f);
+ ctest("%4.8e\n", f);
+ ctest("%5.8e\n", f);
+ ctest("%6.8e\n", f);
+ ctest("%12.8e\n", f);
+ ctest("%1.0e\n", f);
+ ctest("%1.1e\n", f);
+ ctest("%1.2e\n", f);
+ ctest("%1.3e\n", f);
+ ctest("%1.4e\n", f);
+ ctest("%1.5e\n", f);
+ ctest("%1.6e\n", f);
+ ctest("%1.7e\n", f);
+ ctest("%1.8e\n", f);
+ ctest("%1.9e\n", f);
+ ctest("%1.10e\n", f);
+ ctest("%1.11e\n", f);
+ ctest("%1.12e\n", f);
+ ctest("%1.13e\n", f);
+ ctest("%1.14e\n", f);
+ ctest("%1.15e\n", f);
+ ctest("%1.16e\n", f);
+ ctest("%1.17e\n", f);
+ ctest("%1.18e\n", f);
+
+ cout << buffer.str();
+
+ cout.width(0);
+ cout.precision(1);
+ cout << f << "\n";
+
+ string foo1 = "string test";
+ cprintf("%s\n", foo1);
+
+ stringstream foo2;
+ foo2 << "stringstream test";
+ cprintf("%s\n", foo2);
+
+ cprintf("%c %c\n", 'c', 65);
+
+ cout << '9';
+ return 0;
+}
diff --git a/test/foo.ini b/src/unittest/foo.ini
index 534a4e001..534a4e001 100644
--- a/test/foo.ini
+++ b/src/unittest/foo.ini
diff --git a/test/genini.py b/src/unittest/genini.py
index 2af81fe2b..2af81fe2b 100755
--- a/test/genini.py
+++ b/src/unittest/genini.py
diff --git a/test/initest.cc b/src/unittest/initest.cc
index 0c5ac2343..0c5ac2343 100644
--- a/test/initest.cc
+++ b/src/unittest/initest.cc
diff --git a/test/initest.ini b/src/unittest/initest.ini
index ebf2719d8..ebf2719d8 100644
--- a/test/initest.ini
+++ b/src/unittest/initest.ini
diff --git a/test/lru_test.cc b/src/unittest/lru_test.cc
index 2829163de..2829163de 100644
--- a/test/lru_test.cc
+++ b/src/unittest/lru_test.cc
diff --git a/test/nmtest.cc b/src/unittest/nmtest.cc
index e9c20d19d..e9c20d19d 100644
--- a/test/nmtest.cc
+++ b/src/unittest/nmtest.cc
diff --git a/test/offtest.cc b/src/unittest/offtest.cc
index d3f035b73..d3f035b73 100644
--- a/test/offtest.cc
+++ b/src/unittest/offtest.cc
diff --git a/test/paramtest.cc b/src/unittest/paramtest.cc
index cb31c49d5..cb31c49d5 100644
--- a/test/paramtest.cc
+++ b/src/unittest/paramtest.cc
diff --git a/test/rangetest.cc b/src/unittest/rangetest.cc
index 41d438f48..41d438f48 100644
--- a/test/rangetest.cc
+++ b/src/unittest/rangetest.cc
diff --git a/test/sized_test.cc b/src/unittest/sized_test.cc
index 86cd13e5b..86cd13e5b 100644
--- a/test/sized_test.cc
+++ b/src/unittest/sized_test.cc
diff --git a/test/stattest.cc b/src/unittest/stattest.cc
index b944eff45..b944eff45 100644
--- a/test/stattest.cc
+++ b/src/unittest/stattest.cc
diff --git a/test/strnumtest.cc b/src/unittest/strnumtest.cc
index a80dd7c36..a80dd7c36 100644
--- a/test/strnumtest.cc
+++ b/src/unittest/strnumtest.cc
diff --git a/test/symtest.cc b/src/unittest/symtest.cc
index 5fba71736..5fba71736 100644
--- a/test/symtest.cc
+++ b/src/unittest/symtest.cc
diff --git a/test/tokentest.cc b/src/unittest/tokentest.cc
index 7f27d58fe..7f27d58fe 100644
--- a/test/tokentest.cc
+++ b/src/unittest/tokentest.cc
diff --git a/test/tracetest.cc b/src/unittest/tracetest.cc
index 866b67d9b..866b67d9b 100644
--- a/test/tracetest.cc
+++ b/src/unittest/tracetest.cc
diff --git a/test/Makefile b/test/Makefile
deleted file mode 100644
index 6fe0e5f48..000000000
--- a/test/Makefile
+++ /dev/null
@@ -1,69 +0,0 @@
-CC?= gcc
-CXX?= g++
-PYTHON?=/usr/bin/env python
-
-CURDIR?= $(shell /bin/pwd)
-SRCDIR?= $(CURDIR)/..
-
-CCFLAGS= -g -O0 -MMD -I. -I$(SRCDIR) -I- -DTRACING_ON=0
-MYSQL= -I/usr/include/mysql -L/usr/lib/mysql -lmysqlclient
-
-VPATH=$(SRCDIR):$(CURDIR)
-
-default:
- @echo "You must specify a target"
-
-base/traceflags.cc base/traceflags.hh: $(SRCDIR)/base/traceflags.py
- mkdir -p base; \
- cd base; \
- $(PYTHON) $<
-
-bitvectest: test/bitvectest.cc
- $(CXX) $(CCFLAGS) -o $@ $^
-
-circletest: test/circletest.cc base/circlebuf.cc
- $(CXX) $(CCFLAGS) -o $@ $^
-
-cprintftest: test/cprintftest.cc base/cprintf.cc
- $(CXX) $(CCFLAGS) -o $@ $^
-
-initest: test/initest.cc base/str.cc base/inifile.cc base/cprintf.cc
- $(CXX) $(CCFLAGS) -o $@ $^
-
-lrutest: test/lru_test.cc
- $(CXX) $(CCFLAGS) -o $@ $^
-
-nmtest: test/nmtest.cc base/output.cc base/hostinfo.cc base/cprintf.cc base/misc.cc base/loader/object_file.cc base/loader/symtab.cc base/misc.cc base/str.cc base/loader/aout_object.cc base/loader/ecoff_object.cc base/loader/elf_object.cc
- $(CXX) $(CCFLAGS) -I/n/ziff/z/binkertn/build/work/ALPHA_FS -lelf -o $@ $^
-
-offtest: test/offtest.cc
- $(CXX) $(CCFLAGS) -o $@ $^
-
-rangetest: test/rangetest.cc base/range.cc base/str.cc
- $(CXX) $(CCFLAGS) -o $@ $^
-
-STATTEST+= base/cprintf.cc base/hostinfo.cc base/misc.cc base/mysql.cc
-STATTEST+= base/python.cc base/str.cc base/time.cc
-STATTEST+= base/statistics.cc base/stats/mysql.cc base/stats/python.cc
-STATTEST+= base/stats/statdb.cc base/stats/text.cc base/stats/visit.cc
-STATTEST+= test/stattest.cc
-stattest: $(STATTEST)
- $(CXX) $(CCFLAGS) $(MYSQL) -o $@ $^
-
-strnumtest: test/strnumtest.cc base/str.cc
- $(CXX) $(CCFLAGS) -o $@ $^
-
-symtest: test/symtest.cc base/misc.cc base/symtab.cc base/str.cc
- $(CXX) $(CCFLAGS) -o $@ $^
-
-tokentest: test/tokentest.cc base/str.cc
- $(CXX) $(CCFLAGS) -o $@ $^
-
-TRACE+=test/tracetest.cc base/trace.cc base/trace_flags.cc base/cprintf.cc
-TRACE+=base/str.cc base/misc.cc
-tracetest: $(TRACE)
- $(CXX) $(CCFLAGS) -o $@ $^
-
-clean:
- @rm -rf *test *~ .#* *.core core base
-.PHONY: clean
diff --git a/test/cprintftest.cc b/test/cprintftest.cc
deleted file mode 100644
index 611f01bc2..000000000
--- a/test/cprintftest.cc
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * 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 <cstdio>
-#include <iostream>
-#include <list>
-#include <string>
-#include <sstream>
-
-#include "base/cprintf.hh"
-
-using namespace std;
-
-int
-main()
-{
- char foo[9];
- cprintf("%s\n", foo);
-
- cprintf("%shits%%s + %smisses%%s\n", "test", "test");
- cprintf("%%s%-10s %c he went home \'\"%d %#o %#x %1.5f %1.2E\n",
- "hello", 'A', 1, 0xff, 0xfffffffffffffULL, 3.141592653589, 1.1e10);
-
- cout << cformat("%s %#x %s\n") << "hello" << 0 << "foo 0\n";
- cerr << cformat("%s %#x\n") << "hello" << 1 << "foo 1\n";
-
- cprintf("another test\n");
-
- stringstream buffer;
- ccprintf(buffer, "%-10s %c he home \'\"%d %#o %#x %1.5f %1.2E\n",
- "hello", 'A', 1, 0xff, 0xfffffffffffffULL, 3.14159265, 1.1e10);
-
- double f = 314159.26535897932384;
-
- #define ctest(x, y) printf(x, y); cprintf(x, y); cprintf("\n");
- ctest("%1.8f\n", f);
- ctest("%2.8f\n", f);
- ctest("%3.8f\n", f);
- ctest("%4.8f\n", f);
- ctest("%5.8f\n", f);
- ctest("%6.8f\n", f);
- ctest("%12.8f\n", f);
- ctest("%1000.8f\n", f);
- ctest("%1.0f\n", f);
- ctest("%1.1f\n", f);
- ctest("%1.2f\n", f);
- ctest("%1.3f\n", f);
- ctest("%1.4f\n", f);
- ctest("%1.5f\n", f);
- ctest("%1.6f\n", f);
- ctest("%1.7f\n", f);
- ctest("%1.8f\n", f);
- ctest("%1.9f\n", f);
- ctest("%1.10f\n", f);
- ctest("%1.11f\n", f);
- ctest("%1.12f\n", f);
- ctest("%1.13f\n", f);
- ctest("%1.14f\n", f);
- ctest("%1.15f\n", f);
- ctest("%1.16f\n", f);
- ctest("%1.17f\n", f);
- ctest("%1.18f\n", f);
-
- cout << "foo\n";
-
- f = 0.00000026535897932384;
- ctest("%1.8f\n", f);
- ctest("%2.8f\n", f);
- ctest("%3.8f\n", f);
- ctest("%4.8f\n", f);
- ctest("%5.8f\n", f);
- ctest("%6.8f\n", f);
- ctest("%12.8f\n", f);
- ctest("%1.0f\n", f);
- ctest("%1.1f\n", f);
- ctest("%1.2f\n", f);
- ctest("%1.3f\n", f);
- ctest("%1.4f\n", f);
- ctest("%1.5f\n", f);
- ctest("%1.6f\n", f);
- ctest("%1.7f\n", f);
- ctest("%1.8f\n", f);
- ctest("%1.9f\n", f);
- ctest("%1.10f\n", f);
- ctest("%1.11f\n", f);
- ctest("%1.12f\n", f);
- ctest("%1.13f\n", f);
- ctest("%1.14f\n", f);
- ctest("%1.15f\n", f);
- ctest("%1.16f\n", f);
- ctest("%1.17f\n", f);
- ctest("%1.18f\n", f);
-
- f = 0.00000026535897932384;
- ctest("%1.8e\n", f);
- ctest("%2.8e\n", f);
- ctest("%3.8e\n", f);
- ctest("%4.8e\n", f);
- ctest("%5.8e\n", f);
- ctest("%6.8e\n", f);
- ctest("%12.8e\n", f);
- ctest("%1.0e\n", f);
- ctest("%1.1e\n", f);
- ctest("%1.2e\n", f);
- ctest("%1.3e\n", f);
- ctest("%1.4e\n", f);
- ctest("%1.5e\n", f);
- ctest("%1.6e\n", f);
- ctest("%1.7e\n", f);
- ctest("%1.8e\n", f);
- ctest("%1.9e\n", f);
- ctest("%1.10e\n", f);
- ctest("%1.11e\n", f);
- ctest("%1.12e\n", f);
- ctest("%1.13e\n", f);
- ctest("%1.14e\n", f);
- ctest("%1.15e\n", f);
- ctest("%1.16e\n", f);
- ctest("%1.17e\n", f);
- ctest("%1.18e\n", f);
-
- cout << buffer.str();
-
- cout.width(0);
- cout.precision(1);
- cout << f << "\n";
-
- string foo1 = "string test";
- cprintf("%s\n", foo1);
-
- stringstream foo2;
- foo2 << "stringstream test";
- cprintf("%s\n", foo2);
-
- cprintf("%c %c\n", 'c', 65);
-
- cout << '9';
- return 0;
-}
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