From 14cd51f7793a9ce07bc435069f57269450141363 Mon Sep 17 00:00:00 2001 From: Stan Shebs Date: Fri, 16 Apr 1999 01:35:26 +0000 Subject: Initial revision --- sim/ChangeLog | 461 ++ sim/Makefile.in | 254 + sim/README-HACKING | 254 + sim/arm/COPYING | 340 + sim/arm/ChangeLog | 426 ++ sim/arm/Makefile.in | 48 + sim/arm/README.Cygnus | 27 + sim/arm/acconfig.h | 15 + sim/arm/armcopro.c | 357 + sim/arm/armdefs.h | 353 + sim/arm/armemu.c | 3454 +++++++++ sim/arm/armemu.h | 425 ++ sim/arm/armfpe.h | 1351 ++++ sim/arm/arminit.c | 294 + sim/arm/armopts.h | 23 + sim/arm/armos.c | 1136 +++ sim/arm/armos.h | 95 + sim/arm/armrdi.c | 1044 +++ sim/arm/armsupp.c | 712 ++ sim/arm/armvirt.c | 491 ++ sim/arm/bag.c | 141 + sim/arm/bag.h | 42 + sim/arm/communicate.c | 221 + sim/arm/communicate.h | 37 + sim/arm/config.in | 158 + sim/arm/configure | 3892 +++++++++++ sim/arm/configure.in | 10 + sim/arm/dbg_conf.h | 48 + sim/arm/dbg_cp.h | 62 + sim/arm/dbg_hif.h | 47 + sim/arm/dbg_rdi.h | 323 + sim/arm/gdbhost.c | 107 + sim/arm/gdbhost.h | 23 + sim/arm/kid.c | 510 ++ sim/arm/main.c | 183 + sim/arm/parent.c | 483 ++ sim/arm/tconfig.in | 17 + sim/arm/thumbemu.c | 455 ++ sim/arm/wrapper.c | 467 ++ sim/common/ChangeLog | 4005 +++++++++++ sim/common/Make-common.in | 642 ++ sim/common/Makefile.in | 139 + sim/common/acconfig.h | 15 + sim/common/aclocal.m4 | 1259 ++++ sim/common/callback.c | 810 +++ sim/common/cgen-cpu.h | 98 + sim/common/cgen-defs.h | 174 + sim/common/cgen-engine.h | 473 ++ sim/common/cgen-mem.h | 203 + sim/common/cgen-ops.h | 897 +++ sim/common/cgen-run.c | 233 + sim/common/cgen-scache.c | 471 ++ sim/common/cgen-scache.h | 162 + sim/common/cgen-sim.h | 34 + sim/common/cgen-trace.c | 414 ++ sim/common/cgen-trace.h | 91 + sim/common/cgen-types.h | 116 + sim/common/cgen-utils.c | 328 + sim/common/config.in | 167 + sim/common/configure | 3902 +++++++++++ sim/common/configure.in | 40 + sim/common/dv-core.c | 118 + sim/common/dv-glue.c | 373 + sim/common/dv-pal.c | 605 ++ sim/common/dv-sockser.c | 386 + sim/common/dv-sockser.h | 32 + sim/common/gdbinit.in | 10 + sim/common/genmloop.sh | 1122 +++ sim/common/gennltvals.sh | 67 + sim/common/gentmap.c | 125 + sim/common/gentvals.sh | 74 + sim/common/hw-alloc.c | 99 + sim/common/hw-alloc.h | 49 + sim/common/hw-base.c | 571 ++ sim/common/hw-base.h | 109 + sim/common/hw-device.c | 66 + sim/common/hw-device.h | 535 ++ sim/common/hw-events.c | 263 + sim/common/hw-events.h | 61 + sim/common/hw-handles.c | 237 + sim/common/hw-handles.h | 63 + sim/common/hw-instances.c | 285 + sim/common/hw-instances.h | 157 + sim/common/hw-main.h | 73 + sim/common/hw-ports.c | 339 + sim/common/hw-ports.h | 129 + sim/common/hw-properties.c | 905 +++ sim/common/hw-properties.h | 244 + sim/common/hw-tree.c | 1344 ++++ sim/common/hw-tree.h | 119 + sim/common/nltvals.def | 418 ++ sim/common/nrun.c | 214 + sim/common/run.1 | 107 + sim/common/run.c | 308 + sim/common/sim-abort.c | 60 + sim/common/sim-alu.h | 1047 +++ sim/common/sim-arange.c | 301 + sim/common/sim-arange.h | 83 + sim/common/sim-assert.h | 90 + sim/common/sim-base.h | 252 + sim/common/sim-basics.h | 154 + sim/common/sim-bits.c | 208 + sim/common/sim-bits.h | 564 ++ sim/common/sim-break.c | 278 + sim/common/sim-break.h | 38 + sim/common/sim-config.c | 377 + sim/common/sim-config.h | 594 ++ sim/common/sim-core.c | 839 +++ sim/common/sim-core.h | 343 + sim/common/sim-cpu.c | 80 + sim/common/sim-cpu.h | 152 + sim/common/sim-endian.c | 128 + sim/common/sim-endian.h | 414 ++ sim/common/sim-engine.c | 210 + sim/common/sim-engine.h | 161 + sim/common/sim-events.c | 1188 ++++ sim/common/sim-events.h | 271 + sim/common/sim-fpu.c | 2578 +++++++ sim/common/sim-fpu.h | 417 ++ sim/common/sim-hload.c | 69 + sim/common/sim-hrw.c | 41 + sim/common/sim-hw.c | 508 ++ sim/common/sim-hw.h | 98 + sim/common/sim-info.c | 32 + sim/common/sim-inline.c | 96 + sim/common/sim-inline.h | 810 +++ sim/common/sim-io.c | 379 + sim/common/sim-io.h | 84 + sim/common/sim-load.c | 239 + sim/common/sim-memopt.c | 471 ++ sim/common/sim-memopt.h | 46 + sim/common/sim-model.c | 208 + sim/common/sim-model.h | 138 + sim/common/sim-module.c | 399 ++ sim/common/sim-module.h | 125 + sim/common/sim-n-bits.h | 218 + sim/common/sim-n-core.h | 417 ++ sim/common/sim-n-endian.h | 169 + sim/common/sim-options.c | 936 +++ sim/common/sim-options.h | 149 + sim/common/sim-profile.c | 1175 ++++ sim/common/sim-profile.h | 289 + sim/common/sim-reason.c | 57 + sim/common/sim-reg.c | 52 + sim/common/sim-resume.c | 85 + sim/common/sim-run.c | 51 + sim/common/sim-signal.c | 96 + sim/common/sim-signal.h | 49 + sim/common/sim-stop.c | 43 + sim/common/sim-trace.c | 1341 ++++ sim/common/sim-trace.h | 551 ++ sim/common/sim-types.h | 201 + sim/common/sim-utils.c | 411 ++ sim/common/sim-utils.h | 90 + sim/common/sim-watch.c | 458 ++ sim/common/sim-watch.h | 78 + sim/common/syscall.c | 482 ++ sim/common/tconfig.in | 19 + sim/configure | 1917 +++++ sim/configure.in | 187 + sim/d10v/ChangeLog | 974 +++ sim/d10v/Makefile.in | 52 + sim/d10v/acconfig.h | 15 + sim/d10v/config.in | 158 + sim/d10v/configure | 3917 +++++++++++ sim/d10v/configure.in | 13 + sim/d10v/d10v_sim.h | 452 ++ sim/d10v/endian.c | 137 + sim/d10v/gencode.c | 156 + sim/d10v/interp.c | 1086 +++ sim/d10v/simops.c | 3252 +++++++++ sim/d30v/ChangeLog | 1333 ++++ sim/d30v/Makefile.in | 217 + sim/d30v/acconfig.h | 15 + sim/d30v/alu.h | 106 + sim/d30v/config.in | 162 + sim/d30v/configure | 4264 +++++++++++ sim/d30v/configure.in | 40 + sim/d30v/cpu.c | 172 + sim/d30v/cpu.h | 242 + sim/d30v/d30v-insns | 2422 +++++++ sim/d30v/dc-short | 22 + sim/d30v/engine.c | 493 ++ sim/d30v/ic-d30v | 80 + sim/d30v/sim-calls.c | 364 + sim/d30v/sim-main.h | 82 + sim/d30v/tconfig.in | 4 + sim/erc32/ChangeLog | 576 ++ sim/erc32/Makefile.in | 75 + sim/erc32/NEWS | 108 + sim/erc32/README.erc32 | 130 + sim/erc32/README.gdb | 67 + sim/erc32/README.sis | 356 + sim/erc32/acconfig.h | 15 + sim/erc32/config.in | 158 + sim/erc32/configure | 3932 +++++++++++ sim/erc32/configure.in | 13 + sim/erc32/end.c | 26 + sim/erc32/erc32.c | 1888 +++++ sim/erc32/exec.c | 2041 ++++++ sim/erc32/float.c | 212 + sim/erc32/func.c | 1162 +++ sim/erc32/help.c | 40 + sim/erc32/interf.c | 526 ++ sim/erc32/sis.c | 310 + sim/erc32/sis.h | 217 + sim/erc32/startsim | 4 + sim/fr30/ChangeLog | 287 + sim/fr30/Makefile.in | 90 + sim/fr30/README | 14 + sim/fr30/TODO | 14 + sim/fr30/arch.c | 695 ++ sim/fr30/arch.h | 87 + sim/fr30/config.in | 162 + sim/fr30/configure | 4222 +++++++++++ sim/fr30/configure.in | 16 + sim/fr30/cpu.c | 356 + sim/fr30/cpu.h | 1244 ++++ sim/fr30/cpuall.h | 63 + sim/fr30/decode.c | 3303 +++++++++ sim/fr30/decode.h | 289 + sim/fr30/devices.c | 99 + sim/fr30/fr30-sim.h | 108 + sim/fr30/fr30.c | 423 ++ sim/fr30/mloop.in | 236 + sim/fr30/model.c | 4004 +++++++++++ sim/fr30/sem-switch.c | 5397 ++++++++++++++ sim/fr30/sem.c | 5504 +++++++++++++++ sim/fr30/sim-if.c | 208 + sim/fr30/sim-main.h | 70 + sim/fr30/tconfig.in | 42 + sim/fr30/traps.c | 217 + sim/h8300/ChangeLog | 591 ++ sim/h8300/Makefile.in | 25 + sim/h8300/acconfig.h | 15 + sim/h8300/compile.c | 2169 ++++++ sim/h8300/config.in | 158 + sim/h8300/configure | 3892 +++++++++++ sim/h8300/configure.in | 10 + sim/h8300/inst.h | 89 + sim/h8300/tconfig.in | 17 + sim/h8300/writecode.c | 1033 +++ sim/h8500/ChangeLog | 413 ++ sim/h8500/Makefile.in | 28 + sim/h8500/acconfig.h | 15 + sim/h8500/compile.c | 2519 +++++++ sim/h8500/config.in | 158 + sim/h8500/configure | 3892 +++++++++++ sim/h8500/configure.in | 10 + sim/h8500/inst.h | 101 + sim/h8500/tconfig.in | 13 + sim/i960/ChangeLog | 86 + sim/i960/Makefile.in | 101 + sim/i960/README | 14 + sim/i960/TODO | 9 + sim/i960/acconfig.h | 15 + sim/i960/arch.c | 164 + sim/i960/arch.h | 52 + sim/i960/config.in | 162 + sim/i960/configure | 4222 +++++++++++ sim/i960/configure.in | 16 + sim/i960/cpu.c | 84 + sim/i960/cpu.h | 1860 +++++ sim/i960/cpuall.h | 64 + sim/i960/decode.c | 6644 ++++++++++++++++++ sim/i960/decode.h | 433 ++ sim/i960/devices.c | 108 + sim/i960/i960-desc.c | 1784 +++++ sim/i960/i960-desc.h | 342 + sim/i960/i960-opc.h | 156 + sim/i960/i960-sim.h | 49 + sim/i960/i960.c | 141 + sim/i960/mloop.in | 301 + sim/i960/model.c | 9793 ++++++++++++++++++++++++++ sim/i960/sem-switch.c | 7181 +++++++++++++++++++ sim/i960/sem.c | 7406 ++++++++++++++++++++ sim/i960/sim-if.c | 311 + sim/i960/sim-main.h | 69 + sim/i960/tconfig.in | 49 + sim/i960/traps.c | 213 + sim/igen/ChangeLog | 998 +++ sim/igen/Makefile.in | 177 + sim/igen/acconfig.h | 15 + sim/igen/config.in | 31 + sim/igen/configure | 1806 +++++ sim/igen/configure.in | 52 + sim/igen/filter.c | 355 + sim/igen/filter.h | 86 + sim/igen/filter_host.c | 37 + sim/igen/filter_host.h | 27 + sim/igen/gen-engine.c | 807 +++ sim/igen/gen-engine.h | 37 + sim/igen/gen-icache.c | 859 +++ sim/igen/gen-icache.h | 81 + sim/igen/gen-idecode.c | 1391 ++++ sim/igen/gen-idecode.h | 50 + sim/igen/gen-itable.c | 317 + sim/igen/gen-itable.h | 30 + sim/igen/gen-model.c | 416 ++ sim/igen/gen-model.h | 29 + sim/igen/gen-semantics.c | 390 ++ sim/igen/gen-semantics.h | 104 + sim/igen/gen-support.c | 219 + sim/igen/gen-support.h | 29 + sim/igen/gen.c | 1765 +++++ sim/igen/gen.h | 227 + sim/igen/igen.c | 1621 +++++ sim/igen/igen.h | 234 + sim/igen/ld-cache.c | 114 + sim/igen/ld-cache.h | 66 + sim/igen/ld-decode.c | 404 ++ sim/igen/ld-decode.h | 235 + sim/igen/ld-insn.c | 1829 +++++ sim/igen/ld-insn.h | 703 ++ sim/igen/lf.c | 418 ++ sim/igen/lf.h | 143 + sim/igen/misc.c | 284 + sim/igen/misc.h | 149 + sim/igen/table.c | 632 ++ sim/igen/table.h | 155 + sim/m32r/ChangeLog | 1046 +++ sim/m32r/Makefile.in | 95 + sim/m32r/README | 14 + sim/m32r/TODO | 9 + sim/m32r/acconfig.h | 15 + sim/m32r/arch.c | 356 + sim/m32r/arch.h | 69 + sim/m32r/config.in | 162 + sim/m32r/configure | 4251 +++++++++++ sim/m32r/configure.in | 17 + sim/m32r/cpu.c | 196 + sim/m32r/cpu.h | 852 +++ sim/m32r/cpuall.h | 70 + sim/m32r/decode.c | 1996 ++++++ sim/m32r/decode.h | 208 + sim/m32r/devices.c | 108 + sim/m32r/m32r-sim.h | 203 + sim/m32r/m32r.c | 413 ++ sim/m32r/mloop.in | 319 + sim/m32r/model.c | 4168 +++++++++++ sim/m32r/sem-switch.c | 2503 +++++++ sim/m32r/sem.c | 2544 +++++++ sim/m32r/sim-if.c | 287 + sim/m32r/sim-main.h | 85 + sim/m32r/tconfig.in | 47 + sim/m32r/traps.c | 170 + sim/mips/ChangeLog | 2046 ++++++ sim/mips/Makefile.in | 293 + sim/mips/acconfig.h | 15 + sim/mips/config.in | 174 + sim/mips/configure | 4890 +++++++++++++ sim/mips/configure.in | 170 + sim/mips/dv-tx3904cpu.c | 246 + sim/mips/dv-tx3904irc.c | 413 ++ sim/mips/dv-tx3904sio.c | 621 ++ sim/mips/dv-tx3904tmr.c | 698 ++ sim/mips/interp.c | 3228 +++++++++ sim/mips/m16.dc | 25 + sim/mips/m16.igen | 1236 ++++ sim/mips/m16run.c | 74 + sim/mips/mips.dc | 16 + sim/mips/mips.igen | 3895 +++++++++++ sim/mips/sim-main.c | 579 ++ sim/mips/sim-main.h | 785 +++ sim/mips/tconfig.in | 31 + sim/mips/tx.igen | 41 + sim/mips/vr.igen | 78 + sim/mn10200/ChangeLog | 424 ++ sim/mn10200/Makefile.in | 52 + sim/mn10200/acconfig.h | 15 + sim/mn10200/config.in | 158 + sim/mn10200/configure | 3892 +++++++++++ sim/mn10200/configure.in | 10 + sim/mn10200/gencode.c | 154 + sim/mn10200/interp.c | 800 +++ sim/mn10200/mn10200_sim.h | 297 + sim/mn10200/simops.c | 2449 +++++++ sim/mn10300/ChangeLog | 815 +++ sim/mn10300/Makefile.in | 157 + sim/mn10300/acconfig.h | 15 + sim/mn10300/config.in | 183 + sim/mn10300/configure | 4397 ++++++++++++ sim/mn10300/configure.in | 37 + sim/mn10300/dv-mn103cpu.c | 431 ++ sim/mn10300/dv-mn103int.c | 824 +++ sim/mn10300/dv-mn103iop.c | 555 ++ sim/mn10300/dv-mn103ser.c | 712 ++ sim/mn10300/dv-mn103tim.c | 1032 +++ sim/mn10300/gencode.c | 163 + sim/mn10300/interp.c | 1402 ++++ sim/mn10300/mn10300.dc | 4 + sim/mn10300/mn10300.igen | 3537 ++++++++++ sim/mn10300/mn10300_sim.h | 383 + sim/mn10300/op_utils.c | 227 + sim/mn10300/sim-main.c | 4 + sim/mn10300/sim-main.h | 107 + sim/mn10300/simops.c | 3239 +++++++++ sim/mn10300/tconfig.in | 26 + sim/ppc/.gdbinit | 2 + sim/ppc/BUGS | 123 + sim/ppc/COPYING | 340 + sim/ppc/COPYING.LIB | 481 ++ sim/ppc/ChangeLog | 3183 +++++++++ sim/ppc/ChangeLog.00 | 2168 ++++++ sim/ppc/INSTALL | 812 +++ sim/ppc/Makefile.in | 660 ++ sim/ppc/README | 353 + sim/ppc/RUN | 949 +++ sim/ppc/acconfig.h | 15 + sim/ppc/aclocal.m4 | 0 sim/ppc/basics.h | 139 + sim/ppc/bits.c | 114 + sim/ppc/bits.h | 257 + sim/ppc/cap.c | 134 + sim/ppc/cap.h | 60 + sim/ppc/config.in | 362 + sim/ppc/configure | 5197 ++++++++++++++ sim/ppc/configure.in | 745 ++ sim/ppc/corefile-n.h | 97 + sim/ppc/corefile.c | 415 ++ sim/ppc/corefile.h | 227 + sim/ppc/cpu.c | 404 ++ sim/ppc/cpu.h | 254 + sim/ppc/dc-complex | 58 + sim/ppc/dc-simple | 25 + sim/ppc/dc-stupid | 58 + sim/ppc/dc-test.01 | 24 + sim/ppc/dc-test.02 | 24 + sim/ppc/debug.c | 153 + sim/ppc/debug.h | 172 + sim/ppc/device.c | 1998 ++++++ sim/ppc/device.h | 797 +++ sim/ppc/device_table.c | 310 + sim/ppc/device_table.h | 323 + sim/ppc/dgen.c | 336 + sim/ppc/double.c | 42 + sim/ppc/dp-bit.c | 1307 ++++ sim/ppc/emul_bugapi.c | 581 ++ sim/ppc/emul_bugapi.h | 27 + sim/ppc/emul_chirp.c | 2010 ++++++ sim/ppc/emul_chirp.h | 75 + sim/ppc/emul_generic.c | 343 + sim/ppc/emul_generic.h | 178 + sim/ppc/emul_netbsd.c | 1439 ++++ sim/ppc/emul_netbsd.h | 27 + sim/ppc/emul_unix.c | 2812 ++++++++ sim/ppc/emul_unix.h | 28 + sim/ppc/events.c | 387 + sim/ppc/events.h | 79 + sim/ppc/filter.c | 150 + sim/ppc/filter.h | 43 + sim/ppc/filter_filename.c | 38 + sim/ppc/filter_filename.h | 27 + sim/ppc/gen-icache.c | 675 ++ sim/ppc/gen-icache.h | 68 + sim/ppc/gen-idecode.c | 1545 ++++ sim/ppc/gen-idecode.h | 40 + sim/ppc/gen-itable.c | 122 + sim/ppc/gen-itable.h | 28 + sim/ppc/gen-model.c | 393 ++ sim/ppc/gen-model.h | 30 + sim/ppc/gen-semantics.c | 250 + sim/ppc/gen-semantics.h | 81 + sim/ppc/gen-support.c | 132 + sim/ppc/gen-support.h | 29 + sim/ppc/hw_com.c | 559 ++ sim/ppc/hw_core.c | 143 + sim/ppc/hw_cpu.c | 167 + sim/ppc/hw_cpu.h | 34 + sim/ppc/hw_disk.c | 557 ++ sim/ppc/hw_eeprom.c | 839 +++ sim/ppc/hw_glue.c | 371 + sim/ppc/hw_htab.c | 683 ++ sim/ppc/hw_ide.c | 869 +++ sim/ppc/hw_init.c | 721 ++ sim/ppc/hw_iobus.c | 100 + sim/ppc/hw_memory.c | 538 ++ sim/ppc/hw_nvram.c | 264 + sim/ppc/hw_opic.c | 1827 +++++ sim/ppc/hw_pal.c | 366 + sim/ppc/hw_phb.c | 1068 +++ sim/ppc/hw_phb.h | 40 + sim/ppc/hw_register.c | 131 + sim/ppc/hw_trace.c | 103 + sim/ppc/hw_vm.c | 275 + sim/ppc/idecode_branch.h | 62 + sim/ppc/idecode_expression.h | 410 ++ sim/ppc/idecode_fields.h | 105 + sim/ppc/igen.c | 516 ++ sim/ppc/igen.h | 199 + sim/ppc/inline.c | 98 + sim/ppc/inline.h | 490 ++ sim/ppc/interrupts.c | 545 ++ sim/ppc/interrupts.h | 172 + sim/ppc/ld-cache.c | 115 + sim/ppc/ld-cache.h | 81 + sim/ppc/ld-decode.c | 155 + sim/ppc/ld-decode.h | 143 + sim/ppc/ld-insn.c | 925 +++ sim/ppc/ld-insn.h | 281 + sim/ppc/lf.c | 440 ++ sim/ppc/lf.h | 129 + sim/ppc/main.c | 318 + sim/ppc/misc.c | 215 + sim/ppc/misc.h | 94 + sim/ppc/mon.c | 445 ++ sim/ppc/mon.h | 108 + sim/ppc/options.c | 247 + sim/ppc/options.h | 30 + sim/ppc/os_emul.c | 146 + sim/ppc/os_emul.h | 60 + sim/ppc/pk_disklabel.c | 401 ++ sim/ppc/ppc-cache-rules | 65 + sim/ppc/ppc-instructions | 4933 +++++++++++++ sim/ppc/ppc-spr-table | 88 + sim/ppc/ppc.mt | 3 + sim/ppc/psim.c | 1100 +++ sim/ppc/psim.h | 181 + sim/ppc/psim.texinfo | 1105 +++ sim/ppc/registers.c | 169 + sim/ppc/registers.h | 324 + sim/ppc/sim-endian-n.h | 134 + sim/ppc/sim-endian.c | 74 + sim/ppc/sim-endian.h | 409 ++ sim/ppc/sim_callbacks.h | 115 + sim/ppc/sim_calls.c | 445 ++ sim/ppc/std-config.h | 672 ++ sim/ppc/table.c | 279 + sim/ppc/table.h | 60 + sim/ppc/tree.c | 1256 ++++ sim/ppc/tree.h | 139 + sim/ppc/vm.c | 1198 ++++ sim/ppc/vm.h | 155 + sim/ppc/vm_n.h | 134 + sim/ppc/words.h | 116 + sim/sh/ChangeLog | 736 ++ sim/sh/Makefile.in | 41 + sim/sh/acconfig.h | 15 + sim/sh/config.in | 158 + sim/sh/configure | 3892 +++++++++++ sim/sh/configure.in | 10 + sim/sh/gencode.c | 1755 +++++ sim/sh/interp.c | 1414 ++++ sim/sh/syscall.h | 33 + sim/sh/tconfig.in | 17 + sim/testsuite/ChangeLog | 321 + sim/testsuite/Makefile.in | 182 + sim/testsuite/common/Make-common.in | 90 + sim/testsuite/common/Makefile.in | 53 + sim/testsuite/common/alu-n-tst.h | 260 + sim/testsuite/common/alu-tst.c | 104 + sim/testsuite/common/bits-gen.c | 319 + sim/testsuite/common/bits-tst.c | 408 ++ sim/testsuite/common/fpu-tst.c | 538 ++ sim/testsuite/config/default.exp | 42 + sim/testsuite/configure | 1022 +++ sim/testsuite/configure.in | 40 + sim/testsuite/d10v-elf/ChangeLog | 84 + sim/testsuite/d10v-elf/Makefile.in | 150 + sim/testsuite/d10v-elf/configure | 900 +++ sim/testsuite/d10v-elf/configure.in | 19 + sim/testsuite/d10v-elf/exit47.s | 4 + sim/testsuite/d10v-elf/hello.s | 5 + sim/testsuite/d10v-elf/loop.s | 6 + sim/testsuite/d10v-elf/t-dbt.s | 33 + sim/testsuite/d10v-elf/t-mac.s | 71 + sim/testsuite/d10v-elf/t-macros.i | 170 + sim/testsuite/d10v-elf/t-msbu.s | 28 + sim/testsuite/d10v-elf/t-mulxu.s | 28 + sim/testsuite/d10v-elf/t-mvtac.s | 19 + sim/testsuite/d10v-elf/t-mvtc.s | 81 + sim/testsuite/d10v-elf/t-rac.s | 16 + sim/testsuite/d10v-elf/t-rachi.s | 28 + sim/testsuite/d10v-elf/t-rdt.s | 18 + sim/testsuite/d10v-elf/t-rep.s | 45 + sim/testsuite/d10v-elf/t-rte.s | 18 + sim/testsuite/d10v-elf/t-sadd.s | 38 + sim/testsuite/d10v-elf/t-sp.s | 17 + sim/testsuite/d10v-elf/t-sub.s | 42 + sim/testsuite/d10v-elf/t-sub2w.s | 57 + sim/testsuite/d10v-elf/t-subi.s | 39 + sim/testsuite/d10v-elf/t-trap.s | 5 + sim/testsuite/d30v-elf/ChangeLog | 60 + sim/testsuite/d30v-elf/Makefile.in | 217 + sim/testsuite/d30v-elf/br-bra.S | 12 + sim/testsuite/d30v-elf/br-bratnz.S | 12 + sim/testsuite/d30v-elf/br-bratzr.S | 12 + sim/testsuite/d30v-elf/br-bsr.S | 12 + sim/testsuite/d30v-elf/br-dbra.S | 83 + sim/testsuite/d30v-elf/br-djmp.S | 83 + sim/testsuite/d30v-elf/br-djsr.S | 79 + sim/testsuite/d30v-elf/configure | 833 +++ sim/testsuite/d30v-elf/configure.in | 19 + sim/testsuite/d30v-elf/do-2wordops.S | 80 + sim/testsuite/d30v-elf/do-flags.S | 241 + sim/testsuite/d30v-elf/do-shifts.S | 182 + sim/testsuite/d30v-elf/em-e0.S | 4 + sim/testsuite/d30v-elf/em-e47.S | 4 + sim/testsuite/d30v-elf/em-pchr.S | 28 + sim/testsuite/d30v-elf/em-pstr.S | 8 + sim/testsuite/d30v-elf/exit47.s | 4 + sim/testsuite/d30v-elf/hello.s | 9 + sim/testsuite/d30v-elf/loop.s | 1 + sim/testsuite/d30v-elf/ls-ld2h.S | 11 + sim/testsuite/d30v-elf/ls-ld2w.S | 12 + sim/testsuite/d30v-elf/ls-ld4bh.S | 12 + sim/testsuite/d30v-elf/ls-ld4bhu.S | 11 + sim/testsuite/d30v-elf/ls-ldb.S | 11 + sim/testsuite/d30v-elf/ls-ldbu.S | 11 + sim/testsuite/d30v-elf/ls-ldh.S | 11 + sim/testsuite/d30v-elf/ls-ldhh.S | 11 + sim/testsuite/d30v-elf/ls-ldhu.S | 11 + sim/testsuite/d30v-elf/ls-ldw.S | 11 + sim/testsuite/d30v-elf/ls-modaddr.S | 56 + sim/testsuite/d30v-elf/ls-moddec.S | 3 + sim/testsuite/d30v-elf/ls-modinc.S | 3 + sim/testsuite/d30v-elf/ls-st2h.S | 13 + sim/testsuite/d30v-elf/ls-st2w.S | 13 + sim/testsuite/d30v-elf/ls-st4hb.S | 13 + sim/testsuite/d30v-elf/ls-stb.S | 12 + sim/testsuite/d30v-elf/ls-sth.S | 12 + sim/testsuite/d30v-elf/ls-sthh.S | 12 + sim/testsuite/d30v-elf/ls-stw.S | 12 + sim/testsuite/d30v-elf/os-dbt.S | 38 + sim/testsuite/d30v-elf/tick.s | 51 + sim/testsuite/d30v-elf/trap.S | 35 + sim/testsuite/fr30-elf/ChangeLog | 8 + sim/testsuite/fr30-elf/Makefile.in | 157 + sim/testsuite/fr30-elf/configure | 902 +++ sim/testsuite/fr30-elf/configure.in | 19 + sim/testsuite/fr30-elf/exit47.s | 7 + sim/testsuite/fr30-elf/hello.s | 15 + sim/testsuite/fr30-elf/loop.s | 2 + sim/testsuite/lib/sim-defs.exp | 318 + sim/testsuite/m32r-elf/ChangeLog | 4 + sim/testsuite/m32r-elf/Makefile.in | 157 + sim/testsuite/m32r-elf/configure | 902 +++ sim/testsuite/m32r-elf/configure.in | 19 + sim/testsuite/m32r-elf/exit47.s | 7 + sim/testsuite/m32r-elf/hello.s | 17 + sim/testsuite/m32r-elf/loop.s | 2 + sim/testsuite/mips64el-elf/ChangeLog | 5 + sim/testsuite/mips64el-elf/Makefile.in | 171 + sim/testsuite/mips64el-elf/configure | 904 +++ sim/testsuite/mips64el-elf/configure.in | 19 + sim/testsuite/sim/fr30/add.cgs | 55 + sim/testsuite/sim/fr30/add.ms | 13 + sim/testsuite/sim/fr30/add2.cgs | 43 + sim/testsuite/sim/fr30/addc.cgs | 50 + sim/testsuite/sim/fr30/addn.cgs | 55 + sim/testsuite/sim/fr30/addn2.cgs | 43 + sim/testsuite/sim/fr30/addsp.cgs | 31 + sim/testsuite/sim/fr30/allinsn.exp | 19 + sim/testsuite/sim/fr30/and.cgs | 51 + sim/testsuite/sim/fr30/andb.cgs | 31 + sim/testsuite/sim/fr30/andccr.cgs | 51 + sim/testsuite/sim/fr30/andh.cgs | 31 + sim/testsuite/sim/fr30/asr.cgs | 65 + sim/testsuite/sim/fr30/asr2.cgs | 36 + sim/testsuite/sim/fr30/bandh.cgs | 30 + sim/testsuite/sim/fr30/bandl.cgs | 30 + sim/testsuite/sim/fr30/bc.cgs | 109 + sim/testsuite/sim/fr30/beorh.cgs | 36 + sim/testsuite/sim/fr30/beorl.cgs | 36 + sim/testsuite/sim/fr30/beq.cgs | 109 + sim/testsuite/sim/fr30/bge.cgs | 109 + sim/testsuite/sim/fr30/bgt.cgs | 109 + sim/testsuite/sim/fr30/bhi.cgs | 109 + sim/testsuite/sim/fr30/ble.cgs | 109 + sim/testsuite/sim/fr30/bls.cgs | 109 + sim/testsuite/sim/fr30/blt.cgs | 109 + sim/testsuite/sim/fr30/bn.cgs | 109 + sim/testsuite/sim/fr30/bnc.cgs | 109 + sim/testsuite/sim/fr30/bne.cgs | 109 + sim/testsuite/sim/fr30/bno.cgs | 109 + sim/testsuite/sim/fr30/bnv.cgs | 109 + sim/testsuite/sim/fr30/borh.cgs | 30 + sim/testsuite/sim/fr30/borl.cgs | 30 + sim/testsuite/sim/fr30/bp.cgs | 109 + sim/testsuite/sim/fr30/bra.cgs | 109 + sim/testsuite/sim/fr30/btsth.cgs | 30 + sim/testsuite/sim/fr30/btstl.cgs | 30 + sim/testsuite/sim/fr30/bv.cgs | 109 + sim/testsuite/sim/fr30/call.cgs | 69 + sim/testsuite/sim/fr30/cmp.cgs | 53 + sim/testsuite/sim/fr30/cmp2.cgs | 27 + sim/testsuite/sim/fr30/copld.cgs | 21 + sim/testsuite/sim/fr30/copop.cgs | 21 + sim/testsuite/sim/fr30/copst.cgs | 21 + sim/testsuite/sim/fr30/copsv.cgs | 21 + sim/testsuite/sim/fr30/div.ms | 176 + sim/testsuite/sim/fr30/div0s.cgs | 64 + sim/testsuite/sim/fr30/div0u.cgs | 25 + sim/testsuite/sim/fr30/div1.cgs | 113 + sim/testsuite/sim/fr30/div2.cgs | 120 + sim/testsuite/sim/fr30/div3.cgs | 34 + sim/testsuite/sim/fr30/div4s.cgs | 34 + sim/testsuite/sim/fr30/dmov.cgs | 73 + sim/testsuite/sim/fr30/dmovb.cgs | 46 + sim/testsuite/sim/fr30/dmovh.cgs | 46 + sim/testsuite/sim/fr30/enter.cgs | 34 + sim/testsuite/sim/fr30/eor.cgs | 69 + sim/testsuite/sim/fr30/eorb.cgs | 40 + sim/testsuite/sim/fr30/eorh.cgs | 40 + sim/testsuite/sim/fr30/extsb.cgs | 36 + sim/testsuite/sim/fr30/extsh.cgs | 48 + sim/testsuite/sim/fr30/extub.cgs | 42 + sim/testsuite/sim/fr30/extuh.cgs | 54 + sim/testsuite/sim/fr30/hello.ms | 19 + sim/testsuite/sim/fr30/int.cgs | 35 + sim/testsuite/sim/fr30/inte.cgs | 36 + sim/testsuite/sim/fr30/jmp.cgs | 29 + sim/testsuite/sim/fr30/ld.cgs | 219 + sim/testsuite/sim/fr30/ldi20.cgs | 37 + sim/testsuite/sim/fr30/ldi32.cgs | 37 + sim/testsuite/sim/fr30/ldi8.cgs | 37 + sim/testsuite/sim/fr30/ldm0.cgs | 60 + sim/testsuite/sim/fr30/ldm1.cgs | 59 + sim/testsuite/sim/fr30/ldres.cgs | 25 + sim/testsuite/sim/fr30/ldub.cgs | 115 + sim/testsuite/sim/fr30/lduh.cgs | 115 + sim/testsuite/sim/fr30/leave.cgs | 23 + sim/testsuite/sim/fr30/lsl.cgs | 65 + sim/testsuite/sim/fr30/lsl2.cgs | 36 + sim/testsuite/sim/fr30/lsr.cgs | 65 + sim/testsuite/sim/fr30/lsr2.cgs | 36 + sim/testsuite/sim/fr30/misc.exp | 20 + sim/testsuite/sim/fr30/mov.cgs | 108 + sim/testsuite/sim/fr30/mul.cgs | 240 + sim/testsuite/sim/fr30/mulh.cgs | 211 + sim/testsuite/sim/fr30/mulu.cgs | 101 + sim/testsuite/sim/fr30/muluh.cgs | 90 + sim/testsuite/sim/fr30/nop.cgs | 16 + sim/testsuite/sim/fr30/or.cgs | 55 + sim/testsuite/sim/fr30/orb.cgs | 33 + sim/testsuite/sim/fr30/orccr.cgs | 38 + sim/testsuite/sim/fr30/orh.cgs | 33 + sim/testsuite/sim/fr30/ret.cgs | 75 + sim/testsuite/sim/fr30/reti.cgs | 57 + sim/testsuite/sim/fr30/st.cgs | 194 + sim/testsuite/sim/fr30/stb.cgs | 84 + sim/testsuite/sim/fr30/sth.cgs | 84 + sim/testsuite/sim/fr30/stilm.cgs | 41 + sim/testsuite/sim/fr30/stm0.cgs | 101 + sim/testsuite/sim/fr30/stm1.cgs | 97 + sim/testsuite/sim/fr30/stres.cgs | 25 + sim/testsuite/sim/fr30/sub.cgs | 36 + sim/testsuite/sim/fr30/subc.cgs | 62 + sim/testsuite/sim/fr30/subn.cgs | 36 + sim/testsuite/sim/fr30/testutils.inc | 306 + sim/testsuite/sim/fr30/xchb.cgs | 20 + sim/testsuite/sim/m32r/add.cgs | 16 + sim/testsuite/sim/m32r/add3.cgs | 15 + sim/testsuite/sim/m32r/addi.cgs | 16 + sim/testsuite/sim/m32r/addv.cgs | 21 + sim/testsuite/sim/m32r/addv3.cgs | 28 + sim/testsuite/sim/m32r/addx.cgs | 42 + sim/testsuite/sim/m32r/allinsn.exp | 21 + sim/testsuite/sim/m32r/and.cgs | 17 + sim/testsuite/sim/m32r/and3.cgs | 17 + sim/testsuite/sim/m32r/bc24.cgs | 24 + sim/testsuite/sim/m32r/bc8.cgs | 23 + sim/testsuite/sim/m32r/beq.cgs | 20 + sim/testsuite/sim/m32r/beqz.cgs | 18 + sim/testsuite/sim/m32r/bgez.cgs | 18 + sim/testsuite/sim/m32r/bgtz.cgs | 18 + sim/testsuite/sim/m32r/bl24.cgs | 18 + sim/testsuite/sim/m32r/bl8.cgs | 18 + sim/testsuite/sim/m32r/blez.cgs | 19 + sim/testsuite/sim/m32r/bltz.cgs | 19 + sim/testsuite/sim/m32r/bnc24.cgs | 20 + sim/testsuite/sim/m32r/bnc8.cgs | 20 + sim/testsuite/sim/m32r/bne.cgs | 20 + sim/testsuite/sim/m32r/bnez.cgs | 19 + sim/testsuite/sim/m32r/bra24.cgs | 15 + sim/testsuite/sim/m32r/bra8.cgs | 14 + sim/testsuite/sim/m32r/cmp.cgs | 23 + sim/testsuite/sim/m32r/cmpi.cgs | 24 + sim/testsuite/sim/m32r/cmpu.cgs | 23 + sim/testsuite/sim/m32r/cmpui.cgs | 22 + sim/testsuite/sim/m32r/div.cgs | 17 + sim/testsuite/sim/m32r/divu.cgs | 17 + sim/testsuite/sim/m32r/hello.ms | 19 + sim/testsuite/sim/m32r/hw-trap.ms | 31 + sim/testsuite/sim/m32r/jl.cgs | 18 + sim/testsuite/sim/m32r/jmp.cgs | 19 + sim/testsuite/sim/m32r/ld-d.cgs | 22 + sim/testsuite/sim/m32r/ld-plus.cgs | 28 + sim/testsuite/sim/m32r/ld.cgs | 21 + sim/testsuite/sim/m32r/ld24.cgs | 14 + sim/testsuite/sim/m32r/ldb-d.cgs | 20 + sim/testsuite/sim/m32r/ldb.cgs | 21 + sim/testsuite/sim/m32r/ldh-d.cgs | 21 + sim/testsuite/sim/m32r/ldh.cgs | 22 + sim/testsuite/sim/m32r/ldi16.cgs | 14 + sim/testsuite/sim/m32r/ldi8.cgs | 14 + sim/testsuite/sim/m32r/ldub-d.cgs | 21 + sim/testsuite/sim/m32r/ldub.cgs | 21 + sim/testsuite/sim/m32r/lduh-d.cgs | 20 + sim/testsuite/sim/m32r/lduh.cgs | 22 + sim/testsuite/sim/m32r/lock.cgs | 25 + sim/testsuite/sim/m32r/machi.cgs | 17 + sim/testsuite/sim/m32r/maclo.cgs | 17 + sim/testsuite/sim/m32r/macwhi.cgs | 18 + sim/testsuite/sim/m32r/macwlo.cgs | 18 + sim/testsuite/sim/m32r/misc.exp | 21 + sim/testsuite/sim/m32r/mul.cgs | 17 + sim/testsuite/sim/m32r/mulhi.cgs | 16 + sim/testsuite/sim/m32r/mullo.cgs | 16 + sim/testsuite/sim/m32r/mulwhi.cgs | 18 + sim/testsuite/sim/m32r/mulwlo.cgs | 18 + sim/testsuite/sim/m32r/mv.cgs | 17 + sim/testsuite/sim/m32r/mvfachi.cgs | 22 + sim/testsuite/sim/m32r/mvfaclo.cgs | 17 + sim/testsuite/sim/m32r/mvfacmi.cgs | 15 + sim/testsuite/sim/m32r/mvfc.cgs | 23 + sim/testsuite/sim/m32r/mvtachi.cgs | 20 + sim/testsuite/sim/m32r/mvtaclo.cgs | 17 + sim/testsuite/sim/m32r/mvtc.cgs | 18 + sim/testsuite/sim/m32r/neg.cgs | 17 + sim/testsuite/sim/m32r/nop.cgs | 10 + sim/testsuite/sim/m32r/not.cgs | 17 + sim/testsuite/sim/m32r/or.cgs | 17 + sim/testsuite/sim/m32r/or3.cgs | 17 + sim/testsuite/sim/m32r/rac.cgs | 23 + sim/testsuite/sim/m32r/rach.cgs | 22 + sim/testsuite/sim/m32r/rem.cgs | 17 + sim/testsuite/sim/m32r/remu.cgs | 23 + sim/testsuite/sim/m32r/rte.cgs | 87 + sim/testsuite/sim/m32r/seth.cgs | 20 + sim/testsuite/sim/m32r/sll.cgs | 15 + sim/testsuite/sim/m32r/sll3.cgs | 15 + sim/testsuite/sim/m32r/slli.cgs | 14 + sim/testsuite/sim/m32r/sra.cgs | 16 + sim/testsuite/sim/m32r/sra3.cgs | 16 + sim/testsuite/sim/m32r/srai.cgs | 14 + sim/testsuite/sim/m32r/srl.cgs | 15 + sim/testsuite/sim/m32r/srl3.cgs | 15 + sim/testsuite/sim/m32r/srli.cgs | 15 + sim/testsuite/sim/m32r/st-d.cgs | 26 + sim/testsuite/sim/m32r/st-minus.cgs | 29 + sim/testsuite/sim/m32r/st-plus.cgs | 28 + sim/testsuite/sim/m32r/st.cgs | 21 + sim/testsuite/sim/m32r/stb-d.cgs | 25 + sim/testsuite/sim/m32r/stb.cgs | 21 + sim/testsuite/sim/m32r/sth-d.cgs | 25 + sim/testsuite/sim/m32r/sth.cgs | 21 + sim/testsuite/sim/m32r/sub.cgs | 18 + sim/testsuite/sim/m32r/subv.cgs | 20 + sim/testsuite/sim/m32r/subx.cgs | 26 + sim/testsuite/sim/m32r/testutils.inc | 95 + sim/testsuite/sim/m32r/trap.cgs | 109 + sim/testsuite/sim/m32r/unlock.cgs | 30 + sim/testsuite/sim/m32r/uread16.ms | 18 + sim/testsuite/sim/m32r/uread32.ms | 18 + sim/testsuite/sim/m32r/uwrite16.ms | 18 + sim/testsuite/sim/m32r/uwrite32.ms | 18 + sim/testsuite/sim/m32r/xor.cgs | 16 + sim/testsuite/sim/m32r/xor3.cgs | 16 + sim/v850/ChangeLog | 1055 +++ sim/v850/Makefile.in | 142 + sim/v850/acconfig.h | 15 + sim/v850/config.in | 183 + sim/v850/configure | 4267 +++++++++++ sim/v850/configure.in | 18 + sim/v850/gencode.c | 149 + sim/v850/interp.c | 360 + sim/v850/sim-main.h | 388 + sim/v850/simops.c | 2733 ++++++++ sim/v850/v850-dc | 30 + sim/v850/v850.igen | 1407 ++++ sim/v850/v850_sim.h | 8 + sim/w65/ChangeLog | 136 + sim/w65/Makefile.in | 247 + sim/w65/acconfig.h | 18 + sim/w65/config.in | 131 + sim/w65/configure | 3333 +++++++++ sim/w65/configure.in | 48 + sim/w65/gencode.c | 991 +++ sim/w65/interp.c | 388 + sim/w65/interp.h | 194 + sim/w65/run.c | 131 + sim/z8k/ChangeLog | 470 ++ sim/z8k/Makefile.in | 66 + sim/z8k/acconfig.h | 15 + sim/z8k/comped1.c | 31 + sim/z8k/comped2.c | 25 + sim/z8k/comped3.c | 28 + sim/z8k/compedb3.c | 29 + sim/z8k/config.in | 161 + sim/z8k/configure | 3892 +++++++++++ sim/z8k/configure.in | 10 + sim/z8k/iface.c | 263 + sim/z8k/inlines.h | 486 ++ sim/z8k/list.c | 11266 ++++++++++++++++++++++++++++++ sim/z8k/mem.c | 126 + sim/z8k/mem.h | 8 + sim/z8k/quick.c | 783 +++ sim/z8k/sim.h | 9 + sim/z8k/support.c | 784 +++ sim/z8k/syscall.h | 43 + sim/z8k/tconfig.in | 13 + sim/z8k/tm.h | 192 + sim/z8k/writecode.c | 2011 ++++++ 904 files changed, 397352 insertions(+) create mode 100644 sim/ChangeLog create mode 100644 sim/Makefile.in create mode 100644 sim/README-HACKING create mode 100644 sim/arm/COPYING create mode 100644 sim/arm/ChangeLog create mode 100644 sim/arm/Makefile.in create mode 100644 sim/arm/README.Cygnus create mode 100644 sim/arm/acconfig.h create mode 100644 sim/arm/armcopro.c create mode 100644 sim/arm/armdefs.h create mode 100644 sim/arm/armemu.c create mode 100644 sim/arm/armemu.h create mode 100644 sim/arm/armfpe.h create mode 100644 sim/arm/arminit.c create mode 100644 sim/arm/armopts.h create mode 100644 sim/arm/armos.c create mode 100644 sim/arm/armos.h create mode 100644 sim/arm/armrdi.c create mode 100644 sim/arm/armsupp.c create mode 100644 sim/arm/armvirt.c create mode 100644 sim/arm/bag.c create mode 100644 sim/arm/bag.h create mode 100644 sim/arm/communicate.c create mode 100644 sim/arm/communicate.h create mode 100644 sim/arm/config.in create mode 100755 sim/arm/configure create mode 100644 sim/arm/configure.in create mode 100644 sim/arm/dbg_conf.h create mode 100644 sim/arm/dbg_cp.h create mode 100644 sim/arm/dbg_hif.h create mode 100644 sim/arm/dbg_rdi.h create mode 100644 sim/arm/gdbhost.c create mode 100644 sim/arm/gdbhost.h create mode 100644 sim/arm/kid.c create mode 100644 sim/arm/main.c create mode 100644 sim/arm/parent.c create mode 100644 sim/arm/tconfig.in create mode 100644 sim/arm/thumbemu.c create mode 100644 sim/arm/wrapper.c create mode 100644 sim/common/ChangeLog create mode 100644 sim/common/Make-common.in create mode 100644 sim/common/Makefile.in create mode 100644 sim/common/acconfig.h create mode 100644 sim/common/aclocal.m4 create mode 100644 sim/common/callback.c create mode 100644 sim/common/cgen-cpu.h create mode 100644 sim/common/cgen-defs.h create mode 100644 sim/common/cgen-engine.h create mode 100644 sim/common/cgen-mem.h create mode 100644 sim/common/cgen-ops.h create mode 100644 sim/common/cgen-run.c create mode 100644 sim/common/cgen-scache.c create mode 100644 sim/common/cgen-scache.h create mode 100644 sim/common/cgen-sim.h create mode 100644 sim/common/cgen-trace.c create mode 100644 sim/common/cgen-trace.h create mode 100644 sim/common/cgen-types.h create mode 100644 sim/common/cgen-utils.c create mode 100644 sim/common/config.in create mode 100755 sim/common/configure create mode 100644 sim/common/configure.in create mode 100644 sim/common/dv-core.c create mode 100644 sim/common/dv-glue.c create mode 100644 sim/common/dv-pal.c create mode 100644 sim/common/dv-sockser.c create mode 100644 sim/common/dv-sockser.h create mode 100644 sim/common/gdbinit.in create mode 100644 sim/common/genmloop.sh create mode 100644 sim/common/gennltvals.sh create mode 100644 sim/common/gentmap.c create mode 100644 sim/common/gentvals.sh create mode 100644 sim/common/hw-alloc.c create mode 100644 sim/common/hw-alloc.h create mode 100644 sim/common/hw-base.c create mode 100644 sim/common/hw-base.h create mode 100644 sim/common/hw-device.c create mode 100644 sim/common/hw-device.h create mode 100644 sim/common/hw-events.c create mode 100644 sim/common/hw-events.h create mode 100644 sim/common/hw-handles.c create mode 100644 sim/common/hw-handles.h create mode 100644 sim/common/hw-instances.c create mode 100644 sim/common/hw-instances.h create mode 100644 sim/common/hw-main.h create mode 100644 sim/common/hw-ports.c create mode 100644 sim/common/hw-ports.h create mode 100644 sim/common/hw-properties.c create mode 100644 sim/common/hw-properties.h create mode 100644 sim/common/hw-tree.c create mode 100644 sim/common/hw-tree.h create mode 100644 sim/common/nltvals.def create mode 100644 sim/common/nrun.c create mode 100644 sim/common/run.1 create mode 100644 sim/common/run.c create mode 100644 sim/common/sim-abort.c create mode 100644 sim/common/sim-alu.h create mode 100644 sim/common/sim-arange.c create mode 100644 sim/common/sim-arange.h create mode 100644 sim/common/sim-assert.h create mode 100644 sim/common/sim-base.h create mode 100644 sim/common/sim-basics.h create mode 100644 sim/common/sim-bits.c create mode 100644 sim/common/sim-bits.h create mode 100644 sim/common/sim-break.c create mode 100644 sim/common/sim-break.h create mode 100644 sim/common/sim-config.c create mode 100644 sim/common/sim-config.h create mode 100644 sim/common/sim-core.c create mode 100644 sim/common/sim-core.h create mode 100644 sim/common/sim-cpu.c create mode 100644 sim/common/sim-cpu.h create mode 100644 sim/common/sim-endian.c create mode 100644 sim/common/sim-endian.h create mode 100644 sim/common/sim-engine.c create mode 100644 sim/common/sim-engine.h create mode 100644 sim/common/sim-events.c create mode 100644 sim/common/sim-events.h create mode 100644 sim/common/sim-fpu.c create mode 100644 sim/common/sim-fpu.h create mode 100644 sim/common/sim-hload.c create mode 100644 sim/common/sim-hrw.c create mode 100644 sim/common/sim-hw.c create mode 100644 sim/common/sim-hw.h create mode 100644 sim/common/sim-info.c create mode 100644 sim/common/sim-inline.c create mode 100644 sim/common/sim-inline.h create mode 100644 sim/common/sim-io.c create mode 100644 sim/common/sim-io.h create mode 100644 sim/common/sim-load.c create mode 100644 sim/common/sim-memopt.c create mode 100644 sim/common/sim-memopt.h create mode 100644 sim/common/sim-model.c create mode 100644 sim/common/sim-model.h create mode 100644 sim/common/sim-module.c create mode 100644 sim/common/sim-module.h create mode 100644 sim/common/sim-n-bits.h create mode 100644 sim/common/sim-n-core.h create mode 100644 sim/common/sim-n-endian.h create mode 100644 sim/common/sim-options.c create mode 100644 sim/common/sim-options.h create mode 100644 sim/common/sim-profile.c create mode 100644 sim/common/sim-profile.h create mode 100644 sim/common/sim-reason.c create mode 100644 sim/common/sim-reg.c create mode 100644 sim/common/sim-resume.c create mode 100644 sim/common/sim-run.c create mode 100644 sim/common/sim-signal.c create mode 100644 sim/common/sim-signal.h create mode 100644 sim/common/sim-stop.c create mode 100644 sim/common/sim-trace.c create mode 100644 sim/common/sim-trace.h create mode 100644 sim/common/sim-types.h create mode 100644 sim/common/sim-utils.c create mode 100644 sim/common/sim-utils.h create mode 100644 sim/common/sim-watch.c create mode 100644 sim/common/sim-watch.h create mode 100644 sim/common/syscall.c create mode 100644 sim/common/tconfig.in create mode 100755 sim/configure create mode 100644 sim/configure.in create mode 100644 sim/d10v/ChangeLog create mode 100644 sim/d10v/Makefile.in create mode 100644 sim/d10v/acconfig.h create mode 100644 sim/d10v/config.in create mode 100755 sim/d10v/configure create mode 100644 sim/d10v/configure.in create mode 100644 sim/d10v/d10v_sim.h create mode 100644 sim/d10v/endian.c create mode 100644 sim/d10v/gencode.c create mode 100644 sim/d10v/interp.c create mode 100644 sim/d10v/simops.c create mode 100644 sim/d30v/ChangeLog create mode 100644 sim/d30v/Makefile.in create mode 100644 sim/d30v/acconfig.h create mode 100644 sim/d30v/alu.h create mode 100644 sim/d30v/config.in create mode 100755 sim/d30v/configure create mode 100644 sim/d30v/configure.in create mode 100644 sim/d30v/cpu.c create mode 100644 sim/d30v/cpu.h create mode 100644 sim/d30v/d30v-insns create mode 100644 sim/d30v/dc-short create mode 100644 sim/d30v/engine.c create mode 100644 sim/d30v/ic-d30v create mode 100644 sim/d30v/sim-calls.c create mode 100644 sim/d30v/sim-main.h create mode 100644 sim/d30v/tconfig.in create mode 100644 sim/erc32/ChangeLog create mode 100644 sim/erc32/Makefile.in create mode 100644 sim/erc32/NEWS create mode 100644 sim/erc32/README.erc32 create mode 100644 sim/erc32/README.gdb create mode 100644 sim/erc32/README.sis create mode 100644 sim/erc32/acconfig.h create mode 100644 sim/erc32/config.in create mode 100755 sim/erc32/configure create mode 100644 sim/erc32/configure.in create mode 100644 sim/erc32/end.c create mode 100644 sim/erc32/erc32.c create mode 100644 sim/erc32/exec.c create mode 100644 sim/erc32/float.c create mode 100644 sim/erc32/func.c create mode 100644 sim/erc32/help.c create mode 100644 sim/erc32/interf.c create mode 100644 sim/erc32/sis.c create mode 100644 sim/erc32/sis.h create mode 100644 sim/erc32/startsim create mode 100644 sim/fr30/ChangeLog create mode 100644 sim/fr30/Makefile.in create mode 100644 sim/fr30/README create mode 100644 sim/fr30/TODO create mode 100644 sim/fr30/arch.c create mode 100644 sim/fr30/arch.h create mode 100644 sim/fr30/config.in create mode 100644 sim/fr30/configure create mode 100644 sim/fr30/configure.in create mode 100644 sim/fr30/cpu.c create mode 100644 sim/fr30/cpu.h create mode 100644 sim/fr30/cpuall.h create mode 100644 sim/fr30/decode.c create mode 100644 sim/fr30/decode.h create mode 100644 sim/fr30/devices.c create mode 100644 sim/fr30/fr30-sim.h create mode 100644 sim/fr30/fr30.c create mode 100644 sim/fr30/mloop.in create mode 100644 sim/fr30/model.c create mode 100644 sim/fr30/sem-switch.c create mode 100644 sim/fr30/sem.c create mode 100644 sim/fr30/sim-if.c create mode 100644 sim/fr30/sim-main.h create mode 100644 sim/fr30/tconfig.in create mode 100644 sim/fr30/traps.c create mode 100644 sim/h8300/ChangeLog create mode 100644 sim/h8300/Makefile.in create mode 100644 sim/h8300/acconfig.h create mode 100644 sim/h8300/compile.c create mode 100644 sim/h8300/config.in create mode 100755 sim/h8300/configure create mode 100644 sim/h8300/configure.in create mode 100644 sim/h8300/inst.h create mode 100644 sim/h8300/tconfig.in create mode 100644 sim/h8300/writecode.c create mode 100644 sim/h8500/ChangeLog create mode 100644 sim/h8500/Makefile.in create mode 100644 sim/h8500/acconfig.h create mode 100644 sim/h8500/compile.c create mode 100644 sim/h8500/config.in create mode 100755 sim/h8500/configure create mode 100644 sim/h8500/configure.in create mode 100644 sim/h8500/inst.h create mode 100644 sim/h8500/tconfig.in create mode 100644 sim/i960/ChangeLog create mode 100644 sim/i960/Makefile.in create mode 100644 sim/i960/README create mode 100644 sim/i960/TODO create mode 100644 sim/i960/acconfig.h create mode 100644 sim/i960/arch.c create mode 100644 sim/i960/arch.h create mode 100644 sim/i960/config.in create mode 100755 sim/i960/configure create mode 100644 sim/i960/configure.in create mode 100644 sim/i960/cpu.c create mode 100644 sim/i960/cpu.h create mode 100644 sim/i960/cpuall.h create mode 100644 sim/i960/decode.c create mode 100644 sim/i960/decode.h create mode 100644 sim/i960/devices.c create mode 100644 sim/i960/i960-desc.c create mode 100644 sim/i960/i960-desc.h create mode 100644 sim/i960/i960-opc.h create mode 100644 sim/i960/i960-sim.h create mode 100644 sim/i960/i960.c create mode 100644 sim/i960/mloop.in create mode 100644 sim/i960/model.c create mode 100644 sim/i960/sem-switch.c create mode 100644 sim/i960/sem.c create mode 100644 sim/i960/sim-if.c create mode 100644 sim/i960/sim-main.h create mode 100644 sim/i960/tconfig.in create mode 100644 sim/i960/traps.c create mode 100644 sim/igen/ChangeLog create mode 100644 sim/igen/Makefile.in create mode 100644 sim/igen/acconfig.h create mode 100644 sim/igen/config.in create mode 100755 sim/igen/configure create mode 100644 sim/igen/configure.in create mode 100644 sim/igen/filter.c create mode 100644 sim/igen/filter.h create mode 100644 sim/igen/filter_host.c create mode 100644 sim/igen/filter_host.h create mode 100644 sim/igen/gen-engine.c create mode 100644 sim/igen/gen-engine.h create mode 100644 sim/igen/gen-icache.c create mode 100644 sim/igen/gen-icache.h create mode 100644 sim/igen/gen-idecode.c create mode 100644 sim/igen/gen-idecode.h create mode 100644 sim/igen/gen-itable.c create mode 100644 sim/igen/gen-itable.h create mode 100644 sim/igen/gen-model.c create mode 100644 sim/igen/gen-model.h create mode 100644 sim/igen/gen-semantics.c create mode 100644 sim/igen/gen-semantics.h create mode 100644 sim/igen/gen-support.c create mode 100644 sim/igen/gen-support.h create mode 100644 sim/igen/gen.c create mode 100644 sim/igen/gen.h create mode 100644 sim/igen/igen.c create mode 100644 sim/igen/igen.h create mode 100644 sim/igen/ld-cache.c create mode 100644 sim/igen/ld-cache.h create mode 100644 sim/igen/ld-decode.c create mode 100644 sim/igen/ld-decode.h create mode 100644 sim/igen/ld-insn.c create mode 100644 sim/igen/ld-insn.h create mode 100644 sim/igen/lf.c create mode 100644 sim/igen/lf.h create mode 100644 sim/igen/misc.c create mode 100644 sim/igen/misc.h create mode 100644 sim/igen/table.c create mode 100644 sim/igen/table.h create mode 100644 sim/m32r/ChangeLog create mode 100644 sim/m32r/Makefile.in create mode 100644 sim/m32r/README create mode 100644 sim/m32r/TODO create mode 100644 sim/m32r/acconfig.h create mode 100644 sim/m32r/arch.c create mode 100644 sim/m32r/arch.h create mode 100644 sim/m32r/config.in create mode 100755 sim/m32r/configure create mode 100644 sim/m32r/configure.in create mode 100644 sim/m32r/cpu.c create mode 100644 sim/m32r/cpu.h create mode 100644 sim/m32r/cpuall.h create mode 100644 sim/m32r/decode.c create mode 100644 sim/m32r/decode.h create mode 100644 sim/m32r/devices.c create mode 100644 sim/m32r/m32r-sim.h create mode 100644 sim/m32r/m32r.c create mode 100644 sim/m32r/mloop.in create mode 100644 sim/m32r/model.c create mode 100644 sim/m32r/sem-switch.c create mode 100644 sim/m32r/sem.c create mode 100644 sim/m32r/sim-if.c create mode 100644 sim/m32r/sim-main.h create mode 100644 sim/m32r/tconfig.in create mode 100644 sim/m32r/traps.c create mode 100644 sim/mips/ChangeLog create mode 100644 sim/mips/Makefile.in create mode 100644 sim/mips/acconfig.h create mode 100644 sim/mips/config.in create mode 100755 sim/mips/configure create mode 100644 sim/mips/configure.in create mode 100644 sim/mips/dv-tx3904cpu.c create mode 100644 sim/mips/dv-tx3904irc.c create mode 100644 sim/mips/dv-tx3904sio.c create mode 100644 sim/mips/dv-tx3904tmr.c create mode 100644 sim/mips/interp.c create mode 100644 sim/mips/m16.dc create mode 100644 sim/mips/m16.igen create mode 100644 sim/mips/m16run.c create mode 100644 sim/mips/mips.dc create mode 100644 sim/mips/mips.igen create mode 100644 sim/mips/sim-main.c create mode 100644 sim/mips/sim-main.h create mode 100644 sim/mips/tconfig.in create mode 100644 sim/mips/tx.igen create mode 100644 sim/mips/vr.igen create mode 100644 sim/mn10200/ChangeLog create mode 100644 sim/mn10200/Makefile.in create mode 100644 sim/mn10200/acconfig.h create mode 100644 sim/mn10200/config.in create mode 100755 sim/mn10200/configure create mode 100644 sim/mn10200/configure.in create mode 100644 sim/mn10200/gencode.c create mode 100644 sim/mn10200/interp.c create mode 100644 sim/mn10200/mn10200_sim.h create mode 100644 sim/mn10200/simops.c create mode 100644 sim/mn10300/ChangeLog create mode 100644 sim/mn10300/Makefile.in create mode 100644 sim/mn10300/acconfig.h create mode 100644 sim/mn10300/config.in create mode 100755 sim/mn10300/configure create mode 100644 sim/mn10300/configure.in create mode 100644 sim/mn10300/dv-mn103cpu.c create mode 100644 sim/mn10300/dv-mn103int.c create mode 100644 sim/mn10300/dv-mn103iop.c create mode 100644 sim/mn10300/dv-mn103ser.c create mode 100644 sim/mn10300/dv-mn103tim.c create mode 100644 sim/mn10300/gencode.c create mode 100644 sim/mn10300/interp.c create mode 100644 sim/mn10300/mn10300.dc create mode 100644 sim/mn10300/mn10300.igen create mode 100644 sim/mn10300/mn10300_sim.h create mode 100644 sim/mn10300/op_utils.c create mode 100644 sim/mn10300/sim-main.c create mode 100644 sim/mn10300/sim-main.h create mode 100644 sim/mn10300/simops.c create mode 100644 sim/mn10300/tconfig.in create mode 100644 sim/ppc/.gdbinit create mode 100644 sim/ppc/BUGS create mode 100644 sim/ppc/COPYING create mode 100644 sim/ppc/COPYING.LIB create mode 100644 sim/ppc/ChangeLog create mode 100644 sim/ppc/ChangeLog.00 create mode 100644 sim/ppc/INSTALL create mode 100644 sim/ppc/Makefile.in create mode 100644 sim/ppc/README create mode 100644 sim/ppc/RUN create mode 100644 sim/ppc/acconfig.h create mode 100644 sim/ppc/aclocal.m4 create mode 100644 sim/ppc/basics.h create mode 100644 sim/ppc/bits.c create mode 100644 sim/ppc/bits.h create mode 100644 sim/ppc/cap.c create mode 100644 sim/ppc/cap.h create mode 100644 sim/ppc/config.in create mode 100755 sim/ppc/configure create mode 100644 sim/ppc/configure.in create mode 100644 sim/ppc/corefile-n.h create mode 100644 sim/ppc/corefile.c create mode 100644 sim/ppc/corefile.h create mode 100644 sim/ppc/cpu.c create mode 100644 sim/ppc/cpu.h create mode 100644 sim/ppc/dc-complex create mode 100644 sim/ppc/dc-simple create mode 100644 sim/ppc/dc-stupid create mode 100644 sim/ppc/dc-test.01 create mode 100644 sim/ppc/dc-test.02 create mode 100644 sim/ppc/debug.c create mode 100644 sim/ppc/debug.h create mode 100644 sim/ppc/device.c create mode 100644 sim/ppc/device.h create mode 100644 sim/ppc/device_table.c create mode 100644 sim/ppc/device_table.h create mode 100644 sim/ppc/dgen.c create mode 100644 sim/ppc/double.c create mode 100644 sim/ppc/dp-bit.c create mode 100644 sim/ppc/emul_bugapi.c create mode 100644 sim/ppc/emul_bugapi.h create mode 100644 sim/ppc/emul_chirp.c create mode 100644 sim/ppc/emul_chirp.h create mode 100644 sim/ppc/emul_generic.c create mode 100644 sim/ppc/emul_generic.h create mode 100644 sim/ppc/emul_netbsd.c create mode 100644 sim/ppc/emul_netbsd.h create mode 100644 sim/ppc/emul_unix.c create mode 100644 sim/ppc/emul_unix.h create mode 100644 sim/ppc/events.c create mode 100644 sim/ppc/events.h create mode 100644 sim/ppc/filter.c create mode 100644 sim/ppc/filter.h create mode 100644 sim/ppc/filter_filename.c create mode 100644 sim/ppc/filter_filename.h create mode 100644 sim/ppc/gen-icache.c create mode 100644 sim/ppc/gen-icache.h create mode 100644 sim/ppc/gen-idecode.c create mode 100644 sim/ppc/gen-idecode.h create mode 100644 sim/ppc/gen-itable.c create mode 100644 sim/ppc/gen-itable.h create mode 100644 sim/ppc/gen-model.c create mode 100644 sim/ppc/gen-model.h create mode 100644 sim/ppc/gen-semantics.c create mode 100644 sim/ppc/gen-semantics.h create mode 100644 sim/ppc/gen-support.c create mode 100644 sim/ppc/gen-support.h create mode 100644 sim/ppc/hw_com.c create mode 100644 sim/ppc/hw_core.c create mode 100644 sim/ppc/hw_cpu.c create mode 100644 sim/ppc/hw_cpu.h create mode 100644 sim/ppc/hw_disk.c create mode 100644 sim/ppc/hw_eeprom.c create mode 100644 sim/ppc/hw_glue.c create mode 100644 sim/ppc/hw_htab.c create mode 100644 sim/ppc/hw_ide.c create mode 100644 sim/ppc/hw_init.c create mode 100644 sim/ppc/hw_iobus.c create mode 100644 sim/ppc/hw_memory.c create mode 100644 sim/ppc/hw_nvram.c create mode 100644 sim/ppc/hw_opic.c create mode 100644 sim/ppc/hw_pal.c create mode 100644 sim/ppc/hw_phb.c create mode 100644 sim/ppc/hw_phb.h create mode 100644 sim/ppc/hw_register.c create mode 100644 sim/ppc/hw_trace.c create mode 100644 sim/ppc/hw_vm.c create mode 100644 sim/ppc/idecode_branch.h create mode 100644 sim/ppc/idecode_expression.h create mode 100644 sim/ppc/idecode_fields.h create mode 100644 sim/ppc/igen.c create mode 100644 sim/ppc/igen.h create mode 100644 sim/ppc/inline.c create mode 100644 sim/ppc/inline.h create mode 100644 sim/ppc/interrupts.c create mode 100644 sim/ppc/interrupts.h create mode 100644 sim/ppc/ld-cache.c create mode 100644 sim/ppc/ld-cache.h create mode 100644 sim/ppc/ld-decode.c create mode 100644 sim/ppc/ld-decode.h create mode 100644 sim/ppc/ld-insn.c create mode 100644 sim/ppc/ld-insn.h create mode 100644 sim/ppc/lf.c create mode 100644 sim/ppc/lf.h create mode 100644 sim/ppc/main.c create mode 100644 sim/ppc/misc.c create mode 100644 sim/ppc/misc.h create mode 100644 sim/ppc/mon.c create mode 100644 sim/ppc/mon.h create mode 100644 sim/ppc/options.c create mode 100644 sim/ppc/options.h create mode 100644 sim/ppc/os_emul.c create mode 100644 sim/ppc/os_emul.h create mode 100644 sim/ppc/pk_disklabel.c create mode 100644 sim/ppc/ppc-cache-rules create mode 100644 sim/ppc/ppc-instructions create mode 100644 sim/ppc/ppc-spr-table create mode 100644 sim/ppc/ppc.mt create mode 100644 sim/ppc/psim.c create mode 100644 sim/ppc/psim.h create mode 100644 sim/ppc/psim.texinfo create mode 100644 sim/ppc/registers.c create mode 100644 sim/ppc/registers.h create mode 100644 sim/ppc/sim-endian-n.h create mode 100644 sim/ppc/sim-endian.c create mode 100644 sim/ppc/sim-endian.h create mode 100644 sim/ppc/sim_callbacks.h create mode 100644 sim/ppc/sim_calls.c create mode 100644 sim/ppc/std-config.h create mode 100644 sim/ppc/table.c create mode 100644 sim/ppc/table.h create mode 100644 sim/ppc/tree.c create mode 100644 sim/ppc/tree.h create mode 100644 sim/ppc/vm.c create mode 100644 sim/ppc/vm.h create mode 100644 sim/ppc/vm_n.h create mode 100644 sim/ppc/words.h create mode 100644 sim/sh/ChangeLog create mode 100644 sim/sh/Makefile.in create mode 100644 sim/sh/acconfig.h create mode 100644 sim/sh/config.in create mode 100755 sim/sh/configure create mode 100644 sim/sh/configure.in create mode 100644 sim/sh/gencode.c create mode 100644 sim/sh/interp.c create mode 100644 sim/sh/syscall.h create mode 100644 sim/sh/tconfig.in create mode 100644 sim/testsuite/ChangeLog create mode 100644 sim/testsuite/Makefile.in create mode 100644 sim/testsuite/common/Make-common.in create mode 100644 sim/testsuite/common/Makefile.in create mode 100644 sim/testsuite/common/alu-n-tst.h create mode 100644 sim/testsuite/common/alu-tst.c create mode 100644 sim/testsuite/common/bits-gen.c create mode 100644 sim/testsuite/common/bits-tst.c create mode 100644 sim/testsuite/common/fpu-tst.c create mode 100644 sim/testsuite/config/default.exp create mode 100755 sim/testsuite/configure create mode 100644 sim/testsuite/configure.in create mode 100644 sim/testsuite/d10v-elf/ChangeLog create mode 100644 sim/testsuite/d10v-elf/Makefile.in create mode 100755 sim/testsuite/d10v-elf/configure create mode 100644 sim/testsuite/d10v-elf/configure.in create mode 100644 sim/testsuite/d10v-elf/exit47.s create mode 100644 sim/testsuite/d10v-elf/hello.s create mode 100644 sim/testsuite/d10v-elf/loop.s create mode 100644 sim/testsuite/d10v-elf/t-dbt.s create mode 100644 sim/testsuite/d10v-elf/t-mac.s create mode 100644 sim/testsuite/d10v-elf/t-macros.i create mode 100644 sim/testsuite/d10v-elf/t-msbu.s create mode 100644 sim/testsuite/d10v-elf/t-mulxu.s create mode 100644 sim/testsuite/d10v-elf/t-mvtac.s create mode 100644 sim/testsuite/d10v-elf/t-mvtc.s create mode 100644 sim/testsuite/d10v-elf/t-rac.s create mode 100644 sim/testsuite/d10v-elf/t-rachi.s create mode 100644 sim/testsuite/d10v-elf/t-rdt.s create mode 100644 sim/testsuite/d10v-elf/t-rep.s create mode 100644 sim/testsuite/d10v-elf/t-rte.s create mode 100644 sim/testsuite/d10v-elf/t-sadd.s create mode 100644 sim/testsuite/d10v-elf/t-sp.s create mode 100644 sim/testsuite/d10v-elf/t-sub.s create mode 100644 sim/testsuite/d10v-elf/t-sub2w.s create mode 100644 sim/testsuite/d10v-elf/t-subi.s create mode 100644 sim/testsuite/d10v-elf/t-trap.s create mode 100644 sim/testsuite/d30v-elf/ChangeLog create mode 100644 sim/testsuite/d30v-elf/Makefile.in create mode 100644 sim/testsuite/d30v-elf/br-bra.S create mode 100644 sim/testsuite/d30v-elf/br-bratnz.S create mode 100644 sim/testsuite/d30v-elf/br-bratzr.S create mode 100644 sim/testsuite/d30v-elf/br-bsr.S create mode 100644 sim/testsuite/d30v-elf/br-dbra.S create mode 100644 sim/testsuite/d30v-elf/br-djmp.S create mode 100644 sim/testsuite/d30v-elf/br-djsr.S create mode 100755 sim/testsuite/d30v-elf/configure create mode 100644 sim/testsuite/d30v-elf/configure.in create mode 100644 sim/testsuite/d30v-elf/do-2wordops.S create mode 100644 sim/testsuite/d30v-elf/do-flags.S create mode 100644 sim/testsuite/d30v-elf/do-shifts.S create mode 100644 sim/testsuite/d30v-elf/em-e0.S create mode 100644 sim/testsuite/d30v-elf/em-e47.S create mode 100644 sim/testsuite/d30v-elf/em-pchr.S create mode 100644 sim/testsuite/d30v-elf/em-pstr.S create mode 100644 sim/testsuite/d30v-elf/exit47.s create mode 100644 sim/testsuite/d30v-elf/hello.s create mode 100644 sim/testsuite/d30v-elf/loop.s create mode 100644 sim/testsuite/d30v-elf/ls-ld2h.S create mode 100644 sim/testsuite/d30v-elf/ls-ld2w.S create mode 100644 sim/testsuite/d30v-elf/ls-ld4bh.S create mode 100644 sim/testsuite/d30v-elf/ls-ld4bhu.S create mode 100644 sim/testsuite/d30v-elf/ls-ldb.S create mode 100644 sim/testsuite/d30v-elf/ls-ldbu.S create mode 100644 sim/testsuite/d30v-elf/ls-ldh.S create mode 100644 sim/testsuite/d30v-elf/ls-ldhh.S create mode 100644 sim/testsuite/d30v-elf/ls-ldhu.S create mode 100644 sim/testsuite/d30v-elf/ls-ldw.S create mode 100644 sim/testsuite/d30v-elf/ls-modaddr.S create mode 100644 sim/testsuite/d30v-elf/ls-moddec.S create mode 100644 sim/testsuite/d30v-elf/ls-modinc.S create mode 100644 sim/testsuite/d30v-elf/ls-st2h.S create mode 100644 sim/testsuite/d30v-elf/ls-st2w.S create mode 100644 sim/testsuite/d30v-elf/ls-st4hb.S create mode 100644 sim/testsuite/d30v-elf/ls-stb.S create mode 100644 sim/testsuite/d30v-elf/ls-sth.S create mode 100644 sim/testsuite/d30v-elf/ls-sthh.S create mode 100644 sim/testsuite/d30v-elf/ls-stw.S create mode 100644 sim/testsuite/d30v-elf/os-dbt.S create mode 100644 sim/testsuite/d30v-elf/tick.s create mode 100644 sim/testsuite/d30v-elf/trap.S create mode 100644 sim/testsuite/fr30-elf/ChangeLog create mode 100644 sim/testsuite/fr30-elf/Makefile.in create mode 100755 sim/testsuite/fr30-elf/configure create mode 100644 sim/testsuite/fr30-elf/configure.in create mode 100644 sim/testsuite/fr30-elf/exit47.s create mode 100644 sim/testsuite/fr30-elf/hello.s create mode 100644 sim/testsuite/fr30-elf/loop.s create mode 100644 sim/testsuite/lib/sim-defs.exp create mode 100644 sim/testsuite/m32r-elf/ChangeLog create mode 100644 sim/testsuite/m32r-elf/Makefile.in create mode 100755 sim/testsuite/m32r-elf/configure create mode 100644 sim/testsuite/m32r-elf/configure.in create mode 100644 sim/testsuite/m32r-elf/exit47.s create mode 100644 sim/testsuite/m32r-elf/hello.s create mode 100644 sim/testsuite/m32r-elf/loop.s create mode 100644 sim/testsuite/mips64el-elf/ChangeLog create mode 100644 sim/testsuite/mips64el-elf/Makefile.in create mode 100755 sim/testsuite/mips64el-elf/configure create mode 100644 sim/testsuite/mips64el-elf/configure.in create mode 100644 sim/testsuite/sim/fr30/add.cgs create mode 100644 sim/testsuite/sim/fr30/add.ms create mode 100644 sim/testsuite/sim/fr30/add2.cgs create mode 100644 sim/testsuite/sim/fr30/addc.cgs create mode 100644 sim/testsuite/sim/fr30/addn.cgs create mode 100644 sim/testsuite/sim/fr30/addn2.cgs create mode 100644 sim/testsuite/sim/fr30/addsp.cgs create mode 100644 sim/testsuite/sim/fr30/allinsn.exp create mode 100644 sim/testsuite/sim/fr30/and.cgs create mode 100644 sim/testsuite/sim/fr30/andb.cgs create mode 100644 sim/testsuite/sim/fr30/andccr.cgs create mode 100644 sim/testsuite/sim/fr30/andh.cgs create mode 100644 sim/testsuite/sim/fr30/asr.cgs create mode 100644 sim/testsuite/sim/fr30/asr2.cgs create mode 100644 sim/testsuite/sim/fr30/bandh.cgs create mode 100644 sim/testsuite/sim/fr30/bandl.cgs create mode 100644 sim/testsuite/sim/fr30/bc.cgs create mode 100644 sim/testsuite/sim/fr30/beorh.cgs create mode 100644 sim/testsuite/sim/fr30/beorl.cgs create mode 100644 sim/testsuite/sim/fr30/beq.cgs create mode 100644 sim/testsuite/sim/fr30/bge.cgs create mode 100644 sim/testsuite/sim/fr30/bgt.cgs create mode 100644 sim/testsuite/sim/fr30/bhi.cgs create mode 100644 sim/testsuite/sim/fr30/ble.cgs create mode 100644 sim/testsuite/sim/fr30/bls.cgs create mode 100644 sim/testsuite/sim/fr30/blt.cgs create mode 100644 sim/testsuite/sim/fr30/bn.cgs create mode 100644 sim/testsuite/sim/fr30/bnc.cgs create mode 100644 sim/testsuite/sim/fr30/bne.cgs create mode 100644 sim/testsuite/sim/fr30/bno.cgs create mode 100644 sim/testsuite/sim/fr30/bnv.cgs create mode 100644 sim/testsuite/sim/fr30/borh.cgs create mode 100644 sim/testsuite/sim/fr30/borl.cgs create mode 100644 sim/testsuite/sim/fr30/bp.cgs create mode 100644 sim/testsuite/sim/fr30/bra.cgs create mode 100644 sim/testsuite/sim/fr30/btsth.cgs create mode 100644 sim/testsuite/sim/fr30/btstl.cgs create mode 100644 sim/testsuite/sim/fr30/bv.cgs create mode 100644 sim/testsuite/sim/fr30/call.cgs create mode 100644 sim/testsuite/sim/fr30/cmp.cgs create mode 100644 sim/testsuite/sim/fr30/cmp2.cgs create mode 100644 sim/testsuite/sim/fr30/copld.cgs create mode 100644 sim/testsuite/sim/fr30/copop.cgs create mode 100644 sim/testsuite/sim/fr30/copst.cgs create mode 100644 sim/testsuite/sim/fr30/copsv.cgs create mode 100644 sim/testsuite/sim/fr30/div.ms create mode 100644 sim/testsuite/sim/fr30/div0s.cgs create mode 100644 sim/testsuite/sim/fr30/div0u.cgs create mode 100644 sim/testsuite/sim/fr30/div1.cgs create mode 100644 sim/testsuite/sim/fr30/div2.cgs create mode 100644 sim/testsuite/sim/fr30/div3.cgs create mode 100644 sim/testsuite/sim/fr30/div4s.cgs create mode 100644 sim/testsuite/sim/fr30/dmov.cgs create mode 100644 sim/testsuite/sim/fr30/dmovb.cgs create mode 100644 sim/testsuite/sim/fr30/dmovh.cgs create mode 100644 sim/testsuite/sim/fr30/enter.cgs create mode 100644 sim/testsuite/sim/fr30/eor.cgs create mode 100644 sim/testsuite/sim/fr30/eorb.cgs create mode 100644 sim/testsuite/sim/fr30/eorh.cgs create mode 100644 sim/testsuite/sim/fr30/extsb.cgs create mode 100644 sim/testsuite/sim/fr30/extsh.cgs create mode 100644 sim/testsuite/sim/fr30/extub.cgs create mode 100644 sim/testsuite/sim/fr30/extuh.cgs create mode 100644 sim/testsuite/sim/fr30/hello.ms create mode 100644 sim/testsuite/sim/fr30/int.cgs create mode 100644 sim/testsuite/sim/fr30/inte.cgs create mode 100644 sim/testsuite/sim/fr30/jmp.cgs create mode 100644 sim/testsuite/sim/fr30/ld.cgs create mode 100644 sim/testsuite/sim/fr30/ldi20.cgs create mode 100644 sim/testsuite/sim/fr30/ldi32.cgs create mode 100644 sim/testsuite/sim/fr30/ldi8.cgs create mode 100644 sim/testsuite/sim/fr30/ldm0.cgs create mode 100644 sim/testsuite/sim/fr30/ldm1.cgs create mode 100644 sim/testsuite/sim/fr30/ldres.cgs create mode 100644 sim/testsuite/sim/fr30/ldub.cgs create mode 100644 sim/testsuite/sim/fr30/lduh.cgs create mode 100644 sim/testsuite/sim/fr30/leave.cgs create mode 100644 sim/testsuite/sim/fr30/lsl.cgs create mode 100644 sim/testsuite/sim/fr30/lsl2.cgs create mode 100644 sim/testsuite/sim/fr30/lsr.cgs create mode 100644 sim/testsuite/sim/fr30/lsr2.cgs create mode 100644 sim/testsuite/sim/fr30/misc.exp create mode 100644 sim/testsuite/sim/fr30/mov.cgs create mode 100644 sim/testsuite/sim/fr30/mul.cgs create mode 100644 sim/testsuite/sim/fr30/mulh.cgs create mode 100644 sim/testsuite/sim/fr30/mulu.cgs create mode 100644 sim/testsuite/sim/fr30/muluh.cgs create mode 100644 sim/testsuite/sim/fr30/nop.cgs create mode 100644 sim/testsuite/sim/fr30/or.cgs create mode 100644 sim/testsuite/sim/fr30/orb.cgs create mode 100644 sim/testsuite/sim/fr30/orccr.cgs create mode 100644 sim/testsuite/sim/fr30/orh.cgs create mode 100644 sim/testsuite/sim/fr30/ret.cgs create mode 100644 sim/testsuite/sim/fr30/reti.cgs create mode 100644 sim/testsuite/sim/fr30/st.cgs create mode 100644 sim/testsuite/sim/fr30/stb.cgs create mode 100644 sim/testsuite/sim/fr30/sth.cgs create mode 100644 sim/testsuite/sim/fr30/stilm.cgs create mode 100644 sim/testsuite/sim/fr30/stm0.cgs create mode 100644 sim/testsuite/sim/fr30/stm1.cgs create mode 100644 sim/testsuite/sim/fr30/stres.cgs create mode 100644 sim/testsuite/sim/fr30/sub.cgs create mode 100644 sim/testsuite/sim/fr30/subc.cgs create mode 100644 sim/testsuite/sim/fr30/subn.cgs create mode 100644 sim/testsuite/sim/fr30/testutils.inc create mode 100644 sim/testsuite/sim/fr30/xchb.cgs create mode 100644 sim/testsuite/sim/m32r/add.cgs create mode 100644 sim/testsuite/sim/m32r/add3.cgs create mode 100644 sim/testsuite/sim/m32r/addi.cgs create mode 100644 sim/testsuite/sim/m32r/addv.cgs create mode 100644 sim/testsuite/sim/m32r/addv3.cgs create mode 100644 sim/testsuite/sim/m32r/addx.cgs create mode 100644 sim/testsuite/sim/m32r/allinsn.exp create mode 100644 sim/testsuite/sim/m32r/and.cgs create mode 100644 sim/testsuite/sim/m32r/and3.cgs create mode 100644 sim/testsuite/sim/m32r/bc24.cgs create mode 100644 sim/testsuite/sim/m32r/bc8.cgs create mode 100644 sim/testsuite/sim/m32r/beq.cgs create mode 100644 sim/testsuite/sim/m32r/beqz.cgs create mode 100644 sim/testsuite/sim/m32r/bgez.cgs create mode 100644 sim/testsuite/sim/m32r/bgtz.cgs create mode 100644 sim/testsuite/sim/m32r/bl24.cgs create mode 100644 sim/testsuite/sim/m32r/bl8.cgs create mode 100644 sim/testsuite/sim/m32r/blez.cgs create mode 100644 sim/testsuite/sim/m32r/bltz.cgs create mode 100644 sim/testsuite/sim/m32r/bnc24.cgs create mode 100644 sim/testsuite/sim/m32r/bnc8.cgs create mode 100644 sim/testsuite/sim/m32r/bne.cgs create mode 100644 sim/testsuite/sim/m32r/bnez.cgs create mode 100644 sim/testsuite/sim/m32r/bra24.cgs create mode 100644 sim/testsuite/sim/m32r/bra8.cgs create mode 100644 sim/testsuite/sim/m32r/cmp.cgs create mode 100644 sim/testsuite/sim/m32r/cmpi.cgs create mode 100644 sim/testsuite/sim/m32r/cmpu.cgs create mode 100644 sim/testsuite/sim/m32r/cmpui.cgs create mode 100644 sim/testsuite/sim/m32r/div.cgs create mode 100644 sim/testsuite/sim/m32r/divu.cgs create mode 100644 sim/testsuite/sim/m32r/hello.ms create mode 100644 sim/testsuite/sim/m32r/hw-trap.ms create mode 100644 sim/testsuite/sim/m32r/jl.cgs create mode 100644 sim/testsuite/sim/m32r/jmp.cgs create mode 100644 sim/testsuite/sim/m32r/ld-d.cgs create mode 100644 sim/testsuite/sim/m32r/ld-plus.cgs create mode 100644 sim/testsuite/sim/m32r/ld.cgs create mode 100644 sim/testsuite/sim/m32r/ld24.cgs create mode 100644 sim/testsuite/sim/m32r/ldb-d.cgs create mode 100644 sim/testsuite/sim/m32r/ldb.cgs create mode 100644 sim/testsuite/sim/m32r/ldh-d.cgs create mode 100644 sim/testsuite/sim/m32r/ldh.cgs create mode 100644 sim/testsuite/sim/m32r/ldi16.cgs create mode 100644 sim/testsuite/sim/m32r/ldi8.cgs create mode 100644 sim/testsuite/sim/m32r/ldub-d.cgs create mode 100644 sim/testsuite/sim/m32r/ldub.cgs create mode 100644 sim/testsuite/sim/m32r/lduh-d.cgs create mode 100644 sim/testsuite/sim/m32r/lduh.cgs create mode 100644 sim/testsuite/sim/m32r/lock.cgs create mode 100644 sim/testsuite/sim/m32r/machi.cgs create mode 100644 sim/testsuite/sim/m32r/maclo.cgs create mode 100644 sim/testsuite/sim/m32r/macwhi.cgs create mode 100644 sim/testsuite/sim/m32r/macwlo.cgs create mode 100644 sim/testsuite/sim/m32r/misc.exp create mode 100644 sim/testsuite/sim/m32r/mul.cgs create mode 100644 sim/testsuite/sim/m32r/mulhi.cgs create mode 100644 sim/testsuite/sim/m32r/mullo.cgs create mode 100644 sim/testsuite/sim/m32r/mulwhi.cgs create mode 100644 sim/testsuite/sim/m32r/mulwlo.cgs create mode 100644 sim/testsuite/sim/m32r/mv.cgs create mode 100644 sim/testsuite/sim/m32r/mvfachi.cgs create mode 100644 sim/testsuite/sim/m32r/mvfaclo.cgs create mode 100644 sim/testsuite/sim/m32r/mvfacmi.cgs create mode 100644 sim/testsuite/sim/m32r/mvfc.cgs create mode 100644 sim/testsuite/sim/m32r/mvtachi.cgs create mode 100644 sim/testsuite/sim/m32r/mvtaclo.cgs create mode 100644 sim/testsuite/sim/m32r/mvtc.cgs create mode 100644 sim/testsuite/sim/m32r/neg.cgs create mode 100644 sim/testsuite/sim/m32r/nop.cgs create mode 100644 sim/testsuite/sim/m32r/not.cgs create mode 100644 sim/testsuite/sim/m32r/or.cgs create mode 100644 sim/testsuite/sim/m32r/or3.cgs create mode 100644 sim/testsuite/sim/m32r/rac.cgs create mode 100644 sim/testsuite/sim/m32r/rach.cgs create mode 100644 sim/testsuite/sim/m32r/rem.cgs create mode 100644 sim/testsuite/sim/m32r/remu.cgs create mode 100644 sim/testsuite/sim/m32r/rte.cgs create mode 100644 sim/testsuite/sim/m32r/seth.cgs create mode 100644 sim/testsuite/sim/m32r/sll.cgs create mode 100644 sim/testsuite/sim/m32r/sll3.cgs create mode 100644 sim/testsuite/sim/m32r/slli.cgs create mode 100644 sim/testsuite/sim/m32r/sra.cgs create mode 100644 sim/testsuite/sim/m32r/sra3.cgs create mode 100644 sim/testsuite/sim/m32r/srai.cgs create mode 100644 sim/testsuite/sim/m32r/srl.cgs create mode 100644 sim/testsuite/sim/m32r/srl3.cgs create mode 100644 sim/testsuite/sim/m32r/srli.cgs create mode 100644 sim/testsuite/sim/m32r/st-d.cgs create mode 100644 sim/testsuite/sim/m32r/st-minus.cgs create mode 100644 sim/testsuite/sim/m32r/st-plus.cgs create mode 100644 sim/testsuite/sim/m32r/st.cgs create mode 100644 sim/testsuite/sim/m32r/stb-d.cgs create mode 100644 sim/testsuite/sim/m32r/stb.cgs create mode 100644 sim/testsuite/sim/m32r/sth-d.cgs create mode 100644 sim/testsuite/sim/m32r/sth.cgs create mode 100644 sim/testsuite/sim/m32r/sub.cgs create mode 100644 sim/testsuite/sim/m32r/subv.cgs create mode 100644 sim/testsuite/sim/m32r/subx.cgs create mode 100644 sim/testsuite/sim/m32r/testutils.inc create mode 100644 sim/testsuite/sim/m32r/trap.cgs create mode 100644 sim/testsuite/sim/m32r/unlock.cgs create mode 100644 sim/testsuite/sim/m32r/uread16.ms create mode 100644 sim/testsuite/sim/m32r/uread32.ms create mode 100644 sim/testsuite/sim/m32r/uwrite16.ms create mode 100644 sim/testsuite/sim/m32r/uwrite32.ms create mode 100644 sim/testsuite/sim/m32r/xor.cgs create mode 100644 sim/testsuite/sim/m32r/xor3.cgs create mode 100644 sim/v850/ChangeLog create mode 100644 sim/v850/Makefile.in create mode 100644 sim/v850/acconfig.h create mode 100644 sim/v850/config.in create mode 100755 sim/v850/configure create mode 100644 sim/v850/configure.in create mode 100644 sim/v850/gencode.c create mode 100644 sim/v850/interp.c create mode 100644 sim/v850/sim-main.h create mode 100644 sim/v850/simops.c create mode 100644 sim/v850/v850-dc create mode 100644 sim/v850/v850.igen create mode 100644 sim/v850/v850_sim.h create mode 100644 sim/w65/ChangeLog create mode 100644 sim/w65/Makefile.in create mode 100644 sim/w65/acconfig.h create mode 100644 sim/w65/config.in create mode 100755 sim/w65/configure create mode 100644 sim/w65/configure.in create mode 100644 sim/w65/gencode.c create mode 100644 sim/w65/interp.c create mode 100644 sim/w65/interp.h create mode 100644 sim/w65/run.c create mode 100644 sim/z8k/ChangeLog create mode 100644 sim/z8k/Makefile.in create mode 100644 sim/z8k/acconfig.h create mode 100644 sim/z8k/comped1.c create mode 100644 sim/z8k/comped2.c create mode 100644 sim/z8k/comped3.c create mode 100644 sim/z8k/compedb3.c create mode 100644 sim/z8k/config.in create mode 100755 sim/z8k/configure create mode 100644 sim/z8k/configure.in create mode 100644 sim/z8k/iface.c create mode 100644 sim/z8k/inlines.h create mode 100644 sim/z8k/list.c create mode 100644 sim/z8k/mem.c create mode 100644 sim/z8k/mem.h create mode 100644 sim/z8k/quick.c create mode 100644 sim/z8k/sim.h create mode 100644 sim/z8k/support.c create mode 100644 sim/z8k/syscall.h create mode 100644 sim/z8k/tconfig.in create mode 100644 sim/z8k/tm.h create mode 100644 sim/z8k/writecode.c (limited to 'sim') diff --git a/sim/ChangeLog b/sim/ChangeLog new file mode 100644 index 00000000000..c73709fbca7 --- /dev/null +++ b/sim/ChangeLog @@ -0,0 +1,461 @@ +1999-03-14 Stan Shebs + + * Makefile.in (FLAGS_TO_PASS, TARGET_FLAGS_TO_PASS): Remove + RUNTEST instead of commenting out, fixes portability problem. + +1999-02-10 Doug Evans + + * configure.in (sparc*): Configure sparc subdir if --with-cgen or + --with-cgen-sim. + * configure: Rebuild. + +1999-02-08 Nick Clifton + + * configure.in: Add support for StrongARM target. + * configure: Regenerate. + +1999-02-02 Doug Evans + + * configure.in (sparc*): Configure sparc subdir if --with-cgen. + * configure: Rebuild. + +1999-01-04 Jason Molenda (jsm@bugshack.cygnus.com) + + * configure.in: Require autoconf 2.12.1 or higher. + +1998-12-08 James E Wilson + + * configure.in (i960-*-*): Add. + * configure: Rebuild. + +Wed Nov 4 19:11:43 1998 Dave Brolley + + * configure.in: Added case for fr30-*-*. + * configure: Regenerated. + +Fri Sep 25 10:12:19 1998 Christopher Faylor + + * ppc/Makefile.in: Add EXEEXT to installed powerpc-eabi-run program + to allow successful operation on Windows. + +Thu May 28 14:59:46 1998 Jillian Ye + + * Makefile.in: Take RUNTEST out of FLAG_TO_PASS + so that make check can be invoked recursively. + +Wed Apr 29 12:38:53 1998 Mark Alexander + + * configure.in: Build simulator on sparclite and sparc86x targets. + * configure: Regenerate. + +Sun Apr 26 15:21:01 1998 Tom Tromey + + * Makefile.in (autoconf-common autoheader-common): Don't pass -l + to autoconf and autoheader. + +Fri Apr 24 11:14:13 1998 Tom Tromey + + * Makefile.in (autoconf-common autoheader-common): Pass `-l + ../common' to autoconf and autoheader. Unconditionally run + autoconf in every subdir. + (autoconf-changelog autoheader-changelog): Unconditionally run + commands in every subdir. + (autoconf-install autoheader-install): Likewise. + +Tue Mar 24 17:12:43 1998 Stu Grossman + + * Makefile.in: Get SHELL from configure. + * (FLAGS_TO_PASS): Pass down SHELL. + * configure: Regenerate with autoconf 2.12.1 to fix shell issues for + NT native builds. + +Tue Mar 24 11::18:00 1998 Joyce Janczyn + + * configure.in (extra_subdirs): Enable igen for mn10300. + * configure: Re-generate. + +Tue Dec 2 10:10:42 1997 Nick Clifton + + * configure.in (extra_subdirs): Add support for thumb target. + + * configure (extra_subdirs): Add support for thumb target. + +Wed Oct 8 12:38:48 1997 Andrew Cagney + + * configure.in (extra_subdirs): Add IGEN directory when MIPS + target. + * configure: Regenerate. + +Fri Sep 12 13:10:31 1997 Andrew Cagney + + * configure.in (extra_subdirs): v850ea needs igen. + * configure: Re-generate. + +Mon Sep 1 16:48:23 1997 Andrew Cagney + + * configure.in (testdir): When a testsuite directory, add that to + the list of confdirs. + +Tue Aug 19 11:17:46 1997 Andrew Cagney + + * configure.in (extra_subdirs): Enable igen ready for V850. + +Tue Aug 26 15:14:48 1997 Andrew Cagney + + * configure.in (w65-*-*, only_if_enabled): Set. + * configure: Re-generate. + +Mon Aug 25 16:26:53 1997 Andrew Cagney + + * configure.in (sparc*-*-*, only_if_enabled): Set + only_if_enabled=yes. Check only_if_enabled before enabling a + simulator. + * configure: Regenerate. + +Mon Aug 18 10:56:59 1997 Nick Clifton + + * configure.in (extra_subdirs): Add v850e target. + +Mon Aug 18 10:56:59 1997 Nick Clifton + + * configure.in (extra_subdirs): Add v850ea target. + +Fri Jul 25 11:40:47 1997 Doug Evans + + * configure.in (sparc*-*-*): Don't build erc32. + * configure: Regenerate. + +Thu Apr 24 00:47:20 1997 Doug Evans + + * configure.in (m32r-*-*): New target. + * configure: Regenerate. + + * Makefile.in (autoconf-common, autoconf-changelog): Change $* to $@. + +Mon Apr 21 22:57:55 1997 Andrew Cagney + + * Makefile.in (.NOEXPORT, MAKEOVERRIDES): Moved to end, BSD make + thought that .NOEXPORT was the default target. + +Fri Apr 11 17:18:07 1997 Ian Lance Taylor + + * Makefile.in (clean mostlyclean): Restore targets accidentally + deleted in earlier change. + +Thu Apr 3 12:20:32 1997 Andrew Cagney + + * Makefile.in (autoheader-common, autoheader-changelog, + autoheader-install): Perform autoheader in addition to autoconf. + +Wed Apr 2 15:09:05 1997 Doug Evans + + * Makefile.in (autoconf-install): New target. + (autoconf-changelog): Try different way to obtain user name. + +Wed Apr 2 14:25:52 1997 Andrew Cagney + + * Makefile.in (autoconf-changelog): New target, update + ChangeLog for all subdirectories - normally used after + autoconf-common target. + +Wed Mar 19 14:26:21 1997 Andrew Cagney + + * configure.in (extra_subdirs): Include testsuite for d30v. + * configure: Regenerate. + + * Makefile.in (RUNTEST, RUNTESTFLAGS): Borrow test rules from + ../gdb/Makefile.in + (check): New rules - drive the testsuite. + +Mon Mar 3 13:01:00 1997 Jeffrey A Law (law@cygnus.com) + + * configure.in: Add mn10200 configure lines accidentally + removed. + * configure: Regenerated. + +Wed Feb 19 10:34:20 1997 Andrew Cagney + + * configure.in (extra_subdirs): Generalize common sub directory + into a list. + (extra_subdirs): For d30v add igen to the list to be built. + +Sun Feb 16 16:37:47 1997 Andrew Cagney + + * configure.in (d30v): New target. + * configure: Regenerated. + +Wed Feb 19 23:17:13 1997 Jeffrey A Law (law@cygnus.com) + + * configure.in: Don't require GCC to build the mn10200 + simulator anymore. + * configure: Rebuilt. + +Wed Feb 5 13:28:13 1997 Doug Evans + + * configure.in: Don't configure any subdirs if no simulator + is being built. Don't use erc32 for sparc64. + * configure: Regenerated. + +Tue Feb 4 13:19:39 1997 Doug Evans + + * Makefile.in (autoconf-common): New target. + * configure.in: Do configure common. + * configure: Regenerated. + +Thu Jan 23 13:59:52 1997 Stu Grossman (grossman@critters.cygnus.com) + + * configure configure.in: Don't configure common anymore. Files + from common are now built in the individual simualtor directories. + This fixes problems with the WinGDB build procedure. + +Mon Jan 13 13:16:42 1997 Jeffrey A Law (law@cygnus.com) + + * configure: Enable the mn10200 simulator. + +Wed Nov 20 01:00:36 1996 Doug Evans + + * configure.in (configdirs): Add common. + * configure: Regenerated. + +Fri Nov 1 08:03:30 1996 Michael Meissner + + * configure.in (powerpc*-*-linux*): Treat like the other powerpc + system V based targets. + * configure: Regenerate. + +Thu Oct 17 12:50:08 1996 Doug Evans + + * configure.in (--enable-sim-powerpc): Delete. + (--enable-sim): Add. + * configure: Regenerated. + +Fri Oct 11 21:13:43 1996 Jeffrey A Law (law@cygnus.com) + + * configure.in: Only build the V850 simulator if + we are using gcc. + * configure: Rebuild. + +Sun Sep 8 17:22:50 1996 Ian Lance Taylor + + * configure.in: Do build erc32 for DOS and Windows hosts. + * configure: Rebuild. + +Wed Sep 4 18:11:27 1996 Stu Grossman (grossman@critters.cygnus.com) + + * Makefile.in erc32/Makefile.in: Don't set srcroot. This should + be inherited from the parent. Remove INSTALL_XFORM and + INSTALL_XFORM1. Make INSTALL be set from configure. + +Wed Sep 4 15:49:16 1996 Ian Lance Taylor + + * configure.in: Only build the MIPS simulator if we are using + gcc. + * configure: Rebuild. + +Wed Aug 28 19:05:23 1996 Jeffrey A Law (law@cygnus.com) + + * configure.in (v850-*-*): Added V850 simulator. + +Thu Aug 1 17:08:41 1996 Martin M. Hunt + + * configure.in (d10v-*-*): Added D10V simulator. + +Wed Jun 26 12:33:57 1996 Jason Molenda (crash@godzilla.cygnus.co.jp) + + * Makefile.in (bindir, libdir, datadir, mandir, infodir, includedir, + INSTALL_PROGRAM, INSTALL_DATA): Use autoconf-set values. + (docdir): Removed. + * configure.in (AC_PREREQ): autoconf 2.5 or higher. + (AC_PROG_INSTALL): Added. + * configure: Rebuilt. + +Mon Jun 24 14:18:26 1996 Ian Lance Taylor + + * configure.in: Only configure erc32 if using gcc. + * configure: Rebuild. + +Tue Jun 4 09:24:21 1996 Michael Meissner + + * configure.in (sim_target): Build PowerPC simulator for powerpc + System V.4, Solaris, and Elf targets. + * configure: Regenerate with autoconf 2.10. + +Wed May 22 12:10:49 1996 Rob Savoye + + * configure.in: Only built erc32 simulator on Unix hosts as it + uses pseudo ttys. + * configure: Regenerated with autoconf 2.8. + +Sun May 19 20:20:40 1996 Rob Savoye + + * erc32: Sparc simulator from the ESA. + +Sun Apr 7 21:00:09 1996 Fred Fish + + From: Miles Bader + * configure.in: Use AC_CHECK_TOOL to find AR & RANLIB. + * configure: Regenerate using autoconf. + +Thu Feb 22 11:31:50 1996 Michael Meissner + + * Makefile.in (install): Fix typo. + +Wed Feb 21 11:59:57 1996 Ian Lance Taylor + + * configure: Regenerate with autoconf 2.7. + + * Makefile.in (all): Simplify. + (clean, mostlyclean): SUBDIRS may contain whitespace; fix the loop + as in the all target. + (distclean, maintainer-clean, realclean): Likewise. + (install): Likewise. + +Thu Feb 15 18:37:00 1996 Fred Fish + + * Makefile.in (all): Remove extra '\' char from shell script. + +Wed Feb 14 16:43:59 1996 Mike Meissner + + * Makefile.in (all): Avoid a for loop with zero elements, even if + the loop will not be executed because of an if statement. + +Wed Jan 31 21:48:34 1996 Fred Fish + + * Makefile.in (install): Add missing semicolon in "fi \". + +Thu Nov 9 16:10:56 1995 Michael Meissner + + * Makefile.in (AR, CC, CFLAGS, CC_FOR_BUILD, RANLIB): Pick up + defaults from configure. + + * configure.in: Pick up AR, CC, CFLAGS, CC_FOR_BUILD, RANLIB using + configure defaults. + (powerpc*-*-eabi*): Build simulator for all powerpc eabi targets + if either --enable-sim-powerpc is used, or the host compiler is + GCC. + +Wed Nov 8 15:46:49 1995 James G. Smith + + * configure.in (mips*-*-*): Added "mips" simulator target. + * configure: Re-generated. + +Tue Oct 10 11:08:20 1995 Fred Fish + + * Makefile.in (BISON): Remove macro. + (FLAGS_TO_PASS): Remove BISON. + +Sun Oct 8 04:26:27 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de) + + * configure.in: Explicitly `exit 0' for broken shells. + * configure: Rebuilt. + +Fri Oct 6 12:03:27 1995 Jim Wilson + + * common/run.c (main): Initialize the callbacks. + +Wed Sep 20 13:34:50 1995 Ian Lance Taylor + + * Makefile.in (maintainer-clean): New synonym for realclean. + +Fri Aug 25 11:53:43 1995 Michael Meissner + + * configure.in (powerpc*-*-eabisim*): Only build the simulator if + the target is powerpc*-*-eabisim*, since it requires GCC to build. + +Mon Aug 21 17:53:48 1995 Michael Meissner + + * configure.in (powerpc{,le}-*-*): Add psim from Andrew Cagney + . + * configure: Regnerate from configure.in. + +Thu Aug 3 10:45:37 1995 Fred Fish + + * Update all FSF addresses except those in COPYING* files. + +Thu Jul 20 15:17:29 1995 Fred Fish + + * Makefile.in (CC_FOR_BUILD): Define default and arrange to pass + submakes either default or passed in value. + +Wed Jul 5 14:32:54 1995 J.T. Conklin + + * Makefile.in (all, clean, distclean, mostlyclean, realclean, + install): Changed targets so that they descend all + subdirectories in $(SUBDIRS). + (*-all, *-clean, *-install): Removed targets. + + * configure.in: Don't bother with target makefile fragments, they + are no longer needed. + * configure: regenerated. + + * Makefile.in, configure.in: converted to autoconf. + * configure: New file, generated with autconf 2.4. + +Wed May 24 14:48:46 1995 Steve Chamberlain + + * Makefile.in: Support ARM. + * configure.in: Ditto. + +Sun Jan 15 16:53:47 1995 Steve Chamberlain + + * Makefile.in: Support W65. + * configure.in: Ditto. + +Sun Mar 13 09:27:50 1994 Jim Kingdon (kingdon@lioth.cygnus.com) + + * Makefile.in: Add TAGS target. + +Mon Sep 13 12:47:15 1993 K. Richard Pixley (rich@sendai.cygnus.com) + + * Makefile.in (all-z8k, install-z8k, clean-z8k, all-h8300, + install-h8300, clean-h8300, all-h8500, install-h8500, + clean-h8500, all-sh, install-sh, clean-sh): do not echo + recursion lines. + +Wed Jun 30 14:12:05 1993 david d `zoo' zuhn (zoo at poseidon.cygnus.com) + + * Makefile.in: remove endian.h trace from h8500 + +Sun Jun 13 13:08:58 1993 Jim Kingdon (kingdon@cygnus.com) + + * Makefile.in: Add distclean, realclean, and mostlyclean targets. + +Fri May 21 11:21:16 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com) + + * Makefile.in: make all of the all-* target (except all-nothing) + depend on endian.h, so that if we're not building a simulator, we + don't built endian + +Fri May 21 10:55:06 1993 Ian Lance Taylor (ian@cygnus.com) + + * Makefile.in (check, installcheck): Added dummy targets. + +Mon May 3 21:39:43 1993 Fred Fish (fnf@cygnus.com) + + * Makefile.in (endian): Find endian.c in $(srcdir), and also + explicitly make it, since some makes apparently don't work with + VPATH and .c to executable rules (SunOS make for example). + +Mon May 3 08:29:01 1993 Steve Chamberlain (sac@thepub.cygnus.com) + + * Makefile.in (endian): Add explicit rule for broken makes. + +Mon Mar 15 15:47:53 1993 Ian Lance Taylor (ian@cygnus.com) + + * Makefile.in (info, install-info): New targets. + (DO_INSTALL): Renamed from INSTALL, which is overridden by the top + level Makefile. + +Wed Feb 10 20:12:27 1993 K. Richard Pixley (rich@ok.cygnus.com) + + * Makefile.in (endian.h): build endian.h via a temporary file so + that we don't leave an incomplete file lying around on + interrupted builds. + (clean): remove endian, e.h, and endian.h. + +Mon Feb 8 11:46:06 1993 Steve Chamberlain (sac@thepub.cygnus.com) + + * Makefile.in, configure.in: if target isn't supported, build a + harmless makefile. + + diff --git a/sim/Makefile.in b/sim/Makefile.in new file mode 100644 index 00000000000..1e53780fd5d --- /dev/null +++ b/sim/Makefile.in @@ -0,0 +1,254 @@ +# Makefile template for Configure for the sim library. +# Copyright (C) 1993, 1995, 1997, 1998 Free Software Foundation, Inc. +# Written by Cygnus Support. +# +# This file is part of BFD, the Binary File Descriptor library. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +VPATH = @srcdir@ +srcdir = @srcdir@ + +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +host_alias = @host_alias@ +target_alias = @target_alias@ +program_transform_name = @program_transform_name@ +bindir = @bindir@ +libdir = @libdir@ +tooldir = $(libdir)/$(target_alias) + +datadir = @datadir@ +mandir = @mandir@ +man1dir = $(mandir)/man1 +man2dir = $(mandir)/man2 +man3dir = $(mandir)/man3 +man4dir = $(mandir)/man4 +man5dir = $(mandir)/man5 +man6dir = $(mandir)/man6 +man7dir = $(mandir)/man7 +man8dir = $(mandir)/man8 +man9dir = $(mandir)/man9 +infodir = @infodir@ +includedir = @includedir@ + +SHELL = @SHELL@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ + +AR = @AR@ +AR_FLAGS = rc +CC = @CC@ +CFLAGS = @CFLAGS@ +CC_FOR_BUILD = @CC_FOR_BUILD@ +MAKEINFO = makeinfo +RANLIB = @RANLIB@ + +SUBDIRS = @subdirs@ + +INCDIR = $(srcdir)/../include +CSEARCH = -I. -I$(srcdir) -I$(INCDIR) +DEP = mkdep + +# compilers to use to create programs which must be run in the build +# environment. +CC_FOR_BUILD = $(CC) + +#### Makefile fragments come in here. +# @target_makefile_frag@ +### + +RUNTEST = `if [ -f $${srcdir}/../dejagnu/runtest ] ; then \ + echo $${srcdir}/../dejagnu/runtest ; else echo runtest; \ + fi` +RUNTESTFLAGS= + +FLAGS_TO_PASS = \ + "prefix=$(prefix)" \ + "exec_prefix=$(exec_prefix)" \ + "against=$(against)" \ + "AR=$(AR)" \ + "AR_FLAGS=$(AR_FLAGS)" \ + "CC=$(CC)" \ + "CC_FOR_BUILD=$(CC_FOR_BUILD)" \ + "CFLAGS=$(CFLAGS)" \ + "RANLIB=$(RANLIB)" \ + "MAKEINFO=$(MAKEINFO)" \ + "INSTALL=$(INSTALL)" \ + "INSTALL_DATA=$(INSTALL_DATA)" \ + "INSTALL_PROGRAM=$(INSTALL_PROGRAM)" \ + "RUNTESTFLAGS=$(RUNTESTFLAGS)" \ + "SHELL=$(SHELL)" + +# The use of $$(x_FOR_TARGET) reduces the command line length by not +# duplicating the lengthy definition. +TARGET_FLAGS_TO_PASS = \ + "prefix=$(prefix)" \ + "exec_prefix=$(exec_prefix)" \ + "against=$(against)" \ + 'CC=$$(CC_FOR_TARGET)' \ + "CC_FOR_TARGET=$(CC_FOR_TARGET)" \ + "CFLAGS=$(CFLAGS)" \ + "CHILLFLAGS=$(CHILLFLAGS)" \ + 'CHILL=$$(CHILL_FOR_TARGET)' \ + "CHILL_FOR_TARGET=$(CHILL_FOR_TARGET)" \ + "CHILL_LIB=$(CHILL_LIB)" \ + 'CXX=$$(CXX_FOR_TARGET)' \ + "CXX_FOR_TARGET=$(CXX_FOR_TARGET)" \ + "CXXFLAGS=$(CXXFLAGS)" \ + "INSTALL=$(INSTALL)" \ + "INSTALL_PROGRAM=$(INSTALL_PROGRAM)" \ + "INSTALL_DATA=$(INSTALL_DATA)" \ + "MAKEINFO=$(MAKEINFO)" \ + "RUNTESTFLAGS=$(RUNTESTFLAGS)" + + +all: + @rootme=`pwd` ; export rootme ; \ + for dir in . `echo ${SUBDIRS} | sed 's/testsuite//'` ; do \ + if [ "$$dir" = "." ]; then \ + true; \ + elif [ -d $$dir ]; then \ + (cd $$dir; $(MAKE) $(FLAGS_TO_PASS)); \ + else true; fi; \ + done + +clean mostlyclean: + @rootme=`pwd` ; export rootme ; \ + for dir in . ${SUBDIRS}; do \ + if [ "$$dir" = "." ]; then \ + true; \ + elif [ -d $$dir ]; then \ + (cd $$dir; $(MAKE) $(FLAGS_TO_PASS) $@); \ + else true; fi; \ + done + +distclean maintainer-clean realclean: + @rootme=`pwd` ; export rootme ; \ + for dir in . ${SUBDIRS}; do \ + if [ "$$dir" = "." ]; then \ + true; \ + elif [ -d $$dir ]; then \ + (cd $$dir; $(MAKE) $(FLAGS_TO_PASS) $@); \ + else true; fi; \ + done + rm -f Makefile config.cache config.log config.status + +install: + @rootme=`pwd` ; export rootme ; \ + for dir in . ${SUBDIRS}; do \ + if [ "$$dir" = "." ]; then \ + true; \ + elif [ -d $$dir ]; then \ + (cd $$dir; $(MAKE) $(FLAGS_TO_PASS) install); \ + else true; fi; \ + done + +installcheck: + @echo No installcheck target is available yet for the GNU simulators. + +installcheck: + +# The check target can not use subdir_do, because subdir_do does not +# use TARGET_FLAGS_TO_PASS. +check: force + @if [ -f testsuite/Makefile ]; then \ + rootme=`pwd`; export rootme; \ + rootsrc=`cd $(srcdir); pwd`; export rootsrc; \ + cd testsuite; \ + $(MAKE) $(TARGET_FLAGS_TO_PASS) check; \ + else true; fi + + + +info: +install-info: +dvi: + +### +### + +.NOEXPORT: +MAKEOVERRIDES= + +.PHONY: check installcheck +check: +installcheck: + +TAGS: + +force: + +Makefile: Makefile.in config.status + $(SHELL) ./config.status + +config.status: configure + $(SHELL) ./config.status --recheck + +# Utility to run autoconf in each directory that uses the common framework. +# This is intended to be invoked in $srcdir as +# "make -f Makefile.in autoconf-common". +.PHONY: autoconf-common +autoconf-common autoheader-common: + for d in * ; \ + do \ + if [ -d $$d -a -f $$d/configure.in ] ; \ + then \ + echo "Running autoconf in $$d ..." ; \ + (cd $$d && autoconf) ; \ + if [ $@ = autoheader-common ] ; \ + then \ + echo "Running autoheader in $$d ..." ; \ + (cd $$d && autoheader) ; \ + fi ; \ + fi ; \ + done + +autoconf-changelog autoheader-changelog: + id="`id | sed -e 's/^[^(]*(\([^)]*\).*$$/\1/'`" ; \ + name=`grep "^$$id:" /etc/passwd | cut -f 5 -d ':'` ; \ + host="`hostname`" ; \ + date="`date | sed 's/ [^ ]* \([0-9]*\)$$/ \1/'`" ; \ + echo "$$date $$name $$id@$$host" ; \ + for d in * ; \ + do \ + if [ -d $$d -a -f $$d/configure.in ] ; \ + then \ + echo "Creating new-ChangeLog in $$d ..." ; \ + ( echo "$$date $$name <$$id@$$host>" ; \ + echo "" ; \ + echo " * configure: Regenerated to track ../common/aclocal.m4 changes." ; \ + if [ $@ = autoheader-changelog ] ; \ + then \ + echo " * config.in: Ditto." ; \ + fi ; \ + echo "" ; \ + cat $$d/ChangeLog \ + ) > $$d/new-ChangeLog ; \ + fi ; \ + done + +autoconf-install autoheader-install: + for d in * ; \ + do \ + if [ -d $$d -a -f $$d/configure.in ] ; \ + then \ + echo "Moving $$d/new-ChangeLog to $$d/ChangeLog ..." ; \ + mv $$d/new-ChangeLog $$d/ChangeLog ; \ + fi ; \ + done diff --git a/sim/README-HACKING b/sim/README-HACKING new file mode 100644 index 00000000000..e4efeb155b0 --- /dev/null +++ b/sim/README-HACKING @@ -0,0 +1,254 @@ +This is a loose collection of notes for people hacking on simulators. +If this document gets big enough it can be prettied up then. + +Contents + +- The "common" directory +- Common Makefile Support +- TAGS support +- Generating "configure" files +- tconfig.in +- C Language Assumptions +- "dump" commands under gdb + +The "common" directory +====================== + +The common directory contains: + +- common documentation files (e.g. run.1, and maybe in time .texi files) +- common source files (e.g. run.c) +- common Makefile fragment and configury (e.g. Make-common.in, aclocal.m4). + +In addition "common" contains portions of the system call support +(e.g. callback.c, nltvals.def). + +Even though no files are built in this directory, it is still configured +so support for regenerating nltvals.def is present. + +Common Makefile Support +======================= + +A common configuration framework is available for simulators that want +to use it. The common framework exists to remove a lot of duplication +in configure.in and Makefile.in, and it also provides a foundation for +enhancing the simulators uniformly (e.g. the more they share in common +the easier a feature added to one is added to all). + +The configure.in of a simulator using the common framework should look like: + +--- snip --- +dnl Process this file with autoconf to produce a configure script. +sinclude(../common/aclocal.m4) +AC_PREREQ(2.5)dnl +AC_INIT(Makefile.in) + +SIM_AC_COMMON + +... target specific additions ... + +SIM_AC_OUTPUT +--- snip --- + +SIM_AC_COMMON: + +- invokes the autoconf macros most often used by the simulators +- defines --enable/--with options usable by all simulators +- initializes sim_link_files/sim_link_links as the set of symbolic links + to set up + +SIM_AC_OUTPUT: + +- creates the symbolic links defined in sim_link_{files,links} +- creates config.h +- creates the Makefile + +The Makefile.in of a simulator using the common framework should look like: + +--- snip --- +# Makefile for blah ... +# Copyright blah ... + +## COMMON_PRE_CONFIG_FRAG + +# These variables are given default values in COMMON_PRE_CONFIG_FRAG. +# We override the ones we need to here. +# Not all of these need to be mentioned, only the necessary ones. +# In fact it is better to *not* mention ones if the value is the default. + +# List of object files, less common parts. +SIM_OBJS = +# List of extra dependencies. +# Generally this consists of simulator specific files included by sim-main.h. +SIM_EXTRA_DEPS = +# List of flags to always pass to $(CC). +SIM_EXTRA_CFLAGS = +# List of extra libraries to link with. +SIM_EXTRA_LIBS = +# List of extra program dependencies. +SIM_EXTRA_LIBDEPS = +# List of main object files for `run'. +SIM_RUN_OBJS = run.o +# Dependency of `all' to build any extra files. +SIM_EXTRA_ALL = +# Dependency of `install' to install any extra files. +SIM_EXTRA_INSTALL = +# Dependency of `clean' to clean any extra files. +SIM_EXTRA_CLEAN = + +## COMMON_POST_CONFIG_FRAG + +# Rules need to build $(SIM_OBJS), plus whatever else the target wants. + +... target specific rules ... +--- snip --- + +COMMON_{PRE,POST}_CONFIG_FRAG are markers for SIM_AC_OUTPUT to tell it +where to insert the two pieces of common/Make-common.in. +The resulting Makefile is created by doing autoconf substitions on +both the target's Makefile.in and Make-common.in, and inserting +the two pieces of Make-common.in into the target's Makefile.in at +COMMON_{PRE,POST}_CONFIG_FRAG. + +Note that SIM_EXTRA_{INSTALL,CLEAN} could be removed and "::" targets +could be used instead. However, it's not clear yet whether "::" targets +are portable enough. + +TAGS support +============ + +Many files generate program symbols at compile time. +Such symbols can't be found with grep nor do they normally appear in +the TAGS file. To get around this, source files can add the comment + +/* TAGS: foo1 foo2 */ + +where foo1, foo2 are program symbols. Symbols found in such comments +are greppable and appear in the TAGS file. + +Generating "configure" files +============================ + +For targets using the common framework, "configure" can be generated +by running `autoconf'. + +To regenerate the configure files for all targets using the common framework: + + $ cd devo/sim + $ make -f Makefile.in SHELL=/bin/sh autoconf-common + +To add a change-log entry to the ChangeLog file for each updated +directory (WARNING - check the modified new-ChangeLog files before +renaming): + + $ make -f Makefile.in SHELL=/bin/sh autoconf-changelog + $ more */new-ChangeLog + $ make -f Makefile.in SHELL=/bin/sh autoconf-install + +In a similar vein, both the configure and config.in files can be +updated using the sequence: + + $ cd devo/sim + $ make -f Makefile.in SHELL=/bin/sh autoheader-common + $ make -f Makefile.in SHELL=/bin/sh autoheader-changelog + $ more */new-ChangeLog + $ make -f Makefile.in SHELL=/bin/sh autoheader-install + +tconfig.in +========== + +File tconfig.in defines one or more target configuration macros +(e.g. a tm.h file). There are very few that need defining. +For a list of all of them, see common/tconfig.in. +It contains them all, commented out. +The intent is that a new port can just copy this file and +define the ones it needs. + +C Language Assumptions +====================== + +The programmer may assume that the simulator is being built using an +ANSI C compiler that supports a 64 bit data type. Consequently: + + o prototypes can be used (although using + PARAMS() and K&R declarations wouldn't + go astray). + + o If sim-types.h is included, the two + types signed64 and unsigned64 are + available. + + o The type `unsigned' is valid. + +However, the user should be aware of the following: + + o GCC's `LL' is NOT acceptable. + Microsoft-C doesn't reconize it. + + o MSC's `i64' is NOT acceptable. + GCC doesn't reconize it. + + o GCC's `long long' MSC's `_int64' can + NOT be used to define 64 bit integer data + types. + + o An empty array (eg int a[0]) is not valid. + +When building with GCC it is effectivly a requirement that +--enable-build-warnings=,-Werror be specified during configuration. + +"dump" commands under gdb +========================= + +gdbinit.in contains the following + +define dump +set sim_debug_dump () +end + +Simulators that define the sim_debug_dump function can then have their +internal state pretty printed from gdb. + +FIXME: This can obviously be made more elaborate. As needed it will be. + +Rebuilding nltvals.def +====================== + +Checkout a copy of the SIM and LIBGLOSS modules (Unless you've already +got one to hand): + + $ mkdir /tmp/$$ + $ cd /tmp/$$ + $ cvs checkout sim-no-testsuite libgloss-no-testsuite newlib-no-testsuite + +Configure things for an arbitrary simulator target (I've d10v for +convenience): + + $ mkdir /tmp/$$/build + $ cd /tmp/$$/build + $ /tmp/$$/devo/configure --target=d10v-elf + +In the sim/common directory rebuild the headers: + + $ cd sim/common + $ make headers + +To add a new target: + + devo/sim/common/gennltvals.sh + + Add your new processor target (you'll need to grub + around to find where your syscall.h lives). + + devo/sim//Makefile.in + + Add the definition: + + ``NL_TARGET = -DNL_TARGET_d10v'' + + just before the line COMMON_POST_CONFIG_FRAG. + + devo/sim//*.[ch] + + Include targ-vals.h instead of syscall.h. + diff --git a/sim/arm/COPYING b/sim/arm/COPYING new file mode 100644 index 00000000000..60549be514a --- /dev/null +++ b/sim/arm/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 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. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, 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 or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +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 give any other recipients of the Program a copy of this License +along with the Program. + +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 Program or any portion +of it, thus forming a work based on the Program, 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) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +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 Program, 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 Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) 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; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, 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 executable. However, as a +special exception, the source code 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. + +If distribution of executable or 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 counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program 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. + + 5. 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 Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program 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 to +this License. + + 7. 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 Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program 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 Program. + +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. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program 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. + + 9. The Free Software Foundation may publish revised and/or new versions +of the 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 Program +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 Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, 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 + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "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 PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. 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 PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), 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 Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. 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. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; 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. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/sim/arm/ChangeLog b/sim/arm/ChangeLog new file mode 100644 index 00000000000..4149366ee41 --- /dev/null +++ b/sim/arm/ChangeLog @@ -0,0 +1,426 @@ +Mon Sep 14 09:00:05 1998 Nick Clifton + + * wrapper.c (sim_open): Set endianness according to BFD or command + line switch. + + * tconfig.in: Define SIM_HAVE_BIENDIAN. + +Thu Aug 27 11:00:05 1998 Nick Clifton + + * armemu.c (Multiply64): Test for Rm (rather than Rs) not being + the same as either RdHi or RdLo. + +Thu Jul 2 10:24:35 1998 Nick Clifton + + * armos.c (ARMul_OSHandleSWI: AngelSWI_Reason_ReportException): + Set Reg[0] based on reason for for the exception. + +Thu Jun 4 15:22:03 1998 Jason Molenda (crash@bugshack.cygnus.com) + + * armos.c (SWIwrite0): New function. + (WriteCommandLineTo): New function. + (SWIopen): New function. + (SWIread): New function. + (SWIwrite): New function. + (SWIflen): New function. + (ARMul_OSHandleSWI): Call new functions instead of handling + these here. + (ARMul_OSHandleSWI): Handle Angel SWIs correctly. + (*): Reformat spacing to be a bit more GNUly. + Most code taken from a patch by Anthony Thompson + (athompso@cambridge.arm.com) + +Tue Jun 2 15:22:22 1998 Nick Clifton + + * armos.h: Add Angel SWI and its reason codes. + * armos.c (ARMul_OSHandleSWI): Ignore Angel SWIs (for now). + +Mon Jun 1 17:14:19 1998 Anthony Thompson (athompso@cambridge.arm.com) + + * armos.c (ARMul_OSHandleSWI::SWI_Open): Handle special case + of ":tt" to catch stdin in addition to stdout. + (ARMul_OSHandleSWI::SWI_Seek): Return 0 or 1 to indicate failure + or success of lseek(). + +Wed May 20 17:36:25 1998 Nick Clifton + + * armos.c (ARMul_OSHandleSWI): Special case code to catch attempts + to open stdout. + +Wed Apr 29 15:29:55 1998 Jeff Johnston + + * armos.c (ARMul_OSHandleSWI): Added code for SWI_Clock, + SWI_Flen, and SWI_Time. Also fixed SWI_Seek code to only + seek from offset 0 and not to use R2 for whence since it is + not passed as part of the SWI call. + +Tue Apr 28 18:33:31 1998 Geoffrey Noer + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Sun Apr 26 15:31:55 1998 Tom Tromey + + * configure: Regenerated to track ../common/aclocal.m4 changes. + * config.in: Ditto. + +Sun Apr 26 15:20:26 1998 Tom Tromey + + * acconfig.h: New file. + * configure.in: Reverted change of Apr 24; use sinclude again. + +Fri Apr 24 14:16:40 1998 Tom Tromey + + * configure: Regenerated to track ../common/aclocal.m4 changes. + * config.in: Ditto. + +Fri Apr 24 11:20:19 1998 Tom Tromey + + * configure.in: Don't call sinclude. + +Sat Apr 4 20:36:25 1998 Andrew Cagney + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Fri Mar 27 16:15:52 1998 Andrew Cagney + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Wed Mar 25 12:35:29 1998 Andrew Cagney + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Wed Mar 18 12:38:12 1998 Andrew Cagney + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Tue Mar 10 09:26:38 1998 Nick Clifton + + * armopts.h: Remove definition of LITTLEND - it is not used. + +Tue Feb 17 12:35:54 1998 Andrew Cagney + + * wrapper.c (sim_store_register, sim_fetch_register): Pass in + length parameter. Return -1. + +Sun Feb 1 16:47:51 1998 Andrew Cagney + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Sat Jan 31 18:15:41 1998 Andrew Cagney + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Mon Jan 19 22:26:29 1998 Doug Evans + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Mon Dec 15 23:17:11 1997 Andrew Cagney + + * configure: Regenerated to track ../common/aclocal.m4 changes. + * config.in: Ditto. + +Tue Dec 9 11:30:48 1997 Nick Clifton + + * Makefile.in: Updated with changes from branch. + * armdefs.h: ditto + * armemu.c: ditto these changes + * armemu.h: ditto add support for + * armos.c: ditto the Thumb instruction + * armsupp.c: ditto set and the new v4 + * armvirt.c: ditto architecture. + * wrapper.c: ditto + * thumbemu.c: New file from branch. + + +Thu Dec 4 09:21:05 1997 Doug Evans + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Thu Oct 30 13:54:06 1997 Nick Clifton + + * armos.c (ARMul_OSHandleSWI): Add support for GetEnv SWI. Patch + from Tony Thompson at ARM: athompso@arm.com + + * wrapper.c (sim_create_inferior): Add code to create an execution + environment. Patch from Tony Thompson at ARM: athompso@arm.com + +Wed Oct 22 14:43:00 1997 Andrew Cagney + + * wrapper.c (sim_load): Pass lma_p and sim_write args to + sim_load_file. + +Fri Oct 3 09:28:00 1997 Andrew Cagney + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Wed Sep 24 17:38:57 1997 Andrew Cagney + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Tue Sep 23 11:04:38 1997 Andrew Cagney + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Mon Sep 22 11:46:20 1997 Andrew Cagney + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Fri Sep 19 17:45:25 1997 Andrew Cagney + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Mon Sep 15 17:36:15 1997 Andrew Cagney + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Thu Sep 4 17:21:23 1997 Doug Evans + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Wed Aug 27 18:13:22 1997 Andrew Cagney + + * configure: Regenerated to track ../common/aclocal.m4 changes. + * config.in: Ditto. + +Tue Aug 26 10:37:27 1997 Andrew Cagney + + * wrapper.c (sim_kill): Delete. + (sim_create_inferior): Add ABFD argument. + (sim_load): Move setting of PC from here. + (sim_create_inferior): To here. + +Mon Aug 25 17:50:22 1997 Andrew Cagney + + * configure: Regenerated to track ../common/aclocal.m4 changes. + * config.in: Ditto. + +Mon Aug 25 15:35:45 1997 Andrew Cagney + + * wrapper.c (sim_open): Add ABFD argument. + +Tue May 20 10:13:26 1997 Andrew Cagney + + * wrapper.c (sim_open): Add callback argument. + (sim_set_callbacks): Drop SIM_DESC argument. + +Thu Apr 24 00:39:51 1997 Doug Evans + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Fri Apr 18 13:32:23 1997 Andrew Cagney + + * wrapper.c (sim_stop): Stub sim_stop function. + +Thu Apr 17 18:33:01 1997 Fred Fish + + * arminit.c (ARMul_NewState): Preinitialize the state to + all zero/NULL. + +Thu Apr 17 02:39:02 1997 Doug Evans + + * Makefile.in (SIM_OBJS): Add sim-load.o. + * wrapper.c (sim_kind,myname): New static locals. + (sim_open): Set sim_kind, myname. + (sim_load): Call sim_load_file to do work. Set start address from bfd. + (sim_create_inferior): Return SIM_RC. Delete start_address arg. + +Thu Apr 17 11:48:25 1997 Andrew Cagney + + * wrapper.c (sim_trace): Update so that it matches prototype. + +Mon Apr 7 15:45:02 1997 Andrew Cagney + + * configure: Regenerated to track ../common/aclocal.m4 changes. + * config.in: Ditto. + +Mon Apr 7 12:01:17 1997 Andrew Cagney + + * Makefile.in (armemu32.o): Replace $< with autoconf recommended + $(srcdir)/.... + (armemu26.o): Ditto. + +Wed Apr 2 15:06:28 1997 Doug Evans + + * wrapper.c (sim_open): New arg `kind'. + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Wed Apr 2 14:50:44 1997 Ian Lance Taylor + + * COPYING: Update FSF address. + +Wed Apr 2 14:34:19 1997 Andrew Cagney + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Wed Mar 19 01:14:00 1997 Andrew Cagney + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Mon Mar 17 15:10:07 1997 Andrew Cagney + + * configure: Re-generate. + +Fri Mar 14 10:34:11 1997 Michael Meissner + + * configure: Regenerate to track ../common/aclocal.m4 changes. + +Thu Mar 13 12:38:56 1997 Doug Evans + + * wrapper.c (sim_open): Has result now. + (sim_*): New SIM_DESC argument. + +Tue Feb 4 13:22:21 1997 Doug Evans + + * Makefile.in (@COMMON_MAKEFILE_FRAG@): Use + COMMON_{PRE,POST}_CONFIG_FRAG instead. + * configure.in: sinclude ../common/aclocal.m4. + * configure: Regenerated. + +Thu Jan 23 11:46:23 1997 Stu Grossman (grossman@critters.cygnus.com) + + * configure configure.in Makefile.in: Update to new configure + scheme which is more compatible with WinGDB builds. + * configure.in: Improve comment on how to run autoconf. + * configure: Re-run autoconf to get new ../common/aclocal.m4. + * Makefile.in: Use autoconf substitution to install common + makefile fragment. + +Wed Nov 20 01:05:10 1996 Doug Evans + + * run.c: Deleted, use one in ../common now. + * Makefile.in: Delete everything that's been moved to + ../common/Make-common.in. + (SIM_OBJS): Define. + * configure.in: Simplify using macros in ../common/aclocal.m4. + * configure: Regenerated. + * config.in: New file. + * armos.c: #include config.h. + * wrapper.c (mem_size): Value is in bytes now. + (sim_callback): New global. + (arm_sim_set_profile{,_size}): Delete. + (arm_sim_set_mem_size): Rename to sim_size. + (sim_do_command): Call printf_filtered via callback. + (sim_set_callbacks): Record callback. + +Thu Oct 3 16:10:27 1996 Jason Molenda (crash@godzilla.cygnus.co.jp) + + * Makefile.in (mostlyclean): Remove config.log. + +Wed Jun 26 12:17:24 1996 Jason Molenda (crash@godzilla.cygnus.co.jp) + + * Makefile.in (bindir, libdir, datadir, mandir, infodir, includedir, + INSTALL_PROGRAM, INSTALL_DATA): Use autoconf-set values. + (docdir): Removed. + * configure.in (AC_PREREQ): autoconf 2.5 or higher. + (AC_PROG_INSTALL): Added. + * configure: Rebuilt. + +Wed Feb 21 12:14:31 1996 Ian Lance Taylor + + * configure: Regenerate with autoconf 2.7. + +Fri Dec 15 16:27:30 1995 Ian Lance Taylor + + * run.c (main): Use new bfd_big_endian macro. + +Mon Nov 20 17:40:38 1995 Doug Evans + + * run.c: Include "getopt.h". + (verbose): Delete. + (usage): Make static. + (main): Call arm_sim_set_verbosity. + Only load sections marked SEC_LOAD. + * wrapper.c (mem_size, verbosity): New static global. + (arm_sim_set_mem_size): Renamed from sim_size. Callers updated. + (arm_sim_set_profile{,_size}): Renamed from sim_foo. Callers updated. + +Fri Nov 17 19:35:11 1995 Doug Evans + + * armdefs.h (ARMul_State): New member `verbose'. + * armrdi.c (ARMul_ConsolePrint): Add missing va_end. + * run.c (verbose): Make global. + * wrapper.c (init): Set state->verbose. + (ARMul_ConsolePrint): Don't print anything if !verbose. + +Fri Oct 13 15:30:30 1995 Doug Evans + + * armos.c: #include dbg_rdi.h. + (ARMul_OSHandleSWI): Handle SWI_Breakpoint. + * armos.h (SWI_Breakpoint): Define. + * wrapper.c: #include armemu.h, dbg_rdi.h. + (rc): Delete. + (sim_resume): Use state->EndCondition to record stop state. + Call FLUSHPIPE before returning. + (sim_stop_reason): Determine reason from state->EndCondition. + +Fri Oct 13 15:04:05 1995 steve chamberlain + + * wrapper.c (sim_set_callbacks): New. + +Thu Sep 28 19:45:56 1995 Doug Evans + + * armos.c (ARMul_OSHandleSWI): Result of read/write calls is + number of bytes not read/written (or -1). + +Wed Sep 20 13:35:54 1995 Ian Lance Taylor + + * Makefile.in (maintainer-clean): New synonym for realclean. + +Fri Sep 8 14:27:20 1995 Ian Lance Taylor + + * configure.in: Remove AC_PROG_INSTALL. + * configure: Rebuild. + * Makefile.in (INSTALL): Revert to using install.sh. + (INSTALL_PROGRAM, INSTALL_DATA): Set to $(INSTALL). + (INSTALL_XFORM, INSTALL_XFORM1): Restore. + (mostlyclean): Make the same as clean, not distclean. + (clean): Remove config.log. + (install): Don't install in $(tooldir). + +Thu Sep 7 12:00:17 1995 Doug Evans + + (Try to) Update to new bfd autoconf scheme. + * run.c: Don't include sysdep.h. + * Makefile.in (INSTALL{,_PROGRAM,_DATA}): Use autoconf computed value. + (CC, CFLAGS, AR, RANLIB): Likewise. + (HDEFINES, TDEFINES): Define. + (CC_FOR_BUILD): Delete. + (host_makefile_frag): Delete. + (Makefile): Don't depend on frags. + * configure.in (sysdep.h): Don't create symlink. + (host_makefile_frag, frags): Deleted. + (CC, CFLAGS, AR, RANLIB, INSTALL): Compute values. + * configure: Regenerated. + +Thu Aug 3 10:45:37 1995 Fred Fish + + * Update all FSF addresses except those in COPYING* files. + +Wed Jul 5 16:15:54 1995 J.T. Conklin + + * Makefile.in (clean): Remove run, libsim.a. + + * Makefile.in, configure.in: converted to autoconf. + * configure: New file, generated with autconf 2.4. + + * arm.mt: Removed. + +Fri Jun 30 16:49:47 1995 Stan Shebs + + * wrapper.c (sim_do_command): New function. + +Tue Jun 13 10:57:32 1995 Steve Chamberlain + + * armos.c (ARMul_OSHandleSWI): New version to work with + newlib simply. + +Thu Jun 8 14:37:14 1995 Steve Chamberlain + + * run.c (main): Grab return value from right register. + +Wed May 24 14:37:31 1995 Steve Chamberlain + + * New. + + diff --git a/sim/arm/Makefile.in b/sim/arm/Makefile.in new file mode 100644 index 00000000000..b6ae2af0e71 --- /dev/null +++ b/sim/arm/Makefile.in @@ -0,0 +1,48 @@ +# Makefile template for Configure for the arm sim library. +# Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. +# Written by Cygnus Support. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +## COMMON_PRE_CONFIG_FRAG + +SIM_EXTRA_CFLAGS = -DMODET + +SIM_OBJS = armcopro.o armemu26.o armemu32.o arminit.o armos.o armsupp.o \ + armvirt.o bag.o thumbemu.o wrapper.o sim-load.o + +## COMMON_POST_CONFIG_FRAG + + +armos.o: armos.c armdefs.h armos.h armfpe.h + +armcopro.o: armcopro.c armdefs.h + +armemu26.o: armemu.c armdefs.h armemu.h + $(CC) -c $< -o armemu26.o $(ALL_CFLAGS) + +armemu32.o: armemu.c armdefs.h armemu.h + $(CC) -c $< -o armemu32.o -DMODE32 $(ALL_CFLAGS) + +arminit.o: arminit.c armdefs.h armemu.h + +armrdi.o: armrdi.c armdefs.h armemu.h armos.h dbg_cp.h dbg_conf.h dbg_rdi.h \ + dbg_hif.h communicate.h + +armsupp.o: armsupp.c armdefs.h armemu.h + +thumbemu.o: thumbemu.c armdefs.h armemu.h + +bag.o: bag.c bag.h diff --git a/sim/arm/README.Cygnus b/sim/arm/README.Cygnus new file mode 100644 index 00000000000..adfb766451d --- /dev/null +++ b/sim/arm/README.Cygnus @@ -0,0 +1,27 @@ + +This directory contains the standard release of the ARMulator from +Advanced RISC Machines, and was ftp'd from. + +ftp.cl.cam.ac.uk:/arm/gnu + +It likes to use TCP/IP between the simulator and the host, which is +nice, but is a pain to use under anything non-unix. + +I've added created a new Makefile.in (the original in Makefile.orig) +to build a version of the simulator without the TCP/IP stuff, and a +wrapper.c to link directly into gdb and the run command. + +It should be possible (barring major changes in the layout of +the armulator) to upgrade the simulator by copying all the files +out of a release into this directory and renaming the Makefile. + +(Except that I changed armos.c to work more simply with our +simulator rigs) + +Steve + +sac@cygnus.com + +Mon May 15 12:03:28 PDT 1995 + + diff --git a/sim/arm/acconfig.h b/sim/arm/acconfig.h new file mode 100644 index 00000000000..f9b87a10c60 --- /dev/null +++ b/sim/arm/acconfig.h @@ -0,0 +1,15 @@ + +/* Define to 1 if NLS is requested. */ +#undef ENABLE_NLS + +/* Define as 1 if you have catgets and don't want to use GNU gettext. */ +#undef HAVE_CATGETS + +/* Define as 1 if you have gettext and don't want to use GNU gettext. */ +#undef HAVE_GETTEXT + +/* Define as 1 if you have the stpcpy function. */ +#undef HAVE_STPCPY + +/* Define if your locale.h file contains LC_MESSAGES. */ +#undef HAVE_LC_MESSAGES diff --git a/sim/arm/armcopro.c b/sim/arm/armcopro.c new file mode 100644 index 00000000000..fc93a863135 --- /dev/null +++ b/sim/arm/armcopro.c @@ -0,0 +1,357 @@ +/* armcopro.c -- co-processor interface: ARM6 Instruction Emulator. + Copyright (C) 1994 Advanced RISC Machines Ltd. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "armdefs.h" + +extern unsigned ARMul_CoProInit(ARMul_State *state) ; +extern void ARMul_CoProExit(ARMul_State *state) ; +extern void ARMul_CoProAttach(ARMul_State *state, unsigned number, + ARMul_CPInits *init, ARMul_CPExits *exit, + ARMul_LDCs *ldc, ARMul_STCs *stc, + ARMul_MRCs *mrc, ARMul_MCRs *mcr, + ARMul_CDPs *cdp, + ARMul_CPReads *read, ARMul_CPWrites *write) ; +extern void ARMul_CoProDetach(ARMul_State *state, unsigned number) ; + + +/***************************************************************************\ +* Dummy Co-processors * +\***************************************************************************/ + +static unsigned NoCoPro3R(ARMul_State *state,unsigned,ARMword) ; +static unsigned NoCoPro4R(ARMul_State *state,unsigned,ARMword,ARMword) ; +static unsigned NoCoPro4W(ARMul_State *state,unsigned,ARMword,ARMword *) ; + +/***************************************************************************\ +* Define Co-Processor instruction handlers here * +\***************************************************************************/ + +/* Here's ARMulator's MMU definition. A few things to note: +1) it has eight registers, but only two are defined. +2) you can only access its registers with MCR and MRC. +3) MMU Register 0 (ID) returns 0x41440110 +4) Register 1 only has 4 bits defined. Bits 0 to 3 are unused, bit 4 +controls 32/26 bit program space, bit 5 controls 32/26 bit data space, +bit 6 controls late abort timimg and bit 7 controls big/little endian. +*/ + +static ARMword MMUReg[8] ; + +static unsigned MMUInit(ARMul_State *state) +{MMUReg[1] = state->prog32Sig << 4 | + state->data32Sig << 5 | + state->lateabtSig << 6 | + state->bigendSig << 7 ; + ARMul_ConsolePrint (state, ", MMU present") ; + return(TRUE) ; +} + +static unsigned MMUMRC(ARMul_State *state, unsigned type, ARMword instr,ARMword *value) +{int reg = BITS(16,19) & 7 ; + + if (reg == 0) + *value = 0x41440110 ; + else + *value = MMUReg[reg] ; + return(ARMul_DONE) ; + } + +static unsigned MMUMCR(ARMul_State *state, unsigned type, ARMword instr, ARMword value) +{int reg = BITS(16,19) & 7 ; + + MMUReg[reg] = value ; + if (reg == 1) { + state->prog32Sig = value >> 4 & 1 ; + state->data32Sig = value >> 5 & 1 ; + state->lateabtSig = value >> 6 & 1 ; + state->bigendSig = value >> 7 & 1 ; + state->Emulate = TRUE ; /* force ARMulator to notice these now !*/ + } + return(ARMul_DONE) ; + } + + +static unsigned MMURead(ARMul_State *state, unsigned reg, ARMword *value) +{if (reg == 0) + *value = 0x41440110 ; + else if (reg < 8) + *value = MMUReg[reg] ; + return(TRUE) ; + } + +static unsigned MMUWrite(ARMul_State *state, unsigned reg, ARMword value) +{if (reg < 8) + MMUReg[reg] = value ; + if (reg == 1) { + state->prog32Sig = value >> 4 & 1 ; + state->data32Sig = value >> 5 & 1 ; + state->lateabtSig = value >> 6 & 1 ; + state->bigendSig = value >> 7 & 1 ; + state->Emulate = TRUE ; /* force ARMulator to notice these now !*/ + } + return(TRUE) ; + } + + +/* What follows is the Validation Suite Coprocessor. It uses two +co-processor numbers (4 and 5) and has the follwing functionality. +Sixteen registers. Both co-processor nuimbers can be used in an MCR and +MRC to access these registers. CP 4 can LDC and STC to and from the +registers. CP 4 and CP 5 CDP 0 will busy wait for the number of cycles +specified by a CP register. CP 5 CDP 1 issues a FIQ after a number of +cycles (specified in a CP register), CDP 2 issues an IRQW in the same +way, CDP 3 and 4 turn of the FIQ and IRQ source, and CDP 5 stores a 32 +bit time value in a CP register (actually it's the total number of N, S, +I, C and F cyles) */ + +static ARMword ValReg[16] ; + +static unsigned ValLDC(ARMul_State *state, unsigned type, + ARMword instr, ARMword data) +{static unsigned words ; + + if (type != ARMul_DATA) { + words = 0 ; + return(ARMul_DONE) ; + } + if (BIT(22)) { /* it's a long access, get two words */ + ValReg[BITS(12,15)] = data ; + if (words++ == 4) + return(ARMul_DONE) ; + else + return(ARMul_INC) ; + } + else { /* get just one word */ + ValReg[BITS(12,15)] = data ; + return(ARMul_DONE) ; + } + } + +static unsigned ValSTC(ARMul_State *state, unsigned type, + ARMword instr, ARMword *data) +{static unsigned words ; + + if (type != ARMul_DATA) { + words = 0 ; + return(ARMul_DONE) ; + } + if (BIT(22)) { /* it's a long access, get two words */ + *data = ValReg[BITS(12,15)] ; + if (words++ == 4) + return(ARMul_DONE) ; + else + return(ARMul_INC) ; + } + else { /* get just one word */ + *data = ValReg[BITS(12,15)] ; + return(ARMul_DONE) ; + } + } + +static unsigned ValMRC(ARMul_State *state, unsigned type, ARMword instr,ARMword *value) +{ + *value = ValReg[BITS(16,19)] ; + return(ARMul_DONE) ; + } + +static unsigned ValMCR(ARMul_State *state, unsigned type, ARMword instr, ARMword value) +{ + ValReg[BITS(16,19)] = value ; + return(ARMul_DONE) ; + } + +static unsigned ValCDP(ARMul_State *state, unsigned type, ARMword instr) +{ + static unsigned long finish = 0 ; + ARMword howlong ; + + howlong = ValReg[BITS(0,3)] ; + if (BITS(20,23)==0) { + if (type == ARMul_FIRST) { /* First cycle of a busy wait */ + finish = ARMul_Time(state) + howlong ; + if (howlong == 0) + return(ARMul_DONE) ; + else + return(ARMul_BUSY) ; + } + else if (type == ARMul_BUSY) { + if (ARMul_Time(state) >= finish) + return(ARMul_DONE) ; + else + return(ARMul_BUSY) ; + } + } + return(ARMul_CANT) ; + } + +static unsigned DoAFIQ(ARMul_State *state) +{state->NfiqSig = LOW ; + state->Exception++ ; + return(0) ; +} + +static unsigned DoAIRQ(ARMul_State *state) +{state->NirqSig = LOW ; + state->Exception++ ; + return(0) ; +} + +static unsigned IntCDP(ARMul_State *state, unsigned type, ARMword instr) +{static unsigned long finish ; + ARMword howlong ; + + howlong = ValReg[BITS(0,3)] ; + switch((int)BITS(20,23)) { + case 0 : if (type == ARMul_FIRST) { /* First cycle of a busy wait */ + finish = ARMul_Time(state) + howlong ; + if (howlong == 0) + return(ARMul_DONE) ; + else + return(ARMul_BUSY) ; + } + else if (type == ARMul_BUSY) { + if (ARMul_Time(state) >= finish) + return(ARMul_DONE) ; + else + return(ARMul_BUSY) ; + } + return(ARMul_DONE) ; + case 1 : if (howlong == 0) + ARMul_Abort(state,ARMul_FIQV) ; + else + ARMul_ScheduleEvent(state,howlong,DoAFIQ) ; + return(ARMul_DONE) ; + case 2 : if (howlong == 0) + ARMul_Abort(state,ARMul_IRQV) ; + else + ARMul_ScheduleEvent(state,howlong,DoAIRQ) ; + return(ARMul_DONE) ; + case 3 : state->NfiqSig = HIGH ; + state->Exception-- ; + return(ARMul_DONE) ; + case 4 : state->NirqSig = HIGH ; + state->Exception-- ; + return(ARMul_DONE) ; + case 5 : ValReg[BITS(0,3)] = ARMul_Time(state) ; + return(ARMul_DONE) ; + } + return(ARMul_CANT) ; + } + +/***************************************************************************\ +* Install co-processor instruction handlers in this routine * +\***************************************************************************/ + +unsigned ARMul_CoProInit(ARMul_State *state) +{register unsigned i ; + + for (i = 0 ; i < 16 ; i++) /* initialise tham all first */ + ARMul_CoProDetach(state, i) ; + + /* Install CoPro Instruction handlers here + The format is + ARMul_CoProAttach(state, CP Number, Init routine, Exit routine + LDC routine, STC routine, MRC routine, MCR routine, + CDP routine, Read Reg routine, Write Reg routine) ; + */ + + ARMul_CoProAttach(state, 4, NULL, NULL, + ValLDC, ValSTC, ValMRC, ValMCR, + ValCDP, NULL, NULL) ; + + ARMul_CoProAttach(state, 5, NULL, NULL, + NULL, NULL, ValMRC, ValMCR, + IntCDP, NULL, NULL) ; + + ARMul_CoProAttach(state, 15, MMUInit, NULL, + NULL, NULL, MMUMRC, MMUMCR, + NULL, MMURead, MMUWrite) ; + + + /* No handlers below here */ + + for (i = 0 ; i < 16 ; i++) /* Call all the initialisation routines */ + if (state->CPInit[i]) + (state->CPInit[i])(state) ; + return(TRUE) ; + } + +/***************************************************************************\ +* Install co-processor finalisation routines in this routine * +\***************************************************************************/ + +void ARMul_CoProExit(ARMul_State *state) +{register unsigned i ; + + for (i = 0 ; i < 16 ; i++) + if (state->CPExit[i]) + (state->CPExit[i])(state) ; + for (i = 0 ; i < 16 ; i++) /* Detach all handlers */ + ARMul_CoProDetach(state, i) ; + } + +/***************************************************************************\ +* Routines to hook Co-processors into ARMulator * +\***************************************************************************/ + +void ARMul_CoProAttach(ARMul_State *state, unsigned number, + ARMul_CPInits *init, ARMul_CPExits *exit, + ARMul_LDCs *ldc, ARMul_STCs *stc, + ARMul_MRCs *mrc, ARMul_MCRs *mcr, ARMul_CDPs *cdp, + ARMul_CPReads *read, ARMul_CPWrites *write) +{if (init != NULL) + state->CPInit[number] = init ; + if (exit != NULL) + state->CPExit[number] = exit ; + if (ldc != NULL) + state->LDC[number] = ldc ; + if (stc != NULL) + state->STC[number] = stc ; + if (mrc != NULL) + state->MRC[number] = mrc ; + if (mcr != NULL) + state->MCR[number] = mcr ; + if (cdp != NULL) + state->CDP[number] = cdp ; + if (read != NULL) + state->CPRead[number] = read ; + if (write != NULL) + state->CPWrite[number] = write ; +} + +void ARMul_CoProDetach(ARMul_State *state, unsigned number) +{ARMul_CoProAttach(state, number, NULL, NULL, + NoCoPro4R, NoCoPro4W, NoCoPro4W, NoCoPro4R, + NoCoPro3R, NULL, NULL) ; + state->CPInit[number] = NULL ; + state->CPExit[number] = NULL ; + state->CPRead[number] = NULL ; + state->CPWrite[number] = NULL ; +} + +/***************************************************************************\ +* There is no CoPro around, so Undefined Instruction trap * +\***************************************************************************/ + +static unsigned NoCoPro3R(ARMul_State *state,unsigned a,ARMword b) +{return(ARMul_CANT) ;} + +static unsigned NoCoPro4R(ARMul_State *state, unsigned a,ARMword b,ARMword c) +{return(ARMul_CANT) ;} + +static unsigned NoCoPro4W(ARMul_State *state, unsigned a,ARMword b,ARMword *c) +{return(ARMul_CANT) ;} diff --git a/sim/arm/armdefs.h b/sim/arm/armdefs.h new file mode 100644 index 00000000000..1e1f3527dd7 --- /dev/null +++ b/sim/arm/armdefs.h @@ -0,0 +1,353 @@ +/* armdefs.h -- ARMulator common definitions: ARM6 Instruction Emulator. + Copyright (C) 1994 Advanced RISC Machines Ltd. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include +#include + +#define FALSE 0 +#define TRUE 1 +#define LOW 0 +#define HIGH 1 +#define LOWHIGH 1 +#define HIGHLOW 2 + +#ifndef __STDC__ +typedef char * VoidStar ; +#endif + +typedef unsigned long ARMword ; /* must be 32 bits wide */ + +typedef struct ARMul_State ARMul_State ; + +typedef unsigned ARMul_CPInits(ARMul_State *state) ; +typedef unsigned ARMul_CPExits(ARMul_State *state) ; +typedef unsigned ARMul_LDCs(ARMul_State *state,unsigned type,ARMword instr,ARMword value) ; +typedef unsigned ARMul_STCs(ARMul_State *state,unsigned type,ARMword instr,ARMword *value) ; +typedef unsigned ARMul_MRCs(ARMul_State *state,unsigned type,ARMword instr,ARMword *value) ; +typedef unsigned ARMul_MCRs(ARMul_State *state,unsigned type,ARMword instr,ARMword value) ; +typedef unsigned ARMul_CDPs(ARMul_State *state,unsigned type,ARMword instr) ; +typedef unsigned ARMul_CPReads(ARMul_State *state,unsigned reg,ARMword *value) ; +typedef unsigned ARMul_CPWrites(ARMul_State *state,unsigned reg,ARMword value) ; + +struct ARMul_State { + ARMword Emulate ; /* to start and stop emulation */ + unsigned EndCondition ; /* reason for stopping */ + unsigned ErrorCode ; /* type of illegal instruction */ + ARMword Reg[16] ; /* the current register file */ + ARMword RegBank[7][16] ; /* all the registers */ + ARMword Cpsr ; /* the current psr */ + ARMword Spsr[7] ; /* the exception psr's */ + ARMword NFlag, ZFlag, CFlag, VFlag, IFFlags ; /* dummy flags for speed */ +#ifdef MODET + ARMword TFlag ; /* Thumb state */ +#endif + ARMword Bank ; /* the current register bank */ + ARMword Mode ; /* the current mode */ + ARMword instr, pc, temp ; /* saved register state */ + ARMword loaded, decoded ; /* saved pipeline state */ + unsigned long NumScycles, + NumNcycles, + NumIcycles, + NumCcycles, + NumFcycles ; /* emulated cycles used */ + unsigned long NumInstrs ; /* the number of instructions executed */ + unsigned NextInstr ; + unsigned VectorCatch ; /* caught exception mask */ + unsigned CallDebug ; /* set to call the debugger */ + unsigned CanWatch ; /* set by memory interface if its willing to suffer the + overhead of checking for watchpoints on each memory + access */ + unsigned MemReadDebug, MemWriteDebug ; + unsigned long StopHandle ; + + unsigned char *MemDataPtr ; /* admin data */ + unsigned char *MemInPtr ; /* the Data In bus */ + unsigned char *MemOutPtr ; /* the Data Out bus (which you may not need */ + unsigned char *MemSparePtr ; /* extra space */ + ARMword MemSize ; + + unsigned char *OSptr ; /* OS Handle */ + char *CommandLine ; /* Command Line from ARMsd */ + + ARMul_CPInits *CPInit[16] ; /* coprocessor initialisers */ + ARMul_CPExits *CPExit[16] ; /* coprocessor finalisers */ + ARMul_LDCs *LDC[16] ; /* LDC instruction */ + ARMul_STCs *STC[16] ; /* STC instruction */ + ARMul_MRCs *MRC[16] ; /* MRC instruction */ + ARMul_MCRs *MCR[16] ; /* MCR instruction */ + ARMul_CDPs *CDP[16] ; /* CDP instruction */ + ARMul_CPReads *CPRead[16] ; /* Read CP register */ + ARMul_CPWrites *CPWrite[16] ; /* Write CP register */ + unsigned char *CPData[16] ; /* Coprocessor data */ + unsigned char const *CPRegWords[16] ; /* map of coprocessor register sizes */ + + unsigned EventSet ; /* the number of events in the queue */ + unsigned long Now ; /* time to the nearest cycle */ + struct EventNode **EventPtr ; /* the event list */ + + unsigned Exception ; /* enable the next four values */ + unsigned Debug ; /* show instructions as they are executed */ + unsigned NresetSig ; /* reset the processor */ + unsigned NfiqSig ; + unsigned NirqSig ; + + unsigned abortSig ; + unsigned NtransSig ; + unsigned bigendSig ; + unsigned prog32Sig ; + unsigned data32Sig ; + unsigned lateabtSig ; + ARMword Vector ; /* synthesize aborts in cycle modes */ + ARMword Aborted ; /* sticky flag for aborts */ + ARMword Reseted ; /* sticky flag for Reset */ + ARMword Inted, LastInted ; /* sticky flags for interrupts */ + ARMword Base ; /* extra hand for base writeback */ + ARMword AbortAddr ; /* to keep track of Prefetch aborts */ + + const struct Dbg_HostosInterface *hostif; + + int verbose; /* non-zero means print various messages like the banner */ + } ; + +#define ResetPin NresetSig +#define FIQPin NfiqSig +#define IRQPin NirqSig +#define AbortPin abortSig +#define TransPin NtransSig +#define BigEndPin bigendSig +#define Prog32Pin prog32Sig +#define Data32Pin data32Sig +#define LateAbortPin lateabtSig + +/***************************************************************************\ +* Types of ARM we know about * +\***************************************************************************/ + +/* The bitflags */ +#define ARM_Fix26_Prop 0x01 +#define ARM_Nexec_Prop 0x02 +#define ARM_Debug_Prop 0x10 +#define ARM_Isync_Prop ARM_Debug_Prop +#define ARM_Lock_Prop 0x20 + +/* ARM2 family */ +#define ARM2 (ARM_Fix26_Prop) +#define ARM2as ARM2 +#define ARM61 ARM2 +#define ARM3 ARM2 + +#ifdef ARM60 /* previous definition in armopts.h */ +#undef ARM60 +#endif + +/* ARM6 family */ +#define ARM6 (ARM_Lock_Prop) +#define ARM60 ARM6 +#define ARM600 ARM6 +#define ARM610 ARM6 +#define ARM620 ARM6 + + +/***************************************************************************\ +* Macros to extract instruction fields * +\***************************************************************************/ + +#define BIT(n) ( (ARMword)(instr>>(n))&1) /* bit n of instruction */ +#define BITS(m,n) ( (ARMword)(instr<<(31-(n))) >> ((31-(n))+(m)) ) /* bits m to n of instr */ +#define TOPBITS(n) (instr >> (n)) /* bits 31 to n of instr */ + +/***************************************************************************\ +* The hardware vector addresses * +\***************************************************************************/ + +#define ARMResetV 0L +#define ARMUndefinedInstrV 4L +#define ARMSWIV 8L +#define ARMPrefetchAbortV 12L +#define ARMDataAbortV 16L +#define ARMAddrExceptnV 20L +#define ARMIRQV 24L +#define ARMFIQV 28L +#define ARMErrorV 32L /* This is an offset, not an address ! */ + +#define ARMul_ResetV ARMResetV +#define ARMul_UndefinedInstrV ARMUndefinedInstrV +#define ARMul_SWIV ARMSWIV +#define ARMul_PrefetchAbortV ARMPrefetchAbortV +#define ARMul_DataAbortV ARMDataAbortV +#define ARMul_AddrExceptnV ARMAddrExceptnV +#define ARMul_IRQV ARMIRQV +#define ARMul_FIQV ARMFIQV + +/***************************************************************************\ +* Mode and Bank Constants * +\***************************************************************************/ + +#define USER26MODE 0L +#define FIQ26MODE 1L +#define IRQ26MODE 2L +#define SVC26MODE 3L +#define USER32MODE 16L +#define FIQ32MODE 17L +#define IRQ32MODE 18L +#define SVC32MODE 19L +#define ABORT32MODE 23L +#define UNDEF32MODE 27L + +#define ARM32BITMODE (state->Mode > 3) +#define ARM26BITMODE (state->Mode <= 3) +#define ARMMODE (state->Mode) +#define ARMul_MODEBITS 0x1fL +#define ARMul_MODE32BIT ARM32BITMODE +#define ARMul_MODE26BIT ARM26BITMODE + +#define USERBANK 0 +#define FIQBANK 1 +#define IRQBANK 2 +#define SVCBANK 3 +#define ABORTBANK 4 +#define UNDEFBANK 5 +#define DUMMYBANK 6 + +/***************************************************************************\ +* Definitons of things in the emulator * +\***************************************************************************/ + +extern void ARMul_EmulateInit(void) ; +extern ARMul_State *ARMul_NewState(void) ; +extern void ARMul_Reset(ARMul_State *state) ; +extern ARMword ARMul_DoProg(ARMul_State *state) ; +extern ARMword ARMul_DoInstr(ARMul_State *state) ; + +/***************************************************************************\ +* Definitons of things for event handling * +\***************************************************************************/ + +extern void ARMul_ScheduleEvent(ARMul_State *state, unsigned long delay, unsigned (*func)() ) ; +extern void ARMul_EnvokeEvent(ARMul_State *state) ; +extern unsigned long ARMul_Time(ARMul_State *state) ; + +/***************************************************************************\ +* Useful support routines * +\***************************************************************************/ + +extern ARMword ARMul_GetReg(ARMul_State *state, unsigned mode, unsigned reg) ; +extern void ARMul_SetReg(ARMul_State *state, unsigned mode, unsigned reg, ARMword value) ; +extern ARMword ARMul_GetPC(ARMul_State *state) ; +extern ARMword ARMul_GetNextPC(ARMul_State *state) ; +extern void ARMul_SetPC(ARMul_State *state, ARMword value) ; +extern ARMword ARMul_GetR15(ARMul_State *state) ; +extern void ARMul_SetR15(ARMul_State *state, ARMword value) ; + +extern ARMword ARMul_GetCPSR(ARMul_State *state) ; +extern void ARMul_SetCPSR(ARMul_State *state, ARMword value) ; +extern ARMword ARMul_GetSPSR(ARMul_State *state, ARMword mode) ; +extern void ARMul_SetSPSR(ARMul_State *state, ARMword mode, ARMword value) ; + +/***************************************************************************\ +* Definitons of things to handle aborts * +\***************************************************************************/ + +extern void ARMul_Abort(ARMul_State *state, ARMword address) ; +#define ARMul_ABORTWORD 0xefffffff /* SWI -1 */ +#define ARMul_PREFETCHABORT(address) if (state->AbortAddr == 1) \ + state->AbortAddr = (address & ~3L) +#define ARMul_DATAABORT(address) state->abortSig = HIGH ; \ + state->Aborted = ARMul_DataAbortV ; +#define ARMul_CLEARABORT state->abortSig = LOW + +/***************************************************************************\ +* Definitons of things in the memory interface * +\***************************************************************************/ + +extern unsigned ARMul_MemoryInit(ARMul_State *state,unsigned long initmemsize) ; +extern void ARMul_MemoryExit(ARMul_State *state) ; + +extern ARMword ARMul_LoadInstrS(ARMul_State *state,ARMword address,ARMword isize) ; +extern ARMword ARMul_LoadInstrN(ARMul_State *state,ARMword address,ARMword isize) ; +extern ARMword ARMul_ReLoadInstr(ARMul_State *state,ARMword address,ARMword isize) ; + +extern ARMword ARMul_LoadWordS(ARMul_State *state,ARMword address) ; +extern ARMword ARMul_LoadWordN(ARMul_State *state,ARMword address) ; +extern ARMword ARMul_LoadHalfWord(ARMul_State *state,ARMword address) ; +extern ARMword ARMul_LoadByte(ARMul_State *state,ARMword address) ; + +extern void ARMul_StoreWordS(ARMul_State *state,ARMword address, ARMword data) ; +extern void ARMul_StoreWordN(ARMul_State *state,ARMword address, ARMword data) ; +extern void ARMul_StoreHalfWord(ARMul_State *state,ARMword address, ARMword data) ; +extern void ARMul_StoreByte(ARMul_State *state,ARMword address, ARMword data) ; + +extern ARMword ARMul_SwapWord(ARMul_State *state,ARMword address, ARMword data) ; +extern ARMword ARMul_SwapByte(ARMul_State *state,ARMword address, ARMword data) ; + +extern void ARMul_Icycles(ARMul_State *state,unsigned number, ARMword address) ; +extern void ARMul_Ccycles(ARMul_State *state,unsigned number, ARMword address) ; + +extern ARMword ARMul_ReadWord(ARMul_State *state,ARMword address) ; +extern ARMword ARMul_ReadByte(ARMul_State *state,ARMword address) ; +extern void ARMul_WriteWord(ARMul_State *state,ARMword address, ARMword data) ; +extern void ARMul_WriteByte(ARMul_State *state,ARMword address, ARMword data) ; + +extern ARMword ARMul_MemAccess(ARMul_State *state,ARMword,ARMword,ARMword, + ARMword,ARMword,ARMword,ARMword,ARMword,ARMword,ARMword) ; + +/***************************************************************************\ +* Definitons of things in the co-processor interface * +\***************************************************************************/ + +#define ARMul_FIRST 0 +#define ARMul_TRANSFER 1 +#define ARMul_BUSY 2 +#define ARMul_DATA 3 +#define ARMul_INTERRUPT 4 +#define ARMul_DONE 0 +#define ARMul_CANT 1 +#define ARMul_INC 3 + +extern unsigned ARMul_CoProInit(ARMul_State *state) ; +extern void ARMul_CoProExit(ARMul_State *state) ; +extern void ARMul_CoProAttach(ARMul_State *state, unsigned number, + ARMul_CPInits *init, ARMul_CPExits *exit, + ARMul_LDCs *ldc, ARMul_STCs *stc, + ARMul_MRCs *mrc, ARMul_MCRs *mcr, + ARMul_CDPs *cdp, + ARMul_CPReads *read, ARMul_CPWrites *write) ; +extern void ARMul_CoProDetach(ARMul_State *state, unsigned number) ; + +/***************************************************************************\ +* Definitons of things in the host environment * +\***************************************************************************/ + +extern unsigned ARMul_OSInit(ARMul_State *state) ; +extern void ARMul_OSExit(ARMul_State *state) ; +extern unsigned ARMul_OSHandleSWI(ARMul_State *state,ARMword number) ; +extern ARMword ARMul_OSLastErrorP(ARMul_State *state) ; + +extern ARMword ARMul_Debug(ARMul_State *state, ARMword pc, ARMword instr) ; +extern unsigned ARMul_OSException(ARMul_State *state, ARMword vector, ARMword pc) ; +extern int rdi_log ; + +/***************************************************************************\ +* Host-dependent stuff * +\***************************************************************************/ + +#ifdef macintosh +pascal void SpinCursor(short increment); /* copied from CursorCtl.h */ +# define HOURGLASS SpinCursor( 1 ) +# define HOURGLASS_RATE 1023 /* 2^n - 1 */ +#endif + diff --git a/sim/arm/armemu.c b/sim/arm/armemu.c new file mode 100644 index 00000000000..171f1c8c0c8 --- /dev/null +++ b/sim/arm/armemu.c @@ -0,0 +1,3454 @@ +/* armemu.c -- Main instruction emulation: ARM7 Instruction Emulator. + Copyright (C) 1994 Advanced RISC Machines Ltd. + Modifications to add arch. v4 support by . + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "armdefs.h" +#include "armemu.h" + +static ARMword GetDPRegRHS(ARMul_State *state, ARMword instr) ; +static ARMword GetDPSRegRHS(ARMul_State *state, ARMword instr) ; +static void WriteR15(ARMul_State *state, ARMword src) ; +static void WriteSR15(ARMul_State *state, ARMword src) ; +static ARMword GetLSRegRHS(ARMul_State *state, ARMword instr) ; +static ARMword GetLS7RHS(ARMul_State *state, ARMword instr) ; +static unsigned LoadWord(ARMul_State *state, ARMword instr, ARMword address) ; +static unsigned LoadHalfWord(ARMul_State *state, ARMword instr, ARMword address,int signextend) ; +static unsigned LoadByte(ARMul_State *state, ARMword instr, ARMword address,int signextend) ; +static unsigned StoreWord(ARMul_State *state, ARMword instr, ARMword address) ; +static unsigned StoreHalfWord(ARMul_State *state, ARMword instr, ARMword address) ; +static unsigned StoreByte(ARMul_State *state, ARMword instr, ARMword address) ; +static void LoadMult(ARMul_State *state, ARMword address, ARMword instr, ARMword WBBase) ; +static void StoreMult(ARMul_State *state, ARMword address, ARMword instr, ARMword WBBase) ; +static void LoadSMult(ARMul_State *state, ARMword address, ARMword instr, ARMword WBBase) ; +static void StoreSMult(ARMul_State *state, ARMword address, ARMword instr, ARMword WBBase) ; +static unsigned Multiply64(ARMul_State *state, ARMword instr,int signextend,int scc) ; +static unsigned MultiplyAdd64(ARMul_State *state, ARMword instr,int signextend,int scc) ; + +#define LUNSIGNED (0) /* unsigned operation */ +#define LSIGNED (1) /* signed operation */ +#define LDEFAULT (0) /* default : do nothing */ +#define LSCC (1) /* set condition codes on result */ + +/***************************************************************************\ +* short-hand macros for LDR/STR * +\***************************************************************************/ + +/* store post decrement writeback */ +#define SHDOWNWB() \ + lhs = LHS ; \ + if (StoreHalfWord(state, instr, lhs)) \ + LSBase = lhs - GetLS7RHS(state, instr) ; + +/* store post increment writeback */ +#define SHUPWB() \ + lhs = LHS ; \ + if (StoreHalfWord(state, instr, lhs)) \ + LSBase = lhs + GetLS7RHS(state, instr) ; + +/* store pre decrement */ +#define SHPREDOWN() \ + (void)StoreHalfWord(state, instr, LHS - GetLS7RHS(state, instr)) ; + +/* store pre decrement writeback */ +#define SHPREDOWNWB() \ + temp = LHS - GetLS7RHS(state, instr) ; \ + if (StoreHalfWord(state, instr, temp)) \ + LSBase = temp ; + +/* store pre increment */ +#define SHPREUP() \ + (void)StoreHalfWord(state, instr, LHS + GetLS7RHS(state, instr)) ; + +/* store pre increment writeback */ +#define SHPREUPWB() \ + temp = LHS + GetLS7RHS(state, instr) ; \ + if (StoreHalfWord(state, instr, temp)) \ + LSBase = temp ; + +/* load post decrement writeback */ +#define LHPOSTDOWN() \ +{ \ + int done = 1 ; \ + lhs = LHS ; \ + switch (BITS(5,6)) { \ + case 1: /* H */ \ + if (LoadHalfWord(state,instr,lhs,LUNSIGNED)) \ + LSBase = lhs - GetLS7RHS(state,instr) ; \ + break ; \ + case 2: /* SB */ \ + if (LoadByte(state,instr,lhs,LSIGNED)) \ + LSBase = lhs - GetLS7RHS(state,instr) ; \ + break ; \ + case 3: /* SH */ \ + if (LoadHalfWord(state,instr,lhs,LSIGNED)) \ + LSBase = lhs - GetLS7RHS(state,instr) ; \ + break ; \ + case 0: /* SWP handled elsewhere */ \ + default: \ + done = 0 ; \ + break ; \ + } \ + if (done) \ + break ; \ +} + +/* load post increment writeback */ +#define LHPOSTUP() \ +{ \ + int done = 1 ; \ + lhs = LHS ; \ + switch (BITS(5,6)) { \ + case 1: /* H */ \ + if (LoadHalfWord(state,instr,lhs,LUNSIGNED)) \ + LSBase = lhs + GetLS7RHS(state,instr) ; \ + break ; \ + case 2: /* SB */ \ + if (LoadByte(state,instr,lhs,LSIGNED)) \ + LSBase = lhs + GetLS7RHS(state,instr) ; \ + break ; \ + case 3: /* SH */ \ + if (LoadHalfWord(state,instr,lhs,LSIGNED)) \ + LSBase = lhs + GetLS7RHS(state,instr) ; \ + break ; \ + case 0: /* SWP handled elsewhere */ \ + default: \ + done = 0 ; \ + break ; \ + } \ + if (done) \ + break ; \ +} + +/* load pre decrement */ +#define LHPREDOWN() \ +{ \ + int done = 1 ; \ + temp = LHS - GetLS7RHS(state,instr) ; \ + switch (BITS(5,6)) { \ + case 1: /* H */ \ + (void)LoadHalfWord(state,instr,temp,LUNSIGNED) ; \ + break ; \ + case 2: /* SB */ \ + (void)LoadByte(state,instr,temp,LSIGNED) ; \ + break ; \ + case 3: /* SH */ \ + (void)LoadHalfWord(state,instr,temp,LSIGNED) ; \ + break ; \ + case 0: /* SWP handled elsewhere */ \ + default: \ + done = 0 ; \ + break ; \ + } \ + if (done) \ + break ; \ +} + +/* load pre decrement writeback */ +#define LHPREDOWNWB() \ +{ \ + int done = 1 ; \ + temp = LHS - GetLS7RHS(state, instr) ; \ + switch (BITS(5,6)) { \ + case 1: /* H */ \ + if (LoadHalfWord(state,instr,temp,LUNSIGNED)) \ + LSBase = temp ; \ + break ; \ + case 2: /* SB */ \ + if (LoadByte(state,instr,temp,LSIGNED)) \ + LSBase = temp ; \ + break ; \ + case 3: /* SH */ \ + if (LoadHalfWord(state,instr,temp,LSIGNED)) \ + LSBase = temp ; \ + break ; \ + case 0: /* SWP handled elsewhere */ \ + default: \ + done = 0 ; \ + break ; \ + } \ + if (done) \ + break ; \ +} + +/* load pre increment */ +#define LHPREUP() \ +{ \ + int done = 1 ; \ + temp = LHS + GetLS7RHS(state,instr) ; \ + switch (BITS(5,6)) { \ + case 1: /* H */ \ + (void)LoadHalfWord(state,instr,temp,LUNSIGNED) ; \ + break ; \ + case 2: /* SB */ \ + (void)LoadByte(state,instr,temp,LSIGNED) ; \ + break ; \ + case 3: /* SH */ \ + (void)LoadHalfWord(state,instr,temp,LSIGNED) ; \ + break ; \ + case 0: /* SWP handled elsewhere */ \ + default: \ + done = 0 ; \ + break ; \ + } \ + if (done) \ + break ; \ +} + +/* load pre increment writeback */ +#define LHPREUPWB() \ +{ \ + int done = 1 ; \ + temp = LHS + GetLS7RHS(state, instr) ; \ + switch (BITS(5,6)) { \ + case 1: /* H */ \ + if (LoadHalfWord(state,instr,temp,LUNSIGNED)) \ + LSBase = temp ; \ + break ; \ + case 2: /* SB */ \ + if (LoadByte(state,instr,temp,LSIGNED)) \ + LSBase = temp ; \ + break ; \ + case 3: /* SH */ \ + if (LoadHalfWord(state,instr,temp,LSIGNED)) \ + LSBase = temp ; \ + break ; \ + case 0: /* SWP handled elsewhere */ \ + default: \ + done = 0 ; \ + break ; \ + } \ + if (done) \ + break ; \ +} + +/***************************************************************************\ +* EMULATION of ARM6 * +\***************************************************************************/ + +/* The PC pipeline value depends on whether ARM or Thumb instructions + are being executed: */ +ARMword isize; + +#ifdef MODE32 +ARMword ARMul_Emulate32(register ARMul_State *state) +{ +#else +ARMword ARMul_Emulate26(register ARMul_State *state) +{ +#endif + register ARMword instr, /* the current instruction */ + dest, /* almost the DestBus */ + temp, /* ubiquitous third hand */ + pc ; /* the address of the current instruction */ + ARMword lhs, rhs ; /* almost the ABus and BBus */ + ARMword decoded, loaded ; /* instruction pipeline */ + +/***************************************************************************\ +* Execute the next instruction * +\***************************************************************************/ + + if (state->NextInstr < PRIMEPIPE) { + decoded = state->decoded ; + loaded = state->loaded ; + pc = state->pc ; + } + + do { /* just keep going */ +#ifdef MODET + if (TFLAG) { + isize = 2; + } else +#endif + isize = 4; + switch (state->NextInstr) { + case SEQ : + state->Reg[15] += isize ; /* Advance the pipeline, and an S cycle */ + pc += isize ; + instr = decoded ; + decoded = loaded ; + loaded = ARMul_LoadInstrS(state,pc+(isize * 2),isize) ; + break ; + + case NONSEQ : + state->Reg[15] += isize ; /* Advance the pipeline, and an N cycle */ + pc += isize ; + instr = decoded ; + decoded = loaded ; + loaded = ARMul_LoadInstrN(state,pc+(isize * 2),isize) ; + NORMALCYCLE ; + break ; + + case PCINCEDSEQ : + pc += isize ; /* Program counter advanced, and an S cycle */ + instr = decoded ; + decoded = loaded ; + loaded = ARMul_LoadInstrS(state,pc+(isize * 2),isize) ; + NORMALCYCLE ; + break ; + + case PCINCEDNONSEQ : + pc += isize ; /* Program counter advanced, and an N cycle */ + instr = decoded ; + decoded = loaded ; + loaded = ARMul_LoadInstrN(state,pc+(isize * 2),isize) ; + NORMALCYCLE ; + break ; + + case RESUME : /* The program counter has been changed */ + pc = state->Reg[15] ; +#ifndef MODE32 + pc = pc & R15PCBITS ; +#endif + state->Reg[15] = pc + (isize * 2) ; + state->Aborted = 0 ; + instr = ARMul_ReLoadInstr(state,pc,isize) ; + decoded = ARMul_ReLoadInstr(state,pc + isize,isize) ; + loaded = ARMul_ReLoadInstr(state,pc + isize * 2,isize) ; + NORMALCYCLE ; + break ; + + default : /* The program counter has been changed */ + pc = state->Reg[15] ; +#ifndef MODE32 + pc = pc & R15PCBITS ; +#endif + state->Reg[15] = pc + (isize * 2) ; + state->Aborted = 0 ; + instr = ARMul_LoadInstrN(state,pc,isize) ; + decoded = ARMul_LoadInstrS(state,pc + (isize),isize) ; + loaded = ARMul_LoadInstrS(state,pc + (isize * 2),isize) ; + NORMALCYCLE ; + break ; + } + if (state->EventSet) + ARMul_EnvokeEvent(state) ; + +#if 0 + /* Enable this for a helpful bit of debugging when tracing is needed. */ + fprintf (stderr, "pc: %x, instr: %x\n", pc & ~1, instr); + if (instr == 0) abort (); +#endif + + if (state->Exception) { /* Any exceptions */ + if (state->NresetSig == LOW) { + ARMul_Abort(state,ARMul_ResetV) ; + break ; + } + else if (!state->NfiqSig && !FFLAG) { + ARMul_Abort(state,ARMul_FIQV) ; + break ; + } + else if (!state->NirqSig && !IFLAG) { + ARMul_Abort(state,ARMul_IRQV) ; + break ; + } + } + + if (state->CallDebug > 0) { + instr = ARMul_Debug(state,pc,instr) ; + if (state->Emulate < ONCE) { + state->NextInstr = RESUME ; + break ; + } + if (state->Debug) { + fprintf(stderr,"At %08lx Instr %08lx Mode %02lx\n",pc,instr,state->Mode) ; + (void)fgetc(stdin) ; + } + } + else + if (state->Emulate < ONCE) { + state->NextInstr = RESUME ; + break ; + } + + state->NumInstrs++ ; + +#ifdef MODET + /* Provide Thumb instruction decoding. If the processor is in Thumb + mode, then we can simply decode the Thumb instruction, and map it + to the corresponding ARM instruction (by directly loading the + instr variable, and letting the normal ARM simulator + execute). There are some caveats to ensure that the correct + pipelined PC value is used when executing Thumb code, and also for + dealing with the BL instruction. */ + if (TFLAG) { /* check if in Thumb mode */ + ARMword new; + switch (ARMul_ThumbDecode(state,pc,instr,&new)) { + case t_undefined: + ARMul_UndefInstr(state,instr); /* This is a Thumb instruction */ + break; + + case t_branch: /* already processed */ + goto donext; + + case t_decoded: /* ARM instruction available */ + instr = new; /* so continue instruction decoding */ + break; + } + } +#endif + +/***************************************************************************\ +* Check the condition codes * +\***************************************************************************/ + if ((temp = TOPBITS(28)) == AL) + goto mainswitch ; /* vile deed in the need for speed */ + + switch ((int)TOPBITS(28)) { /* check the condition code */ + case AL : temp=TRUE ; + break ; + case NV : temp=FALSE ; + break ; + case EQ : temp=ZFLAG ; + break ; + case NE : temp=!ZFLAG ; + break ; + case VS : temp=VFLAG ; + break ; + case VC : temp=!VFLAG ; + break ; + case MI : temp=NFLAG ; + break ; + case PL : temp=!NFLAG ; + break ; + case CS : temp=CFLAG ; + break ; + case CC : temp=!CFLAG ; + break ; + case HI : temp=(CFLAG && !ZFLAG) ; + break ; + case LS : temp=(!CFLAG || ZFLAG) ; + break ; + case GE : temp=((!NFLAG && !VFLAG) || (NFLAG && VFLAG)) ; + break ; + case LT : temp=((NFLAG && !VFLAG) || (!NFLAG && VFLAG)) ; + break ; + case GT : temp=((!NFLAG && !VFLAG && !ZFLAG) || (NFLAG && VFLAG && !ZFLAG)) ; + break ; + case LE : temp=((NFLAG && !VFLAG) || (!NFLAG && VFLAG)) || ZFLAG ; + break ; + } /* cc check */ + +/***************************************************************************\ +* Actual execution of instructions begins here * +\***************************************************************************/ + + if (temp) { /* if the condition codes don't match, stop here */ +mainswitch: + + switch ((int)BITS(20,27)) { + +/***************************************************************************\ +* Data Processing Register RHS Instructions * +\***************************************************************************/ + + case 0x00 : /* AND reg and MUL */ +#ifdef MODET + if (BITS(4,11) == 0xB) { + /* STRH register offset, no write-back, down, post indexed */ + SHDOWNWB() ; + break ; + } + /* TODO: CHECK: should 0xD and 0xF generate undefined intruction aborts? */ +#endif + if (BITS(4,7) == 9) { /* MUL */ + rhs = state->Reg[MULRHSReg] ; + if (MULLHSReg == MULDESTReg) { + UNDEF_MULDestEQOp1 ; + state->Reg[MULDESTReg] = 0 ; + } + else if (MULDESTReg != 15) + state->Reg[MULDESTReg] = state->Reg[MULLHSReg] * rhs ; + else { + UNDEF_MULPCDest ; + } + for (dest = 0, temp = 0 ; dest < 32 ; dest++) + if (rhs & (1L << dest)) + temp = dest ; /* mult takes this many/2 I cycles */ + ARMul_Icycles(state,ARMul_MultTable[temp],0L) ; + } + else { /* AND reg */ + rhs = DPRegRHS ; + dest = LHS & rhs ; + WRITEDEST(dest) ; + } + break ; + + case 0x01 : /* ANDS reg and MULS */ +#ifdef MODET + if ((BITS(4,11) & 0xF9) == 0x9) { + /* LDR register offset, no write-back, down, post indexed */ + LHPOSTDOWN() ; + /* fall through to rest of decoding */ + } +#endif + if (BITS(4,7) == 9) { /* MULS */ + rhs = state->Reg[MULRHSReg] ; + if (MULLHSReg == MULDESTReg) { + UNDEF_MULDestEQOp1 ; + state->Reg[MULDESTReg] = 0 ; + CLEARN ; + SETZ ; + } + else if (MULDESTReg != 15) { + dest = state->Reg[MULLHSReg] * rhs ; + ARMul_NegZero(state,dest) ; + state->Reg[MULDESTReg] = dest ; + } + else { + UNDEF_MULPCDest ; + } + for (dest = 0, temp = 0 ; dest < 32 ; dest++) + if (rhs & (1L << dest)) + temp = dest ; /* mult takes this many/2 I cycles */ + ARMul_Icycles(state,ARMul_MultTable[temp],0L) ; + } + else { /* ANDS reg */ + rhs = DPSRegRHS ; + dest = LHS & rhs ; + WRITESDEST(dest) ; + } + break ; + + case 0x02 : /* EOR reg and MLA */ +#ifdef MODET + if (BITS(4,11) == 0xB) { + /* STRH register offset, write-back, down, post indexed */ + SHDOWNWB() ; + break ; + } +#endif + if (BITS(4,7) == 9) { /* MLA */ + rhs = state->Reg[MULRHSReg] ; + if (MULLHSReg == MULDESTReg) { + UNDEF_MULDestEQOp1 ; + state->Reg[MULDESTReg] = state->Reg[MULACCReg] ; + } + else if (MULDESTReg != 15) + state->Reg[MULDESTReg] = state->Reg[MULLHSReg] * rhs + state->Reg[MULACCReg] ; + else { + UNDEF_MULPCDest ; + } + for (dest = 0, temp = 0 ; dest < 32 ; dest++) + if (rhs & (1L << dest)) + temp = dest ; /* mult takes this many/2 I cycles */ + ARMul_Icycles(state,ARMul_MultTable[temp],0L) ; + } + else { + rhs = DPRegRHS ; + dest = LHS ^ rhs ; + WRITEDEST(dest) ; + } + break ; + + case 0x03 : /* EORS reg and MLAS */ +#ifdef MODET + if ((BITS(4,11) & 0xF9) == 0x9) { + /* LDR register offset, write-back, down, post-indexed */ + LHPOSTDOWN() ; + /* fall through to rest of the decoding */ + } +#endif + if (BITS(4,7) == 9) { /* MLAS */ + rhs = state->Reg[MULRHSReg] ; + if (MULLHSReg == MULDESTReg) { + UNDEF_MULDestEQOp1 ; + dest = state->Reg[MULACCReg] ; + ARMul_NegZero(state,dest) ; + state->Reg[MULDESTReg] = dest ; + } + else if (MULDESTReg != 15) { + dest = state->Reg[MULLHSReg] * rhs + state->Reg[MULACCReg] ; + ARMul_NegZero(state,dest) ; + state->Reg[MULDESTReg] = dest ; + } + else { + UNDEF_MULPCDest ; + } + for (dest = 0, temp = 0 ; dest < 32 ; dest++) + if (rhs & (1L << dest)) + temp = dest ; /* mult takes this many/2 I cycles */ + ARMul_Icycles(state,ARMul_MultTable[temp],0L) ; + } + else { /* EORS Reg */ + rhs = DPSRegRHS ; + dest = LHS ^ rhs ; + WRITESDEST(dest) ; + } + break ; + + case 0x04 : /* SUB reg */ +#ifdef MODET + if (BITS(4,7) == 0xB) { + /* STRH immediate offset, no write-back, down, post indexed */ + SHDOWNWB() ; + break ; + } +#endif + rhs = DPRegRHS; + dest = LHS - rhs ; + WRITEDEST(dest) ; + break ; + + case 0x05 : /* SUBS reg */ +#ifdef MODET + if ((BITS(4,7) & 0x9) == 0x9) { + /* LDR immediate offset, no write-back, down, post indexed */ + LHPOSTDOWN() ; + /* fall through to the rest of the instruction decoding */ + } +#endif + lhs = LHS ; + rhs = DPRegRHS ; + dest = lhs - rhs ; + if ((lhs >= rhs) || ((rhs | lhs) >> 31)) { + ARMul_SubCarry(state,lhs,rhs,dest) ; + ARMul_SubOverflow(state,lhs,rhs,dest) ; + } + else { + CLEARC ; + CLEARV ; + } + WRITESDEST(dest) ; + break ; + + case 0x06 : /* RSB reg */ +#ifdef MODET + if (BITS(4,7) == 0xB) { + /* STRH immediate offset, write-back, down, post indexed */ + SHDOWNWB() ; + break ; + } +#endif + rhs = DPRegRHS ; + dest = rhs - LHS ; + WRITEDEST(dest) ; + break ; + + case 0x07 : /* RSBS reg */ +#ifdef MODET + if ((BITS(4,7) & 0x9) == 0x9) { + /* LDR immediate offset, write-back, down, post indexed */ + LHPOSTDOWN() ; + /* fall through to remainder of instruction decoding */ + } +#endif + lhs = LHS ; + rhs = DPRegRHS ; + dest = rhs - lhs ; + if ((rhs >= lhs) || ((rhs | lhs) >> 31)) { + ARMul_SubCarry(state,rhs,lhs,dest) ; + ARMul_SubOverflow(state,rhs,lhs,dest) ; + } + else { + CLEARC ; + CLEARV ; + } + WRITESDEST(dest) ; + break ; + + case 0x08 : /* ADD reg */ +#ifdef MODET + if (BITS(4,11) == 0xB) { + /* STRH register offset, no write-back, up, post indexed */ + SHUPWB() ; + break ; + } +#endif +#ifdef MODET + if (BITS(4,7) == 0x9) { /* MULL */ + /* 32x32 = 64 */ + ARMul_Icycles(state,Multiply64(state,instr,LUNSIGNED,LDEFAULT),0L) ; + break ; + } +#endif + rhs = DPRegRHS ; + dest = LHS + rhs ; + WRITEDEST(dest) ; + break ; + + case 0x09 : /* ADDS reg */ +#ifdef MODET + if ((BITS(4,11) & 0xF9) == 0x9) { + /* LDR register offset, no write-back, up, post indexed */ + LHPOSTUP() ; + /* fall through to remaining instruction decoding */ + } +#endif +#ifdef MODET + if (BITS(4,7) == 0x9) { /* MULL */ + /* 32x32=64 */ + ARMul_Icycles(state,Multiply64(state,instr,LUNSIGNED,LSCC),0L) ; + break ; + } +#endif + lhs = LHS ; + rhs = DPRegRHS ; + dest = lhs + rhs ; + ASSIGNZ(dest==0) ; + if ((lhs | rhs) >> 30) { /* possible C,V,N to set */ + ASSIGNN(NEG(dest)) ; + ARMul_AddCarry(state,lhs,rhs,dest) ; + ARMul_AddOverflow(state,lhs,rhs,dest) ; + } + else { + CLEARN ; + CLEARC ; + CLEARV ; + } + WRITESDEST(dest) ; + break ; + + case 0x0a : /* ADC reg */ +#ifdef MODET + if (BITS(4,11) == 0xB) { + /* STRH register offset, write-back, up, post-indexed */ + SHUPWB() ; + break ; + } +#endif +#ifdef MODET + if (BITS(4,7) == 0x9) { /* MULL */ + /* 32x32=64 */ + ARMul_Icycles(state,MultiplyAdd64(state,instr,LUNSIGNED,LDEFAULT),0L) ; + break ; + } +#endif + rhs = DPRegRHS ; + dest = LHS + rhs + CFLAG ; + WRITEDEST(dest) ; + break ; + + case 0x0b : /* ADCS reg */ +#ifdef MODET + if ((BITS(4,11) & 0xF9) == 0x9) { + /* LDR register offset, write-back, up, post indexed */ + LHPOSTUP() ; + /* fall through to remaining instruction decoding */ + } +#endif +#ifdef MODET + if (BITS(4,7) == 0x9) { /* MULL */ + /* 32x32=64 */ + ARMul_Icycles(state,MultiplyAdd64(state,instr,LUNSIGNED,LSCC),0L) ; + break ; + } +#endif + lhs = LHS ; + rhs = DPRegRHS ; + dest = lhs + rhs + CFLAG ; + ASSIGNZ(dest==0) ; + if ((lhs | rhs) >> 30) { /* possible C,V,N to set */ + ASSIGNN(NEG(dest)) ; + ARMul_AddCarry(state,lhs,rhs,dest) ; + ARMul_AddOverflow(state,lhs,rhs,dest) ; + } + else { + CLEARN ; + CLEARC ; + CLEARV ; + } + WRITESDEST(dest) ; + break ; + + case 0x0c : /* SBC reg */ +#ifdef MODET + if (BITS(4,7) == 0xB) { + /* STRH immediate offset, no write-back, up post indexed */ + SHUPWB() ; + break ; + } +#endif +#ifdef MODET + if (BITS(4,7) == 0x9) { /* MULL */ + /* 32x32=64 */ + ARMul_Icycles(state,Multiply64(state,instr,LSIGNED,LDEFAULT),0L) ; + break ; + } +#endif + rhs = DPRegRHS ; + dest = LHS - rhs - !CFLAG ; + WRITEDEST(dest) ; + break ; + + case 0x0d : /* SBCS reg */ +#ifdef MODET + if ((BITS(4,7) & 0x9) == 0x9) { + /* LDR immediate offset, no write-back, up, post indexed */ + LHPOSTUP() ; + } +#endif +#ifdef MODET + if (BITS(4,7) == 0x9) { /* MULL */ + /* 32x32=64 */ + ARMul_Icycles(state,Multiply64(state,instr,LSIGNED,LSCC),0L) ; + break ; + } +#endif + lhs = LHS ; + rhs = DPRegRHS ; + dest = lhs - rhs - !CFLAG ; + if ((lhs >= rhs) || ((rhs | lhs) >> 31)) { + ARMul_SubCarry(state,lhs,rhs,dest) ; + ARMul_SubOverflow(state,lhs,rhs,dest) ; + } + else { + CLEARC ; + CLEARV ; + } + WRITESDEST(dest) ; + break ; + + case 0x0e : /* RSC reg */ +#ifdef MODET + if (BITS(4,7) == 0xB) { + /* STRH immediate offset, write-back, up, post indexed */ + SHUPWB() ; + break ; + } +#endif +#ifdef MODET + if (BITS(4,7) == 0x9) { /* MULL */ + /* 32x32=64 */ + ARMul_Icycles(state,MultiplyAdd64(state,instr,LSIGNED,LDEFAULT),0L) ; + break ; + } +#endif + rhs = DPRegRHS ; + dest = rhs - LHS - !CFLAG ; + WRITEDEST(dest) ; + break ; + + case 0x0f : /* RSCS reg */ +#ifdef MODET + if ((BITS(4,7) & 0x9) == 0x9) { + /* LDR immediate offset, write-back, up, post indexed */ + LHPOSTUP() ; + /* fall through to remaining instruction decoding */ + } +#endif +#ifdef MODET + if (BITS(4,7) == 0x9) { /* MULL */ + /* 32x32=64 */ + ARMul_Icycles(state,MultiplyAdd64(state,instr,LSIGNED,LSCC),0L) ; + break ; + } +#endif + lhs = LHS ; + rhs = DPRegRHS ; + dest = rhs - lhs - !CFLAG ; + if ((rhs >= lhs) || ((rhs | lhs) >> 31)) { + ARMul_SubCarry(state,rhs,lhs,dest) ; + ARMul_SubOverflow(state,rhs,lhs,dest) ; + } + else { + CLEARC ; + CLEARV ; + } + WRITESDEST(dest) ; + break ; + + case 0x10 : /* TST reg and MRS CPSR and SWP word */ +#ifdef MODET + if (BITS(4,11) == 0xB) { + /* STRH register offset, no write-back, down, pre indexed */ + SHPREDOWN() ; + break ; + } +#endif + if (BITS(4,11) == 9) { /* SWP */ + UNDEF_SWPPC ; + temp = LHS ; + BUSUSEDINCPCS ; +#ifndef MODE32 + if (VECTORACCESS(temp) || ADDREXCEPT(temp)) { + INTERNALABORT(temp) ; + (void)ARMul_LoadWordN(state,temp) ; + (void)ARMul_LoadWordN(state,temp) ; + } + else +#endif + dest = ARMul_SwapWord(state,temp,state->Reg[RHSReg]) ; + if (temp & 3) + DEST = ARMul_Align(state,temp,dest) ; + else + DEST = dest ; + if (state->abortSig || state->Aborted) { + TAKEABORT ; + } + } + else if ((BITS(0,11)==0) && (LHSReg==15)) { /* MRS CPSR */ + UNDEF_MRSPC ; + DEST = ECC | EINT | EMODE ; + } + else { + UNDEF_Test ; + } + break ; + + case 0x11 : /* TSTP reg */ +#ifdef MODET + if ((BITS(4,11) & 0xF9) == 0x9) { + /* LDR register offset, no write-back, down, pre indexed */ + LHPREDOWN() ; + /* continue with remaining instruction decode */ + } +#endif + if (DESTReg == 15) { /* TSTP reg */ +#ifdef MODE32 + state->Cpsr = GETSPSR(state->Bank) ; + ARMul_CPSRAltered(state) ; +#else + rhs = DPRegRHS ; + temp = LHS & rhs ; + SETR15PSR(temp) ; +#endif + } + else { /* TST reg */ + rhs = DPSRegRHS ; + dest = LHS & rhs ; + ARMul_NegZero(state,dest) ; + } + break ; + + case 0x12 : /* TEQ reg and MSR reg to CPSR (ARM6) */ +#ifdef MODET + if (BITS(4,11) == 0xB) { + /* STRH register offset, write-back, down, pre indexed */ + SHPREDOWNWB() ; + break ; + } +#endif +#ifdef MODET + if (BITS(4,27)==0x12FFF1) { /* BX */ + /* Branch to the address in RHSReg. If bit0 of + destination address is 1 then switch to Thumb mode: */ + ARMword addr = state->Reg[RHSReg]; + + /* If we read the PC then the bottom bit is clear */ + if (RHSReg == 15) addr &= ~1; + + /* Enable this for a helpful bit of debugging when + GDB is not yet fully working... + fprintf (stderr, "BX at %x to %x (go %s)\n", + state->Reg[15], addr, (addr & 1) ? "thumb": "arm" ); */ + + if (addr & (1 << 0)) { /* Thumb bit */ + SETT; + state->Reg[15] = addr & 0xfffffffe; + /* NOTE: The other CPSR flag setting blocks do not + seem to update the state->Cpsr state, but just do + the explicit flag. The copy from the seperate + flags to the register must happen later. */ + FLUSHPIPE; + } else { + CLEART; + state->Reg[15] = addr & 0xfffffffc; + FLUSHPIPE; + } + } +#endif + if (DESTReg==15 && BITS(17,18)==0) { /* MSR reg to CPSR */ + UNDEF_MSRPC ; + temp = DPRegRHS ; + ARMul_FixCPSR(state,instr,temp) ; + } + else { + UNDEF_Test ; + } + break ; + + case 0x13 : /* TEQP reg */ +#ifdef MODET + if ((BITS(4,11) & 0xF9) == 0x9) { + /* LDR register offset, write-back, down, pre indexed */ + LHPREDOWNWB() ; + /* continue with remaining instruction decode */ + } +#endif + if (DESTReg == 15) { /* TEQP reg */ +#ifdef MODE32 + state->Cpsr = GETSPSR(state->Bank) ; + ARMul_CPSRAltered(state) ; +#else + rhs = DPRegRHS ; + temp = LHS ^ rhs ; + SETR15PSR(temp) ; +#endif + } + else { /* TEQ Reg */ + rhs = DPSRegRHS ; + dest = LHS ^ rhs ; + ARMul_NegZero(state,dest) ; + } + break ; + + case 0x14 : /* CMP reg and MRS SPSR and SWP byte */ +#ifdef MODET + if (BITS(4,7) == 0xB) { + /* STRH immediate offset, no write-back, down, pre indexed */ + SHPREDOWN() ; + break ; + } +#endif + if (BITS(4,11) == 9) { /* SWP */ + UNDEF_SWPPC ; + temp = LHS ; + BUSUSEDINCPCS ; +#ifndef MODE32 + if (VECTORACCESS(temp) || ADDREXCEPT(temp)) { + INTERNALABORT(temp) ; + (void)ARMul_LoadByte(state,temp) ; + (void)ARMul_LoadByte(state,temp) ; + } + else +#endif + DEST = ARMul_SwapByte(state,temp,state->Reg[RHSReg]) ; + if (state->abortSig || state->Aborted) { + TAKEABORT ; + } + } + else if ((BITS(0,11)==0) && (LHSReg==15)) { /* MRS SPSR */ + UNDEF_MRSPC ; + DEST = GETSPSR(state->Bank) ; + } + else { + UNDEF_Test ; + } + break ; + + case 0x15 : /* CMPP reg */ +#ifdef MODET + if ((BITS(4,7) & 0x9) == 0x9) { + /* LDR immediate offset, no write-back, down, pre indexed */ + LHPREDOWN() ; + /* continue with remaining instruction decode */ + } +#endif + if (DESTReg == 15) { /* CMPP reg */ +#ifdef MODE32 + state->Cpsr = GETSPSR(state->Bank) ; + ARMul_CPSRAltered(state) ; +#else + rhs = DPRegRHS ; + temp = LHS - rhs ; + SETR15PSR(temp) ; +#endif + } + else { /* CMP reg */ + lhs = LHS ; + rhs = DPRegRHS ; + dest = lhs - rhs ; + ARMul_NegZero(state,dest) ; + if ((lhs >= rhs) || ((rhs | lhs) >> 31)) { + ARMul_SubCarry(state,lhs,rhs,dest) ; + ARMul_SubOverflow(state,lhs,rhs,dest) ; + } + else { + CLEARC ; + CLEARV ; + } + } + break ; + + case 0x16 : /* CMN reg and MSR reg to SPSR */ +#ifdef MODET + if (BITS(4,7) == 0xB) { + /* STRH immediate offset, write-back, down, pre indexed */ + SHPREDOWNWB() ; + break ; + } +#endif + if (DESTReg==15 && BITS(17,18)==0) { /* MSR */ + UNDEF_MSRPC ; + ARMul_FixSPSR(state,instr,DPRegRHS); + } + else { + UNDEF_Test ; + } + break ; + + case 0x17 : /* CMNP reg */ +#ifdef MODET + if ((BITS(4,7) & 0x9) == 0x9) { + /* LDR immediate offset, write-back, down, pre indexed */ + LHPREDOWNWB() ; + /* continue with remaining instruction decoding */ + } +#endif + if (DESTReg == 15) { +#ifdef MODE32 + state->Cpsr = GETSPSR(state->Bank) ; + ARMul_CPSRAltered(state) ; +#else + rhs = DPRegRHS ; + temp = LHS + rhs ; + SETR15PSR(temp) ; +#endif + break ; + } + else { /* CMN reg */ + lhs = LHS ; + rhs = DPRegRHS ; + dest = lhs + rhs ; + ASSIGNZ(dest==0) ; + if ((lhs | rhs) >> 30) { /* possible C,V,N to set */ + ASSIGNN(NEG(dest)) ; + ARMul_AddCarry(state,lhs,rhs,dest) ; + ARMul_AddOverflow(state,lhs,rhs,dest) ; + } + else { + CLEARN ; + CLEARC ; + CLEARV ; + } + } + break ; + + case 0x18 : /* ORR reg */ +#ifdef MODET + if (BITS(4,11) == 0xB) { + /* STRH register offset, no write-back, up, pre indexed */ + SHPREUP() ; + break ; + } +#endif + rhs = DPRegRHS ; + dest = LHS | rhs ; + WRITEDEST(dest) ; + break ; + + case 0x19 : /* ORRS reg */ +#ifdef MODET + if ((BITS(4,11) & 0xF9) == 0x9) { + /* LDR register offset, no write-back, up, pre indexed */ + LHPREUP() ; + /* continue with remaining instruction decoding */ + } +#endif + rhs = DPSRegRHS ; + dest = LHS | rhs ; + WRITESDEST(dest) ; + break ; + + case 0x1a : /* MOV reg */ +#ifdef MODET + if (BITS(4,11) == 0xB) { + /* STRH register offset, write-back, up, pre indexed */ + SHPREUPWB() ; + break ; + } +#endif + dest = DPRegRHS ; + WRITEDEST(dest) ; + break ; + + case 0x1b : /* MOVS reg */ +#ifdef MODET + if ((BITS(4,11) & 0xF9) == 0x9) { + /* LDR register offset, write-back, up, pre indexed */ + LHPREUPWB() ; + /* continue with remaining instruction decoding */ + } +#endif + dest = DPSRegRHS ; + WRITESDEST(dest) ; + break ; + + case 0x1c : /* BIC reg */ +#ifdef MODET + if (BITS(4,7) == 0xB) { + /* STRH immediate offset, no write-back, up, pre indexed */ + SHPREUP() ; + break ; + } +#endif + rhs = DPRegRHS ; + dest = LHS & ~rhs ; + WRITEDEST(dest) ; + break ; + + case 0x1d : /* BICS reg */ +#ifdef MODET + if ((BITS(4,7) & 0x9) == 0x9) { + /* LDR immediate offset, no write-back, up, pre indexed */ + LHPREUP() ; + /* continue with instruction decoding */ + } +#endif + rhs = DPSRegRHS ; + dest = LHS & ~rhs ; + WRITESDEST(dest) ; + break ; + + case 0x1e : /* MVN reg */ +#ifdef MODET + if (BITS(4,7) == 0xB) { + /* STRH immediate offset, write-back, up, pre indexed */ + SHPREUPWB() ; + break ; + } +#endif + dest = ~DPRegRHS ; + WRITEDEST(dest) ; + break ; + + case 0x1f : /* MVNS reg */ +#ifdef MODET + if ((BITS(4,7) & 0x9) == 0x9) { + /* LDR immediate offset, write-back, up, pre indexed */ + LHPREUPWB() ; + /* continue instruction decoding */ + } +#endif + dest = ~DPSRegRHS ; + WRITESDEST(dest) ; + break ; + +/***************************************************************************\ +* Data Processing Immediate RHS Instructions * +\***************************************************************************/ + + case 0x20 : /* AND immed */ + dest = LHS & DPImmRHS ; + WRITEDEST(dest) ; + break ; + + case 0x21 : /* ANDS immed */ + DPSImmRHS ; + dest = LHS & rhs ; + WRITESDEST(dest) ; + break ; + + case 0x22 : /* EOR immed */ + dest = LHS ^ DPImmRHS ; + WRITEDEST(dest) ; + break ; + + case 0x23 : /* EORS immed */ + DPSImmRHS ; + dest = LHS ^ rhs ; + WRITESDEST(dest) ; + break ; + + case 0x24 : /* SUB immed */ + dest = LHS - DPImmRHS ; + WRITEDEST(dest) ; + break ; + + case 0x25 : /* SUBS immed */ + lhs = LHS ; + rhs = DPImmRHS ; + dest = lhs - rhs ; + if ((lhs >= rhs) || ((rhs | lhs) >> 31)) { + ARMul_SubCarry(state,lhs,rhs,dest) ; + ARMul_SubOverflow(state,lhs,rhs,dest) ; + } + else { + CLEARC ; + CLEARV ; + } + WRITESDEST(dest) ; + break ; + + case 0x26 : /* RSB immed */ + dest = DPImmRHS - LHS ; + WRITEDEST(dest) ; + break ; + + case 0x27 : /* RSBS immed */ + lhs = LHS ; + rhs = DPImmRHS ; + dest = rhs - lhs ; + if ((rhs >= lhs) || ((rhs | lhs) >> 31)) { + ARMul_SubCarry(state,rhs,lhs,dest) ; + ARMul_SubOverflow(state,rhs,lhs,dest) ; + } + else { + CLEARC ; + CLEARV ; + } + WRITESDEST(dest) ; + break ; + + case 0x28 : /* ADD immed */ + dest = LHS + DPImmRHS ; + WRITEDEST(dest) ; + break ; + + case 0x29 : /* ADDS immed */ + lhs = LHS ; + rhs = DPImmRHS ; + dest = lhs + rhs ; + ASSIGNZ(dest==0) ; + if ((lhs | rhs) >> 30) { /* possible C,V,N to set */ + ASSIGNN(NEG(dest)) ; + ARMul_AddCarry(state,lhs,rhs,dest) ; + ARMul_AddOverflow(state,lhs,rhs,dest) ; + } + else { + CLEARN ; + CLEARC ; + CLEARV ; + } + WRITESDEST(dest) ; + break ; + + case 0x2a : /* ADC immed */ + dest = LHS + DPImmRHS + CFLAG ; + WRITEDEST(dest) ; + break ; + + case 0x2b : /* ADCS immed */ + lhs = LHS ; + rhs = DPImmRHS ; + dest = lhs + rhs + CFLAG ; + ASSIGNZ(dest==0) ; + if ((lhs | rhs) >> 30) { /* possible C,V,N to set */ + ASSIGNN(NEG(dest)) ; + ARMul_AddCarry(state,lhs,rhs,dest) ; + ARMul_AddOverflow(state,lhs,rhs,dest) ; + } + else { + CLEARN ; + CLEARC ; + CLEARV ; + } + WRITESDEST(dest) ; + break ; + + case 0x2c : /* SBC immed */ + dest = LHS - DPImmRHS - !CFLAG ; + WRITEDEST(dest) ; + break ; + + case 0x2d : /* SBCS immed */ + lhs = LHS ; + rhs = DPImmRHS ; + dest = lhs - rhs - !CFLAG ; + if ((lhs >= rhs) || ((rhs | lhs) >> 31)) { + ARMul_SubCarry(state,lhs,rhs,dest) ; + ARMul_SubOverflow(state,lhs,rhs,dest) ; + } + else { + CLEARC ; + CLEARV ; + } + WRITESDEST(dest) ; + break ; + + case 0x2e : /* RSC immed */ + dest = DPImmRHS - LHS - !CFLAG ; + WRITEDEST(dest) ; + break ; + + case 0x2f : /* RSCS immed */ + lhs = LHS ; + rhs = DPImmRHS ; + dest = rhs - lhs - !CFLAG ; + if ((rhs >= lhs) || ((rhs | lhs) >> 31)) { + ARMul_SubCarry(state,rhs,lhs,dest) ; + ARMul_SubOverflow(state,rhs,lhs,dest) ; + } + else { + CLEARC ; + CLEARV ; + } + WRITESDEST(dest) ; + break ; + + case 0x30 : /* TST immed */ + UNDEF_Test ; + break ; + + case 0x31 : /* TSTP immed */ + if (DESTReg == 15) { /* TSTP immed */ +#ifdef MODE32 + state->Cpsr = GETSPSR(state->Bank) ; + ARMul_CPSRAltered(state) ; +#else + temp = LHS & DPImmRHS ; + SETR15PSR(temp) ; +#endif + } + else { + DPSImmRHS ; /* TST immed */ + dest = LHS & rhs ; + ARMul_NegZero(state,dest) ; + } + break ; + + case 0x32 : /* TEQ immed and MSR immed to CPSR */ + if (DESTReg==15 && BITS(17,18)==0) { /* MSR immed to CPSR */ + ARMul_FixCPSR(state,instr,DPImmRHS) ; + } + else { + UNDEF_Test ; + } + break ; + + case 0x33 : /* TEQP immed */ + if (DESTReg == 15) { /* TEQP immed */ +#ifdef MODE32 + state->Cpsr = GETSPSR(state->Bank) ; + ARMul_CPSRAltered(state) ; +#else + temp = LHS ^ DPImmRHS ; + SETR15PSR(temp) ; +#endif + } + else { + DPSImmRHS ; /* TEQ immed */ + dest = LHS ^ rhs ; + ARMul_NegZero(state,dest) ; + } + break ; + + case 0x34 : /* CMP immed */ + UNDEF_Test ; + break ; + + case 0x35 : /* CMPP immed */ + if (DESTReg == 15) { /* CMPP immed */ +#ifdef MODE32 + state->Cpsr = GETSPSR(state->Bank) ; + ARMul_CPSRAltered(state) ; +#else + temp = LHS - DPImmRHS ; + SETR15PSR(temp) ; +#endif + break ; + } + else { + lhs = LHS ; /* CMP immed */ + rhs = DPImmRHS ; + dest = lhs - rhs ; + ARMul_NegZero(state,dest) ; + if ((lhs >= rhs) || ((rhs | lhs) >> 31)) { + ARMul_SubCarry(state,lhs,rhs,dest) ; + ARMul_SubOverflow(state,lhs,rhs,dest) ; + } + else { + CLEARC ; + CLEARV ; + } + } + break ; + + case 0x36 : /* CMN immed and MSR immed to SPSR */ + if (DESTReg==15 && BITS(17,18)==0) /* MSR */ + ARMul_FixSPSR(state, instr, DPImmRHS) ; + else { + UNDEF_Test ; + } + break ; + + case 0x37 : /* CMNP immed */ + if (DESTReg == 15) { /* CMNP immed */ +#ifdef MODE32 + state->Cpsr = GETSPSR(state->Bank) ; + ARMul_CPSRAltered(state) ; +#else + temp = LHS + DPImmRHS ; + SETR15PSR(temp) ; +#endif + break ; + } + else { + lhs = LHS ; /* CMN immed */ + rhs = DPImmRHS ; + dest = lhs + rhs ; + ASSIGNZ(dest==0) ; + if ((lhs | rhs) >> 30) { /* possible C,V,N to set */ + ASSIGNN(NEG(dest)) ; + ARMul_AddCarry(state,lhs,rhs,dest) ; + ARMul_AddOverflow(state,lhs,rhs,dest) ; + } + else { + CLEARN ; + CLEARC ; + CLEARV ; + } + } + break ; + + case 0x38 : /* ORR immed */ + dest = LHS | DPImmRHS ; + WRITEDEST(dest) ; + break ; + + case 0x39 : /* ORRS immed */ + DPSImmRHS ; + dest = LHS | rhs ; + WRITESDEST(dest) ; + break ; + + case 0x3a : /* MOV immed */ + dest = DPImmRHS ; + WRITEDEST(dest) ; + break ; + + case 0x3b : /* MOVS immed */ + DPSImmRHS ; + WRITESDEST(rhs) ; + break ; + + case 0x3c : /* BIC immed */ + dest = LHS & ~DPImmRHS ; + WRITEDEST(dest) ; + break ; + + case 0x3d : /* BICS immed */ + DPSImmRHS ; + dest = LHS & ~rhs ; + WRITESDEST(dest) ; + break ; + + case 0x3e : /* MVN immed */ + dest = ~DPImmRHS ; + WRITEDEST(dest) ; + break ; + + case 0x3f : /* MVNS immed */ + DPSImmRHS ; + WRITESDEST(~rhs) ; + break ; + +/***************************************************************************\ +* Single Data Transfer Immediate RHS Instructions * +\***************************************************************************/ + + case 0x40 : /* Store Word, No WriteBack, Post Dec, Immed */ + lhs = LHS ; + if (StoreWord(state,instr,lhs)) + LSBase = lhs - LSImmRHS ; + break ; + + case 0x41 : /* Load Word, No WriteBack, Post Dec, Immed */ + lhs = LHS ; + if (LoadWord(state,instr,lhs)) + LSBase = lhs - LSImmRHS ; + break ; + + case 0x42 : /* Store Word, WriteBack, Post Dec, Immed */ + UNDEF_LSRBaseEQDestWb ; + UNDEF_LSRPCBaseWb ; + lhs = LHS ; + temp = lhs - LSImmRHS ; + state->NtransSig = LOW ; + if (StoreWord(state,instr,lhs)) + LSBase = temp ; + state->NtransSig = (state->Mode & 3)?HIGH:LOW ; + break ; + + case 0x43 : /* Load Word, WriteBack, Post Dec, Immed */ + UNDEF_LSRBaseEQDestWb ; + UNDEF_LSRPCBaseWb ; + lhs = LHS ; + state->NtransSig = LOW ; + if (LoadWord(state,instr,lhs)) + LSBase = lhs - LSImmRHS ; + state->NtransSig = (state->Mode & 3)?HIGH:LOW ; + break ; + + case 0x44 : /* Store Byte, No WriteBack, Post Dec, Immed */ + lhs = LHS ; + if (StoreByte(state,instr,lhs)) + LSBase = lhs - LSImmRHS ; + break ; + + case 0x45 : /* Load Byte, No WriteBack, Post Dec, Immed */ + lhs = LHS ; + if (LoadByte(state,instr,lhs,LUNSIGNED)) + LSBase = lhs - LSImmRHS ; + break ; + + case 0x46 : /* Store Byte, WriteBack, Post Dec, Immed */ + UNDEF_LSRBaseEQDestWb ; + UNDEF_LSRPCBaseWb ; + lhs = LHS ; + state->NtransSig = LOW ; + if (StoreByte(state,instr,lhs)) + LSBase = lhs - LSImmRHS ; + state->NtransSig = (state->Mode & 3)?HIGH:LOW ; + break ; + + case 0x47 : /* Load Byte, WriteBack, Post Dec, Immed */ + UNDEF_LSRBaseEQDestWb ; + UNDEF_LSRPCBaseWb ; + lhs = LHS ; + state->NtransSig = LOW ; + if (LoadByte(state,instr,lhs,LUNSIGNED)) + LSBase = lhs - LSImmRHS ; + state->NtransSig = (state->Mode & 3)?HIGH:LOW ; + break ; + + case 0x48 : /* Store Word, No WriteBack, Post Inc, Immed */ + lhs = LHS ; + if (StoreWord(state,instr,lhs)) + LSBase = lhs + LSImmRHS ; + break ; + + case 0x49 : /* Load Word, No WriteBack, Post Inc, Immed */ + lhs = LHS ; + if (LoadWord(state,instr,lhs)) + LSBase = lhs + LSImmRHS ; + break ; + + case 0x4a : /* Store Word, WriteBack, Post Inc, Immed */ + UNDEF_LSRBaseEQDestWb ; + UNDEF_LSRPCBaseWb ; + lhs = LHS ; + state->NtransSig = LOW ; + if (StoreWord(state,instr,lhs)) + LSBase = lhs + LSImmRHS ; + state->NtransSig = (state->Mode & 3)?HIGH:LOW ; + break ; + + case 0x4b : /* Load Word, WriteBack, Post Inc, Immed */ + UNDEF_LSRBaseEQDestWb ; + UNDEF_LSRPCBaseWb ; + lhs = LHS ; + state->NtransSig = LOW ; + if (LoadWord(state,instr,lhs)) + LSBase = lhs + LSImmRHS ; + state->NtransSig = (state->Mode & 3)?HIGH:LOW ; + break ; + + case 0x4c : /* Store Byte, No WriteBack, Post Inc, Immed */ + lhs = LHS ; + if (StoreByte(state,instr,lhs)) + LSBase = lhs + LSImmRHS ; + break ; + + case 0x4d : /* Load Byte, No WriteBack, Post Inc, Immed */ + lhs = LHS ; + if (LoadByte(state,instr,lhs,LUNSIGNED)) + LSBase = lhs + LSImmRHS ; + break ; + + case 0x4e : /* Store Byte, WriteBack, Post Inc, Immed */ + UNDEF_LSRBaseEQDestWb ; + UNDEF_LSRPCBaseWb ; + lhs = LHS ; + state->NtransSig = LOW ; + if (StoreByte(state,instr,lhs)) + LSBase = lhs + LSImmRHS ; + state->NtransSig = (state->Mode & 3)?HIGH:LOW ; + break ; + + case 0x4f : /* Load Byte, WriteBack, Post Inc, Immed */ + UNDEF_LSRBaseEQDestWb ; + UNDEF_LSRPCBaseWb ; + lhs = LHS ; + state->NtransSig = LOW ; + if (LoadByte(state,instr,lhs,LUNSIGNED)) + LSBase = lhs + LSImmRHS ; + state->NtransSig = (state->Mode & 3)?HIGH:LOW ; + break ; + + + case 0x50 : /* Store Word, No WriteBack, Pre Dec, Immed */ + (void)StoreWord(state,instr,LHS - LSImmRHS) ; + break ; + + case 0x51 : /* Load Word, No WriteBack, Pre Dec, Immed */ + (void)LoadWord(state,instr,LHS - LSImmRHS) ; + break ; + + case 0x52 : /* Store Word, WriteBack, Pre Dec, Immed */ + UNDEF_LSRBaseEQDestWb ; + UNDEF_LSRPCBaseWb ; + temp = LHS - LSImmRHS ; + if (StoreWord(state,instr,temp)) + LSBase = temp ; + break ; + + case 0x53 : /* Load Word, WriteBack, Pre Dec, Immed */ + UNDEF_LSRBaseEQDestWb ; + UNDEF_LSRPCBaseWb ; + temp = LHS - LSImmRHS ; + if (LoadWord(state,instr,temp)) + LSBase = temp ; + break ; + + case 0x54 : /* Store Byte, No WriteBack, Pre Dec, Immed */ + (void)StoreByte(state,instr,LHS - LSImmRHS) ; + break ; + + case 0x55 : /* Load Byte, No WriteBack, Pre Dec, Immed */ + (void)LoadByte(state,instr,LHS - LSImmRHS,LUNSIGNED) ; + break ; + + case 0x56 : /* Store Byte, WriteBack, Pre Dec, Immed */ + UNDEF_LSRBaseEQDestWb ; + UNDEF_LSRPCBaseWb ; + temp = LHS - LSImmRHS ; + if (StoreByte(state,instr,temp)) + LSBase = temp ; + break ; + + case 0x57 : /* Load Byte, WriteBack, Pre Dec, Immed */ + UNDEF_LSRBaseEQDestWb ; + UNDEF_LSRPCBaseWb ; + temp = LHS - LSImmRHS ; + if (LoadByte(state,instr,temp,LUNSIGNED)) + LSBase = temp ; + break ; + + case 0x58 : /* Store Word, No WriteBack, Pre Inc, Immed */ + (void)StoreWord(state,instr,LHS + LSImmRHS) ; + break ; + + case 0x59 : /* Load Word, No WriteBack, Pre Inc, Immed */ + (void)LoadWord(state,instr,LHS + LSImmRHS) ; + break ; + + case 0x5a : /* Store Word, WriteBack, Pre Inc, Immed */ + UNDEF_LSRBaseEQDestWb ; + UNDEF_LSRPCBaseWb ; + temp = LHS + LSImmRHS ; + if (StoreWord(state,instr,temp)) + LSBase = temp ; + break ; + + case 0x5b : /* Load Word, WriteBack, Pre Inc, Immed */ + UNDEF_LSRBaseEQDestWb ; + UNDEF_LSRPCBaseWb ; + temp = LHS + LSImmRHS ; + if (LoadWord(state,instr,temp)) + LSBase = temp ; + break ; + + case 0x5c : /* Store Byte, No WriteBack, Pre Inc, Immed */ + (void)StoreByte(state,instr,LHS + LSImmRHS) ; + break ; + + case 0x5d : /* Load Byte, No WriteBack, Pre Inc, Immed */ + (void)LoadByte(state,instr,LHS + LSImmRHS,LUNSIGNED) ; + break ; + + case 0x5e : /* Store Byte, WriteBack, Pre Inc, Immed */ + UNDEF_LSRBaseEQDestWb ; + UNDEF_LSRPCBaseWb ; + temp = LHS + LSImmRHS ; + if (StoreByte(state,instr,temp)) + LSBase = temp ; + break ; + + case 0x5f : /* Load Byte, WriteBack, Pre Inc, Immed */ + UNDEF_LSRBaseEQDestWb ; + UNDEF_LSRPCBaseWb ; + temp = LHS + LSImmRHS ; + if (LoadByte(state,instr,temp,LUNSIGNED)) + LSBase = temp ; + break ; + +/***************************************************************************\ +* Single Data Transfer Register RHS Instructions * +\***************************************************************************/ + + case 0x60 : /* Store Word, No WriteBack, Post Dec, Reg */ + if (BIT(4)) { + ARMul_UndefInstr(state,instr) ; + break ; + } + UNDEF_LSRBaseEQOffWb ; + UNDEF_LSRBaseEQDestWb ; + UNDEF_LSRPCBaseWb ; + UNDEF_LSRPCOffWb ; + lhs = LHS ; + if (StoreWord(state,instr,lhs)) + LSBase = lhs - LSRegRHS ; + break ; + + case 0x61 : /* Load Word, No WriteBack, Post Dec, Reg */ + if (BIT(4)) { + ARMul_UndefInstr(state,instr) ; + break ; + } + UNDEF_LSRBaseEQOffWb ; + UNDEF_LSRBaseEQDestWb ; + UNDEF_LSRPCBaseWb ; + UNDEF_LSRPCOffWb ; + lhs = LHS ; + if (LoadWord(state,instr,lhs)) + LSBase = lhs - LSRegRHS ; + break ; + + case 0x62 : /* Store Word, WriteBack, Post Dec, Reg */ + if (BIT(4)) { + ARMul_UndefInstr(state,instr) ; + break ; + } + UNDEF_LSRBaseEQOffWb ; + UNDEF_LSRBaseEQDestWb ; + UNDEF_LSRPCBaseWb ; + UNDEF_LSRPCOffWb ; + lhs = LHS ; + state->NtransSig = LOW ; + if (StoreWord(state,instr,lhs)) + LSBase = lhs - LSRegRHS ; + state->NtransSig = (state->Mode & 3)?HIGH:LOW ; + break ; + + case 0x63 : /* Load Word, WriteBack, Post Dec, Reg */ + if (BIT(4)) { + ARMul_UndefInstr(state,instr) ; + break ; + } + UNDEF_LSRBaseEQOffWb ; + UNDEF_LSRBaseEQDestWb ; + UNDEF_LSRPCBaseWb ; + UNDEF_LSRPCOffWb ; + lhs = LHS ; + state->NtransSig = LOW ; + if (LoadWord(state,instr,lhs)) + LSBase = lhs - LSRegRHS ; + state->NtransSig = (state->Mode & 3)?HIGH:LOW ; + break ; + + case 0x64 : /* Store Byte, No WriteBack, Post Dec, Reg */ + if (BIT(4)) { + ARMul_UndefInstr(state,instr) ; + break ; + } + UNDEF_LSRBaseEQOffWb ; + UNDEF_LSRBaseEQDestWb ; + UNDEF_LSRPCBaseWb ; + UNDEF_LSRPCOffWb ; + lhs = LHS ; + if (StoreByte(state,instr,lhs)) + LSBase = lhs - LSRegRHS ; + break ; + + case 0x65 : /* Load Byte, No WriteBack, Post Dec, Reg */ + if (BIT(4)) { + ARMul_UndefInstr(state,instr) ; + break ; + } + UNDEF_LSRBaseEQOffWb ; + UNDEF_LSRBaseEQDestWb ; + UNDEF_LSRPCBaseWb ; + UNDEF_LSRPCOffWb ; + lhs = LHS ; + if (LoadByte(state,instr,lhs,LUNSIGNED)) + LSBase = lhs - LSRegRHS ; + break ; + + case 0x66 : /* Store Byte, WriteBack, Post Dec, Reg */ + if (BIT(4)) { + ARMul_UndefInstr(state,instr) ; + break ; + } + UNDEF_LSRBaseEQOffWb ; + UNDEF_LSRBaseEQDestWb ; + UNDEF_LSRPCBaseWb ; + UNDEF_LSRPCOffWb ; + lhs = LHS ; + state->NtransSig = LOW ; + if (StoreByte(state,instr,lhs)) + LSBase = lhs - LSRegRHS ; + state->NtransSig = (state->Mode & 3)?HIGH:LOW ; + break ; + + case 0x67 : /* Load Byte, WriteBack, Post Dec, Reg */ + if (BIT(4)) { + ARMul_UndefInstr(state,instr) ; + break ; + } + UNDEF_LSRBaseEQOffWb ; + UNDEF_LSRBaseEQDestWb ; + UNDEF_LSRPCBaseWb ; + UNDEF_LSRPCOffWb ; + lhs = LHS ; + state->NtransSig = LOW ; + if (LoadByte(state,instr,lhs,LUNSIGNED)) + LSBase = lhs - LSRegRHS ; + state->NtransSig = (state->Mode & 3)?HIGH:LOW ; + break ; + + case 0x68 : /* Store Word, No WriteBack, Post Inc, Reg */ + if (BIT(4)) { + ARMul_UndefInstr(state,instr) ; + break ; + } + UNDEF_LSRBaseEQOffWb ; + UNDEF_LSRBaseEQDestWb ; + UNDEF_LSRPCBaseWb ; + UNDEF_LSRPCOffWb ; + lhs = LHS ; + if (StoreWord(state,instr,lhs)) + LSBase = lhs + LSRegRHS ; + break ; + + case 0x69 : /* Load Word, No WriteBack, Post Inc, Reg */ + if (BIT(4)) { + ARMul_UndefInstr(state,instr) ; + break ; + } + UNDEF_LSRBaseEQOffWb ; + UNDEF_LSRBaseEQDestWb ; + UNDEF_LSRPCBaseWb ; + UNDEF_LSRPCOffWb ; + lhs = LHS ; + if (LoadWord(state,instr,lhs)) + LSBase = lhs + LSRegRHS ; + break ; + + case 0x6a : /* Store Word, WriteBack, Post Inc, Reg */ + if (BIT(4)) { + ARMul_UndefInstr(state,instr) ; + break ; + } + UNDEF_LSRBaseEQOffWb ; + UNDEF_LSRBaseEQDestWb ; + UNDEF_LSRPCBaseWb ; + UNDEF_LSRPCOffWb ; + lhs = LHS ; + state->NtransSig = LOW ; + if (StoreWord(state,instr,lhs)) + LSBase = lhs + LSRegRHS ; + state->NtransSig = (state->Mode & 3)?HIGH:LOW ; + break ; + + case 0x6b : /* Load Word, WriteBack, Post Inc, Reg */ + if (BIT(4)) { + ARMul_UndefInstr(state,instr) ; + break ; + } + UNDEF_LSRBaseEQOffWb ; + UNDEF_LSRBaseEQDestWb ; + UNDEF_LSRPCBaseWb ; + UNDEF_LSRPCOffWb ; + lhs = LHS ; + state->NtransSig = LOW ; + if (LoadWord(state,instr,lhs)) + LSBase = lhs + LSRegRHS ; + state->NtransSig = (state->Mode & 3)?HIGH:LOW ; + break ; + + case 0x6c : /* Store Byte, No WriteBack, Post Inc, Reg */ + if (BIT(4)) { + ARMul_UndefInstr(state,instr) ; + break ; + } + UNDEF_LSRBaseEQOffWb ; + UNDEF_LSRBaseEQDestWb ; + UNDEF_LSRPCBaseWb ; + UNDEF_LSRPCOffWb ; + lhs = LHS ; + if (StoreByte(state,instr,lhs)) + LSBase = lhs + LSRegRHS ; + break ; + + case 0x6d : /* Load Byte, No WriteBack, Post Inc, Reg */ + if (BIT(4)) { + ARMul_UndefInstr(state,instr) ; + break ; + } + UNDEF_LSRBaseEQOffWb ; + UNDEF_LSRBaseEQDestWb ; + UNDEF_LSRPCBaseWb ; + UNDEF_LSRPCOffWb ; + lhs = LHS ; + if (LoadByte(state,instr,lhs,LUNSIGNED)) + LSBase = lhs + LSRegRHS ; + break ; + + case 0x6e : /* Store Byte, WriteBack, Post Inc, Reg */ + if (BIT(4)) { + ARMul_UndefInstr(state,instr) ; + break ; + } + UNDEF_LSRBaseEQOffWb ; + UNDEF_LSRBaseEQDestWb ; + UNDEF_LSRPCBaseWb ; + UNDEF_LSRPCOffWb ; + lhs = LHS ; + state->NtransSig = LOW ; + if (StoreByte(state,instr,lhs)) + LSBase = lhs + LSRegRHS ; + state->NtransSig = (state->Mode & 3)?HIGH:LOW ; + break ; + + case 0x6f : /* Load Byte, WriteBack, Post Inc, Reg */ + if (BIT(4)) { + ARMul_UndefInstr(state,instr) ; + break ; + } + UNDEF_LSRBaseEQOffWb ; + UNDEF_LSRBaseEQDestWb ; + UNDEF_LSRPCBaseWb ; + UNDEF_LSRPCOffWb ; + lhs = LHS ; + state->NtransSig = LOW ; + if (LoadByte(state,instr,lhs,LUNSIGNED)) + LSBase = lhs + LSRegRHS ; + state->NtransSig = (state->Mode & 3)?HIGH:LOW ; + break ; + + + case 0x70 : /* Store Word, No WriteBack, Pre Dec, Reg */ + if (BIT(4)) { + ARMul_UndefInstr(state,instr) ; + break ; + } + (void)StoreWord(state,instr,LHS - LSRegRHS) ; + break ; + + case 0x71 : /* Load Word, No WriteBack, Pre Dec, Reg */ + if (BIT(4)) { + ARMul_UndefInstr(state,instr) ; + break ; + } + (void)LoadWord(state,instr,LHS - LSRegRHS) ; + break ; + + case 0x72 : /* Store Word, WriteBack, Pre Dec, Reg */ + if (BIT(4)) { + ARMul_UndefInstr(state,instr) ; + break ; + } + UNDEF_LSRBaseEQOffWb ; + UNDEF_LSRBaseEQDestWb ; + UNDEF_LSRPCBaseWb ; + UNDEF_LSRPCOffWb ; + temp = LHS - LSRegRHS ; + if (StoreWord(state,instr,temp)) + LSBase = temp ; + break ; + + case 0x73 : /* Load Word, WriteBack, Pre Dec, Reg */ + if (BIT(4)) { + ARMul_UndefInstr(state,instr) ; + break ; + } + UNDEF_LSRBaseEQOffWb ; + UNDEF_LSRBaseEQDestWb ; + UNDEF_LSRPCBaseWb ; + UNDEF_LSRPCOffWb ; + temp = LHS - LSRegRHS ; + if (LoadWord(state,instr,temp)) + LSBase = temp ; + break ; + + case 0x74 : /* Store Byte, No WriteBack, Pre Dec, Reg */ + if (BIT(4)) { + ARMul_UndefInstr(state,instr) ; + break ; + } + (void)StoreByte(state,instr,LHS - LSRegRHS) ; + break ; + + case 0x75 : /* Load Byte, No WriteBack, Pre Dec, Reg */ + if (BIT(4)) { + ARMul_UndefInstr(state,instr) ; + break ; + } + (void)LoadByte(state,instr,LHS - LSRegRHS,LUNSIGNED) ; + break ; + + case 0x76 : /* Store Byte, WriteBack, Pre Dec, Reg */ + if (BIT(4)) { + ARMul_UndefInstr(state,instr) ; + break ; + } + UNDEF_LSRBaseEQOffWb ; + UNDEF_LSRBaseEQDestWb ; + UNDEF_LSRPCBaseWb ; + UNDEF_LSRPCOffWb ; + temp = LHS - LSRegRHS ; + if (StoreByte(state,instr,temp)) + LSBase = temp ; + break ; + + case 0x77 : /* Load Byte, WriteBack, Pre Dec, Reg */ + if (BIT(4)) { + ARMul_UndefInstr(state,instr) ; + break ; + } + UNDEF_LSRBaseEQOffWb ; + UNDEF_LSRBaseEQDestWb ; + UNDEF_LSRPCBaseWb ; + UNDEF_LSRPCOffWb ; + temp = LHS - LSRegRHS ; + if (LoadByte(state,instr,temp,LUNSIGNED)) + LSBase = temp ; + break ; + + case 0x78 : /* Store Word, No WriteBack, Pre Inc, Reg */ + if (BIT(4)) { + ARMul_UndefInstr(state,instr) ; + break ; + } + (void)StoreWord(state,instr,LHS + LSRegRHS) ; + break ; + + case 0x79 : /* Load Word, No WriteBack, Pre Inc, Reg */ + if (BIT(4)) { + ARMul_UndefInstr(state,instr) ; + break ; + } + (void)LoadWord(state,instr,LHS + LSRegRHS) ; + break ; + + case 0x7a : /* Store Word, WriteBack, Pre Inc, Reg */ + if (BIT(4)) { + ARMul_UndefInstr(state,instr) ; + break ; + } + UNDEF_LSRBaseEQOffWb ; + UNDEF_LSRBaseEQDestWb ; + UNDEF_LSRPCBaseWb ; + UNDEF_LSRPCOffWb ; + temp = LHS + LSRegRHS ; + if (StoreWord(state,instr,temp)) + LSBase = temp ; + break ; + + case 0x7b : /* Load Word, WriteBack, Pre Inc, Reg */ + if (BIT(4)) { + ARMul_UndefInstr(state,instr) ; + break ; + } + UNDEF_LSRBaseEQOffWb ; + UNDEF_LSRBaseEQDestWb ; + UNDEF_LSRPCBaseWb ; + UNDEF_LSRPCOffWb ; + temp = LHS + LSRegRHS ; + if (LoadWord(state,instr,temp)) + LSBase = temp ; + break ; + + case 0x7c : /* Store Byte, No WriteBack, Pre Inc, Reg */ + if (BIT(4)) { + ARMul_UndefInstr(state,instr) ; + break ; + } + (void)StoreByte(state,instr,LHS + LSRegRHS) ; + break ; + + case 0x7d : /* Load Byte, No WriteBack, Pre Inc, Reg */ + if (BIT(4)) { + ARMul_UndefInstr(state,instr) ; + break ; + } + (void)LoadByte(state,instr,LHS + LSRegRHS,LUNSIGNED) ; + break ; + + case 0x7e : /* Store Byte, WriteBack, Pre Inc, Reg */ + if (BIT(4)) { + ARMul_UndefInstr(state,instr) ; + break ; + } + UNDEF_LSRBaseEQOffWb ; + UNDEF_LSRBaseEQDestWb ; + UNDEF_LSRPCBaseWb ; + UNDEF_LSRPCOffWb ; + temp = LHS + LSRegRHS ; + if (StoreByte(state,instr,temp)) + LSBase = temp ; + break ; + + case 0x7f : /* Load Byte, WriteBack, Pre Inc, Reg */ + if (BIT(4)) { + ARMul_UndefInstr(state,instr) ; + break ; + } + UNDEF_LSRBaseEQOffWb ; + UNDEF_LSRBaseEQDestWb ; + UNDEF_LSRPCBaseWb ; + UNDEF_LSRPCOffWb ; + temp = LHS + LSRegRHS ; + if (LoadByte(state,instr,temp,LUNSIGNED)) + LSBase = temp ; + break ; + +/***************************************************************************\ +* Multiple Data Transfer Instructions * +\***************************************************************************/ + + case 0x80 : /* Store, No WriteBack, Post Dec */ + STOREMULT(instr,LSBase - LSMNumRegs + 4L,0L) ; + break ; + + case 0x81 : /* Load, No WriteBack, Post Dec */ + LOADMULT(instr,LSBase - LSMNumRegs + 4L,0L) ; + break ; + + case 0x82 : /* Store, WriteBack, Post Dec */ + temp = LSBase - LSMNumRegs ; + STOREMULT(instr,temp + 4L,temp) ; + break ; + + case 0x83 : /* Load, WriteBack, Post Dec */ + temp = LSBase - LSMNumRegs ; + LOADMULT(instr,temp + 4L,temp) ; + break ; + + case 0x84 : /* Store, Flags, No WriteBack, Post Dec */ + STORESMULT(instr,LSBase - LSMNumRegs + 4L,0L) ; + break ; + + case 0x85 : /* Load, Flags, No WriteBack, Post Dec */ + LOADSMULT(instr,LSBase - LSMNumRegs + 4L,0L) ; + break ; + + case 0x86 : /* Store, Flags, WriteBack, Post Dec */ + temp = LSBase - LSMNumRegs ; + STORESMULT(instr,temp + 4L,temp) ; + break ; + + case 0x87 : /* Load, Flags, WriteBack, Post Dec */ + temp = LSBase - LSMNumRegs ; + LOADSMULT(instr,temp + 4L,temp) ; + break ; + + + case 0x88 : /* Store, No WriteBack, Post Inc */ + STOREMULT(instr,LSBase,0L) ; + break ; + + case 0x89 : /* Load, No WriteBack, Post Inc */ + LOADMULT(instr,LSBase,0L) ; + break ; + + case 0x8a : /* Store, WriteBack, Post Inc */ + temp = LSBase ; + STOREMULT(instr,temp,temp + LSMNumRegs) ; + break ; + + case 0x8b : /* Load, WriteBack, Post Inc */ + temp = LSBase ; + LOADMULT(instr,temp,temp + LSMNumRegs) ; + break ; + + case 0x8c : /* Store, Flags, No WriteBack, Post Inc */ + STORESMULT(instr,LSBase,0L) ; + break ; + + case 0x8d : /* Load, Flags, No WriteBack, Post Inc */ + LOADSMULT(instr,LSBase,0L) ; + break ; + + case 0x8e : /* Store, Flags, WriteBack, Post Inc */ + temp = LSBase ; + STORESMULT(instr,temp,temp + LSMNumRegs) ; + break ; + + case 0x8f : /* Load, Flags, WriteBack, Post Inc */ + temp = LSBase ; + LOADSMULT(instr,temp,temp + LSMNumRegs) ; + break ; + + + case 0x90 : /* Store, No WriteBack, Pre Dec */ + STOREMULT(instr,LSBase - LSMNumRegs,0L) ; + break ; + + case 0x91 : /* Load, No WriteBack, Pre Dec */ + LOADMULT(instr,LSBase - LSMNumRegs,0L) ; + break ; + + case 0x92 : /* Store, WriteBack, Pre Dec */ + temp = LSBase - LSMNumRegs ; + STOREMULT(instr,temp,temp) ; + break ; + + case 0x93 : /* Load, WriteBack, Pre Dec */ + temp = LSBase - LSMNumRegs ; + LOADMULT(instr,temp,temp) ; + break ; + + case 0x94 : /* Store, Flags, No WriteBack, Pre Dec */ + STORESMULT(instr,LSBase - LSMNumRegs,0L) ; + break ; + + case 0x95 : /* Load, Flags, No WriteBack, Pre Dec */ + LOADSMULT(instr,LSBase - LSMNumRegs,0L) ; + break ; + + case 0x96 : /* Store, Flags, WriteBack, Pre Dec */ + temp = LSBase - LSMNumRegs ; + STORESMULT(instr,temp,temp) ; + break ; + + case 0x97 : /* Load, Flags, WriteBack, Pre Dec */ + temp = LSBase - LSMNumRegs ; + LOADSMULT(instr,temp,temp) ; + break ; + + + case 0x98 : /* Store, No WriteBack, Pre Inc */ + STOREMULT(instr,LSBase + 4L,0L) ; + break ; + + case 0x99 : /* Load, No WriteBack, Pre Inc */ + LOADMULT(instr,LSBase + 4L,0L) ; + break ; + + case 0x9a : /* Store, WriteBack, Pre Inc */ + temp = LSBase ; + STOREMULT(instr,temp + 4L,temp + LSMNumRegs) ; + break ; + + case 0x9b : /* Load, WriteBack, Pre Inc */ + temp = LSBase ; + LOADMULT(instr,temp + 4L,temp + LSMNumRegs) ; + break ; + + case 0x9c : /* Store, Flags, No WriteBack, Pre Inc */ + STORESMULT(instr,LSBase + 4L,0L) ; + break ; + + case 0x9d : /* Load, Flags, No WriteBack, Pre Inc */ + LOADSMULT(instr,LSBase + 4L,0L) ; + break ; + + case 0x9e : /* Store, Flags, WriteBack, Pre Inc */ + temp = LSBase ; + STORESMULT(instr,temp + 4L,temp + LSMNumRegs) ; + break ; + + case 0x9f : /* Load, Flags, WriteBack, Pre Inc */ + temp = LSBase ; + LOADSMULT(instr,temp + 4L,temp + LSMNumRegs) ; + break ; + +/***************************************************************************\ +* Branch forward * +\***************************************************************************/ + + case 0xa0 : case 0xa1 : case 0xa2 : case 0xa3 : + case 0xa4 : case 0xa5 : case 0xa6 : case 0xa7 : + state->Reg[15] = pc + 8 + POSBRANCH ; + FLUSHPIPE ; + break ; + +/***************************************************************************\ +* Branch backward * +\***************************************************************************/ + + case 0xa8 : case 0xa9 : case 0xaa : case 0xab : + case 0xac : case 0xad : case 0xae : case 0xaf : + state->Reg[15] = pc + 8 + NEGBRANCH ; + FLUSHPIPE ; + break ; + +/***************************************************************************\ +* Branch and Link forward * +\***************************************************************************/ + + case 0xb0 : case 0xb1 : case 0xb2 : case 0xb3 : + case 0xb4 : case 0xb5 : case 0xb6 : case 0xb7 : +#ifdef MODE32 + state->Reg[14] = pc + 4 ; /* put PC into Link */ +#else + state->Reg[14] = pc + 4 | ECC | ER15INT | EMODE ; /* put PC into Link */ +#endif + state->Reg[15] = pc + 8 + POSBRANCH ; + FLUSHPIPE ; + break ; + +/***************************************************************************\ +* Branch and Link backward * +\***************************************************************************/ + + case 0xb8 : case 0xb9 : case 0xba : case 0xbb : + case 0xbc : case 0xbd : case 0xbe : case 0xbf : +#ifdef MODE32 + state->Reg[14] = pc + 4 ; /* put PC into Link */ +#else + state->Reg[14] = (pc + 4) | ECC | ER15INT | EMODE ; /* put PC into Link */ +#endif + state->Reg[15] = pc + 8 + NEGBRANCH ; + FLUSHPIPE ; + break ; + +/***************************************************************************\ +* Co-Processor Data Transfers * +\***************************************************************************/ + + case 0xc0 : + case 0xc4 : /* Store , No WriteBack , Post Dec */ + ARMul_STC(state,instr,LHS) ; + break ; + + case 0xc1 : + case 0xc5 : /* Load , No WriteBack , Post Dec */ + ARMul_LDC(state,instr,LHS) ; + break ; + + case 0xc2 : + case 0xc6 : /* Store , WriteBack , Post Dec */ + lhs = LHS ; + state->Base = lhs - LSCOff ; + ARMul_STC(state,instr,lhs) ; + break ; + + case 0xc3 : + case 0xc7 : /* Load , WriteBack , Post Dec */ + lhs = LHS ; + state->Base = lhs - LSCOff ; + ARMul_LDC(state,instr,lhs) ; + break ; + + case 0xc8 : + case 0xcc : /* Store , No WriteBack , Post Inc */ + ARMul_STC(state,instr,LHS) ; + break ; + + case 0xc9 : + case 0xcd : /* Load , No WriteBack , Post Inc */ + ARMul_LDC(state,instr,LHS) ; + break ; + + case 0xca : + case 0xce : /* Store , WriteBack , Post Inc */ + lhs = LHS ; + state->Base = lhs + LSCOff ; + ARMul_STC(state,instr,LHS) ; + break ; + + case 0xcb : + case 0xcf : /* Load , WriteBack , Post Inc */ + lhs = LHS ; + state->Base = lhs + LSCOff ; + ARMul_LDC(state,instr,LHS) ; + break ; + + + case 0xd0 : + case 0xd4 : /* Store , No WriteBack , Pre Dec */ + ARMul_STC(state,instr,LHS - LSCOff) ; + break ; + + case 0xd1 : + case 0xd5 : /* Load , No WriteBack , Pre Dec */ + ARMul_LDC(state,instr,LHS - LSCOff) ; + break ; + + case 0xd2 : + case 0xd6 : /* Store , WriteBack , Pre Dec */ + lhs = LHS - LSCOff ; + state->Base = lhs ; + ARMul_STC(state,instr,lhs) ; + break ; + + case 0xd3 : + case 0xd7 : /* Load , WriteBack , Pre Dec */ + lhs = LHS - LSCOff ; + state->Base = lhs ; + ARMul_LDC(state,instr,lhs) ; + break ; + + case 0xd8 : + case 0xdc : /* Store , No WriteBack , Pre Inc */ + ARMul_STC(state,instr,LHS + LSCOff) ; + break ; + + case 0xd9 : + case 0xdd : /* Load , No WriteBack , Pre Inc */ + ARMul_LDC(state,instr,LHS + LSCOff) ; + break ; + + case 0xda : + case 0xde : /* Store , WriteBack , Pre Inc */ + lhs = LHS + LSCOff ; + state->Base = lhs ; + ARMul_STC(state,instr,lhs) ; + break ; + + case 0xdb : + case 0xdf : /* Load , WriteBack , Pre Inc */ + lhs = LHS + LSCOff ; + state->Base = lhs ; + ARMul_LDC(state,instr,lhs) ; + break ; + +/***************************************************************************\ +* Co-Processor Register Transfers (MCR) and Data Ops * +\***************************************************************************/ + + case 0xe0 : case 0xe2 : case 0xe4 : case 0xe6 : + case 0xe8 : case 0xea : case 0xec : case 0xee : + if (BIT(4)) { /* MCR */ + if (DESTReg == 15) { + UNDEF_MCRPC ; +#ifdef MODE32 + ARMul_MCR(state,instr,state->Reg[15] + isize) ; +#else + ARMul_MCR(state,instr,ECC | ER15INT | EMODE | + ((state->Reg[15] + isize) & R15PCBITS) ) ; +#endif + } + else + ARMul_MCR(state,instr,DEST) ; + } + else /* CDP Part 1 */ + ARMul_CDP(state,instr) ; + break ; + +/***************************************************************************\ +* Co-Processor Register Transfers (MRC) and Data Ops * +\***************************************************************************/ + + case 0xe1 : case 0xe3 : case 0xe5 : case 0xe7 : + case 0xe9 : case 0xeb : case 0xed : case 0xef : + if (BIT(4)) { /* MRC */ + temp = ARMul_MRC(state,instr) ; + if (DESTReg == 15) { + ASSIGNN((temp & NBIT) != 0) ; + ASSIGNZ((temp & ZBIT) != 0) ; + ASSIGNC((temp & CBIT) != 0) ; + ASSIGNV((temp & VBIT) != 0) ; + } + else + DEST = temp ; + } + else /* CDP Part 2 */ + ARMul_CDP(state,instr) ; + break ; + +/***************************************************************************\ +* SWI instruction * +\***************************************************************************/ + + case 0xf0 : case 0xf1 : case 0xf2 : case 0xf3 : + case 0xf4 : case 0xf5 : case 0xf6 : case 0xf7 : + case 0xf8 : case 0xf9 : case 0xfa : case 0xfb : + case 0xfc : case 0xfd : case 0xfe : case 0xff : + if (instr == ARMul_ABORTWORD && state->AbortAddr == pc) { /* a prefetch abort */ + ARMul_Abort(state,ARMul_PrefetchAbortV) ; + break ; + } + + if (!ARMul_OSHandleSWI(state,BITS(0,23))) { + ARMul_Abort(state,ARMul_SWIV) ; + } + break ; + } /* 256 way main switch */ + } /* if temp */ + +#ifdef MODET +donext: +#endif + + if (state->Emulate == ONCE) + state->Emulate = STOP; + else if (state->Emulate != RUN) + break; + } while (1) ; /* do loop */ + + state->decoded = decoded ; + state->loaded = loaded ; + state->pc = pc ; + return(pc) ; + } /* Emulate 26/32 in instruction based mode */ + + +/***************************************************************************\ +* This routine evaluates most Data Processing register RHS's with the S * +* bit clear. It is intended to be called from the macro DPRegRHS, which * +* filters the common case of an unshifted register with in line code * +\***************************************************************************/ + +static ARMword GetDPRegRHS(ARMul_State *state, ARMword instr) +{ARMword shamt , base ; + + base = RHSReg ; + if (BIT(4)) { /* shift amount in a register */ + UNDEF_Shift ; + INCPC ; +#ifndef MODE32 + if (base == 15) + base = ECC | ER15INT | R15PC | EMODE ; + else +#endif + base = state->Reg[base] ; + ARMul_Icycles(state,1,0L) ; + shamt = state->Reg[BITS(8,11)] & 0xff ; + switch ((int)BITS(5,6)) { + case LSL : if (shamt == 0) + return(base) ; + else if (shamt >= 32) + return(0) ; + else + return(base << shamt) ; + case LSR : if (shamt == 0) + return(base) ; + else if (shamt >= 32) + return(0) ; + else + return(base >> shamt) ; + case ASR : if (shamt == 0) + return(base) ; + else if (shamt >= 32) + return((ARMword)((long int)base >> 31L)) ; + else + return((ARMword)((long int)base >> (int)shamt)) ; + case ROR : shamt &= 0x1f ; + if (shamt == 0) + return(base) ; + else + return((base << (32 - shamt)) | (base >> shamt)) ; + } + } + else { /* shift amount is a constant */ +#ifndef MODE32 + if (base == 15) + base = ECC | ER15INT | R15PC | EMODE ; + else +#endif + base = state->Reg[base] ; + shamt = BITS(7,11) ; + switch ((int)BITS(5,6)) { + case LSL : return(base<> shamt) ; + case ASR : if (shamt == 0) + return((ARMword)((long int)base >> 31L)) ; + else + return((ARMword)((long int)base >> (int)shamt)) ; + case ROR : if (shamt==0) /* its an RRX */ + return((base >> 1) | (CFLAG << 31)) ; + else + return((base << (32 - shamt)) | (base >> shamt)) ; + } + } + return(0) ; /* just to shut up lint */ + } +/***************************************************************************\ +* This routine evaluates most Logical Data Processing register RHS's * +* with the S bit set. It is intended to be called from the macro * +* DPSRegRHS, which filters the common case of an unshifted register * +* with in line code * +\***************************************************************************/ + +static ARMword GetDPSRegRHS(ARMul_State *state, ARMword instr) +{ARMword shamt , base ; + + base = RHSReg ; + if (BIT(4)) { /* shift amount in a register */ + UNDEF_Shift ; + INCPC ; +#ifndef MODE32 + if (base == 15) + base = ECC | ER15INT | R15PC | EMODE ; + else +#endif + base = state->Reg[base] ; + ARMul_Icycles(state,1,0L) ; + shamt = state->Reg[BITS(8,11)] & 0xff ; + switch ((int)BITS(5,6)) { + case LSL : if (shamt == 0) + return(base) ; + else if (shamt == 32) { + ASSIGNC(base & 1) ; + return(0) ; + } + else if (shamt > 32) { + CLEARC ; + return(0) ; + } + else { + ASSIGNC((base >> (32-shamt)) & 1) ; + return(base << shamt) ; + } + case LSR : if (shamt == 0) + return(base) ; + else if (shamt == 32) { + ASSIGNC(base >> 31) ; + return(0) ; + } + else if (shamt > 32) { + CLEARC ; + return(0) ; + } + else { + ASSIGNC((base >> (shamt - 1)) & 1) ; + return(base >> shamt) ; + } + case ASR : if (shamt == 0) + return(base) ; + else if (shamt >= 32) { + ASSIGNC(base >> 31L) ; + return((ARMword)((long int)base >> 31L)) ; + } + else { + ASSIGNC((ARMword)((long int)base >> (int)(shamt-1)) & 1) ; + return((ARMword)((long int)base >> (int)shamt)) ; + } + case ROR : if (shamt == 0) + return(base) ; + shamt &= 0x1f ; + if (shamt == 0) { + ASSIGNC(base >> 31) ; + return(base) ; + } + else { + ASSIGNC((base >> (shamt-1)) & 1) ; + return((base << (32-shamt)) | (base >> shamt)) ; + } + } + } + else { /* shift amount is a constant */ +#ifndef MODE32 + if (base == 15) + base = ECC | ER15INT | R15PC | EMODE ; + else +#endif + base = state->Reg[base] ; + shamt = BITS(7,11) ; + switch ((int)BITS(5,6)) { + case LSL : ASSIGNC((base >> (32-shamt)) & 1) ; + return(base << shamt) ; + case LSR : if (shamt == 0) { + ASSIGNC(base >> 31) ; + return(0) ; + } + else { + ASSIGNC((base >> (shamt - 1)) & 1) ; + return(base >> shamt) ; + } + case ASR : if (shamt == 0) { + ASSIGNC(base >> 31L) ; + return((ARMword)((long int)base >> 31L)) ; + } + else { + ASSIGNC((ARMword)((long int)base >> (int)(shamt-1)) & 1) ; + return((ARMword)((long int)base >> (int)shamt)) ; + } + case ROR : if (shamt == 0) { /* its an RRX */ + shamt = CFLAG ; + ASSIGNC(base & 1) ; + return((base >> 1) | (shamt << 31)) ; + } + else { + ASSIGNC((base >> (shamt - 1)) & 1) ; + return((base << (32-shamt)) | (base >> shamt)) ; + } + } + } + return(0) ; /* just to shut up lint */ + } + +/***************************************************************************\ +* This routine handles writes to register 15 when the S bit is not set. * +\***************************************************************************/ + +static void WriteR15(ARMul_State *state, ARMword src) +{ + /* The ARM documentation implies (but doe snot state) that the bottom bit of the PC is never set */ +#ifdef MODE32 + state->Reg[15] = src & PCBITS & ~ 0x1 ; +#else + state->Reg[15] = (src & R15PCBITS & ~ 0x1) | ECC | ER15INT | EMODE ; + ARMul_R15Altered(state) ; +#endif + FLUSHPIPE ; + } + +/***************************************************************************\ +* This routine handles writes to register 15 when the S bit is set. * +\***************************************************************************/ + +static void WriteSR15(ARMul_State *state, ARMword src) +{ +#ifdef MODE32 + state->Reg[15] = src & PCBITS ; + if (state->Bank > 0) { + state->Cpsr = state->Spsr[state->Bank] ; + ARMul_CPSRAltered(state) ; + } +#else + if (state->Bank == USERBANK) + state->Reg[15] = (src & (CCBITS | R15PCBITS)) | ER15INT | EMODE ; + else + state->Reg[15] = src ; + ARMul_R15Altered(state) ; +#endif + FLUSHPIPE ; + } + +/***************************************************************************\ +* This routine evaluates most Load and Store register RHS's. It is * +* intended to be called from the macro LSRegRHS, which filters the * +* common case of an unshifted register with in line code * +\***************************************************************************/ + +static ARMword GetLSRegRHS(ARMul_State *state, ARMword instr) +{ARMword shamt, base ; + + base = RHSReg ; +#ifndef MODE32 + if (base == 15) + base = ECC | ER15INT | R15PC | EMODE ; /* Now forbidden, but .... */ + else +#endif + base = state->Reg[base] ; + + shamt = BITS(7,11) ; + switch ((int)BITS(5,6)) { + case LSL : return(base << shamt) ; + case LSR : if (shamt == 0) + return(0) ; + else + return(base >> shamt) ; + case ASR : if (shamt == 0) + return((ARMword)((long int)base >> 31L)) ; + else + return((ARMword)((long int)base >> (int)shamt)) ; + case ROR : if (shamt==0) /* its an RRX */ + return((base >> 1) | (CFLAG << 31)) ; + else + return((base << (32-shamt)) | (base >> shamt)) ; + } + return(0) ; /* just to shut up lint */ + } + +/***************************************************************************\ +* This routine evaluates the ARM7T halfword and signed transfer RHS's. * +\***************************************************************************/ + +static ARMword GetLS7RHS(ARMul_State *state, ARMword instr) +{ + if (BIT(22) == 0) { /* register */ +#ifndef MODE32 + if (RHSReg == 15) + return ECC | ER15INT | R15PC | EMODE ; /* Now forbidden, but ... */ +#endif + return state->Reg[RHSReg] ; + } + + /* else immediate */ + return BITS(0,3) | (BITS(8,11) << 4) ; + } + +/***************************************************************************\ +* This function does the work of loading a word for a LDR instruction. * +\***************************************************************************/ + +static unsigned LoadWord(ARMul_State *state, ARMword instr, ARMword address) +{ + ARMword dest ; + + BUSUSEDINCPCS ; +#ifndef MODE32 + if (ADDREXCEPT(address)) { + INTERNALABORT(address) ; + } +#endif + dest = ARMul_LoadWordN(state,address) ; + if (state->Aborted) { + TAKEABORT ; + return(state->lateabtSig) ; + } + if (address & 3) + dest = ARMul_Align(state,address,dest) ; + WRITEDEST(dest) ; + ARMul_Icycles(state,1,0L) ; + + return(DESTReg != LHSReg) ; +} + +#ifdef MODET +/***************************************************************************\ +* This function does the work of loading a halfword. * +\***************************************************************************/ + +static unsigned LoadHalfWord(ARMul_State *state, ARMword instr, ARMword address,int signextend) +{ + ARMword dest ; + + BUSUSEDINCPCS ; +#ifndef MODE32 + if (ADDREXCEPT(address)) { + INTERNALABORT(address) ; + } +#endif + dest = ARMul_LoadHalfWord(state,address) ; + if (state->Aborted) { + TAKEABORT ; + return(state->lateabtSig) ; + } + UNDEF_LSRBPC ; + if (signextend) + { + if (dest & 1 << (16 - 1)) + dest = (dest & ((1 << 16) - 1)) - (1 << 16) ; + } + WRITEDEST(dest) ; + ARMul_Icycles(state,1,0L) ; + return(DESTReg != LHSReg) ; +} +#endif /* MODET */ + +/***************************************************************************\ +* This function does the work of loading a byte for a LDRB instruction. * +\***************************************************************************/ + +static unsigned LoadByte(ARMul_State *state, ARMword instr, ARMword address,int signextend) +{ + ARMword dest ; + + BUSUSEDINCPCS ; +#ifndef MODE32 + if (ADDREXCEPT(address)) { + INTERNALABORT(address) ; + } +#endif + dest = ARMul_LoadByte(state,address) ; + if (state->Aborted) { + TAKEABORT ; + return(state->lateabtSig) ; + } + UNDEF_LSRBPC ; + if (signextend) + { + if (dest & 1 << (8 - 1)) + dest = (dest & ((1 << 8) - 1)) - (1 << 8) ; + } + WRITEDEST(dest) ; + ARMul_Icycles(state,1,0L) ; + return(DESTReg != LHSReg) ; +} + +/***************************************************************************\ +* This function does the work of storing a word from a STR instruction. * +\***************************************************************************/ + +static unsigned StoreWord(ARMul_State *state, ARMword instr, ARMword address) +{BUSUSEDINCPCN ; +#ifndef MODE32 + if (DESTReg == 15) + state->Reg[15] = ECC | ER15INT | R15PC | EMODE ; +#endif +#ifdef MODE32 + ARMul_StoreWordN(state,address,DEST) ; +#else + if (VECTORACCESS(address) || ADDREXCEPT(address)) { + INTERNALABORT(address) ; + (void)ARMul_LoadWordN(state,address) ; + } + else + ARMul_StoreWordN(state,address,DEST) ; +#endif + if (state->Aborted) { + TAKEABORT ; + return(state->lateabtSig) ; + } + return(TRUE) ; +} + +#ifdef MODET +/***************************************************************************\ +* This function does the work of storing a byte for a STRH instruction. * +\***************************************************************************/ + +static unsigned StoreHalfWord(ARMul_State *state, ARMword instr, ARMword address) +{BUSUSEDINCPCN ; + +#ifndef MODE32 + if (DESTReg == 15) + state->Reg[15] = ECC | ER15INT | R15PC | EMODE ; +#endif + +#ifdef MODE32 + ARMul_StoreHalfWord(state,address,DEST); +#else + if (VECTORACCESS(address) || ADDREXCEPT(address)) { + INTERNALABORT(address) ; + (void)ARMul_LoadHalfWord(state,address) ; + } + else + ARMul_StoreHalfWord(state,address,DEST) ; +#endif + + if (state->Aborted) { + TAKEABORT ; + return(state->lateabtSig) ; + } + + return(TRUE) ; +} +#endif /* MODET */ + +/***************************************************************************\ +* This function does the work of storing a byte for a STRB instruction. * +\***************************************************************************/ + +static unsigned StoreByte(ARMul_State *state, ARMword instr, ARMword address) +{BUSUSEDINCPCN ; +#ifndef MODE32 + if (DESTReg == 15) + state->Reg[15] = ECC | ER15INT | R15PC | EMODE ; +#endif +#ifdef MODE32 + ARMul_StoreByte(state,address,DEST) ; +#else + if (VECTORACCESS(address) || ADDREXCEPT(address)) { + INTERNALABORT(address) ; + (void)ARMul_LoadByte(state,address) ; + } + else + ARMul_StoreByte(state,address,DEST) ; +#endif + if (state->Aborted) { + TAKEABORT ; + return(state->lateabtSig) ; + } + UNDEF_LSRBPC ; + return(TRUE) ; +} + +/***************************************************************************\ +* This function does the work of loading the registers listed in an LDM * +* instruction, when the S bit is clear. The code here is always increment * +* after, it's up to the caller to get the input address correct and to * +* handle base register modification. * +\***************************************************************************/ + +static void LoadMult(ARMul_State *state, ARMword instr, + ARMword address, ARMword WBBase) +{ARMword dest, temp ; + + UNDEF_LSMNoRegs ; + UNDEF_LSMPCBase ; + UNDEF_LSMBaseInListWb ; + BUSUSEDINCPCS ; +#ifndef MODE32 + if (ADDREXCEPT(address)) { + INTERNALABORT(address) ; + } +#endif + if (BIT(21) && LHSReg != 15) + LSBase = WBBase ; + + for (temp = 0 ; !BIT(temp) ; temp++) ; /* N cycle first */ + dest = ARMul_LoadWordN(state,address) ; + if (!state->abortSig && !state->Aborted) + state->Reg[temp++] = dest ; + else + if (!state->Aborted) + state->Aborted = ARMul_DataAbortV ; + + for (; temp < 16 ; temp++) /* S cycles from here on */ + if (BIT(temp)) { /* load this register */ + address += 4 ; + dest = ARMul_LoadWordS(state,address) ; + if (!state->abortSig && !state->Aborted) + state->Reg[temp] = dest ; + else + if (!state->Aborted) + state->Aborted = ARMul_DataAbortV ; + } + + if (BIT(15)) { /* PC is in the reg list */ +#ifdef MODE32 + state->Reg[15] = PC ; +#endif + FLUSHPIPE ; + } + + ARMul_Icycles(state,1,0L) ; /* to write back the final register */ + + if (state->Aborted) { + if (BIT(21) && LHSReg != 15) + LSBase = WBBase ; + TAKEABORT ; + } + } + +/***************************************************************************\ +* This function does the work of loading the registers listed in an LDM * +* instruction, when the S bit is set. The code here is always increment * +* after, it's up to the caller to get the input address correct and to * +* handle base register modification. * +\***************************************************************************/ + +static void LoadSMult(ARMul_State *state, ARMword instr, + ARMword address, ARMword WBBase) +{ARMword dest, temp ; + + UNDEF_LSMNoRegs ; + UNDEF_LSMPCBase ; + UNDEF_LSMBaseInListWb ; + BUSUSEDINCPCS ; +#ifndef MODE32 + if (ADDREXCEPT(address)) { + INTERNALABORT(address) ; + } +#endif + + if (!BIT(15) && state->Bank != USERBANK) { + (void)ARMul_SwitchMode(state,state->Mode,USER26MODE) ; /* temporary reg bank switch */ + UNDEF_LSMUserBankWb ; + } + + if (BIT(21) && LHSReg != 15) + LSBase = WBBase ; + + for (temp = 0 ; !BIT(temp) ; temp++) ; /* N cycle first */ + dest = ARMul_LoadWordN(state,address) ; + if (!state->abortSig) + state->Reg[temp++] = dest ; + else + if (!state->Aborted) + state->Aborted = ARMul_DataAbortV ; + + for (; temp < 16 ; temp++) /* S cycles from here on */ + if (BIT(temp)) { /* load this register */ + address += 4 ; + dest = ARMul_LoadWordS(state,address) ; + if (!state->abortSig || state->Aborted) + state->Reg[temp] = dest ; + else + if (!state->Aborted) + state->Aborted = ARMul_DataAbortV ; + } + + if (BIT(15)) { /* PC is in the reg list */ +#ifdef MODE32 + if (state->Mode != USER26MODE && state->Mode != USER32MODE) { + state->Cpsr = GETSPSR(state->Bank) ; + ARMul_CPSRAltered(state) ; + } + state->Reg[15] = PC ; +#else + if (state->Mode == USER26MODE || state->Mode == USER32MODE) { /* protect bits in user mode */ + ASSIGNN((state->Reg[15] & NBIT) != 0) ; + ASSIGNZ((state->Reg[15] & ZBIT) != 0) ; + ASSIGNC((state->Reg[15] & CBIT) != 0) ; + ASSIGNV((state->Reg[15] & VBIT) != 0) ; + } + else + ARMul_R15Altered(state) ; +#endif + FLUSHPIPE ; + } + + if (!BIT(15) && state->Mode != USER26MODE && state->Mode != USER32MODE) + (void)ARMul_SwitchMode(state,USER26MODE,state->Mode) ; /* restore the correct bank */ + + ARMul_Icycles(state,1,0L) ; /* to write back the final register */ + + if (state->Aborted) { + if (BIT(21) && LHSReg != 15) + LSBase = WBBase ; + TAKEABORT ; + } + +} + +/***************************************************************************\ +* This function does the work of storing the registers listed in an STM * +* instruction, when the S bit is clear. The code here is always increment * +* after, it's up to the caller to get the input address correct and to * +* handle base register modification. * +\***************************************************************************/ + +static void StoreMult(ARMul_State *state, ARMword instr, + ARMword address, ARMword WBBase) +{ARMword temp ; + + UNDEF_LSMNoRegs ; + UNDEF_LSMPCBase ; + UNDEF_LSMBaseInListWb ; + if (!TFLAG) { + BUSUSEDINCPCN ; /* N-cycle, increment the PC and update the NextInstr state */ + } + +#ifndef MODE32 + if (VECTORACCESS(address) || ADDREXCEPT(address)) { + INTERNALABORT(address) ; + } + if (BIT(15)) + PATCHR15 ; +#endif + + for (temp = 0 ; !BIT(temp) ; temp++) ; /* N cycle first */ +#ifdef MODE32 + ARMul_StoreWordN(state,address,state->Reg[temp++]) ; +#else + if (state->Aborted) { + (void)ARMul_LoadWordN(state,address) ; + for ( ; temp < 16 ; temp++) /* Fake the Stores as Loads */ + if (BIT(temp)) { /* save this register */ + address += 4 ; + (void)ARMul_LoadWordS(state,address) ; + } + if (BIT(21) && LHSReg != 15) + LSBase = WBBase ; + TAKEABORT ; + return ; + } + else + ARMul_StoreWordN(state,address,state->Reg[temp++]) ; +#endif + if (state->abortSig && !state->Aborted) + state->Aborted = ARMul_DataAbortV ; + + if (BIT(21) && LHSReg != 15) + LSBase = WBBase ; + + for ( ; temp < 16 ; temp++) /* S cycles from here on */ + if (BIT(temp)) { /* save this register */ + address += 4 ; + ARMul_StoreWordS(state,address,state->Reg[temp]) ; + if (state->abortSig && !state->Aborted) + state->Aborted = ARMul_DataAbortV ; + } + if (state->Aborted) { + TAKEABORT ; + } + } + +/***************************************************************************\ +* This function does the work of storing the registers listed in an STM * +* instruction when the S bit is set. The code here is always increment * +* after, it's up to the caller to get the input address correct and to * +* handle base register modification. * +\***************************************************************************/ + +static void StoreSMult(ARMul_State *state, ARMword instr, + ARMword address, ARMword WBBase) +{ARMword temp ; + + UNDEF_LSMNoRegs ; + UNDEF_LSMPCBase ; + UNDEF_LSMBaseInListWb ; + BUSUSEDINCPCN ; +#ifndef MODE32 + if (VECTORACCESS(address) || ADDREXCEPT(address)) { + INTERNALABORT(address) ; + } + if (BIT(15)) + PATCHR15 ; +#endif + + if (state->Bank != USERBANK) { + (void)ARMul_SwitchMode(state,state->Mode,USER26MODE) ; /* Force User Bank */ + UNDEF_LSMUserBankWb ; + } + + for (temp = 0 ; !BIT(temp) ; temp++) ; /* N cycle first */ +#ifdef MODE32 + ARMul_StoreWordN(state,address,state->Reg[temp++]) ; +#else + if (state->Aborted) { + (void)ARMul_LoadWordN(state,address) ; + for ( ; temp < 16 ; temp++) /* Fake the Stores as Loads */ + if (BIT(temp)) { /* save this register */ + address += 4 ; + (void)ARMul_LoadWordS(state,address) ; + } + if (BIT(21) && LHSReg != 15) + LSBase = WBBase ; + TAKEABORT ; + return ; + } + else + ARMul_StoreWordN(state,address,state->Reg[temp++]) ; +#endif + if (state->abortSig && !state->Aborted) + state->Aborted = ARMul_DataAbortV ; + + if (BIT(21) && LHSReg != 15) + LSBase = WBBase ; + + for (; temp < 16 ; temp++) /* S cycles from here on */ + if (BIT(temp)) { /* save this register */ + address += 4 ; + ARMul_StoreWordS(state,address,state->Reg[temp]) ; + if (state->abortSig && !state->Aborted) + state->Aborted = ARMul_DataAbortV ; + } + + if (state->Mode != USER26MODE && state->Mode != USER32MODE) + (void)ARMul_SwitchMode(state,USER26MODE,state->Mode) ; /* restore the correct bank */ + + if (state->Aborted) { + TAKEABORT ; + } +} + +/***************************************************************************\ +* This function does the work of adding two 32bit values together, and * +* calculating if a carry has occurred. * +\***************************************************************************/ + +static ARMword Add32(ARMword a1,ARMword a2,int *carry) +{ + ARMword result = (a1 + a2); + unsigned int uresult = (unsigned int)result; + unsigned int ua1 = (unsigned int)a1; + + /* If (result == RdLo) and (state->Reg[nRdLo] == 0), + or (result > RdLo) then we have no carry: */ + if ((uresult == ua1) ? (a2 != 0) : (uresult < ua1)) + *carry = 1; + else + *carry = 0; + + return(result); +} + +/***************************************************************************\ +* This function does the work of multiplying two 32bit values to give a * +* 64bit result. * +\***************************************************************************/ + +static unsigned Multiply64(ARMul_State *state,ARMword instr,int msigned,int scc) +{ + int nRdHi, nRdLo, nRs, nRm; /* operand register numbers */ + ARMword RdHi, RdLo, Rm; + int scount; /* cycle count */ + + nRdHi = BITS(16,19); + nRdLo = BITS(12,15); + nRs = BITS(8,11); + nRm = BITS(0,3); + + /* Needed to calculate the cycle count: */ + Rm = state->Reg[nRm]; + + /* Check for illegal operand combinations first: */ + if ( nRdHi != 15 + && nRdLo != 15 + && nRs != 15 + && nRm != 15 + && nRdHi != nRdLo + && nRdHi != nRm + && nRdLo != nRm) + { + ARMword lo, mid1, mid2, hi; /* intermediate results */ + int carry; + ARMword Rs = state->Reg[ nRs ]; + int sign = 0; + + if (msigned) + { + /* Compute sign of result and adjust operands if necessary. */ + + sign = (Rm ^ Rs) & 0x80000000; + + if (((signed long)Rm) < 0) + Rm = -Rm; + + if (((signed long)Rs) < 0) + Rs = -Rs; + } + + /* We can split the 32x32 into four 16x16 operations. This ensures + that we do not lose precision on 32bit only hosts: */ + lo = ((Rs & 0xFFFF) * (Rm & 0xFFFF)); + mid1 = ((Rs & 0xFFFF) * ((Rm >> 16) & 0xFFFF)); + mid2 = (((Rs >> 16) & 0xFFFF) * (Rm & 0xFFFF)); + hi = (((Rs >> 16) & 0xFFFF) * ((Rm >> 16) & 0xFFFF)); + + /* We now need to add all of these results together, taking care + to propogate the carries from the additions: */ + RdLo = Add32(lo,(mid1 << 16),&carry); + RdHi = carry; + RdLo = Add32(RdLo,(mid2 << 16),&carry); + RdHi += (carry + ((mid1 >> 16) & 0xFFFF) + ((mid2 >> 16) & 0xFFFF) + hi); + + if (sign) + { + /* Negate result if necessary. */ + + RdLo = ~ RdLo; + RdHi = ~ RdHi; + if (RdLo == 0xFFFFFFFF) + { + RdLo = 0; + RdHi += 1; + } + else + RdLo += 1; + } + + state->Reg[nRdLo] = RdLo; + state->Reg[nRdHi] = RdHi; + + } /* else undefined result */ + else fprintf (stderr, "MULTIPLY64 - INVALID ARGUMENTS\n"); + + if (scc) + { + if ((RdHi == 0) && (RdLo == 0)) + ARMul_NegZero(state,RdHi); /* zero value */ + else + ARMul_NegZero(state,scc); /* non-zero value */ + } + + /* The cycle count depends on whether the instruction is a signed or + unsigned multiply, and what bits are clear in the multiplier: */ + if (msigned && (Rm & ((unsigned)1 << 31))) + Rm = ~Rm; /* invert the bits to make the check against zero */ + + if ((Rm & 0xFFFFFF00) == 0) + scount = 1 ; + else if ((Rm & 0xFFFF0000) == 0) + scount = 2 ; + else if ((Rm & 0xFF000000) == 0) + scount = 3 ; + else + scount = 4 ; + + return 2 + scount ; +} + +/***************************************************************************\ +* This function does the work of multiplying two 32bit values and adding * +* a 64bit value to give a 64bit result. * +\***************************************************************************/ + +static unsigned MultiplyAdd64(ARMul_State *state,ARMword instr,int msigned,int scc) +{ + unsigned scount; + ARMword RdLo, RdHi; + int nRdHi, nRdLo; + int carry = 0; + + nRdHi = BITS(16,19); + nRdLo = BITS(12,15); + + RdHi = state->Reg[nRdHi] ; + RdLo = state->Reg[nRdLo] ; + + scount = Multiply64(state,instr,msigned,LDEFAULT); + + RdLo = Add32(RdLo,state->Reg[nRdLo],&carry); + RdHi = (RdHi + state->Reg[nRdHi]) + carry; + + state->Reg[nRdLo] = RdLo; + state->Reg[nRdHi] = RdHi; + + if (scc) { + if ((RdHi == 0) && (RdLo == 0)) + ARMul_NegZero(state,RdHi); /* zero value */ + else + ARMul_NegZero(state,scc); /* non-zero value */ + } + + return scount + 1; /* extra cycle for addition */ +} diff --git a/sim/arm/armemu.h b/sim/arm/armemu.h new file mode 100644 index 00000000000..9c40b8cc230 --- /dev/null +++ b/sim/arm/armemu.h @@ -0,0 +1,425 @@ +/* armemu.h -- ARMulator emulation macros: ARM6 Instruction Emulator. + Copyright (C) 1994 Advanced RISC Machines Ltd. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +extern ARMword isize; + +/***************************************************************************\ +* Condition code values * +\***************************************************************************/ + +#define EQ 0 +#define NE 1 +#define CS 2 +#define CC 3 +#define MI 4 +#define PL 5 +#define VS 6 +#define VC 7 +#define HI 8 +#define LS 9 +#define GE 10 +#define LT 11 +#define GT 12 +#define LE 13 +#define AL 14 +#define NV 15 + +/***************************************************************************\ +* Shift Opcodes * +\***************************************************************************/ + +#define LSL 0 +#define LSR 1 +#define ASR 2 +#define ROR 3 + +/***************************************************************************\ +* Macros to twiddle the status flags and mode * +\***************************************************************************/ + +#define NBIT ((unsigned)1L << 31) +#define ZBIT (1L << 30) +#define CBIT (1L << 29) +#define VBIT (1L << 28) +#define IBIT (1L << 7) +#define FBIT (1L << 6) +#define IFBITS (3L << 6) +#define R15IBIT (1L << 27) +#define R15FBIT (1L << 26) +#define R15IFBITS (3L << 26) + +#define POS(i) ( (~(i)) >> 31 ) +#define NEG(i) ( (i) >> 31 ) + +#ifdef MODET /* Thumb support */ +/* ??? This bit is actually in the low order bit of the PC in the hardware. + It isn't clear if the simulator needs to model that or not. */ +#define TBIT (1L << 5) +#define TFLAG state->TFlag +#define SETT state->TFlag = 1 +#define CLEART state->TFlag = 0 +#define ASSIGNT(res) state->TFlag = res +#endif + +#define NFLAG state->NFlag +#define SETN state->NFlag = 1 +#define CLEARN state->NFlag = 0 +#define ASSIGNN(res) state->NFlag = res + +#define ZFLAG state->ZFlag +#define SETZ state->ZFlag = 1 +#define CLEARZ state->ZFlag = 0 +#define ASSIGNZ(res) state->ZFlag = res + +#define CFLAG state->CFlag +#define SETC state->CFlag = 1 +#define CLEARC state->CFlag = 0 +#define ASSIGNC(res) state->CFlag = res + +#define VFLAG state->VFlag +#define SETV state->VFlag = 1 +#define CLEARV state->VFlag = 0 +#define ASSIGNV(res) state->VFlag = res + +#define IFLAG (state->IFFlags >> 1) +#define FFLAG (state->IFFlags & 1) +#define IFFLAGS state->IFFlags +#define ASSIGNINT(res) state->IFFlags = (((res) >> 6) & 3) +#define ASSIGNR15INT(res) state->IFFlags = (((res) >> 26) & 3) ; + +#define CCBITS (0xf0000000L) +#define INTBITS (0xc0L) + +#if defined MODET && defined MODE32 +#define PCBITS (0xffffffffL) +#else +#define PCBITS (0xfffffffcL) +#endif + +#define MODEBITS (0x1fL) +#define R15INTBITS (3L << 26) + +#if defined MODET && defined MODE32 +#define R15PCBITS (0x03ffffffL) +#else +#define R15PCBITS (0x03fffffcL) +#endif + +#define R15PCMODEBITS (0x03ffffffL) +#define R15MODEBITS (0x3L) + +#ifdef MODE32 +#define PCMASK PCBITS +#define PCWRAP(pc) (pc) +#else +#define PCMASK R15PCBITS +#define PCWRAP(pc) ((pc) & R15PCBITS) +#endif + +#define PC (state->Reg[15] & PCMASK) +#define R15CCINTMODE (state->Reg[15] & (CCBITS | R15INTBITS | R15MODEBITS)) +#define R15INT (state->Reg[15] & R15INTBITS) +#define R15INTPC (state->Reg[15] & (R15INTBITS | R15PCBITS)) +#define R15INTPCMODE (state->Reg[15] & (R15INTBITS | R15PCBITS | R15MODEBITS)) +#define R15INTMODE (state->Reg[15] & (R15INTBITS | R15MODEBITS)) +#define R15PC (state->Reg[15] & R15PCBITS) +#define R15PCMODE (state->Reg[15] & (R15PCBITS | R15MODEBITS)) +#define R15MODE (state->Reg[15] & R15MODEBITS) + +#define ECC ((NFLAG << 31) | (ZFLAG << 30) | (CFLAG << 29) | (VFLAG << 28)) +#define EINT (IFFLAGS << 6) +#define ER15INT (IFFLAGS << 26) +#define EMODE (state->Mode) + +#ifdef MODET +#define CPSR (ECC | EINT | EMODE | (TFLAG << 5)) +#else +#define CPSR (ECC | EINT | EMODE) +#endif + +#ifdef MODE32 +#define PATCHR15 +#else +#define PATCHR15 state->Reg[15] = ECC | ER15INT | EMODE | R15PC +#endif + +#define GETSPSR(bank) bank>0?state->Spsr[bank]:ECC | EINT | EMODE ; +#define SETPSR(d,s) d = (s) & (ARMword)(CCBITS | INTBITS | MODEBITS) +#define SETINTMODE(d,s) d = ((d) & CCBITS) | ((s) & (INTBITS | MODEBITS)) +#define SETCC(d,s) d = ((d) & (INTBITS | MODEBITS)) | ((s) & CCBITS) +#define SETR15PSR(s) if (state->Mode == USER26MODE) { \ + state->Reg[15] = ((s) & CCBITS) | R15PC | ER15INT | EMODE ; \ + ASSIGNN((state->Reg[15] & NBIT) != 0) ; \ + ASSIGNZ((state->Reg[15] & ZBIT) != 0) ; \ + ASSIGNC((state->Reg[15] & CBIT) != 0) ; \ + ASSIGNV((state->Reg[15] & VBIT) != 0) ; \ + } \ + else { \ + state->Reg[15] = R15PC | (s) & (CCBITS | R15INTBITS | R15MODEBITS) ; \ + ARMul_R15Altered(state) ; \ + } +#define SETABORT(i,m) state->Cpsr = ECC | EINT | (i) | (m) + +#ifndef MODE32 +#define VECTORS 0x20 +#define LEGALADDR 0x03ffffff +#define VECTORACCESS(address) (address < VECTORS && ARMul_MODE26BIT && state->prog32Sig) +#define ADDREXCEPT(address) (address > LEGALADDR && !state->data32Sig) +#endif + +#define INTERNALABORT(address) if (address < VECTORS) \ + state->Aborted = ARMul_DataAbortV ; \ + else \ + state->Aborted = ARMul_AddrExceptnV ; + +#ifdef MODE32 +#define TAKEABORT ARMul_Abort(state,ARMul_DataAbortV) +#else +#define TAKEABORT if (state->Aborted == ARMul_AddrExceptnV) \ + ARMul_Abort(state,ARMul_AddrExceptnV) ; \ + else \ + ARMul_Abort(state,ARMul_DataAbortV) +#endif +#define CPTAKEABORT if (!state->Aborted) \ + ARMul_Abort(state,ARMul_UndefinedInstrV) ; \ + else if (state->Aborted == ARMul_AddrExceptnV) \ + ARMul_Abort(state,ARMul_AddrExceptnV) ; \ + else \ + ARMul_Abort(state,ARMul_DataAbortV) + + +/***************************************************************************\ +* Different ways to start the next instruction * +\***************************************************************************/ + +#define SEQ 0 +#define NONSEQ 1 +#define PCINCEDSEQ 2 +#define PCINCEDNONSEQ 3 +#define PRIMEPIPE 4 +#define RESUME 8 + +#define NORMALCYCLE state->NextInstr = 0 +#define BUSUSEDN state->NextInstr |= 1 /* the next fetch will be an N cycle */ +#define BUSUSEDINCPCS state->Reg[15] += isize ; /* a standard PC inc and an S cycle */ \ + state->NextInstr = (state->NextInstr & 0xff) | 2 +#define BUSUSEDINCPCN state->Reg[15] += isize ; /* a standard PC inc and an N cycle */ \ + state->NextInstr |= 3 +#define INCPC state->Reg[15] += isize ; /* a standard PC inc */ \ + state->NextInstr |= 2 +#define FLUSHPIPE state->NextInstr |= PRIMEPIPE + +/***************************************************************************\ +* Cycle based emulation * +\***************************************************************************/ + +#define OUTPUTCP(i,a,b) +#define NCYCLE +#define SCYCLE +#define ICYCLE +#define CCYCLE +#define NEXTCYCLE(c) + +/***************************************************************************\ +* States of the cycle based state machine * +\***************************************************************************/ + + +/***************************************************************************\ +* Macros to extract parts of instructions * +\***************************************************************************/ + +#define DESTReg (BITS(12,15)) +#define LHSReg (BITS(16,19)) +#define RHSReg (BITS(0,3)) + +#define DEST (state->Reg[DESTReg]) + +#ifdef MODE32 +#ifdef MODET +#define LHS ((LHSReg == 15) ? (state->Reg[15] & 0xFFFFFFFC): (state->Reg[LHSReg])) +#else +#define LHS (state->Reg[LHSReg]) +#endif +#else +#define LHS ((LHSReg == 15) ? R15PC : (state->Reg[LHSReg]) ) +#endif + +#define MULDESTReg (BITS(16,19)) +#define MULLHSReg (BITS(0,3)) +#define MULRHSReg (BITS(8,11)) +#define MULACCReg (BITS(12,15)) + +#define DPImmRHS (ARMul_ImmedTable[BITS(0,11)]) +#define DPSImmRHS temp = BITS(0,11) ; \ + rhs = ARMul_ImmedTable[temp] ; \ + if (temp > 255) /* there was a shift */ \ + ASSIGNC(rhs >> 31) ; + +#ifdef MODE32 +#define DPRegRHS ((BITS(4,11)==0) ? state->Reg[RHSReg] \ + : GetDPRegRHS(state, instr)) +#define DPSRegRHS ((BITS(4,11)==0) ? state->Reg[RHSReg] \ + : GetDPSRegRHS(state, instr)) +#else +#define DPRegRHS ((BITS(0,11)<15) ? state->Reg[RHSReg] \ + : GetDPRegRHS(state, instr)) +#define DPSRegRHS ((BITS(0,11)<15) ? state->Reg[RHSReg] \ + : GetDPSRegRHS(state, instr)) +#endif + +#define LSBase state->Reg[LHSReg] +#define LSImmRHS (BITS(0,11)) + +#ifdef MODE32 +#define LSRegRHS ((BITS(4,11)==0) ? state->Reg[RHSReg] \ + : GetLSRegRHS(state, instr)) +#else +#define LSRegRHS ((BITS(0,11)<15) ? state->Reg[RHSReg] \ + : GetLSRegRHS(state, instr)) +#endif + +#define LSMNumRegs ((ARMword)ARMul_BitList[BITS(0,7)] + \ + (ARMword)ARMul_BitList[BITS(8,15)] ) +#define LSMBaseFirst ((LHSReg == 0 && BIT(0)) || \ + (BIT(LHSReg) && BITS(0,LHSReg-1) == 0)) + +#define SWAPSRC (state->Reg[RHSReg]) + +#define LSCOff (BITS(0,7) << 2) +#define CPNum BITS(8,11) + +/***************************************************************************\ +* Macro to rotate n right by b bits * +\***************************************************************************/ + +#define ROTATER(n,b) (((n)>>(b))|((n)<<(32-(b)))) + +/***************************************************************************\ +* Macros to store results of instructions * +\***************************************************************************/ + +#define WRITEDEST(d) if (DESTReg==15) \ + WriteR15(state, d) ; \ + else \ + DEST = d + +#define WRITESDEST(d) if (DESTReg == 15) \ + WriteSR15(state, d) ; \ + else { \ + DEST = d ; \ + ARMul_NegZero(state, d) ; \ + } + +#define BYTETOBUS(data) ((data & 0xff) | \ + ((data & 0xff) << 8) | \ + ((data & 0xff) << 16) | \ + ((data & 0xff) << 24)) +#define BUSTOBYTE(address,data) \ + if (state->bigendSig) \ + temp = (data >> (((address ^ 3) & 3) << 3)) & 0xff ; \ + else \ + temp = (data >> ((address & 3) << 3)) & 0xff + +#define LOADMULT(instr,address,wb) LoadMult(state,instr,address,wb) +#define LOADSMULT(instr,address,wb) LoadSMult(state,instr,address,wb) +#define STOREMULT(instr,address,wb) StoreMult(state,instr,address,wb) +#define STORESMULT(instr,address,wb) StoreSMult(state,instr,address,wb) + +#define POSBRANCH ((instr & 0x7fffff) << 2) +#define NEGBRANCH (0xff000000 | ((instr & 0xffffff) << 2)) + +/***************************************************************************\ +* Values for Emulate * +\***************************************************************************/ + +#define STOP 0 /* stop */ +#define CHANGEMODE 1 /* change mode */ +#define ONCE 2 /* execute just one interation */ +#define RUN 3 /* continuous execution */ + +/***************************************************************************\ +* Stuff that is shared across modes * +\***************************************************************************/ + +extern ARMword ARMul_Emulate26(ARMul_State *state) ; +extern ARMword ARMul_Emulate32(ARMul_State *state) ; +extern unsigned ARMul_MultTable[] ; /* Number of I cycles for a mult */ +extern ARMword ARMul_ImmedTable[] ; /* immediate DP LHS values */ +extern char ARMul_BitList[] ; /* number of bits in a byte table */ +extern void ARMul_Abort26(ARMul_State *state, ARMword) ; +extern void ARMul_Abort32(ARMul_State *state, ARMword) ; +extern unsigned ARMul_NthReg(ARMword instr,unsigned number) ; +extern void ARMul_MSRCpsr(ARMul_State *state, ARMword instr, ARMword rhs) ; +extern void ARMul_NegZero(ARMul_State *state, ARMword result) ; +extern void ARMul_AddCarry(ARMul_State *state, ARMword a, ARMword b, ARMword result) ; +extern void ARMul_AddOverflow(ARMul_State *state, ARMword a, ARMword b, ARMword result) ; +extern void ARMul_SubCarry(ARMul_State *state, ARMword a, ARMword b, ARMword result) ; +extern void ARMul_SubOverflow(ARMul_State *state, ARMword a, ARMword b, ARMword result) ; +extern void ARMul_CPSRAltered(ARMul_State *state) ; +extern void ARMul_R15Altered(ARMul_State *state) ; +extern ARMword ARMul_SwitchMode(ARMul_State *state,ARMword oldmode, ARMword newmode) ; +extern unsigned ARMul_NthReg(ARMword instr, unsigned number) ; +extern void ARMul_LDC(ARMul_State *state,ARMword instr,ARMword address) ; +extern void ARMul_STC(ARMul_State *state,ARMword instr,ARMword address) ; +extern void ARMul_MCR(ARMul_State *state,ARMword instr, ARMword source) ; +extern ARMword ARMul_MRC(ARMul_State *state,ARMword instr) ; +extern void ARMul_CDP(ARMul_State *state,ARMword instr) ; +extern unsigned IntPending(ARMul_State *state) ; +extern ARMword ARMul_Align(ARMul_State *state, ARMword address, ARMword data) ; +#define EVENTLISTSIZE 1024L + +/* Thumb support: */ + +typedef enum { + t_undefined, /* undefined Thumb instruction */ + t_decoded, /* instruction decoded to ARM equivalent */ + t_branch /* Thumb branch (already processed) */ +} tdstate; + +extern tdstate ARMul_ThumbDecode(ARMul_State *state,ARMword pc,ARMword tinstr, ARMword *ainstr); + +/***************************************************************************\ +* Macros to scrutinize instructions * +\***************************************************************************/ + + +#define UNDEF_Test +#define UNDEF_Shift +#define UNDEF_MSRPC +#define UNDEF_MRSPC +#define UNDEF_MULPCDest +#define UNDEF_MULDestEQOp1 +#define UNDEF_LSRBPC +#define UNDEF_LSRBaseEQOffWb +#define UNDEF_LSRBaseEQDestWb +#define UNDEF_LSRPCBaseWb +#define UNDEF_LSRPCOffWb +#define UNDEF_LSMNoRegs +#define UNDEF_LSMPCBase +#define UNDEF_LSMUserBankWb +#define UNDEF_LSMBaseInListWb +#define UNDEF_SWPPC +#define UNDEF_CoProHS +#define UNDEF_MCRPC +#define UNDEF_LSCPCBaseWb +#define UNDEF_UndefNotBounced +#define UNDEF_ShortInt +#define UNDEF_IllegalMode +#define UNDEF_Prog32SigChange +#define UNDEF_Data32SigChange + diff --git a/sim/arm/armfpe.h b/sim/arm/armfpe.h new file mode 100644 index 00000000000..b10af160c03 --- /dev/null +++ b/sim/arm/armfpe.h @@ -0,0 +1,1351 @@ +/* armfpe.h -- ARMulator pre-compiled FPE: ARM6 Instruction Emulator. + Copyright (C) 1994 Advanced RISC Machines Ltd. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* Array containing the Floating Point Emualtor (FPE). */ + + +unsigned long fpecode[] = { +0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000, +0x00070000,0x00000000,0xe92d400e,0xeb0013ef, +0xe28f00d4,0xe1a00120,0xe38004ea,0xe3a01004, +0xe5912000,0xe24f3028,0xe1500002,0x15832000, +0x15810000,0xe3a00001,0xe8bd800e,0xe28d9040, +0xe1a0a00e,0xe24f7048,0xe597b000,0xe20b74ee, +0xe14f8000,0xe2088040,0xe388809b,0xe121f008, +0xe35704ea,0x004bb007,0x01a0b10b,0x028bf00c, +0xe20b733b,0xe3570339,0x01a0ba0b,0x01a0ba2b, +0x059bb00c,0x0249800c,0x08880e00,0x0919ff80, +0xe24f7094,0xe1a0f007,0xe14f8000,0xe2088040, +0xe3888093,0xe121f008,0xe8dd7fff,0xe1a00000, +0xe28dd03c,0xe8fd8000,0xe14f8000,0xe2088040, +0xe3888093,0xe121f008,0xe8bd1fff,0xe28dd00c, +0xe1b0f00e,0xe14f8000,0xe2088040,0xe3888093, +0xe121f008,0xe28dd01c,0xe8bd1f80,0xe28dd00c, +0xe1b0f00e,0x00002100,0xe90d4007,0xe14f0000, +0xe24d1010,0xe10f2000,0xe20220c0,0xe3822003, +0xe121f002,0xe169f000,0xe8914007,0xe24dd040, +0xe8cd7fff,0xe24fcf6b,0xe58de03c,0xe24ea004, +0xe14f9000,0xe20990c0,0xe3899003,0xe121f009, +0xe4ba9008,0xe20987fe,0xe2197010,0xe0077aa9, +0xe0288a07,0x02097402,0x00077509,0x00888007, +0xe2097c0f,0xe3370c01,0x0209733e,0x0337033a, +0x008ff8a8,0xea00009f,0xea0003b7,0xea0003b6, +0xea000307,0xea000306,0xea0003b3,0xea0003b2, +0xea000303,0xea000302,0xea0003c3,0xea0003c2, +0xea00030d,0xea00030c,0xea0003bf,0xea0003be, +0xea000309,0xea000308,0xea0003cf,0xea0003ce, +0xea000314,0xea000313,0xea0003cb,0xea0003ca, +0xea000310,0xea00030f,0xea0003db,0xea0003da, +0xea00031a,0xea000319,0xea0003d7,0xea0003d6, +0xea000316,0xea000315,0xea0003e7,0xea0003e6, +0xea000321,0xea000320,0xea0003f7,0xea0003f6, +0xea00032b,0xea00032a,0xea000449,0xea000448, +0xea000335,0xea000334,0xea000459,0xea000458, +0xea000340,0xea00033f,0xea000469,0xea000468, +0xea00034b,0xea00034a,0xea000479,0xea000478, +0xea000355,0xea000354,0xea000489,0xea000488, +0xea00035f,0xea00035e,0xea000499,0xea000498, +0xea00036a,0xea000369,0xea000ac8,0xea000ac5, +0xea000c3d,0xea000c3a,0xea000b7b,0xea000b78, +0xea000b79,0xea000b76,0xea000d34,0xea000d31, +0xea000d08,0xea000d05,0xea000e34,0xea000e31, +0xea000e1c,0xea000e19,0xea000ecf,0xea000ecc, +0xea000c2d,0xea000c2a,0xea000d28,0xea000d25, +0xea000cfc,0xea000cf9,0xea00123d,0xea00123a, +0xeaffff55,0xeaffff54,0xeaffff53,0xeaffff52, +0xeaffff51,0xeaffff50,0xea0007b8,0xea0007ec, +0xea00073c,0xea00073b,0xea000806,0xea000805, +0xea00080f,0xea00080e,0xeaffff47,0xeaffff46, +0xeaffff45,0xeaffff44,0xeaffff43,0xeaffff42, +0xeaffff41,0xeaffff40,0xeaffff3f,0xeaffff3e, +0xea00086f,0xea00086e,0xeaffff3b,0xeaffff3a, +0xea00086b,0xea00086a,0xeaffff37,0xeaffff36, +0xea0007ff,0xea0007fe,0xeaffff33,0xeaffff32, +0xea0007fb,0xea0007fa,0xea000914,0xea0008f3, +0xea00091f,0xea0008fb,0xea00092b,0xea000904, +0xea0009dc,0xea0009d9,0xea0009fd,0xea0009fa, +0xea000ef8,0xea000ef5,0xea000ef6,0xea000ef3, +0xea000f9d,0xea000f9a,0xea00111e,0xea00111b, +0xea00111c,0xea001119,0xea00104e,0xea00104b, +0xea001147,0xea001144,0xea001145,0xea001142, +0xea00125a,0xea001257,0xeaffff13,0xeaffff12, +0xeaffff11,0xeaffff10,0xe3190c0e,0x1affff0e, +0xe3190c01,0x13190302,0x0affff0b,0xe28fb016, +0xe79b7d27,0xe14fb000,0xe1a0be2b,0xe28bb010, +0xe1170b37,0x0affff51,0xeaffff29,0x8000f0f0, +0x80000f0f,0x8000cccc,0x80003333,0x8000ff00, +0x800000ff,0x8000aaaa,0x80005555,0x8000cfcf, +0x80003030,0x800055aa,0x8000aa55,0x80005faf, +0x8000a050,0x80000000,0x8000ffff,0xe1300007, +0x5a000002,0xea00004a,0xe3100102,0x1a000048, +0xe053400b,0x4a00002d,0xe2745020,0xda00001b, +0xe092243a,0x20822518,0x30922518,0xe0b11438, +0xe1a0451a,0x2a000006,0xe0922fa4,0xe2b11000, +0x31b0f00e,0xe3a01102,0xe2833001,0xe1a040a4, +0xe1b0f00e,0xe2833001,0xe1a040a4,0xe1844f82, +0xe1a020a2,0xe1822f81,0xe1a01061,0xe0922fa4, +0xe2a11000,0xe1b0f00e,0xe1a04538,0xe0922fa4, +0xe2b11000,0x23a01102,0x22833001,0xe1b0f00e, +0xe2545040,0xaafffff7,0xe2444020,0xe2645020, +0xe0922438,0xe2b11000,0xe1a04518,0xe184443a, +0x2affffe7,0xe0922fa4,0xe2b11000,0x31b0f00e, +0xe3a01102,0xe2833001,0xe1a040a4,0xe1b0f00e, +0xe2644000,0xe1a0300b,0xe1a05001,0xe1a01008, +0xe1a08005,0xe1a05002,0xe1a0200a,0xe1a0a005, +0xe2745020,0xdaffffe5,0xe092243a,0x20822518, +0x30922518,0xe0b11438,0xe1a0451a,0x2affffd0, +0xe0922fa4,0xe2b11000,0x31b0f00e,0xe3a01102, +0xe2833001,0xe1a040a4,0xe1b0f00e,0xe3100102, +0x1affffb6,0xe053600b,0x4a00003d,0x01510008, +0x0152000a,0x0a00004f,0x3a000039,0xe3a04000, +0xe2765020,0xda00001a,0xe054451a,0xe0d2263a, +0x30422518,0x20522518,0xe0d11638,0x5a000002, +0xe0922fa4,0xe2a11000,0xe1b0f00e,0xe0944004, +0xe0b22002,0xe0b11001,0xe2433001,0x5afffffa, +0xe0922fa4,0xe2b11000,0x31b0f00e,0xe3a01102, +0xe2833001,0xe1a040a4,0xe1b0f00e,0xe0544538, +0x41b0f00e,0xe2d22000,0xe2d11000,0x41b0f00e, +0xeaffffed,0xe3a04000,0xe2565040,0xaafffff6, +0xe2466020,0xe2665020,0xe054751a,0xe0d4463a, +0x30444518,0x20544518,0xe0d22638,0xe2d11000, +0x5a000002,0xe0922fa4,0xe2a11000,0xe1b0f00e, +0xe0977007,0xe0b44004,0xe0b22002,0xe0b11001, +0xe2433001,0x5afffff9,0xe0922fa4,0xe2b11000, +0x31b0f00e,0xe3a01102,0xe2833001,0xe1a040a4, +0xe1b0f00e,0xe2666000,0xe2200102,0xe1a0300b, +0xe1a05001,0xe1a01008,0xe1a08005,0xe1a05002, +0xe1a0200a,0xe1a0a005,0xe3a04000,0xe2765020, +0xdaffffd7,0xe054451a,0xe0d2263a,0x30422518, +0x20522518,0xe0d11638,0x5affffbf,0xe0922fa4, +0xe2a11000,0xe1b0f00e,0xe3a03000,0xe3a02000, +0xe3a01000,0xe3a04000,0xe1b0f00e,0xe1a07000, +0xe1a08001,0xe1a0a002,0xe1a0b003,0xe0200007, +0xe1914002,0x1198400a,0x0afffff2,0xe3b054ff, +0xe0a3300b,0xe185b425,0xe043392b,0xe92c4209, +0xe1a04821,0xe1c1500b,0xe1a06822,0xe1c2700b, +0xe1c8900b,0xe1a08828,0xe1cab00b,0xe1a0a82a, +0xe0030b96,0xe0020b94,0xe0010994,0xe0000a97, +0xe0933000,0xe0000a95,0xe0b22000,0xe0000895, +0xe0b11000,0x33a0e000,0x23a0e001,0xe0000996, +0xe0922000,0xe2b11000,0xe2aee000,0xe0000897, +0xe0922000,0xe2b11000,0xe2aee000,0xe18ee803, +0xe1a03823,0xe1833802,0xe1a02822,0xe1822801, +0xe1a01821,0xe181180e,0xe3cee0ff,0xe0000b95, +0xe00b0b97,0xe09eb00b,0xe0b33000,0xe0000896, +0xe0b22000,0xe0000894,0xe0a11000,0xe0000a94, +0xe00a0a96,0xe09aa003,0xe0b22000,0xe2a11000, +0xe0000997,0xe09a4000,0xe0000995,0xe0b22000, +0xe2b11000,0xe8bc4209,0x4a000005,0xe09bb00b, +0xe0b44004,0xe0b22002,0xe0b11001,0xe2433001, +0x5afffff9,0xe0922fa4,0xe2b11000,0x31b0f00e, +0xe3a01102,0xe2833001,0xe1a040a4,0xe1b0f00e, +0xe1a07000,0xe1a08001,0xe1a0a002,0xe1a0b003, +0xe3a00000,0xe3a01102,0xe3b02100,0xe2e23901, +0xe0200007,0xe1914002,0x1198400a,0x0affff9d, +0xe043300b,0xe2833901,0xe2433001,0xe3a0b000, +0xe052500a,0xe0d14008,0x23a01003,0x2a00000c, +0xe1a05002,0xe1a04001,0xe3a01001,0xe2433001, +0xe0955005,0xe0b44004,0xe2abb000,0xe055700a, +0xe0d46008,0x31b0b0ab,0x21a05007,0x21a04006, +0xe0a11001,0xe0955005,0xe0b44004,0xe2abb000, +0xe055700a,0xe0d46008,0x31b0b0ab,0x21a05007, +0x21a04006,0xe0a11001,0xe0955005,0xe0b44004, +0xe2abb000,0xe055700a,0xe0d46008,0x31b0b0ab, +0x21a05007,0x21a04006,0xe0a11001,0xe0955005, +0xe0b44004,0xe2abb000,0xe055700a,0xe0d46008, +0x31b0b0ab,0x21a05007,0x21a04006,0xe0b11001, +0x3affffda,0xe1942005,0x01b0f00e,0xe3a02001, +0xe0955005,0xe0b44004,0xe2abb000,0xe055700a, +0xe0d46008,0x31b0b0ab,0x21a05007,0x21a04006, +0xe0a22002,0xe0955005,0xe0b44004,0xe2abb000, +0xe055700a,0xe0d46008,0x31b0b0ab,0x21a05007, +0x21a04006,0xe0a22002,0xe0955005,0xe0b44004, +0xe2abb000,0xe055700a,0xe0d46008,0x31b0b0ab, +0x21a05007,0x21a04006,0xe0a22002,0xe0955005, +0xe0b44004,0xe2abb000,0xe055700a,0xe0d46008, +0x31b0b0ab,0x21a05007,0x21a04006,0xe0b22002, +0x3affffda,0xe0955005,0xe0b44004,0x2a000001, +0xe1540008,0x0155000a,0xe2b22000,0xe2b11000, +0x31b0f00e,0xe2a33000,0xe3a01102,0xe1b0f00e, +0xe1b04883,0x0affff37,0xe2833901,0xe2433001, +0xe1b030a3,0xe1a05002,0x32414102,0x22414101, +0x33a07201,0x23a07202,0xe3a01102,0xe0955005, +0xe0b44004,0xe0216007,0x31540006,0x20444006, +0x20211087,0xe1b070e7,0x5afffff7,0xe1942005, +0x01b0f00e,0xe3a02000,0xe0955005,0xe0b44004, +0xe0a00000,0xe0226007,0xe055a006,0xe0d48001, +0x31b000a0,0x21a0500a,0x21a04008,0x20222087, +0x20211fa7,0xe1b070a7,0x1afffff2,0xe0955005, +0xe0b44004,0xe0b70007,0xe0d5a002,0xe0d48001, +0x31b000a0,0x21a0500a,0x21a04008,0x22222001, +0x23a07102,0xe3a00000,0xe0977007,0xe0b55005, +0xe0b44004,0x2a000002,0xe1540001,0x01550002, +0x03570101,0xe2b22000,0xe2b11000,0xe2a33000, +0x23a01102,0xe1b0f00e,0xe1b07004,0x42644000, +0xe3a0b901,0xe3a0a000,0xe1a08004,0xe1b04828, +0x01a08808,0x128bb010,0xe1b04c28,0x01a08408, +0x128bb008,0xe1b04e28,0x01a08208,0x128bb004, +0xe1b04f28,0x01a08108,0x128bb002,0xe1b04fa8, +0x01a08088,0x024bb001,0xe1b0f00e,0xe1a07000, +0xe1a0b003,0xe24b40fe,0xe2544c3f,0xda000011, +0xe2745020,0x4a000003,0xe3a0a000,0xe1a08531, +0xe1a08518,0xe1b0f00e,0xe1a08001,0xe1a0a002, +0xe2745040,0x41b0f00e,0xe1a0a53a,0xe1a0a51a, +0xe1b0f00e,0x03a04001,0x03a08102,0xe3a0a000, +0x028bb001,0x01b0f00e,0xe3a04000,0xe3a08000, +0xe3a0a000,0xe3a0b000,0xe1b0f00e,0xe1a07000, +0xe1a0b003,0xe24b40fe,0xe2544c3f,0xdafffff0, +0xe2745020,0x4a000007,0xe3a0a000,0xe1b04531, +0xe2a44000,0xe1b08514,0x31b0f00e,0xe1a08068, +0xe28bb001,0xe1b0f00e,0xe1a08001,0xe1a0a002, +0xe2745040,0xe3e04000,0x41b0f00e,0xe1b0a53a, +0xe2aaa000,0xe1b0a51a,0xe2b88000,0x31b0f00e, +0xe1a0a0aa,0xe18aaf88,0xe1a08068,0xe28bb001, +0xe1b0f00e,0xe38ee101,0xe24340fe,0xe2544c3f, +0xda000032,0xe2745020,0x4a000018,0xe1a08411, +0x01a08002,0x11a0a002,0x03a0a000,0xe3a02000, +0xe1a01531,0xe2194060,0x1a000007,0xe19aa088, +0x00088f81,0xe0911fa8,0x31b01511,0x31b0f00e, +0xe1a01061,0xe2833001,0xe1b0f00e,0xe3540060, +0x1198a00a,0x0a000003,0xe0304d04,0x5a000001, +0xe2911001,0xeafffff3,0xe1a01511,0xe1b0f00e, +0xe2745040,0xd1b0f00e,0xe2444020,0xe1a08412, +0xe1b02532,0xe2194060,0x1a00000a,0xe1b0a088, +0x00088f82,0xe0822fa8,0xe1b02512,0xe2b11000, +0x31b0f00e,0xe1a020a2,0xe1822f81,0xe1a01061, +0xe2833001,0xe1b0f00e,0xe3540060,0x13580000, +0x0afffff4,0xe0304d04,0x42822001,0xeafffff1, +0x0a000011,0xe2194060,0x1a000006,0xe1918002, +0x01b0f00e,0xe3a01000,0xe3a02000,0xe3a03000, +0xe3a04008,0xe1a0f00e,0xe1918002,0x13540060, +0x0afffff5,0xe0304d04,0x5afffff3,0xe3a01102, +0xe3b02100,0xe2e23901,0xe1b0f00e,0xe2194060, +0x1afffff4,0xe1924081,0x1afffff7,0xeaffffea, +0xe1a04000,0xe1a00007,0xe1a07004,0xe1a04001, +0xe1a01008,0xe1a08004,0xe1a04002,0xe1a0200a, +0xe1a0a004,0xe1a04003,0xe1a0300b,0xe1a0b004, +0xe1b0f00e,0xe209ba07,0xe08c542b,0xe209780f, +0xe79da727,0xe21980ff,0xe04a8108,0x178d8727, +0xe2199902,0xe3899901,0xe1a09789,0xe4ba6004, +0x14ba7004,0xe88503c0,0xeafffcae,0xe209ba07, +0xe08c542b,0xe209780f,0xe79da727,0xe21980ff, +0xe04a8108,0x178d8727,0xe2199902,0xe3899905, +0xe1a09789,0xe4ba6004,0xe4ba7004,0xe4ba8000, +0xe88503c0,0xeafffc9f,0xe209ba07,0xe08c542b, +0xe209780f,0xe79da727,0xe21980ff,0xe08a8108, +0x178d8727,0xe2199902,0xe3899901,0xe1a09789, +0xe4ba6004,0x14ba7004,0xe88503c0,0xeafffc91, +0xe209ba07,0xe08c542b,0xe209780f,0xe79da727, +0xe21980ff,0xe08a8108,0x178d8727,0xe2199902, +0xe3899905,0xe1a09789,0xe4ba6004,0xe4ba7004, +0xe4ba8000,0xe88503c0,0xeafffc82,0xe209ba07, +0xe08cc42b,0xe209780f,0xe337080f,0x179da727, +0xe21980ff,0xe04aa108,0xe2199902,0xe3899901, +0xe1a0b789,0xe4ba8004,0x14ba9004,0xe88c0f00, +0xeafffc83,0xe209ba07,0xe08c542b,0xe209780f, +0xe79da727,0xe21980ff,0xe04aa108,0x178da727, +0xe2199902,0xe3899901,0xe1a09789,0xe4ba6004, +0x14ba7004,0xe88503c0,0xeafffc66,0xe209ba07, +0xe08cc42b,0xe209780f,0xe337080f,0x179da727, +0xe21980ff,0xe04aa108,0xe2199902,0xe3899905, +0xe1a0b789,0xe4ba8004,0xe4ba9004,0xe4baa000, +0xe88c0f00,0xeafffc66,0xe209ba07,0xe08c542b, +0xe209780f,0xe79da727,0xe21980ff,0xe04aa108, +0x178da727,0xe2199902,0xe3899905,0xe1a09789, +0xe4ba6004,0xe4ba7004,0xe4ba8000,0xe88503c0, +0xeafffc48,0xe209ba07,0xe08cc42b,0xe209780f, +0xe337080f,0x179da727,0xe21980ff,0xe08aa108, +0xe2199902,0xe3899901,0xe1a0b789,0xe4ba8004, +0x14ba9004,0xe88c0f00,0xeafffc49,0xe209ba07, +0xe08c542b,0xe209780f,0xe79da727,0xe21980ff, +0xe08aa108,0x178da727,0xe2199902,0xe3899901, +0xe1a09789,0xe4ba6004,0x14ba7004,0xe88503c0, +0xeafffc2c,0xe209ba07,0xe08cc42b,0xe209780f, +0xe337080f,0x179da727,0xe21980ff,0xe08aa108, +0xe2199902,0xe3899905,0xe1a0b789,0xe4ba8004, +0xe4ba9004,0xe4baa000,0xe88c0f00,0xeafffc2c, +0xe209ba07,0xe08c542b,0xe209780f,0xe79da727, +0xe21980ff,0xe08aa108,0x178da727,0xe2199902, +0xe3899905,0xe1a09789,0xe4ba6004,0xe4ba7004, +0xe4ba8000,0xe88503c0,0xeafffc0e,0xe2095a07, +0xe08c5425,0xe895000f,0xe3a04002,0xe0044729, +0xe3844001,0xe1340ea3,0xe1844d23,0xe28f7004, +0xe28f5f6f,0x1085f104,0xe209780f,0xe79da727, +0xe21980ff,0xe04a8108,0x178d8727,0xe4aa0004, +0xe3130101,0x14aa1000,0xeafffbfa,0xe2095a07, +0xe08c5425,0xe895000f,0xe3a04002,0xe0044729, +0xe3844005,0xe1340ea3,0xe1844d23,0xe28f7004, +0xe28f5f5b,0x1085f104,0xe209780f,0xe79da727, +0xe21980ff,0xe04a8108,0x178d8727,0xe4aa0004, +0xe4aa1004,0xe4aa2000,0xeafffbe6,0xe2095a07, +0xe08c5425,0xe895000f,0xe3a04002,0xe0044729, +0xe3844001,0xe1340ea3,0xe1844d23,0xe28f7004, +0xe28f5f47,0x1085f104,0xe209780f,0xe79da727, +0xe21980ff,0xe08a8108,0x178d8727,0xe4aa0004, +0xe3130101,0x14aa1000,0xeafffbd2,0xe2095a07, +0xe08c5425,0xe895000f,0xe3a04002,0xe0044729, +0xe3844005,0xe1340ea3,0xe1844d23,0xe28f7004, +0xe28f50cc,0x1085f104,0xe209780f,0xe79da727, +0xe21980ff,0xe08a8108,0x178d8727,0xe4aa0004, +0xe4aa1004,0xe4aa2000,0xeafffbbe,0xe2095a07, +0xe08c5425,0xe895000f,0xe3a04002,0xe0044729, +0xe3844001,0xe1340ea3,0xe1844d23,0xe28f7004, +0xe28f507c,0x1085f104,0xe209780f,0xe337080f, +0x179da727,0xe21980ff,0xe04aa108,0xe4aa0004, +0xe3130101,0x14aa1000,0xeafffbb2,0xe2095a07, +0xe08c5425,0xe895000f,0xe3a04002,0xe0044729, +0xe3844001,0xe1340ea3,0xe1844d23,0xe28f7004, +0xe28f502c,0x1085f104,0xe209780f,0xe79da727, +0xe21980ff,0xe04aa108,0x178da727,0xe4aa0004, +0xe3130101,0x14aa1000,0xeafffb96,0xe08ff104, +0xeb00036b,0xe1a0f007,0xea0000b6,0xeb000368, +0xea0000ea,0xeb000366,0xea000123,0xeb000364, +0xea0001ca,0xea000124,0xe1a0f007,0xeb000360, +0xea000134,0xeb00035e,0xea00014b,0xeb00035c, +0xea0001bd,0xeb00035a,0xeb000359,0xeb000358, +0xeb000357,0xeb000356,0xeb000355,0xeb000354, +0xeb000353,0xea000156,0xea00016f,0xeb000350, +0xe1a0f007,0xeb00034e,0xea00018c,0xeb00034c, +0xea0001ad,0xeb00034a,0xeb000349,0xeb000348, +0xeb000347,0xeb000346,0xeb000345,0xeb000344, +0xeb000343,0xea00019f,0xea00008d,0xeb000340, +0xea0000c1,0xeb00033e,0xe1a0f007,0xeb00033c, +0xea00019d,0xeb00033a,0xeb000339,0xeb000338, +0xeb000337,0xeb000336,0xeb000335,0xeb000334, +0xeb000333,0xea00024f,0xea00024e,0xeb000330, +0xea00024c,0xeb00032e,0xea00024a,0xeb00032c, +0xe1a0f007,0xe2095a07,0xe08c5425,0xe895000f, +0xe3a04002,0xe0044729,0xe3844005,0xe1340ea3, +0xe1844d23,0xe28f7004,0xe24f5f4b,0x1085f104, +0xe209780f,0xe337080f,0x179da727,0xe21980ff, +0xe04aa108,0xe4aa0004,0xe4aa1004,0xe4aa2004, +0xeafffb48,0xe2095a07,0xe08c5425,0xe895000f, +0xe3a04002,0xe0044729,0xe3844005,0xe1340ea3, +0xe1844d23,0xe28f7004,0xe24f5f5f,0x1085f104, +0xe209780f,0xe79da727,0xe21980ff,0xe04aa108, +0x178da727,0xe4aa0004,0xe4aa1004,0xe4aa2000, +0xeafffb2c,0xe2095a07,0xe08c5425,0xe895000f, +0xe3a04002,0xe0044729,0xe3844001,0xe1340ea3, +0xe1844d23,0xe28f7004,0xe24f5f73,0x1085f104, +0xe209780f,0xe337080f,0x179da727,0xe21980ff, +0xe08aa108,0xe4aa0004,0xe3130101,0x14aa1000, +0xeafffb20,0xe2095a07,0xe08c5425,0xe895000f, +0xe3a04002,0xe0044729,0xe3844001,0xe1340ea3, +0xe1844d23,0xe28f7004,0xe24f5f87,0x1085f104, +0xe209780f,0xe79da727,0xe21980ff,0xe08aa108, +0x178da727,0xe4aa0004,0xe3130101,0x14aa1000, +0xeafffb04,0xe2095a07,0xe08c5425,0xe895000f, +0xe3a04002,0xe0044729,0xe3844005,0xe1340ea3, +0xe1844d23,0xe28f7004,0xe24f5f9b,0x1085f104, +0xe209780f,0xe337080f,0x179da727,0xe21980ff, +0xe08aa108,0xe4aa0004,0xe4aa1004,0xe4aa2004, +0xeafffaf8,0xe2095a07,0xe08c5425,0xe895000f, +0xe3a04002,0xe0044729,0xe3844005,0xe1340ea3, +0xe1844d23,0xe28f7004,0xe24f5faf,0x1085f104, +0xe209780f,0xe79da727,0xe21980ff,0xe08aa108, +0x178da727,0xe4aa0004,0xe4aa1004,0xe4aa2000, +0xeafffadc,0xe3c03102,0xe2000102,0xe1b05883, +0x12955802,0x0a00000e,0xe3320000,0x01922c81, +0xe2012080,0x000220a1,0xe0911002,0x31a01081, +0xe2a33000,0xe2533dfe,0x9a00001c,0xe35300ff, +0x31800b83,0x318004a1,0x33a03202,0x31a0f007, +0xea000008,0xe1b04c03,0xe18000a4,0xe3a03202, +0x13c11102,0x11800421,0x11a0f007,0xe1922001, +0x01a0f007,0xea000015,0xe380047f,0xe3800502, +0xe3a03202,0xe3a04004,0xe59c5080,0xe1855004, +0xe58c5080,0xe1140825,0x11a00004,0x1a000e8a, +0xe3540004,0x11a0f007,0xe3a04010,0xeafffff5, +0xe3730017,0xda000005,0xe1a01521,0xe3811501, +0xe2633000,0xe1800331,0xe3a03202,0xe1a0f007, +0xe3a03202,0xe3a04008,0xeaffffea,0xe3c03102, +0xe2000102,0xe1b05883,0x12955802,0x0a000012, +0xe1b04b02,0xe2024b01,0x000440a2,0xe0922004, +0xe2b11000,0xe2a33000,0xe0922002,0xe0a11001, +0xe2533b0f,0x9a000019,0xe2834001,0xe3540b02, +0x31800a03,0x31800621,0x31a01a01,0x31811622, +0x33a03206,0x31a0f007,0xea00000a,0xe1b04a83, +0xe18000a4,0xe3a03206,0x13c11102,0x118005a1, +0x11a01a81,0x118115a2,0x11a0f007,0xe1922001, +0x01a0f007,0xea000014,0xe380047f,0xe380060f, +0xe3a01000,0xe3a03206,0xe3a04004,0xeaffffc1, +0xe3730034,0xda00000c,0xe1a026a2,0xe1822981, +0xe1a016a1,0xe3811702,0xe2633000,0xe2534020, +0x21a01431,0x32634020,0x31800331,0x31a01411, +0x31811332,0xe3a03206,0xe1a0f007,0xe3a01000, +0xe3a03206,0xe3a04008,0xeaffffae,0xe2000102, +0xe1800003,0xe3a0320a,0xe1a0f007,0xe3a02000, +0xe1a03080,0xe1b03c23,0x133300ff,0x11a01400, +0x13811102,0x12833dfe,0x11a0f007,0xe1933383, +0x11a01400,0x13c11102,0x11a0f007,0xe1b01480, +0x01a0f007,0xe3a03dfe,0x52433001,0x51b01081, +0x5afffffc,0xe1a0f007,0xe1a01e80,0xe3c03102, +0xe2000102,0xe18001a3,0xe3a03206,0xe21026ff, +0x133206ff,0x1280030e,0x11a0f007,0xe1800182, +0xe3320000,0x11a0f007,0xe1912600,0x01a0f007, +0xe1a01a21,0xe1911600,0xe2000102,0xe380030e, +0x52400601,0x51b01081,0x5afffffc,0xe1a01081, +0xe1800621,0xe1a01a01,0xe1a0f007,0xe3a02000, +0xe1a03080,0xe1b03c23,0x133300ff,0xe1a01400, +0x13811102,0x12833dfe,0xe2000102,0xe1800003, +0xe3a0320a,0x11a0f007,0xe1800380,0xe31000ff, +0x13c11102,0x11a0f007,0xe1b01081,0x01a0f007, +0xe3800dfe,0x52400001,0x51b01081,0x5afffffc, +0xe1a0f007,0xe1a03080,0xe1b03aa3,0x12834001, +0x13340b02,0xe1a02581,0xe1a01aa1,0xe1811580, +0x13811102,0x12833b0f,0x11a0f007,0xe1933203, +0x11a0f007,0xe0922002,0xe0a11001,0xe1924001, +0x01a0f007,0xe3a03b0f,0xe1b01001,0x52433001, +0xe3a04000,0x51844fa2,0x51844081,0x51a02082, +0x51b01004,0x5afffff8,0xe1a0f007,0xe1a03080, +0xe1b03aa3,0x12834001,0x13340b02,0x0a00000f, +0xe1b04201,0xe1a01a21,0xe1811600,0xe2014c01, +0x000440a1,0xe0911004,0xe2a33000,0xe2000102, +0xe2533d0e,0x9affff49,0xe35300ff,0x31800b83, +0x318004a1,0x33a03202,0x31a0f007,0xeaffff35, +0xe1812600,0xe1a01a21,0xe1811600,0xe2000102, +0xe1b04c03,0xe18000a4,0xe3a03202,0x118004a1, +0x11a0f007,0xe3320000,0x01a0f007,0xeaffff3f, +0xe1a03080,0xe1b03aa3,0x12834001,0x13340b02, +0xe1a02581,0xe1a01aa1,0xe1811580,0x13811102, +0x12833b0f,0xe2000102,0xe1800003,0xe3a0320a, +0x11a0f007,0xe1800200,0xe31000ff,0x11a0f007, +0xe0922002,0xe0a11001,0xe1924001,0x01a0f007, +0xe3800b0f,0xe1b01001,0x52400001,0xe3a04000, +0x51844fa2,0x51844081,0x51a02082,0x51b01004, +0x5afffff8,0xe1a0f007,0xe3c03102,0xe1a0f007, +0x9a209a84,0xfbcff799,0x00003ffd,0xe92c0080, +0xe28f7004,0xe3c44007,0xeafffe2b,0xe8bc0080, +0xe1b05883,0x12955802,0x0a000099,0xe3a05901, +0xe2455001,0xe1530005,0x3a000006,0xe2855003, +0xe1530005,0x0351020a,0x33a04000,0x33a05000, +0x392c4ff0,0x3a000021,0xe92c4fcf,0xe3a00902, +0xe2404003,0xe0644083,0xebfffc46,0xe24bb001, +0xe24f4078,0xe894000e,0xebfffb4b,0xe3a04901, +0xe2444002,0xe0434004,0xe2644020,0xe1a09431, +0xe1510419,0x03520000,0x1210b102,0x12899001, +0xe200b102,0xe8bc000f,0xe92c0a00,0xeb0000bf, +0xe59c4004,0xe1b04004,0x5bfffb90,0x4bfffb3a, +0xe3a05901,0xe2455001,0xe1530005,0x3a000051, +0xe2855003,0xe1530005,0x0351020a,0x2a000040, +0xe3a04901,0xe2844002,0xe0544003,0xe2645020, +0xe1a03512,0x11a02432,0x11822511,0x11a01431, +0xe1a04e21,0xe3a07003,0xe3c1120f,0xe0933003, +0xe0b22002,0xe0a11001,0xe1a08101,0xe1888f22, +0xe1a0a102,0xe18aaf23,0xe092200a,0xe0a11008, +0xe2577001,0x11a04204,0x11844e21,0x1afffff1, +0xe1915002,0x03a06000,0x0a000019,0xe3a0700f, +0xe1a05205,0xe1855e26,0xe1a06206,0xe1866e21, +0xe3c1120f,0xe0922002,0xe0a11001,0xe1a08101, +0xe1888f22,0xe0922102,0xe0a11008,0xe2577001, +0x1afffff2,0xe1a05205,0xe1855e26,0xe1a06206, +0xe1866e21,0xe1b01281,0x3a000005,0xe2866001, +0xe1911002,0x03c66001,0xe206100f,0xe351000a, +0x02466001,0xe8bc0008,0xeb000023,0xe2000102, +0xe1800221,0xe8bc0080,0xe18000a7,0xe1800004, +0xe1a01005,0xe1a02006,0xe3a0320e,0xe8bc4fc0, +0xe1a0f007,0xe8bc0030,0xe3150102,0x12644000, +0xe2844001,0xe2145102,0x12644000,0xe92c0030, +0xe3a07901,0xe3a0820a,0xe3a0a000,0xe287b002, +0xebfffb3a,0xeaffffb1,0xe8bc0030,0xe3150102, +0x12644000,0xe2444001,0xe2145102,0x12644000, +0xe92c0030,0xe3a07901,0xe3a0820a,0xe3a0a000, +0xe287b002,0xebfffad8,0xeaffffa4,0xe1a02003, +0xe3a03010,0xe0922002,0x3352020a,0x2242220a, +0xe0b33003,0x3afffffa,0xe1a01622,0xe3530064, +0xa2433064,0xa2811201,0xaafffffb,0xe353000a, +0xa243300a,0xa2811401,0xaafffffb,0xe1811a03, +0xe1b0f00e,0xe3530000,0x1a00000a,0xe1915002, +0x03a0320e,0x03a00000,0x01a0f007,0xe3110102, +0x1affff5d,0xe0922002,0xe0b11001,0xe2433001, +0x5afffffb,0xeaffff58,0xe2000102,0xe1800603, +0xe3800302,0xe18009a1,0xe1a01681,0xe18119a2, +0xe1a02682,0xe3a0320e,0xe1a0f007,0x9392ee8e, +0x921d5d07,0x00003fc3,0xe1915002,0x01b05a00, +0x1200540f,0x1355040f,0x0a0000ac,0xe92c4fd0, +0xe3a07000,0xe3a06000,0xe1a04a00,0xe3a05003, +0xeb00009a,0xe1a04001,0xe3a05008,0xeb000097, +0xe1a04002,0xe3a05008,0xeb000094,0xe1a02007, +0xe1b01006,0xe3a0303e,0xe2833901,0x4a000003, +0xe0922002,0xe0b11001,0xe2433001,0x5afffffb, +0xe3a06000,0xe3a07000,0xe1a04200,0xe3a05004, +0xeb000086,0xe1a09007,0xeb00000c,0xe3100101, +0x1bfffade,0x0bfffa88,0xe24f70a4,0xe8970d00, +0xebfffa85,0xe8bc4fd0,0xe2935001,0xda000090, +0xe1b057a5,0x1a0000a7,0xe2044007,0xeafffd46, +0xe3590014,0xd28f8084,0xd0889209,0xd8990d80, +0xd1b0f00e,0xe92c400f,0xe3a01102,0xe3a02000, +0xe3a00901,0xe2403001,0xe3590000,0x0a000011, +0xe92c000f,0xe2833003,0xe3b0120a,0x3bfffa6a, +0xe1b090a9,0x3afffffc,0xe8bc0d80,0x192c000f, +0xebfffa69,0x0a000007,0xe8bc0d80,0xe92c000f, +0xe1a00007,0xe1a01008,0xe1a0200a,0xe1a0300b, +0xebfffa61,0xeafffff1,0xe1a07000,0xe1a08001, +0xe1a0a002,0xe1a0b003,0xe8bc400f,0xe1b0f00e, +0x00000000,0x80000000,0x00000000,0x00003fff, +0x00000000,0xa0000000,0x00000000,0x00004002, +0x00000000,0xc8000000,0x00000000,0x00004005, +0x00000000,0xfa000000,0x00000000,0x00004008, +0x00000000,0x9c400000,0x00000000,0x0000400c, +0x00000000,0xc3500000,0x00000000,0x0000400f, +0x00000000,0xf4240000,0x00000000,0x00004012, +0x00000000,0x98968000,0x00000000,0x00004016, +0x00000000,0xbebc2000,0x00000000,0x00004019, +0x00000000,0xee6b2800,0x00000000,0x0000401c, +0x00000000,0x9502f900,0x00000000,0x00004020, +0x00000000,0xba43b740,0x00000000,0x00004023, +0x00000000,0xe8d4a510,0x00000000,0x00004026, +0x00000000,0x9184e72a,0x00000000,0x0000402a, +0x00000000,0xb5e620f4,0x80000000,0x0000402d, +0x00000000,0xe35fa931,0xa0000000,0x00004030, +0x00000000,0x8e1bc9bf,0x04000000,0x00004034, +0x00000000,0xb1a2bc2e,0xc5000000,0x00004037, +0x00000000,0xde0b6b3a,0x76400000,0x0000403a, +0x00000000,0x8ac72304,0x89e80000,0x0000403e, +0x00000000,0xad78ebc5,0xac620000,0x00004041, +0xe0977007,0xe0a66006,0xe0978107,0xe0a6af27, +0xe08a6106,0xe1a07008,0xe0977e24,0xe2a66000, +0xe1a04204,0xe2555001,0x1afffff4,0xe1b0f00e, +0xe1a03280,0xe1a038a3,0xe1a026a2,0xe1822981, +0xe1a016a1,0xe1811980,0xe3c11102,0xe2044007, +0xeafffcb9,0xe2144007,0x13540005,0x0a000003, +0xe2000102,0xe3540001,0x0afffda0,0xeafffdda, +0xe2633000,0xe3530040,0xaa000008,0xe2735020, +0x42435020,0x41a02531,0x51a02332,0x51822511, +0xe1a01331,0xe3a03000,0xe2044007,0xeafffca6, +0xe2000102,0xe3a01000,0xe3a02000,0xe1a03e84, +0xe3a04008,0xeafffd7b,0xe2144007,0x0a000003, +0xe3a00000,0xe3540003,0x0afffdae,0xbafffd71, +0xe3a01000,0xe3b02100,0xe2e23902,0xe2000102, +0xe1800003,0xe3540000,0x13a0320a,0xe3a04004, +0xeafffd6c,0xeafffffe,0xe209aa0f,0xe3190008, +0x1a000069,0xe2095007,0xe08c5205,0xe895000f, +0xe1b04d23,0xe28f7000,0x1afffc87,0xe1b04883, +0x12944802,0x0a00002b,0x5a000039,0xe354083e, +0xe20448ff,0x4a000049,0xe1a048a4,0xe2199060, +0x1a00000e,0xe2846002,0xe1922611,0xe3a02101, +0xe0012432,0x000220a1,0xe264401f,0xe1a01431, +0xe3320000,0x12811001,0xe3100102,0x12611000, +0xe0312000,0x4a000049,0xe78d152a,0xeafff805, +0xe3590060,0x1a000005,0xe264401f,0xe1a01431, +0xe3100102,0x12611000,0xe78d152a,0xeafff7fd, +0xe0307d09,0x5afffff7,0xe2846001,0xe1922611, +0x0afffff4,0xe264401f,0xe1a01431,0xe2811001, +0xe3100102,0x12611000,0xe0312000,0x4a000033, +0xe78d152a,0xeafff7ef,0xe31300ff,0x1a000003, +0xe1921001,0x1a000006,0xe78d152a,0xeafff7e9, +0xe1921001,0x0a000029,0xe28f70bc,0xe3a04001, +0xeafffd28,0xe02970a9,0xe3170020,0x0a000010, +0xea000003,0xe2199060,0x0a000008,0xe3590060, +0x0a00000b,0xe0307d09,0x5a000009,0xe3a01001, +0xe3100102,0x12611000,0xe78d152a,0xeafff7d5, +0xe2947802,0x5a000002,0xe3510102,0x03520000, +0x8afffff5,0xe3a01000,0xe78d152a,0xea000016, +0xe354083e,0x03510102,0xe2000102,0x03500102, +0x1a00000a,0xe3520000,0x0affffae,0xe2199060, +0x0a000004,0xe3590060,0x0affffaa,0xe0307d09, +0x5affffa8,0xea000001,0xe3520102,0x9affffa5, +0xe28f7014,0xe3a04001,0xeafffcfe,0xe2091007, +0xe3510006,0xaa000001,0xe78d152a,0xeafff7b5, +0xe2811003,0xe351000a,0x13a01001,0xe2099060, +0x13590020,0x1affffde,0xe78d152a,0xeafff7ad, +0xe3190080,0x1a000034,0xe2097a0f,0xe79d8527, +0xe209b807,0xe08cb62b,0xe1b07008,0x42688000, +0xe3a0a09e,0xe28aadfe,0x03a0a01f,0xe1b0c828, +0x01a08808,0x024aa010,0xe1b0cc28,0x01a08408, +0x024aa008,0xe1b0ce28,0x01a08208,0x024aa004, +0xe1b0cf28,0x01a08108,0x024aa002,0xe1b0cfa8, +0x01a08088,0x024aa001,0xe1b0cc08,0x1a000002, +0xe3a09000,0xe88b0780,0xeafff79d,0xe2199060, +0x1a000008,0xe1b0c08c,0xe208c080,0x000cc0a8, +0xe098800c,0xe2aaa000,0x23a08102,0xe3c880ff, +0xe88b0780,0xeafff792,0xe2399060,0x0afffffa, +0xe027cc89,0xe20cc102,0xe0988bac,0xe2aaa000, +0x23a08102,0xe3a09000,0xe3c880ff,0xe88b0780, +0xeafff787,0xe3190080,0x1afff75f,0xe2097a0f, +0xe79d8527,0xe209b807,0xe08cb62b,0xe1b07008, +0x42688000,0xe3a0a09e,0xe28aadfe,0x03a0a01f, +0xe1b09828,0x01a08808,0x024aa010,0xe1b09c28, +0x01a08408,0x024aa008,0xe1b09e28,0x01a08208, +0x024aa004,0xe1b09f28,0x01a08108,0x024aa002, +0xe1b09fa8,0x01a08088,0x024aa001,0xe3a09000, +0xe88b0780,0xeafff76a,0xe2097a0f,0xe79da527, +0xe3ca801f,0xe3d8881f,0x1a000002,0xe38aa000, +0xe58ca080,0xeafff762,0xe24f700c,0xe3a04001, +0xeafffc94,0xe2097a0f,0xe59ca080,0xe78da527, +0xeafff74c,0xe1b08e09,0x4a000037,0xe08c8c28, +0xe898000f,0xe1b04d23,0xe28f7000,0x1afffbae, +0xe2097807,0xe1a0b003,0xe1a0a002,0xe0208509, +0xe1a09001,0xe08cc627,0xe89c000f,0xe1b04d23, +0xe28f7000,0x1afffba4,0x188c000f,0xe3a04803, +0xe0945883,0x3094588b,0x2a000015,0xe0305008, +0x4a000009,0xe153000b,0x01510009,0x0152000a, +0xe10f7000,0xe2077206,0x33877102,0x13100102, +0x1227720a,0xe168f007,0xeafff72a,0xe19b4003, +0x019a4002,0x01994001,0x0a000003,0xe3100102, +0x1368f102,0x0368f202,0xeafff722,0xe368f206, +0xeafff720,0xe0945883,0x3a000001,0xe1915002, +0x1a000003,0xe094588b,0x3affffe3,0xe199500a, +0x0affffe1,0xe368f201,0xe24fc0c0,0xe24ccc24, +0xe24f7038,0xe3a04001,0xeafffc56,0xe2097807, +0xe2095602,0xe24f6074,0xe0866c28,0xe8960f00, +0xe0288505,0xeaffffca,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x80000000, +0x00000000,0x00003fff,0x00000000,0x80000000, +0x00000000,0x00004000,0x00000000,0xc0000000, +0x00000000,0x00004000,0x00000000,0x80000000, +0x00000000,0x00004001,0x00000000,0xa0000000, +0x00000000,0x00004001,0x00000000,0x80000000, +0x00000000,0x00003ffe,0x00000000,0xa0000000, +0x00000000,0x00004002,0xe2097807,0xe2095602, +0xe24f6e11,0xe0866c28,0xe8960f00,0xe0288505, +0xea00000b,0xe1b08e09,0x4afffff6,0xe08c8c28, +0xe898000f,0xe1b04d23,0xe28f7000,0x1afffb46, +0xe2097807,0xe1a0b003,0xe1a0a002,0xe0208509, +0xe1a09001,0xe08cc627,0xe89c000f,0xe1b04d23, +0xe28f7000,0x1afffb3c,0x188c000f,0xe3a04803, +0xe0945883,0x3094588b,0x2a00000b,0xe0305008, +0x4affffa1,0xe153000b,0x01510009,0x0152000a, +0xe10f7000,0xe2077206,0x33877102,0x13100102, +0x1227720a,0xe168f007,0xeafff6c2,0xe0945883, +0x3a000001,0xe1915002,0x1a000003,0xe094588b, +0x3affffed,0xe199500a,0x0affffeb,0xe368f201, +0xeafff6b8,0xe2099060,0xe3590020,0x03a07209, +0x0a000006,0xe3a00000,0xe08cb42a,0xe28f708c, +0xe2877c05,0xea0000de,0xe357020e,0x0afffff4, +0xe24f8c02,0xe0887c27,0xe08cb42a,0xe8970780, +0xe88b0780,0xeafff6b6,0xe24f8f85,0xe0887c27, +0xe08cb42a,0xe8970700,0xe3a07102,0xe88b0780, +0xeafff6af,0xe24f7e23,0xe0878c28,0xe8980d00, +0xe3a04000,0xea0001f3,0xe24f7f91,0xe0878c28, +0xe8980d00,0xe3a04000,0xea0002a5,0xe3580102, +0x0a00040f,0xe24f7e26,0xe0878c28,0xe8980d00, +0xea00035f,0xe3580102,0x0a00050f,0xe24f7f9e, +0xe0878c28,0xe8980d00,0xea000456,0xe24f7fa3, +0xe0876c26,0xe896000f,0xea000463,0xe3580102, +0x0a0005b3,0xe24f7e2a,0xe0878c28,0xe8980d00, +0xea000546,0xe24f7fad,0xe0876c26,0xe896000f, +0xea000549,0xe24f8fb1,0xe0888c27,0xe08cb42a, +0xe898000f,0xe3570209,0x9a00018e,0xea000143, +0xe24f8e2e,0xe0888c27,0xe898000f,0xea00063a, +0xe24f8e2f,0xe0888c27,0xe898000f,0xea0006dd, +0xe24f8c03,0xe0888c27,0xe898000f,0xea000790, +0xe24f8e31,0xe0888c27,0xe898000f,0xea000858, +0xe3570102,0x13570209,0x1357020e,0x1a0008fe, +0xe24f8e33,0xe0888c27,0xe898000f,0xea000880, +0xe24f8d0d,0xe0888c27,0xe898000f,0xea000992, +0xe24f7e35,0xe0876c26,0xe896000f,0xea000937, +0xe24f7fd7,0xe0878c28,0xe8980d00,0xea0005b6, +0xe3190080,0x1afff638,0xe1b07e09,0xe209aa07, +0x4affff9e,0xe08c7c27,0xe08cb42a,0xe8970780, +0xe88b0780,0xeafff656,0xe3190080,0x1afff62e, +0xe1b07e09,0xe209aa07,0x4affff9a,0xe08c7c27, +0xe08cb42a,0xe8970780,0xe2277102,0xe88b0780, +0xeafff64b,0xe3190080,0x1afff623,0xe1b07e09, +0xe209aa07,0x4affff89,0xe08c7c27,0xe08cb42a, +0xe8970780,0xe3c77102,0xe88b0780,0xeafff640, +0xe1b07e09,0xe209aa07,0x4affff80,0xe08c7c27, +0xe08ca42a,0xe897000f,0xe2098080,0xe3888040, +0xe1580ba3,0x21b04183,0x3a00001d,0xe88a000f, +0xeafff62c,0xe1b07e09,0xe209aa07,0x4affff79, +0xe08c7c27,0xe08ca42a,0xe897000f,0xe2200102, +0xe2098080,0xe3888040,0xe1580ba3,0x21b04183, +0x3a00000f,0xe88a000f,0xeafff61e,0xe1b07e09, +0xe209aa07,0x4affff65,0xe08c7c27,0xe08ca42a, +0xe897000f,0xe3c00102,0xe2098080,0xe3888040, +0xe1580ba3,0x21b04183,0x3a000001,0xe88a000f, +0xeafff610,0xe1a04328,0xe1844d23,0xe24f7018, +0xe3540019,0x0a00006b,0xc3c03102,0xe3140002, +0x1a000034,0xe1b05883,0x12955802,0x0a00001c, +0xe2195060,0x1a00000c,0xe1925c81,0xe2012080, +0x000220a1,0xe0911002,0x23a01102,0xe2a33000, +0xe3a02000,0xe3c110ff,0xe2535dfe,0x9a00001a, +0xe35500ff,0x31a0f007,0xea000012,0xe3550060, +0x11922c01,0x10305d05,0x5afffff4,0xe2911c01, +0x23a01102,0xe2a33000,0xe3a02000,0xe3c110ff, +0xe2535dfe,0x9a00000c,0xe35500ff,0x31a0f007, +0xea000004,0xe31300ff,0x11a0f007,0xe1922001, +0x01a0f007,0xea00000a,0xe3a030ff,0xe3833c7f, +0xe3a01000,0xe3a04004,0xeafffb1a,0xe3750017, +0xda000003,0xe2655009,0xe1a01531,0xe1a01511, +0xe1a0f007,0xe3a03000,0xe3a02000,0xe3a01000, +0xe3a04008,0xeafffb0f,0xe1b05883,0x12955802, +0x0a000022,0xe2195060,0x1a00000f,0xe1b04b02, +0xe2024b01,0x000440a2,0xe0922004,0xe2b11000, +0xe2a33000,0x23a01102,0xe1a025a2,0xe1a02582, +0xe2535b0f,0x9a00001a,0xe2854001,0xe3540b02, +0x31a0f007,0xe3a02000,0xeaffffda,0xe3550060, +0x11b04a82,0x10305d05,0x5afffff2,0xe2922b02, +0xe2b11000,0x23a01102,0xe2a33000,0xe1a025a2, +0xe1a02582,0xe2535b0f,0x9a000009,0xe2854001, +0xe3540b02,0x31a0f007,0xe3a02000,0xeaffffc9, +0xe31300ff,0x11a0f007,0xe1922001,0x01a0f007, +0xeaffffcf,0xe3750034,0xdaffffcd,0xe265500c, +0xe2554020,0x21a02431,0x31a02532,0x21a01412, +0xe1a02512,0xe1a0f007,0xe1a03080,0xe1b03aa3, +0x12834001,0x13340b02,0x0a000023,0xe2833b0f, +0xe2195060,0x1a00000f,0xe1b04201,0xe1a01aa1, +0xe1811580,0xe3811102,0xe2014080,0x000440a1, +0xe0911004,0x23a01102,0xe2a33000,0xe3c110ff, +0xe3a02000,0xe2535dfe,0x9affffab,0xe35500ff, +0x31a0f007,0xeaffffa3,0xe1b04181,0xe1a01aa1, +0xe1811580,0xe3811102,0x13550060,0x10305d05, +0x5afffff1,0xe2911c01,0x23a01102,0xe2a33000, +0xe3a02000,0xe3c110ff,0xe2535dfe,0x9affff9a, +0xe35500ff,0x31a0f007,0xeaffff92,0xe1833203, +0xe1912600,0x01a0f007,0xe1a02581,0xe1a01aa1, +0xe1811580,0xe31300ff,0x11a0f007,0xeaffff94, +0xe3190080,0x1afff54c,0xe1b07e09,0xe209aa07, +0x4afffeb0,0xe08c7c27,0xe08cb42a,0xe897000f, +0xe1b04d23,0xe28f7000,0x1afff9c3,0xe1a04883, +0xe2944802,0x0a00000b,0xe92c4000,0xebfff83c, +0xe8bc4000,0xe28f7014,0x1afffa96,0xe1898629, +0xe3180080,0x0affff4e,0xe3190080,0x1affff81, +0xe88b000f,0xeafff553,0xe1928001,0x0a000003, +0xe3811101,0xe24f701c,0xe3a04001,0xeafffa89, +0xe3a02000,0xe24f702c,0xeaffff66,0xe3190080, +0x1afff529,0xe1b07e09,0xe209aa07,0x4afffec0, +0xe08c8c27,0xe08cb42a,0xe898000f,0xe1b04d23, +0xe28f7000,0x1afff9a0,0x1888000f,0xe1b04883, +0x12944802,0x0a000063,0xe3100102,0x1a000059, +0xe2833901,0xe2433001,0xe1b030a3,0xe1a05002, +0x32414102,0x22414101,0x33a07201,0x23a07202, +0xe3a01102,0xe0955005,0xe0b44004,0xe0216007, +0x31540006,0x20444006,0x20211087,0xe1b070e7, +0x5afffff7,0xe1942005,0x11892629,0x12122080, +0x03a07000,0x0a000018,0xe3a02000,0xe0955005, +0xe0b44004,0xe0a00000,0xe0226007,0xe055a006, +0xe0d48001,0x31b000a0,0x21a0500a,0x21a04008, +0x20222087,0x20211fa7,0xe1b070a7,0x1afffff2, +0xe0955005,0xe0b44004,0xe0b70007,0xe0d5a002, +0xe0d48001,0x31b000a0,0x21a0500a,0x21a04008, +0x22222001,0x23a07102,0xe3a00000,0xe3190702, +0x1a000008,0xe1954004,0x01944007,0x13822001, +0xe28f7044,0xe3530000,0xdaffff29,0xe3190080, +0x0afffef7,0xeaffff2b,0xe2196060,0x1a000015, +0xe0977007,0xe0b55005,0xe0b44004,0x2a000002, +0xe1540001,0x01550002,0x03570101,0xe2b22000, +0xe2b11000,0xe2a33000,0x23a01102,0xe59c5080, +0xe3150010,0x0a000001,0xe88b000f,0xeafff4ed, +0xe3855010,0xe58c5080,0xe3150601,0x0afffff9, +0xe3a00010,0xea0008b4,0xe1945005,0x01955007, +0x13560060,0x0afffff0,0xe1300c86,0x4affffee, +0xe2922001,0xeaffffe9,0xe3a014c5,0xe3a02000, +0xe3a030ff,0xe1833383,0xe3811101,0xe24f705c, +0xe3a04001,0xeafffa13,0xe3530000,0x1a000008, +0xe1914002,0x0affffe3,0xe1b01001,0x4affff95, +0xe0922002,0xe0b11001,0xe2433001,0x5afffffb, +0xeaffff90,0xe1914002,0x1affffee,0xe3100102, +0x0affffd5,0xeaffffe7,0xe3190080,0x1afff4a6, +0xe1b08e09,0x4afffe1a,0xe08c8c28,0xe898000f, +0xe1b04d23,0x0a00000b,0xe28f7024,0xe3540008, +0x1afff91d,0xe3a02000,0xe1a03080,0xe1b03c23, +0x133300ff,0x11a01400,0x13811102,0x12833dfe, +0x0afffa4d,0xe888000f,0xe1a0b003,0xe1a0a002, +0xe1a08001,0xe2004102,0xe2096807,0xe08c6626, +0xe896000f,0xe1340000,0x4a0000b6,0xe1b04d23, +0x0a00000b,0xe28f7024,0xe3540008,0x1afff906, +0xe3a02000,0xe1a03080,0xe1b03c23,0x133300ff, +0x11a01400,0x13811102,0x12833dfe,0x0afffa36, +0xe886000f,0xe3a06802,0xe0965883,0x3096588b, +0x2a000061,0xe053400b,0x4a000046,0xe2745020, +0xda00000e,0xe092243a,0x20822518,0x30922518, +0xe0b11438,0xe1a0851a,0xe1a0a088,0x2a000011, +0xe3190702,0x1a00001d,0xe19aa008,0x13822001, +0xe28f7090,0xe3190080,0x0afffe7d,0xeafffeb1, +0xe3540040,0xc18aa008,0xc3a08000,0xaa00000b, +0xe2444020,0xe2645020,0xe0922438,0xe2b11000, +0xe1a08518,0xe18aa088,0xe2a33000,0x218aa008, +0x21a08f82,0x21a020a2,0x21822f81,0x21a01061, +0xe3190702,0x1a000005,0xe19aa008,0x13822001, +0xe28f7030,0xe3190080,0x0afffe65,0xeafffe99, +0xe2197060,0x1a000014,0xe19aa088,0x00088f82, +0xe0922fa8,0xe2b11000,0xe2a33000,0x23a01102, +0xe0965883,0x0a00003b,0xe59c5080,0xe3150010, +0x0a000003,0xe2099a07,0xe08c9429,0xe889000f, +0xeafff45c,0xe3855010,0xe58c5080,0xe3150601, +0x0afffff7,0xe3a00010,0xea000823,0xe19aa008, +0x13570060,0x0affffef,0xe1300c87,0x4affffed, +0xe2922001,0xeaffffe6,0xe2644000,0xe1a0300b, +0xe1a05001,0xe1a01008,0xe1a08005,0xe1a05002, +0xe1a0200a,0xe1a0a005,0xe2745020,0xdaffffbf, +0xe092243a,0x20822518,0x30922518,0xe0b11438, +0xe1a0851a,0xe1a0a088,0x2affffc2,0xe3190702, +0x1affffce,0xe19aa008,0x13822001,0xe24f70ac, +0xe3190080,0x0afffe2e,0xeafffe62,0xe0965883, +0x1a000001,0xe1925001,0x1a000006,0xe096588b, +0x1affffcc,0xe1a0300b,0xe1a01008,0xe1a0200a, +0xe1915002,0x0affffc7,0xe3811101,0xe24f70ec, +0xe3a04001,0xeafff963,0xe3a030ff,0xe1833383, +0xe3a02000,0xe3a01000,0xe24f7f42,0xe3a04004, +0xeafff95c,0xe1b04d23,0x0a00000b,0xe28f7024, +0xe3540008,0x1afff87c,0xe3a02000,0xe1a03080, +0xe1b03c23,0x133300ff,0x11a01400,0x13811102, +0x12833dfe,0x0afff9ac,0xe886000f,0xe0200589, +0xeaffff73,0xe3190080,0x1afff3ef,0xe1b08e09, +0x4afffd68,0xe08c8c28,0xe898000f,0xe1b04d23, +0x0a00000b,0xe28f7024,0xe3540008,0x1afff866, +0xe3a02000,0xe1a03080,0xe1b03c23,0x133300ff, +0x11a01400,0x13811102,0x12833dfe,0x0afff996, +0xe888000f,0xe1a0b003,0xe1a0a002,0xe1a08001, +0xe2004102,0xe2096807,0xe08c6626,0xe896000f, +0xe1340000,0x4affffd2,0xe1b04d23,0x0a00000b, +0xe28f7024,0xe3540008,0x1afff84f,0xe3a02000, +0xe1a03080,0xe1b03c23,0x133300ff,0x11a01400, +0x13811102,0x12833dfe,0x0afff97f,0xe886000f, +0xe0200589,0xe3a06802,0xe0965883,0x3096588b, +0x2a00006b,0xe053400b,0x01510008,0x0152000a, +0x0a000078,0x3a00004c,0xe3a07000,0xe2745020, +0xda000015,0xe057651a,0xe0d2243a,0x30422518, +0x20522518,0xe0d11438,0x5a00001b,0xe3190702, +0x1a000029,0xe1977006,0x13822001,0xe28f70c0, +0xe3190080,0x0afffdc2,0xeafffdf6,0x13a06102, +0xe3a07001,0xe198500a,0x0a000029,0xe2522001, +0xe2d11000,0x5a00000c,0xea000011,0xe3a06000, +0xe3540040,0xaafffff4,0xe2444020,0xe2645020, +0xe057751a,0xe0d6643a,0x30466518,0x20566518, +0xe0d22438,0xe2d11000,0x4a000005,0xe0977007, +0xe0b66006,0xe0b22002,0xe0b11001,0xe2433001, +0x5afffff9,0xe3190702,0x1a000007,0xe3530000, +0xda00004c,0xe1977006,0x13822001,0xe28f7030, +0xe3190080,0x0afffd9e,0xeafffdd2,0xe2195060, +0x1a00000e,0xe1977086,0x00066f82,0xe0922fa6, +0xe2b11000,0xe2a33000,0x23a01102,0xe1b03003, +0x4a000042,0xe59c5080,0xe3150010,0x0affff3c, +0xe2099a07,0xe08c9429,0xe889000f,0xeafff395, +0xe1977006,0x13550060,0x0afffff3,0xe1300c85, +0x4afffff1,0xe2922001,0xeaffffec,0xe2644000, +0xe2200102,0xe1a0300b,0xe1a05001,0xe1a01008, +0xe1a08005,0xe1a05002,0xe1a0200a,0xe1a0a005, +0xe3a07000,0xe2745020,0xdaffffbf,0xe057651a, +0xe0d2243a,0x30422518,0x20522518,0xe0d11438, +0x5affffc5,0xe3190702,0x1affffd3,0xe1977006, +0x13822001,0xe24f7098,0xe3190080,0x0afffd6c, +0xeafffda0,0xe0965883,0x1a000005,0xe1925001, +0x1affff44,0xe153000b,0x0198500a,0x03a014c1, +0x0affff40,0xe096588b,0x1affffcd,0xe2200102, +0xe1a0300b,0xe1a01008,0xe1a0200a,0xe1915002, +0x0affffc7,0xeaffff37,0xe3a03000,0xe3a02000, +0xe3a01000,0xeaffffc2,0xe3a03000,0xe3a02000, +0xe3a01000,0xe24f7f42,0xe3a04008,0xeafff895, +0xe2633000,0xe2734020,0x42435020,0x41a02531, +0x51a02332,0x51822411,0xe1a01331,0xe3a03000, +0xeaffffb3,0xe3190080,0x1afff32f,0xe1b08e09, +0x4afffcad,0xe08c8c28,0xe898000f,0xe1b04d23, +0x0a00000b,0xe28f7024,0xe3540008,0x1afff7a6, +0xe3a02000,0xe1a03080,0xe1b03c23,0x133300ff, +0x11a01400,0x13811102,0x12833dfe,0x0afff8d6, +0xe888000f,0xe2000102,0xe183b000,0xe1a0a002, +0xe1a08001,0xe2096807,0xe08c6626,0xe896000f, +0xe1b04d23,0x0a00000b,0xe28f7024,0xe3540008, +0x1afff791,0xe3a02000,0xe1a03080,0xe1b03c23, +0x133300ff,0x11a01400,0x13811102,0x12833dfe, +0x0afff8c1,0xe886000f,0xe020000b,0xe3cbb102, +0xe3a06802,0xe3530000,0x135b0000,0x0a00008c, +0xe0965883,0x3096588b,0x2afffee7,0xe3b054ff, +0xe0a3300b,0xe185b425,0xe043392b,0xe19a4088, +0x11924081,0x0a000064,0xe92c4209,0xe1a04821, +0xe1c1500b,0xe1a06822,0xe1c2700b,0xe1c8900b, +0xe1a08828,0xe1cab00b,0xe1a0a82a,0xe0030b96, +0xe0020b94,0xe0010994,0xe0000a97,0xe0933000, +0xe0000a95,0xe0b22000,0xe0000895,0xe0b11000, +0x33a0e000,0x23a0e001,0xe0000996,0xe0922000, +0xe2b11000,0xe2aee000,0xe0000897,0xe0922000, +0xe2b11000,0xe2aee000,0xe18ee803,0xe1a03823, +0xe1833802,0xe1a02822,0xe1822801,0xe1a01821, +0xe181180e,0xe3cee0ff,0xe0000b95,0xe00b0b97, +0xe09eb00b,0xe0b33000,0xe0000896,0xe0b22000, +0xe0000894,0xe0a11000,0xe0000a94,0xe00a0a96, +0xe09aa003,0xe0b22000,0xe2a11000,0xe0000997, +0xe09aa000,0xe0000995,0xe0b22000,0xe2b11000, +0xe8bc4209,0x5a000009,0xe3190702,0x1a000017, +0xe19bb00a,0x13822001,0xe3530000,0xdaffff79, +0xe28f7078,0xe3190080,0x0afffccd,0xeafffd01, +0xe09bb00b,0xe0baa00a,0xe0b22002,0xe0b11001, +0xe2433001,0x5afffff9,0xe3190702,0x1a000007, +0xe3530000,0xdaffff6b,0xe19bb00a,0x13822001, +0xe28f7038,0xe3190080,0x0afffcbd,0xeafffcf1, +0xe2195060,0x1a00001c,0xe19bb08a,0x000aaf82, +0xe0922faa,0xe2b11000,0xe2a33000,0x23a01102, +0xe2934001,0xda00001b,0xe1b047a4,0x1afffe91, +0xe59c5080,0xe3150010,0x0afffe59,0xe2099a07, +0xe08c9429,0xe889000f,0xeafff2b2,0xe19a4088, +0x11a0200a,0x11a01008,0xe2433001,0xe3190702, +0x1affffee,0xe3530000,0xdaffff4a,0xe24f7044, +0xe3190080,0x0afffc9e,0xeafffcd2,0xe19bb00a, +0x13550060,0x0affffe5,0xe1300c85,0x4affffe3, +0xe2922001,0xeaffffde,0xe2633000,0xe3530040, +0xaaffff3c,0xe2734020,0x42435020,0x41a02531, +0x51a02332,0x51822411,0xe1a01331,0xe3a03000, +0xeaffffda,0xe3530000,0x1a000003,0xe1915002, +0x0a00000c,0xe35b0000,0x1affff6c,0xe198500a, +0x1affff6a,0xe0965883,0x33a03000,0x33a02000, +0x33a01000,0x3affffcd,0xe1915002,0x1afffe59, +0xe3a014c2,0xeafffe57,0xe096588b,0x3affffc7, +0xe198500a,0x1afffe48,0xe1a0300b,0xeafffff7, +0xe3190080,0x1afff25c,0xe2096807,0xe08c6626, +0xe896000f,0xe1b04d23,0x0a00000b,0xe28f7024, +0xe3540008,0x1afff6d4,0xe3a02000,0xe1a03080, +0xe1b03c23,0x133300ff,0x11a01400,0x13811102, +0x12833dfe,0x0afff804,0xe886000f,0xe2000102, +0xe183b000,0xe1a0a002,0xe1a08001,0xe1b06e09, +0x4afffbd1,0xe08c6c26,0xe896000f,0xe1b04d23, +0x0a000035,0xe28f7024,0xe3540008,0x1afff6be, +0xe3a02000,0xe1a03080,0xe1b03c23,0x133300ff, +0x11a01400,0x13811102,0x12833dfe,0x0afff7ee, +0xe886000f,0xea000028,0xe3190080,0x1afff232, +0xe1b08e09,0x4afffbb6,0xe08c8c28,0xe898000f, +0xe1b04d23,0x0a00000b,0xe28f7024,0xe3540008, +0x1afff6a9,0xe3a02000,0xe1a03080,0xe1b03c23, +0x133300ff,0x11a01400,0x13811102,0x12833dfe, +0x0afff7d9,0xe888000f,0xe2000102,0xe183b000, +0xe1a0a002,0xe1a08001,0xe2096807,0xe08c6626, +0xe896000f,0xe1b04d23,0x0a00000b,0xe28f7024, +0xe3540008,0x1afff694,0xe3a02000,0xe1a03080, +0xe1b03c23,0x133300ff,0x11a01400,0x13811102, +0x12833dfe,0x0afff7c4,0xe886000f,0xe020000b, +0xe3cbb102,0xe1b04883,0x11b0588b,0x12944802, +0x12955802,0x0a000082,0xe043300b,0xe2833901, +0xe2433001,0xe3a0b000,0xe052500a,0xe0d14008, +0x23a01003,0x2a00000c,0xe1a05002,0xe1a04001, +0xe3a01001,0xe2433001,0xe0955005,0xe0b44004, +0xe2abb000,0xe055700a,0xe0d46008,0x31b0b0ab, +0x21a05007,0x21a04006,0xe0a11001,0xe0955005, +0xe0b44004,0xe2abb000,0xe055700a,0xe0d46008, +0x31b0b0ab,0x21a05007,0x21a04006,0xe0a11001, +0xe0955005,0xe0b44004,0xe2abb000,0xe055700a, +0xe0d46008,0x31b0b0ab,0x21a05007,0x21a04006, +0xe0a11001,0xe0955005,0xe0b44004,0xe2abb000, +0xe055700a,0xe0d46008,0x31b0b0ab,0x21a05007, +0x21a04006,0xe0b11001,0x3affffda,0xe1942005, +0x11892629,0x12122080,0x0a000025,0xe3a02001, +0xe0955005,0xe0b44004,0xe2abb000,0xe055700a, +0xe0d46008,0x31b0b0ab,0x21a05007,0x21a04006, +0xe0a22002,0xe0955005,0xe0b44004,0xe2abb000, +0xe055700a,0xe0d46008,0x31b0b0ab,0x21a05007, +0x21a04006,0xe0a22002,0xe0955005,0xe0b44004, +0xe2abb000,0xe055700a,0xe0d46008,0x31b0b0ab, +0x21a05007,0x21a04006,0xe0a22002,0xe0955005, +0xe0b44004,0xe2abb000,0xe055700a,0xe0d46008, +0x31b0b0ab,0x21a05007,0x21a04006,0xe0b22002, +0x3affffda,0xe3190702,0x1a000007,0xe1954004, +0x13822001,0xe3530000,0xdafffe62,0xe28f7048, +0xe3190080,0x0afffbb6,0xeafffbea,0xe2197060, +0x1a000014,0xe0955005,0xe0b44004,0x2a000002, +0xe1540008,0x0155000a,0x011500a2,0xe2b22000, +0xe2b11000,0xe2a33000,0x23a01102,0xe2934001, +0xdaffff10,0xe1b047a4,0x1afffd86,0xe59c5080, +0xe3150010,0x0afffd4e,0xe2099a07,0xe08c9429, +0xe889000f,0xeafff1a7,0xe1945005,0x13570060, +0x0afffff1,0xe1300c87,0x4affffef,0xe2922001, +0xeaffffea,0xe1b04883,0x1a000013,0xe1915002, +0x1a00000d,0xe1b0588b,0x0198600a,0x03a014c3, +0x03a030ff,0x01833383,0x0afffd6a,0xe2955802, +0x1affffe8,0xe198600a,0x0affffe6,0xe1a01008, +0xe1a0200a,0xe1a0300b,0xeafffd62,0xe0922002, +0xe0b11001,0xe2433001,0x5afffffb,0xe1b0588b, +0x1a000010,0xe198600a,0x1a00000a,0xe2944802, +0x1a000001,0xe1916002,0x1afffd56,0xe3a01000, +0xe3a02000,0xe3a030ff,0xe1833383,0xe24f70bc, +0xe3a04002,0xeafff6b7,0xe09aa00a,0xe0b88008, +0xe24bb001,0x5afffffb,0xe2956802,0x12946802, +0x1affff50,0xe2946802,0x1a000006,0xe1916002, +0x1afffd44,0xe2956802,0x1affffbf,0xe198600a, +0x03a01331,0x0afffd3f,0xe198600a,0x0afffe09, +0xe1a01008,0xe1a0200a,0xe1a0300b,0xeafffd39, +0xe3190080,0x1afff144,0xe2096807,0xe08c6626, +0xe896000f,0xe1b04d23,0xe28f7000,0x1afff5be, +0x1886000f,0xe2000102,0xe183b000,0xe1a0a002, +0xe1a08001,0xe1b06e09,0x4afffacd,0xe08c6c26, +0xe896000f,0xe1b04d23,0xe28f7000,0x1afff5b2, +0x1886000f,0xea000014,0xe3190080,0x1afff12e, +0xe1b08e09,0x4afffabc,0xe08c8c28,0xe898000f, +0xe1b04d23,0xe28f7000,0x1afff5a7,0x1888000f, +0xe2000102,0xe183b000,0xe1a0a002,0xe1a08001, +0xe2096807,0xe08c6626,0xe896000f,0xe1b04d23, +0xe28f7000,0x1afff59c,0x1886000f,0xe1a0700b, +0xe3cbb102,0xe1b04883,0x12944802,0x11b0588b, +0x12955802,0x0a00004e,0xe92c4200,0x5a000035, +0xe24b4c3f,0xe24440fe,0xe3540010,0xca00002a, +0xe19a5418,0x1a00002f,0xe2649020,0xe1a09938, +0xe0000f89,0xe92c0080,0xe3a08102,0xe3a0a000, +0xe3a07901,0xe257b001,0xe92c0d80,0x3bfff2b6, +0xe1b090a9,0x3afffffc,0xe8bc0d80,0x192c000f, +0xebfff2b5,0xe2834001,0x0a000009,0xe3540902, +0xaa000010,0xe8bc0d80,0xe92c000f,0xe1a00007, +0xe1a01008,0xe1a0200a,0xe1a0300b,0xebfff2aa, +0xeaffffee,0xe8bc0080,0xe3170102,0x1bfff2f3, +0xe8bc4200,0xe2934001,0xdafffe6a,0xe1b047a4, +0x1afffce0,0xea0000cb,0xe28cc010,0xe8bc4280, +0xe3170102,0x1afffda3,0xeafffcda,0xe3540040, +0x2a000012,0xe2545020,0x21b0651a,0x0a000010, +0xe19a6418,0x0a00000e,0xe3100102,0x1a00000e, +0xe92c0001,0xe3a00000,0xe92c0d80,0xe3c99601, +0xeb0000e1,0xe8bc0d80,0xebfff28b,0xeb000166, +0xe8bc4201,0x0a0000b3,0xe28f7e2f,0xeafff629, +0x13b05100,0x33a00000,0xeafffff0,0xe8bc4200, +0xe3a014c7,0xe3a02000,0xe3a030ff,0xe1833383, +0xeafffcb8,0xe3540000,0x1a00001e,0xe3530000, +0x0a000002,0xe1916002,0x1afffcb2,0xea000001, +0xe1916002,0x1a000010,0xe1b0588b,0x1a000006, +0xe198600a,0x03a01102,0x03a02000,0x03a00000, +0x03a03901,0x02433001,0xea000096,0xe2955802, +0x1a000094,0xe198600a,0x0a000092,0xe1a01008, +0xe1a0200a,0xe1a0300b,0xeafffc9e,0xe0922002, +0xe0b11001,0xe2433001,0x5afffffb,0xe1b0588b, +0x12955802,0x1affff8f,0xe35b0000,0x0a000008, +0xe1a01008,0xe1a0200a,0xe1a00007,0xe1a0300b, +0xe198600a,0x1afffc8f,0xe3100102,0x13a03000, +0xea00007c,0xe198600a,0x0affffdd,0xe09aa00a, +0xe0b88008,0xe24bb001,0x5afffffb,0xe92c4200, +0xeaffffb4,0xe3190080,0x1afff08f,0xe1b08e09, +0x4afffa4e,0xe08c8c28,0xe898000f,0xe1b04d23, +0xe28f7000,0x1afff508,0x1888000f,0xe2000102, +0xe183b000,0xe1a0a002,0xe1a08001,0xe2096807, +0xe08c6626,0xe896000f,0xe1b04d23,0xe28f7000, +0x1afff4fd,0x1886000f,0xe1a0700b,0xe3cbb102, +0xe1b04883,0x12944802,0x11b0588b,0x12955802, +0x0a00000a,0xe92c400f,0xe92c0d80,0xebfff27f, +0xebfff36f,0xe8bc0d80,0xebfff227,0xe2200102, +0xe8bc0d80,0xebfff178,0xe8bc4000,0xea00004d, +0xe1b04883,0x1a000010,0xe1915002,0x1a00000a, +0xe1b0588b,0x0198600a,0x0a000013,0xe2955802, +0x1a000015,0xe198600a,0x0a000013,0xe1a01008, +0xe1a0200a,0xe1a0300b,0xeafffc4e,0xe0922002, +0xe0b11001,0xe2433001,0x5afffffb,0xe1b0588b, +0x1a000012,0xe198600a,0x1a00000c,0xe2944802, +0x1a000001,0xe1916002,0x1afffc42,0xe3a01333, +0xe3b02100,0xe2e23902,0xeafffc3e,0xe3a00000, +0xe3a01000,0xe3a02000,0xe3a03000,0xea000029, +0xe09aa00a,0xe0b88008,0xe24bb001,0x5afffffb, +0xe2956802,0x12946802,0x1affffc9,0xe2946802, +0x1a000008,0xe1916002,0x1afffc2e,0x03a01333, +0xe2956802,0x1afffc2b,0xe198600a,0x11a01008, +0x11a0200a,0xeafffc27,0xe198600a,0x0a000015, +0xe1a01008,0xe1a0200a,0xe1a0300b,0xeafffc21, +0xe3190080,0x1afff02c,0xe1b07e09,0x4afff9cb, +0xe08c8c27,0xe898000f,0xe1b04d23,0xe28f7000, +0x1afff4a5,0x1888000f,0xe1b04883,0x12944802, +0x0a00001d,0xe3100102,0x1a000016,0xe92c4000, +0xeb000029,0xe8bc4000,0xe3190702,0x1a000005, +0xe28f7018,0xe3530000,0xdafffa5d,0xe3190080, +0x0afffa2b,0xeafffa5f,0xe3530000,0xba000006, +0xe59c5080,0xe3150010,0x0afffbd1,0xe2099a07, +0xe08c9429,0xe889000f,0xeafff02a,0xe3730040, +0xcafffcce,0xeafffa4e,0xe3a014c6,0xe3a02000, +0xe3a030ff,0xe1833383,0xeafffbf6,0xe3530000, +0x1a000008,0xe1914002,0x0afffff6,0xe1b01001, +0x4affffdb,0xe0922002,0xe0b11001,0xe2433001, +0x5afffffb,0xeaffffd6,0xe1914002,0x1afffbe9, +0xe3100102,0x0affffe1,0xeaffffea,0xe28f4f52, +0xe8940500,0xe1510008,0x0152000a,0xe1a0a0a2, +0xe18aaf81,0xe1a080a1,0xe3888102,0xe3a0b0fe, +0xe18bb30b,0xe043400b,0x92444001,0xe92c4210, +0xe1a0300b,0x8a000005,0xe3c88101,0xe0922002, +0xe0b11001,0xe2433001,0x5a000003,0xea000008, +0xe3a00102,0xe2722000,0xe2f11000,0x03520000, +0x0a000035,0xe0922002,0xe0b11001,0xe2433001, +0x5afffff9,0xe3a07000,0xebfff1e0,0xe92c000f, +0xebfff185,0xe92c000f,0xe28f90c4,0xe8b90d00, +0xebfff125,0xe89c0d80,0xebfff183,0xe8b90d00, +0xebfff0d8,0xe89c0d80,0xebfff17f,0xe8b90d00, +0xebfff11d,0xe89c0d80,0xe92c000f,0xe3a00102, +0xe8b9000e,0xebfff178,0xe8b90d00,0xebfff0cd, +0xe28c4010,0xe8940d80,0xebfff173,0xe8b90d00, +0xebfff111,0xe8bc0d80,0xebfff1c4,0xe8bc0d80, +0xebfff16d,0xe89c0d80,0xebfff16b,0xe8bc0d80, +0xebfff0bd,0xe8bc0010,0xebfff25e,0xe92c000f, +0xe3a00000,0xe8b9000e,0xebfff163,0xe8bc0d80, +0xebfff0b5,0xe8bc0200,0xe3190601,0xe28f7074, +0x18970d00,0x1bfff15c,0xe8bc8000,0xe3a00000, +0xe3a03000,0xe28f9050,0xeaffffed,0xb504f333, +0xf9de6484,0x8eac025b,0x3e7076bb,0x00004004, +0x9c041fd0,0xa933ef60,0x00004007,0xc05ff4e0, +0x6c83bb96,0x00004008,0xca20ad9a,0xb5e946e9, +0x00003ffe,0x83125100,0xb57f6509,0x00004003, +0x803ff895,0x9dacd228,0x00004005,0xb17217f7, +0xd1cf79ac,0x00003ffe,0xde5bd8a9,0x37287195, +0x00003ffd,0xe3190080,0x1affef83,0xe1b07e09, +0x4afff926,0xe08c8c27,0xe898000f,0xe1b04d23, +0xe28f7000,0x1afff3fc,0x1888000f,0xe1a04883, +0xe2944802,0x0a000005,0xe92c4000,0xeb00000a, +0xe8bc4000,0x0affff57,0xe24f7d0a,0xeafff4cd, +0xe1914002,0x1afffb63,0xe3100102,0x0affff5b, +0xe3a00000,0xe3a03000,0xeaffff58,0xe28f4f6e, +0xe3100102,0x128f4f72,0xe8b40d00,0xe153000b, +0x01510008,0x0152000a,0x8a00005d,0xe8940d00, +0xe153000b,0x01510008,0x0152000a,0x3a000052, +0xe92c421f,0xe28f9e1b,0xe3a07000,0xe8b90d00, +0xebfff111,0xebfff238,0xe3170102,0x12644000, +0xe58c4010,0xe92c0d80,0xe3a00000,0xe8b9000e, +0xebfff109,0xe8bc0d80,0xe92c000f,0xe8b9000e, +0xe3a00102,0xebfff104,0xe92c000f,0xe28c4020, +0xe894000f,0xebfff20c,0xe3170102,0x0bfff09e, +0x1bfff054,0xe1a0400c,0xe92c000f,0xe894000f, +0xebfff04d,0xe8bc0d80,0xebfff04b,0xe28cc010, +0xe8bc0d80,0xebfff048,0xe88c000f,0xebfff0ee, +0xe92c000f,0xe3a07000,0xe8b90d00,0xebfff0ee, +0xe8b90d00,0xebfff043,0xe89c0d80,0xebfff0ea, +0xe8b90d00,0xebfff03f,0xe89c0d80,0xebfff0e6, +0xe8b90d00,0xebfff03b,0xe89c0d80,0xe92c000f, +0xe3a00000,0xe8b9000e,0xebfff0df,0xe8b90d00, +0xebfff034,0xe28c7010,0xe8970d80,0xebfff0da, +0xe8b90d00,0xebfff02f,0xe28c7020,0xe8970d80, +0xebfff0d5,0xe8bc0d80,0xe92c000f,0xe2200102, +0xebfff025,0xe1a07000,0xe1a08001,0xe1a0a002, +0xe1a0b003,0xe8bc000f,0xebfff120,0xe8b90d00, +0xebfff020,0xe28cc020,0xe8bc4210,0xe2844001, +0xe0833004,0xe3b04000,0xe1a0f00e,0xe3b00000, +0xe3a01102,0xe3a02000,0xe3a03901,0xe2433001, +0xe1a0f00e,0xe3100102,0xe3a00000,0xe3a01000, +0xe3a02000,0x13a03000,0x13a04008,0x03a030ff, +0x01833383,0x03b04004,0xe1a0f00e,0xb17217f7, +0xd1cf79ab,0x0000400c,0x80000000,0x00000000, +0x00003fbe,0xb21dfe7f,0x09e2baa9,0x0000400c, +0x80000000,0x00000000,0x00003fbe,0xb8aa3b29, +0x5c17f0bc,0x00003fff,0xde8082e3,0x08654362, +0x00003ff2,0xb1800000,0x00000000,0x00003ffe, +0xc99b1867,0x2822a93e,0x00003fea,0xa57862e1, +0x46a6fb39,0x00003ff4,0xe8b9428e,0xfecff592, +0x00003ffa,0x80000000,0x00000000,0x00003ffe, +0x845a2157,0x3490f106,0x00003ff0,0xf83a5f91, +0x50952c99,0x00003ff7,0x80000000,0x00000000, +0x00003ffd,0x80000000,0x00000000,0x00003ffe, +0xe3190080,0x1affeecc,0xe1b07e09,0x4afff873, +0xe08c8c27,0xe898000f,0xe1b04d23,0xe28f7000, +0x1afff345,0x1888000f,0xe1a04883,0xe2944802, +0x0a000006,0xe92c4000,0xeb000007,0xe8bc4000, +0x0afffea0,0xe24f705c,0xe2477c05,0xeafff415, +0xe1914002,0x03a01332,0xeafffaaa,0xe28f4f8f, +0xe8b40d00,0xe153000b,0x01510008,0x0152000a, +0x8a00006c,0xe1b01001,0x5a000063,0xe92c421f, +0xe3190601,0xe28f9e22,0xe3a07000,0xe8b90d00, +0xebfff061,0xebfff188,0x1b00006d,0xe58c4010, +0xe92c0d80,0xe3a00000,0xe8b9000e,0xebfff05a, +0xe8bc0d80,0xe92c000f,0xe8b9000e,0xe3a00102, +0xebfff055,0xe92c000f,0xe28c4020,0xe894000f, +0xebfff15d,0xe3170102,0x0bffefef,0x1bffefa5, +0xe1a0400c,0xe92c000f,0xe894000f,0xebffef9e, +0xe8bc0d80,0xebffef9c,0xe28cc010,0xe8bc0d80, +0xebffef99,0xe3a04c3f,0xe38440df,0xe1530004, +0xba000037,0xe88c000f,0xebfff03b,0xe92c000f, +0xe3a07000,0xe8b90d00,0xebfff03b,0xe8b90d00, +0xebffefd9,0xe89c0d80,0xebfff037,0xe8b90d00, +0xebffef8c,0xe89c0d80,0xebfff033,0xe8b90d00, +0xebffefd1,0xe89c0d80,0xebfff02f,0xe8b90d00, +0xebffef84,0xe89c0d80,0xe92c000f,0xe3a00102, +0xe8b9000e,0xebfff028,0xe8b90d00,0xebffef7d, +0xe28c7010,0xe8970d80,0xebfff023,0xe8b90d00, +0xebffefc1,0xe28c7010,0xe8970d80,0xebfff01e, +0xe28c7020,0xe8970d80,0xebfff01b,0xe28c7020, +0xe8970d80,0xebffef6c,0xe8bc0d80,0xe28cc020, +0xe8bc0010,0xe3140001,0x12200102,0x1bfff1a7, +0xe29b4902,0x4a000018,0xe35b0000,0x0198400a, +0x0a000015,0xebfff061,0xe8bc4200,0xe3b04000, +0xe1a0f00e,0xe24cc010,0xe3a07000,0xe3a08102, +0xe3b0a100,0xe2eab901,0xeaffffeb,0xe1914002, +0x0affff99,0xe2433001,0xe0922002,0xe0b11001, +0x5afffffb,0xeaffff94,0xe3a01332,0xe3b02100, +0xe2f23902,0xe3a04001,0xe1a0f00e,0xe3a01000, +0xe3b02100,0xe2f33902,0xe3a04004,0xe8bc4200, +0xe1a0f00e,0xe2844001,0xe35b0000,0x03a08102, +0xe3a06901,0x0246b002,0x01a0f00e,0xe2466002, +0xe04b6006,0xe3a05102,0xe153000b,0x01510008, +0x0152000a,0x20888635,0x21a0f00e,0xe0588635, +0x51a08088,0x524bb001,0xe2444001,0xe1a0f00e, +0xc90fdaa2,0x00000000,0x0000401d,0xa2f9836e, +0x4e44152a,0x00003ffe,0x95777a5c,0xf72cece6, +0x00003fed,0xc9100000,0x00000000,0x00003fff, +0x85bba783,0xb3c748a9,0x00003fea,0xa37b24c8, +0x4a42092e,0x00003ff3,0xd23cf50b,0xf10aca84, +0x00003ff9,0xeef5823f,0xdecea969,0x00003ffd, +0x80000000,0x00000000,0x00003fff,0x95d5b975, +0x16391da8,0x00003fef,0xe0741531,0xdd56f650, +0x00003ff6,0x8895af2a,0x6847fcd5,0x00003ffc, +0xe3190080,0x1affee00,0xe1b07e09,0x4afff7ab, +0xe08c8c27,0xe898000f,0xe1b04d23,0xe28f7000, +0x1afff279,0x1888000f,0xe1a04883,0xe2944802, +0x0a000015,0xe1c00589,0xe92c4000,0xe1914002, +0x12433001,0xebffff38,0x1a000012,0xe92c000f, +0xebffefa1,0xe3a08102,0xe3b0a100,0xe2eab901, +0xebffeef8,0xe1a07000,0xe1a08001,0xe1a0a002, +0xe1a0b003,0xe8bc000f,0xebffeff0,0xe1914002, +0x12833001,0xe8bc4000,0xeafffdc2,0xe1914002, +0x03a014c9,0xeafff9cf,0xe8bc4000,0xe3540004, +0x03a03000,0x03a00000,0x0afffdba,0xe3a014c9, +0xe3b02100,0xe2e23902,0xeafff9c6,0xe3190080, +0x1affedd1,0xe1b07e09,0x4afff780,0xe08c8c27, +0xe898000f,0xe1b04d23,0xe28f7000,0x1afff24a, +0x1888000f,0xe1b04883,0x0a00006b,0x52944802, +0x4a000072,0xe92c4201,0xe3a00000,0xe3a05901, +0xe2455002,0xe1530005,0xaa000009,0xe2094501, +0xe92c0010,0xe3a04901,0xe2444021,0xe1530004, +0xba000049,0xe92c000f,0xebffef6b,0xe92c000f, +0xea000012,0xe2094501,0xe2244501,0xe92c0010, +0xe3a00102,0xe3a08102,0xe3b0a100,0xe2eab901, +0xebffeebc,0xe1914002,0x0a00003b,0xe2433001, +0xe24cc010,0xe92c000f,0xebfff01c,0xe2200102, +0xe2833001,0xe28c4010,0xe884000f,0xe89c000f, +0xe28f9f59,0xe8b90d00,0xebffeef7,0xe89c0d80, +0xebffef55,0xe8b90d00,0xebffeeaa,0xe89c0d80, +0xebffef51,0xe8b90d00,0xebffeeef,0xe89c0d80, +0xebffef4d,0xe8b90d00,0xebffeea2,0xe89c0d80, +0xebffef49,0xe8b90d00,0xebffeee7,0xe89c0d80, +0xe92c000f,0xe3a00102,0xe8b9000e,0xebffef42, +0xe8b90d00,0xebffee97,0xe28c7010,0xe8970d80, +0xebffef3d,0xe8b90d00,0xebffeedb,0xe28c7010, +0xe8970d80,0xebffef38,0xe8b90d00,0xebffee8d, +0xe28c7010,0xe8970d80,0xebffef33,0xe8b90d00, +0xebffeed1,0xe28c7010,0xe8970d80,0xebffef2e, +0xe8bc0d80,0xe28cc010,0xebffef80,0xe89c0d80, +0xebffef29,0xe8bc0d80,0xebffee7b,0xe8bc0230, +0xe3190501,0x0a000008,0xe3150102,0x028f5c01, +0x128f5f46,0xe0855924,0x02200102,0xe8950d00, +0xebffee74,0xe8bc4000,0xeafffd46,0xe3150102, +0xe28f50dc,0xe0855924,0xe8950d00,0xebffee6d, +0x12200102,0xe8bc4000,0xeafffd3e,0xe1915002, +0x0affff93,0xe1b01001,0x4affff91,0xe2433001, +0xe0922002,0xe0b11001,0x5afffffb,0xeaffff8c, +0xe2f35901,0x01925081,0x0affff89,0xe2944802, +0x1a000001,0xe1914002,0x1afff93e,0xe3a014ca, +0xe3b02100,0xe2e23902,0xeafff93a,0xbe974377, +0xcc30f9e6,0x00004003,0x96f3e4b2,0xc8e37cbc, +0x00004006,0xbeee77e2,0xb5423cf3,0x00004007, +0xd0927880,0xf5c2170b,0x00004007,0xa43601f1, +0x5c3e6196,0x00004006,0xb25dedaf,0x30f3242c, +0x00003ffe,0xa270bb27,0x61c93957,0x00004002, +0x9ec1654d,0x36d4f820,0x00004004,0xe4d539b0, +0x56a451ad,0x00004004,0xdaf2ad41,0xd05311c4, +0x00004003,0x00000000,0x00000000,0x00000000, +0x00000000,0xc90fdaa2,0x2168c235,0x00003fff, +0xc90fdaa2,0x2168c235,0x00004000,0x00000000, +0xc90fdaa2,0x2168c235,0x00003fff,0xe3190080, +0x1affed19,0xe2096807,0xe08c6626,0xe896000f, +0xe1b04d23,0xe28f7000,0x1afff193,0x1886000f, +0xe2000102,0xe183b000,0xe1a0a002,0xe1a08001, +0xe1b06e09,0x4afff6c9,0xe08c6c26,0xe896000f, +0xe1b04d23,0xe28f7000,0x1afff187,0x1886000f, +0xe1a0700b,0xe3cbb102,0xe1b04883,0x12944802, +0x11b0588b,0x12955802,0x192c4281,0x1bffef0b, +0x1a00004e,0xe1b04883,0x1a000010,0xe1915002, +0x1a00000a,0xe1b0588b,0x0198600a,0x0a00001f, +0xe2955802,0x1a000016,0xe198600a,0x0a000014, +0xe1a01008,0xe1a0200a,0xe1a0300b,0xeafff8e1, +0xe0922002,0xe0b11001,0xe2433001,0x5afffffb, +0xe1b0588b,0x1a000019,0xe198600a,0x1a000013, +0xe2944802,0x1a000001,0xe1916002,0x1afff8d5, +0xe1a04000,0xe1a05007,0xe28f0fbd,0xe890000e, +0xea00008c,0xe1a04000,0xe1a05007,0xe3a00000, +0xe3a01000,0xe3a02000,0xe3a03000,0xea00007d, +0xe3a014cb,0xe3b02100,0xe2e23902,0xeafff8c5, +0xe09aa00a,0xe0b88008,0xe24bb001,0x5afffffb, +0xe2956802,0x12946802,0x1affffca,0xe2946802, +0x1a000006,0xe1916002,0x1afff8ba,0xe2956802, +0x1affffe2,0xe198600a,0x03a014cb,0x0afff8b5, +0xe198600a,0x0affffe2,0xe1a01008,0xe1a0200a, +0xe1a0300b,0xeafff8af,0xe3190080,0x1affecba, +0xe1b07e09,0x4afff671,0xe08c8c27,0xe898000f, +0xe1b04d23,0xe28f7000,0x1afff133,0x1888000f, +0xe1b04883,0x12944802,0x0a000060,0xe92c4281, +0xe3b00100,0xe2f34901,0xdbffeeb0,0xd3a04002, +0xc3a04000,0xe28f9d06,0xe8b90d00,0xe153000b, +0x01510008,0x0152000a,0xc2844001,0xe92c0010, +0xda00000d,0xe92c000f,0xe8990d00,0xebffedad, +0xe8bc0d80,0xe92c000f,0xe3a00000,0xe8b9000e, +0xebffee51,0xe3a08102,0xe3b0a100,0xe2eab901, +0xebffeded,0xe8bc0d80,0xebffeea0,0xe3a04901, +0xe2444021,0xe1530004,0xba00002c,0xe92c000f, +0xebffee41,0xe92c000f,0xe28f9f49,0xe8b90d00, +0xebffed98,0xe89c0d80,0xebffee3f,0xe8b90d00, +0xebffed94,0xe89c0d80,0xebffee3b,0xe8b90d00, +0xebffed90,0xe89c0d80,0xebffee37,0xe8b90d00, +0xebffed8c,0xe89c0d80,0xe92c000f,0xe3a00102, +0xe8b9000e,0xebffee30,0xe8b90d00,0xebffedce, +0xe28c7010,0xe8970d80,0xebffee2b,0xe8b90d00, +0xebffedc9,0xe28c7010,0xe8970d80,0xebffee26, +0xe8b90d00,0xebffedc4,0xe28c7010,0xe8970d80, +0xebffee21,0xe8bc0d80,0xe28cc010,0xebffee73, +0xe89c0d80,0xebffee1c,0xe8bc0d80,0xebffed6e, +0xe28f90dc,0xe8bc0010,0xe0200f04,0xe0899204, +0xe8990d00,0xebffed6b,0xe8bc4230,0xe3190601, +0x10200004,0x1afffc3b,0xe3150102,0x0a000005, +0xe92c4010,0xe2200102,0xe24f7d0d,0xe8970d00, +0xebffed60,0xe8bc4010,0xe0200004,0xeafffc31, +0xe3530000,0x0afffc2f,0xe1914002,0x1afff83d, +0xe28f009c,0xe890000e,0xeafffc2a,0x8930a2f4, +0xf66ab18a,0x00003ffd,0xddb3d742,0xc265539e, +0x00003fff,0xf0624f0a,0x56388310,0x00004002, +0xee505190,0x6d1eb4e8,0x00004004,0xac509020, +0x5b6d243b,0x00004005,0xa443e5e6,0x24ad4b90, +0x00004004,0xd66bd6cd,0x8c3de934,0x00003ffe, +0x87e9fae4,0x6b531a29,0x00004002,0xa40bfdcf, +0x15e65691,0x00004003,0xdb053288,0x30e70eb4, +0x00004002,0x00000000,0x00000000,0x00000000, +0x00000000,0x860a91c1,0x6b9b2c23,0x00003ffe, +0x00000000,0xc90fdaa2,0x2168c235,0x00003fff, +0x00000000,0x860a91c1,0x6b9b2c23,0x00003fff, +0xe92d5001,0xe24fc05c,0xe24ccc50,0xe3a00807, +0xe58c0080,0xe8bd9001,0xe1a00000,0xe3100001, +0x128f0e15,0x1a00000a,0xe3100004,0x128f0f47, +0x1a000007,0xe3100002,0x128f00e0,0x1a000004, +0xe3100008,0x128f00a8,0x1a000001,0xe28f0070, +0xeaffffff,0xe28f101c,0xe14fb000,0xe8bd07f8, +0xe8a107f8,0xe8bd07f8,0xe24aa004,0xe8a10ff8, +0xe28f1000,0xef000071,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x00002278, +0xffffffff,0x80000204,0x616f6c46,0x676e6974, +0x696f5020,0x4520746e,0x70656378,0x6e6f6974, +0x49203a20,0x6178656e,0x52207463,0x6c757365, +0x00000074,0x80000203,0x616f6c46,0x676e6974, +0x696f5020,0x4520746e,0x70656378,0x6e6f6974, +0x55203a20,0x7265646e,0x776f6c66,0x00000000, +0x80000202,0x616f6c46,0x676e6974,0x696f5020, +0x4520746e,0x70656378,0x6e6f6974,0x44203a20, +0x64697669,0x79422065,0x72655a20,0x0000006f, +0x80000201,0x616f6c46,0x676e6974,0x696f5020, +0x4520746e,0x70656378,0x6e6f6974,0x4f203a20, +0x66726576,0x00776f6c,0x80000200,0x616f6c46, +0x676e6974,0x696f5020,0x4520746e,0x70656378, +0x6e6f6974,0x49203a20,0x6c61766e,0x4f206469, +0x61726570,0x6e6f6974,0x00000000,0xfefefeff,0} ; + +unsigned long fpesize = 0x00005300 ; diff --git a/sim/arm/arminit.c b/sim/arm/arminit.c new file mode 100644 index 00000000000..9ef7b1cbaca --- /dev/null +++ b/sim/arm/arminit.c @@ -0,0 +1,294 @@ +/* arminit.c -- ARMulator initialization: ARM6 Instruction Emulator. + Copyright (C) 1994 Advanced RISC Machines Ltd. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "armdefs.h" +#include "armemu.h" + +/***************************************************************************\ +* Definitions for the emulator architecture * +\***************************************************************************/ + +void ARMul_EmulateInit(void) ; +ARMul_State *ARMul_NewState(void) ; +void ARMul_Reset(ARMul_State *state) ; +ARMword ARMul_DoCycle(ARMul_State *state) ; +unsigned ARMul_DoCoPro(ARMul_State *state) ; +ARMword ARMul_DoProg(ARMul_State *state) ; +ARMword ARMul_DoInstr(ARMul_State *state) ; +void ARMul_Abort(ARMul_State *state, ARMword address) ; + +unsigned ARMul_MultTable[32] = {1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9, + 10,10,11,11,12,12,13,13,14,14,15,15,16,16,16} ; +ARMword ARMul_ImmedTable[4096] ; /* immediate DP LHS values */ +char ARMul_BitList[256] ; /* number of bits in a byte table */ + +/***************************************************************************\ +* Call this routine once to set up the emulator's tables. * +\***************************************************************************/ + +void ARMul_EmulateInit(void) +{unsigned long i, j ; + + for (i = 0 ; i < 4096 ; i++) { /* the values of 12 bit dp rhs's */ + ARMul_ImmedTable[i] = ROTATER(i & 0xffL,(i >> 7L) & 0x1eL) ; + } + + for (i = 0 ; i < 256 ; ARMul_BitList[i++] = 0 ) ; /* how many bits in LSM */ + for (j = 1 ; j < 256 ; j <<= 1) + for (i = 0 ; i < 256 ; i++) + if ((i & j) > 0 ) + ARMul_BitList[i]++ ; + + for (i = 0 ; i < 256 ; i++) + ARMul_BitList[i] *= 4 ; /* you always need 4 times these values */ + +} + +/***************************************************************************\ +* Returns a new instantiation of the ARMulator's state * +\***************************************************************************/ + +ARMul_State *ARMul_NewState(void) +{ARMul_State *state ; + unsigned i, j ; + + state = (ARMul_State *)malloc(sizeof(ARMul_State)) ; + memset (state, 0, sizeof (ARMul_State)); + + state->Emulate = RUN ; + for (i = 0 ; i < 16 ; i++) { + state->Reg[i] = 0 ; + for (j = 0 ; j < 7 ; j++) + state->RegBank[j][i] = 0 ; + } + for (i = 0 ; i < 7 ; i++) + state->Spsr[i] = 0 ; + state->Mode = 0 ; + + state->CallDebug = FALSE ; + state->Debug = FALSE ; + state->VectorCatch = 0 ; + state->Aborted = FALSE ; + state->Reseted = FALSE ; + state->Inted = 3 ; + state->LastInted = 3 ; + + state->MemDataPtr = NULL ; + state->MemInPtr = NULL ; + state->MemOutPtr = NULL ; + state->MemSparePtr = NULL ; + state->MemSize = 0 ; + + state->OSptr = NULL ; + state->CommandLine = NULL ; + + state->EventSet = 0 ; + state->Now = 0 ; + state->EventPtr = (struct EventNode **)malloc((unsigned)EVENTLISTSIZE * + sizeof(struct EventNode *)) ; + for (i = 0 ; i < EVENTLISTSIZE ; i++) + *(state->EventPtr + i) = NULL ; + +#ifdef ARM61 + state->prog32Sig = LOW ; + state->data32Sig = LOW ; +#else + state->prog32Sig = HIGH ; + state->data32Sig = HIGH ; +#endif + + state->lateabtSig = LOW ; + state->bigendSig = LOW ; + + ARMul_Reset(state) ; + return(state) ; + } + +/***************************************************************************\ +* Call this routine to set ARMulator to model a certain processor * +\***************************************************************************/ + +void ARMul_SelectProcessor(ARMul_State *state, unsigned processor) { + if (processor & ARM_Fix26_Prop) { + state->prog32Sig = LOW; + state->data32Sig = LOW; + }else{ + state->prog32Sig = HIGH; + state->data32Sig = HIGH; + } + + state->lateabtSig = LOW; +} + +/***************************************************************************\ +* Call this routine to set up the initial machine state (or perform a RESET * +\***************************************************************************/ + +void ARMul_Reset(ARMul_State *state) +{state->NextInstr = 0 ; + if (state->prog32Sig) { + state->Reg[15] = 0 ; + state->Cpsr = INTBITS | SVC32MODE ; + } + else { + state->Reg[15] = R15INTBITS | SVC26MODE ; + state->Cpsr = INTBITS | SVC26MODE ; + } + ARMul_CPSRAltered(state) ; + state->Bank = SVCBANK ; + FLUSHPIPE ; + + state->EndCondition = 0 ; + state->ErrorCode = 0 ; + + state->Exception = FALSE ; + state->NresetSig = HIGH ; + state->NfiqSig = HIGH ; + state->NirqSig = HIGH ; + state->NtransSig = (state->Mode & 3)?HIGH:LOW ; + state->abortSig = LOW ; + state->AbortAddr = 1 ; + + state->NumInstrs = 0 ; + state->NumNcycles = 0 ; + state->NumScycles = 0 ; + state->NumIcycles = 0 ; + state->NumCcycles = 0 ; + state->NumFcycles = 0 ; +#ifdef ASIM + (void)ARMul_MemoryInit() ; + ARMul_OSInit(state) ; +#endif +} + + +/***************************************************************************\ +* Emulate the execution of an entire program. Start the correct emulator * +* (Emulate26 for a 26 bit ARM and Emulate32 for a 32 bit ARM), return the * +* address of the last instruction that is executed. * +\***************************************************************************/ + +ARMword ARMul_DoProg(ARMul_State *state) +{ARMword pc = 0 ; + + state->Emulate = RUN ; + while (state->Emulate != STOP) { + state->Emulate = RUN ; + if (state->prog32Sig && ARMul_MODE32BIT) + pc = ARMul_Emulate32(state) ; + else + pc = ARMul_Emulate26(state) ; + } + return(pc) ; + } + +/***************************************************************************\ +* Emulate the execution of one instruction. Start the correct emulator * +* (Emulate26 for a 26 bit ARM and Emulate32 for a 32 bit ARM), return the * +* address of the instruction that is executed. * +\***************************************************************************/ + +ARMword ARMul_DoInstr(ARMul_State *state) +{ARMword pc = 0 ; + + state->Emulate = ONCE ; + if (state->prog32Sig && ARMul_MODE32BIT) + pc = ARMul_Emulate32(state) ; + else + pc = ARMul_Emulate26(state) ; + + return(pc) ; + } + +/***************************************************************************\ +* This routine causes an Abort to occur, including selecting the correct * +* mode, register bank, and the saving of registers. Call with the * +* appropriate vector's memory address (0,4,8 ....) * +\***************************************************************************/ + +void ARMul_Abort(ARMul_State *state, ARMword vector) +{ARMword temp ; + + state->Aborted = FALSE ; + + if (ARMul_OSException(state,vector,ARMul_GetPC(state))) + return ; + + if (state->prog32Sig) + if (ARMul_MODE26BIT) + temp = R15PC ; + else + temp = state->Reg[15] ; + else + temp = R15PC | ECC | ER15INT | EMODE ; + + switch (vector) { + case ARMul_ResetV : /* RESET */ + state->Spsr[SVCBANK] = CPSR ; + SETABORT(INTBITS,state->prog32Sig?SVC32MODE:SVC26MODE) ; + ARMul_CPSRAltered(state) ; + state->Reg[14] = temp ; + break ; + case ARMul_UndefinedInstrV : /* Undefined Instruction */ + state->Spsr[state->prog32Sig?UNDEFBANK:SVCBANK] = CPSR ; + SETABORT(IBIT,state->prog32Sig?UNDEF32MODE:SVC26MODE) ; + ARMul_CPSRAltered(state) ; + state->Reg[14] = temp - 4 ; + break ; + case ARMul_SWIV : /* Software Interrupt */ + state->Spsr[SVCBANK] = CPSR ; + SETABORT(IBIT,state->prog32Sig?SVC32MODE:SVC26MODE) ; + ARMul_CPSRAltered(state) ; + state->Reg[14] = temp - 4 ; + break ; + case ARMul_PrefetchAbortV : /* Prefetch Abort */ + state->AbortAddr = 1 ; + state->Spsr[state->prog32Sig?ABORTBANK:SVCBANK] = CPSR ; + SETABORT(IBIT,state->prog32Sig?ABORT32MODE:SVC26MODE) ; + ARMul_CPSRAltered(state) ; + state->Reg[14] = temp - 4 ; + break ; + case ARMul_DataAbortV : /* Data Abort */ + state->Spsr[state->prog32Sig?ABORTBANK:SVCBANK] = CPSR ; + SETABORT(IBIT,state->prog32Sig?ABORT32MODE:SVC26MODE) ; + ARMul_CPSRAltered(state) ; + state->Reg[14] = temp - 4 ; /* the PC must have been incremented */ + break ; + case ARMul_AddrExceptnV : /* Address Exception */ + state->Spsr[SVCBANK] = CPSR ; + SETABORT(IBIT,SVC26MODE) ; + ARMul_CPSRAltered(state) ; + state->Reg[14] = temp - 4 ; + break ; + case ARMul_IRQV : /* IRQ */ + state->Spsr[IRQBANK] = CPSR ; + SETABORT(IBIT,state->prog32Sig?IRQ32MODE:IRQ26MODE) ; + ARMul_CPSRAltered(state) ; + state->Reg[14] = temp - 4 ; + break ; + case ARMul_FIQV : /* FIQ */ + state->Spsr[FIQBANK] = CPSR ; + SETABORT(INTBITS,state->prog32Sig?FIQ32MODE:FIQ26MODE) ; + ARMul_CPSRAltered(state) ; + state->Reg[14] = temp - 4 ; + break ; + } + if (ARMul_MODE32BIT) + ARMul_SetR15(state,vector) ; + else + ARMul_SetR15(state,R15CCINTMODE | vector) ; +} diff --git a/sim/arm/armopts.h b/sim/arm/armopts.h new file mode 100644 index 00000000000..c3b5cb770d3 --- /dev/null +++ b/sim/arm/armopts.h @@ -0,0 +1,23 @@ +/* armopts.h -- ARMulator configuration options: ARM6 Instruction Emulator. + Copyright (C) 1994 Advanced RISC Machines Ltd. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* Define one of ARM60 or ARM61 */ +#ifndef ARM60 +#ifndef ARM61 +#define ARM60 +#endif +#endif diff --git a/sim/arm/armos.c b/sim/arm/armos.c new file mode 100644 index 00000000000..2906d41f083 --- /dev/null +++ b/sim/arm/armos.c @@ -0,0 +1,1136 @@ +/* armos.c -- ARMulator OS interface: ARM6 Instruction Emulator. + Copyright (C) 1994 Advanced RISC Machines Ltd. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* This file contains a model of Demon, ARM Ltd's Debug Monitor, +including all the SWI's required to support the C library. The code in +it is not really for the faint-hearted (especially the abort handling +code), but it is a complete example. Defining NOOS will disable all the +fun, and definign VAILDATE will define SWI 1 to enter SVC mode, and SWI +0x11 to halt the emulator. */ + +#include "config.h" + +#include +#include +#include +#include + +#ifndef O_RDONLY +#define O_RDONLY 0 +#endif +#ifndef O_WRONLY +#define O_WRONLY 1 +#endif +#ifndef O_RDWR +#define O_RDWR 2 +#endif +#ifndef O_BINARY +#define O_BINARY 0 +#endif + +#ifdef __STDC__ +#define unlink(s) remove(s) +#endif + +#ifdef HAVE_UNISTD_H +#include /* For SEEK_SET etc */ +#endif + +#ifdef __riscos +extern int _fisatty(FILE *); +#define isatty_(f) _fisatty(f) +#else +#ifdef __ZTC__ +#include +#define isatty_(f) isatty((f)->_file) +#else +#ifdef macintosh +#include +#define isatty_(f) (~ioctl ((f)->_file, FIOINTERACTIVE, NULL)) +#else +#define isatty_(f) isatty (fileno (f)) +#endif +#endif +#endif + +#include "armdefs.h" +#include "armos.h" +#ifndef NOOS +#ifndef VALIDATE +/* #ifndef ASIM */ +#include "armfpe.h" +/* #endif */ +#endif +#endif + +/* For RDIError_BreakpointReached. */ +#include "dbg_rdi.h" + +extern unsigned ARMul_OSInit(ARMul_State *state) ; +extern void ARMul_OSExit(ARMul_State *state) ; +extern unsigned ARMul_OSHandleSWI(ARMul_State *state,ARMword number) ; +extern unsigned ARMul_OSException(ARMul_State *state, ARMword vector, ARMword pc) ; +extern ARMword ARMul_OSLastErrorP(ARMul_State *state) ; +extern ARMword ARMul_Debug(ARMul_State *state, ARMword pc, ARMword instr) ; + +#define BUFFERSIZE 4096 +#ifndef FOPEN_MAX +#define FOPEN_MAX 64 +#endif +#define UNIQUETEMPS 256 + +#ifndef NOOS +static void UnwindDataAbort(ARMul_State *state, ARMword addr); +static void getstring(ARMul_State *state, ARMword from, char *to) ; +#endif + +/***************************************************************************\ +* OS private Information * +\***************************************************************************/ + +struct OSblock { + ARMword Time0 ; + ARMword ErrorP ; + ARMword ErrorNo ; + FILE *FileTable[FOPEN_MAX] ; + char FileFlags[FOPEN_MAX] ; + char *tempnames[UNIQUETEMPS] ; + } ; + +#define NOOP 0 +#define BINARY 1 +#define READOP 2 +#define WRITEOP 4 + +#ifdef macintosh +#define FIXCRLF(t,c) ((t & BINARY) ? \ + c : \ + ((c == '\n' || c == '\r' ) ? (c ^ 7) : c) \ + ) +#else +#define FIXCRLF(t,c) c +#endif + +static ARMword softvectorcode[] = +{ /* basic: swi tidyexception + event; mov pc, lr; + ldmia r11,{r11,pc}; swi generateexception + event + */ + 0xef000090, 0xe1a0e00f, 0xe89b8800, 0xef000080, /*Reset*/ + 0xef000091, 0xe1a0e00f, 0xe89b8800, 0xef000081, /*Undef*/ + 0xef000092, 0xe1a0e00f, 0xe89b8800, 0xef000082, /*SWI */ + 0xef000093, 0xe1a0e00f, 0xe89b8800, 0xef000083, /*Prefetch abort*/ + 0xef000094, 0xe1a0e00f, 0xe89b8800, 0xef000084, /*Data abort*/ + 0xef000095, 0xe1a0e00f, 0xe89b8800, 0xef000085, /*Address exception*/ + 0xef000096, 0xe1a0e00f, 0xe89b8800, 0xef000086, /*IRQ*/ + 0xef000097, 0xe1a0e00f, 0xe89b8800, 0xef000087, /*FIQ*/ + 0xef000098, 0xe1a0e00f, 0xe89b8800, 0xef000088, /*Error*/ + 0xe1a0f00e /* default handler */ +}; + +/***************************************************************************\ +* Time for the Operating System to initialise itself. * +\***************************************************************************/ + +unsigned +ARMul_OSInit (ARMul_State *state) +{ +#ifndef NOOS +#ifndef VALIDATE + ARMword instr, i , j ; + struct OSblock* OSptr = (struct OSblock*)state->OSptr; + + if (state->OSptr == NULL) { + state->OSptr = (unsigned char *)malloc(sizeof(struct OSblock)); + if (state->OSptr == NULL) { + perror("OS Memory"); + exit(15); + } + } + OSptr = (struct OSblock*)state->OSptr; + OSptr->ErrorP = 0; + state->Reg[13] = ADDRSUPERSTACK; /* set up a stack for the current mode */ + ARMul_SetReg(state,SVC32MODE,13,ADDRSUPERSTACK); /* and for supervisor mode */ + ARMul_SetReg(state,ABORT32MODE,13,ADDRSUPERSTACK); /* and for abort 32 mode */ + ARMul_SetReg(state,UNDEF32MODE,13,ADDRSUPERSTACK); /* and for undef 32 mode */ + instr = 0xe59ff000 | (ADDRSOFTVECTORS - 8); /* load pc from soft vector */ + for (i = ARMul_ResetV ; i <= ARMFIQV ; i += 4) + ARMul_WriteWord(state, i, instr); /* write hardware vectors */ + for (i = ARMul_ResetV ; i <= ARMFIQV + 4 ; i += 4) { + ARMul_WriteWord(state, ADDRSOFTVECTORS + i, SOFTVECTORCODE + i * 4); + ARMul_WriteWord(state, ADDRSOFHANDLERS + 2*i + 4L, SOFTVECTORCODE + sizeof(softvectorcode) - 4L); + } + for (i = 0 ; i < sizeof(softvectorcode) ; i += 4) + ARMul_WriteWord(state, SOFTVECTORCODE + i, softvectorcode[i/4]); + for (i = 0 ; i < FOPEN_MAX ; i++) + OSptr->FileTable[i] = NULL ; + for (i = 0 ; i < UNIQUETEMPS ; i++) + OSptr->tempnames[i] = NULL ; + ARMul_ConsolePrint (state, ", Demon 1.01"); + +/* #ifndef ASIM */ + + /* install fpe */ + for (i = 0 ; i < fpesize ; i+=4) /* copy the code */ + ARMul_WriteWord(state,FPESTART + i,fpecode[i >> 2]) ; + for (i = FPESTART + fpesize ; ; i-=4) { /* reverse the error strings */ + if ((j = ARMul_ReadWord(state,i)) == 0xffffffff) + break ; + if (state->bigendSig && j < 0x80000000) { /* it's part of the string so swap it */ + j = ((j >> 0x18) & 0x000000ff) | + ((j >> 0x08) & 0x0000ff00) | + ((j << 0x08) & 0x00ff0000) | + ((j << 0x18) & 0xff000000) ; + ARMul_WriteWord(state,i,j) ; + } + } + ARMul_WriteWord(state,FPEOLDVECT,ARMul_ReadWord(state,4)) ; /* copy old illegal instr vector */ + ARMul_WriteWord(state,4,FPENEWVECT(ARMul_ReadWord(state,i-4))) ; /* install new vector */ + ARMul_ConsolePrint (state, ", FPE") ; + +/* #endif /* ASIM */ +#endif /* VALIDATE */ +#endif /* NOOS */ + + return(TRUE) ; +} + +void +ARMul_OSExit (ARMul_State *state) +{ + free((char *)state->OSptr); +} + + +/***************************************************************************\ +* Return the last Operating System Error. * +\***************************************************************************/ + +ARMword +ARMul_OSLastErrorP (ARMul_State *state) +{ + return ((struct OSblock *)state->OSptr)->ErrorP; +} + +#if 1 /* CYGNUS LOCAL */ +/* This is the cygnus way of doing it, which makes it simple to do our tests */ + +static int translate_open_mode[] = +{ + O_RDONLY, /* "r" */ + O_RDONLY+O_BINARY, /* "rb" */ + O_RDWR, /* "r+" */ + O_RDWR +O_BINARY, /* "r+b" */ + O_WRONLY +O_CREAT+O_TRUNC, /* "w" */ + O_WRONLY+O_BINARY+O_CREAT+O_TRUNC, /* "wb" */ + O_RDWR +O_CREAT+O_TRUNC, /* "w+" */ + O_RDWR +O_BINARY+O_CREAT+O_TRUNC, /* "w+b" */ + O_WRONLY +O_APPEND+O_CREAT,/* "a" */ + O_WRONLY+O_BINARY+O_APPEND+O_CREAT,/* "ab" */ + O_RDWR +O_APPEND+O_CREAT,/* "a+" */ + O_RDWR +O_BINARY+O_APPEND+O_CREAT /* "a+b" */ +}; + +static void +SWIWrite0 (ARMul_State *state, ARMword addr) +{ + ARMword temp; + struct OSblock* OSptr = (struct OSblock*) state->OSptr; + + while ((temp = ARMul_ReadByte (state, addr++)) != 0) + (void) fputc ((char) temp, stderr); + + OSptr->ErrorNo = errno; +} + +static void +WriteCommandLineTo (ARMul_State *state, ARMword addr) +{ + ARMword temp; + char *cptr = state->CommandLine; + if (cptr == NULL) + cptr = "\0"; + do { + temp = (ARMword) *cptr++; + ARMul_WriteByte (state, addr++, temp); + } while (temp != 0); +} + +static void +SWIopen (ARMul_State *state, ARMword name, ARMword SWIflags) +{ + struct OSblock* OSptr = (struct OSblock*)state->OSptr; + char dummy[2000]; + int flags; + int i; + + for (i = 0; + dummy[i] = ARMul_ReadByte (state, name + i); + i++) + ; + + /* Now we need to decode the Demon open mode */ + flags = translate_open_mode[SWIflags]; + + /* Filename ":tt" is special: it denotes stdin/out */ + if (strcmp (dummy, ":tt") == 0) + { + if (flags == O_RDONLY) /* opening tty "r" */ + state->Reg[0] = 0; /* stdin */ + else + state->Reg[0] = 1; /* stdout */ + } + else + { + state->Reg[0] = (int) open (dummy, flags); + OSptr->ErrorNo = errno; + } +} + +static void +SWIread (ARMul_State *state, ARMword f, ARMword ptr, ARMword len) +{ + struct OSblock* OSptr = (struct OSblock*) state->OSptr; + int res; + int i; + char *local = malloc (len); + + res = read (f, local, len); + if (res > 0) + for (i = 0; i < res; i++) + ARMul_WriteByte (state, ptr + i, local[i]); + free (local); + state->Reg[0] = res == -1 ? -1 : len - res; + OSptr->ErrorNo = errno; +} + +static void +SWIwrite (ARMul_State *state, ARMword f, ARMword ptr, ARMword len) +{ + struct OSblock* OSptr = (struct OSblock*) state->OSptr; + int res; + int i; + char *local = malloc (len); + + for (i = 0; i < len; i++) + { + local[i] = ARMul_ReadByte (state, ptr + i); + } + res = write (f, local, len); + state->Reg[0] = res == -1 ? -1 : len - res; + free (local); + OSptr->ErrorNo = errno; +} + +static void +SWIflen (ARMul_State *state, ARMword fh) +{ + struct OSblock* OSptr = (struct OSblock*) state->OSptr; + ARMword addr; + + if (fh == 0 || fh > FOPEN_MAX) + { + OSptr->ErrorNo = EBADF; + state->Reg[0] = -1L; + return; + } + + addr = lseek (fh, 0, SEEK_CUR); + if (addr < 0) + state->Reg[0] = -1L; + else + { + state->Reg[0] = lseek (fh, 0L, SEEK_END); + (void) lseek (fh, addr, SEEK_SET); + } + + OSptr->ErrorNo = errno; +} + +/***************************************************************************\ +* The emulator calls this routine when a SWI instruction is encuntered. The * +* parameter passed is the SWI number (lower 24 bits of the instruction). * +\***************************************************************************/ + +unsigned +ARMul_OSHandleSWI (ARMul_State *state, ARMword number) +{ + ARMword addr, temp, fildes; + char buffer[BUFFERSIZE], *cptr; + FILE *fptr; + struct OSblock* OSptr = (struct OSblock*)state->OSptr; + + switch (number) + { + case SWI_Read: + SWIread (state, state->Reg[0], state->Reg[1], state->Reg[2]); + return TRUE; + + case SWI_Write: + SWIwrite (state, state->Reg[0], state->Reg[1], state->Reg[2]); + return TRUE; + + case SWI_Open: + SWIopen (state, state->Reg[0],state->Reg[1]); + return TRUE; + + case SWI_Clock : + /* return number of centi-seconds... */ + state->Reg[0] = +#ifdef CLOCKS_PER_SEC + (CLOCKS_PER_SEC >= 100) + ? (ARMword) (clock() / (CLOCKS_PER_SEC / 100)) + : (ARMword) ((clock() * 100) / CLOCKS_PER_SEC) ; +#else + /* presume unix... clock() returns microseconds */ + (ARMword) (clock() / 10000) ; +#endif + OSptr->ErrorNo = errno ; + return(TRUE) ; + + case SWI_Time : + state->Reg[0] = (ARMword)time(NULL) ; + OSptr->ErrorNo = errno ; + return(TRUE) ; + + case SWI_Close: + state->Reg[0] = close (state->Reg[0]); + OSptr->ErrorNo = errno; + return TRUE; + + case SWI_Flen : + SWIflen (state, state->Reg[0]); + return(TRUE) ; + + case SWI_Exit: + state->Emulate = FALSE ; + return TRUE; + + case SWI_Seek: + { + /* We must return non-zero for failure */ + state->Reg[0] = -1 >= lseek (state->Reg[0], + state->Reg[1], + SEEK_SET); + OSptr->ErrorNo = errno; + return TRUE; + } + + case SWI_WriteC : + (void)fputc((int)state->Reg[0],stderr) ; + OSptr->ErrorNo = errno ; + return(TRUE) ; + + case SWI_Write0 : + SWIWrite0 (state, state->Reg[0]); + return(TRUE) ; + + case SWI_GetErrno : + state->Reg[0] = OSptr->ErrorNo ; + return(TRUE) ; + + case SWI_Breakpoint : + state->EndCondition = RDIError_BreakpointReached ; + state->Emulate = FALSE ; + return(TRUE) ; + + case SWI_GetEnv : + state->Reg[0] = ADDRCMDLINE ; + if (state->MemSize) + state->Reg[1] = state->MemSize ; + else + state->Reg[1] = ADDRUSERSTACK ; + + WriteCommandLineTo (state, state->Reg[0]); + return(TRUE) ; + + /* Handle Angel SWIs as well as Demon ones */ + case AngelSWI_ARM: + case AngelSWI_Thumb: + /* R1 is almost always a parameter block */ + addr = state->Reg[1]; + /* R0 is a reason code */ + switch (state->Reg[0]) + { + /* Unimplemented reason codes */ + case AngelSWI_Reason_ReadC: + case AngelSWI_Reason_IsTTY: + case AngelSWI_Reason_TmpNam: + case AngelSWI_Reason_Remove: + case AngelSWI_Reason_Rename: + case AngelSWI_Reason_System: + case AngelSWI_Reason_EnterSVC: + default: + state->Emulate = FALSE; + return(FALSE); + + case AngelSWI_Reason_Clock: + /* return number of centi-seconds... */ + state->Reg[0] = +#ifdef CLOCKS_PER_SEC + (CLOCKS_PER_SEC >= 100) + ? (ARMword) (clock() / (CLOCKS_PER_SEC / 100)) + : (ARMword) ((clock() * 100) / CLOCKS_PER_SEC) ; +#else + /* presume unix... clock() returns microseconds */ + (ARMword) (clock() / 10000) ; +#endif + OSptr->ErrorNo = errno; + return (TRUE); + + case AngelSWI_Reason_Time: + state->Reg[0] = (ARMword) time (NULL); + OSptr->ErrorNo = errno; + return (TRUE); + + case AngelSWI_Reason_WriteC: + (void) fputc ((int) ARMul_ReadByte (state,addr), stderr); + OSptr->ErrorNo = errno; + return (TRUE); + + case AngelSWI_Reason_Write0: + SWIWrite0 (state, addr); + return (TRUE); + + case AngelSWI_Reason_Close: + state->Reg[0] = close (ARMul_ReadWord (state, addr)); + OSptr->ErrorNo = errno; + return (TRUE); + + case AngelSWI_Reason_Seek: + state->Reg[0] = -1 >= lseek (ARMul_ReadWord(state,addr), + ARMul_ReadWord(state,addr+4), + SEEK_SET); + OSptr->ErrorNo = errno; + return (TRUE); + + case AngelSWI_Reason_FLen: + SWIflen (state, ARMul_ReadWord (state, addr)); + return (TRUE); + + case AngelSWI_Reason_GetCmdLine: + WriteCommandLineTo (state, ARMul_ReadWord (state, addr)); + return (TRUE); + + case AngelSWI_Reason_HeapInfo: + /* R1 is a pointer to a pointer */ + addr = ARMul_ReadWord (state, addr); + + /* Pick up the right memory limit */ + if (state->MemSize) + temp = state->MemSize; + else + temp = ADDRUSERSTACK; + + ARMul_WriteWord (state, addr, 0); /* Heap base */ + ARMul_WriteWord (state, addr+4, temp); /* Heap limit */ + ARMul_WriteWord (state, addr+8, temp); /* Stack base */ + ARMul_WriteWord (state, addr+12, temp); /* Stack limit */ + return (TRUE); + + case AngelSWI_Reason_ReportException: + if (state->Reg[1] == ADP_Stopped_ApplicationExit) + state->Reg[0] = 0; + else + state->Reg[0] = -1; + state->Emulate = FALSE ; + return (TRUE); + + case ADP_Stopped_ApplicationExit: + state->Reg[0] = 0; + state->Emulate = FALSE ; + return (TRUE); + + case ADP_Stopped_RunTimeError: + state->Reg[0] = -1; + state->Emulate = FALSE ; + return (TRUE); + + case AngelSWI_Reason_Errno: + state->Reg[0] = OSptr->ErrorNo; + return (TRUE); + + case AngelSWI_Reason_Open: + SWIopen(state, + ARMul_ReadWord(state, addr), + ARMul_ReadWord(state, addr+4)); + return TRUE; + + case AngelSWI_Reason_Read: + SWIread(state, + ARMul_ReadWord(state, addr), + ARMul_ReadWord(state, addr+4), + ARMul_ReadWord(state, addr+8)); + return TRUE; + + case AngelSWI_Reason_Write: + SWIwrite(state, + ARMul_ReadWord(state, addr), + ARMul_ReadWord(state, addr+4), + ARMul_ReadWord(state, addr+8)); + return TRUE; + } + + default : + state->Emulate = FALSE ; + return(FALSE) ; + } +} + +#else /* CYGNUS LOCAL: #if 1 */ + +unsigned +ARMul_OSHandleSWI (ARMul_State *state, ARMword number) +{ +#ifdef NOOS + return(FALSE) ; +#else +#ifdef VALIDATE + switch (number) { + case 0x11 : + state->Emulate = FALSE ; + return(TRUE) ; + case 0x01 : + if (ARM32BITMODE) + ARMul_SetCPSR(state, (ARMul_GetCPSR(state) & 0xffffffc0) | 0x13) ; + else + ARMul_SetCPSR(state, (ARMul_GetCPSR(state) & 0xffffffc0) | 0x3) ; + return(TRUE) ; + default : + return(FALSE) ; + } +#else + ARMword addr, temp ; + char buffer[BUFFERSIZE], *cptr ; + FILE *fptr ; + struct OSblock* OSptr = (struct OSblock*)state->OSptr ; + + switch (number) { + case SWI_WriteC : + (void)fputc((int)state->Reg[0],stderr) ; + OSptr->ErrorNo = errno ; + return(TRUE) ; + + case SWI_Write0 : + addr = state->Reg[0] ; + while ((temp = ARMul_ReadByte(state,addr++)) != 0) + fputc((char)temp,stderr) ; + OSptr->ErrorNo = errno ; + return(TRUE) ; + + case SWI_ReadC : + state->Reg[0] = (ARMword)fgetc(stdin) ; + OSptr->ErrorNo = errno ; + return(TRUE) ; + + case SWI_CLI : + addr = state->Reg[0] ; + getstring(state,state->Reg[0],buffer) ; + state->Reg[0] = (ARMword)system(buffer) ; + OSptr->ErrorNo = errno ; + return(TRUE) ; + + case SWI_GetEnv : + state->Reg[0] = ADDRCMDLINE ; + if (state->MemSize) + state->Reg[1] = state->MemSize ; + else + state->Reg[1] = ADDRUSERSTACK ; + + addr = state->Reg[0] ; + cptr = state->CommandLine ; + if (cptr == NULL) + cptr = "\0" ; + do { + temp = (ARMword)*cptr++ ; + ARMul_WriteByte(state,addr++,temp) ; + } while (temp != 0) ; + return(TRUE) ; + + case SWI_Exit : +#ifdef ASIM + simkernel1_abort_run() ; +#else + state->Emulate = FALSE ; +#endif + return(TRUE) ; + + case SWI_EnterOS : + if (ARM32BITMODE) + ARMul_SetCPSR(state, (ARMul_GetCPSR(state) & 0xffffffc0) | 0x13) ; + else + ARMul_SetCPSR(state, (ARMul_GetCPSR(state) & 0xffffffc0) | 0x3) ; + return(TRUE) ; + + case SWI_GetErrno : + state->Reg[0] = OSptr->ErrorNo ; + return(TRUE) ; + + case SWI_Clock : + /* return muber of centi-seconds... */ + state->Reg[0] = +#ifdef CLOCKS_PER_SEC + (CLOCKS_PER_SEC >= 100) + ? (ARMword) (clock() / (CLOCKS_PER_SEC / 100)) + : (ARMword) ((clock() * 100) / CLOCKS_PER_SEC) ; +#else + /* presume unix... clock() returns microseconds */ + (ARMword) (clock() / 10000) ; +#endif + OSptr->ErrorNo = errno ; + return(TRUE) ; + + case SWI_Time : + state->Reg[0] = (ARMword)time(NULL) ; + OSptr->ErrorNo = errno ; + return(TRUE) ; + + case SWI_Remove : + getstring(state,state->Reg[0],buffer) ; + state->Reg[0] = unlink(buffer) ; + OSptr->ErrorNo = errno ; + return(TRUE) ; + + case SWI_Rename : { + char buffer2[BUFFERSIZE] ; + + getstring(state,state->Reg[0],buffer) ; + getstring(state,state->Reg[1],buffer2) ; + state->Reg[0] = rename(buffer,buffer2) ; + OSptr->ErrorNo = errno ; + return(TRUE) ; + } + + case SWI_Open : { +#if 0 + /* It seems to me that these are in the wrong order + sac@cygnus.com, so I've redone it to use the + flags instead, with the functionality which was already + there -- ahh, perhaps the TRUNC bit is in a different + place on the original host ?*/ + static char* fmode[] = {"r","rb","r+","r+b", + "w","wb","w+","w+b", + "a","ab","a+","a+b", + "r","r","r","r"} /* last 4 are illegal */ ; +#endif + + unsigned type ; + + type = (unsigned)(state->Reg[1] & 3L) ; + getstring(state,state->Reg[0],buffer) ; + if (strcmp(buffer,":tt")==0 && (type == O_RDONLY )) /* opening tty "r" */ + fptr = stdin ; + else if (strcmp(buffer,":tt")==0 && (type == O_WRONLY)) /* opening tty "w" */ + fptr = stderr ; + else + { + switch (type) + { + case O_RDONLY: + fptr = fopen(buffer,"r") ; + break; + case O_WRONLY: + fptr = fopen(buffer,"w") ; + break; + case O_RDWR: + fptr = fopen(buffer,"rw") ; + break; + } + } + + state->Reg[0] = 0 ; + if (fptr != NULL) { + for (temp = 0 ; temp < FOPEN_MAX ; temp++) + if (OSptr->FileTable[temp] == NULL) { + OSptr->FileTable[temp] = fptr ; + OSptr->FileFlags[temp] = type & 1 ; /* preserve the binary bit */ + state->Reg[0] = (ARMword)(temp + 1) ; + break ; + } + if (state->Reg[0] == 0) + OSptr->ErrorNo = EMFILE ; /* too many open files */ + else + OSptr->ErrorNo = errno ; + } + else + OSptr->ErrorNo = errno ; + return(TRUE) ; + } + + case SWI_Close : + temp = state->Reg[0] ; + if (temp == 0 || temp > FOPEN_MAX || OSptr->FileTable[temp - 1] == 0) { + OSptr->ErrorNo = EBADF ; + state->Reg[0] = -1L ; + return(TRUE) ; + } + temp-- ; + fptr = OSptr->FileTable[temp] ; + if (fptr == stdin || fptr == stderr) + state->Reg[0] = 0 ; + else + state->Reg[0] = fclose(fptr) ; + OSptr->FileTable[temp] = NULL ; + OSptr->ErrorNo = errno ; + return(TRUE) ; + + case SWI_Write : { + unsigned size, upto, type ; + char ch ; + + temp = state->Reg[0] ; + if (temp == 0 || temp > FOPEN_MAX || OSptr->FileTable[temp - 1] == 0) { + OSptr->ErrorNo = EBADF ; + state->Reg[0] = -1L ; + return(TRUE) ; + } + temp-- ; + fptr = OSptr->FileTable[temp] ; + type = OSptr->FileFlags[temp] ; + addr = state->Reg[1] ; + size = (unsigned)state->Reg[2] ; + + if (type & READOP) + fseek(fptr,0L,SEEK_CUR) ; + OSptr->FileFlags[temp] = (type & BINARY) | WRITEOP ; ; + while (size > 0) { + if (size >= BUFFERSIZE) + upto = BUFFERSIZE ; + else + upto = size ; + for (cptr = buffer ; (cptr - buffer) < upto ; cptr++) { + ch = (char)ARMul_ReadByte(state,(ARMword)addr++) ; + *cptr = FIXCRLF(type,ch) ; + } + temp = fwrite(buffer,1,upto,fptr) ; + if (temp < upto) { + state->Reg[0] = (ARMword)(size - temp) ; + OSptr->ErrorNo = errno ; + return(TRUE) ; + } + size -= upto ; + } + state->Reg[0] = 0 ; + OSptr->ErrorNo = errno ; + return(TRUE) ; + } + + case SWI_Read : { + unsigned size, upto, type ; + char ch ; + + temp = state->Reg[0] ; + if (temp == 0 || temp > FOPEN_MAX || OSptr->FileTable[temp - 1] == 0) { + OSptr->ErrorNo = EBADF ; + state->Reg[0] = -1L ; + return(TRUE) ; + } + temp-- ; + fptr = OSptr->FileTable[temp] ; + addr = state->Reg[1] ; + size = (unsigned)state->Reg[2] ; + type = OSptr->FileFlags[temp] ; + + if (type & WRITEOP) + fseek(fptr,0L,SEEK_CUR) ; + OSptr->FileFlags[temp] = (type & BINARY) | READOP ; ; + while (size > 0) { + if (isatty_(fptr)) { + upto = (size >= BUFFERSIZE)?BUFFERSIZE:size + 1 ; + if (fgets(buffer, upto, fptr) != 0) + temp = strlen(buffer) ; + else + temp = 0 ; + upto-- ; /* 1 char used for terminating null */ + } + else { + upto = (size>=BUFFERSIZE)?BUFFERSIZE:size ; + temp = fread(buffer,1,upto,fptr) ; + } + for (cptr = buffer ; (cptr - buffer) < temp ; cptr++) { + ch = *cptr ; + ARMul_WriteByte(state,(ARMword)addr++,FIXCRLF(type,ch)) ; + } + if (temp < upto) { + state->Reg[0] = (ARMword)(size - temp) ; + OSptr->ErrorNo = errno ; + return(TRUE) ; + } + size -= upto ; + } + state->Reg[0] = 0 ; + OSptr->ErrorNo = errno ; + return(TRUE) ; + } + + case SWI_Seek : + if (state->Reg[0] == 0 || state->Reg[0] > FOPEN_MAX + || OSptr->FileTable[state->Reg[0] - 1] == 0) { + OSptr->ErrorNo = EBADF ; + state->Reg[0] = -1L ; + return(TRUE) ; + } + fptr = OSptr->FileTable[state->Reg[0] - 1] ; + state->Reg[0] = fseek(fptr,(long)state->Reg[1],SEEK_SET) ; + OSptr->ErrorNo = errno ; + return(TRUE) ; + + case SWI_Flen : + if (state->Reg[0] == 0 || state->Reg[0] > FOPEN_MAX + || OSptr->FileTable[state->Reg[0] - 1] == 0) { + OSptr->ErrorNo = EBADF ; + state->Reg[0] = -1L ; + return(TRUE) ; + } + fptr = OSptr->FileTable[state->Reg[0] - 1] ; + addr = (ARMword)ftell(fptr) ; + if (fseek(fptr,0L,SEEK_END) < 0) + state->Reg[0] = -1 ; + else { + state->Reg[0] = (ARMword)ftell(fptr) ; + (void)fseek(fptr,addr,SEEK_SET) ; + } + OSptr->ErrorNo = errno ; + return(TRUE) ; + + case SWI_IsTTY : + if (state->Reg[0] == 0 || state->Reg[0] > FOPEN_MAX + || OSptr->FileTable[state->Reg[0] - 1] == 0) { + OSptr->ErrorNo = EBADF ; + state->Reg[0] = -1L ; + return(TRUE) ; + } + fptr = OSptr->FileTable[state->Reg[0] - 1] ; + state->Reg[0] = isatty_(fptr) ; + OSptr->ErrorNo = errno ; + return(TRUE) ; + + case SWI_TmpNam :{ + ARMword size ; + + addr = state->Reg[0] ; + temp = state->Reg[1] & 0xff ; + size = state->Reg[2] ; + if (OSptr->tempnames[temp] == NULL) { + if ((OSptr->tempnames[temp] = malloc(L_tmpnam)) == NULL) { + state->Reg[0] = 0 ; + return(TRUE) ; + } + (void)tmpnam(OSptr->tempnames[temp]) ; + } + cptr = OSptr->tempnames[temp] ; + if (strlen(cptr) > state->Reg[2]) + state->Reg[0] = 0 ; + else + do { + ARMul_WriteByte(state,addr++,*cptr) ; + } while (*cptr++ != 0) ; + OSptr->ErrorNo = errno ; + return(TRUE) ; + } + + case SWI_InstallHandler: + { ARMword handlerp = ADDRSOFHANDLERS + state->Reg[0] * 8; + ARMword oldr1 = ARMul_ReadWord(state, handlerp), + oldr2 = ARMul_ReadWord(state, handlerp + 4); + ARMul_WriteWord(state, handlerp, state->Reg[1]); + ARMul_WriteWord(state, handlerp + 4, state->Reg[2]); + state->Reg[1] = oldr1; + state->Reg[2] = oldr2; + return(TRUE); + } + + case SWI_GenerateError: + ARMul_Abort(state, ARMSWIV) ; + if (state->Emulate) + ARMul_SetR15(state, ARMul_ReadWord(state, ADDRSOFTVECTORS + ARMErrorV)); + return(TRUE); + +/* SWI's 0x9x unwind the state of the CPU after an abort of type x */ + + case 0x90: /* Branch through zero */ + { ARMword oldpsr = ARMul_GetCPSR(state) ; + ARMul_SetCPSR(state, (oldpsr & 0xffffffc0) | 0x13) ; + ARMul_SetSPSR(state, SVC32MODE, oldpsr) ; + state->Reg[14] = 0; + goto TidyCommon; + } + + case 0x98: /* Error */ + { ARMword errorp = state->Reg[0], + regp = state->Reg[1]; + unsigned i; + ARMword errorpsr = ARMul_ReadWord(state, regp + 16*4); + for (i = 0; i < 15; i++) + ARMul_SetReg(state,errorpsr,i,ARMul_ReadWord(state, regp + i*4L)) ; + state->Reg[14] = ARMul_ReadWord(state, regp + 15*4L); + state->Reg[10] = errorp; + ARMul_SetSPSR(state,state->Mode,errorpsr) ; + OSptr->ErrorP = errorp; + goto TidyCommon; + } + + case 0x94: /* Data abort */ + { ARMword addr = state->Reg[14] - 8; + ARMword cpsr = ARMul_GetCPSR(state) ; + if (ARM26BITMODE) + addr = addr & 0x3fffffc ; + ARMul_SetCPSR(state,ARMul_GetSPSR(state,cpsr)) ; + UnwindDataAbort(state, addr); + if (addr >= FPESTART && addr < FPEEND) { /* in the FPE */ + ARMword sp, spsr ; + unsigned i ; + + sp = state->Reg[13] ; + state->Reg[13] += 64 ; /* fix the aborting mode sp */ + state->Reg[14] = ARMul_ReadWord(state,sp + 60) ; /* and its lr */ + spsr = ARMul_GetSPSR(state,state->Mode) ; + state->Mode = ARMul_SwitchMode(state, state->Mode, spsr); + for (i = 0 ; i < 15 ; i++) { + ARMul_SetReg(state,spsr,i,ARMul_ReadWord(state,sp)) ; + sp += 4 ; + } + ARMul_SetCPSR(state,cpsr) ; + state->Reg[14] = ARMul_ReadWord(state,sp) + 4 ; /* botch it */ + ARMul_SetSPSR(state,state->Mode,spsr) ; + } + else + ARMul_SetCPSR(state,cpsr) ; + + /* and fall through to correct r14 */ + } + case 0x95: /* Address Exception */ + state->Reg[14] -= 4; + case 0x91: /* Undefined instruction */ + case 0x92: /* SWI */ + case 0x93: /* Prefetch abort */ + case 0x96: /* IRQ */ + case 0x97: /* FIQ */ + state->Reg[14] -= 4; + TidyCommon: + if (state->VectorCatch & (1 << (number - 0x90))) { + ARMul_SetR15(state, state->Reg[14] + 8) ; /* the 8 is the pipelining the the RDI will undo */ + ARMul_SetCPSR(state,ARMul_GetSPSR(state,ARMul_GetCPSR(state))) ; + if (number == 0x90) + state->EndCondition = 10 ; /* Branch through Zero Error */ + else + state->EndCondition = (unsigned)number - 0x8f; + state->Emulate = FALSE ; + } + else { + ARMword sp = state->Reg[13]; + ARMul_WriteWord(state, sp - 4, state->Reg[14]); + ARMul_WriteWord(state, sp - 8, state->Reg[12]); + ARMul_WriteWord(state, sp - 12, state->Reg[11]); + ARMul_WriteWord(state, sp - 16, state->Reg[10]); + state->Reg[13] = sp - 16; + state->Reg[11] = ADDRSOFHANDLERS + 8 * (number - 0x90); + } + return(TRUE); + +/* SWI's 0x8x pass an abort of type x to the debugger if a handler returns */ + + case 0x80: case 0x81: case 0x82: case 0x83: + case 0x84: case 0x85: case 0x86: case 0x87: case 0x88: + { ARMword sp = state->Reg[13]; + state->Reg[10] = ARMul_ReadWord(state, sp); + state->Reg[11] = ARMul_ReadWord(state, sp + 4); + state->Reg[12] = ARMul_ReadWord(state, sp + 8); + state->Reg[14] = ARMul_ReadWord(state, sp + 12); + state->Reg[13] = sp + 16; + ARMul_SetR15(state, state->Reg[14] + 8) ; /* the 8 is the pipelining the the RDI will undo */ + ARMul_SetCPSR(state,ARMul_GetSPSR(state,ARMul_GetCPSR(state))) ; + if (number == 0x80) + state->EndCondition = 10 ; /* Branch through Zero Error */ + else + state->EndCondition = (unsigned)number - 0x7f; + state->Emulate = FALSE ; + return(TRUE); + } + + default : + state->Emulate = FALSE ; + return(FALSE) ; + } +#endif +#endif + } +#endif /* CYGNUS LOCAL: #if 1 */ + +#ifndef NOOS +#ifndef ASIM + +/***************************************************************************\ +* The emulator calls this routine when an Exception occurs. The second * +* parameter is the address of the relevant exception vector. Returning * +* FALSE from this routine causes the trap to be taken, TRUE causes it to * +* be ignored (so set state->Emulate to FALSE!). * +\***************************************************************************/ + +unsigned +ARMul_OSException (ARMul_State *state, ARMword vector, ARMword pc) +{ /* don't use this here */ + return(FALSE) ; +} + +#endif + +/***************************************************************************\ +* Unwind a data abort * +\***************************************************************************/ + +static void +UnwindDataAbort (ARMul_State *state, ARMword addr) +{ + ARMword instr = ARMul_ReadWord(state, addr); + ARMword rn = BITS(16, 19); + ARMword itype = BITS(24, 27); + ARMword offset; + if (rn == 15) return; + if (itype == 8 || itype == 9) { + /* LDM or STM */ + unsigned long regs = BITS(0, 15); + offset = 0; + if (!BIT(21)) return; /* no wb */ + for (; regs != 0; offset++) + regs ^= (regs & -regs); + if (offset == 0) offset = 16; + } else if (itype == 12 || /* post-indexed CPDT */ + (itype == 13 && BIT(21))) { /* pre_indexed CPDT with WB */ + offset = BITS(0, 7); + } else + return; + + if (BIT(23)) + state->Reg[rn] -= offset * 4; + else + state->Reg[rn] += offset * 4; +} + +/***************************************************************************\ +* Copy a string from the debuggee's memory to the host's * +\***************************************************************************/ + +static void +getstring (ARMul_State *state, ARMword from, char *to) +{ + do + { + *to = (char) ARMul_ReadByte (state, from++); + } while (*to++ != '\0'); +} + +#endif /* NOOS */ diff --git a/sim/arm/armos.h b/sim/arm/armos.h new file mode 100644 index 00000000000..ca1f05ecfdd --- /dev/null +++ b/sim/arm/armos.h @@ -0,0 +1,95 @@ +/* armos.h -- ARMulator OS definitions: ARM6 Instruction Emulator. + Copyright (C) 1994 Advanced RISC Machines Ltd. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/***************************************************************************\ +* Define the initial layout of memory * +\***************************************************************************/ + +#define ADDRSUPERSTACK 0x800L /* supervisor stack space */ +#define ADDRUSERSTACK 0x80000L /* default user stack start */ +#define ADDRSOFTVECTORS 0x840L /* soft vectors are here */ +#define ADDRCMDLINE 0xf00L /* command line is here after a SWI GetEnv */ +#define ADDRSOFHANDLERS 0xad0L /* address and workspace for installed handlers */ +#define SOFTVECTORCODE 0xb80L /* default handlers */ + +/***************************************************************************\ +* SWI numbers * +\***************************************************************************/ + +#define SWI_WriteC 0x0 +#define SWI_Write0 0x2 +#define SWI_ReadC 0x4 +#define SWI_CLI 0x5 +#define SWI_GetEnv 0x10 +#define SWI_Exit 0x11 +#define SWI_EnterOS 0x16 + +#define SWI_GetErrno 0x60 +#define SWI_Clock 0x61 +#define SWI_Time 0x63 +#define SWI_Remove 0x64 +#define SWI_Rename 0x65 +#define SWI_Open 0x66 + +#define SWI_Close 0x68 +#define SWI_Write 0x69 +#define SWI_Read 0x6a +#define SWI_Seek 0x6b +#define SWI_Flen 0x6c + +#define SWI_IsTTY 0x6e +#define SWI_TmpNam 0x6f +#define SWI_InstallHandler 0x70 +#define SWI_GenerateError 0x71 + +#define SWI_Breakpoint 0x180000 /* see gdb's tm-arm.h */ + +#define AngelSWI_ARM 0x123456 +#define AngelSWI_Thumb 0xAB + +/* The reason codes: */ +#define AngelSWI_Reason_Open (0x01) +#define AngelSWI_Reason_Close (0x02) +#define AngelSWI_Reason_WriteC (0x03) +#define AngelSWI_Reason_Write0 (0x04) +#define AngelSWI_Reason_Write (0x05) +#define AngelSWI_Reason_Read (0x06) +#define AngelSWI_Reason_ReadC (0x07) +#define AngelSWI_Reason_IsTTY (0x09) +#define AngelSWI_Reason_Seek (0x0A) +#define AngelSWI_Reason_FLen (0x0C) +#define AngelSWI_Reason_TmpNam (0x0D) +#define AngelSWI_Reason_Remove (0x0E) +#define AngelSWI_Reason_Rename (0x0F) +#define AngelSWI_Reason_Clock (0x10) +#define AngelSWI_Reason_Time (0x11) +#define AngelSWI_Reason_System (0x12) +#define AngelSWI_Reason_Errno (0x13) +#define AngelSWI_Reason_GetCmdLine (0x15) +#define AngelSWI_Reason_HeapInfo (0x16) +#define AngelSWI_Reason_EnterSVC (0x17) +#define AngelSWI_Reason_ReportException (0x18) +#define ADP_Stopped_ApplicationExit ((2 << 16) + 38) +#define ADP_Stopped_RunTimeError ((2 << 16) + 34) + +#define FPESTART 0x2000L +#define FPEEND 0x8000L +#define FPEOLDVECT FPESTART + 0x100L + 8L * 16L + 4L /* stack + 8 regs + fpsr */ +#define FPENEWVECT(addr) 0xea000000L + ((addr) >> 2) - 3L /* branch from 4 to 0x2400 */ + +extern unsigned long fpecode[] ; +extern unsigned long fpesize ; diff --git a/sim/arm/armrdi.c b/sim/arm/armrdi.c new file mode 100644 index 00000000000..348c7be0f31 --- /dev/null +++ b/sim/arm/armrdi.c @@ -0,0 +1,1044 @@ +/* armrdi.c -- ARMulator RDI interface: ARM6 Instruction Emulator. + Copyright (C) 1994 Advanced RISC Machines Ltd. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include +#include +#include "armdefs.h" +#include "armemu.h" +#include "armos.h" +#include "dbg_cp.h" +#include "dbg_conf.h" +#include "dbg_rdi.h" +#include "dbg_hif.h" +#include "communicate.h" + +/***************************************************************************\ +* Declarations * +\***************************************************************************/ + +#define Watch_AnyRead (RDIWatch_ByteRead+RDIWatch_HalfRead+RDIWatch_WordRead) +#define Watch_AnyWrite (RDIWatch_ByteWrite+RDIWatch_HalfWrite+RDIWatch_WordWrite) + +static unsigned FPRegsAddr ; /* last known address of FPE regs */ +#define FPESTART 0x2000L +#define FPEEND 0x8000L + +#define IGNORE(d) (d = d) +#ifdef RDI_VERBOSE +#define TracePrint(s) \ + if (rdi_log & 1) ARMul_DebugPrint s +#else +#define TracePrint(s) +#endif + +static ARMul_State *state = NULL ; +static unsigned BreaksSet ; /* The number of breakpoints set */ + +static int rdi_log = 0 ; /* debugging ? */ + +#define LOWEST_RDI_LEVEL 0 +#define HIGHEST_RDI_LEVEL 1 +static int MYrdi_level = LOWEST_RDI_LEVEL; + +typedef struct BreakNode BreakNode; +typedef struct WatchNode WatchNode; + +struct BreakNode { /* A breakpoint list node */ + BreakNode *next ; + ARMword address ; /* The address of this breakpoint */ + unsigned type ; /* The type of comparison */ + ARMword bound ; /* The other address for a range */ + ARMword inst; + }; + +struct WatchNode { /* A watchpoint list node */ + WatchNode *next ; + ARMword address ; /* The address of this watchpoint */ + unsigned type ; /* The type of comparison */ + unsigned datatype ; /* The type of access to watch for */ + ARMword bound ; /* The other address for a range */ + }; + +BreakNode *BreakList = NULL ; +WatchNode *WatchList = NULL ; + +void ARMul_DebugPrint_i(const Dbg_HostosInterface *hostif, const char *format, ...) +{ va_list ap; + va_start(ap, format); + hostif->dbgprint(hostif->dbgarg, format, ap); + va_end(ap); +} + +void ARMul_DebugPrint(ARMul_State *state, const char *format, ...) +{ va_list ap; + va_start(ap, format); + if(!(rdi_log & 8)) + state->hostif->dbgprint(state->hostif->dbgarg, format, ap); + va_end(ap); +} + +#define CONSOLE_PRINT_MAX_LEN 128 + +void ARMul_ConsolePrint(ARMul_State *state, const char *format, ...) +{ + va_list ap; + int ch; + char *str, buf[CONSOLE_PRINT_MAX_LEN]; + int i, j; + ARMword junk; + + va_start(ap, format); + vsprintf(buf, format, ap); + + for (i = 0; buf[i] ;i++); /* The string is i chars long */ + + str = buf; + while (i >= 32) { + MYwrite_char(kidmum[1], RDP_OSOp); + MYwrite_word(kidmum[1], SWI_Write0); + MYwrite_char(kidmum[1], OS_SendString); + MYwrite_char(kidmum[1], 32); /* Send string 32bytes at a time */ + for (j = 0; j < 32; j++, str++) + MYwrite_char(kidmum[1], *str); + wait_for_osreply(&junk); + i -= 32; + } + + if (i > 0) { + MYwrite_char(kidmum[1], RDP_OSOp); + MYwrite_word(kidmum[1], SWI_Write0); + MYwrite_char(kidmum[1], OS_SendString); + MYwrite_char(kidmum[1], (unsigned char) i); /* Send remainder of string */ + for (j = 0; j < i; j++, str++) + MYwrite_char(kidmum[1], *str); + wait_for_osreply(&junk); + } + + va_end (ap); + return; + +/* str = buf; */ +/* while ((ch=*str++) != 0) */ +/* state->hostif->writec(state->hostif->hostosarg, ch); */ +} + +void ARMul_DebugPause(ARMul_State *state) +{ + if(!(rdi_log & 8)) + state->hostif->dbgpause(state->hostif->dbgarg); +} + +/***************************************************************************\ +* RDI_open * +\***************************************************************************/ + +static void InitFail(int exitcode, char const *which) { + ARMul_ConsolePrint(state, "%s interface failed to initialise. Exiting\n", + which); + exit(exitcode); +} + +static void RDIInit(unsigned type) +{if (type == 0) { /* cold start */ + state->CallDebug = state->MemReadDebug = state->MemWriteDebug = 0 ; + BreaksSet = 0 ; + } + } + +#define UNKNOWNPROC 0 + +typedef struct { char name[16]; unsigned val; } Processor; + +Processor const p_arm2 = {"ARM2", ARM2}; +Processor const p_arm2as = {"ARM2AS", ARM2as}; +Processor const p_arm61 = {"ARM61", ARM61}; +Processor const p_arm3 = {"ARM3", ARM3}; +Processor const p_arm6 = {"ARM6", ARM6}; +Processor const p_arm60 = {"ARM60", ARM60}; +Processor const p_arm600 = {"ARM600", ARM600}; +Processor const p_arm610 = {"ARM610", ARM610}; +Processor const p_arm620 = {"ARM620", ARM620}; +Processor const p_unknown= {"", UNKNOWNPROC}; + +Processor const *const processors[] = { + &p_arm6, /* default: must come first */ + &p_arm2, + &p_arm2as, + &p_arm61, + &p_arm3, + &p_arm60, + &p_arm600, + &p_arm610, + &p_arm620, + &p_unknown +}; + +typedef struct ProcessorConfig ProcessorConfig; +struct ProcessorConfig { + long id[2]; + ProcessorConfig const *self; + long count; + Processor const * const *processors; +}; + +ProcessorConfig const processorconfig = { + { ((((((long)'x' << 8) | ' ') << 8) | 'c') << 8) | 'p', + ((((((long)'u' << 8) | 's') << 8) | ' ') << 8) | 'x' + }, + &processorconfig, + 16, + processors +}; + +static int RDI_open(unsigned type, const Dbg_ConfigBlock *config, + const Dbg_HostosInterface *hostif, + struct Dbg_MCState *dbg_state) +/* Initialise everything */ +{int virgin = (state == NULL); + IGNORE(dbg_state); + +#ifdef RDI_VERBOSE + if (rdi_log & 1) { + if (virgin) + ARMul_DebugPrint_i(hostif, "RDI_open: type = %d\n",type) ; + else + ARMul_DebugPrint(state, "RDI_open: type = %d\n",type) ; + } +#endif + + if (type & 1) { /* Warm start */ + ARMul_Reset(state) ; + RDIInit(1) ; + } + else { + if (virgin) { + ARMul_EmulateInit(); + state = ARMul_NewState(); + state->hostif = hostif; + { int req = config->processor; + unsigned processor = processors[req]->val; + ARMul_SelectProcessor(state, processor); + ARMul_Reset(state); + ARMul_ConsolePrint(state, "ARMulator V1.50, %s", processors[req]->name); + } + if (ARMul_MemoryInit(state,config->memorysize) == FALSE) + InitFail(1, "Memory"); + if (config->bytesex != RDISex_DontCare) + state->bigendSig = config->bytesex ; + if (ARMul_CoProInit(state) == FALSE) + InitFail(2, "Co-Processor"); + if (ARMul_OSInit(state) == FALSE) + InitFail(3, "Operating System"); + } + ARMul_Reset(state) ; + RDIInit(0) ; + } + if (type & 2) { /* Reset the comms link */ + /* what comms link ? */ + } + if (virgin && (type & 1) == 0) /* Cold start */ + ARMul_ConsolePrint(state, ", %s endian.\n", + state->bigendSig ? "Big" : "Little"); + + if (config->bytesex == RDISex_DontCare) + return(state->bigendSig ? RDIError_BigEndian : RDIError_LittleEndian); + else + return(RDIError_NoError) ; +} + +/***************************************************************************\ +* RDI_close * +\***************************************************************************/ + +static int RDI_close(void) +{ + TracePrint((state, "RDI_close\n")); + ARMul_OSExit(state) ; + ARMul_CoProExit(state) ; + ARMul_MemoryExit(state) ; + return(RDIError_NoError) ; + } + +/***************************************************************************\ +* RDI_read * +\***************************************************************************/ + +static int RDI_read(ARMword source, void *dest, unsigned *nbytes) +{unsigned i ; + char *memptr = (char *)dest ; + + TracePrint((state, "RDI_read: source=%.8lx dest=%p nbytes=%.8x\n", + source, dest, *nbytes)); + + for (i=0 ; i < *nbytes ; i++) + *memptr++ = (char)ARMul_ReadByte(state,source++) ; + if (state->abortSig) { + state->abortSig = LOW ; + return(RDIError_DataAbort) ; + } + return(RDIError_NoError) ; + } + +/***************************************************************************\ +* RDI_write * +\***************************************************************************/ + +static int RDI_write(const void *source, ARMword dest, unsigned *nbytes) +{unsigned i ; + char *memptr = (char *)source ; + + TracePrint((state, "RDI_write: source=%p dest=%.8lx nbytes=%.8x\n", + source, dest, *nbytes)); + + for (i=0 ; i < *nbytes ; i++) + ARMul_WriteByte(state,(ARMword)dest++,(ARMword)*memptr++) ; + + if (state->abortSig) { + state->abortSig = LOW ; + return(RDIError_DataAbort) ; + } + return(RDIError_NoError) ; + } + +/***************************************************************************\ +* RDI_CPUread * +\***************************************************************************/ + +static int RDI_CPUread(unsigned mode, unsigned long mask, ARMword buffer[]) +{unsigned i , upto ; + + if (mode == RDIMode_Curr) + mode = (unsigned)(ARMul_GetCPSR(state) & MODEBITS) ; + + for (upto = 0, i = 0 ; i < 15 ; i++) + if (mask & (1L << i)){ + buffer[upto++] = ARMul_GetReg(state,mode,i) ; + } + + if (mask & RDIReg_R15) { + buffer[upto++] = ARMul_GetR15(state) ; + } + + if (mask & RDIReg_PC) { + buffer[upto++] = ARMul_GetPC(state) ; + } + + if (mask & RDIReg_CPSR) + buffer[upto++] = ARMul_GetCPSR(state) ; + + if (mask & RDIReg_SPSR) + buffer[upto++] = ARMul_GetSPSR(state,mode) ; + + TracePrint((state, "RDI_CPUread: mode=%.8x mask=%.8lx", mode, mask)); +#ifdef RDI_VERBOSE + if (rdi_log & 1) { + for (upto = 0, i = 0 ; i <= 20 ; i++) + if (mask & (1L << i)) { + ARMul_DebugPrint(state, "%c%.8lx",upto%4==0?'\n':' ',buffer[upto]) ; + upto++ ; + } + ARMul_DebugPrint(state, "\n") ; + } +#endif + + return(RDIError_NoError) ; +} + +/***************************************************************************\ +* RDI_CPUwrite * +\***************************************************************************/ + +static int RDI_CPUwrite(unsigned mode, unsigned long mask, ARMword const buffer[]) +{int i, upto; + + + TracePrint((state, "RDI_CPUwrite: mode=%.8x mask=%.8lx", mode, mask)); +#ifdef RDI_VERBOSE + if (rdi_log & 1) { + for (upto = 0, i = 0 ; i <= 20 ; i++) + if (mask & (1L << i)) { + ARMul_DebugPrint(state, "%c%.8lx",upto%4==0?'\n':' ',buffer[upto]) ; + upto++ ; + } + ARMul_DebugPrint(state, "\n") ; + } +#endif + + if (mode == RDIMode_Curr) + mode = (unsigned)(ARMul_GetCPSR(state) & MODEBITS) ; + + for (upto = 0, i = 0 ; i < 15 ; i++) + if (mask & (1L << i)) + ARMul_SetReg(state,mode,i,buffer[upto++]) ; + + if (mask & RDIReg_R15) + ARMul_SetR15(state,buffer[upto++]) ; + + if (mask & RDIReg_PC) { + + ARMul_SetPC(state,buffer[upto++]) ; + } + if (mask & RDIReg_CPSR) + ARMul_SetCPSR(state,buffer[upto++]) ; + + if (mask & RDIReg_SPSR) + ARMul_SetSPSR(state,mode,buffer[upto++]) ; + + return(RDIError_NoError) ; +} + +/***************************************************************************\ +* RDI_CPread * +\***************************************************************************/ + +static int RDI_CPread(unsigned CPnum, unsigned long mask, ARMword buffer[]) +{ARMword fpregsaddr, word[4] ; + + unsigned r, w ; + unsigned upto ; + + if (CPnum != 1 && CPnum != 2) { + unsigned char const *rmap = state->CPRegWords[CPnum]; + if (rmap == NULL) + return(RDIError_UnknownCoPro) ; + for (upto = 0, r = 0 ; r < rmap[-1] ; r++) + if (mask & (1L << r)) { + (void)state->CPRead[CPnum](state, r, &buffer[upto]); + upto += rmap[r]; + } + TracePrint((state, "RDI_CPread: CPnum=%d mask=%.8lx", CPnum, mask)); +#ifdef RDI_VERBOSE + if (rdi_log & 1) { + w = 0; + for (upto = 0, r = 0; r < rmap[-1]; r++) + if (mask & (1L << r)) { + int words = rmap[r]; + ARMul_DebugPrint(state, "%c%2d", (w >= 4 ? (w = 0, '\n') : ' '), r); + while (--words >= 0) { + ARMul_DebugPrint(state, " %.8lx", buffer[upto++]); + w++; + } + } + ARMul_DebugPrint(state, "\n") ; + } +#endif + return RDIError_NoError; + } + +#ifdef NOFPE + return RDIError_UnknownCoPro; + +#else + if (FPRegsAddr == 0) { + fpregsaddr = ARMul_ReadWord(state, 4L) ; + if ((fpregsaddr & 0xff800000) != 0xea000000) /* Must be a forward branch */ + return RDIError_UnknownCoPro; + fpregsaddr = ((fpregsaddr & 0xffffff) << 2) + 8 ; /* address in __fp_decode - 4 */ + if ((fpregsaddr < FPESTART) || (fpregsaddr >= FPEEND)) + return RDIError_UnknownCoPro; + fpregsaddr = ARMul_ReadWord(state, fpregsaddr) ; /* pointer to fp registers */ + FPRegsAddr = fpregsaddr ; + } + else + fpregsaddr = FPRegsAddr ; + + if (fpregsaddr == 0) return RDIError_UnknownCoPro; + for (upto = 0, r = 0 ; r < 8 ; r++) + if (mask & (1L << r)) { + for (w = 0 ; w < 4 ; w++) + word[w] = ARMul_ReadWord(state,fpregsaddr + (ARMword)r * 16 + (ARMword)w * 4) ; + switch ((int)(word[3] >> 29)) { + case 0 : + case 2 : + case 4 : + case 6 : /* its unpacked, convert to extended */ + buffer[upto++] = 2 ; /* mark as extended */ + buffer[upto++] = (word[3] & 0x7fff) | (word[0] & 0x80000000) ; /* exp and sign */ + buffer[upto++] = word[1] ; /* mantissa 1 */ + buffer[upto++] = word[2] ; /* mantissa 2 */ + break ; + case 1 : /* packed single */ + buffer[upto++] = 0 ; /* mark as single */ + buffer[upto++] = word[0] ; /* sign, exp and mantissa */ + buffer[upto++] = word[1] ; /* padding */ + buffer[upto++] = word[2] ; /* padding */ + break ; + case 3 : /* packed double */ + buffer[upto++] = 1 ; /* mark as double */ + buffer[upto++] = word[0] ; /* sign, exp and mantissa1 */ + buffer[upto++] = word[1] ; /* mantissa 2 */ + buffer[upto++] = word[2] ; /* padding */ + break ; + case 5 : /* packed extended */ + buffer[upto++] = 2 ; /* mark as extended */ + buffer[upto++] = word[0] ; /* sign and exp */ + buffer[upto++] = word[1] ; /* mantissa 1 */ + buffer[upto++] = word[2] ; /* mantissa 2 */ + break ; + case 7 : /* packed decimal */ + buffer[upto++] = 3 ; /* mark as packed decimal */ + buffer[upto++] = word[0] ; /* sign, exp and mantissa1 */ + buffer[upto++] = word[1] ; /* mantissa 2 */ + buffer[upto++] = word[2] ; /* mantissa 3 */ + break ; + } + } + if (mask & (1L << r)) + buffer[upto++] = ARMul_ReadWord(state,fpregsaddr + 128) ; /* fpsr */ + if (mask & (1L << (r+1) )) + buffer[upto++] = 0 ; /* fpcr */ + + TracePrint((state, "RDI_CPread: CPnum=%d mask=%.8lx\n", CPnum, mask)); +#ifdef RDI_VERBOSE + if (rdi_log & 1) { + for (upto = 0, r = 0 ; r < 9 ; r++) + if (mask & (1L << r)) { + if (r != 8) { + ARMul_DebugPrint(state, "%08lx ",buffer[upto++]) ; + ARMul_DebugPrint(state, "%08lx ",buffer[upto++]) ; + ARMul_DebugPrint(state, "%08lx ",buffer[upto++]) ; + } + ARMul_DebugPrint(state, "%08lx\n",buffer[upto++]) ; + } + ARMul_DebugPrint(state, "\n") ; + } +#endif + return(RDIError_NoError) ; +#endif /* NOFPE */ + } + +/***************************************************************************\ +* RDI_CPwrite * +\***************************************************************************/ + +static int RDI_CPwrite(unsigned CPnum, unsigned long mask, ARMword const buffer[]) +{unsigned r ; + unsigned upto ; + ARMword fpregsaddr; + + if (CPnum != 1 && CPnum != 2) { + unsigned char const *rmap = state->CPRegWords[CPnum]; + if (rmap == NULL) + return(RDIError_UnknownCoPro) ; + TracePrint((state, "RDI_CPwrite: CPnum=%d mask=%.8lx", CPnum, mask)); +#ifdef RDI_VERBOSE + if (rdi_log & 1) { + int w = 0; + for (upto = 0, r = 0; r < rmap[-1]; r++) + if (mask & (1L << r)) { + int words = rmap[r]; + ARMul_DebugPrint(state, "%c%2d", (w >= 4 ? (w = 0, '\n') : ' '), r); + while (--words >= 0) { + ARMul_DebugPrint(state, " %.8lx", buffer[upto++]); + w++; + } + } + ARMul_DebugPrint(state, "\n") ; + } +#endif + for (upto = 0, r = 0; r < rmap[-1]; r++) + if (mask & (1L << r)) { + (void)state->CPWrite[CPnum](state, r, &buffer[upto]); + upto += rmap[r]; + } + return RDIError_NoError; + } + +#ifdef NOFPE + return RDIError_UnknownCoPro; + +#else + TracePrint((state, "RDI_CPwrite: CPnum=%d mask=%.8lx", CPnum, mask)); +#ifdef RDI_VERBOSE + if (rdi_log & 1) { + for (upto = 0, r = 0 ; r < 9 ; r++) + if (mask & (1L << r)) { + if (r != 8) { + ARMul_DebugPrint(state, "%08lx ",buffer[upto++]) ; + ARMul_DebugPrint(state, "%08lx ",buffer[upto++]) ; + ARMul_DebugPrint(state, "%08lx ",buffer[upto++]) ; + } + ARMul_DebugPrint(state, "%08lx\n",buffer[upto++]) ; + } + ARMul_DebugPrint(state, "\n") ; + } +#endif + + if (FPRegsAddr == 0) { + fpregsaddr = ARMul_ReadWord(state, 4L) ; + if ((fpregsaddr & 0xff800000) != 0xea000000) /* Must be a forward branch */ + return RDIError_UnknownCoPro; + fpregsaddr = ((fpregsaddr & 0xffffff) << 2) + 8 ; /* address in __fp_decode - 4 */ + if ((fpregsaddr < FPESTART) || (fpregsaddr >= FPEEND)) + return RDIError_UnknownCoPro; + fpregsaddr = ARMul_ReadWord(state, fpregsaddr) ; /* pointer to fp registers */ + FPRegsAddr = fpregsaddr ; + } + else + fpregsaddr = FPRegsAddr ; + + if (fpregsaddr == 0) return RDIError_UnknownCoPro; + for (upto = 0, r = 0 ; r < 8 ; r++) + if (mask & (1L << r)) { + ARMul_WriteWord(state,fpregsaddr + (ARMword)r * 16,buffer[upto+1]) ; + ARMul_WriteWord(state,fpregsaddr + (ARMword)r * 16 + 4,buffer[upto+2]) ; + ARMul_WriteWord(state,fpregsaddr + (ARMword)r * 16 + 8,buffer[upto+3]) ; + ARMul_WriteWord(state,fpregsaddr + (ARMword)r * 16 + 12,(buffer[upto] * 2 + 1) << 29) ; /* mark type */ + upto += 4 ; + } + if (mask & (1L << r)) + ARMul_WriteWord(state,fpregsaddr + 128,buffer[upto++]) ; /* fpsr */ + return(RDIError_NoError) ; +#endif /* NOFPE */ +} + +static void deletebreaknode(BreakNode **prevp) { + BreakNode *p = *prevp; + *prevp = p->next; + ARMul_WriteWord(state, p->address, p->inst); + free((char *)p); + BreaksSet-- ; + state->CallDebug-- ; +} + +static int removebreak(ARMword address, unsigned type) +{ BreakNode *p, **prevp = &BreakList; + for (; (p = *prevp) != NULL ; prevp = &p->next) + if (p->address == address && p->type == type) { + deletebreaknode(prevp); + return TRUE; + } + return FALSE; +} + +/* This routine installs a breakpoint into the breakpoint table */ + +static BreakNode *installbreak(ARMword address, unsigned type, ARMword bound) +{ BreakNode *p = (BreakNode *)malloc(sizeof(BreakNode)); + p->next = BreakList; + BreakList = p; + p->address = address; + p->type = type; + p->bound = bound; + p->inst = ARMul_ReadWord(state, address); + ARMul_WriteWord(state, address, 0xee000000L); + return p; +} + +/***************************************************************************\ +* RDI_setbreak * +\***************************************************************************/ + +static int RDI_setbreak(ARMword address, unsigned type, ARMword bound, + PointHandle *handle) +{ BreakNode *p; + TracePrint((state, "RDI_setbreak: address=%.8lx type=%d bound=%.8lx\n", + address, type, bound)); + + removebreak(address, type); + p = installbreak(address, type, bound); + BreaksSet++ ; + state->CallDebug++ ; + *handle = (PointHandle)p; + TracePrint((state, " returns %.8lx\n", *handle)); + return RDIError_NoError; +} + +/***************************************************************************\ +* RDI_clearbreak * +\***************************************************************************/ + +static int RDI_clearbreak(PointHandle handle) +{ TracePrint((state, "RDI_clearbreak: address=%.8lx\n", handle)); + { BreakNode *p, **prevp = &BreakList; + for (; (p = *prevp) != NULL; prevp = &p->next) + if (p == (BreakNode *)handle) break; + if (p == NULL) return RDIError_NoSuchPoint; + deletebreaknode(prevp); + return RDIError_NoError; + } +} + +/***************************************************************************\ +* Internal functions for breakpoint table manipulation * +\***************************************************************************/ + +static void deletewatchnode(WatchNode **prevp) +{ WatchNode *p = *prevp; + if (p->datatype & Watch_AnyRead) state->MemReadDebug--; + if (p->datatype & Watch_AnyWrite) state->MemWriteDebug--; + *prevp = p->next; + free((char *)p); +} + +int removewatch(ARMword address, unsigned type) +{ WatchNode *p, **prevp = &WatchList; + for (; (p = *prevp) != NULL ; prevp = &p->next) + if (p->address == address && p->type == type) { /* found a match */ + deletewatchnode(prevp); + return TRUE; + } + return FALSE; /* never found a match */ +} + +static WatchNode *installwatch(ARMword address, unsigned type, unsigned datatype, + ARMword bound) +{ WatchNode *p = (WatchNode *)malloc(sizeof(WatchNode)); + p->next = WatchList; + WatchList = p; + p->address = address; + p->type = type; + p->datatype = datatype; + p->bound = bound; + return p; +} + +/***************************************************************************\ +* RDI_setwatch * +\***************************************************************************/ + +static int RDI_setwatch(ARMword address, unsigned type, unsigned datatype, + ARMword bound, PointHandle *handle) +{ WatchNode *p; + TracePrint((state, "RDI_setwatch: address=%.8lx type=%d datatype=%d bound=%.8lx", + address, type, datatype, bound)); + + if (!state->CanWatch) return RDIError_UnimplementedMessage; + + removewatch(address, type); + p = installwatch(address, type, datatype, bound); + if (datatype & Watch_AnyRead) state->MemReadDebug++; + if (datatype & Watch_AnyWrite) state->MemWriteDebug++; + *handle = (PointHandle)p; + TracePrint((state, " returns %.8lx\n", *handle)); + return RDIError_NoError; +} + +/***************************************************************************\ +* RDI_clearwatch * +\***************************************************************************/ + +static int RDI_clearwatch(PointHandle handle) +{ TracePrint((state, "RDI_clearwatch: address=%.8lx\n", handle)); + { WatchNode *p, **prevp = &WatchList; + for (; (p = *prevp) != NULL; prevp = &p->next) + if (p == (WatchNode *)handle) break; + if (p == NULL) return RDIError_NoSuchPoint; + deletewatchnode(prevp); + return RDIError_NoError; + } +} + +/***************************************************************************\ +* RDI_execute * +\***************************************************************************/ + +static int RDI_execute(PointHandle *handle) +{ + TracePrint((state, "RDI_execute\n")); + if (rdi_log & 4) { + state->CallDebug++ ; + state->Debug = TRUE ; + } + state->EndCondition = RDIError_NoError ; + state->StopHandle = 0; + + ARMul_DoProg(state); + + *handle = state->StopHandle; + state->Reg[15] -= 8 ; /* undo the pipeline */ + if (rdi_log & 4) { + state->CallDebug-- ; + state->Debug = FALSE ; + } + return(state->EndCondition) ; +} + +/***************************************************************************\ +* RDI_step * +\***************************************************************************/ + +static int RDI_step(unsigned ninstr, PointHandle *handle) +{ + + TracePrint((state, "RDI_step\n")); + if (ninstr != 1) return RDIError_UnimplementedMessage; + if (rdi_log & 4) { + state->CallDebug++ ; + state->Debug = TRUE ; + } + state->EndCondition = RDIError_NoError ; + state->StopHandle = 0; + ARMul_DoInstr(state) ; + *handle = state->StopHandle; + state->Reg[15] -= 8 ; /* undo the pipeline */ + if (rdi_log & 4) { + state->CallDebug-- ; + state->Debug = FALSE ; + } + return(state->EndCondition) ; +} + +/***************************************************************************\ +* RDI_info * +\***************************************************************************/ + +static int RDI_info(unsigned type, ARMword *arg1, ARMword *arg2) +{ + switch (type) { + case RDIInfo_Target: + TracePrint((state, "RDI_Info_Target\n")); + /* Emulator, speed 10**5 IPS */ + *arg1 = 5 | HIGHEST_RDI_LEVEL << 5 | LOWEST_RDI_LEVEL << 8; + *arg2 = 1298224434; + return RDIError_NoError; + + case RDIInfo_Points: + { ARMword n = RDIPointCapability_Comparison | RDIPointCapability_Range | + RDIPointCapability_Mask | RDIPointCapability_Status; + TracePrint((state, "RDI_Info_Points\n")); + if (state->CanWatch) n |= (Watch_AnyRead+Watch_AnyWrite) << 2; + *arg1 = n; + return RDIError_NoError; + } + + case RDIInfo_Step: + TracePrint((state, "RDI_Info_Step\n")); + *arg1 = RDIStep_Single; + return RDIError_NoError; + + case RDIInfo_MMU: + TracePrint((state, "RDI_Info_MMU\n")); + *arg1 = 1313820229 ; + return RDIError_NoError; + + case RDISignal_Stop: + TracePrint((state, "RDISignal_Stop\n")); + state->CallDebug++ ; + state->EndCondition = RDIError_UserInterrupt ; + return RDIError_NoError; + + case RDIVector_Catch: + TracePrint((state, "RDIVector_Catch %.8lx\n", *arg1)); + state->VectorCatch = (unsigned)*arg1 ; + return RDIError_NoError; + + case RDISet_Cmdline: + TracePrint((state, "RDI_Set_Cmdline %s\n", (char *)arg1)); + state->CommandLine = (char *)malloc((unsigned)strlen((char *)arg1)+1) ; + (void)strcpy(state->CommandLine,(char *)arg1) ; + return RDIError_NoError; + + case RDICycles: + TracePrint((state, "RDI_Info_Cycles\n")); + arg1[0] = 0; + arg1[1] = state->NumInstrs; + arg1[2] = 0; + arg1[3] = state->NumScycles; + arg1[4] = 0; + arg1[5] = state->NumNcycles; + arg1[6] = 0; + arg1[7] = state->NumIcycles; + arg1[8] = 0; + arg1[9] = state->NumCcycles; + arg1[10] = 0; + arg1[11] = state->NumFcycles; + return RDIError_NoError; + + case RDIErrorP: + *arg1 = ARMul_OSLastErrorP(state); + TracePrint((state, "RDI_ErrorP returns %ld\n", *arg1)); + return RDIError_NoError; + + case RDIInfo_DescribeCoPro: + { int cpnum = *(int *)arg1; + struct Dbg_CoProDesc *cpd = (struct Dbg_CoProDesc *)arg2; + int i; + unsigned char const *map = state->CPRegWords[cpnum]; + if (map == NULL) return RDIError_UnknownCoPro; + for (i = 0; i < cpd->entries; i++) { + unsigned r, w = cpd->regdesc[i].nbytes / sizeof(ARMword); + for (r = cpd->regdesc[i].rmin; r <= cpd->regdesc[i].rmax; r++) + if (map[r] != w) return RDIError_BadCoProState; + } + return RDIError_NoError; + } + + case RDIInfo_RequestCoProDesc: + { int cpnum = *(int *)arg1; + struct Dbg_CoProDesc *cpd = (struct Dbg_CoProDesc *)arg2; + int i = -1, lastw = -1, r; + unsigned char const *map; + if ((unsigned)cpnum >= 16) return RDIError_UnknownCoPro; + map = state->CPRegWords[cpnum]; + if (map == NULL) return RDIError_UnknownCoPro; + for (r = 0; r < map[-1]; r++) { + int words = map[r]; + if (words == lastw) + cpd->regdesc[i].rmax = r; + else { + if (++i >= cpd->entries) return RDIError_BufferFull; + cpd->regdesc[i].rmax = cpd->regdesc[i].rmin = r; + cpd->regdesc[i].nbytes = words * sizeof(ARMword); + cpd->regdesc[i].access = Dbg_Access_Readable+Dbg_Access_Writable; + } + } + cpd->entries = i+1; + return RDIError_NoError; + } + + case RDIInfo_Log: + *arg1 = (ARMword)rdi_log; + return RDIError_NoError; + + case RDIInfo_SetLog: + rdi_log = (int)*arg1; + return RDIError_NoError; + + case RDIInfo_CoPro: + return RDIError_NoError; + + case RDIPointStatus_Watch: + { WatchNode *p, *handle = (WatchNode *)*arg1; + for (p = WatchList; p != NULL; p = p->next) + if (p == handle) { + *arg1 = -1; + *arg2 = 1; + return RDIError_NoError; + } + return RDIError_NoSuchPoint; + } + + case RDIPointStatus_Break: + { BreakNode *p, *handle = (BreakNode *)*arg1; + for (p = BreakList; p != NULL; p = p->next) + if (p == handle) { + *arg1 = -1; + *arg2 = 1; + return RDIError_NoError; + } + return RDIError_NoSuchPoint; + } + + case RDISet_RDILevel: + if (*arg1 < LOWEST_RDI_LEVEL || *arg1 > HIGHEST_RDI_LEVEL) + return RDIError_IncompatibleRDILevels; + MYrdi_level = *arg1; + return RDIError_NoError; + + default: + return RDIError_UnimplementedMessage; + + } +} + +/***************************************************************************\ +* The emulator calls this routine at the beginning of every cycle when the * +* CallDebug flag is set. The second parameter passed is the address of the * +* currently executing instruction (i.e Program Counter - 8), the third * +* parameter is the instruction being executed. * +\***************************************************************************/ + +ARMword ARMul_Debug(ARMul_State *state, ARMword pc, ARMword instr) +{ + + if (state->EndCondition == RDIError_UserInterrupt) { + TracePrint((state, "User interrupt at %.8lx\n", pc)); + state->CallDebug--; + state->Emulate = STOP; + } else { + BreakNode *p = BreakList; + for (; p != NULL ; p = p->next) { + switch (p->type) { + case RDIPoint_EQ: if (pc == p->address) break; continue; + case RDIPoint_GT: if (pc > p->address) break; continue; + case RDIPoint_GE: if (pc >= p->address) break; continue; + case RDIPoint_LT: if (pc < p->address) break; continue; + case RDIPoint_LE: if (pc <= p->address) break; continue; + case RDIPoint_IN: if (p->address <= pc && pc < p->address+p->bound) break; + continue; + case RDIPoint_OUT:if (p->address > pc || pc >= p->address+p->bound) break; + continue; + case RDIPoint_MASK:if ((pc & p->bound) == p->address) break; continue; + } + /* found a match */ + TracePrint((state, "Breakpoint reached at %.8lx\n", pc)); + state->EndCondition = RDIError_BreakpointReached ; + state->Emulate = STOP; + state->StopHandle = (ARMword)p; + break; + } + } + return instr; +} + +void ARMul_CheckWatch(ARMul_State *state, ARMword addr, int access) +{ WatchNode *p; + for (p = WatchList; p != NULL; p = p->next) + if (p->datatype & access) { + switch (p->type) { + case RDIPoint_EQ: if (addr == p->address) break; continue; + case RDIPoint_GT: if (addr > p->address) break; continue; + case RDIPoint_GE: if (addr >= p->address) break; continue; + case RDIPoint_LT: if (addr < p->address) break; continue; + case RDIPoint_LE: if (addr <= p->address) break; continue; + case RDIPoint_IN: if (p->address <= addr && addr < p->address+p->bound) break; + continue; + case RDIPoint_OUT:if (p->address > addr || addr >= p->address+p->bound) break; + continue; + case RDIPoint_MASK:if ((addr & p->bound) == p->address) break; continue; + } + /* found a match */ + TracePrint((state, "Watchpoint at %.8lx accessed\n", addr)); + state->EndCondition = RDIError_WatchpointAccessed; + state->Emulate = STOP; + state->StopHandle = (ARMword)p; + return; + } +} + +static RDI_NameList const *RDI_cpunames() { + return (RDI_NameList const *)&processorconfig.count; +} + +const struct RDIProcVec armul_rdi = { + "ARMUL", + RDI_open, + RDI_close, + RDI_read, + RDI_write, + RDI_CPUread, + RDI_CPUwrite, + RDI_CPread, + RDI_CPwrite, + RDI_setbreak, + RDI_clearbreak, + RDI_setwatch, + RDI_clearwatch, + RDI_execute, + RDI_step, + RDI_info, + + 0, /*pointinq*/ + 0, /*addconfig*/ + 0, /*loadconfigdata*/ + 0, /*selectconfig*/ + 0, /*drivernames*/ + + RDI_cpunames +}; + diff --git a/sim/arm/armsupp.c b/sim/arm/armsupp.c new file mode 100644 index 00000000000..67edd95594d --- /dev/null +++ b/sim/arm/armsupp.c @@ -0,0 +1,712 @@ +/* armsupp.c -- ARMulator support code: ARM6 Instruction Emulator. + Copyright (C) 1994 Advanced RISC Machines Ltd. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "armdefs.h" +#include "armemu.h" + +/***************************************************************************\ +* Definitions for the support routines * +\***************************************************************************/ + +ARMword ARMul_GetReg(ARMul_State *state, unsigned mode, unsigned reg) ; +void ARMul_SetReg(ARMul_State *state, unsigned mode, unsigned reg, ARMword value) ; +ARMword ARMul_GetPC(ARMul_State *state) ; +ARMword ARMul_GetNextPC(ARMul_State *state) ; +void ARMul_SetPC(ARMul_State *state, ARMword value) ; +ARMword ARMul_GetR15(ARMul_State *state) ; +void ARMul_SetR15(ARMul_State *state, ARMword value) ; + +ARMword ARMul_GetCPSR(ARMul_State *state) ; +void ARMul_SetCPSR(ARMul_State *state, ARMword value) ; +void ARMul_FixCPSR(ARMul_State *state, ARMword instr, ARMword rhs) ; +ARMword ARMul_GetSPSR(ARMul_State *state, ARMword mode) ; +void ARMul_SetSPSR(ARMul_State *state, ARMword mode, ARMword value) ; +void ARMul_FixSPSR(ARMul_State *state, ARMword instr, ARMword rhs) ; + +void ARMul_CPSRAltered(ARMul_State *state) ; +void ARMul_R15Altered(ARMul_State *state) ; + +ARMword ARMul_SwitchMode(ARMul_State *state,ARMword oldmode, ARMword newmode) ; +static ARMword ModeToBank(ARMul_State *state,ARMword mode) ; + +unsigned ARMul_NthReg(ARMword instr, unsigned number) ; + +void ARMul_NegZero(ARMul_State *state, ARMword result) ; +void ARMul_AddCarry(ARMul_State *state, ARMword a, ARMword b, ARMword result) ; +void ARMul_AddOverflow(ARMul_State *state, ARMword a, ARMword b, ARMword result) ; +void ARMul_SubCarry(ARMul_State *state, ARMword a, ARMword b, ARMword result) ; +void ARMul_SubOverflow(ARMul_State *state, ARMword a, ARMword b, ARMword result) ; + +void ARMul_LDC(ARMul_State *state,ARMword instr,ARMword address) ; +void ARMul_STC(ARMul_State *state,ARMword instr,ARMword address) ; +void ARMul_MCR(ARMul_State *state,ARMword instr, ARMword source) ; +ARMword ARMul_MRC(ARMul_State *state,ARMword instr) ; +void ARMul_CDP(ARMul_State *state,ARMword instr) ; +void ARMul_UndefInstr(ARMul_State *state,ARMword instr) ; +unsigned IntPending(ARMul_State *state) ; + +ARMword ARMul_Align(ARMul_State *state, ARMword address, ARMword data) ; + +void ARMul_ScheduleEvent(ARMul_State *state, unsigned long delay, + unsigned (*what)()) ; +void ARMul_EnvokeEvent(ARMul_State *state) ; +unsigned long ARMul_Time(ARMul_State *state) ; +static void EnvokeList(ARMul_State *state, unsigned long from, unsigned long to) ; + +struct EventNode { /* An event list node */ + unsigned (*func)() ; /* The function to call */ + struct EventNode *next ; + } ; + +/***************************************************************************\ +* This routine returns the value of a register from a mode. * +\***************************************************************************/ + +ARMword ARMul_GetReg(ARMul_State *state, unsigned mode, unsigned reg) +{mode &= MODEBITS ; + if (mode != state->Mode) + return(state->RegBank[ModeToBank(state,(ARMword)mode)][reg]) ; + else + return(state->Reg[reg]) ; +} + +/***************************************************************************\ +* This routine sets the value of a register for a mode. * +\***************************************************************************/ + +void ARMul_SetReg(ARMul_State *state, unsigned mode, unsigned reg, ARMword value) +{mode &= MODEBITS ; + if (mode != state->Mode) + state->RegBank[ModeToBank(state,(ARMword)mode)][reg] = value ; + else + state->Reg[reg] = value ; +} + +/***************************************************************************\ +* This routine returns the value of the PC, mode independently. * +\***************************************************************************/ + +ARMword ARMul_GetPC(ARMul_State *state) +{if (state->Mode > SVC26MODE) + return(state->Reg[15]) ; + else + return(R15PC) ; +} + +/***************************************************************************\ +* This routine returns the value of the PC, mode independently. * +\***************************************************************************/ + +ARMword ARMul_GetNextPC(ARMul_State *state) +{if (state->Mode > SVC26MODE) + return(state->Reg[15] + isize) ; + else + return((state->Reg[15] + isize) & R15PCBITS) ; +} + +/***************************************************************************\ +* This routine sets the value of the PC. * +\***************************************************************************/ + +void ARMul_SetPC(ARMul_State *state, ARMword value) +{if (ARMul_MODE32BIT) + state->Reg[15] = value & PCBITS ; + else + state->Reg[15] = R15CCINTMODE | (value & R15PCBITS) ; + FLUSHPIPE ; +} + +/***************************************************************************\ +* This routine returns the value of register 15, mode independently. * +\***************************************************************************/ + +ARMword ARMul_GetR15(ARMul_State *state) +{if (state->Mode > SVC26MODE) + return(state->Reg[15]) ; + else + return(R15PC | ECC | ER15INT | EMODE) ; +} + +/***************************************************************************\ +* This routine sets the value of Register 15. * +\***************************************************************************/ + +void ARMul_SetR15(ARMul_State *state, ARMword value) +{ + if (ARMul_MODE32BIT) + state->Reg[15] = value & PCBITS ; + else { + state->Reg[15] = value ; + ARMul_R15Altered(state) ; + } + FLUSHPIPE ; +} + +/***************************************************************************\ +* This routine returns the value of the CPSR * +\***************************************************************************/ + +ARMword ARMul_GetCPSR(ARMul_State *state) +{ + return(CPSR) ; + } + +/***************************************************************************\ +* This routine sets the value of the CPSR * +\***************************************************************************/ + +void ARMul_SetCPSR(ARMul_State *state, ARMword value) +{state->Cpsr = CPSR ; + SETPSR(state->Cpsr,value) ; + ARMul_CPSRAltered(state) ; + } + +/***************************************************************************\ +* This routine does all the nasty bits involved in a write to the CPSR, * +* including updating the register bank, given a MSR instruction. * +\***************************************************************************/ + +void ARMul_FixCPSR(ARMul_State *state, ARMword instr, ARMword rhs) +{state->Cpsr = CPSR ; + if (state->Bank==USERBANK) { /* Only write flags in user mode */ + if (BIT(19)) { + SETCC(state->Cpsr,rhs) ; + } + } + else { /* Not a user mode */ + if (BITS(16,19)==9) SETPSR(state->Cpsr,rhs) ; + else if (BIT(16)) SETINTMODE(state->Cpsr,rhs) ; + else if (BIT(19)) SETCC(state->Cpsr,rhs) ; + } + ARMul_CPSRAltered(state) ; + } + +/***************************************************************************\ +* Get an SPSR from the specified mode * +\***************************************************************************/ + +ARMword ARMul_GetSPSR(ARMul_State *state, ARMword mode) +{ARMword bank = ModeToBank(state,mode & MODEBITS) ; + if (bank == USERBANK || bank == DUMMYBANK) + return(CPSR) ; + else + return(state->Spsr[bank]) ; +} + +/***************************************************************************\ +* This routine does a write to an SPSR * +\***************************************************************************/ + +void ARMul_SetSPSR(ARMul_State *state, ARMword mode, ARMword value) +{ARMword bank = ModeToBank(state,mode & MODEBITS) ; + if (bank != USERBANK && bank !=DUMMYBANK) + state->Spsr[bank] = value ; +} + +/***************************************************************************\ +* This routine does a write to the current SPSR, given an MSR instruction * +\***************************************************************************/ + +void ARMul_FixSPSR(ARMul_State *state, ARMword instr, ARMword rhs) +{if (state->Bank != USERBANK && state->Bank !=DUMMYBANK) { + if (BITS(16,19)==9) SETPSR(state->Spsr[state->Bank],rhs) ; + else if (BIT(16)) SETINTMODE(state->Spsr[state->Bank],rhs) ; + else if (BIT(19)) SETCC(state->Spsr[state->Bank],rhs) ; + } +} + +/***************************************************************************\ +* This routine updates the state of the emulator after the Cpsr has been * +* changed. Both the processor flags and register bank are updated. * +\***************************************************************************/ + +void ARMul_CPSRAltered(ARMul_State *state) +{ARMword oldmode ; + + if (state->prog32Sig == LOW) + state->Cpsr &= (CCBITS | INTBITS | R15MODEBITS) ; + oldmode = state->Mode ; + if (state->Mode != (state->Cpsr & MODEBITS)) { + state->Mode = ARMul_SwitchMode(state,state->Mode,state->Cpsr & MODEBITS) ; + state->NtransSig = (state->Mode & 3)?HIGH:LOW ; + } + + ASSIGNINT(state->Cpsr & INTBITS) ; + ASSIGNN((state->Cpsr & NBIT) != 0) ; + ASSIGNZ((state->Cpsr & ZBIT) != 0) ; + ASSIGNC((state->Cpsr & CBIT) != 0) ; + ASSIGNV((state->Cpsr & VBIT) != 0) ; +#ifdef MODET + ASSIGNT((state->Cpsr & TBIT) != 0); +#endif + + if (oldmode > SVC26MODE) { + if (state->Mode <= SVC26MODE) { + state->Emulate = CHANGEMODE ; + state->Reg[15] = ECC | ER15INT | EMODE | R15PC ; + } + } + else { + if (state->Mode > SVC26MODE) { + state->Emulate = CHANGEMODE ; + state->Reg[15] = R15PC ; + } + else + state->Reg[15] = ECC | ER15INT | EMODE | R15PC ; + } + +} + +/***************************************************************************\ +* This routine updates the state of the emulator after register 15 has * +* been changed. Both the processor flags and register bank are updated. * +* This routine should only be called from a 26 bit mode. * +\***************************************************************************/ + +void ARMul_R15Altered(ARMul_State *state) +{ + if (state->Mode != R15MODE) { + state->Mode = ARMul_SwitchMode(state,state->Mode,R15MODE) ; + state->NtransSig = (state->Mode & 3)?HIGH:LOW ; + } + if (state->Mode > SVC26MODE) + state->Emulate = CHANGEMODE ; + ASSIGNR15INT(R15INT) ; + ASSIGNN((state->Reg[15] & NBIT) != 0) ; + ASSIGNZ((state->Reg[15] & ZBIT) != 0) ; + ASSIGNC((state->Reg[15] & CBIT) != 0) ; + ASSIGNV((state->Reg[15] & VBIT) != 0) ; +} + +/***************************************************************************\ +* This routine controls the saving and restoring of registers across mode * +* changes. The regbank matrix is largely unused, only rows 13 and 14 are * +* used across all modes, 8 to 14 are used for FIQ, all others use the USER * +* column. It's easier this way. old and new parameter are modes numbers. * +* Notice the side effect of changing the Bank variable. * +\***************************************************************************/ + +ARMword ARMul_SwitchMode(ARMul_State *state,ARMword oldmode, ARMword newmode) +{unsigned i ; + + oldmode = ModeToBank(state,oldmode) ; + state->Bank = ModeToBank(state,newmode) ; + if (oldmode != state->Bank) { /* really need to do it */ + switch (oldmode) { /* save away the old registers */ + case USERBANK : + case IRQBANK : + case SVCBANK : + case ABORTBANK : + case UNDEFBANK : if (state->Bank == FIQBANK) + for (i = 8 ; i < 13 ; i++) + state->RegBank[USERBANK][i] = state->Reg[i] ; + state->RegBank[oldmode][13] = state->Reg[13] ; + state->RegBank[oldmode][14] = state->Reg[14] ; + break ; + case FIQBANK : for (i = 8 ; i < 15 ; i++) + state->RegBank[FIQBANK][i] = state->Reg[i] ; + break ; + case DUMMYBANK : for (i = 8 ; i < 15 ; i++) + state->RegBank[DUMMYBANK][i] = 0 ; + break ; + + } + switch (state->Bank) { /* restore the new registers */ + case USERBANK : + case IRQBANK : + case SVCBANK : + case ABORTBANK : + case UNDEFBANK : if (oldmode == FIQBANK) + for (i = 8 ; i < 13 ; i++) + state->Reg[i] = state->RegBank[USERBANK][i] ; + state->Reg[13] = state->RegBank[state->Bank][13] ; + state->Reg[14] = state->RegBank[state->Bank][14] ; + break ; + case FIQBANK : for (i = 8 ; i < 15 ; i++) + state->Reg[i] = state->RegBank[FIQBANK][i] ; + break ; + case DUMMYBANK : for (i = 8 ; i < 15 ; i++) + state->Reg[i] = 0 ; + break ; + } /* switch */ + } /* if */ + return(newmode) ; +} + +/***************************************************************************\ +* Given a processor mode, this routine returns the register bank that * +* will be accessed in that mode. * +\***************************************************************************/ + +static ARMword ModeToBank(ARMul_State *state, ARMword mode) +{static ARMword bankofmode[] = {USERBANK, FIQBANK, IRQBANK, SVCBANK, + DUMMYBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK, + DUMMYBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK, + DUMMYBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK, + USERBANK, FIQBANK, IRQBANK, SVCBANK, + DUMMYBANK, DUMMYBANK, DUMMYBANK, ABORTBANK, + DUMMYBANK, DUMMYBANK, DUMMYBANK, UNDEFBANK + } ; + + if (mode > UNDEF32MODE) + return(DUMMYBANK) ; + else + return(bankofmode[mode]) ; + } + +/***************************************************************************\ +* Returns the register number of the nth register in a reg list. * +\***************************************************************************/ + +unsigned ARMul_NthReg(ARMword instr, unsigned number) +{unsigned bit, upto ; + + for (bit = 0, upto = 0 ; upto <= number ; bit++) + if (BIT(bit)) upto++ ; + return(bit - 1) ; +} + +/***************************************************************************\ +* Assigns the N and Z flags depending on the value of result * +\***************************************************************************/ + +void ARMul_NegZero(ARMul_State *state, ARMword result) +{ + if (NEG(result)) { SETN ; CLEARZ ; } + else if (result == 0) { CLEARN ; SETZ ; } + else { CLEARN ; CLEARZ ; } ; + } + +/***************************************************************************\ +* Assigns the C flag after an addition of a and b to give result * +\***************************************************************************/ + +void ARMul_AddCarry(ARMul_State *state, ARMword a,ARMword b,ARMword result) +{ + ASSIGNC( (NEG(a) && NEG(b)) || + (NEG(a) && POS(result)) || + (NEG(b) && POS(result)) ) ; + } + +/***************************************************************************\ +* Assigns the V flag after an addition of a and b to give result * +\***************************************************************************/ + +void ARMul_AddOverflow(ARMul_State *state, ARMword a,ARMword b,ARMword result) +{ + ASSIGNV( (NEG(a) && NEG(b) && POS(result)) || + (POS(a) && POS(b) && NEG(result)) ) ; + } + +/***************************************************************************\ +* Assigns the C flag after an subtraction of a and b to give result * +\***************************************************************************/ + +void ARMul_SubCarry(ARMul_State *state, ARMword a,ARMword b,ARMword result) +{ +ASSIGNC( (NEG(a) && POS(b)) || + (NEG(a) && POS(result)) || + (POS(b) && POS(result)) ) ; +} + +/***************************************************************************\ +* Assigns the V flag after an subtraction of a and b to give result * +\***************************************************************************/ + +void ARMul_SubOverflow(ARMul_State *state,ARMword a,ARMword b,ARMword result) +{ +ASSIGNV( (NEG(a) && POS(b) && POS(result)) || + (POS(a) && NEG(b) && NEG(result)) ) ; +} + +/***************************************************************************\ +* This function does the work of generating the addresses used in an * +* LDC instruction. The code here is always post-indexed, it's up to the * +* caller to get the input address correct and to handle base register * +* modification. It also handles the Busy-Waiting. * +\***************************************************************************/ + +void ARMul_LDC(ARMul_State *state,ARMword instr,ARMword address) +{unsigned cpab ; + ARMword data ; + + UNDEF_LSCPCBaseWb ; + if (ADDREXCEPT(address)) { + INTERNALABORT(address) ; + } + cpab = (state->LDC[CPNum])(state,ARMul_FIRST,instr,0) ; + while (cpab == ARMul_BUSY) { + ARMul_Icycles(state,1,0) ; + if (IntPending(state)) { + cpab = (state->LDC[CPNum])(state,ARMul_INTERRUPT,instr,0) ; + return ; + } + else + cpab = (state->LDC[CPNum])(state,ARMul_BUSY,instr,0) ; + } + if (cpab == ARMul_CANT) { + CPTAKEABORT ; + return ; + } + cpab = (state->LDC[CPNum])(state,ARMul_TRANSFER,instr,0) ; + data = ARMul_LoadWordN(state,address) ; + BUSUSEDINCPCN ; + if (BIT(21)) + LSBase = state->Base ; + cpab = (state->LDC[CPNum])(state,ARMul_DATA,instr,data) ; + while (cpab == ARMul_INC) { + address += 4 ; + data = ARMul_LoadWordN(state,address) ; + cpab = (state->LDC[CPNum])(state,ARMul_DATA,instr,data) ; + } + if (state->abortSig || state->Aborted) { + TAKEABORT ; + } + } + +/***************************************************************************\ +* This function does the work of generating the addresses used in an * +* STC instruction. The code here is always post-indexed, it's up to the * +* caller to get the input address correct and to handle base register * +* modification. It also handles the Busy-Waiting. * +\***************************************************************************/ + +void ARMul_STC(ARMul_State *state,ARMword instr,ARMword address) +{unsigned cpab ; + ARMword data ; + + UNDEF_LSCPCBaseWb ; + if (ADDREXCEPT(address) || VECTORACCESS(address)) { + INTERNALABORT(address) ; + } + cpab = (state->STC[CPNum])(state,ARMul_FIRST,instr,&data) ; + while (cpab == ARMul_BUSY) { + ARMul_Icycles(state,1,0) ; + if (IntPending(state)) { + cpab = (state->STC[CPNum])(state,ARMul_INTERRUPT,instr,0) ; + return ; + } + else + cpab = (state->STC[CPNum])(state,ARMul_BUSY,instr,&data) ; + } + if (cpab == ARMul_CANT) { + CPTAKEABORT ; + return ; + } +#ifndef MODE32 + if (ADDREXCEPT(address) || VECTORACCESS(address)) { + INTERNALABORT(address) ; + } +#endif + BUSUSEDINCPCN ; + if (BIT(21)) + LSBase = state->Base ; + cpab = (state->STC[CPNum])(state,ARMul_DATA,instr,&data) ; + ARMul_StoreWordN(state,address,data) ; + while (cpab == ARMul_INC) { + address += 4 ; + cpab = (state->STC[CPNum])(state,ARMul_DATA,instr,&data) ; + ARMul_StoreWordN(state,address,data) ; + } + if (state->abortSig || state->Aborted) { + TAKEABORT ; + } + } + +/***************************************************************************\ +* This function does the Busy-Waiting for an MCR instruction. * +\***************************************************************************/ + +void ARMul_MCR(ARMul_State *state,ARMword instr, ARMword source) +{unsigned cpab ; + + cpab = (state->MCR[CPNum])(state,ARMul_FIRST,instr,source) ; + while (cpab == ARMul_BUSY) { + ARMul_Icycles(state,1,0) ; + if (IntPending(state)) { + cpab = (state->MCR[CPNum])(state,ARMul_INTERRUPT,instr,0) ; + return ; + } + else + cpab = (state->MCR[CPNum])(state,ARMul_BUSY,instr,source) ; + } + if (cpab == ARMul_CANT) + ARMul_Abort(state,ARMul_UndefinedInstrV) ; + else { + BUSUSEDINCPCN ; + ARMul_Ccycles(state,1,0) ; + } + } + +/***************************************************************************\ +* This function does the Busy-Waiting for an MRC instruction. * +\***************************************************************************/ + +ARMword ARMul_MRC(ARMul_State *state,ARMword instr) +{unsigned cpab ; + ARMword result = 0 ; + + cpab = (state->MRC[CPNum])(state,ARMul_FIRST,instr,&result) ; + while (cpab == ARMul_BUSY) { + ARMul_Icycles(state,1,0) ; + if (IntPending(state)) { + cpab = (state->MRC[CPNum])(state,ARMul_INTERRUPT,instr,0) ; + return(0) ; + } + else + cpab = (state->MRC[CPNum])(state,ARMul_BUSY,instr,&result) ; + } + if (cpab == ARMul_CANT) { + ARMul_Abort(state,ARMul_UndefinedInstrV) ; + result = ECC ; /* Parent will destroy the flags otherwise */ + } + else { + BUSUSEDINCPCN ; + ARMul_Ccycles(state,1,0) ; + ARMul_Icycles(state,1,0) ; + } + return(result) ; +} + +/***************************************************************************\ +* This function does the Busy-Waiting for an CDP instruction. * +\***************************************************************************/ + +void ARMul_CDP(ARMul_State *state,ARMword instr) +{unsigned cpab ; + + cpab = (state->CDP[CPNum])(state,ARMul_FIRST,instr) ; + while (cpab == ARMul_BUSY) { + ARMul_Icycles(state,1,0) ; + if (IntPending(state)) { + cpab = (state->CDP[CPNum])(state,ARMul_INTERRUPT,instr) ; + return ; + } + else + cpab = (state->CDP[CPNum])(state,ARMul_BUSY,instr) ; + } + if (cpab == ARMul_CANT) + ARMul_Abort(state,ARMul_UndefinedInstrV) ; + else + BUSUSEDN ; +} + +/***************************************************************************\ +* This function handles Undefined instructions, as CP isntruction * +\***************************************************************************/ + +void ARMul_UndefInstr(ARMul_State *state,ARMword instr) +{ + ARMul_Abort(state,ARMul_UndefinedInstrV) ; +} + +/***************************************************************************\ +* Return TRUE if an interrupt is pending, FALSE otherwise. * +\***************************************************************************/ + +unsigned IntPending(ARMul_State *state) +{ + if (state->Exception) { /* Any exceptions */ + if (state->NresetSig == LOW) { + ARMul_Abort(state,ARMul_ResetV) ; + return(TRUE) ; + } + else if (!state->NfiqSig && !FFLAG) { + ARMul_Abort(state,ARMul_FIQV) ; + return(TRUE) ; + } + else if (!state->NirqSig && !IFLAG) { + ARMul_Abort(state,ARMul_IRQV) ; + return(TRUE) ; + } + } + return(FALSE) ; + } + +/***************************************************************************\ +* Align a word access to a non word boundary * +\***************************************************************************/ + +ARMword ARMul_Align(ARMul_State *state, ARMword address, ARMword data) +{/* this code assumes the address is really unaligned, + as a shift by 32 is undefined in C */ + + address = (address & 3) << 3 ; /* get the word address */ + return( ( data >> address) | (data << (32 - address)) ) ; /* rot right */ +} + +/***************************************************************************\ +* This routine is used to call another routine after a certain number of * +* cycles have been executed. The first parameter is the number of cycles * +* delay before the function is called, the second argument is a pointer * +* to the function. A delay of zero doesn't work, just call the function. * +\***************************************************************************/ + +void ARMul_ScheduleEvent(ARMul_State *state, unsigned long delay, unsigned (*what)()) +{unsigned long when ; + struct EventNode *event ; + + if (state->EventSet++ == 0) + state->Now = ARMul_Time(state) ; + when = (state->Now + delay) % EVENTLISTSIZE ; + event = (struct EventNode *)malloc(sizeof(struct EventNode)) ; + event->func = what ; + event->next = *(state->EventPtr + when) ; + *(state->EventPtr + when) = event ; +} + +/***************************************************************************\ +* This routine is called at the beginning of every cycle, to envoke * +* scheduled events. * +\***************************************************************************/ + +void ARMul_EnvokeEvent(ARMul_State *state) +{static unsigned long then ; + + then = state->Now ; + state->Now = ARMul_Time(state) % EVENTLISTSIZE ; + if (then < state->Now) /* schedule events */ + EnvokeList(state,then,state->Now) ; + else if (then > state->Now) { /* need to wrap around the list */ + EnvokeList(state,then,EVENTLISTSIZE-1L) ; + EnvokeList(state,0L,state->Now) ; + } + } + +static void EnvokeList(ARMul_State *state, unsigned long from, unsigned long to) +/* envokes all the entries in a range */ +{struct EventNode *anevent ; + + for (; from <= to ; from++) { + anevent = *(state->EventPtr + from) ; + while (anevent) { + (anevent->func)(state) ; + state->EventSet-- ; + anevent = anevent->next ; + } + *(state->EventPtr + from) = NULL ; + } + } + +/***************************************************************************\ +* This routine is returns the number of clock ticks since the last reset. * +\***************************************************************************/ + +unsigned long ARMul_Time(ARMul_State *state) +{return(state->NumScycles + state->NumNcycles + + state->NumIcycles + state->NumCcycles + state->NumFcycles) ; +} diff --git a/sim/arm/armvirt.c b/sim/arm/armvirt.c new file mode 100644 index 00000000000..57ebedf826b --- /dev/null +++ b/sim/arm/armvirt.c @@ -0,0 +1,491 @@ +/* armvirt.c -- ARMulator virtual memory interace: ARM6 Instruction Emulator. + Copyright (C) 1994 Advanced RISC Machines Ltd. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* This file contains a complete ARMulator memory model, modelling a +"virtual memory" system. A much simpler model can be found in armfast.c, +and that model goes faster too, but has a fixed amount of memory. This +model's memory has 64K pages, allocated on demand from a 64K entry page +table. The routines PutWord and GetWord implement this. Pages are never +freed as they might be needed again. A single area of memory may be +defined to generate aborts. */ + +#include "armopts.h" +#include "armdefs.h" + +#ifdef VALIDATE /* for running the validate suite */ +#define TUBE 48 * 1024 * 1024 /* write a char on the screen */ +#define ABORTS 1 +#endif + +#define ABORTS + +#ifdef ABORTS /* the memory system will abort */ +/* For the old test suite Abort between 32 Kbytes and 32 Mbytes + For the new test suite Abort between 8 Mbytes and 26 Mbytes */ +/* #define LOWABORT 32 * 1024 +#define HIGHABORT 32 * 1024 * 1024 */ +#define LOWABORT 8 * 1024 * 1024 +#define HIGHABORT 26 * 1024 * 1024 + +#endif + +#define NUMPAGES 64 * 1024 +#define PAGESIZE 64 * 1024 +#define PAGEBITS 16 +#define OFFSETBITS 0xffff + +/***************************************************************************\ +* Get a Word from Virtual Memory, maybe allocating the page * +\***************************************************************************/ + +static ARMword +GetWord (ARMul_State * state, ARMword address) +{ + ARMword page; + ARMword offset; + ARMword ** pagetable; + ARMword * pageptr; + + page = address >> PAGEBITS; + offset = (address & OFFSETBITS) >> 2; + pagetable = (ARMword **) state->MemDataPtr; + pageptr = *(pagetable + page); + + if (pageptr == NULL) + { + pageptr = (ARMword *) malloc (PAGESIZE); + + if (pageptr == NULL) + { + perror ("ARMulator can't allocate VM page"); + exit (12); + } + + *(pagetable + page) = pageptr; + } + + return *(pageptr + offset); +} + +/***************************************************************************\ +* Put a Word into Virtual Memory, maybe allocating the page * +\***************************************************************************/ + +static void +PutWord (ARMul_State * state, ARMword address, ARMword data) +{ + ARMword page; + ARMword offset; + ARMword ** pagetable; + ARMword * pageptr; + + page = address >> PAGEBITS; + offset = (address & OFFSETBITS) >> 2; + pagetable = (ARMword **)state->MemDataPtr; + pageptr = *(pagetable + page); + + if (pageptr == NULL) + { + pageptr = (ARMword *) malloc (PAGESIZE); + if (pageptr == NULL) + { + perror ("ARMulator can't allocate VM page"); + exit(13); + } + + *(pagetable + page) = pageptr; + } + + *(pageptr + offset) = data; +} + +/***************************************************************************\ +* Initialise the memory interface * +\***************************************************************************/ + +unsigned +ARMul_MemoryInit (ARMul_State * state, unsigned long initmemsize) +{ + ARMword ** pagetable; + unsigned page; + + if (initmemsize) + state->MemSize = initmemsize; + + pagetable = (ARMword **) malloc (sizeof (ARMword) * NUMPAGES); + + if (pagetable == NULL) + return FALSE; + + for (page = 0 ; page < NUMPAGES ; page++) + *(pagetable + page) = NULL; + + state->MemDataPtr = (unsigned char *)pagetable; + + ARMul_ConsolePrint (state, ", 4 Gb memory"); + + return TRUE; +} + +/***************************************************************************\ +* Remove the memory interface * +\***************************************************************************/ + +void +ARMul_MemoryExit (ARMul_State * state) +{ + ARMword page; + ARMword ** pagetable; + ARMword * pageptr; + + pagetable = (ARMword **)state->MemDataPtr; + for (page = 0 ; page < NUMPAGES ; page++) + { + pageptr = *(pagetable + page); + if (pageptr != NULL) + free ((char *)pageptr); + } + free ((char *)pagetable); + return; +} + +/***************************************************************************\ +* ReLoad Instruction * +\***************************************************************************/ + +ARMword +ARMul_ReLoadInstr (ARMul_State * state, ARMword address, ARMword isize) +{ +#ifdef ABORTS + if (address >= LOWABORT && address < HIGHABORT) + { + ARMul_PREFETCHABORT (address); + return ARMul_ABORTWORD; + } + else + { + ARMul_CLEARABORT; + } +#endif + + if ((isize == 2) && (address & 0x2)) + { + /* We return the next two halfwords: */ + ARMword lo = GetWord (state, address); + ARMword hi = GetWord (state, address + 4); + + if (state->bigendSig == HIGH) + return (lo << 16) | (hi >> 16); + else + return ((hi & 0xFFFF) << 16) | (lo >> 16); + } + + return GetWord (state, address); +} + +/***************************************************************************\ +* Load Instruction, Sequential Cycle * +\***************************************************************************/ + +ARMword +ARMul_LoadInstrS (ARMul_State * state, ARMword address, ARMword isize) +{ + state->NumScycles ++; + +#ifdef HOURGLASS + if (( state->NumScycles & HOURGLASS_RATE ) == 0) + { + HOURGLASS; + } +#endif + + return ARMul_ReLoadInstr (state, address, isize); +} + +/***************************************************************************\ +* Load Instruction, Non Sequential Cycle * +\***************************************************************************/ + +ARMword +ARMul_LoadInstrN (ARMul_State * state, ARMword address, ARMword isize) +{ + state->NumNcycles ++; + + return ARMul_ReLoadInstr (state, address, isize); +} + +/***************************************************************************\ +* Read Word (but don't tell anyone!) * +\***************************************************************************/ + +ARMword +ARMul_ReadWord (ARMul_State * state, ARMword address) +{ +#ifdef ABORTS + if (address >= LOWABORT && address < HIGHABORT) + { + ARMul_DATAABORT (address); + return ARMul_ABORTWORD; + } + else + { + ARMul_CLEARABORT; + } +#endif + + return GetWord (state, address); +} + +/***************************************************************************\ +* Load Word, Sequential Cycle * +\***************************************************************************/ + +ARMword +ARMul_LoadWordS (ARMul_State * state, ARMword address) +{ + state->NumScycles ++; + + return ARMul_ReadWord (state, address); +} + +/***************************************************************************\ +* Load Word, Non Sequential Cycle * +\***************************************************************************/ + +ARMword +ARMul_LoadWordN (ARMul_State * state, ARMword address) +{ + state->NumNcycles ++; + + return ARMul_ReadWord (state, address); +} + +/***************************************************************************\ +* Load Halfword, (Non Sequential Cycle) * +\***************************************************************************/ + +ARMword +ARMul_LoadHalfWord (ARMul_State * state, ARMword address) +{ + ARMword temp, offset; + + state->NumNcycles ++; + + temp = ARMul_ReadWord (state, address); + offset = (((ARMword)state->bigendSig * 2) ^ (address & 2)) << 3; /* bit offset into the word */ + + return (temp >> offset) & 0xffff; +} + +/***************************************************************************\ +* Read Byte (but don't tell anyone!) * +\***************************************************************************/ + +ARMword +ARMul_ReadByte (ARMul_State * state, ARMword address) +{ + ARMword temp, offset; + + temp = ARMul_ReadWord (state, address); + offset = (((ARMword)state->bigendSig * 3) ^ (address & 3)) << 3; /* bit offset into the word */ + + return (temp >> offset & 0xffL); +} + +/***************************************************************************\ +* Load Byte, (Non Sequential Cycle) * +\***************************************************************************/ + +ARMword +ARMul_LoadByte (ARMul_State * state, ARMword address) +{ + state->NumNcycles ++; + + return ARMul_ReadByte (state, address); +} + +/***************************************************************************\ +* Write Word (but don't tell anyone!) * +\***************************************************************************/ + +void +ARMul_WriteWord (ARMul_State * state, ARMword address, ARMword data) +{ +#ifdef ABORTS + if (address >= LOWABORT && address < HIGHABORT) + { + ARMul_DATAABORT (address); + return; + } + else + { + ARMul_CLEARABORT; + } +#endif + + PutWord (state, address, data); +} + +/***************************************************************************\ +* Store Word, Sequential Cycle * +\***************************************************************************/ + +void +ARMul_StoreWordS (ARMul_State * state, ARMword address, ARMword data) +{ + state->NumScycles ++; + + ARMul_WriteWord (state, address, data); +} + +/***************************************************************************\ +* Store Word, Non Sequential Cycle * +\***************************************************************************/ + +void +ARMul_StoreWordN (ARMul_State * state, ARMword address, ARMword data) +{ + state->NumNcycles ++; + + ARMul_WriteWord (state, address, data); +} + +/***************************************************************************\ +* Store HalfWord, (Non Sequential Cycle) * +\***************************************************************************/ + +void +ARMul_StoreHalfWord (ARMul_State * state, ARMword address, ARMword data) +{ + ARMword temp, offset; + + state->NumNcycles ++; + +#ifdef VALIDATE + if (address == TUBE) + { + if (data == 4) + state->Emulate = FALSE; + else + (void) putc ((char)data, stderr); /* Write Char */ + return; + } +#endif + + temp = ARMul_ReadWord (state, address); + offset = (((ARMword)state->bigendSig * 2) ^ (address & 2)) << 3; /* bit offset into the word */ + + PutWord (state, address, (temp & ~(0xffffL << offset)) | ((data & 0xffffL) << offset)); +} + +/***************************************************************************\ +* Write Byte (but don't tell anyone!) * +\***************************************************************************/ + +void +ARMul_WriteByte (ARMul_State * state, ARMword address, ARMword data) +{ + ARMword temp, offset; + + temp = ARMul_ReadWord (state, address); + offset = (((ARMword)state->bigendSig * 3) ^ (address & 3)) << 3; /* bit offset into the word */ + + PutWord (state, address, (temp & ~(0xffL << offset)) | ((data & 0xffL) << offset)); +} + +/***************************************************************************\ +* Store Byte, (Non Sequential Cycle) * +\***************************************************************************/ + +void +ARMul_StoreByte (ARMul_State * state, ARMword address, ARMword data) +{ + state->NumNcycles ++; + +#ifdef VALIDATE + if (address == TUBE) + { + if (data == 4) + state->Emulate = FALSE; + else + (void) putc ((char)data,stderr); /* Write Char */ + return; + } +#endif + + ARMul_WriteByte (state, address, data); +} + +/***************************************************************************\ +* Swap Word, (Two Non Sequential Cycles) * +\***************************************************************************/ + +ARMword +ARMul_SwapWord (ARMul_State * state, ARMword address, ARMword data) +{ + ARMword temp; + + state->NumNcycles ++; + + temp = ARMul_ReadWord (state, address); + + state->NumNcycles ++; + + PutWord (state, address, data); + + return temp; +} + +/***************************************************************************\ +* Swap Byte, (Two Non Sequential Cycles) * +\***************************************************************************/ + +ARMword +ARMul_SwapByte (ARMul_State * state, ARMword address, ARMword data) +{ + ARMword temp; + + temp = ARMul_LoadByte (state, address); + ARMul_StoreByte (state, address, data); + + return temp; +} + +/***************************************************************************\ +* Count I Cycles * +\***************************************************************************/ + +void +ARMul_Icycles (ARMul_State * state, unsigned number, ARMword address) +{ + state->NumIcycles += number; + ARMul_CLEARABORT; +} + +/***************************************************************************\ +* Count C Cycles * +\***************************************************************************/ + +void +ARMul_Ccycles (ARMul_State * state, unsigned number, ARMword address) +{ + state->NumCcycles += number; + ARMul_CLEARABORT; +} + + + diff --git a/sim/arm/bag.c b/sim/arm/bag.c new file mode 100644 index 00000000000..f4b9661be3d --- /dev/null +++ b/sim/arm/bag.c @@ -0,0 +1,141 @@ +/* bag.c -- ARMulator support code: ARM6 Instruction Emulator. + Copyright (C) 1994 Advanced RISC Machines Ltd. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/********************************************************************/ +/* bag.c: */ +/* Offers a data structure for storing and getting pairs of number. */ +/* The numbers are stored together, put one can be looked up by */ +/* quoting the other. If a new pair is entered and one of the */ +/* numbers is a repeat of a previous pair, then the previos pair */ +/* is deleted. */ +/********************************************************************/ + +#include "bag.h" + +#define HASH_TABLE_SIZE 256 +#define hash(x) (((x)&0xff)^(((x)>>8)&0xff)^(((x)>>16)&0xff)^(((x)>>24)&0xff)) + +typedef struct hashentry { + struct hashentry *next; + int first; + int second; +} Hashentry; + +Hashentry *lookupbyfirst[HASH_TABLE_SIZE]; +Hashentry *lookupbysecond[HASH_TABLE_SIZE]; + +void addtolist(Hashentry **add, long first, long second) { + while (*add) add = &((*add)->next); + /* Malloc will never fail? :o( */ + (*add) = (Hashentry *) malloc(sizeof(Hashentry)); + (*add)->next = (Hashentry *) 0; + (*add)->first = first; + (*add)->second = second; +} + +void killwholelist(Hashentry *p) { + Hashentry *q; + + while (p) { + q = p; + p = p->next; + free(q); + } +} + +void removefromlist(Hashentry **p, long first, long second) { + Hashentry *q; + + while (*p) { + if ((*p)->first == first) { + q = (*p)->next; + free(*p); + *p = q; + return; + } + p = &((*p)->next); + } +} + +void BAG_putpair(long first, long second) { + long junk; + + if (BAG_getfirst(&junk, second) != NO_SUCH_PAIR) + BAG_killpair_bysecond(second); + addtolist(&lookupbyfirst[hash(first)], first, second); + addtolist(&lookupbysecond[hash(second)], first, second); +} + +Bag_error BAG_getfirst(long *first, long second) { + Hashentry *look; + + look = lookupbysecond[hash(second)]; + while(look) if (look->second == second) { + *first = look->first; + return NO_ERROR; + } + return NO_SUCH_PAIR; +} + +Bag_error BAG_getsecond(long first, long *second) { + Hashentry *look; + + look = lookupbyfirst[hash(first)]; + while(look) { + if (look->first == first) { + *second = look->second; + return NO_ERROR; + } + look = look->next; + } + return NO_SUCH_PAIR; +} + +Bag_error BAG_killpair_byfirst(long first) { + long second; + + if (BAG_getsecond(first, &second) == NO_SUCH_PAIR) + return NO_SUCH_PAIR; + removefromlist(&lookupbyfirst[hash(first)], first, second); + removefromlist(&lookupbysecond[hash(second)], first, second); + return NO_ERROR; +} + +Bag_error BAG_killpair_bysecond(long second) { + long first; + + if (BAG_getfirst(&first, second) == NO_SUCH_PAIR) + return NO_SUCH_PAIR; + removefromlist(&lookupbyfirst[hash(first)], first, second); + removefromlist(&lookupbysecond[hash(second)], first, second); + return NO_ERROR; +} + +void BAG_newbag() { + int i; + + for (i = 0; i < 256; i++) { + killwholelist(lookupbyfirst[i]); + killwholelist(lookupbysecond[i]); + lookupbyfirst[i] = lookupbysecond[i] = (Hashentry *) 0; + } +} + + + + + diff --git a/sim/arm/bag.h b/sim/arm/bag.h new file mode 100644 index 00000000000..8914e96b699 --- /dev/null +++ b/sim/arm/bag.h @@ -0,0 +1,42 @@ +/* bag.h -- ARMulator support code: ARM6 Instruction Emulator. + Copyright (C) 1994 Advanced RISC Machines Ltd. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/********************************************************************/ +/* bag.h: */ +/* Header file for bag.c */ +/* Offers a data structure for storing and getting pairs of number. */ +/* The numbers are stored together, put one can be looked up by */ +/* quoting the other. If a new pair is entered and one of the */ +/* numbers is a repeat of a previous pair, then the previos pair */ +/* is deleted. */ +/********************************************************************/ + +typedef enum { + NO_ERROR, + DELETED_OLD_PAIR, + NO_SUCH_PAIR, +} Bag_error; + +void BAG_putpair(long first, long second); + +void BAG_newbag(void); +Bag_error BAG_killpair_byfirst(long first); +Bag_error BAG_killpair_bysecond(long second); + +Bag_error BAG_getfirst(long *first, long second); +Bag_error BAG_getsecond(long first, long *second); + diff --git a/sim/arm/communicate.c b/sim/arm/communicate.c new file mode 100644 index 00000000000..55ee2f3e0f6 --- /dev/null +++ b/sim/arm/communicate.c @@ -0,0 +1,221 @@ +/* communicate.c -- ARMulator RDP comms code: ARM6 Instruction Emulator. + Copyright (C) 1994 Advanced RISC Machines Ltd. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/**************************************************************************/ +/* Functions to read and write characters or groups of characters */ +/* down sockets or pipes. Those that return a value return -1 on failure */ +/* and 0 on success. */ +/**************************************************************************/ + +#include +#include +#include +#include + +#include "armdefs.h" + +/* The socket to the debugger */ +int debugsock; + +/* The maximum number of file descriptors */ +extern int nfds; + +/* The socket handle */ +extern int sockethandle; + +/* Read and Write routines down a pipe or socket */ + +/****************************************************************/ +/* Read an individual character. */ +/* All other read functions rely on this one. */ +/* It waits 15 seconds until there is a character available: if */ +/* no character is available, then it timeouts and returns -1. */ +/****************************************************************/ +int MYread_char(int sock, unsigned char *c) { + int i; + fd_set readfds; + struct timeval timeout= {15, 0}; + struct sockaddr_in isa; + + retry: + + FD_ZERO(&readfds); + FD_SET(sock, &readfds); + + i = select(nfds, &readfds, + (fd_set *) 0, + (fd_set *) 0, + &timeout); + + if (i < 0) { + perror("select"); + exit(1); + } + + if (!i) { + fprintf(stderr, "read: Timeout\n"); + return -1; + } + + if ((i = read(sock, c, 1)) < 1) { + if (!i && sock == debugsock) { + fprintf(stderr, "Connection with debugger severed.\n"); + /* This shouldn't be necessary for a detached armulator, but + the armulator cannot be cold started a second time, so + this is probably preferable to locking up. */ + return -1; + fprintf(stderr, "Waiting for connection from debugger..."); + debugsock = accept(sockethandle, &isa, &i); + if (debugsock < 0) { /* Now we are in serious trouble... */ + perror("accept"); + return -1; + } + fprintf(stderr, " done.\nConnection Established.\n"); + sock = debugsock; + goto retry; + } + perror("read"); + return -1; + } + +#ifdef DEBUG + if (sock == debugsock) fprintf(stderr, "<%02x ", *c); +#endif + + return 0; +} + +/****************************************************************/ +/* Read an individual character. */ +/* It waits until there is a character available. Returns -1 if */ +/* an error occurs. */ +/****************************************************************/ +int MYread_charwait(int sock, unsigned char *c) { + int i; + fd_set readfds; + struct sockaddr_in isa; + + retry: + + FD_ZERO(&readfds); + FD_SET(sock, &readfds); + + i = select(nfds, &readfds, + (fd_set *) 0, + (fd_set *) 0, + (struct timeval *) 0); + + if (i < 0) { + perror("select"); + exit(-1); + } + + if ((i = read(sock, c, 1)) < 1) { + if (!i && sock == debugsock) { + fprintf(stderr, "Connection with debugger severed.\n"); + return -1; + fprintf(stderr, "Waiting for connection from debugger..."); + debugsock = accept(sockethandle, &isa, &i); + if (debugsock < 0) { /* Now we are in serious trouble... */ + perror("accept"); + return -1; + } + fprintf(stderr, " done.\nConnection Established.\n"); + sock = debugsock; + goto retry; + } + perror("read"); + return -1; + } + +#ifdef DEBUG + if (sock == debugsock) fprintf(stderr, "<%02x ", *c); +#endif + + return 0; +} + +void MYwrite_char(int sock, unsigned char c) { + + if (write(sock, &c, 1) < 1) + perror("write"); +#ifdef DEBUG + if (sock == debugsock) fprintf(stderr, ">%02x ", c); +#endif +} + +int MYread_word(int sock, ARMword *here) { + unsigned char a, b, c, d; + + if (MYread_char(sock, &a) < 0) return -1; + if (MYread_char(sock, &b) < 0) return -1; + if (MYread_char(sock, &c) < 0) return -1; + if (MYread_char(sock, &d) < 0) return -1; + *here = a | b << 8 | c << 16 | d << 24; + return 0; +} + +void MYwrite_word(int sock, ARMword i) { + MYwrite_char(sock, i & 0xff); + MYwrite_char(sock, (i & 0xff00) >> 8); + MYwrite_char(sock, (i & 0xff0000) >> 16); + MYwrite_char(sock, (i & 0xff000000) >> 24); +} + +void MYwrite_string(int sock, char *s) { + int i; + for (i = 0; MYwrite_char(sock, s[i]), s[i]; i++); +} + +int MYread_FPword(int sock, char *putinhere) { + int i; + for (i = 0; i < 16; i++) + if (MYread_char(sock, &putinhere[i]) < 0) return -1; + return 0; +} + +void MYwrite_FPword(int sock, char *fromhere) { + int i; + for (i = 0; i < 16; i++) + MYwrite_char(sock, fromhere[i]); +} + +/* Takes n bytes from source and those n bytes */ +/* down to dest */ +int passon(int source, int dest, int n) { + char *p; + int i; + + p = (char *) malloc(n); + if (!p) { + perror("Out of memory\n"); + exit(1); + } + if (n) { + for (i = 0; i < n; i++) + if (MYread_char(source, &p[i]) < 0) return -1; + +#ifdef DEBUG + if (dest == debugsock) + for (i = 0; i < n; i++) fprintf(stderr, ")%02x ", (unsigned char) p[i]); +#endif + + write(dest, p, n); + } + free(p); + return 0; +} diff --git a/sim/arm/communicate.h b/sim/arm/communicate.h new file mode 100644 index 00000000000..0630fe4af47 --- /dev/null +++ b/sim/arm/communicate.h @@ -0,0 +1,37 @@ +/* communicate.h -- ARMulator comms support defns: ARM6 Instruction Emulator. + Copyright (C) 1994 Advanced RISC Machines Ltd. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +int MYread_char(int sock, unsigned char *c); +void MYwrite_char(int sock, unsigned char c); +int MYread_word(int sock, ARMword *here); +void MYwrite_word(int sock, ARMword i); +void MYwrite_string(int sock, char *s); +int MYread_FPword(int sock, char *putinhere); +void MYwrite_FPword(int sock, char *fromhere); +int passon(int source, int dest, int n); + +int wait_for_osreply(ARMword *reply); /* from kid.c */ + +#define OS_SendNothing 0x0 +#define OS_SendChar 0x1 +#define OS_SendWord 0x2 +#define OS_SendString 0x3 + +/* The pipes between the two processes */ +extern int mumkid[2]; +extern int kidmum[2]; + diff --git a/sim/arm/config.in b/sim/arm/config.in new file mode 100644 index 00000000000..1f87a2bee4e --- /dev/null +++ b/sim/arm/config.in @@ -0,0 +1,158 @@ +/* config.in. Generated automatically from configure.in by autoheader. */ + +/* Define if using alloca.c. */ +#undef C_ALLOCA + +/* Define to empty if the keyword does not work. */ +#undef const + +/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems. + This function is required for alloca.c support on those systems. */ +#undef CRAY_STACKSEG_END + +/* Define if you have alloca, as a function or macro. */ +#undef HAVE_ALLOCA + +/* Define if you have and it should be used (not on Ultrix). */ +#undef HAVE_ALLOCA_H + +/* Define if you have a working `mmap' system call. */ +#undef HAVE_MMAP + +/* Define as __inline if that's what the C compiler calls it. */ +#undef inline + +/* Define to `long' if doesn't define. */ +#undef off_t + +/* Define if you need to in order for stat and other things to work. */ +#undef _POSIX_SOURCE + +/* Define as the return type of signal handlers (int or void). */ +#undef RETSIGTYPE + +/* Define to `unsigned' if doesn't define. */ +#undef size_t + +/* If using the C implementation of alloca, define if you know the + direction of stack growth for your system; otherwise it will be + automatically deduced at run-time. + STACK_DIRECTION > 0 => grows toward higher addresses + STACK_DIRECTION < 0 => grows toward lower addresses + STACK_DIRECTION = 0 => direction of growth unknown + */ +#undef STACK_DIRECTION + +/* Define if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Define to 1 if NLS is requested. */ +#undef ENABLE_NLS + +/* Define as 1 if you have gettext and don't want to use GNU gettext. */ +#undef HAVE_GETTEXT + +/* Define as 1 if you have the stpcpy function. */ +#undef HAVE_STPCPY + +/* Define if your locale.h file contains LC_MESSAGES. */ +#undef HAVE_LC_MESSAGES + +/* Define if you have the __argz_count function. */ +#undef HAVE___ARGZ_COUNT + +/* Define if you have the __argz_next function. */ +#undef HAVE___ARGZ_NEXT + +/* Define if you have the __argz_stringify function. */ +#undef HAVE___ARGZ_STRINGIFY + +/* Define if you have the __setfpucw function. */ +#undef HAVE___SETFPUCW + +/* Define if you have the dcgettext function. */ +#undef HAVE_DCGETTEXT + +/* Define if you have the getcwd function. */ +#undef HAVE_GETCWD + +/* Define if you have the getpagesize function. */ +#undef HAVE_GETPAGESIZE + +/* Define if you have the getrusage function. */ +#undef HAVE_GETRUSAGE + +/* Define if you have the munmap function. */ +#undef HAVE_MUNMAP + +/* Define if you have the putenv function. */ +#undef HAVE_PUTENV + +/* Define if you have the setenv function. */ +#undef HAVE_SETENV + +/* Define if you have the setlocale function. */ +#undef HAVE_SETLOCALE + +/* Define if you have the sigaction function. */ +#undef HAVE_SIGACTION + +/* Define if you have the stpcpy function. */ +#undef HAVE_STPCPY + +/* Define if you have the strcasecmp function. */ +#undef HAVE_STRCASECMP + +/* Define if you have the strchr function. */ +#undef HAVE_STRCHR + +/* Define if you have the time function. */ +#undef HAVE_TIME + +/* Define if you have the header file. */ +#undef HAVE_ARGZ_H + +/* Define if you have the header file. */ +#undef HAVE_FCNTL_H + +/* Define if you have the header file. */ +#undef HAVE_FPU_CONTROL_H + +/* Define if you have the header file. */ +#undef HAVE_LIMITS_H + +/* Define if you have the header file. */ +#undef HAVE_LOCALE_H + +/* Define if you have the header file. */ +#undef HAVE_MALLOC_H + +/* Define if you have the header file. */ +#undef HAVE_NL_TYPES_H + +/* Define if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define if you have the header file. */ +#undef HAVE_STRING_H + +/* Define if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_PARAM_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_RESOURCE_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_TIME_H + +/* Define if you have the header file. */ +#undef HAVE_TIME_H + +/* Define if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define if you have the header file. */ +#undef HAVE_VALUES_H diff --git a/sim/arm/configure b/sim/arm/configure new file mode 100755 index 00000000000..e646fa8a499 --- /dev/null +++ b/sim/arm/configure @@ -0,0 +1,3892 @@ +#! /bin/sh + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +sim_inline="-DDEFAULT_INLINE=0" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +# This file is derived from `gettext.m4'. The difference is that the +# included macros assume Cygnus-style source and build trees. + +# Macro to add for using GNU gettext. +# Ulrich Drepper , 1995. +# +# This file file be copied and used freely without restrictions. It can +# be used in projects which are not available under the GNU Public License +# but which still want to provide support for the GNU gettext functionality. +# Please note that the actual code is *not* freely available. + +# serial 3 + + + + + +# Search path for a program which passes the given test. +# Ulrich Drepper , 1996. +# +# This file file be copied and used freely without restrictions. It can +# be used in projects which are not available under the GNU Public License +# but which still want to provide support for the GNU gettext functionality. +# Please note that the actual code is *not* freely available. + +# serial 1 + + + +# Check whether LC_MESSAGES is available in . +# Ulrich Drepper , 1995. +# +# This file file be copied and used freely without restrictions. It can +# be used in projects which are not available under the GNU Public License +# but which still want to provide support for the GNU gettext functionality. +# Please note that the actual code is *not* freely available. + +# serial 1 + + + +# Check to see if we're running under Cygwin32, without using +# AC_CANONICAL_*. If so, set output variable CYGWIN32 to "yes". +# Otherwise set it to "no". + + + +# Check to see if we're running under Win32, without using +# AC_CANONICAL_*. If so, set output variable EXEEXT to ".exe". +# Otherwise set it to "". + + + + +# Guess values for system-dependent variables and create Makefiles. +# Generated automatically using autoconf version 2.12.2 +# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc. +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. + +# Defaults: +ac_help= +ac_default_prefix=/usr/local +# Any additions from configure.in: +ac_help="$ac_help + --disable-nls do not use Native Language Support" +ac_help="$ac_help + --with-included-gettext use the GNU gettext library included here" +ac_help="$ac_help + --enable-maintainer-mode Enable developer functionality." +ac_help="$ac_help + --enable-sim-bswap Use Host specific BSWAP instruction." +ac_help="$ac_help + --enable-sim-cflags=opts Extra CFLAGS for use in building simulator" +ac_help="$ac_help + --enable-sim-debug=opts Enable debugging flags" +ac_help="$ac_help + --enable-sim-stdio Specify whether to use stdio for console input/output." +ac_help="$ac_help + --enable-sim-trace=opts Enable tracing flags" +ac_help="$ac_help + --enable-sim-profile=opts Enable profiling flags" + +# Initialize some variables set by options. +# The variables have the same names as the options, with +# dashes changed to underlines. +build=NONE +cache_file=./config.cache +exec_prefix=NONE +host=NONE +no_create= +nonopt=NONE +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +target=NONE +verbose= +x_includes=NONE +x_libraries=NONE +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +# Initialize some other variables. +subdirs= +MFLAGS= MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} +# Maximum number of lines to put in a shell here document. +ac_max_here_lines=12 + +ac_prev= +for ac_option +do + + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval "$ac_prev=\$ac_option" + ac_prev= + continue + fi + + case "$ac_option" in + -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) ac_optarg= ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case "$ac_option" in + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir="$ac_optarg" ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build="$ac_optarg" ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file="$ac_optarg" ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir="$ac_optarg" ;; + + -disable-* | --disable-*) + ac_feature=`echo $ac_option|sed -e 's/-*disable-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + eval "enable_${ac_feature}=no" ;; + + -enable-* | --enable-*) + ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "enable_${ac_feature}='$ac_optarg'" ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix="$ac_optarg" ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he) + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat << EOF +Usage: configure [options] [host] +Options: [defaults in brackets after descriptions] +Configuration: + --cache-file=FILE cache test results in FILE + --help print this message + --no-create do not create output files + --quiet, --silent do not print \`checking...' messages + --version print the version of autoconf that created configure +Directory and file names: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [same as prefix] + --bindir=DIR user executables in DIR [EPREFIX/bin] + --sbindir=DIR system admin executables in DIR [EPREFIX/sbin] + --libexecdir=DIR program executables in DIR [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data in DIR + [PREFIX/share] + --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data in DIR + [PREFIX/com] + --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var] + --libdir=DIR object code libraries in DIR [EPREFIX/lib] + --includedir=DIR C header files in DIR [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include] + --infodir=DIR info documentation in DIR [PREFIX/info] + --mandir=DIR man documentation in DIR [PREFIX/man] + --srcdir=DIR find the sources in DIR [configure dir or ..] + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM + run sed PROGRAM on installed program names +EOF + cat << EOF +Host type: + --build=BUILD configure for building on BUILD [BUILD=HOST] + --host=HOST configure for HOST [guessed] + --target=TARGET configure for TARGET [TARGET=HOST] +Features and packages: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --x-includes=DIR X include files are in DIR + --x-libraries=DIR X library files are in DIR +EOF + if test -n "$ac_help"; then + echo "--enable and --with options recognized:$ac_help" + fi + exit 0 ;; + + -host | --host | --hos | --ho) + ac_prev=host ;; + -host=* | --host=* | --hos=* | --ho=*) + host="$ac_optarg" ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir="$ac_optarg" ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir="$ac_optarg" ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir="$ac_optarg" ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir="$ac_optarg" ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + localstatedir="$ac_optarg" ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir="$ac_optarg" ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir="$ac_optarg" ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix="$ac_optarg" ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix="$ac_optarg" ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix="$ac_optarg" ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name="$ac_optarg" ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir="$ac_optarg" ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir="$ac_optarg" ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site="$ac_optarg" ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir="$ac_optarg" ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir="$ac_optarg" ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target="$ac_optarg" ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers) + echo "configure generated by autoconf version 2.12.2" + exit 0 ;; + + -with-* | --with-*) + ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "with_${ac_package}='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`echo $ac_option|sed -e 's/-*without-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + eval "with_${ac_package}=no" ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes="$ac_optarg" ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries="$ac_optarg" ;; + + -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; } + ;; + + *) + if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then + echo "configure: warning: $ac_option: invalid host type" 1>&2 + fi + if test "x$nonopt" != xNONE; then + { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } + fi + nonopt="$ac_option" + ;; + + esac +done + +if test -n "$ac_prev"; then + { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; } +fi + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +# File descriptor usage: +# 0 standard input +# 1 file creation +# 2 errors and warnings +# 3 some systems may open it to /dev/tty +# 4 used on the Kubota Titan +# 6 checking for... messages and results +# 5 compiler messages saved in config.log +if test "$silent" = yes; then + exec 6>/dev/null +else + exec 6>&1 +fi +exec 5>./config.log + +echo "\ +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. +" 1>&5 + +# Strip out --no-create and --no-recursion so they do not pile up. +# Also quote any args containing shell metacharacters. +ac_configure_args= +for ac_arg +do + case "$ac_arg" in + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) ;; + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) + ac_configure_args="$ac_configure_args '$ac_arg'" ;; + *) ac_configure_args="$ac_configure_args $ac_arg" ;; + esac +done + +# NLS nuisances. +# Only set these to C if already set. These must not be set unconditionally +# because not all systems understand e.g. LANG=C (notably SCO). +# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'! +# Non-C LC_CTYPE values break the ctype check. +if test "${LANG+set}" = set; then LANG=C; export LANG; fi +if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi +if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi +if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo > confdefs.h + +# A filename unique to this package, relative to the directory that +# configure is in, which we can look for to find out if srcdir is correct. +ac_unique_file=Makefile.in + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then its parent. + ac_prog=$0 + ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'` + test "x$ac_confdir" = "x$ac_prog" && ac_confdir=. + srcdir=$ac_confdir + if test ! -r $srcdir/$ac_unique_file; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r $srcdir/$ac_unique_file; then + if test "$ac_srcdir_defaulted" = yes; then + { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; } + else + { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; } + fi +fi +srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'` + +# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + echo "loading site script $ac_site_file" + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + echo "loading cache $cache_file" + . $cache_file +else + echo "creating cache $cache_file" + > $cache_file +fi + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +ac_exeext= +ac_objext=o +if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then + # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. + if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then + ac_n= ac_c=' +' ac_t=' ' + else + ac_n=-n ac_c= ac_t= + fi +else + ac_n= ac_c='\c' ac_t= +fi + + + +echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 +echo "configure:677: checking how to run the C preprocessor" >&5 +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then +if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + # This must be in double quotes, not single quotes, because CPP may get + # substituted into the Makefile and "${CC-cc}" will confuse make. + CPP="${CC-cc} -E" + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. + cat > conftest.$ac_ext < +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:698: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP="${CC-cc} -E -traditional-cpp" + cat > conftest.$ac_ext < +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:715: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP="${CC-cc} -nologo -E" + cat > conftest.$ac_ext < +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:732: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP=/lib/cpp +fi +rm -f conftest* +fi +rm -f conftest* +fi +rm -f conftest* + ac_cv_prog_CPP="$CPP" +fi + CPP="$ac_cv_prog_CPP" +else + ac_cv_prog_CPP="$CPP" +fi +echo "$ac_t""$CPP" 1>&6 + +echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6 +echo "configure:757: checking whether ${MAKE-make} sets \${MAKE}" >&5 +set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftestmake <<\EOF +all: + @echo 'ac_maketemp="${MAKE}"' +EOF +# GNU make sometimes prints "make[1]: Entering...", which would confuse us. +eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=` +if test -n "$ac_maketemp"; then + eval ac_cv_prog_make_${ac_make}_set=yes +else + eval ac_cv_prog_make_${ac_make}_set=no +fi +rm -f conftestmake +fi +if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then + echo "$ac_t""yes" 1>&6 + SET_MAKE= +else + echo "$ac_t""no" 1>&6 + SET_MAKE="MAKE=${MAKE-make}" +fi + +echo $ac_n "checking for POSIXized ISC""... $ac_c" 1>&6 +echo "configure:784: checking for POSIXized ISC" >&5 +if test -d /etc/conf/kconfig.d && + grep _POSIX_VERSION /usr/include/sys/unistd.h >/dev/null 2>&1 +then + echo "$ac_t""yes" 1>&6 + ISC=yes # If later tests want to check for ISC. + cat >> confdefs.h <<\EOF +#define _POSIX_SOURCE 1 +EOF + + if test "$GCC" = yes; then + CC="$CC -posix" + else + CC="$CC -Xp" + fi +else + echo "$ac_t""no" 1>&6 + ISC= +fi + +echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6 +echo "configure:805: checking for ANSI C header files" >&5 +if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#include +#include +#include +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:818: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + ac_cv_header_stdc=yes +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_header_stdc=no +fi +rm -f conftest* + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. +cat > conftest.$ac_ext < +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "memchr" >/dev/null 2>&1; then + : +else + rm -rf conftest* + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. +cat > conftest.$ac_ext < +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "free" >/dev/null 2>&1; then + : +else + rm -rf conftest* + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. +if test "$cross_compiling" = yes; then + : +else + cat > conftest.$ac_ext < +#define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int main () { int i; for (i = 0; i < 256; i++) +if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); +exit (0); } + +EOF +if { (eval echo configure:885: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +then + : +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_header_stdc=no +fi +rm -fr conftest* +fi + +fi +fi + +echo "$ac_t""$ac_cv_header_stdc" 1>&6 +if test $ac_cv_header_stdc = yes; then + cat >> confdefs.h <<\EOF +#define STDC_HEADERS 1 +EOF + +fi + +echo $ac_n "checking for working const""... $ac_c" 1>&6 +echo "configure:909: checking for working const" >&5 +if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <j = 5; +} +{ /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ + const int foo = 10; +} + +; return 0; } +EOF +if { (eval echo configure:963: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_c_const=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_c_const=no +fi +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_c_const" 1>&6 +if test $ac_cv_c_const = no; then + cat >> confdefs.h <<\EOF +#define const +EOF + +fi + +echo $ac_n "checking for inline""... $ac_c" 1>&6 +echo "configure:984: checking for inline" >&5 +if eval "test \"`echo '$''{'ac_cv_c_inline'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_cv_c_inline=no +for ac_kw in inline __inline__ __inline; do + cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_c_inline=$ac_kw; break +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 +fi +rm -f conftest* +done + +fi + +echo "$ac_t""$ac_cv_c_inline" 1>&6 +case "$ac_cv_c_inline" in + inline | yes) ;; + no) cat >> confdefs.h <<\EOF +#define inline +EOF + ;; + *) cat >> confdefs.h <&6 +echo "configure:1024: checking for off_t" >&5 +if eval "test \"`echo '$''{'ac_cv_type_off_t'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#if STDC_HEADERS +#include +#include +#endif +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "off_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then + rm -rf conftest* + ac_cv_type_off_t=yes +else + rm -rf conftest* + ac_cv_type_off_t=no +fi +rm -f conftest* + +fi +echo "$ac_t""$ac_cv_type_off_t" 1>&6 +if test $ac_cv_type_off_t = no; then + cat >> confdefs.h <<\EOF +#define off_t long +EOF + +fi + +echo $ac_n "checking for size_t""... $ac_c" 1>&6 +echo "configure:1057: checking for size_t" >&5 +if eval "test \"`echo '$''{'ac_cv_type_size_t'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#if STDC_HEADERS +#include +#include +#endif +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "size_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then + rm -rf conftest* + ac_cv_type_size_t=yes +else + rm -rf conftest* + ac_cv_type_size_t=no +fi +rm -f conftest* + +fi +echo "$ac_t""$ac_cv_type_size_t" 1>&6 +if test $ac_cv_type_size_t = no; then + cat >> confdefs.h <<\EOF +#define size_t unsigned +EOF + +fi + +# The Ultrix 4.2 mips builtin alloca declared by alloca.h only works +# for constant arguments. Useless! +echo $ac_n "checking for working alloca.h""... $ac_c" 1>&6 +echo "configure:1092: checking for working alloca.h" >&5 +if eval "test \"`echo '$''{'ac_cv_header_alloca_h'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +int main() { +char *p = alloca(2 * sizeof(int)); +; return 0; } +EOF +if { (eval echo configure:1104: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + ac_cv_header_alloca_h=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_header_alloca_h=no +fi +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_header_alloca_h" 1>&6 +if test $ac_cv_header_alloca_h = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_ALLOCA_H 1 +EOF + +fi + +echo $ac_n "checking for alloca""... $ac_c" 1>&6 +echo "configure:1125: checking for alloca" >&5 +if eval "test \"`echo '$''{'ac_cv_func_alloca_works'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +# define alloca _alloca +# else +# if HAVE_ALLOCA_H +# include +# else +# ifdef _AIX + #pragma alloca +# else +# ifndef alloca /* predefined by HP cc +Olibcalls */ +char *alloca (); +# endif +# endif +# endif +# endif +#endif + +int main() { +char *p = (char *) alloca(1); +; return 0; } +EOF +if { (eval echo configure:1158: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + ac_cv_func_alloca_works=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_func_alloca_works=no +fi +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_func_alloca_works" 1>&6 +if test $ac_cv_func_alloca_works = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_ALLOCA 1 +EOF + +fi + +if test $ac_cv_func_alloca_works = no; then + # The SVR3 libPW and SVR4 libucb both contain incompatible functions + # that cause trouble. Some versions do not even contain alloca or + # contain a buggy version. If you still want to use their alloca, + # use ar to extract alloca.o from them instead of compiling alloca.c. + ALLOCA=alloca.${ac_objext} + cat >> confdefs.h <<\EOF +#define C_ALLOCA 1 +EOF + + +echo $ac_n "checking whether alloca needs Cray hooks""... $ac_c" 1>&6 +echo "configure:1190: checking whether alloca needs Cray hooks" >&5 +if eval "test \"`echo '$''{'ac_cv_os_cray'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <&5 | + egrep "webecray" >/dev/null 2>&1; then + rm -rf conftest* + ac_cv_os_cray=yes +else + rm -rf conftest* + ac_cv_os_cray=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_os_cray" 1>&6 +if test $ac_cv_os_cray = yes; then +for ac_func in _getb67 GETB67 getb67; do + echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:1220: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:1248: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + cat >> confdefs.h <&6 +fi + +done +fi + +echo $ac_n "checking stack direction for C alloca""... $ac_c" 1>&6 +echo "configure:1275: checking stack direction for C alloca" >&5 +if eval "test \"`echo '$''{'ac_cv_c_stack_direction'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$cross_compiling" = yes; then + ac_cv_c_stack_direction=0 +else + cat > conftest.$ac_ext < addr) ? 1 : -1; +} +main () +{ + exit (find_stack_direction() < 0); +} +EOF +if { (eval echo configure:1302: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +then + ac_cv_c_stack_direction=1 +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_c_stack_direction=-1 +fi +rm -fr conftest* +fi + +fi + +echo "$ac_t""$ac_cv_c_stack_direction" 1>&6 +cat >> confdefs.h <&6 +echo "configure:1327: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1337: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <&6 +fi +done + +for ac_func in getpagesize +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:1366: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:1394: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <&6 +fi +done + +echo $ac_n "checking for working mmap""... $ac_c" 1>&6 +echo "configure:1419: checking for working mmap" >&5 +if eval "test \"`echo '$''{'ac_cv_func_mmap_fixed_mapped'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$cross_compiling" = yes; then + ac_cv_func_mmap_fixed_mapped=no +else + cat > conftest.$ac_ext < +#include +#include + +/* This mess was copied from the GNU getpagesize.h. */ +#ifndef HAVE_GETPAGESIZE +# ifdef HAVE_UNISTD_H +# include +# endif + +/* Assume that all systems that can run configure have sys/param.h. */ +# ifndef HAVE_SYS_PARAM_H +# define HAVE_SYS_PARAM_H 1 +# endif + +# ifdef _SC_PAGESIZE +# define getpagesize() sysconf(_SC_PAGESIZE) +# else /* no _SC_PAGESIZE */ +# ifdef HAVE_SYS_PARAM_H +# include +# ifdef EXEC_PAGESIZE +# define getpagesize() EXEC_PAGESIZE +# else /* no EXEC_PAGESIZE */ +# ifdef NBPG +# define getpagesize() NBPG * CLSIZE +# ifndef CLSIZE +# define CLSIZE 1 +# endif /* no CLSIZE */ +# else /* no NBPG */ +# ifdef NBPC +# define getpagesize() NBPC +# else /* no NBPC */ +# ifdef PAGESIZE +# define getpagesize() PAGESIZE +# endif /* PAGESIZE */ +# endif /* no NBPC */ +# endif /* no NBPG */ +# endif /* no EXEC_PAGESIZE */ +# else /* no HAVE_SYS_PARAM_H */ +# define getpagesize() 8192 /* punt totally */ +# endif /* no HAVE_SYS_PARAM_H */ +# endif /* no _SC_PAGESIZE */ + +#endif /* no HAVE_GETPAGESIZE */ + +#ifdef __cplusplus +extern "C" { void *malloc(unsigned); } +#else +char *malloc(); +#endif + +int +main() +{ + char *data, *data2, *data3; + int i, pagesize; + int fd; + + pagesize = getpagesize(); + + /* + * First, make a file with some known garbage in it. + */ + data = malloc(pagesize); + if (!data) + exit(1); + for (i = 0; i < pagesize; ++i) + *(data + i) = rand(); + umask(0); + fd = creat("conftestmmap", 0600); + if (fd < 0) + exit(1); + if (write(fd, data, pagesize) != pagesize) + exit(1); + close(fd); + + /* + * Next, try to mmap the file at a fixed address which + * already has something else allocated at it. If we can, + * also make sure that we see the same garbage. + */ + fd = open("conftestmmap", O_RDWR); + if (fd < 0) + exit(1); + data2 = malloc(2 * pagesize); + if (!data2) + exit(1); + data2 += (pagesize - ((int) data2 & (pagesize - 1))) & (pagesize - 1); + if (data2 != mmap(data2, pagesize, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_FIXED, fd, 0L)) + exit(1); + for (i = 0; i < pagesize; ++i) + if (*(data + i) != *(data2 + i)) + exit(1); + + /* + * Finally, make sure that changes to the mapped area + * do not percolate back to the file as seen by read(). + * (This is a bug on some variants of i386 svr4.0.) + */ + for (i = 0; i < pagesize; ++i) + *(data2 + i) = *(data2 + i) + 1; + data3 = malloc(pagesize); + if (!data3) + exit(1); + if (read(fd, data3, pagesize) != pagesize) + exit(1); + for (i = 0; i < pagesize; ++i) + if (*(data + i) != *(data3 + i)) + exit(1); + close(fd); + unlink("conftestmmap"); + exit(0); +} + +EOF +if { (eval echo configure:1567: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +then + ac_cv_func_mmap_fixed_mapped=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_func_mmap_fixed_mapped=no +fi +rm -fr conftest* +fi + +fi + +echo "$ac_t""$ac_cv_func_mmap_fixed_mapped" 1>&6 +if test $ac_cv_func_mmap_fixed_mapped = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_MMAP 1 +EOF + +fi + + +# autoconf.info says this should be called right after AC_INIT. + + +ac_aux_dir= +for ac_dir in `cd $srcdir;pwd`/../.. $srcdir/`cd $srcdir;pwd`/../..; do + if test -f $ac_dir/install-sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f $ac_dir/install.sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + fi +done +if test -z "$ac_aux_dir"; then + { echo "configure: error: can not find install-sh or install.sh in `cd $srcdir;pwd`/../.. $srcdir/`cd $srcdir;pwd`/../.." 1>&2; exit 1; } +fi +ac_config_guess=$ac_aux_dir/config.guess +ac_config_sub=$ac_aux_dir/config.sub +ac_configure=$ac_aux_dir/configure # This should be Cygnus configure. + + +# Do some error checking and defaulting for the host and target type. +# The inputs are: +# configure --host=HOST --target=TARGET --build=BUILD NONOPT +# +# The rules are: +# 1. You are not allowed to specify --host, --target, and nonopt at the +# same time. +# 2. Host defaults to nonopt. +# 3. If nonopt is not specified, then host defaults to the current host, +# as determined by config.guess. +# 4. Target and build default to nonopt. +# 5. If nonopt is not specified, then target and build default to host. + +# The aliases save the names the user supplied, while $host etc. +# will get canonicalized. +case $host---$target---$nonopt in +NONE---*---* | *---NONE---* | *---*---NONE) ;; +*) { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } ;; +esac + + +# Make sure we can run config.sub. +if ${CONFIG_SHELL-/bin/sh} $ac_config_sub sun4 >/dev/null 2>&1; then : +else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; } +fi + +echo $ac_n "checking host system type""... $ac_c" 1>&6 +echo "configure:1640: checking host system type" >&5 + +host_alias=$host +case "$host_alias" in +NONE) + case $nonopt in + NONE) + if host_alias=`${CONFIG_SHELL-/bin/sh} $ac_config_guess`; then : + else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; } + fi ;; + *) host_alias=$nonopt ;; + esac ;; +esac + +host=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $host_alias` +host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` +echo "$ac_t""$host" 1>&6 + +echo $ac_n "checking target system type""... $ac_c" 1>&6 +echo "configure:1661: checking target system type" >&5 + +target_alias=$target +case "$target_alias" in +NONE) + case $nonopt in + NONE) target_alias=$host_alias ;; + *) target_alias=$nonopt ;; + esac ;; +esac + +target=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $target_alias` +target_cpu=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +target_vendor=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +target_os=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` +echo "$ac_t""$target" 1>&6 + +echo $ac_n "checking build system type""... $ac_c" 1>&6 +echo "configure:1679: checking build system type" >&5 + +build_alias=$build +case "$build_alias" in +NONE) + case $nonopt in + NONE) build_alias=$host_alias ;; + *) build_alias=$nonopt ;; + esac ;; +esac + +build=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $build_alias` +build_cpu=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +build_vendor=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +build_os=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` +echo "$ac_t""$build" 1>&6 + +test "$host_alias" != "$target_alias" && + test "$program_prefix$program_suffix$program_transform_name" = \ + NONENONEs,x,x, && + program_prefix=${target_alias}- + +if test "$program_transform_name" = s,x,x,; then + program_transform_name= +else + # Double any \ or $. echo might interpret backslashes. + cat <<\EOF_SED > conftestsed +s,\\,\\\\,g; s,\$,$$,g +EOF_SED + program_transform_name="`echo $program_transform_name|sed -f conftestsed`" + rm -f conftestsed +fi +test "$program_prefix" != NONE && + program_transform_name="s,^,${program_prefix},; $program_transform_name" +# Use a double $ so make ignores it. +test "$program_suffix" != NONE && + program_transform_name="s,\$\$,${program_suffix},; $program_transform_name" + +# sed with no file args requires a program. +test "$program_transform_name" = "" && program_transform_name="s,x,x," + +# Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1723: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CC="gcc" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1752: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_prog_rejected=no + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + break + fi + done + IFS="$ac_save_ifs" +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# -gt 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + set dummy "$ac_dir/$ac_word" "$@" + shift + ac_cv_prog_CC="$@" + fi +fi +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + if test -z "$CC"; then + case "`uname -s`" in + *win32* | *WIN32*) + # Extract the first word of "cl", so it can be a program name with args. +set dummy cl; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1802: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CC="cl" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + ;; + esac + fi + test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; } +fi + +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 +echo "configure:1833: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + ac_cv_prog_cc_works=yes + # If we can't run a trivial program, we are probably using a cross compiler. + if (./conftest; exit) 2>/dev/null; then + ac_cv_prog_cc_cross=no + else + ac_cv_prog_cc_cross=yes + fi +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + ac_cv_prog_cc_works=no +fi +rm -fr conftest* + +echo "$ac_t""$ac_cv_prog_cc_works" 1>&6 +if test $ac_cv_prog_cc_works = no; then + { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } +fi +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 +echo "configure:1867: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 +cross_compiling=$ac_cv_prog_cc_cross + +echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 +echo "configure:1872: checking whether we are using GNU C" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.c <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then + ac_cv_prog_gcc=yes +else + ac_cv_prog_gcc=no +fi +fi + +echo "$ac_t""$ac_cv_prog_gcc" 1>&6 + +if test $ac_cv_prog_gcc = yes; then + GCC=yes +else + GCC= +fi + +ac_test_CFLAGS="${CFLAGS+set}" +ac_save_CFLAGS="$CFLAGS" +CFLAGS= +echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 +echo "configure:1900: checking whether ${CC-cc} accepts -g" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + echo 'void f(){}' > conftest.c +if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then + ac_cv_prog_cc_g=yes +else + ac_cv_prog_cc_g=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_prog_cc_g" 1>&6 +if test "$ac_test_CFLAGS" = set; then + CFLAGS="$ac_save_CFLAGS" +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# ./install, which can be erroneously created by make from ./install.sh. +echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 +echo "configure:1943: checking for a BSD compatible install" >&5 +if test -z "$INSTALL"; then +if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":" + for ac_dir in $PATH; do + # Account for people who put trailing slashes in PATH elements. + case "$ac_dir/" in + /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + if test -f $ac_dir/$ac_prog; then + if test $ac_prog = install && + grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + else + ac_cv_path_install="$ac_dir/$ac_prog -c" + break 2 + fi + fi + done + ;; + esac + done + IFS="$ac_save_IFS" + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL="$ac_cv_path_install" + else + # As a last resort, use the slow shell script. We don't cache a + # path for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the path is relative. + INSTALL="$ac_install_sh" + fi +fi +echo "$ac_t""$INSTALL" 1>&6 + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + + +# Put a plausible default for CC_FOR_BUILD in Makefile. +if test "x$cross_compiling" = "xno"; then + CC_FOR_BUILD='$(CC)' +else + CC_FOR_BUILD=gcc +fi + + + + +AR=${AR-ar} + +# Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:2009: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_RANLIB="ranlib" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":" +fi +fi +RANLIB="$ac_cv_prog_RANLIB" +if test -n "$RANLIB"; then + echo "$ac_t""$RANLIB" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + +ALL_LINGUAS= + + for ac_hdr in argz.h limits.h locale.h nl_types.h malloc.h string.h \ +unistd.h values.h sys/param.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:2043: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:2053: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <&6 +fi +done + + for ac_func in getcwd munmap putenv setenv setlocale strchr strcasecmp \ +__argz_count __argz_stringify __argz_next +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:2083: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:2111: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <&6 +fi +done + + + if test "${ac_cv_func_stpcpy+set}" != "set"; then + for ac_func in stpcpy +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:2140: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:2168: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <&6 +fi +done + + fi + if test "${ac_cv_func_stpcpy}" = "yes"; then + cat >> confdefs.h <<\EOF +#define HAVE_STPCPY 1 +EOF + + fi + + if test $ac_cv_header_locale_h = yes; then + echo $ac_n "checking for LC_MESSAGES""... $ac_c" 1>&6 +echo "configure:2202: checking for LC_MESSAGES" >&5 +if eval "test \"`echo '$''{'am_cv_val_LC_MESSAGES'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +int main() { +return LC_MESSAGES +; return 0; } +EOF +if { (eval echo configure:2214: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + am_cv_val_LC_MESSAGES=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + am_cv_val_LC_MESSAGES=no +fi +rm -f conftest* +fi + +echo "$ac_t""$am_cv_val_LC_MESSAGES" 1>&6 + if test $am_cv_val_LC_MESSAGES = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_LC_MESSAGES 1 +EOF + + fi + fi + echo $ac_n "checking whether NLS is requested""... $ac_c" 1>&6 +echo "configure:2235: checking whether NLS is requested" >&5 + # Check whether --enable-nls or --disable-nls was given. +if test "${enable_nls+set}" = set; then + enableval="$enable_nls" + USE_NLS=$enableval +else + USE_NLS=yes +fi + + echo "$ac_t""$USE_NLS" 1>&6 + + + USE_INCLUDED_LIBINTL=no + + if test "$USE_NLS" = "yes"; then + cat >> confdefs.h <<\EOF +#define ENABLE_NLS 1 +EOF + + echo $ac_n "checking whether included gettext is requested""... $ac_c" 1>&6 +echo "configure:2255: checking whether included gettext is requested" >&5 + # Check whether --with-included-gettext or --without-included-gettext was given. +if test "${with_included_gettext+set}" = set; then + withval="$with_included_gettext" + nls_cv_force_use_gnu_gettext=$withval +else + nls_cv_force_use_gnu_gettext=no +fi + + echo "$ac_t""$nls_cv_force_use_gnu_gettext" 1>&6 + + nls_cv_use_gnu_gettext="$nls_cv_force_use_gnu_gettext" + if test "$nls_cv_force_use_gnu_gettext" != "yes"; then + nls_cv_header_intl= + nls_cv_header_libgt= + CATOBJEXT=NONE + + ac_safe=`echo "libintl.h" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for libintl.h""... $ac_c" 1>&6 +echo "configure:2274: checking for libintl.h" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:2284: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + echo $ac_n "checking for gettext in libc""... $ac_c" 1>&6 +echo "configure:2301: checking for gettext in libc" >&5 +if eval "test \"`echo '$''{'gt_cv_func_gettext_libc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +int main() { +return (int) gettext ("") +; return 0; } +EOF +if { (eval echo configure:2313: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + gt_cv_func_gettext_libc=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + gt_cv_func_gettext_libc=no +fi +rm -f conftest* +fi + +echo "$ac_t""$gt_cv_func_gettext_libc" 1>&6 + + if test "$gt_cv_func_gettext_libc" != "yes"; then + echo $ac_n "checking for bindtextdomain in -lintl""... $ac_c" 1>&6 +echo "configure:2329: checking for bindtextdomain in -lintl" >&5 +ac_lib_var=`echo intl'_'bindtextdomain | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lintl $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + echo $ac_n "checking for gettext in libintl""... $ac_c" 1>&6 +echo "configure:2364: checking for gettext in libintl" >&5 +if eval "test \"`echo '$''{'gt_cv_func_gettext_libintl'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + gt_cv_func_gettext_libintl=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + gt_cv_func_gettext_libintl=no +fi +rm -f conftest* +fi + +echo "$ac_t""$gt_cv_func_gettext_libintl" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + fi + + if test "$gt_cv_func_gettext_libc" = "yes" \ + || test "$gt_cv_func_gettext_libintl" = "yes"; then + cat >> confdefs.h <<\EOF +#define HAVE_GETTEXT 1 +EOF + + # Extract the first word of "msgfmt", so it can be a program name with args. +set dummy msgfmt; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:2404: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_MSGFMT'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$MSGFMT" in + /*) + ac_cv_path_MSGFMT="$MSGFMT" # Let the user override the test with a path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"; then + ac_cv_path_MSGFMT="$ac_dir/$ac_word" + break + fi + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_MSGFMT" && ac_cv_path_MSGFMT="no" + ;; +esac +fi +MSGFMT="$ac_cv_path_MSGFMT" +if test -n "$MSGFMT"; then + echo "$ac_t""$MSGFMT" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + if test "$MSGFMT" != "no"; then + for ac_func in dcgettext +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:2438: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:2466: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <&6 +fi +done + + # Extract the first word of "gmsgfmt", so it can be a program name with args. +set dummy gmsgfmt; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:2493: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_GMSGFMT'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$GMSGFMT" in + /*) + ac_cv_path_GMSGFMT="$GMSGFMT" # Let the user override the test with a path. + ;; + ?:/*) + ac_cv_path_GMSGFMT="$GMSGFMT" # Let the user override the test with a dos path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_path_GMSGFMT="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_GMSGFMT" && ac_cv_path_GMSGFMT="$MSGFMT" + ;; +esac +fi +GMSGFMT="$ac_cv_path_GMSGFMT" +if test -n "$GMSGFMT"; then + echo "$ac_t""$GMSGFMT" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + # Extract the first word of "xgettext", so it can be a program name with args. +set dummy xgettext; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:2528: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_XGETTEXT'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$XGETTEXT" in + /*) + ac_cv_path_XGETTEXT="$XGETTEXT" # Let the user override the test with a path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"; then + ac_cv_path_XGETTEXT="$ac_dir/$ac_word" + break + fi + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_XGETTEXT" && ac_cv_path_XGETTEXT=":" + ;; +esac +fi +XGETTEXT="$ac_cv_path_XGETTEXT" +if test -n "$XGETTEXT"; then + echo "$ac_t""$XGETTEXT" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + CATOBJEXT=.gmo + DATADIRNAME=share +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CATOBJEXT=.mo + DATADIRNAME=lib +fi +rm -f conftest* + INSTOBJEXT=.mo + fi + fi + +else + echo "$ac_t""no" 1>&6 +fi + + + + if test "$CATOBJEXT" = "NONE"; then + nls_cv_use_gnu_gettext=yes + fi + fi + + if test "$nls_cv_use_gnu_gettext" = "yes"; then + INTLOBJS="\$(GETTOBJS)" + # Extract the first word of "msgfmt", so it can be a program name with args. +set dummy msgfmt; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:2600: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_MSGFMT'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$MSGFMT" in + /*) + ac_cv_path_MSGFMT="$MSGFMT" # Let the user override the test with a path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"; then + ac_cv_path_MSGFMT="$ac_dir/$ac_word" + break + fi + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_MSGFMT" && ac_cv_path_MSGFMT="msgfmt" + ;; +esac +fi +MSGFMT="$ac_cv_path_MSGFMT" +if test -n "$MSGFMT"; then + echo "$ac_t""$MSGFMT" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + # Extract the first word of "gmsgfmt", so it can be a program name with args. +set dummy gmsgfmt; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:2634: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_GMSGFMT'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$GMSGFMT" in + /*) + ac_cv_path_GMSGFMT="$GMSGFMT" # Let the user override the test with a path. + ;; + ?:/*) + ac_cv_path_GMSGFMT="$GMSGFMT" # Let the user override the test with a dos path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_path_GMSGFMT="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_GMSGFMT" && ac_cv_path_GMSGFMT="$MSGFMT" + ;; +esac +fi +GMSGFMT="$ac_cv_path_GMSGFMT" +if test -n "$GMSGFMT"; then + echo "$ac_t""$GMSGFMT" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + # Extract the first word of "xgettext", so it can be a program name with args. +set dummy xgettext; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:2669: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_XGETTEXT'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$XGETTEXT" in + /*) + ac_cv_path_XGETTEXT="$XGETTEXT" # Let the user override the test with a path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"; then + ac_cv_path_XGETTEXT="$ac_dir/$ac_word" + break + fi + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_XGETTEXT" && ac_cv_path_XGETTEXT=":" + ;; +esac +fi +XGETTEXT="$ac_cv_path_XGETTEXT" +if test -n "$XGETTEXT"; then + echo "$ac_t""$XGETTEXT" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + + USE_INCLUDED_LIBINTL=yes + CATOBJEXT=.gmo + INSTOBJEXT=.mo + DATADIRNAME=share + INTLDEPS='$(top_builddir)/../intl/libintl.a' + INTLLIBS=$INTLDEPS + LIBS=`echo $LIBS | sed -e 's/-lintl//'` + nls_cv_header_intl=libintl.h + nls_cv_header_libgt=libgettext.h + fi + + if test "$XGETTEXT" != ":"; then + if $XGETTEXT --omit-header /dev/null 2> /dev/null; then + : ; + else + echo "$ac_t""found xgettext programs is not GNU xgettext; ignore it" 1>&6 + XGETTEXT=":" + fi + fi + + # We need to process the po/ directory. + POSUB=po + else + DATADIRNAME=share + nls_cv_header_intl=libintl.h + nls_cv_header_libgt=libgettext.h + fi + + # If this is used in GNU gettext we have to set USE_NLS to `yes' + # because some of the sources are only built for this goal. + if test "$PACKAGE" = gettext; then + USE_NLS=yes + USE_INCLUDED_LIBINTL=yes + fi + + for lang in $ALL_LINGUAS; do + GMOFILES="$GMOFILES $lang.gmo" + POFILES="$POFILES $lang.po" + done + + + + + + + + + + + + + + + if test "x$CATOBJEXT" != "x"; then + if test "x$ALL_LINGUAS" = "x"; then + LINGUAS= + else + echo $ac_n "checking for catalogs to be installed""... $ac_c" 1>&6 +echo "configure:2759: checking for catalogs to be installed" >&5 + NEW_LINGUAS= + for lang in ${LINGUAS=$ALL_LINGUAS}; do + case "$ALL_LINGUAS" in + *$lang*) NEW_LINGUAS="$NEW_LINGUAS $lang" ;; + esac + done + LINGUAS=$NEW_LINGUAS + echo "$ac_t""$LINGUAS" 1>&6 + fi + + if test -n "$LINGUAS"; then + for lang in $LINGUAS; do CATALOGS="$CATALOGS $lang$CATOBJEXT"; done + fi + fi + + if test $ac_cv_header_locale_h = yes; then + INCLUDE_LOCALE_H="#include " + else + INCLUDE_LOCALE_H="\ +/* The system does not provide the header . Take care yourself. */" + fi + + + if test -f $srcdir/po2tbl.sed.in; then + if test "$CATOBJEXT" = ".cat"; then + ac_safe=`echo "linux/version.h" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for linux/version.h""... $ac_c" 1>&6 +echo "configure:2787: checking for linux/version.h" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:2797: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + msgformat=linux +else + echo "$ac_t""no" 1>&6 +msgformat=xopen +fi + + + sed -e '/^#/d' $srcdir/$msgformat-msg.sed > po2msg.sed + fi + sed -e '/^#.*[^\\]$/d' -e '/^#$/d' \ + $srcdir/po2tbl.sed.in > po2tbl.sed + fi + + if test "$PACKAGE" = "gettext"; then + GT_NO="#NO#" + GT_YES= + else + GT_NO= + GT_YES="#YES#" + fi + + + + MKINSTALLDIRS="\$(srcdir)/../../mkinstalldirs" + + + l= + + + if test -d $srcdir/po; then + test -d po || mkdir po + if test "x$srcdir" != "x."; then + if test "x`echo $srcdir | sed 's@/.*@@'`" = "x"; then + posrcprefix="$srcdir/" + else + posrcprefix="../$srcdir/" + fi + else + posrcprefix="../" + fi + rm -f po/POTFILES + sed -e "/^#/d" -e "/^\$/d" -e "s,.*, $posrcprefix& \\\\," -e "\$s/\(.*\) \\\\/\1/" \ + < $srcdir/po/POTFILES.in > po/POTFILES + fi + + +# Check for common headers. +# FIXME: Seems to me this can cause problems for i386-windows hosts. +# At one point there were hardcoded AC_DEFINE's if ${host} = i386-*-windows*. +for ac_hdr in stdlib.h string.h strings.h unistd.h time.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:2866: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:2876: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <&6 +fi +done + +for ac_hdr in sys/time.h sys/resource.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:2906: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:2916: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <&6 +fi +done + +for ac_hdr in fcntl.h fpu_control.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:2946: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:2956: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <&6 +fi +done + +for ac_func in getrusage time sigaction __setfpucw +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:2985: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:3013: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <&6 +fi +done + + +# Check for socket libraries +echo $ac_n "checking for bind in -lsocket""... $ac_c" 1>&6 +echo "configure:3040: checking for bind in -lsocket" >&5 +ac_lib_var=`echo socket'_'bind | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lsocket $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_lib=HAVE_LIB`echo socket | sed -e 's/[^a-zA-Z0-9_]/_/g' \ + -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'` + cat >> confdefs.h <&6 +fi + +echo $ac_n "checking for gethostbyname in -lnsl""... $ac_c" 1>&6 +echo "configure:3087: checking for gethostbyname in -lnsl" >&5 +ac_lib_var=`echo nsl'_'gethostbyname | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lnsl $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_lib=HAVE_LIB`echo nsl | sed -e 's/[^a-zA-Z0-9_]/_/g' \ + -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'` + cat >> confdefs.h <&6 +fi + + +. ${srcdir}/../../bfd/configure.host + + + +USE_MAINTAINER_MODE=no +# Check whether --enable-maintainer-mode or --disable-maintainer-mode was given. +if test "${enable_maintainer_mode+set}" = set; then + enableval="$enable_maintainer_mode" + case "${enableval}" in + yes) MAINT="" USE_MAINTAINER_MODE=yes ;; + no) MAINT="#" ;; + *) { echo "configure: error: "--enable-maintainer-mode does not take a value"" 1>&2; exit 1; }; MAINT="#" ;; +esac +if test x"$silent" != x"yes" && test x"$MAINT" = x""; then + echo "Setting maintainer mode" 6>&1 +fi +else + MAINT="#" +fi + + + +# Check whether --enable-sim-bswap or --disable-sim-bswap was given. +if test "${enable_sim_bswap+set}" = set; then + enableval="$enable_sim_bswap" + case "${enableval}" in + yes) sim_bswap="-DWITH_BSWAP=1 -DUSE_BSWAP=1";; + no) sim_bswap="-DWITH_BSWAP=0";; + *) { echo "configure: error: "--enable-sim-bswap does not take a value"" 1>&2; exit 1; }; sim_bswap="";; +esac +if test x"$silent" != x"yes" && test x"$sim_bswap" != x""; then + echo "Setting bswap flags = $sim_bswap" 6>&1 +fi +else + sim_bswap="" +fi + + + +# Check whether --enable-sim-cflags or --disable-sim-cflags was given. +if test "${enable_sim_cflags+set}" = set; then + enableval="$enable_sim_cflags" + case "${enableval}" in + yes) sim_cflags="-O2 -fomit-frame-pointer";; + trace) { echo "configure: error: "Please use --enable-sim-debug instead."" 1>&2; exit 1; }; sim_cflags="";; + no) sim_cflags="";; + *) sim_cflags=`echo "${enableval}" | sed -e "s/,/ /g"`;; +esac +if test x"$silent" != x"yes" && test x"$sim_cflags" != x""; then + echo "Setting sim cflags = $sim_cflags" 6>&1 +fi +else + sim_cflags="" +fi + + + +# Check whether --enable-sim-debug or --disable-sim-debug was given. +if test "${enable_sim_debug+set}" = set; then + enableval="$enable_sim_debug" + case "${enableval}" in + yes) sim_debug="-DDEBUG=7 -DWITH_DEBUG=7";; + no) sim_debug="-DDEBUG=0 -DWITH_DEBUG=0";; + *) sim_debug="-DDEBUG='(${enableval})' -DWITH_DEBUG='(${enableval})'";; +esac +if test x"$silent" != x"yes" && test x"$sim_debug" != x""; then + echo "Setting sim debug = $sim_debug" 6>&1 +fi +else + sim_debug="" +fi + + + +# Check whether --enable-sim-stdio or --disable-sim-stdio was given. +if test "${enable_sim_stdio+set}" = set; then + enableval="$enable_sim_stdio" + case "${enableval}" in + yes) sim_stdio="-DWITH_STDIO=DO_USE_STDIO";; + no) sim_stdio="-DWITH_STDIO=DONT_USE_STDIO";; + *) { echo "configure: error: "Unknown value $enableval passed to --enable-sim-stdio"" 1>&2; exit 1; }; sim_stdio="";; +esac +if test x"$silent" != x"yes" && test x"$sim_stdio" != x""; then + echo "Setting stdio flags = $sim_stdio" 6>&1 +fi +else + sim_stdio="" +fi + + + +# Check whether --enable-sim-trace or --disable-sim-trace was given. +if test "${enable_sim_trace+set}" = set; then + enableval="$enable_sim_trace" + case "${enableval}" in + yes) sim_trace="-DTRACE=1 -DWITH_TRACE=-1";; + no) sim_trace="-DTRACE=0 -DWITH_TRACE=0";; + [-0-9]*) + sim_trace="-DTRACE='(${enableval})' -DWITH_TRACE='(${enableval})'";; + [a-z]*) + sim_trace="" + for x in `echo "$enableval" | sed -e "s/,/ /g"`; do + if test x"$sim_trace" = x; then + sim_trace="-DWITH_TRACE='(TRACE_$x" + else + sim_trace="${sim_trace}|TRACE_$x" + fi + done + sim_trace="$sim_trace)'" ;; +esac +if test x"$silent" != x"yes" && test x"$sim_trace" != x""; then + echo "Setting sim trace = $sim_trace" 6>&1 +fi +else + sim_trace="" +fi + + + +# Check whether --enable-sim-profile or --disable-sim-profile was given. +if test "${enable_sim_profile+set}" = set; then + enableval="$enable_sim_profile" + case "${enableval}" in + yes) sim_profile="-DPROFILE=1 -DWITH_PROFILE=-1";; + no) sim_profile="-DPROFILE=0 -DWITH_PROFILE=0";; + [-0-9]*) + sim_profile="-DPROFILE='(${enableval})' -DWITH_PROFILE='(${enableval})'";; + [a-z]*) + sim_profile="" + for x in `echo "$enableval" | sed -e "s/,/ /g"`; do + if test x"$sim_profile" = x; then + sim_profile="-DWITH_PROFILE='(PROFILE_$x" + else + sim_profile="${sim_profile}|PROFILE_$x" + fi + done + sim_profile="$sim_profile)'" ;; +esac +if test x"$silent" != x"yes" && test x"$sim_profile" != x""; then + echo "Setting sim profile = $sim_profile" 6>&1 +fi +else + sim_profile="" +fi + + + +echo $ac_n "checking return type of signal handlers""... $ac_c" 1>&6 +echo "configure:3282: checking return type of signal handlers" >&5 +if eval "test \"`echo '$''{'ac_cv_type_signal'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#include +#ifdef signal +#undef signal +#endif +#ifdef __cplusplus +extern "C" void (*signal (int, void (*)(int)))(int); +#else +void (*signal ()) (); +#endif + +int main() { +int i; +; return 0; } +EOF +if { (eval echo configure:3304: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_type_signal=void +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_type_signal=int +fi +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_type_signal" 1>&6 +cat >> confdefs.h <&6 +echo "configure:3324: checking for executable suffix" >&5 +if eval "test \"`echo '$''{'am_cv_exeext'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$CYGWIN32" = yes; then +am_cv_exeext=.exe +else +cat > am_c_test.c << 'EOF' +int main() { +/* Nothing needed here */ +} +EOF +${CC-cc} -o am_c_test $CFLAGS $CPPFLAGS $LDFLAGS am_c_test.c $LIBS 1>&5 +am_cv_exeext=`ls am_c_test.* | grep -v am_c_test.c | sed -e s/am_c_test//` +rm -f am_c_test* +fi + +test x"${am_cv_exeext}" = x && am_cv_exeext=no +fi +EXEEXT="" +test x"${am_cv_exeext}" != xno && EXEEXT=${am_cv_exeext} +echo "$ac_t""${am_cv_exeext}" 1>&6 + + +sim_link_files= +sim_link_links= + +sim_link_links=tconfig.h +if test -f ${srcdir}/tconfig.in +then + sim_link_files=tconfig.in +else + sim_link_files=../common/tconfig.in +fi + +# targ-vals.def points to the libc macro description file. +case "${target}" in +*-*-*) TARG_VALS_DEF=../common/nltvals.def ;; +esac +sim_link_files="${sim_link_files} ${TARG_VALS_DEF}" +sim_link_links="${sim_link_links} targ-vals.def" + + + +for ac_hdr in unistd.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:3372: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:3382: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <&6 +fi +done + + + + +trap '' 1 2 15 +cat > confcache <<\EOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs. It is not useful on other systems. +# If it contains results you don't want to keep, you may remove or edit it. +# +# By default, configure uses ./config.cache as the cache file, +# creating it if it does not exist already. You can give configure +# the --cache-file=FILE option to use a different cache file; that is +# what configure does when it calls configure scripts in +# subdirectories, so they share the cache. +# Giving --cache-file=/dev/null disables caching, for debugging configure. +# config.status only pays attention to the cache file if you give it the +# --recheck option to rerun configure. +# +EOF +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +(set) 2>&1 | + case `(ac_space=' '; set) 2>&1 | grep ac_space` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote substitution + # turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + -e "s/'/'\\\\''/g" \ + -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' + ;; + esac >> confcache +if cmp -s $cache_file confcache; then + : +else + if test -w $cache_file; then + echo "updating cache $cache_file" + cat confcache > $cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# Any assignment to VPATH causes Sun make to only execute +# the first set of double-colon rules, so remove it if not needed. +# If there is a colon in the path, we need to keep it. +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d' +fi + +trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15 + +DEFS=-DHAVE_CONFIG_H + +# Without the "./", some shells look in PATH for config.status. +: ${CONFIG_STATUS=./config.status} + +echo creating $CONFIG_STATUS +rm -f $CONFIG_STATUS +cat > $CONFIG_STATUS </dev/null | sed 1q`: +# +# $0 $ac_configure_args +# +# Compiler output produced by configure, useful for debugging +# configure, is in ./config.log if it exists. + +ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]" +for ac_option +do + case "\$ac_option" in + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion" + exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;; + -version | --version | --versio | --versi | --vers | --ver | --ve | --v) + echo "$CONFIG_STATUS generated by autoconf version 2.12.2" + exit 0 ;; + -help | --help | --hel | --he | --h) + echo "\$ac_cs_usage"; exit 0 ;; + *) echo "\$ac_cs_usage"; exit 1 ;; + esac +done + +ac_given_srcdir=$srcdir +ac_given_INSTALL="$INSTALL" + +trap 'rm -fr `echo "Makefile.sim:Makefile.in Make-common.sim:../common/Make-common.in .gdbinit:../common/gdbinit.in config.h:config.in" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 +EOF +cat >> $CONFIG_STATUS < conftest.subs <<\\CEOF +$ac_vpsub +$extrasub +s%@sim_environment@%$sim_environment%g +s%@sim_alignment@%$sim_alignment%g +s%@sim_assert@%$sim_assert%g +s%@sim_bitsize@%$sim_bitsize%g +s%@sim_endian@%$sim_endian%g +s%@sim_hostendian@%$sim_hostendian%g +s%@sim_float@%$sim_float%g +s%@sim_scache@%$sim_scache%g +s%@sim_default_model@%$sim_default_model%g +s%@sim_hw_cflags@%$sim_hw_cflags%g +s%@sim_hw_objs@%$sim_hw_objs%g +s%@sim_hw@%$sim_hw%g +s%@sim_inline@%$sim_inline%g +s%@sim_packages@%$sim_packages%g +s%@sim_regparm@%$sim_regparm%g +s%@sim_reserved_bits@%$sim_reserved_bits%g +s%@sim_smp@%$sim_smp%g +s%@sim_stdcall@%$sim_stdcall%g +s%@sim_xor_endian@%$sim_xor_endian%g +s%@build_warnings@%$build_warnings%g +s%@SHELL@%$SHELL%g +s%@CFLAGS@%$CFLAGS%g +s%@CPPFLAGS@%$CPPFLAGS%g +s%@CXXFLAGS@%$CXXFLAGS%g +s%@DEFS@%$DEFS%g +s%@LDFLAGS@%$LDFLAGS%g +s%@LIBS@%$LIBS%g +s%@exec_prefix@%$exec_prefix%g +s%@prefix@%$prefix%g +s%@program_transform_name@%$program_transform_name%g +s%@bindir@%$bindir%g +s%@sbindir@%$sbindir%g +s%@libexecdir@%$libexecdir%g +s%@datadir@%$datadir%g +s%@sysconfdir@%$sysconfdir%g +s%@sharedstatedir@%$sharedstatedir%g +s%@localstatedir@%$localstatedir%g +s%@libdir@%$libdir%g +s%@includedir@%$includedir%g +s%@oldincludedir@%$oldincludedir%g +s%@infodir@%$infodir%g +s%@mandir@%$mandir%g +s%@host@%$host%g +s%@host_alias@%$host_alias%g +s%@host_cpu@%$host_cpu%g +s%@host_vendor@%$host_vendor%g +s%@host_os@%$host_os%g +s%@target@%$target%g +s%@target_alias@%$target_alias%g +s%@target_cpu@%$target_cpu%g +s%@target_vendor@%$target_vendor%g +s%@target_os@%$target_os%g +s%@build@%$build%g +s%@build_alias@%$build_alias%g +s%@build_cpu@%$build_cpu%g +s%@build_vendor@%$build_vendor%g +s%@build_os@%$build_os%g +s%@CC@%$CC%g +s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g +s%@INSTALL_DATA@%$INSTALL_DATA%g +s%@CC_FOR_BUILD@%$CC_FOR_BUILD%g +s%@HDEFINES@%$HDEFINES%g +s%@AR@%$AR%g +s%@RANLIB@%$RANLIB%g +s%@SET_MAKE@%$SET_MAKE%g +s%@CPP@%$CPP%g +s%@ALLOCA@%$ALLOCA%g +s%@USE_NLS@%$USE_NLS%g +s%@MSGFMT@%$MSGFMT%g +s%@GMSGFMT@%$GMSGFMT%g +s%@XGETTEXT@%$XGETTEXT%g +s%@USE_INCLUDED_LIBINTL@%$USE_INCLUDED_LIBINTL%g +s%@CATALOGS@%$CATALOGS%g +s%@CATOBJEXT@%$CATOBJEXT%g +s%@DATADIRNAME@%$DATADIRNAME%g +s%@GMOFILES@%$GMOFILES%g +s%@INSTOBJEXT@%$INSTOBJEXT%g +s%@INTLDEPS@%$INTLDEPS%g +s%@INTLLIBS@%$INTLLIBS%g +s%@INTLOBJS@%$INTLOBJS%g +s%@POFILES@%$POFILES%g +s%@POSUB@%$POSUB%g +s%@INCLUDE_LOCALE_H@%$INCLUDE_LOCALE_H%g +s%@GT_NO@%$GT_NO%g +s%@GT_YES@%$GT_YES%g +s%@MKINSTALLDIRS@%$MKINSTALLDIRS%g +s%@l@%$l%g +s%@MAINT@%$MAINT%g +s%@sim_bswap@%$sim_bswap%g +s%@sim_cflags@%$sim_cflags%g +s%@sim_debug@%$sim_debug%g +s%@sim_stdio@%$sim_stdio%g +s%@sim_trace@%$sim_trace%g +s%@sim_profile@%$sim_profile%g +s%@EXEEXT@%$EXEEXT%g + +CEOF +EOF + +cat >> $CONFIG_STATUS <<\EOF + +# Split the substitutions into bite-sized pieces for seds with +# small command number limits, like on Digital OSF/1 and HP-UX. +ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script. +ac_file=1 # Number of current file. +ac_beg=1 # First line for current file. +ac_end=$ac_max_sed_cmds # Line after last line for current file. +ac_more_lines=: +ac_sed_cmds="" +while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file + else + sed "${ac_end}q" conftest.subs > conftest.s$ac_file + fi + if test ! -s conftest.s$ac_file; then + ac_more_lines=false + rm -f conftest.s$ac_file + else + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f conftest.s$ac_file" + else + ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file" + fi + ac_file=`expr $ac_file + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_cmds` + fi +done +if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat +fi +EOF + +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories. + + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`" + # A "../" for each directory in $ac_dir_suffix. + ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'` + else + ac_dir_suffix= ac_dots= + fi + + case "$ac_given_srcdir" in + .) srcdir=. + if test -z "$ac_dots"; then top_srcdir=. + else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;; + /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;; + *) # Relative path. + srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix" + top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + + case "$ac_given_INSTALL" in + [/$]*) INSTALL="$ac_given_INSTALL" ;; + *) INSTALL="$ac_dots$ac_given_INSTALL" ;; + esac + + echo creating "$ac_file" + rm -f "$ac_file" + configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure." + case "$ac_file" in + *Makefile*) ac_comsub="1i\\ +# $configure_input" ;; + *) ac_comsub= ;; + esac + + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + sed -e "$ac_comsub +s%@configure_input@%$configure_input%g +s%@srcdir@%$srcdir%g +s%@top_srcdir@%$top_srcdir%g +s%@INSTALL@%$INSTALL%g +" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file +fi; done +rm -f conftest.s* + +# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where +# NAME is the cpp macro being defined and VALUE is the value it is being given. +# +# ac_d sets the value in "#define NAME VALUE" lines. +ac_dA='s%^\([ ]*\)#\([ ]*define[ ][ ]*\)' +ac_dB='\([ ][ ]*\)[^ ]*%\1#\2' +ac_dC='\3' +ac_dD='%g' +# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE". +ac_uA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_uB='\([ ]\)%\1#\2define\3' +ac_uC=' ' +ac_uD='\4%g' +# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE". +ac_eA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_eB='$%\1#\2define\3' +ac_eC=' ' +ac_eD='%g' + +if test "${CONFIG_HEADERS+set}" != set; then +EOF +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +fi +for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + echo creating $ac_file + + rm -f conftest.frag conftest.in conftest.out + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + cat $ac_file_inputs > conftest.in + +EOF + +# Transform confdefs.h into a sed script conftest.vals that substitutes +# the proper values into config.h.in to produce config.h. And first: +# Protect against being on the right side of a sed subst in config.status. +# Protect against being in an unquoted here document in config.status. +rm -f conftest.vals +cat > conftest.hdr <<\EOF +s/[\\&%]/\\&/g +s%[\\$`]%\\&%g +s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp +s%ac_d%ac_u%gp +s%ac_u%ac_e%gp +EOF +sed -n -f conftest.hdr confdefs.h > conftest.vals +rm -f conftest.hdr + +# This sed command replaces #undef with comments. This is necessary, for +# example, in the case of _POSIX_SOURCE, which is predefined and required +# on some systems where configure will not decide to define it. +cat >> conftest.vals <<\EOF +s%^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */% +EOF + +# Break up conftest.vals because some shells have a limit on +# the size of here documents, and old seds have small limits too. + +rm -f conftest.tail +while : +do + ac_lines=`grep -c . conftest.vals` + # grep -c gives empty output for an empty file on some AIX systems. + if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi + # Write a limited-size here document to conftest.frag. + echo ' cat > conftest.frag <> $CONFIG_STATUS + sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS + echo 'CEOF + sed -f conftest.frag conftest.in > conftest.out + rm -f conftest.in + mv conftest.out conftest.in +' >> $CONFIG_STATUS + sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail + rm -f conftest.vals + mv conftest.tail conftest.vals +done +rm -f conftest.vals + +cat >> $CONFIG_STATUS <<\EOF + rm -f conftest.frag conftest.h + echo "/* $ac_file. Generated automatically by configure. */" > conftest.h + cat conftest.in >> conftest.h + rm -f conftest.in + if cmp -s $ac_file conftest.h 2>/dev/null; then + echo "$ac_file is unchanged" + rm -f conftest.h + else + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + fi + rm -f $ac_file + mv conftest.h $ac_file + fi +fi; done + +EOF + +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +srcdir=$ac_given_srcdir +while test -n "$ac_sources"; do + set $ac_dests; ac_dest=$1; shift; ac_dests=$* + set $ac_sources; ac_source=$1; shift; ac_sources=$* + + echo "linking $srcdir/$ac_source to $ac_dest" + + if test ! -r $srcdir/$ac_source; then + { echo "configure: error: $srcdir/$ac_source: File not found" 1>&2; exit 1; } + fi + rm -f $ac_dest + + # Make relative symlinks. + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dest_dir=`echo $ac_dest|sed 's%/[^/][^/]*$%%'` + if test "$ac_dest_dir" != "$ac_dest" && test "$ac_dest_dir" != .; then + # The dest file is in a subdirectory. + test ! -d "$ac_dest_dir" && mkdir "$ac_dest_dir" + ac_dest_dir_suffix="/`echo $ac_dest_dir|sed 's%^\./%%'`" + # A "../" for each directory in $ac_dest_dir_suffix. + ac_dots=`echo $ac_dest_dir_suffix|sed 's%/[^/]*%../%g'` + else + ac_dest_dir_suffix= ac_dots= + fi + + case "$srcdir" in + [/$]*) ac_rel_source="$srcdir/$ac_source" ;; + *) ac_rel_source="$ac_dots$srcdir/$ac_source" ;; + esac + + # Make a symlink if possible; otherwise try a hard link. + if ln -s $ac_rel_source $ac_dest 2>/dev/null || + ln $srcdir/$ac_source $ac_dest; then : + else + { echo "configure: error: can not link $ac_dest to $srcdir/$ac_source" 1>&2; exit 1; } + fi +done +EOF +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +case "x$CONFIG_FILES" in + xMakefile*) + echo "Merging Makefile.sim+Make-common.sim into Makefile ..." + rm -f Makesim1.tmp Makesim2.tmp Makefile + sed -n -e '/^## COMMON_PRE_/,/^## End COMMON_PRE_/ p' Makesim1.tmp + sed -n -e '/^## COMMON_POST_/,/^## End COMMON_POST_/ p' Makesim2.tmp + sed -e '/^## COMMON_PRE_/ r Makesim1.tmp' \ + -e '/^## COMMON_POST_/ r Makesim2.tmp' \ + Makefile + rm -f Makefile.sim Make-common.sim Makesim1.tmp Makesim2.tmp + ;; + esac + case "x$CONFIG_HEADERS" in xconfig.h:config.in) echo > stamp-h ;; esac + +exit 0 +EOF +chmod +x $CONFIG_STATUS +rm -fr confdefs* $ac_clean_files +test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1 + + diff --git a/sim/arm/configure.in b/sim/arm/configure.in new file mode 100644 index 00000000000..033b0bc1615 --- /dev/null +++ b/sim/arm/configure.in @@ -0,0 +1,10 @@ +dnl Process this file with autoconf to produce a configure script. +sinclude(../common/aclocal.m4) +AC_PREREQ(2.5)dnl +AC_INIT(Makefile.in) + +SIM_AC_COMMON + +AC_CHECK_HEADERS(unistd.h) + +SIM_AC_OUTPUT diff --git a/sim/arm/dbg_conf.h b/sim/arm/dbg_conf.h new file mode 100644 index 00000000000..c0e486f23e4 --- /dev/null +++ b/sim/arm/dbg_conf.h @@ -0,0 +1,48 @@ +/* dbg_conf.h -- ARMulator debug interface: ARM6 Instruction Emulator. + Copyright (C) 1994 Advanced RISC Machines Ltd. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef Dbg_Conf__h + +#define Dbg_Conf__h + +typedef struct Dbg_ConfigBlock { + int bytesex; + long memorysize; + int serialport; /*) remote connection parameters */ + int seriallinespeed; /*) (serial connection) */ + int parallelport; /*) ditto */ + int parallellinespeed; /*) (parallel connection) */ + int processor; /* processor the armulator is to emulate (eg ARM60) */ + int rditype; /* armulator / remote processor */ + int drivertype; /* parallel / serial / etc */ + char const *configtoload; + int flags; +} Dbg_ConfigBlock; + +#define Dbg_ConfigFlag_Reset 1 + +typedef struct Dbg_HostosInterface Dbg_HostosInterface; +/* This structure allows access by the (host-independent) C-library support + module of armulator or pisd (armos.c) to host-dependent functions for + which there is no host-independent interface. Its contents are unknown + to the debugger toolbox. + The assumption is that, in a windowed system, fputc(stderr) for example + may not achieve the desired effect of the character appearing in some + window. + */ + +#endif diff --git a/sim/arm/dbg_cp.h b/sim/arm/dbg_cp.h new file mode 100644 index 00000000000..9f2f93d3aa8 --- /dev/null +++ b/sim/arm/dbg_cp.h @@ -0,0 +1,62 @@ +/* dbg_cp.h -- ARMulator debug interface: ARM6 Instruction Emulator. + Copyright (C) 1994 Advanced RISC Machines Ltd. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef Dbg_CP__h + +#define Dbg_CP__h + +#define Dbg_Access_Readable 1 +#define Dbg_Access_Writable 2 +#define Dbg_Access_CPDT 4 /* else CPRT */ + +typedef struct { + unsigned short rmin, rmax; + /* a single description can be used for a range of registers with + the same properties *accessed via CPDT instructions* + */ + unsigned char nbytes; /* size of register */ + unsigned char access; /* see above (Access_xxx) */ + union { + struct { /* CPDT instructions do not allow the coprocessor much freedom: + only bit 22 ('N') and 12-15 ('CRd') are free for the + coprocessor to use as it sees fit. + */ + unsigned char nbit; + unsigned char rdbits; + } cpdt; + struct { /* CPRT instructions have much more latitude. The bits fixed + by the ARM are 24..31 (condition mask & opcode) + 20 (direction) + 8..15 (cpnum, arm register) + 4 (CPRT not CPDO) + leaving 14 bits free to the coprocessor (fortunately + falling within two bytes). + */ + unsigned char read_b0, read_b1, + write_b0, write_b1; + } cprt; + } accessinst; +} Dbg_CoProRegDesc; + +struct Dbg_CoProDesc { + int entries; + Dbg_CoProRegDesc regdesc[1/* really nentries */]; +}; + +#define Dbg_CoProDesc_Size(n) (sizeof(struct Dbg_CoProDesc) + (n-1)*sizeof(Dbg_CoProRegDesc)) + +#endif diff --git a/sim/arm/dbg_hif.h b/sim/arm/dbg_hif.h new file mode 100644 index 00000000000..727b759a495 --- /dev/null +++ b/sim/arm/dbg_hif.h @@ -0,0 +1,47 @@ +/* dbg_hif.h -- ARMulator debug interface: ARM6 Instruction Emulator. + Copyright (C) 1994 Advanced RISC Machines Ltd. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +typedef void Hif_DbgPrint(void *arg, const char *format, va_list ap); +typedef void Hif_DbgPause(void *arg); + +typedef void Hif_WriteC(void *arg, int c); +typedef int Hif_ReadC(void *arg); +typedef int Hif_Write(void *arg, char const *buffer, int len); +typedef char *Hif_GetS(void *arg, char *buffer, int len); + +typedef void Hif_RDIResetProc(void *arg); + +struct Dbg_HostosInterface { + Hif_DbgPrint *dbgprint; + Hif_DbgPause *dbgpause; + void *dbgarg; + + Hif_WriteC *writec; + Hif_ReadC *readc; + Hif_Write *write; + Hif_GetS *gets; + void *hostosarg; + + Hif_RDIResetProc *reset; + void *resetarg; +}; diff --git a/sim/arm/dbg_rdi.h b/sim/arm/dbg_rdi.h new file mode 100644 index 00000000000..4ef41e522bf --- /dev/null +++ b/sim/arm/dbg_rdi.h @@ -0,0 +1,323 @@ +/* dbg_rdi.h -- ARMulator RDI interface: ARM6 Instruction Emulator. + Copyright (C) 1994 Advanced RISC Machines Ltd. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef dbg_rdi__h +#define dbg_rdi__h + +/***************************************************************************\ +* Error Codes * +\***************************************************************************/ + +#define RDIError_NoError 0 + +#define RDIError_Reset 1 +#define RDIError_UndefinedInstruction 2 +#define RDIError_SoftwareInterrupt 3 +#define RDIError_PrefetchAbort 4 +#define RDIError_DataAbort 5 +#define RDIError_AddressException 6 +#define RDIError_IRQ 7 +#define RDIError_FIQ 8 +#define RDIError_Error 9 +#define RDIError_BranchThrough0 10 + +#define RDIError_NotInitialised 128 +#define RDIError_UnableToInitialise 129 +#define RDIError_WrongByteSex 130 +#define RDIError_UnableToTerminate 131 +#define RDIError_BadInstruction 132 +#define RDIError_IllegalInstruction 133 +#define RDIError_BadCPUStateSetting 134 +#define RDIError_UnknownCoPro 135 +#define RDIError_UnknownCoProState 136 +#define RDIError_BadCoProState 137 +#define RDIError_BadPointType 138 +#define RDIError_UnimplementedType 139 +#define RDIError_BadPointSize 140 +#define RDIError_UnimplementedSize 141 +#define RDIError_NoMorePoints 142 +#define RDIError_BreakpointReached 143 +#define RDIError_WatchpointAccessed 144 +#define RDIError_NoSuchPoint 145 +#define RDIError_ProgramFinishedInStep 146 +#define RDIError_UserInterrupt 147 +#define RDIError_CantSetPoint 148 +#define RDIError_IncompatibleRDILevels 149 + +#define RDIError_CantLoadConfig 150 +#define RDIError_BadConfigData 151 +#define RDIError_NoSuchConfig 152 +#define RDIError_BufferFull 153 +#define RDIError_OutOfStore 154 +#define RDIError_NotInDownload 155 +#define RDIError_PointInUse 156 +#define RDIError_BadImageFormat 157 +#define RDIError_TargetRunning 158 + +#define RDIError_LittleEndian 240 +#define RDIError_BigEndian 241 +#define RDIError_SoftInitialiseError 242 + +#define RDIError_InsufficientPrivilege 253 +#define RDIError_UnimplementedMessage 254 +#define RDIError_UndefinedMessage 255 + +/***************************************************************************\ +* RDP Message Numbers * +\***************************************************************************/ + +#define RDP_Start (unsigned char)0x0 +#define RDP_End (unsigned char)0x1 +#define RDP_Read (unsigned char)0x2 +#define RDP_Write (unsigned char)0x3 +#define RDP_CPUread (unsigned char)0x4 +#define RDP_CPUwrite (unsigned char)0x5 +#define RDP_CPread (unsigned char)0x6 +#define RDP_CPwrite (unsigned char)0x7 +#define RDP_SetBreak (unsigned char)0xa +#define RDP_ClearBreak (unsigned char)0xb +#define RDP_SetWatch (unsigned char)0xc +#define RDP_ClearWatch (unsigned char)0xd +#define RDP_Execute (unsigned char)0x10 +#define RDP_Step (unsigned char)0x11 +#define RDP_Info (unsigned char)0x12 +#define RDP_OSOpReply (unsigned char)0x13 + +#define RDP_AddConfig (unsigned char)0x14 +#define RDP_LoadConfigData (unsigned char)0x15 +#define RDP_SelectConfig (unsigned char)0x16 +#define RDP_LoadAgent (unsigned char)0x17 + +#define RDP_Stopped (unsigned char)0x20 +#define RDP_OSOp (unsigned char)0x21 +#define RDP_Fatal (unsigned char)0x5e +#define RDP_Return (unsigned char)0x5f +#define RDP_Reset (unsigned char)0x7f + +/***************************************************************************\ +* Other RDI values * +\***************************************************************************/ + +#define RDISex_Little 0 /* the byte sex of the debuggee */ +#define RDISex_Big 1 +#define RDISex_DontCare 2 + +#define RDIPoint_EQ 0 /* the different types of break/watchpoints */ +#define RDIPoint_GT 1 +#define RDIPoint_GE 2 +#define RDIPoint_LT 3 +#define RDIPoint_LE 4 +#define RDIPoint_IN 5 +#define RDIPoint_OUT 6 +#define RDIPoint_MASK 7 + +#define RDIPoint_Inquiry 64 /* ORRed with point type in extended RDP */ +#define RDIPoint_Handle 128 /* messages */ + +#define RDIWatch_ByteRead 1 /* types of data accesses to watch for */ +#define RDIWatch_HalfRead 2 +#define RDIWatch_WordRead 4 +#define RDIWatch_ByteWrite 8 +#define RDIWatch_HalfWrite 16 +#define RDIWatch_WordWrite 32 + +#define RDIReg_R15 (1L << 15) /* mask values for CPU */ +#define RDIReg_PC (1L << 16) +#define RDIReg_CPSR (1L << 17) +#define RDIReg_SPSR (1L << 18) +#define RDINumCPURegs 19 + +#define RDINumCPRegs 10 /* current maximum */ + +#define RDIMode_Curr 255 + +/* Bits set in return value from RDIInfo_Target */ +#define RDITarget_LogSpeed 0x0f +#define RDITarget_HW 0x10 /* else emulator */ +#define RDITarget_AgentMaxLevel 0xe0 +#define RDITarget_AgentLevelShift 5 +#define RDITarget_DebuggerMinLevel 0x700 +#define RDITarget_DebuggerLevelShift 8 +#define RDITarget_CanReloadAgent 0x800 +#define RDITarget_CanInquireLoadSize 0x1000 + +/* Bits set in return value from RDIInfo_Step */ +#define RDIStep_Multiple 1 +#define RDIStep_PCChange 2 +#define RDIStep_Single 4 + +/* Bits set in return value from RDIInfo_Points */ +#define RDIPointCapability_Comparison 1 +#define RDIPointCapability_Range 2 +/* 4 to 128 are RDIWatch_xx{Read,Write} left-shifted by two */ +#define RDIPointCapability_Mask 256 +#define RDIPointCapability_Status 512 /* Point status enquiries available */ + +/* RDI_Info subcodes */ +#define RDIInfo_Target 0 +#define RDIInfo_Points 1 +#define RDIInfo_Step 2 +#define RDIInfo_MMU 3 +#define RDIInfo_DownLoad 4 /* Inquires whether configuration download + and selection is available. + */ +#define RDIInfo_SemiHosting 5 /* Inquires whether RDISemiHosting_* RDI_Info + calls are available. + */ +#define RDIInfo_CoPro 6 /* Inquires whether CoPro RDI_Info calls are + available. + */ +#define RDIInfo_Icebreaker 7 + +/* The next two are only to be used if the value returned by RDIInfo_Points */ +/* has RDIPointCapability_Status set. */ +#define RDIPointStatus_Watch 0x80 +#define RDIPointStatus_Break 0x81 + +#define RDISignal_Stop 0x100 + +#define RDIVector_Catch 0x180 + +/* The next four are only to be used if RDIInfo_Semihosting returned no error */ +#define RDISemiHosting_SetState 0x181 +#define RDISemiHosting_GetState 0x182 +#define RDISemiHosting_SetVector 0x183 +#define RDISemiHosting_GetVector 0x184 + +/* The next two are only to be used if RDIInfo_Icebreaker returned no error */ +#define RDIIcebreaker_GetLocks 0x185 +#define RDIIcebreaker_SetLocks 0x186 + +/* Only if RDIInfo_Target returned RDITarget_CanInquireLoadSize */ +#define RDIInfo_GetLoadSize 0x187 + +#define RDICycles 0x200 +#define RDICycles_Size 48 +#define RDIErrorP 0x201 + +#define RDISet_Cmdline 0x300 +#define RDISet_RDILevel 0x301 +#define RDISet_Thread 0x302 + +/* The next two are only to be used if RDIInfo_CoPro returned no error */ +#define RDIInfo_DescribeCoPro 0x400 +#define RDIInfo_RequestCoProDesc 0x401 + +#define RDIInfo_Log 0x800 +#define RDIInfo_SetLog 0x801 + +typedef unsigned long PointHandle; +typedef unsigned long ThreadHandle; +#define RDINoPointHandle ((PointHandle)-1L) +#define RDINoHandle ((ThreadHandle)-1L) + +struct Dbg_ConfigBlock; +struct Dbg_HostosInterface; +struct Dbg_MCState; +typedef int rdi_open_proc(unsigned type, struct Dbg_ConfigBlock const *config, + struct Dbg_HostosInterface const *i, + struct Dbg_MCState *dbg_state); +typedef int rdi_close_proc(void); +typedef int rdi_read_proc(ARMword source, void *dest, unsigned *nbytes); +typedef int rdi_write_proc(const void *source, ARMword dest, unsigned *nbytes); +typedef int rdi_CPUread_proc(unsigned mode, unsigned long mask, ARMword *state); +typedef int rdi_CPUwrite_proc(unsigned mode, unsigned long mask, ARMword const *state); +typedef int rdi_CPread_proc(unsigned CPnum, unsigned long mask, ARMword *state); +typedef int rdi_CPwrite_proc(unsigned CPnum, unsigned long mask, ARMword const *state); +typedef int rdi_setbreak_proc(ARMword address, unsigned type, ARMword bound, + PointHandle *handle); +typedef int rdi_clearbreak_proc(PointHandle handle); +typedef int rdi_setwatch_proc(ARMword address, unsigned type, unsigned datatype, + ARMword bound, PointHandle *handle); +typedef int rdi_clearwatch_proc(PointHandle handle); +typedef int rdi_execute_proc(PointHandle *handle); +typedef int rdi_step_proc(unsigned ninstr, PointHandle *handle); +typedef int rdi_info_proc(unsigned type, ARMword *arg1, ARMword *arg2); +typedef int rdi_pointinq_proc(ARMword *address, unsigned type, + unsigned datatype, ARMword *bound); + +typedef enum { + RDI_ConfigCPU, + RDI_ConfigSystem +} RDI_ConfigAspect; + +typedef enum { + RDI_MatchAny, + RDI_MatchExactly, + RDI_MatchNoEarlier +} RDI_ConfigMatchType; + +typedef int rdi_addconfig_proc(unsigned long nbytes); +typedef int rdi_loadconfigdata_proc(unsigned long nbytes, char const *data); +typedef int rdi_selectconfig_proc(RDI_ConfigAspect aspect, char const *name, + RDI_ConfigMatchType matchtype, unsigned versionreq, + unsigned *versionp); + +typedef char *getbufferproc(void *getbarg, unsigned long *sizep); +typedef int rdi_loadagentproc(ARMword dest, unsigned long size, getbufferproc *getb, void *getbarg); + +typedef struct { + int itemmax; + char const * const *names; +} RDI_NameList; + +typedef RDI_NameList const *rdi_namelistproc(void); + +typedef int rdi_errmessproc(char *buf, int buflen, int errno); + +struct RDIProcVec { + char rditypename[12]; + + rdi_open_proc *open; + rdi_close_proc *close; + rdi_read_proc *read; + rdi_write_proc *write; + rdi_CPUread_proc *CPUread; + rdi_CPUwrite_proc *CPUwrite; + rdi_CPread_proc *CPread; + rdi_CPwrite_proc *CPwrite; + rdi_setbreak_proc *setbreak; + rdi_clearbreak_proc *clearbreak; + rdi_setwatch_proc *setwatch; + rdi_clearwatch_proc *clearwatch; + rdi_execute_proc *execute; + rdi_step_proc *step; + rdi_info_proc *info; + /* V2 RDI */ + rdi_pointinq_proc *pointinquiry; + + /* These three useable only if RDIInfo_DownLoad returns no error */ + rdi_addconfig_proc *addconfig; + rdi_loadconfigdata_proc *loadconfigdata; + rdi_selectconfig_proc *selectconfig; + + rdi_namelistproc *drivernames; + rdi_namelistproc *cpunames; + + rdi_errmessproc *errmess; + + /* Only if RDIInfo_Target returns a value with RDITarget_LoadAgent set */ + rdi_loadagentproc *loadagent; +}; + +#endif + + + + + + diff --git a/sim/arm/gdbhost.c b/sim/arm/gdbhost.c new file mode 100644 index 00000000000..4d938429777 --- /dev/null +++ b/sim/arm/gdbhost.c @@ -0,0 +1,107 @@ +/* gdbhost.c -- ARMulator RDP to gdb comms code: ARM6 Instruction Emulator. + Copyright (C) 1994 Advanced RISC Machines Ltd. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/***********************************************************/ +/* Functions that communicate info back to the debugger... */ +/***********************************************************/ + +#include +#include +#include "armdefs.h" +#include "communicate.h" +#include "dbg_rdi.h" +#include "armos.h" + +#define OS_SendNothing 0x0 +#define OS_SendChar 0x1 +#define OS_SendWord 0x2 +#define OS_SendString 0x3 + +/* Defined in kid.c */ +extern int wait_for_osreply(ARMword *reply); + +/* A pipe for handling SWI return values that goes straight from the */ +/* parent to the ARMulator host interface, bypassing the childs RDP */ +/* to RDI interpreter */ +int DebuggerARMul[2]; + +/* The pipes between the two processes */ +int mumkid[2]; +int kidmum[2]; + +void myprint (void *arg, const char *format, va_list ap) +{ +#ifdef DEBUG + fprintf (stderr, "Host: myprint\n"); +#endif + vfprintf (stderr, format, ap); +} + + +/* Waits for a keypress on the debuggers' keyboard */ +void mypause (void *arg) +{ +#ifdef DEBUG + fprintf (stderr, "Host: mypause\n"); +#endif +} /* I do love exciting functions */ + +void mywritec(void *arg, int c) +{ +#ifdef DEBUG + fprintf(stderr, "Mywrite : %c\n", c); +#endif + MYwrite_char(kidmum[1], RDP_OSOp); /* OS Operation Request Message */ + MYwrite_word(kidmum[1], SWI_WriteC); /* Print... */ + MYwrite_char(kidmum[1], OS_SendChar); /* ...a single character */ + MYwrite_char(kidmum[1], (unsigned char) c); + + wait_for_osreply((ARMword *) 0); +} + +int myreadc(void *arg) +{ + char c; + ARMword x; + +#ifdef DEBUG + fprintf(stderr, "Host: myreadc\n"); +#endif + MYwrite_char(kidmum[1], RDP_OSOp); /* OS Operation Request Message */ + MYwrite_word(kidmum[1], SWI_ReadC); /* Read... */ + MYwrite_char(kidmum[1], OS_SendNothing); + + c = wait_for_osreply(&x); + return (x); +} + + +int mywrite(void *arg, char const *buffer, int len) +{ +#ifdef DEBUG + fprintf(stderr, "Host: mywrite\n"); +#endif + return 0; +} + +char *mygets(void *arg, char *buffer, int len) +{ +#ifdef DEBUG + fprintf(stderr, "Host: mygets\n"); +#endif + return buffer; +} diff --git a/sim/arm/gdbhost.h b/sim/arm/gdbhost.h new file mode 100644 index 00000000000..e1bfd24ef53 --- /dev/null +++ b/sim/arm/gdbhost.h @@ -0,0 +1,23 @@ +/* gdbhost.h -- ARMulator to gdb interface: ARM6 Instruction Emulator. + Copyright (C) 1994 Advanced RISC Machines Ltd. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +void myprint(void *arg, const char *format, va_list ap); +void mypause(void *arg); +void mywritec(void *arg, int c); +int myreadc(void *arg); +int mywrite(void *arg, char const *buffer, int len); +char *mygets(void *arg, char *buffer, int len); diff --git a/sim/arm/kid.c b/sim/arm/kid.c new file mode 100644 index 00000000000..10e3f35821e --- /dev/null +++ b/sim/arm/kid.c @@ -0,0 +1,510 @@ +/* kid.c -- ARMulator RDP/RDI interface: ARM6 Instruction Emulator. + Copyright (C) 1994 Advanced RISC Machines Ltd. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/*****************************************************************/ +/* The child process continues here... */ +/* It waits on a pipe from the parent and translates the RDP */ +/* messages into RDI calls to the ARMulator passing RDP replies */ +/* back up a pipe to the parent. */ +/*****************************************************************/ + +#include +#include + +#include "armdefs.h" +#include "dbg_conf.h" +#include "dbg_hif.h" +#include "dbg_rdi.h" +#include "gdbhost.h" +#include "communicate.h" + +/* The pipes between the two processes */ +extern int mumkid[2]; +extern int kidmum[2]; + +/* The maximum number of file descriptors */ +extern int nfds; + +/* The machine name */ +#define MAXHOSTNAMELENGTH 64 +extern char localhost[MAXHOSTNAMELENGTH + 1]; + +/* The socket number */ +extern unsigned int socketnumber; + +/* RDI interface */ +extern const struct RDIProcVec armul_rdi; + +static int MYrdp_level = 0; + +static int rdi_state = 0; + +/**************************************************************/ +/* Signal handler that terminates excecution in the ARMulator */ +/**************************************************************/ +void kid_handlesignal(int sig) { +#ifdef DEBUG + fprintf(stderr, "Terminate ARMulator excecution\n"); +#endif + if (sig != SIGUSR1) { + fprintf(stderr, "Unsupported signal.\n"); + return; + } + armul_rdi.info(RDISignal_Stop, (unsigned long *) 0, (unsigned long *) 0); +} + +/********************************************************************/ +/* Waits on a pipe from the socket demon for RDP and */ +/* acts as an RDP to RDI interpreter on the front of the ARMulator. */ +/********************************************************************/ +void kid() { + char *p, *q; + int i, j, k; + long outofthebag; + unsigned char c, d, message; + ARMword x, y, z; + struct sigaction action; + PointHandle point; + Dbg_ConfigBlock config; + Dbg_HostosInterface hostif; + struct Dbg_MCState *MCState; + char command_line[256]; + struct fd_set readfds; + + /* Setup a signal handler for SIGUSR1 */ + action.sa_handler = kid_handlesignal; + action.sa_mask = 0; + action.sa_flags = 0; + + sigaction(SIGUSR1, &action, (struct sigaction *) 0); + + while (1) + { + /* Wait for ever */ + FD_ZERO(&readfds); + FD_SET(mumkid[0], &readfds); + + i = select(nfds, &readfds, + (fd_set *) 0, + (fd_set *) 0, + (struct timeval *) 0); + + if (i < 0) { + perror("select"); + } + + if (read(mumkid[0], &message, 1) < 1) { + perror("read"); + } + + switch (message) { + case RDP_Start : + /* Open and/or Initialise */ + BAG_newbag(); + + MYread_char(mumkid[0], &c); /* type */ + MYread_word(mumkid[0], &x); /* memorysize */ + if (c & 0x2) MYread_char(mumkid[0], &d); /* speed */ + config.processor = 0; + config.memorysize = x; + config.bytesex = (c & 0x4) ? RDISex_Big : RDISex_Little; + if (c & 0x8) config.bytesex = RDISex_DontCare; + + hostif.dbgprint = myprint; + hostif.dbgpause = mypause; + hostif.dbgarg = stdout; + hostif.writec = mywritec; + hostif.readc = myreadc; + hostif.write = mywrite; + hostif.gets = mygets; + hostif.reset = mypause; /* do nothing */ + hostif.resetarg = "Do I love resetting or what!\n"; + + if (rdi_state) + { + /* we have restarted, so kill off the existing run. */ + /* armul_rdi.close(); */ + } + i = armul_rdi.open(c & 0x3, &config, &hostif, MCState); + rdi_state = 1; + + MYwrite_char(kidmum[1], RDP_Return); + MYwrite_char(kidmum[1], (unsigned char) i); + + x = ~0x4; + armul_rdi.info(RDIVector_Catch, &x, 0); + + break; + + case RDP_End : + /* Close and Finalise */ + i = armul_rdi.close(); + rdi_state = 0; + MYwrite_char(kidmum[1], RDP_Return); + MYwrite_char(kidmum[1], (unsigned char) i); + break; + + case RDP_Read : + /* Read Memory Address */ + MYread_word(mumkid[0], &x); /* address */ + MYread_word(mumkid[0], &y); /* nbytes */ + p = (char *) malloc(y); + i = armul_rdi.read(x, p, (unsigned *) &y); + MYwrite_char(kidmum[1], RDP_Return); + for (k = 0; k < y; k++) + MYwrite_char(kidmum[1], p[k]); + free(p); + MYwrite_char(kidmum[1], (unsigned char) i); + if (i) + MYwrite_word(kidmum[1], y); /* number of bytes sent without error */ + break; + + case RDP_Write : + /* Write Memory Address */ + MYread_word(mumkid[0], &x); /* address */ + MYread_word(mumkid[0], &y); /* nbytes */ + p = (char *) malloc(y); + for (k = 0; k < y; k++) + MYread_char(mumkid[0], &p[k]); + i = armul_rdi.write(p, x, (unsigned *) &y); + free(p); + MYwrite_char(kidmum[1], RDP_Return); + MYwrite_char(kidmum[1], (unsigned char) i); + if (i) + MYwrite_word(kidmum[1], y); /* number of bytes sent without error */ + break; + + case RDP_CPUread : + /* Read CPU State */ + MYread_char(mumkid[0], &c); /* mode */ + MYread_word(mumkid[0], &x); /* mask */ + p = (char *) malloc(4 * RDINumCPURegs); + i = armul_rdi.CPUread(c, x, (ARMword *) p); + MYwrite_char(kidmum[1], RDP_Return); + for (k = 1, j = 0; k != 0x80000000; k *= 2) + if (k & x) MYwrite_word(kidmum[1], ((ARMword *) p)[j++]); + free(p); + if (i) MYwrite_char(kidmum[1], (unsigned char) j); + MYwrite_char(kidmum[1], (unsigned char) i); + break; + + case RDP_CPUwrite : + /* Write CPU State */ + MYread_char(mumkid[0], &c); /* mode */ + MYread_word(mumkid[0], &x); /* mask */ + + p = (char *) malloc(4 * RDINumCPURegs); + for (k = 1, j = 0; k != 0x80000000; k *= 2) + if (k & x) MYread_word(mumkid[0], &(((ARMword *) p)[j++])); + i = armul_rdi.CPUwrite(c, x, (ARMword *) p); + MYwrite_char(kidmum[1], RDP_Return); + MYwrite_char(kidmum[1], (unsigned char) i); + free(p); + break; + + case RDP_CPread : + /* Read Co-Processor State */ + MYread_char(mumkid[0], &c); /* CPnum */ + MYread_word(mumkid[0], &x); /* mask */ + p = q = (char *) malloc(16 * RDINumCPRegs); + i = armul_rdi.CPread(c, x, (ARMword *) p); + MYwrite_char(kidmum[1], RDP_Return); + for (k = 1, j = 0; k != 0x80000000; k *= 2, j++) + if (k & x) { + if ((c == 1 || c == 2) && k <= 128) { + MYwrite_FPword(kidmum[1], q); + q += 16; + } + else { + MYwrite_word(kidmum[1], *q); + q += 4; + } + } + free(p); + if (i) MYwrite_char(kidmum[1], (unsigned char) j); + MYwrite_char(kidmum[1], (unsigned char) i); + break; + + case RDP_CPwrite : + /* Write Co-Processor State */ + MYread_char(mumkid[0], &c); /* CPnum */ + MYread_word(mumkid[0], &x); /* mask */ + p = q = (char *) malloc(16 * RDINumCPURegs); + for (k = 1, j = 0; k != 0x80000000; k *= 2, j++) + if (k & x) { + if ((c == 1 || c == 2) && k <= 128) { + MYread_FPword(kidmum[1], q); + q += 16; + } + else { + MYread_word(mumkid[0], (ARMword *) q); + q += 4; + } + } + i = armul_rdi.CPwrite(c, x, (ARMword *) p); + MYwrite_char(kidmum[1], RDP_Return); + MYwrite_char(kidmum[1], (unsigned char) i); + free(p); + break; + + case RDP_SetBreak : + /* Set Breakpoint */ + MYread_word(mumkid[0], &x); /* address */ + MYread_char(mumkid[0], &c); /* type */ + if ((c & 0xf) >= 5) MYread_word(mumkid[0], &y); /* bound */ + i = armul_rdi.setbreak(x, c, y, &point); + if (!MYrdp_level) BAG_putpair((long) x, (long) point); + MYwrite_char(kidmum[1], RDP_Return); + if (MYrdp_level) MYwrite_word(kidmum[1], point); + MYwrite_char(kidmum[1], (unsigned char) i); + break; + + case RDP_ClearBreak : + /* Clear Breakpoint */ + MYread_word(mumkid[0], &point); /* PointHandle */ + if (!MYrdp_level) { + BAG_getsecond((long) point, &outofthebag); /* swap pointhandle for address */ + BAG_killpair_byfirst(outofthebag); + point = outofthebag; + } + i = armul_rdi.clearbreak(point); + MYwrite_char(kidmum[1], RDP_Return); + MYwrite_char(kidmum[1], (unsigned char) i); + break; + + case RDP_SetWatch : + /* Set Watchpoint */ + MYread_word(mumkid[0], &x); /* address */ + MYread_char(mumkid[0], &c); /* type */ + MYread_char(mumkid[0], &d); /* datatype */ + if ((c & 0xf) >= 5) MYread_word(mumkid[0], &y); /* bound */ + i = armul_rdi.setwatch(x, c, d, y, &point); + MYwrite_char(kidmum[1], RDP_Return); + MYwrite_word(kidmum[1], point); + MYwrite_char(kidmum[1], (unsigned char) i); + break; + + case RDP_ClearWatch : + /* Clear Watchpoint */ + MYread_word(mumkid[0], &point); /* PointHandle */ + i = armul_rdi.clearwatch(point); + MYwrite_char(kidmum[1], RDP_Return); + MYwrite_char(kidmum[1], (unsigned char) i); + break; + + case RDP_Execute : + /* Excecute */ + + MYread_char(mumkid[0], &c); /* return */ + +#ifdef DEBUG + fprintf(stderr, "Starting execution\n"); +#endif + i = armul_rdi.execute(&point); +#ifdef DEBUG + fprintf(stderr, "Completed execution\n"); +#endif + MYwrite_char(kidmum[1], RDP_Return); + if (c & 0x80) MYwrite_word(kidmum[1], point); + MYwrite_char(kidmum[1], (unsigned char) i); + break; + + case RDP_Step : + /* Step */ + MYread_char(mumkid[0], &c); /* return */ + MYread_word(mumkid[0], &x); /* ninstr */ + point = 0x87654321; + i = armul_rdi.step(x, &point); + MYwrite_char(kidmum[1], RDP_Return); + if (c & 0x80) MYwrite_word(kidmum[1], point); + MYwrite_char(kidmum[1], (unsigned char) i); + break; + + case RDP_Info: + /* Info */ + MYread_word (mumkid[0], &x); + switch (x) + { + case RDIInfo_Target: + i = armul_rdi.info (RDIInfo_Target, &y, &z); + MYwrite_char (kidmum[1], RDP_Return); + MYwrite_word (kidmum[1], y); /* Loads of info... */ + MYwrite_word (kidmum[1], z); /* Model */ + MYwrite_char (kidmum[1], (unsigned char) i); + break; + + case RDISet_RDILevel: + MYread_word (mumkid[0], &x); /* arg1, debug level */ + i = armul_rdi.info (RDISet_RDILevel, &x, 0); + if (i == RDIError_NoError) + MYrdp_level = x; + MYwrite_char (kidmum[1], RDP_Return); + MYwrite_char (kidmum[1], (unsigned char) i); + break; + + case RDISet_Cmdline: + for (p = command_line; MYread_char (mumkid[0], p), *p; p++) + ; /* String */ + i = armul_rdi.info (RDISet_Cmdline, + (unsigned long *) command_line, 0); + MYwrite_char (kidmum[1], RDP_Return); + MYwrite_char (kidmum[1], (unsigned char) i); + break; + + case RDIInfo_Step: + i = armul_rdi.info (RDIInfo_Step, &x, 0); + MYwrite_char (kidmum[1], RDP_Return); + MYwrite_word (kidmum[1], x); + MYwrite_char (kidmum[1], (unsigned char) i); + break; + + case RDIVector_Catch: + MYread_word (mumkid[0], &x); + i = armul_rdi.info (RDIVector_Catch, &x, 0); + MYwrite_char (kidmum[1], RDP_Return); + MYwrite_char (kidmum[1], i); + break; + + case RDIInfo_Points: + i = armul_rdi.info (RDIInfo_Points, &x, 0); + MYwrite_char (kidmum[1], RDP_Return); + MYwrite_word (kidmum[1], x); + MYwrite_char (kidmum[1], (unsigned char) i); + break; + + default: + fprintf (stderr, "Unsupported info code %d\n", x); + break; + } + break; + + case RDP_OSOpReply: + /* OS Operation Reply */ + MYwrite_char (kidmum[1], RDP_Fatal); + break; + + case RDP_Reset: + /* Reset */ + for (i = 0; i < 50; i++) + MYwrite_char(kidmum[1], RDP_Reset); + p = (char *) malloc(MAXHOSTNAMELENGTH + 5 + 20); + sprintf(p, "Running on %s:%d\n", localhost, socketnumber); + MYwrite_string(kidmum[1], p); + free(p); + + break; + default: + fprintf (stderr, "Oh dear: Something is seriously wrong :-(\n"); + /* Hmm.. bad RDP operation */ + break; + } + } +} + + +/* Handles memory read operations until an OS Operation Reply Message is */ +/* encounterd. It then returns the byte info value (0, 1, or 2) and fills */ +/* in 'putinr0' with the data if appropriate. */ +int wait_for_osreply(ARMword *reply) +{ + char *p, *q; + int i, j, k; + unsigned char c, d, message; + ARMword x, y, z; + struct sigaction action; + PointHandle point; + Dbg_ConfigBlock config; + Dbg_HostosInterface hostif; + struct Dbg_MCState *MCState; + char command_line[256]; + struct fd_set readfds; + +#ifdef DEBUG + fprintf(stderr, "wait_for_osreply ().\n"); +#endif + + /* Setup a signal handler for SIGUSR1 */ + action.sa_handler = kid_handlesignal; + action.sa_mask = 0; + action.sa_flags = 0; + + sigaction(SIGUSR1, &action, (struct sigaction *) 0); + + while (1) + { + /* Wait for ever */ + FD_ZERO(&readfds); + FD_SET(mumkid[0], &readfds); + + i = select(nfds, &readfds, + (fd_set *) 0, + (fd_set *) 0, + (struct timeval *) 0); + + if (i < 0) { + perror("select"); + } + + if (read(mumkid[0], &message, 1) < 1) { + perror("read"); + } + + switch (message) { + case RDP_Read : + /* Read Memory Address */ + MYread_word(mumkid[0], &x); /* address */ + MYread_word(mumkid[0], &y); /* nbytes */ + p = (char *) malloc(y); + i = armul_rdi.read(x, p, (unsigned *) &y); + MYwrite_char(kidmum[1], RDP_Return); + for (k = 0; k < y; k++) + MYwrite_char(kidmum[1], p[k]); + free(p); + MYwrite_char(kidmum[1], (unsigned char) i); + if (i) + MYwrite_word(kidmum[1], y); /* number of bytes sent without error */ + break; + + case RDP_Write : + /* Write Memory Address */ + MYread_word(mumkid[0], &x); /* address */ + MYread_word(mumkid[0], &y); /* nbytes */ + p = (char *) malloc(y); + for (k = 0; k < y; k++) + MYread_char(mumkid[0], &p[k]); + i = armul_rdi.write(p, x, (unsigned *) &y); + free(p); + MYwrite_char(kidmum[1], RDP_Return); + MYwrite_char(kidmum[1], (unsigned char) i); + if (i) + MYwrite_word(kidmum[1], y); /* number of bytes sent without error */ + break; + + case RDP_OSOpReply : + /* OS Operation Reply */ + MYread_char(mumkid[0], &c); + if (c == 1) MYread_char(mumkid[0], (char *) reply); + if (c == 2) MYread_word(mumkid[0], reply); + return c; + break; + + default : + fprintf(stderr, "HELP! Unaccounted-for message during OS request. \n"); + MYwrite_char(kidmum[1], RDP_Fatal); + } + } +} diff --git a/sim/arm/main.c b/sim/arm/main.c new file mode 100644 index 00000000000..f012b28e6da --- /dev/null +++ b/sim/arm/main.c @@ -0,0 +1,183 @@ +/* main.c -- top level of ARMulator: ARM6 Instruction Emulator. + Copyright (C) 1994 Advanced RISC Machines Ltd. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/**********************************************************************/ +/* Forks the ARMulator and hangs on a socket passing on RDP messages */ +/* down a pipe to the ARMulator which translates them into RDI calls. */ +/**********************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "armdefs.h" +#include "dbg_rdi.h" +#include "dbg_conf.h" + +#define MAXHOSTNAMELENGTH 64 + +/* Read and write routines down sockets and pipes */ + +void MYread_chars(int sock, void *p, int n); +unsigned char MYread_char(int sock); +ARMword MYread_word(int sock); +void MYread_FPword(int sock, char *putinhere); + +void MYwrite_word(int sock, ARMword i); +void MYwrite_string(int sock, char *s); +void MYwrite_FPword(int sock, char *fromhere); +void MYwrite_char(int sock, unsigned char c); + +void passon(int source, int dest, int n); + + +/* Mother and child processes */ +void parent (void); +void kid(void); + +/* The child process id. */ +pid_t child; + +/* The socket to the debugger */ +int debugsock; + +/* The pipes between the two processes */ +int mumkid[2]; +int kidmum[2]; + +/* A pipe for handling SWI return values that goes straight from the */ +/* parent to the ARMulator host interface, bypassing the childs RDP */ +/* to RDI interpreter */ +int DebuggerARMul[2]; + +/* The maximum number of file descriptors */ +int nfds; + +/* The socket handle */ +int sockethandle; + +/* The machine name */ +char localhost[MAXHOSTNAMELENGTH + 1]; + +/* The socket number */ +unsigned int socketnumber; + +/**************************************************************/ +/* Takes one argument: the socket number. */ +/* Opens a socket to the debugger, and once opened spawns the */ +/* ARMulator and sets up a couple of pipes. */ +/**************************************************************/ +int main(int argc, char *argv[]) { + int i; + struct sockaddr_in devil, isa; + struct hostent *hp; + + + if (argc == 1) { + fprintf(stderr, "No socket number\n"); + return 1; + } + + sscanf(argv[1], "%d", &socketnumber); + if (!socketnumber || socketnumber > 0xffff) { + fprintf(stderr, "Invalid socket number: %d\n", socketnumber); + return 1; + } + + gethostname(localhost, MAXHOSTNAMELENGTH); + hp = gethostbyname(localhost); + if (!hp) { + fprintf(stderr, "Cannot get local host info\n"); + return 1; + } + + /* Open a socket */ + sockethandle = socket(hp->h_addrtype, SOCK_STREAM, 0); + if (sockethandle < 0) { + perror("socket"); + return 1; + } + + devil.sin_family = hp->h_addrtype; + devil.sin_port = htons(socketnumber); + devil.sin_addr.s_addr = 0; + for(i = 0; i < sizeof(devil.sin_zero); i++) devil.sin_zero[i] = '\000'; + memcpy(&devil.sin_addr, hp->h_addr_list[0], hp->h_length); + + if (bind(sockethandle, &devil, sizeof(devil)) < 0) { + perror("bind"); + return 1; + } + + /* May only accept one debugger at once */ + + if (listen(sockethandle, 0)) { + perror("listen"); + return 1; + } + + fprintf(stderr, "Waiting for connection from debugger..."); + + debugsock = accept(sockethandle, &isa, &i); + if (debugsock < 0) { + perror("accept"); + return 1; + } + + fprintf(stderr, " done.\nConnection Established.\n"); + + nfds = getdtablesize(); + + if (pipe(mumkid)) { + perror("pipe"); + return 1; + } + if (pipe(kidmum)) { + perror("pipe"); + return 1; + } + + if (pipe(DebuggerARMul)) { + perror("pipe"); + return 1; + } + +#ifdef DEBUG + fprintf(stderr, "Created pipes ok\n"); +#endif + + child = fork(); + +#ifdef DEBUG + fprintf(stderr, "fork() ok\n"); +#endif + + if (child == 0) kid (); + if (child != -1) parent (); + + perror("fork"); + return 1; +} + + + + diff --git a/sim/arm/parent.c b/sim/arm/parent.c new file mode 100644 index 00000000000..21da64332aa --- /dev/null +++ b/sim/arm/parent.c @@ -0,0 +1,483 @@ +/* parent.c -- ARMulator RDP comms code: ARM6 Instruction Emulator. + Copyright (C) 1994 Advanced RISC Machines Ltd. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/*****************************************************************/ +/* The Parent process continues here... */ +/* It waits on the socket and passes on RDP messages down a pipe */ +/* to the ARMulator RDP to RDI interpreter. */ +/*****************************************************************/ + +#include +#include +#include +#include "time.h" +#include "armdefs.h" +#include "dbg_rdi.h" +#include "communicate.h" + +/* The socket to the debugger */ +extern int debugsock; + +/* The pipes between the two processes */ +extern int mumkid[2]; +extern int kidmum[2]; + +/* A pipe for handling SWI return values that goes straight from the */ +/* parent to the ARMulator host interface, bypassing the child's RDP */ +/* to RDI interpreter */ +extern int DebuggerARMul[2]; + +/* The maximum number of file descriptors */ +extern int nfds; + +/* The child process id. */ +extern pid_t child; + +void +parent () +{ + int i, j, k; + unsigned char message, CPnum, exreturn; + ARMword mask, nbytes, messagetype; + unsigned char c, d; + ARMword x, y; + int virgin = 1; + struct fd_set readfds; + +#ifdef DEBUG + fprintf (stderr, "parent ()...\n"); +#endif + + panic_error: + + if (!virgin) + { +#ifdef DEBUG + fprintf(stderr, "Arghh! What is going on?\n"); +#endif + kill (child, SIGHUP); + MYwrite_char(debugsock, RDP_Reset); + } + + virgin = 0; + + while (1) + { + + /* Wait either for the ARMulator or the debugger */ + + FD_ZERO (&readfds); + FD_SET (kidmum[0], &readfds); /* Wait for messages from ARMulator */ + FD_SET (debugsock, &readfds); /* Wait for messages from debugger */ + +#ifdef DEBUG + fprintf (stderr, "Waiting for ARMulator or debugger... "); +#endif + + while ((i = select (nfds, &readfds, (fd_set *) 0, (fd_set *) 0, 0)) < 0) + { + perror ("select"); + } + +#ifdef DEBUG + fprintf(stderr, "(%d/2)", i); +#endif + + if (FD_ISSET (debugsock, &readfds)) { +#ifdef DEBUG + fprintf (stderr, "->debugger\n"); +#endif + + /* Inside this rather large if statement with simply pass on a complete + message to the ARMulator. The reason we need to pass messages on one + at a time is that we have to know whether the message is an OSOpReply + or an info(stop), so that we can take different action in those + cases. */ + + if (MYread_char (debugsock, &message)) + goto panic_error; + + switch (message) + { + case RDP_Start: + /* Open and/or Initialise */ +#ifdef DEBUG + fprintf (stderr, "RDP Open\n"); +#endif + if (MYread_char(debugsock, &c)) /* type */ + goto panic_error; + + if (MYread_word(debugsock, &x)) /* memory size */ + goto panic_error; + + MYwrite_char (mumkid[1], message); + MYwrite_char (mumkid[1], c); + MYwrite_word (mumkid[1], x); + if (c & 0x2) + { + passon (debugsock, mumkid[1], 1); /* speed */ + } + break; + + case RDP_End: + /* Close and Finalise */ +#ifdef DEBUG + fprintf(stderr, "RDP Close\n"); +#endif + MYwrite_char (mumkid[1], message); + break; + + case RDP_Read: + /* Read Memory Address */ +#ifdef DEBUG + fprintf (stderr, "RDP Read Memory\n"); +#endif + MYwrite_char (mumkid[1], message); + if (passon (debugsock, mumkid[1], 4)) + goto panic_error; /* address */ + if (MYread_word(debugsock, &nbytes)) + goto panic_error; /* nbytes */ + MYwrite_word (mumkid[1], nbytes); + break; + + case RDP_Write : + /* Write Memory Address */ +#ifdef DEBUG + fprintf (stderr, "RDP Write Memory\n"); +#endif + if (MYread_word (debugsock, &x)) + goto panic_error; /* address */ + + if (MYread_word (debugsock, &y)) + goto panic_error; /* nbytes */ + + MYwrite_char (mumkid[1], message); + MYwrite_word (mumkid[1], x); + MYwrite_word (mumkid[1], y); + passon (debugsock, mumkid[1], y); /* actual data */ + break; + + case RDP_CPUread: + /* Read CPU State */ +#ifdef DEBUG + fprintf (stderr, "RDP Read CPU\n"); +#endif + if (MYread_char(debugsock, &c)) + goto panic_error; /* mode */ + + if (MYread_word (debugsock, &mask)) + goto panic_error; /* mask */ + + MYwrite_char (mumkid[1], message); + MYwrite_char (mumkid[1], c); + MYwrite_word (mumkid[1], mask); + break; + + case RDP_CPUwrite : + /* Write CPU State */ +#ifdef DEBUG + fprintf (stderr, "RDP Write CPU\n"); +#endif + if (MYread_char (debugsock, &c)) + goto panic_error; /* mode */ + + if (MYread_word (debugsock, &x)) + goto panic_error; /* mask */ + + MYwrite_char (mumkid[1], message); + MYwrite_char (mumkid[1], c); + MYwrite_word (mumkid[1], x); + for (k = 1, j = 0; k != 0x80000000; k *= 2, j++) + if ((k & x) + && passon(debugsock, mumkid[1], 4)) + goto panic_error; + break; + + case RDP_CPread: + /* Read Co-Processor State */ +#ifdef DEBUG + fprintf (stderr, "RDP Read CP state\n"); +#endif + if (MYread_char (debugsock, &CPnum)) + goto panic_error; + + if (MYread_word (debugsock, &mask)) + goto panic_error; + + MYwrite_char (mumkid[1], message); + MYwrite_char (mumkid[1], CPnum); + MYwrite_word (mumkid[1], mask); + break; + + case RDP_CPwrite: + /* Write Co-Processor State */ +#ifdef DEBUG + fprintf(stderr, "RDP Write CP state\n"); +#endif + if (MYread_char (debugsock, &CPnum)) + goto panic_error; + + if (MYread_word (debugsock, &mask)) + goto panic_error; + + MYwrite_char (mumkid[1], message); + MYwrite_char (mumkid[1], c); + MYwrite_char (mumkid[1], x); + for (k = 1, j = 0; k != 0x80000000; k *= 2, j++) + if (k & x) + { + if ((c == 1 || c == 2) && k <= 128) + { + /* FP register = 12 bytes + 4 bytes format */ + if (passon(debugsock, mumkid[1], 16)) + goto panic_error; + } + else + { + /* Normal register = 4 bytes */ + if (passon(debugsock, mumkid[1], 4)) + goto panic_error; + } + } + break; + + case RDP_SetBreak: + /* Set Breakpoint */ +#ifdef DEBUG + fprintf (stderr, "RDP Set Breakpoint\n"); +#endif + if (MYread_word (debugsock, &x)) + goto panic_error; /* address */ + + if (MYread_char (debugsock, &c)) + goto panic_error; /* type */ + + MYwrite_char (mumkid[1], message); + MYwrite_word (mumkid[1], x); + MYwrite_char (mumkid[1], c); + if (((c & 0xf) >= 5) + && passon(debugsock, mumkid[1], 4)) + goto panic_error; /* bound */ + break; + + case RDP_ClearBreak: + /* Clear Breakpoint */ +#ifdef DEBUG + fprintf (stderr, "RDP Clear Breakpoint\n"); +#endif + MYwrite_char (mumkid[1], message); + if (passon (debugsock, mumkid[1], 4)) + goto panic_error; /* point */ + break; + + case RDP_SetWatch: + /* Set Watchpoint */ +#ifdef DEBUG + fprintf (stderr, "RDP Set Watchpoint\n"); +#endif + if (MYread_word (debugsock, &x)) + goto panic_error; /* address */ + + if (MYread_char(debugsock, &c)) + goto panic_error; /* type */ + + if (MYread_char (debugsock, &d)) + goto panic_error; /* datatype */ + + MYwrite_char (mumkid[1], message); + MYwrite_word (mumkid[1], x); + MYwrite_char (mumkid[1], c); + MYwrite_char (mumkid[1], d); + if (((c & 0xf) >= 5) + && passon(debugsock, mumkid[1], 4)) + goto panic_error; /* bound */ + break; + + case RDP_ClearWatch: + /* Clear Watchpoint */ +#ifdef DEBUG + fprintf (stderr, "RDP Clear Watchpoint\n"); +#endif + MYwrite_char (mumkid[1], message); + if (passon (debugsock, mumkid[1], 4)) + goto panic_error; /* point */ + break; + + case RDP_Execute: + /* Excecute */ +#ifdef DEBUG + fprintf (stderr, "RDP Execute\n"); +#endif + + /* LEAVE THIS ONE 'TIL LATER... */ + /* NEED TO WORK THINGS OUT */ + + /* NO ASCYNCHROUS RUNNING */ + + if (MYread_char(debugsock, &c)) + goto panic_error; /* return */ + + /* Remember incase bit 7 is set and we have to send back a word */ + exreturn = c; + + MYwrite_char(mumkid[1], message); + MYwrite_char(mumkid[1], c); + break; + + case RDP_Step: + /* Step */ +#ifdef DEBUG + fprintf (stderr, "RDP Step\n"); +#endif + + if (MYread_char(debugsock, &c)) + goto panic_error; /* return */ + + if (MYread_word(debugsock, &x)) + goto panic_error; /* ninstr */ + + MYwrite_char (mumkid[1], message); + MYwrite_char (mumkid[1], c); + MYwrite_word (mumkid[1], x); + break; + + case RDP_Info: + /* Info */ +#ifdef DEBUG + fprintf (stderr, "RDP Info\n"); +#endif + /* INFO TARGET, SET RDI LEVEL */ + if (MYread_word (debugsock, &messagetype)) + goto panic_error; /* info */ + + switch (messagetype) + { + case RDIInfo_Target: + MYwrite_char (mumkid[1], message); + MYwrite_word (mumkid[1], messagetype); + break; + + case RDISet_RDILevel: + MYwrite_char (mumkid[1], message); + MYwrite_word (mumkid[1], messagetype); + if (passon (debugsock, mumkid[1], 1)) + goto panic_error; /* argument */ + break; + + case RDISet_Cmdline: + /* Got to pass on a string argument */ + MYwrite_char (mumkid[1], message); + MYwrite_word (mumkid[1], messagetype); + do + { + if (MYread_char (debugsock, &c)) + goto panic_error; + + MYwrite_char (mumkid[1], c); + } while (c); + break; + + case RDISignal_Stop: + kill (child, SIGUSR1); + MYwrite_char (debugsock, RDP_Return); + MYwrite_char (debugsock, RDIError_UserInterrupt); + break; + + case RDIVector_Catch: + MYread_word (debugsock, &x); + MYwrite_char (mumkid[1], message); + MYwrite_word (mumkid[1], messagetype); + MYwrite_word (mumkid[1], x); + break; + + case RDIInfo_Step: + MYwrite_char (mumkid[1], message); + MYwrite_word (mumkid[1], messagetype); + break; + + case RDIInfo_Points: + MYwrite_char (mumkid[1], message); + MYwrite_word (mumkid[1], messagetype); + break; + + default: + fprintf (stderr, "Unrecognized RDIInfo request %d\n", + messagetype); + goto panic_error; + } + break; + + case RDP_OSOpReply: + /* OS Operation Reply */ +#ifdef DEBUG + fprintf (stderr, "RDP OS Reply\n"); +#endif + MYwrite_char (mumkid[1], message); + if (MYread_char (debugsock, &message)) + goto panic_error; + MYwrite_char (mumkid[1], message); + switch(message) + { + case 0: /* return value i.e. nothing else.*/ + break; + + case 1: /* returns a byte... */ + if (MYread_char(debugsock, &c)) + goto panic_error; + + MYwrite_char (mumkid[1], c); + break; + + case 2: /* returns a word... */ + if (MYread_word(debugsock, &x)) + goto panic_error; + + MYwrite_word (mumkid[1], x); + break; + } + break; + + case RDP_Reset: + /* Reset */ +#ifdef DEBUG + fprintf (stderr, "RDP Reset\n"); +#endif + MYwrite_char (mumkid[1], message); + break; + + default: + /* Hmm.. bad RDP operation */ + fprintf (stderr, "RDP Bad RDP request (%d)\n", message); + MYwrite_char (debugsock, RDP_Return); + MYwrite_char (debugsock, RDIError_UnimplementedMessage); + break; + } + } + + if (FD_ISSET (kidmum[0], &readfds)) + { +#ifdef DEBUG + fprintf (stderr, "->ARMulator\n"); +#endif + /* Anything we get from the ARMulator has to go to the debugger... */ + /* It is that simple! */ + + passon (kidmum[0], debugsock, 1); + } + } +} + diff --git a/sim/arm/tconfig.in b/sim/arm/tconfig.in new file mode 100644 index 00000000000..04f702d5a4e --- /dev/null +++ b/sim/arm/tconfig.in @@ -0,0 +1,17 @@ +/* ARM target configuration file. */ + +/* Define this if the simulator supports profiling. + See the mips simulator for an example. + This enables the `-p foo' and `-s bar' options. + The target is required to provide sim_set_profile{,_size}. */ +/* #define SIM_HAVE_PROFILE */ + +/* Define this if the simulator uses an instruction cache. + See the h8/300 simulator for an example. + This enables the `-c size' option to set the size of the cache. + The target is required to provide sim_set_simcache_size. */ +/* #define SIM_HAVE_SIMCACHE */ + +/* Define this if the target cpu is bi-endian + and the simulator supports it. */ +#define SIM_HAVE_BIENDIAN diff --git a/sim/arm/thumbemu.c b/sim/arm/thumbemu.c new file mode 100644 index 00000000000..eaf6e0cca65 --- /dev/null +++ b/sim/arm/thumbemu.c @@ -0,0 +1,455 @@ +/* thumbemu.c -- Thumb instruction emulation. + Copyright (C) 1996, Cygnus Software Technologies Ltd. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* We can provide simple Thumb simulation by decoding the Thumb +instruction into its corresponding ARM instruction, and using the +existing ARM simulator. */ + +#ifndef MODET /* required for the Thumb instruction support */ +#if 1 +#error "MODET needs to be defined for the Thumb world to work" +#else +#define MODET (1) +#endif +#endif + +#include "armdefs.h" +#include "armemu.h" + +/* Decode a 16bit Thumb instruction. The instruction is in the low + 16-bits of the tinstr field, with the following Thumb instruction + held in the high 16-bits. Passing in two Thumb instructions allows + easier simulation of the special dual BL instruction. */ + +tdstate +ARMul_ThumbDecode (state,pc,tinstr,ainstr) + ARMul_State *state; + ARMword pc; + ARMword tinstr; + ARMword *ainstr; +{ + tdstate valid = t_decoded; /* default assumes a valid instruction */ + ARMword next_instr; + + if (state->bigendSig) + { + next_instr = tinstr & 0xFFFF; + tinstr >>= 16; + } + else + { + next_instr = tinstr >> 16; + tinstr &= 0xFFFF; + } + +#if 1 /* debugging to catch non updates */ + *ainstr = 0xDEADC0DE; +#endif + + switch ((tinstr & 0xF800) >> 11) + { + case 0: /* LSL */ + case 1: /* LSR */ + case 2: /* ASR */ + /* Format 1 */ + *ainstr = 0xE1B00000 /* base opcode */ + | ((tinstr & 0x1800) >> (11 - 5)) /* shift type */ + | ((tinstr & 0x07C0) << (7 - 6)) /* imm5 */ + | ((tinstr & 0x0038) >> 3) /* Rs */ + | ((tinstr & 0x0007) << 12); /* Rd */ + break; + case 3: /* ADD/SUB */ + /* Format 2 */ + { + ARMword subset[4] = { + 0xE0900000, /* ADDS Rd,Rs,Rn */ + 0xE0500000, /* SUBS Rd,Rs,Rn */ + 0xE2900000, /* ADDS Rd,Rs,#imm3 */ + 0xE2500000 /* SUBS Rd,Rs,#imm3 */ + }; + /* It is quicker indexing into a table, than performing switch + or conditionals: */ + *ainstr = subset[(tinstr & 0x0600) >> 9] /* base opcode */ + | ((tinstr & 0x01C0) >> 6) /* Rn or imm3 */ + | ((tinstr & 0x0038) << (16 - 3)) /* Rs */ + | ((tinstr & 0x0007) << (12 - 0)); /* Rd */ + } + break; + case 4: /* MOV */ + case 5: /* CMP */ + case 6: /* ADD */ + case 7: /* SUB */ + /* Format 3 */ + { + ARMword subset[4] = { + 0xE3B00000, /* MOVS Rd,#imm8 */ + 0xE3500000, /* CMP Rd,#imm8 */ + 0xE2900000, /* ADDS Rd,Rd,#imm8 */ + 0xE2500000, /* SUBS Rd,Rd,#imm8 */ + }; + *ainstr = subset[(tinstr & 0x1800) >> 11] /* base opcode */ + | ((tinstr & 0x00FF) >> 0) /* imm8 */ + | ((tinstr & 0x0700) << (16 - 8)) /* Rn */ + | ((tinstr & 0x0700) << (12 - 8)); /* Rd */ + } + break ; + case 8: /* Arithmetic and high register transfers */ + /* TODO: Since the subsets for both Format 4 and Format 5 + instructions are made up of different ARM encodings, we could + save the following conditional, and just have one large + subset. */ + if ((tinstr & (1 << 10)) == 0) + { + /* Format 4 */ + struct { + ARMword opcode; + enum {t_norm,t_shift,t_neg,t_mul} otype; + } subset[16] = { + {0xE0100000, t_norm}, /* ANDS Rd,Rd,Rs */ + {0xE0300000, t_norm}, /* EORS Rd,Rd,Rs */ + {0xE1B00010, t_shift}, /* MOVS Rd,Rd,LSL Rs */ + {0xE1B00030, t_shift}, /* MOVS Rd,Rd,LSR Rs */ + {0xE1B00050, t_shift}, /* MOVS Rd,Rd,ASR Rs */ + {0xE0B00000, t_norm}, /* ADCS Rd,Rd,Rs */ + {0xE0D00000, t_norm}, /* SBCS Rd,Rd,Rs */ + {0xE1B00070, t_shift}, /* MOVS Rd,Rd,ROR Rs */ + {0xE1100000, t_norm}, /* TST Rd,Rs */ + {0xE2700000, t_neg}, /* RSBS Rd,Rs,#0 */ + {0xE1500000, t_norm}, /* CMP Rd,Rs */ + {0xE1700000, t_norm}, /* CMN Rd,Rs */ + {0xE1900000, t_norm}, /* ORRS Rd,Rd,Rs */ + {0xE0100090, t_mul}, /* MULS Rd,Rd,Rs */ + {0xE1D00000, t_norm}, /* BICS Rd,Rd,Rs */ + {0xE1F00000, t_norm} /* MVNS Rd,Rs */ + }; + *ainstr = subset[(tinstr & 0x03C0)>>6].opcode; /* base */ + switch (subset[(tinstr & 0x03C0)>>6].otype) + { + case t_norm: + *ainstr |= ((tinstr & 0x0007) << 16) /* Rn */ + | ((tinstr & 0x0007) << 12) /* Rd */ + | ((tinstr & 0x0038) >> 3); /* Rs */ + break; + case t_shift: + *ainstr |= ((tinstr & 0x0007) << 12) /* Rd */ + | ((tinstr & 0x0007) >> 0) /* Rm */ + | ((tinstr & 0x0038) << (8 - 3)); /* Rs */ + break; + case t_neg: + *ainstr |= ((tinstr & 0x0007) << 12) /* Rd */ + | ((tinstr & 0x0038) << (16 - 3)); /* Rn */ + break; + case t_mul: + *ainstr |= ((tinstr & 0x0007) << 16) /* Rd */ + | ((tinstr & 0x0007) << 8) /* Rs */ + | ((tinstr & 0x0038) >> 3); /* Rm */ + break; + } + } + else + { + /* Format 5 */ + ARMword Rd = ((tinstr & 0x0007) >> 0); + ARMword Rs = ((tinstr & 0x0038) >> 3); + if (tinstr & (1 << 7)) + Rd += 8; + if (tinstr & (1 << 6)) + Rs += 8; + switch ((tinstr & 0x03C0) >> 6) + { + case 0x1: /* ADD Rd,Rd,Hs */ + case 0x2: /* ADD Hd,Hd,Rs */ + case 0x3: /* ADD Hd,Hd,Hs */ + *ainstr = 0xE0800000 /* base */ + | (Rd << 16) /* Rn */ + | (Rd << 12) /* Rd */ + | (Rs << 0); /* Rm */ + break; + case 0x5: /* CMP Rd,Hs */ + case 0x6: /* CMP Hd,Rs */ + case 0x7: /* CMP Hd,Hs */ + *ainstr = 0xE1500000 /* base */ + | (Rd << 16) /* Rn */ + | (Rd << 12) /* Rd */ + | (Rs << 0); /* Rm */ + break; + case 0x9: /* MOV Rd,Hs */ + case 0xA: /* MOV Hd,Rs */ + case 0xB: /* MOV Hd,Hs */ + *ainstr = 0xE1A00000 /* base */ + | (Rd << 16) /* Rn */ + | (Rd << 12) /* Rd */ + | (Rs << 0); /* Rm */ + break; + case 0xC: /* BX Rs */ + case 0xD: /* BX Hs */ + *ainstr = 0xE12FFF10 /* base */ + | ((tinstr & 0x0078) >> 3); /* Rd */ + break; + case 0x0: /* UNDEFINED */ + case 0x4: /* UNDEFINED */ + case 0x8: /* UNDEFINED */ + case 0xE: /* UNDEFINED */ + case 0xF: /* UNDEFINED */ + valid = t_undefined; + break; + } + } + break; + case 9: /* LDR Rd,[PC,#imm8] */ + /* Format 6 */ + *ainstr = 0xE59F0000 /* base */ + | ((tinstr & 0x0700) << (12 - 8)) /* Rd */ + | ((tinstr & 0x00FF) << (2 - 0)); /* off8 */ + break; + case 10: + case 11: + /* TODO: Format 7 and Format 8 perform the same ARM encoding, so + the following could be merged into a single subset, saving on + the following boolean: */ + if ((tinstr & (1 << 9)) == 0) + { + /* Format 7 */ + ARMword subset[4] = { + 0xE7800000, /* STR Rd,[Rb,Ro] */ + 0xE7C00000, /* STRB Rd,[Rb,Ro] */ + 0xE7900000, /* LDR Rd,[Rb,Ro] */ + 0xE7D00000 /* LDRB Rd,[Rb,Ro] */ + }; + *ainstr = subset[(tinstr & 0x0C00) >> 10] /* base */ + | ((tinstr & 0x0007) << (12 - 0)) /* Rd */ + | ((tinstr & 0x0038) << (16 - 3)) /* Rb */ + | ((tinstr & 0x01C0) >> 6); /* Ro */ + } + else + { + /* Format 8 */ + ARMword subset[4] = { + 0xE18000B0, /* STRH Rd,[Rb,Ro] */ + 0xE19000D0, /* LDRSB Rd,[Rb,Ro] */ + 0xE19000B0, /* LDRH Rd,[Rb,Ro] */ + 0xE19000F0 /* LDRSH Rd,[Rb,Ro] */ + }; + *ainstr = subset[(tinstr & 0x0C00) >> 10] /* base */ + | ((tinstr & 0x0007) << (12 - 0)) /* Rd */ + | ((tinstr & 0x0038) << (16 - 3)) /* Rb */ + | ((tinstr & 0x01C0) >> 6); /* Ro */ + } + break; + case 12: /* STR Rd,[Rb,#imm5] */ + case 13: /* LDR Rd,[Rb,#imm5] */ + case 14: /* STRB Rd,[Rb,#imm5] */ + case 15: /* LDRB Rd,[Rb,#imm5] */ + /* Format 9 */ + { + ARMword subset[4] = { + 0xE5800000, /* STR Rd,[Rb,#imm5] */ + 0xE5900000, /* LDR Rd,[Rb,#imm5] */ + 0xE5C00000, /* STRB Rd,[Rb,#imm5] */ + 0xE5D00000 /* LDRB Rd,[Rb,#imm5] */ + }; + /* The offset range defends on whether we are transferring a + byte or word value: */ + *ainstr = subset[(tinstr & 0x1800) >> 11] /* base */ + | ((tinstr & 0x0007) << (12 - 0)) /* Rd */ + | ((tinstr & 0x0038) << (16 - 3)) /* Rb */ + | ((tinstr & 0x07C0) >> + (6 - ((tinstr & (1 << 12)) ? 0 : 2))); /* off5 */ + } + break; + case 16: /* STRH Rd,[Rb,#imm5] */ + case 17: /* LDRH Rd,[Rb,#imm5] */ + /* Format 10 */ + *ainstr = ((tinstr & (1 << 11)) /* base */ + ? 0xE1D000B0 /* LDRH */ + : 0xE1C000B0) /* STRH */ + | ((tinstr & 0x0007) << (12 - 0)) /* Rd */ + | ((tinstr & 0x0038) << (16 - 3)) /* Rb */ + | ((tinstr & 0x01C0) >> (6 - 1)) /* off5, low nibble */ + | ((tinstr & 0x0600) >> (9 - 8)); /* off5, high nibble */ + break; + case 18: /* STR Rd,[SP,#imm8] */ + case 19: /* LDR Rd,[SP,#imm8] */ + /* Format 11 */ + *ainstr = ((tinstr & (1 << 11)) /* base */ + ? 0xE59D0000 /* LDR */ + : 0xE58D0000) /* STR */ + | ((tinstr & 0x0700) << (12 - 8)) /* Rd */ + | ((tinstr & 0x00FF) << 2); /* off8 */ + break; + case 20: /* ADD Rd,PC,#imm8 */ + case 21: /* ADD Rd,SP,#imm8 */ + /* Format 12 */ + if ((tinstr & (1 << 11)) == 0) + { + /* NOTE: The PC value used here should by word aligned */ + /* We encode shift-left-by-2 in the rotate immediate field, + so no shift of off8 is needed. */ + *ainstr = 0xE28F0F00 /* base */ + | ((tinstr & 0x0700) << (12 - 8)) /* Rd */ + | (tinstr & 0x00FF); /* off8 */ + } + else + { + /* We encode shift-left-by-2 in the rotate immediate field, + so no shift of off8 is needed. */ + *ainstr = 0xE28D0F00 /* base */ + | ((tinstr & 0x0700) << (12 - 8)) /* Rd */ + | (tinstr & 0x00FF); /* off8 */ + } + break; + case 22: + case 23: + if ((tinstr & 0x0F00) == 0x0000) + { + /* Format 13 */ + /* NOTE: The instruction contains a shift left of 2 + equivalent (implemented as ROR #30): */ + *ainstr = ((tinstr & (1 << 7)) /* base */ + ? 0xE24DDF00 /* SUB */ + : 0xE28DDF00) /* ADD */ + | (tinstr & 0x007F); /* off7 */ + } + else + { + /* Format 14 */ + ARMword subset[4] = { + 0xE92D0000, /* STMDB sp!,{rlist} */ + 0xE92D4000, /* STMDB sp!,{rlist,lr} */ + 0xE8BD0000, /* LDMIA sp!,{rlist} */ + 0xE8BD8000 /* LDMIA sp!,{rlist,pc} */ + }; + *ainstr = subset[((tinstr & (1 << 11)) >> 10) + | ((tinstr & (1 << 8)) >> 8)] /* base */ + | (tinstr & 0x00FF); /* mask8 */ + } + break; + case 24: /* STMIA */ + case 25: /* LDMIA */ + /* Format 15 */ + *ainstr = ((tinstr & (1 << 11)) /* base */ + ? 0xE8B00000 /* LDMIA */ + : 0xE8A00000) /* STMIA */ + | ((tinstr & 0x0700) << (16 - 8)) /* Rb */ + | (tinstr & 0x00FF); /* mask8 */ + break; + case 26: /* Bcc */ + case 27: /* Bcc/SWI */ + if ((tinstr & 0x0F00) == 0x0F00) + { + /* Format 17 : SWI */ + *ainstr = 0xEF000000; + /* Breakpoint must be handled specially. */ + if ((tinstr & 0x00FF) == 0x18) + *ainstr |= ((tinstr & 0x00FF) << 16); + else + *ainstr |= (tinstr & 0x00FF); + } + else if ((tinstr & 0x0F00) != 0x0E00) + { + /* Format 16 */ + int doit = FALSE; + /* TODO: Since we are doing a switch here, we could just add + the SWI and undefined instruction checks into this + switch to same on a couple of conditionals: */ + switch ((tinstr & 0x0F00) >> 8) { + case EQ : doit=ZFLAG ; + break ; + case NE : doit=!ZFLAG ; + break ; + case VS : doit=VFLAG ; + break ; + case VC : doit=!VFLAG ; + break ; + case MI : doit=NFLAG ; + break ; + case PL : doit=!NFLAG ; + break ; + case CS : doit=CFLAG ; + break ; + case CC : doit=!CFLAG ; + break ; + case HI : doit=(CFLAG && !ZFLAG) ; + break ; + case LS : doit=(!CFLAG || ZFLAG) ; + break ; + case GE : doit=((!NFLAG && !VFLAG) || (NFLAG && VFLAG)) ; + break ; + case LT : doit=((NFLAG && !VFLAG) || (!NFLAG && VFLAG)) ; + break ; + case GT : doit=((!NFLAG && !VFLAG && !ZFLAG) || (NFLAG && VFLAG && !ZFLAG)) ; + break ; + case LE : doit=((NFLAG && !VFLAG) || (!NFLAG && VFLAG)) || ZFLAG ; + break ; + } + if (doit) { + state->Reg[15] = pc + 4 + + (((tinstr & 0x7F) << 1) + | ((tinstr & (1 << 7)) ? 0xFFFFFF00 : 0)); + FLUSHPIPE; + } + valid = t_branch; + } + else /* UNDEFINED : cc=1110(AL) uses different format */ + valid = t_undefined; + break; + case 28: /* B */ + /* Format 18 */ + state->Reg[15] = pc + 4 + + (((tinstr & 0x3FF) << 1) + | ((tinstr & (1 << 10)) ? 0xFFFFF800 : 0)); + FLUSHPIPE; + valid = t_branch; + break; + case 29: /* UNDEFINED */ + valid = t_undefined; + break; + case 30: /* BL instruction 1 */ + /* Format 19 */ + /* There is no single ARM instruction equivalent for this Thumb + instruction. To keep the simulation simple (from the user + perspective) we check if the following instruction is the + second half of this BL, and if it is we simulate it + immediately. */ + state->Reg[14] = state->Reg[15] \ + + (((tinstr & 0x07FF) << 12) \ + | ((tinstr & (1 << 10)) ? 0xFF800000 : 0)); + valid = t_branch; /* in-case we don't have the 2nd half */ + tinstr = next_instr; /* move the instruction down */ + if (((tinstr & 0xF800) >> 11) != 31) + break; /* exit, since not correct instruction */ + /* else we fall through to process the second half of the BL */ + pc += 2; /* point the pc at the 2nd half */ + case 31: /* BL instruction 2 */ + /* Format 19 */ + /* There is no single ARM instruction equivalent for this + instruction. Also, it should only ever be matched with the + fmt19 "BL instruction 1" instruction. However, we do allow + the simulation of it on its own, with undefined results if + r14 is not suitably initialised.*/ + { + ARMword tmp = (pc + 2); + state->Reg[15] = (state->Reg[14] + ((tinstr & 0x07FF) << 1)); + state->Reg[14] = (tmp | 1); + valid = t_branch; + FLUSHPIPE; + } + break; + } + + return valid; +} diff --git a/sim/arm/wrapper.c b/sim/arm/wrapper.c new file mode 100644 index 00000000000..40380040a01 --- /dev/null +++ b/sim/arm/wrapper.c @@ -0,0 +1,467 @@ +/* run front end support for arm + Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + +This file is part of ARM SIM. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* This file provides the interface between the simulator and run.c and gdb + (when the simulator is linked with gdb). + All simulator interaction should go through this file. */ + +#include +#include +#include +#include +#include "callback.h" +#include "remote-sim.h" +#include "armdefs.h" +#include "armemu.h" +#include "dbg_rdi.h" + +host_callback *sim_callback; + +static struct ARMul_State *state; + +/* Who is using the simulator. */ +static SIM_OPEN_KIND sim_kind; + +/* argv[0] */ +static char *myname; + +/* Memory size in bytes. */ +static int mem_size = (1 << 21); + +/* Non-zero to display start up banner, and maybe other things. */ +static int verbosity; + +/* Non-zero to set big endian mode. */ +static int big_endian; + +static void +init () +{ + static int done; + + if (!done) + { + ARMul_EmulateInit(); + state = ARMul_NewState (); + state->bigendSig = (big_endian ? HIGH : LOW); + ARMul_MemoryInit(state, mem_size); + ARMul_OSInit(state); + ARMul_CoProInit(state); + state->verbose = verbosity; + done = 1; + } +} + +/* Set verbosity level of simulator. + This is not intended to produce detailed tracing or debugging information. + Just summaries. */ +/* FIXME: common/run.c doesn't do this yet. */ + +void +sim_set_verbose (v) + int v; +{ + verbosity = v; +} + +/* Set the memory size to SIZE bytes. + Must be called before initializing simulator. */ +/* FIXME: Rename to sim_set_mem_size. */ + +void +sim_size (size) + int size; +{ + mem_size = size; +} + +void +ARMul_ConsolePrint (ARMul_State * state, const char *format,...) +{ + va_list ap; + + if (state->verbose) + { + va_start (ap, format); + vprintf (format, ap); + va_end (ap); + } +} + +ARMword +ARMul_Debug (ARMul_State * state, ARMword pc, ARMword instr) +{ + +} + +int +sim_write (sd, addr, buffer, size) + SIM_DESC sd; + SIM_ADDR addr; + unsigned char *buffer; + int size; +{ + int i; + init (); + for (i = 0; i < size; i++) + { + ARMul_WriteByte (state, addr+i, buffer[i]); + } + return size; +} + +int +sim_read (sd, addr, buffer, size) + SIM_DESC sd; + SIM_ADDR addr; + unsigned char *buffer; + int size; +{ + int i; + init (); + for (i = 0; i < size; i++) + { + buffer[i] = ARMul_ReadByte (state, addr + i); + } + return size; +} + +int +sim_trace (sd) + SIM_DESC sd; +{ + (*sim_callback->printf_filtered) (sim_callback, "This simulator does not support tracing\n"); + return 1; +} + +int +sim_stop (sd) + SIM_DESC sd; +{ + return 0; +} + +void +sim_resume (sd, step, siggnal) + SIM_DESC sd; + int step, siggnal; +{ + state->EndCondition = 0; + + if (step) + { + state->Reg[15] = ARMul_DoInstr (state); + if (state->EndCondition == 0) + state->EndCondition = RDIError_BreakpointReached; + } + else + { +#if 1 /* JGS */ + state->NextInstr = RESUME; /* treat as PC change */ +#endif + state->Reg[15] = ARMul_DoProg (state); + } + + FLUSHPIPE; +} + +SIM_RC +sim_create_inferior (sd, abfd, argv, env) + SIM_DESC sd; + struct _bfd *abfd; + char **argv; + char **env; +{ + int argvlen=0; + char **arg; + + if (abfd != NULL) + ARMul_SetPC (state, bfd_get_start_address (abfd)); + else + ARMul_SetPC (state, 0); /* ??? */ + +#if 1 /* JGS */ + /* We explicitly select a processor capable of supporting the ARM + 32bit mode, and then we force the simulated CPU into the 32bit + User mode: */ + ARMul_SelectProcessor(state, ARM600); + ARMul_SetCPSR(state, USER32MODE); +#endif + + if (argv != NULL) + { + /* + ** Set up the command line (by laboriously stringing together the + ** environment carefully picked apart by our caller...) + */ + /* Free any old stuff */ + if (state->CommandLine != NULL) + { + free(state->CommandLine); + state->CommandLine = NULL; + } + + /* See how much we need */ + for (arg = argv; *arg != NULL; arg++) + argvlen += strlen(*arg)+1; + + /* allocate it... */ + state->CommandLine = malloc(argvlen+1); + if (state->CommandLine != NULL) + { + arg = argv; + state->CommandLine[0]='\0'; + for (arg = argv; *arg != NULL; arg++) + { + strcat(state->CommandLine, *arg); + strcat(state->CommandLine, " "); + } + } + } + + if (env != NULL) + { + /* Now see if there's a MEMSIZE spec in the environment */ + while (*env) + { + if (strncmp(*env, "MEMSIZE=", sizeof("MEMSIZE=")-1)==0) + { + unsigned long top_of_memory; + char *end_of_num; + + /* Set up memory limit */ + state->MemSize = strtoul(*env + sizeof("MEMSIZE=")-1, &end_of_num, 0); + } + env++; + } + } + + return SIM_RC_OK; +} + +void +sim_info (sd, verbose) + SIM_DESC sd; + int verbose; +{ +} + + +static int +frommem (state, memory) + struct ARMul_State *state; + unsigned char *memory; +{ + if (state->bigendSig == HIGH) + { + return (memory[0] << 24) + | (memory[1] << 16) + | (memory[2] << 8) + | (memory[3] << 0); + } + else + { + return (memory[3] << 24) + | (memory[2] << 16) + | (memory[1] << 8) + | (memory[0] << 0); + } +} + + +static void +tomem (state, memory, val) + struct ARMul_State *state; + unsigned char *memory; + int val; +{ + if (state->bigendSig == HIGH) + { + memory[0] = val >> 24; + memory[1] = val >> 16; + memory[2] = val >> 8; + memory[3] = val >> 0; + } + else + { + memory[3] = val >> 24; + memory[2] = val >> 16; + memory[1] = val >> 8; + memory[0] = val >> 0; + } +} + +int +sim_store_register (sd, rn, memory, length) + SIM_DESC sd; + int rn; + unsigned char *memory; + int length; +{ + init (); + ARMul_SetReg(state, state->Mode, rn, frommem (state, memory)); + return -1; +} + +int +sim_fetch_register (sd, rn, memory, length) + SIM_DESC sd; + int rn; + unsigned char *memory; + int length; +{ + ARMword regval; + + init (); + if (rn < 16) + regval = ARMul_GetReg(state, state->Mode, rn); + else if (rn == 25) /* FIXME: use PS_REGNUM from gdb/config/arm/tm-arm.h */ + regval = ARMul_GetCPSR(state); + else + regval = 0; /* FIXME: should report an error */ + tomem (state, memory, regval); + return -1; +} + +SIM_DESC +sim_open (kind, ptr, abfd, argv) + SIM_OPEN_KIND kind; + host_callback *ptr; + struct _bfd *abfd; + char **argv; +{ + sim_kind = kind; + myname = argv[0]; + sim_callback = ptr; + + /* Decide upon the endian-ness of the processor. + If we can, get the information from the bfd itself. + Otherwise look to see if we have been given a command + line switch that tells us. Otherwise default to little endian. */ + if (abfd != NULL) + big_endian = bfd_big_endian (abfd); + else if (argv[1] != NULL) + { + int i; + + /* Scan for endian-ness switch. */ + for (i = 0; (argv[i] != NULL) && (argv[i][0] != 0); i++) + if (argv[i][0] == '-' && argv[i][1] == 'E') + { + char c; + + if ((c = argv[i][2]) == 0) + { + ++i; + c = argv[i][0]; + } + + switch (c) + { + case 0: + sim_callback->printf_filtered + (sim_callback, "No argument to -E option provided\n"); + break; + + case 'b': + case 'B': + big_endian = 1; + break; + + case 'l': + case 'L': + big_endian = 0; + break; + + default: + sim_callback->printf_filtered + (sim_callback, "Unrecognised argument to -E option\n"); + break; + } + } + } + + return (SIM_DESC) 1; +} + +void +sim_close (sd, quitting) + SIM_DESC sd; + int quitting; +{ + /* nothing to do */ +} + +SIM_RC +sim_load (sd, prog, abfd, from_tty) + SIM_DESC sd; + char *prog; + bfd *abfd; + int from_tty; +{ + extern bfd *sim_load_file (); /* ??? Don't know where this should live. */ + bfd *prog_bfd; + + prog_bfd = sim_load_file (sd, myname, sim_callback, prog, abfd, + sim_kind == SIM_OPEN_DEBUG, + 0, sim_write); + if (prog_bfd == NULL) + return SIM_RC_FAIL; + ARMul_SetPC (state, bfd_get_start_address (prog_bfd)); + if (abfd == NULL) + bfd_close (prog_bfd); + return SIM_RC_OK; +} + +void +sim_stop_reason (sd, reason, sigrc) + SIM_DESC sd; + enum sim_stop *reason; + int *sigrc; +{ + if (state->EndCondition == 0) + { + *reason = sim_exited; + *sigrc = state->Reg[0] & 255; + } + else + { + *reason = sim_stopped; + if (state->EndCondition == RDIError_BreakpointReached) + *sigrc = SIGTRAP; + else + *sigrc = 0; + } +} + +void +sim_do_command (sd, cmd) + SIM_DESC sd; + char *cmd; +{ + (*sim_callback->printf_filtered) (sim_callback, "This simulator does not accept any commands.\n"); +} + + +void +sim_set_callbacks (ptr) + host_callback *ptr; +{ + sim_callback = ptr; +} diff --git a/sim/common/ChangeLog b/sim/common/ChangeLog new file mode 100644 index 00000000000..bde07108db9 --- /dev/null +++ b/sim/common/ChangeLog @@ -0,0 +1,4005 @@ +1999-02-09 Doug Evans + + * Make-common.in (CGEN_READ_SCM): Renamed from CGEN_MAIN_SCM. + (CGEN_DESC_SCM): New variable. + (cgen-desc): New rule. + * cgen-cpu.h (CGEN_DISASSEMBLER): New type. + (CGEN_CPU): Member opcode renamed to cpu_desc. + New members get_idata,disassembler. + * cgen-defs.h (CGEN_INSN_VIRTUAL_P): CGEN_INSN_ATTR renamed to + CGEN_INSN_ATTR_VALUE. + (CGEN_STATE): Delete member opcode_table. + (sim_disassemble_insn): Delete decl. + * cgen-engine.h (struct insn_sem): Moved to here from -decode.c. + (struct idesc): Moved to here from -decode.h. + * cgen-run.c (prime_cpu): Call prepare_run callback. + * cgen-trace.h (SFILE): New type. + (sim_disasm_sprintf): Declare. + (sim_disasm_read_memory,sim_disasm_perror_memory): Declare. + (sim_cgen_disassemble_insn): Declare. + * cgen-trace.c: Include errno.h,dis-asm.h. Don't include cpu-opc.h. + (insn_fields): Delete. + (trace_insn_fini): STATE_OPCODE_TABLE (sd) replaced with + CPU_CPU_DESC (cpu). + (trace_insn): Call CPU_DISASSEMBLER hook. + (sim_disasm_sprintf): New function. + (sim_disasm_read_memory): New function. + (sim_disasm_perror_memory): New function. + (sim_cgen_disassemble_insn): New function. + * cgen-utils.c: Don't include cpu-opc.h. + (virtual_insn_entries): New static local. + (cgen_virtual_insn_table): Renamed from cgen_virtual_opcode_table. + (cgen_insn_name): Rewrite. + (disasm_sprintf,sim_disassemble_insn): Moved to cgen-trace.c. + * cgen.sh (desc): New file generator handler. + * genmloop.sh: -parallel changed to -parallel-read/-parallel-write. + Define WITH_PARALLEL_READ/WITH_PARALLEL_WRITE appropriately. + Don't include cpu-opc.h,cpu-sim.h. + * sim-model.c (model_set): Delete SIM_DESC arg. + (sim_model_set): Update. + * sim-model.h (MACH): New member prepare_run. + +1999-01-28 Frank Ch. Eigler + + * sim-memopt.c (memory_option_handler): Avoid memset() calls + if redundant with allocator functions. + +Wed Jan 27 17:19:09 1999 Doug Evans + + * cgen-engine.h (EXTRACT_LSB0_{INT,UINT}): Fix. + + * sim-profile.h: Make like sim-trace.h. + (PROFILE_USEFUL_MASK): New macro. + * sim-profile.c (profile_options): Make like trace_options, allow + optional on|off arg where applicable. + (set_profile_option_mask): New function. + (sim_profile_set_option): New function. + (profile_option_handler): Simplify. + Have -p only enable selected things, not everything. + Add missing break to OPTION_PROFILE_PC_RANGE. + * cgen-scache.c (scache_options): Allow optional on|off arg to + --profile-scache. + (scache_option_handler): Use sim_profile_set_option. + +1999-01-26 Frank Ch. Eigler + + * sim-memopt.c (memory_options): Add MEMORY_FILL option. + (memory_option_handler): Implement MEMORY_FILL option. Make + MEMORY_CLEAR an alias for MEMORY_FILL=0. + (parse_ulong_value): New function. + (do_memopt_add): Allocate all buffers. Optionally fill them. + +1999-01-15 Richard Henderson + + * hw-events.c (hw_event_queue_schedule): _vtracef takes a + va_list, not an integer. + * sim-events.c (sim_events_schedule): Likewise. + + * sim-types.h (UNSIGNED32, UNSIGNED64): Properly cast to + the appropriate type. + +1999-01-14 Doug Evans + + * cgen-defs.h (PCADDR,CIA): Define in terms of IADDR. + (sim_disassemble_insn): Update prototype. + (sim_engine_invalid_insn): Ditto. + * cgen-engine.h (SEMANTIC_FN): Add !WITH_SCACHE version. + (SEM_BRANCH_INIT): PCADDR->IADDR. + (SEM_NBRANCH_FINI): New macro for !WITH_SCACHE case. + * cgen-scache.c (scache_lookup,scache_lookup_or_alloc): PCADDR->IADDR. + * cgen-scache.h (*): Ditto. + * cgen-trace.c (*): Ditto. + * cgen-trace.h (*): Ditto. + * cgen-utils.c (*): Ditto. + * cgen-types.h (integer modes): Use signedNN/unsignedNN types. + (insn_t): Delete. + * genmloop.sh (@cpu@_fill_argbuf): Add !WITH_SCACHE support. + (simple engine framework): Rewrite. + * sim-module.c (modules): Install model module sooner (and in + particular before the profile module). + +1999-01-12 Doug Evans + + * sim-model.h (sim_mach_lookup_bfd_name): Add prototype. + * sim-model.c (sim_mach_lookup_bfd_name): New function. + (sim_model_init): Call it. + + * cgen-trace.c (trace_insn): Pass pc to trace_prefix for virtual insns. + +1999-01-05 Doug Evans + + * Make-common.in (CGEN_INCLUDE_DEPS): Add cgen-defs.h, cgen-engine.h. + (CGEN_MAIN_SCM): Add rtx-funcs.scm. + (cgen-arch): Pass $(mach) to cgen.sh. + * cgen-engine.h (SEM_BRANCH_FINI): New arg pcvar, all uses updated. + (SEM_BRANCH_INIT_EXTRACT): New macro. + (SEM_BRANCH_INIT): Add taken_p. + (TARGET_SEM_BRANCH_FINI): Provide default definition. + (SEM_BRANCH_FINI): Use it. + (SEM_INSN): Update. + * cgen-run.c (sim_resume): Handle tracing of last insn. + * cgen-scache.h (WITH_SCACHE): Define as 0 if not defined. + * cgen-trace.c (current_abuf): New static global. + (trace_insn_init): Initialize it. + (trace_insn_fini): Use it. + (trace_insn): Set it. + * cgen.sh (arch case): Pass -m ${mach} to cgen. + * genmloop.sh (@cpu@_emit_before): Only define if WITH_SCACHE_PBB. + (@cpu@_emit_after): Ditto. + (simple @cpu@_engine_run_full): New local `pc'. Initialize semantic + labels if WITH_SEM_SWITCH_FULL. + * sim-model.c: Include bfd.h. + (sim_model_init): New function. + (sim_model_install): Record init fn. + * sim-model.h (MACH): New member bfd_name. + * sim-module.c (modules): Initialize model before scache. + +1998-12-24 Frank Ch. Eigler + + * dv-sockser.c (DEFAULT_TIMEOUT): Increase to 1 ms. + + * nrun.c (main): Remain in simulation loop for traps and + exceptions when in operating environment mode. + (ui_loop_hook): New stub hook for standalone use. + * sim-events.c (sim_events_process): Call ui_loop_hook + periodically on CYGWIN host. + + * sim-reason.c (sim_stop_reason): Return host signal numbers + to gdb on sim_stopped and sim_signalled cases. + * sim-engine.c (sim_engine_halt): Call SIM_CPU_EXCEPTION_SUSPEND + hook just before longjmp. + * sim-resume.c (sim_resume): Call SIM_CPU_EXCEPTION_RESUME + hook just before sim_engine_run. + + * sim-n-core.h (sim_core_trace_M): Allay const warning. + * sim-trace.h (trace_generic): Ditto. + * sim-trace.c (trace_generic): Ditto. + +1998-12-14 Doug Evans + + * Make-common.in (SIM_MAIN_DEPS): New var. + (CGEN_MAIN_CPU_DEPS): New var. + * aclocal.m4: Add --enable-cgen-maint option. + * cgen-mem.h (GETMEM*): New arg `pc'. Pass to sim_core routine. + (SETMEM*): Ditto. + (GETIMEM*): Pass pc value to sim_core routine. + +Fri Dec 11 16:58:36 1998 Andrew Cagney + + * hw-handles.c (hw_handle_add_ihandle, hw_handle_add_phandle): + Compare with ZERO not NULL. + +Thu Dec 10 14:14:39 1998 Andrew Cagney + + * hw-properties.c, hw-instances.c, hw-tree.c: Include + "sim-assert.h". + +1998-12-09 Doug Evans + + * sim-arange.c: Include libiberty.h, and stdlib.h if present. + * sim-trace.c: Include stdlib.h if present. + * dv-sockser.c: Include unistd.h if present. + (dv_sockser_init): Add missing arg to call to sim_io_eprintf. + * cgen-scache.c (scache_flush): Delete unused locals i,sc. + +1998-12-08 James E Wilson + + * gennltvals.sh: Add i960. + * nltvals.def: Rebuild. + +1998-12-04 Doug Evans + + * cgen-defs.h: New file, old cgen-sim.h. + * cgen-sim.h: Simple header that includes others. + * sim-arange.c: New file. + * sim-arange.h: New file. + * sim-basics.h: Include it. + * Make-common.in (SIM_NEW_COMMON_OBJS): Add sim-arange.o. + (sim-arange.o): Add rule for. + * sim-cpu.h (sim_cpu_msg_prefix): Add prototype. + (sim_io_eprintf_cpu): Add prototype. + * sim-inline.h (HAVE_INLINE): Define if GNUC. + (INLINE2): New macro. + (EXTERN_INLINE): New macro. + * sim-module.c (sim_post_argv_init): Initialize cpu backlink + before calling module init fns. + * sim-profile.c (OPTION_PROFILE_*): Move into enum. + (profile_init): New function. + (profile_options): New option --profile-range. + (profile_option_handler): Handle --profile-range. + (profile_print_insn): Qualify address range specific section titles. + (profile_print_addr_ranges): New function. + (profile_info): Print address ranges if specified. + (profile_install): Set profile_init init fn. + * sim-profile.h (PROFILE_DATA): New member `range'. + * sim-trace.c (trace_init): New function. + (trace_options): New option --trace-range. + (trace_option_handler): Handle --trace-range. + (trace_install): Set trace_init init fn. + * sim-trace.h (TRACE_DATA): New member `range'. + * sim-utils.c (sim_cpu_msg_prefix): New function. + (sim_io_eprintf_cpu): New function. + * cgen-engine.h (PC_IN_TRACE_RANGE_P): New macro. + (PC_IN_PROFILE_RANGE_P): New macro. + * cgen-trace.c (trace_insn_init): Set current_insn to NULL. + (trace_insn_fini): New arg abuf. All callers updated. + Exit early if trace_insn not called. Check ARGBUF_PROFILE_P before + printing cycle counts. + * cgen-trace.h (trace_insn_fini): Update prototype. + (TRACE_RESULT_P): New macro. + (TRACE_INSN_INIT,TRACE_INSN_FINI): New arg abuf. All callers updated. + (TRACE_INSN): Check ARGBUF_TRACE_P. + (TRACE_EXTRACT,TRACE_RESULT): New arg abuf. All callers updated. + * cgen-types.h (SIM_INLINE): Delete. + (SIM_HAVE_MODEL,SIM_HAVE_ADDR_RANGE): Define. + * cgen-utils.c: Don't include cgen-engine.h + * genmloop.sh (@cpu@_fill_argbuf): New function. + (@cpu@_fill_argbuf_tp): New function. + (@cpu@_emit_before,@cpu@_emit_after): New functions. + (@cpu@_pbb_begin): Prefix cti_sc,insn_count with '_'. + (SET_CTI_VPC,SET_INSN_COUNT): Update. + (@cpu@_pbb_before): Check ARGBUF_PROFILE_P before calling + doing profiling. Update call to TRACE_INSN_INIT,TRACE_INSN_FINI. + (@cpu@_pbb_after): Check ARGBUF_PROFILE_P before calling + doing profiling. Update call to TRACE_INSN_FINI. + + * sim-memopt.c (sim_memory_uninstall): Result type is `void'. + +1998-12-03 Frank Ch. Eigler + + * sim-memopt.c (sim_memory_uninstall): Deallocate all memory + regions. + +1998-12-01 Doug Evans + + * sim-inline.c (SIM_INLINE_P): Fix typo. + +1998-11-30 Doug Evans + + * cgen-utils.c (cgen_virtual_opcode_table): Update. + +Tue Nov 24 18:40:03 1998 Andrew Cagney + + * gennltvals.sh: Add v850 and d10v. Sort alphabetically. + * nltvals.def: Re-generate. + +Mon Nov 23 13:28:38 1998 Andrew Cagney + + * sim-core.c (reverse_n, sim_core_uninstall, sim_core_init, + sim_core_map_attach, sim_core_map_detach, next_event_queue, + new_sim_core_mapping): Only define when EXTERN_SIM_CORE_P, pacify + GCC. + * sim-events.c (sim_events_uninstall, sim_events_suspend, + sim_events_resume, sim_events_zalloc, insert_sim_event): Ditto. + +1998-11-22 Doug Evans + + * genmloop.sh (${cpu}_pbb_chain): Watch for Ctrl-C's. + (${cpu}_pbb_cti_chain): Ditto. + +1998-11-18 Doug Evans + + * Make-common.in (cgen-utils.o): Depend on cgen-engine.h. + (CGEN_ARCH_SCM): New variable. + * cgen-engine.h (EXTRACT_[ML]SB0_{INT,UINT}): New macros. + (EXTRACT_INT,EXTRACT_UINT): New macros. + (SEM_SEM_ARG): New macro. + (SEM_NEXT_VPC): New arg `pc'. + * cgen-sim.h (EXTRACT_SIGNED,EXTRACT_UNSIGNED): Delete. + (sim_disassemble_insn): Update prototype. + * cgen-trace.c (current_insn,insn_fields): New static locals. + (trace_insn): Set them. + * cgen-utils.scm: #include cgen-engine.h. + (sim_disassemble_insn): New arg insn_fields. + Handle variable length insns. + * genmloop.sh: Only emit pbb decls if -pbb. + (${cpu}_scache_lookup): New arg `vpc'. + (scache support): Fetch pc before entering loop. + + * gennltvals.sh: Add fr30 support. + * nltvals.def: Rebuild. + +Wed Nov 18 10:22:22 1998 Andrew Cagney + + * sim-types.h: Re-do type system so that GCC's attribute and mode + are used to specify types. Handle case of ALPHA. + +1998-11-13 Frank Ch. Eigler + + * aclocal.m4: Add tests for dlopen family. + * config.in: Regenerated. + +Wed Nov 11 14:02:25 1998 Doug Evans + + * sim-hload.c (sim_load): Pass `prog_name' to sim_load_file, not NULL. + +Wed Nov 4 23:51:19 1998 Doug Evans + + * genmloop.sh (eng.hin): Rename HAVE_PARALLEL_EXEC to + HAVE_PARALLEL_INSNS, define as 0 or 1. Emit decls of fns in mloop.cin. + * cgen-engine.h: Typedefs of IADDR,CIA,SEM_ARG,SEM_PC moved ... + * cgen-sim.h: ... to here. + +Wed Oct 28 12:00:57 1998 Andrew Cagney + + * aclocal.m4 (enable-build-warnings): Replace + enable-sim-warnings. Extend =LIST syntax so that prepend and + append of options is possible. Drop -Werror, add + -Wstrict-prototypes for GDB compatibility. + * Make-common.in (SIM_WARNINGS): Update. + +Mon Oct 19 13:56:32 1998 Doug Evans + + * Make-common.in (CGEN_INCLUDE_DEPS): Define. + (sim-core.o): Delete duplicate dependence on $(SIM_EXTRA_DEPS). + (sim-cpu.o,sim-endian.o,sim-hw.o): Ditto. + (cgen-run.o,cgen-scache.o,cgen-trace.o,cgen-utils.o): Delete + explicit cgen header dependencies, require SIM_EXTRA_DEPS to include + CGEN_INCLUDE_DEPS. + * cgen-cpu.h: New file. + * cgen-engine.h: New file. + * cgen-scache.h: New file. + * cgen-sim.h: Delete portions moved to new files. + * genmloop.sh: Generate two files eng.hin,mloop.cin explicitly, + rather than sending result to stdout. + +Fri Oct 9 14:20:22 1998 Doug Evans + + * Make-common.in (sim-reg.o): New rule. + (cgen-run.o): New rule. + * cgen-ops.h: Delete many BI macros. Change all UBI -> BI. + * cgen-run.c (prime_cpu): New function. + * cgen-scache.c: Add pseudo-basic-block (pbb) scaching support. + (scache_option_handler, case OPTION_PROFILE_SCACHE): Handle explicitly + mentioned cpu. + (scache_flush_cpu,scache_lookup,scache_lookup_or_alloc): New fns. + * cgen-sim.h (CGEN_INSN_VIRTUAL_TYPE): New enum. + (CGEN_INSN_VIRTUAL_P): New macro. + (SEM_PC): New typedef. + (SEMANTIC_FN): Change type of result to SEM_PC. + (SEM_SET_FULL_CODE,SEM_SET_FAST_CODE,SEM_SET_CODE): New macros. + (IDESC_CTI_P,IDESC_SKIP_P): New macros. + (SCACHE_MAP): New typedef. + (CPU_SCACHE): Add pbb support. + (scace_lookup,scache_lookup_or_alloc,scache_flush_cpu): Declare. + (SEM_BRANCH_INIT_EXTRACT,SEM_BRANCH_INIT,SEM_BRANCH_FINI): New macros. + (CGEN_CPU): New members running_p,insn_count,{fast,full}_engine_fn, + max_slice_insns. + (INSN_NAME): Delete. + (cgen_insn_name): Declare. + (sim_engine_invalid_insn): Renamed from sim_engine_illegal_insn. + * cgen-trace.c (trace_buf): Shrink from 1024 to 256 bytes. + (first_insn_p): Make static. + (trace_insn): Handle virtual insns specially. + (cgen_trace_printf): Ensure we haven't overflowed the buffer. + * cgen-types.h (UBI): Delete. + (MODE_TYPE): New enum. + (HOSTINT,HOSTUINT,HOSTPTR): Delete. + * cgen-utils.c (mode_names): Delete UBI. Add INT,UINT,PTR. + (cgen_virtual_opcode_table): New global. + (cgen_insn_name): New function. + (sim_disassemble_insn): Ignore virtual insns. + * genmloop.sh: Delete top level loop generation. Add pbb support. + * sim-cpu.h (CPU_INSN_NAME_FN): New typedef. + (sim_cpu_base): New members max_insns,insn_name,model_data. + (CPU_PC_GET,CPU_PC_SET): New macros. + (sim_pc_get,sim_pc_set): Declare. + * sim-model.c (model_set): Call model init fn. + * sim-model.h (MODEL_FN): New typedef. + (INSN_TIMING): New member model_fn. + (MODEL): New members num,init. + * sim-profile.c (sim_profile_print_bar): Renamed from print_bar. + All callers updated. + (profile_insn_init): New fn. + (profile_print_insn): Update, INSN_NAME -> CPU_INSN_NAME. + Exit early if insn profiling not supported. + (profile_print_memory): Update, MAX_MODES -> MODE_TARGET_MAX. + (profile_install): Record profile_insn_init as init fn. + (profile_uninstall): Free PROFILE_INSN_COUNT if non-null. + * sim-profile.h: Update, MAX_MODES -> MODE_TARGET_MAX. + (PROFILE_DATA): Delete member exec_time. + Change insn_count to pointer to array, rather than the array. + (sim_profile_print_bar): Declare. + +Wed Oct 7 16:56:42 1998 Doug Evans + + * cgen-run.c: New file. + * sim-reg.c: New file. + +Mon Sep 14 10:58:19 1998 Frank Ch. Eigler + + * aclocal.m4: Add checks for -lsocket and -lnsl. + + * dv-sockser.c (dv_sockser_init): Use SO_REUSEADDR to + allow local port reuse on listening socket. + +Tue Sep 1 15:36:52 1998 Frank Ch. Eigler + + * sim-config.h: Remove reference to linux kernel header. + +Tue Aug 25 12:45:27 1998 Frank Ch. Eigler + + * dv-sockser.c (sockser_addr): Make variable non-static. + +Mon Aug 24 11:47:37 1998 Joyce Janczyn + + * sim-hw.{c,h} (sim_hw_parse): Return struct hw pointer. + +Tue Aug 11 18:12:19 1998 Doug Evans + + * sim-events.c (sim_events_elapsed_time): Fix calculation. + +Tue Aug 4 20:36:46 1998 Jeff Holcomb + + * Make-common.in (install-common): Add $(EXEEXT) when installing + run. + +Mon Aug 3 11:46:01 1998 Doug Evans + + * cgen-sim.h (cgen_state): New member opcode_table. + * cgen-utils.c (sim_disassemble_insn): Use it. + +Fri Jul 24 10:14:18 1998 Doug Evans + + * cgen-mem.h (DECLARE_SETT): Fix return type. + * cgen-sim.h (sim_engine_illegal_insn): Declare. + * cgen-scache.c: Include stdlib.h. + * cgen-trace.c (trace_extract): Use %lx for PCADDR. + * sim-model.c (model_option_handler): Remove unused variable `n'. + +Tue Jul 21 16:27:43 1998 Doug Evans + + * cgen-utils.c: Include bfd.h. + (sim_disassemble_insn): Update call to CGEN_EXTRACT_FN. + +Wed Jul 8 18:24:10 1998 Jeffrey A Law (law@cygnus.com) + + * sim-bits.h (EXTEND24): Fix typo. + +Wed Jul 8 17:41:47 1998 Andrew Cagney + + * sim-events.c (ETRACE_P): New macro. + (struct _sim_event): Add member trace. + (sim_events_free): Reclaim trace message. + + * sim-events.c, sim-events.h (sim_events_schedule_vtracef, + sim_events_schedule_tracef): New functions, include printf trace + information in argument list. If tracing, store asprintf'd trace + message in sim_event. + + * hw-events.c, hw-events.h (hw_event_queue_schedule_tracef, + hw_event_queue_schedule_vtracef): New functions, mimic + sim_event_tracef. + +Mon Jul 6 15:51:14 1998 Jeffrey A Law (law@cygnus.com) + + * sim-bits.h (EXTEND24): Define. + +Thu Jul 2 17:13:25 1998 Doug Evans + + * cgen-sim.h (CPU_SCACHE): Make size unsigned. + (CPU_SCACHE_HASH_MASK): New macro. + (SCACHE_HASH_PC): Rewrite. + * genmloop.sh (engine_resume_{full,fast}): Move some of hash + computation out of main loop. + +Wed Jul 1 16:44:12 1998 Doug Evans + + * Make-common.in (SCHEME,SCHEMEFLAGS): Delete. + (CGENDIR,CGEN): New variables. + (CGEN_VERBOSE): Renamed to CGENFLAGS. + (cgen-arch,cgen-cpu,cgen-decode): Update. + (CGEN_CPU_WRITE): New variable. + (CGEN_CPU_SEMSW): -W -> -X. + (CGEN_FLAGS_TO_PASS): Delete SCHEME. Add CGEN,CGENFLAGS. + * cgen.sh: Delete args scheme,schemeflags. New arg cgen. + + * cgen-sim.h (RECORD_IADDR): Delete. + * cgen-types.h (HOSTINT,HOSTUINT,HOSTPTR): New types. + * genmloop.sh (engine_resume_{full,fast}): Delete icount. + +Wed Jun 17 12:25:08 1998 Mark Alexander + + * gennltvals.def (mn10200): Add entry. + * nltvals.def: Regenerate with MN10200 additions. + +Wed Jun 17 13:18:28 1998 Andrew Cagney + + * sim-inline.h (EXTERN_*): Replace with EXTERN_*_P. Correct + documentation on how it works. + + * sim-core.h, sim-core.c (sim_core_install, sim_core_attach, + sim_core_detach, sim_core_read_buffer, sim_core_write_buffer, + sim_core_set_xor, sim_core_xor_read_buffer, + sim_core_xor_write_buffer): Update. + + * sim-events.h, sim-events.c (sim_events_install, + sim_events_watch_clock, sim_events_schedule_after_signal, + sim_events_schedule, sim_events_watch_sim, sim_events_watch_core, + sim_events_deschedule): Update. + + * sim-fpu.h, sim-fpu.c (sim_fpu_zero, sim_fpu_one, sim_fpu_two, + sim_fpu_max32, sim_fpu_max64): Update. + +Sat Jun 13 07:45:38 1998 Doug Evans + + * cgen-trace.c (trace_insn_fini): Redo cycle handling. + * sim-profile.h (PROFILE_DATA): Rename cycle handling members. + * sim-profile.c (profile_print_model): Update. + +Fri Jun 12 18:35:07 1998 Doug Evans + + * gennltvals.def (m32r): Use common syscall.h now. + (mn10300): Add entry. + * nltvals.def: Regenerate. + + * sim-engine.c (sim_engine_get_run_state): New function. + * sim-engine.h (sim_engine_get_run_state): Declare it. + +Thu Jun 11 00:50:03 1998 Doug Evans + + * sim-core.h (SIM_CORE_SIGNAL_FN): New typedef. + * sim-core.c (sim_core_signal): Make extern, always define. + +Wed Jun 10 16:02:29 1998 Doug Evans + + * Make-common.in (CGEN_FLAGS_TO_PASS): New variable. + * cgen-ops.h (ANDIF): New macro. + (ANDIF[BQHSD]I): Delete. + +Thu Jun 4 13:53:54 1998 Andrew Cagney + + * hw-events.c (create_hw_event, delete_hw_event): Delete. + (hw_event_queue_schedule, hw_event_queue_deschedule, + bounce_hw_event): Fix hw-event memory corruptions found by Joyce + Janczyn. + + * hw-alloc.h (HW_NZALLOC): Define. + + * Make-common.in (test-hw-events): Add target for testing the + hw-event code. + +Mon May 25 21:11:26 1998 Andrew Cagney + + * Make-common.in (SIM_COMMON_HW_OBJS): Add hw-handles.o and + hw-instances.o. + hw-handles.c, hw-instances.c, hw-handles.h, hw-instances.h: New + files. + * hw-main.h: Include hw-handles.h, hw-instances.h. + * hw-base.h ({create,delete}_hw_{handles,instances}_data): Declare + * hw-base.c (hw_create, hw_delete): Call same. + +Mon May 25 18:55:35 1998 Andrew Cagney + + * dv-core.c: Include hw-main.h and sim-main.h. + * dv-pal.c: Include hw-main.h and sim-io.h. + * dv-glue.c: Include hw-main.h. + + * hw-main.h: New file. Move list of includes to here. + * hw-base.h: From here. + * Make-common.in (hw_base_headers): Rename to hw_main_headers. + (hw-*.o, dv-*.o): Update. + * hw-tree.c, hw-base.c, hw-properties.c, hw-ports.c, hw-device.c, + hw-events.c, hw-alloc.c, sim-hw.c: Include hw-main.h instead of + sim-main.h. + + * hw-base.h (do_hw_attach_regs, do_hw_poll_read_method, + do_hw_poll_read): Move declarations from here. + * hw-main.h: To here. + + * hw-base.h (struct hw_device_descriptor, hw_finish_callback): + Move from here. + * hw-main.h (struct hw_descriptor, hw_finish_method): To here, + rename. + * Make-common.in (hw-config.h): Update + * hw-base.c, dv-pal.c, dv-glue.c: Update + + * dv-glue.c, hw-device.h, hw-base.h, hw-ports.c: Rename + `*_callback' to `*_method. + +Mon May 25 18:41:18 1998 Andrew Cagney + + * hw-base.h (set_*): Move set method macros from here. + * hw-device.h: To here. + +Mon May 25 18:21:38 1998 Andrew Cagney + + * hw-base.h (create_hw_property_data, delete_hw_property_data): + Declare. + + * hw-base.c (hw_create, hw_delete): Call + * hw-properties.c (create_hw_property_data, + delete_hw_property_data): Define. + +Mon May 25 17:40:46 1998 Andrew Cagney + + * hw-device.c, hw-properties.c: Include hw-base.h + + * hw-alloc.h, hw-alloc.c: New files. Move alloc code to here. + * hw-device.c: From here. + * hw-base.h: Include "hw-events.h". + + * hw-base.h (create_hw_alloc_data, delete_hw_alloc_data): Declare. + * hw-base.c (hw_create, hw_delete): Call. + * hw-alloc.c (create_hw_alloc_data, delete_hw_alloc_data): Define. + + * Make-common.in (SIM_NEW_COMMON_OBJS): Add hw-alloc.o. + (hw-alloc.o): New target. + +Mon May 25 17:14:27 1998 Andrew Cagney + + * hw-events.h, hw-events.c: New files. Move event code to here. + * sim-hw.c: From here. + * hw-base.h: Include "hw-events.h". + * Make-common.in (SIM_NEW_COMMON_OBJS): Add hw-events.o. + (hw-events.o): New target. + + * hw-device.h (struct hw): Add struct hw_event_data events_of_hw. + * hw-events.h (struct hw_event): Replace typedef hw_event. + + * hw-base.h (create_hw_event_data, delete_hw_event_data): Declare. + * hw-base.c (hw_create, hw_delete): Call. + * hw-events.c (create_hw_event_data, delete_hw_event_data): Define. + + * dv-pal.c: Update. + +Mon May 25 16:55:16 1998 Andrew Cagney + + * hw-base.c (panic_hw_port_event, empty_hw_ports): Move from here. + * hw-ports.c: To here. + + * hw-base.h, hw-ports.c (create_hw_port_data, + delete_hw_port_data): New functions. + * hw-base.c (hw_delete, hw_create): Call same. + + * hw-base.h (set_hw_ports, set_hw_port_event): Move set functions + from here. + * hw-ports.h: To here. + +Mon May 25 16:42:48 1998 Andrew Cagney + + * hw-device.c (hw_ioctl), hw-device.h (hw_ioctl_callback): Drop + PROCESSOR and CIA arguments. + +Fri May 22 12:16:27 1998 Andrew Cagney + + * aclocal.m4 (SIM_AC_OPTION_HW): Add enable / disable argument. + Move common object files from here. + * Make-common.in (SIM_COMMON_HW_OBJS): To here. + +Thu May 21 17:57:16 1998 Andrew Cagney + + * sim-hw.c: Include ctype.h. + (do_hw_poll_read): Do not assume EAGAIN. + +Wed May 20 04:37:57 1998 Doug Evans + + * cgen-trace.c (first_insn_p): New static local. + (trace_insn_init): Set it. + (trace_insn_fini): Use TRACE_PREFIX. + (trace_insn): Rewrite to use trace_prefix. + * sim-trace.c (trace_prefix): Don't print filename arg if NULL. + Adjust width accordingly. + + * sim-profile.h (PROFILE_DATA): New member profile_any_p. + (PROFILE_ANY_P,PROFILE_INSN_P,PROFILE_MEMORY): New macros. + (PROFILE_SCACHE_P,PROFILE_PC_P,PROFILE_CORE_P): New macros. + (PROFILE_COUNT_INSN,PROFILE_COUNT_READ,PROFILE_COUNT_WRITE): Simplify. + (PROFILE_COUNT_CORE): Simplify. + * sim-profile.c (profile_option_handler): Compute profile_any_p. + +Tue May 19 23:55:30 1998 Doug Evans + + * cgen-ops.h (ADDCFSI): Fix typo. + +Sat May 16 12:44:52 1998 Doug Evans + + * cgen-sim.h (CGEN_CPU): New members idesc_{read,sem}_init_p. + * genmloop.sh: Use them rather than static locals. + + * sim-engine.c (sim_engine_set_run_state): New function. + * sim-engine.h (sim_engine_set_run_state): Declare. + * genmloop.sh (pending_reason,pending_sigrc): New static locals. + (@cpu@_engine_stop): New args reason,sigrc. All callers updated. + (engine_resume): Reorganize. Allow synchronous exit from main loop. + +Fri May 15 16:06:05 1998 Doug Evans + + * cgen-trace.c (trace_insn_init): New arg first_p. + All callers updated. + (trace_insn_fini): New arg last_p. All callers updated. + * cgen-trace.h (trace_insn_init,trace_insn_fini): Update. + (TRACE_INSN_INIT,TRACE_INSN_FINI): Update. + * genmloop.sh (engine_resume): Update. + +Fri May 15 15:59:00 1998 Joyce Janczyn + + * Make-common.in (install-common): Run ranlib on installed copy of + libsim.a. + +Fri May 15 15:03:00 1998 Joyce Janczyn + + * Make-common.in (install-common): Rename and install libsim.a. + +Tue May 12 15:23:57 1998 Andrew Cagney + + * sim-io.c (unistd.h): Include. + +Wed May 6 16:04:18 1998 Doug Evans + + * Make-common (sim_main_headers): Sort. + (cgen-*.o): Add cgen-sim.h dependency. + + * cgen-scache.c (scache_init): Only allocate space if scache element + size is non-zero. + (scache_flush,scache_print_profile): Check if scache in use first. + + * cgen-sim.h (IDESC): Provide forward declaration. + (DECODE): Delete. + (CGEN_CPU): Always define scache member. New members idesc,opcode. + (cgen_cpu_max_extra_bytes): Declare. + * cgen-utils.c (cgen_cpu_max_extra_bytes): New function. + + * cgen.sh: s/@arch@/${arch}/ for cpu files. + + * sim-cpu.h: New file. sim_cpu_base moved here. + Move sim_cpu_lookup decl here. + * sim-base.h: #include "sim-cpu.h". + * sim-cpu.c: New file. + * Make-common (sim_main_headers): Add sim-cpu.h. + (sim-cpu.o): Add rule for. + + * sim-model.c (set_model): Delete. + (sim_model_set,model_set): New functions. + (sim_model_install): Renamed from model_install. + Don't set default model here. + (model_option_handler): Rewrite --model processing. + (sim_model_lookup,sim_mach_lookup): New functions. + * sim-model.h (MAX_MODELS,MAX_INSNS): Delete. + (insn_timing): Delete. + (INSN_TIMING): New member `num'. + (IMP_PROPERTIES): Always define scache_elm_size member. + (MACH): New member init_cpu. + (sim_machs): Renamed from machs. + (sim_model_install): Renamed from model_install. + (sim_model_set,sim_model_lookup,sim_mach_lookup): Declare. + * sim-module.c (modules): Update. + + * sim-profile.c (profile_print_insn): Add cpu arg to INSN_NAME macro. + + * sim-io.c: #include . + +Wed May 6 12:39:15 1998 Andrew Cagney + + * dv-pal.c (struct hw_pal_device): Add reader. + (hw_pal_finish): Initialize reader. + (scan_hw_pal): Use reader. + + * hw-base.h, sim-hw.c (do_hw_poll_read): New function. + (HW_IO_EOF, HW_IO_NOT_READY): Define. + * dv-pal.c: Use. + + * sim-io.h, sim-io.c (sim_io_poll_read): New function. Copy from + ../ppc/main.c sim_io_read_stdin. + +Fri May 1 12:11:02 1998 Andrew Cagney + + * hw-tree.h (hw_tree_print): Paramaterize with print and file + arguments. + * hw-tree.c: Update. + + * hw-base.h (hw_port_event_callback): Delete CPU/CIA args. + * hw-device.h (hw_io_read_buffer, hw_io_write_buffer): Delete + CPU/CIA args. + * hw-ports.h (hw_port_event): Ditto. + * hw-ports.c (hw_port_event): Update. + * hw-base.c (panic_hw_io_read_buffer, panic_hw_io_write_buffer): + Update. + * dv-pal.c (hw_pal_io_read_buffer, hw_pal_io_write_buffer): + Update. + (hw_pal_io_write_buffer): Call hw_halt not sim_engine_halt. + (do_counter_event): Update. + * dv-glue.c (hw_glue_io_read_buffer): Update. + (hw_glue_port_event): Update. + + * hw-device.h (SIM_DESC): Replace with struct sim_state. + * hw-base.h (hw_create): Ditto. + * hw-base.c (hw_create): Ditto. + + * hw-device.c (hw_abort, hw_trace, hw_hw_event_queue_schedule, + hw_event_queue_deschedule, hw_event_queue_time): Delete, moved + from here to. + * sim-hw.c: Here. + * hw-device.h (hw_system_cpu): Declare. + * sim-hw.c (hw_system_cpu): New function. + + * sim-core.c (sim_core_map_attach, sim_core_attach): Call + sim_hw_abort not hw_abort. + (sim-hw.h): Include. + (sim_core_read_buffer, sim_core_write_buffer): Call + sim_hw_io_read_buffer and sim_hw_io_write_buffer. Do not pass CPU + argument. + (sim_core_set_xor): Do not pass CPU when aborting. + + * sim-n-core.h (sim_core_read_aligned_N, + sim_core_write_aligned_N): Call sim_hw_abort not hw_abort. + (sim_core_read_aligned_N, sim_core_write_aligned_N): Call + sim_cpu_hw_io_read_buffer and sim_cpu_hw_io_write_buffer. Does not + return length. + + * sim-hw.h: Declare sim_hw_io_{read,write}_buffer. Declare + sim_hw_print. + * sim-hw.c (sim_hw_io_read_buffer, sim_hw_io_write_buffer, + sim_cpu_hw_io_read_buffer, sim_cpu_hw_io_write_buffer): New + functions. + (sim_hw_print): New function. + + * sim-engine.h (sim_engine_vabort): Declare. + * sim-engine.c (sim_engine_vabort): New function. + +Wed Apr 29 23:58:52 1998 Andrew Cagney + + * sim-trace.c (print_data): For floating-point numbers trace raw + hex value. + (trace_result_fp2): New function. + * sim-trace.h (trace_result_fp2): New declaration. + (TRACE_FP_RESULT2): New macro. + +Tue Apr 28 18:28:58 1998 Geoffrey Noer + + * common/aclocal.m4: call AM_EXEEXT in SIM_AC_COMMON, define + AM_CYGWIN32 and AM_EXEEXT. + * common/Make-common.in: set EXEEXT, add missing EXEEXTs + to run and install-common rules. + * common/configure: regenerate + +Sat Apr 25 17:45:01 1998 Andrew Cagney + + * sim-types.h (cell_word): New type. + (natural_cell): Delete type. + +Sun Apr 26 15:31:55 1998 Tom Tromey + + * configure: Regenerated to track ../common/aclocal.m4 changes. + * config.in: Ditto. + +Sun Apr 26 15:25:07 1998 Tom Tromey + + * acconfig.h (NEED_DECLARATION_PRINTF): Removed. + +Fri Apr 24 14:16:40 1998 Tom Tromey + + * configure: Regenerated to track ../common/aclocal.m4 changes. + * config.in: Ditto. + +Fri Apr 24 11:38:08 1998 Tom Tromey + + * acconfig.h: New file. + * Make-common.in (top_builddir): New macro. + (INTL_LIB): Removed. + (INTLLIBS): New macro. + (INTLDEPS): Likewise. + (LIBDEPS): Use INTLDEPS. + (EXTRA_LIBS): Use INTLLIBS. + * aclocal.m4 (SIM_AC_COMMON): Call CY_GNU_GETTEXT. + (CY_WITH_NLS, CY_GNU_GETTEXT, AM_PATH_PROG_WITH_TEST, + AM_LC_MESSAGES): New macros from GNU gettext. + +Fri Apr 24 19:57:59 1998 Andrew Cagney + + * sim-config.h: Discard leading _ from macros. + * sim-types.h: Ditto. + +Wed Apr 22 14:14:19 1998 Michael Meissner + + * Make-common.in (CSEARCH): Add -I to intl directories. + (INTL_LIB): Point to libintl.a. + (LIBDEPS): Add $(INTL_LIB). + (EXTRA_LIBS): Ditto. + +Tue Apr 21 12:44:27 1998 Doug Evans + + * cgen-types.h (GETHIDI,MAKEDI): Tweak. + + * cgen-ops.h (ADDCFSI): Fix. + (SUBCFSI): Tweak. + +Tue Apr 21 13:18:41 1998 Andrew Cagney + + * sim-types.h (signed_address, unsigned_address): Define. + +Mon Apr 20 21:47:54 1998 Andrew Cagney + + * sim-fpu.c (sim_fpu_2d): Don't return an SNaN, convert it into a + QNaN. + +Thu Apr 16 10:30:14 1998 Andrew Cagney + + * sim-fpu.c, sim-fpu.h (sim_fpu_fractionto, sim_fpu_tofraction): + New functions, pack / unpack sim_fpu struct using raw values. + (sim_fpu_is): Differentiate between negative and positive + infinity. + +Tue Apr 14 18:49:31 1998 Andrew Cagney + + * sim-bits.h (EXTEND4): Define. + (EXTEND4, EXTEND15, EXTEND11): Ditto. + +Tue Apr 14 16:31:35 1998 John Metzler + + * sim-memopt.c (parse_addr): Sunos 4.5 does not have strtol + declared so we need this cast to prevent long long addresses + from being misconfigures. Results in access to unmapped memory. + +Tue Apr 14 13:19:14 1998 Doug Evans + + * Make-common.in (RUNTESTFLAGS): Define. + (check): Pass RUNTESTFLAGS to recursive make. + +Tue Apr 14 15:09:19 1998 Andrew Cagney + + * sim-info.c (sim_info): Be verbose when either VERBOSE or + STATE_VERBOSE_P. + +Sat Apr 4 23:24:17 1998 Andrew Cagney + + * aclocal.m4 (sim-inline): By default, disable sim-inline when + cross compiling. + +Sat Apr 4 20:36:25 1998 Andrew Cagney + + * aclocal.m4 (sim-cflags): Add -fomit-frame-pointer to defaults. + (sim-inline): Update to match sim-inline.[hc] + * configure: Regenerated to track ../common/aclocal.m4 changes. + + * Make-common.in (sim_main_headers): Add sim-inline.h + + * sim-bits.h (sim-bits.c): Include when H_REVEALS_MODULE_P. + selected. + * sim-endian.h (sim-endian.c): Ditto. + + * sim-events.h (_SIM_EVENTS_H_): Replace with SIM_EVENTS_H. + (sim_events_set_trace): Delete unused prototype. + + * sim-core.h (_SIM_CORE_H_): Replace with SIM_CORE_H. + * sim-core.c (_SIM_CORE_C_): Ditto for SIM_CORE_C. + + * sim-fpu.h (sim-fpu.c): Include when H_REVEALS_MODULE_P. + (sim_fpu_to232i, sim_fpu_to232u, sim_fpu_i232to, sim_fpu_u232to): + Comment out, not yet implemented in sim-fpu.c. + (sim_fpu_zero, sim_fpu_one, sim_fpu_two, sim_fpu_qnan, + sim_fpu_max32, sim_fpu_max64): Mark as EXTERN_SIM_FPU. + + * sim-inline.h: Rewrite description. + (H_REVEALS_MODULE_P, C_REVEALS_MODULE_P): Define. + (SIM_MAIN_INLINE): Add inline option. + + * sim-inline.c (semantics.c, idecode.c, engine.c, ...): Do not + include generated files. Handled by generator directly. + +Sat Apr 4 01:07:06 1998 Andrew Cagney + + * sim-trace.c (set_trace_option_mask): Keep TRACE_ANY_P + up-to-date. + + * sim-trace.h (TRACE_ANY_P): Define. + (struct _trace_data): Add trace_any_p. + +Mon Mar 30 17:11:55 1998 Andrew Cagney + + * run.c (main): Handle all alternatives of enum sim_stop. + (main): Delete unused `asection *s'. + +Fri Mar 27 16:15:52 1998 Andrew Cagney + + * hw-tree.h, hw-tree.c (hw_tree_vparse): New function + + * configure: Regenerated to track ../common/aclocal.m4 changes. + + * sim-hw.c: New file. + * sim-hw.h (sim_hw_parse): Declare function. + (hw-tree.h): Do not include. + + * sim-base.h (STATE_HW): Define. + (struct sim_state_base): Add member struct *hw. + + * sim-module.c (sim-hw.h): Include. + (modules): Add sim_hw_install. + + * aclocal.m4 (sim_hw_obj): Add sim-hw.o + +Fri Mar 27 14:55:06 1998 Andrew Cagney + + * sim-base.h (CPU_INDEX): Define. + + * sim-utils.c (sim_state_alloc): Initialize. + * sim-module.c (sim_post_argv_init): Ditto. + +Thu Mar 26 10:07:57 1998 Stu Grossman + + * aclocal.m4 (sim_hw_obj): Fix sed expression to generate + properly formatted lists. + +Thu Mar 26 10:37:22 1998 Andrew Cagney + + * dv-pal.c (enum hw_pal_address_mask): From Stu Grossman, was + 0x2f needs to be 0x3f. + +Thu Mar 26 09:10:56 1998 Andrew Cagney + + * hw-tree.c (hw_tree_find_property): Return NULL when device is + not found. + (hw_tree_find_*_property): Clean up error message when property is + not found. + + * dv-pal.c (hw_pal_io_read_buffer): Check the smp property is + present before looking for it. + +Wed Mar 25 16:17:38 1998 Ian Carmichael + + * aclocal.m4 (AC_CHECK_HEADERS): Add check for fpu_control.h. + (AC_CHECK_FUNCS): Add check for __setfpucw. + * configure: Regenerated. + +Wed Mar 25 09:18:34 1998 Andrew Cagney + + * dv-pal.c (hw_pal_countdown, hw_pal_countdown_value, + hw_pal_timer, hw_pal_timer_value): Define. + (hw_pal_io_read_buffer, hw_pal_io_write_buffer): Add timer support + (do_counter_event, do_counter_read, do_counter_value, + do_counter_write): new functions. + +Tue Mar 24 12:24:24 1998 Andrew Cagney + + * hw-tree.c (hw_printf): Send tree dump to stderr, same as other + trace output. + + * hw-base.c (hw_create): Stop searching for a device when one is + found. + +Wed Mar 25 12:35:29 1998 Andrew Cagney + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Mon Mar 23 10:25:08 1998 Andrew Cagney + + * aclocal.m4 (SIM_AC_OPTION_HARDWARE): Add second argument, + appends extra devices. + (SIM_AC_OPTION_HARDWARE): Substute sim_hw, a non-duplicate list of + the device names. + + * Make-common.in (hw-config.h): New target, create hw-config.h + file. + (SIM_HW): Definition from @sim_hw@. + (hw-base.o): Depend on hw-config.h + +Tue Mar 24 17:41:35 1998 Stu Grossman + + * Make-common.in: Get SHELL from configure. + * (stamp-tvals sim-inline.c): Use $(SHELL) when invoking + move-if-change. Fixes NT native build problem. + * Makefile.in (nltvals.def): Use $(SHELL) when invoking + move-if-change. Fixes NT native build problem. + * configure: Regenerate with autoconf 2.12.1 to fix shell issues for + NT native builds. + +Sun Mar 22 16:54:40 1998 Andrew Cagney + + * hw-device.h, hw-device.c (hw_strdup): New function. + + * hw-base.c (hw_create): Use hw_strdup when saving a copy of the + strings name, family and args. + (full_name_of_hw): Use hw_strdup when returning the full path. + + * hw-properties.c: Clean up property not found / wrong type error + messages. + + * hw-tree.c (hw_tree_parse): Finish a devices initialization + before attaching any ports. + + * hw-base.c (hw-config.): Include. Replace hardwired table. + + * dv-glue.c: Copy over ../ppc/hw_glue.c. Update to new framework. + + * Make-common.in: Add rule for dv-glue.o. + +Sun Mar 22 16:45:54 1998 Andrew Cagney + + * hw-base.c (hw_finish): Move setting of trace level to here. + (hw_create): From here. + + * hw-base.h, hw-base.c (do_hw_attach_regs): Copy function from + ../ppc/device_table.c. + + * dv-pal.c (hw_pal_finish): Attach PAL device to parent bus. + + * hw-tree.c (print_properties): Supress path when printing + properties of root node. + +Sun Mar 22 16:21:15 1998 Andrew Cagney + + * hw-device.h (HW_TRACE): Define. + (hw_trace): Declare. + * hw-device.c (hw_trace): Implement function. + + * hw-base.c (hw_create): Set hw trace level from "trace?" + property. + + * dv-core.c (dv_core_attach_address_callback): Add trace. + + * dv-pal.c: Replace DTRACE with HW_TRACE. + +Sun Mar 22 15:23:35 1998 Andrew Cagney + + * hw-device.h (HW_ZALLOC, HW_MALLOC): New macros. + (hw_alloc_data): Delcare. + (struct hw): Add member alloc_of_hw. + + * hw-device.c (hw_zalloc, hw_malloc, hw_free, hw_free_all): New + functions. Assocate memory with a device. + (stdlib.h): Include. + + * hw-base.h (set_hw_delete): Define. + (hw_delete_callback): Declare. + (hw_delete): Declare. + + * hw-base.c (hw_delete): Implement function. + (struct hw_base_data): Add member to_delete. + (ignore_hw_delete): New function, does nothing. + (hw_create): Set the hw_delete method. + (hw_create): Allocate the base type using HW_ZALLOC before setting + any methods. + + * hw-tree.h, hw-tree.c (hw_tree_delete): New function. + + * hw-properties.c: Replace zalloc/zfree with hw_zalloc/hw_free. + + * hw-ports.c: Replace zalloc/zfree with hw_zalloc/hw_free. + (attach_hw_port_edge): Add struct hw argument + + * dv-pal.c (hw_pal_finish): Replace zalloc/zfree with + hw_zalloc/hw_free. + +Sun Mar 22 15:09:52 1998 Andrew Cagney + + * hw-device.h (hw_attach_address_callback, + hw_detach_address_callback): Attach to a single space not a space + mask. Clarify interpretation of SPACE:ADDR parameters. + + * hw-base.c (passthrough_hw_attach_address, + passthrough_hw_detach_address): Update. + * dv-core.c (dv_core_attach_address_callback): Ditto. + * dv-pal.c (hw_pal_attach_address): Ditto. + +Thu Mar 19 00:41:00 1998 Andrew Cagney + + * sim-options.h: Document additional CPU arg to OPTION_HANDLER. + +Wed Mar 18 14:13:02 1998 Andrew Cagney + + * Make-common.in (SIM_HW_OBJS, SIM_HW_SRC, SIM_DV_OBJS): Define. + (hw-base_h, hw-device_h, hw-handles_h, hw-instances_h, hw_ports_h, + hw-properties_h, hw-tree_h): Define, point at corresponding + header. + (hw_base_headers): Define list of headers included by hw-base.h + (hw-base.o, hw-device.o, hw-instances.o, hw-handles.o, hw-ports.o, + hw-properties.o, hw-tree.o): Specify dependencies. + (dv-core.o, dv-pal.o): Ditto. + + * sim-hw.h: New file. + + * hw-device.h, hw-device.c, hw-properties.h, hw-properties.c, + hw-ports.h, hw-ports.c: New files. Copied from ../ppc/device.[ch]. + + * hw-tree.h, hw-tree.c: New files. Copied from ../ppc/tree.[hc]. + + * hw-base.h, hw-base.c: new files. Copied from + ../ppc/device_table.[hc]. + + * dv-core.c, dv-pal.c: New files. Copied from + ../ppc/hw_{core,pal}.c + + * sim-basics.h (struct hw): Declare. + (enum port_direction, enum object_disposition): Declare. + +Wed Mar 18 12:38:12 1998 Andrew Cagney + + * aclocal.m4 (SIM_AC_OPTION_HARDWARE): Set sim_hw_obj, sim_dv_obj, + sim_dv_src in Makefile. Take list of devices as parameter to m4 + macro.. + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Mon Mar 16 12:37:33 1998 Andrew Cagney + + * sim-trace.h, sim-trace.c (trace_prefix): Pass in sim_cia so that + trace_prefix can abort cleanly. + +Sat Mar 14 18:36:12 1998 Doug Evans + + * dv-sockser.c, dv-sockser.h: New files. + * Make-common.in (dv-sockser.o): Add rule for. + * aclocal.m4: Check for fcntl.h. + * config.h: Add HAVE_FCNTL_H. + + * sim-break.c (remove_breakpoint): Fix thinko. + + * sim-hload.c (sim_load): Provide default value of SIM_HANDLES_LMA. + Use SIM_HANDLES_LMA for lma_p arg to sim_load_file. + +1998-03-13 Fred Fish + + * sim-base.h (struct sim_state_base): Add prog_syms and + define macro STATE_PROG_SYMS. + * sim-trace.c (trace_prefix): Add variables abfd, symsize, + symbol_count, and asymbols. Call bfd_get_symtab_upper_bound + and bfd_canonicalize_symtab, to get symbol table on first use + and preserve it via STATE_PROG_SYMS for future calls to + bfd_find_nearest_line. + +Wed Mar 11 14:02:47 1998 Andrew Cagney + + * sim-core.h, sim-core.c (sim_core_map_to_str): Delete. + + * sim-core.c (sim_core_attach): Handle a generic number of maps - + up to nr_maps, not just access_* maps. + + * sim-profile.h (struct PROFILE_DATA): Track nr_maps different + maps. + + * sim-profile.c (profile_print_core): Make map unsigned. Iterate + over nr_maps not sim_core_nr_maps. + + * sim-events.h, sim-events.c (sim_events_watch_core): Change + core_map argument to unsigned. + (struct _sim_core): Ditto for struct member core_map. + + * sim-core.h (nr_sim_core_maps, sim_core_*_map): Delete + + * sim-basics.h (access_io, access_*_io): Define. + (map_read, map_write, map_exec, map_io): Define. + + * sim-core.c, sim-core.h (sim_core_attach): Replace argument + attach with more generic mapmask. + (sim_core_{read,write}_*): Change map argument to unsigned. + + * sim-core.c (sim_core_uninstall, sim_core_attach, + sim_core_detach): Iterate over nr_maps instead of + sim_core_nr_maps. + + * sim-break.c (insert_breakpoint): Write breakpoints to exec_map + instead of the write_map. + (remove_breakpoint): Ditto. + + * genmloop.sh (engine_resume_full): Replace sim_core_*_map + with read_map, write_map, exec_map resp. + + * cgen-mem.h (DECLARE_GETMEM, DECLARE_SETMEM, DECLARE_GETIMEM): + Ditto. + + * cgen-utils.c (sim_disassemble_insn): Ditto. + + * sim-hrw.c (sim_write, sim_write): Ditto. + + * sim-utils.h, sim-utils.c (access_to_str, map_to_str, + transfer_to_str): New functions. + +Mon Mar 9 12:50:59 1998 Doug Evans + + * sim-base.h (sim_state_base): New member environment. + (STATE_ENVIRONMENT): New macro. + * sim-config.c (current_environment): Delete. + (sim_config_default): New function. + (sim_config): Set STATE_ENVIRONMENT, not current_environment. + * sim-config.h (current_environment,CURRENT_ENVIRONMENT): Delete. + (sim_config_default): Add prototype. + * sim-module.c (sim_pre_argv_init): Call sim_config_default. + * sim-options.c (standard_option_handler, case OPTION_ENVIRONMENT): + Set STATE_ENVIRONMENT, not current_environment. + +Mon Mar 9 11:59:03 1998 Jim Wilson + + * sim-fpu.c (NR_GUARDS64): Change NR_PAD32 to NR_PAD64. + +Tue Mar 3 10:53:05 1998 Andrew Cagney + + * sim-types.h (SIGNED32, SIGNED64): Pacify GCC. + + * sim-alu.h (ALU64_BEGIN): Make alu64_r unsigned. + +Mon Mar 2 10:20:06 1998 Doug Evans + + * Make-common.in (TAGS): Make smarter. + * Makefile.in (TAGS): Ditto. + +Fri Feb 27 19:09:57 1998 Doug Evans + + * sim-module.c (*): Fix typos in assertion tests. + +Sat Feb 28 13:54:10 1998 Andrew Cagney + + * sim-module.c (sim_pre_argv_init): String passed to asprintf + can't be constant. + + * sim-options.c (sim_parse_args): Ditto. + (sim_args_command): Return OK, instead of nothing, for an empty + command. + +Fri Feb 27 13:29:13 1998 Andrew Cagney + + * sim-profile.c (profile_info): Rename from profile_print. Drop + misc and misc_cpu callback arguments. Use + PROFILE_INFO_CPU_CALLBACK and STATE_PROFILE_INFO_CALLBACK instead. + (profile_install): Install profile_info function. + + * sim-profile.h (PROFILE_INFO_CPU_CALLBACK, + STATE_PROFILE_INFO_CALLBACK): Define. + (struct PROFILE_DATA): Add field info_cpu_callback. + (profile_print): Delete function. + + * sim-base.h (STATE_MODULES): Define. Replace individual + STATE_*_LIST with single struct module_list. + + * sim-module.h (MODULE_INFO_FN, MODULE_INFO_LIST): Declare. + (struct module_list): Declare. + + * sim-module.h, sim-module.c (sim_module_add_info_fn, + sim_module_info): New functions. + (sim_module_install): Clean up module data structures. + + * sim-info.c (sim_info): New file. New function. Call + sim_module_info. + + * Make-common.in (sim-info.o): Define rule. + (SIM_NEW_COMMON_OBJS): Add sim-info.o. + + +Fri Feb 27 18:26:16 1998 Doug Evans + + * sim-base.h (sim_cpu_base): New members name, options. + (sim_cpu_lookup): Add prototype. + * sim-module.c (sim_pre_argv_init): Provide default names for cpus. + * sim-options.h (DECLARE_OPTION_HANDLER): New argument `cpu'. + (sim_add_option_table): Update prototype. + * sim-options.c (sim_add_option_table): New argument `cpu'. + (standard_option_handler,standard_install): Update. + (sim_parse_args): Handle cpu specific options. + (print_help): New static function. + (sim_print_help): Call it. Print cpu specific options. + (find_match): New static function. + (sim_args_command): Call it. Handle cpu specific options. + * sim-utils.c (sim_cpu_lookup): New function. + * sim-memopt.c (memory_option_handler): Update. + (sim_memopt_install): Update. + * sim-model.c (model_option_handler): Update. + (model_install): Update. + * sim-profile.c (profile_option_handler): Update. + (profile_install): Update. + * sim-trace.c (trace_option_handler): Update. + (trace_install): Update. + * sim-watch.c (watchpoint_option_handler): Update. + (sim_watchpoint_install): Update. + * cgen-scache.c (scache_option_handler): Update. + (scache_install): Update. + +Wed Feb 25 11:00:26 1998 Doug Evans + + * Make-common.in (check): Run `make check' in testsuite dir. + +Wed Feb 25 14:40:24 1998 Andrew Cagney + + * sim-trace.c (trace_result0): New function. + + * sim-trace.h (TRACE_FP_*, TRACE_FPU_*): Rename TRACE_FPU_* + macro's to TRACE_FP_*. TRACE_FPU_* should be defined and used when + tracing sim_fpu variables. + (TRACE_ALU_RESULT0): Define. + (TRACE_FP_RESULT_WORD): Define. + (TRACE_FP_INPUT_WORD1): Define. + + * sim-fpu.c, sim-fpu.h (sim_fpu_max32, sim_fpu_max64, sim_fpu_one, + sim_fpu_two): New constants. + (sim_fpu_op1, sim_fpu_op2): New types. + (struct _sim_fpu): Delete member result. Re-order other members. + (sim_fpu_sign, sim_fpu_exp): New functions. + (sim_fpu_max, sim_fpu_min): new functions. + (EXPMAX32, EXPMAX64, NR_PAD32, NR_PAD64, NR_GUARDS32, NR_GUARDS64, + NORMAL_EXPMAX32, NORMAL_EXPMAX64): Define. + +Tue Feb 24 22:45:39 1998 Doug Evans + + * sim-profile.c (profile_print): Delete duplicate test of + PROFILE_INSN_IDX. + (profile_print_pc): Exit early if data collection not set up. + (profile_print_core): Simplify by calling sim_core_map_to_str. + * sim-core.h (sim_core_map_to_str): Declare. + * sim-core.c (sim_core_map_to_str): Make non-static. + + * genmloop.sh (engine_resume): Update insn_count before exiting. + (engine_resume_full): Keep accurate core profile data. + + * cgen-utils.c (sim_disassemble_insn): Don't use + sim_core_read_aligned_N, it messes up profiling results. + +Mon Feb 23 20:45:57 1998 Mark Alexander + + * nltvals.def: Regenerate with MN10300 additions. + +Tue Feb 24 13:18:42 1998 Andrew Cagney + + * sim-trace.h (TRACE_ALU_RESULT2): Define. + + * sim-trace.h, sim-trace.c (trace_result_word2, + trace_input_word4, trace_result_word4): New function. + +Mon Feb 23 13:08:35 1998 Doug Evans + + * cgen-sim.h (SEM_NEXT_PC): New arg `len'. + + * sim-xcat.h: Delete. + * cgen-mem.h: Delete inclusion of sim-xcat.h. + * cgen-sim.h: Ditto. + * sim-alu.h: Replace sim-xcat.h with symcat.h. + * sim-n-bits.h: Ditto. + * sim-n-core.h: Ditto. + * sim-n-endian.h: Ditto. + +Mon Feb 23 13:19:58 1998 Michael Meissner + + * syscall.c (cb_syscall): Handle short reads, and EOF. + +Tue Feb 24 00:29:57 1998 Andrew Cagney + + * sim-trace.c (print_data): case trace_fmt_fp missing break. Use + sim_fpu to safely print fp_word values. + (print_data): Add trace_fmt_bool and trace_fmt_addr. + (trace_result_bool1, trace_result_addr1): New functions. + (trace_input_bool1, trace_input_addr1): New functions. + + * sim-trace.h (TRACE_FPU_*): Define. + +Mon Feb 23 13:24:54 1998 Andrew Cagney + + * sim-fpu.h (enum sim_fpu_class): Add sim_fpu_class_denorm. + (sim_fpu_fpto, sim_fpu_tofp): Define. + +Fri Feb 20 18:08:51 1998 Andrew Cagney + + * sim-fpu.c (sim_fpu_cmp): New function. + +Wed Feb 18 16:29:21 1998 Doug Evans + + * cgen-utils.h (sim_disassemble_insn): Use CGEN_INSN_BITSIZE + instead of abuf->length. + * sim-trace.c (trace_options): Have -t only trace a few useful things. + (set_trace_option_mask): Renamed from set_trace_options. + (set_trace_option): New function. + (trace_option_handler): Update calls to set_trace_option{,_mask}. + * sim-trace.h (TRACE_USEFUL_MASK): New macro. + +Wed Feb 18 12:42:15 1998 Andrew Cagney + + * sim-basics.h: Declare struct _sim_fpu. + +Tue Feb 17 16:27:46 1998 Andrew Cagney + + * sim-trace.h (TRACE_ALU_INPUT*, TRACE_ALU_RESULT): Define. + (trace_prefix, trace_input*, trace_result*): Declare. + (trace_one_insn): Change declaration, assume trace_prefix called. + (trace_generic): Like trace_one_insn. + (TRACE_ALU_IDX, TRACE_*_IDX): Change #define's to enum. + (TRACE_alu, TRACE_[a-z]*): Update. + + * sim-trace.c (trace_prefix, trace_input*, trace_result*, + trace_insn, save_data, trace_idx_to_str, print_data): New + functions. + (trace_one_insn): Rewrite. + (trace_generic): New function. + +Tue Feb 17 17:27:30 1998 Doug Evans + + * Make-common.in (CGEN_MAIN_SCM): Update. + * aclocal.m4 (USE_MAINTAINER_MODE): New variable. + + * cgen-sim.h (SEMANTIC_CACHE_FN): Delete. + (SEMANTIC_FN): Rewrite declaration. + (DECODE): Update type of semantic_fast member. + ({EX,SEM}_FN_NAME): Have only one version. + * cgen.sh: Support building cpu.c. + * sim-base.h (sim_state_base): Delete conditionals surrounding + member scache_size. + +Tue Feb 10 18:31:49 1998 Andrew Cagney + + * sim-load.c (sim_load_file): Print LMA/VMA according to value + used. + +Tue Feb 10 14:56:23 1998 Ian Carmichael + + * sim-core.c: Add missing prototypes for WITH_DEVICES. + Add missing parameters to device_io calls. + * sim-core.h: Add missing parameters to device_io calls. + +Mon Feb 9 14:48:37 1998 Doug Evans + + * cgen-sim.h (DECODE): Always use switch for `read' for now. + (PAREXEC): Renamed from PARALLEL_EXEC. All uses updated. + (SEMANTIC{,_CACHE}_FN): Fix return type. + * cgen.sh (decode): Add s/@arch@/$arch/. + * genmloop.sh (@cpu@_engine_run): Delete `current_state'. + (engine_resume): Likewise. Make `engine' volatile. Save copy + of cpu pointer in volatile object. Initialize read switch if + -parallel. + +Thu Feb 5 13:27:04 1998 Doug Evans + + * cgen-sim.h (EX_FN_NAME): _exc_ -> _ex_. + (SEM_INSN): New macro. + +Tue Feb 3 16:31:56 1998 Andrew Cagney + + * sim-run.c (sim_engine_run): Assume IMEM is 32 bit. + +Sun Feb 1 16:47:51 1998 Andrew Cagney + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Sun Feb 1 16:16:57 1998 Andrew Cagney + + * sim-types.h (fp_word): New type, define according to + WITH_TARGET_FLOATING_POINT_BITSIZE. + + * aclocal.m4 (default_sim_floating_point_bitsize): Add + configuration of size of floating point registers. + +Sun Feb 1 14:02:31 1998 Andrew Cagney + + * sim-profile.c (profile_print): Only print CPU if other + output is going to appear. + +Sat Jan 31 18:15:41 1998 Andrew Cagney + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Sat Jan 31 18:03:55 1998 Andrew Cagney + + * sim-types.h (address_word): Typedef according to + WITH_TARGET_ADDRESS_BITSIZE. + (signed_cell, unsigned_cell, natural_cell): Ditto using + WITH_TARGET_CELL_BITSIZE. + + * sim-config.h (WITH_TARGET_ADDRESS_BITSIZE): Define. + (WITH_TARGET_CELL_BITSIZE): Define. + (WITH_HOST_WORD_BITSIZE): Delete. + + * sim-config.c (print_sim_config): Update. + + * aclocal.m4 (SIM_AC_OPTION_BITSIZE): Add support for + configuration of address and OpenFirmware cell sizes. + +Fri Jan 30 09:36:33 1998 Andrew Cagney + + * sim-engine.h (sim_engine_run): Add argument nr_cpus. + * sim-run.c (sim_engine_run): Update. + + * sim-engine.h (SIM_ENGINE_HALT_HOOK): Use SET_CPU_CIA instead of + CPU_CIA. + * sim-run.c (sim_engine_run): Ditto. + + * sim-resume.c (sim_resume): Obtain nr_cpus from sim_engine. + (sim_resume): Pass nr_cpus to sim_engine_run. + + * sim-engine.h (struct _sim_engine): Add member nr_cpus. + + * sim-engine.c (sim_engine_init): Hardwire nr_cpus to + MAX_NR_PROCESSORS. + (sim_engine_nr_cpus) sim-engine.c, sim-engine.h: New function + +Thu Jan 29 12:13:01 1998 Doug Evans + + * cgen.sh: Portably read parms past $9. + +Fri Jan 23 14:20:54 1998 Doug Evans + + * Make-common.in (stamp-tvals): New rule. + (targ-vals.h,targ-map.c): Depend on it. + (clean): Remove stamp-tvals. + +Tue Jan 20 21:35:13 1998 Michael Meissner + + * sim-utils.c (sim_state_alloc): #if 0 variable that is only used + in code also #if 0'ed. + +Mon Jan 19 22:26:29 1998 Doug Evans + + * configure: Regenerated to track ../common/aclocal.m4 changes. + * aclocal.m4: Recognize --enable-maintainer-mode. + +Mon Jan 19 12:45:45 1998 Doug Evans + + * cgen-scache.h: Deleted. + * Make-common.in (cgen-run.o,cgen-scache.o): Delete cgen-scache.h dep. + (CGEN_CPU_SCM): Add sim-model.scm. + * cgen-scache.c: Only compile contents if WITH_SCACHE. + (scache_init): Use runtime computed size of SCACHE. + (scache_flush): Likewise. + * cgen-mem.h (GETIMEMU[QHSD]I): Declare. + ([GS]ETT{QI,UQI,HI,UHI,SI,USI,DI,UDI}): Declare. + * cgen-sim.h: Scache support moved here. + (PC): Redo definition. + (ARGBUF,SCACHE,PARALLEL_EXEC): Provide forward decls. + (DECODE): Add parallel execution support. + Only include semantic label members if using switch. + (SWITCH,CASE,BREAK,DEFAULT,ENDSWITCH): Portable computed goto support. + (CGEN_CPU): Delete members exec_state, halt_sigrc, halt_jmp_buf. + (IADDR,CIA,SEM_ARG,EX_FN_NAME,SEM_FN_NAME,RECORD_IADDR,SEM_ARGBUF, + SEM_NEXT_PC,SEM_BRANCH_VIA_{CACHE,ADDR},SEM_NEW_PC_ADDR): Moved here + from cgen-types.h. + (engine_{stop,run,resume,halt,signal}): Delete decls. + * cgen-types.h (CGEN_{XCAT3,CAT3}): Delete. + (argbuf,scache): Delete forward decls. + (STATE): Delete decl. + * cgen-utils.c: Don't include decode.h, mem-ops.h, sem-ops.h. + Include cgen-mem.h, cgen-ops.h. + (engine_halt,engine_signal): Delete. + ({ex,exc,sem,semc}_illegal): Delete. + (sim_disassemble_insn): Result of extract fn is in bits. + * genmloop.sh: Rewrite. + + * cgen-trace.c (trace_insn): Set printed_result_p=0 if not tracing + line numbers. + + * sim-base.h (sim_state_base): Delete member `model'. + (sim_cpu_base): Add member `model'. + * sim-model.h (IMP_PROPERTIES): New type. + (MACH): New members imp_props, models. + (models): Delete decl. + * sim-model.c (set_model): Update. + * sim-profile.c (profile_print_model): Update. + + * sim-utils.c (sim_state_alloc): Delete setting of cpu backlink here. + +Fri Jan 16 12:33:09 1998 Nick Clifton + + * cgen-trace.c (trace_insn): Call CGEN_INSN_MNEMONIC() rather than + CGEN_INSN_SYNTAX(). + +Mon Dec 15 23:17:11 1997 Andrew Cagney + + * configure: Regenerated to track ../common/aclocal.m4 changes. + * config.in: Ditto. + +Mon Dec 15 23:16:03 1997 Andrew Cagney + + * aclocal.m4 (AR): Check for sigaction. + +Thu Dec 4 09:21:05 1997 Doug Evans + + * Make-common.in (sim-core.o): Depend on $(sim_main_headers). + + * sim-config.h (WITH_TREE_PROPERTIES): Define as 0. + * sim-config.c (sim_config): Replace WITH_DEVICES with + WITH_TREE_PROPERTIES. + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Wed Dec 3 17:56:02 1997 Doug Evans + + * Make-common.in (SIM_ENVIRONMENT): New variable. + (CONFIG_CFLAGS): Add it. + * aclocal.m4 (SIM_AC_OPTION_ENVIRONMENT): Handle + --enable-sim-environment option. + * configure: Regenerated. + * sim-config.h (environment support): Rewrite. + * sim-config.c (current_environment): Define as enum, unconditionally. + (current_alignment): Define unconditionally. + (config_environment_to_a): Update. + (config_alignment_to_a): Fix type of argument. Define unconditionally. + (sim_config): Handle environment and alignment determination + unconditionally. Delete sanity checks of current_environment, + unnecessary. + (print_sim_config): Update. + * sim-options.c (STANDARD_OPTIONS enum): Add OPTION_ENVIRONMENT. + (standard_options): Add --environment. + (standard_option_handler): Likewise. + +Fri Nov 28 12:21:25 1997 Andrew Cagney + + * sim-alu.h: Add notes on carry vs borrow for subtraction. + (ALU{,8,16,32,64}ADD): Redefine ADD macro as add overflowing. + (ALU{,8,16,32,64}ADDC): Define - add carrying. + (ALU{,8,16,32,64}SUB): Redefine SUB macro as subtract overflowing. + (ALU{,8,16,32,64}SUBB): Define - subtract borrowing. + (ALU{,8,16,32,64}SUBC): Define - tract carrying. + (ALU{,8,16,32,64}ADD_CA, ALU{,8,16,32,64}ADDC_C): Replace single + argument ADD_CA macro with two argument ADDC_C - add carrying with + carry in. + (ALU{,8,16,32,64}SUB_CA, ALU{,8,16,32,64}SUBC_X): Replace single + argument SUB_CA macro with two argument SUBC_X - subtract + carrying, extended. + (ALU{,8,16,32,64}SUBB_B): Define - subtract borrowing with + borrow-in. + (ALU{,8,16,32,64}NEGC, ALU{,8,16,32,64}NEGB): Define. + +Sun Nov 30 17:40:57 1997 Michael Meissner + + * sim-io.c (sim_io_{syscalls,getstring}): Delete. No longer used. + * sim-io.h (sim_io_syscalls): Delete. + +Fri Nov 28 20:10:09 1997 Michael Meissner + + * syscall.c (cb_syscall): Add missing else, so write to stdout + isn't doubled. + + * sim-alu.h (ALU{,8,16,32,64}_SET_CARRY): Provide macros to import + the carry bit from the CPU's psw. + +Fri Nov 28 11:15:05 1997 Doug Evans + + * gennltvals.sh: Redo syscall support. + * nltvals.def: Regenerated. + +Wed Nov 26 16:49:38 1997 Michael Meissner + + * syscall.c (cb_syscall): If writing to stdout or stderr, flush + the stream immediately. + +Wed Nov 26 12:32:11 1997 Andrew Cagney + + * sim-io.c (sim_io_getstring): Delete unused len2. + (sim_io_syscalls): Ditto for sys_errno. + +Wed Nov 26 11:18:40 1997 Doug Evans + + * syscall.c (cb_syscall): Test CB_SYSCALL struct magic number. + + * Make-common.in (run.o): Depend on remote-sim.h. + (nrun.o,sim-hload.o,sim-hrw.o): Likewise. + (sim-io.o,sim-reason.o,sim-resume.o): Likewise. + +Tue Nov 25 20:12:46 1997 Michael Meissner + + * sim-io.c (sim_io_syscalls): Disable lseek. + +Tue Nov 25 00:12:38 1997 Doug Evans + + * gennltvals.sh: Generate syscall values for d30v. + + * gennltvals.sh: Use libgloss/syscall.h for sparc. + * nltvals.def: Regenerate. + + * callback.c (os_stat): Make 3rd arg a host struct stat ptr. + (os_fstat): Likewise. Validate fd argument. + (cb_host_to_target_stat): Delete big_p arg. If HS arg is NULL, + just compute target stat struct length. + * syscall.c: #include "libiberty.h", , . + (ENOSYS,ENAMETOOLONG): Provide definitions if missing. + (get_string): Return host errno values so they can be properly + translated later. + (cb_syscall): Likewise. + (cb_syscall, cases open,unlink): Use get_path instead of get_string. + (cb_syscall, case read): Use read_stdin for file descriptor 0. + (cb_syscall, case write): Use write_stderr for file descriptor 2. + (cb_syscall): Add cases for lseek, unlink, stat, fstat, time. + (get_path): New function. + +Mon Nov 24 18:56:07 1997 Michael Meissner + + * sim-io.c (sim_io_syscalls): New function to provide system call + emulation. Provide exit, open, close, read, write, lseek, and + unlink. + (sim_io_getstring): New function to return a string from a + simulated memory location. + + * sim-io.h (sim_io_syscalls): Add declaration. + +Mon Nov 24 12:09:59 1997 Doug Evans + + * sim-core.c (sim_core_signal): Fix spelling error in message. + + * sim-hrw.c (sim_read): Use read map, not write map. + + * Make-common.in (all): Add .gdbinit. + * gdbinit.in: Add dump command. + + * sim-model.c (model_options): Use '\0' for `shortopt'. + + * sim-trace.c (trace_option_handler): Set state trace file + for --trace-file in addition to cpu's values. + (trace_vprintf): If cpu == NULL, try state's trace file. + (trace_options): Reorganize table, reword some descriptions. + +Sun Nov 23 10:57:00 1997 Andrew Cagney + + * sim-fpu.c (sim_fpu_abs, sim_fpu_neg, sim_fpu_inv), sim-fpu.h: + New functions. + +Sat Nov 22 19:16:54 1997 Andrew Cagney + + * sim-reason.c (sim_stop_reason): For sim_signalled, return the + signal untranslated, document problem with this. + + * nrun.c (main): Check for a prog name of `*step'. If present, + step the simulator instead of allowing it to run free. + + * sim-signal.c (SIGQUIT): Define on _MSC_VER hosts. + + * Make-common.in (sim_main_headers): Add sim-signal.h. + +Fri Nov 21 09:32:32 1997 Andrew Cagney + + * sim-signal.c (sim_signal_to_host): Return 0 for SIM_SIGNONE. + +Thu Nov 20 20:35:20 1997 Andrew Cagney + + * sim-signal.h: Start simulator signals at 64 so that host signal + numbers can be detected and reported. + + * sim-signal.h (SIM_SIGFPE), sim-signal.h: Add signal. + +Wed Nov 19 12:02:41 1997 Doug Evans + + * callback.c (cb_host_to_target_stat): Fix return values. + + * cgen-sim.h (enum_signal_type): Delete. + (engine_signal): Update prototype. + * cgen-utils.c: Don't include . + (sim_signal_to_host): Delete, lives in sim-signal.c now. + (engine_signal): Update. + + * sim-utils.c (sim_state_alloc): Call SIM_STATE_ALLOC if defined. + (sim_state_free): Call SIM_STATE_FREE if defined. + + * sim-module.c (sim_module_install): Don't leave any modules + installed if one fails to install. + +Wed Nov 19 13:25:48 1997 Michael Meissner + + * sim-options.c: Don't include ../libiberty/alloca-conf.h any + more, since alloca is not used in this file. + + * sim-alu.h (ALU{32,64}_*): Rewrite 32 and 64 bit ALU support to + correctly set the carry and overflow bits for those types. + (ALU{8,16,32,64}_{ADD,SUB}_CA): Take VAL argument to add along + with carry, so carry is correct after doing both adds. + (ALU*): Space out '\' to make it easier to read. + +Tue Nov 18 15:53:45 1997 Doug Evans + + * sim-core.c (sim_core_signal): Use sim_stopped instead of + sim_signalled. + + * sim-signal.c, sim-signal.h: New files. + * Make-common.in (sim-signal.o): Add rule for. + (SIM_NEW_COMMON_OBJS): Add sim-signal.o. + * sim-abort.c: Don't include . + * sim-basics.h: #include "sim-signal.h". + * sim-break.c: Don't include . + (sim_handle_breakpoint): Replace SIGTRAP with SIM_SIGTRAP. + * sim-core.c: Don't include . + (SIGBUS): Delete definition. + (sim_core_signal): Replace SIGSEGV,SIGBUS with SIM_SIGSEGV,SIM_SIGBUS. + * sim-engine.c: Don't include . + (sim_engine_abort): Replace SIGABRT with SIM_SIGABRT. + * sim-reason.c (sim_stop_reason): Call sim_signal_to_host. + * sim-resume.c: Don't include . + (SIGTRAP): Delete definition. + (has_stepped): Replace SIGTRAP with SIM_SIGTRAP. + * sim-stop.c: Don't include . + (control_c_simulation): Replace SIGINT with SIM_SIGINT. + * sim-watch.c: Don't include . + (handle_watchpoint): Replace SIGINT with SIM_SIGINT. + + * Make-common.in (SIM_NEW_COMMON_OBJS): New variable. + + * sim-base.h (CIA_ADDR): Provide default definition. + * sim-core.c (sim_core_signal): Use CIA_ADDR to fetch value. + * sim-break.c (sim_handle_breakpoint): Likewise. + +Mon Nov 17 14:15:31 1997 Doug Evans + + * Make-common.in (srccom): New variable. + + * Make-common.in (DEP, COMMON_DEP_CFLAGS): Define. + (LIB_OBJS): Add syscall.o. + (gentmap): Pass $(NL_TARGET) to $(CC). + (syscall.o): Add rule for. + (sim_main_headers): Add $(SIM_EXTRA_DEPS). + (sim-bits.o): Depend on $(sim-n-bits_h). + (sim-load.o): Depend on callback.h. + + * Make-common.in (cgen-*.o): Update dependencies, mem-ops.h renamed to + cgen-mem.h, sem-ops.h renamed to cgen-ops.h. + * cgen-mem.h, cgen-ops.h: New files. + + * aclocal.m4 (--enable-sim-scache): Pass -DWITH_SCACHE=0 for "=no". + + * Makefile.in (nltvals.def): Depend on gennltvals.sh. + Rewrite build rule. + * callback.c: #include string.h or strings.h. + #include sys/types.h and sys/stat.h. + (cb_init_syscall_map,cb_init_errno_map,cb_init_open_map): Declare. + (os_get_errno,os_open): Update. + (os_stat,os_fstat): New functions. + (os_init): Initialize syscall_map, errno_map, open_map. + (default_callback): Add entries for os_stat, os_fstat, syscall_map, + errno_map, open_map, signal_map, stat_map. + (cb_read_target_syscall_maps): New function. + (cb_target_to_host_syscall): New function. + (cb_host_to_target_errno): Renamed from host_to_target_errno. + (cb_target_to_host_open): Renamed from target_to_host_open. + (store): New function. + (cb_host_to_target_stat): New function. + * syscall.c: New file. + * gentmap.c (sys_tdefs): New global. + (gen_targ_vals_h): Output target syscall numbers. + (gen_targ_map_c): Update. Output target syscall translation map. + * gentvals.sh: New first argument `target'. Preface table with + #ifdef NL_TARGET_$target if non-null target passed. + * gennltvals.sh: New file. + * nltvals.def: Regenerated. + +Fri Nov 14 11:33:34 1997 Andrew Cagney + + * sim-n-core.h (sim_core_read_unaligned_N): Return static + sim_core_dummy_M. + (sim_core_dummy_M): Declare. + +Wed Nov 12 18:16:15 1997 Andrew Cagney + + * sim-core.c (sim_core_signal): Print the address of the + instruction. + +Thu Nov 13 11:49:41 1997 Doug Evans + + * sim-base.h (sim_state_base): Move `magic' to end of struct. + + * sim-base.h (sim_state_base): Add member trace_data. + (STATE_TRACE_DATA): New macro. + * sim-trace.h (TRACE_DEBUG_IDX,TRACE_debug): New macros. + ({WITH_,}TRACE_DEBUG_P): New macros. + (STATE_TRACE_FLAGS,STRACE_P,STRACE_DEBUG_P): New macros. + (_sim_cpu): Delete forward reference. + (debug_printf): Update. + * sim-trace.c (OPTION_TRACE_DEBUG): Define. + (trace_options): Add --trace-debug. + (set_trace_options): Handle it. + (trace_option_handler): Likewise. + (trace_install): Init state trace_data struct. + (trace_uninstall): Close state trace file. + * sim-events.c (ETRACE): Only print source file and line number if + --trace-debug. + * sim-n-core.h (sim_core_trace_M): Likewise. + + * sim-core.c (sim_core_signal): Add missing "\n" in message. + +1997-11-13 Felix Lee + + * sim-n-core.h (sim_core_read_unaligned_N): illegal empty + initializer. + * sim-types.h (unsigned128,signed128): fix typo for MSVC. + +Wed Nov 12 12:18:08 1997 Doug Evans + + * aclocal.m4 (SIM_AC_OPTION_SCACHE): Fix typo. + + * Make-common.in (BUILT_SRC_FROM_COMMON): Remove files no longer + built this way. + (sim-config.o): Remove non-existent $(sim-nconfig_h) dependency. + (clean): Don't delete $(BUILT_SRC_FROM_COMMON) if building in + source tree. + +Tue Nov 11 13:28:02 1997 Andrew Cagney + + * sim-events.c (sim_events_process): Re-compute the time - + update_time_from_event - as each event is processed. Reverses + previous change. + +Fri Nov 7 00:37:36 1997 Andrew Cagney + + * callback.c (os_poll_quit): Replace _WIN32 with _MSC_VER. + +Fri Nov 7 00:37:36 1997 Andrew Cagney + + * sim-events.c (sim_events_process): Delete redundant call to + update_time_from_event. + (sim_events_slip): Always decrement time_from_event. + (sim_events_tick, sim_events_deschedule, update_time_from_event): + Delete assertion that time_from_event >=0 when work in queue, no + longer applicable. + +Thu Nov 6 12:06:46 1997 Andrew Cagney + + * sim-options.c (STANDARD_OPTIONS): Change OPTION_* to an enum. + (standard_option_handler): Update. + + * sim-options.h: Clarify documentation. + (OPTION_LONG_ONLY_P): Delete definition. + (OPTION_VALID_P): Define. + + * sim-options.c (sim_print_help): Allow short only options. + (sim_parse_args): Ditto. + (sim_args_command): Skip short only options. + (sim_parse_args): Allocate space for NUM_OPTS not just 256. Make + separate entries for short and long options in the HANDLERS and + ORIG_VAL tables. + (sim_parse_args): Disable argument permutation. + +Wed Nov 5 13:40:31 1997 Andrew Cagney + + * sim-core.h (DECLARE_SIM_CORE_WRITE_N. DECLARE_SIM_CORE_READ_N): + Add argument M, size of data type. + (sim_core_read_misaligned_3, sim_core_write_misaligned_3): + Declare, ditto for 5, 6 & 7 byte transfers. + (sim_core_write_unaligned_1, sim_core_write_unaligned_1): Define + as aligned variant. + + * sim-n-core.h (sim_core_trace_M): Rename from + sim_core_trace_N. Add nr_bytes argument. Replace transfer argument + with transfer type. Print transfer direction. Handle 1 and 2 byte + transfers. + (sim_core_read_unaligned_N, sim_core_write_unaligned_N): Trace + unaligned accesses. + (unsigned_M, T2H_M, H2T_M): Rename from unsigned_N, T2H_N, H2T_N. + Update all functions. + + * sim-core.c: Generate functions starting with 16 not 1. + (sim_core_read_unaligned_3): Generate. Ditto for 3 byte write and + all 5, 6 & 7 byte transfers. + + * sim-n-core.h (sim_core_read_misaligned_N, + sim_core_write_misaligned_N): Implement. + +Mon Nov 3 15:03:04 1997 Andrew Cagney + + * sim-endian.h (U16_8): Implement + + * sim-endian.c (sim_endian_split_16, sim_endian_join_16): New functions + + * sim-endian.h (VL8_16, VH8_16): Implement. + + * sim-memopt.c (memory_option_handler): Typecast 64bit value to + long in printf. + (memory_option_handler): Only zalloc modulo bytes when non-zero. + (memory_option_handler): Skip comma in alias address list + +Fri Oct 31 13:03:33 1997 Andrew Cagney + + * sim-memopt.c (do_memopt_add, do_memopt_delete): Add level and + space params. + (parse_size, parse_addr): New functions + (memory_option_handler, memory_options): Parse address & size + using new functions. Pass level, space, modulo to do_memopt_add & + do_memopt_del. + + * sim-memopt.h (struct _sim_memopt): Add level & space fields. + + * sim-core.h (sim_core_arrach, sim_core_detach): Replace + `attach_type attach' argument with `unsigned level' argument. + Document. + + * sim-core.c (new_sim_core_mapping, sim_core_map_attach, + sim_core_attach): Replace argument attach with level. Update + verification of arguments. + (sim_core_map_detach, sim_core_detach): Replace argument attach + with level. + + * sim-basics.h (enum _attach_type): Delete. + +Thu Oct 30 13:45:00 1997 Doug Evans + + * sim-core.h (sim_core_write_8): Define. + +Tue Oct 28 12:29:22 1997 Andrew Cagney + + * sim-bits.h: Document ROTn macro. + + * sim-endian.h (H2T): Handle 16 byte variables. + + * sim-n-core.h (sim_core_read_unaligned_N): Return a dummy when an + error. + + * sim-core.c: Do not generate sim_core_*_word. + + * sim-n-core.h (sim_core_trace_N): Add line_nr argument. + (sim_core_write_aligned_N, sim_core_read_aligned_N): Update. + + * sim-core.h (sim_core_read_unaligned_word, + sim_core_read_aligned_word, sim_core_read_word, + sim_core_write_unaligned_word, sim_core_write_aligned_word, + sim_core_write_word): Change to macros that map onto sim_core_*_N. + +Mon Oct 27 11:25:10 1997 Doug Evans + + * sim-n-endian.h: Add TAGS entrys for 16 byte versions. + + * sim-endian.h: Disable 16 byte support. + +Mon Oct 27 12:00:48 1997 Andrew Cagney + + * sim-endian.c (_SWAP_16): Define. Generate 126 bit swap code. + + * sim-n-core.h (sim_core_trace_N): New function. + (sim_core_read_aligned_N, sim_core_write_aligned_N): Use, + (sim_core_read_unaligned_N): Do not retyrn bogus value wden error. + + * sim-endian.h: Add 128 bit variant. + + * sim-core.h, sim-core.c: Add 128 bit variant. + + * sim-types.h: Add signed128 and unsigned128 types using a struct. + +Fri Oct 24 11:33:07 1997 Andrew Cagney + + * sim-events.c (sim_events_process): Clear events->work_pending. + (sim_events_tickn, sim_events_tick): Accumulate, instead of + setting, nr_ticks_to_process. + (sim_events_preprocess): Allow nr_ticks_to_process to be non-zero + when the event queue isn't next. + + * sim-events.h, sim-events.c (sim_events_slip): New function. + +Wed Oct 22 14:18:38 1997 Andrew Cagney + + * sim-hload.c (sim_load): Pass lma_p==0 and do_load=sim_load. + + * sim-utils.h, sim-load.c (sim_load_file): Add lma_p and do_load + arguments. + +Tue Oct 21 18:37:57 1997 Doug Evans + + * nrun.c (main): Remove useless test of name != NULL. + Exit if bfd_openr fails. Call bfd_check_format after bfd_openr. + +Tue Oct 21 10:42:38 1997 Andrew Cagney + + * sim-fpu.c (EXPMAX): Type is unsigned. + (MIN_INT, MAX_INT): Type is signed64. + (i2fpu): Type of val is signed64. + +Tue Oct 21 10:42:38 1997 Andrew Cagney + + * sim-profile.h (PROFILE_PC_BUCKET_SIZE): Treat a shift of zero as + a bucket size of zero. + + * sim-profile.c (OPTION_PROFILE_PC_GRANULARITY, + OPTION_PROFILE_PC): Define. + (profile_option_handler): Add support for --profile-pc and + --profile-pc-granularity options. + (profile_pc_init): When possible, compute nr buckets from bucket + size. + + * sim-profile.c (profile_pc_init): Align the profile-pc end + address with the profile-pc bucket size. + + * sim-profile.h (PROFILE_PC_NR_BUCKETS): Rename PROFILE_PC_SIZE to + something less ambiguous. + (PROFILE_PC_BUCKET_SIZE): Ditto for PROFILE_PC_SAMPLE_SIZE. + + * sim-profile.c (profile_pc_cleanup): New function. Move + profile_pc_uninstall code to here. + (profile_pc_uninstall): Call. + (profile_pc_init): Call. + +Mon Oct 20 17:23:58 1997 Andrew Cagney + + * sim-profile.c (profile_print_pc): Dump pc profile to dmon.out + file using BSD gprof format. + + * sim-bits.h (LSBIT, MSBIT, BIT): Force result to type + unsigned_word. + (LSBIT8, LSBIT16, LSBIT32, LSBIT64, MSBIT8, MSBIT16, MSBIT32, + MSBIT64): Force result to unsignedN. + +Thu Oct 16 11:38:56 1997 Andrew Cagney + + * sim-alu.h (ALU16_BEGIN, ALU32_BEGIN, ALU64_BEGIN): Drop opening + brace from macro. + (ALU8_BEGIN, ALU8_SET, ALU8_ADD, ALU8_SUB, ALU8_NEGATE): Define. + (ALU16_ADD, ALU16_SUB, ALU16_NEGATE): Simplify arrithmetic. + (ALU32_ADD, ALU32_SUB, ALU32_NEGATE): Simplify arrithmetic. + (ALU64_ADD, ALU64_SUB, ALU64_NEGATE): Simplify arrithmetic. + +Wed Oct 15 09:24:19 1997 Andrew Cagney + + * sim-core.h (struct _sim_core_mapping): Change free_buffer to + type void*. + + * sim-core.c (sim_core_uninstall, new_sim_core_mapping, + sim_core_map_attach, sim_core_map_detach): Change free_buffer to + type void*. + (sim_core_attach): Rename buffer_freed to free_buffer, type + void*. Ensure that allocated buffer is alligned according to + region's address. + +Mon Oct 13 11:34:50 1997 Andrew Cagney + + * sim-alu.h (ALU64_HAD_OVERFLOW): Define. + (ALU64_SUB): Define. + + * Make-common.in (all): Build SIM_EXTRA_ALL first. + (.gdbinit): Remove dependencies, generate once per build. + +Tue Oct 14 19:20:09 1997 Andrew Cagney + + * sim-n-core.h (sim_core_read_aligned_N, + sim_core_write_aligned_N): Make xaddr param type address_word not + unsigned_word. + +Fri Oct 3 09:49:18 1997 Andrew Cagney + + * sim-fpu.h, sim-fpu.c: Rewrite. Change sim_fpu object to an + unpacked floating point struct. Pass sim_fpu object by reference. + Add preliminary support for rounding modes. + +Fri Oct 3 09:28:00 1997 Andrew Cagney + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Thu Oct 2 19:43:52 1997 Andrew Cagney + + * aclocal.m4 (sim-bitsize): Fix typo, WITH_TARGET_WORD_BITSIZE not + WITH_TARGET_BITSIZE. + +Thu Sep 25 23:20:20 1997 Felix Lee + + * sim-profile.c (profile_print_core): label needs empty statement. + +Thu Sep 25 11:20:47 1997 Stu Grossman + + * sim-break.c (sim_set_breakpoint sim_clear_breakpoint): Use ZALLOC + and zfree instead of xmalloc and free. Prevents warnings. + +Wed Sep 24 17:38:57 1997 Andrew Cagney + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Wed Sep 24 17:23:31 1997 Andrew Cagney + + * Make-common.in (SIM_BITSIZE): Assign from configured value. + (CONFIG_CFLAGS): Add SIM_BITSIZE. + + * aclocal.m4 (--enable-sim-bitsize): Developer option for + controling the bitsize/msb of the target. + +Wed Sep 24 17:41:40 1997 Stu Grossman + + * Make-common.in: New files sim-break.c, sim-break.h. + * sim-base.h: Add point to breakpoint list to sim_state_base. + * sim-break.c sim-break.h: New modules that implement intrinsic + breakpoint support. + * sim-module.c: Add breakpoint module. + +Tue Sep 23 00:26:39 1997 Felix Lee + + * sim-events.c (SIM_EVENTS_POLL_RATE): poll more often than once + an hour. + * sim-n-core.h (WITH_XOR_ENDIAN): MSVC barfs on + if (0) { 1 % 0; } + * sim-core.c (sim_core_xor_write_buffer): WITH_XOR_ENDIAN + 1. + (SIGBUS) define for Windows. + * sim-trace.c (trace_printf,debug_printf): added ALMOST_STDC. + * sim-resume.c: define SIGTRAP for windows. + * sim-xcat.h: use token pasting if ALMOST_STDC. + +Tue Sep 23 11:04:38 1997 Andrew Cagney + + * Make-common.in (SIM_SCACHE, SIM_DEFAULT_MODEL): Assign + configured values. + (CONFIG_CFLAGS): Add same. + +Mon Sep 22 17:20:27 1997 Felix Lee + + * sim-types.h (SIGNED64): ##i64 when _MSC_VER, not _WIN32. + (SIGNED32): use ##i32. + +Tue Sep 23 11:04:38 1997 Andrew Cagney + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Tue Sep 23 10:07:47 1997 Andrew Cagney + + * aclocal.m4 (sim-endian): Simplify logic determining [default] + endian of target. + + * Make-common.in (SIM_WARNINGS, SIM_ALIGNMENT, SIM_ENDIAN, + SIM_HOSTENDIAN, SIM_RESERVED_BITS, SIM_ASSERT, SIM_FLOAT, + SIM_HARDWARE, SIM_INLINE, SIM_PACKAGES, SIM_REGPARM, SIM_SMP, + SIM_STDCALL, SIM_XOR_ENDIAN): Assign configured values. + (CONFIG_CFLAGS): Add same. + + * aclocal.m4: Perform AC_SUBST on optional options. + +Mon Sep 22 11:46:20 1997 Andrew Cagney + + * sim-config.h (WITH_DEFAULT_ALIGNMENT): Don't hardwire any alignment. + + * sim-options.c (standard_option_handler): Typo in warning message. + + * sim-base.h (STATE_MODEL): Make conditional on SIM_HAVE_MODEL. + + * sim-profile.c (profile_print_insn): Check 0 .. MAX_INSN for any + insn count. Make count conditional on there being a valid + INSN_NAME. + (profile_pc_init): Make default PC profile frequency an arbitrary + 256. + + * sim-base.h: Ditto. + + * sim-profile.h (WITH_PROFILE_MODEL_P): Only enable modeling when + SIM_HAVE_MODEL. + + * sim-model.h (struct MACH): Depreciate, to be replaced by bfd + archure struct. + +Mon Sep 22 11:46:20 1997 Andrew Cagney + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Mon Sep 22 11:45:00 1997 Andrew Cagney + + * aclocal.m4 (sim_alignment): Simplify logic for selecting the + configured alignment. + +Fri Sep 19 17:45:25 1997 Andrew Cagney + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Fri Sep 19 17:26:14 1997 Andrew Cagney + + * sim-config.c (sim_config): Check for default alignment. + + * sim-options.c (standard_option_handler): Add alignment option. + + * aclocal.m4 (sim_alignment): Allow configuration of hardwired and + default alignment requirements on memory accesses. + +Fri Sep 19 11:51:35 1997 Jeffrey A Law (law@cygnus.com) + + * sim-load.c (sim_load_file): Return failure if the executable + had no loadable sections. + +Wed Sep 17 13:33:28 1997 Andrew Cagney + + * sim-events.c (ETRACE): Use trace_printf not sim_io_printf for + trace output. + + * sim-core.c (sim_core_signal): When bad access halt simulator + SIGSEGV / SIGBUS instead of aborting. + (signal.h): Include. + + * sim-watch.c (sim_watchpoint_install): Handler for watchpoint + options was missing. + + * sim-bits.h (MOVED): Define + +Wed Sep 17 10:33:28 1997 Andrew Cagney + + * sim-alu.h (ALU32_HAD_OVERFLOW): Pacify GCC, Use MSBIT instead of + BIT. + + * sim-bits.h (LSBIT, MSBIT): Check for overflow of shift value. + + * sim-bits.c: Add 8 bit versions of bit macros. + + * sim-bits.h: Ditto. + +Tue Sep 16 16:15:16 1997 Andrew Cagney + + * sim-bits.c (LSSEXT, MSSEXT): Replace SEXT. + (LSINSERTED, MSINSERTED): Ditto for INSERTED. + + * sim-n-bits.h (MSSEXTn, LSSEXTn): Replace SEXTn. + (LSINSERTDn, MSINSERTEDN): Ditto for INSERTEDn. + + * sim-bits.h (SEXT*): Define as MSEXT/LSEXT. + (INSERTED*): Ditto for LSINSERTED/MSINSERTED. + +Mon Sep 15 17:36:15 1997 Andrew Cagney + + * aclocal.m4 (SIM_AC_COMMON): Add optional config.h file argument. + configure.in: Output to cconfig.h instead of config.h. + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Mon Sep 15 15:39:28 1997 Andrew Cagney + + * sim-utils.c (sim_analyze_program): Set STATE_ARCHITECTURE from + BFD if known. + +Tue Sep 9 21:46:46 1997 Felix Lee + + * callback.c (os_write): divert stdout and stderr to their + respective hooks. + +Thu Sep 11 10:08:48 1997 Andrew Cagney + + * sim-profile.c (profile_print_speed): Call + sim_events_elapsed_time instead of PROFILE_EXEC_TIME for moment. + + * sim-events.c (sim_events_elapsed_time): New function return nr + host MS consumed by the simulator. + (sim_watch_valid): Use. + + * sim-module.c (modules): Install sim_events very very early. + + * sim-profile.c (profile_print): Call profile_print_pc. + (print_bar): + (profile_pc_init): New function, set up processor for PC + profiling. + (profile_print_pc): New function, print a PC profile. + (profile_pc_event): New function, sample PC. + + * sim-profile.h (PROFILE_PC_COUNT, PROFILE_PC_START, + PROFILE_PC_END, PROFILE_PC_SHIFT, PROFILE_PC_SAMPLE_SIZE): Add to + profile struct. + + * sim-options.c (sim_print_help): Pacify GCC. + + * sim-n-core.h (sim_core_read_aligned_N, + sim_core_write_aligned_N): Add un-conditional profile call. + (sim_core_read_unaligned_N, sim_core_write_unaligned_N): Add + profile call when aligned read/write isn't used. + + * sim-base.h: Include sim-profile, sim-model after sim-core & + sim-events allow sim-core to define useful values. + + * sim-profile.c (OPTION_PROFILE_CORE): Define. + (profile_option_handler, profile_options): Add support for + --profile-core option. + (print_bar): Include when core profiling. + (profile_print_core): New function, print core profile. + + * sim-config.c (print_sim_config): Print profile status. + + * sim-profile.h (PROFILE_NEXT_IDX, PROFILE_core, + WITH_PROFILE_PC_P): Define. + (PROFILE_CORE_COUNT): Count each core-map/size separatly. + (PROFILE_COUNT_CORE): Define. + +Thu Sep 11 08:44:52 1997 Andrew Cagney + + * sim-watch.c (handle_watchpoint): Pass a char** index into the + interrupt_names array as the data. + (sim-watch.h): Document. + +Wed Sep 10 16:15:22 1997 Andrew Cagney + + * sim-options.c (sim_print_help): When the doc string is to long + word wrap it. + + * sim-watch.c (sim_watchpoint_install): Use option.doc_name so + that only the first few the watch options are listed. Generate + meanginful usage messages. + + * sim-options.h (struct OPTION): Clarify use of doc_name field + +Wed Sep 10 13:23:24 1997 Andrew Cagney + + * sim-options.c (OPTION_ARCHITECTURE_INFO): New option. + (standard_option_handler): Handle --architecture-info. + +Tue Sep 9 21:46:46 1997 Felix Lee + + * sim-core.h (sim_cpu_core): [WITH_XOR_ENDIAN + 1], to avoid + illegal zero-sized array. + * sim-core.c (sim_core_xor_read_buffer): same. + +Tue Sep 9 11:20:35 1997 Doug Evans + + * nltvals.def: Regenerate. + +Tue Sep 9 02:10:36 1997 Andrew Cagney + + * sim-fpu.c (DP_FRACHIGH2): Define LL using SIGNED64. + +Mon Sep 8 12:22:20 1997 Andrew Cagney + + * sim-bits.c (MASKED): Delete. + (EXTRACTED): Delete. + (LSEXTRACTED, MSEXTRACTED): New functions. + + * sim-n-bits.h (MASKEDn): Delete, define as MSMASKED or LSMASKED. + (MSMASKEDn, LSMASKEDn): Add last argument. + (MSMASK*): Ditto. + + * sim-bits.h (EXTEND8, EXTEND16): Define. + (EXTRACTED64): Define as 64 bit extract, not 32 bit. + + * sim-run.c (sim_engine_run): Use CPU_CIA macro. + + * sim-engine.h (SIM_ENGINE_HALT_HOOK): Use CPU_CIA to get at + current instruction address. + + * sim-inline.h (*_ENGINE): Define. + +Fri Sep 5 08:39:02 1997 Andrew Cagney + + * sim-core.c (sim_core_attach): Fix checks of modulo/mask. + + * sim-watch.c (delete_watchpoint): Delete by ident and type. + (watch_option_handler): Call delete_watchpoint with ident or type. + (sim_watchpoint_install): Create interrupt specific watchpoint + commands on the fly. + (do_watchpoint_create): New function, create a watch point using + type/int-nr info encoded in the option nr. + (do_watchpoint_info): New function. List active watchpoints. + + * sim-watch.h: Change data structure to a list. + + * sim-memopt.c (memory_option_handler): Require explicit "all" + before deleting all memory regions. + + * sim-utils.c (sim_do_commandf): New function, printf version of + sim_do_command. + + * sim-basics.h (asprintf, vasprintf): Hack, define for CYGWIN32. + + * sim-alu.h (ALU64_ADD): Use explicit MSEXTRACTED64, do not assume + bit endianness. + (SIGNED64, UNSIGNED64): Delete. + (ALU64_ADD): Don't rely on bit endianness. + (ALU64_BEGIN): Define. + + * sim-n-bits.h (MSEXTRACTEDn, LSEXTRACTED): New functions. + (EXTRACTEDn): Delete, define as either LSEXTRACTED or MSEXTRACTED. + + * sim-types.h (SIGNED64, UNSIGNED64): New macros, attach relevant + suffix - u64, LL - to 64 bit constants. + +Thu Sep 4 09:27:54 1997 Andrew Cagney + + * sim-config.c (sim_config): Add assert for SIM_MAGIC_NUMBER. + + * sim-utils.h (NZALLOC): Define - zalloc * N. + + * sim-hrw.c (sim_read, sim_write): New file. Provide generic + implementation of read/write functions. + + * Make-common.in (sim-hrw.o): New target. + + * sim-base.h (STATE_MEMOPT_P): Delete, simulators _always_ add + memory. + + * sim-memopt.c (memory_option_handler): Implement memory-size + command. Implement memory-alias command. Let memory-delete delete + all memory regions. + (add_memopt): New function. Add a memory region. + (do_memopt_delete): New function. Delete a memory region. + + * sim-utils.c (sim_elapsed_time_get): Never return zero. + + * sim-core.c (sim_core_detach): New function. + (sim_core_map_detach): New function. Perform the actual detach. + (sim_core_init): Move initialization code from here. + (sim_core_install): To here. + (sim_core_uninstall): And here. + + * sim-module.c: Add memopt module. + + * sim-base.h (STATE_MEMOPT, STATE_MEMOPT_P): Add memopt to + simulator base type. + + * Make-common.in (sim_main_headers): Add sim-memopt.h + (sim-memopt.o): New target. + + * sim-core.c (sim_core_install): Add core_options to the option + table. + + * sim-watch.c (watch_options): Make --delete-watch a synonym for + --watch-delete. + + * sim-config.h (WITH_MODULO_MEMORY): Define as 0. Update + comments. + + * sim-core.h (struct _sim_core_mapping): Change nr_bytes to type + address_word, add mask member. + + * sim-core.h, sim-core.c (sim_core_attach): Make nr_bytes of type + address_word, allow for 64bit targets in 32bit host. Add modulo + argument. + (sim_core_map_attach): Ditto. + (new_sim_core_mapping): Ditto. + (sim_core_translate): Mask address when modulo memory. + +Wed Sep 3 17:32:54 1997 Doug Evans + + * sim-hload.c (sim_load): Add assert for SIM_MAGIC_NUMBER. + + * gdbinit.in: New file. + * aclocal.m4 (SIM_AC_OUTPUT): Build .gdbinit. + * Make-common.in (distclean): Delete .gdbinit. + (.gdbinit): Add rule for. + * configure: Regenerated to track ../common/aclocal.m4 changes. + + * Make-common.in (cgen-run.o): Add rule for. + +Wed Sep 3 10:08:21 1997 Andrew Cagney + + * sim-resume.c (sim_resume): Suspend/resume the simulator. + + * sim-events.c (sim_watch_valid): Compute total elapsed time from + both resumed and previous elapsed time. + (sim_events_init): Set initial_wallclock and current_wallclock to + zero. + (sim_events_install): Install sim_events_suspend and + sim_events_resume. + (sim_events_watch_clock): Allow for suspended simulator when + computing the time of the clock event. + + * sim-events.h (struct _sim_event): Add resume_wallclock, rename + initial_wallclock to elapsed_wallclock, set both to zero. + (sim_events_init, sim_events_uninstall): Delete prototypes. + + * sim-module.h (MODULE_SUSPEND_FN, MODULE_RESUME_FN): Define types. + + * sim-module.c(sim_module_resume, sim_module_suspend): New + functions. + +Wed Sep 3 10:08:21 1997 Andrew Cagney + + * sim-core.c (sim_core_map_attach): Clarify memory overlap error + message. + +Tue Sep 2 14:57:06 1997 Doug Evans + + * Makefile.in (TAGS): Add support for "/* TAGS: foo */" marker. + * Make-common.in (TAGS): Likewise. + * sim-n-bits.h: Add TAGS comments for all functions. + * sim-n-core.h: Likewise. + * sim-n-endian.h: Likewise. + +Mon Sep 1 10:50:11 1997 Andrew Cagney + + * sim-utils.c (sim_state_alloc): Set CPU backlinks, callback and + kind. + + * sim-base.h (sim_state_alloc): Add callback and kind arguments. + + * sim-base.h (INVALID_INSTRUCTION_ADDRESS): Add default + definition. + +Sat Aug 30 09:47:21 1997 Andrew Cagney + + * sim-fpu.c (DP_GARDMSB, ...): Make unsigned. + (DP_FRACHIGH, DP_FRACHIGH2, ..): Use MSMASK to avoid LL. + +Fri Aug 29 13:37:44 1997 Andrew Cagney + + * sim-core.c (sim_core_map_attach): Cast attach enum to int. + (sim_core_xor_read_buffer, sim_core_xor_write_buffer): Make + nr_transfered and nr_this_transfer unsigned. + + * sim-events.c (sim_events_tickn): N is signed, as limited to + MAXINT. + + * sim-n-endian.h (offset_N): Change size to unsigned. + + * callback.c (os_poll_quit): Add prototypes for kbhit and getkey. + +Fri Aug 29 10:10:53 1997 Andrew Cagney + + * sim-utils.c (sim_copy_argv): Delete, replaced by dupargv. + + * sim-options.c (sim_parse_args): Use dupargv. + +Thu Aug 28 10:36:34 1997 Doug Evans + + * sim-options.c (standard_option_handler): Use xstrdup, not strdup. + +Thu Aug 28 12:09:15 1997 Andrew Cagney + + * sim-base.h (STATE_ARCHITECTURE, STATE_TARGET): Add to simulator + base type. + + * sim-options.c (standard_options): Add --architecture=MACHINE and + --target=TARGET options. + (OPTION_ARCHITECTURE, OPTION_TARGET): Define. + (standard_option_handler): Handle architecture and target options. + (bfd.h): Include. + + * sim-utils.c (sim_analyze_program): Pass STATE_TARGET to + bfd_openr. + (sim_analyze_program): Set prog_bfd architecture from + STATE_ARCHITECTURE if known. + +Wed Aug 27 18:13:22 1997 Andrew Cagney + + * configure: Regenerated to track ../common/aclocal.m4 changes. + * config.in: Ditto. + +Wed Aug 27 18:11:30 1997 Andrew Cagney + + * aclocal.m4 (enable-sim-warnings): Remove comment stating + that option does not apply to certain files. + +Wed Aug 27 15:13:04 1997 Andrew Cagney + + * sim-bits.h (LSBIT8, LSBIT16, LSBIT32, LSBIT64, LSBIT, MSBIT8, + MSBIT16, MSBIT32, MSBIT64, MSBIT): New macros - single bit as + offset from MSB/LSB. + + * sim-endian.h (A1_8, A2_8, A4_8, A1_4, A2_4, A1_2): New macro, + access address of sub word quantity of a hosts 16, 32, 64 bit word + type. + (V1_2, V1_4, V2_4, V1_8, V2_8, V4_8): Ditto for values. + (U8_1, U8_2, U8_4, U4_1, U4_2, U2_1): Ditto for set of values. + (V2_H1, V2_L1, V4_H2, V4_L2, V8_L4, V8_H4): Given N byte argument, + return N*2 byte value with argument in Hi/Lo word. Renamed from + V1_H2, V1_L2, V2_H4, V2_L4, V4_H8, V4_L8. + + * sim-alu.h (ALU32_HAD_OVERFLOW): Use 64 bit mask not 32bit. + (ALU16_HAD_CARRY, ALU32_HAD_CARRY, ALU16_HAD_OVERFLOW): Use MSBIT + so that bit offset is explicit. + +Wed Aug 27 11:55:35 1997 Andrew Cagney + + * sim-utils.c (sim_analyze_program): Add prog_name argument. + Update STATE_PROG_BFD when needed with a dup'd copy of the + program. + + * sim-config.c (sim_config): Delete ABFD argument, use + STATE_PROG_BFD directly. + +Tue Aug 26 12:55:26 1997 Andrew Cagney + + * run.c (main): Pass the open ABFD to sim_create_inferior. + + * nrun.c (main): Determine prog_bfd. Pass to sim_create_inferior + and sim_load. + (bfd.h): Include. + + * sim-hload.c (sim_load): New file. Implement generic sim_load for + hardware only simulator targets. + + * Make-common.in (sim-hload.o): Add rule. + +Wed Aug 27 09:51:42 1997 Andrew Cagney + + * sim-utils.c (sim_copy_argv): Rewrite to match malloc strategy + used by copyargv and freeargv. + + * sim-options.c (sim_parse_args): Save a copy of PROG-ARGS in + STATE_PROG_ARGV, not just a pointer. + +Mon Aug 25 17:50:22 1997 Andrew Cagney + + * configure: Regenerated to track ../common/aclocal.m4 changes. + * config.in: Ditto. + +Mon Aug 25 12:11:06 1997 Andrew Cagney + + * aclocal.m4 (sim-endian): Add second argument to + SIM_AC_OPTION_ENDIAN. First is hardwired endian, second is + default endian when not hardwired. + + * sim-config.h (WITH_DEFAULT_TARGET_BYTE_ORDER): New macro, if all + else failes value for target byte order. + + * sim-config.c (sim_config): Add abfd arguments. Set + STATE_PROG_BFD accordingly. Determine prefered_target_byte_order + from same. + (sim_config): Return SIM_RC, don't abort. + (bfd.h): Include. + + * run.c (main): Update call to sim_open - add ABFD argument. + * nrun.c (main): Add NULL ABFD argument. + +Thu Aug 14 12:48:57 1997 Doug Evans + + * callback.c (os_poll_quit): Make static. + Call sim_cb_eprintf, not p->eprintf. + (sim_cb_printf, sim_cb_eprintf): New functions. + * sim-utils.h (sim_cb_printf, sim_cb_eprintf): Declare. + + * sim-basics.h (zalloc,zfree,sim_add_commas,SIM_ELAPSED_TIME, + sim_elapsed_time_get,sim_elapsed_time_since): Move decls to + sim-utils.h. #include sim-utils.h. + * sim-utils.h: Above decls moved here. + (sim_analyze_program,sim_load_file): Use `struct _bfd', not `bfd'. + + * sim-watch.c (action_watchpoint): Fix thinkos. + +Thu Jul 24 08:48:05 1997 Stu Grossman (grossman@critters.cygnus.com) + + * sim-types.h: Fix defs of 64 bit data types for MSVC. + +Tue Jul 22 10:35:37 1997 Doug Evans + + * sim-n-core.h (sim_core_write_unaligned_N): Add missing break + to FORCED_ALIGNMENT case. + +Thu Jun 5 13:48:37 1997 Andrew Cagney + + * callback.c (target_to_host_open): Handle hosts with O_BINARY. + +Thu Jun 5 08:47:10 1997 Jeffrey A Law (law@cygnus.com) + + * Make-common.in (libsim.a): Fix typo. + +Thu Jun 5 13:48:37 1997 Andrew Cagney + + * nrun.c (main): Verify the structure returned before using it. + +Wed Jun 4 11:44:06 1997 Andrew Cagney + + * sim-config.h (WITH_ENGINE): Enable the sim-engine module by + default. + + * sim-engine.c (sim_engine_install): New function. Install the + engine init functions. + (sim_engine_init): [Re]initialize the simulator engine. + + * sim-module.c: Add sim_engine to list of modules that always + install. + +Tue Jun 3 04:52:04 1997 Andrew Cagney + + * sim-watch.c (schedule_watchpoint): Use sim_unschedule_watchpoint + to remove the old watchpoint, not delete_watchpoint. + (watch_option_handler): Action the correct watchpoint, not just + cycles. + +Wed May 28 14:47:41 1997 Andrew Cagney + + * sim-n-core.h (sim_core_write_aligned_N): For 8byte reads, output + both low and high word. + (sim_core_write_aligned_N): Ditto. + + * sim-trace.c (set_trace_options): Delete code explicitly setting + core->trace. + + * sim-options.c (sim_print_help): Call the list commands if not a + standalone simulator. + (sim_print_help): Advise that some options may not be applicable. + + * sim-trace.c (set_trace_options): Assume core present. + + * sim-events.c (sim_events_schedule_after_signal): Overflow signal + buffer when full not almost full. + +Tue May 27 14:32:00 1997 Andrew Cagney + + * sim-events.c (sim_events_process): Don't blat the event queue + when processing watchpoints. + + * sim-watch.h: Make arg unsigned long - stop sign extension. + + * sim-events.c (sim_watch_valid): rewrite so debugable. + + * sim-config.h (WITH_XOR_ENDIAN): Default to zero. + + * sim-watch.c (schedule_watchpoint): Add is_within option so that + inequality test is possible. + (handle_watchpoint): Re-pass is_within arg. + (watch_option_handler): When `!' prefix to pc-watchpoint arg pass + 0 to schedule_watchpoint's is_within arg. + (sim_watchpoint_init): Re-pass is_within arg. + + * sim-options.c (sim_print_help): Add is_command argument. Don't + include -- prefix when called from the command line interpreter. + + * sim-watch.c (schedule_watchpoint): Pass true is_within argument. + + * sim-events.c (sim_events_watch_sim): Add is_within argument, + zero indicates that the test should be reversed. + (sim_events_watch_core): Ditto. + (WATCH_CORE): Compare range against is_within. + (WATCH_SIM): Ditto. + +Tue May 27 12:48:03 1997 Andrew Cagney + + * sim-events.c (WATCH_CORE): Pass NULL cpu argument to + sim_core_read_buffer. Check nr-bytes transfered. + + * sim-core.h (sim_core_common): Define a new struct that contains + the common data. to sd and cpu structures. + * sim-core.c (sim_core_attach): Update. + (sim_core_init): Update. Remember to copy initialized data to each + cpu. + (sim_core_find_mapping): Ditto. + + * sim-core.c (sim_core_read_buffer): Add cpu argument. + (sim_core_write_buffer): Ditto. + + * sim-n-core.h (sim_core_read_unaligned_N): When mis-aligned + transfer use xor version of read buffer. + (sim_core_write_unaligned_N): Ditto for write. + + * sim-core.c (sim_core_xor_read_buffer): New function implement + xor-endian data read breaking transfer up into xor-endian sized + blocks. + (sim_core_xor_write_buffer): Ditto for write. + (reverse_n): Reverse order of arbitrary number of bytes in buffer + - needed for xor-endian transfers. + +Fri May 23 14:24:31 1997 Andrew Cagney + + * sim-inline.h: Review description. + + * sim-core.h, sim-core.c: Reduce number of functions being inlined + to just those involved in data transfers and configuration. + + * sim-xcat.h (XSTRING): New macro, map macro definition onto + string. + * sim-n-core.h (sim_core_read_aligned_N): Use. + (sim_core_read_unaligned_N): Ditto. + (sim_core_read_unaligned_N): Ditto.. + (sim_core_write_unaligned_N): Ditto. + + * sim-core.h: Add xor endian bitmap to main structure. * + + sim-n-core.h (sim_core_write_aligned_N): Add suport for xor + endian. + (sim_core_read_aligned_N): Ditto. + + * sim-core.c (sim_core_set_xor_endian): New function. + (sim_core_attach): Don't overwrite the per-cpu xor map when + cloning the global core. + +Fri May 23 10:53:13 1997 Andrew Cagney + + * sim-engine.h: Update below so that it is using an enumerated + type. + +Thu May 22 09:12:16 1997 Gavin Koch + + * sim-engine.c (sim_engine_restart): + * sim-resume.c (sim_resume): Change longjmp param/setjmp + return value used for simulator restart from 0 to 2. + +Wed May 21 08:47:30 1997 Andrew Cagney + + * cgen-scache.c (scache_option_handler): Add is_command arg. + + * sim-model.c (model_option_handler): Add is_command argument. + + * sim-profile.c (profile_option_handler): Add is_command arg. + + * sim-events.c (sim_watch_valid): Use ub64, lb64 when 64bit value + involved. + + * sim-module.c (sim_module_add_init_fn): Call init fn in the same + order that they are registered. + + * sim-options.h (OPTION_HANDLER): Add argument to differentiate + between option and command line processing. + + * sim-options.c: Include stdlib.h, ctype.h. + + * Make-common.in (sim-watch.o): Add rule. + (sim_main_headers): Assume sim-assert.h included. + (sim-*.o): Simplify make rule. + + * sim-module.c: Add sim_watch_install to module list. + +Tue May 20 14:15:23 1997 Andrew Cagney + + * sim-base.h (STATE_LOADED_P): New predicate. Set once everything + has been loaded. + + * sim-trace.c (trace_install): Check magic. Include sim-assert.h. + * sim-events.c (sim_events_install): Ditto. + * sim-core.c (sim_core_install): Ditto. + * sim-model.c (model_install): Ditto. + * sim-options.c (standard_install): Ditto. + * sim-profile.c (profile_install): Ditto. + * sim-reason.c (sim_stop_reason): Ditto. + * sim-run.c (sim_engine_run): Ditto. + * sim-utils.c (sim_analyze_program): Ditto. + + * sim-module.c (modules): Make profile_install and trace_install + optional. + + * sim-base.h (STATE_MEM_BASE): Define for flat memory systems. + + * sim-options.c (standard_option_handler): Set the byte order. + + * sim-events.c (sim_events_process): Allow multi tick processing. + (sim_events_tickn): New function - multi cycle tick. + + * sim-events.h (sim_events_tickn, sim_events_timewarp): Add + prototypes. Under development. + (sim_events): Replace processing with nr_ticks_to_process. + +Tue May 20 09:39:22 1997 Andrew Cagney + + * nrun.c (main): Pass callbacks to sim_open instead of using + sim_set_callbacks. + + * run.c (main): Ditto. + +Mon May 19 12:07:22 1997 Andrew Cagney + + * sim-events.c (sim_events_zalloc): Signal save memory allocator - + stop tk interrupting malloc calls. + (sim_events_zalloc): Converse. + + * Make-common.in (sim_main_headers): Add sim-events.h. + + * sim-events.c (sim_events_schedule_after_signal): Change return + type to void - signal events are strictly internal. + (sim_events_init): Allocate a finite buffer for signal events. + (sim_events_schedule_after_signal): Enter signal events into the + signal buffer. + + * sim-engine.c (sim_engine_halt): Check SIM_DESC magic. + (sim_engine_restart): Ditto. + (sim_engine_abort): Ditto. + * sim-stop.c (sim_stop): Ditto. + (control_c_simulation): Ditto. + * sim-resume.c (sim_resume): Ditto. + (has_stepped): Ditto. + * sim-abort.c (sim_engine_abort): Ditto. + + * sim-basics.h (transfer_type): New type. + + * sim-core.c (sim_core_signal): New function. Print core signal + information. + (sim_core_find_mapping): Add transfer argument. + + * sim-n-core.h (sim_core_{write,write}_unaligned_N): Call + SIM_CORE_SIGNAL if a recoverable abort. + * sim-core.c (sim_core_find_mapping): Ditto. + +Fri May 16 15:13:21 1997 Andrew Cagney + + * sim-core.c (sim_core_find_mapping): Replace calls to + sim_io_error to more resiliant sim_engine_abort. + + * sim-n-core.h (sim_core_read_unaligned_N): Ditto. + (sim_core_write_unaligned_N): Ditto. + +Tue May 13 13:50:06 1997 Andrew Cagney + + * sim-module.c: Add sim_events_install to list. + + * sim-events.c (sim_events_install, sim_events_uninstall): Clonse + from sim_core_*. + (sim_events_init): Now returns SIG_RC. + + * sim-run.c: New file. Generic sim_engine_run. + * sim-reason.c: New file. Generic sim_stop_reason. + * sim-stop.c: New file. Generic sim_stop. + * sim-resume.c: New file. Generic sim_resume. + + * Make-common.in (sim-engine.o): Add rule. + (sim-run.o, sim-reason.o, sim-stop.o, sim-resume.o): Ditto. + + * sim-engine.h, sim-engine.c: New file. Provide generic + implementation of sim_engine_halt, sim_engine_error. et.al. + + * sim-base.h (sim_state_base): Add member halt. + (sim-engine.h): Include. + + * sim-events.h (sim_event_handler): Always pass SIM_DESC to event + handlers. + * sim-events.c (sim_events_poll): Update event handler. + +Tue May 13 09:57:49 1997 Andrew Cagney + + * sim-events.h, sim-events.c (sim_events_watch_clock): New + function. + (sim_events_watch_sim): New function. + (sim_events_watch_core): New function. + (sim_watch_valid): New function. + (sim_events_preprocess): New function. + (sim_events_process): Process the watchpoints as well as the timer + queue. + (sim_events_tick): Check WORK_PENDING instead of the hold queue. + (sim_events_deschedule): Check all the queues when removing an + event. + (sim_events_init): Ditto for cleaning. + +Mon May 19 12:07:22 1997 Andrew Cagney + + * sim-fpu.c (is_ufpu_number): Comment out - currently unused. + +Mon May 19 11:23:03 1997 Andrew Cagney + + * callback.c (os_open): Type of arg flags is int. + +Fri May 16 22:26:43 1997 Michael Meissner + + * sim-fpu.c (sim_fpu_is_{eq,ne,lt,le,gt,ge}): Compare Infinities + just like normal numbers as per IEEE rules. + +Wed May 14 21:20:38 1997 Bob Manson + + * callback.c (os_close): Mark the descriptor as being + available if the close succeeded. + (os_open): Pass 0644 as the mode of the file being created. + +Thu May 15 10:58:52 1997 Andrew Cagney + + * sim-fpu.c (pack_fpu, unpack_fpu): New functions - decode a + float. + + * sim-inline.c (SIM_INLINE_C): Rename from _SIM_INLINE_C_. + * sim-lnline.h: Update. + + * sim-fpu.h, sim-fpu.c (sim_fpu_[iu]{32,64}to): New int2fp + conversion functions. + (sim_fpu_to{32,64}[iu]): New fp2int functions. + + * sim-fpu.h, sim-fpu.c (sim_fpu_is_{lt,le,eq,ne,ge,gt}): New fp + compare functions. Replacing. + (sim_fpu_cmp): This. Delete. + +Mon May 12 14:49:05 1997 Andrew Cagney + + * sim-core.c (sim_core_find_mapping): Call engine_error not + sim_io_error when possible. + +Mon May 12 08:55:07 1997 Andrew Cagney + + * sim-endian.h (V1_H2): Add macro's to insert a word into a + high/low double word. + + * sim-trace.h: Remove definition of attribute - defined in + sim_basics.h. + +Mon May 12 08:55:07 1997 Andrew Cagney + + * sim-options.h (struct OPTION): Add doc_opt as the documenting + name of the option - or family of options. + + * sim-options.c (sim_args_command): Match command `a-b c' with + option `--a-b-c' from option table. + +Thu May 8 12:40:07 1997 Andrew Cagney + + * sim-options.c (sim_print_help): For optional arguments, wrap + them in []. + + * sim-trace.c (set_trace_options): New function, handle optional + argument and multiple assignment. + (trace_option_handler): Update. + + * sim-trace.c (trace_option_handler): Trace branch and not fpu + when branch tracing selected. + +Wed May 7 15:19:58 1997 Andrew Cagney + + * sim-trace.c (trace_one_insn): Make a va-args function. + + * sim-trace.c (trace_vprintf): New function, va-arg version of + trace_printf. + +Tue May 6 16:38:16 1997 Doug Evans + + * sim-trace.c (trace_uninstall): Don't close a file twice. + * sim-profile.c (profile_uninstall): Likewise. + +Tue May 6 06:14:01 1997 Mike Meissner + + * sim-trace.c (toplevel): Include bfd.h. + (trace_options): Note that --trace-linenum also turns on + --trace-insn. Add --trace-{branch,semantics}. + (trace_option_handler): If --trace-linenum, also turn on + --trace-insn. Add --trace-branch support. If --trace-semantics, + turn on ALU, FPU, branch, and memory tracing. + (trace_one_insn): New function to trace an instruction. Support + --trace-linenum. + (OPTION_TRACE_*): Use an enum, rather than lots of defines. + + * sim-trace.h (TRACE_{SEMANTICS,BRANCH}_IDX): Add new macros. + (MAX_TRACE_VALUES): Use 32, not 12 by default. + (TRACE_branch): Add new mask. + (TRACE_*_P): Define all possible trace_p macros. + (trace_one_insn): Declare function. + +Mon May 5 14:08:34 1997 Mike Meissner + + * sim-trace.h (__attribute__): Define as nothing if not GNU C or + GNU C doesn't support __attributes__. + ({trace,debug}_printf): Add attribute's so -Wformat can check the + format strings. + +Mon May 5 11:16:12 1997 Andrew Cagney + + * sim-config.h (FORCED_ALIGNMENT): New alignment option - + addresses are masked forcing them to be correctly aligned. + (WITH_ALIGNMENT): Make NONSTRICT_ALIGNMENT the default. + * sim-config.c (config_alignment_to_a): Update. + + * sim-core.h (sim_cpu_core): New data type contains cpu specific + core data. + * sim-base.h (CPU_CORE): Add cpu specific core data to cpu base + type. + * sim-core.c (sim_core_attach): Add CPU argument. Ready for + processor specific core maps. + (sim_core_map_attach): Copy the core map data to each of the + processor specific core data structures. + * sim-core.c (sim_core_find_mapping): Update. + + * sim-n-core.h (sim_core_read_N, sim_core_write_N): Rename. + (sim_core_write_aligned_N, sim_core_write_aligned_N): New names. + (sim_core_write_unaligned_N, sim_core_write_unaligned_N): New + alternatives that handle unaligned addresses. + (sim_core_{read,write}_{,un}aligned_N): Drop SIM_DESC arg, replace + with just CPU arg. + * cgen-utils.c (sim_disassemble_insn): Update. + +Mon May 5 13:19:16 1997 Andrew Cagney + + * sim-trace.h (TRACE_FPU_IDX): Add Floating-point specific + tracing. + + * sim-fpu.h, sim-fpu.c: New files - prototype for generic target + fpu support. + + * sim-inline.h, sim-inline.c: Add support for SIM_FPU. + +Fri May 2 17:59:42 1997 Andrew Cagney + + * sim-core.c (sim_core_map_to_str): New function ascii equivalent + to map type. + + * sim-n-core.h (sim_core_read_N, sim_core_write_N): Use in trace + statement. + +Fri May 2 17:28:02 1997 Andrew Cagney + + * cgen-trace.c: Prepend additional trace_printf argument. + + * cgen-utils.c (sim_disassemble_insn): Add additional core + arguments. + +Fri May 2 11:40:23 1997 Andrew Cagney + + * nrun.c (main): Catch/report errorenous simulator states. + + * sim-module.c: #include "libiberty.h" so that xmalloc is defined. + * sim-trace.c: #include string.h/strings.h so that memset is + defined. + * sim-utils.c: Ditto. + * sim-profile.c: Ditto. And stdlib.h. + (print_bar): Only define when used by instruction or memory profiler. + + * sim-options.c (standard_option_handler): Make ul more local. + + * sim-load.c (sim_load_file): Make the name constant. + (sim_load_file): Passify gcc. + + * sim-utils.h: New file, pre-declare utilites in corresponding .c + file. + * sim-utils.c, sim-load.c: Include sim-utils.h. + + * sim-base.h (sim_cpu): Pre define here so available to all. + + * sim-core.h (DECLARE_SIM_CORE_WRITE_N, DECLARE_SIM_CORE_READ_N): + Restore the sim_cpu and instruction_address arguments so that full + information is available to the abort function. + * sim-core.c (sim_core_find_mapping, sim_core_write_buffer): Ditto. + * sim-n-core.h (sim_core_write_N, sim_core_read_N): Update. + + * sim-trace.h, sim-trace.c (trace_option_handler): Add interim + tracing support for sim-events and sim-core. + (trace_option_handler): Convert #if to if where possible so always + compiled/checked by C compiler. + * sim-n-core.h (sim_core_write_N, sim_core_read_N): Update. + + * sim-base.h: Adjust comment documenting how to define the cpu + structure. + (sim_state_base): Add sim_core and sim_events to simulator base + object. + + * sim-trace.h, sim-trace.c (trace_printf): Add SIM_DESC argument. + * sim-core.c (sim_core_init, sim_core_attach, + sim_core_find_mapping): Update. + * sim-events.c (ETRACE, sim_events_init, sim_events_time, + update_time_from_event, insert_sim_event, + sim_events_schedule_after_signal, sim_events_deschedule, + sim_events_tick): Ditto. + + * sim-basics.h (sim-module.h, sim-trace.h, sim-profile.h, + sim-model.h): Move #includes from here. + * sim-base.h: To here. + (sim-core.h, sim-events.h, sim-io.h): Include also + +Wed Apr 30 15:37:54 1997 Andrew Cagney + + * callback.c (default_callback): Missing initialisers. + +Thu May 1 10:40:47 1997 Doug Evans + + * sim-utils.c (sim_add_commas): New function. + * sim-basics.h (sim_add_commas): Add prototype. + * cgen-scache.c (scache_print_profile): Print commas in numbers. + * sim-profile.c (COMMAS): New macro. + (print_*): Use it to print commas in numbers. + + * configure: Regenerated. + + * cgen-sim.h (sim_signal_type): Add SIM_SIGINT. + (cgen_state): New member run_fast_p. + (cgen_init): Add prototype. + (sim_disassemble_insn): New arg `cpu'. + * cgen-trace.c (trace_insn): Update call to sim_disassemble_insn. + * cgen-utils.c (cgen_init): New function. + (sim_disassemble_insn): New arg `cpu'. Rewrite fetching of insn. + * genmloop.sh: Call engine_halt if loop exits. + + * Makefile.in (sim-options_h): Define. + (sim-{module,options,trace,profile,utils}.o): Clean up dependencies. + (sim-model.o): Add new rule. + (cgen-{scache,trace,utils}.o): Add new rules. + * aclocal.m4 (SIM_AC_OPTION_{SCACHE,DEFAULT_MODEL}): Add. + * cgen-scache.c (scache_print_profile): Change `sd' arg to `cpu'. + Indent output by 2 spaces. + * cgen-scache.h (scache_print_profile): Update. + * cgen-trace.c (trace_insn_fini): Indent output by 2 spaces. + Use trace_printf, not fprintf. + (trace_extract): Use trace_printf, not cgen_trace_printf. + * genmloop.sh (!FAST case): Increment `insn_count'. + * sim-base.h (sim_state_base): Only include scache_size if WITH_SCACHE. + (sim_cpu_base): Rename member `sd' to `state' to be consistent with + access macro's name. + * sim-core.c (sim_core_init): Use EXTERN_SIM_CORE to define it. + Change return type to SIM_RC. + (sim_core_{install,uninstall}): New functions. + * sim-core.h (sim_core_{install,uninstall}): Declare. + (sim_core_init): Use EXTERN_SIM_CORE to define it. + Change return type to SIM_RC. + * sim-model.h (models,machs,model_install): Declare. + * sim-module.c (modules): Add scache_install, model_install. + (sim_post_argv_init): Set cpu->state backlinks. + * sim-options.c (standard_options): Delete --simcache-size,--max-insns. + (standard_option_handler): Likewise. + * sim-profile.c (PROFILE_{HISTOGRAM,LABEL}_WIDTH): Move to + sim-profile.h. + (*): Assume ANSI C. + (profile_options): Delete --profile-simcache. + (profile_option_handler): Likewise. + (profile_print_insn): Change `sd' arg to `cpu'. Indent output 2 + spaces. + (profile_print_{memory,model}): Likewise. + (profile_print_simcache): Delete. + (profile_print_speed): New function. + (profile_print): Rewrite. + * sim-profile.h (PROFILE_scache): Renamed from PROFILE_simcache. + (WITH_PROFILE_SCACHE_P): Renamed from WITH_PROFILE_SIMCACHE_P. + (PROFILE_DATA): Delete members simcache_{hits,misses}. + (PROFILE_COUNT_SIMCACHE_{HIT,MISS}): Delete. + (PROFILE_{CALLBACK,CPU_CALLBACK}): New types. + (profile_print): Update prototype. + +Wed Apr 30 11:34:14 1997 Doug Evans + + * cgen-scache.[ch], cgen-sim.h: New files. + * cgen-trace.[ch], cgen-types.h, cgen-utils.c, genmloop.sh: New files. + * sim-model.c: New file. + + * Make-common.in (clean targets): Undo patch of Apr. 22. + +Fri Apr 25 15:28:32 1997 Mike Meissner + + * sim-n-bits.h (signed): If we have a standard compiler, undef + signed, so that signedN is defined correctly. + +Thu Apr 24 00:00:07 1997 Doug Evans + + * sim-module.h, sim-model.h, sim-profile.h: New files. + * sim-module.c, sim-profile.c: New files. + * Make-common.in (SIM_PROFILE): Define + (CONFIG_CFLAGS): Add $(SIM_PROFILE). + (sim_main_headers): Add sim-module.h, sim-model.h, sim-profile.h. + (sim_module.o,sim-profile.o): Add rules for. + * aclocal.m4 (--enable-sim-trace): Allow symbolic arguments. + (--enable-sim-profile): Add. + * configure: Regenerated. + * sim-base.h (sim_state_base): New members init_list, uninstall_list, + model. Move trace and profile support to sim-{trace,profile}.h. + New members trace_data, profile_data. + * sim-basics.h: #include sim-module.h, sim-model.h, sim-profile.h. + * sim-config.h: Provide default definition of WITH_PROFILE. + (WITH_TRACE): Change default to -1. + (MAX_NR_PROCESSORS): Always define. + * sim-options.c: Move trace and profile support to + sim-{trace,profile}.h. + (sim_pre_argv_init): Moved to sim-model.c. + (standard_install): New function. + * sim-options.h (sim_pre_argv_init): Move decl to sim-model.c. + (standard_install): Declare. + * sim-trace.c: Tracing option handling moved here from sim-options.c. + (trace_install, trace_uninstall): New functions. + (trace_printf): Update reference to TRACE_FILE. + * sim-trace.h (TRACE_FOO_IDX): Moved here from sim-base.h. + (TRACE_foo): Bit masks for symbolic arguments to --enable-sim-trace. + (WITH_TRACE_FOO_P): Define. + (trace_install): Declare. + (TRACE_DATA): New struct. + +Wed Apr 23 17:23:15 1997 Doug Evans + + * run.c: Undo last exec_bfd patch. + (main): Only pass -E ifdef SIM_HAVE_BIENDIAN. + +Wed Apr 23 17:54:27 1997 Mike Meissner + + * run.c (exec_bfd): Add back in. + (main): Set exec_bfd. + +Tue Apr 22 14:43:46 1997 Doug Evans + + * sim-load.c (sim_load_file): #include for NULL. + +Wed Apr 23 02:55:54 1997 Andrew Cagney + + * sim-events.c (insert_sim_event): Call sim_io_error instead of + less well defined engine_error. + * sim-core.c: Ditto. + +Tue Apr 22 08:48:16 1997 Stu Grossman (grossman@critters.cygnus.com) + + * Make-common.in: Change clean targets to use :: so that other + Makefiles can have their own clean targets. + * sim-load.c (xprintf eprintf): Use ANSI_PROTOTYPES instead of + __STDC__ to control use of stdarg vs. varargs syntax. Some + systems can't use __STDC__, but require stdarg. + +Fri Apr 18 11:14:43 1997 Doug Evans + + * sim-options.c (standard_options): Add --endian. + (standard_option_handler): Likewise. + + * nrun.c: #include . + (main, cntrl_c): Wrap calls to sim_resume in a SIGINT + handler that calls sim_stop (). + +Fri Apr 18 13:11:36 1997 Andrew Cagney + + * run.c (main, cntrl_c): Wrap calls to sim_resume in a SIGINT + handler that calls sim_stop (). Simulators may still be + establishing their own handler. + + * sim-events.c (sim_events_poll): Rename from + sim_events_at_large_int. Poll IO. + + * sim-io.c (sim_io_poll_quit): New function - pass on a polling + request. + + * callback.c (os_poll_quit): New function poll for quit signal + where needed. + (default_callback): Include magic number. + +Thu Apr 17 02:25:11 1997 Doug Evans + + * aclocal.m4: Check for headers time.h, sys/time.h, sys/resource.h. + Check for functions getrusage, time. + * sim-basics.h (SIM_ELAPSED_TIME): New typedef. + (sim_elapsed_time_get, sim_elapsed_time_since): Add prototypes. + * sim-utils.c: #include time.h, sys/time.h, sys/resource.h if able. + (sim_elapsed_time_get, sim_elapsed_time_since): New functions. + + * sim-utils.c (sim_copy_argv, sim_analyze_program): New functions. + + * sim-options.c, sim-options.h: New files. + * sim-config.h (WITH_DEBUG): Provide default value of zero. + * Make-common.in (nrun.o): Add rules for. + * nrun.c: New file. + + * run.c (main): Check return value of sim_open. + + * Make-common.in (sim-options.o, sim-load.o, sim-trace.o): Add rules. + (sim_main_headers): Add sim-trace.h. + * run.c (exec_bfd, target_byte_order): Delete. + (main): Pass -E to sim_open. Delete code to load sections, + call sim_load instead. Check return code of sim_create_inferior. + * sim-base.h (CURRENT_STATE): Define. + (sim_state_base): Make typedef. New members options, prog_argv, + prog_bfd, text_{section,start,end}, start_addr, simcache_size, + mem_size, memory [+ corresponding access macros]. + (sim_cpu_base): New typedef. + * sim-trace.h: New file. + * sim-trace.c: New file. + * sim-basics.h: #include it. + * sim-load.c: New file. + +Tue Apr 15 15:10:13 1997 Ian Lance Taylor + + * Make-common.in (INSTALL): Set to @INSTALL@. + (INSTALL_XFORM, INSTALL_XFORM1): Remove. + (install-common): Depend upon installdirs. Use + $(program_transform_name) directly, rather than using + $(INSTALL_XFORM). + (installdirs): New target. + * Makefile.in (INSTALL): Set to @INSTALL@. + (INSTALL_XFORM, INSTALL_XFORM1): Remove. + (install-man): Depend upon installdirs. Use + $(program_transform_name) directly, rather than using + $(INSTALL_XFORM). + (installdirs): New target. + +Tue Apr 15 15:08:12 1997 Andrew Cagney + + * sim-assert.h (SIM_ASSERT, ASSERT): Allow these macros to + be overriden. + +Wed Apr 9 16:06:44 1997 Andrew Cagney + + * sim-basics.h: Only bring in config.h and tconfig.h if + HAVE_CONFIG_H. + +Mon Apr 7 11:39:45 1997 Andrew Cagney + + * sim-config.h (WITH_TARGET_WORD_MSB): New Macro. Define the bit + numbering convention of the target. + * sim-config.c (print_sim_config): Print WITH_TARGET_WORD_BITSIZE + and WITH_TARGET_WORD_MSB. + (sim_config): When possible, check for consistency with bitsize + and msb. + + * sim-bits.h: Allow MSB to be other than zero. + * sim-bits.c: Ditto. + * sim-n-bits.h: Ditto. + + * sim-bits.h (MSMASK*): New macros - converce to LSMASK*. + * sim-n-bits.h (MSMASKEDn): Ditto. + +Mon Apr 14 16:29:21 1997 Ian Lance Taylor + + * Makefile.in (INSTALL): Change install.sh to install-sh. + +Mon Apr 7 10:46:38 1997 Doug Evans + + * sim-base.h (sim_state_base): Move `magic' to end of struct. + +Mon Apr 7 15:53:21 1997 Andrew Cagney + + * run.c (main): Check that a program to run was specified. + +Mon Apr 7 15:45:02 1997 Andrew Cagney + + * aclocal.m4 (AC_TYPE_SIGNAL): Add check. + + * configure: Regenerated to track ../common/aclocal.m4 changes. + * config.in: Ditto. + +Wed Apr 2 15:06:28 1997 Doug Evans + + * sim-endian.h: Move host {LITTLE,BIG}_ENDIAN support from here, + * sim-config.h: To here. + + * Make-common.in (SIM_EXTRA_DEPS): New config var. + (sim_main_headers): Define. + (sim-*.o): Depend on $(SIM_EXTRA_DEPS). + (BUILT_SRC_FROM_COMMON): Move here from ../d30v/Makefile.in. + (clean): Use it. + (sim-utils.o): Add rule for. + * sim-utils.o: New file. + * sim-basics.h: #include sim-base.h. + (zalloc): Make argument unsigned long. + * sim-base.h: New file. + * sim-inline.h (SIM_IO support): Delete. + * sim-io.h: Delete inline support. + * sim-io.c: Likewise. sim-state.h renamed to sim-main.h. + * sim-config.c: sim-state.h renamed to sim-main.h. + * sim-core.c: Likewise. + * sim-events.c: Likewise. + + * run.c (main): Pass SIM_OPEN_STANDALONE to sim_open. + + * aclocal.m4: Check for stdlib.h, string.h, strings.h, unistd.h. + (sim-debug): Allow arguments. Define WITH_DEBUG in addition to + -DDEBUG. + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Wed Apr 2 14:34:19 1997 Andrew Cagney + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Wed Apr 2 11:08:11 1997 Andrew Cagney + + * sim-config.h (WITH_ALIGNMENT, WITH_FLOATING_POINT, + WITH_XOR_ENDIAN, WITH_SMP, WITH_RESERVED_BITS): Assume that these + are defined by the configure. + + * aclocal.m4 (sim-stdio): Add option stdio from ../ppc configure. + + * aclocal.m4 (floating-point, xor-endian, alignment, smp, + reserved-bits): Always define. + + * sim-config.h, sim-config.c (sim_config): New function - and new + file - co-ordinate the setting/checking of the common simulator + configuration options. + + * Make-common.in (sim-config.o): Add rule. + +Fri Mar 28 15:32:00 1997 Mike Meissner + + * callback.c (os_{,e}vprintf_filtered): Change stdarg type to + va_list from void *, since va_list might not be a pointer type. + +Mon Mar 24 15:27:12 1997 Andrew Cagney + + * sim-n-endian.h (offset_N): Correct assertion - word and sub word + in wrong order. + (offset_N): Correct computation of LE offset. + + * sim-io.c (sim_io_error): Include a new line when reporting + errors. + + * sim-assert.h (SIM_FILTER_PATH): Out by one when locating last + `/'. + +Thu Mar 20 22:31:06 1997 Jeffrey A Law (law@cygnus.com) + + * run.c: Include alloca-conf.h. + + * callback.c (os_evprintf_filtered): Fix typo. + +Fri Mar 21 13:36:20 1997 Andrew Cagney + + * run.c (string.h, strings.h, stdlib.h): Include. + + * sim-events.c (sim_events_tick): Recent cleanup failed to return + 0 when nothing pending. + + * run.c (sim_size, sim_trace): Plicate GCC - these two functions + will soon be going away. + (getopt): Plicate GCC. + + * sim-endian.c (sim-io.h): Plicate GCC. + * sim-bits.c (sim-io.h): Ditto. + * sim-n-bits.h (ROTn): Ditto. + + * sim-io.c (sim_io_error): Correct check for NULL. + + * sim-assert.h (SIM_FILTER_PATH): Separate out the code filtering + the __FILE__. + * sim-events.c: Use SIM_FILTER_PATH to filter out the filename + path. + +Wed Mar 19 01:12:06 1997 Andrew Cagney + + * aclocal.m4 (SIM_AC_OPTION_*: Move so that they are outside of + SIM_AC_COMMON - SIM_AC_COMMON was gobling arguments. + +Tue Mar 18 20:48:12 1997 Andrew Cagney + + * sim-alu.h: Include sim-xcat.h. + +Tue Mar 18 13:58:18 1997 Andrew Cagney + + * Make-common.in (sim-bits.c, sim-core.c, sim-endian.c, + sim-events.c, sim-inline.c, sim-io.c): Define rules for building + these. + + * sim-events.c (sim_events_at_large_int): New function. Just + schedules an event every large-int ticks. + (sim_events_init): Call. + (sim_events_tick, sim_events_process): Move async handing to + sim_events_process. Move timer decrement so that it occures after + events have been processed. + + * sim-basics.h (struct _engine): Remove declaration. + + * sim-events.h, sim-events.c: Rename type to sim_events. Prefix + everything with same. Rename global struct to SIM_DESC. + * sim-core.h, sim-core.c, sim-n-core.c: Ditto for sim_core. + * sim-io.h, sim-io.c: Ditto. + + * sim-assert.h: New file. Optional assertion checking macros. + * sim-io.c (sim_io_error): Make just this function tolerant to + null pointers. + + * sim-xcat.h: New file. Define concatenate macros. + * sim-basics.h (XCONCAT*): Move to sim-xcat.h. + * sim-n-core.h, sim-n-bits.h, sim-n-endian.h: Explicitly include + concat macros. + + +Tue Mar 18 12:44:55 1997 Andrew Cagney + + * sim-bits.h (LSMASK): New macro. Create mask of LS bits. + +Mon Mar 17 18:10:05 1997 Andrew Cagney + + * sim-inline.h: Add definitions for sim-types. + (ALL_BY_MODULE): New macro, encapsulate full inlining by the + module. + +Mon Mar 17 15:38:27 1997 Andrew Cagney + + * sim-events.h: Remove defunct reference to callback struct. + +Mon Mar 17 15:10:07 1997 Andrew Cagney + + * configure: Re-generate. + +Mon Mar 17 15:04:47 1997 Andrew Cagney + + * Make-common.in (CSEARCH): Do not include the gdb directory in + the search path. + +Mon Mar 17 13:16:26 1997 Andrew Cagney + + * Make-common.in (SIM_ENDIAN, SIM_HOSTENDIAN, SIM_INLINE, + SIM_WARNING): Drop, requiring the simulator specific Makefile.in + to explicitly incorporate these. + + * aclocal.m4 (--enable-sim-alignment); New option. Strongly + specify the alignment restrictions of the target architecture - + without this option all alignment restrictions are accomodated. + (--enable-sim-assert): New option. Conditionally compile in + assertion statements. + (--enable-sim-float): New option. Strongly specify the target's + floating point support. + (--enable-sim-hardware): New option. Specify the hardware devices + included in the simulation. + (--enable-sim-packages): New option. Specify the hardware + packages included in the simulation. + (--enable-sim-regparm): New option. Specify that parameters be + passed in registers instead of on the stack. + (--enable-sim-reserved-bits): New option. Specify that reserved + bits within an instruction are are correctly set. + (--enable-sim-smp): New option. Specify the level of SMP support + to be included in the simulator. + (--enable-sim-stdcall): New option. Specify an alternative + function call convention. + (--enable-sim-xor-endian): New option. Configure xor-endian + support used by some targets to implement bi-endian support. + +Fri Mar 14 19:51:21 1997 Andrew Cagney + + * aclocal.m4 (--enable-sim-hostendian): New option. Allow the + host endianness to be overridden. + (--enable-sim-endian): Allow the target platform's byte order + to be overridden. + (--enable-sim-inline): Control the inlining of common components. + (--enable-sim-bswap): For compatibility, also define WITH_BSWAP. + (--enable-sim-warnings): Enable additional GCC compiler checks. + * Make-common.in (SIM_ENDIAN, SIM_HOSTENDIAN, SIM_INLINE, + SIM_WARNINGS): Add. + + * sim-n-core.h, sim-n-bits.h, sim-n-endian.h: Rename from + sim-*-n.h so that the names are uniq on dos machines + * sim-core.c, sim-bits.c, sim-endian.c: Update. + +Thu Mar 13 12:32:42 1997 Doug Evans + + * run.c: #include "libiberty.h". + (main): New locals sd,no_args,sim_argv. + Run buildargv on -a option. Pass argv to sim_open, argv[0] + is program name. Update call to sim_set_callbacks. + Record result of sim_open, pass to other sim_foo routines. + +Thu Mar 13 10:24:05 1997 Michael Meissner + + * callback.c (os_printf_filtered): Do not call exit(1) or print a + final newline. + +Thu Mar 6 15:50:28 1997 Andrew Cagney + + * callback.c: Add os_flush_stdout and vprintf_filtered callbacks. + Route stdout through buffered IO. + + * callback.c: Add os_flush_stderr, os_write_stderr, + os_evprintf_filtered functions to route error output through + stderr. + + * sim-io.h, sim-io.c (sim_io_flush_stderr, sim_io_flush_stdout): + Correct return type - should be void. + +Fri Mar 7 20:14:37 1997 Andrew Cagney + + * sim-basics.h: Clean up. Many macro's moved to sim-inline.h. + + * sim-config.h: Ditto. For some options - eg WITH_DEVICES - do + not provide a default value as undefined indicates disable code. + +Thu Mar 6 15:50:28 1997 Andrew Cagney + + * sim-core.h, sim-core-n.h, sim-core.c: Borrow code from ppc + directory. + * sim-events.h, sim-events.c: Ditto. + * sim-io.h, sim-io.c: Ditto. + +Tue Mar 4 09:35:56 1997 Andrew Cagney + + * sim-alu.h (ALU_SUB_CA, ALU*_SUB_CA): New alu operation. + + * sim-bits.h, sim-bits-n.h, sim-bits.c (LSMASKED*): New macro's + extract the tail or least signifiant bits from an integer of the + specified size. + + * sim-bits.h, sim-bits.c: Clean up conditionally compiled #if + WITH_TARGET_BITSIZE so that the compilation will fail when an + unsupported bitsize value is defined. + + (INSERTED*): Convert to functions. + (EXTRACTED*): Ditto. + + (SIGN_EXTEND, SEXT): Change to more terse name. + +Tue Mar 4 09:35:56 1997 Andrew Cagney + + * sim-inline.h: Allow explicit control over which .c files will be + included by their header. + + * sim-inline.h: Allow explicit control over which .c files use the + alternative - REGPARM - parameter passing mechanism. + + * sim-inline.h, sim-inline.c: Don't attempt to include any of + icache.c, idecode.c, semantics.c or support.c. Those names are + not generally applicable. + +Thu Feb 27 10:17:23 1997 Andrew Cagney + + * sim-bits.c, sim-bits-n.h (new): Split sim-bits.c into two parts + in a fashion similar to sim-endian-n. + + * sim-endian.h: (H_word, L_word, AL_*, VL_*): Extend to include + both value and address macro's. + +Tue Feb 25 18:51:57 1997 Andrew Cagney + + * sim-alu.h (ALU16_BEGIN, ALU16_SET, ...): Fill in. + + * sim-endian.h (L_word, H_word): Replace MS2W_4, LS2W_4 with more + generic L_word, H_word macro's. + +Thu Feb 20 18:36:55 1997 Andrew Cagney + + * sim-basics.h: Borrow code from ppc directory. + * sim-bits.c: Ditto. + * sim-bits.h: Ditto. + * sim-config.h: Ditto. + * sim-endian-n.h: Ditto. + * sim-endian.c: Ditto. + * sim-endian.h: Ditto. + * sim-inline.c: Ditto. + * sim-inline.h: Ditto. + * sim-types.h: Ditto. + +Wed Feb 19 12:40:50 1997 Andrew Cagney + + * sim-alu.h (ALU_SET16, ALU_SET32, ALU_SET64, etc): Make available + all the ALU size alternatives and then auto-configure a default. + + * sim-alu.h: Copy ppc/idecode_expression.h. + +Mon Feb 17 10:44:18 1997 Andrew Cagney + + * bits.h, bits.c (SIGN_EXTEND32, SIGN_EXTEND64): New functions, + sign extend a bit within a value. + + * sim-endian.h, sim-endian-n.h (offset_N): New functions - return + a pointer into the middle of a host word. + * sim-endian.h (MS2W_4, LS2W_4): Use this function. + +Tue Feb 11 13:46:49 1997 Michael Meissner + + * callback.c: If HAVE_CONFIG_H is defined, include config.h from + autoconf. If HAVE_UNISTD_H is defined, include unistd.h to get + appropriate definitions of read, write, etc. Add prototype for + system. + +Tue Feb 4 13:24:44 1997 Doug Evans + + * Makefile.in (libcommon.a): Delete. + (callback.o,targ-map.o): Delete, moved to Make-common.in. + (gentmap,targ-vals.h,targ-map.c): Likewise. + (run-autoconf): Delete. + * aclocal.m4 (SIM_AC_OUTPUT): Redo creation of Makefile. + (common makefile fragment): Moved back into ... + * Make-common.in: Resurrect. + * configure.in (AC_LINK_FILES): Delete, unnecessary now. + * configure: Regenerated. + +Fri Jan 31 07:16:49 1997 Doug Evans + + * aclocal.m4 (SIM_AC_COMMON): Move COMMON_MAKEFILE_FRAG from here. + (SIM_AC_OUTPUT): To here. + +Fri Jan 24 10:37:17 1997 Stu Grossman (grossman@critters.cygnus.com) + + * aclocal.m4 (COMMON_MAKEFILE_FRAG): Quote a couple of $'s in + comments and single quotes. Fixes a problem found on hpux. + +Thu Jan 23 13:35:03 1997 Stu Grossman (grossman@critters.cygnus.com) + + * aclocal.m4: Remove Make-common.in from dependencies. + * (distclean): Remove targ-vals.def. + + * aclocal.m4 (SIM_AC_COMMON): Move contents of Make-common.in + into here. Makes insertion into makefiles easier. Also, change + the way that callback.o, gentmap, targ-vals.h, targ-map.c, + targ-map.o, and run are built. They are now built in the + individual simulator directories, taking sources from ../common as + necessary. This replaces the merging of libcommon.a into + linsim.a, which was problematic for the WinGDB build process. + * run.c: Include config.h from . instead of ../common. + * Make-common.in: Remove. It's no longer necessary. + +Mon Dec 16 15:02:33 1996 Ian Lance Taylor + + * Make-common.in (ALL_CLAGS): Put CFLAGS at the end. + (.c.o): Put $(ALL_CFLAGS) before the file being compiled. + +Wed Dec 11 11:30:58 1996 Jim Wilson + + * run.c (main): Set target_byte_order before call to sim_open. + +Sun Dec 8 18:22:06 1996 Doug Evans + + * callback.c: #include + (os_error): New function. + (default_callback): Add os_error. + +Mon Nov 25 19:44:35 1996 Doug Evans + + * Make-common.in (Makefile): Set CONFIG_HEADERS="". + * aclocal.m4: Mark the fact that --enable-sim-bswap isn't host + specific. + (SIM_AC_OUTPUT): Don't build Makefile if CONFIG_FILES="". + +Wed Nov 20 01:11:04 1996 Doug Evans + + * run.c: #include ../common/config.h, tconfig.h. + (myname): New static global. + (main): Recognize new options -a, -c. Also recognize -h if h8/300. + Only process -c ifdef SIM_HAVE_SIMCACHE. + Only process -p/-s ifdef SIM_HAVE_PROFILE. + Parse program name from argv[0] and use in error messages. + Pass sim_args to sim_open. Pass prog_args to sim_create_inferior. + Add support for incomplete h8/300 termination indicators. + (usage): Make more verbose. + * aclocal.m4,config.in,tconfig.in,configure.in,configure: New files. + * Makefile.in,Make-common.in,callback.c: New files. + * nltvals.def,gentmap.c,gentvals.sh: New files. + +Tue Nov 12 13:34:00 1996 Dawn Perchik + + * run.c: Include stdarg.h if __STDC__. + +Tue Oct 15 11:16:31 1996 Jeffrey A Law (law@cygnus.com) + + * run.c (main): Don't print out anything if the signal + number is zero (ie no signal). + +Tue Oct 15 11:20:44 1996 Michael Meissner + + * run.c (main): Print out if the program raised a signal. + +Wed Sep 18 09:52:14 1996 Michael Meissner + + * run.c (exec_bfd): Rename from sim_bfd, to use the gdb name. + (main): Ditto. + +Tue Sep 17 11:04:50 1996 James G. Smith + + * run.c (main): Explicitly cast malloc() parameter. + +Thu Sep 12 11:27:21 1996 Michael Meissner + + * run.c (sim_bfd): New global to hold the bfd pointer for the + executable. + (main): Initialize sim_bfd. + +Fri Dec 15 16:27:49 1995 Ian Lance Taylor + + * run.c (main): Use new bfd_big_endian macro. + +Wed Nov 8 15:49:49 1995 James G. Smith + + * run.c (main): Removed SH specific comments, so source is + generic. Also updated to only load relevant sections. Moved + sim_open() to after callback attach (to match GDB). + + * run.1: Removed SH specific comments. + +Sat Oct 21 12:31:01 1995 Jim Wilson + + * run.c (main): Always return sigrc at end. + +Tue Oct 10 12:03:13 1995 J.T. Conklin + + * run.c (main): Print error diagnostic and exit if bfd_openr() or + bfd_check_format() fails. + +Thu Sep 28 15:40:36 1995 steve chamberlain + + * run.c, run.1: From sh directory. diff --git a/sim/common/Make-common.in b/sim/common/Make-common.in new file mode 100644 index 00000000000..71b4f69a612 --- /dev/null +++ b/sim/common/Make-common.in @@ -0,0 +1,642 @@ +# Makefile fragment for common parts of all simulators. +# Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc. +# Contributed by Cygnus Support. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# This Makefile fragment consists of two separate parts. +# They are merged into the final Makefile at points denoted by +# "## COMMON_PRE_CONFIG_FRAG" and "## COMMON_POST_CONFIG_FRAG". +# +# The target Makefile should look like: +# +#># Copyright blah blah +#> +#>## COMMON_PRE_CONFIG_FRAG +#> +#># Any overrides necessary for the SIM_FOO config vars. +#>SIM_FOO = ... +#> +#>## COMMON_POST_CONFIG_FRAG +#> +#># Rules to build target specific .o's. + +## COMMON_PRE_CONFIG_FRAG + +VPATH = @srcdir@ +srcdir = @srcdir@ +srccom = $(srcdir)/../common +srcroot = $(srcdir)/../.. + +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +host_alias = @host_alias@ +target_alias = @target_alias@ +program_transform_name = @program_transform_name@ +bindir = @bindir@ + +libdir = @libdir@ +tooldir = $(libdir)/$(target_alias) + +datadir = @datadir@ +mandir = @mandir@ +man1dir = $(mandir)/man1 +infodir = @infodir@ +includedir = @includedir@ + +# This can be referenced by the gettext configuration code. +top_builddir = .. + +EXEEXT = @EXEEXT@ +SHELL = @SHELL@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ + +CC = @CC@ +CC_FOR_BUILD = @CC_FOR_BUILD@ +CFLAGS = @CFLAGS@ +SIM_BSWAP = @sim_bswap@ +SIM_CFLAGS = @sim_cflags@ +SIM_DEBUG = @sim_debug@ +SIM_TRACE = @sim_trace@ +SIM_PROFILE = @sim_profile@ + +SIM_ASSERT = @sim_assert@ +SIM_ALIGNMENT = @sim_alignment@ +SIM_BITSIZE = @sim_bitsize@ +SIM_DEFAULT_MODEL = @sim_default_model@ +SIM_ENDIAN = @sim_endian@ +SIM_ENVIRONMENT = @sim_environment@ +SIM_FLOAT = @sim_float@ +SIM_HW_CFLAGS = @sim_hw_cflags@ +SIM_HW_OBJS = @sim_hw_objs@ +SIM_HW = @sim_hw@ +SIM_HOSTENDIAN = @sim_hostendian@ +SIM_INLINE = @sim_inline@ +SIM_PACKAGES = @sim_packages@ +SIM_REGPARM = @sim_regparm@ +SIM_RESERVED_BITS = @sim_reserved_bits@ +SIM_SCACHE = @sim_scache@ +SIM_SMP = @sim_smp@ +SIM_STDCALL = @sim_stdcall@ +SIM_WARNINGS = @build_warnings@ +SIM_XOR_ENDIAN = @sim_xor_endian@ + +HDEFINES = @HDEFINES@ +TDEFINES = + +AR = @AR@ +AR_FLAGS = rc +RANLIB = @RANLIB@ +MAKEINFO = makeinfo + +DEP = $(srcroot)/mkdep + +# Each simulator's Makefile.in defines one or more of these variables +# to override our settings as necessary. There is no need to define these +# in the simulator's Makefile.in if one is using the default value. In fact +# it's preferable not to. + +# List of object files, less common parts. +SIM_OBJS = +# List of extra dependencies. +# Generally this consists of simulator specific files included by sim-main.h. +SIM_EXTRA_DEPS = +# List of flags to always pass to $(CC). +SIM_EXTRA_CFLAGS = +# List of extra libraries to link with. +SIM_EXTRA_LIBS = +# List of extra program dependencies. +SIM_EXTRA_LIBDEPS = +# List of main object files for `run'. +SIM_RUN_OBJS = run.o +# Dependency of `all' to build any extra files. +SIM_EXTRA_ALL = +# Dependency of `install' to install any extra files. +SIM_EXTRA_INSTALL = +# Dependency of `clean' to clean any extra files. +SIM_EXTRA_CLEAN = + +# Every time a new general purpose source file was added every target's +# Makefile.in needed to be updated to include the file in SIM_OBJS. +# This doesn't scale. +# This variable specifies all the generic stuff common to the newer simulators. +# Things like sim-reason.o can't go here as the cpu may provide its own +# (though hopefully in time that won't be so). Things like sim-bits.o can go +# here. Some files are used by all simulators (e.g. callback.o). +# Those files are specified in LIB_OBJS below. + +SIM_COMMON_HW_OBJS = \ + hw-alloc.o \ + hw-base.o \ + hw-device.o \ + hw-events.o \ + hw-handles.o \ + hw-instances.o \ + hw-ports.o \ + hw-properties.o \ + hw-tree.o \ + sim-hw.o \ + +SIM_NEW_COMMON_OBJS = \ + sim-arange.o \ + sim-bits.o \ + sim-break.o \ + sim-config.o \ + sim-core.o \ + sim-endian.o \ + sim-events.o \ + sim-fpu.o \ + sim-io.o \ + sim-info.o \ + sim-load.o \ + sim-memopt.o \ + sim-module.o \ + sim-options.o \ + sim-profile.o \ + sim-signal.o \ + sim-trace.o \ + sim-utils.o \ + sim-watch.o \ + \ + $(SIM_HW_OBJS) \ + +# Add this to SIM_EXTRA_DEPS. +CGEN_INCLUDE_DEPS = \ + $(srccom)/cgen-cpu.h \ + $(srccom)/cgen-defs.h \ + $(srccom)/cgen-engine.h \ + $(srccom)/cgen-scache.h \ + $(srccom)/cgen-sim.h \ + $(srccom)/cgen-trace.h \ + $(srccom)/cgen-types.h \ + $(srcdir)/../../include/opcode/cgen.h + +## End COMMON_PRE_CONFIG_FRAG + +## COMMON_POST_CONFIG_FRAG + +CONFIG_CFLAGS = \ + @DEFS@ \ + $(SIM_CFLAGS) \ + $(SIM_DEBUG) \ + $(SIM_DEFAULT_MODEL) \ + $(SIM_TRACE) \ + $(SIM_PROFILE) \ + $(SIM_BSWAP) \ + $(SIM_ASSERT) \ + $(SIM_ALIGNMENT) \ + $(SIM_BITSIZE) \ + $(SIM_ENDIAN) \ + $(SIM_ENVIRONMENT) \ + $(SIM_FLOAT) \ + $(SIM_HW_CFLAGS) \ + $(SIM_HOSTENDIAN) \ + $(SIM_INLINE) \ + $(SIM_PACKAGES) \ + $(SIM_REGPARM) \ + $(SIM_RESERVED_BITS) \ + $(SIM_SCACHE) \ + $(SIM_SMP) \ + $(SIM_STDCALL) \ + $(SIM_WARNINGS) \ + $(SIM_XOR_ENDIAN) \ + $(SIM_HARDWARE) \ + $(SIM_EXTRA_CFLAGS) \ + $(HDEFINES) $(TDEFINES) +CSEARCH = -I. -I$(srcdir) -I../common -I$(srccom) \ + -I../../include -I$(srcroot)/include \ + -I../../bfd -I$(srcroot)/bfd \ + -I../../opcodes -I$(srcroot)/opcodes \ + -I../../intl -I$(srcroot)/intl +ALL_CFLAGS = $(CONFIG_CFLAGS) $(CSEARCH) $(CFLAGS) +BUILD_CFLAGS = -g -O $(CSEARCH) + +COMMON_DEP_CFLAGS = $(CONFIG_CFLAGS) $(CSEARCH) + +LIBIBERTY_LIB = ../../libiberty/libiberty.a +BFD_LIB = ../../bfd/libbfd.a +OPCODES_LIB = ../../opcodes/libopcodes.a +INTLLIBS = @INTLLIBS@ +INTLDEPS = @INTLDEPS@ +CONFIG_LIBS = @LIBS@ +LIBDEPS = $(BFD_LIB) $(OPCODES_LIB) $(INTLLIBS) $(LIBIBERTY_LIB) \ + $(SIM_EXTRA_LIBDEPS) +EXTRA_LIBS = $(BFD_LIB) $(OPCODES_LIB) $(INTLLIBS) $(LIBIBERTY_LIB) \ + $(CONFIG_LIBS) $(SIM_EXTRA_LIBS) + +LIB_OBJS = callback.o syscall.o targ-map.o $(SIM_OBJS) + +RUNTESTFLAGS = + +all: $(SIM_EXTRA_ALL) libsim.a run .gdbinit + +libsim.a: $(LIB_OBJS) + rm -f libsim.a + $(AR) $(AR_FLAGS) libsim.a $(LIB_OBJS) + $(RANLIB) libsim.a + +run: $(SIM_RUN_OBJS) libsim.a $(LIBDEPS) + $(CC) $(ALL_CFLAGS) -o run$(EXEEXT) \ + $(SIM_RUN_OBJS) libsim.a $(EXTRA_LIBS) + +run.o: $(srccom)/run.c config.h tconfig.h \ + $(srcroot)/include/remote-sim.h $(srcroot)/include/callback.h + $(CC) -c $(srccom)/run.c $(ALL_CFLAGS) + +# FIXME: Ideally, callback.o and friends live in a library outside of +# both the gdb and simulator source trees (e.g. devo/remote. Not +# devo/libremote because this directory would contain more than just +# a library). + +callback.o: $(srccom)/callback.c config.h tconfig.h \ + $(srcroot)/include/callback.h targ-vals.h + $(CC) -c $(srccom)/callback.c $(ALL_CFLAGS) + +syscall.o: $(srccom)/syscall.c config.h tconfig.h \ + $(srcroot)/include/callback.h targ-vals.h + $(CC) -c $(srccom)/syscall.c $(ALL_CFLAGS) + +targ-map.o: targ-map.c targ-vals.h + +gentmap: Makefile $(srccom)/gentmap.c targ-vals.def + $(CC_FOR_BUILD) $(srccom)/gentmap.c -o gentmap $(BUILD_CFLAGS) $(NL_TARGET) + +targ-vals.h targ-map.c: stamp-tvals +stamp-tvals: gentmap + rm -f tmp-tvals.h tmp-tmap.c + ./gentmap -h >tmp-tvals.h + $(SHELL) $(srcroot)/move-if-change tmp-tvals.h targ-vals.h + ./gentmap -c >tmp-tmap.c + $(SHELL) $(srcroot)/move-if-change tmp-tmap.c targ-map.c + touch stamp-tvals + +# +# Rules for building sim-* components. Triggered by listing the corresponding +# .o file in the list of simulator targets. +# + +sim_main_headers = \ + sim-main.h \ + $(srccom)/sim-assert.h \ + $(srccom)/sim-base.h \ + $(srccom)/sim-basics.h \ + $(srccom)/sim-config.h \ + $(srccom)/sim-cpu.h \ + $(srccom)/sim-engine.h \ + $(srccom)/sim-events.h \ + $(srccom)/sim-inline.h \ + $(srccom)/sim-memopt.h \ + $(srccom)/sim-model.h \ + $(srccom)/sim-module.h \ + $(srccom)/sim-profile.h \ + $(srccom)/sim-signal.h \ + $(srccom)/sim-trace.h \ + $(srccom)/sim-watch.h \ + tconfig.h \ + $(SIM_EXTRA_DEPS) + +# Exported version of sim_main_headers. +SIM_MAIN_DEPS = \ + $(sim_main_headers) + +sim-assert_h = $(srccom)/sim-assert.h +sim-endian_h = $(srccom)/sim-endian.h +sim-n-endian_h = $(srccom)/sim-n-endian.h +sim-arange_h = $(srccom)/sim-arange.h +sim-bits_h = $(srccom)/sim-bits.h +sim-config_h = $(srccom)/sim-config.h +sim-n-bits_h = $(srccom)/sim-n-bits.h +sim-core_h = $(srccom)/sim-core.h +sim-n-core_h = $(srccom)/sim-n-core.h +sim-engine_h = $(srccom)/sim-engine.h +sim-events_h = $(srccom)/sim-events.h +sim-fpu_h = $(srccom)/sim-fpu.h +sim-io_h = $(srccom)/sim-io.h +sim-options_h = $(srccom)/sim-options.h +sim-break_h = $(srccom)/sim-break.h +sim-signal_h = $(srccom)/sim-signal.h + +hw-alloc_h = $(srccom)/hw-alloc.h +hw-base_h = $(srccom)/hw-base.h +hw-device_h = $(srccom)/hw-device.h +hw-events_h = $(srccom)/hw-events.h +hw-handles_h = $(srccom)/hw-handles.h +hw-instances_h = $(srccom)/hw-instances.h +hw-ports_h = $(srccom)/hw-ports.h +hw-properties_h = $(srccom)/hw-properties.h +hw-tree_h = $(srccom)/hw-tree.h + +hw_main_headers = \ + $(srccom)/hw-main.h \ + $(hw-alloc_h) \ + $(hw-base_h) \ + $(hw-device_h) \ + $(hw-events_h) \ + $(hw-instances_h) \ + $(hw-handles_h) \ + $(hw-ports_h) \ + $(hw-properties_h) \ + +# FIXME: If this complicated way of building .o files from ../common is +# necessary, the reason should be documented here. + +BUILT_SRC_FROM_COMMON= \ + sim-inline.c + +sim-abort.o: $(srccom)/sim-abort.c \ + $(SIM_EXTRA_DEPS) + $(CC) -c $(srccom)/sim-abort.c $(ALL_CFLAGS) + +sim-arange.o: $(srccom)/sim-arange.c $(sim-arange_h) $(SIM_EXTRA_DEPS) + $(CC) -c $(srccom)/sim-arange.c $(ALL_CFLAGS) + +sim-bits.o: $(srccom)/sim-bits.c $(sim-bits_h) $(sim-n-bits_h) \ + $(SIM_EXTRA_DEPS) + $(CC) -c $(srccom)/sim-bits.c $(ALL_CFLAGS) + +sim-config.o: $(srccom)/sim-config.c $(sim-config_h) \ + $(SIM_EXTRA_DEPS) + $(CC) -c $(srccom)/sim-config.c $(ALL_CFLAGS) + +sim-core.o: $(srccom)/sim-core.c $(sim_main_headers) \ + $(sim-core_h) $(sim-n-core_h) + $(CC) -c $(srccom)/sim-core.c $(ALL_CFLAGS) + +sim-cpu.o: $(srccom)/sim-cpu.c $(sim_main_headers) + $(CC) -c $(srccom)/sim-cpu.c $(ALL_CFLAGS) + +sim-endian.o: $(srccom)/sim-endian.c $(sim-endian_h) $(sim-n-endian_h) + $(CC) -c $(srccom)/sim-endian.c $(ALL_CFLAGS) + +sim-engine.o: $(srccom)/sim-engine.c $(sim_main_headers) $(sim-engine_h) + $(CC) -c $(srccom)/sim-engine.c $(ALL_CFLAGS) + +sim-events.o: $(srccom)/sim-events.c $(sim-events_h) \ + $(SIM_EXTRA_DEPS) + $(CC) -c $(srccom)/sim-events.c $(ALL_CFLAGS) + +sim-fpu.o: $(srccom)/sim-fpu.c $(sim-fpu_h) \ + $(SIM_EXTRA_DEPS) + $(CC) -c $(srccom)/sim-fpu.c $(ALL_CFLAGS) + + +sim-hload.o: $(srccom)/sim-hload.c $(sim-assert_h) \ + $(srcroot)/include/remote-sim.h \ + $(SIM_EXTRA_DEPS) + $(CC) -c $(srccom)/sim-hload.c $(ALL_CFLAGS) + +sim-hrw.o: $(srccom)/sim-hrw.c $(sim-assert_h) $(sim_core_h) \ + $(srcroot)/include/remote-sim.h \ + $(SIM_EXTRA_DEPS) + $(CC) -c $(srccom)/sim-hrw.c $(ALL_CFLAGS) + +sim-hw.o: $(srccom)/sim-hw.c $(sim_main_headers) + $(CC) -c $(srccom)/sim-hw.c $(ALL_CFLAGS) + +sim-info.o: $(srccom)/sim-info.c $(sim-assert_h) \ + $(srcroot)/include/remote-sim.h \ + $(SIM_EXTRA_DEPS) + $(CC) -c $(srccom)/sim-info.c $(ALL_CFLAGS) + +sim-inline.c: $(srccom)/sim-inline.c + rm -f $@ tmp-$@ + echo "# 1 \"$(srccom)/$@\"" > tmp-$@ + cat $(srccom)/$@ >> tmp-$@ + $(SHELL) $(srcdir)/../../move-if-change tmp-$@ $@ + +sim-io.o: $(srccom)/sim-io.c $(sim_main_headers) $(sim-io_h) \ + $(srcroot)/include/remote-sim.h + $(CC) -c $(srccom)/sim-io.c $(ALL_CFLAGS) + +sim-memopt.o: $(srccom)/sim-memopt.c $(sim_main_headers) \ + $(sim-io_h) + $(CC) -c $(srccom)/sim-memopt.c $(ALL_CFLAGS) + +sim-module.o: $(srccom)/sim-module.c $(sim_main_headers) \ + $(sim-io_h) + $(CC) -c $(srccom)/sim-module.c $(ALL_CFLAGS) + +sim-options.o: $(srccom)/sim-options.c $(sim_main_headers) \ + $(sim-options_h) $(sim-io_h) + $(CC) -c $(srccom)/sim-options.c $(ALL_CFLAGS) + +sim-reason.o: $(srccom)/sim-reason.c $(sim_main_headers) \ + $(srcroot)/include/remote-sim.h + $(CC) -c $(srccom)/sim-reason.c $(ALL_CFLAGS) + +sim-reg.o: $(srccom)/sim-reg.c $(sim_main_headers) \ + $(srcroot)/include/remote-sim.h + $(CC) -c $(srccom)/sim-reg.c $(ALL_CFLAGS) + +sim-resume.o: $(srccom)/sim-resume.c $(sim_main_headers) \ + $(srcroot)/include/remote-sim.h + $(CC) -c $(srccom)/sim-resume.c $(ALL_CFLAGS) + +sim-run.o: $(srccom)/sim-run.c $(sim_main_headers) + $(CC) -c $(srccom)/sim-run.c $(ALL_CFLAGS) + +sim-signal.o: $(srccom)/sim-signal.c $(sim_main_headers) $(sim-signal_h) + $(CC) -c $(srccom)/sim-signal.c $(ALL_CFLAGS) + +sim-stop.o: $(srccom)/sim-stop.c $(sim_main_headers) + $(CC) -c $(srccom)/sim-stop.c $(ALL_CFLAGS) + +sim-trace.o: $(srccom)/sim-trace.c $(sim_main_headers) \ + $(sim-options_h) $(sim-io_h) + $(CC) -c $(srccom)/sim-trace.c $(ALL_CFLAGS) + +sim-profile.o: $(srccom)/sim-profile.c $(sim_main_headers) \ + $(sim-options_h) $(sim-io_h) + $(CC) -c $(srccom)/sim-profile.c $(ALL_CFLAGS) + +sim-model.o: $(srccom)/sim-model.c $(sim_main_headers) \ + $(sim-io_h) + $(CC) -c $(srccom)/sim-model.c $(ALL_CFLAGS) + +sim-utils.o: $(srccom)/sim-utils.c $(sim_main_headers) + $(CC) -c $(srccom)/sim-utils.c $(ALL_CFLAGS) + +sim-watch.o: $(srccom)/sim-watch.c $(sim_main_headers) + $(CC) -c $(srccom)/sim-watch.c $(ALL_CFLAGS) + +sim-load.o: $(srccom)/sim-load.c $(srcroot)/include/callback.h + $(CC) -c $(srccom)/sim-load.c $(ALL_CFLAGS) + +sim-break.o: $(srccom)/sim-break.c $(sim_main_headers) \ + $(sim_break_h) + $(CC) -c $(srccom)/sim-break.c $(ALL_CFLAGS) + + +# FIXME This is one very simple-minded way of generating the file hw-config.h +hw-config.h: Makefile.in $(srccom)/Make-common.in config.status Makefile + rm -f tmp-hw.h + echo "/* generated by Makefile */" > tmp-hw.h + for hw in $(SIM_HW) ; do \ + echo "extern const struct hw_descriptor dv_$${hw}_descriptor[];" ; \ + done >> tmp-hw.h + echo "const struct hw_descriptor *hw_descriptors[] = {" >> tmp-hw.h + for hw in $(SIM_HW) ; do \ + echo " dv_$${hw}_descriptor," ; \ + done >> tmp-hw.h + echo " NULL," >> tmp-hw.h + echo "};" >> tmp-hw.h + mv tmp-hw.h hw-config.h + +hw-alloc.o: $(srccom)/hw-alloc.c $(hw_main_headers) + $(CC) -c $(srccom)/hw-alloc.c $(ALL_CFLAGS) + +hw-base.o: $(srccom)/hw-base.c $(hw_main_headers) hw-config.h + $(CC) -c $(srccom)/hw-base.c $(ALL_CFLAGS) + +hw-device.o: $(srccom)/hw-device.c $(hw_main_headers) + $(CC) -c $(srccom)/hw-device.c $(ALL_CFLAGS) + +hw-events.o: $(srccom)/hw-events.c $(hw_main_headers) $(sim_main_headers) + $(CC) -c $(srccom)/hw-events.c $(ALL_CFLAGS) + +test-hw-events: $(srccom)/hw-events.c libsim.a + $(CC) $(ALL_CFLAGS) -DMAIN -o test-hw-events$(EXEEXT) \ + $(srccom)/hw-events.c libsim.a $(EXTRA_LIBS) + +hw-instances.o: $(srccom)/hw-instances.c $(hw_main_headers) + $(CC) -c $(srccom)/hw-instances.c $(ALL_CFLAGS) + +hw-handles.o: $(srccom)/hw-handles.c $(hw_main_headers) + $(CC) -c $(srccom)/hw-handles.c $(ALL_CFLAGS) + +hw-ports.o: $(srccom)/hw-ports.c $(hw_main_headers) + $(CC) -c $(srccom)/hw-ports.c $(ALL_CFLAGS) + +hw-properties.o: $(srccom)/hw-properties.c $(hw_main_headers) + $(CC) -c $(srccom)/hw-properties.c $(ALL_CFLAGS) + +hw-tree.o: $(srccom)/hw-tree.c $(hw_main_headers) $(hw-tree_h) + $(CC) -c $(srccom)/hw-tree.c $(ALL_CFLAGS) + +# Devices. + +dv-core.o: $(srccom)/dv-core.c $(hw_main_headers) $(sim_main_headers) + $(CC) -c $(srccom)/dv-core.c $(ALL_CFLAGS) + +dv-glue.o: $(srccom)/dv-glue.c $(hw_main_headers) $(sim_main_headers) + $(CC) -c $(srccom)/dv-glue.c $(ALL_CFLAGS) + +dv-pal.o: $(srccom)/dv-pal.c $(hw_main_headers) $(sim_main_headers) + $(CC) -c $(srccom)/dv-pal.c $(ALL_CFLAGS) + +dv-sockser.o: $(srccom)/dv-sockser.h $(sim_main_headers) + $(CC) -c $(srccom)/dv-sockser.c $(ALL_CFLAGS) + + +nrun.o: $(srccom)/nrun.c config.h tconfig.h \ + $(srcroot)/include/remote-sim.h $(srcroot)/include/callback.h \ + $(sim_main_headers) + $(CC) -c $(srccom)/nrun.c $(ALL_CFLAGS) + +# CGEN support. + +# For use in Makefile.in for cpu-specific files. +CGEN_MAIN_CPU_DEPS = \ + $(SIM_MAIN_DEPS) \ + $(CGEN_INCLUDE_DEPS) \ + $(srccom)/cgen-ops.h \ + $(srccom)/cgen-mem.h + +cgen-run.o: $(srccom)/cgen-run.c $(sim_main_headers) + $(CC) -c $(srccom)/cgen-run.c $(ALL_CFLAGS) + +cgen-scache.o: $(srccom)/cgen-scache.c $(sim_main_headers) + $(CC) -c $(srccom)/cgen-scache.c $(ALL_CFLAGS) + +cgen-trace.o: $(srccom)/cgen-trace.c $(sim_main_headers) + $(CC) -c $(srccom)/cgen-trace.c $(ALL_CFLAGS) + +cgen-utils.o: $(srccom)/cgen-utils.c $(sim_main_headers) \ + $(srccom)/cgen-mem.h $(srccom)/cgen-ops.h $(srccom)/cgen-engine.h + $(CC) -c $(srccom)/cgen-utils.c $(ALL_CFLAGS) + +# Support targets. + +install: install-common $(SIM_EXTRA_INSTALL) + +install-common: installdirs + n=`echo run | sed '$(program_transform_name)'`; \ + $(INSTALL_PROGRAM) run$(EXEEXT) $(bindir)/$$n$(EXEEXT) + n=`echo libsim.a | sed s/libsim.a/lib$(target_alias)-sim.a/`; \ + $(INSTALL_DATA) libsim.a $(libdir)/$$n ; \ + ( cd $(libdir) ; $(RANLIB) $$n ) + +installdirs: + $(SHELL) $(srcdir)/../../mkinstalldirs $(bindir) + +check: + cd ../testsuite && $(MAKE) check RUNTESTFLAGS="$(RUNTESTFLAGS)" + +info: +clean-info: +install-info: + +.NOEXPORT: +MAKEOVERRIDES= + +tags etags: TAGS + +# Macros like EXTERN_SIM_CORE confuse tags. +# And the sim-n-foo.h files create functions that can't be found either. +TAGS: force + cd $(srcdir) && \ + etags --regex '/^\([a-z_]+\) (/\1/' --regex '/^\/[*] TAGS: .*/' \ + *.[ch] ../common/*.[ch] + +clean: $(SIM_EXTRA_CLEAN) + rm -f *.[oa] *~ core + rm -f run libsim.a + rm -f gentmap targ-map.c targ-vals.h stamp-tvals + if [ ! -f Make-common.in ] ; then \ + rm -f $(BUILT_SRC_FROM_COMMON) ; \ + fi + rm -f tmp-mloop.hin tmp-mloop.h tmp-mloop.cin tmp-mloop.c + +distclean mostlyclean maintainer-clean realclean: clean + rm -f TAGS + rm -f Makefile config.cache config.log config.status .gdbinit + rm -f tconfig.h config.h stamp-h + rm -f targ-vals.def + +.c.o: + $(CC) -c $(ALL_CFLAGS) $< + +# Dummy target to force execution of dependent targets. +force: + +Makefile: Makefile.in $(srccom)/Make-common.in config.status + CONFIG_HEADERS= $(SHELL) ./config.status + +config.status: configure + $(SHELL) ./config.status --recheck + +config.h: stamp-h ; @true +stamp-h: config.in config.status + CONFIG_FILES= CONFIG_HEADERS=config.h:config.in $(SHELL) ./config.status + +.gdbinit: # config.status $(srccom)/gdbinit.in + CONFIG_FILES=$@:../common/gdbinit.in CONFIG_HEADERS= $(SHELL) ./config.status + + +## End COMMON_POST_CONFIG_FRAG diff --git a/sim/common/Makefile.in b/sim/common/Makefile.in new file mode 100644 index 00000000000..dd7c5e0e9ec --- /dev/null +++ b/sim/common/Makefile.in @@ -0,0 +1,139 @@ +# Makefile template for Configure for simulator common directory +# Copyright (C) 1996, 1997 Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +default: all + +VPATH = @srcdir@ +srcdir = @srcdir@ +srcroot = $(srcdir)/../.. + +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +host_alias = @host_alias@ +target_alias = @target_alias@ +program_transform_name = @program_transform_name@ +bindir = @bindir@ + +libdir = @libdir@ +tooldir = $(libdir)/$(target_alias) + +datadir = @datadir@ +mandir = @mandir@ +man1dir = $(mandir)/man1 +infodir = @infodir@ +includedir = @includedir@ + +SHELL = /bin/sh + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ + +CC = @CC@ +CC_FOR_BUILD = @CC_FOR_BUILD@ +CFLAGS = @CFLAGS@ +SIM_CFLAGS = @sim_cflags@ + +# These are used to rebuild nltvals.def. +CPP_FOR_TARGET = @CPP_FOR_TARGET@ +TARGET_SUBDIR = @TARGET_SUBDIR@ + +HDEFINES = @HDEFINES@ +TDEFINES = + +CONFIG_CFLAGS = @DEFS@ $(SIM_CFLAGS) $(HDEFINES) $(TDEFINES) +CSEARCH = -I. -I$(srcdir) -I$(srcroot)/include +ALL_CFLAGS = $(CFLAGS) $(CONFIG_CFLAGS) $(CSEARCH) +BUILD_CFLAGS = -g -O $(CSEARCH) + +AR = @AR@ +AR_FLAGS = rc +RANLIB = @RANLIB@ +MAKEINFO = makeinfo + +.NOEXPORT: +MAKEOVERRIDES= + +all: + +# Generate TARG_VALS_H for newlib/libgloss using devo and build tree. +# This file is shipped with distributions so we build in the source dir. +# This is built in srcdir so putting dependencies here is risky. +# Use `make headers' to rebuild. +headers: nltvals.def +.PHONY: headers + +# Note: If gdb releases begin to contain target header files, generate +# targ-vals.def at build time. + +nltvals.def: Makefile gennltvals.sh gentvals.sh + rootme=`pwd` ; \ + cd $(srcdir) ; \ + rm -f nltvals.new ; \ + $(SHELL) $(srcdir)/gennltvals.sh $(SHELL) $(srcroot) "$(CPP_FOR_TARGET)" > nltvals.new ; \ + $(SHELL) $(srcroot)/move-if-change nltvals.new nltvals.def + +.c.o: + $(CC) -c $< $(ALL_CFLAGS) + +check: + +info: +clean-info: +install-info: + +tags etags: TAGS + +# Macros like EXTERN_SIM_CORE confuse tags. +# And the sim-n-foo.h files create functions that can't be found either. +TAGS: force + cd $(srcdir) && \ + etags --regex '/^\([a-z_]+\) (/\1/' --regex '/^\/[*] TAGS: .*/' \ + *.[ch] + +clean: + rm -f *.[oa] *~ core + rm -f $(ALL) + +distclean mostlyclean maintainer-clean realclean: clean + rm -f TAGS + rm -f Makefile config.cache config.log config.status + rm -f config.h stamp-h + +# Dummy target to force execution of dependent targets. +force: + +# Copy the files into directories where they will be run. +install: + +install-man: installdirs + n=`echo run | sed '$(program_transform_name)'`; \ + $(INSTALL_DATA) $(srcdir)/run.1 $(man1dir)/$$n.1 + +installdirs: + $(SHELL) $(srcdir)/../../mkinstalldirs $(man1dir) + +Makefile: Makefile.in config.status + $(SHELL) ./config.status + +config.status: configure + $(SHELL) ./config.status --recheck + +config.h: stamp-h ; @true +stamp-h: config.in config.status + CONFIG_FILES= CONFIG_HEADERS=config.h:config.in $(SHELL) ./config.status diff --git a/sim/common/acconfig.h b/sim/common/acconfig.h new file mode 100644 index 00000000000..f9b87a10c60 --- /dev/null +++ b/sim/common/acconfig.h @@ -0,0 +1,15 @@ + +/* Define to 1 if NLS is requested. */ +#undef ENABLE_NLS + +/* Define as 1 if you have catgets and don't want to use GNU gettext. */ +#undef HAVE_CATGETS + +/* Define as 1 if you have gettext and don't want to use GNU gettext. */ +#undef HAVE_GETTEXT + +/* Define as 1 if you have the stpcpy function. */ +#undef HAVE_STPCPY + +/* Define if your locale.h file contains LC_MESSAGES. */ +#undef HAVE_LC_MESSAGES diff --git a/sim/common/aclocal.m4 b/sim/common/aclocal.m4 new file mode 100644 index 00000000000..e3b595aee91 --- /dev/null +++ b/sim/common/aclocal.m4 @@ -0,0 +1,1259 @@ +# This file contains common code used by all simulators. +# +# SIM_AC_COMMON invokes AC macros used by all simulators and by the common +# directory. It is intended to be invoked before any target specific stuff. +# SIM_AC_OUTPUT is a cover function to AC_OUTPUT to generate the Makefile. +# It is intended to be invoked last. +# +# The simulator's configure.in should look like: +# +# dnl Process this file with autoconf to produce a configure script. +# sinclude(../common/aclocal.m4) +# AC_PREREQ(2.5)dnl +# AC_INIT(Makefile.in) +# +# SIM_AC_COMMON +# +# ... target specific stuff ... +# +# SIM_AC_OUTPUT + +AC_DEFUN(SIM_AC_COMMON, +[ +# autoconf.info says this should be called right after AC_INIT. +AC_CONFIG_HEADER(ifelse([$1],,config.h,[$1]):config.in) + +AC_CONFIG_AUX_DIR(`cd $srcdir;pwd`/../..) +AC_CANONICAL_SYSTEM +AC_ARG_PROGRAM +AC_PROG_CC +AC_PROG_INSTALL + +# Put a plausible default for CC_FOR_BUILD in Makefile. +if test "x$cross_compiling" = "xno"; then + CC_FOR_BUILD='$(CC)' +else + CC_FOR_BUILD=gcc +fi +AC_SUBST(CC_FOR_BUILD) + +AC_SUBST(CFLAGS) +AC_SUBST(HDEFINES) +AR=${AR-ar} +AC_SUBST(AR) +AC_PROG_RANLIB + +dnl We don't use gettext, but bfd does. So we do the appropriate checks +dnl to see if there are intl libraries we should link against. +ALL_LINGUAS= +CY_GNU_GETTEXT + +# Check for common headers. +# FIXME: Seems to me this can cause problems for i386-windows hosts. +# At one point there were hardcoded AC_DEFINE's if ${host} = i386-*-windows*. +AC_CHECK_HEADERS(stdlib.h string.h strings.h unistd.h time.h) +AC_CHECK_HEADERS(sys/time.h sys/resource.h) +AC_CHECK_HEADERS(fcntl.h fpu_control.h) +AC_CHECK_HEADERS(dlfcn.h errno.h sys/stat.h) +AC_CHECK_FUNCS(getrusage time sigaction __setfpucw) + +# Check for socket libraries +AC_CHECK_LIB(socket, bind) +AC_CHECK_LIB(nsl, gethostbyname) + +. ${srcdir}/../../bfd/configure.host + +dnl Standard (and optional) simulator options. +dnl Eventually all simulators will support these. +dnl Do not add any here that cannot be supported by all simulators. +dnl Do not add similar but different options to a particular simulator, +dnl all shall eventually behave the same way. + + +dnl We don't use automake, but we still want to support +dnl --enable-maintainer-mode. +USE_MAINTAINER_MODE=no +AC_ARG_ENABLE(maintainer-mode, +[ --enable-maintainer-mode Enable developer functionality.], +[case "${enableval}" in + yes) MAINT="" USE_MAINTAINER_MODE=yes ;; + no) MAINT="#" ;; + *) AC_MSG_ERROR("--enable-maintainer-mode does not take a value"); MAINT="#" ;; +esac +if test x"$silent" != x"yes" && test x"$MAINT" = x""; then + echo "Setting maintainer mode" 6>&1 +fi],[MAINT="#"])dnl +AC_SUBST(MAINT) + + +dnl This is a generic option to enable special byte swapping +dnl insns on *any* cpu. +AC_ARG_ENABLE(sim-bswap, +[ --enable-sim-bswap Use Host specific BSWAP instruction.], +[case "${enableval}" in + yes) sim_bswap="-DWITH_BSWAP=1 -DUSE_BSWAP=1";; + no) sim_bswap="-DWITH_BSWAP=0";; + *) AC_MSG_ERROR("--enable-sim-bswap does not take a value"); sim_bswap="";; +esac +if test x"$silent" != x"yes" && test x"$sim_bswap" != x""; then + echo "Setting bswap flags = $sim_bswap" 6>&1 +fi],[sim_bswap=""])dnl +AC_SUBST(sim_bswap) + + +AC_ARG_ENABLE(sim-cflags, +[ --enable-sim-cflags=opts Extra CFLAGS for use in building simulator], +[case "${enableval}" in + yes) sim_cflags="-O2 -fomit-frame-pointer";; + trace) AC_MSG_ERROR("Please use --enable-sim-debug instead."); sim_cflags="";; + no) sim_cflags="";; + *) sim_cflags=`echo "${enableval}" | sed -e "s/,/ /g"`;; +esac +if test x"$silent" != x"yes" && test x"$sim_cflags" != x""; then + echo "Setting sim cflags = $sim_cflags" 6>&1 +fi],[sim_cflags=""])dnl +AC_SUBST(sim_cflags) + + +dnl --enable-sim-debug is for developers of the simulator +dnl the allowable values are work-in-progress +AC_ARG_ENABLE(sim-debug, +[ --enable-sim-debug=opts Enable debugging flags], +[case "${enableval}" in + yes) sim_debug="-DDEBUG=7 -DWITH_DEBUG=7";; + no) sim_debug="-DDEBUG=0 -DWITH_DEBUG=0";; + *) sim_debug="-DDEBUG='(${enableval})' -DWITH_DEBUG='(${enableval})'";; +esac +if test x"$silent" != x"yes" && test x"$sim_debug" != x""; then + echo "Setting sim debug = $sim_debug" 6>&1 +fi],[sim_debug=""])dnl +AC_SUBST(sim_debug) + + +dnl --enable-sim-stdio is for users of the simulator +dnl It determines if IO from the program is routed through STDIO (buffered) +AC_ARG_ENABLE(sim-stdio, +[ --enable-sim-stdio Specify whether to use stdio for console input/output.], +[case "${enableval}" in + yes) sim_stdio="-DWITH_STDIO=DO_USE_STDIO";; + no) sim_stdio="-DWITH_STDIO=DONT_USE_STDIO";; + *) AC_MSG_ERROR("Unknown value $enableval passed to --enable-sim-stdio"); sim_stdio="";; +esac +if test x"$silent" != x"yes" && test x"$sim_stdio" != x""; then + echo "Setting stdio flags = $sim_stdio" 6>&1 +fi],[sim_stdio=""])dnl +AC_SUBST(sim_stdio) + + +dnl --enable-sim-trace is for users of the simulator +dnl The argument is either a bitmask of things to enable [exactly what is +dnl up to the simulator], or is a comma separated list of names of tracing +dnl elements to enable. The latter is only supported on simulators that +dnl use WITH_TRACE. +AC_ARG_ENABLE(sim-trace, +[ --enable-sim-trace=opts Enable tracing flags], +[case "${enableval}" in + yes) sim_trace="-DTRACE=1 -DWITH_TRACE=-1";; + no) sim_trace="-DTRACE=0 -DWITH_TRACE=0";; + [[-0-9]]*) + sim_trace="-DTRACE='(${enableval})' -DWITH_TRACE='(${enableval})'";; + [[a-z]]*) + sim_trace="" + for x in `echo "$enableval" | sed -e "s/,/ /g"`; do + if test x"$sim_trace" = x; then + sim_trace="-DWITH_TRACE='(TRACE_$x" + else + sim_trace="${sim_trace}|TRACE_$x" + fi + done + sim_trace="$sim_trace)'" ;; +esac +if test x"$silent" != x"yes" && test x"$sim_trace" != x""; then + echo "Setting sim trace = $sim_trace" 6>&1 +fi],[sim_trace=""])dnl +AC_SUBST(sim_trace) + + +dnl --enable-sim-profile +dnl The argument is either a bitmask of things to enable [exactly what is +dnl up to the simulator], or is a comma separated list of names of profiling +dnl elements to enable. The latter is only supported on simulators that +dnl use WITH_PROFILE. +AC_ARG_ENABLE(sim-profile, +[ --enable-sim-profile=opts Enable profiling flags], +[case "${enableval}" in + yes) sim_profile="-DPROFILE=1 -DWITH_PROFILE=-1";; + no) sim_profile="-DPROFILE=0 -DWITH_PROFILE=0";; + [[-0-9]]*) + sim_profile="-DPROFILE='(${enableval})' -DWITH_PROFILE='(${enableval})'";; + [[a-z]]*) + sim_profile="" + for x in `echo "$enableval" | sed -e "s/,/ /g"`; do + if test x"$sim_profile" = x; then + sim_profile="-DWITH_PROFILE='(PROFILE_$x" + else + sim_profile="${sim_profile}|PROFILE_$x" + fi + done + sim_profile="$sim_profile)'" ;; +esac +if test x"$silent" != x"yes" && test x"$sim_profile" != x""; then + echo "Setting sim profile = $sim_profile" 6>&1 +fi],[sim_profile=""])dnl +AC_SUBST(sim_profile) + + +dnl Types used by common code +AC_TYPE_SIGNAL + +dnl Detect exe extension +AM_EXEEXT + +dnl These are available to append to as desired. +sim_link_files= +sim_link_links= + +dnl Create tconfig.h either from simulator's tconfig.in or default one +dnl in common. +sim_link_links=tconfig.h +if test -f ${srcdir}/tconfig.in +then + sim_link_files=tconfig.in +else + sim_link_files=../common/tconfig.in +fi + +# targ-vals.def points to the libc macro description file. +case "${target}" in +*-*-*) TARG_VALS_DEF=../common/nltvals.def ;; +esac +sim_link_files="${sim_link_files} ${TARG_VALS_DEF}" +sim_link_links="${sim_link_links} targ-vals.def" + +]) dnl End of SIM_AC_COMMON + + +dnl Additional SIM options that can (optionally) be configured +dnl For optional simulator options, a macro SIM_AC_OPTION_* is defined. +dnl Simulators that wish to use the relevant option specify the macro +dnl in the simulator specific configure.in file between the SIM_AC_COMMON +dnl and SIM_AC_OUTPUT lines. + + +dnl Specify the running environment. +dnl If the simulator invokes this in its configure.in then without this option +dnl the default is the user environment and all are runtime selectable. +dnl If the simulator doesn't invoke this, only the user environment is +dnl supported. +dnl ??? Until there is demonstrable value in doing something more complicated, +dnl let's not. +AC_DEFUN(SIM_AC_OPTION_ENVIRONMENT, +[ +AC_ARG_ENABLE(sim-environment, +[ --enable-sim-environment=environment Specify mixed, user, virtual or operating environment.], +[case "${enableval}" in + all | ALL) sim_environment="-DWITH_ENVIRONMENT=ALL_ENVIRONMENT";; + user | USER) sim_environment="-DWITH_ENVIRONMENT=USER_ENVIRONMENT";; + virtual | VIRTUAL) sim_environment="-DWITH_ENVIRONMENT=VIRTUAL_ENVIRONMENT";; + operating | OPERATING) sim_environment="-DWITH_ENVIRONMENT=OPERATING_ENVIRONMENT";; + *) AC_MSG_ERROR("Unknown value $enableval passed to --enable-sim-environment"); + sim_environment="";; +esac +if test x"$silent" != x"yes" && test x"$sim_environment" != x""; then + echo "Setting sim environment = $sim_environment" 6>&1 +fi], +[sim_environment="-DWITH_ENVIRONMENT=ALL_ENVIRONMENT"])dnl +]) +AC_SUBST(sim_environment) + + +dnl Specify the alignment restrictions of the target architecture. +dnl Without this option all possible alignment restrictions are accommodated. +dnl arg[1] is hardwired target alignment +dnl arg[2] is default target alignment +AC_DEFUN(SIM_AC_OPTION_ALIGNMENT, +wire_alignment="[$1]" +default_alignment="[$2]" +[ +AC_ARG_ENABLE(sim-alignment, +[ --enable-sim-alignment=align Specify strict, nonstrict or forced alignment of memory accesses.], +[case "${enableval}" in + strict | STRICT) sim_alignment="-DWITH_ALIGNMENT=STRICT_ALIGNMENT";; + nonstrict | NONSTRICT) sim_alignment="-DWITH_ALIGNMENT=NONSTRICT_ALIGNMENT";; + forced | FORCED) sim_alignment="-DWITH_ALIGNMENT=FORCED_ALIGNMENT";; + yes) if test x"$wire_alignment" != x; then + sim_alignment="-DWITH_ALIGNMENT=${wire_alignment}" + else + if test x"$default_alignment" != x; then + sim_alignment="-DWITH_ALIGNMENT=${default_alignment}" + else + echo "No hard-wired alignment for target $target" 1>&6 + sim_alignment="-DWITH_ALIGNMENT=0" + fi + fi;; + no) if test x"$default_alignment" != x; then + sim_alignment="-DWITH_DEFAULT_ALIGNMENT=${default_alignment}" + else + if test x"$wire_alignment" != x; then + sim_alignment="-DWITH_DEFAULT_ALIGNMENT=${wire_alignment}" + else + echo "No default alignment for target $target" 1>&6 + sim_alignment="-DWITH_DEFAULT_ALIGNMENT=0" + fi + fi;; + *) AC_MSG_ERROR("Unknown value $enableval passed to --enable-sim-alignment"); sim_alignment="";; +esac +if test x"$silent" != x"yes" && test x"$sim_alignment" != x""; then + echo "Setting alignment flags = $sim_alignment" 6>&1 +fi], +[if test x"$default_alignment" != x; then + sim_alignment="-DWITH_DEFAULT_ALIGNMENT=${default_alignment}" +else + if test x"$wire_alignment" != x; then + sim_alignment="-DWITH_ALIGNMENT=${wire_alignment}" + else + sim_alignment= + fi +fi])dnl +])dnl +AC_SUBST(sim_alignment) + + +dnl Conditionally compile in assertion statements. +AC_DEFUN(SIM_AC_OPTION_ASSERT, +[ +AC_ARG_ENABLE(sim-assert, +[ --enable-sim-assert Specify whether to perform random assertions.], +[case "${enableval}" in + yes) sim_assert="-DWITH_ASSERT=1";; + no) sim_assert="-DWITH_ASSERT=0";; + *) AC_MSG_ERROR("--enable-sim-assert does not take a value"); sim_assert="";; +esac +if test x"$silent" != x"yes" && test x"$sim_assert" != x""; then + echo "Setting assert flags = $sim_assert" 6>&1 +fi],[sim_assert=""])dnl +]) +AC_SUBST(sim_assert) + + + +dnl --enable-sim-bitsize is for developers of the simulator +dnl It specifies the number of BITS in the target. +dnl arg[1] is the number of bits in a word +dnl arg[2] is the number assigned to the most significant bit +dnl arg[3] is the number of bits in an address +dnl arg[4] is the number of bits in an OpenFirmware cell. +dnl FIXME: this information should be obtained from bfd/archure +AC_DEFUN(SIM_AC_OPTION_BITSIZE, +wire_word_bitsize="[$1]" +wire_word_msb="[$2]" +wire_address_bitsize="[$3]" +wire_cell_bitsize="[$4]" +[AC_ARG_ENABLE(sim-bitsize, +[ --enable-sim-bitsize=N Specify target bitsize (32 or 64).], +[sim_bitsize= +case "${enableval}" in + 64,63 | 64,63,* ) sim_bitsize="-DWITH_TARGET_WORD_BITSIZE=64 -DWITH_TARGET_WORD_MSB=63";; + 32,31 | 32,31,* ) sim_bitsize="-DWITH_TARGET_WORD_BITSIZE=32 -DWITH_TARGET_WORD_MSB=31";; + 64,0 | 64,0,* ) sim_bitsize="-DWITH_TARGET_WORD_BITSIZE=32 -DWITH_TARGET_WORD_MSB=0";; + 32,0 | 64,0,* ) sim_bitsize="-DWITH_TARGET_WORD_BITSIZE=32 -DWITH_TARGET_WORD_MSB=0";; + 32) if test x"$wire_word_msb" != x -a x"$wire_word_msb" != x0; then + sim_bitsize="-DWITH_TARGET_WORD_BITSIZE=32 -DWITH_TARGET_WORD_MSB=31" + else + sim_bitsize="-DWITH_TARGET_WORD_BITSIZE=32 -DWITH_TARGET_WORD_MSB=0" + fi ;; + 64) if test x"$wire_word_msb" != x -a x"$wire_word_msb" != x0; then + sim_bitsize="-DWITH_TARGET_WORD_BITSIZE=64 -DWITH_TARGET_WORD_MSB=63" + else + sim_bitsize="-DWITH_TARGET_WORD_BITSIZE=64 -DWITH_TARGET_WORD_MSB=0" + fi ;; + *) AC_MSG_ERROR("--enable-sim-bitsize was given $enableval. Expected 32 or 64") ;; +esac +# address bitsize +tmp=`echo "${enableval}" | sed -e "s/^[[0-9]]*,*[[0-9]]*,*//"` +case x"${tmp}" in + x ) ;; + x32 | x32,* ) sim_bitsize="${sim_bitsize} -DWITH_TARGET_ADDRESS_BITSIZE=32" ;; + x64 | x64,* ) sim_bitsize="${sim_bitsize} -DWITH_TARGET_ADDRESS_BITSIZE=64" ;; + * ) AC_MSG_ERROR("--enable-sim-bitsize was given address size $enableval. Expected 32 or 64") ;; +esac +# cell bitsize +tmp=`echo "${enableval}" | sed -e "s/^[[0-9]]*,*[[0-9*]]*,*[[0-9]]*,*//"` +case x"${tmp}" in + x ) ;; + x32 | x32,* ) sim_bitsize="${sim_bitsize} -DWITH_TARGET_CELL_BITSIZE=32" ;; + x64 | x64,* ) sim_bitsize="${sim_bitsize} -DWITH_TARGET_CELL_BITSIZE=64" ;; + * ) AC_MSG_ERROR("--enable-sim-bitsize was given cell size $enableval. Expected 32 or 64") ;; +esac +if test x"$silent" != x"yes" && test x"$sim_bitsize" != x""; then + echo "Setting bitsize flags = $sim_bitsize" 6>&1 +fi], +[sim_bitsize="" +if test x"$wire_word_bitsize" != x; then + sim_bitsize="$sim_bitsize -DWITH_TARGET_WORD_BITSIZE=$wire_word_bitsize" +fi +if test x"$wire_word_msb" != x; then + sim_bitsize="$sim_bitsize -DWITH_TARGET_WORD_MSB=$wire_word_msb" +fi +if test x"$wire_address_bitsize" != x; then + sim_bitsize="$sim_bitsize -DWITH_TARGET_ADDRESS_BITSIZE=$wire_address_bitsize" +fi +if test x"$wire_cell_bitsize" != x; then + sim_bitsize="$sim_bitsize -DWITH_TARGET_CELL_BITSIZE=$wire_cell_bitsize" +fi])dnl +]) +AC_SUBST(sim_bitsize) + + + +dnl --enable-sim-endian={yes,no,big,little} is for simulators +dnl that support both big and little endian targets. +dnl arg[1] is hardwired target endianness. +dnl arg[2] is default target endianness. +AC_DEFUN(SIM_AC_OPTION_ENDIAN, +[ +wire_endian="[$1]" +default_endian="[$2]" +AC_ARG_ENABLE(sim-endian, +[ --enable-sim-endian=endian Specify target byte endian orientation.], +[case "${enableval}" in + b*|B*) sim_endian="-DWITH_TARGET_BYTE_ORDER=BIG_ENDIAN";; + l*|L*) sim_endian="-DWITH_TARGET_BYTE_ORDER=LITTLE_ENDIAN";; + yes) if test x"$wire_endian" != x; then + sim_endian="-DWITH_TARGET_BYTE_ORDER=${wire_endian}" + else + if test x"$default_endian" != x; then + sim_endian="-DWITH_TARGET_BYTE_ORDER=${default_endian}" + else + echo "No hard-wired endian for target $target" 1>&6 + sim_endian="-DWITH_TARGET_BYTE_ORDER=0" + fi + fi;; + no) if test x"$default_endian" != x; then + sim_endian="-DWITH_DEFAULT_TARGET_BYTE_ORDER=${default_endian}" + else + if test x"$wire_endian" != x; then + sim_endian="-DWITH_DEFAULT_TARGET_BYTE_ORDER=${wire_endian}" + else + echo "No default endian for target $target" 1>&6 + sim_endian="-DWITH_DEFAULT_TARGET_BYTE_ORDER=0" + fi + fi;; + *) AC_MSG_ERROR("Unknown value $enableval for --enable-sim-endian"); sim_endian="";; +esac +if test x"$silent" != x"yes" && test x"$sim_endian" != x""; then + echo "Setting endian flags = $sim_endian" 6>&1 +fi], +[if test x"$default_endian" != x; then + sim_endian="-DWITH_DEFAULT_TARGET_BYTE_ORDER=${default_endian}" +else + if test x"$wire_endian" != x; then + sim_endian="-DWITH_TARGET_BYTE_ORDER=${wire_endian}" + else + sim_endian= + fi +fi])dnl +]) +AC_SUBST(sim_endian) + + +dnl --enable-sim-hostendian is for users of the simulator when +dnl they find that AC_C_BIGENDIAN does not function correctly +dnl (for instance in a canadian cross) +AC_DEFUN(SIM_AC_OPTION_HOSTENDIAN, +[ +AC_ARG_ENABLE(sim-hostendian, +[ --enable-sim-hostendian=end Specify host byte endian orientation.], +[case "${enableval}" in + no) sim_hostendian="-DWITH_HOST_BYTE_ORDER=0";; + b*|B*) sim_hostendian="-DWITH_HOST_BYTE_ORDER=BIG_ENDIAN";; + l*|L*) sim_hostendian="-DWITH_HOST_BYTE_ORDER=LITTLE_ENDIAN";; + *) AC_MSG_ERROR("Unknown value $enableval for --enable-sim-hostendian"); sim_hostendian="";; +esac +if test x"$silent" != x"yes" && test x"$sim_hostendian" != x""; then + echo "Setting hostendian flags = $sim_hostendian" 6>&1 +fi],[ +if test "x$cross_compiling" = "xno"; then + AC_C_BIGENDIAN + if test $ac_cv_c_bigendian = yes; then + sim_hostendian="-DWITH_HOST_BYTE_ORDER=BIG_ENDIAN" + else + sim_hostendian="-DWITH_HOST_BYTE_ORDER=LITTLE_ENDIAN" + fi +else + sim_hostendian="-DWITH_HOST_BYTE_ORDER=0" +fi])dnl +]) +AC_SUBST(sim_hostendian) + + +dnl --enable-sim-float is for developers of the simulator +dnl It specifies the presence of hardware floating point +dnl And optionally the bitsize of the floating point register. +dnl arg[1] specifies the presence (or absence) of floating point hardware +dnl arg[2] specifies the number of bits in a floating point register +AC_DEFUN(SIM_AC_OPTION_FLOAT, +[ +default_sim_float="[$1]" +default_sim_float_bitsize="[$2]" +AC_ARG_ENABLE(sim-float, +[ --enable-sim-float Specify that the target processor has floating point hardware.], +[case "${enableval}" in + yes | hard) sim_float="-DWITH_FLOATING_POINT=HARD_FLOATING_POINT";; + no | soft) sim_float="-DWITH_FLOATING_POINT=SOFT_FLOATING_POINT";; + 32) sim_float="-DWITH_FLOATING_POINT=HARD_FLOATING_POINT -DWITH_TARGET_FLOATING_POINT_BITSIZE=32";; + 64) sim_float="-DWITH_FLOATING_POINT=HARD_FLOATING_POINT -DWITH_TARGET_FLOATING_POINT_BITSIZE=64";; + *) AC_MSG_ERROR("Unknown value $enableval passed to --enable-sim-float"); sim_float="";; +esac +if test x"$silent" != x"yes" && test x"$sim_float" != x""; then + echo "Setting float flags = $sim_float" 6>&1 +fi],[ +sim_float= +if test x"${default_sim_float}" != x""; then + sim_float="-DWITH_FLOATING_POINT=${default_sim_float}" +fi +if test x"${default_sim_float_bitsize}" != x""; then + sim_float="$sim_float -DWITH_TARGET_FLOATING_POINT_BITSIZE=${default_sim_float_bitsize}" +fi +])dnl +]) +AC_SUBST(sim_float) + + +dnl The argument is the default cache size if none is specified. +AC_DEFUN(SIM_AC_OPTION_SCACHE, +[ +default_sim_scache="ifelse([$1],,0,[$1])" +AC_ARG_ENABLE(sim-scache, +[ --enable-sim-scache=size Specify simulator execution cache size.], +[case "${enableval}" in + yes) sim_scache="-DWITH_SCACHE=${default_sim_scache}";; + no) sim_scache="-DWITH_SCACHE=0" ;; + [[0-9]]*) sim_cache=${enableval};; + *) AC_MSG_ERROR("Bad value $enableval passed to --enable-sim-scache"); + sim_scache="";; +esac +if test x"$silent" != x"yes" && test x"$sim_scache" != x""; then + echo "Setting scache size = $sim_scache" 6>&1 +fi],[sim_scache="-DWITH_SCACHE=${default_sim_scache}"]) +]) +AC_SUBST(sim_scache) + + +dnl The argument is the default model if none is specified. +AC_DEFUN(SIM_AC_OPTION_DEFAULT_MODEL, +[ +default_sim_default_model="ifelse([$1],,0,[$1])" +AC_ARG_ENABLE(sim-default-model, +[ --enable-sim-default-model=model Specify default model to simulate.], +[case "${enableval}" in + yes|no) AC_MSG_ERROR("Missing argument to --enable-sim-default-model");; + *) sim_default_model="-DWITH_DEFAULT_MODEL='\"${enableval}\"'";; +esac +if test x"$silent" != x"yes" && test x"$sim_default_model" != x""; then + echo "Setting default model = $sim_default_model" 6>&1 +fi],[sim_default_model="-DWITH_DEFAULT_MODEL='\"${default_sim_default_model}\"'"]) +]) +AC_SUBST(sim_default_model) + + +dnl --enable-sim-hardware is for users of the simulator +dnl arg[1] Enable sim-hw by default? ("yes" or "no") +dnl arg[2] is a space separated list of devices that override the defaults +dnl arg[3] is a space separated list of extra target specific devices. +AC_DEFUN(SIM_AC_OPTION_HARDWARE, +[ +if test x"[$1]" = x"yes"; then + sim_hw_p=yes +else + sim_hw_p=no +fi +if test "[$2]"; then + hardware="core pal glue" +else + hardware="core pal glue [$3]" +fi +sim_hw_cflags="-DWITH_HW=1" +sim_hw="$hardware" +sim_hw_objs="\$(SIM_COMMON_HW_OBJS) `echo $sim_hw | sed -e 's/\([[^ ]][[^ ]]*\)/dv-\1.o/g'`" +AC_ARG_ENABLE(sim-hardware, +[ --enable-sim-hardware=LIST Specify the hardware to be included in the build.], +[ +case "${enableval}" in + yes) sim_hw_p=yes;; + no) sim_hw_p=no;; + ,*) sim_hw_p=yes; hardware="${hardware} `echo ${enableval} | sed -e 's/,/ /'`";; + *,) sim_hw_p=yes; hardware="`echo ${enableval} | sed -e 's/,/ /'` ${hardware}";; + *) sim_hw_p=yes; hardware="`echo ${enableval} | sed -e 's/,/ /'`"'';; +esac +if test "$sim_hw_p" != yes; then + sim_hw_objs= + sim_hw_cflags="-DWITH_HW=0" + sim_hw= +else + sim_hw_cflags="-DWITH_HW=1" + # remove duplicates + sim_hw="" + sim_hw_objs="\$(SIM_COMMON_HW_OBJS)" + for i in x $hardware ; do + case " $f " in + x) ;; + *" $i "*) ;; + *) sim_hw="$sim_hw $i" ; sim_hw_objs="$sim_hw_objs dv-$i.o";; + esac + done +fi +if test x"$silent" != x"yes" && test "$sim_hw_p" = "yes"; then + echo "Setting hardware to $sim_hw_cflags, $sim_hw, $sim_hw_objs" +fi],[ +if test "$sim_hw_p" != yes; then + sim_hw_objs= + sim_hw_cflags="-DWITH_HW=0" + sim_hw= +fi +if test x"$silent" != x"yes"; then + echo "Setting hardware to $sim_hw_cflags, $sim_hw, $sim_hw_objs" +fi])dnl +]) +AC_SUBST(sim_hw_cflags) +AC_SUBST(sim_hw_objs) +AC_SUBST(sim_hw) + + +dnl --enable-sim-inline is for users that wish to ramp up the simulator's +dnl performance by inlining functions. +dnl Guarantee that unconfigured simulators do not do any inlining +sim_inline="-DDEFAULT_INLINE=0" +AC_DEFUN(SIM_AC_OPTION_INLINE, +[ +default_sim_inline="ifelse([$1],,,-DDEFAULT_INLINE=[$1])" +AC_ARG_ENABLE(sim-inline, +[ --enable-sim-inline=inlines Specify which functions should be inlined.], +[sim_inline="" +case "$enableval" in + no) sim_inline="-DDEFAULT_INLINE=0";; + 0) sim_inline="-DDEFAULT_INLINE=0";; + yes | 2) sim_inline="-DDEFAULT_INLINE=ALL_C_INLINE";; + 1) sim_inline="-DDEFAULT_INLINE=INLINE_LOCALS";; + *) for x in `echo "$enableval" | sed -e "s/,/ /g"`; do + new_flag="" + case "$x" in + *_INLINE=*) new_flag="-D$x";; + *=*) new_flag=`echo "$x" | sed -e "s/=/_INLINE=/" -e "s/^/-D/"`;; + *_INLINE) new_flag="-D$x=ALL_C_INLINE";; + *) new_flag="-D$x""_INLINE=ALL_C_INLINE";; + esac + if test x"$sim_inline" = x""; then + sim_inline="$new_flag" + else + sim_inline="$sim_inline $new_flag" + fi + done;; +esac +if test x"$silent" != x"yes" && test x"$sim_inline" != x""; then + echo "Setting inline flags = $sim_inline" 6>&1 +fi],[ +if test "x$cross_compiling" = "xno"; then + if test x"$GCC" != "x" -a x"${default_sim_inline}" != "x" ; then + sim_inline="${default_sim_inline}" + if test x"$silent" != x"yes"; then + echo "Setting inline flags = $sim_inline" 6>&1 + fi + else + sim_inline="" + fi +else + sim_inline="-DDEFAULT_INLINE=0" +fi])dnl +]) +AC_SUBST(sim_inline) + + +AC_DEFUN(SIM_AC_OPTION_PACKAGES, +[ +AC_ARG_ENABLE(sim-packages, +[ --enable-sim-packages=list Specify the packages to be included in the build.], +[packages=disklabel +case "${enableval}" in + yes) ;; + no) AC_MSG_ERROR("List of packages must be specified for --enable-sim-packages"); packages="";; + ,*) packages="${packages}${enableval}";; + *,) packages="${enableval}${packages}";; + *) packages="${enableval}"'';; +esac +sim_pk_src=`echo $packages | sed -e 's/,/.c pk_/g' -e 's/^/pk_/' -e 's/$/.c/'` +sim_pk_obj=`echo $sim_pk_src | sed -e 's/\.c/.o/g'` +if test x"$silent" != x"yes" && test x"$packages" != x""; then + echo "Setting packages to $sim_pk_src, $sim_pk_obj" +fi],[packages=disklabel +sim_pk_src=`echo $packages | sed -e 's/,/.c pk_/g' -e 's/^/pk_/' -e 's/$/.c/'` +sim_pk_obj=`echo $sim_pk_src | sed -e 's/\.c/.o/g'` +if test x"$silent" != x"yes"; then + echo "Setting packages to $sim_pk_src, $sim_pk_obj" +fi])dnl +]) +AC_SUBST(sim_packages) + + +AC_DEFUN(SIM_AC_OPTION_REGPARM, +[ +AC_ARG_ENABLE(sim-regparm, +[ --enable-sim-regparm=nr-parm Pass parameters in registers instead of on the stack - x86/GCC specific.], +[case "${enableval}" in + 0*|1*|2*|3*|4*|5*|6*|7*|8*|9*) sim_regparm="-DWITH_REGPARM=${enableval}";; + no) sim_regparm="" ;; + yes) sim_regparm="-DWITH_REGPARM=3";; + *) AC_MSG_ERROR("Unknown value $enableval for --enable-sim-regparm"); sim_regparm="";; +esac +if test x"$silent" != x"yes" && test x"$sim_regparm" != x""; then + echo "Setting regparm flags = $sim_regparm" 6>&1 +fi],[sim_regparm=""])dnl +]) +AC_SUBST(sim_regparm) + + +AC_DEFUN(SIM_AC_OPTION_RESERVED_BITS, +[ +default_sim_reserved_bits="ifelse([$1],,1,[$1])" +AC_ARG_ENABLE(sim-reserved-bits, +[ --enable-sim-reserved-bits Specify whether to check reserved bits in instruction.], +[case "${enableval}" in + yes) sim_reserved_bits="-DWITH_RESERVED_BITS=1";; + no) sim_reserved_bits="-DWITH_RESERVED_BITS=0";; + *) AC_MSG_ERROR("--enable-sim-reserved-bits does not take a value"); sim_reserved_bits="";; +esac +if test x"$silent" != x"yes" && test x"$sim_reserved_bits" != x""; then + echo "Setting reserved flags = $sim_reserved_bits" 6>&1 +fi],[sim_reserved_bits="-DWITH_RESERVED_BITS=${default_sim_reserved_bits}"])dnl +]) +AC_SUBST(sim_reserved_bits) + + +AC_DEFUN(SIM_AC_OPTION_SMP, +[ +default_sim_smp="ifelse([$1],,5,[$1])" +AC_ARG_ENABLE(sim-smp, +[ --enable-sim-smp=n Specify number of processors to configure for (default ${default_sim_smp}).], +[case "${enableval}" in + yes) sim_smp="-DWITH_SMP=5" ; sim_igen_smp="-N 5";; + no) sim_smp="-DWITH_SMP=0" ; sim_igen_smp="-N 0";; + *) sim_smp="-DWITH_SMP=$enableval" ; sim_igen_smp="-N $enableval";; +esac +if test x"$silent" != x"yes" && test x"$sim_smp" != x""; then + echo "Setting smp flags = $sim_smp" 6>&1 +fi],[sim_smp="-DWITH_SMP=${default_sim_smp}" ; sim_igen_smp="-N ${default_sim_smp}" +if test x"$silent" != x"yes"; then + echo "Setting smp flags = $sim_smp" 6>&1 +fi])dnl +]) +AC_SUBST(sim_smp) + + +AC_DEFUN(SIM_AC_OPTION_STDCALL, +[ +AC_ARG_ENABLE(sim-stdcall, +[ --enable-sim-stdcall=type Use an alternative function call/return mechanism - x86/GCC specific.], +[case "${enableval}" in + no) sim_stdcall="" ;; + std*) sim_stdcall="-DWITH_STDCALL=1";; + yes) sim_stdcall="-DWITH_STDCALL=1";; + *) AC_MSG_ERROR("Unknown value $enableval for --enable-sim-stdcall"); sim_stdcall="";; +esac +if test x"$silent" != x"yes" && test x"$sim_stdcall" != x""; then + echo "Setting function call flags = $sim_stdcall" 6>&1 +fi],[sim_stdcall=""])dnl +]) +AC_SUBST(sim_stdcall) + + +AC_DEFUN(SIM_AC_OPTION_XOR_ENDIAN, +[ +default_sim_xor_endian="ifelse([$1],,8,[$1])" +AC_ARG_ENABLE(sim-xor-endian, +[ --enable-sim-xor-endian=n Specify number bytes involved in XOR bi-endian mode (default ${default_sim_xor_endian}).], +[case "${enableval}" in + yes) sim_xor_endian="-DWITH_XOR_ENDIAN=8";; + no) sim_xor_endian="-DWITH_XOR_ENDIAN=0";; + *) sim_xor_endian="-DWITH_XOR_ENDIAN=$enableval";; +esac +if test x"$silent" != x"yes" && test x"$sim_xor_endian" != x""; then + echo "Setting xor-endian flag = $sim_xor_endian" 6>&1 +fi],[sim_xor_endian="-DWITH_XOR_ENDIAN=${default_sim_xor_endian}"])dnl +]) +AC_SUBST(sim_xor_endian) + + +dnl --enable-build-warnings is for developers of the simulator. +dnl it enables extra GCC specific warnings. +AC_DEFUN(SIM_AC_OPTION_WARNINGS, +[ +AC_ARG_ENABLE(build-warnings, +[ --enable-build-warnings[=LIST] Enable build-time compiler warnings], +[build_warnings="-Wall -Wpointer-arith -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations" +case "${enableval}" in + yes) ;; + no) build_warnings="-w";; + ,*) t=`echo "${enableval}" | sed -e "s/,/ /g"` + build_warnings="${build_warnings} ${t}";; + *,) t=`echo "${enableval}" | sed -e "s/,/ /g"` + build_warnings="${t} ${build_warnings}";; + *) build_warnings=`echo "${enableval}" | sed -e "s/,/ /g"`;; +esac +if test x"$silent" != x"yes" && test x"$build_warnings" != x""; then + echo "Setting warning flags = $build_warnings" 6>&1 +fi],[build_warnings=""])dnl +]) +AC_SUBST(build_warnings) + + +dnl Generate the Makefile in a target specific directory. +dnl Substitutions aren't performed on the file in AC_SUBST_FILE, +dnl so this is a cover macro to tuck the details away of how we cope. +dnl We cope by having autoconf generate two files and then merge them into +dnl one afterwards. The two pieces of the common fragment are inserted into +dnl the target's fragment at the appropriate points. + +AC_DEFUN(SIM_AC_OUTPUT, +[ +AC_LINK_FILES($sim_link_files, $sim_link_links) +AC_OUTPUT(Makefile.sim:Makefile.in Make-common.sim:../common/Make-common.in .gdbinit:../common/gdbinit.in, +[case "x$CONFIG_FILES" in + xMakefile*) + echo "Merging Makefile.sim+Make-common.sim into Makefile ..." + rm -f Makesim1.tmp Makesim2.tmp Makefile + sed -n -e '/^## COMMON_PRE_/,/^## End COMMON_PRE_/ p' Makesim1.tmp + sed -n -e '/^## COMMON_POST_/,/^## End COMMON_POST_/ p' Makesim2.tmp + sed -e '/^## COMMON_PRE_/ r Makesim1.tmp' \ + -e '/^## COMMON_POST_/ r Makesim2.tmp' \ + Makefile + rm -f Makefile.sim Make-common.sim Makesim1.tmp Makesim2.tmp + ;; + esac + case "x$CONFIG_HEADERS" in xconfig.h:config.in) echo > stamp-h ;; esac +]) +]) + +# This file is derived from `gettext.m4'. The difference is that the +# included macros assume Cygnus-style source and build trees. + +# Macro to add for using GNU gettext. +# Ulrich Drepper , 1995. +# +# This file file be copied and used freely without restrictions. It can +# be used in projects which are not available under the GNU Public License +# but which still want to provide support for the GNU gettext functionality. +# Please note that the actual code is *not* freely available. + +# serial 3 + +AC_DEFUN(CY_WITH_NLS, + [AC_MSG_CHECKING([whether NLS is requested]) + dnl Default is enabled NLS + AC_ARG_ENABLE(nls, + [ --disable-nls do not use Native Language Support], + USE_NLS=$enableval, USE_NLS=yes) + AC_MSG_RESULT($USE_NLS) + AC_SUBST(USE_NLS) + + USE_INCLUDED_LIBINTL=no + + dnl If we use NLS figure out what method + if test "$USE_NLS" = "yes"; then + AC_DEFINE(ENABLE_NLS) + AC_MSG_CHECKING([whether included gettext is requested]) + AC_ARG_WITH(included-gettext, + [ --with-included-gettext use the GNU gettext library included here], + nls_cv_force_use_gnu_gettext=$withval, + nls_cv_force_use_gnu_gettext=no) + AC_MSG_RESULT($nls_cv_force_use_gnu_gettext) + + nls_cv_use_gnu_gettext="$nls_cv_force_use_gnu_gettext" + if test "$nls_cv_force_use_gnu_gettext" != "yes"; then + dnl User does not insist on using GNU NLS library. Figure out what + dnl to use. If gettext or catgets are available (in this order) we + dnl use this. Else we have to fall back to GNU NLS library. + dnl catgets is only used if permitted by option --with-catgets. + nls_cv_header_intl= + nls_cv_header_libgt= + CATOBJEXT=NONE + + AC_CHECK_HEADER(libintl.h, + [AC_CACHE_CHECK([for gettext in libc], gt_cv_func_gettext_libc, + [AC_TRY_LINK([#include ], [return (int) gettext ("")], + gt_cv_func_gettext_libc=yes, gt_cv_func_gettext_libc=no)]) + + if test "$gt_cv_func_gettext_libc" != "yes"; then + AC_CHECK_LIB(intl, bindtextdomain, + [AC_CACHE_CHECK([for gettext in libintl], + gt_cv_func_gettext_libintl, + [AC_TRY_LINK([], [return (int) gettext ("")], + gt_cv_func_gettext_libintl=yes, + gt_cv_func_gettext_libintl=no)])]) + fi + + if test "$gt_cv_func_gettext_libc" = "yes" \ + || test "$gt_cv_func_gettext_libintl" = "yes"; then + AC_DEFINE(HAVE_GETTEXT) + AM_PATH_PROG_WITH_TEST(MSGFMT, msgfmt, + [test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"], no)dnl + if test "$MSGFMT" != "no"; then + AC_CHECK_FUNCS(dcgettext) + AC_PATH_PROG(GMSGFMT, gmsgfmt, $MSGFMT) + AM_PATH_PROG_WITH_TEST(XGETTEXT, xgettext, + [test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"], :) + AC_TRY_LINK(, [extern int _nl_msg_cat_cntr; + return _nl_msg_cat_cntr], + [CATOBJEXT=.gmo + DATADIRNAME=share], + [CATOBJEXT=.mo + DATADIRNAME=lib]) + INSTOBJEXT=.mo + fi + fi + ]) + + dnl In the standard gettext, we would now check for catgets. + dnl However, we never want to use catgets for our releases. + + if test "$CATOBJEXT" = "NONE"; then + dnl Neither gettext nor catgets in included in the C library. + dnl Fall back on GNU gettext library. + nls_cv_use_gnu_gettext=yes + fi + fi + + if test "$nls_cv_use_gnu_gettext" = "yes"; then + dnl Mark actions used to generate GNU NLS library. + INTLOBJS="\$(GETTOBJS)" + AM_PATH_PROG_WITH_TEST(MSGFMT, msgfmt, + [test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"], msgfmt) + AC_PATH_PROG(GMSGFMT, gmsgfmt, $MSGFMT) + AM_PATH_PROG_WITH_TEST(XGETTEXT, xgettext, + [test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"], :) + AC_SUBST(MSGFMT) + USE_INCLUDED_LIBINTL=yes + CATOBJEXT=.gmo + INSTOBJEXT=.mo + DATADIRNAME=share + INTLDEPS='$(top_builddir)/../intl/libintl.a' + INTLLIBS=$INTLDEPS + LIBS=`echo $LIBS | sed -e 's/-lintl//'` + nls_cv_header_intl=libintl.h + nls_cv_header_libgt=libgettext.h + fi + + dnl Test whether we really found GNU xgettext. + if test "$XGETTEXT" != ":"; then + dnl If it is no GNU xgettext we define it as : so that the + dnl Makefiles still can work. + if $XGETTEXT --omit-header /dev/null 2> /dev/null; then + : ; + else + AC_MSG_RESULT( + [found xgettext programs is not GNU xgettext; ignore it]) + XGETTEXT=":" + fi + fi + + # We need to process the po/ directory. + POSUB=po + else + DATADIRNAME=share + nls_cv_header_intl=libintl.h + nls_cv_header_libgt=libgettext.h + fi + + # If this is used in GNU gettext we have to set USE_NLS to `yes' + # because some of the sources are only built for this goal. + if test "$PACKAGE" = gettext; then + USE_NLS=yes + USE_INCLUDED_LIBINTL=yes + fi + + dnl These rules are solely for the distribution goal. While doing this + dnl we only have to keep exactly one list of the available catalogs + dnl in configure.in. + for lang in $ALL_LINGUAS; do + GMOFILES="$GMOFILES $lang.gmo" + POFILES="$POFILES $lang.po" + done + + dnl Make all variables we use known to autoconf. + AC_SUBST(USE_INCLUDED_LIBINTL) + AC_SUBST(CATALOGS) + AC_SUBST(CATOBJEXT) + AC_SUBST(DATADIRNAME) + AC_SUBST(GMOFILES) + AC_SUBST(INSTOBJEXT) + AC_SUBST(INTLDEPS) + AC_SUBST(INTLLIBS) + AC_SUBST(INTLOBJS) + AC_SUBST(POFILES) + AC_SUBST(POSUB) + ]) + +AC_DEFUN(CY_GNU_GETTEXT, + [AC_REQUIRE([AC_PROG_MAKE_SET])dnl + AC_REQUIRE([AC_PROG_CC])dnl + AC_REQUIRE([AC_PROG_RANLIB])dnl + AC_REQUIRE([AC_ISC_POSIX])dnl + AC_REQUIRE([AC_HEADER_STDC])dnl + AC_REQUIRE([AC_C_CONST])dnl + AC_REQUIRE([AC_C_INLINE])dnl + AC_REQUIRE([AC_TYPE_OFF_T])dnl + AC_REQUIRE([AC_TYPE_SIZE_T])dnl + AC_REQUIRE([AC_FUNC_ALLOCA])dnl + AC_REQUIRE([AC_FUNC_MMAP])dnl + + AC_CHECK_HEADERS([argz.h limits.h locale.h nl_types.h malloc.h string.h \ +unistd.h values.h sys/param.h]) + AC_CHECK_FUNCS([getcwd munmap putenv setenv setlocale strchr strcasecmp \ +__argz_count __argz_stringify __argz_next]) + + if test "${ac_cv_func_stpcpy+set}" != "set"; then + AC_CHECK_FUNCS(stpcpy) + fi + if test "${ac_cv_func_stpcpy}" = "yes"; then + AC_DEFINE(HAVE_STPCPY) + fi + + AM_LC_MESSAGES + CY_WITH_NLS + + if test "x$CATOBJEXT" != "x"; then + if test "x$ALL_LINGUAS" = "x"; then + LINGUAS= + else + AC_MSG_CHECKING(for catalogs to be installed) + NEW_LINGUAS= + for lang in ${LINGUAS=$ALL_LINGUAS}; do + case "$ALL_LINGUAS" in + *$lang*) NEW_LINGUAS="$NEW_LINGUAS $lang" ;; + esac + done + LINGUAS=$NEW_LINGUAS + AC_MSG_RESULT($LINGUAS) + fi + + dnl Construct list of names of catalog files to be constructed. + if test -n "$LINGUAS"; then + for lang in $LINGUAS; do CATALOGS="$CATALOGS $lang$CATOBJEXT"; done + fi + fi + + dnl The reference to in the installed file + dnl must be resolved because we cannot expect the users of this + dnl to define HAVE_LOCALE_H. + if test $ac_cv_header_locale_h = yes; then + INCLUDE_LOCALE_H="#include " + else + INCLUDE_LOCALE_H="\ +/* The system does not provide the header . Take care yourself. */" + fi + AC_SUBST(INCLUDE_LOCALE_H) + + dnl Determine which catalog format we have (if any is needed) + dnl For now we know about two different formats: + dnl Linux libc-5 and the normal X/Open format + if test -f $srcdir/po2tbl.sed.in; then + if test "$CATOBJEXT" = ".cat"; then + AC_CHECK_HEADER(linux/version.h, msgformat=linux, msgformat=xopen) + + dnl Transform the SED scripts while copying because some dumb SEDs + dnl cannot handle comments. + sed -e '/^#/d' $srcdir/$msgformat-msg.sed > po2msg.sed + fi + dnl po2tbl.sed is always needed. + sed -e '/^#.*[^\\]$/d' -e '/^#$/d' \ + $srcdir/po2tbl.sed.in > po2tbl.sed + fi + + dnl In the intl/Makefile.in we have a special dependency which makes + dnl only sense for gettext. We comment this out for non-gettext + dnl packages. + if test "$PACKAGE" = "gettext"; then + GT_NO="#NO#" + GT_YES= + else + GT_NO= + GT_YES="#YES#" + fi + AC_SUBST(GT_NO) + AC_SUBST(GT_YES) + + MKINSTALLDIRS="\$(srcdir)/../../mkinstalldirs" + AC_SUBST(MKINSTALLDIRS) + + dnl *** For now the libtool support in intl/Makefile is not for real. + l= + AC_SUBST(l) + + dnl Generate list of files to be processed by xgettext which will + dnl be included in po/Makefile. But only do this if the po directory + dnl exists in srcdir. + if test -d $srcdir/po; then + test -d po || mkdir po + if test "x$srcdir" != "x."; then + if test "x`echo $srcdir | sed 's@/.*@@'`" = "x"; then + posrcprefix="$srcdir/" + else + posrcprefix="../$srcdir/" + fi + else + posrcprefix="../" + fi + rm -f po/POTFILES + sed -e "/^#/d" -e "/^\$/d" -e "s,.*, $posrcprefix& \\\\," -e "\$s/\(.*\) \\\\/\1/" \ + < $srcdir/po/POTFILES.in > po/POTFILES + fi + ]) + +# Search path for a program which passes the given test. +# Ulrich Drepper , 1996. +# +# This file file be copied and used freely without restrictions. It can +# be used in projects which are not available under the GNU Public License +# but which still want to provide support for the GNU gettext functionality. +# Please note that the actual code is *not* freely available. + +# serial 1 + +dnl AM_PATH_PROG_WITH_TEST(VARIABLE, PROG-TO-CHECK-FOR, +dnl TEST-PERFORMED-ON-FOUND_PROGRAM [, VALUE-IF-NOT-FOUND [, PATH]]) +AC_DEFUN(AM_PATH_PROG_WITH_TEST, +[# Extract the first word of "$2", so it can be a program name with args. +set dummy $2; ac_word=[$]2 +AC_MSG_CHECKING([for $ac_word]) +AC_CACHE_VAL(ac_cv_path_$1, +[case "[$]$1" in + /*) + ac_cv_path_$1="[$]$1" # Let the user override the test with a path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in ifelse([$5], , $PATH, [$5]); do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if [$3]; then + ac_cv_path_$1="$ac_dir/$ac_word" + break + fi + fi + done + IFS="$ac_save_ifs" +dnl If no 4th arg is given, leave the cache variable unset, +dnl so AC_PATH_PROGS will keep looking. +ifelse([$4], , , [ test -z "[$]ac_cv_path_$1" && ac_cv_path_$1="$4" +])dnl + ;; +esac])dnl +$1="$ac_cv_path_$1" +if test -n "[$]$1"; then + AC_MSG_RESULT([$]$1) +else + AC_MSG_RESULT(no) +fi +AC_SUBST($1)dnl +]) + +# Check whether LC_MESSAGES is available in . +# Ulrich Drepper , 1995. +# +# This file file be copied and used freely without restrictions. It can +# be used in projects which are not available under the GNU Public License +# but which still want to provide support for the GNU gettext functionality. +# Please note that the actual code is *not* freely available. + +# serial 1 + +AC_DEFUN(AM_LC_MESSAGES, + [if test $ac_cv_header_locale_h = yes; then + AC_CACHE_CHECK([for LC_MESSAGES], am_cv_val_LC_MESSAGES, + [AC_TRY_LINK([#include ], [return LC_MESSAGES], + am_cv_val_LC_MESSAGES=yes, am_cv_val_LC_MESSAGES=no)]) + if test $am_cv_val_LC_MESSAGES = yes; then + AC_DEFINE(HAVE_LC_MESSAGES) + fi + fi]) + +# Check to see if we're running under Cygwin32, without using +# AC_CANONICAL_*. If so, set output variable CYGWIN32 to "yes". +# Otherwise set it to "no". + +dnl AM_CYGWIN32() +dnl You might think we can do this by checking for a cygwin32-specific +dnl cpp define. +AC_DEFUN(AM_CYGWIN32, +[AC_CACHE_CHECK(for Cygwin32 environment, am_cv_cygwin32, +[AC_TRY_COMPILE(,[int main () { return __CYGWIN32__; }], +am_cv_cygwin32=yes, am_cv_cygwin32=no) +rm -f conftest*]) +CYGWIN32= +test "$am_cv_cygwin32" = yes && CYGWIN32=yes]) + +# Check to see if we're running under Win32, without using +# AC_CANONICAL_*. If so, set output variable EXEEXT to ".exe". +# Otherwise set it to "". + +dnl AM_EXEEXT() +dnl This knows we add .exe if we're building in the Cygwin32 +dnl environment. But if we're not, then it compiles a test program +dnl to see if there is a suffix for executables. +AC_DEFUN(AM_EXEEXT, +dnl AC_REQUIRE([AC_PROG_CC])AC_REQUIRE([AM_CYGWIN32]) +AC_MSG_CHECKING([for executable suffix]) +[AC_CACHE_VAL(am_cv_exeext, +[if test "$CYGWIN32" = yes; then +am_cv_exeext=.exe +else +cat > am_c_test.c << 'EOF' +int main() { +/* Nothing needed here */ +} +EOF +${CC-cc} -o am_c_test $CFLAGS $CPPFLAGS $LDFLAGS am_c_test.c $LIBS 1>&5 +am_cv_exeext=`ls am_c_test.* | grep -v am_c_test.c | sed -e s/am_c_test//` +rm -f am_c_test*]) +test x"${am_cv_exeext}" = x && am_cv_exeext=no +fi +EXEEXT="" +test x"${am_cv_exeext}" != xno && EXEEXT=${am_cv_exeext} +AC_MSG_RESULT(${am_cv_exeext}) +AC_SUBST(EXEEXT)]) + + +dnl --enable-cgen-maint support +AC_DEFUN(SIM_AC_OPTION_CGEN_MAINT, +[ +cgen_maint=no +dnl Default is to use one in build tree. +cgen=../../cgen/cgen +cgendir='$(srcdir)/../../cgen' +dnl Having --enable-maintainer-mode take arguments is another way to go. +dnl ??? One can argue --with is more appropriate if one wants to specify +dnl a directory name, but what we're doing here is an enable/disable kind +dnl of thing and specifying both --enable and --with is klunky. +dnl If you reeely want this to be --with, go ahead and change it. +AC_ARG_ENABLE(cgen-maint, +[ --enable-cgen-maint[=DIR] build cgen generated files], +[case "${enableval}" in + yes) cgen_maint=yes ;; + no) cgen_maint=no ;; + *) + # argument is cgen install directory (not implemented yet). + # Having a `share' directory might be more appropriate for the .scm, + # .cpu, etc. files. + cgendir=${cgen_maint}/lib/cgen + cgen=${cgendir}/bin/cgen + ;; +esac])dnl +dnl AM_CONDITIONAL(CGEN_MAINT, test x${cgen_maint} != xno) +if test x${cgen_maint} != xno ; then + CGEN_MAINT='' +else + CGEN_MAINT='#' +fi +AC_SUBST(CGEN_MAINT) +AC_SUBST(cgendir) +AC_SUBST(cgen) +]) diff --git a/sim/common/callback.c b/sim/common/callback.c new file mode 100644 index 00000000000..e8a28c43f3b --- /dev/null +++ b/sim/common/callback.c @@ -0,0 +1,810 @@ +/* Remote target callback routines. + Copyright 1995, 1996, 1997 Free Software Foundation, Inc. + Contributed by Cygnus Solutions. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GAS; see the file COPYING. If not, write to the Free Software + Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* This file provides a standard way for targets to talk to the host OS + level. */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "ansidecl.h" +#ifdef ANSI_PROTOTYPES +#include +#else +#include +#endif +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#else +#ifdef HAVE_STRINGS_H +#include +#endif +#endif +#include +#include +#include +#include +#include +#include "callback.h" +#include "targ-vals.h" + +#ifdef HAVE_UNISTD_H +#include +#endif + +/* ??? sim_cb_printf should be cb_printf, but until the callback support is + broken out of the simulator directory, these are here to not require + sim-utils.h. */ +void sim_cb_printf PARAMS ((host_callback *, const char *, ...)); +void sim_cb_eprintf PARAMS ((host_callback *, const char *, ...)); + +extern CB_TARGET_DEFS_MAP cb_init_syscall_map[]; +extern CB_TARGET_DEFS_MAP cb_init_errno_map[]; +extern CB_TARGET_DEFS_MAP cb_init_open_map[]; + +extern int system PARAMS ((const char *)); + +static int os_init PARAMS ((host_callback *)); +static int os_shutdown PARAMS ((host_callback *)); +static int os_unlink PARAMS ((host_callback *, const char *)); +static long os_time PARAMS ((host_callback *, long *)); +static int os_system PARAMS ((host_callback *, const char *)); +static int os_rename PARAMS ((host_callback *, const char *, const char *)); +static int os_write_stdout PARAMS ((host_callback *, const char *, int)); +static void os_flush_stdout PARAMS ((host_callback *)); +static int os_write_stderr PARAMS ((host_callback *, const char *, int)); +static void os_flush_stderr PARAMS ((host_callback *)); +static int os_write PARAMS ((host_callback *, int, const char *, int)); +static int os_read_stdin PARAMS ((host_callback *, char *, int)); +static int os_read PARAMS ((host_callback *, int, char *, int)); +static int os_open PARAMS ((host_callback *, const char *, int)); +static int os_lseek PARAMS ((host_callback *, int, long, int)); +static int os_isatty PARAMS ((host_callback *, int)); +static int os_get_errno PARAMS ((host_callback *)); +static int os_close PARAMS ((host_callback *, int)); +static void os_vprintf_filtered PARAMS ((host_callback *, const char *, va_list)); +static void os_evprintf_filtered PARAMS ((host_callback *, const char *, va_list)); +static void os_error PARAMS ((host_callback *, const char *, ...)); +static int fdmap PARAMS ((host_callback *, int)); +static int fdbad PARAMS ((host_callback *, int)); +static int wrap PARAMS ((host_callback *, int)); + +/* Set the callback copy of errno from what we see now. */ + +static int +wrap (p, val) + host_callback *p; + int val; +{ + p->last_errno = errno; + return val; +} + +/* Make sure the FD provided is ok. If not, return non-zero + and set errno. */ + +static int +fdbad (p, fd) + host_callback *p; + int fd; +{ + if (fd < 0 || fd > MAX_CALLBACK_FDS || !p->fdopen[fd]) + { + p->last_errno = EINVAL; + return -1; + } + return 0; +} + +static int +fdmap (p, fd) + host_callback *p; + int fd; +{ + return p->fdmap[fd]; +} + +static int +os_close (p, fd) + host_callback *p; + int fd; +{ + int result; + + result = fdbad (p, fd); + if (result) + return result; + result = wrap (p, close (fdmap (p, fd))); + if (result == 0 && !p->alwaysopen[fd]) + p->fdopen[fd] = 0; + + return result; +} + + +/* taken from gdb/util.c:notice_quit() - should be in a library */ + + +#if defined(__GO32__) || defined (_MSC_VER) +static int +os_poll_quit (p) + host_callback *p; +{ +#if defined(__GO32__) + int kbhit (); + int getkey (); + if (kbhit ()) + { + int k = getkey (); + if (k == 1) + { + return 1; + } + else if (k == 2) + { + return 1; + } + else + { + sim_cb_eprintf (p, "CTRL-A to quit, CTRL-B to quit harder\n"); + } + } +#endif +#if defined (_MSC_VER) + /* NB - this will not compile! */ + int k = win32pollquit(); + if (k == 1) + return 1; + else if (k == 2) + return 1; +#endif + return 0; +} +#else +#define os_poll_quit 0 +#endif /* defined(__GO32__) || defined(_MSC_VER) */ + +static int +os_get_errno (p) + host_callback *p; +{ + return cb_host_to_target_errno (p, p->last_errno); +} + + +static int +os_isatty (p, fd) + host_callback *p; + int fd; +{ + int result; + + result = fdbad (p, fd); + if (result) + return result; + result = wrap (p, isatty (fdmap (p, fd))); + + return result; +} + +static int +os_lseek (p, fd, off, way) + host_callback *p; + int fd; + long off; + int way; +{ + int result; + + result = fdbad (p, fd); + if (result) + return result; + result = lseek (fdmap (p, fd), off, way); + return result; +} + +static int +os_open (p, name, flags) + host_callback *p; + const char *name; + int flags; +{ + int i; + for (i = 0; i < MAX_CALLBACK_FDS; i++) + { + if (!p->fdopen[i]) + { + int f = open (name, cb_target_to_host_open (p, flags), 0644); + if (f < 0) + { + p->last_errno = errno; + return f; + } + p->fdopen[i] = 1; + p->fdmap[i] = f; + return i; + } + } + p->last_errno = EMFILE; + return -1; +} + +static int +os_read (p, fd, buf, len) + host_callback *p; + int fd; + char *buf; + int len; +{ + int result; + + result = fdbad (p, fd); + if (result) + return result; + result = wrap (p, read (fdmap (p, fd), buf, len)); + return result; +} + +static int +os_read_stdin (p, buf, len) + host_callback *p; + char *buf; + int len; +{ + return wrap (p, read (0, buf, len)); +} + +static int +os_write (p, fd, buf, len) + host_callback *p; + int fd; + const char *buf; + int len; +{ + int result; + int real_fd; + + result = fdbad (p, fd); + if (result) + return result; + real_fd = fdmap (p, fd); + switch (real_fd) + { + default: + result = wrap (p, write (real_fd, buf, len)); + break; + case 1: + result = p->write_stdout (p, buf, len); + break; + case 2: + result = p->write_stderr (p, buf, len); + break; + } + return result; +} + +static int +os_write_stdout (p, buf, len) + host_callback *p; + const char *buf; + int len; +{ + return fwrite (buf, 1, len, stdout); +} + +static void +os_flush_stdout (p) + host_callback *p; +{ + fflush (stdout); +} + +static int +os_write_stderr (p, buf, len) + host_callback *p; + const char *buf; + int len; +{ + return fwrite (buf, 1, len, stderr); +} + +static void +os_flush_stderr (p) + host_callback *p; +{ + fflush (stderr); +} + +static int +os_rename (p, f1, f2) + host_callback *p; + const char *f1; + const char *f2; +{ + return wrap (p, rename (f1, f2)); +} + + +static int +os_system (p, s) + host_callback *p; + const char *s; +{ + return wrap (p, system (s)); +} + +static long +os_time (p, t) + host_callback *p; + long *t; +{ + return wrap (p, time (t)); +} + + +static int +os_unlink (p, f1) + host_callback *p; + const char *f1; +{ + return wrap (p, unlink (f1)); +} + +static int +os_stat (p, file, buf) + host_callback *p; + const char *file; + struct stat *buf; +{ + /* ??? There is an issue of when to translate to the target layout. + One could do that inside this function, or one could have the + caller do it. It's more flexible to let the caller do it, though + I'm not sure the flexibility will ever be useful. */ + return wrap (p, stat (file, buf)); +} + +static int +os_fstat (p, fd, buf) + host_callback *p; + int fd; + struct stat *buf; +{ + if (fdbad (p, fd)) + return -1; + /* ??? There is an issue of when to translate to the target layout. + One could do that inside this function, or one could have the + caller do it. It's more flexible to let the caller do it, though + I'm not sure the flexibility will ever be useful. */ + return wrap (p, fstat (fdmap (p, fd), buf)); +} + +static int +os_shutdown (p) + host_callback *p; +{ + int i; + for (i = 0; i < MAX_CALLBACK_FDS; i++) + { + if (p->fdopen[i] && !p->alwaysopen[i]) { + close (p->fdmap[i]); + p->fdopen[i] = 0; + } + } + return 1; +} + +static int +os_init (p) + host_callback *p; +{ + int i; + + os_shutdown (p); + for (i = 0; i < 3; i++) + { + p->fdmap[i] = i; + p->fdopen[i] = 1; + p->alwaysopen[i] = 1; + } + + p->syscall_map = cb_init_syscall_map; + p->errno_map = cb_init_errno_map; + p->open_map = cb_init_open_map; + + return 1; +} + +/* DEPRECIATED */ + +/* VARARGS */ +static void +#ifdef ANSI_PROTOTYPES +os_printf_filtered (host_callback *p, const char *format, ...) +#else +os_printf_filtered (p, va_alist) + host_callback *p; + va_dcl +#endif +{ + va_list args; +#ifdef ANSI_PROTOTYPES + va_start (args, format); +#else + char *format; + + va_start (args); + format = va_arg (args, char *); +#endif + + vfprintf (stdout, format, args); + va_end (args); +} + +/* VARARGS */ +static void +#ifdef ANSI_PROTOTYPES +os_vprintf_filtered (host_callback *p, const char *format, va_list args) +#else +os_vprintf_filtered (p, format, args) + host_callback *p; + const char *format; + va_list args; +#endif +{ + vprintf (format, args); +} + +/* VARARGS */ +static void +#ifdef ANSI_PROTOTYPES +os_evprintf_filtered (host_callback *p, const char *format, va_list args) +#else +os_evprintf_filtered (p, format, args) + host_callback *p; + const char *format; + va_list args; +#endif +{ + vfprintf (stderr, format, args); +} + +/* VARARGS */ +static void +#ifdef ANSI_PROTOTYPES +os_error (host_callback *p, const char *format, ...) +#else +os_error (p, va_alist) + host_callback *p; + va_dcl +#endif +{ + va_list args; +#ifdef ANSI_PROTOTYPES + va_start (args, format); +#else + char *format; + + va_start (args); + format = va_arg (args, char *); +#endif + + vfprintf (stderr, format, args); + fprintf (stderr, "\n"); + + va_end (args); + exit (1); +} + +host_callback default_callback = +{ + os_close, + os_get_errno, + os_isatty, + os_lseek, + os_open, + os_read, + os_read_stdin, + os_rename, + os_system, + os_time, + os_unlink, + os_write, + os_write_stdout, + os_flush_stdout, + os_write_stderr, + os_flush_stderr, + + os_stat, + os_fstat, + + os_poll_quit, + + os_shutdown, + os_init, + + os_printf_filtered, /* deprecated */ + + os_vprintf_filtered, + os_evprintf_filtered, + os_error, + + 0, /* last errno */ + + { 0, }, /* fdmap */ + { 0, }, /* fdopen */ + { 0, }, /* alwaysopen */ + + 0, /* syscall_map */ + 0, /* errno_map */ + 0, /* open_map */ + 0, /* signal_map */ + 0, /* stat_map */ + + HOST_CALLBACK_MAGIC, +}; + +/* Read in a file describing the target's system call values. + E.g. maybe someone will want to use something other than newlib. + This assumes that the basic system call recognition and value passing/ + returning is supported. So maybe some coding/recompilation will be + necessary, but not as much. + + If an error occurs, the existing mapping is not changed. */ + +CB_RC +cb_read_target_syscall_maps (cb, file) + host_callback *cb; + const char *file; +{ + CB_TARGET_DEFS_MAP *syscall_map, *errno_map, *open_map, *signal_map; + const char *stat_map; + FILE *f; + + if ((f = fopen (file, "r")) == NULL) + return CB_RC_ACCESS; + + /* ... read in and parse file ... */ + + fclose (f); + return CB_RC_NO_MEM; /* FIXME:wip */ + + /* Free storage allocated for any existing maps. */ + if (cb->syscall_map) + free (cb->syscall_map); + if (cb->errno_map) + free (cb->errno_map); + if (cb->open_map) + free (cb->open_map); + if (cb->signal_map) + free (cb->signal_map); + if (cb->stat_map) + free ((PTR) cb->stat_map); + + cb->syscall_map = syscall_map; + cb->errno_map = errno_map; + cb->open_map = open_map; + cb->signal_map = signal_map; + cb->stat_map = stat_map; + + return CB_RC_OK; +} + +/* Translate the target's version of a syscall number to the host's. + This isn't actually the host's version, rather a canonical form. + ??? Perhaps this should be renamed to ..._canon_syscall. */ + +int +cb_target_to_host_syscall (cb, target_val) + host_callback *cb; + int target_val; +{ + CB_TARGET_DEFS_MAP *m; + + for (m = &cb->syscall_map[0]; m->target_val != -1; ++m) + if (m->target_val == target_val) + return m->host_val; + + return -1; +} + +/* FIXME: sort tables if large. + Alternatively, an obvious improvement for errno conversion is + to machine generate a function with a large switch(). */ + +/* Translate the host's version of errno to the target's. */ + +int +cb_host_to_target_errno (cb, host_val) + host_callback *cb; + int host_val; +{ + CB_TARGET_DEFS_MAP *m; + + for (m = &cb->errno_map[0]; m->host_val; ++m) + if (m->host_val == host_val) + return m->target_val; + + /* ??? Which error to return in this case is up for grabs. + Note that some missing values may have standard alternatives. + For now return 0 and require caller to deal with it. */ + return 0; +} + +/* Given a set of target bitmasks for the open system call, + return the host equivalent. + Mapping open flag values is best done by looping so there's no need + to machine generate this function. */ + +int +cb_target_to_host_open (cb, target_val) + host_callback *cb; + int target_val; +{ + int host_val = 0; + CB_TARGET_DEFS_MAP *m; + + for (m = &cb->open_map[0]; m->host_val != -1; ++m) + { + switch (m->target_val) + { + /* O_RDONLY can be (and usually is) 0 which needs to be treated + specially. */ + case TARGET_O_RDONLY : + case TARGET_O_WRONLY : + case TARGET_O_RDWR : + if ((target_val & (TARGET_O_RDONLY | TARGET_O_WRONLY | TARGET_O_RDWR)) + == m->target_val) + host_val |= m->host_val; + /* Handle the host/target differentiating between binary and + text mode. Only one case is of importance */ +#if ! defined (TARGET_O_BINARY) && defined (O_BINARY) + host_val |= O_BINARY; +#endif + break; + default : + if ((m->target_val & target_val) == m->target_val) + host_val |= m->host_val; + break; + } + } + + return host_val; +} + +/* Utility for cb_host_to_target_stat to store values in the target's + stat struct. */ + +static void +store (p, size, val, big_p) + char *p; + int size; + long val; /* ??? must be as big as target word size */ + int big_p; +{ + if (big_p) + { + p += size; + while (size-- > 0) + { + *--p = val; + val >>= 8; + } + } + else + { + while (size-- > 0) + { + *p++ = val; + val >>= 8; + } + } +} + +/* Translate a host's stat struct into a target's. + If HS is NULL, just compute the length of the buffer required, + TS is ignored. + + The result is the size of the target's stat struct, + or zero if an error occured during the translation. */ + +int +cb_host_to_target_stat (cb, hs, ts) + host_callback *cb; + const struct stat *hs; + PTR ts; +{ + const char *m = cb->stat_map; + char *p; + int big_p = 0; + + if (hs == NULL) + ts = NULL; + p = ts; + + while (m) + { + char *q = strchr (m, ','); + int size; + + /* FIXME: Use sscanf? */ + if (q == NULL) + { + /* FIXME: print error message */ + return 0; + } + size = atoi (q + 1); + if (size == 0) + { + /* FIXME: print error message */ + return 0; + } + + if (hs != NULL) + { + if (strncmp (m, "st_dev", q - m) == 0) + store (p, size, hs->st_dev, big_p); + else if (strncmp (m, "st_ino", q - m) == 0) + store (p, size, hs->st_ino, big_p); + /* FIXME:wip */ + else + store (p, size, 0, big_p); /* unsupported field, store 0 */ + } + + p += size; + m = strchr (q, ':'); + if (m) + ++m; + } + + return p - (char *) ts; +} + +/* Cover functions to the vfprintf callbacks. + + ??? If one thinks of the callbacks as a subsystem onto itself [or part of + a larger "remote target subsystem"] with a well defined interface, then + one would think that the subsystem would provide these. However, until + one is allowed to create such a subsystem (with its own source tree + independent of any particular user), such a critter can't exist. Thus + these functions are here for the time being. */ + +void +sim_cb_printf (host_callback *p, const char *fmt, ...) +{ + va_list ap; + + va_start (ap, fmt); + p->vprintf_filtered (p, fmt, ap); + va_end (ap); +} + +void +sim_cb_eprintf (host_callback *p, const char *fmt, ...) +{ + va_list ap; + + va_start (ap, fmt); + p->evprintf_filtered (p, fmt, ap); + va_end (ap); +} diff --git a/sim/common/cgen-cpu.h b/sim/common/cgen-cpu.h new file mode 100644 index 00000000000..b2121009033 --- /dev/null +++ b/sim/common/cgen-cpu.h @@ -0,0 +1,98 @@ +/* Simulator header for cgen cpus. + Copyright (C) 1998, 1999 Free Software Foundation, Inc. + Contributed by Cygnus Support. + +This file is part of GDB, the GNU debugger. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef CGEN_CPU_H +#define CGEN_CPU_H + +/* Type of function that is ultimately called by sim_resume. */ +typedef void (ENGINE_FN) (SIM_CPU *); + +/* Type of function to do disassembly. */ +typedef void (CGEN_DISASSEMBLER) (SIM_CPU *, const CGEN_INSN *, + const ARGBUF *, IADDR pc_, char *buf_); + +/* Additional non-machine generated per-cpu data to go in SIM_CPU. + The member's name must be `cgen_cpu'. */ + +typedef struct { + /* Non-zero while cpu simulation is running. */ + int running_p; +#define CPU_RUNNING_P(cpu) ((cpu)->cgen_cpu.running_p) + + /* Instruction count. This is maintained even in fast mode to keep track + of simulator speed. */ + unsigned long insn_count; +#define CPU_INSN_COUNT(cpu) ((cpu)->cgen_cpu.insn_count) + + /* sim_resume handlers */ + ENGINE_FN *fast_engine_fn; +#define CPU_FAST_ENGINE_FN(cpu) ((cpu)->cgen_cpu.fast_engine_fn) + ENGINE_FN *full_engine_fn; +#define CPU_FULL_ENGINE_FN(cpu) ((cpu)->cgen_cpu.full_engine_fn) + + /* Maximum number of instructions per time slice. + When single stepping this is 1. If using the pbb model, this can be + more than 1. 0 means "as long as you want". */ + unsigned int max_slice_insns; +#define CPU_MAX_SLICE_INSNS(cpu) ((cpu)->cgen_cpu.max_slice_insns) + + /* Simulator's execution cache. + Allocate space for this even if not used as some simulators may have + one machine variant that uses the scache and another that doesn't and + we don't want members in this struct to move about. */ + CPU_SCACHE scache; + + /* Instruction descriptor table. */ + IDESC *idesc; +#define CPU_IDESC(cpu) ((cpu)->cgen_cpu.idesc) + + /* Whether the read,write,semantic entries (computed goto labels) have been + initialized or not. */ + int idesc_read_init_p; +#define CPU_IDESC_READ_INIT_P(cpu) ((cpu)->cgen_cpu.idesc_read_init_p) + int idesc_write_init_p; +#define CPU_IDESC_WRITE_INIT_P(cpu) ((cpu)->cgen_cpu.idesc_write_init_p) + int idesc_sem_init_p; +#define CPU_IDESC_SEM_INIT_P(cpu) ((cpu)->cgen_cpu.idesc_sem_init_p) + + /* Cpu descriptor table. + This is a CGEN created entity that contains the description file + turned into C code and tables for our use. */ + CGEN_CPU_DESC cpu_desc; +#define CPU_CPU_DESC(cpu) ((cpu)->cgen_cpu.cpu_desc) + + /* Function to fetch the insn data entry in the IDESC. */ + const CGEN_INSN * (*get_idata) (SIM_CPU *, int); +#define CPU_GET_IDATA(cpu) ((cpu)->cgen_cpu.get_idata) + + /* Disassembler. */ + CGEN_DISASSEMBLER *disassembler; +#define CPU_DISASSEMBLER(cpu) ((cpu)->cgen_cpu.disassembler) + + /* Allow slop in size calcs for case where multiple cpu types are supported + and space for the specified cpu is malloc'd at run time. */ + double slop; +} CGEN_CPU; + +/* Shorthand macro for fetching registers. + CPU_CGEN_HW is defined in cpu.h. */ +#define CPU(x) (CPU_CGEN_HW (current_cpu)->x) + +#endif /* CGEN_CPU_H */ diff --git a/sim/common/cgen-defs.h b/sim/common/cgen-defs.h new file mode 100644 index 00000000000..d3c9a8ae57b --- /dev/null +++ b/sim/common/cgen-defs.h @@ -0,0 +1,174 @@ +/* General Cpu tools GENerated simulator support. + Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc. + Contributed by Cygnus Support. + +This file is part of GDB, the GNU debugger. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef CGEN_DEFS_H +#define CGEN_DEFS_H + +/* Compute number of longs required to hold N bits. */ +#define HOST_LONGS_FOR_BITS(n) \ + (((n) + sizeof (long) * 8 - 1) / sizeof (long) * 8) + +/* Forward decls. Defined in the machine generated files. */ + +/* This holds the contents of the extracted insn. + There are a few common entries (e.g. pc address), and then one big + union with an entry for each of the instruction formats. */ +typedef struct argbuf ARGBUF; + +/* ARGBUF accessors. */ +#define ARGBUF_ADDR(abuf) ((abuf)->addr) +#define ARGBUF_IDESC(abuf) ((abuf)->idesc) +#define ARGBUF_TRACE_P(abuf) ((abuf)->trace_p) +#define ARGBUF_PROFILE_P(abuf) ((abuf)->profile_p) + +/* This is one ARGBUF plus whatever else is needed for WITH_SCACHE support. + At present there is nothing else, but it also provides a level of + abstraction. */ +typedef struct scache SCACHE; + +/* This is a union with one entry for each instruction format. + Each entry contains all of the non-constant inputs of the instruction + in the case of read-before-exec support, or all outputs of the instruction + in the case of write-after-exec support. */ +typedef struct parexec PAREXEC; + +/* An "Instruction DESCriptor". + This is the main handle on an instruction for the simulator. */ +typedef struct idesc IDESC; + +/* Engine support. + ??? This is here because it's needed before eng.h (built by genmloop.sh) + which is needed before cgen-engine.h and cpu.h. + ??? This depends on a cpu family specific type, IADDR, but no machine + generated headers will have been included yet. sim/common currently + requires the typedef of sim_cia in sim-main.h between the inclusion of + sim-basics.h and sim-base.h so this is no different. */ + +/* SEM_ARG is intended to hide whether or not the scache is in use from the + semantic routines. In reality for the with-extraction case it is always + an SCACHE * even when not using the SCACHE since there's no current win to + making it something else ("not using the SCACHE" is like having a cache + size of 1). + The without-extraction case still uses an ARGBUF: + - consistency with scache version + - still need to record which operands are written + This wouldn't be needed if modeling was done in the semantic routines + but this isn't as general as handling it outside of the semantic routines. + For example Shade allows calling user-supplied code before/after each + instruction and this is something that is being planned. + ??? There is still some clumsiness in how much of ARGBUF to use. */ +typedef SCACHE *SEM_ARG; + +/* instruction address + ??? This was intended to be a struct of two elements in the WITH_SCACHE_PBB + case. The first element is the IADDR, the second element is the SCACHE *. + Haven't found the time yet to make this work, but it seemed a nicer approach + than the current br_cache stuff. */ +typedef IADDR PCADDR; + +/* Current instruction address, used by common. */ +typedef IADDR CIA; + +/* Semantic routines' version of the PC. */ +#if WITH_SCACHE_PBB +typedef SCACHE *SEM_PC; +#else +typedef IADDR SEM_PC; +#endif + +/* Virtual insn support. */ + +/* Opcode table for virtual insns (only used by the simulator). */ +extern const CGEN_INSN cgen_virtual_insn_table[]; + +/* -ve of indices of virtual insns in cgen_virtual_insn_table. */ +typedef enum { + VIRTUAL_INSN_X_INVALID = 0, + VIRTUAL_INSN_X_BEFORE = -1, VIRTUAL_INSN_X_AFTER = -2, + VIRTUAL_INSN_X_BEGIN = -3, + VIRTUAL_INSN_X_CHAIN= -4, VIRTUAL_INSN_X_CTI_CHAIN = -5 +} CGEN_INSN_VIRTUAL_TYPE; + +/* Return non-zero if OPCODE is a virtual insn. */ +#define CGEN_INSN_VIRTUAL_P(insn) \ + CGEN_INSN_ATTR_VALUE ((insn), CGEN_INSN_VIRTUAL) + +/* GNU C's "computed goto" facility is used to speed things up where + possible. These macros provide a portable way to use them. + Nesting of these switch statements is done by providing an extra argument + that distinguishes them. `N' can be a number or symbol. + Variable `labels_##N' must be initialized with the labels of each case. */ + +#ifdef __GNUC__ +#define SWITCH(N, X) goto *X; +#define CASE(N, X) case_##N##_##X +#define BREAK(N) goto end_switch_##N +#define DEFAULT(N) default_##N +#define ENDSWITCH(N) end_switch_##N: +#else +#define SWITCH(N, X) switch (X) +#define CASE(N, X) case X /* FIXME: old sem-switch had (@arch@_,X) here */ +#define BREAK(N) break +#define DEFAULT(N) default +#define ENDSWITCH(N) +#endif + +/* Simulator state. */ + +/* Records simulator descriptor so utilities like @cpu@_dump_regs can be + called from gdb. */ +extern SIM_DESC current_state; + +/* Simulator state. */ + +/* CGEN_STATE contains additional state information not present in + sim_state_base. */ + +typedef struct cgen_state { + /* FIXME: Moved to sim_state_base. */ + /* argv, env */ + char **argv; +#define STATE_ARGV(s) ((s) -> cgen_state.argv) + /* FIXME: Move to sim_state_base. */ + char **envp; +#define STATE_ENVP(s) ((s) -> cgen_state.envp) + + /* Non-zero if no tracing or profiling is selected. */ + int run_fast_p; +#define STATE_RUN_FAST_P(sd) ((sd) -> cgen_state.run_fast_p) +} CGEN_STATE; + +/* Various utilities. */ + +/* Called after sim_post_argv_init to do any cgen initialization. */ +extern void cgen_init (SIM_DESC); + +/* Return the name of an insn. */ +extern CPU_INSN_NAME_FN cgen_insn_name; + +/* Return the maximum number of extra bytes required for a sim_cpu struct. */ +/* ??? Ok, yes, this is less pretty than it should be. Give me a better + language [or suggest a better way]. */ +extern int cgen_cpu_max_extra_bytes (void); + +/* Called to process an invalid instruction. */ +extern void sim_engine_invalid_insn (SIM_CPU *, IADDR); + +#endif /* CGEN_DEFS_H */ diff --git a/sim/common/cgen-engine.h b/sim/common/cgen-engine.h new file mode 100644 index 00000000000..9421332b439 --- /dev/null +++ b/sim/common/cgen-engine.h @@ -0,0 +1,473 @@ +/* Engine header for Cpu tools GENerated simulators. + Copyright (C) 1998, 1999 Free Software Foundation, Inc. + Contributed by Cygnus Support. + +This file is part of GDB, the GNU debugger. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* This file must be included after eng.h and before ${cpu}.h. */ + +/* Semantic functions come in six versions on two axes: + fast/full-featured, and using one of the simple/scache/compilation engines. + A full featured simulator is always provided. --enable-sim-fast includes + support for fast execution by duplicating the semantic code but leaving + out all features like tracing and profiling. + Using the scache is selected with --enable-sim-scache. */ +/* FIXME: --enable-sim-fast not implemented yet. */ +/* FIXME: undecided how to handle WITH_SCACHE_PBB. */ + +/* There are several styles of engines, all generally supported by the + same code: + + WITH_SCACHE && WITH_SCACHE_PBB - pseudo-basic-block scaching + WITH_SCACHE && !WITH_SCACHE_PBB - scaching on an insn by insn basis + !WITH_SCACHE - simple engine: fetch an insn, execute an insn + + The !WITH_SCACHE case can also be broken up into two flavours: + extract the fields of the insn into an ARGBUF struct, or defer the + extraction to the semantic handler. The former can be viewed as the + WITH_SCACHE case with a cache size of 1 (thus there's no need for a + WITH_EXTRACTION macro). The WITH_SCACHE case always extracts the fields + into an ARGBUF struct. */ + +#ifndef CGEN_ENGINE_H +#define CGEN_ENGINE_H + +/* Instruction field support macros. */ + +#define EXTRACT_MSB0_INT(val, total, start, length) \ +(((INT) (val) << ((sizeof (INT) * 8) - (total) + (start))) \ + >> ((sizeof (INT) * 8) - (length))) +#define EXTRACT_MSB0_UINT(val, total, start, length) \ +(((UINT) (val) << ((sizeof (UINT) * 8) - (total) + (start))) \ + >> ((sizeof (UINT) * 8) - (length))) + +#define EXTRACT_LSB0_INT(val, total, start, length) \ +(((INT) (val) << ((sizeof (INT) * 8) - (start) - 1)) \ + >> ((sizeof (INT) * 8) - (length))) +#define EXTRACT_LSB0_UINT(val, total, start, length) \ +(((UINT) (val) << ((sizeof (UINT) * 8) - (start) - 1)) \ + >> ((sizeof (UINT) * 8) - (length))) + +#if CGEN_INSN_LSB0_P + +#define EXTRACT_INT(val, total, start, length) \ + EXTRACT_LSB0_INT ((val), (total), (start), (length)) +#define EXTRACT_UINT(val, total, start, length) \ + EXTRACT_LSB0_UINT ((val), (total), (start), (length)) + +#else + +#define EXTRACT_INT(val, total, start, length) \ + EXTRACT_MSB0_INT ((val), (total), (start), (length)) +#define EXTRACT_UINT(val, total, start, length) \ + EXTRACT_MSB0_UINT ((val), (total), (start), (length)) + +#endif + +/* Semantic routines. */ + +/* Type of the machine generated extraction fns. */ +/* ??? No longer used. */ +typedef void (EXTRACT_FN) (SIM_CPU *, IADDR, CGEN_INSN_INT, ARGBUF *); + +/* Type of the machine generated semantic fns. */ + +#if WITH_SCACHE + +/* Instruction fields are extracted into ARGBUF before calling the + semantic routine. */ +#if HAVE_PARALLEL_INSNS +typedef SEM_PC (SEMANTIC_FN) (SIM_CPU *, SEM_ARG, PAREXEC *); +#else +typedef SEM_PC (SEMANTIC_FN) (SIM_CPU *, SEM_ARG); +#endif + +#else + +/* Result of semantic routines is a status indicator (wip). */ +typedef unsigned int SEM_STATUS; + +/* Instruction fields are extracted by the semantic routine. + ??? TODO: multi word insns. */ +#if HAVE_PARALLEL_INSNS +typedef SEM_STATUS (SEMANTIC_FN) (SIM_CPU *, SEM_ARG, PAREXEC *, CGEN_INSN_INT); +#else +typedef SEM_STATUS (SEMANTIC_FN) (SIM_CPU *, SEM_ARG, CGEN_INSN_INT); +#endif + +#endif + +/* In the ARGBUF struct, a pointer to the semantic routine for the insn. */ + +union sem { +#if ! WITH_SEM_SWITCH_FULL + SEMANTIC_FN *sem_full; +#endif +#if ! WITH_SEM_SWITCH_FAST + SEMANTIC_FN *sem_fast; +#endif +#if WITH_SEM_SWITCH_FULL || WITH_SEM_SWITCH_FAST +#ifdef __GNUC__ + void *sem_case; +#else + int sem_case; +#endif +#endif +}; + +/* Set the appropriate semantic handler in ABUF. */ + +#if WITH_SEM_SWITCH_FULL +#ifdef __GNUC__ +#define SEM_SET_FULL_CODE(abuf, idesc) \ + do { (abuf)->semantic.sem_case = (idesc)->sem_full_lab; } while (0) +#else +#define SEM_SET_FULL_CODE(abuf, idesc) \ + do { (abuf)->semantic.sem_case = (idesc)->num; } while (0) +#endif +#else +#define SEM_SET_FULL_CODE(abuf, idesc) \ + do { (abuf)->semantic.sem_full = (idesc)->sem_full; } while (0) +#endif + +#if WITH_SEM_SWITCH_FAST +#ifdef __GNUC__ +#define SEM_SET_FAST_CODE(abuf, idesc) \ + do { (abuf)->semantic.sem_case = (idesc)->sem_fast_lab; } while (0) +#else +#define SEM_SET_FAST_CODE(abuf, idesc) \ + do { (abuf)->semantic.sem_case = (idesc)->num; } while (0) +#endif +#else +#define SEM_SET_FAST_CODE(abuf, idesc) \ + do { (abuf)->semantic.sem_fast = (idesc)->sem_fast; } while (0) +#endif + +#define SEM_SET_CODE(abuf, idesc, fast_p) \ +do { \ + if (fast_p) \ + SEM_SET_FAST_CODE ((abuf), (idesc)); \ + else \ + SEM_SET_FULL_CODE ((abuf), (idesc)); \ +} while (0) + +/* Return non-zero if IDESC is a conditional or unconditional CTI. */ + +#define IDESC_CTI_P(idesc) \ + ((CGEN_ATTR_BOOLS (CGEN_INSN_ATTRS ((idesc)->idata)) \ + & (CGEN_ATTR_MASK (CGEN_INSN_COND_CTI) \ + | CGEN_ATTR_MASK (CGEN_INSN_UNCOND_CTI))) \ + != 0) + +/* Return non-zero if IDESC is a skip insn. */ + +#define IDESC_SKIP_P(idesc) \ + ((CGEN_ATTR_BOOLS (CGEN_INSN_ATTRS ((idesc)->idata)) \ + & CGEN_ATTR_MASK (CGEN_INSN_SKIP_CTI)) \ + != 0) + +/* These are used so that we can compile two copies of the semantic code, + one with full feature support and one without that runs fast(er). */ +#define SEM_FN_NAME(cpu,fn) XCONCAT3 (cpu,_sem_,fn) +#define SEMF_FN_NAME(cpu,fn) XCONCAT3 (cpu,_semf_,fn) + +/* Return pointer to ARGBUF given ptr to SCACHE. */ +#define SEM_ARGBUF(sem_arg) (& (sem_arg) -> argbuf) + +/* There are several styles of engines, all generally supported by the + same code: + + WITH_SCACHE && WITH_SCACHE_PBB - pseudo-basic-block scaching + WITH_SCACHE && !WITH_SCACHE_PBB - scaching on an insn by insn basis + !WITH_SCACHE - simple engine: fetch an insn, execute an insn + + ??? The !WITH_SCACHE case can also be broken up into two flavours: + extract the fields of the insn into an ARGBUF struct, or defer the + extraction to the semantic handler. The WITH_SCACHE case always + extracts the fields into an ARGBUF struct. */ + +#if WITH_SCACHE + +#define CIA_ADDR(cia) (cia) + +#if WITH_SCACHE_PBB + +/* Return the scache pointer of the current insn. */ +#define SEM_SEM_ARG(vpc, sc) (vpc) + +/* Return the virtual pc of the next insn to execute + (assuming this isn't a cti or the branch isn't taken). */ +#define SEM_NEXT_VPC(sem_arg, pc, len) ((sem_arg) + 1) + +/* Update the instruction counter. */ +#define PBB_UPDATE_INSN_COUNT(cpu,sc) \ + (CPU_INSN_COUNT (cpu) += SEM_ARGBUF (sc) -> fields.chain.insn_count) + +/* Value for br_addr_ptr indicating branch wasn't taken. */ +#define SEM_BRANCH_UNTAKEN ((SEM_PC *) 0) + +/* Value for br_addr_ptr indicating branch was taken to uncacheable + address (e.g. j reg). */ +#define SEM_BRANCH_UNCACHEABLE ((SEM_PC *) 1) + +/* Initialize next-pbb link for SEM_BRANCH_VIA_CACHE. */ +#define SEM_BRANCH_INIT_EXTRACT(abuf) \ +do { (abuf)->fields.cti.addr_cache = 0; } while (0) + +/* Do not append a `;' to invocations of this. + npc,npc_ptr are for communication between the cti insn and cti-chain. */ +#define SEM_BRANCH_INIT \ + IADDR npc = 0; /* assign a value for -Wall */ \ + SEM_PC *npc_ptr = SEM_BRANCH_UNTAKEN; + +/* SEM_IN_SWITCH is defined at the top of the mainloop.c files + generated by genmloop.sh. It exists so generated semantic code needn't + care whether it's being put in a switch or in a function. */ +#ifdef SEM_IN_SWITCH +#define SEM_BRANCH_FINI(pcvar) \ +do { \ + pbb_br_npc = npc; \ + pbb_br_npc_ptr = npc_ptr; \ +} while (0) +#else /* 1 semantic function per instruction */ +#define SEM_BRANCH_FINI(pcvar) \ +do { \ + CPU_PBB_BR_NPC (current_cpu) = npc; \ + CPU_PBB_BR_NPC_PTR (current_cpu) = npc_ptr; \ +} while (0) +#endif + +/* Return address of cached branch address value. */ +#define SEM_BRANCH_ADDR_CACHE(sem_arg) \ + (& SEM_ARGBUF (sem_arg)->fields.cti.addr_cache) + +#define SEM_BRANCH_VIA_CACHE(cpu, sc, newval, pcvar, cachevarptr) \ +do { \ + npc = (newval); \ + npc_ptr = (cachevarptr); \ +} while (0) + +#define SEM_BRANCH_VIA_ADDR(cpu, sc, newval, pcvar) \ +do { \ + npc = (newval); \ + npc_ptr = SEM_BRANCH_UNCACHEABLE; \ +} while (0) + +#else /* ! WITH_SCACHE_PBB */ + +#define SEM_SEM_ARG(vpc, sc) (sc) + +#define SEM_NEXT_VPC(sem_arg, pc, len) ((pc) + (len)) + +#define SEM_BRANCH_INIT_EXTRACT(abuf) do { } while (0) + +/* ??? May wish to move taken_p out of here and make it explicit. */ +#define SEM_BRANCH_INIT \ + int taken_p = 0; + +#ifndef TARGET_SEM_BRANCH_FINI(pcvar, taken_p) +#define TARGET_SEM_BRANCH_FINI(pcvar, taken_p) +#endif +#define SEM_BRANCH_FINI(pcvar) \ + do { TARGET_SEM_BRANCH_FINI (pcvar, taken_p); } while (0) + +#define SEM_BRANCH_ADDR_CACHE(sem_arg) shouldnt_be_used + +#define SEM_BRANCH_VIA_CACHE(cpu, sc, newval, pcvar, cachevar) \ +do { \ + (pcvar) = (newval); \ + taken_p = 1; \ +} while (0) + +#define SEM_BRANCH_VIA_ADDR(cpu, sc, newval, pcvar) \ +do { \ + (pcvar) = (newval); \ + taken_p = 1; \ +} while (0) + +#endif /* ! WITH_SCACHE_PBB */ + +#else /* ! WITH_SCACHE */ + +/* This is the "simple" engine case. */ + +#define CIA_ADDR(cia) (cia) + +#define SEM_SEM_ARG(vpc, sc) (sc) + +#define SEM_NEXT_VPC(sem_arg, pc, len) ((pc) + (len)) + +#define SEM_BRANCH_INIT \ + int taken_p = 0; + +#define SEM_BRANCH_ADDR_CACHE(sem_arg) shouldnt_be_used + +#define SEM_BRANCH_VIA_CACHE(cpu, abuf, newval, pcvar, cachevar) \ +do { \ + (pcvar) = (newval); \ + taken_p = 1; \ +} while (0) + +#define SEM_BRANCH_VIA_ADDR(cpu, abuf, newval, pcvar) \ +do { \ + (pcvar) = (newval); \ + taken_p = 1; \ +} while (0) + +/* Finish off branch insns. + The target must define TARGET_SEM_BRANCH_FINI. + ??? This can probably go away when define-execute is finished. */ +#define SEM_BRANCH_FINI(pcvar, bool_attrs) \ + do { TARGET_SEM_BRANCH_FINI ((pcvar), (bool_attrs), taken_p); } while (0) + +/* Finish off non-branch insns. + The target must define TARGET_SEM_NBRANCH_FINI. + ??? This can probably go away when define-execute is finished. */ +#define SEM_NBRANCH_FINI(pcvar, bool_attrs) \ + do { TARGET_SEM_NBRANCH_FINI ((pcvar), (bool_attrs)); } while (0) + +#endif /* ! WITH_SCACHE */ + +/* Instruction information. */ + +/* Compile time computable instruction data. + + ??? May wish to move parallel execution support into its own struct. + It's a fair bit of "clutter" for the "normal" case. */ + +struct insn_sem { + /* The instruction type (a number that identifies each insn over the + entire architecture). */ + CGEN_INSN_TYPE type; + + /* Index in IDESC table. */ + int index; + + /* Sanity check, at most one of these may be true. */ +#if WITH_PARALLEL_READ && WITH_PARALLEL_WRITE +#error "Both WITH_PARALLEL_READ && WITH_PARALLEL_WRITE can't be true." +#endif + +#if WITH_PARALLEL_READ || WITH_PARALLEL_WRITE + /* Index in IDESC table of parallel handler. */ + int par_index; +#endif + +#if WITH_PARALLEL_READ +#ifndef __GNUC__ + /* Semantic format number of pre-read handler. + Only used by chips that support parallel execution of several insns. + It is always implemented as a `switch'. In the case of GNUC we use + computed gotos. When not GNUC, this is the argument to `switch'. */ + int fmt; +#endif +#endif + +#if WITH_PARALLEL_WRITE + /* Index in IDESC table of writeback handler. + Only used by chips that support parallel execution of several insns. */ + int write_index; +#endif + + /* Routines to execute the insn. + The full version has all features (profiling,tracing) compiled in. + The fast version has none of that. */ +#if ! WITH_SEM_SWITCH_FULL + SEMANTIC_FN *sem_full; +#endif +#if WITH_FAST && ! WITH_SEM_SWITCH_FAST + SEMANTIC_FN *sem_fast; +#endif +}; + +/* Run-time computed instruction descriptor. */ + +struct idesc { + /* Parallel read-before-exec support. */ +#if WITH_PARALLEL_READ + struct idesc *par_idesc; +#ifdef __GNUC__ + void *read; +#else + int fmt; +#endif +#endif + + /* Parallel write-after-exec support. */ +#if WITH_PARALLEL_WRITE + /* Pointer to parallel handler if serial insn. + Pointer to writeback handler if parallel insn. */ + struct idesc *par_idesc; +#endif + +#if WITH_SEM_SWITCH_FULL +#ifdef __GNUC__ + void *sem_full_lab; +#else + /* nothing needed, switch's on `num' member */ +#endif +#else + SEMANTIC_FN *sem_full; +#endif + +#if WITH_SEM_SWITCH_FAST +#ifdef __GNUC__ + void *sem_fast_lab; +#else + /* nothing needed, switch's on `num' member */ +#endif +#else + SEMANTIC_FN *sem_fast; +#endif + + /* Instruction number (index in IDESC table, profile table). + Also used to switch on in non-gcc semantic switches. */ + int num; + + /* instruction data (name, attributes, size, etc.) */ + const CGEN_INSN *idata; + + /* instruction attributes, copied from `idata' for speed */ + const CGEN_INSN_ATTR_TYPE *attrs; + + /* instruction length in bytes, copied from `idata' for speed */ + int length; + + /* profiling/modelling support */ + const INSN_TIMING *timing; +}; + +/* Tracing/profiling. */ + +/* Return non-zero if a before/after handler is needed. + When tracing/profiling a selected range there's no need to slow + down simulation of the other insns (except to get more accurate data!). + + ??? May wish to profile all insns if doing insn tracing, or to + get more accurate cycle data. + + First test ANY_P so we avoid a potentially expensive HIT_P call + [if there are lots of address ranges]. */ + +#define PC_IN_TRACE_RANGE_P(cpu, pc) \ + (TRACE_ANY_P (cpu) \ + && ADDR_RANGE_HIT_P (TRACE_RANGE (CPU_TRACE_DATA (cpu)), (pc))) +#define PC_IN_PROFILE_RANGE_P(cpu, pc) \ + (PROFILE_ANY_P (cpu) \ + && ADDR_RANGE_HIT_P (PROFILE_RANGE (CPU_PROFILE_DATA (cpu)), (pc))) + +#endif /* CGEN_ENGINE_H */ diff --git a/sim/common/cgen-mem.h b/sim/common/cgen-mem.h new file mode 100644 index 00000000000..c91ccb3f688 --- /dev/null +++ b/sim/common/cgen-mem.h @@ -0,0 +1,203 @@ +/* Memory ops header for CGEN-based simulators. + Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. + Contributed by Cygnus Solutions. + +This file is part of the GNU Simulators. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef CGEN_MEM_H +#define CGEN_MEM_H + +#ifdef MEMOPS_DEFINE_INLINE +#define MEMOPS_INLINE +#else +#define MEMOPS_INLINE extern inline +#endif + +/* Memory read support. */ + +#if defined (__GNUC__) || defined (MEMOPS_DEFINE_INLINE) +#define DECLARE_GETMEM(mode, size) \ +MEMOPS_INLINE mode \ +XCONCAT2 (GETMEM,mode) (SIM_CPU *cpu, IADDR pc, ADDR a) \ +{ \ + PROFILE_COUNT_READ (cpu, a, XCONCAT2 (MODE_,mode)); \ + /* Don't read anything into "unaligned" here. Bad name choice. */\ + return XCONCAT2 (sim_core_read_unaligned_,size) (cpu, pc, read_map, a); \ +} +#else +#define DECLARE_GETMEM(mode, size) \ +extern mode XCONCAT2 (GETMEM,mode) (SIM_CPU *, IADDR, ADDR); +#endif + +DECLARE_GETMEM (QI, 1) +DECLARE_GETMEM (UQI, 1) +DECLARE_GETMEM (HI, 2) +DECLARE_GETMEM (UHI, 2) +DECLARE_GETMEM (SI, 4) +DECLARE_GETMEM (USI, 4) +DECLARE_GETMEM (DI, 8) +DECLARE_GETMEM (UDI, 8) + +#undef DECLARE_GETMEM + +#if defined (__GNUC__) || defined (MEMOPS_DEFINE_INLINE) +#define DECLARE_GETMEM(mode, size) \ +MEMOPS_INLINE mode \ +XCONCAT2 (GETMEM,mode) (SIM_CPU *cpu, IADDR pc, ADDR a) \ +{ \ + PROFILE_COUNT_READ (cpu, a, XCONCAT2 (MODE_,mode)); \ + /* Don't read anything into "unaligned" here. Bad name choice. */\ + return XCONCAT2 (sim_core_read_unaligned_,size) (cpu, pc, read_map, a); \ +} +#else +#define DECLARE_GETMEM(mode, size) \ +extern mode XCONCAT2 (GETMEM,mode) (SIM_CPU *, IADDR, ADDR); +#endif + +DECLARE_GETMEM (SF, 4) +DECLARE_GETMEM (DF, 8) +/*DECLARE_GETMEM (TF, 16)*/ + +#undef DECLARE_GETMEM + +/* Memory write support. */ + +#if defined (__GNUC__) || defined (MEMOPS_DEFINE_INLINE) +#define DECLARE_SETMEM(mode, size) \ +MEMOPS_INLINE void \ +XCONCAT2 (SETMEM,mode) (SIM_CPU *cpu, IADDR pc, ADDR a, mode val) \ +{ \ + PROFILE_COUNT_WRITE (cpu, a, XCONCAT2 (MODE_,mode)); \ + /* Don't read anything into "unaligned" here. Bad name choice. */ \ + XCONCAT2 (sim_core_write_unaligned_,size) (cpu, pc, write_map, a, val); \ +} +#else +#define DECLARE_SETMEM(mode, size) \ +extern void XCONCAT2 (SETMEM,mode) (SIM_CPU *, IADDR, ADDR, mode); +#endif + +DECLARE_SETMEM (QI, 1) +DECLARE_SETMEM (UQI, 1) +DECLARE_SETMEM (HI, 2) +DECLARE_SETMEM (UHI, 2) +DECLARE_SETMEM (SI, 4) +DECLARE_SETMEM (USI, 4) +DECLARE_SETMEM (DI, 8) +DECLARE_SETMEM (UDI, 8) + +/* +DECLARE_SETMEM (SF, 4) +DECLARE_SETMEM (DF, 8) +DECLARE_SETMEM (TF, 16) +*/ + +#undef DECLARE_SETMEM + +/* Instruction read support. */ + +#if defined (__GNUC__) || defined (MEMOPS_DEFINE_INLINE) +#define DECLARE_GETIMEM(mode, size) \ +MEMOPS_INLINE mode \ +XCONCAT2 (GETIMEM,mode) (SIM_CPU *cpu, IADDR a) \ +{ \ + /*PROFILE_COUNT_READ (cpu, a, XCONCAT2 (MODE_,mode));*/ \ + /* Don't read anything into "unaligned" here. Bad name choice. */\ + return XCONCAT2 (sim_core_read_unaligned_,size) (cpu, a, exec_map, a); \ +} +#else +#define DECLARE_GETIMEM(mode, size) \ +extern mode XCONCAT2 (GETIMEM,mode) (SIM_CPU *, ADDR); +#endif + +DECLARE_GETIMEM (UQI, 1) +DECLARE_GETIMEM (UHI, 2) +DECLARE_GETIMEM (USI, 4) +DECLARE_GETIMEM (UDI, 8) + +#undef DECLARE_GETIMEM + +/* GETT: translate target value at P to host value. + This needn't be very efficient (i.e. can call memcpy) as this is + only used when interfacing with the outside world (e.g. gdb). */ + +#if defined (__GNUC__) || defined (MEMOPS_DEFINE_INLINE) +#define DECLARE_GETT(mode, size) \ +MEMOPS_INLINE mode \ +XCONCAT2 (GETT,mode) (unsigned char *p) \ +{ \ + mode tmp; \ + memcpy (&tmp, p, sizeof (mode)); \ + return XCONCAT2 (T2H_,size) (tmp); \ +} +#else +#define DECLARE_GETT(mode, size) \ +extern mode XCONCAT2 (GETT,mode) (unsigned char *); +#endif + +DECLARE_GETT (QI, 1) +DECLARE_GETT (UQI, 1) +DECLARE_GETT (HI, 2) +DECLARE_GETT (UHI, 2) +DECLARE_GETT (SI, 4) +DECLARE_GETT (USI, 4) +DECLARE_GETT (DI, 8) +DECLARE_GETT (UDI, 8) + +/* +DECLARE_GETT (SF, 4) +DECLARE_GETT (DF, 8) +DECLARE_GETT (TF, 16) +*/ + +#undef DECLARE_GETT + +/* SETT: translate host value to target value and store at P. + This needn't be very efficient (i.e. can call memcpy) as this is + only used when interfacing with the outside world (e.g. gdb). */ + +#if defined (__GNUC__) || defined (MEMOPS_DEFINE_INLINE) +#define DECLARE_SETT(mode, size) \ +MEMOPS_INLINE void \ +XCONCAT2 (SETT,mode) (unsigned char *buf, mode val) \ +{ \ + mode tmp; \ + tmp = XCONCAT2 (H2T_,size) (val); \ + memcpy (buf, &tmp, sizeof (mode)); \ +} +#else +#define DECLARE_SETT(mode, size) \ +extern mode XCONCAT2 (GETT,mode) (unsigned char *, mode); +#endif + +DECLARE_SETT (QI, 1) +DECLARE_SETT (UQI, 1) +DECLARE_SETT (HI, 2) +DECLARE_SETT (UHI, 2) +DECLARE_SETT (SI, 4) +DECLARE_SETT (USI, 4) +DECLARE_SETT (DI, 8) +DECLARE_SETT (UDI, 8) + +/* +DECLARE_SETT (SF, 4) +DECLARE_SETT (DF, 8) +DECLARE_SETT (TF, 16) +*/ + +#undef DECLARE_SETT + +#endif /* CGEN_MEM_H */ diff --git a/sim/common/cgen-ops.h b/sim/common/cgen-ops.h new file mode 100644 index 00000000000..1ec0e6c2019 --- /dev/null +++ b/sim/common/cgen-ops.h @@ -0,0 +1,897 @@ +/* Semantics ops support for CGEN-based simulators. + Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. + Contributed by Cygnus Solutions. + +This file is part of the GNU Simulators. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifndef CGEN_SEM_OPS_H +#define CGEN_SEM_OPS_H + +/* Semantic operations. + At one point this file was machine generated. Maybe it will be again. */ + +/* These don't really have a mode. */ +#define ANDIF(x, y) ((x) && (y)) +#define ORIF(x, y) ((x) || (y)) + +#define ANDBI(x, y) ((x) & (y)) +#define ORBI(x, y) ((x) | (y)) +#define XORBI(x, y) ((x) ^ (y)) +#define NEGBI(x) (- (x)) +#define NOTBI(x) (! (BI) (x)) +#define INVBI(x) (~ (x)) +#define EQBI(x, y) ((BI) (x) == (BI) (y)) +#define NEBI(x, y) ((BI) (x) != (BI) (y)) +#define LTBI(x, y) ((BI) (x) < (BI) (y)) +#define LEBI(x, y) ((BI) (x) <= (BI) (y)) +#define GTBI(x, y) ((BI) (x) > (BI) (y)) +#define GEBI(x, y) ((BI) (x) >= (BI) (y)) +#define LTUBI(x, y) ((BI) (x) < (BI) (y)) +#define LEUBI(x, y) ((BI) (x) <= (BI) (y)) +#define GTUBI(x, y) ((BI) (x) > (BI) (y)) +#define GEUBI(x, y) ((BI) (x) >= (BI) (y)) + +#define ADDQI(x, y) ((x) + (y)) +#define SUBQI(x, y) ((x) - (y)) +#define MULQI(x, y) ((x) * (y)) +#define DIVQI(x, y) ((QI) (x) / (QI) (y)) +#define UDIVQI(x, y) ((UQI) (x) / (UQI) (y)) +#define MODQI(x, y) ((QI) (x) % (QI) (y)) +#define UMODQI(x, y) ((UQI) (x) % (UQI) (y)) +#define SRAQI(x, y) ((QI) (x) >> (y)) +#define SRLQI(x, y) ((UQI) (x) >> (y)) +#define SLLQI(x, y) ((UQI) (x) << (y)) +extern QI RORQI PARAMS ((QI, int)); +extern QI ROLQI PARAMS ((QI, int)); +#define ANDQI(x, y) ((x) & (y)) +#define ORQI(x, y) ((x) | (y)) +#define XORQI(x, y) ((x) ^ (y)) +#define NEGQI(x) (- (x)) +#define NOTQI(x) (! (QI) (x)) +#define INVQI(x) (~ (x)) +#define EQQI(x, y) ((QI) (x) == (QI) (y)) +#define NEQI(x, y) ((QI) (x) != (QI) (y)) +#define LTQI(x, y) ((QI) (x) < (QI) (y)) +#define LEQI(x, y) ((QI) (x) <= (QI) (y)) +#define GTQI(x, y) ((QI) (x) > (QI) (y)) +#define GEQI(x, y) ((QI) (x) >= (QI) (y)) +#define LTUQI(x, y) ((UQI) (x) < (UQI) (y)) +#define LEUQI(x, y) ((UQI) (x) <= (UQI) (y)) +#define GTUQI(x, y) ((UQI) (x) > (UQI) (y)) +#define GEUQI(x, y) ((UQI) (x) >= (UQI) (y)) + +#define ADDHI(x, y) ((x) + (y)) +#define SUBHI(x, y) ((x) - (y)) +#define MULHI(x, y) ((x) * (y)) +#define DIVHI(x, y) ((HI) (x) / (HI) (y)) +#define UDIVHI(x, y) ((UHI) (x) / (UHI) (y)) +#define MODHI(x, y) ((HI) (x) % (HI) (y)) +#define UMODHI(x, y) ((UHI) (x) % (UHI) (y)) +#define SRAHI(x, y) ((HI) (x) >> (y)) +#define SRLHI(x, y) ((UHI) (x) >> (y)) +#define SLLHI(x, y) ((UHI) (x) << (y)) +extern HI RORHI PARAMS ((HI, int)); +extern HI ROLHI PARAMS ((HI, int)); +#define ANDHI(x, y) ((x) & (y)) +#define ORHI(x, y) ((x) | (y)) +#define XORHI(x, y) ((x) ^ (y)) +#define NEGHI(x) (- (x)) +#define NOTHI(x) (! (HI) (x)) +#define INVHI(x) (~ (x)) +#define EQHI(x, y) ((HI) (x) == (HI) (y)) +#define NEHI(x, y) ((HI) (x) != (HI) (y)) +#define LTHI(x, y) ((HI) (x) < (HI) (y)) +#define LEHI(x, y) ((HI) (x) <= (HI) (y)) +#define GTHI(x, y) ((HI) (x) > (HI) (y)) +#define GEHI(x, y) ((HI) (x) >= (HI) (y)) +#define LTUHI(x, y) ((UHI) (x) < (UHI) (y)) +#define LEUHI(x, y) ((UHI) (x) <= (UHI) (y)) +#define GTUHI(x, y) ((UHI) (x) > (UHI) (y)) +#define GEUHI(x, y) ((UHI) (x) >= (UHI) (y)) + +#define ADDSI(x, y) ((x) + (y)) +#define SUBSI(x, y) ((x) - (y)) +#define MULSI(x, y) ((x) * (y)) +#define DIVSI(x, y) ((SI) (x) / (SI) (y)) +#define UDIVSI(x, y) ((USI) (x) / (USI) (y)) +#define MODSI(x, y) ((SI) (x) % (SI) (y)) +#define UMODSI(x, y) ((USI) (x) % (USI) (y)) +#define SRASI(x, y) ((SI) (x) >> (y)) +#define SRLSI(x, y) ((USI) (x) >> (y)) +#define SLLSI(x, y) ((USI) (x) << (y)) +extern SI RORSI PARAMS ((SI, int)); +extern SI ROLSI PARAMS ((SI, int)); +#define ANDSI(x, y) ((x) & (y)) +#define ORSI(x, y) ((x) | (y)) +#define XORSI(x, y) ((x) ^ (y)) +#define NEGSI(x) (- (x)) +#define NOTSI(x) (! (SI) (x)) +#define INVSI(x) (~ (x)) +#define EQSI(x, y) ((SI) (x) == (SI) (y)) +#define NESI(x, y) ((SI) (x) != (SI) (y)) +#define LTSI(x, y) ((SI) (x) < (SI) (y)) +#define LESI(x, y) ((SI) (x) <= (SI) (y)) +#define GTSI(x, y) ((SI) (x) > (SI) (y)) +#define GESI(x, y) ((SI) (x) >= (SI) (y)) +#define LTUSI(x, y) ((USI) (x) < (USI) (y)) +#define LEUSI(x, y) ((USI) (x) <= (USI) (y)) +#define GTUSI(x, y) ((USI) (x) > (USI) (y)) +#define GEUSI(x, y) ((USI) (x) >= (USI) (y)) + +#ifdef DI_FN_SUPPORT +extern DI ADDDI PARAMS ((DI, DI)); +extern DI SUBDI PARAMS ((DI, DI)); +extern DI MULDI PARAMS ((DI, DI)); +extern DI DIVDI PARAMS ((DI, DI)); +extern DI UDIVDI PARAMS ((DI, DI)); +extern DI MODDI PARAMS ((DI, DI)); +extern DI UMODDI PARAMS ((DI, DI)); +extern DI SRADI PARAMS ((DI, int)); +extern UDI SRLDI PARAMS ((UDI, int)); +extern UDI SLLDI PARAMS ((UDI, int)); +extern DI RORDI PARAMS ((DI, int)); +extern DI ROLDI PARAMS ((DI, int)); +extern DI ANDDI PARAMS ((DI, DI)); +extern DI ORDI PARAMS ((DI, DI)); +extern DI XORDI PARAMS ((DI, DI)); +extern DI NEGDI PARAMS ((DI)); +extern int NOTDI PARAMS ((DI)); +extern DI INVDI PARAMS ((DI)); +extern int EQDI PARAMS ((DI, DI)); +extern int NEDI PARAMS ((DI, DI)); +extern int LTDI PARAMS ((DI, DI)); +extern int LEDI PARAMS ((DI, DI)); +extern int GTDI PARAMS ((DI, DI)); +extern int GEDI PARAMS ((DI, DI)); +extern int LTUDI PARAMS ((UDI, UDI)); +extern int LEUDI PARAMS ((UDI, UDI)); +extern int GTUDI PARAMS ((UDI, UDI)); +extern int GEUDI PARAMS ((UDI, UDI)); +#else /* ! DI_FN_SUPPORT */ +#define ADDDI(x, y) ((x) + (y)) +#define SUBDI(x, y) ((x) - (y)) +#define MULDI(x, y) ((x) * (y)) +#define DIVDI(x, y) ((DI) (x) / (DI) (y)) +#define UDIVDI(x, y) ((UDI) (x) / (UDI) (y)) +#define MODDI(x, y) ((DI) (x) % (DI) (y)) +#define UMODDI(x, y) ((UDI) (x) % (UDI) (y)) +#define SRADI(x, y) ((DI) (x) >> (y)) +#define SRLDI(x, y) ((UDI) (x) >> (y)) +#define SLLDI(x, y) ((UDI) (x) << (y)) +extern DI RORDI PARAMS ((DI, int)); +extern DI ROLDI PARAMS ((DI, int)); +#define ANDDI(x, y) ((x) & (y)) +#define ORDI(x, y) ((x) | (y)) +#define XORDI(x, y) ((x) ^ (y)) +#define NEGDI(x) (- (x)) +#define NOTDI(x) (! (DI) (x)) +#define INVDI(x) (~ (x)) +#define EQDI(x, y) ((DI) (x) == (DI) (y)) +#define NEDI(x, y) ((DI) (x) != (DI) (y)) +#define LTDI(x, y) ((DI) (x) < (DI) (y)) +#define LEDI(x, y) ((DI) (x) <= (DI) (y)) +#define GTDI(x, y) ((DI) (x) > (DI) (y)) +#define GEDI(x, y) ((DI) (x) >= (DI) (y)) +#define LTUDI(x, y) ((UDI) (x) < (UDI) (y)) +#define LEUDI(x, y) ((UDI) (x) <= (UDI) (y)) +#define GTUDI(x, y) ((UDI) (x) > (UDI) (y)) +#define GEUDI(x, y) ((UDI) (x) >= (UDI) (y)) +#endif /* DI_FN_SUPPORT */ + +#ifdef SF_FN_SUPPORT +extern SF ADDSF PARAMS ((SF, SF)); +extern SF SUBSF PARAMS ((SF, SF)); +extern SF NEGSF PARAMS ((SF)); +extern SF MULSF PARAMS ((SF, SF)); +extern SF DIVSF PARAMS ((SF, SF)); +extern int EQSF PARAMS ((SF, SF)); +extern int NESF PARAMS ((SF, SF)); +extern int LTSF PARAMS ((SF, SF)); +extern int LESF PARAMS ((SF, SF)); +extern int GTSF PARAMS ((SF, SF)); +extern int GESF PARAMS ((SF, SF)); +extern SF ABSSF PARAMS ((SF)); +extern SF SQRTSF PARAMS ((SF)); +extern SF COSSF PARAMS ((SF)); +extern SF SINSF PARAMS ((SF)); +#else /* ! SF_FN_SUPPORT */ +#define ADDSF(x, y) ((x) + (y)) +#define SUBSF(x, y) ((x) - (y)) +#define NEGSF(x) (- (x)) +#define MULSF(x, y) ((x) * (y)) +#define DIVSF(x, y) ((x) / (y)) +#define EQSF(x, y) ((SF) (x) == (SF) (y)) +#define NESF(x, y) ((SF) (x) != (SF) (y)) +#define LTSF(x, y) ((SF) (x) < (SF) (y)) +#define LESF(x, y) ((SF) (x) <= (SF) (y)) +#define GTSF(x, y) ((SF) (x) > (SF) (y)) +#define GESF(x, y) ((SF) (x) >= (SF) (y)) +extern SF ABSSF PARAMS ((SF)); +extern SF SQRTSF PARAMS ((SF)); +extern SF COSSF PARAMS ((SF)); +extern SF SINSF PARAMS ((SF)); +#endif /* SF_FN_SUPPORT */ + +#ifdef DF_FN_SUPPORT +extern DF ADDDF PARAMS ((DF, DF)); +extern DF SUBDF PARAMS ((DF, DF)); +extern DF NEGDF PARAMS ((DF)); +extern DF MULDF PARAMS ((DF, DF)); +extern DF DIVDF PARAMS ((DF, DF)); +extern int EQDF PARAMS ((DF, DF)); +extern int NEDF PARAMS ((DF, DF)); +extern int LTDF PARAMS ((DF, DF)); +extern int LEDF PARAMS ((DF, DF)); +extern int GTDF PARAMS ((DF, DF)); +extern int GEDF PARAMS ((DF, DF)); +extern DF ABSDF PARAMS ((DF)); +extern DF SQRTDF PARAMS ((DF)); +extern DF COSDF PARAMS ((DF)); +extern DF SINDF PARAMS ((DF)); +#else /* ! DF_FN_SUPPORT */ +#define ADDDF(x, y) ((x) + (y)) +#define SUBDF(x, y) ((x) - (y)) +#define NEGDF(x) (- (x)) +#define MULDF(x, y) ((x) * (y)) +#define DIVDF(x, y) ((x) / (y)) +#define EQDF(x, y) ((DF) (x) == (DF) (y)) +#define NEDF(x, y) ((DF) (x) != (DF) (y)) +#define LTDF(x, y) ((DF) (x) < (DF) (y)) +#define LEDF(x, y) ((DF) (x) <= (DF) (y)) +#define GTDF(x, y) ((DF) (x) > (DF) (y)) +#define GEDF(x, y) ((DF) (x) >= (DF) (y)) +extern DF ABSDF PARAMS ((DF)); +extern DF SQRTDF PARAMS ((DF)); +extern DF COSDF PARAMS ((DF)); +extern DF SINDF PARAMS ((DF)); +#endif /* DF_FN_SUPPORT */ + +#ifdef XF_FN_SUPPORT +extern XF ADDXF PARAMS ((XF, XF)); +extern XF SUBXF PARAMS ((XF, XF)); +extern XF NEGXF PARAMS ((XF)); +extern XF MULXF PARAMS ((XF, XF)); +extern XF DIVXF PARAMS ((XF, XF)); +extern int EQXF PARAMS ((XF, XF)); +extern int NEXF PARAMS ((XF, XF)); +extern int LTXF PARAMS ((XF, XF)); +extern int LEXF PARAMS ((XF, XF)); +extern int GTXF PARAMS ((XF, XF)); +extern int GEXF PARAMS ((XF, XF)); +extern XF ABSXF PARAMS ((XF)); +extern XF SQRTXF PARAMS ((XF)); +extern XF COSXF PARAMS ((XF)); +extern XF SINXF PARAMS ((XF)); +#else /* ! XF_FN_SUPPORT */ +#define ADDXF(x, y) ((x) + (y)) +#define SUBXF(x, y) ((x) - (y)) +#define NEGXF(x) (- (x)) +#define MULXF(x, y) ((x) * (y)) +#define DIVXF(x, y) ((x) / (y)) +#define EQXF(x, y) ((XF) (x) == (XF) (y)) +#define NEXF(x, y) ((XF) (x) != (XF) (y)) +#define LTXF(x, y) ((XF) (x) < (XF) (y)) +#define LEXF(x, y) ((XF) (x) <= (XF) (y)) +#define GTXF(x, y) ((XF) (x) > (XF) (y)) +#define GEXF(x, y) ((XF) (x) >= (XF) (y)) +extern XF ABSXF PARAMS ((XF)); +extern XF SQRTXF PARAMS ((XF)); +extern XF COSXF PARAMS ((XF)); +extern XF SINXF PARAMS ((XF)); +#endif /* XF_FN_SUPPORT */ + +#ifdef TF_FN_SUPPORT +extern TF ADDTF PARAMS ((TF, TF)); +extern TF SUBTF PARAMS ((TF, TF)); +extern TF NEGTF PARAMS ((TF)); +extern TF MULTF PARAMS ((TF, TF)); +extern TF DIVTF PARAMS ((TF, TF)); +extern int EQTF PARAMS ((TF, TF)); +extern int NETF PARAMS ((TF, TF)); +extern int LTTF PARAMS ((TF, TF)); +extern int LETF PARAMS ((TF, TF)); +extern int GTTF PARAMS ((TF, TF)); +extern int GETF PARAMS ((TF, TF)); +extern TF ABSTF PARAMS ((TF)); +extern TF SQRTTF PARAMS ((TF)); +extern TF COSTF PARAMS ((TF)); +extern TF SINTF PARAMS ((TF)); +#else /* ! TF_FN_SUPPORT */ +#define ADDTF(x, y) ((x) + (y)) +#define SUBTF(x, y) ((x) - (y)) +#define NEGTF(x) (- (x)) +#define MULTF(x, y) ((x) * (y)) +#define DIVTF(x, y) ((x) / (y)) +#define EQTF(x, y) ((TF) (x) == (TF) (y)) +#define NETF(x, y) ((TF) (x) != (TF) (y)) +#define LTTF(x, y) ((TF) (x) < (TF) (y)) +#define LETF(x, y) ((TF) (x) <= (TF) (y)) +#define GTTF(x, y) ((TF) (x) > (TF) (y)) +#define GETF(x, y) ((TF) (x) >= (TF) (y)) +extern TF ABSTF PARAMS ((TF)); +extern TF SQRTTF PARAMS ((TF)); +extern TF COSTF PARAMS ((TF)); +extern TF SINTF PARAMS ((TF)); +#endif /* TF_FN_SUPPORT */ + + +#define EXTBIQI(x) ((QI) (BI) (x)) +#define EXTBIHI(x) ((HI) (BI) (x)) +#define EXTBISI(x) ((SI) (BI) (x)) +#if defined (DI_FN_SUPPORT) +extern DI EXTBIDI PARAMS ((BI)); +#else +#define EXTBIDI(x) ((DI) (BI) (x)) +#endif +#define EXTQIHI(x) ((HI) (QI) (x)) +#define EXTQISI(x) ((SI) (QI) (x)) +#if defined (DI_FN_SUPPORT) +extern DI EXTQIDI PARAMS ((QI)); +#else +#define EXTQIDI(x) ((DI) (QI) (x)) +#endif +#define EXTHISI(x) ((SI) (HI) (x)) +#if defined (DI_FN_SUPPORT) +extern DI EXTHIDI PARAMS ((HI)); +#else +#define EXTHIDI(x) ((DI) (HI) (x)) +#endif +#if defined (DI_FN_SUPPORT) +extern DI EXTSIDI PARAMS ((SI)); +#else +#define EXTSIDI(x) ((DI) (SI) (x)) +#endif +#if defined (SF_FN_SUPPORT) || defined (DF_FN_SUPPORT) +extern DF EXTSFDF PARAMS ((SF)); +#else +#define EXTSFDF(x) ((DF) (SF) (x)) +#endif +#if defined (SF_FN_SUPPORT) || defined (XF_FN_SUPPORT) +extern XF EXTSFXF PARAMS ((SF)); +#else +#define EXTSFXF(x) ((XF) (SF) (x)) +#endif +#if defined (SF_FN_SUPPORT) || defined (TF_FN_SUPPORT) +extern TF EXTSFTF PARAMS ((SF)); +#else +#define EXTSFTF(x) ((TF) (SF) (x)) +#endif +#if defined (DF_FN_SUPPORT) || defined (XF_FN_SUPPORT) +extern XF EXTDFXF PARAMS ((DF)); +#else +#define EXTDFXF(x) ((XF) (DF) (x)) +#endif +#if defined (DF_FN_SUPPORT) || defined (TF_FN_SUPPORT) +extern TF EXTDFTF PARAMS ((DF)); +#else +#define EXTDFTF(x) ((TF) (DF) (x)) +#endif +#if defined (XF_FN_SUPPORT) || defined (TF_FN_SUPPORT) +extern TF EXTXFTF PARAMS ((XF)); +#else +#define EXTXFTF(x) ((TF) (XF) (x)) +#endif +#define ZEXTBIQI(x) ((QI) (BI) (x)) +#define ZEXTBIHI(x) ((HI) (BI) (x)) +#define ZEXTBISI(x) ((SI) (BI) (x)) +#if defined (DI_FN_SUPPORT) +extern DI ZEXTBIDI PARAMS ((BI)); +#else +#define ZEXTBIDI(x) ((DI) (BI) (x)) +#endif +#define ZEXTQIHI(x) ((HI) (UQI) (x)) +#define ZEXTQISI(x) ((SI) (UQI) (x)) +#if defined (DI_FN_SUPPORT) +extern DI ZEXTQIDI PARAMS ((QI)); +#else +#define ZEXTQIDI(x) ((DI) (UQI) (x)) +#endif +#define ZEXTHISI(x) ((SI) (UHI) (x)) +#if defined (DI_FN_SUPPORT) +extern DI ZEXTHIDI PARAMS ((HI)); +#else +#define ZEXTHIDI(x) ((DI) (UHI) (x)) +#endif +#if defined (DI_FN_SUPPORT) +extern DI ZEXTSIDI PARAMS ((SI)); +#else +#define ZEXTSIDI(x) ((DI) (USI) (x)) +#endif +#define TRUNCQIBI(x) ((BI) (QI) (x)) +#define TRUNCHIBI(x) ((BI) (HI) (x)) +#define TRUNCHIQI(x) ((QI) (HI) (x)) +#define TRUNCSIBI(x) ((BI) (SI) (x)) +#define TRUNCSIQI(x) ((QI) (SI) (x)) +#define TRUNCSIHI(x) ((HI) (SI) (x)) +#if defined (DI_FN_SUPPORT) +extern BI TRUNCDIBI PARAMS ((DI)); +#else +#define TRUNCDIBI(x) ((BI) (DI) (x)) +#endif +#if defined (DI_FN_SUPPORT) +extern QI TRUNCDIQI PARAMS ((DI)); +#else +#define TRUNCDIQI(x) ((QI) (DI) (x)) +#endif +#if defined (DI_FN_SUPPORT) +extern HI TRUNCDIHI PARAMS ((DI)); +#else +#define TRUNCDIHI(x) ((HI) (DI) (x)) +#endif +#if defined (DI_FN_SUPPORT) +extern SI TRUNCDISI PARAMS ((DI)); +#else +#define TRUNCDISI(x) ((SI) (DI) (x)) +#endif +#if defined (DF_FN_SUPPORT) || defined (SF_FN_SUPPORT) +extern SF TRUNCDFSF PARAMS ((DF)); +#else +#define TRUNCDFSF(x) ((SF) (DF) (x)) +#endif +#if defined (XF_FN_SUPPORT) || defined (SF_FN_SUPPORT) +extern SF TRUNCXFSF PARAMS ((XF)); +#else +#define TRUNCXFSF(x) ((SF) (XF) (x)) +#endif +#if defined (XF_FN_SUPPORT) || defined (DF_FN_SUPPORT) +extern DF TRUNCXFDF PARAMS ((XF)); +#else +#define TRUNCXFDF(x) ((DF) (XF) (x)) +#endif +#if defined (TF_FN_SUPPORT) || defined (SF_FN_SUPPORT) +extern SF TRUNCTFSF PARAMS ((TF)); +#else +#define TRUNCTFSF(x) ((SF) (TF) (x)) +#endif +#if defined (TF_FN_SUPPORT) || defined (DF_FN_SUPPORT) +extern DF TRUNCTFDF PARAMS ((TF)); +#else +#define TRUNCTFDF(x) ((DF) (TF) (x)) +#endif +#if defined (TF_FN_SUPPORT) || defined (XF_FN_SUPPORT) +extern XF TRUNCTFXF PARAMS ((TF)); +#else +#define TRUNCTFXF(x) ((XF) (TF) (x)) +#endif +#if defined (SF_FN_SUPPORT) +extern SF FLOATQISF PARAMS ((QI)); +#else +#define FLOATQISF(x) ((SF) (QI) (x)) +#endif +#if defined (DF_FN_SUPPORT) +extern DF FLOATQIDF PARAMS ((QI)); +#else +#define FLOATQIDF(x) ((DF) (QI) (x)) +#endif +#if defined (XF_FN_SUPPORT) +extern XF FLOATQIXF PARAMS ((QI)); +#else +#define FLOATQIXF(x) ((XF) (QI) (x)) +#endif +#if defined (TF_FN_SUPPORT) +extern TF FLOATQITF PARAMS ((QI)); +#else +#define FLOATQITF(x) ((TF) (QI) (x)) +#endif +#if defined (SF_FN_SUPPORT) +extern SF FLOATHISF PARAMS ((HI)); +#else +#define FLOATHISF(x) ((SF) (HI) (x)) +#endif +#if defined (DF_FN_SUPPORT) +extern DF FLOATHIDF PARAMS ((HI)); +#else +#define FLOATHIDF(x) ((DF) (HI) (x)) +#endif +#if defined (XF_FN_SUPPORT) +extern XF FLOATHIXF PARAMS ((HI)); +#else +#define FLOATHIXF(x) ((XF) (HI) (x)) +#endif +#if defined (TF_FN_SUPPORT) +extern TF FLOATHITF PARAMS ((HI)); +#else +#define FLOATHITF(x) ((TF) (HI) (x)) +#endif +#if defined (SF_FN_SUPPORT) +extern SF FLOATSISF PARAMS ((SI)); +#else +#define FLOATSISF(x) ((SF) (SI) (x)) +#endif +#if defined (DF_FN_SUPPORT) +extern DF FLOATSIDF PARAMS ((SI)); +#else +#define FLOATSIDF(x) ((DF) (SI) (x)) +#endif +#if defined (XF_FN_SUPPORT) +extern XF FLOATSIXF PARAMS ((SI)); +#else +#define FLOATSIXF(x) ((XF) (SI) (x)) +#endif +#if defined (TF_FN_SUPPORT) +extern TF FLOATSITF PARAMS ((SI)); +#else +#define FLOATSITF(x) ((TF) (SI) (x)) +#endif +#if defined (DI_FN_SUPPORT) || defined (SF_FN_SUPPORT) +extern SF FLOATDISF PARAMS ((DI)); +#else +#define FLOATDISF(x) ((SF) (DI) (x)) +#endif +#if defined (DI_FN_SUPPORT) || defined (DF_FN_SUPPORT) +extern DF FLOATDIDF PARAMS ((DI)); +#else +#define FLOATDIDF(x) ((DF) (DI) (x)) +#endif +#if defined (DI_FN_SUPPORT) || defined (XF_FN_SUPPORT) +extern XF FLOATDIXF PARAMS ((DI)); +#else +#define FLOATDIXF(x) ((XF) (DI) (x)) +#endif +#if defined (DI_FN_SUPPORT) || defined (TF_FN_SUPPORT) +extern TF FLOATDITF PARAMS ((DI)); +#else +#define FLOATDITF(x) ((TF) (DI) (x)) +#endif +#if defined (SF_FN_SUPPORT) +extern SF UFLOATQISF PARAMS ((QI)); +#else +#define UFLOATQISF(x) ((SF) (UQI) (x)) +#endif +#if defined (DF_FN_SUPPORT) +extern DF UFLOATQIDF PARAMS ((QI)); +#else +#define UFLOATQIDF(x) ((DF) (UQI) (x)) +#endif +#if defined (XF_FN_SUPPORT) +extern XF UFLOATQIXF PARAMS ((QI)); +#else +#define UFLOATQIXF(x) ((XF) (UQI) (x)) +#endif +#if defined (TF_FN_SUPPORT) +extern TF UFLOATQITF PARAMS ((QI)); +#else +#define UFLOATQITF(x) ((TF) (UQI) (x)) +#endif +#if defined (SF_FN_SUPPORT) +extern SF UFLOATHISF PARAMS ((HI)); +#else +#define UFLOATHISF(x) ((SF) (UHI) (x)) +#endif +#if defined (DF_FN_SUPPORT) +extern DF UFLOATHIDF PARAMS ((HI)); +#else +#define UFLOATHIDF(x) ((DF) (UHI) (x)) +#endif +#if defined (XF_FN_SUPPORT) +extern XF UFLOATHIXF PARAMS ((HI)); +#else +#define UFLOATHIXF(x) ((XF) (UHI) (x)) +#endif +#if defined (TF_FN_SUPPORT) +extern TF UFLOATHITF PARAMS ((HI)); +#else +#define UFLOATHITF(x) ((TF) (UHI) (x)) +#endif +#if defined (SF_FN_SUPPORT) +extern SF UFLOATSISF PARAMS ((SI)); +#else +#define UFLOATSISF(x) ((SF) (USI) (x)) +#endif +#if defined (DF_FN_SUPPORT) +extern DF UFLOATSIDF PARAMS ((SI)); +#else +#define UFLOATSIDF(x) ((DF) (USI) (x)) +#endif +#if defined (XF_FN_SUPPORT) +extern XF UFLOATSIXF PARAMS ((SI)); +#else +#define UFLOATSIXF(x) ((XF) (USI) (x)) +#endif +#if defined (TF_FN_SUPPORT) +extern TF UFLOATSITF PARAMS ((SI)); +#else +#define UFLOATSITF(x) ((TF) (USI) (x)) +#endif +#if defined (DI_FN_SUPPORT) || defined (SF_FN_SUPPORT) +extern SF UFLOATDISF PARAMS ((DI)); +#else +#define UFLOATDISF(x) ((SF) (UDI) (x)) +#endif +#if defined (DI_FN_SUPPORT) || defined (DF_FN_SUPPORT) +extern DF UFLOATDIDF PARAMS ((DI)); +#else +#define UFLOATDIDF(x) ((DF) (UDI) (x)) +#endif +#if defined (DI_FN_SUPPORT) || defined (XF_FN_SUPPORT) +extern XF UFLOATDIXF PARAMS ((DI)); +#else +#define UFLOATDIXF(x) ((XF) (UDI) (x)) +#endif +#if defined (DI_FN_SUPPORT) || defined (TF_FN_SUPPORT) +extern TF UFLOATDITF PARAMS ((DI)); +#else +#define UFLOATDITF(x) ((TF) (UDI) (x)) +#endif +#if defined (SF_FN_SUPPORT) +extern BI FIXSFBI PARAMS ((SF)); +#else +#define FIXSFBI(x) ((BI) (SF) (x)) +#endif +#if defined (SF_FN_SUPPORT) +extern QI FIXSFQI PARAMS ((SF)); +#else +#define FIXSFQI(x) ((QI) (SF) (x)) +#endif +#if defined (SF_FN_SUPPORT) +extern HI FIXSFHI PARAMS ((SF)); +#else +#define FIXSFHI(x) ((HI) (SF) (x)) +#endif +#if defined (SF_FN_SUPPORT) +extern SI FIXSFSI PARAMS ((SF)); +#else +#define FIXSFSI(x) ((SI) (SF) (x)) +#endif +#if defined (SF_FN_SUPPORT) || defined (DI_FN_SUPPORT) +extern DI FIXSFDI PARAMS ((SF)); +#else +#define FIXSFDI(x) ((DI) (SF) (x)) +#endif +#if defined (DF_FN_SUPPORT) +extern BI FIXDFBI PARAMS ((DF)); +#else +#define FIXDFBI(x) ((BI) (DF) (x)) +#endif +#if defined (DF_FN_SUPPORT) +extern QI FIXDFQI PARAMS ((DF)); +#else +#define FIXDFQI(x) ((QI) (DF) (x)) +#endif +#if defined (DF_FN_SUPPORT) +extern HI FIXDFHI PARAMS ((DF)); +#else +#define FIXDFHI(x) ((HI) (DF) (x)) +#endif +#if defined (DF_FN_SUPPORT) +extern SI FIXDFSI PARAMS ((DF)); +#else +#define FIXDFSI(x) ((SI) (DF) (x)) +#endif +#if defined (DF_FN_SUPPORT) || defined (DI_FN_SUPPORT) +extern DI FIXDFDI PARAMS ((DF)); +#else +#define FIXDFDI(x) ((DI) (DF) (x)) +#endif +#if defined (XF_FN_SUPPORT) +extern BI FIXXFBI PARAMS ((XF)); +#else +#define FIXXFBI(x) ((BI) (XF) (x)) +#endif +#if defined (XF_FN_SUPPORT) +extern QI FIXXFQI PARAMS ((XF)); +#else +#define FIXXFQI(x) ((QI) (XF) (x)) +#endif +#if defined (XF_FN_SUPPORT) +extern HI FIXXFHI PARAMS ((XF)); +#else +#define FIXXFHI(x) ((HI) (XF) (x)) +#endif +#if defined (XF_FN_SUPPORT) +extern SI FIXXFSI PARAMS ((XF)); +#else +#define FIXXFSI(x) ((SI) (XF) (x)) +#endif +#if defined (XF_FN_SUPPORT) || defined (DI_FN_SUPPORT) +extern DI FIXXFDI PARAMS ((XF)); +#else +#define FIXXFDI(x) ((DI) (XF) (x)) +#endif +#if defined (TF_FN_SUPPORT) +extern BI FIXTFBI PARAMS ((TF)); +#else +#define FIXTFBI(x) ((BI) (TF) (x)) +#endif +#if defined (TF_FN_SUPPORT) +extern QI FIXTFQI PARAMS ((TF)); +#else +#define FIXTFQI(x) ((QI) (TF) (x)) +#endif +#if defined (TF_FN_SUPPORT) +extern HI FIXTFHI PARAMS ((TF)); +#else +#define FIXTFHI(x) ((HI) (TF) (x)) +#endif +#if defined (TF_FN_SUPPORT) +extern SI FIXTFSI PARAMS ((TF)); +#else +#define FIXTFSI(x) ((SI) (TF) (x)) +#endif +#if defined (TF_FN_SUPPORT) || defined (DI_FN_SUPPORT) +extern DI FIXTFDI PARAMS ((TF)); +#else +#define FIXTFDI(x) ((DI) (TF) (x)) +#endif +#if defined (SF_FN_SUPPORT) +extern QI UFIXSFQI PARAMS ((SF)); +#else +#define UFIXSFQI(x) ((UQI) (SF) (x)) +#endif +#if defined (SF_FN_SUPPORT) +extern HI UFIXSFHI PARAMS ((SF)); +#else +#define UFIXSFHI(x) ((UHI) (SF) (x)) +#endif +#if defined (SF_FN_SUPPORT) +extern SI UFIXSFSI PARAMS ((SF)); +#else +#define UFIXSFSI(x) ((USI) (SF) (x)) +#endif +#if defined (SF_FN_SUPPORT) || defined (DI_FN_SUPPORT) +extern DI UFIXSFDI PARAMS ((SF)); +#else +#define UFIXSFDI(x) ((UDI) (SF) (x)) +#endif +#if defined (DF_FN_SUPPORT) +extern QI UFIXDFQI PARAMS ((DF)); +#else +#define UFIXDFQI(x) ((UQI) (DF) (x)) +#endif +#if defined (DF_FN_SUPPORT) +extern HI UFIXDFHI PARAMS ((DF)); +#else +#define UFIXDFHI(x) ((UHI) (DF) (x)) +#endif +#if defined (DF_FN_SUPPORT) +extern SI UFIXDFSI PARAMS ((DF)); +#else +#define UFIXDFSI(x) ((USI) (DF) (x)) +#endif +#if defined (DF_FN_SUPPORT) || defined (DI_FN_SUPPORT) +extern DI UFIXDFDI PARAMS ((DF)); +#else +#define UFIXDFDI(x) ((UDI) (DF) (x)) +#endif +#if defined (XF_FN_SUPPORT) +extern QI UFIXXFQI PARAMS ((XF)); +#else +#define UFIXXFQI(x) ((UQI) (XF) (x)) +#endif +#if defined (XF_FN_SUPPORT) +extern HI UFIXXFHI PARAMS ((XF)); +#else +#define UFIXXFHI(x) ((UHI) (XF) (x)) +#endif +#if defined (XF_FN_SUPPORT) +extern SI UFIXXFSI PARAMS ((XF)); +#else +#define UFIXXFSI(x) ((USI) (XF) (x)) +#endif +#if defined (XF_FN_SUPPORT) || defined (DI_FN_SUPPORT) +extern DI UFIXXFDI PARAMS ((XF)); +#else +#define UFIXXFDI(x) ((UDI) (XF) (x)) +#endif +#if defined (TF_FN_SUPPORT) +extern QI UFIXTFQI PARAMS ((TF)); +#else +#define UFIXTFQI(x) ((UQI) (TF) (x)) +#endif +#if defined (TF_FN_SUPPORT) +extern HI UFIXTFHI PARAMS ((TF)); +#else +#define UFIXTFHI(x) ((UHI) (TF) (x)) +#endif +#if defined (TF_FN_SUPPORT) +extern SI UFIXTFSI PARAMS ((TF)); +#else +#define UFIXTFSI(x) ((USI) (TF) (x)) +#endif +#if defined (TF_FN_SUPPORT) || defined (DI_FN_SUPPORT) +extern DI UFIXTFDI PARAMS ((TF)); +#else +#define UFIXTFDI(x) ((UDI) (TF) (x)) +#endif + +/* Semantic support utilities. */ + +#ifdef __GNUC__ + +#ifdef SEMOPS_DEFINE_INLINE +#define SEMOPS_INLINE +#else +#define SEMOPS_INLINE extern inline +#endif + +SEMOPS_INLINE SI +ADDCSI (SI a, SI b, BI c) +{ + SI res = ADDSI (a, ADDSI (b, c)); + return res; +} + +SEMOPS_INLINE BI +ADDCFSI (SI a, SI b, BI c) +{ + SI tmp = ADDSI (a, ADDSI (b, c)); + BI res = ((USI) tmp < (USI) a) || (c && tmp == a); + return res; +} + +SEMOPS_INLINE BI +ADDOFSI (SI a, SI b, BI c) +{ + SI tmp = ADDSI (a, ADDSI (b, c)); + BI res = (((a < 0) == (b < 0)) + && ((a < 0) != (tmp < 0))); + return res; +} + +SEMOPS_INLINE SI +SUBCSI (SI a, SI b, BI c) +{ + SI res = SUBSI (a, ADDSI (b, c)); + return res; +} + +SEMOPS_INLINE BI +SUBCFSI (SI a, SI b, BI c) +{ + BI res = ((USI) a < (USI) b) || (c && a == b); + return res; +} + +SEMOPS_INLINE BI +SUBOFSI (SI a, SI b, BI c) +{ + SI tmp = SUBSI (a, ADDSI (b, c)); + BI res = (((a < 0) != (b < 0)) + && ((a < 0) != (tmp < 0))); + return res; +} + +#else + +SI ADDCSI (SI, SI, BI); +UBI ADDCFSI (SI, SI, BI); +UBI ADDOFSI (SI, SI, BI); +SI SUBCSI (SI, SI, BI); +UBI SUBCFSI (SI, SI, BI); +UBI SUBOFSI (SI, SI, BI); + +#endif + +/* DI mode support if "long long" doesn't exist. + At one point CGEN supported K&R C compilers, and ANSI C compilers without + "long long". One can argue the various merits of keeping this in or + throwing it out. I went to the trouble of adding it so for the time being + I'm leaving it in. */ + +#ifdef DI_FN_SUPPORT + +DI make_struct_di (SI, SI); +/* FIXME: needed? */ +DI CONVHIDI (HI); +DI CONVSIDI (SI); +SI CONVDISI (DI); + +#endif /* DI_FN_SUPPORT */ + +#endif /* CGEN_SEM_OPS_H */ diff --git a/sim/common/cgen-run.c b/sim/common/cgen-run.c new file mode 100644 index 00000000000..07ee19197d7 --- /dev/null +++ b/sim/common/cgen-run.c @@ -0,0 +1,233 @@ +/* Main simulator loop for CGEN-based simulators. + Copyright (C) 1998 Free Software Foundation, Inc. + Contributed by Cygnus Solutions. + +This file is part of GDB, the GNU debugger. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* ??? These are old notes, kept around for now. + Collecting profile data and tracing slow us down so we don't do them in + "fast mode". + There are 6 possibilities on 2 axes: + - no-scaching, insn-scaching, basic-block-scaching + - run with full features or run fast + Supporting all six possibilities in one executable is a bit much but + supporting full/fast seems reasonable. + If the scache is configured in it is always used. + If pbb-scaching is configured in it is always used. + ??? Sometimes supporting more than one set of semantic functions will make + the simulator too large - this should be configurable. Blah blah blah. + ??? Supporting full/fast can be more modular, blah blah blah. + When the framework is more modular, this can be. +*/ + +#include "sim-main.h" +#include "sim-assert.h" + +#ifndef SIM_ENGINE_PREFIX_HOOK +#define SIM_ENGINE_PREFIX_HOOK(sd) +#endif +#ifndef SIM_ENGINE_POSTFIX_HOOK +#define SIM_ENGINE_POSTFIX_HOOK(sd) +#endif + +static sim_event_handler has_stepped; +static void prime_cpu (SIM_CPU *, int); +static void engine_run_1 (SIM_DESC, int, int); +static void engine_run_n (SIM_DESC, int, int, int, int); + +/* sim_resume for cgen */ + +void +sim_resume (SIM_DESC sd, int step, int siggnal) +{ + sim_engine *engine = STATE_ENGINE (sd); + jmp_buf buf; + int jmpval; + + ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); + + /* we only want to be single stepping the simulator once */ + if (engine->stepper != NULL) + { + sim_events_deschedule (sd, engine->stepper); + engine->stepper = NULL; + } + if (step) + engine->stepper = sim_events_schedule (sd, 1, has_stepped, sd); + + sim_module_resume (sd); + +#if WITH_SCACHE + if (USING_SCACHE_P (sd)) + scache_flush (sd); +#endif + + /* run/resume the simulator */ + + sim_engine_set_run_state (sd, sim_running, 0); + + engine->jmpbuf = &buf; + jmpval = setjmp (buf); + if (jmpval == sim_engine_start_jmpval + || jmpval == sim_engine_restart_jmpval) + { + int last_cpu_nr = sim_engine_last_cpu_nr (sd); + int next_cpu_nr = sim_engine_next_cpu_nr (sd); + int nr_cpus = sim_engine_nr_cpus (sd); + /* ??? Setting max_insns to 0 allows pbb/jit code to run wild and is + useful if all one wants to do is run a benchmark. Need some better + way to identify this case. */ + int max_insns = (step + ? 1 + : (nr_cpus == 1 /*&& wip:no-events*/) + ? 0 + : 4); /*FIXME: magic number*/ + int fast_p = STATE_RUN_FAST_P (sd); + + sim_events_preprocess (sd, last_cpu_nr >= nr_cpus, next_cpu_nr >= nr_cpus); + if (next_cpu_nr >= nr_cpus) + next_cpu_nr = 0; + if (nr_cpus == 1) + engine_run_1 (sd, max_insns, fast_p); + else + engine_run_n (sd, next_cpu_nr, nr_cpus, max_insns, fast_p); + } +#if 1 /*wip*/ + else + { + /* Account for the last insn executed. */ + SIM_CPU *cpu = STATE_CPU (sd, sim_engine_last_cpu_nr (sd)); + ++ CPU_INSN_COUNT (cpu); + TRACE_INSN_FINI (cpu, NULL, 1); + } +#endif + + engine->jmpbuf = NULL; + + { + int i; + int nr_cpus = sim_engine_nr_cpus (sd); + +#if 0 /*wip,ignore*/ + /* If the loop exits, either we single-stepped or @cpu@_engine_stop + was called. */ + if (step) + sim_engine_set_run_state (sd, sim_stopped, SIM_SIGTRAP); + else + sim_engine_set_run_state (sd, pending_reason, pending_sigrc); +#endif + + for (i = 0; i < nr_cpus; ++i) + { + SIM_CPU *cpu = STATE_CPU (sd, i); + + PROFILE_TOTAL_INSN_COUNT (CPU_PROFILE_DATA (cpu)) += CPU_INSN_COUNT (cpu); + } + } + + sim_module_suspend (sd); +} + +/* Halt the simulator after just one instruction. */ + +static void +has_stepped (SIM_DESC sd, void *data) +{ + ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); + sim_engine_halt (sd, NULL, NULL, NULL_CIA, sim_stopped, SIM_SIGTRAP); +} + +/* Prepare a cpu for running. + MAX_INSNS is the number of insns to execute per time slice. + If 0 it means the cpu can run as long as it wants (e.g. until the + program completes). + ??? Perhaps this should be an argument to the engine_fn. */ + +static void +prime_cpu (SIM_CPU *cpu, int max_insns) +{ + CPU_MAX_SLICE_INSNS (cpu) = max_insns; + CPU_INSN_COUNT (cpu) = 0; + + /* Initialize the insn descriptor table. + This has to be done after all initialization so we just defer it to + here. */ + + if (MACH_PREPARE_RUN (CPU_MACH (cpu))) + (* MACH_PREPARE_RUN (CPU_MACH (cpu))) (cpu); +} + +/* Main loop, for 1 cpu. */ + +static void +engine_run_1 (SIM_DESC sd, int max_insns, int fast_p) +{ + sim_cpu *cpu = STATE_CPU (sd, 0); + ENGINE_FN *fn = fast_p ? CPU_FAST_ENGINE_FN (cpu) : CPU_FULL_ENGINE_FN (cpu); + + prime_cpu (cpu, max_insns); + + while (1) + { + SIM_ENGINE_PREFIX_HOOK (sd); + + (*fn) (cpu); + + SIM_ENGINE_POSTFIX_HOOK (sd); + + /* process any events */ + if (sim_events_tick (sd)) + sim_events_process (sd); + } +} + +/* Main loop, for multiple cpus. */ + +static void +engine_run_n (SIM_DESC sd, int next_cpu_nr, int nr_cpus, int max_insns, int fast_p) +{ + int i; + ENGINE_FN *engine_fns[MAX_NR_PROCESSORS]; + + for (i = 0; i < nr_cpus; ++i) + { + SIM_CPU *cpu = STATE_CPU (sd, i); + + engine_fns[i] = fast_p ? CPU_FAST_ENGINE_FN (cpu) : CPU_FULL_ENGINE_FN (cpu); + prime_cpu (cpu, max_insns); + } + + while (1) + { + SIM_ENGINE_PREFIX_HOOK (sd); + + /* FIXME: proper cycling of all of them, blah blah blah. */ + while (next_cpu_nr != nr_cpus) + { + SIM_CPU *cpu = STATE_CPU (sd, next_cpu_nr); + + (* engine_fns[next_cpu_nr]) (cpu); + ++next_cpu_nr; + } + + SIM_ENGINE_POSTFIX_HOOK (sd); + + /* process any events */ + if (sim_events_tick (sd)) + sim_events_process (sd); + } +} diff --git a/sim/common/cgen-scache.c b/sim/common/cgen-scache.c new file mode 100644 index 00000000000..c5ea075a9f1 --- /dev/null +++ b/sim/common/cgen-scache.c @@ -0,0 +1,471 @@ +/* Simulator cache routines for CGEN simulators (and maybe others). + Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. + Contributed by Cygnus Support. + +This file is part of GDB, the GNU debugger. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#define SCACHE_DEFINE_INLINE + +#include "sim-main.h" +#ifdef HAVE_STDLIB_H +#include +#endif +#include "libiberty.h" +#include "sim-options.h" +#include "sim-io.h" + +#define MAX(a,b) ((a) > (b) ? (a) : (b)) + +/* Unused address. */ +#define UNUSED_ADDR 0xffffffff + +/* Scache configuration parameters. + ??? Experiments to determine reasonable values is wip. + These are just guesses. */ + +/* Default number of scache elements. + The size of an element is typically 32-64 bytes, so the size of the + default scache will be between 512K and 1M bytes. */ +#ifdef CONFIG_SIM_CACHE_SIZE +#define SCACHE_DEFAULT_CACHE_SIZE CONFIG_SIM_CACHE_SIZE +#else +#define SCACHE_DEFAULT_CACHE_SIZE 16384 +#endif + +/* Minimum cache size. + The m32r port assumes a cache size of at least 2 so it can decode both 16 + bit insns. When compiling we need an extra for the chain entry. And this + must be a multiple of 2. Hence 4 is the minimum (though, for those with + featuritis or itchy pedantic bits, we could make this conditional on + WITH_SCACHE_PBB). */ +#define MIN_SCACHE_SIZE 4 + +/* Ratio of size of text section to size of scache. + When compiling, we don't want to flush the scache more than we have to + but we also don't want it to be exorbitantly(sp?) large. So we pick a high + default value, then reduce it by the size of the program being simulated, + but we don't override any value specified on the command line. + If not specified on the command line, the size to use is computed as + max (MIN_SCACHE_SIZE, + min (DEFAULT_SCACHE_SIZE, + text_size / (base_insn_size * INSN_SCACHE_RATIO))). */ +/* ??? Interesting idea but not currently used. */ +#define INSN_SCACHE_RATIO 4 + +/* Default maximum insn chain length. + The only reason for a maximum is so we can place a maximum size on the + profiling table. Chain lengths are determined by cti's. + 32 is a more reasonable number, but when profiling, the before/after + handlers take up that much more space. The scache is filled from front to + back so all this determines is when the scache needs to be flushed. */ +#define MAX_CHAIN_LENGTH 64 + +/* Default maximum hash list length. */ +#define MAX_HASH_CHAIN_LENGTH 4 + +/* Minimum hash table size. */ +#define MIN_HASH_CHAINS 32 + +/* Ratio of number of scache elements to number of hash lists. + Since the user can only specify the size of the scache, we compute the + size of the hash table as + max (MIN_HASH_CHAINS, scache_size / SCACHE_HASH_RATIO). */ +#define SCACHE_HASH_RATIO 8 + +/* Hash a PC value. + FIXME: May wish to make the hashing architecture specific. + FIXME: revisit */ +#define HASH_PC(pc) (((pc) >> 2) + ((pc) >> 5)) + +static MODULE_INIT_FN scache_init; +static MODULE_UNINSTALL_FN scache_uninstall; + +static DECLARE_OPTION_HANDLER (scache_option_handler); + +#define OPTION_PROFILE_SCACHE (OPTION_START + 0) + +static const OPTION scache_options[] = { + { {"scache-size", optional_argument, NULL, 'c'}, + 'c', "[SIZE]", "Specify size of simulator execution cache", + scache_option_handler }, +#if WITH_SCACHE_PBB + /* ??? It might be nice to allow the user to specify the size of the hash + table, the maximum hash list length, and the maximum chain length, but + for now that might be more akin to featuritis. */ +#endif + { {"profile-scache", optional_argument, NULL, OPTION_PROFILE_SCACHE}, + '\0', "on|off", "Perform simulator execution cache profiling", + scache_option_handler }, + { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL } +}; + +static SIM_RC +scache_option_handler (SIM_DESC sd, sim_cpu *cpu, int opt, + char *arg, int is_command) +{ + int n; + + switch (opt) + { + case 'c' : + if (WITH_SCACHE) + { + if (arg != NULL) + { + int n = strtol (arg, NULL, 0); + if (n < MIN_SCACHE_SIZE) + { + sim_io_eprintf (sd, "invalid scache size `%d', must be at least 4", n); + return SIM_RC_FAIL; + } + /* Ensure it's a multiple of 2. */ + if ((n & (n - 1)) != 0) + { + sim_io_eprintf (sd, "scache size `%d' not a multiple of 2\n", n); + { + /* round up to nearest multiple of 2 */ + int i; + for (i = 1; i < n; i <<= 1) + continue; + n = i; + } + sim_io_eprintf (sd, "rounding scache size up to %d\n", n); + } + if (cpu == NULL) + STATE_SCACHE_SIZE (sd) = n; + else + CPU_SCACHE_SIZE (cpu) = n; + } + else + { + if (cpu == NULL) + STATE_SCACHE_SIZE (sd) = SCACHE_DEFAULT_CACHE_SIZE; + else + CPU_SCACHE_SIZE (cpu) = SCACHE_DEFAULT_CACHE_SIZE; + } + } + else + sim_io_eprintf (sd, "Simulator execution cache not enabled, `--scache-size' ignored\n"); + break; + + case OPTION_PROFILE_SCACHE : + if (WITH_SCACHE && WITH_PROFILE_SCACHE_P) + { + /* FIXME: handle cpu != NULL. */ + return sim_profile_set_option (sd, "-scache", PROFILE_SCACHE_IDX, + arg); + } + else + sim_io_eprintf (sd, "Simulator cache profiling not compiled in, `--profile-scache' ignored\n"); + break; + } + + return SIM_RC_OK; +} + +SIM_RC +scache_install (SIM_DESC sd) +{ + sim_add_option_table (sd, NULL, scache_options); + sim_module_add_init_fn (sd, scache_init); + sim_module_add_uninstall_fn (sd, scache_uninstall); + + /* This is the default, it may be overridden on the command line. */ + STATE_SCACHE_SIZE (sd) = WITH_SCACHE; + + return SIM_RC_OK; +} + +static SIM_RC +scache_init (SIM_DESC sd) +{ + int c; + + for (c = 0; c < MAX_NR_PROCESSORS; ++c) + { + SIM_CPU *cpu = STATE_CPU (sd, c); + int elm_size = IMP_PROPS_SCACHE_ELM_SIZE (MACH_IMP_PROPS (CPU_MACH (cpu))); + + /* elm_size is 0 if the cpu doesn't not have scache support */ + if (elm_size == 0) + { + CPU_SCACHE_SIZE (cpu) = 0; + CPU_SCACHE_CACHE (cpu) = NULL; + } + else + { + if (CPU_SCACHE_SIZE (cpu) == 0) + CPU_SCACHE_SIZE (cpu) = STATE_SCACHE_SIZE (sd); + CPU_SCACHE_CACHE (cpu) = + (SCACHE *) xmalloc (CPU_SCACHE_SIZE (cpu) * elm_size); +#if WITH_SCACHE_PBB + CPU_SCACHE_MAX_CHAIN_LENGTH (cpu) = MAX_CHAIN_LENGTH; + CPU_SCACHE_NUM_HASH_CHAIN_ENTRIES (cpu) = MAX_HASH_CHAIN_LENGTH; + CPU_SCACHE_NUM_HASH_CHAINS (cpu) = MAX (MIN_HASH_CHAINS, + CPU_SCACHE_SIZE (cpu) + / SCACHE_HASH_RATIO); + CPU_SCACHE_HASH_TABLE (cpu) = + (SCACHE_MAP *) xmalloc (CPU_SCACHE_NUM_HASH_CHAINS (cpu) + * CPU_SCACHE_NUM_HASH_CHAIN_ENTRIES (cpu) + * sizeof (SCACHE_MAP)); + CPU_SCACHE_PBB_BEGIN (cpu) = (SCACHE *) zalloc (elm_size); + CPU_SCACHE_CHAIN_LENGTHS (cpu) = + (unsigned long *) zalloc ((CPU_SCACHE_MAX_CHAIN_LENGTH (cpu) + 1) + * sizeof (long)); +#endif + } + } + + scache_flush (sd); + + return SIM_RC_OK; +} + +static void +scache_uninstall (SIM_DESC sd) +{ + int c; + + for (c = 0; c < MAX_NR_PROCESSORS; ++c) + { + SIM_CPU *cpu = STATE_CPU (sd, c); + + if (CPU_SCACHE_CACHE (cpu) != NULL) + free (CPU_SCACHE_CACHE (cpu)); +#if WITH_SCACHE_PBB + if (CPU_SCACHE_HASH_TABLE (cpu) != NULL) + free (CPU_SCACHE_HASH_TABLE (cpu)); + if (CPU_SCACHE_PBB_BEGIN (cpu) != NULL) + free (CPU_SCACHE_PBB_BEGIN (cpu)); + if (CPU_SCACHE_CHAIN_LENGTHS (cpu) != NULL) + free (CPU_SCACHE_CHAIN_LENGTHS (cpu)); +#endif + } +} + +void +scache_flush (SIM_DESC sd) +{ + int c; + + for (c = 0; c < MAX_NR_PROCESSORS; ++c) + { + SIM_CPU *cpu = STATE_CPU (sd, c); + scache_flush_cpu (cpu); + } +} + +void +scache_flush_cpu (SIM_CPU *cpu) +{ + int i,n; + + /* Don't bother if cache not in use. */ + if (CPU_SCACHE_SIZE (cpu) == 0) + return; + +#if WITH_SCACHE_PBB + /* It's important that this be reasonably fast as this can be done when + the simulation is running. */ + CPU_SCACHE_NEXT_FREE (cpu) = CPU_SCACHE_CACHE (cpu); + n = CPU_SCACHE_NUM_HASH_CHAINS (cpu) * CPU_SCACHE_NUM_HASH_CHAIN_ENTRIES (cpu); + /* ??? Might be faster to just set the first entry, then update the + "last entry" marker during allocation. */ + for (i = 0; i < n; ++i) + CPU_SCACHE_HASH_TABLE (cpu) [i] . pc = UNUSED_ADDR; +#else + { + int elm_size = IMP_PROPS_SCACHE_ELM_SIZE (MACH_IMP_PROPS (CPU_MACH (cpu))); + SCACHE *sc; + + /* Technically, this may not be necessary, but it helps debugging. */ + memset (CPU_SCACHE_CACHE (cpu), 0, + CPU_SCACHE_SIZE (cpu) * elm_size); + + for (i = 0, sc = CPU_SCACHE_CACHE (cpu); i < CPU_SCACHE_SIZE (cpu); + ++i, sc = (SCACHE *) ((char *) sc + elm_size)) + { + sc->argbuf.addr = UNUSED_ADDR; + } + } +#endif +} + +#if WITH_SCACHE_PBB + +/* Look up PC in the hash table of scache entry points. + Returns the entry or NULL if not found. */ + +SCACHE * +scache_lookup (SIM_CPU *cpu, IADDR pc) +{ + unsigned int slot = HASH_PC (pc) & (CPU_SCACHE_NUM_HASH_CHAINS (cpu) - 1); + int i, max_i = CPU_SCACHE_NUM_HASH_CHAIN_ENTRIES (cpu); + SCACHE_MAP *scm; + + /* We don't update hit/miss statistics as this is only used when recording + branch target addresses. */ + + scm = & CPU_SCACHE_HASH_TABLE (cpu) [slot]; + for (i = 0; i < max_i && scm->pc != UNUSED_ADDR; ++i, ++scm) + { + if (scm->pc == pc) + return scm->sc; + } + return 0; +} + +/* Look up PC and if not found create an entry for it. + If found the result is a pointer to the SCACHE entry. + If not found the result is NULL, and the address of a buffer of at least + N entries is stored in BUFP. + It's done this way so the caller can still distinguish found/not-found. + If the table is full, it is emptied to make room. + If the maximum length of a hash list is reached a random entry is thrown out + to make room. + ??? One might want to try to make this smarter, but let's see some + measurable benefit first. */ + +SCACHE * +scache_lookup_or_alloc (SIM_CPU *cpu, IADDR pc, int n, SCACHE **bufp) +{ + unsigned int slot = HASH_PC (pc) & (CPU_SCACHE_NUM_HASH_CHAINS (cpu) - 1); + int i, max_i = CPU_SCACHE_NUM_HASH_CHAIN_ENTRIES (cpu); + SCACHE_MAP *scm; + SCACHE *sc; + + scm = & CPU_SCACHE_HASH_TABLE (cpu) [slot]; + for (i = 0; i < max_i && scm->pc != UNUSED_ADDR; ++i, ++scm) + { + if (scm->pc == pc) + { + PROFILE_COUNT_SCACHE_HIT (cpu); + return scm->sc; + } + } + PROFILE_COUNT_SCACHE_MISS (cpu); + + /* The address we want isn't cached. Bummer. + If the hash chain we have for this address is full, throw out an entry + to make room. */ + + if (i == max_i) + { + /* Rather than do something sophisticated like LRU, we just throw out + a semi-random entry. Let someone else have the joy of saying how + wrong this is. NEXT_FREE is the entry to throw out and cycles + through all possibilities. */ + static int next_free = 0; + + scm = & CPU_SCACHE_HASH_TABLE (cpu) [slot]; + for (i = 0; i < next_free; ++i, ++scm) + continue; + ++next_free; + if (next_free == CPU_SCACHE_NUM_HASH_CHAIN_ENTRIES (cpu)) + next_free = 0; + } + + /* At this point SCM points to the hash table entry to use. + Now make sure there's room in the cache. */ + + { + int elm_size = IMP_PROPS_SCACHE_ELM_SIZE (MACH_IMP_PROPS (CPU_MACH (cpu))); + int elms_used = (((char *) CPU_SCACHE_NEXT_FREE (cpu) + - (char *) CPU_SCACHE_CACHE (cpu)) + / elm_size); + int elms_left = CPU_SCACHE_SIZE (cpu) - elms_used; + + if (elms_left < n) + { + PROFILE_COUNT_SCACHE_FULL_FLUSH (cpu); + scache_flush_cpu (cpu); + } + } + + sc = CPU_SCACHE_NEXT_FREE (cpu); + scm->pc = pc; + scm->sc = sc; + + *bufp = sc; + return NULL; +} + +#endif /* WITH_SCACHE_PBB */ + +/* Print cache access statics for CPU. */ + +void +scache_print_profile (SIM_CPU *cpu, int verbose) +{ + SIM_DESC sd = CPU_STATE (cpu); + unsigned long hits = CPU_SCACHE_HITS (cpu); + unsigned long misses = CPU_SCACHE_MISSES (cpu); + char buf[20]; + unsigned long max_val; + unsigned long *lengths; + int i; + + if (CPU_SCACHE_SIZE (cpu) == 0) + return; + + sim_io_printf (sd, "Simulator Cache Statistics\n\n"); + + /* One could use PROFILE_LABEL_WIDTH here. I chose not to. */ + sim_io_printf (sd, " Cache size: %s\n", + sim_add_commas (buf, sizeof (buf), CPU_SCACHE_SIZE (cpu))); + sim_io_printf (sd, " Hits: %s\n", + sim_add_commas (buf, sizeof (buf), hits)); + sim_io_printf (sd, " Misses: %s\n", + sim_add_commas (buf, sizeof (buf), misses)); + if (hits + misses != 0) + sim_io_printf (sd, " Hit rate: %.2f%%\n", + ((double) hits / ((double) hits + (double) misses)) * 100); + +#if WITH_SCACHE_PBB + sim_io_printf (sd, "\n"); + sim_io_printf (sd, " Hash table size: %s\n", + sim_add_commas (buf, sizeof (buf), CPU_SCACHE_NUM_HASH_CHAINS (cpu))); + sim_io_printf (sd, " Max hash list length: %s\n", + sim_add_commas (buf, sizeof (buf), CPU_SCACHE_NUM_HASH_CHAIN_ENTRIES (cpu))); + sim_io_printf (sd, " Max insn chain length: %s\n", + sim_add_commas (buf, sizeof (buf), CPU_SCACHE_MAX_CHAIN_LENGTH (cpu))); + sim_io_printf (sd, " Cache full flushes: %s\n", + sim_add_commas (buf, sizeof (buf), CPU_SCACHE_FULL_FLUSHES (cpu))); + sim_io_printf (sd, "\n"); + + if (verbose) + { + sim_io_printf (sd, " Insn chain lengths:\n\n"); + max_val = 0; + lengths = CPU_SCACHE_CHAIN_LENGTHS (cpu); + for (i = 1; i < CPU_SCACHE_MAX_CHAIN_LENGTH (cpu); ++i) + if (lengths[i] > max_val) + max_val = lengths[i]; + for (i = 1; i < CPU_SCACHE_MAX_CHAIN_LENGTH (cpu); ++i) + { + sim_io_printf (sd, " %2d: %*s: ", + i, + max_val < 10000 ? 5 : 10, + sim_add_commas (buf, sizeof (buf), lengths[i])); + sim_profile_print_bar (sd, PROFILE_HISTOGRAM_WIDTH, + lengths[i], max_val); + sim_io_printf (sd, "\n"); + } + sim_io_printf (sd, "\n"); + } +#endif /* WITH_SCACHE_PBB */ +} diff --git a/sim/common/cgen-scache.h b/sim/common/cgen-scache.h new file mode 100644 index 00000000000..7ca4e65c471 --- /dev/null +++ b/sim/common/cgen-scache.h @@ -0,0 +1,162 @@ +/* Simulator header for cgen scache support. + Copyright (C) 1998 Free Software Foundation, Inc. + Contributed by Cygnus Solutions. + +This file is part of GDB, the GNU debugger. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef CGEN_SCACHE_H +#define CGEN_SCACHE_H + +#ifndef WITH_SCACHE +#define WITH_SCACHE 0 +#endif + +/* When caching bb's, instructions are extracted into "chains". + SCACHE_MAP is a hash table into these chains. */ + +typedef struct { + IADDR pc; + SCACHE *sc; +} SCACHE_MAP; + +typedef struct cpu_scache { + /* Simulator cache size. Must be a power of 2. + This is the number of elements in the `cache' member. */ + unsigned int size; +#define CPU_SCACHE_SIZE(cpu) ((cpu) -> cgen_cpu.scache.size) + /* The cache. */ + SCACHE *cache; +#define CPU_SCACHE_CACHE(cpu) ((cpu) -> cgen_cpu.scache.cache) + +#if WITH_SCACHE_PBB + /* Number of hash chains. Must be a power of 2. */ + unsigned int num_hash_chains; +#define CPU_SCACHE_NUM_HASH_CHAINS(cpu) ((cpu) -> cgen_cpu.scache.num_hash_chains) + /* Number of entries in each hash chain. + The hash table is a statically allocated NxM array where + N = num_hash_chains + M = num_hash_chain_entries. */ + unsigned int num_hash_chain_entries; +#define CPU_SCACHE_NUM_HASH_CHAIN_ENTRIES(cpu) ((cpu) -> cgen_cpu.scache.num_hash_chain_entries) + /* Maximum number of instructions in a chain. + ??? This just let's us set a static size of chain_lengths table. + In a simulation that handles more than just the cpu, this might also be + used to keep too many instructions from being executed before checking + for events (or some such). */ + unsigned int max_chain_length; +#define CPU_SCACHE_MAX_CHAIN_LENGTH(cpu) ((cpu) -> cgen_cpu.scache.max_chain_length) + /* Special scache entry for (re)starting bb extraction. */ + SCACHE *pbb_begin; +#define CPU_SCACHE_PBB_BEGIN(cpu) ((cpu) -> cgen_cpu.scache.pbb_begin) + /* Hash table into cached chains. */ + SCACHE_MAP *hash_table; +#define CPU_SCACHE_HASH_TABLE(cpu) ((cpu) -> cgen_cpu.scache.hash_table) + /* Next free entry in cache. */ + SCACHE *next_free; +#define CPU_SCACHE_NEXT_FREE(cpu) ((cpu) -> cgen_cpu.scache.next_free) + + /* Address of cti-chain insn, only used by functional semantics, + not switch form. */ + SCACHE **pbb_br_npc_ptr; +#define CPU_PBB_BR_NPC_PTR(cpu) ((cpu) -> cgen_cpu.scache.pbb_br_npc_ptr) + /* Target's branch address. */ + IADDR pbb_br_npc; +#define CPU_PBB_BR_NPC(cpu) ((cpu) -> cgen_cpu.scache.pbb_br_npc) +#endif /* WITH_SCACHE_PBB */ + +#if WITH_PROFILE_SCACHE_P + /* Cache hits, misses. */ + unsigned long hits, misses; +#define CPU_SCACHE_HITS(cpu) ((cpu) -> cgen_cpu.scache.hits) +#define CPU_SCACHE_MISSES(cpu) ((cpu) -> cgen_cpu.scache.misses) + +#if WITH_SCACHE_PBB + /* Chain length counts. + Each element is a count of the number of chains created with that + length. */ + unsigned long *chain_lengths; +#define CPU_SCACHE_CHAIN_LENGTHS(cpu) ((cpu) -> cgen_cpu.scache.chain_lengths) + /* Number of times cache was flushed due to its being full. */ + unsigned long full_flushes; +#define CPU_SCACHE_FULL_FLUSHES(cpu) ((cpu) -> cgen_cpu.scache.full_flushes) +#endif +#endif +} CPU_SCACHE; + +/* Hash a PC value. + This is split into two parts to help with moving as much of the + computation out of the main loop. */ +#define CPU_SCACHE_HASH_MASK(cpu) (CPU_SCACHE_SIZE (cpu) - 1) +#define SCACHE_HASH_PC(pc, mask) \ +((CGEN_MIN_INSN_SIZE == 2 ? ((pc) >> 1) \ + : CGEN_MIN_INSN_SIZE == 4 ? ((pc) >> 2) \ + : (pc)) \ + & (mask)) + +/* Non-zero if cache is in use. */ +#define USING_SCACHE_P(sd) (STATE_SCACHE_SIZE (sd) > 0) + +/* Install the simulator cache into the simulator. */ +MODULE_INSTALL_FN scache_install; + +/* Lookup a PC value in the scache [compilation only]. */ +extern SCACHE * scache_lookup (SIM_CPU *, IADDR); +/* Return a pointer to at least N buffers. */ +extern SCACHE *scache_lookup_or_alloc (SIM_CPU *, IADDR, int, SCACHE **); +/* Flush all cpu's scaches. */ +extern void scache_flush (SIM_DESC); +/* Flush a cpu's scache. */ +extern void scache_flush_cpu (SIM_CPU *); + +/* Scache profiling support. */ + +/* Print summary scache usage information. */ +extern void scache_print_profile (SIM_CPU *cpu, int verbose); + +#if WITH_PROFILE_SCACHE_P + +#define PROFILE_COUNT_SCACHE_HIT(cpu) \ +do { \ + if (CPU_PROFILE_FLAGS (cpu) [PROFILE_SCACHE_IDX]) \ + ++ CPU_SCACHE_HITS (cpu); \ +} while (0) +#define PROFILE_COUNT_SCACHE_MISS(cpu) \ +do { \ + if (CPU_PROFILE_FLAGS (cpu) [PROFILE_SCACHE_IDX]) \ + ++ CPU_SCACHE_MISSES (cpu); \ +} while (0) +#define PROFILE_COUNT_SCACHE_CHAIN_LENGTH(cpu,length) \ +do { \ + if (CPU_PROFILE_FLAGS (cpu) [PROFILE_SCACHE_IDX]) \ + ++ CPU_SCACHE_CHAIN_LENGTHS (cpu) [length]; \ +} while (0) +#define PROFILE_COUNT_SCACHE_FULL_FLUSH(cpu) \ +do { \ + if (CPU_PROFILE_FLAGS (cpu) [PROFILE_SCACHE_IDX]) \ + ++ CPU_SCACHE_FULL_FLUSHES (cpu); \ +} while (0) + +#else + +#define PROFILE_COUNT_SCACHE_HIT(cpu) +#define PROFILE_COUNT_SCACHE_MISS(cpu) +#define PROFILE_COUNT_SCACHE_CHAIN_LENGTH(cpu,length) +#define PROFILE_COUNT_SCACHE_FULL_FLUSH(cpu) + +#endif + +#endif /* CGEN_SCACHE_H */ diff --git a/sim/common/cgen-sim.h b/sim/common/cgen-sim.h new file mode 100644 index 00000000000..748015f5724 --- /dev/null +++ b/sim/common/cgen-sim.h @@ -0,0 +1,34 @@ +/* Main header file for Cpu tools GENerated simulators. + Copyright (C) 1998 Free Software Foundation, Inc. + Contributed by Cygnus Support. + +This file is part of GDB, the GNU debugger. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* This file must be included after sim-base.h. */ + +#ifndef CGEN_SIM_H +#define CGEN_SIM_H + +#include "cgen-defs.h" +#include "cgen-scache.h" +#include "cgen-cpu.h" +#include "cgen-trace.h" + +/* This is a machine generated file. */ +#include "cpuall.h" + +#endif /* CGEN_SIM_H */ diff --git a/sim/common/cgen-trace.c b/sim/common/cgen-trace.c new file mode 100644 index 00000000000..9b7d1faf5d4 --- /dev/null +++ b/sim/common/cgen-trace.c @@ -0,0 +1,414 @@ +/* Tracing support for CGEN-based simulators. + Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc. + Contributed by Cygnus Support. + +This file is part of GDB, the GNU debugger. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include +#include "dis-asm.h" +#include "bfd.h" +#include "sim-main.h" + +#undef min +#define min(a,b) ((a) < (b) ? (a) : (b)) + +#ifndef SIZE_INSTRUCTION +#define SIZE_INSTRUCTION 16 +#endif + +#ifndef SIZE_LOCATION +#define SIZE_LOCATION 20 +#endif + +#ifndef SIZE_PC +#define SIZE_PC 6 +#endif + +#ifndef SIZE_LINE_NUMBER +#define SIZE_LINE_NUMBER 4 +#endif + +#ifndef SIZE_CYCLE_COUNT +#define SIZE_CYCLE_COUNT 2 +#endif + +#ifndef SIZE_TOTAL_CYCLE_COUNT +#define SIZE_TOTAL_CYCLE_COUNT 9 +#endif + +#ifndef SIZE_TRACE_BUF +#define SIZE_TRACE_BUF 256 +#endif + +static void +disassemble_insn (SIM_CPU *, const CGEN_INSN *, + const struct argbuf *, IADDR, char *); + +/* Text is queued in TRACE_BUF because we want to output the insn's cycle + count first but that isn't known until after the insn has executed. + This also handles the queueing of trace results, TRACE_RESULT may be + called multiple times for one insn. */ +static char trace_buf[SIZE_TRACE_BUF]; +/* If NULL, output to stdout directly. */ +static char *bufptr; + +/* Non-zero if this is the first insn in a set of parallel insns. */ +static int first_insn_p; + +/* For communication between trace_insn and trace_result. */ +static int printed_result_p; + +/* Insn and its extracted fields. + Set by trace_insn, used by trace_insn_fini. + ??? Move to SIM_CPU to support heterogeneous multi-cpu case. */ +static const struct cgen_insn *current_insn; +static const struct argbuf *current_abuf; + +void +trace_insn_init (SIM_CPU *cpu, int first_p) +{ + bufptr = trace_buf; + *bufptr = 0; + first_insn_p = first_p; + + /* Set to NULL so trace_insn_fini can know if trace_insn was called. */ + current_insn = NULL; + current_abuf = NULL; +} + +void +trace_insn_fini (SIM_CPU *cpu, const struct argbuf *abuf, int last_p) +{ + SIM_DESC sd = CPU_STATE (cpu); + + /* Was insn traced? It might not be if trace ranges are in effect. */ + if (current_insn == NULL) + return; + + /* The first thing printed is current and total cycle counts. */ + + if (PROFILE_MODEL_P (cpu) + && ARGBUF_PROFILE_P (current_abuf)) + { + unsigned long total = PROFILE_MODEL_TOTAL_CYCLES (CPU_PROFILE_DATA (cpu)); + unsigned long this_insn = PROFILE_MODEL_CUR_INSN_CYCLES (CPU_PROFILE_DATA (cpu)); + + if (last_p) + { + trace_printf (sd, cpu, "%-*ld %-*ld ", + SIZE_CYCLE_COUNT, this_insn, + SIZE_TOTAL_CYCLE_COUNT, total); + } + else + { + trace_printf (sd, cpu, "%-*ld %-*s ", + SIZE_CYCLE_COUNT, this_insn, + SIZE_TOTAL_CYCLE_COUNT, "---"); + } + } + + /* Print the disassembled insn. */ + + trace_printf (sd, cpu, "%s", TRACE_PREFIX (CPU_TRACE_DATA (cpu))); + +#if 0 + /* Print insn results. */ + { + const CGEN_OPINST *opinst = CGEN_INSN_OPERANDS (current_insn); + + if (opinst) + { + int i; + int indices[MAX_OPERAND_INSTANCES]; + + /* Fetch the operands used by the insn. */ + /* FIXME: Add fn ptr to CGEN_CPU_DESC. */ + CGEN_SYM (get_insn_operands) (CPU_CPU_DESC (cpu), current_insn, + 0, CGEN_FIELDS_BITSIZE (&insn_fields), + indices); + + for (i = 0; + CGEN_OPINST_TYPE (opinst) != CGEN_OPINST_END; + ++i, ++opinst) + { + if (CGEN_OPINST_TYPE (opinst) == CGEN_OPINST_OUTPUT) + trace_result (cpu, current_insn, opinst, indices[i]); + } + } + } +#endif + + /* Print anything else requested. */ + + if (*trace_buf) + trace_printf (sd, cpu, " %s\n", trace_buf); + else + trace_printf (sd, cpu, "\n"); +} + +void +trace_insn (SIM_CPU *cpu, const struct cgen_insn *opcode, + const struct argbuf *abuf, IADDR pc) +{ + char disasm_buf[50]; + + printed_result_p = 0; + current_insn = opcode; + current_abuf = abuf; + + if (CGEN_INSN_VIRTUAL_P (opcode)) + { + trace_prefix (CPU_STATE (cpu), cpu, NULL_CIA, pc, 0, + NULL, 0, CGEN_INSN_NAME (opcode)); + return; + } + + CPU_DISASSEMBLER (cpu) (cpu, opcode, abuf, pc, disasm_buf); + trace_prefix (CPU_STATE (cpu), cpu, NULL_CIA, pc, TRACE_LINENUM_P (cpu), + NULL, 0, + "%s%-*s", + first_insn_p ? " " : "|", + SIZE_INSTRUCTION, disasm_buf); +} + +void +trace_extract (SIM_CPU *cpu, IADDR pc, char *name, ...) +{ + va_list args; + int printed_one_p = 0; + char *fmt; + + va_start (args, name); + + trace_printf (CPU_STATE (cpu), cpu, "Extract: 0x%.*lx: %s ", + SIZE_PC, pc, name); + + do { + int type,ival; + + fmt = va_arg (args, char *); + + if (fmt) + { + if (printed_one_p) + trace_printf (CPU_STATE (cpu), cpu, ", "); + printed_one_p = 1; + type = va_arg (args, int); + switch (type) + { + case 'x' : + ival = va_arg (args, int); + trace_printf (CPU_STATE (cpu), cpu, fmt, ival); + break; + default : + abort (); + } + } + } while (fmt); + + va_end (args); + trace_printf (CPU_STATE (cpu), cpu, "\n"); +} + +void +trace_result (SIM_CPU *cpu, char *name, int type, ...) +{ + va_list args; + + va_start (args, type); + if (printed_result_p) + cgen_trace_printf (cpu, ", "); + + switch (type) + { + case 'x' : + default : + cgen_trace_printf (cpu, "%s <- 0x%x", name, va_arg (args, int)); + break; + case 'D' : + { + DI di; + /* this is separated from previous line for sunos cc */ + di = va_arg (args, DI); + cgen_trace_printf (cpu, "%s <- 0x%x%08x", name, + GETHIDI(di), GETLODI (di)); + break; + } + } + + printed_result_p = 1; + va_end (args); +} + +/* Print trace output to BUFPTR if active, otherwise print normally. + This is only for tracing semantic code. */ + +void +cgen_trace_printf (SIM_CPU *cpu, char *fmt, ...) +{ + va_list args; + + va_start (args, fmt); + + if (bufptr == NULL) + { + if (TRACE_FILE (CPU_TRACE_DATA (cpu)) == NULL) + (* STATE_CALLBACK (CPU_STATE (cpu))->evprintf_filtered) + (STATE_CALLBACK (CPU_STATE (cpu)), fmt, args); + else + vfprintf (TRACE_FILE (CPU_TRACE_DATA (cpu)), fmt, args); + } + else + { + vsprintf (bufptr, fmt, args); + bufptr += strlen (bufptr); + /* ??? Need version of SIM_ASSERT that is always enabled. */ + if (bufptr - trace_buf > SIZE_TRACE_BUF) + abort (); + } + + va_end (args); +} + +/* Disassembly support. */ + +/* sprintf to a "stream" */ + +int +sim_disasm_sprintf VPARAMS ((SFILE *f, const char *format, ...)) +{ +#ifndef __STDC__ + SFILE *f; + const char *format; +#endif + int n; + va_list args; + + VA_START (args, format); +#ifndef __STDC__ + f = va_arg (args, SFILE *); + format = va_arg (args, char *); +#endif + vsprintf (f->current, format, args); + f->current += n = strlen (f->current); + va_end (args); + return n; +} + +/* Memory read support for an opcodes disassembler. */ + +int +sim_disasm_read_memory (bfd_vma memaddr, bfd_byte *myaddr, int length, + struct disassemble_info *info) +{ + SIM_CPU *cpu = (SIM_CPU *) info->application_data; + SIM_DESC sd = CPU_STATE (cpu); + int length_read; + + length_read = sim_core_read_buffer (sd, cpu, read_map, myaddr, memaddr, + length); + if (length_read != length) + return EIO; + return 0; +} + +/* Memory error support for an opcodes disassembler. */ + +void +sim_disasm_perror_memory (int status, bfd_vma memaddr, + struct disassemble_info *info) +{ + if (status != EIO) + /* Can't happen. */ + info->fprintf_func (info->stream, "Unknown error %d.", status); + else + /* Actually, address between memaddr and memaddr + len was + out of bounds. */ + info->fprintf_func (info->stream, + "Address 0x%x is out of bounds.", + (int) memaddr); +} + +/* Disassemble using the CGEN opcode table. + ??? While executing an instruction, the insn has been decoded and all its + fields have been extracted. It is certainly possible to do the disassembly + with that data. This seems simpler, but maybe in the future the already + extracted fields will be used. */ + +void +sim_cgen_disassemble_insn (SIM_CPU *cpu, const CGEN_INSN *insn, + const ARGBUF *abuf, IADDR pc, char *buf) +{ + unsigned int length; + unsigned long insn_value; + struct disassemble_info disasm_info; + SFILE sfile; + union { + unsigned8 bytes[CGEN_MAX_INSN_SIZE]; + unsigned16 shorts[8]; + unsigned32 words[4]; + } insn_buf; + SIM_DESC sd = CPU_STATE (cpu); + CGEN_CPU_DESC cd = CPU_CPU_DESC (cpu); + CGEN_EXTRACT_INFO ex_info; + CGEN_FIELDS *fields = alloca (CGEN_CPU_SIZEOF_FIELDS (cd)); + int insn_bit_length = CGEN_INSN_BITSIZE (insn); + int insn_length = insn_bit_length / 8; + + sfile.buffer = sfile.current = buf; + INIT_DISASSEMBLE_INFO (disasm_info, (FILE *) &sfile, + (fprintf_ftype) sim_disasm_sprintf); + disasm_info.endian = + (bfd_big_endian (STATE_PROG_BFD (sd)) ? BFD_ENDIAN_BIG + : bfd_little_endian (STATE_PROG_BFD (sd)) ? BFD_ENDIAN_LITTLE + : BFD_ENDIAN_UNKNOWN); + + length = sim_core_read_buffer (sd, cpu, read_map, &insn_buf, pc, + insn_length); + + switch (min (CGEN_BASE_INSN_SIZE, insn_length)) + { + case 0 : return; /* fake insn, typically "compile" (aka "invalid") */ + case 1 : insn_value = insn_buf.bytes[0]; break; + case 2 : insn_value = T2H_2 (insn_buf.shorts[0]); break; + case 4 : insn_value = T2H_4 (insn_buf.words[0]); break; + default: abort (); + } + + disasm_info.buffer_vma = pc; + disasm_info.buffer = insn_buf.bytes; + disasm_info.buffer_length = length; + + ex_info.dis_info = (PTR) &disasm_info; + ex_info.valid = (1 << length) - 1; + ex_info.insn_bytes = insn_buf.bytes; + + length = (*CGEN_EXTRACT_FN (cd, insn)) (cd, insn, &ex_info, insn_value, fields, pc); + /* Result of extract fn is in bits. */ + /* ??? This assumes that each instruction has a fixed length (and thus + for insns with multiple versions of variable lengths they would each + have their own table entry). */ + if (length == insn_bit_length) + { + (*CGEN_PRINT_FN (cd, insn)) (cd, &disasm_info, insn, fields, pc, length); + } + else + { + /* This shouldn't happen, but aborting is too drastic. */ + strcpy (buf, "***unknown***"); + } +} diff --git a/sim/common/cgen-trace.h b/sim/common/cgen-trace.h new file mode 100644 index 00000000000..5e796fbf061 --- /dev/null +++ b/sim/common/cgen-trace.h @@ -0,0 +1,91 @@ +/* Simulator tracing support for Cpu tools GENerated simulators. + Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc. + Contributed by Cygnus Support. + +This file is part of GDB, the GNU debugger. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef CGEN_TRACE_H +#define CGEN_TRACE_H + +void trace_insn_init (SIM_CPU *, int); +void trace_insn_fini (SIM_CPU *, const struct argbuf *, int); +void trace_insn (SIM_CPU *, const struct cgen_insn *, + const struct argbuf *, IADDR); +void trace_extract (SIM_CPU *, IADDR, char *, ...); +void trace_result (SIM_CPU *, char *, int, ...); +void cgen_trace_printf (SIM_CPU *, char *fmt, ...); + +/* Trace instruction results. */ +#define TRACE_RESULT_P(cpu, abuf) (TRACE_INSN_P (cpu) && ARGBUF_TRACE_P (abuf)) + +#define TRACE_INSN_INIT(cpu, abuf, first_p) \ +do { \ + if (TRACE_INSN_P (cpu)) \ + trace_insn_init ((cpu), (first_p)); \ +} while (0) +#define TRACE_INSN_FINI(cpu, abuf, last_p) \ +do { \ + if (TRACE_INSN_P (cpu)) \ + trace_insn_fini ((cpu), (abuf), (last_p)); \ +} while (0) +#define TRACE_PRINTF(cpu, what, args) \ +do { \ + if (TRACE_P ((cpu), (what))) \ + cgen_trace_printf args ; \ +} while (0) +#define TRACE_INSN(cpu, insn, abuf, pc) \ +do { \ + if (TRACE_INSN_P (cpu) && ARGBUF_TRACE_P (abuf)) \ + trace_insn ((cpu), (insn), (abuf), (pc)) ; \ +} while (0) +#define TRACE_EXTRACT(cpu, abuf, args) \ +do { \ + if (TRACE_EXTRACT_P (cpu)) \ + trace_extract args ; \ +} while (0) +#define TRACE_RESULT(cpu, abuf, name, type, val) \ +do { \ + if (TRACE_RESULT_P ((cpu), (abuf))) \ + trace_result ((cpu), (name), (type), (val)) ; \ +} while (0) + +/* Disassembly support. */ + +/* Function to use for cgen-based disassemblers. */ +extern CGEN_DISASSEMBLER sim_cgen_disassemble_insn; + +/* Pseudo FILE object for strings. */ +typedef struct { + char *buffer; + char *current; +} SFILE; + +/* String printer for the disassembler. */ +extern int sim_disasm_sprintf (SFILE *, const char *, ...); + +/* For opcodes based disassemblers. */ +#ifdef BFD_VERSION +struct disassemble_info; +extern int +sim_disasm_read_memory (bfd_vma memaddr_, bfd_byte *myaddr_, int length_, + struct disassemble_info *info_); +extern void +sim_disasm_perror_memory (int status_, bfd_vma memaddr_, + struct disassemble_info *info_); +#endif + +#endif /* CGEN_TRACE_H */ diff --git a/sim/common/cgen-types.h b/sim/common/cgen-types.h new file mode 100644 index 00000000000..e57e601ef55 --- /dev/null +++ b/sim/common/cgen-types.h @@ -0,0 +1,116 @@ +/* Types for Cpu tools GENerated simulators. + Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc. + Contributed by Cygnus Support. + +This file is part of GDB, the GNU debugger. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* This file is not included with cgen-sim.h as it defines types + needed by sim-base.h. */ + +#ifndef CGEN_TYPES_H +#define CGEN_TYPES_H + +/* Miscellaneous cgen configury defined here as this file gets + included soon enough. */ + +/* Indicate we support --profile-model. */ +#undef SIM_HAVE_MODEL +#define SIM_HAVE_MODEL + +/* Indicate we support --{profile,trace}-{range,function}. */ +#undef SIM_HAVE_ADDR_RANGE +#define SIM_HAVE_ADDR_RANGE + +#ifdef __GNUC__ +#define HAVE_LONGLONG +#undef DI_FN_SUPPORT +#else +#undef HAVE_LONGLONG +#define DI_FN_SUPPORT +#endif + +/* Mode support. */ + +/* Common mode types. */ +/* ??? Target specific modes. */ +typedef enum mode_type { + MODE_VM, MODE_BI, + MODE_QI, MODE_HI, MODE_SI, MODE_DI, + MODE_UQI, MODE_UHI, MODE_USI, MODE_UDI, + MODE_SF, MODE_DF, MODE_XF, MODE_TF, + MODE_TARGET_MAX /* = MODE_TF? */, + /* These are host modes. */ + MODE_INT, MODE_UINT, MODE_PTR, /*??? MODE_ADDR, MODE_IADDR,*/ + MODE_MAX +} MODE_TYPE; + +#define MAX_TARGET_MODES ((int) MODE_TARGET_MAX) +#define MAX_MODES ((int) MODE_MAX) + +extern const char *mode_names[]; +#define MODE_NAME(m) (mode_names[m]) + +typedef unsigned char BI; +typedef signed8 QI; +typedef signed16 HI; +typedef signed32 SI; +typedef unsigned8 UQI; +typedef unsigned16 UHI; +typedef unsigned32 USI; + +#ifdef HAVE_LONGLONG +typedef signed64 DI; +typedef unsigned64 UDI; +#define GETLODI(di) ((SI) (di)) +#define GETHIDI(di) ((SI) ((UDI) (di) >> 32)) +#define SETLODI(di, val) ((di) = (((di) & 0xffffffff00000000LL) | (val))) +#define SETHIDI(di, val) ((di) = (((di) & 0xffffffffLL) | (((DI) (val)) << 32))) +#define SETDI(di, hi, lo) ((di) = MAKEDI (hi, lo)) +#define MAKEDI(hi, lo) ((((DI) (SI) (hi)) << 32) | ((UDI) (USI) (lo))) +#else +/* DI mode support if "long long" doesn't exist. + At one point CGEN supported K&R C compilers, and ANSI C compilers without + "long long". One can argue the various merits of keeping this in or + throwing it out. I went to the trouble of adding it so for the time being + I'm leaving it in. */ +typedef struct { SI hi,lo; } DI; +typedef DI UDI; +#define GETLODI(di) ((di).lo) +#define GETHIDI(di) ((di).hi) +#define SETLODI(di, val) ((di).lo = (val)) +#define SETHIDI(di, val) ((di).hi = (val)) +#define SETDI(di, hi, lo) ((di) = MAKEDI (hi, lo)) +extern DI make_struct_di (SI, SI); +#define MAKEDI(hi, lo) (make_struct_di ((hi), (lo))) +#endif + +/* FIXME: Need to provide libraries if these aren't appropriate for target, + or user's needs. */ +typedef float SF; +typedef double DF; +typedef double XF; /* FIXME: configure, provide library */ +typedef double TF; /* FIXME: configure, provide library */ + +/* These are used to record extracted raw data from an instruction, among other + things. It must be a host data type, and not a target one. */ +typedef int INT; +typedef unsigned int UINT; + +typedef unsigned_address ADDR; /* FIXME: wip*/ +typedef unsigned_address IADDR; /* FIXME: wip*/ + +#endif /* CGEN_TYPES_H */ diff --git a/sim/common/cgen-utils.c b/sim/common/cgen-utils.c new file mode 100644 index 00000000000..2faff5c2948 --- /dev/null +++ b/sim/common/cgen-utils.c @@ -0,0 +1,328 @@ +/* Support code for various pieces of CGEN simulators. + Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc. + Contributed by Cygnus Support. + +This file is part of GDB, the GNU debugger. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "bfd.h" +#include "sim-main.h" +#include "dis-asm.h" + +#define MEMOPS_DEFINE_INLINE +#include "cgen-mem.h" + +#define SEMOPS_DEFINE_INLINE +#include "cgen-ops.h" + +#undef min +#define min(a,b) ((a) < (b) ? (a) : (b)) + +const char *mode_names[] = { + "VM", + "BI", + "QI", + "HI", + "SI", + "DI", + "UQI", + "UHI", + "USI", + "UDI", + "SF", + "DF", + "XF", + "TF", + 0, /* MODE_TARGET_MAX */ + "INT", + "UINT", + "PTR" +}; + +/* Opcode table for virtual insns used by the simulator. */ + +#define V CGEN_ATTR_MASK (CGEN_INSN_VIRTUAL) + +static const CGEN_IBASE virtual_insn_entries[] = +{ + { + VIRTUAL_INSN_X_INVALID, "--invalid--", NULL, 0, + { CGEN_INSN_NBOOL_ATTRS, V, { 0 } } + }, + { + VIRTUAL_INSN_X_BEFORE, "--before--", NULL, 0, + { CGEN_INSN_NBOOL_ATTRS, V, { 0 } } + }, + { + VIRTUAL_INSN_X_AFTER, "--after--", NULL, 0, + { CGEN_INSN_NBOOL_ATTRS, V, { 0 } } + }, + { + VIRTUAL_INSN_X_BEGIN, "--begin--", NULL, 0, + { CGEN_INSN_NBOOL_ATTRS, V, { 0 } } + }, + { + VIRTUAL_INSN_X_CHAIN, "--chain--", NULL, 0, + { CGEN_INSN_NBOOL_ATTRS, V, { 0 } } + }, + { + VIRTUAL_INSN_X_CTI_CHAIN, "--cti-chain--", NULL, 0, + { CGEN_INSN_NBOOL_ATTRS, V, { 0 } } + } +}; + +#undef V + +const CGEN_INSN cgen_virtual_insn_table[] = +{ + { & virtual_insn_entries[0] }, + { & virtual_insn_entries[1] }, + { & virtual_insn_entries[2] }, + { & virtual_insn_entries[3] }, + { & virtual_insn_entries[4] }, + { & virtual_insn_entries[5] } +}; + +/* Initialize cgen things. + This is called after sim_post_argv_init. */ + +void +cgen_init (SIM_DESC sd) +{ + int i, c; + + /* If no profiling or tracing has been enabled, run in fast mode. */ + { + int run_fast_p = 1; + + for (c = 0; c < MAX_NR_PROCESSORS; ++c) + { + SIM_CPU *cpu = STATE_CPU (sd, c); + + for (i = 0; i < MAX_PROFILE_VALUES; ++i) + if (CPU_PROFILE_FLAGS (cpu) [i]) + { + run_fast_p = 0; + break; + } + for (i = 0; i < MAX_TRACE_VALUES; ++i) + if (CPU_TRACE_FLAGS (cpu) [i]) + { + run_fast_p = 0; + break; + } + if (! run_fast_p) + break; + } + STATE_RUN_FAST_P (sd) = run_fast_p; + } +} + +/* Return the name of insn number I. */ + +const char * +cgen_insn_name (SIM_CPU *cpu, int i) +{ + return CGEN_INSN_NAME ((* CPU_GET_IDATA (cpu)) ((cpu), (i))); +} + +/* Return the maximum number of extra bytes required for a SIM_CPU struct. */ + +int +cgen_cpu_max_extra_bytes (void) +{ + int i; + int extra = 0; + + for (i = 0; sim_machs[i] != 0; ++i) + { + int size = IMP_PROPS_SIM_CPU_SIZE (MACH_IMP_PROPS (sim_machs[i])); + if (size > extra) + extra = size; + } + return extra; +} + +#ifdef DI_FN_SUPPORT + +DI +make_struct_di (hi, lo) + SI hi, lo; +{ + DI result; + + result.hi = hi; + result.lo = lo; + return result; +} + +DI +ANDDI (a, b) + DI a, b; +{ + SI ahi = GETHIDI (a); + SI alo = GETLODI (a); + SI bhi = GETHIDI (b); + SI blo = GETLODI (b); + return MAKEDI (ahi & bhi, alo & blo); +} + +DI +ORDI (a, b) + DI a, b; +{ + SI ahi = GETHIDI (a); + SI alo = GETLODI (a); + SI bhi = GETHIDI (b); + SI blo = GETLODI (b); + return MAKEDI (ahi | bhi, alo | blo); +} + +DI +ADDDI (a, b) + DI a, b; +{ + USI ahi = GETHIDI (a); + USI alo = GETLODI (a); + USI bhi = GETHIDI (b); + USI blo = GETLODI (b); + USI x = alo + blo; + return MAKEDI (ahi + bhi + (x < alo), x); +} + +DI +MULDI (a, b) + DI a, b; +{ + USI ahi = GETHIDI (a); + USI alo = GETLODI (a); + USI bhi = GETHIDI (b); + USI blo = GETLODI (b); + USI rhi,rlo; + USI x0, x1, x2, x3; + + x0 = alo * blo; + x1 = alo * bhi; + x2 = ahi * blo; + x3 = ahi * bhi; + +#define SI_TYPE_SIZE 32 +#define BITS4 (SI_TYPE_SIZE / 4) +#define ll_B (1L << (SI_TYPE_SIZE / 2)) +#define ll_lowpart(t) ((USI) (t) % ll_B) +#define ll_highpart(t) ((USI) (t) / ll_B) + x1 += ll_highpart (x0); /* this can't give carry */ + x1 += x2; /* but this indeed can */ + if (x1 < x2) /* did we get it? */ + x3 += ll_B; /* yes, add it in the proper pos. */ + + rhi = x3 + ll_highpart (x1); + rlo = ll_lowpart (x1) * ll_B + ll_lowpart (x0); + return MAKEDI (rhi + (alo * bhi) + (ahi * blo), rlo); +} + +DI +SHLDI (val, shift) + DI val; + SI shift; +{ + USI hi = GETHIDI (val); + USI lo = GETLODI (val); + /* FIXME: Need to worry about shift < 0 || shift >= 32. */ + return MAKEDI ((hi << shift) | (lo >> (32 - shift)), lo << shift); +} + +DI +SLADI (val, shift) + DI val; + SI shift; +{ + SI hi = GETHIDI (val); + USI lo = GETLODI (val); + /* FIXME: Need to worry about shift < 0 || shift >= 32. */ + return MAKEDI ((hi << shift) | (lo >> (32 - shift)), lo << shift); +} + +DI +SRADI (val, shift) + DI val; + SI shift; +{ + SI hi = GETHIDI (val); + USI lo = GETLODI (val); + /* We use SRASI because the result is implementation defined if hi < 0. */ + /* FIXME: Need to worry about shift < 0 || shift >= 32. */ + return MAKEDI (SRASI (hi, shift), (hi << (32 - shift)) | (lo >> shift)); +} + +int +GEDI (a, b) + DI a, b; +{ + SI ahi = GETHIDI (a); + USI alo = GETLODI (a); + SI bhi = GETHIDI (b); + USI blo = GETLODI (b); + if (ahi > bhi) + return 1; + if (ahi == bhi) + return alo >= blo; + return 0; +} + +int +LEDI (a, b) + DI a, b; +{ + SI ahi = GETHIDI (a); + USI alo = GETLODI (a); + SI bhi = GETHIDI (b); + USI blo = GETLODI (b); + if (ahi < bhi) + return 1; + if (ahi == bhi) + return alo <= blo; + return 0; +} + +DI +CONVHIDI (val) + HI val; +{ + if (val < 0) + return MAKEDI (-1, val); + else + return MAKEDI (0, val); +} + +DI +CONVSIDI (val) + SI val; +{ + if (val < 0) + return MAKEDI (-1, val); + else + return MAKEDI (0, val); +} + +SI +CONVDISI (val) + DI val; +{ + return GETLODI (val); +} + +#endif /* DI_FN_SUPPORT */ diff --git a/sim/common/config.in b/sim/common/config.in new file mode 100644 index 00000000000..4df95600dd8 --- /dev/null +++ b/sim/common/config.in @@ -0,0 +1,167 @@ +/* config.in. Generated automatically from configure.in by autoheader. */ + +/* Define if using alloca.c. */ +#undef C_ALLOCA + +/* Define to empty if the keyword does not work. */ +#undef const + +/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems. + This function is required for alloca.c support on those systems. */ +#undef CRAY_STACKSEG_END + +/* Define if you have alloca, as a function or macro. */ +#undef HAVE_ALLOCA + +/* Define if you have and it should be used (not on Ultrix). */ +#undef HAVE_ALLOCA_H + +/* Define if you have a working `mmap' system call. */ +#undef HAVE_MMAP + +/* Define as __inline if that's what the C compiler calls it. */ +#undef inline + +/* Define to `long' if doesn't define. */ +#undef off_t + +/* Define if you need to in order for stat and other things to work. */ +#undef _POSIX_SOURCE + +/* Define as the return type of signal handlers (int or void). */ +#undef RETSIGTYPE + +/* Define to `unsigned' if doesn't define. */ +#undef size_t + +/* If using the C implementation of alloca, define if you know the + direction of stack growth for your system; otherwise it will be + automatically deduced at run-time. + STACK_DIRECTION > 0 => grows toward higher addresses + STACK_DIRECTION < 0 => grows toward lower addresses + STACK_DIRECTION = 0 => direction of growth unknown + */ +#undef STACK_DIRECTION + +/* Define if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Define to 1 if NLS is requested. */ +#undef ENABLE_NLS + +/* Define as 1 if you have gettext and don't want to use GNU gettext. */ +#undef HAVE_GETTEXT + +/* Define as 1 if you have the stpcpy function. */ +#undef HAVE_STPCPY + +/* Define if your locale.h file contains LC_MESSAGES. */ +#undef HAVE_LC_MESSAGES + +/* Define if you have the __argz_count function. */ +#undef HAVE___ARGZ_COUNT + +/* Define if you have the __argz_next function. */ +#undef HAVE___ARGZ_NEXT + +/* Define if you have the __argz_stringify function. */ +#undef HAVE___ARGZ_STRINGIFY + +/* Define if you have the __setfpucw function. */ +#undef HAVE___SETFPUCW + +/* Define if you have the dcgettext function. */ +#undef HAVE_DCGETTEXT + +/* Define if you have the getcwd function. */ +#undef HAVE_GETCWD + +/* Define if you have the getpagesize function. */ +#undef HAVE_GETPAGESIZE + +/* Define if you have the getrusage function. */ +#undef HAVE_GETRUSAGE + +/* Define if you have the munmap function. */ +#undef HAVE_MUNMAP + +/* Define if you have the putenv function. */ +#undef HAVE_PUTENV + +/* Define if you have the setenv function. */ +#undef HAVE_SETENV + +/* Define if you have the setlocale function. */ +#undef HAVE_SETLOCALE + +/* Define if you have the sigaction function. */ +#undef HAVE_SIGACTION + +/* Define if you have the stpcpy function. */ +#undef HAVE_STPCPY + +/* Define if you have the strcasecmp function. */ +#undef HAVE_STRCASECMP + +/* Define if you have the strchr function. */ +#undef HAVE_STRCHR + +/* Define if you have the time function. */ +#undef HAVE_TIME + +/* Define if you have the header file. */ +#undef HAVE_ARGZ_H + +/* Define if you have the header file. */ +#undef HAVE_DLFCN_H + +/* Define if you have the header file. */ +#undef HAVE_ERRNO_H + +/* Define if you have the header file. */ +#undef HAVE_FCNTL_H + +/* Define if you have the header file. */ +#undef HAVE_FPU_CONTROL_H + +/* Define if you have the header file. */ +#undef HAVE_LIMITS_H + +/* Define if you have the header file. */ +#undef HAVE_LOCALE_H + +/* Define if you have the header file. */ +#undef HAVE_MALLOC_H + +/* Define if you have the header file. */ +#undef HAVE_NL_TYPES_H + +/* Define if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define if you have the header file. */ +#undef HAVE_STRING_H + +/* Define if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_PARAM_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_RESOURCE_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_TIME_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_TIMES_H + +/* Define if you have the header file. */ +#undef HAVE_TIME_H + +/* Define if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define if you have the header file. */ +#undef HAVE_VALUES_H diff --git a/sim/common/configure b/sim/common/configure new file mode 100755 index 00000000000..4dc7670494a --- /dev/null +++ b/sim/common/configure @@ -0,0 +1,3902 @@ +#! /bin/sh + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +sim_inline="-DDEFAULT_INLINE=0" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +# This file is derived from `gettext.m4'. The difference is that the +# included macros assume Cygnus-style source and build trees. + +# Macro to add for using GNU gettext. +# Ulrich Drepper , 1995. +# +# This file file be copied and used freely without restrictions. It can +# be used in projects which are not available under the GNU Public License +# but which still want to provide support for the GNU gettext functionality. +# Please note that the actual code is *not* freely available. + +# serial 3 + + + + + +# Search path for a program which passes the given test. +# Ulrich Drepper , 1996. +# +# This file file be copied and used freely without restrictions. It can +# be used in projects which are not available under the GNU Public License +# but which still want to provide support for the GNU gettext functionality. +# Please note that the actual code is *not* freely available. + +# serial 1 + + + +# Check whether LC_MESSAGES is available in . +# Ulrich Drepper , 1995. +# +# This file file be copied and used freely without restrictions. It can +# be used in projects which are not available under the GNU Public License +# but which still want to provide support for the GNU gettext functionality. +# Please note that the actual code is *not* freely available. + +# serial 1 + + + +# Check to see if we're running under Cygwin32, without using +# AC_CANONICAL_*. If so, set output variable CYGWIN32 to "yes". +# Otherwise set it to "no". + + + +# Check to see if we're running under Win32, without using +# AC_CANONICAL_*. If so, set output variable EXEEXT to ".exe". +# Otherwise set it to "". + + + +# Guess values for system-dependent variables and create Makefiles. +# Generated automatically using autoconf version 2.12.2 +# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc. +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. + +# Defaults: +ac_help= +ac_default_prefix=/usr/local +# Any additions from configure.in: +ac_help="$ac_help + --disable-nls do not use Native Language Support" +ac_help="$ac_help + --with-included-gettext use the GNU gettext library included here" +ac_help="$ac_help + --enable-maintainer-mode Enable developer functionality." +ac_help="$ac_help + --enable-sim-bswap Use Host specific BSWAP instruction." +ac_help="$ac_help + --enable-sim-cflags=opts Extra CFLAGS for use in building simulator" +ac_help="$ac_help + --enable-sim-debug=opts Enable debugging flags" +ac_help="$ac_help + --enable-sim-stdio Specify whether to use stdio for console input/output." +ac_help="$ac_help + --enable-sim-trace=opts Enable tracing flags" +ac_help="$ac_help + --enable-sim-profile=opts Enable profiling flags" + +# Initialize some variables set by options. +# The variables have the same names as the options, with +# dashes changed to underlines. +build=NONE +cache_file=./config.cache +exec_prefix=NONE +host=NONE +no_create= +nonopt=NONE +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +target=NONE +verbose= +x_includes=NONE +x_libraries=NONE +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +# Initialize some other variables. +subdirs= +MFLAGS= MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} +# Maximum number of lines to put in a shell here document. +ac_max_here_lines=12 + +ac_prev= +for ac_option +do + + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval "$ac_prev=\$ac_option" + ac_prev= + continue + fi + + case "$ac_option" in + -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) ac_optarg= ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case "$ac_option" in + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir="$ac_optarg" ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build="$ac_optarg" ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file="$ac_optarg" ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir="$ac_optarg" ;; + + -disable-* | --disable-*) + ac_feature=`echo $ac_option|sed -e 's/-*disable-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + eval "enable_${ac_feature}=no" ;; + + -enable-* | --enable-*) + ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "enable_${ac_feature}='$ac_optarg'" ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix="$ac_optarg" ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he) + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat << EOF +Usage: configure [options] [host] +Options: [defaults in brackets after descriptions] +Configuration: + --cache-file=FILE cache test results in FILE + --help print this message + --no-create do not create output files + --quiet, --silent do not print \`checking...' messages + --version print the version of autoconf that created configure +Directory and file names: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [same as prefix] + --bindir=DIR user executables in DIR [EPREFIX/bin] + --sbindir=DIR system admin executables in DIR [EPREFIX/sbin] + --libexecdir=DIR program executables in DIR [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data in DIR + [PREFIX/share] + --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data in DIR + [PREFIX/com] + --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var] + --libdir=DIR object code libraries in DIR [EPREFIX/lib] + --includedir=DIR C header files in DIR [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include] + --infodir=DIR info documentation in DIR [PREFIX/info] + --mandir=DIR man documentation in DIR [PREFIX/man] + --srcdir=DIR find the sources in DIR [configure dir or ..] + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM + run sed PROGRAM on installed program names +EOF + cat << EOF +Host type: + --build=BUILD configure for building on BUILD [BUILD=HOST] + --host=HOST configure for HOST [guessed] + --target=TARGET configure for TARGET [TARGET=HOST] +Features and packages: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --x-includes=DIR X include files are in DIR + --x-libraries=DIR X library files are in DIR +EOF + if test -n "$ac_help"; then + echo "--enable and --with options recognized:$ac_help" + fi + exit 0 ;; + + -host | --host | --hos | --ho) + ac_prev=host ;; + -host=* | --host=* | --hos=* | --ho=*) + host="$ac_optarg" ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir="$ac_optarg" ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir="$ac_optarg" ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir="$ac_optarg" ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir="$ac_optarg" ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + localstatedir="$ac_optarg" ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir="$ac_optarg" ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir="$ac_optarg" ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix="$ac_optarg" ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix="$ac_optarg" ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix="$ac_optarg" ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name="$ac_optarg" ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir="$ac_optarg" ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir="$ac_optarg" ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site="$ac_optarg" ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir="$ac_optarg" ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir="$ac_optarg" ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target="$ac_optarg" ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers) + echo "configure generated by autoconf version 2.12.2" + exit 0 ;; + + -with-* | --with-*) + ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "with_${ac_package}='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`echo $ac_option|sed -e 's/-*without-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + eval "with_${ac_package}=no" ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes="$ac_optarg" ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries="$ac_optarg" ;; + + -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; } + ;; + + *) + if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then + echo "configure: warning: $ac_option: invalid host type" 1>&2 + fi + if test "x$nonopt" != xNONE; then + { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } + fi + nonopt="$ac_option" + ;; + + esac +done + +if test -n "$ac_prev"; then + { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; } +fi + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +# File descriptor usage: +# 0 standard input +# 1 file creation +# 2 errors and warnings +# 3 some systems may open it to /dev/tty +# 4 used on the Kubota Titan +# 6 checking for... messages and results +# 5 compiler messages saved in config.log +if test "$silent" = yes; then + exec 6>/dev/null +else + exec 6>&1 +fi +exec 5>./config.log + +echo "\ +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. +" 1>&5 + +# Strip out --no-create and --no-recursion so they do not pile up. +# Also quote any args containing shell metacharacters. +ac_configure_args= +for ac_arg +do + case "$ac_arg" in + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) ;; + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) + ac_configure_args="$ac_configure_args '$ac_arg'" ;; + *) ac_configure_args="$ac_configure_args $ac_arg" ;; + esac +done + +# NLS nuisances. +# Only set these to C if already set. These must not be set unconditionally +# because not all systems understand e.g. LANG=C (notably SCO). +# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'! +# Non-C LC_CTYPE values break the ctype check. +if test "${LANG+set}" = set; then LANG=C; export LANG; fi +if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi +if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi +if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo > confdefs.h + +# A filename unique to this package, relative to the directory that +# configure is in, which we can look for to find out if srcdir is correct. +ac_unique_file=Makefile.in + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then its parent. + ac_prog=$0 + ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'` + test "x$ac_confdir" = "x$ac_prog" && ac_confdir=. + srcdir=$ac_confdir + if test ! -r $srcdir/$ac_unique_file; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r $srcdir/$ac_unique_file; then + if test "$ac_srcdir_defaulted" = yes; then + { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; } + else + { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; } + fi +fi +srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'` + +# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + echo "loading site script $ac_site_file" + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + echo "loading cache $cache_file" + . $cache_file +else + echo "creating cache $cache_file" + > $cache_file +fi + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +ac_exeext= +ac_objext=o +if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then + # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. + if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then + ac_n= ac_c=' +' ac_t=' ' + else + ac_n=-n ac_c= ac_t= + fi +else + ac_n= ac_c='\c' ac_t= +fi + + + +# This is intended for use by the target specific directories, and by us. +echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 +echo "configure:677: checking how to run the C preprocessor" >&5 +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then +if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + # This must be in double quotes, not single quotes, because CPP may get + # substituted into the Makefile and "${CC-cc}" will confuse make. + CPP="${CC-cc} -E" + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. + cat > conftest.$ac_ext < +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:698: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP="${CC-cc} -E -traditional-cpp" + cat > conftest.$ac_ext < +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:715: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP="${CC-cc} -nologo -E" + cat > conftest.$ac_ext < +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:732: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP=/lib/cpp +fi +rm -f conftest* +fi +rm -f conftest* +fi +rm -f conftest* + ac_cv_prog_CPP="$CPP" +fi + CPP="$ac_cv_prog_CPP" +else + ac_cv_prog_CPP="$CPP" +fi +echo "$ac_t""$CPP" 1>&6 + +echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6 +echo "configure:757: checking whether ${MAKE-make} sets \${MAKE}" >&5 +set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftestmake <<\EOF +all: + @echo 'ac_maketemp="${MAKE}"' +EOF +# GNU make sometimes prints "make[1]: Entering...", which would confuse us. +eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=` +if test -n "$ac_maketemp"; then + eval ac_cv_prog_make_${ac_make}_set=yes +else + eval ac_cv_prog_make_${ac_make}_set=no +fi +rm -f conftestmake +fi +if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then + echo "$ac_t""yes" 1>&6 + SET_MAKE= +else + echo "$ac_t""no" 1>&6 + SET_MAKE="MAKE=${MAKE-make}" +fi + +echo $ac_n "checking for POSIXized ISC""... $ac_c" 1>&6 +echo "configure:784: checking for POSIXized ISC" >&5 +if test -d /etc/conf/kconfig.d && + grep _POSIX_VERSION /usr/include/sys/unistd.h >/dev/null 2>&1 +then + echo "$ac_t""yes" 1>&6 + ISC=yes # If later tests want to check for ISC. + cat >> confdefs.h <<\EOF +#define _POSIX_SOURCE 1 +EOF + + if test "$GCC" = yes; then + CC="$CC -posix" + else + CC="$CC -Xp" + fi +else + echo "$ac_t""no" 1>&6 + ISC= +fi + +echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6 +echo "configure:805: checking for ANSI C header files" >&5 +if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#include +#include +#include +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:818: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + ac_cv_header_stdc=yes +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_header_stdc=no +fi +rm -f conftest* + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. +cat > conftest.$ac_ext < +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "memchr" >/dev/null 2>&1; then + : +else + rm -rf conftest* + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. +cat > conftest.$ac_ext < +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "free" >/dev/null 2>&1; then + : +else + rm -rf conftest* + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. +if test "$cross_compiling" = yes; then + : +else + cat > conftest.$ac_ext < +#define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int main () { int i; for (i = 0; i < 256; i++) +if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); +exit (0); } + +EOF +if { (eval echo configure:885: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +then + : +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_header_stdc=no +fi +rm -fr conftest* +fi + +fi +fi + +echo "$ac_t""$ac_cv_header_stdc" 1>&6 +if test $ac_cv_header_stdc = yes; then + cat >> confdefs.h <<\EOF +#define STDC_HEADERS 1 +EOF + +fi + +echo $ac_n "checking for working const""... $ac_c" 1>&6 +echo "configure:909: checking for working const" >&5 +if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <j = 5; +} +{ /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ + const int foo = 10; +} + +; return 0; } +EOF +if { (eval echo configure:963: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_c_const=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_c_const=no +fi +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_c_const" 1>&6 +if test $ac_cv_c_const = no; then + cat >> confdefs.h <<\EOF +#define const +EOF + +fi + +echo $ac_n "checking for inline""... $ac_c" 1>&6 +echo "configure:984: checking for inline" >&5 +if eval "test \"`echo '$''{'ac_cv_c_inline'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_cv_c_inline=no +for ac_kw in inline __inline__ __inline; do + cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_c_inline=$ac_kw; break +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 +fi +rm -f conftest* +done + +fi + +echo "$ac_t""$ac_cv_c_inline" 1>&6 +case "$ac_cv_c_inline" in + inline | yes) ;; + no) cat >> confdefs.h <<\EOF +#define inline +EOF + ;; + *) cat >> confdefs.h <&6 +echo "configure:1024: checking for off_t" >&5 +if eval "test \"`echo '$''{'ac_cv_type_off_t'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#if STDC_HEADERS +#include +#include +#endif +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "off_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then + rm -rf conftest* + ac_cv_type_off_t=yes +else + rm -rf conftest* + ac_cv_type_off_t=no +fi +rm -f conftest* + +fi +echo "$ac_t""$ac_cv_type_off_t" 1>&6 +if test $ac_cv_type_off_t = no; then + cat >> confdefs.h <<\EOF +#define off_t long +EOF + +fi + +echo $ac_n "checking for size_t""... $ac_c" 1>&6 +echo "configure:1057: checking for size_t" >&5 +if eval "test \"`echo '$''{'ac_cv_type_size_t'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#if STDC_HEADERS +#include +#include +#endif +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "size_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then + rm -rf conftest* + ac_cv_type_size_t=yes +else + rm -rf conftest* + ac_cv_type_size_t=no +fi +rm -f conftest* + +fi +echo "$ac_t""$ac_cv_type_size_t" 1>&6 +if test $ac_cv_type_size_t = no; then + cat >> confdefs.h <<\EOF +#define size_t unsigned +EOF + +fi + +# The Ultrix 4.2 mips builtin alloca declared by alloca.h only works +# for constant arguments. Useless! +echo $ac_n "checking for working alloca.h""... $ac_c" 1>&6 +echo "configure:1092: checking for working alloca.h" >&5 +if eval "test \"`echo '$''{'ac_cv_header_alloca_h'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +int main() { +char *p = alloca(2 * sizeof(int)); +; return 0; } +EOF +if { (eval echo configure:1104: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + ac_cv_header_alloca_h=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_header_alloca_h=no +fi +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_header_alloca_h" 1>&6 +if test $ac_cv_header_alloca_h = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_ALLOCA_H 1 +EOF + +fi + +echo $ac_n "checking for alloca""... $ac_c" 1>&6 +echo "configure:1125: checking for alloca" >&5 +if eval "test \"`echo '$''{'ac_cv_func_alloca_works'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +# define alloca _alloca +# else +# if HAVE_ALLOCA_H +# include +# else +# ifdef _AIX + #pragma alloca +# else +# ifndef alloca /* predefined by HP cc +Olibcalls */ +char *alloca (); +# endif +# endif +# endif +# endif +#endif + +int main() { +char *p = (char *) alloca(1); +; return 0; } +EOF +if { (eval echo configure:1158: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + ac_cv_func_alloca_works=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_func_alloca_works=no +fi +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_func_alloca_works" 1>&6 +if test $ac_cv_func_alloca_works = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_ALLOCA 1 +EOF + +fi + +if test $ac_cv_func_alloca_works = no; then + # The SVR3 libPW and SVR4 libucb both contain incompatible functions + # that cause trouble. Some versions do not even contain alloca or + # contain a buggy version. If you still want to use their alloca, + # use ar to extract alloca.o from them instead of compiling alloca.c. + ALLOCA=alloca.${ac_objext} + cat >> confdefs.h <<\EOF +#define C_ALLOCA 1 +EOF + + +echo $ac_n "checking whether alloca needs Cray hooks""... $ac_c" 1>&6 +echo "configure:1190: checking whether alloca needs Cray hooks" >&5 +if eval "test \"`echo '$''{'ac_cv_os_cray'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <&5 | + egrep "webecray" >/dev/null 2>&1; then + rm -rf conftest* + ac_cv_os_cray=yes +else + rm -rf conftest* + ac_cv_os_cray=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_os_cray" 1>&6 +if test $ac_cv_os_cray = yes; then +for ac_func in _getb67 GETB67 getb67; do + echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:1220: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:1248: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + cat >> confdefs.h <&6 +fi + +done +fi + +echo $ac_n "checking stack direction for C alloca""... $ac_c" 1>&6 +echo "configure:1275: checking stack direction for C alloca" >&5 +if eval "test \"`echo '$''{'ac_cv_c_stack_direction'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$cross_compiling" = yes; then + ac_cv_c_stack_direction=0 +else + cat > conftest.$ac_ext < addr) ? 1 : -1; +} +main () +{ + exit (find_stack_direction() < 0); +} +EOF +if { (eval echo configure:1302: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +then + ac_cv_c_stack_direction=1 +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_c_stack_direction=-1 +fi +rm -fr conftest* +fi + +fi + +echo "$ac_t""$ac_cv_c_stack_direction" 1>&6 +cat >> confdefs.h <&6 +echo "configure:1327: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1337: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <&6 +fi +done + +for ac_func in getpagesize +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:1366: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:1394: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <&6 +fi +done + +echo $ac_n "checking for working mmap""... $ac_c" 1>&6 +echo "configure:1419: checking for working mmap" >&5 +if eval "test \"`echo '$''{'ac_cv_func_mmap_fixed_mapped'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$cross_compiling" = yes; then + ac_cv_func_mmap_fixed_mapped=no +else + cat > conftest.$ac_ext < +#include +#include + +/* This mess was copied from the GNU getpagesize.h. */ +#ifndef HAVE_GETPAGESIZE +# ifdef HAVE_UNISTD_H +# include +# endif + +/* Assume that all systems that can run configure have sys/param.h. */ +# ifndef HAVE_SYS_PARAM_H +# define HAVE_SYS_PARAM_H 1 +# endif + +# ifdef _SC_PAGESIZE +# define getpagesize() sysconf(_SC_PAGESIZE) +# else /* no _SC_PAGESIZE */ +# ifdef HAVE_SYS_PARAM_H +# include +# ifdef EXEC_PAGESIZE +# define getpagesize() EXEC_PAGESIZE +# else /* no EXEC_PAGESIZE */ +# ifdef NBPG +# define getpagesize() NBPG * CLSIZE +# ifndef CLSIZE +# define CLSIZE 1 +# endif /* no CLSIZE */ +# else /* no NBPG */ +# ifdef NBPC +# define getpagesize() NBPC +# else /* no NBPC */ +# ifdef PAGESIZE +# define getpagesize() PAGESIZE +# endif /* PAGESIZE */ +# endif /* no NBPC */ +# endif /* no NBPG */ +# endif /* no EXEC_PAGESIZE */ +# else /* no HAVE_SYS_PARAM_H */ +# define getpagesize() 8192 /* punt totally */ +# endif /* no HAVE_SYS_PARAM_H */ +# endif /* no _SC_PAGESIZE */ + +#endif /* no HAVE_GETPAGESIZE */ + +#ifdef __cplusplus +extern "C" { void *malloc(unsigned); } +#else +char *malloc(); +#endif + +int +main() +{ + char *data, *data2, *data3; + int i, pagesize; + int fd; + + pagesize = getpagesize(); + + /* + * First, make a file with some known garbage in it. + */ + data = malloc(pagesize); + if (!data) + exit(1); + for (i = 0; i < pagesize; ++i) + *(data + i) = rand(); + umask(0); + fd = creat("conftestmmap", 0600); + if (fd < 0) + exit(1); + if (write(fd, data, pagesize) != pagesize) + exit(1); + close(fd); + + /* + * Next, try to mmap the file at a fixed address which + * already has something else allocated at it. If we can, + * also make sure that we see the same garbage. + */ + fd = open("conftestmmap", O_RDWR); + if (fd < 0) + exit(1); + data2 = malloc(2 * pagesize); + if (!data2) + exit(1); + data2 += (pagesize - ((int) data2 & (pagesize - 1))) & (pagesize - 1); + if (data2 != mmap(data2, pagesize, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_FIXED, fd, 0L)) + exit(1); + for (i = 0; i < pagesize; ++i) + if (*(data + i) != *(data2 + i)) + exit(1); + + /* + * Finally, make sure that changes to the mapped area + * do not percolate back to the file as seen by read(). + * (This is a bug on some variants of i386 svr4.0.) + */ + for (i = 0; i < pagesize; ++i) + *(data2 + i) = *(data2 + i) + 1; + data3 = malloc(pagesize); + if (!data3) + exit(1); + if (read(fd, data3, pagesize) != pagesize) + exit(1); + for (i = 0; i < pagesize; ++i) + if (*(data + i) != *(data3 + i)) + exit(1); + close(fd); + unlink("conftestmmap"); + exit(0); +} + +EOF +if { (eval echo configure:1567: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +then + ac_cv_func_mmap_fixed_mapped=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_func_mmap_fixed_mapped=no +fi +rm -fr conftest* +fi + +fi + +echo "$ac_t""$ac_cv_func_mmap_fixed_mapped" 1>&6 +if test $ac_cv_func_mmap_fixed_mapped = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_MMAP 1 +EOF + +fi + + +# autoconf.info says this should be called right after AC_INIT. + + +ac_aux_dir= +for ac_dir in `cd $srcdir;pwd`/../.. $srcdir/`cd $srcdir;pwd`/../..; do + if test -f $ac_dir/install-sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f $ac_dir/install.sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + fi +done +if test -z "$ac_aux_dir"; then + { echo "configure: error: can not find install-sh or install.sh in `cd $srcdir;pwd`/../.. $srcdir/`cd $srcdir;pwd`/../.." 1>&2; exit 1; } +fi +ac_config_guess=$ac_aux_dir/config.guess +ac_config_sub=$ac_aux_dir/config.sub +ac_configure=$ac_aux_dir/configure # This should be Cygnus configure. + + +# Do some error checking and defaulting for the host and target type. +# The inputs are: +# configure --host=HOST --target=TARGET --build=BUILD NONOPT +# +# The rules are: +# 1. You are not allowed to specify --host, --target, and nonopt at the +# same time. +# 2. Host defaults to nonopt. +# 3. If nonopt is not specified, then host defaults to the current host, +# as determined by config.guess. +# 4. Target and build default to nonopt. +# 5. If nonopt is not specified, then target and build default to host. + +# The aliases save the names the user supplied, while $host etc. +# will get canonicalized. +case $host---$target---$nonopt in +NONE---*---* | *---NONE---* | *---*---NONE) ;; +*) { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } ;; +esac + + +# Make sure we can run config.sub. +if ${CONFIG_SHELL-/bin/sh} $ac_config_sub sun4 >/dev/null 2>&1; then : +else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; } +fi + +echo $ac_n "checking host system type""... $ac_c" 1>&6 +echo "configure:1640: checking host system type" >&5 + +host_alias=$host +case "$host_alias" in +NONE) + case $nonopt in + NONE) + if host_alias=`${CONFIG_SHELL-/bin/sh} $ac_config_guess`; then : + else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; } + fi ;; + *) host_alias=$nonopt ;; + esac ;; +esac + +host=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $host_alias` +host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` +echo "$ac_t""$host" 1>&6 + +echo $ac_n "checking target system type""... $ac_c" 1>&6 +echo "configure:1661: checking target system type" >&5 + +target_alias=$target +case "$target_alias" in +NONE) + case $nonopt in + NONE) target_alias=$host_alias ;; + *) target_alias=$nonopt ;; + esac ;; +esac + +target=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $target_alias` +target_cpu=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +target_vendor=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +target_os=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` +echo "$ac_t""$target" 1>&6 + +echo $ac_n "checking build system type""... $ac_c" 1>&6 +echo "configure:1679: checking build system type" >&5 + +build_alias=$build +case "$build_alias" in +NONE) + case $nonopt in + NONE) build_alias=$host_alias ;; + *) build_alias=$nonopt ;; + esac ;; +esac + +build=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $build_alias` +build_cpu=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +build_vendor=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +build_os=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` +echo "$ac_t""$build" 1>&6 + +test "$host_alias" != "$target_alias" && + test "$program_prefix$program_suffix$program_transform_name" = \ + NONENONEs,x,x, && + program_prefix=${target_alias}- + +if test "$program_transform_name" = s,x,x,; then + program_transform_name= +else + # Double any \ or $. echo might interpret backslashes. + cat <<\EOF_SED > conftestsed +s,\\,\\\\,g; s,\$,$$,g +EOF_SED + program_transform_name="`echo $program_transform_name|sed -f conftestsed`" + rm -f conftestsed +fi +test "$program_prefix" != NONE && + program_transform_name="s,^,${program_prefix},; $program_transform_name" +# Use a double $ so make ignores it. +test "$program_suffix" != NONE && + program_transform_name="s,\$\$,${program_suffix},; $program_transform_name" + +# sed with no file args requires a program. +test "$program_transform_name" = "" && program_transform_name="s,x,x," + +# Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1723: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CC="gcc" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1752: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_prog_rejected=no + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + break + fi + done + IFS="$ac_save_ifs" +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# -gt 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + set dummy "$ac_dir/$ac_word" "$@" + shift + ac_cv_prog_CC="$@" + fi +fi +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + if test -z "$CC"; then + case "`uname -s`" in + *win32* | *WIN32*) + # Extract the first word of "cl", so it can be a program name with args. +set dummy cl; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1802: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CC="cl" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + ;; + esac + fi + test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; } +fi + +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 +echo "configure:1833: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + ac_cv_prog_cc_works=yes + # If we can't run a trivial program, we are probably using a cross compiler. + if (./conftest; exit) 2>/dev/null; then + ac_cv_prog_cc_cross=no + else + ac_cv_prog_cc_cross=yes + fi +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + ac_cv_prog_cc_works=no +fi +rm -fr conftest* + +echo "$ac_t""$ac_cv_prog_cc_works" 1>&6 +if test $ac_cv_prog_cc_works = no; then + { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } +fi +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 +echo "configure:1867: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 +cross_compiling=$ac_cv_prog_cc_cross + +echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 +echo "configure:1872: checking whether we are using GNU C" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.c <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then + ac_cv_prog_gcc=yes +else + ac_cv_prog_gcc=no +fi +fi + +echo "$ac_t""$ac_cv_prog_gcc" 1>&6 + +if test $ac_cv_prog_gcc = yes; then + GCC=yes +else + GCC= +fi + +ac_test_CFLAGS="${CFLAGS+set}" +ac_save_CFLAGS="$CFLAGS" +CFLAGS= +echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 +echo "configure:1900: checking whether ${CC-cc} accepts -g" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + echo 'void f(){}' > conftest.c +if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then + ac_cv_prog_cc_g=yes +else + ac_cv_prog_cc_g=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_prog_cc_g" 1>&6 +if test "$ac_test_CFLAGS" = set; then + CFLAGS="$ac_save_CFLAGS" +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# ./install, which can be erroneously created by make from ./install.sh. +echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 +echo "configure:1943: checking for a BSD compatible install" >&5 +if test -z "$INSTALL"; then +if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":" + for ac_dir in $PATH; do + # Account for people who put trailing slashes in PATH elements. + case "$ac_dir/" in + /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + if test -f $ac_dir/$ac_prog; then + if test $ac_prog = install && + grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + else + ac_cv_path_install="$ac_dir/$ac_prog -c" + break 2 + fi + fi + done + ;; + esac + done + IFS="$ac_save_IFS" + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL="$ac_cv_path_install" + else + # As a last resort, use the slow shell script. We don't cache a + # path for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the path is relative. + INSTALL="$ac_install_sh" + fi +fi +echo "$ac_t""$INSTALL" 1>&6 + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + + +# Put a plausible default for CC_FOR_BUILD in Makefile. +if test "x$cross_compiling" = "xno"; then + CC_FOR_BUILD='$(CC)' +else + CC_FOR_BUILD=gcc +fi + + + + +AR=${AR-ar} + +# Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:2009: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_RANLIB="ranlib" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":" +fi +fi +RANLIB="$ac_cv_prog_RANLIB" +if test -n "$RANLIB"; then + echo "$ac_t""$RANLIB" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + +ALL_LINGUAS= + + for ac_hdr in argz.h limits.h locale.h nl_types.h malloc.h string.h \ +unistd.h values.h sys/param.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:2043: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:2053: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <&6 +fi +done + + for ac_func in getcwd munmap putenv setenv setlocale strchr strcasecmp \ +__argz_count __argz_stringify __argz_next +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:2083: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:2111: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <&6 +fi +done + + + if test "${ac_cv_func_stpcpy+set}" != "set"; then + for ac_func in stpcpy +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:2140: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:2168: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <&6 +fi +done + + fi + if test "${ac_cv_func_stpcpy}" = "yes"; then + cat >> confdefs.h <<\EOF +#define HAVE_STPCPY 1 +EOF + + fi + + if test $ac_cv_header_locale_h = yes; then + echo $ac_n "checking for LC_MESSAGES""... $ac_c" 1>&6 +echo "configure:2202: checking for LC_MESSAGES" >&5 +if eval "test \"`echo '$''{'am_cv_val_LC_MESSAGES'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +int main() { +return LC_MESSAGES +; return 0; } +EOF +if { (eval echo configure:2214: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + am_cv_val_LC_MESSAGES=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + am_cv_val_LC_MESSAGES=no +fi +rm -f conftest* +fi + +echo "$ac_t""$am_cv_val_LC_MESSAGES" 1>&6 + if test $am_cv_val_LC_MESSAGES = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_LC_MESSAGES 1 +EOF + + fi + fi + echo $ac_n "checking whether NLS is requested""... $ac_c" 1>&6 +echo "configure:2235: checking whether NLS is requested" >&5 + # Check whether --enable-nls or --disable-nls was given. +if test "${enable_nls+set}" = set; then + enableval="$enable_nls" + USE_NLS=$enableval +else + USE_NLS=yes +fi + + echo "$ac_t""$USE_NLS" 1>&6 + + + USE_INCLUDED_LIBINTL=no + + if test "$USE_NLS" = "yes"; then + cat >> confdefs.h <<\EOF +#define ENABLE_NLS 1 +EOF + + echo $ac_n "checking whether included gettext is requested""... $ac_c" 1>&6 +echo "configure:2255: checking whether included gettext is requested" >&5 + # Check whether --with-included-gettext or --without-included-gettext was given. +if test "${with_included_gettext+set}" = set; then + withval="$with_included_gettext" + nls_cv_force_use_gnu_gettext=$withval +else + nls_cv_force_use_gnu_gettext=no +fi + + echo "$ac_t""$nls_cv_force_use_gnu_gettext" 1>&6 + + nls_cv_use_gnu_gettext="$nls_cv_force_use_gnu_gettext" + if test "$nls_cv_force_use_gnu_gettext" != "yes"; then + nls_cv_header_intl= + nls_cv_header_libgt= + CATOBJEXT=NONE + + ac_safe=`echo "libintl.h" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for libintl.h""... $ac_c" 1>&6 +echo "configure:2274: checking for libintl.h" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:2284: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + echo $ac_n "checking for gettext in libc""... $ac_c" 1>&6 +echo "configure:2301: checking for gettext in libc" >&5 +if eval "test \"`echo '$''{'gt_cv_func_gettext_libc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +int main() { +return (int) gettext ("") +; return 0; } +EOF +if { (eval echo configure:2313: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + gt_cv_func_gettext_libc=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + gt_cv_func_gettext_libc=no +fi +rm -f conftest* +fi + +echo "$ac_t""$gt_cv_func_gettext_libc" 1>&6 + + if test "$gt_cv_func_gettext_libc" != "yes"; then + echo $ac_n "checking for bindtextdomain in -lintl""... $ac_c" 1>&6 +echo "configure:2329: checking for bindtextdomain in -lintl" >&5 +ac_lib_var=`echo intl'_'bindtextdomain | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lintl $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + echo $ac_n "checking for gettext in libintl""... $ac_c" 1>&6 +echo "configure:2364: checking for gettext in libintl" >&5 +if eval "test \"`echo '$''{'gt_cv_func_gettext_libintl'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + gt_cv_func_gettext_libintl=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + gt_cv_func_gettext_libintl=no +fi +rm -f conftest* +fi + +echo "$ac_t""$gt_cv_func_gettext_libintl" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + fi + + if test "$gt_cv_func_gettext_libc" = "yes" \ + || test "$gt_cv_func_gettext_libintl" = "yes"; then + cat >> confdefs.h <<\EOF +#define HAVE_GETTEXT 1 +EOF + + # Extract the first word of "msgfmt", so it can be a program name with args. +set dummy msgfmt; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:2404: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_MSGFMT'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$MSGFMT" in + /*) + ac_cv_path_MSGFMT="$MSGFMT" # Let the user override the test with a path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"; then + ac_cv_path_MSGFMT="$ac_dir/$ac_word" + break + fi + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_MSGFMT" && ac_cv_path_MSGFMT="no" + ;; +esac +fi +MSGFMT="$ac_cv_path_MSGFMT" +if test -n "$MSGFMT"; then + echo "$ac_t""$MSGFMT" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + if test "$MSGFMT" != "no"; then + for ac_func in dcgettext +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:2438: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:2466: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <&6 +fi +done + + # Extract the first word of "gmsgfmt", so it can be a program name with args. +set dummy gmsgfmt; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:2493: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_GMSGFMT'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$GMSGFMT" in + /*) + ac_cv_path_GMSGFMT="$GMSGFMT" # Let the user override the test with a path. + ;; + ?:/*) + ac_cv_path_GMSGFMT="$GMSGFMT" # Let the user override the test with a dos path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_path_GMSGFMT="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_GMSGFMT" && ac_cv_path_GMSGFMT="$MSGFMT" + ;; +esac +fi +GMSGFMT="$ac_cv_path_GMSGFMT" +if test -n "$GMSGFMT"; then + echo "$ac_t""$GMSGFMT" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + # Extract the first word of "xgettext", so it can be a program name with args. +set dummy xgettext; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:2528: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_XGETTEXT'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$XGETTEXT" in + /*) + ac_cv_path_XGETTEXT="$XGETTEXT" # Let the user override the test with a path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"; then + ac_cv_path_XGETTEXT="$ac_dir/$ac_word" + break + fi + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_XGETTEXT" && ac_cv_path_XGETTEXT=":" + ;; +esac +fi +XGETTEXT="$ac_cv_path_XGETTEXT" +if test -n "$XGETTEXT"; then + echo "$ac_t""$XGETTEXT" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + CATOBJEXT=.gmo + DATADIRNAME=share +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CATOBJEXT=.mo + DATADIRNAME=lib +fi +rm -f conftest* + INSTOBJEXT=.mo + fi + fi + +else + echo "$ac_t""no" 1>&6 +fi + + + + if test "$CATOBJEXT" = "NONE"; then + nls_cv_use_gnu_gettext=yes + fi + fi + + if test "$nls_cv_use_gnu_gettext" = "yes"; then + INTLOBJS="\$(GETTOBJS)" + # Extract the first word of "msgfmt", so it can be a program name with args. +set dummy msgfmt; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:2600: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_MSGFMT'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$MSGFMT" in + /*) + ac_cv_path_MSGFMT="$MSGFMT" # Let the user override the test with a path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"; then + ac_cv_path_MSGFMT="$ac_dir/$ac_word" + break + fi + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_MSGFMT" && ac_cv_path_MSGFMT="msgfmt" + ;; +esac +fi +MSGFMT="$ac_cv_path_MSGFMT" +if test -n "$MSGFMT"; then + echo "$ac_t""$MSGFMT" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + # Extract the first word of "gmsgfmt", so it can be a program name with args. +set dummy gmsgfmt; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:2634: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_GMSGFMT'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$GMSGFMT" in + /*) + ac_cv_path_GMSGFMT="$GMSGFMT" # Let the user override the test with a path. + ;; + ?:/*) + ac_cv_path_GMSGFMT="$GMSGFMT" # Let the user override the test with a dos path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_path_GMSGFMT="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_GMSGFMT" && ac_cv_path_GMSGFMT="$MSGFMT" + ;; +esac +fi +GMSGFMT="$ac_cv_path_GMSGFMT" +if test -n "$GMSGFMT"; then + echo "$ac_t""$GMSGFMT" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + # Extract the first word of "xgettext", so it can be a program name with args. +set dummy xgettext; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:2669: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_XGETTEXT'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$XGETTEXT" in + /*) + ac_cv_path_XGETTEXT="$XGETTEXT" # Let the user override the test with a path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"; then + ac_cv_path_XGETTEXT="$ac_dir/$ac_word" + break + fi + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_XGETTEXT" && ac_cv_path_XGETTEXT=":" + ;; +esac +fi +XGETTEXT="$ac_cv_path_XGETTEXT" +if test -n "$XGETTEXT"; then + echo "$ac_t""$XGETTEXT" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + + USE_INCLUDED_LIBINTL=yes + CATOBJEXT=.gmo + INSTOBJEXT=.mo + DATADIRNAME=share + INTLDEPS='$(top_builddir)/../intl/libintl.a' + INTLLIBS=$INTLDEPS + LIBS=`echo $LIBS | sed -e 's/-lintl//'` + nls_cv_header_intl=libintl.h + nls_cv_header_libgt=libgettext.h + fi + + if test "$XGETTEXT" != ":"; then + if $XGETTEXT --omit-header /dev/null 2> /dev/null; then + : ; + else + echo "$ac_t""found xgettext programs is not GNU xgettext; ignore it" 1>&6 + XGETTEXT=":" + fi + fi + + # We need to process the po/ directory. + POSUB=po + else + DATADIRNAME=share + nls_cv_header_intl=libintl.h + nls_cv_header_libgt=libgettext.h + fi + + # If this is used in GNU gettext we have to set USE_NLS to `yes' + # because some of the sources are only built for this goal. + if test "$PACKAGE" = gettext; then + USE_NLS=yes + USE_INCLUDED_LIBINTL=yes + fi + + for lang in $ALL_LINGUAS; do + GMOFILES="$GMOFILES $lang.gmo" + POFILES="$POFILES $lang.po" + done + + + + + + + + + + + + + + + if test "x$CATOBJEXT" != "x"; then + if test "x$ALL_LINGUAS" = "x"; then + LINGUAS= + else + echo $ac_n "checking for catalogs to be installed""... $ac_c" 1>&6 +echo "configure:2759: checking for catalogs to be installed" >&5 + NEW_LINGUAS= + for lang in ${LINGUAS=$ALL_LINGUAS}; do + case "$ALL_LINGUAS" in + *$lang*) NEW_LINGUAS="$NEW_LINGUAS $lang" ;; + esac + done + LINGUAS=$NEW_LINGUAS + echo "$ac_t""$LINGUAS" 1>&6 + fi + + if test -n "$LINGUAS"; then + for lang in $LINGUAS; do CATALOGS="$CATALOGS $lang$CATOBJEXT"; done + fi + fi + + if test $ac_cv_header_locale_h = yes; then + INCLUDE_LOCALE_H="#include " + else + INCLUDE_LOCALE_H="\ +/* The system does not provide the header . Take care yourself. */" + fi + + + if test -f $srcdir/po2tbl.sed.in; then + if test "$CATOBJEXT" = ".cat"; then + ac_safe=`echo "linux/version.h" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for linux/version.h""... $ac_c" 1>&6 +echo "configure:2787: checking for linux/version.h" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:2797: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + msgformat=linux +else + echo "$ac_t""no" 1>&6 +msgformat=xopen +fi + + + sed -e '/^#/d' $srcdir/$msgformat-msg.sed > po2msg.sed + fi + sed -e '/^#.*[^\\]$/d' -e '/^#$/d' \ + $srcdir/po2tbl.sed.in > po2tbl.sed + fi + + if test "$PACKAGE" = "gettext"; then + GT_NO="#NO#" + GT_YES= + else + GT_NO= + GT_YES="#YES#" + fi + + + + MKINSTALLDIRS="\$(srcdir)/../../mkinstalldirs" + + + l= + + + if test -d $srcdir/po; then + test -d po || mkdir po + if test "x$srcdir" != "x."; then + if test "x`echo $srcdir | sed 's@/.*@@'`" = "x"; then + posrcprefix="$srcdir/" + else + posrcprefix="../$srcdir/" + fi + else + posrcprefix="../" + fi + rm -f po/POTFILES + sed -e "/^#/d" -e "/^\$/d" -e "s,.*, $posrcprefix& \\\\," -e "\$s/\(.*\) \\\\/\1/" \ + < $srcdir/po/POTFILES.in > po/POTFILES + fi + + +# Check for common headers. +# FIXME: Seems to me this can cause problems for i386-windows hosts. +# At one point there were hardcoded AC_DEFINE's if ${host} = i386-*-windows*. +for ac_hdr in stdlib.h string.h strings.h unistd.h time.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:2866: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:2876: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <&6 +fi +done + +for ac_hdr in sys/time.h sys/resource.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:2906: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:2916: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <&6 +fi +done + +for ac_hdr in fcntl.h fpu_control.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:2946: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:2956: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <&6 +fi +done + +for ac_hdr in dlfcn.h errno.h sys/stat.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:2986: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:2996: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <&6 +fi +done + +for ac_func in getrusage time sigaction __setfpucw +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:3025: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:3053: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <&6 +fi +done + + +# Check for socket libraries +echo $ac_n "checking for bind in -lsocket""... $ac_c" 1>&6 +echo "configure:3080: checking for bind in -lsocket" >&5 +ac_lib_var=`echo socket'_'bind | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lsocket $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_lib=HAVE_LIB`echo socket | sed -e 's/[^a-zA-Z0-9_]/_/g' \ + -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'` + cat >> confdefs.h <&6 +fi + +echo $ac_n "checking for gethostbyname in -lnsl""... $ac_c" 1>&6 +echo "configure:3127: checking for gethostbyname in -lnsl" >&5 +ac_lib_var=`echo nsl'_'gethostbyname | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lnsl $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_lib=HAVE_LIB`echo nsl | sed -e 's/[^a-zA-Z0-9_]/_/g' \ + -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'` + cat >> confdefs.h <&6 +fi + + +. ${srcdir}/../../bfd/configure.host + + + +USE_MAINTAINER_MODE=no +# Check whether --enable-maintainer-mode or --disable-maintainer-mode was given. +if test "${enable_maintainer_mode+set}" = set; then + enableval="$enable_maintainer_mode" + case "${enableval}" in + yes) MAINT="" USE_MAINTAINER_MODE=yes ;; + no) MAINT="#" ;; + *) { echo "configure: error: "--enable-maintainer-mode does not take a value"" 1>&2; exit 1; }; MAINT="#" ;; +esac +if test x"$silent" != x"yes" && test x"$MAINT" = x""; then + echo "Setting maintainer mode" 6>&1 +fi +else + MAINT="#" +fi + + + +# Check whether --enable-sim-bswap or --disable-sim-bswap was given. +if test "${enable_sim_bswap+set}" = set; then + enableval="$enable_sim_bswap" + case "${enableval}" in + yes) sim_bswap="-DWITH_BSWAP=1 -DUSE_BSWAP=1";; + no) sim_bswap="-DWITH_BSWAP=0";; + *) { echo "configure: error: "--enable-sim-bswap does not take a value"" 1>&2; exit 1; }; sim_bswap="";; +esac +if test x"$silent" != x"yes" && test x"$sim_bswap" != x""; then + echo "Setting bswap flags = $sim_bswap" 6>&1 +fi +else + sim_bswap="" +fi + + + +# Check whether --enable-sim-cflags or --disable-sim-cflags was given. +if test "${enable_sim_cflags+set}" = set; then + enableval="$enable_sim_cflags" + case "${enableval}" in + yes) sim_cflags="-O2 -fomit-frame-pointer";; + trace) { echo "configure: error: "Please use --enable-sim-debug instead."" 1>&2; exit 1; }; sim_cflags="";; + no) sim_cflags="";; + *) sim_cflags=`echo "${enableval}" | sed -e "s/,/ /g"`;; +esac +if test x"$silent" != x"yes" && test x"$sim_cflags" != x""; then + echo "Setting sim cflags = $sim_cflags" 6>&1 +fi +else + sim_cflags="" +fi + + + +# Check whether --enable-sim-debug or --disable-sim-debug was given. +if test "${enable_sim_debug+set}" = set; then + enableval="$enable_sim_debug" + case "${enableval}" in + yes) sim_debug="-DDEBUG=7 -DWITH_DEBUG=7";; + no) sim_debug="-DDEBUG=0 -DWITH_DEBUG=0";; + *) sim_debug="-DDEBUG='(${enableval})' -DWITH_DEBUG='(${enableval})'";; +esac +if test x"$silent" != x"yes" && test x"$sim_debug" != x""; then + echo "Setting sim debug = $sim_debug" 6>&1 +fi +else + sim_debug="" +fi + + + +# Check whether --enable-sim-stdio or --disable-sim-stdio was given. +if test "${enable_sim_stdio+set}" = set; then + enableval="$enable_sim_stdio" + case "${enableval}" in + yes) sim_stdio="-DWITH_STDIO=DO_USE_STDIO";; + no) sim_stdio="-DWITH_STDIO=DONT_USE_STDIO";; + *) { echo "configure: error: "Unknown value $enableval passed to --enable-sim-stdio"" 1>&2; exit 1; }; sim_stdio="";; +esac +if test x"$silent" != x"yes" && test x"$sim_stdio" != x""; then + echo "Setting stdio flags = $sim_stdio" 6>&1 +fi +else + sim_stdio="" +fi + + + +# Check whether --enable-sim-trace or --disable-sim-trace was given. +if test "${enable_sim_trace+set}" = set; then + enableval="$enable_sim_trace" + case "${enableval}" in + yes) sim_trace="-DTRACE=1 -DWITH_TRACE=-1";; + no) sim_trace="-DTRACE=0 -DWITH_TRACE=0";; + [-0-9]*) + sim_trace="-DTRACE='(${enableval})' -DWITH_TRACE='(${enableval})'";; + [a-z]*) + sim_trace="" + for x in `echo "$enableval" | sed -e "s/,/ /g"`; do + if test x"$sim_trace" = x; then + sim_trace="-DWITH_TRACE='(TRACE_$x" + else + sim_trace="${sim_trace}|TRACE_$x" + fi + done + sim_trace="$sim_trace)'" ;; +esac +if test x"$silent" != x"yes" && test x"$sim_trace" != x""; then + echo "Setting sim trace = $sim_trace" 6>&1 +fi +else + sim_trace="" +fi + + + +# Check whether --enable-sim-profile or --disable-sim-profile was given. +if test "${enable_sim_profile+set}" = set; then + enableval="$enable_sim_profile" + case "${enableval}" in + yes) sim_profile="-DPROFILE=1 -DWITH_PROFILE=-1";; + no) sim_profile="-DPROFILE=0 -DWITH_PROFILE=0";; + [-0-9]*) + sim_profile="-DPROFILE='(${enableval})' -DWITH_PROFILE='(${enableval})'";; + [a-z]*) + sim_profile="" + for x in `echo "$enableval" | sed -e "s/,/ /g"`; do + if test x"$sim_profile" = x; then + sim_profile="-DWITH_PROFILE='(PROFILE_$x" + else + sim_profile="${sim_profile}|PROFILE_$x" + fi + done + sim_profile="$sim_profile)'" ;; +esac +if test x"$silent" != x"yes" && test x"$sim_profile" != x""; then + echo "Setting sim profile = $sim_profile" 6>&1 +fi +else + sim_profile="" +fi + + + +echo $ac_n "checking return type of signal handlers""... $ac_c" 1>&6 +echo "configure:3322: checking return type of signal handlers" >&5 +if eval "test \"`echo '$''{'ac_cv_type_signal'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#include +#ifdef signal +#undef signal +#endif +#ifdef __cplusplus +extern "C" void (*signal (int, void (*)(int)))(int); +#else +void (*signal ()) (); +#endif + +int main() { +int i; +; return 0; } +EOF +if { (eval echo configure:3344: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_type_signal=void +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_type_signal=int +fi +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_type_signal" 1>&6 +cat >> confdefs.h <&6 +echo "configure:3364: checking for executable suffix" >&5 +if eval "test \"`echo '$''{'am_cv_exeext'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$CYGWIN32" = yes; then +am_cv_exeext=.exe +else +cat > am_c_test.c << 'EOF' +int main() { +/* Nothing needed here */ +} +EOF +${CC-cc} -o am_c_test $CFLAGS $CPPFLAGS $LDFLAGS am_c_test.c $LIBS 1>&5 +am_cv_exeext=`ls am_c_test.* | grep -v am_c_test.c | sed -e s/am_c_test//` +rm -f am_c_test* +fi + +test x"${am_cv_exeext}" = x && am_cv_exeext=no +fi +EXEEXT="" +test x"${am_cv_exeext}" != xno && EXEEXT=${am_cv_exeext} +echo "$ac_t""${am_cv_exeext}" 1>&6 + + +sim_link_files= +sim_link_links= + +sim_link_links=tconfig.h +if test -f ${srcdir}/tconfig.in +then + sim_link_files=tconfig.in +else + sim_link_files=../common/tconfig.in +fi + +# targ-vals.def points to the libc macro description file. +case "${target}" in +*-*-*) TARG_VALS_DEF=../common/nltvals.def ;; +esac +sim_link_files="${sim_link_files} ${TARG_VALS_DEF}" +sim_link_links="${sim_link_links} targ-vals.def" + + + +# Put a useful copy of CPP_FOR_TARGET in Makefile. +# This is only used to build the target values header files. These files are +# shipped with distributions so CPP_FOR_TARGET only needs to work in +# developer's trees. This value is borrowed from ../../Makefile.in. +CPP_FOR_TARGET="\` \ + if test -f \$\${rootme}/../../gcc/Makefile ; then \ + if test -f \$\${rootme}/../../\$(TARGET_SUBDIR)/newlib/Makefile ; then \ + echo \$\${rootme}/../../gcc/xgcc -B\$\${rootme}/../../gcc/ -idirafter \$\${rootme}/../../\$(TARGET_SUBDIR)/newlib/targ-include -idirafter \$(srcroot)/newlib/libc/include -nostdinc; \ + else \ + echo \$\${rootme}/../../gcc/xgcc -B\$\${rootme}/../../gcc/; \ + fi; \ + else \ + if test '\$(host_canonical)' = '\$(target_canonical)' ; then \ + echo \$(CC); \ + else \ + t='\$(program_transform_name)'; echo gcc | sed -e 's/x/x/' \$\$t; \ + fi; \ + fi\` -E" + + +# Set TARGET_SUBDIR, needed by CPP_FOR_TARGET. +if test x"${host}" = x"${target}" ; then + TARGET_SUBDIR="." +else + TARGET_SUBDIR=${target_alias} +fi + + +# These aren't all needed yet, but will be eventually. +for ac_hdr in stdlib.h string.h strings.h time.h sys/times.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:3441: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:3451: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <&6 +fi +done + + +trap '' 1 2 15 +cat > confcache <<\EOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs. It is not useful on other systems. +# If it contains results you don't want to keep, you may remove or edit it. +# +# By default, configure uses ./config.cache as the cache file, +# creating it if it does not exist already. You can give configure +# the --cache-file=FILE option to use a different cache file; that is +# what configure does when it calls configure scripts in +# subdirectories, so they share the cache. +# Giving --cache-file=/dev/null disables caching, for debugging configure. +# config.status only pays attention to the cache file if you give it the +# --recheck option to rerun configure. +# +EOF +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +(set) 2>&1 | + case `(ac_space=' '; set) 2>&1 | grep ac_space` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote substitution + # turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + -e "s/'/'\\\\''/g" \ + -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' + ;; + esac >> confcache +if cmp -s $cache_file confcache; then + : +else + if test -w $cache_file; then + echo "updating cache $cache_file" + cat confcache > $cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# Any assignment to VPATH causes Sun make to only execute +# the first set of double-colon rules, so remove it if not needed. +# If there is a colon in the path, we need to keep it. +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d' +fi + +trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15 + +DEFS=-DHAVE_CONFIG_H + +# Without the "./", some shells look in PATH for config.status. +: ${CONFIG_STATUS=./config.status} + +echo creating $CONFIG_STATUS +rm -f $CONFIG_STATUS +cat > $CONFIG_STATUS </dev/null | sed 1q`: +# +# $0 $ac_configure_args +# +# Compiler output produced by configure, useful for debugging +# configure, is in ./config.log if it exists. + +ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]" +for ac_option +do + case "\$ac_option" in + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion" + exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;; + -version | --version | --versio | --versi | --vers | --ver | --ve | --v) + echo "$CONFIG_STATUS generated by autoconf version 2.12.2" + exit 0 ;; + -help | --help | --hel | --he | --h) + echo "\$ac_cs_usage"; exit 0 ;; + *) echo "\$ac_cs_usage"; exit 1 ;; + esac +done + +ac_given_srcdir=$srcdir +ac_given_INSTALL="$INSTALL" + +trap 'rm -fr `echo "Makefile cconfig.h:config.in" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 +EOF +cat >> $CONFIG_STATUS < conftest.subs <<\\CEOF +$ac_vpsub +$extrasub +s%@sim_environment@%$sim_environment%g +s%@sim_alignment@%$sim_alignment%g +s%@sim_assert@%$sim_assert%g +s%@sim_bitsize@%$sim_bitsize%g +s%@sim_endian@%$sim_endian%g +s%@sim_hostendian@%$sim_hostendian%g +s%@sim_float@%$sim_float%g +s%@sim_scache@%$sim_scache%g +s%@sim_default_model@%$sim_default_model%g +s%@sim_hw_cflags@%$sim_hw_cflags%g +s%@sim_hw_objs@%$sim_hw_objs%g +s%@sim_hw@%$sim_hw%g +s%@sim_inline@%$sim_inline%g +s%@sim_packages@%$sim_packages%g +s%@sim_regparm@%$sim_regparm%g +s%@sim_reserved_bits@%$sim_reserved_bits%g +s%@sim_smp@%$sim_smp%g +s%@sim_stdcall@%$sim_stdcall%g +s%@sim_xor_endian@%$sim_xor_endian%g +s%@build_warnings@%$build_warnings%g +s%@SHELL@%$SHELL%g +s%@CFLAGS@%$CFLAGS%g +s%@CPPFLAGS@%$CPPFLAGS%g +s%@CXXFLAGS@%$CXXFLAGS%g +s%@DEFS@%$DEFS%g +s%@LDFLAGS@%$LDFLAGS%g +s%@LIBS@%$LIBS%g +s%@exec_prefix@%$exec_prefix%g +s%@prefix@%$prefix%g +s%@program_transform_name@%$program_transform_name%g +s%@bindir@%$bindir%g +s%@sbindir@%$sbindir%g +s%@libexecdir@%$libexecdir%g +s%@datadir@%$datadir%g +s%@sysconfdir@%$sysconfdir%g +s%@sharedstatedir@%$sharedstatedir%g +s%@localstatedir@%$localstatedir%g +s%@libdir@%$libdir%g +s%@includedir@%$includedir%g +s%@oldincludedir@%$oldincludedir%g +s%@infodir@%$infodir%g +s%@mandir@%$mandir%g +s%@host@%$host%g +s%@host_alias@%$host_alias%g +s%@host_cpu@%$host_cpu%g +s%@host_vendor@%$host_vendor%g +s%@host_os@%$host_os%g +s%@target@%$target%g +s%@target_alias@%$target_alias%g +s%@target_cpu@%$target_cpu%g +s%@target_vendor@%$target_vendor%g +s%@target_os@%$target_os%g +s%@build@%$build%g +s%@build_alias@%$build_alias%g +s%@build_cpu@%$build_cpu%g +s%@build_vendor@%$build_vendor%g +s%@build_os@%$build_os%g +s%@CC@%$CC%g +s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g +s%@INSTALL_DATA@%$INSTALL_DATA%g +s%@CC_FOR_BUILD@%$CC_FOR_BUILD%g +s%@HDEFINES@%$HDEFINES%g +s%@AR@%$AR%g +s%@RANLIB@%$RANLIB%g +s%@SET_MAKE@%$SET_MAKE%g +s%@CPP@%$CPP%g +s%@ALLOCA@%$ALLOCA%g +s%@USE_NLS@%$USE_NLS%g +s%@MSGFMT@%$MSGFMT%g +s%@GMSGFMT@%$GMSGFMT%g +s%@XGETTEXT@%$XGETTEXT%g +s%@USE_INCLUDED_LIBINTL@%$USE_INCLUDED_LIBINTL%g +s%@CATALOGS@%$CATALOGS%g +s%@CATOBJEXT@%$CATOBJEXT%g +s%@DATADIRNAME@%$DATADIRNAME%g +s%@GMOFILES@%$GMOFILES%g +s%@INSTOBJEXT@%$INSTOBJEXT%g +s%@INTLDEPS@%$INTLDEPS%g +s%@INTLLIBS@%$INTLLIBS%g +s%@INTLOBJS@%$INTLOBJS%g +s%@POFILES@%$POFILES%g +s%@POSUB@%$POSUB%g +s%@INCLUDE_LOCALE_H@%$INCLUDE_LOCALE_H%g +s%@GT_NO@%$GT_NO%g +s%@GT_YES@%$GT_YES%g +s%@MKINSTALLDIRS@%$MKINSTALLDIRS%g +s%@l@%$l%g +s%@MAINT@%$MAINT%g +s%@sim_bswap@%$sim_bswap%g +s%@sim_cflags@%$sim_cflags%g +s%@sim_debug@%$sim_debug%g +s%@sim_stdio@%$sim_stdio%g +s%@sim_trace@%$sim_trace%g +s%@sim_profile@%$sim_profile%g +s%@EXEEXT@%$EXEEXT%g +s%@CPP_FOR_TARGET@%$CPP_FOR_TARGET%g +s%@TARGET_SUBDIR@%$TARGET_SUBDIR%g + +CEOF +EOF + +cat >> $CONFIG_STATUS <<\EOF + +# Split the substitutions into bite-sized pieces for seds with +# small command number limits, like on Digital OSF/1 and HP-UX. +ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script. +ac_file=1 # Number of current file. +ac_beg=1 # First line for current file. +ac_end=$ac_max_sed_cmds # Line after last line for current file. +ac_more_lines=: +ac_sed_cmds="" +while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file + else + sed "${ac_end}q" conftest.subs > conftest.s$ac_file + fi + if test ! -s conftest.s$ac_file; then + ac_more_lines=false + rm -f conftest.s$ac_file + else + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f conftest.s$ac_file" + else + ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file" + fi + ac_file=`expr $ac_file + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_cmds` + fi +done +if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat +fi +EOF + +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories. + + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`" + # A "../" for each directory in $ac_dir_suffix. + ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'` + else + ac_dir_suffix= ac_dots= + fi + + case "$ac_given_srcdir" in + .) srcdir=. + if test -z "$ac_dots"; then top_srcdir=. + else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;; + /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;; + *) # Relative path. + srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix" + top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + + case "$ac_given_INSTALL" in + [/$]*) INSTALL="$ac_given_INSTALL" ;; + *) INSTALL="$ac_dots$ac_given_INSTALL" ;; + esac + + echo creating "$ac_file" + rm -f "$ac_file" + configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure." + case "$ac_file" in + *Makefile*) ac_comsub="1i\\ +# $configure_input" ;; + *) ac_comsub= ;; + esac + + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + sed -e "$ac_comsub +s%@configure_input@%$configure_input%g +s%@srcdir@%$srcdir%g +s%@top_srcdir@%$top_srcdir%g +s%@INSTALL@%$INSTALL%g +" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file +fi; done +rm -f conftest.s* + +# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where +# NAME is the cpp macro being defined and VALUE is the value it is being given. +# +# ac_d sets the value in "#define NAME VALUE" lines. +ac_dA='s%^\([ ]*\)#\([ ]*define[ ][ ]*\)' +ac_dB='\([ ][ ]*\)[^ ]*%\1#\2' +ac_dC='\3' +ac_dD='%g' +# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE". +ac_uA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_uB='\([ ]\)%\1#\2define\3' +ac_uC=' ' +ac_uD='\4%g' +# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE". +ac_eA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_eB='$%\1#\2define\3' +ac_eC=' ' +ac_eD='%g' + +if test "${CONFIG_HEADERS+set}" != set; then +EOF +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +fi +for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + echo creating $ac_file + + rm -f conftest.frag conftest.in conftest.out + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + cat $ac_file_inputs > conftest.in + +EOF + +# Transform confdefs.h into a sed script conftest.vals that substitutes +# the proper values into config.h.in to produce config.h. And first: +# Protect against being on the right side of a sed subst in config.status. +# Protect against being in an unquoted here document in config.status. +rm -f conftest.vals +cat > conftest.hdr <<\EOF +s/[\\&%]/\\&/g +s%[\\$`]%\\&%g +s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp +s%ac_d%ac_u%gp +s%ac_u%ac_e%gp +EOF +sed -n -f conftest.hdr confdefs.h > conftest.vals +rm -f conftest.hdr + +# This sed command replaces #undef with comments. This is necessary, for +# example, in the case of _POSIX_SOURCE, which is predefined and required +# on some systems where configure will not decide to define it. +cat >> conftest.vals <<\EOF +s%^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */% +EOF + +# Break up conftest.vals because some shells have a limit on +# the size of here documents, and old seds have small limits too. + +rm -f conftest.tail +while : +do + ac_lines=`grep -c . conftest.vals` + # grep -c gives empty output for an empty file on some AIX systems. + if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi + # Write a limited-size here document to conftest.frag. + echo ' cat > conftest.frag <> $CONFIG_STATUS + sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS + echo 'CEOF + sed -f conftest.frag conftest.in > conftest.out + rm -f conftest.in + mv conftest.out conftest.in +' >> $CONFIG_STATUS + sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail + rm -f conftest.vals + mv conftest.tail conftest.vals +done +rm -f conftest.vals + +cat >> $CONFIG_STATUS <<\EOF + rm -f conftest.frag conftest.h + echo "/* $ac_file. Generated automatically by configure. */" > conftest.h + cat conftest.in >> conftest.h + rm -f conftest.in + if cmp -s $ac_file conftest.h 2>/dev/null; then + echo "$ac_file is unchanged" + rm -f conftest.h + else + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + fi + rm -f $ac_file + mv conftest.h $ac_file + fi +fi; done + +EOF +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +case x$CONFIG_HEADERS in xcconfig.h:config.in) echo > stamp-h ;; esac +exit 0 +EOF +chmod +x $CONFIG_STATUS +rm -fr confdefs* $ac_clean_files +test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1 + diff --git a/sim/common/configure.in b/sim/common/configure.in new file mode 100644 index 00000000000..b8ea5382f54 --- /dev/null +++ b/sim/common/configure.in @@ -0,0 +1,40 @@ +dnl Process this file with autoconf to produce a configure script. +AC_PREREQ(2.5)dnl +AC_INIT(Makefile.in) + +# This is intended for use by the target specific directories, and by us. +SIM_AC_COMMON(cconfig.h) + +# Put a useful copy of CPP_FOR_TARGET in Makefile. +# This is only used to build the target values header files. These files are +# shipped with distributions so CPP_FOR_TARGET only needs to work in +# developer's trees. This value is borrowed from ../../Makefile.in. +CPP_FOR_TARGET="\` \ + if test -f \$\${rootme}/../../gcc/Makefile ; then \ + if test -f \$\${rootme}/../../\$(TARGET_SUBDIR)/newlib/Makefile ; then \ + echo \$\${rootme}/../../gcc/xgcc -B\$\${rootme}/../../gcc/ -idirafter \$\${rootme}/../../\$(TARGET_SUBDIR)/newlib/targ-include -idirafter \$(srcroot)/newlib/libc/include -nostdinc; \ + else \ + echo \$\${rootme}/../../gcc/xgcc -B\$\${rootme}/../../gcc/; \ + fi; \ + else \ + if test '\$(host_canonical)' = '\$(target_canonical)' ; then \ + echo \$(CC); \ + else \ + t='\$(program_transform_name)'; echo gcc | sed -e 's/x/x/' \$\$t; \ + fi; \ + fi\` -E" +AC_SUBST(CPP_FOR_TARGET) + +# Set TARGET_SUBDIR, needed by CPP_FOR_TARGET. +if test x"${host}" = x"${target}" ; then + TARGET_SUBDIR="." +else + TARGET_SUBDIR=${target_alias} +fi +AC_SUBST(TARGET_SUBDIR) + +# These aren't all needed yet, but will be eventually. +AC_CHECK_HEADERS(stdlib.h string.h strings.h time.h sys/times.h) + +AC_OUTPUT(Makefile, +[case x$CONFIG_HEADERS in xcconfig.h:config.in) echo > stamp-h ;; esac]) diff --git a/sim/common/dv-core.c b/sim/common/dv-core.c new file mode 100644 index 00000000000..1bf4f68b4ce --- /dev/null +++ b/sim/common/dv-core.c @@ -0,0 +1,118 @@ +/* This file is part of the program psim. + + Copyright (C) 1994-1996, Andrew Cagney + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + + +#include "sim-main.h" +#include "hw-main.h" + +/* DEVICE + + core - root of the device tree + + DESCRIPTION + + The core device, positioned at the root of the device tree appears + to its child devices as a normal device just like every other + device in the tree. + + Internally it is implemented using a core object. Requests to + attach (or detach) address spaces are passed to that core object. + Requests to transfer (DMA) data are reflected back down the device + tree using the core_map data transfer methods. + + PROPERTIES + + None. + + */ + + +static void +dv_core_attach_address_callback (struct hw *me, + int level, + int space, + address_word addr, + address_word nr_bytes, + struct hw *client) +{ + HW_TRACE ((me, "attach - level=%d, space=%d, addr=0x%lx, nr_bytes=%ld, client=%s", + level, space, (unsigned long) addr, (unsigned long) nr_bytes, hw_path (client))); + /* NOTE: At preset the space is assumed to be zero. Perhaphs the + space should be mapped onto something for instance: space0 - + unified memory; space1 - IO memory; ... */ + if (space != 0) + hw_abort (me, "Hey! Unknown space %d", space); + sim_core_attach (hw_system (me), + NULL, /*cpu*/ + level, + access_read_write_exec, + space, addr, + nr_bytes, + 0, /* modulo */ + client, + NULL); +} + + +static unsigned +dv_core_dma_read_buffer_callback (struct hw *me, + void *dest, + int space, + unsigned_word addr, + unsigned nr_bytes) +{ + return sim_core_read_buffer (hw_system (me), + NULL, /*CPU*/ + space, /*???*/ + dest, + addr, + nr_bytes); +} + + +static unsigned +dv_core_dma_write_buffer_callback (struct hw *me, + const void *source, + int space, + unsigned_word addr, + unsigned nr_bytes, + int violate_read_only_section) +{ + return sim_core_write_buffer (hw_system (me), + NULL, /*cpu*/ + space, /*???*/ + source, + addr, + nr_bytes); +} + + +static void +dv_core_finish (struct hw *me) +{ + set_hw_attach_address (me, dv_core_attach_address_callback); + set_hw_dma_write_buffer (me, dv_core_dma_write_buffer_callback); + set_hw_dma_read_buffer (me, dv_core_dma_read_buffer_callback); +} + +const struct hw_descriptor dv_core_descriptor[] = { + { "core", dv_core_finish, }, + { NULL }, +}; diff --git a/sim/common/dv-glue.c b/sim/common/dv-glue.c new file mode 100644 index 00000000000..a235531ae84 --- /dev/null +++ b/sim/common/dv-glue.c @@ -0,0 +1,373 @@ +/* This file is part of the program psim. + + Copyright (C) 1994-1996,1998 Andrew Cagney + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + + +#include "hw-main.h" + +#ifdef HAVE_STRING_H +#include +#else +#ifdef HAVE_STRINGS_H +#include +#endif +#endif + +/* DEVICE + + + glue - glue to interconnect and test hardware ports + + + DESCRIPTION + + + The glue device provides two functions. Firstly, it provides a + mechanism for inspecting and driving the port network. Secondly, + it provides a set of boolean primitives that can be used to apply + combinatorial operations to the port network. + + Glue devices have a variable number of big endian <> + registers. Each register is target-word sized. The registers can + be read and written. + + Writing to an output register results in an event being driven + (level determined by the value written) on the devices + corresponding output port. + + Reading an <> register returns either the last value + written or the most recently computed value (for that register) as + a result of an event ariving on that port (which ever was computed + last). + + At present the following sub device types are available: + + <>: In addition to driving its output interrupt port with any + value written to an interrupt input port is stored in the + corresponding <> register. Such input interrupts, however, + are not propogated to an output interrupt port. + + <>: The bit-wise AND of the interrupt inputs is computed + and then both stored in <> register zero and propogated to + output interrupt output port zero. + + + PROPERTIES + + + reg =
(required) + + Specify the address (within the parent bus) that this device is to + live. The address must be 2048 * sizeof (word) (8k in a 32bit + simulation) aligned. + + + interrupt-ranges = (optional) + + If present, this specifies the number of valid interrupt inputs (up + to the maximum of 2048). By default, <> is zero and + range is determined by the <> size. + + + PORTS + + + int[0..] (input, output) + + Both an input and an output port. + + + EXAMPLES + + + Enable tracing of the device: + + | -t glue-device \ + + + Create source, bitwize-and, and sink glue devices. Since the + device at address <<0x10000>> is of size <<8>> it will have two + output interrupt ports. + + | -o '/iobus@0xf0000000/glue@0x10000/reg 0x10000 8' \ + | -o '/iobus@0xf0000000/glue-and@0x20000/reg 0x20000 4' \ + | -o '/iobus@0xf0000000/glue-and/interrupt-ranges 0 2' \ + | -o '/iobus@0xf0000000/glue@0x30000/reg 0x30000 4' \ + + + Wire the two source interrupts to the AND device: + + | -o '/iobus@0xf0000000/glue@0x10000 > 0 0 /iobus/glue-and' \ + | -o '/iobus@0xf0000000/glue@0x10000 > 1 1 /iobus/glue-and' \ + + + Wire the AND device up to the sink so that the and's output is not + left open. + + | -o '/iobus@0xf0000000/glue-and > 0 0 /iobus/glue@0x30000' \ + + + With the above configuration. The client program is able to + compute a two bit AND. For instance the <> stub below prints 1 + AND 0. + + | unsigned *input = (void*)0xf0010000; + | unsigned *output = (void*)0xf0030000; + | unsigned ans; + | input[0] = htonl(1); + | input[1] = htonl(0); + | ans = ntohl(*output); + | write_string("AND is "); + | write_int(ans); + | write_line(); + + + BUGS + + + A future implementation of this device may support multiple + interrupt ranges. + + Some of the devices listed may not yet be fully implemented. + + Additional devices such as a D flip-flop (DFF), an inverter (INV) + or a latch (LAT) may prove useful. + + */ + + +enum { + max_nr_ports = 2048, +}; + +enum hw_glue_type { + glue_undefined = 0, + glue_io, + glue_and, + glue_nand, + glue_or, + glue_xor, + glue_nor, + glue_not, +}; + +struct hw_glue { + enum hw_glue_type type; + int int_number; + int *input; + int nr_inputs; + unsigned sizeof_input; + /* our output registers */ + int space; + unsigned_word address; + unsigned sizeof_output; + int *output; + int nr_outputs; +}; + + +static hw_io_read_buffer_method hw_glue_io_read_buffer; +static hw_io_write_buffer_method hw_glue_io_write_buffer; +static hw_port_event_method hw_glue_port_event; +const static struct hw_port_descriptor hw_glue_ports[]; + +static void +hw_glue_finish (struct hw *me) +{ + struct hw_glue *glue = HW_ZALLOC (me, struct hw_glue); + + /* establish our own methods */ + set_hw_data (me, glue); + set_hw_io_read_buffer (me, hw_glue_io_read_buffer); + set_hw_io_write_buffer (me, hw_glue_io_write_buffer); + set_hw_ports (me, hw_glue_ports); + set_hw_port_event (me, hw_glue_port_event); + + /* attach to our parent bus */ + do_hw_attach_regs (me); + + /* establish the output registers */ + { + reg_property_spec unit; + int reg_nr; + /* find a relevant reg entry */ + reg_nr = 0; + while (hw_find_reg_array_property (me, "reg", reg_nr, &unit) + && !hw_unit_size_to_attach_size (hw_parent (me), + &unit.size, + &glue->sizeof_output, + me)) + reg_nr++; + /* check out the size */ + if (glue->sizeof_output == 0) + hw_abort (me, "at least one reg property size must be nonzero"); + if (glue->sizeof_output % sizeof (unsigned_word) != 0) + hw_abort (me, "reg property size must be %d aligned", + sizeof (unsigned_word)); + /* and the address */ + hw_unit_address_to_attach_address (hw_parent (me), + &unit.address, + &glue->space, + &glue->address, + me); + if (glue->address % (sizeof (unsigned_word) * max_nr_ports) != 0) + hw_abort (me, "reg property address must be %d aligned", + sizeof (unsigned_word) * max_nr_ports); + glue->nr_outputs = glue->sizeof_output / sizeof (unsigned_word); + glue->output = hw_zalloc (me, glue->sizeof_output); + } + + /* establish the input ports */ + { + const struct hw_property *ranges; + ranges = hw_find_property (me, "interrupt-ranges"); + if (ranges == NULL) + { + glue->int_number = 0; + glue->nr_inputs = glue->nr_outputs; + } + else if (ranges->sizeof_array != sizeof (unsigned_cell) * 2) + { + hw_abort (me, "invalid interrupt-ranges property (incorrect size)"); + } + else + { + const unsigned_cell *int_range = ranges->array; + glue->int_number = BE2H_cell (int_range[0]); + glue->nr_inputs = BE2H_cell (int_range[1]); + } + glue->sizeof_input = glue->nr_inputs * sizeof (unsigned); + glue->input = hw_zalloc (me, glue->sizeof_input); + } + + /* determine our type */ + { + const char *name = hw_name(me); + if (strcmp (name, "glue") == 0) + glue->type = glue_io; + else if (strcmp (name, "glue-and") == 0) + glue->type = glue_and; + else + hw_abort (me, "unimplemented glue type"); + } + + HW_TRACE ((me, "int-number %d, nr_inputs %d, nr_outputs %d", + glue->int_number, glue->nr_inputs, glue->nr_outputs)); +} + +static unsigned +hw_glue_io_read_buffer (struct hw *me, + void *dest, + int space, + unsigned_word addr, + unsigned nr_bytes) +{ + struct hw_glue *glue = (struct hw_glue *) hw_data (me); + int reg = ((addr - glue->address) / sizeof (unsigned_word)) % glue->nr_outputs; + if (nr_bytes != sizeof (unsigned_word) + || (addr % sizeof (unsigned_word)) != 0) + hw_abort (me, "missaligned read access (%d:0x%lx:%d) not supported", + space, (unsigned long)addr, nr_bytes); + *(unsigned_word*)dest = H2BE_4(glue->output[reg]); + HW_TRACE ((me, "read - port %d (0x%lx), level %d", + reg, (unsigned long) addr, glue->output[reg])); + return nr_bytes; +} + + +static unsigned +hw_glue_io_write_buffer (struct hw *me, + const void *source, + int space, + unsigned_word addr, + unsigned nr_bytes) +{ + struct hw_glue *glue = (struct hw_glue *) hw_data (me); + int reg = ((addr - glue->address) / sizeof (unsigned_word)) % max_nr_ports; + if (nr_bytes != sizeof (unsigned_word) + || (addr % sizeof (unsigned_word)) != 0) + hw_abort (me, "missaligned write access (%d:0x%lx:%d) not supported", + space, (unsigned long) addr, nr_bytes); + glue->output[reg] = H2BE_4 (*(unsigned_word*)source); + HW_TRACE ((me, "write - port %d (0x%lx), level %d", + reg, (unsigned long) addr, glue->output[reg])); + hw_port_event (me, reg, glue->output[reg]); + return nr_bytes; +} + +static void +hw_glue_port_event (struct hw *me, + int my_port, + struct hw *source, + int source_port, + int level) +{ + struct hw_glue *glue = (struct hw_glue *) hw_data (me); + int i; + if (my_port < glue->int_number + || my_port >= glue->int_number + glue->nr_inputs) + hw_abort (me, "port %d outside of valid range", my_port); + glue->input[my_port - glue->int_number] = level; + switch (glue->type) + { + case glue_io: + { + int port = my_port % glue->nr_outputs; + glue->output[port] = level; + HW_TRACE ((me, "input - port %d (0x%lx), level %d", + my_port, + (unsigned long) glue->address + port * sizeof (unsigned_word), + level)); + break; + } + case glue_and: + { + glue->output[0] = glue->input[0]; + for (i = 1; i < glue->nr_inputs; i++) + glue->output[0] &= glue->input[i]; + HW_TRACE ((me, "and - port %d, level %d arrived - output %d", + my_port, level, glue->output[0])); + hw_port_event (me, 0, glue->output[0]); + break; + } + default: + { + hw_abort (me, "operator not implemented"); + break; + } + } +} + + +static const struct hw_port_descriptor hw_glue_ports[] = { + { "int", 0, max_nr_ports }, + { NULL } +}; + + +const struct hw_descriptor dv_glue_descriptor[] = { + { "glue", hw_glue_finish, }, + { "glue-and", hw_glue_finish, }, + { "glue-nand", hw_glue_finish, }, + { "glue-or", hw_glue_finish, }, + { "glue-xor", hw_glue_finish, }, + { "glue-nor", hw_glue_finish, }, + { "glue-not", hw_glue_finish, }, + { NULL }, +}; diff --git a/sim/common/dv-pal.c b/sim/common/dv-pal.c new file mode 100644 index 00000000000..421bde7e216 --- /dev/null +++ b/sim/common/dv-pal.c @@ -0,0 +1,605 @@ +/* This file is part of the program psim. + + Copyright (C) 1994-1996,1998, Andrew Cagney + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + + +#include "hw-main.h" +#include "sim-io.h" + +/* NOTE: pal is naughty and grubs around looking at things outside of + its immediate domain */ +#include "hw-tree.h" + +#ifdef HAVE_STRING_H +#include +#else +#ifdef HAVE_STRINGS_H +#include +#endif +#endif + +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif + +/* DEVICE + + + pal - glue logic device containing assorted junk + + + DESCRIPTION + + + Typical hardware dependant hack. This device allows the firmware + to gain access to all the things the firmware needs (but the OS + doesn't). + + The pal contains the following registers: + + |0 reset register (write, 8bit) + |4 processor id register (read, 8bit) + |8 interrupt register (8 - port, 9 - level) (write, 16bit) + |12 processor count register (read, 8bit) + + |16 tty input fifo register (read, 8bit) + |20 tty input status register (read, 8bit) + |24 tty output fifo register (write, 8bit) + |28 tty output status register (read, 8bit) + + |32 countdown register (read/write, 32bit, big-endian) + |36 countdown value register (read, 32bit, big-endian) + |40 timer register (read/write, 32bit, big-endian) + |44 timer value register (read, 32bit, big-endian) + + RESET (write): halts the simulator. The value written to the + register is used as an exit status. + + PROCESSOR ID (read): returns the processor identifier (0 .. N-1) of + the processor performing the read. + + INTERRUPT (write): This register must be written using a two byte + store. The low byte specifies a port and the upper byte specifies + the a level. LEVEL is driven on the specified port. By + convention, the pal's interrupt ports (int0, int1, ...) are wired + up to the corresponding processor's level sensative external + interrupt pin. Eg: A two byte write to address 8 of 0x0102 + (big-endian) will result in processor 2's external interrupt pin + being asserted. + + PROCESSOR COUNT (read): returns the total number of processors + active in the current simulation. + + TTY INPUT FIFO (read): if the TTY input status register indicates a + character is available by being nonzero, returns the next available + character from the pal's tty input port. + + TTY OUTPUT FIFO (write): if the TTY output status register + indicates the output fifo is not full by being nonzero, outputs the + character written to the tty's output port. + + COUNDOWN (read/write): The countdown registers provide a + non-repeating timed interrupt source. Writing a 32 bit big-endian + zero value to this register clears the countdown timer. Writing a + non-zero 32 bit big-endian value to this register sets the + countdown timer to expire in VALUE ticks (ticks is target + dependant). Reading the countdown register returns the last value + writen. + + COUNTDOWN VALUE (read): Reading this 32 bit big-endian register + returns the number of ticks remaining until the countdown timer + expires. + + TIMER (read/write): The timer registers provide a periodic timed + interrupt source. Writing a 32 bit big-endian zero value to this + register clears the periodic timer. Writing a 32 bit non-zero + value to this register sets the periodic timer to triger every + VALUE ticks (ticks is target dependant). Reading the timer + register returns the last value written. + + TIMER VALUE (read): Reading this 32 bit big-endian register returns + the number of ticks until the next periodic interrupt. + + + PROPERTIES + + + reg =
(required) + + Specify the address (within the parent bus) that this device is to + be located. + + poll? = + + If present and true, indicates that the device should poll its + input. + + + PORTS + + + int[0..NR_PROCESSORS] (output) + + Driven as a result of a write to the interrupt-port / + interrupt-level register pair. + + + countdown + + Driven whenever the countdown counter reaches zero. + + + timer + + Driven whenever the timer counter reaches zero. + + + BUGS + + + At present the common simulator framework does not support input + polling. + + */ + + +enum { + hw_pal_reset_register = 0x0, + hw_pal_cpu_nr_register = 0x4, + hw_pal_int_register = 0x8, + hw_pal_nr_cpu_register = 0xa, + hw_pal_read_fifo = 0x10, + hw_pal_read_status = 0x14, + hw_pal_write_fifo = 0x18, + hw_pal_write_status = 0x1a, + hw_pal_countdown = 0x20, + hw_pal_countdown_value = 0x24, + hw_pal_timer = 0x28, + hw_pal_timer_value = 0x2c, + hw_pal_address_mask = 0x3f, +}; + + +typedef struct _hw_pal_console_buffer { + char buffer; + int status; +} hw_pal_console_buffer; + +typedef struct _hw_pal_counter { + struct hw_event *handler; + signed64 start; + unsigned32 delta; + int periodic_p; +} hw_pal_counter; + + +typedef struct _hw_pal_device { + hw_pal_console_buffer input; + hw_pal_console_buffer output; + hw_pal_counter countdown; + hw_pal_counter timer; + struct hw *disk; + do_hw_poll_read_method *reader; +} hw_pal_device; + +enum { + COUNTDOWN_PORT, + TIMER_PORT, + INT_PORT, +}; + +static const struct hw_port_descriptor hw_pal_ports[] = { + { "countdown", COUNTDOWN_PORT, 0, output_port, }, + { "timer", TIMER_PORT, 0, output_port, }, + { "int", INT_PORT, MAX_NR_PROCESSORS, output_port, }, + { NULL } +}; + + +/* countdown and simple timer */ + +static void +do_counter_event (struct hw *me, + void *data) +{ + hw_pal_counter *counter = (hw_pal_counter *) data; + if (counter->periodic_p) + { + HW_TRACE ((me, "timer expired")); + counter->start = hw_event_queue_time (me); + hw_port_event (me, TIMER_PORT, 1); + hw_event_queue_schedule (me, counter->delta, do_counter_event, counter); + } + else + { + HW_TRACE ((me, "countdown expired")); + counter->delta = 0; + hw_port_event (me, COUNTDOWN_PORT, 1); + } +} + +static void +do_counter_read (struct hw *me, + hw_pal_device *pal, + const char *reg, + hw_pal_counter *counter, + unsigned32 *word, + unsigned nr_bytes) +{ + unsigned32 val; + if (nr_bytes != 4) + hw_abort (me, "%s - bad read size must be 4 bytes", reg); + val = counter->delta; + HW_TRACE ((me, "read - %s %ld", reg, (long) val)); + *word = H2BE_4 (val); +} + +static void +do_counter_value (struct hw *me, + hw_pal_device *pal, + const char *reg, + hw_pal_counter *counter, + unsigned32 *word, + unsigned nr_bytes) +{ + unsigned32 val; + if (nr_bytes != 4) + hw_abort (me, "%s - bad read size must be 4 bytes", reg); + if (counter->delta != 0) + val = (counter->start + counter->delta + - hw_event_queue_time (me)); + else + val = 0; + HW_TRACE ((me, "read - %s %ld", reg, (long) val)); + *word = H2BE_4 (val); +} + +static void +do_counter_write (struct hw *me, + hw_pal_device *pal, + const char *reg, + hw_pal_counter *counter, + const unsigned32 *word, + unsigned nr_bytes) +{ + if (nr_bytes != 4) + hw_abort (me, "%s - bad write size must be 4 bytes", reg); + if (counter->handler != NULL) + { + hw_event_queue_deschedule (me, counter->handler); + counter->handler = NULL; + } + counter->delta = BE2H_4 (*word); + counter->start = hw_event_queue_time (me); + HW_TRACE ((me, "write - %s %ld", reg, (long) counter->delta)); + if (counter->delta > 0) + hw_event_queue_schedule (me, counter->delta, do_counter_event, counter); +} + + + + +/* check the console for an available character */ +static void +scan_hw_pal (struct hw *me) +{ + hw_pal_device *hw_pal = (hw_pal_device *)hw_data (me); + char c; + int count; + count = do_hw_poll_read (me, hw_pal->reader, 0/*STDIN*/, &c, sizeof(c)); + switch (count) + { + case HW_IO_NOT_READY: + case HW_IO_EOF: + hw_pal->input.buffer = 0; + hw_pal->input.status = 0; + break; + default: + hw_pal->input.buffer = c; + hw_pal->input.status = 1; + } +} + +/* write the character to the hw_pal */ + +static void +write_hw_pal (struct hw *me, + char val) +{ + hw_pal_device *hw_pal = (hw_pal_device *) hw_data (me); + sim_io_write_stdout (hw_system (me), &val, 1); + hw_pal->output.buffer = val; + hw_pal->output.status = 1; +} + + +/* Reads/writes */ + +static unsigned +hw_pal_io_read_buffer (struct hw *me, + void *dest, + int space, + unsigned_word addr, + unsigned nr_bytes) +{ + hw_pal_device *hw_pal = (hw_pal_device *) hw_data (me); + unsigned_1 *byte = (unsigned_1 *) dest; + memset (dest, 0, nr_bytes); + switch (addr & hw_pal_address_mask) + { + + case hw_pal_cpu_nr_register: +#ifdef CPU_INDEX + *byte = CPU_INDEX (hw_system_cpu (me)); +#else + *byte = 0; +#endif + HW_TRACE ((me, "read - cpu-nr %d\n", *byte)); + break; + + case hw_pal_nr_cpu_register: + if (hw_tree_find_property (me, "/openprom/options/smp") == NULL) + { + *byte = 1; + HW_TRACE ((me, "read - nr-cpu %d (not defined)\n", *byte)); + } + else + { + *byte = hw_tree_find_integer_property (me, "/openprom/options/smp"); + HW_TRACE ((me, "read - nr-cpu %d\n", *byte)); + } + break; + + case hw_pal_read_fifo: + *byte = hw_pal->input.buffer; + HW_TRACE ((me, "read - input-fifo %d\n", *byte)); + break; + + case hw_pal_read_status: + scan_hw_pal (me); + *byte = hw_pal->input.status; + HW_TRACE ((me, "read - input-status %d\n", *byte)); + break; + + case hw_pal_write_fifo: + *byte = hw_pal->output.buffer; + HW_TRACE ((me, "read - output-fifo %d\n", *byte)); + break; + + case hw_pal_write_status: + *byte = hw_pal->output.status; + HW_TRACE ((me, "read - output-status %d\n", *byte)); + break; + + case hw_pal_countdown: + do_counter_read (me, hw_pal, "countdown", + &hw_pal->countdown, dest, nr_bytes); + break; + + case hw_pal_countdown_value: + do_counter_value (me, hw_pal, "countdown-value", + &hw_pal->countdown, dest, nr_bytes); + break; + + case hw_pal_timer: + do_counter_read (me, hw_pal, "timer", + &hw_pal->timer, dest, nr_bytes); + break; + + case hw_pal_timer_value: + do_counter_value (me, hw_pal, "timer-value", + &hw_pal->timer, dest, nr_bytes); + break; + + default: + HW_TRACE ((me, "read - ???\n")); + break; + + } + return nr_bytes; +} + + +static unsigned +hw_pal_io_write_buffer (struct hw *me, + const void *source, + int space, + unsigned_word addr, + unsigned nr_bytes) +{ + hw_pal_device *hw_pal = (hw_pal_device*) hw_data (me); + unsigned_1 *byte = (unsigned_1 *) source; + + switch (addr & hw_pal_address_mask) + { + + case hw_pal_reset_register: + hw_halt (me, sim_exited, byte[0]); + break; + + case hw_pal_int_register: + hw_port_event (me, + INT_PORT + byte[0], /*port*/ + (nr_bytes > 1 ? byte[1] : 0)); /* val */ + break; + + case hw_pal_read_fifo: + hw_pal->input.buffer = byte[0]; + HW_TRACE ((me, "write - input-fifo %d\n", byte[0])); + break; + + case hw_pal_read_status: + hw_pal->input.status = byte[0]; + HW_TRACE ((me, "write - input-status %d\n", byte[0])); + break; + + case hw_pal_write_fifo: + write_hw_pal (me, byte[0]); + HW_TRACE ((me, "write - output-fifo %d\n", byte[0])); + break; + + case hw_pal_write_status: + hw_pal->output.status = byte[0]; + HW_TRACE ((me, "write - output-status %d\n", byte[0])); + break; + + case hw_pal_countdown: + do_counter_write (me, hw_pal, "countdown", + &hw_pal->countdown, source, nr_bytes); + break; + + case hw_pal_timer: + do_counter_write (me, hw_pal, "timer", + &hw_pal->timer, source, nr_bytes); + break; + + } + return nr_bytes; +} + + +/* instances of the hw_pal struct hw */ + +#if NOT_YET +static void +hw_pal_instance_delete_callback(hw_instance *instance) +{ + /* nothing to delete, the hw_pal is attached to the struct hw */ + return; +} +#endif + +#if NOT_YET +static int +hw_pal_instance_read_callback (hw_instance *instance, + void *buf, + unsigned_word len) +{ + DITRACE (pal, ("read - %s (%ld)", (const char*) buf, (long int) len)); + return sim_io_read_stdin (buf, len); +} +#endif + +#if NOT_YET +static int +hw_pal_instance_write_callback (hw_instance *instance, + const void *buf, + unsigned_word len) +{ + int i; + const char *chp = buf; + hw_pal_device *hw_pal = hw_instance_data (instance); + DITRACE (pal, ("write - %s (%ld)", (const char*) buf, (long int) len)); + for (i = 0; i < len; i++) + write_hw_pal (hw_pal, chp[i]); + sim_io_flush_stdoutput (); + return i; +} +#endif + +#if NOT_YET +static const hw_instance_callbacks hw_pal_instance_callbacks = { + hw_pal_instance_delete_callback, + hw_pal_instance_read_callback, + hw_pal_instance_write_callback, +}; +#endif + +#if 0 +static hw_instance * +hw_pal_create_instance (struct hw *me, + const char *path, + const char *args) +{ + return hw_create_instance_from (me, NULL, + hw_data (me), + path, args, + &hw_pal_instance_callbacks); +} +#endif + + +static void +hw_pal_attach_address (struct hw *me, + int level, + int space, + address_word addr, + address_word nr_bytes, + struct hw *client) +{ + hw_pal_device *pal = (hw_pal_device*) hw_data (me); + pal->disk = client; +} + + +#if 0 +static hw_callbacks const hw_pal_callbacks = { + { generic_hw_init_address, }, + { hw_pal_attach_address, }, /* address */ + { hw_pal_io_read_buffer_callback, + hw_pal_io_write_buffer_callback, }, + { NULL, }, /* DMA */ + { NULL, NULL, hw_pal_interrupt_ports }, /* interrupt */ + { generic_hw_unit_decode, + generic_hw_unit_encode, + generic_hw_address_to_attach_address, + generic_hw_size_to_attach_size }, + hw_pal_create_instance, +}; +#endif + + +static void +hw_pal_finish (struct hw *hw) +{ + /* create the descriptor */ + hw_pal_device *hw_pal = HW_ZALLOC (hw, hw_pal_device); + hw_pal->output.status = 1; + hw_pal->output.buffer = '\0'; + hw_pal->input.status = 0; + hw_pal->input.buffer = '\0'; + set_hw_data (hw, hw_pal); + set_hw_attach_address (hw, hw_pal_attach_address); + set_hw_io_read_buffer (hw, hw_pal_io_read_buffer); + set_hw_io_write_buffer (hw, hw_pal_io_write_buffer); + set_hw_ports (hw, hw_pal_ports); + /* attach ourselves */ + do_hw_attach_regs (hw); + /* If so configured, enable polled input */ + if (hw_find_property (hw, "poll?") != NULL + && hw_find_boolean_property (hw, "poll?")) + { + hw_pal->reader = sim_io_poll_read; + } + else + { + hw_pal->reader = sim_io_read; + } + /* tag the periodic timer */ + hw_pal->timer.periodic_p = 1; +} + + +const struct hw_descriptor dv_pal_descriptor[] = { + { "pal", hw_pal_finish, }, + { NULL }, +}; diff --git a/sim/common/dv-sockser.c b/sim/common/dv-sockser.c new file mode 100644 index 00000000000..c95288ca775 --- /dev/null +++ b/sim/common/dv-sockser.c @@ -0,0 +1,386 @@ +/* Serial port emulation using sockets. + Copyright (C) 1998 Free Software Foundation, Inc. + Contributed by Cygnus Solutions. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* FIXME: will obviously need to evolve. + - connectionless sockets might be more appropriate. */ + +#include "sim-main.h" + +#ifdef HAVE_STRING_H +#include +#else +#ifdef HAVE_STRINGS_H +#include +#endif +#endif +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_FCNTL_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include + +#ifndef __CYGWIN32__ +#include +#endif + +#include "sim-assert.h" +#include "sim-options.h" + +#include "dv-sockser.h" + +/* Get definitions for both O_NONBLOCK and O_NDELAY. */ + +#ifndef O_NDELAY +#ifdef FNDELAY +#define O_NDELAY FNDELAY +#else /* ! defined (FNDELAY) */ +#define O_NDELAY 0 +#endif /* ! defined (FNDELAY) */ +#endif /* ! defined (O_NDELAY) */ + +#ifndef O_NONBLOCK +#ifdef FNBLOCK +#define O_NONBLOCK FNBLOCK +#else /* ! defined (FNBLOCK) */ +#define O_NONBLOCK 0 +#endif /* ! defined (FNBLOCK) */ +#endif /* ! defined (O_NONBLOCK) */ + +#define MIN(a,b) ((a) < (b) ? (a) : (b)) + +/* Compromise between eating cpu and properly busy-waiting. + One could have an option to set this but for now that seems + like featuritis. */ +#define DEFAULT_TIMEOUT 1000 /* microseconds */ + +/* FIXME: These should allocated at run time and kept with other simulator + state (duh...). Later. */ +const char * sockser_addr = NULL; +/* Timeout in microseconds during status flag computation. + Setting this to zero achieves proper busy wait semantics but eats cpu. */ +static unsigned int sockser_timeout = DEFAULT_TIMEOUT; +static int sockser_listen_fd = -1; +static int sockser_fd = -1; + +/* FIXME: use tree properties when they're ready. */ + +typedef enum { + OPTION_ADDR = OPTION_START +} SOCKSER_OPTIONS; + +static DECLARE_OPTION_HANDLER (sockser_option_handler); + +static const OPTION sockser_options[] = +{ + { { "sockser-addr", required_argument, NULL, OPTION_ADDR }, + '\0', "SOCKET ADDRESS", "Set serial emulation socket address", + sockser_option_handler }, + { { NULL, no_argument, NULL, 0 }, '\0', NULL, NULL, NULL } +}; + +static SIM_RC +sockser_option_handler (SIM_DESC sd, sim_cpu *cpu, int opt, + char *arg, int is_command) +{ + switch (opt) + { + case OPTION_ADDR : + sockser_addr = arg; + break; + } + + return SIM_RC_OK; +} + +static SIM_RC +dv_sockser_init (SIM_DESC sd) +{ + struct hostent *hostent; + struct sockaddr_in sockaddr; + char hostname[100]; + const char *port_str; + int tmp,port; + + if (STATE_ENVIRONMENT (sd) != OPERATING_ENVIRONMENT + || sockser_addr == NULL) + return SIM_RC_OK; + + if (*sockser_addr == '/') + { + /* support for these can come later */ + sim_io_eprintf (sd, "sockser init: unix domain sockets not supported: `%s'\n", + sockser_addr); + return SIM_RC_FAIL; + } + + port_str = strchr (sockser_addr, ':'); + if (!port_str) + { + sim_io_eprintf (sd, "sockser init: missing port number: `%s'\n", + sockser_addr); + return SIM_RC_FAIL; + } + tmp = MIN (port_str - sockser_addr, (int) sizeof hostname - 1); + strncpy (hostname, sockser_addr, tmp); + hostname[tmp] = '\000'; + port = atoi (port_str + 1); + + hostent = gethostbyname (hostname); + if (! hostent) + { + sim_io_eprintf (sd, "sockser init: unknown host: %s\n", + hostname); + return SIM_RC_FAIL; + } + + sockser_listen_fd = socket (PF_INET, SOCK_STREAM, 0); + if (sockser_listen_fd < 0) + { + sim_io_eprintf (sd, "sockser init: unable to get socket: %s\n", + strerror (errno)); + return SIM_RC_FAIL; + } + + sockaddr.sin_family = PF_INET; + sockaddr.sin_port = htons(port); + memcpy (&sockaddr.sin_addr.s_addr, hostent->h_addr, + sizeof (struct in_addr)); + + tmp = 1; + if (setsockopt (sockser_listen_fd, SOL_SOCKET, SO_REUSEADDR, (void*)& tmp, sizeof(tmp)) < 0) + { + sim_io_eprintf (sd, "sockser init: unable to set SO_REUSEADDR: %s\n", + strerror (errno)); + } + if (bind (sockser_listen_fd, (struct sockaddr *) &sockaddr, sizeof (sockaddr)) < 0) + { + sim_io_eprintf (sd, "sockser init: unable to bind socket address: %s\n", + strerror (errno)); + close (sockser_listen_fd); + sockser_listen_fd = -1; + return SIM_RC_FAIL; + } + if (listen (sockser_listen_fd, 1) < 0) + { + sim_io_eprintf (sd, "sockser init: unable to set up listener: %s\n", + strerror (errno)); + close (sockser_listen_fd); + sockser_listen_fd = -1; + return SIM_RC_OK; + } + + /* Handle writes to missing client -> SIGPIPE. + ??? Need a central signal management module. */ + { + RETSIGTYPE (*orig) (); + orig = signal (SIGPIPE, SIG_IGN); + /* If a handler is already set up, don't mess with it. */ + if (orig != SIG_DFL && orig != SIG_IGN) + signal (SIGPIPE, orig); + } + + return SIM_RC_OK; +} + +static void +dv_sockser_uninstall (SIM_DESC sd) +{ + if (sockser_listen_fd != -1) + { + close (sockser_listen_fd); + sockser_listen_fd = -1; + } + if (sockser_fd != -1) + { + close (sockser_fd); + sockser_fd = -1; + } +} + +SIM_RC +dv_sockser_install (SIM_DESC sd) +{ + SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); + if (sim_add_option_table (sd, NULL, sockser_options) != SIM_RC_OK) + return SIM_RC_FAIL; + sim_module_add_init_fn (sd, dv_sockser_init); + sim_module_add_uninstall_fn (sd, dv_sockser_uninstall); + return SIM_RC_OK; +} + +static int +connected_p (SIM_DESC sd) +{ + int numfds,flags; + struct timeval tv; + fd_set readfds; + struct sockaddr sockaddr; + int addrlen; + + if (sockser_listen_fd == -1) + return 0; + + if (sockser_fd >= 0) + { + /* FIXME: has client gone away? */ + return 1; + } + + /* Not connected. Connect with a client if there is one. */ + + FD_ZERO (&readfds); + FD_SET (sockser_listen_fd, &readfds); + + /* ??? One can certainly argue this should be done differently, + but for now this is sufficient. */ + tv.tv_sec = 0; + tv.tv_usec = sockser_timeout; + + numfds = select (sockser_listen_fd + 1, &readfds, 0, 0, &tv); + if (numfds <= 0) + return 0; + + sockser_fd = accept (sockser_listen_fd, &sockaddr, &addrlen); + if (sockser_fd < 0) + return 0; + + /* Set non-blocking i/o. */ + flags = fcntl (sockser_fd, F_GETFL); + flags |= O_NONBLOCK | O_NDELAY; + if (fcntl (sockser_fd, F_SETFL, flags) == -1) + { + sim_io_eprintf (sd, "unable to set nonblocking i/o"); + close (sockser_fd); + sockser_fd = -1; + return 0; + } + return 1; +} + +int +dv_sockser_status (SIM_DESC sd) +{ + int numrfds,numwfds,status; + struct timeval tv; + fd_set readfds,writefds; + + /* status to return if the socket isn't set up, or select fails */ + status = DV_SOCKSER_INPUT_EMPTY | DV_SOCKSER_OUTPUT_EMPTY; + + if (! connected_p (sd)) + return status; + + FD_ZERO (&readfds); + FD_ZERO (&writefds); + FD_SET (sockser_fd, &readfds); + FD_SET (sockser_fd, &writefds); + + /* ??? One can certainly argue this should be done differently, + but for now this is sufficient. The read is done separately + from the write to enforce the delay which we heuristically set to + once every SOCKSER_TIMEOUT_FREQ tries. + No, this isn't great for SMP situations, blah blah blah. */ + + { + static int n; +#define SOCKSER_TIMEOUT_FREQ 42 + if (++n == SOCKSER_TIMEOUT_FREQ) + n = 0; + if (n == 0) + { + tv.tv_sec = 0; + tv.tv_usec = sockser_timeout; + numrfds = select (sockser_fd + 1, &readfds, 0, 0, &tv); + tv.tv_sec = 0; + tv.tv_usec = 0; + numwfds = select (sockser_fd + 1, 0, &writefds, 0, &tv); + } + else /* do both selects at once */ + { + tv.tv_sec = 0; + tv.tv_usec = 0; + numrfds = numwfds = select (sockser_fd + 1, &readfds, &writefds, 0, &tv); + } + } + + status = 0; + if (numrfds <= 0 || ! FD_ISSET (sockser_fd, &readfds)) + status |= DV_SOCKSER_INPUT_EMPTY; + if (numwfds <= 0 || FD_ISSET (sockser_fd, &writefds)) + status |= DV_SOCKSER_OUTPUT_EMPTY; + return status; +} + +int +dv_sockser_write (SIM_DESC sd, unsigned char c) +{ + int n; + + if (! connected_p (sd)) + return -1; + n = write (sockser_fd, &c, 1); + if (n == -1) + { + if (errno == EPIPE) + { + close (sockser_fd); + sockser_fd = -1; + } + return -1; + } + if (n != 1) + return -1; + return 1; +} + +int +dv_sockser_read (SIM_DESC sd) +{ + unsigned char c; + int n; + + if (! connected_p (sd)) + return -1; + n = read (sockser_fd, &c, 1); + /* ??? We're assuming semantics that may not be correct for all hosts. + In particular (from cvssrc/src/server.c), this assumes that we are using + BSD or POSIX nonblocking I/O. System V nonblocking I/O returns zero if + there is nothing to read. */ + if (n == 0) + { + close (sockser_fd); + sockser_fd = -1; + return -1; + } + if (n != 1) + return -1; + return c; +} diff --git a/sim/common/dv-sockser.h b/sim/common/dv-sockser.h new file mode 100644 index 00000000000..ef0a7a9973a --- /dev/null +++ b/sim/common/dv-sockser.h @@ -0,0 +1,32 @@ +/* Serial port emulation via sockets. + Copyright (C) 1998, Free Software Foundation, Inc. + +This file is part of the GNU simulators. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef DV_SOCKSER_H +#define DV_SOCKSER_H + +/* bits in result of dev_sockser_status */ +#define DV_SOCKSER_INPUT_EMPTY 1 +#define DV_SOCKSER_OUTPUT_EMPTY 2 + +/* FIXME: later add a device ptr arg */ +extern int dv_sockser_status (SIM_DESC); +int dv_sockser_write (SIM_DESC, unsigned char); +int dv_sockser_read (SIM_DESC); + +#endif /* DV_SOCKSER_H */ diff --git a/sim/common/gdbinit.in b/sim/common/gdbinit.in new file mode 100644 index 00000000000..ddda344a2e3 --- /dev/null +++ b/sim/common/gdbinit.in @@ -0,0 +1,10 @@ +break sim_io_error + +define dump +set sim_debug_dump () +end + +document dump +Dump cpu and simulator registers for debugging the simulator. +Requires the simulator to provide function sim_debug_dump. +end diff --git a/sim/common/genmloop.sh b/sim/common/genmloop.sh new file mode 100644 index 00000000000..865fe7242f5 --- /dev/null +++ b/sim/common/genmloop.sh @@ -0,0 +1,1122 @@ +# Generate the main loop of the simulator. +# Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc. +# Contributed by Cygnus Support. +# +# This file is part of the GNU simulators. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# This file creates two files: eng.hin and mloop.cin. +# eng.hin defines a few macros that specify what kind of engine was selected +# based on the arguments to this script. +# mloop.cin contains the engine. +# +# ??? Rename mloop.c to eng.c? +# ??? Rename mainloop.in to engine.in? +# ??? Add options to specify output file names? +# ??? Rename this file to genengine.sh? +# +# Syntax: genmloop.sh [options] +# +# Options: +# +# -mono | -multi +# - specify single cpu or multiple cpus (number specifyable at runtime), +# maximum number is a configuration parameter +# - -multi wip +# +# -fast: include support for fast execution in addition to full featured mode +# +# Full featured mode is for tracing, profiling, etc. and is always +# provided. Fast mode contains no frills, except speed. +# A target need only provide a "full" version of one of +# simple,scache,pbb. If the target wants it can also provide a fast +# version of same. It can't provide more than this. +# ??? Later add ability to have another set of full/fast semantics +# for use in with-devices/with-smp situations (pbb can be inappropriate +# here). +# +# -full-switch: same as -fast but for full featured version of -switch +# Only needed if -fast present. +# +# -simple: simple execution engine (the default) +# +# This engine fetches and executes one instruction at a time. +# Field extraction is done in the semantic routines. +# +# ??? There are two possible flavours of -simple. One that extracts +# fields in the semantic routine (which is what is implemented here), +# and one that stores the extracted fields in ARGBUF before calling the +# semantic routine. The latter is essentially the -scache case with a +# cache size of one (and the scache lookup code removed). There are no +# current uses of this and it's not clear when doing this would be a win. +# More complicated ISA's that want to use -simple may find this a win. +# Should this ever be desirable, implement a new engine style here and +# call it -extract (or some such). It's believed that the CGEN-generated +# code for the -scache case would be usable here, so no new code +# generation option would be needed for CGEN. +# +# -scache: use the scache to speed things up (not always a win) +# +# This engine caches the extracted instruction before executing it. +# When executing instructions they are first looked up in the scache. +# +# -pbb: same as -scache but extract a (pseudo-) basic block at a time +# +# This engine is basically identical to the scache version except that +# extraction is done a pseudo-basic-block at a time and the address of +# the scache entry of a branch target is recorded as well. +# Additional speedups are then possible by defering Ctrl-C checking +# to the end of basic blocks and by threading the insns together. +# We call them pseudo-basic-block's instead of just basic-blocks because +# they're not necessarily basic-blocks, though normally are. +# +# -parallel-read: support parallel execution with read-before-exec support. +# -parallel-write: support parallel execution with write-after-exec support. +# +# One of these options is specified in addition to -simple, -scache, +# -pbb. Note that while the code can determine if the cpu supports +# parallel execution with HAVE_PARALLEL_INSNS [and thus this option is +# technically unnecessary], having this option cuts down on the clutter +# in the result. +# +# -switch file: specify file containing semantics implemented as a switch() +# +# -cpu +# +# Specify the cpu family name. +# +# -infile +# +# Specify the mainloop.in input file. +# +# Only one of -scache/-pbb may be selected. +# -simple is the default. +# +#### +# +# TODO +# - build mainloop.in from .cpu file + +type=mono +#scache= +#fast= +#full_switch= +#pbb= +parallel=no +switch= +cpu="unknown" +infile="" + +while test $# -gt 0 +do + case $1 in + -mono) type=mono ;; + -multi) type=multi ;; + -no-fast) ;; + -fast) fast=yes ;; + -full-switch) full_switch=yes ;; + -simple) ;; + -scache) scache=yes ;; + -pbb) pbb=yes ;; + -no-parallel) ;; + -parallel-read) parallel=read ;; + -parallel-write) parallel=write ;; + -switch) shift ; switch=$1 ;; + -cpu) shift ; cpu=$1 ;; + -infile) shift ; infile=$1 ;; + *) echo "unknown option: $1" >&2 ; exit 1 ;; + esac + shift +done + +# Argument validation. + +if [ x$scache = xyes -a x$pbb = xyes ] ; then + echo "only one of -scache and -pbb may be selected" >&2 + exit 1 +fi + +if [ "x$cpu" = xunknown ] ; then + echo "cpu family not specified" >&2 + exit 1 +fi + +if [ "x$infile" = x ] ; then + echo "mainloop.in not specified" >&2 + exit 1 +fi + +lowercase='abcdefghijklmnopqrstuvwxyz' +uppercase='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +CPU=`echo ${cpu} | tr "${lowercase}" "${uppercase}"` + +########################################################################## + +rm -f eng.hin +exec 1>eng.hin + +echo "/* engine configuration for ${cpu} */" +echo "" + +echo "/* WITH_FAST: non-zero if a fast version of the engine is available" +echo " in addition to the full-featured version. */" +if [ x$fast = xyes ] ; then + echo "#define WITH_FAST 1" +else + echo "#define WITH_FAST 0" +fi + +echo "" +echo "/* WITH_SCACHE_PBB_${CPU}: non-zero if the pbb engine was selected. */" +if [ x$pbb = xyes ] ; then + echo "#define WITH_SCACHE_PBB_${CPU} 1" +else + echo "#define WITH_SCACHE_PBB_${CPU} 0" +fi + +echo "" +echo "/* HAVE_PARALLEL_INSNS: non-zero if cpu can parallelly execute > 1 insn. */" +if [ x$parallel != xno ] ; then + echo "#define HAVE_PARALLEL_INSNS 1" + if [ x$parallel = xread ] ; then + echo "/* Parallel execution is supported by read-before-exec. */" + echo "#define WITH_PARALLEL_READ 1" + echo "#define WITH_PARALLEL_WRITE 0" + else + echo "/* Parallel execution is supported by write-after-exec. */" + echo "#define WITH_PARALLEL_READ 0" + echo "#define WITH_PARALLEL_WRITE 1" + fi +else + echo "#define HAVE_PARALLEL_INSNS 0" + echo "#define WITH_PARALLEL_READ 0" + echo "#define WITH_PARALLEL_WRITE 0" +fi + +if [ "x$switch" != x ] ; then + echo "" + echo "/* WITH_SEM_SWITCH_FULL: non-zero if full-featured engine is" + echo " implemented as a switch(). */" + if [ x$fast != xyes -o x$full_switch = xyes ] ; then + echo "#define WITH_SEM_SWITCH_FULL 1" + else + echo "#define WITH_SEM_SWITCH_FULL 0" + fi + echo "" + echo "/* WITH_SEM_SWITCH_FAST: non-zero if fast engine is" + echo " implemented as a switch(). */" + if [ x$fast = xyes ] ; then + echo "#define WITH_SEM_SWITCH_FAST 1" + else + echo "#define WITH_SEM_SWITCH_FAST 0" + fi +fi + +# Decls of functions we define. + +echo "" +echo "/* Functions defined in the generated mainloop.c file" +echo " (which doesn't necessarily have that file name). */" +echo "" +echo "extern ENGINE_FN ${cpu}_engine_run_full;" +echo "extern ENGINE_FN ${cpu}_engine_run_fast;" + +if [ x$pbb = xyes ] ; then + echo "" + echo "extern SEM_PC ${cpu}_pbb_begin (SIM_CPU *, int);" + echo "extern SEM_PC ${cpu}_pbb_chain (SIM_CPU *, SEM_ARG);" + echo "extern SEM_PC ${cpu}_pbb_cti_chain (SIM_CPU *, SEM_ARG, SEM_PC *, PCADDR);" + echo "extern void ${cpu}_pbb_before (SIM_CPU *, SCACHE *);" + echo "extern void ${cpu}_pbb_after (SIM_CPU *, SCACHE *);" +fi + +########################################################################## + +rm -f tmp-mloop.cin mloop.cin +exec 1>tmp-mloop.cin + +# We use @cpu@ instead of ${cpu} because we still need to run sed to handle +# transformation of @cpu@ for mainloop.in, so there's no need to use ${cpu} +# here. + +cat << EOF +/* This file is generated by the genmloop script. DO NOT EDIT! */ + +/* Enable switch() support in cgen headers. */ +#define SEM_IN_SWITCH + +#define WANT_CPU @cpu@ +#define WANT_CPU_@CPU@ + +#include "sim-main.h" +#include "bfd.h" +#include "cgen-mem.h" +#include "cgen-ops.h" +#include "sim-assert.h" + +/* Fill in the administrative ARGBUF fields required by all insns, + virtual and real. */ + +static INLINE void +@cpu@_fill_argbuf (const SIM_CPU *cpu, ARGBUF *abuf, const IDESC *idesc, + PCADDR pc, int fast_p) +{ +#if WITH_SCACHE + SEM_SET_CODE (abuf, idesc, fast_p); + ARGBUF_ADDR (abuf) = pc; +#endif + ARGBUF_IDESC (abuf) = idesc; +} + +/* Fill in tracing/profiling fields of an ARGBUF. */ + +static INLINE void +@cpu@_fill_argbuf_tp (const SIM_CPU *cpu, ARGBUF *abuf, + int trace_p, int profile_p) +{ + ARGBUF_TRACE_P (abuf) = trace_p; + ARGBUF_PROFILE_P (abuf) = profile_p; +} + +#if WITH_SCACHE_PBB + +/* Emit the "x-before" handler. + x-before is emitted before each insn (serial or parallel). + This is as opposed to x-after which is only emitted at the end of a group + of parallel insns. */ + +static INLINE void +@cpu@_emit_before (SIM_CPU *current_cpu, SCACHE *sc, PCADDR pc, int first_p) +{ + ARGBUF *abuf = &sc[0].argbuf; + const IDESC *id = & CPU_IDESC (current_cpu) [@CPU@_INSN_X_BEFORE]; + + abuf->fields.before.first_p = first_p; + @cpu@_fill_argbuf (current_cpu, abuf, id, pc, 0); + /* no need to set trace_p,profile_p */ +} + +/* Emit the "x-after" handler. + x-after is emitted after a serial insn or at the end of a group of + parallel insns. */ + +static INLINE void +@cpu@_emit_after (SIM_CPU *current_cpu, SCACHE *sc, PCADDR pc) +{ + ARGBUF *abuf = &sc[0].argbuf; + const IDESC *id = & CPU_IDESC (current_cpu) [@CPU@_INSN_X_AFTER]; + + @cpu@_fill_argbuf (current_cpu, abuf, id, pc, 0); + /* no need to set trace_p,profile_p */ +} + +#endif /* WITH_SCACHE_PBB */ + +EOF + +${SHELL} $infile support + +########################################################################## + +# Simple engine: fetch an instruction, execute the instruction. +# +# Instruction fields are not extracted into ARGBUF, they are extracted in +# the semantic routines themselves. However, there is still a need to pass +# and return misc. information to the semantic routines so we still use ARGBUF. +# [One could certainly implement things differently and remove ARGBUF. +# It's not clear this is necessarily always a win.] +# ??? The use of the SCACHE struct is for consistency with the with-scache +# case though it might be a source of confusion. + +if [ x$scache != xyes -a x$pbb != xyes ] ; then + + cat << EOF + +#define FAST_P 0 + +void +@cpu@_engine_run_full (SIM_CPU *current_cpu) +{ +#define FAST_P 0 + SIM_DESC current_state = CPU_STATE (current_cpu); + /* ??? Use of SCACHE is a bit of a hack as we don't actually use the scache. + We do however use ARGBUF so for consistency with the other engine flavours + the SCACHE type is used. */ + SCACHE cache[MAX_LIW_INSNS]; + SCACHE *sc = &cache[0]; + +EOF + +if [ x$parallel != xno ] ; then + cat << EOF + PAREXEC pbufs[MAX_PARALLEL_INSNS]; + PAREXEC *par_exec; + +EOF +fi + +# Any initialization code before looping starts. +# Note that this code may declare some locals. +${SHELL} $infile init + +if [ x$parallel != xno ] ; then + cat << EOF + +#if defined (HAVE_PARALLEL_EXEC) && defined (__GNUC__) + { + if (! CPU_IDESC_READ_INIT_P (current_cpu)) + { +/* ??? Later maybe paste read.c in when building mainloop.c. */ +#define DEFINE_LABELS +#include "readx.c" + CPU_IDESC_READ_INIT_P (current_cpu) = 1; + } + } +#endif + +EOF +fi + +cat << EOF + +#if WITH_SEM_SWITCH_FULL && defined (__GNUC__) + { + if (! CPU_IDESC_SEM_INIT_P (current_cpu)) + { +/* ??? Later maybe paste sem-switch.c in when building mainloop.c. */ +#define DEFINE_LABELS +#include "$switch" + CPU_IDESC_SEM_INIT_P (current_cpu) = 1; + } + } +#endif + + do + { +/* begin full-exec-simple */ +EOF + +${SHELL} $infile full-exec-simple + +cat << EOF +/* end full-exec-simple */ + + ++ CPU_INSN_COUNT (current_cpu); + } + while (0 /*CPU_RUNNING_P (current_cpu)*/); +} + +#undef FAST_P + +EOF + +#################################### + +# Simple engine: fast version. +# ??? A somewhat dubious effort, but for completeness' sake. + +if [ x$fast = xyes ] ; then + + cat << EOF + +#define FAST_P 1 + +FIXME: "fast simple version unimplemented, delete -fast arg to genmloop.sh." + +#undef FAST_P + +EOF + +fi # -fast + +fi # simple engine + +########################################################################## + +# Scache engine: lookup insn in scache, fetch if missing, then execute it. + +if [ x$scache = xyes ] ; then + + cat << EOF + +static INLINE SCACHE * +@cpu@_scache_lookup (SIM_CPU *current_cpu, PCADDR vpc, SCACHE *scache, + unsigned int hash_mask, int FAST_P) +{ + /* First step: look up current insn in hash table. */ + SCACHE *sc = scache + SCACHE_HASH_PC (vpc, hash_mask); + + /* If the entry isn't the one we want (cache miss), + fetch and decode the instruction. */ + if (sc->argbuf.addr != vpc) + { + insn_t insn; + + if (FAST_P) + PROFILE_COUNT_SCACHE_MISS (current_cpu); + +/* begin extract-scache */ +EOF + +${SHELL} $infile extract-scache + +cat << EOF +/* end extract-scache */ + } + else if (FAST_P) + { + PROFILE_COUNT_SCACHE_HIT (current_cpu); + /* Make core access statistics come out right. + The size is a guess, but it's currently not used either. */ + PROFILE_COUNT_CORE (current_cpu, vpc, 2, exec_map); + } + + return sc; +} + +#define FAST_P 0 + +void +@cpu@_engine_run_full (SIM_CPU *current_cpu) +{ + SIM_DESC current_state = CPU_STATE (current_cpu); + SCACHE *scache = CPU_SCACHE_CACHE (current_cpu); + unsigned int hash_mask = CPU_SCACHE_HASH_MASK (current_cpu); + SEM_PC vpc; + +EOF + +if [ x$parallel != xno ] ; then + cat << EOF + PAREXEC pbufs[MAX_PARALLEL_INSNS]; + PAREXEC *par_exec; + +EOF +fi + +# Any initialization code before looping starts. +# Note that this code may declare some locals. +${SHELL} $infile init + +if [ x$parallel != xno ] ; then + cat << EOF + +#if defined (HAVE_PARALLEL_EXEC) && defined (__GNUC__) + { + if (! CPU_IDESC_READ_INIT_P (current_cpu)) + { +/* ??? Later maybe paste read.c in when building mainloop.c. */ +#define DEFINE_LABELS +#include "readx.c" + CPU_IDESC_READ_INIT_P (current_cpu) = 1; + } + } +#endif + +EOF +fi + +cat << EOF + + vpc = GET_H_PC (); + + do + { + SCACHE *sc; + + sc = @cpu@_scache_lookup (current_cpu, vpc, scache, hash_mask, FAST_P); + +/* begin full-exec-scache */ +EOF + +${SHELL} $infile full-exec-scache + +cat << EOF +/* end full-exec-scache */ + + SET_H_PC (vpc); + + ++ CPU_INSN_COUNT (current_cpu); + } + while (0 /*CPU_RUNNING_P (current_cpu)*/); +} + +#undef FAST_P + +EOF + +#################################### + +# Scache engine: fast version. + +if [ x$fast = xyes ] ; then + + cat << EOF + +#define FAST_P 1 + +void +@cpu@_engine_run_fast (SIM_CPU *current_cpu) +{ + SIM_DESC current_state = CPU_STATE (current_cpu); + SCACHE *scache = CPU_SCACHE_CACHE (current_cpu); + unsigned int hash_mask = CPU_SCACHE_HASH_MASK (current_cpu); + SEM_PC vpc; + +EOF + +if [ x$parallel != xno ] ; then + cat << EOF + PAREXEC pbufs[MAX_PARALLEL_INSNS]; + PAREXEC *par_exec; + +EOF +fi + +# Any initialization code before looping starts. +# Note that this code may declare some locals. +${SHELL} $infile init + +if [ x$parallel != xno ] ; then + cat << EOF + +#if defined (HAVE_PARALLEL_EXEC) && defined (__GNUC__) + { + if (! CPU_IDESC_READ_INIT_P (current_cpu)) + { +/* ??? Later maybe paste read.c in when building mainloop.c. */ +#define DEFINE_LABELS +#include "readx.c" + CPU_IDESC_READ_INIT_P (current_cpu) = 1; + } + } +#endif + +EOF +fi # parallel != no + +cat << EOF + +#if WITH_SEM_SWITCH_FAST && defined (__GNUC__) + { + if (! CPU_IDESC_SEM_INIT_P (current_cpu)) + { +/* ??? Later maybe paste sem-switch.c in when building mainloop.c. */ +#define DEFINE_LABELS +#include "$switch" + CPU_IDESC_SEM_INIT_P (current_cpu) = 1; + } + } +#endif + + vpc = GET_H_PC (); + + do + { + SCACHE *sc; + + sc = @cpu@_scache_lookup (current_cpu, vpc, scache, hash_mask, FAST_P); + +/* begin fast-exec-scache */ +EOF + +${SHELL} $infile fast-exec-scache + +cat << EOF +/* end fast-exec-scache */ + + SET_H_PC (vpc); + + ++ CPU_INSN_COUNT (current_cpu); + } + while (0 /*CPU_RUNNING_P (current_cpu)*/); +} + +#undef FAST_P + +EOF + +fi # -fast + +fi # -scache + +########################################################################## + +# Compilation engine: lookup insn in scache, extract a pbb +# (pseudo-basic-block) if missing, then execute the pbb. +# A "pbb" is a sequence of insns up to the next cti insn or until +# some prespecified maximum. +# CTI: control transfer instruction. + +if [ x$pbb = xyes ] ; then + + cat << EOF + +/* Record address of cti terminating a pbb. */ +#define SET_CTI_VPC(sc) do { _cti_sc = (sc); } while (0) +/* Record number of [real] insns in pbb. */ +#define SET_INSN_COUNT(n) do { _insn_count = (n); } while (0) + +/* Fetch and extract a pseudo-basic-block. + FAST_P is non-zero if no tracing/profiling/etc. is wanted. */ + +INLINE SEM_PC +@cpu@_pbb_begin (SIM_CPU *current_cpu, int FAST_P) +{ + SEM_PC new_vpc; + PCADDR pc; + SCACHE *sc; + int max_insns = CPU_SCACHE_MAX_CHAIN_LENGTH (current_cpu); + + pc = GET_H_PC (); + + new_vpc = scache_lookup_or_alloc (current_cpu, pc, max_insns, &sc); + if (! new_vpc) + { + /* Leading '_' to avoid collision with mainloop.in. */ + int _insn_count = 0; + SCACHE *orig_sc = sc; + SCACHE *_cti_sc = NULL; + int slice_insns = CPU_MAX_SLICE_INSNS (current_cpu); + + /* First figure out how many instructions to compile. + MAX_INSNS is the size of the allocated buffer, which includes space + for before/after handlers if they're being used. + SLICE_INSNS is the maxinum number of real insns that can be + executed. Zero means "as many as we want". */ + /* ??? max_insns is serving two incompatible roles. + 1) Number of slots available in scache buffer. + 2) Number of real insns to execute. + They're incompatible because there are virtual insns emitted too + (chain,cti-chain,before,after handlers). */ + + if (slice_insns == 1) + { + /* No need to worry about extra slots required for virtual insns + and parallel exec support because MAX_CHAIN_LENGTH is + guaranteed to be big enough to execute at least 1 insn! */ + max_insns = 1; + } + else + { + /* Allow enough slop so that while compiling insns, if max_insns > 0 + then there's guaranteed to be enough space to emit one real insn. + MAX_CHAIN_LENGTH is typically much longer than + the normal number of insns between cti's anyway. */ + max_insns -= (1 /* one for the trailing chain insn */ + + (FAST_P + ? 0 + : (1 + MAX_PARALLEL_INSNS) /* before+after */) + + (MAX_PARALLEL_INSNS > 1 + ? (MAX_PARALLEL_INSNS * 2) + : 0)); + + /* Account for before/after handlers. */ + if (! FAST_P) + slice_insns *= 3; + + if (slice_insns > 0 + && slice_insns < max_insns) + max_insns = slice_insns; + } + + new_vpc = sc; + + /* SC,PC must be updated to point passed the last entry used. + SET_CTI_VPC must be called if pbb is terminated by a cti. + SET_INSN_COUNT must be called to record number of real insns in + pbb [could be computed by us of course, extra cpu but perhaps + negligible enough]. */ + +/* begin extract-pbb */ +EOF + +${SHELL} $infile extract-pbb + +cat << EOF +/* end extract-pbb */ + + /* The last one is a pseudo-insn to link to the next chain. + It is also used to record the insn count for this chain. */ + { + const IDESC *id; + + /* Was pbb terminated by a cti? */ + if (_cti_sc) + { + id = & CPU_IDESC (current_cpu) [@CPU@_INSN_X_CTI_CHAIN]; + } + else + { + id = & CPU_IDESC (current_cpu) [@CPU@_INSN_X_CHAIN]; + } + SEM_SET_CODE (&sc->argbuf, id, FAST_P); + sc->argbuf.idesc = id; + sc->argbuf.addr = pc; + sc->argbuf.fields.chain.insn_count = _insn_count; + sc->argbuf.fields.chain.next = 0; + ++sc; + } + + /* Update the pointer to the next free entry. */ + CPU_SCACHE_NEXT_FREE (current_cpu) = sc; + /* Record length of chain if profiling. + This includes virtual insns since they count against + max_insns too. */ + if (! FAST_P) + PROFILE_COUNT_SCACHE_CHAIN_LENGTH (current_cpu, sc - orig_sc); + } + + return new_vpc; +} + +/* Chain to the next block from a non-cti terminated previous block. */ + +INLINE SEM_PC +@cpu@_pbb_chain (SIM_CPU *current_cpu, SEM_ARG sem_arg) +{ + ARGBUF *abuf = SEM_ARGBUF (sem_arg); + + PBB_UPDATE_INSN_COUNT (current_cpu, sem_arg); + + SET_H_PC (abuf->addr); + + /* If not running forever, exit back to main loop. */ + if (CPU_MAX_SLICE_INSNS (current_cpu) != 0 + /* Also exit back to main loop if there's an event. + Note that if CPU_MAX_SLICE_INSNS != 1, events won't get processed + at the "right" time, but then that was what was asked for. + There is no silver bullet for simulator engines. + ??? Clearly this needs a cleaner interface. + At present it's just so Ctrl-C works. */ + || STATE_EVENTS (CPU_STATE (current_cpu))->work_pending) + CPU_RUNNING_P (current_cpu) = 0; + + /* If chained to next block, go straight to it. */ + if (abuf->fields.chain.next) + return abuf->fields.chain.next; + /* See if next block has already been compiled. */ + abuf->fields.chain.next = scache_lookup (current_cpu, abuf->addr); + if (abuf->fields.chain.next) + return abuf->fields.chain.next; + /* Nope, so next insn is a virtual insn to invoke the compiler + (begin a pbb). */ + return CPU_SCACHE_PBB_BEGIN (current_cpu); +} + +/* Chain to the next block from a cti terminated previous block. + NEW_VPC_PTR is one of SEM_BRANCH_UNTAKEN, SEM_BRANCH_UNCACHEABLE, or + a pointer to a location containing the SEM_PC of the branch's address. + NEW_PC is the target's branch address, and is only valid if + NEW_VPC_PTR != SEM_BRANCH_UNTAKEN. */ + +INLINE SEM_PC +@cpu@_pbb_cti_chain (SIM_CPU *current_cpu, SEM_ARG sem_arg, + SEM_PC *new_vpc_ptr, PCADDR new_pc) +{ + ARGBUF *abuf; + + PBB_UPDATE_INSN_COUNT (current_cpu, sem_arg); + + /* If not running forever, exit back to main loop. */ + if (CPU_MAX_SLICE_INSNS (current_cpu) != 0 + /* Also exit back to main loop if there's an event. + Note that if CPU_MAX_SLICE_INSNS != 1, events won't get processed + at the "right" time, but then that was what was asked for. + There is no silver bullet for simulator engines. + ??? Clearly this needs a cleaner interface. + At present it's just so Ctrl-C works. */ + || STATE_EVENTS (CPU_STATE (current_cpu))->work_pending) + CPU_RUNNING_P (current_cpu) = 0; + + /* Restart compiler if we branched to an uncacheable address + (e.g. "j reg"). */ + if (new_vpc_ptr == SEM_BRANCH_UNCACHEABLE) + { + SET_H_PC (new_pc); + return CPU_SCACHE_PBB_BEGIN (current_cpu); + } + + /* If branch wasn't taken, update the pc and set BR_ADDR_PTR to our + next chain ptr. */ + if (new_vpc_ptr == SEM_BRANCH_UNTAKEN) + { + abuf = SEM_ARGBUF (sem_arg); + SET_H_PC (abuf->addr); + new_vpc_ptr = &abuf->fields.chain.next; + } + else + { + SET_H_PC (new_pc); + } + + /* If chained to next block, go straight to it. */ + if (*new_vpc_ptr) + return *new_vpc_ptr; + /* See if next block has already been compiled. */ + *new_vpc_ptr = scache_lookup (current_cpu, GET_H_PC ()); + if (*new_vpc_ptr) + return *new_vpc_ptr; + /* Nope, so next insn is a virtual insn to invoke the compiler + (begin a pbb). */ + return CPU_SCACHE_PBB_BEGIN (current_cpu); +} + +/* x-before handler. + This is called before each insn. */ + +void +@cpu@_pbb_before (SIM_CPU *current_cpu, SCACHE *sc) +{ + SEM_ARG sem_arg = sc; + const ARGBUF *abuf = SEM_ARGBUF (sem_arg); + int first_p = abuf->fields.before.first_p; + const ARGBUF *cur_abuf = SEM_ARGBUF (sc + 1); + const IDESC *cur_idesc = cur_abuf->idesc; + PCADDR pc = cur_abuf->addr; + + if (ARGBUF_PROFILE_P (cur_abuf)) + PROFILE_COUNT_INSN (current_cpu, pc, cur_idesc->num); + + /* If this isn't the first insn, finish up the previous one. */ + + if (! first_p) + { + if (PROFILE_MODEL_P (current_cpu)) + { + const SEM_ARG prev_sem_arg = sc - 1; + const ARGBUF *prev_abuf = SEM_ARGBUF (prev_sem_arg); + const IDESC *prev_idesc = prev_abuf->idesc; + int cycles; + + /* ??? May want to measure all insns if doing insn tracing. */ + if (ARGBUF_PROFILE_P (prev_abuf)) + { + cycles = (*prev_idesc->timing->model_fn) (current_cpu, prev_sem_arg); + @cpu@_model_insn_after (current_cpu, 0 /*last_p*/, cycles); + } + } + + TRACE_INSN_FINI (current_cpu, cur_abuf, 0 /*last_p*/); + } + + /* FIXME: Later make cover macros: PROFILE_INSN_{INIT,FINI}. */ + if (PROFILE_MODEL_P (current_cpu) + && ARGBUF_PROFILE_P (cur_abuf)) + @cpu@_model_insn_before (current_cpu, first_p); + + TRACE_INSN_INIT (current_cpu, cur_abuf, first_p); + TRACE_INSN (current_cpu, cur_idesc->idata, cur_abuf, pc); +} + +/* x-after handler. + This is called after a serial insn or at the end of a group of parallel + insns. */ + +void +@cpu@_pbb_after (SIM_CPU *current_cpu, SCACHE *sc) +{ + SEM_ARG sem_arg = sc; + const ARGBUF *abuf = SEM_ARGBUF (sem_arg); + const SEM_ARG prev_sem_arg = sc - 1; + const ARGBUF *prev_abuf = SEM_ARGBUF (prev_sem_arg); + + /* ??? May want to measure all insns if doing insn tracing. */ + if (PROFILE_MODEL_P (current_cpu) + && ARGBUF_PROFILE_P (prev_abuf)) + { + const IDESC *prev_idesc = prev_abuf->idesc; + int cycles; + + cycles = (*prev_idesc->timing->model_fn) (current_cpu, prev_sem_arg); + @cpu@_model_insn_after (current_cpu, 1 /*last_p*/, cycles); + } + TRACE_INSN_FINI (current_cpu, prev_abuf, 1 /*last_p*/); +} + +#define FAST_P 0 + +void +@cpu@_engine_run_full (SIM_CPU *current_cpu) +{ + SIM_DESC current_state = CPU_STATE (current_cpu); + SCACHE *scache = CPU_SCACHE_CACHE (current_cpu); + /* virtual program counter */ + SEM_PC vpc; +#if WITH_SEM_SWITCH_FULL + /* For communication between cti's and cti-chain. */ + PCADDR pbb_br_npc; + SEM_PC *pbb_br_npc_ptr; +#endif + +EOF + +if [ x$parallel != xno ] ; then + cat << EOF + PAREXEC pbufs[MAX_PARALLEL_INSNS]; + PAREXEC *par_exec = &pbufs[0]; + +EOF +fi + +# Any initialization code before looping starts. +# Note that this code may declare some locals. +${SHELL} $infile init + +cat << EOF + + if (! CPU_IDESC_SEM_INIT_P (current_cpu)) + { + /* ??? 'twould be nice to move this up a level and only call it once. + On the other hand, in the "let's go fast" case the test is only done + once per pbb (since we only return to the main loop at the end of + a pbb). And in the "let's run until we're done" case we don't return + until the program exits. */ + +#if WITH_SEM_SWITCH_FULL && defined (__GNUC__) +/* ??? Later maybe paste sem-switch.c in when building mainloop.c. */ +#define DEFINE_LABELS +#include "$switch" +#endif + + /* Initialize the "begin (compile) a pbb" virtual insn. */ + vpc = CPU_SCACHE_PBB_BEGIN (current_cpu); + SEM_SET_FULL_CODE (SEM_ARGBUF (vpc), + & CPU_IDESC (current_cpu) [@CPU@_INSN_X_BEGIN]); + vpc->argbuf.idesc = & CPU_IDESC (current_cpu) [@CPU@_INSN_X_BEGIN]; + + CPU_IDESC_SEM_INIT_P (current_cpu) = 1; + } + + CPU_RUNNING_P (current_cpu) = 1; + /* ??? In the case where we're returning to the main loop after every + pbb we don't want to call pbb_begin each time (which hashes on the pc + and does a table lookup). A way to speed this up is to save vpc + between calls. */ + vpc = @cpu@_pbb_begin (current_cpu, FAST_P); + + do + { +/* begin full-exec-pbb */ +EOF + +${SHELL} $infile full-exec-pbb + +cat << EOF +/* end full-exec-pbb */ + } + while (CPU_RUNNING_P (current_cpu)); +} + +#undef FAST_P + +EOF + +#################################### + +# Compile engine: fast version. + +if [ x$fast = xyes ] ; then + + cat << EOF + +#define FAST_P 1 + +void +@cpu@_engine_run_fast (SIM_CPU *current_cpu) +{ + SIM_DESC current_state = CPU_STATE (current_cpu); + SCACHE *scache = CPU_SCACHE_CACHE (current_cpu); + /* virtual program counter */ + SEM_PC vpc; +#if WITH_SEM_SWITCH_FAST + /* For communication between cti's and cti-chain. */ + PCADDR pbb_br_npc; + SEM_PC *pbb_br_npc_ptr; +#endif + +EOF + +if [ x$parallel != xno ] ; then + cat << EOF + PAREXEC pbufs[MAX_PARALLEL_INSNS]; + PAREXEC *par_exec = &pbufs[0]; + +EOF +fi + +# Any initialization code before looping starts. +# Note that this code may declare some locals. +${SHELL} $infile init + +cat << EOF + + if (! CPU_IDESC_SEM_INIT_P (current_cpu)) + { + /* ??? 'twould be nice to move this up a level and only call it once. + On the other hand, in the "let's go fast" case the test is only done + once per pbb (since we only return to the main loop at the end of + a pbb). And in the "let's run until we're done" case we don't return + until the program exits. */ + +#if WITH_SEM_SWITCH_FAST && defined (__GNUC__) +/* ??? Later maybe paste sem-switch.c in when building mainloop.c. */ +#define DEFINE_LABELS +#include "$switch" +#endif + + /* Initialize the "begin (compile) a pbb" virtual insn. */ + vpc = CPU_SCACHE_PBB_BEGIN (current_cpu); + SEM_SET_FAST_CODE (SEM_ARGBUF (vpc), + & CPU_IDESC (current_cpu) [@CPU@_INSN_X_BEGIN]); + vpc->argbuf.idesc = & CPU_IDESC (current_cpu) [@CPU@_INSN_X_BEGIN]; + + CPU_IDESC_SEM_INIT_P (current_cpu) = 1; + } + + CPU_RUNNING_P (current_cpu) = 1; + /* ??? In the case where we're returning to the main loop after every + pbb we don't want to call pbb_begin each time (which hashes on the pc + and does a table lookup). A way to speed this up is to save vpc + between calls. */ + vpc = @cpu@_pbb_begin (current_cpu, FAST_P); + + do + { +/* begin fast-exec-pbb */ +EOF + +${SHELL} $infile fast-exec-pbb + +cat << EOF +/* end fast-exec-pbb */ + } + while (CPU_RUNNING_P (current_cpu)); +} + +#undef FAST_P + +EOF +fi # -fast + +fi # -pbb + +# Process @cpu@,@CPU@ appearing in mainloop.in. +sed -e "s/@cpu@/$cpu/g" -e "s/@CPU@/$CPU/g" < tmp-mloop.cin > mloop.cin +rc=$? +rm -f tmp-mloop.cin + +exit $rc diff --git a/sim/common/gennltvals.sh b/sim/common/gennltvals.sh new file mode 100644 index 00000000000..63ff6621ec6 --- /dev/null +++ b/sim/common/gennltvals.sh @@ -0,0 +1,67 @@ +#! /bin/sh +# Generate nltvals.def, a file that describes various newlib/libgloss +# target values used by the host/target interface. +# +# Syntax: /bin/sh gennltvals.sh shell srcroot cpp + +shell=$1 +srcroot=$2 +cpp=$3 + +srccom=$srcroot/sim/common + +echo '/* Newlib/libgloss macro values needed by remote target support. */' +echo '/* This file is machine generated by gennltvals.sh. */' + +$shell ${srccom}/gentvals.sh "" errno ${srcroot}/newlib/libc/include \ + "errno.h sys/errno.h" 'E[A-Z0-9]*' "${cpp}" + +$shell ${srccom}/gentvals.sh "" signal ${srcroot}/newlib/libc/include \ + "signal.h sys/signal.h" 'SIG[A-Z0-9]*' "${cpp}" + +$shell ${srccom}/gentvals.sh "" open ${srcroot}/newlib/libc/include \ + "fcntl.h sys/fcntl.h" 'O_[A-Z0-9]*' "${cpp}" + +# Unfortunately, each newlib/libgloss port has seen fit to define their own +# syscall.h file. This means that system call numbers can vary for each port. +# Support for all this crud is kept here, rather than trying to get too fancy. +# If you want to try to improve this, please do, but don't break anything. +# Note that there is a standard syscall.h file (libgloss/syscall.h) now which +# hopefully more targets can use. + +dir=newlib/libc/sys/d10v/sys target=d10v +$shell ${srccom}/gentvals.sh $target sys ${srcroot}/$dir \ + "syscall.h" 'SYS_[_A-Za-z0-9]*' "${cpp}" + +dir=libgloss target=d30v +$shell ${srccom}/gentvals.sh $target sys ${srcroot}/$dir \ + "syscall.h" 'SYS_[_A-Za-z0-9]*' "${cpp}" + +dir=libgloss target=fr30 +$shell ${srccom}/gentvals.sh $target sys ${srcroot}/$dir \ + "syscall.h" 'SYS_[_A-Za-z0-9]*' "${cpp}" + +dir=libgloss/i960 target=i960 +$shell ${srccom}/gentvals.sh $target sys ${srcroot}/$dir \ + "syscall.h" 'SYS_[_A-Za-z0-9]*' "${cpp}" + +dir=libgloss target=m32r +$shell ${srccom}/gentvals.sh $target sys ${srcroot}/$dir \ + "syscall.h" 'SYS_[_A-Za-z0-9]*' "${cpp}" + +dir=libgloss target=mn10200 +$shell ${srccom}/gentvals.sh $target sys ${srcroot}/$dir \ + "syscall.h" 'SYS_[_A-Za-z0-9]*' "${cpp}" + +dir=libgloss target=mn10300 +$shell ${srccom}/gentvals.sh $target sys ${srcroot}/$dir \ + "syscall.h" 'SYS_[_A-Za-z0-9]*' "${cpp}" + +dir=libgloss target=sparc +$shell ${srccom}/gentvals.sh $target sys ${srcroot}/$dir \ + "syscall.h" 'SYS_[_A-Za-z0-9]*' "${cpp}" + +dir=libgloss/v850/sys target=v850 +$shell ${srccom}/gentvals.sh $target sys ${srcroot}/$dir \ + "syscall.h" 'SYS_[_A-Za-z0-9]*' "${cpp}" + diff --git a/sim/common/gentmap.c b/sim/common/gentmap.c new file mode 100644 index 00000000000..e4f5d0dc8b4 --- /dev/null +++ b/sim/common/gentmap.c @@ -0,0 +1,125 @@ +/* Generate targ-vals.h and targ-map.c. */ + +#include + +struct tdefs { + char *symbol; + int value; +}; + +static struct tdefs sys_tdefs[] = { +#define sys_defs +#include "targ-vals.def" +#undef sys_defs + { 0, 0 } +}; + +static struct tdefs errno_tdefs[] = { +#define errno_defs +#include "targ-vals.def" +#undef errno_defs + { 0, 0 } +}; + +static struct tdefs open_tdefs[] = { +#define open_defs +#include "targ-vals.def" +#undef open_defs + { 0, 0 } +}; + +static void +gen_targ_vals_h () +{ + struct tdefs *t; + + printf ("/* Target header values needed by the simulator and gdb. */\n"); + printf ("/* This file is machine generated by gentmap.c. */\n\n"); + + printf ("#ifndef TARG_VALS_H\n"); + printf ("#define TARG_VALS_H\n\n"); + + printf ("/* syscall values */\n"); + for (t = &sys_tdefs[0]; t->symbol; ++t) + printf ("#define TARGET_%s %d\n", t->symbol, t->value); + printf ("\n"); + + printf ("/* errno values */\n"); + for (t = &errno_tdefs[0]; t->symbol; ++t) + printf ("#define TARGET_%s %d\n", t->symbol, t->value); + printf ("\n"); + + printf ("/* open flag values */\n"); + for (t = &open_tdefs[0]; t->symbol; ++t) + printf ("#define TARGET_%s 0x%x\n", t->symbol, t->value); + printf ("\n"); + + printf ("#endif /* TARG_VALS_H */\n"); +} + +static void +gen_targ_map_c () +{ + struct tdefs *t; + + printf ("/* Target value mapping utilities needed by the simulator and gdb. */\n"); + printf ("/* This file is machine generated by gentmap.c. */\n\n"); + + printf ("#include \n"); + printf ("#include \n"); + printf ("#include \"ansidecl.h\"\n"); + printf ("#include \"callback.h\"\n"); + printf ("#include \"targ-vals.h\"\n"); + printf ("\n"); + + printf ("/* syscall mapping table */\n"); + printf ("CB_TARGET_DEFS_MAP cb_init_syscall_map[] = {\n"); + for (t = &sys_tdefs[0]; t->symbol; ++t) + { + printf ("#ifdef CB_%s\n", t->symbol); + printf (" { CB_%s, TARGET_%s },\n", t->symbol, t->symbol); + printf ("#endif\n"); + } + printf (" { -1, -1 }\n"); + printf ("};\n\n"); + + printf ("/* errno mapping table */\n"); + printf ("CB_TARGET_DEFS_MAP cb_init_errno_map[] = {\n"); + for (t = &errno_tdefs[0]; t->symbol; ++t) + { + printf ("#ifdef %s\n", t->symbol); + printf (" { %s, TARGET_%s },\n", t->symbol, t->symbol); + printf ("#endif\n"); + } + printf (" { 0, 0 }\n"); + printf ("};\n\n"); + + printf ("/* open flags mapping table */\n"); + printf ("CB_TARGET_DEFS_MAP cb_init_open_map[] = {\n"); + for (t = &open_tdefs[0]; t->symbol; ++t) + { + printf ("#ifdef %s\n", t->symbol); + printf (" { %s, TARGET_%s },\n", t->symbol, t->symbol); + printf ("#endif\n"); + } + printf (" { -1, -1 }\n"); + printf ("};\n\n"); +} + +int +main (argc, argv) + int argc; + char *argv[]; +{ + if (argc != 2) + abort (); + + if (strcmp (argv[1], "-h") == 0) + gen_targ_vals_h (); + else if (strcmp (argv[1], "-c") == 0) + gen_targ_map_c (); + else + abort (); + + exit (0); +} diff --git a/sim/common/gentvals.sh b/sim/common/gentvals.sh new file mode 100644 index 00000000000..6dd7315f30a --- /dev/null +++ b/sim/common/gentvals.sh @@ -0,0 +1,74 @@ +#!/bin/sh +# Usage: gentvals.sh target type dir files pattern cpp + +target=$1 +type=$2 +dir=$3 +# FIXME: Would be nice to process #include's in these files. +files=$4 +pattern=$5 +cpp=$6 + +# FIXME: need trap to remove tmp files. + +rm -f tmpvals.list tmpvals.uniq +for f in $files +do + if test -f $dir/$f ; then + grep "#define[ ]$pattern" $dir/$f | sed -e "s/^.*#define[ ]\($pattern\)[ ]*\([^ ][^ ]*\).*$/\1/" >> tmpvals.list + fi +done + +sort tmpvals.uniq + +rm -f tmpvals.h +for f in $files +do + if test -f $dir/$f ; then + echo "#include <$f>" >>tmpvals.h + fi +done + +cat tmpvals.uniq | +while read sym +do + echo "#ifdef $sym" >>tmpvals.h + echo 'DEFVAL { "'$sym'", '$sym ' },' >>tmpvals.h + echo "#endif" >>tmpvals.h +done + +if test -z "$target" +then + echo "#ifdef ${type}_defs" +else + echo "#ifdef NL_TARGET_$target" + echo "#ifdef ${type}_defs" +fi + +for f in $files +do + if test -f $dir/$f ; then + echo "/* from $f */" + fi +done + +if test -z "$target" +then + echo "/* begin $type target macros */" +else + echo "/* begin $target $type target macros */" +fi + +$cpp -I$dir tmpvals.h | grep DEFVAL | sed -e 's/DEFVAL//' -e 's/ / /' + +if test -z "$target" +then + echo "/* end $type target macros */" + echo "#endif" +else + echo "/* end $target $type target macros */" + echo "#endif" + echo "#endif" +fi + +rm -f tmpvals.list tmpvals.uniq tmpvals.h diff --git a/sim/common/hw-alloc.c b/sim/common/hw-alloc.c new file mode 100644 index 00000000000..e64ae82997e --- /dev/null +++ b/sim/common/hw-alloc.c @@ -0,0 +1,99 @@ +/* Hardware memory allocator. + Copyright (C) 1998 Free Software Foundation, Inc. + Contributed by Cygnus Support. + +This file is part of GDB, the GNU debugger. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + + +#include "hw-main.h" +#include "hw-base.h" + + +#ifdef HAVE_STDLIB_H +#include +#endif + +struct hw_alloc_data { + void *alloc; + int zalloc_p; + struct hw_alloc_data *next; +}; + +void +create_hw_alloc_data (struct hw *me) +{ + /* NULL */ +} + +void +delete_hw_alloc_data (struct hw *me) +{ + if (me->alloc_of_hw != NULL) + hw_abort (me, "hw-alloc botch"); + while (me->alloc_of_hw != NULL) + { + hw_free (me, me->alloc_of_hw->alloc); + } +} + + + +void * +hw_zalloc (struct hw *me, unsigned long size) +{ + struct hw_alloc_data *memory = ZALLOC (struct hw_alloc_data); + memory->alloc = zalloc (size); + memory->zalloc_p = 1; + memory->next = me->alloc_of_hw; + me->alloc_of_hw = memory; + return memory->alloc; +} + +void * +hw_malloc (struct hw *me, unsigned long size) +{ + struct hw_alloc_data *memory = ZALLOC (struct hw_alloc_data); + memory->alloc = zalloc (size); + memory->zalloc_p = 0; + memory->next = me->alloc_of_hw; + me->alloc_of_hw = memory; + return memory->alloc; +} + +void +hw_free (struct hw *me, + void *alloc) +{ + struct hw_alloc_data **memory; + for (memory = &me->alloc_of_hw; + *memory != NULL; + memory = &(*memory)->next) + { + if ((*memory)->alloc == alloc) + { + struct hw_alloc_data *die = (*memory); + (*memory) = die->next; + if (die->zalloc_p) + zfree (die->alloc); + else + free (die->alloc); + zfree (die); + return; + } + } + hw_abort (me, "free of memory not belonging to a device"); +} diff --git a/sim/common/hw-alloc.h b/sim/common/hw-alloc.h new file mode 100644 index 00000000000..48b03f22ddb --- /dev/null +++ b/sim/common/hw-alloc.h @@ -0,0 +1,49 @@ +/* Hardware memory allocator. + Copyright (C) 1998 Free Software Foundation, Inc. + Contributed by Cygnus Support. + +This file is part of GDB, the GNU debugger. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + + +#ifndef HW_ALLOC_H +#define HW_ALLOC_H + +/* Mechanism for associating memory allocated by a device to that + device. + + When a device is deleted any remaining memory regions associated to + it are reclaimed. + + FIXME: Perhaphs this can be generalized. Perhaphs it should not + be. */ + + +#define HW_ZALLOC(me,type) (type*) hw_zalloc (me, sizeof (type)) +#define HW_MALLOC(me,type) (type*) hw_malloc (me, sizeof (type)) +#define HW_NZALLOC(ME,TYPE,N) (TYPE*) hw_zalloc (me, sizeof (TYPE) * (N)) + +extern void *hw_zalloc (struct hw *me, unsigned long size); +extern void *hw_malloc (struct hw *me, unsigned long size); + +extern void hw_free (struct hw *me, void *); + + +/* Duplicate a string allocating memory using the per-device heap */ + +extern char *hw_strdup (struct hw *me, const char *str); + +#endif diff --git a/sim/common/hw-base.c b/sim/common/hw-base.c new file mode 100644 index 00000000000..a13ac64ba3b --- /dev/null +++ b/sim/common/hw-base.c @@ -0,0 +1,571 @@ +/* This file is part of the program psim. + + Copyright (C) 1994-1996, 1998, Andrew Cagney + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + + +#include "hw-main.h" +#include "hw-base.h" + + +#ifdef HAVE_STRING_H +#include +#else +#ifdef HAVE_STRINGS_H +#include +#endif +#endif + +#if HAVE_STDLIB_H +#include +#endif + +#include + +#include "hw-config.h" + +struct hw_base_data { + int finished_p; + const struct hw_descriptor *descriptor; + hw_delete_callback *to_delete; +}; + +static int +generic_hw_unit_decode (struct hw *bus, + const char *unit, + hw_unit *phys) +{ + memset (phys, 0, sizeof (*phys)); + if (unit == NULL) + return 0; + else + { + int nr_cells = 0; + const int max_nr_cells = hw_unit_nr_address_cells (bus); + while (1) + { + char *end = NULL; + unsigned long val; + val = strtoul (unit, &end, 0); + /* parse error? */ + if (unit == end) + return -1; + /* two many cells? */ + if (nr_cells >= max_nr_cells) + return -1; + /* save it */ + phys->cells[nr_cells] = val; + nr_cells++; + unit = end; + /* more to follow? */ + if (isspace (*unit) || *unit == '\0') + break; + if (*unit != ',') + return -1; + unit++; + } + if (nr_cells < max_nr_cells) { + /* shift everything to correct position */ + int i; + for (i = 1; i <= nr_cells; i++) + phys->cells[max_nr_cells - i] = phys->cells[nr_cells - i]; + for (i = 0; i < (max_nr_cells - nr_cells); i++) + phys->cells[i] = 0; + } + phys->nr_cells = max_nr_cells; + return max_nr_cells; + } +} + +static int +generic_hw_unit_encode (struct hw *bus, + const hw_unit *phys, + char *buf, + int sizeof_buf) +{ + int i; + int len; + char *pos = buf; + /* skip leading zero's */ + for (i = 0; i < phys->nr_cells; i++) + { + if (phys->cells[i] != 0) + break; + } + /* don't output anything if empty */ + if (phys->nr_cells == 0) + { + strcpy(pos, ""); + len = 0; + } + else if (i == phys->nr_cells) + { + /* all zero */ + strcpy(pos, "0"); + len = 1; + } + else + { + for (; i < phys->nr_cells; i++) + { + if (pos != buf) { + strcat(pos, ","); + pos = strchr(pos, '\0'); + } + if (phys->cells[i] < 10) + sprintf (pos, "%ld", (unsigned long)phys->cells[i]); + else + sprintf (pos, "0x%lx", (unsigned long)phys->cells[i]); + pos = strchr(pos, '\0'); + } + len = pos - buf; + } + if (len >= sizeof_buf) + hw_abort (NULL, "generic_unit_encode - buffer overflow\n"); + return len; +} + +static int +generic_hw_unit_address_to_attach_address (struct hw *me, + const hw_unit *address, + int *attach_space, + unsigned_word *attach_address, + struct hw *client) +{ + int i; + for (i = 0; i < address->nr_cells - 2; i++) + { + if (address->cells[i] != 0) + hw_abort (me, "Only 32bit addresses supported"); + } + if (address->nr_cells >= 2) + *attach_space = address->cells[address->nr_cells - 2]; + else + *attach_space = 0; + *attach_address = address->cells[address->nr_cells - 1]; + return 1; +} + +static int +generic_hw_unit_size_to_attach_size (struct hw *me, + const hw_unit *size, + unsigned *nr_bytes, + struct hw *client) +{ + int i; + for (i = 0; i < size->nr_cells - 1; i++) + { + if (size->cells[i] != 0) + hw_abort (me, "Only 32bit sizes supported"); + } + *nr_bytes = size->cells[0]; + return *nr_bytes; +} + + +/* ignore/passthrough versions of each function */ + +static void +passthrough_hw_attach_address (struct hw *me, + int level, + int space, + address_word addr, + address_word nr_bytes, + struct hw *client) /*callback/default*/ +{ + if (hw_parent (me) == NULL) + hw_abort (client, "hw_attach_address: no parent attach method"); + hw_attach_address (hw_parent (me), level, + space, addr, nr_bytes, + client); +} + +static void +passthrough_hw_detach_address (struct hw *me, + int level, + int space, + address_word addr, + address_word nr_bytes, + struct hw *client) /*callback/default*/ +{ + if (hw_parent (me) == NULL) + hw_abort (client, "hw_attach_address: no parent attach method"); + hw_detach_address (hw_parent (me), level, + space, addr, nr_bytes, + client); +} + +static unsigned +panic_hw_io_read_buffer (struct hw *me, + void *dest, + int space, + unsigned_word addr, + unsigned nr_bytes) +{ + hw_abort (me, "no io-read method"); + return 0; +} + +static unsigned +panic_hw_io_write_buffer (struct hw *me, + const void *source, + int space, + unsigned_word addr, + unsigned nr_bytes) +{ + hw_abort (me, "no io-write method"); + return 0; +} + +static unsigned +passthrough_hw_dma_read_buffer (struct hw *me, + void *dest, + int space, + unsigned_word addr, + unsigned nr_bytes) +{ + if (hw_parent (me) == NULL) + hw_abort (me, "no parent dma-read method"); + return hw_dma_read_buffer (hw_parent (me), dest, + space, addr, nr_bytes); +} + +static unsigned +passthrough_hw_dma_write_buffer (struct hw *me, + const void *source, + int space, + unsigned_word addr, + unsigned nr_bytes, + int violate_read_only_section) +{ + if (hw_parent (me) == NULL) + hw_abort (me, "no parent dma-write method"); + return hw_dma_write_buffer (hw_parent (me), source, + space, addr, + nr_bytes, + violate_read_only_section); +} + +static void +ignore_hw_delete (struct hw *me) +{ + /* NOP */ +} + + + + +static const char * +full_name_of_hw (struct hw *leaf, + char *buf, + unsigned sizeof_buf) +{ + /* get a buffer */ + char full_name[1024]; + if (buf == (char*)0) + { + buf = full_name; + sizeof_buf = sizeof (full_name); + } + + /* use head recursion to construct the path */ + + if (hw_parent (leaf) == NULL) + /* root */ + { + if (sizeof_buf < 1) + hw_abort (leaf, "buffer overflow"); + *buf = '\0'; + } + else + /* sub node */ + { + char unit[1024]; + full_name_of_hw (hw_parent (leaf), buf, sizeof_buf); + if (hw_unit_encode (hw_parent (leaf), + hw_unit_address (leaf), + unit + 1, + sizeof (unit) - 1) + > 0) + unit[0] = '@'; + else + unit[0] = '\0'; + if (strlen (buf) + strlen ("/") + strlen (hw_name (leaf)) + strlen (unit) + >= sizeof_buf) + hw_abort (leaf, "buffer overflow"); + strcat (buf, "/"); + strcat (buf, hw_name (leaf)); + strcat (buf, unit); + } + + /* return it usefully */ + if (buf == full_name) + buf = hw_strdup (leaf, full_name); + return buf; +} + +struct hw * +hw_create (struct sim_state *sd, + struct hw *parent, + const char *family, + const char *name, + const char *unit, + const char *args) +{ + /* NOTE: HW must be allocated using ZALLOC, others use HW_ZALLOC */ + struct hw *hw = ZALLOC (struct hw); + + /* our identity */ + hw->family_of_hw = hw_strdup (hw, family); + hw->name_of_hw = hw_strdup (hw, name); + hw->args_of_hw = hw_strdup (hw, args); + + /* a hook into the system */ + if (sd != NULL) + hw->system_of_hw = sd; + else if (parent != NULL) + hw->system_of_hw = hw_system (parent); + else + hw_abort (parent, "No system found"); + + /* in a tree */ + if (parent != NULL) + { + struct hw **sibling = &parent->child_of_hw; + while ((*sibling) != NULL) + sibling = &(*sibling)->sibling_of_hw; + *sibling = hw; + hw->parent_of_hw = parent; + } + + /* top of tree */ + if (parent != NULL) + { + struct hw *root = parent; + while (root->parent_of_hw != NULL) + root = root->parent_of_hw; + hw->root_of_hw = root; + } + + /* a unique identifier for the device on the parents bus */ + if (parent != NULL) + { + hw_unit_decode (parent, unit, &hw->unit_address_of_hw); + } + + /* Determine our path */ + if (parent != NULL) + hw->path_of_hw = full_name_of_hw (hw, NULL, 0); + else + hw->path_of_hw = "/"; + + /* create our base type */ + hw->base_of_hw = HW_ZALLOC (hw, struct hw_base_data); + hw->base_of_hw->finished_p = 0; + + /* our callbacks */ + set_hw_io_read_buffer (hw, panic_hw_io_read_buffer); + set_hw_io_write_buffer (hw, panic_hw_io_write_buffer); + set_hw_dma_read_buffer (hw, passthrough_hw_dma_read_buffer); + set_hw_dma_write_buffer (hw, passthrough_hw_dma_write_buffer); + set_hw_unit_decode (hw, generic_hw_unit_decode); + set_hw_unit_encode (hw, generic_hw_unit_encode); + set_hw_unit_address_to_attach_address (hw, generic_hw_unit_address_to_attach_address); + set_hw_unit_size_to_attach_size (hw, generic_hw_unit_size_to_attach_size); + set_hw_attach_address (hw, passthrough_hw_attach_address); + set_hw_detach_address (hw, passthrough_hw_detach_address); + set_hw_delete (hw, ignore_hw_delete); + + /* locate a descriptor */ + { + const struct hw_descriptor **table; + for (table = hw_descriptors; + *table != NULL; + table++) + { + const struct hw_descriptor *entry; + for (entry = *table; + entry->family != NULL; + entry++) + { + if (strcmp (family, entry->family) == 0) + { + hw->base_of_hw->descriptor = entry; + break; + } + } + } + if (hw->base_of_hw->descriptor == NULL) + { + hw_abort (parent, "Unknown device `%s'", family); + } + } + + /* Attach dummy ports */ + create_hw_alloc_data (hw); + create_hw_property_data (hw); + create_hw_port_data (hw); + create_hw_event_data (hw); + create_hw_handle_data (hw); + create_hw_instance_data (hw); + + return hw; +} + + +int +hw_finished_p (struct hw *me) +{ + return (me->base_of_hw->finished_p); +} + +void +hw_finish (struct hw *me) +{ + if (hw_finished_p (me)) + hw_abort (me, "Attempt to finish finished device"); + + /* Fill in the (hopefully) defined address/size cells values */ + if (hw_find_property (me, "#address-cells") != NULL) + me->nr_address_cells_of_hw_unit = + hw_find_integer_property (me, "#address-cells"); + else + me->nr_address_cells_of_hw_unit = 2; + if (hw_find_property (me, "#size-cells") != NULL) + me->nr_size_cells_of_hw_unit = + hw_find_integer_property (me, "#size-cells"); + else + me->nr_size_cells_of_hw_unit = 1; + + /* Fill in the (hopefully) defined trace variable */ + if (hw_find_property (me, "trace?") != NULL) + me->trace_of_hw_p = hw_find_boolean_property (me, "trace?"); + /* allow global variable to define default tracing */ + else if (! hw_trace_p (me) + && hw_find_property (hw_root (me), "global-trace?") != NULL + && hw_find_boolean_property (hw_root (me), "global-trace?")) + me->trace_of_hw_p = 1; + + + /* Allow the real device to override any methods */ + me->base_of_hw->descriptor->to_finish (me); + me->base_of_hw->finished_p = 1; +} + + +void +hw_delete (struct hw *me) +{ + /* give the object a chance to tidy up */ + me->base_of_hw->to_delete (me); + + delete_hw_instance_data (me); + delete_hw_handle_data (me); + delete_hw_event_data (me); + delete_hw_port_data (me); + delete_hw_property_data (me); + + /* now unlink us from the tree */ + if (hw_parent (me)) + { + struct hw **sibling = &hw_parent (me)->child_of_hw; + while (*sibling != NULL) + { + if (*sibling == me) + { + *sibling = me->sibling_of_hw; + me->sibling_of_hw = NULL; + me->parent_of_hw = NULL; + break; + } + } + } + + /* some sanity checks */ + if (hw_child (me) != NULL) + { + hw_abort (me, "attempt to delete device with children"); + } + if (hw_sibling (me) != NULL) + { + hw_abort (me, "attempt to delete device with siblings"); + } + + /* blow away all memory belonging to the device */ + delete_hw_alloc_data (me); + + /* finally */ + zfree (me->base_of_hw); + zfree (me); +} + + +/* Go through the devices various reg properties for those that + specify attach addresses */ + + +void +do_hw_attach_regs (struct hw *hw) +{ + static const char *(reg_property_names[]) = { + "attach-addresses", + "assigned-addresses", + "reg", + "alternate-reg" , + NULL + }; + const char **reg_property_name; + int nr_valid_reg_properties = 0; + for (reg_property_name = reg_property_names; + *reg_property_name != NULL; + reg_property_name++) + { + if (hw_find_property (hw, *reg_property_name) != NULL) + { + reg_property_spec reg; + int reg_entry; + for (reg_entry = 0; + hw_find_reg_array_property (hw, *reg_property_name, reg_entry, + ®); + reg_entry++) + { + unsigned_word attach_address; + int attach_space; + unsigned attach_size; + if (!hw_unit_address_to_attach_address (hw_parent (hw), + ®.address, + &attach_space, + &attach_address, + hw)) + continue; + if (!hw_unit_size_to_attach_size (hw_parent (hw), + ®.size, + &attach_size, hw)) + continue; + hw_attach_address (hw_parent (hw), + 0, + attach_space, attach_address, attach_size, + hw); + nr_valid_reg_properties++; + } + /* if first option matches don't try for any others */ + if (reg_property_name == reg_property_names) + break; + } + } +} diff --git a/sim/common/hw-base.h b/sim/common/hw-base.h new file mode 100644 index 00000000000..d6452d1b389 --- /dev/null +++ b/sim/common/hw-base.h @@ -0,0 +1,109 @@ +/* This file is part of the program psim. + + Copyright (C) 1994-1998, Andrew Cagney + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + + +#ifndef HW_BASE +#define HW_BASE + +/* Create a primative device */ + +struct hw *hw_create +(struct sim_state *sd, + struct hw *parent, + const char *family, + const char *name, + const char *unit, + const char *args); + + +/* Complete the creation of that device (finish overrides methods + using the set_hw_* operations below) */ + +void hw_finish +(struct hw *me); + +int hw_finished_p +(struct hw *me); + + +/* Delete the entire device */ + +void hw_delete +(struct hw *me); + + +/* Override device methods */ + +typedef void (hw_delete_callback) + (struct hw *me); + +#define set_hw_delete(hw, method) \ +((hw)->base_of_hw->to_delete = (method)) + + +/* ALLOC */ + +extern void create_hw_alloc_data +(struct hw *hw); +extern void delete_hw_alloc_data +(struct hw *hw); + + +/* PORTS */ + +extern void create_hw_port_data +(struct hw *hw); +extern void delete_hw_port_data +(struct hw *hw); + + +/* PROPERTIES */ + +extern void create_hw_property_data +(struct hw *hw); +extern void delete_hw_property_data +(struct hw *hw); + + +/* EVENTS */ + +extern void create_hw_event_data +(struct hw *hw); +extern void delete_hw_event_data +(struct hw *hw); + + +/* HANDLES */ + +extern void create_hw_handle_data +(struct hw *hw); +extern void delete_hw_handle_data +(struct hw *hw); + + +/* INSTANCES */ + +extern void create_hw_instance_data +(struct hw *hw); +extern void delete_hw_instance_data +(struct hw *hw); + + +#endif diff --git a/sim/common/hw-device.c b/sim/common/hw-device.c new file mode 100644 index 00000000000..c7f50e30953 --- /dev/null +++ b/sim/common/hw-device.c @@ -0,0 +1,66 @@ +/* This file is part of the program psim. + + Copyright (C) 1994-1998, Andrew Cagney + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + + +#include "hw-main.h" +#include "hw-base.h" + +#if HAVE_STDLIB_H +#include +#endif + +/* Address methods */ + +const hw_unit * +hw_unit_address (struct hw *me) +{ + return &me->unit_address_of_hw; +} + + +/* IOCTL: */ + +int +hw_ioctl (struct hw *me, + hw_ioctl_request request, + ...) +{ + int status; + va_list ap; + va_start(ap, request); + status = me->to_ioctl (me, request, ap); + va_end(ap); + return status; +} + +char * +hw_strdup (struct hw *me, const char *str) +{ + if (str != NULL) + { + char *dup = hw_zalloc (me, strlen (str) + 1); + strcpy (dup, str); + return dup; + } + else + { + return NULL; + } +} diff --git a/sim/common/hw-device.h b/sim/common/hw-device.h new file mode 100644 index 00000000000..2cbdc5adc46 --- /dev/null +++ b/sim/common/hw-device.h @@ -0,0 +1,535 @@ +/* This file is part of the program psim. + + Copyright (C) 1994-1998, Andrew Cagney + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + + +#ifndef HW_DEVICE_H +#define HW_DEVICE_H + +/* declared in sim-basics.h, this object is used everywhere */ +/* typedef struct _device device; */ + + +/* Introduction: + + As explained in earlier sections, the device, device instance, + property and ports lie at the heart of PSIM's device model. + + In the below a synopsis of the device object and the operations it + supports are given. + */ + + +/* Creation: + + The devices are created using a sequence of steps. In particular: + + o A tree framework is created. + + At this point, properties can be modified and extra + devices inserted (or removed?). + +#if LATER + + Any properties that have a run-time value (eg ihandle + or device instance pointer properties) are entered + into the device tree using a named reference to the + corresponding runtime object that is to be created. + +#endif + + o Real devices are created for all the dummy devices. + + A device can assume that all of its parents have been + initialized. + + A device can assume that all non run-time properties + have been initialized. + + As part of being created, the device normally attaches + itself to its parent bus. + +#if LATER + + Device instance data is initialized. + +#endif + +#if LATER + + o Any run-time properties are created. + +#endif + +#if MUCH_MUCH_LATER + + o Some devices, as part of their initialization + might want to refer to ihandle properties + in the device tree. + +#endif + + NOTES: + + o It is important to separate the creation + of an actual device from the creation + of the tree. The alternative creating + the device in two stages: As a separate + entity and then as a part of the tree. + +#if LATER + o Run-time properties can not be created + until after the devices in the tree + have been created. Hence an extra pass + for handling them. +#endif + + */ + +/* Relationships: + + A device is able to determine its relationship to other devices + within the tree. Operations include querying for a devices parent, + sibling, child, name, and path (from the root). + + */ + + +#define hw_parent(hw) ((hw)->parent_of_hw + 0) + +#define hw_sibling(hw) ((hw)->sibling_of_hw + 0) + +#define hw_child(hw) ((hw)->child_of_hw + 0) + + + +/* Herritage: + + */ + +#define hw_family(hw) ((hw)->family_of_hw + 0) + +#define hw_name(hw) ((hw)->name_of_hw + 0) + +#define hw_args(hw) ((hw)->args_of_hw + 0) + +#define hw_path(hw) ((hw)->path_of_hw + 0) + + + +/* Short cut to the root node of the tree */ + +#define hw_root(hw) ((hw)->root_of_hw + 0) + +/* Short cut back to the simulator object */ + +#define hw_system(hw) ((hw)->system_of_hw) + +/* For requests initiated by a CPU the cpu that initiated the request */ + +struct _sim_cpu *hw_system_cpu (struct hw *hw); + + +/* Device private data */ + +#define hw_data(hw) ((hw)->data_of_hw) + +#define set_hw_data(hw, value) \ +((hw)->data_of_hw = (value)) + + + +/* Perform a soft reset of the device */ + +typedef unsigned (hw_reset_method) + (struct hw *me); + +#define hw_reset(hw) ((hw)->to_reset (hw)) + +#define set_hw_reset(hw, method) \ +((hw)->to_reset = method) + + +/* Hardware operations: + + Connecting a parent to its children is a common bus. The parent + node is described as the bus owner and is responisble for + co-ordinating bus operations. On the bus, a SPACE:ADDR pair is used + to specify an address. A device that is both a bus owner (parent) + and bus client (child) are refered to as a bridging device. + + A child performing a data (DMA) transfer will pass its request to + the bus owner (the devices parent). The bus owner will then either + reflect the request to one of the other devices attached to the bus + (a child of the bus owner) or bridge the request up the tree to the + next bus. */ + + +/* Children attached to a bus can register (attach) themselves to + specific addresses on their attached bus. + + (A device may also be implicitly attached to certain bus + addresses). + + The SPACE:ADDR pair specify an address on the common bus that + connects the parent and child devices. */ + +typedef void (hw_attach_address_method) + (struct hw *me, + int level, + int space, + address_word addr, + address_word nr_bytes, + struct hw *client); /*callback/default*/ + +#define hw_attach_address(me, level, space, addr, nr_bytes, client) \ +((me)->to_attach_address (me, level, space, addr, nr_bytes, client)) + +#define set_hw_attach_address(hw, method) \ +((hw)->to_attach_address = (method)) + +typedef void (hw_detach_address_method) + (struct hw *me, + int level, + int space, + address_word addr, + address_word nr_bytes, + struct hw *client); /*callback/default*/ + +#define hw_detach_address(me, level, space, addr, nr_bytes, client) \ +((me)->to_detach_address (me, level, space, addr, nr_bytes, client)) + +#define set_hw_detach_address(hw, method) \ +((hw)->to_detach_address = (method)) + + +/* An IO operation from a parent to a child via the conecting bus. + + The SPACE:ADDR pair specify an address on the bus shared between + the parent and child devices. */ + +typedef unsigned (hw_io_read_buffer_method) + (struct hw *me, + void *dest, + int space, + unsigned_word addr, + unsigned nr_bytes); + +#define hw_io_read_buffer(hw, dest, space, addr, nr_bytes) \ +((hw)->to_io_read_buffer (hw, dest, space, addr, nr_bytes)) + +#define set_hw_io_read_buffer(hw, method) \ +((hw)->to_io_read_buffer = (method)) + +typedef unsigned (hw_io_write_buffer_method) + (struct hw *me, + const void *source, + int space, + unsigned_word addr, + unsigned nr_bytes); + +#define hw_io_write_buffer(hw, src, space, addr, nr_bytes) \ +((hw)->to_io_write_buffer (hw, src, space, addr, nr_bytes)) + +#define set_hw_io_write_buffer(hw, method) \ +((hw)->to_io_write_buffer = (method)) + + +/* Conversly, the device pci1000,1@1 may need to perform a dma transfer + into the cpu/memory core. Just as I/O moves towards the leaves, + dma transfers move towards the core via the initiating devices + parent nodes. The root device (special) converts the DMA transfer + into reads/writes to memory. + + The SPACE:ADDR pair specify an address on the common bus connecting + the parent and child devices. */ + +typedef unsigned (hw_dma_read_buffer_method) + (struct hw *bus, + void *dest, + int space, + unsigned_word addr, + unsigned nr_bytes); + +#define hw_dma_read_buffer(bus, dest, space, addr, nr_bytes) \ +((bus)->to_dma_read_buffer (bus, dest, space, addr, nr_bytes)) + +#define set_hw_dma_read_buffer(me, method) \ +((me)->to_dma_read_buffer = (method)) + +typedef unsigned (hw_dma_write_buffer_method) + (struct hw *bus, + const void *source, + int space, + unsigned_word addr, + unsigned nr_bytes, + int violate_read_only_section); + +#define hw_dma_write_buffer(bus, src, space, addr, nr_bytes, violate_ro) \ +((bus)->to_dma_write_buffer (bus, src, space, addr, nr_bytes, violate_ro)) + +#define set_hw_dma_write_buffer(me, method) \ +((me)->to_dma_write_buffer = (method)) + +/* Address/size specs for devices are encoded following a convention + similar to that used by OpenFirmware. In particular, an + address/size is packed into a sequence of up to four cell words. + The number of words determined by the number of {address,size} + cells attributes of the device. */ + +typedef struct _hw_unit { + int nr_cells; + unsigned_cell cells[4]; /* unused cells are zero */ +} hw_unit; + + +/* For the given bus, the number of address and size cells used in a + hw_unit. */ + +#define hw_unit_nr_address_cells(bus) ((bus)->nr_address_cells_of_hw_unit + 0) + +#define hw_unit_nr_size_cells(bus) ((bus)->nr_size_cells_of_hw_unit + 0) + + +/* For the given device, its identifying hw_unit address. + + Each device has an identifying hw_unit address. That address is + used when identifying one of a number of identical devices on a + common controller bus. ex fd0&fd1. */ + +const hw_unit *hw_unit_address +(struct hw *me); + + +/* Convert between a textual and the internal representation of a + hw_unit address/size. + + NOTE: A device asks its parent to translate between a hw_unit and + textual representation. This is because the textual address of a + device is specified using the parent busses notation. */ + +typedef int (hw_unit_decode_method) + (struct hw *bus, + const char *encoded, + hw_unit *unit); + +#define hw_unit_decode(bus, encoded, unit) \ +((bus)->to_unit_decode (bus, encoded, unit)) + +#define set_hw_unit_decode(hw, method) \ +((hw)->to_unit_decode = (method)) + +typedef int (hw_unit_encode_method) + (struct hw *bus, + const hw_unit *unit, + char *encoded, + int sizeof_buf); + +#define hw_unit_encode(bus, unit, encoded, sizeof_encoded) \ +((bus)->to_unit_encode (bus, unit, encoded, sizeof_encoded)) + +#define set_hw_unit_encode(hw, method) \ +((hw)->to_unit_encode = (method)) + + +/* As the bus that the device is attached too, to translate a devices + hw_unit address/size into a form suitable for an attach address + call. + + Return a zero result if the address should be ignored when looking + for attach addresses. */ + +typedef int (hw_unit_address_to_attach_address_method) + (struct hw *bus, + const hw_unit *unit_addr, + int *attach_space, + unsigned_word *attach_addr, + struct hw *client); + +#define hw_unit_address_to_attach_address(bus, unit_addr, attach_space, attach_addr, client) \ +((bus)->to_unit_address_to_attach_address (bus, unit_addr, attach_space, attach_addr, client)) + +#define set_hw_unit_address_to_attach_address(hw, method) \ +((hw)->to_unit_address_to_attach_address = (method)) + +typedef int (hw_unit_size_to_attach_size_method) + (struct hw *bus, + const hw_unit *unit_size, + unsigned *attach_size, + struct hw *client); + +#define hw_unit_size_to_attach_size(bus, unit_size, attach_size, client) \ +((bus)->to_unit_size_to_attach_size (bus, unit_size, attach_size, client)) + +#define set_hw_unit_size_to_attach_size(hw, method) \ +((hw)->to_unit_size_to_attach_size = (method)) + + +extern char *hw_strdup (struct hw *me, const char *str); + + +/* Utilities: + + */ + +/* IOCTL:: + + Often devices require `out of band' operations to be performed. + For instance a pal device may need to notify a PCI bridge device + that an interrupt ack cycle needs to be performed on the PCI bus. + Within PSIM such operations are performed by using the generic + ioctl call <>. + + */ + +typedef enum { + hw_ioctl_break, /* unsigned_word requested_break */ + hw_ioctl_set_trace, /* void */ + hw_ioctl_create_stack, /* unsigned_word *sp, char **argv, char **envp */ + hw_ioctl_change_media, /* const char *new_image (possibly NULL) */ + nr_hw_ioctl_requests, +} hw_ioctl_request; + +typedef int (hw_ioctl_method) + (struct hw *me, + hw_ioctl_request request, + va_list ap); + +int hw_ioctl +(struct hw *me, + hw_ioctl_request request, + ...); + + +/* Error reporting:: + + So that errors originating from devices appear in a consistent + format, the <> function can be used. Formats and + outputs the error message before aborting the simulation + + Devices should use this function to abort the simulation except + when the abort reason leaves the simulation in a hazardous + condition (for instance a failed malloc). + + */ + +void hw_abort +(struct hw *me, + const char *fmt, + ...) __attribute__ ((format (printf, 2, 3))); + +void hw_vabort +(struct hw *me, + const char *fmt, + va_list ap); + +void hw_halt +(struct hw *me, + int reason, + int status); + + +#define hw_trace_p(hw) ((hw)->trace_of_hw_p + 0) + +void hw_trace +(struct hw *me, + const char *fmt, + ...) __attribute__ ((format (printf, 2, 3))); + +#define HW_TRACE(ARGS) \ +do { \ + if (hw_trace_p (me)) \ + { \ + hw_trace ARGS; \ + } \ +} while (0) + + +/* Some of the related functions require specific types */ + +struct hw_property_data; +struct hw_port_data; +struct hw_base_data; +struct hw_alloc_data; +struct hw_event_data; +struct hw_handle_data; +struct hw_instance_data; + +/* Finally the hardware device - keep your grubby little mits off of + these internals! :-) */ + +struct hw { + + /* our relatives */ + struct hw *parent_of_hw; + struct hw *sibling_of_hw; + struct hw *child_of_hw; + + /* our identity */ + const char *name_of_hw; + const char *family_of_hw; + const char *args_of_hw; + const char *path_of_hw; + + /* our data */ + void *data_of_hw; + + /* hot links */ + struct hw *root_of_hw; + struct sim_state *system_of_hw; + + /* identifying data */ + hw_unit unit_address_of_hw; + int nr_address_cells_of_hw_unit; + int nr_size_cells_of_hw_unit; + + /* Soft reset */ + hw_reset_method *to_reset; + + /* Basic callbacks */ + hw_io_read_buffer_method *to_io_read_buffer; + hw_io_write_buffer_method *to_io_write_buffer; + hw_dma_read_buffer_method *to_dma_read_buffer; + hw_dma_write_buffer_method *to_dma_write_buffer; + hw_attach_address_method *to_attach_address; + hw_detach_address_method *to_detach_address; + + /* More complicated callbacks */ + hw_ioctl_method *to_ioctl; + int trace_of_hw_p; + + /* address callbacks */ + hw_unit_decode_method *to_unit_decode; + hw_unit_encode_method *to_unit_encode; + hw_unit_address_to_attach_address_method *to_unit_address_to_attach_address; + hw_unit_size_to_attach_size_method *to_unit_size_to_attach_size; + + /* related data */ + struct hw_property_data *properties_of_hw; + struct hw_port_data *ports_of_hw; + struct hw_base_data *base_of_hw; + struct hw_alloc_data *alloc_of_hw; + struct hw_event_data *events_of_hw; + struct hw_handle_data *handles_of_hw; + struct hw_instance_data *instances_of_hw; + +}; + + +#endif diff --git a/sim/common/hw-events.c b/sim/common/hw-events.c new file mode 100644 index 00000000000..31c5a4026ab --- /dev/null +++ b/sim/common/hw-events.c @@ -0,0 +1,263 @@ +/* Hardware event manager. + Copyright (C) 1998 Free Software Foundation, Inc. + Contributed by Cygnus Support. + +This file is part of GDB, the GNU debugger. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + + +#include "hw-main.h" +#include "hw-base.h" + +#include "sim-events.h" + + +/* The hw-events object is implemented using sim-events */ + +struct hw_event { + void *data; + struct hw *me; + hw_event_callback *callback; + sim_event *real; + struct hw_event_data *entry; +}; + +struct hw_event_data { + struct hw_event event; + struct hw_event_data *next; +}; + +void +create_hw_event_data (struct hw *me) +{ + if (me->events_of_hw != NULL) + hw_abort (me, "stray events"); + /* NOP */ +} + +void +delete_hw_event_data (struct hw *me) +{ + if (me->events_of_hw != NULL) + hw_abort (me, "stray events"); +} + + +/* Pass the H/W event onto the real callback */ + +static void +bounce_hw_event (SIM_DESC sd, + void *data) +{ + /* save the data */ + struct hw_event_data *entry = (struct hw_event_data *) data; + struct hw *me = entry->event.me; + void *event_data = entry->event.data; + hw_event_callback *callback = entry->event.callback; + struct hw_event_data **prev = &me->events_of_hw; + while ((*prev) != entry) + prev = &(*prev)->next; + (*prev) = entry->next; + hw_free (me, entry); + callback (me, event_data); /* may not return */ +} + + + +/* Map onto the event functions */ + +struct hw_event * +hw_event_queue_schedule (struct hw *me, + signed64 delta_time, + hw_event_callback *callback, + void *data) +{ + struct hw_event *event; + va_list dummy; + event = hw_event_queue_schedule_vtracef (me, delta_time, callback, data, + NULL, dummy); + return event; +} + +struct hw_event * +hw_event_queue_schedule_tracef (struct hw *me, + signed64 delta_time, + hw_event_callback *callback, + void *data, + const char *fmt, + ...) +{ + struct hw_event *event; + va_list ap; + va_start (ap, fmt); + event = hw_event_queue_schedule_vtracef (me, delta_time, callback, data, fmt, ap); + va_end (ap); + return event; +} + +struct hw_event * +hw_event_queue_schedule_vtracef (struct hw *me, + signed64 delta_time, + hw_event_callback *callback, + void *data, + const char *fmt, + va_list ap) +{ + struct hw_event_data *entry = HW_ZALLOC (me, struct hw_event_data); + entry->next = me->events_of_hw; + me->events_of_hw = entry; + /* fill it in */ + entry->event.entry = entry; + entry->event.data = data; + entry->event.callback = callback; + entry->event.me = me; + entry->event.real = sim_events_schedule_vtracef (hw_system (me), + delta_time, + bounce_hw_event, + entry, + fmt, ap); + return &entry->event; +} + + +void +hw_event_queue_deschedule (struct hw *me, + struct hw_event *event_to_remove) +{ +/* ZAP the event but only if it is still in the event queue. Note + that event_to_remove is only de-referenced after its validity has + been confirmed. */ + struct hw_event_data **prev; + for (prev = &me->events_of_hw; + (*prev) != NULL; + prev = &(*prev)->next) + { + struct hw_event_data *entry = (*prev); + if (&entry->event == event_to_remove) + { + sim_events_deschedule (hw_system (me), + entry->event.real); + (*prev) = entry->next; + hw_free (me, entry); + return; + } + } +} + + +signed64 +hw_event_queue_time (struct hw *me) +{ + return sim_events_time (hw_system (me)); +} + + +/* Only worry about this compling on ANSI systems. + Build with `make test-hw-events' in sim/ directory*/ + +#if defined (MAIN) +#include "sim-main.h" +#include +#include + +static void +test_handler (struct hw *me, + void *data) +{ + int *n = data; + if (*n != hw_event_queue_time (me)) + abort (); + *n = -(*n); +} + +int +main (int argc, + char **argv) +{ + host_callback *cb = ZALLOC (host_callback); + struct sim_state *sd = sim_state_alloc (0, cb); + struct hw *me = ZALLOC (struct hw); + sim_pre_argv_init (sd, "test-hw-events"); + sim_post_argv_init (sd); + me->system_of_hw = sd; + + printf ("Create hw-event-data\n"); + { + create_hw_alloc_data (me); + create_hw_event_data (me); + delete_hw_event_data (me); + delete_hw_alloc_data (me); + } + + printf ("Create hw-events\n"); + { + struct hw_event *a; + struct hw_event *b; + struct hw_event *c; + struct hw_event *d; + create_hw_alloc_data (me); + create_hw_event_data (me); + a = hw_event_queue_schedule (me, 0, NULL, NULL); + b = hw_event_queue_schedule (me, 1, NULL, NULL); + c = hw_event_queue_schedule (me, 2, NULL, NULL); + d = hw_event_queue_schedule (me, 1, NULL, NULL); + hw_event_queue_deschedule (me, c); + hw_event_queue_deschedule (me, b); + hw_event_queue_deschedule (me, a); + hw_event_queue_deschedule (me, d); + c = HW_ZALLOC (me, struct hw_event); + hw_event_queue_deschedule (me, b); /* OOPS! */ + hw_free (me, c); + delete_hw_event_data (me); + delete_hw_alloc_data (me); + } + + printf ("Schedule hw-events\n"); + { + struct hw_event **e; + int *n; + int i; + int nr = 4; + e = HW_NZALLOC (me, struct hw_event *, nr); + n = HW_NZALLOC (me, int, nr); + create_hw_alloc_data (me); + create_hw_event_data (me); + for (i = 0; i < nr; i++) + { + n[i] = i; + e[i] = hw_event_queue_schedule (me, i, test_handler, &n[i]); + } + sim_events_preprocess (sd, 1, 1); + for (i = 0; i < nr; i++) + { + if (sim_events_tick (sd)) + sim_events_process (sd); + } + for (i = 0; i < nr; i++) + { + if (n[i] != -i) + abort (); + hw_event_queue_deschedule (me, e[i]); + } + hw_free (me, n); + hw_free (me, e); + delete_hw_event_data (me); + delete_hw_alloc_data (me); + } + + return 0; +} +#endif diff --git a/sim/common/hw-events.h b/sim/common/hw-events.h new file mode 100644 index 00000000000..a9b6f8b5dc0 --- /dev/null +++ b/sim/common/hw-events.h @@ -0,0 +1,61 @@ +/* Hardware event manager. + Copyright (C) 1998 Free Software Foundation, Inc. + Contributed by Cygnus Support. + +This file is part of GDB, the GNU debugger. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef HW_EVENTS_H +#define HW_EVENTS_H + +/* Event manager customized for hardware models. + + This interface is discussed further in sim-events.h. */ + +struct hw_event; +typedef void (hw_event_callback) (struct hw *me, void *data); + +struct hw_event *hw_event_queue_schedule +(struct hw *me, + signed64 delta_time, + hw_event_callback *handler, + void *data); + +struct hw_event *hw_event_queue_schedule_tracef +(struct hw *me, + signed64 delta_time, + hw_event_callback *handler, + void *data, + const char *fmt, + ...) __attribute__ ((format (printf, 5, 6))); + +struct hw_event *hw_event_queue_schedule_vtracef +(struct hw *me, + signed64 delta_time, + hw_event_callback *handler, + void *data, + const char *fmt, + va_list ap); + + +void hw_event_queue_deschedule +(struct hw *me, + struct hw_event *event_to_remove); + +signed64 hw_event_queue_time +(struct hw *me); + +#endif diff --git a/sim/common/hw-handles.c b/sim/common/hw-handles.c new file mode 100644 index 00000000000..9400ca82e92 --- /dev/null +++ b/sim/common/hw-handles.c @@ -0,0 +1,237 @@ +/* This file is part of the program psim. + + Copyright (C) 1994-1995,1997-1998, Andrew Cagney + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + + +#include "hw-main.h" +#include "hw-base.h" + + +struct hw_handle_mapping { + cell_word external; + struct hw *phandle; + struct hw_instance *ihandle; + struct hw_handle_mapping *next; +}; + + +struct hw_handle_data { + int nr_mappings; + struct hw_handle_mapping *mappings; +}; + +void +create_hw_handle_data (struct hw *hw) +{ + if (hw_parent (hw) == NULL) + { + hw->handles_of_hw = HW_ZALLOC (hw, struct hw_handle_data); + } + else + { + hw->handles_of_hw = hw_root (hw)->handles_of_hw; + } +} + +void +delete_hw_handle_data (struct hw *hw) +{ + /* NULL */ +} + + + +#if 0 +void +hw_handle_init (struct hw *hw) +{ + struct hw_handle_mapping *current_map = db->mappings; + if (current_map != NULL) + { + db->nr_mappings = db->mappings->external; + /* verify that the mappings that were not removed are in + sequence down to nr 1 */ + while (current_map->next != NULL) + { + if (current_map->external != current_map->next->external + 1) + error ("hw_handle: hw_handle database possibly corrupt"); + current_map = current_map->next; + } + ASSERT (current_map->next == NULL); + if (current_map->external != 1) + error ("hw_handle: hw_handle database possibly corrupt"); + } + else + { + db->nr_mappings = 0; + } +} +#endif + + +struct hw_instance * +hw_handle_ihandle2 (struct hw *hw, + cell_word external) +{ + struct hw_handle_data *db = hw->handles_of_hw; + struct hw_handle_mapping *current_map = db->mappings; + while (current_map != NULL) + { + if (current_map->external == external) + return current_map->ihandle; + current_map = current_map->next; + } + return (void*)0; +} + + +struct hw * +hw_handle_phandle2 (struct hw *hw, + cell_word external) +{ + struct hw_handle_data *db = hw->handles_of_hw; + struct hw_handle_mapping *current_map = db->mappings; + while (current_map != NULL) + { + if (current_map->external == external) + return current_map->phandle; + current_map = current_map->next; + } + return (void*)0; +} + + +cell_word +hw_handle_2ihandle (struct hw *hw, + struct hw_instance *internal) +{ + struct hw_handle_data *db = hw->handles_of_hw; + struct hw_handle_mapping *current_map = db->mappings; + while (current_map != NULL) + { + if (current_map->ihandle == internal) + return current_map->external; + current_map = current_map->next; + } + return 0; +} + + +cell_word +hw_handle_2phandle (struct hw *hw, + struct hw *internal) +{ + struct hw_handle_data *db = hw->handles_of_hw; + struct hw_handle_mapping *current_map = db->mappings; + while (current_map != NULL) + { + if (current_map->phandle == internal) + return current_map->external; + current_map = current_map->next; + } + return 0; +} + + +void +hw_handle_add_ihandle (struct hw *hw, + struct hw_instance *internal) +{ + struct hw_handle_data *db = hw->handles_of_hw; + if (hw_handle_2ihandle (hw, internal) != 0) + { + hw_abort (hw, "attempting to add an ihandle already in the data base"); + } + else + { + /* insert at the front making things in decending order */ + struct hw_handle_mapping *new_map = ZALLOC (struct hw_handle_mapping); + new_map->next = db->mappings; + new_map->ihandle = internal; + db->nr_mappings += 1; + new_map->external = db->nr_mappings; + db->mappings = new_map; + } +} + + +void +hw_handle_add_phandle (struct hw *hw, + struct hw *internal) +{ + struct hw_handle_data *db = hw->handles_of_hw; + if (hw_handle_2phandle (hw, internal) != 0) + { + hw_abort (hw, "attempting to add a phandle already in the data base"); + } + else + { + /* insert at the front making things in decending order */ + struct hw_handle_mapping *new_map = ZALLOC (struct hw_handle_mapping); + new_map->next = db->mappings; + new_map->phandle = internal; + db->nr_mappings += 1; + new_map->external = db->nr_mappings; + db->mappings = new_map; + } +} + + +void +hw_handle_remove_ihandle (struct hw *hw, + struct hw_instance *internal) +{ + struct hw_handle_data *db = hw->handles_of_hw; + struct hw_handle_mapping **current_map = &db->mappings; + while (*current_map != NULL) + { + if ((*current_map)->ihandle == internal) + { + struct hw_handle_mapping *delete = *current_map; + *current_map = delete->next; + zfree (delete); + return; + } + current_map = &(*current_map)->next; + } + hw_abort (hw, "attempt to remove nonexistant ihandle"); +} + + +void +hw_handle_remove_phandle (struct hw *hw, + struct hw *internal) +{ + struct hw_handle_data *db = hw->handles_of_hw; + struct hw_handle_mapping **current_map = &db->mappings; + while (*current_map != NULL) + { + if ((*current_map)->phandle == internal) + { + struct hw_handle_mapping *delete = *current_map; + *current_map = delete->next; + zfree (delete); + return; + } + current_map = &(*current_map)->next; + } + hw_abort (hw, "attempt to remove nonexistant phandle"); +} + + diff --git a/sim/common/hw-handles.h b/sim/common/hw-handles.h new file mode 100644 index 00000000000..087c9d02e75 --- /dev/null +++ b/sim/common/hw-handles.h @@ -0,0 +1,63 @@ +/* This file is part of the program psim. + + Copyright (C) 1994-1995,1997-1998, Andrew Cagney + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + + +#ifndef HW_HANDLES_H +#define HW_HANDLES_H + + +/* Export a capability (handle) data base that maps between internal + data values and those given to a simulation. */ + + +cell_word hw_handle_2ihandle +(struct hw *db, + struct hw_instance *instance); + +struct hw_instance *hw_handle_ihandle2 +(struct hw *db, + cell_word external); + +void hw_handle_add_ihandle +(struct hw *db, + struct hw_instance *instance); + +void hw_handle_remove_ihandle +(struct hw *db, + struct hw_instance *instance); + + +cell_word hw_handle_2phandle +(struct hw *db, + struct hw *hw); + +struct hw *hw_handle_phandle2 +(struct hw *db, + cell_word external); + +void hw_handle_add_phandle +(struct hw *db, + struct hw *hw); + +void hw_handle_remove_phandle +(struct hw *db, + struct hw *hw); + +#endif diff --git a/sim/common/hw-instances.c b/sim/common/hw-instances.c new file mode 100644 index 00000000000..613f8198e54 --- /dev/null +++ b/sim/common/hw-instances.c @@ -0,0 +1,285 @@ +/* This file is part of the program psim. + + Copyright (C) 1994-1998, Andrew Cagney + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + + +#include "hw-main.h" +#include "hw-base.h" + +#include "sim-assert.h" + +struct hw_instance_data { + hw_finish_instance_method *to_finish; + struct hw_instance *instances; +}; + +static hw_finish_instance_method abort_hw_finish_instance; + +void +create_hw_instance_data (struct hw *me) +{ + me->instances_of_hw = HW_ZALLOC (me, struct hw_instance_data); + set_hw_finish_instance (me, abort_hw_finish_instance); +} + +void +delete_hw_instance_data (struct hw *me) +{ + /* NOP */ +} + + +static void +abort_hw_finish_instance (struct hw *hw, + struct hw_instance *instance) +{ + hw_abort (hw, "no instance finish method"); +} + +void +set_hw_finish_instance (struct hw *me, + hw_finish_instance_method *finish) +{ + me->instances_of_hw->to_finish = finish; +} + + +#if 0 +void +clean_hw_instances (struct hw *me) +{ + struct hw_instance **instance = &me->instances; + while (*instance != NULL) + { + struct hw_instance *old_instance = *instance; + hw_instance_delete (old_instance); + instance = &me->instances; + } +} +#endif + + +void +hw_instance_delete (struct hw_instance *instance) +{ +#if 1 + hw_abort (hw_instance_hw (instance), "not implemented"); +#else + struct hw *me = hw_instance_hw (instance); + if (instance->to_instance_delete == NULL) + hw_abort (me, "no delete method"); + instance->method->delete(instance); + if (instance->args != NULL) + zfree (instance->args); + if (instance->path != NULL) + zfree (instance->path); + if (instance->child == NULL) + { + /* only remove leaf nodes */ + struct hw_instance **curr = &me->instances; + while (*curr != instance) + { + ASSERT (*curr != NULL); + curr = &(*curr)->next; + } + *curr = instance->next; + } + else + { + /* check it isn't in the instance list */ + struct hw_instance *curr = me->instances; + while (curr != NULL) + { + ASSERT(curr != instance); + curr = curr->next; + } + /* unlink the child */ + ASSERT (instance->child->parent == instance); + instance->child->parent = NULL; + } + cap_remove (me->ihandles, instance); + zfree (instance); +#endif +} + + +static int +panic_hw_instance_read (struct hw_instance *instance, + void *addr, + unsigned_word len) +{ + hw_abort (hw_instance_hw (instance), "no read method"); + return -1; +} + + + +static int +panic_hw_instance_write (struct hw_instance *instance, + const void *addr, + unsigned_word len) +{ + hw_abort (hw_instance_hw (instance), "no write method"); + return -1; +} + + +static int +panic_hw_instance_seek (struct hw_instance *instance, + unsigned_word pos_hi, + unsigned_word pos_lo) +{ + hw_abort (hw_instance_hw (instance), "no seek method"); + return -1; +} + + +int +hw_instance_call_method (struct hw_instance *instance, + const char *method_name, + int n_stack_args, + unsigned_cell stack_args[/*n_stack_args*/], + int n_stack_returns, + unsigned_cell stack_returns[/*n_stack_args*/]) +{ +#if 1 + hw_abort (hw_instance_hw (instance), "not implemented"); + return -1; +#else + struct hw *me = instance->owner; + const hw_instance_methods *method = instance->method->methods; + if (method == NULL) + { + hw_abort (me, "no methods (want %s)", method_name); + } + while (method->name != NULL) + { + if (strcmp(method->name, method_name) == 0) + { + return method->method (instance, + n_stack_args, stack_args, + n_stack_returns, stack_returns); + } + method++; + } + hw_abort (me, "no %s method", method_name); + return 0; +#endif +} + + +#define set_hw_instance_read(instance, method)\ +((instance)->to_instance_read = (method)) + +#define set_hw_instance_write(instance, method)\ +((instance)->to_instance_write = (method)) + +#define set_hw_instance_seek(instance, method)\ +((instance)->to_instance_seek = (method)) + + +#if 0 +static void +set_hw_instance_finish (struct hw *me, + hw_instance_finish_method *method) +{ + if (me->instances_of_hw == NULL) + me->instances_of_hw = HW_ZALLOC (me, struct hw_instance_data); + me->instances_of_hw->to_finish = method; +} +#endif + + +struct hw_instance * +hw_instance_create (struct hw *me, + struct hw_instance *parent, + const char *path, + const char *args) +{ + struct hw_instance *instance = ZALLOC (struct hw_instance); + /*instance->unit*/ + /* link this instance into the devices list */ + instance->hw_of_instance = me; + instance->parent_of_instance = NULL; + /* link this instance into the front of the devices instance list */ + instance->sibling_of_instance = me->instances_of_hw->instances; + me->instances_of_hw->instances = instance; + if (parent != NULL) + { + ASSERT (parent->child_of_instance == NULL); + parent->child_of_instance = instance; + instance->parent_of_instance = parent; + } + instance->args_of_instance = hw_strdup (me, args); + instance->path_of_instance = hw_strdup (me, path); + set_hw_instance_read (instance, panic_hw_instance_read); + set_hw_instance_write (instance, panic_hw_instance_write); + set_hw_instance_seek (instance, panic_hw_instance_seek); + hw_handle_add_ihandle (me, instance); + me->instances_of_hw->to_finish (me, instance); + return instance; +} + + +struct hw_instance * +hw_instance_interceed (struct hw_instance *parent, + const char *path, + const char *args) +{ +#if 1 + return NULL; +#else + struct hw_instance *instance = ZALLOC (struct hw_instance); + /*instance->unit*/ + /* link this instance into the devices list */ + if (me != NULL) + { + ASSERT (parent == NULL); + instance->hw_of_instance = me; + instance->parent_of_instance = NULL; + /* link this instance into the front of the devices instance list */ + instance->sibling_of_instance = me->instances_of_hw->instances; + me->instances_of_hw->instances = instance; + } + if (parent != NULL) + { + struct hw_instance **previous; + ASSERT (parent->child_of_instance == NULL); + parent->child_of_instance = instance; + instance->owner = parent->owner; + instance->parent_of_instance = parent; + /* in the devices instance list replace the parent instance with + this one */ + instance->next = parent->next; + /* replace parent with this new node */ + previous = &instance->owner->instances; + while (*previous != parent) + { + ASSERT (*previous != NULL); + previous = &(*previous)->next; + } + *previous = instance; + } + instance->data = data; + instance->args = (args == NULL ? NULL : (char *) strdup(args)); + instance->path = (path == NULL ? NULL : (char *) strdup(path)); + cap_add (instance->owner->ihandles, instance); + return instance; +#endif +} diff --git a/sim/common/hw-instances.h b/sim/common/hw-instances.h new file mode 100644 index 00000000000..6d27b114873 --- /dev/null +++ b/sim/common/hw-instances.h @@ -0,0 +1,157 @@ +/* This file is part of the program psim. + + Copyright (C) 1994-1998, Andrew Cagney + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + + +#ifndef HW_INSTANCES_H +#define HW_INSTANCES_H + +/* Instances: + + As with IEEE1275, a device can be opened, creating an instance. + Instances provide more abstract interfaces to the underlying + hardware. For example, the instance methods for a disk may include + code that is able to interpret file systems found on disks. Such + methods would there for allow the manipulation of files on the + disks file system. The operations would be implemented using the + basic block I/O model provided by the disk. + + This model includes methods that faciliate the creation of device + instance and (should a given device support it) standard operations + on those instances. + + */ + + +struct hw_instance; + + +typedef void (hw_finish_instance_method) + (struct hw *hw, + struct hw_instance *); + +extern void set_hw_finish_instance +(struct hw *hw, + hw_finish_instance_method *method); + + +/* construct an instance of the hardware */ + +struct hw_instance *hw_instance_create +(struct hw *hw, + struct hw_instance *parent, + const char *path, + const char *args); + +struct hw_instance *hw_instance_interceed +(struct hw_instance *parent, + const char *path, + const char *args); + +void hw_instance_delete +(struct hw_instance *instance); + + +/* methods applied to an instance of the hw */ + +typedef int (hw_instance_read_method) + (struct hw_instance *instance, + void *addr, + unsigned_cell len); + +#define hw_instance_read(instance, addr, len) \ +((instance)->to_instance_read ((instance), (addr), (len))) + +#define set_hw_instance_read(instance, method) \ +((instance)->to_instance_read = (method)) + + +typedef int (hw_instance_write_method) + (struct hw_instance *instance, + const void *addr, + unsigned_cell len); + +#define hw_instance_write(instance, addr, len) \ +((instance)->to_instance_write ((instance), (addr), (len))) + +#define set_hw_instance_write(instance, method) \ +((instance)->to_instance_write = (method)) + + +typedef int (hw_instance_seek_method) + (struct hw_instance *instance, + unsigned_cell pos_hi, + unsigned_cell pos_lo); + +#define hw_instance_seek(instance, pos_hi, pos_lo) \ +((instance)->to_instance_seek ((instance), (pos_hi), (pos_lo))); + +#define set_hw_instance_seek(instance, method) \ +((instance)->to_instance_seek = (method)) + + +int hw_instance_call_method +(struct hw_instance *instance, + const char *method, + int n_stack_args, + unsigned_cell stack_args[/*n_stack_args + 1(NULL)*/], + int n_stack_returns, + unsigned_cell stack_returns[/*n_stack_returns + 1(NULL)*/]); + + + +/* the definition of the instance */ + +#define hw_instance_hw(instance) ((instance)->hw_of_instance + 0) + +#define hw_instance_path(instance) ((instance)->path_of_instance + 0) + +#define hw_instance_args(instance) ((instance)->args_of_instance) + +#define hw_instance_data(instance) ((instance)->data_of_instance) + +#define hw_instance_system(instance) (hw_system (hw_instance_hw (instance))) + + + +/* Finally an instance of a hardware device - keep your grubby little + mits off of these internals! :-) */ + +struct hw_instance { + + void *data_of_instance; + char *args_of_instance; + char *path_of_instance; + + /* the device that owns the instance */ + struct hw *hw_of_instance; + struct hw_instance *sibling_of_instance; + + /* interposed instance */ + struct hw_instance *parent_of_instance; + struct hw_instance *child_of_instance; + + /* methods */ + hw_instance_read_method *to_instance_read; + hw_instance_write_method *to_instance_write; + hw_instance_seek_method *to_instance_seek; + +}; + +#endif diff --git a/sim/common/hw-main.h b/sim/common/hw-main.h new file mode 100644 index 00000000000..3c086c19b98 --- /dev/null +++ b/sim/common/hw-main.h @@ -0,0 +1,73 @@ +/* Common hardware header file. + Copyright (C) 1998 Free Software Foundation, Inc. + Contributed by Andrew Cagney and Cygnus Support. + +This file is part of GDB, the GNU debugger. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + + +#ifndef HW_MAIN +#define HW_MAIN + +/* establish a type system */ +#include "sim-basics.h" + +/* construct a hw device */ +#include "hw-device.h" +#include "hw-properties.h" +#include "hw-events.h" +#include "hw-alloc.h" +#include "hw-instances.h" +#include "hw-handles.h" +#include "hw-ports.h" + +/* Description of a hardware device */ + +typedef void (hw_finish_method) + (struct hw *me); + +struct hw_descriptor { + const char *family; + hw_finish_method *to_finish; +}; + +/* Helper functions to make the implementation of a device easier */ + +/* Go through the devices reg properties and look for those specifying + an address to attach various registers to */ + +void do_hw_attach_regs (struct hw *me); + +/* Perform a polling read on FD returning either the number of bytes + or a hw_io status code that indicates the reason for the read + failure */ + +enum { + HW_IO_EOF = -1, HW_IO_NOT_READY = -2, /* See: IEEE 1275 */ +}; + +typedef int (do_hw_poll_read_method) + (SIM_DESC sd, int, char *, int); + +int do_hw_poll_read +(struct hw *me, + do_hw_poll_read_method *read, + int sim_io_fd, + void *buf, + unsigned size_of_buf); + + +#endif diff --git a/sim/common/hw-ports.c b/sim/common/hw-ports.c new file mode 100644 index 00000000000..b7dc9850926 --- /dev/null +++ b/sim/common/hw-ports.c @@ -0,0 +1,339 @@ +/* Hardware ports. + Copyright (C) 1998 Free Software Foundation, Inc. + Contributed by Andrew Cagney and Cygnus Solutions. + +This file is part of GDB, the GNU debugger. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + + +#include "hw-main.h" +#include "hw-base.h" + +#ifdef HAVE_STDLIB_H +#include +#endif + +#ifdef HAVE_STRING_H +#include +#else +#ifdef HAVE_STRINGS_H +#include +#endif +#endif + +#include + +#define TRACE(x,y) + + +struct hw_port_edge { + int my_port; + struct hw *dest; + int dest_port; + struct hw_port_edge *next; + object_disposition disposition; +}; + +struct hw_port_data { + hw_port_event_method *to_port_event; + const struct hw_port_descriptor *ports; + struct hw_port_edge *edges; +}; + +const struct hw_port_descriptor empty_hw_ports[] = { + { NULL, }, +}; + +static void +panic_hw_port_event (struct hw *me, + int my_port, + struct hw *source, + int source_port, + int level) +{ + hw_abort (me, "no port method"); +} + +void +create_hw_port_data (struct hw *me) +{ + me->ports_of_hw = HW_ZALLOC (me, struct hw_port_data); + set_hw_port_event (me, panic_hw_port_event); + set_hw_ports (me, empty_hw_ports); +} + +void +delete_hw_port_data (struct hw *me) +{ + hw_free (me, me->ports_of_hw); + me->ports_of_hw = NULL; +} + +void +set_hw_ports (struct hw *me, + const struct hw_port_descriptor ports[]) +{ + me->ports_of_hw->ports = ports; +} + +void +set_hw_port_event (struct hw *me, + hw_port_event_method *port_event) +{ + me->ports_of_hw->to_port_event = port_event; +} + + +static void +attach_hw_port_edge (struct hw *me, + struct hw_port_edge **list, + int my_port, + struct hw *dest, + int dest_port, + object_disposition disposition) +{ + struct hw_port_edge *new_edge = HW_ZALLOC (me, struct hw_port_edge); + new_edge->my_port = my_port; + new_edge->dest = dest; + new_edge->dest_port = dest_port; + new_edge->next = *list; + new_edge->disposition = disposition; + *list = new_edge; +} + + +static void +detach_hw_port_edge (struct hw *me, + struct hw_port_edge **list, + int my_port, + struct hw *dest, + int dest_port) +{ + while (*list != NULL) + { + struct hw_port_edge *old_edge = *list; + if (old_edge->dest == dest + && old_edge->dest_port == dest_port + && old_edge->my_port == my_port) + { + if (old_edge->disposition == permenant_object) + hw_abort (me, "attempt to delete permenant port edge"); + *list = old_edge->next; + hw_free (me, old_edge); + return; + } + } + hw_abort (me, "attempt to delete unattached port"); +} + + +#if 0 +static void +clean_hw_port_edges (struct hw_port_edge **list) +{ + while (*list != NULL) + { + struct hw_port_edge *old_edge = *list; + switch (old_edge->disposition) + { + case permenant_object: + list = &old_edge->next; + break; + case temporary_object: + *list = old_edge->next; + hw_free (me, old_edge); + break; + } + } +} +#endif + + +/* Ports: */ + +void +hw_port_event (struct hw *me, + int my_port, + int level) +{ + int found_an_edge = 0; + struct hw_port_edge *edge; + /* device's lines directly connected */ + for (edge = me->ports_of_hw->edges; + edge != NULL; + edge = edge->next) + { + if (edge->my_port == my_port) + { + edge->dest->ports_of_hw->to_port_event (edge->dest, + edge->dest_port, + me, + my_port, + level); + found_an_edge = 1; + } + } + if (!found_an_edge) + hw_abort (me, "No edge for port %d", my_port); +} + + +void +hw_port_attach (struct hw *me, + int my_port, + struct hw *dest, + int dest_port, + object_disposition disposition) +{ + attach_hw_port_edge (me, + &me->ports_of_hw->edges, + my_port, + dest, + dest_port, + disposition); +} + + +void +hw_port_detach (struct hw *me, + int my_port, + struct hw *dest, + int dest_port) +{ + detach_hw_port_edge (me, + &me->ports_of_hw->edges, + my_port, + dest, + dest_port); +} + + +void +hw_port_traverse (struct hw *me, + hw_port_traverse_function *handler, + void *data) +{ + struct hw_port_edge *port_edge; + for (port_edge = me->ports_of_hw->edges; + port_edge != NULL; + port_edge = port_edge->next) + { + handler (me, port_edge->my_port, + port_edge->dest, port_edge->dest_port, + data); + } +} + + +int +hw_port_decode (struct hw *me, + const char *port_name, + port_direction direction) +{ + if (port_name == NULL || port_name[0] == '\0') + return 0; + if (isdigit(port_name[0])) + { + return strtoul (port_name, NULL, 0); + } + else + { + const struct hw_port_descriptor *ports = + me->ports_of_hw->ports; + if (ports != NULL) + { + while (ports->name != NULL) + { + if (ports->direction == bidirect_port + || ports->direction == direction) + { + if (ports->nr_ports > 0) + { + int len = strlen (ports->name); + if (strncmp (port_name, ports->name, len) == 0) + { + if (port_name[len] == '\0') + return ports->number; + else if(isdigit (port_name[len])) + { + int port = (ports->number + + strtoul (&port_name[len], NULL, 0)); + if (port >= ports->number + ports->nr_ports) + hw_abort (me, + "Port %s out of range", + port_name); + return port; + } + } + } + else if (strcmp (port_name, ports->name) == 0) + return ports->number; + } + ports++; + } + } + } + hw_abort (me, "Unreconized port %s", port_name); + return 0; +} + + +int +hw_port_encode (struct hw *me, + int port_number, + char *buf, + int sizeof_buf, + port_direction direction) +{ + const struct hw_port_descriptor *ports = NULL; + ports = me->ports_of_hw->ports; + if (ports != NULL) { + while (ports->name != NULL) + { + if (ports->direction == bidirect_port + || ports->direction == direction) + { + if (ports->nr_ports > 0) + { + if (port_number >= ports->number + && port_number < ports->number + ports->nr_ports) + { + strcpy (buf, ports->name); + sprintf (buf + strlen(buf), "%d", port_number - ports->number); + if (strlen (buf) >= sizeof_buf) + hw_abort (me, "hw_port_encode: buffer overflow"); + return strlen (buf); + } + } + else + { + if (ports->number == port_number) + { + if (strlen(ports->name) >= sizeof_buf) + hw_abort (me, "hw_port_encode: buffer overflow"); + strcpy(buf, ports->name); + return strlen(buf); + } + } + } + ports++; + } + } + sprintf (buf, "%d", port_number); + if (strlen(buf) >= sizeof_buf) + hw_abort (me, "hw_port_encode: buffer overflow"); + return strlen(buf); +} diff --git a/sim/common/hw-ports.h b/sim/common/hw-ports.h new file mode 100644 index 00000000000..566895a2f4a --- /dev/null +++ b/sim/common/hw-ports.h @@ -0,0 +1,129 @@ +/* Hardware ports. + Copyright (C) 1998 Free Software Foundation, Inc. + Contributed by Andrew Cagney and Cygnus Solutions. + +This file is part of GDB, the GNU debugger. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + + +#ifndef HW_PORTS_H +#define HW_PORTS_H + +/* Initialize a port */ + +struct hw_port_descriptor { + const char *name; + int number; + int nr_ports; + port_direction direction; +}; + +void set_hw_ports (struct hw *hw, const struct hw_port_descriptor ports[]); + +typedef void (hw_port_event_method) + (struct hw *me, + int my_port, + struct hw *source, + int source_port, + int level); + +void set_hw_port_event (struct hw *hw, hw_port_event_method *to_port_event); + + +/* Port source + + A device drives its output ports using the call + + */ + +void hw_port_event +(struct hw *me, + int my_port, + int value); + +/* This port event will then be propogated to any attached + destination ports. + + Any interpretation of PORT and VALUE is model dependant. As a + guideline the following are recommended: PCI interrupts A-D should + correspond to ports 0-3; level sensative interrupts be requested + with a value of one and withdrawn with a value of 0; edge sensative + interrupts always have a value of 1, the event its self is treated + as the interrupt. + + + Port destinations + + Attached to each port of a device can be zero or more + desitinations. These destinations consist of a device/port pair. + A destination is attached/detached to a device line using the + attach and detach calls. */ + +void hw_port_attach +(struct hw *me, + int my_port, + struct hw *dest, + int dest_port, + object_disposition disposition); + +void hw_port_detach +(struct hw *me, + int my_port, + struct hw *dest, + int dest_port); + + +/* Iterate over the list of ports attached to a device */ + +typedef void (hw_port_traverse_function) + (struct hw *me, + int my_port, + struct hw *dest, + int dest_port, + void *data); + +void hw_port_traverse +(struct hw *me, + hw_port_traverse_function *handler, + void *data); + + +/* DESTINATION is attached (detached) to LINE of the device ME + + + Port conversion + + Users refer to port numbers symbolically. For instance a device + may refer to its `INT' signal which is internally represented by + port 3. + + To convert to/from the symbolic and internal representation of a + port name/number. The following functions are available. */ + +int hw_port_decode +(struct hw *me, + const char *symbolic_name, + port_direction direction); + +int hw_port_encode +(struct hw *me, + int port_number, + char *buf, + int sizeof_buf, + port_direction direction); + + +#endif diff --git a/sim/common/hw-properties.c b/sim/common/hw-properties.c new file mode 100644 index 00000000000..a1e9291269c --- /dev/null +++ b/sim/common/hw-properties.c @@ -0,0 +1,905 @@ +/* This file is part of the program psim. + + Copyright (C) 1994-1998, Andrew Cagney + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + +#include "hw-main.h" +#include "hw-base.h" + +#include "sim-assert.h" + +#ifdef HAVE_STRING_H +#include +#else +#ifdef HAVE_STRINGS_H +#include +#endif +#endif + +#define TRACE(A,B) + +/* property entries */ + +struct hw_property_data { + struct hw_property_data *next; + struct hw_property *property; + const void *init_array; + unsigned sizeof_init_array; +}; + +void +create_hw_property_data (struct hw *me) +{ +} + +void +delete_hw_property_data (struct hw *me) +{ +} + + +/* Device Properties: */ + +static struct hw_property_data * +find_property_data (struct hw *me, + const char *property) +{ + struct hw_property_data *entry; + ASSERT (property != NULL); + entry = me->properties_of_hw; + while (entry != NULL) + { + if (strcmp (entry->property->name, property) == 0) + return entry; + entry = entry->next; + } + return NULL; +} + + +static void +hw_add_property (struct hw *me, + const char *property, + hw_property_type type, + const void *init_array, + unsigned sizeof_init_array, + const void *array, + unsigned sizeof_array, + const struct hw_property *original, + object_disposition disposition) +{ + struct hw_property_data *new_entry = NULL; + struct hw_property *new_value = NULL; + + /* find the list end */ + struct hw_property_data **insertion_point = &me->properties_of_hw; + while (*insertion_point != NULL) + { + if (strcmp ((*insertion_point)->property->name, property) == 0) + return; + insertion_point = &(*insertion_point)->next; + } + + /* create a new value */ + new_value = HW_ZALLOC (me, struct hw_property); + new_value->name = (char *) strdup (property); + new_value->type = type; + if (sizeof_array > 0) + { + void *new_array = hw_zalloc (me, sizeof_array); + memcpy (new_array, array, sizeof_array); + new_value->array = new_array; + new_value->sizeof_array = sizeof_array; + } + new_value->owner = me; + new_value->original = original; + new_value->disposition = disposition; + + /* insert the value into the list */ + new_entry = HW_ZALLOC (me, struct hw_property_data); + *insertion_point = new_entry; + if (sizeof_init_array > 0) + { + void *new_init_array = hw_zalloc (me, sizeof_init_array); + memcpy (new_init_array, init_array, sizeof_init_array); + new_entry->init_array = new_init_array; + new_entry->sizeof_init_array = sizeof_init_array; + } + new_entry->property = new_value; +} + + +static void +hw_set_property (struct hw *me, + const char *property, + hw_property_type type, + const void *array, + int sizeof_array) +{ + /* find the property */ + struct hw_property_data *entry = find_property_data (me, property); + if (entry != NULL) + { + /* existing property - update it */ + void *new_array = 0; + struct hw_property *value = entry->property; + /* check the type matches */ + if (value->type != type) + hw_abort (me, "conflict between type of new and old value for property %s", property); + /* replace its value */ + if (value->array != NULL) + hw_free (me, (void*)value->array); + new_array = (sizeof_array > 0 + ? hw_zalloc (me, sizeof_array) + : (void*)0); + value->array = new_array; + value->sizeof_array = sizeof_array; + if (sizeof_array > 0) + memcpy (new_array, array, sizeof_array); + return; + } + else + { + /* new property - create it */ + hw_add_property (me, property, type, + NULL, 0, array, sizeof_array, + NULL, temporary_object); + } +} + + +#if 0 +static void +clean_hw_properties (struct hw *me) +{ + struct hw_property_data **delete_point = &me->properties_of_hw; + while (*delete_point != NULL) + { + struct hw_property_data *current = *delete_point; + switch (current->property->disposition) + { + case permenant_object: + /* zap the current value, will be initialized later */ + ASSERT (current->init_array != NULL); + if (current->property->array != NULL) + { + hw_free (me, (void*)current->property->array); + current->property->array = NULL; + } + delete_point = &(*delete_point)->next; + break; + case temporary_object: + /* zap the actual property, was created during simulation run */ + ASSERT (current->init_array == NULL); + *delete_point = current->next; + if (current->property->array != NULL) + hw_free (me, (void*)current->property->array); + hw_free (me, current->property); + hw_free (me, current); + break; + } + } +} +#endif + +#if 0 +void +hw_init_static_properties (SIM_DESC sd, + struct hw *me, + void *data) +{ + struct hw_property_data *property; + for (property = me->properties_of_hw; + property != NULL; + property = property->next) + { + ASSERT (property->init_array != NULL); + ASSERT (property->property->array == NULL); + ASSERT(property->property->disposition == permenant_object); + switch (property->property->type) + { + case array_property: + case boolean_property: + case range_array_property: + case reg_array_property: + case string_property: + case string_array_property: + case integer_property: + /* delete the property, and replace it with the original */ + hw_set_property (me, property->property->name, + property->property->type, + property->init_array, + property->sizeof_init_array); + break; +#if 0 + case ihandle_property: + break; +#endif + } + } +} +#endif + + +#if 0 +void +hw_init_runtime_properties (SIM_DESC sd, + struct hw *me, + void *data) +{ + struct hw_property_data *property; + for (property = me->properties_of_hw; + property != NULL; + property = property->next) + { + switch (property->property->disposition) + { + case permenant_object: + switch (property->property->type) + { +#if 0 + case ihandle_property: + { + struct hw_instance *ihandle; + ihandle_runtime_property_spec spec; + ASSERT (property->init_array != NULL); + ASSERT (property->property->array == NULL); + hw_find_ihandle_runtime_property (me, property->property->name, &spec); + ihandle = tree_instance (me, spec.full_path); + hw_set_ihandle_property (me, property->property->name, ihandle); + break; + } +#endif + case array_property: + case boolean_property: + case range_array_property: + case integer_property: + case reg_array_property: + case string_property: + case string_array_property: + ASSERT (property->init_array != NULL); + ASSERT (property->property->array != NULL); + break; + } + break; + case temporary_object: + ASSERT (property->init_array == NULL); + ASSERT (property->property->array != NULL); + break; + } + } +} +#endif + + + +const struct hw_property * +hw_next_property (const struct hw_property *property) +{ + /* find the property in the list */ + struct hw *owner = property->owner; + struct hw_property_data *entry = owner->properties_of_hw; + while (entry != NULL && entry->property != property) + entry = entry->next; + /* now return the following property */ + ASSERT (entry != NULL); /* must be a member! */ + if (entry->next != NULL) + return entry->next->property; + else + return NULL; +} + + +const struct hw_property * +hw_find_property (struct hw *me, + const char *property) +{ + if (me == NULL) + { + return NULL; + } + else if (property == NULL || strcmp (property, "") == 0) + { + if (me->properties_of_hw == NULL) + return NULL; + else + return me->properties_of_hw->property; + } + else + { + struct hw_property_data *entry = find_property_data (me, property); + if (entry != NULL) + return entry->property; + } + return NULL; +} + + +void +hw_add_array_property (struct hw *me, + const char *property, + const void *array, + int sizeof_array) +{ + hw_add_property (me, property, array_property, + array, sizeof_array, array, sizeof_array, + NULL, permenant_object); +} + +void +hw_set_array_property (struct hw *me, + const char *property, + const void *array, + int sizeof_array) +{ + hw_set_property (me, property, array_property, array, sizeof_array); +} + +const struct hw_property * +hw_find_array_property (struct hw *me, + const char *property) +{ + const struct hw_property *node; + node = hw_find_property (me, property); + if (node == NULL) + hw_abort (me, "property \"%s\" not found", property); + if (node->type != array_property) + hw_abort (me, "property \"%s\" of wrong type (array)", property); + return node; +} + + + +void +hw_add_boolean_property (struct hw *me, + const char *property, + int boolean) +{ + signed32 new_boolean = (boolean ? -1 : 0); + hw_add_property (me, property, boolean_property, + &new_boolean, sizeof(new_boolean), + &new_boolean, sizeof(new_boolean), + NULL, permenant_object); +} + +int +hw_find_boolean_property (struct hw *me, + const char *property) +{ + const struct hw_property *node; + unsigned_cell boolean; + node = hw_find_property (me, property); + if (node == NULL) + hw_abort (me, "property \"%s\" not found", property); + if (node->type != boolean_property) + hw_abort (me, "property \"%s\" of wrong type (boolean)", property); + ASSERT (sizeof (boolean) == node->sizeof_array); + memcpy (&boolean, node->array, sizeof (boolean)); + return boolean; +} + + + +#if 0 +void +hw_add_ihandle_runtime_property (struct hw *me, + const char *property, + const ihandle_runtime_property_spec *ihandle) +{ + /* enter the full path as the init array */ + hw_add_property (me, property, ihandle_property, + ihandle->full_path, strlen(ihandle->full_path) + 1, + NULL, 0, + NULL, permenant_object); +} +#endif + +#if 0 +void +hw_find_ihandle_runtime_property (struct hw *me, + const char *property, + ihandle_runtime_property_spec *ihandle) +{ + struct hw_property_data *entry = find_property_data (me, property); + TRACE (trace_devices, + ("hw_find_ihandle_runtime_property(me=0x%lx, property=%s)\n", + (long)me, property)); + if (entry == NULL) + hw_abort (me, "property \"%s\" not found", property); + if (entry->property->type != ihandle_property + || entry->property->disposition != permenant_object) + hw_abort (me, "property \"%s\" of wrong type", property); + ASSERT (entry->init_array != NULL); + /* the full path */ + ihandle->full_path = entry->init_array; +} +#endif + + + +#if 0 +void +hw_set_ihandle_property (struct hw *me, + const char *property, + hw_instance *ihandle) +{ + unsigned_cell cells; + cells = H2BE_cell (hw_instance_to_external (ihandle)); + hw_set_property (me, property, ihandle_property, + &cells, sizeof (cells)); + +} +#endif + +#if 0 +hw_instance * +hw_find_ihandle_property (struct hw *me, + const char *property) +{ + const hw_property_data *node; + unsigned_cell ihandle; + hw_instance *instance; + + node = hw_find_property (me, property); + if (node == NULL) + hw_abort (me, "property \"%s\" not found", property); + if (node->type != ihandle_property) + hw_abort(me, "property \"%s\" of wrong type (ihandle)", property); + if (node->array == NULL) + hw_abort(me, "runtime property \"%s\" not yet initialized", property); + + ASSERT (sizeof(ihandle) == node->sizeof_array); + memcpy (&ihandle, node->array, sizeof(ihandle)); + instance = external_to_hw_instance (me, BE2H_cell(ihandle)); + ASSERT (instance != NULL); + return instance; +} +#endif + + +void +hw_add_integer_property (struct hw *me, + const char *property, + signed_cell integer) +{ + H2BE (integer); + hw_add_property (me, property, integer_property, + &integer, sizeof(integer), + &integer, sizeof(integer), + NULL, permenant_object); +} + +signed_cell +hw_find_integer_property (struct hw *me, + const char *property) +{ + const struct hw_property *node; + signed_cell integer; + TRACE (trace_devices, + ("hw_find_integer(me=0x%lx, property=%s)\n", + (long)me, property)); + node = hw_find_property (me, property); + if (node == NULL) + hw_abort (me, "property \"%s\" not found", property); + if (node->type != integer_property) + hw_abort (me, "property \"%s\" of wrong type (integer)", property); + ASSERT (sizeof(integer) == node->sizeof_array); + memcpy (&integer, node->array, sizeof (integer)); + return BE2H_cell (integer); +} + +int +hw_find_integer_array_property (struct hw *me, + const char *property, + unsigned index, + signed_cell *integer) +{ + const struct hw_property *node; + int sizeof_integer = sizeof (*integer); + signed_cell *cell; + TRACE (trace_devices, + ("hw_find_integer(me=0x%lx, property=%s)\n", + (long)me, property)); + + /* check things sane */ + node = hw_find_property (me, property); + if (node == NULL) + hw_abort (me, "property \"%s\" not found", property); + if (node->type != integer_property + && node->type != array_property) + hw_abort (me, "property \"%s\" of wrong type (integer or array)", property); + if ((node->sizeof_array % sizeof_integer) != 0) + hw_abort (me, "property \"%s\" contains an incomplete number of cells", property); + if (node->sizeof_array <= sizeof_integer * index) + return 0; + + /* Find and convert the value */ + cell = ((signed_cell*)node->array) + index; + *integer = BE2H_cell (*cell); + + return node->sizeof_array / sizeof_integer; +} + + +static unsigned_cell * +unit_address_to_cells (const hw_unit *unit, + unsigned_cell *cell, + int nr_cells) +{ + int i; + ASSERT(nr_cells == unit->nr_cells); + for (i = 0; i < unit->nr_cells; i++) + { + *cell = H2BE_cell (unit->cells[i]); + cell += 1; + } + return cell; +} + + +static const unsigned_cell * +cells_to_unit_address (const unsigned_cell *cell, + hw_unit *unit, + int nr_cells) +{ + int i; + memset(unit, 0, sizeof(*unit)); + unit->nr_cells = nr_cells; + for (i = 0; i < unit->nr_cells; i++) + { + unit->cells[i] = BE2H_cell (*cell); + cell += 1; + } + return cell; +} + + +static unsigned +nr_range_property_cells (struct hw *me, + int nr_ranges) +{ + return ((hw_unit_nr_address_cells (me) + + hw_unit_nr_address_cells (hw_parent (me)) + + hw_unit_nr_size_cells (me)) + ) * nr_ranges; +} + +void +hw_add_range_array_property (struct hw *me, + const char *property, + const range_property_spec *ranges, + unsigned nr_ranges) +{ + unsigned sizeof_cells = (nr_range_property_cells (me, nr_ranges) + * sizeof (unsigned_cell)); + unsigned_cell *cells = hw_zalloc (me, sizeof_cells); + unsigned_cell *cell; + int i; + + /* copy the property elements over */ + cell = cells; + for (i = 0; i < nr_ranges; i++) + { + const range_property_spec *range = &ranges[i]; + /* copy the child address */ + cell = unit_address_to_cells (&range->child_address, cell, + hw_unit_nr_address_cells (me)); + /* copy the parent address */ + cell = unit_address_to_cells (&range->parent_address, cell, + hw_unit_nr_address_cells (hw_parent (me))); + /* copy the size */ + cell = unit_address_to_cells (&range->size, cell, + hw_unit_nr_size_cells (me)); + } + ASSERT (cell == &cells[nr_range_property_cells (me, nr_ranges)]); + + /* add it */ + hw_add_property (me, property, range_array_property, + cells, sizeof_cells, + cells, sizeof_cells, + NULL, permenant_object); + + hw_free (me, cells); +} + +int +hw_find_range_array_property (struct hw *me, + const char *property, + unsigned index, + range_property_spec *range) +{ + const struct hw_property *node; + unsigned sizeof_entry = (nr_range_property_cells (me, 1) + * sizeof (unsigned_cell)); + const unsigned_cell *cells; + + /* locate the property */ + node = hw_find_property (me, property); + if (node == NULL) + hw_abort (me, "property \"%s\" not found", property); + if (node->type != range_array_property) + hw_abort (me, "property \"%s\" of wrong type (range array)", property); + + /* aligned ? */ + if ((node->sizeof_array % sizeof_entry) != 0) + hw_abort (me, "property \"%s\" contains an incomplete number of entries", + property); + + /* within bounds? */ + if (node->sizeof_array < sizeof_entry * (index + 1)) + return 0; + + /* find the range of interest */ + cells = (unsigned_cell*)((char*)node->array + sizeof_entry * index); + + /* copy the child address out - converting as we go */ + cells = cells_to_unit_address (cells, &range->child_address, + hw_unit_nr_address_cells (me)); + + /* copy the parent address out - converting as we go */ + cells = cells_to_unit_address (cells, &range->parent_address, + hw_unit_nr_address_cells (hw_parent (me))); + + /* copy the size - converting as we go */ + cells = cells_to_unit_address (cells, &range->size, + hw_unit_nr_size_cells (me)); + + return node->sizeof_array / sizeof_entry; +} + + +static unsigned +nr_reg_property_cells (struct hw *me, + int nr_regs) +{ + return (hw_unit_nr_address_cells (hw_parent(me)) + + hw_unit_nr_size_cells (hw_parent(me)) + ) * nr_regs; +} + +void +hw_add_reg_array_property (struct hw *me, + const char *property, + const reg_property_spec *regs, + unsigned nr_regs) +{ + unsigned sizeof_cells = (nr_reg_property_cells (me, nr_regs) + * sizeof (unsigned_cell)); + unsigned_cell *cells = hw_zalloc (me, sizeof_cells); + unsigned_cell *cell; + int i; + + /* copy the property elements over */ + cell = cells; + for (i = 0; i < nr_regs; i++) + { + const reg_property_spec *reg = ®s[i]; + /* copy the address */ + cell = unit_address_to_cells (®->address, cell, + hw_unit_nr_address_cells (hw_parent (me))); + /* copy the size */ + cell = unit_address_to_cells (®->size, cell, + hw_unit_nr_size_cells (hw_parent (me))); + } + ASSERT (cell == &cells[nr_reg_property_cells (me, nr_regs)]); + + /* add it */ + hw_add_property (me, property, reg_array_property, + cells, sizeof_cells, + cells, sizeof_cells, + NULL, permenant_object); + + hw_free (me, cells); +} + +int +hw_find_reg_array_property (struct hw *me, + const char *property, + unsigned index, + reg_property_spec *reg) +{ + const struct hw_property *node; + unsigned sizeof_entry = (nr_reg_property_cells (me, 1) + * sizeof (unsigned_cell)); + const unsigned_cell *cells; + + /* locate the property */ + node = hw_find_property (me, property); + if (node == NULL) + hw_abort (me, "property \"%s\" not found", property); + if (node->type != reg_array_property) + hw_abort (me, "property \"%s\" of wrong type (reg array)", property); + + /* aligned ? */ + if ((node->sizeof_array % sizeof_entry) != 0) + hw_abort (me, "property \"%s\" contains an incomplete number of entries", + property); + + /* within bounds? */ + if (node->sizeof_array < sizeof_entry * (index + 1)) + return 0; + + /* find the range of interest */ + cells = (unsigned_cell*)((char*)node->array + sizeof_entry * index); + + /* copy the address out - converting as we go */ + cells = cells_to_unit_address (cells, ®->address, + hw_unit_nr_address_cells (hw_parent (me))); + + /* copy the size out - converting as we go */ + cells = cells_to_unit_address (cells, ®->size, + hw_unit_nr_size_cells (hw_parent (me))); + + return node->sizeof_array / sizeof_entry; +} + + +void +hw_add_string_property (struct hw *me, + const char *property, + const char *string) +{ + hw_add_property (me, property, string_property, + string, strlen(string) + 1, + string, strlen(string) + 1, + NULL, permenant_object); +} + +const char * +hw_find_string_property (struct hw *me, + const char *property) +{ + const struct hw_property *node; + const char *string; + node = hw_find_property (me, property); + if (node == NULL) + hw_abort (me, "property \"%s\" not found", property); + if (node->type != string_property) + hw_abort (me, "property \"%s\" of wrong type (string)", property); + string = node->array; + ASSERT (strlen(string) + 1 == node->sizeof_array); + return string; +} + +void +hw_add_string_array_property (struct hw *me, + const char *property, + const string_property_spec *strings, + unsigned nr_strings) +{ + int sizeof_array; + int string_nr; + char *array; + char *chp; + if (nr_strings == 0) + hw_abort (me, "property \"%s\" must be non-null", property); + /* total up the size of the needed array */ + for (sizeof_array = 0, string_nr = 0; + string_nr < nr_strings; + string_nr ++) + { + sizeof_array += strlen (strings[string_nr]) + 1; + } + /* create the array */ + array = (char*) hw_zalloc (me, sizeof_array); + chp = array; + for (string_nr = 0; + string_nr < nr_strings; + string_nr++) + { + strcpy (chp, strings[string_nr]); + chp += strlen (chp) + 1; + } + ASSERT (chp == array + sizeof_array); + /* now enter it */ + hw_add_property (me, property, string_array_property, + array, sizeof_array, + array, sizeof_array, + NULL, permenant_object); +} + +int +hw_find_string_array_property (struct hw *me, + const char *property, + unsigned index, + string_property_spec *string) +{ + const struct hw_property *node; + node = hw_find_property (me, property); + if (node == NULL) + hw_abort (me, "property \"%s\" not found", property); + switch (node->type) + { + default: + hw_abort (me, "property \"%s\" of wrong type", property); + break; + case string_property: + if (index == 0) + { + *string = node->array; + ASSERT (strlen(*string) + 1 == node->sizeof_array); + return 1; + } + break; + case array_property: + if (node->sizeof_array == 0 + || ((char*)node->array)[node->sizeof_array - 1] != '\0') + hw_abort (me, "property \"%s\" invalid for string array", property); + /* FALL THROUGH */ + case string_array_property: + ASSERT (node->sizeof_array > 0); + ASSERT (((char*)node->array)[node->sizeof_array - 1] == '\0'); + { + const char *chp = node->array; + int nr_entries = 0; + /* count the number of strings, keeping an eye out for the one + we're looking for */ + *string = chp; + do + { + if (*chp == '\0') + { + /* next string */ + nr_entries++; + chp++; + if (nr_entries == index) + *string = chp; + } + else + { + chp++; + } + } while (chp < (char*)node->array + node->sizeof_array); + if (index < nr_entries) + return nr_entries; + else + { + *string = NULL; + return 0; + } + } + break; + } + return 0; +} + +void +hw_add_duplicate_property (struct hw *me, + const char *property, + const struct hw_property *original) +{ + struct hw_property_data *master; + TRACE (trace_devices, + ("hw_add_duplicate_property(me=0x%lx, property=%s, ...)\n", + (long)me, property)); + if (original->disposition != permenant_object) + hw_abort (me, "Can only duplicate permenant objects"); + /* find the original's master */ + master = original->owner->properties_of_hw; + while (master->property != original) + { + master = master->next; + ASSERT(master != NULL); + } + /* now duplicate it */ + hw_add_property (me, property, + original->type, + master->init_array, master->sizeof_init_array, + original->array, original->sizeof_array, + original, permenant_object); +} diff --git a/sim/common/hw-properties.h b/sim/common/hw-properties.h new file mode 100644 index 00000000000..511fba34daa --- /dev/null +++ b/sim/common/hw-properties.h @@ -0,0 +1,244 @@ +/* This file is part of the program psim. + + Copyright (C) 1994-1998, Andrew Cagney + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + + +#ifndef HW_PROPERTIES_H +#define HW_PROPERTIES_H + +/* The following are valid property types. The property `array' is + for generic untyped data. */ + +typedef enum { + array_property, + boolean_property, +#if 0 + ihandle_property, /*runtime*/ +#endif + integer_property, + range_array_property, + reg_array_property, + string_property, + string_array_property, +} hw_property_type; + +struct hw_property { + struct hw *owner; + const char *name; + hw_property_type type; + unsigned sizeof_array; + const void *array; + const struct hw_property *original; + object_disposition disposition; +}; + +#define hw_property_owner(p) ((p)->owner + 0) +#define hw_property_name(p) ((p)->name + 0) +#define hw_property_type(p) ((p)->type + 0) +#define hw_property_array(p) ((p)->array + 0) +#define hw_property_sizeof_array(p) ((p)->sizeof_array + 0) +#define hw_property_original(p) ((p)->original + 0) +#define hw_property_disposition(p) ((p)->disposition + 0) + + +/* Find/iterate over properites attached to a device. + + To iterate over all properties attached to a device, call + hw_find_property (.., NULL) and then hw_property_next. */ + +const struct hw_property *hw_find_property +(struct hw *me, + const char *property); + +const struct hw_property *hw_next_property +(const struct hw_property *previous); + + +/* Manipulate the properties belonging to a given device. + + HW_ADD_* will, if the property is not already present, add a + property to the device. Adding a property to a device after it has + been created is a checked run-time error (use HW_SET_*). + + HW_SET_* will always update (or create) the property so that it has + the specified value. Changing the type of a property is a checked + run-time error. + + FIND returns the specified properties value. It is a checked + runtime error to either request a nonexistant property or to + request a property using the wrong type. Code locating a property + should first check its type (using hw_find_property above) and then + obtain its value using the below. + + Naming convention: + + void hw_add__property(struct hw *, const char *, ) + void hw_add_*_array_property(struct hw *, const char *, const *, int) + void hw_set_*_property(struct hw *, const char *, ) + void hw_set_*_array_property(struct hw *, const char *, const *, int) + hw_find_*_property(struct hw *, const char *) + int hw_find_*_array_property(struct hw *, const char *, int, *) + + */ + + +void hw_add_array_property +(struct hw *me, + const char *property, + const void *array, + int sizeof_array); + +void hw_set_array_property +(struct hw *me, + const char *property, + const void *array, + int sizeof_array); + +const struct hw_property *hw_find_array_property +(struct hw *me, + const char *property); + + + +void hw_add_boolean_property +(struct hw *me, + const char *property, + int bool); + +int hw_find_boolean_property +(struct hw *me, + const char *property); + + + +#if 0 +typedef struct _ihandle_runtime_property_spec { + const char *full_path; +} ihandle_runtime_property_spec; + +void hw_add_ihandle_runtime_property +(struct hw *me, + const char *property, + const ihandle_runtime_property_spec *ihandle); + +void hw_find_ihandle_runtime_property +(struct hw *me, + const char *property, + ihandle_runtime_property_spec *ihandle); + +void hw_set_ihandle_property +(struct hw *me, + const char *property, + hw_instance *ihandle); + +hw_instance * hw_find_ihandle_property +(struct hw *me, + const char *property); +#endif + + +void hw_add_integer_property +(struct hw *me, + const char *property, + signed_cell integer); + +signed_cell hw_find_integer_property +(struct hw *me, + const char *property); + +int hw_find_integer_array_property +(struct hw *me, + const char *property, + unsigned index, + signed_word *integer); + + + +typedef struct _range_property_spec { + hw_unit child_address; + hw_unit parent_address; + hw_unit size; +} range_property_spec; + +void hw_add_range_array_property +(struct hw *me, + const char *property, + const range_property_spec *ranges, + unsigned nr_ranges); + +int hw_find_range_array_property +(struct hw *me, + const char *property, + unsigned index, + range_property_spec *range); + + + +typedef struct _reg_property_spec { + hw_unit address; + hw_unit size; +} reg_property_spec; + +void hw_add_reg_array_property +(struct hw *me, + const char *property, + const reg_property_spec *reg, + unsigned nr_regs); + +int hw_find_reg_array_property +(struct hw *me, + const char *property, + unsigned index, + reg_property_spec *reg); + + + +void hw_add_string_property +(struct hw *me, + const char *property, + const char *string); + +const char *hw_find_string_property +(struct hw *me, + const char *property); + + + +typedef const char *string_property_spec; + +void hw_add_string_array_property +(struct hw *me, + const char *property, + const string_property_spec *strings, + unsigned nr_strings); + +int hw_find_string_array_property +(struct hw *me, + const char *property, + unsigned index, + string_property_spec *string); + + + +void hw_add_duplicate_property +(struct hw *me, + const char *property, + const struct hw_property *original); + +#endif diff --git a/sim/common/hw-tree.c b/sim/common/hw-tree.c new file mode 100644 index 00000000000..1a558351b25 --- /dev/null +++ b/sim/common/hw-tree.c @@ -0,0 +1,1344 @@ +/* This file is part of the program psim. + + Copyright (C) 1994-1998, Andrew Cagney + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + +#include "hw-main.h" +#include "hw-base.h" +#include "hw-tree.h" + +#include "sim-assert.h" + +#ifdef HAVE_STDLIB_H +#include +#endif + +#ifdef HAVE_STRING_H +#include +#else +#ifdef HAVE_STRINGS_H +#include +#endif +#endif + +#include + +/* manipulate/lookup device names */ + +typedef struct _name_specifier { + + /* components in the full length name */ + char *path; + char *property; + char *value; + + /* current device */ + char *family; + char *name; + char *unit; + char *args; + + /* previous device */ + char *last_name; + char *last_family; + char *last_unit; + char *last_args; + + /* work area */ + char buf[1024]; + +} name_specifier; + + + +/* Given a device specifier, break it up into its main components: + path (and if present) property name and property value. */ + +static int +split_device_specifier (struct hw *current, + const char *device_specifier, + name_specifier *spec) +{ + char *chp = NULL; + + /* expand any leading alias if present */ + if (current != NULL + && *device_specifier != '\0' + && *device_specifier != '.' + && *device_specifier != '/') + { + struct hw *aliases = hw_tree_find_device (current, "/aliases"); + char alias[32]; + int len = 0; + while (device_specifier[len] != '\0' + && device_specifier[len] != '/' + && device_specifier[len] != ':' + && !isspace (device_specifier[len])) + { + alias[len] = device_specifier[len]; + len++; + if (len >= sizeof(alias)) + hw_abort (NULL, "split_device_specifier: buffer overflow"); + } + alias[len] = '\0'; + if (aliases != NULL + && hw_find_property (aliases, alias)) + { + strcpy (spec->buf, hw_find_string_property(aliases, alias)); + strcat (spec->buf, device_specifier + len); + } + else + { + strcpy (spec->buf, device_specifier); + } + } + else + { + strcpy(spec->buf, device_specifier); + } + + /* check no overflow */ + if (strlen(spec->buf) >= sizeof(spec->buf)) + hw_abort (NULL, "split_device_specifier: buffer overflow\n"); + + /* strip leading spaces */ + chp = spec->buf; + while (*chp != '\0' && isspace(*chp)) + chp++; + if (*chp == '\0') + return 0; + + /* find the path and terminate it with null */ + spec->path = chp; + while (*chp != '\0' && !isspace(*chp)) + chp++; + if (*chp != '\0') + { + *chp = '\0'; + chp++; + } + + /* and any value */ + while (*chp != '\0' && isspace(*chp)) + chp++; + spec->value = chp; + + /* now go back and chop the property off of the path */ + if (spec->value[0] == '\0') + { + spec->property = NULL; /*not a property*/ + spec->value = NULL; + } + else if (spec->value[0] == '>' + || spec->value[0] == '<') + { + /* an interrupt spec */ + spec->property = NULL; + } + else { + chp = strrchr(spec->path, '/'); + if (chp == NULL) + { + spec->property = spec->path; + spec->path = strchr(spec->property, '\0'); + } + else { + *chp = '\0'; + spec->property = chp+1; + } + } + + /* and mark the rest as invalid */ + spec->name = NULL; + spec->family = NULL; + spec->unit = NULL; + spec->args = NULL; + spec->last_name = NULL; + spec->last_family = NULL; + spec->last_unit = NULL; + spec->last_args = NULL; + + return 1; +} + + +/* given a device specifier break it up into its main components - + path and property name - assuming that the last `device' is a + property name. */ + +static int +split_property_specifier (struct hw *current, + const char *property_specifier, + name_specifier *spec) +{ + if (split_device_specifier (current, property_specifier, spec)) + { + if (spec->property == NULL) + { + /* force the last name to be a property name */ + char *chp = strrchr (spec->path, '/'); + if (chp == NULL) + { + spec->property = spec->path; + spec->path = strrchr (spec->property, '\0');; + } + else + { + *chp = '\0'; + spec->property = chp + 1; + } + } + return 1; + } + else + return 0; +} + + +/* device the next device name and split it up, return 0 when no more + names to struct hw */ + +static int +split_device_name (name_specifier *spec) +{ + char *chp; + /* remember what came before */ + spec->last_name = spec->name; + spec->last_family = spec->family; + spec->last_unit = spec->unit; + spec->last_args = spec->args; + /* finished? */ + if (spec->path[0] == '\0') + { + spec->name = NULL; + spec->family = NULL; + spec->unit = NULL; + spec->args = NULL; + return 0; + } + /* break the current device spec from the path */ + spec->name = spec->path; + chp = strchr (spec->name, '/'); + if (chp == NULL) + spec->path = strchr (spec->name, '\0'); + else + { + spec->path = chp+1; + *chp = '\0'; + } + /* break out the base */ + if (spec->name[0] == '(') + { + chp = strchr(spec->name, ')'); + if (chp == NULL) + { + spec->family = spec->name; + } + else + { + *chp = '\0'; + spec->family = spec->name + 1; + spec->name = chp + 1; + } + } + else + { + spec->family = spec->name; + } + /* now break out the unit */ + chp = strchr(spec->name, '@'); + if (chp == NULL) + { + spec->unit = NULL; + chp = spec->name; + } + else + { + *chp = '\0'; + chp += 1; + spec->unit = chp; + } + /* finally any args */ + chp = strchr(chp, ':'); + if (chp == NULL) + spec->args = NULL; + else + { + *chp = '\0'; + spec->args = chp+1; + } + return 1; +} + + +/* device the value, returning the next non-space token */ + +static char * +split_value (name_specifier *spec) +{ + char *token; + if (spec->value == NULL) + return NULL; + /* skip leading white space */ + while (isspace (spec->value[0])) + spec->value++; + if (spec->value[0] == '\0') + { + spec->value = NULL; + return NULL; + } + token = spec->value; + /* find trailing space */ + while (spec->value[0] != '\0' && !isspace (spec->value[0])) + spec->value++; + /* chop this value out */ + if (spec->value[0] != '\0') + { + spec->value[0] = '\0'; + spec->value++; + } + return token; +} + + + +/* traverse the path specified by spec starting at current */ + +static struct hw * +split_find_device (struct hw *current, + name_specifier *spec) +{ + /* strip off (and process) any leading ., .., ./ and / */ + while (1) + { + if (strncmp (spec->path, "/", strlen ("/")) == 0) + { + /* cd /... */ + while (current != NULL && hw_parent (current) != NULL) + current = hw_parent (current); + spec->path += strlen ("/"); + } + else if (strncmp (spec->path, "./", strlen ("./")) == 0) + { + /* cd ./... */ + current = current; + spec->path += strlen ("./"); + } + else if (strncmp (spec->path, "../", strlen ("../")) == 0) + { + /* cd ../... */ + if (current != NULL && hw_parent (current) != NULL) + current = hw_parent (current); + spec->path += strlen ("../"); + } + else if (strcmp (spec->path, ".") == 0) + { + /* cd . */ + current = current; + spec->path += strlen ("."); + } + else if (strcmp (spec->path, "..") == 0) + { + /* cd .. */ + if (current != NULL && hw_parent (current) != NULL) + current = hw_parent (current); + spec->path += strlen (".."); + } + else + break; + } + + /* now go through the path proper */ + + if (current == NULL) + { + split_device_name (spec); + return NULL; + } + + while (split_device_name (spec)) + { + struct hw *child; + for (child = hw_child (current); + child != NULL; child = hw_sibling (child)) + { + if (strcmp (spec->name, hw_name (child)) == 0) + { + if (spec->unit == NULL) + break; + else + { + hw_unit phys; + hw_unit_decode (current, spec->unit, &phys); + if (memcmp (&phys, hw_unit_address (child), + sizeof (hw_unit)) == 0) + break; + } + } + } + if (child == NULL) + return current; /* search failed */ + current = child; + } + + return current; +} + + +static struct hw * +split_fill_path (struct hw *current, + const char *device_specifier, + name_specifier *spec) +{ + /* break it up */ + if (!split_device_specifier (current, device_specifier, spec)) + hw_abort (current, "error parsing %s\n", device_specifier); + + /* fill our tree with its contents */ + current = split_find_device (current, spec); + + /* add any additional devices as needed */ + if (spec->name != NULL) + { + do + { + if (current != NULL && !hw_finished_p (current)) + hw_finish (current); + current = hw_create (NULL, + current, + spec->family, + spec->name, + spec->unit, + spec->args); + } + while (split_device_name (spec)); + } + + return current; +} + + +/* */ + +static const char * +skip_token(const char *chp) +{ + while (!isspace(*chp) && *chp != '\0') + chp++; + while (isspace(*chp) && *chp != '\0') + chp++; + return chp; +} + + +/* count the number of entries */ + +static int +count_entries (struct hw *current, + const char *property_name, + const char *property_value, + int modulo) +{ + const char *chp = property_value; + int nr_entries = 0; + while (*chp != '\0') + { + nr_entries += 1; + chp = skip_token (chp); + } + if ((nr_entries % modulo) != 0) + { + hw_abort (current, "incorrect number of entries for %s property %s, should be multiple of %d", + property_name, property_value, modulo); + } + return nr_entries / modulo; +} + + + +/* parse:
::= ; device dependant */ + +static const char * +parse_address (struct hw *current, + struct hw *bus, + const char *chp, + hw_unit *address) +{ + if (hw_unit_decode (bus, chp, address) < 0) + hw_abort (current, "invalid unit address in %s", chp); + return skip_token (chp); +} + + +/* parse: ::= { "," } ; */ + +static const char * +parse_size (struct hw *current, + struct hw *bus, + const char *chp, + hw_unit *size) +{ + int i; + int nr; + const char *curr = chp; + memset(size, 0, sizeof(*size)); + /* parse the numeric list */ + size->nr_cells = hw_unit_nr_size_cells (bus); + nr = 0; + while (1) + { + char *next; + size->cells[nr] = strtoul (curr, &next, 0); + if (curr == next) + hw_abort (current, "Problem parsing %s", chp); + nr += 1; + if (next[0] != ',') + break; + if (nr == size->nr_cells) + hw_abort (current, "Too many values in %s", chp); + curr = next + 1; + } + ASSERT (nr > 0 && nr <= size->nr_cells); + /* right align the numbers */ + for (i = 1; i <= size->nr_cells; i++) + { + if (i <= nr) + size->cells[size->nr_cells - i] = size->cells[nr - i]; + else + size->cells[size->nr_cells - i] = 0; + } + return skip_token (chp); +} + + +/* parse: ::= {
} ; */ + +static void +parse_reg_property (struct hw *current, + const char *property_name, + const char *property_value) +{ + int nr_regs; + int reg_nr; + reg_property_spec *regs; + const char *chp; + + /* determine the number of reg entries by counting tokens */ + nr_regs = count_entries (current, property_name, property_value, 2); + + /* create working space */ + regs = zalloc (nr_regs * sizeof (*regs)); + + /* fill it in */ + chp = property_value; + for (reg_nr = 0; reg_nr < nr_regs; reg_nr++) + { + chp = parse_address (current, hw_parent(current), + chp, ®s[reg_nr].address); + chp = parse_size (current, hw_parent(current), + chp, ®s[reg_nr].size); + } + + /* create it */ + hw_add_reg_array_property (current, property_name, + regs, nr_regs); + + zfree (regs); +} + + +/* { }* */ + +static void +parse_ranges_property (struct hw *current, + const char *property_name, + const char *property_value) +{ + int nr_ranges; + int range_nr; + range_property_spec *ranges; + const char *chp; + + /* determine the number of ranges specified */ + nr_ranges = count_entries (current, property_name, property_value, 3); + + /* create a property of that size */ + ranges = zalloc (nr_ranges * sizeof(*ranges)); + + /* fill it in */ + chp = property_value; + for (range_nr = 0; range_nr < nr_ranges; range_nr++) + { + chp = parse_address (current, current, + chp, &ranges[range_nr].child_address); + chp = parse_address (current, hw_parent(current), + chp, &ranges[range_nr].parent_address); + chp = parse_size (current, current, + chp, &ranges[range_nr].size); + } + + /* create it */ + hw_add_range_array_property (current, property_name, ranges, nr_ranges); + + zfree (ranges); +} + + +/* ... */ + +static void +parse_integer_property (struct hw *current, + const char *property_name, + const char *property_value) +{ + int nr_entries; + unsigned_cell words[1024]; + /* integer or integer array? */ + nr_entries = 0; + while (1) + { + char *end; + words[nr_entries] = strtoul (property_value, &end, 0); + if (property_value == end) + break; + nr_entries += 1; + if (nr_entries * sizeof (words[0]) >= sizeof (words)) + hw_abort (current, "buffer overflow"); + property_value = end; + } + if (nr_entries == 0) + hw_abort (current, "error parsing integer property %s (%s)", + property_name, property_value); + else if (nr_entries == 1) + hw_add_integer_property (current, property_name, words[0]); + else + { + int i; + for (i = 0; i < nr_entries; i++) + { + H2BE (words[i]); + } + /* perhaphs integer array property is better */ + hw_add_array_property (current, property_name, words, + sizeof(words[0]) * nr_entries); + } +} + + +/* ... */ + +static void +parse_string_property (struct hw *current, + const char *property_name, + const char *property_value) +{ + char **strings; + const char *chp; + int nr_strings; + int approx_nr_strings; + + /* get an estimate as to the number of strings by counting double + quotes */ + approx_nr_strings = 2; + for (chp = property_value; *chp; chp++) + { + if (*chp == '"') + approx_nr_strings++; + } + approx_nr_strings = (approx_nr_strings) / 2; + + /* create a string buffer for that many (plus a null) */ + strings = (char**) zalloc ((approx_nr_strings + 1) * sizeof(char*)); + + /* now find all the strings */ + chp = property_value; + nr_strings = 0; + while (1) + { + + /* skip leading space */ + while (*chp != '\0' && isspace (*chp)) + chp += 1; + if (*chp == '\0') + break; + + /* copy it in */ + if (*chp == '"') + { + /* a quoted string - watch for '\' et.al. */ + /* estimate the size and allocate space for it */ + int pos; + chp++; + pos = 0; + while (chp[pos] != '\0' && chp[pos] != '"') + { + if (chp[pos] == '\\' && chp[pos+1] != '\0') + pos += 2; + else + pos += 1; + } + strings[nr_strings] = zalloc (pos + 1); + /* copy the string over */ + pos = 0; + while (*chp != '\0' && *chp != '"') + { + if (*chp == '\\' && *(chp+1) != '\0') { + strings[nr_strings][pos] = *(chp+1); + chp += 2; + pos++; + } + else + { + strings[nr_strings][pos] = *chp; + chp += 1; + pos++; + } + } + if (*chp != '\0') + chp++; + strings[nr_strings][pos] = '\0'; + } + else + { + /* copy over a single unquoted token */ + int len = 0; + while (chp[len] != '\0' && !isspace(chp[len])) + len++; + strings[nr_strings] = zalloc(len + 1); + strncpy(strings[nr_strings], chp, len); + strings[nr_strings][len] = '\0'; + chp += len; + } + nr_strings++; + if (nr_strings > approx_nr_strings) + hw_abort (current, "String property %s badly formatted", + property_name); + } + ASSERT (strings[nr_strings] == NULL); /* from zalloc */ + + /* install it */ + if (nr_strings == 0) + hw_add_string_property (current, property_name, ""); + else if (nr_strings == 1) + hw_add_string_property (current, property_name, strings[0]); + else + { + const char **specs = (const char**) strings; /* stop a bogus error */ + hw_add_string_array_property (current, property_name, + specs, nr_strings); + } + + /* flush the created string */ + while (nr_strings > 0) + { + nr_strings--; + zfree (strings[nr_strings]); + } + zfree(strings); +} + + +/* */ + +#if NOT_YET +static void +parse_ihandle_property (struct hw *current, + const char *property, + const char *value) +{ + ihandle_runtime_property_spec ihandle; + + /* pass the full path */ + ihandle.full_path = value; + + /* save this ready for the ihandle create */ + hw_add_ihandle_runtime_property (current, property, + &ihandle); +} +#endif + + +struct hw * +hw_tree_create (SIM_DESC sd, + const char *family) +{ + return hw_create (sd, NULL, family, family, NULL, NULL); +} + +void +hw_tree_delete (struct hw *me) +{ + /* Need to allow devices to disapear under our feet */ + while (hw_child (me) != NULL) + { + hw_tree_delete (hw_child (me)); + } + hw_delete (me); +} + + +struct hw * +hw_tree_parse (struct hw *current, + const char *fmt, + ...) +{ + va_list ap; + va_start (ap, fmt); + current = hw_tree_vparse (current, fmt, ap); + va_end (ap); + return current; +} + +struct hw * +hw_tree_vparse (struct hw *current, + const char *fmt, + va_list ap) +{ + char device_specifier[1024]; + name_specifier spec; + + /* format the path */ + vsprintf (device_specifier, fmt, ap); + if (strlen (device_specifier) >= sizeof (device_specifier)) + hw_abort (NULL, "device_tree_add_deviced: buffer overflow\n"); + + /* construct the tree down to the final struct hw */ + current = split_fill_path (current, device_specifier, &spec); + + /* is there an interrupt spec */ + if (spec.property == NULL + && spec.value != NULL) + { + char *op = split_value (&spec); + switch (op[0]) + { + case '>': + { + char *my_port_name = split_value (&spec); + int my_port; + char *dest_port_name = split_value (&spec); + int dest_port; + name_specifier dest_spec; + char *dest_hw_name = split_value (&spec); + struct hw *dest; + /* find my name */ + if (!hw_finished_p (current)) + hw_finish (current); + my_port = hw_port_decode (current, my_port_name, output_port); + /* find the dest device and port */ + dest = split_fill_path (current, dest_hw_name, &dest_spec); + if (!hw_finished_p (dest)) + hw_finish (dest); + dest_port = hw_port_decode (dest, dest_port_name, + input_port); + /* connect the two */ + hw_port_attach (current, + my_port, + dest, + dest_port, + permenant_object); + break; + } + default: + hw_abort (current, "unreconised interrupt spec %s\n", spec.value); + break; + } + } + + /* is there a property */ + if (spec.property != NULL) + { + if (strcmp (spec.value, "true") == 0) + hw_add_boolean_property (current, spec.property, 1); + else if (strcmp (spec.value, "false") == 0) + hw_add_boolean_property (current, spec.property, 0); + else + { + const struct hw_property *property; + switch (spec.value[0]) + { +#if NOT_YET + case '*': + { + parse_ihandle_property (current, spec.property, spec.value + 1); + break; + } +#endif + case '[': + { + unsigned8 words[1024]; + char *curr = spec.value + 1; + int nr_words = 0; + while (1) + { + char *next; + words[nr_words] = H2BE_1 (strtoul (curr, &next, 0)); + if (curr == next) + break; + curr = next; + nr_words += 1; + } + hw_add_array_property (current, spec.property, + words, sizeof(words[0]) * nr_words); + break; + } + case '"': + { + parse_string_property (current, spec.property, spec.value); + break; + } + case '!': + { + spec.value++; + property = hw_tree_find_property (current, spec.value); + if (property == NULL) + hw_abort (current, "property %s not found\n", spec.value); + hw_add_duplicate_property (current, + spec.property, + property); + break; + } + default: + { + if (strcmp (spec.property, "reg") == 0 + || strcmp (spec.property, "assigned-addresses") == 0 + || strcmp (spec.property, "alternate-reg") == 0) + { + parse_reg_property (current, spec.property, spec.value); + } + else if (strcmp (spec.property, "ranges") == 0) + { + parse_ranges_property (current, spec.property, spec.value); + } + else if (isdigit(spec.value[0]) + || (spec.value[0] == '-' && isdigit(spec.value[1])) + || (spec.value[0] == '+' && isdigit(spec.value[1]))) + { + parse_integer_property(current, spec.property, spec.value); + } + else + parse_string_property(current, spec.property, spec.value); + break; + } + } + } + } + return current; +} + + +static void +finish_hw_tree (struct hw *me, + void *data) +{ + if (!hw_finished_p (me)) + hw_finish (me); +} + +void +hw_tree_finish (struct hw *root) +{ + hw_tree_traverse (root, finish_hw_tree, NULL, NULL); +} + + + +void +hw_tree_traverse (struct hw *root, + hw_tree_traverse_function *prefix, + hw_tree_traverse_function *postfix, + void *data) +{ + struct hw *child; + if (prefix != NULL) + prefix (root, data); + for (child = hw_child (root); + child != NULL; + child = hw_sibling (child)) + { + hw_tree_traverse (child, prefix, postfix, data); + } + if (postfix != NULL) + postfix (root, data); +} + + + +struct printer { + hw_tree_print_callback *print; + void *file; +}; + +static void +print_address (struct hw *bus, + const hw_unit *phys, + struct printer *p) +{ + char unit[32]; + hw_unit_encode (bus, phys, unit, sizeof(unit)); + p->print (p->file, " %s", unit); +} + +static void +print_size (struct hw *bus, + const hw_unit *size, + struct printer *p) +{ + int i; + for (i = 0; i < size->nr_cells; i++) + if (size->cells[i] != 0) + break; + if (i < size->nr_cells) { + p->print (p->file, " 0x%lx", (unsigned long) size->cells[i]); + i++; + for (; i < size->nr_cells; i++) + p->print (p->file, ",0x%lx", (unsigned long) size->cells[i]); + } + else + p->print (p->file, " 0"); +} + +static void +print_reg_property (struct hw *me, + const struct hw_property *property, + struct printer *p) +{ + int reg_nr; + reg_property_spec reg; + for (reg_nr = 0; + hw_find_reg_array_property (me, property->name, reg_nr, ®); + reg_nr++) { + print_address (hw_parent (me), ®.address, p); + print_size (me, ®.size, p); + } +} + +static void +print_ranges_property (struct hw *me, + const struct hw_property *property, + struct printer *p) +{ + int range_nr; + range_property_spec range; + for (range_nr = 0; + hw_find_range_array_property (me, property->name, range_nr, &range); + range_nr++) + { + print_address (me, &range.child_address, p); + print_address (hw_parent (me), &range.parent_address, p); + print_size (me, &range.size, p); + } +} + +static void +print_string (struct hw *me, + const char *string, + struct printer *p) +{ + p->print (p->file, " \""); + while (*string != '\0') { + switch (*string) { + case '"': + p->print (p->file, "\\\""); + break; + case '\\': + p->print (p->file, "\\\\"); + break; + default: + p->print (p->file, "%c", *string); + break; + } + string++; + } + p->print (p->file, "\""); +} + +static void +print_string_array_property (struct hw *me, + const struct hw_property *property, + struct printer *p) +{ + int nr; + string_property_spec string; + for (nr = 0; + hw_find_string_array_property (me, property->name, nr, &string); + nr++) + { + print_string (me, string, p); + } +} + +static void +print_properties (struct hw *me, + struct printer *p) +{ + const struct hw_property *property; + for (property = hw_find_property (me, NULL); + property != NULL; + property = hw_next_property (property)) + { + if (hw_parent (me) == NULL) + p->print (p->file, "/%s", property->name); + else + p->print (p->file, "%s/%s", hw_path (me), property->name); + if (property->original != NULL) + { + p->print (p->file, " !"); + p->print (p->file, "%s/%s", + hw_path (property->original->owner), + property->original->name); + } + else + { + switch (property->type) + { + case array_property: + { + if ((property->sizeof_array % sizeof (signed_cell)) == 0) + { + unsigned_cell *w = (unsigned_cell*) property->array; + int cell_nr; + for (cell_nr = 0; + cell_nr < (property->sizeof_array / sizeof (unsigned_cell)); + cell_nr++) + { + p->print (p->file, " 0x%lx", (unsigned long) BE2H_cell (w[cell_nr])); + } + } + else + { + unsigned8 *w = (unsigned8*)property->array; + p->print (p->file, " ["); + while ((char*)w - (char*)property->array < property->sizeof_array) { + p->print (p->file, " 0x%2x", BE2H_1 (*w)); + w++; + } + } + break; + } + case boolean_property: + { + int b = hw_find_boolean_property(me, property->name); + p->print (p->file, " %s", b ? "true" : "false"); + break; + } +#if NOT_YET + case ihandle_property: + { + if (property->array != NULL) + { + device_instance *instance = hw_find_ihandle_property (me, property->name); + p->print (p->file, " *%s", device_instance_path(instance)); + } + else + { + /* not yet initialized, ask the device for the path */ + ihandle_runtime_property_spec spec; + hw_find_ihandle_runtime_property (me, property->name, &spec); + p->print (p->file, " *%s", spec.full_path); + } + break; + } +#endif + case integer_property: + { + unsigned_word w = hw_find_integer_property (me, property->name); + p->print (p->file, " 0x%lx", (unsigned long)w); + break; + } + case range_array_property: + { + print_ranges_property (me, property, p); + break; + } + case reg_array_property: + { + print_reg_property (me, property, p); + break; + } + case string_property: + { + const char *s = hw_find_string_property (me, property->name); + print_string (me, s, p); + break; + } + case string_array_property: + { + print_string_array_property (me, property, p); + break; + } + } + } + p->print (p->file, "\n"); + } +} + +static void +print_interrupts (struct hw *me, + int my_port, + struct hw *dest, + int dest_port, + void *data) +{ + struct printer *p = data; + char src[32]; + char dst[32]; + hw_port_encode (me, my_port, src, sizeof(src), output_port); + hw_port_encode (dest, dest_port, dst, sizeof(dst), input_port); + p->print (p->file, + "%s > %s %s %s\n", + hw_path (me), + src, dst, + hw_path (dest)); +} + +static void +print_device (struct hw *me, + void *data) +{ + struct printer *p = data; + p->print (p->file, "%s\n", hw_path (me)); + print_properties (me, p); + hw_port_traverse (me, print_interrupts, data); +} + +void +hw_tree_print (struct hw *root, + hw_tree_print_callback *print, + void *file) +{ + struct printer p; + p.print = print; + p.file = file; + hw_tree_traverse (root, + print_device, NULL, + &p); +} + + + +#if NOT_YET +device_instance * +tree_instance(struct hw *root, + const char *device_specifier) +{ + /* find the device node */ + struct hw *me; + name_specifier spec; + if (!split_device_specifier(root, device_specifier, &spec)) + return NULL; + me = split_find_device(root, &spec); + if (spec.name != NULL) + return NULL; + /* create the instance */ + return device_create_instance(me, device_specifier, spec.last_args); +} +#endif + +struct hw * +hw_tree_find_device (struct hw *root, + const char *path_to_device) +{ + struct hw *node; + name_specifier spec; + + /* parse the path */ + split_device_specifier (root, path_to_device, &spec); + if (spec.value != NULL) + return NULL; /* something wierd */ + + /* now find it */ + node = split_find_device (root, &spec); + if (spec.name != NULL) + return NULL; /* not a leaf */ + + return node; +} + + +const struct hw_property * +hw_tree_find_property (struct hw *root, + const char *path_to_property) +{ + name_specifier spec; + if (!split_property_specifier (root, path_to_property, &spec)) + hw_abort (root, "Invalid property path %s", path_to_property); + root = split_find_device (root, &spec); + if (spec.name != NULL) + return NULL; /* not a leaf */ + return hw_find_property (root, spec.property); +} + +int +hw_tree_find_boolean_property (struct hw *root, + const char *path_to_property) +{ + name_specifier spec; + if (!split_property_specifier (root, path_to_property, &spec)) + hw_abort (root, "Invalid property path %s", path_to_property); + root = split_find_device (root, &spec); + if (spec.name != NULL) + hw_abort (root, "device \"%s\" not found (property \"%s\")", + spec.name, path_to_property); + return hw_find_boolean_property (root, spec.property); +} + +signed_cell +hw_tree_find_integer_property (struct hw *root, + const char *path_to_property) +{ + name_specifier spec; + if (!split_property_specifier (root, path_to_property, &spec)) + hw_abort (root, "Invalid property path %s", path_to_property); + root = split_find_device (root, &spec); + if (spec.name != NULL) + hw_abort (root, "device \"%s\" not found (property \"%s\")", + spec.name, path_to_property); + return hw_find_integer_property (root, spec.property); +} + +#if NOT_YET +device_instance * +hw_tree_find_ihandle_property (struct hw *root, + const char *path_to_property) +{ + struct hw *root; + name_specifier spec; + if (!split_property_specifier (root, path_to_property, &spec)) + hw_abort (root, "Invalid property path %s", path_to_property); + root = split_find_device (root, &spec); + if (spec.name != NULL) + hw_abort (root, "device \"%s\" not found (property \"%s\")", + spec.name, path_to_property); + return hw_find_ihandle_property (root, spec.property); +} +#endif + +const char * +hw_tree_find_string_property (struct hw *root, + const char *path_to_property) +{ + name_specifier spec; + if (!split_property_specifier (root, path_to_property, &spec)) + hw_abort (root, "Invalid property path %s", path_to_property); + root = split_find_device (root, &spec); + if (spec.name != NULL) + hw_abort (root, "device \"%s\" not found (property \"%s\")", + spec.name, path_to_property); + return hw_find_string_property (root, spec.property); +} diff --git a/sim/common/hw-tree.h b/sim/common/hw-tree.h new file mode 100644 index 00000000000..bfa5681e707 --- /dev/null +++ b/sim/common/hw-tree.h @@ -0,0 +1,119 @@ +/* This file is part of the program psim. + + Copyright (C) 1994-1997, Andrew Cagney + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + + +#ifndef HW_TREE +#define HW_TREE + + +struct hw *hw_tree_create +(SIM_DESC sd, + const char *device); + +void hw_tree_delete +(struct hw *root); + +struct hw *hw_tree_parse +(struct hw *root, + const char *fmt, + ...) __attribute__ ((format (printf, 2, 3))); + +struct hw *hw_tree_vparse +(struct hw *root, + const char *fmt, + va_list ap); + + +void hw_tree_finish +(struct hw *root); + +typedef void (hw_tree_print_callback) + (void *, + const char *fmt, + ...); + +void hw_tree_print +(struct hw *root, + hw_tree_print_callback *print, + void *file); + + +/* Tree traversal:: + + The entire device tree can be traversed using the + <> function. The traversal can be in + either prefix or postfix order. + + */ + +typedef void (hw_tree_traverse_function) + (struct hw *device, + void *data); + +void hw_tree_traverse +(struct hw *root, + hw_tree_traverse_function *prefix, + hw_tree_traverse_function *postfix, + void *data); + + +/* Tree lookup:: + + The function <> will attempt to locate the + specified device within the tree. If the device is not found a + NULL device is returned. + + */ + +struct hw * hw_tree_find_device +(struct hw *root, + const char *path); + + +const struct hw_property *hw_tree_find_property +(struct hw *root, + const char *path_to_property); + +int hw_tree_find_boolean_property +(struct hw *root, + const char *path_to_property); + +signed_cell hw_tree_find_integer_property +(struct hw *root, + const char *path_to_property); + +#if NOT_YET +device_instance *hw_tree_find_ihandle_property +(struct hw *root, + const char *path_to_property); +#endif + +const char *hw_tree_find_string_property +(struct hw *root, + const char *path_to_property); + + +/* Perform a soft reset on the created tree. */ + +void hw_tree_reset +(struct hw *root); + + +#endif diff --git a/sim/common/nltvals.def b/sim/common/nltvals.def new file mode 100644 index 00000000000..b5e82fcfb48 --- /dev/null +++ b/sim/common/nltvals.def @@ -0,0 +1,418 @@ +/* Newlib/libgloss macro values needed by remote target support. */ +/* This file is machine generated by gennltvals.sh. */ +#ifdef errno_defs +/* from errno.h */ +/* from sys/errno.h */ +/* begin errno target macros */ + { "E2BIG", 7 }, + { "EACCES", 13 }, + { "EADDRINUSE", 112 }, + { "EADDRNOTAVAIL", 125 }, + { "EADV", 68 }, + { "EAFNOSUPPORT", 106 }, + { "EAGAIN", 11 }, + { "EALREADY", 120 }, + { "EBADE", 50 }, + { "EBADF", 9 }, + { "EBADFD", 81 }, + { "EBADMSG", 77 }, + { "EBADR", 51 }, + { "EBADRQC", 54 }, + { "EBADSLT", 55 }, + { "EBFONT", 57 }, + { "EBUSY", 16 }, + { "ECHILD", 10 }, + { "ECHRNG", 37 }, + { "ECOMM", 70 }, + { "ECONNABORTED", 113 }, + { "ECONNREFUSED", 111 }, + { "ECONNRESET", 104 }, + { "EDEADLK", 45 }, + { "EDEADLOCK", 56 }, + { "EDESTADDRREQ", 121 }, + { "EDOM", 33 }, + { "EDOTDOT", 76 }, + { "EDQUOT", 132 }, + { "EEXIST", 17 }, + { "EFAULT", 14 }, + { "EFBIG", 27 }, + { "EHOSTDOWN", 117 }, + { "EHOSTUNREACH", 118 }, + { "EIDRM", 36 }, + { "EINPROGRESS", 119 }, + { "EINTR", 4 }, + { "EINVAL", 22 }, + { "EIO", 5 }, + { "EISCONN", 127 }, + { "EISDIR", 21 }, + { "EL2HLT", 44 }, + { "EL2NSYNC", 38 }, + { "EL3HLT", 39 }, + { "EL3RST", 40 }, + { "ELBIN", 75 }, + { "ELIBACC", 83 }, + { "ELIBBAD", 84 }, + { "ELIBEXEC", 87 }, + { "ELIBMAX", 86 }, + { "ELIBSCN", 85 }, + { "ELNRNG", 41 }, + { "ELOOP", 92 }, + { "EMFILE", 24 }, + { "EMLINK", 31 }, + { "EMSGSIZE", 122 }, + { "EMULTIHOP", 74 }, + { "ENAMETOOLONG", 91 }, + { "ENETDOWN", 115 }, + { "ENETRESET", 126 }, + { "ENETUNREACH", 114 }, + { "ENFILE", 23 }, + { "ENMFILE", 89 }, + { "ENOANO", 53 }, + { "ENOBUFS", 105 }, + { "ENOCSI", 43 }, + { "ENODATA", 61 }, + { "ENODEV", 19 }, + { "ENOENT", 2 }, + { "ENOEXEC", 8 }, + { "ENOLCK", 46 }, + { "ENOLINK", 67 }, + { "ENOMEM", 12 }, + { "ENOMSG", 35 }, + { "ENONET", 64 }, + { "ENOPKG", 65 }, + { "ENOPROTOOPT", 109 }, + { "ENOSPC", 28 }, + { "ENOSR", 63 }, + { "ENOSTR", 60 }, + { "ENOSYS", 88 }, + { "ENOTBLK", 15 }, + { "ENOTCONN", 128 }, + { "ENOTDIR", 20 }, + { "ENOTEMPTY", 90 }, + { "ENOTSOCK", 108 }, + { "ENOTSUP", 134 }, + { "ENOTTY", 25 }, + { "ENOTUNIQ", 80 }, + { "ENXIO", 6 }, + { "EOPNOTSUPP", 95 }, + { "EPERM", 1 }, + { "EPFNOSUPPORT", 96 }, + { "EPIPE", 32 }, + { "EPROCLIM", 130 }, + { "EPROTO", 71 }, + { "EPROTONOSUPPORT", 123 }, + { "EPROTOTYPE", 107 }, + { "ERANGE", 34 }, + { "EREMCHG", 82 }, + { "EREMOTE", 66 }, + { "EROFS", 30 }, + { "ESHUTDOWN", 110 }, + { "ESOCKTNOSUPPORT", 124 }, + { "ESPIPE", 29 }, + { "ESRCH", 3 }, + { "ESRMNT", 69 }, + { "ESTALE", 133 }, + { "ETIME", 62 }, + { "ETIMEDOUT", 116 }, + { "ETOOMANYREFS", 129 }, + { "ETXTBSY", 26 }, + { "EUNATCH", 42 }, + { "EUSERS", 131 }, + { "EWOULDBLOCK", 11 }, + { "EXDEV", 18 }, + { "EXFULL", 52 }, +/* end errno target macros */ +#endif +#ifdef signal_defs +/* from signal.h */ +/* from sys/signal.h */ +/* begin signal target macros */ + { "SIGABRT", 6 }, + { "SIGALRM", 14 }, + { "SIGBUS", 10 }, + { "SIGCHLD", 20 }, + { "SIGCLD", 20 }, + { "SIGCONT", 19 }, + { "SIGEMT", 7 }, + { "SIGFPE", 8 }, + { "SIGHUP", 1 }, + { "SIGILL", 4 }, + { "SIGINT", 2 }, + { "SIGIO", 23 }, + { "SIGIOT", 6 }, + { "SIGKILL", 9 }, + { "SIGLOST", 29 }, + { "SIGPIPE", 13 }, + { "SIGPOLL", 23 }, + { "SIGPROF", 27 }, + { "SIGQUIT", 3 }, + { "SIGSEGV", 11 }, + { "SIGSTOP", 17 }, + { "SIGSYS", 12 }, + { "SIGTERM", 15 }, + { "SIGTRAP", 5 }, + { "SIGTSTP", 18 }, + { "SIGTTIN", 21 }, + { "SIGTTOU", 22 }, + { "SIGURG", 16 }, + { "SIGUSR1", 30 }, + { "SIGUSR2", 31 }, + { "SIGVTALRM", 26 }, + { "SIGWINCH", 28 }, + { "SIGXCPU", 24 }, + { "SIGXFSZ", 25 }, +/* end signal target macros */ +#endif +#ifdef open_defs +/* from fcntl.h */ +/* from sys/fcntl.h */ +/* begin open target macros */ + { "O_ACCMODE", (0 | 1 | 2 ) }, + { "O_APPEND", 0x0008 }, + { "O_CREAT", 0x0200 }, + { "O_EXCL", 0x0800 }, + { "O_NOCTTY", 0x8000 }, + { "O_NONBLOCK", 0x4000 }, + { "O_RDONLY", 0 }, + { "O_RDWR", 2 }, + { "O_SYNC", 0x2000 }, + { "O_TRUNC", 0x0400 }, + { "O_WRONLY", 1 }, +/* end open target macros */ +#endif +#ifdef NL_TARGET_d10v +#ifdef sys_defs +/* from syscall.h */ +/* begin d10v sys target macros */ + { "SYS_ARG", 24 }, + { "SYS_chdir", 12 }, + { "SYS_chmod", 15 }, + { "SYS_chown", 16 }, + { "SYS_close", 6 }, + { "SYS_creat", 8 }, + { "SYS_execv", 11 }, + { "SYS_execve", 59 }, + { "SYS_exit", 1 }, + { "SYS_fork", 2 }, + { "SYS_fstat", 22 }, + { "SYS_getpid", 20 }, + { "SYS_isatty", 21 }, + { "SYS_kill", 60 }, + { "SYS_link", 9 }, + { "SYS_lseek", 19 }, + { "SYS_mknod", 14 }, + { "SYS_open", 5 }, + { "SYS_pipe", 42 }, + { "SYS_read", 3 }, + { "SYS_stat", 38 }, + { "SYS_time", 23 }, + { "SYS_unlink", 10 }, + { "SYS_utime", 201 }, + { "SYS_wait", 202 }, + { "SYS_wait4", 7 }, + { "SYS_write", 4 }, +/* end d10v sys target macros */ +#endif +#endif +#ifdef NL_TARGET_d30v +#ifdef sys_defs +/* from syscall.h */ +/* begin d30v sys target macros */ + { "SYS_argv", 13 }, + { "SYS_argvlen", 12 }, + { "SYS_chdir", 14 }, + { "SYS_chmod", 16 }, + { "SYS_close", 3 }, + { "SYS_exit", 1 }, + { "SYS_fstat", 10 }, + { "SYS_getpid", 8 }, + { "SYS_kill", 9 }, + { "SYS_lseek", 6 }, + { "SYS_open", 2 }, + { "SYS_read", 4 }, + { "SYS_stat", 15 }, + { "SYS_time", 18 }, + { "SYS_unlink", 7 }, + { "SYS_utime", 17 }, + { "SYS_write", 5 }, +/* end d30v sys target macros */ +#endif +#endif +#ifdef NL_TARGET_fr30 +#ifdef sys_defs +/* from syscall.h */ +/* begin fr30 sys target macros */ + { "SYS_argv", 13 }, + { "SYS_argvlen", 12 }, + { "SYS_chdir", 14 }, + { "SYS_chmod", 16 }, + { "SYS_close", 3 }, + { "SYS_exit", 1 }, + { "SYS_fstat", 10 }, + { "SYS_getpid", 8 }, + { "SYS_kill", 9 }, + { "SYS_lseek", 6 }, + { "SYS_open", 2 }, + { "SYS_read", 4 }, + { "SYS_stat", 15 }, + { "SYS_time", 18 }, + { "SYS_unlink", 7 }, + { "SYS_utime", 17 }, + { "SYS_write", 5 }, +/* end fr30 sys target macros */ +#endif +#endif +#ifdef NL_TARGET_i960 +#ifdef sys_defs +/* from syscall.h */ +/* begin i960 sys target macros */ + { "SYS_argv", 13 }, + { "SYS_argvlen", 12 }, + { "SYS_chdir", 14 }, + { "SYS_chmod", 16 }, + { "SYS_close", 234 }, + { "SYS_exit", 257 }, + { "SYS_fstat", 10 }, + { "SYS_getpid", 8 }, + { "SYS_kill", 9 }, + { "SYS_lseek", 233 }, + { "SYS_open", 230 }, + { "SYS_read", 231 }, + { "SYS_stat", 15 }, + { "SYS_time", 18 }, + { "SYS_unlink", 7 }, + { "SYS_utime", 17 }, + { "SYS_write", 232 }, +/* end i960 sys target macros */ +#endif +#endif +#ifdef NL_TARGET_m32r +#ifdef sys_defs +/* from syscall.h */ +/* begin m32r sys target macros */ + { "SYS_argv", 13 }, + { "SYS_argvlen", 12 }, + { "SYS_chdir", 14 }, + { "SYS_chmod", 16 }, + { "SYS_close", 3 }, + { "SYS_exit", 1 }, + { "SYS_fstat", 10 }, + { "SYS_getpid", 8 }, + { "SYS_kill", 9 }, + { "SYS_lseek", 6 }, + { "SYS_open", 2 }, + { "SYS_read", 4 }, + { "SYS_stat", 15 }, + { "SYS_time", 18 }, + { "SYS_unlink", 7 }, + { "SYS_utime", 17 }, + { "SYS_write", 5 }, +/* end m32r sys target macros */ +#endif +#endif +#ifdef NL_TARGET_mn10200 +#ifdef sys_defs +/* from syscall.h */ +/* begin mn10200 sys target macros */ + { "SYS_argv", 13 }, + { "SYS_argvlen", 12 }, + { "SYS_chdir", 14 }, + { "SYS_chmod", 16 }, + { "SYS_close", 3 }, + { "SYS_exit", 1 }, + { "SYS_fstat", 10 }, + { "SYS_getpid", 8 }, + { "SYS_kill", 9 }, + { "SYS_lseek", 6 }, + { "SYS_open", 2 }, + { "SYS_read", 4 }, + { "SYS_stat", 15 }, + { "SYS_time", 18 }, + { "SYS_unlink", 7 }, + { "SYS_utime", 17 }, + { "SYS_write", 5 }, +/* end mn10200 sys target macros */ +#endif +#endif +#ifdef NL_TARGET_mn10300 +#ifdef sys_defs +/* from syscall.h */ +/* begin mn10300 sys target macros */ + { "SYS_argv", 13 }, + { "SYS_argvlen", 12 }, + { "SYS_chdir", 14 }, + { "SYS_chmod", 16 }, + { "SYS_close", 3 }, + { "SYS_exit", 1 }, + { "SYS_fstat", 10 }, + { "SYS_getpid", 8 }, + { "SYS_kill", 9 }, + { "SYS_lseek", 6 }, + { "SYS_open", 2 }, + { "SYS_read", 4 }, + { "SYS_stat", 15 }, + { "SYS_time", 18 }, + { "SYS_unlink", 7 }, + { "SYS_utime", 17 }, + { "SYS_write", 5 }, +/* end mn10300 sys target macros */ +#endif +#endif +#ifdef NL_TARGET_sparc +#ifdef sys_defs +/* from syscall.h */ +/* begin sparc sys target macros */ + { "SYS_argv", 13 }, + { "SYS_argvlen", 12 }, + { "SYS_chdir", 14 }, + { "SYS_chmod", 16 }, + { "SYS_close", 3 }, + { "SYS_exit", 1 }, + { "SYS_fstat", 10 }, + { "SYS_getpid", 8 }, + { "SYS_kill", 9 }, + { "SYS_lseek", 6 }, + { "SYS_open", 2 }, + { "SYS_read", 4 }, + { "SYS_stat", 15 }, + { "SYS_time", 18 }, + { "SYS_unlink", 7 }, + { "SYS_utime", 17 }, + { "SYS_write", 5 }, +/* end sparc sys target macros */ +#endif +#endif +#ifdef NL_TARGET_v850 +#ifdef sys_defs +/* from syscall.h */ +/* begin v850 sys target macros */ + { "SYS_ARG", 24 }, + { "SYS_chdir", 12 }, + { "SYS_chmod", 15 }, + { "SYS_chown", 16 }, + { "SYS_close", 6 }, + { "SYS_creat", 8 }, + { "SYS_execv", 11 }, + { "SYS_execve", 59 }, + { "SYS_exit", 1 }, + { "SYS_fork", 2 }, + { "SYS_fstat", 22 }, + { "SYS_getpid", 20 }, + { "SYS_gettimeofday", 116 }, + { "SYS_isatty", 21 }, + { "SYS_link", 9 }, + { "SYS_lseek", 19 }, + { "SYS_mknod", 14 }, + { "SYS_open", 5 }, + { "SYS_pipe", 42 }, + { "SYS_read", 3 }, + { "SYS_stat", 38 }, + { "SYS_time", 23 }, + { "SYS_unlink", 10 }, + { "SYS_utime", 201 }, + { "SYS_wait", 202 }, + { "SYS_wait4", 7 }, + { "SYS_write", 4 }, +/* end v850 sys target macros */ +#endif +#endif diff --git a/sim/common/nrun.c b/sim/common/nrun.c new file mode 100644 index 00000000000..42be33ef655 --- /dev/null +++ b/sim/common/nrun.c @@ -0,0 +1,214 @@ +/* New version of run front end support for simulators. + Copyright (C) 1997 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include +#include "sim-main.h" + +#include "bfd.h" + +#ifdef HAVE_ENVIRON +extern char **environ; +#endif + +static void usage (void); + +extern host_callback default_callback; + +static char *myname; + +static SIM_DESC sd; + +static RETSIGTYPE +cntrl_c (int sig) +{ + if (! sim_stop (sd)) + { + fprintf (stderr, "Quit!\n"); + exit (1); + } +} + +int +main (int argc, char **argv) +{ + char *name; + char **prog_argv = NULL; + struct _bfd *prog_bfd; + enum sim_stop reason; + int sigrc = 0; + int single_step = 0; + RETSIGTYPE (*prev_sigint) (); + + myname = argv[0] + strlen (argv[0]); + while (myname > argv[0] && myname[-1] != '/') + --myname; + + /* INTERNAL: When MYNAME is `step', single step the simulator + instead of allowing it to run free. The sole purpose of this + HACK is to allow the sim_resume interface's step argument to be + tested without having to build/run gdb. */ + if (strlen (myname) > 4 && strcmp (myname - 4, "step") == 0) + { + single_step = 1; + } + + /* Create an instance of the simulator. */ + default_callback.init (&default_callback); + sd = sim_open (SIM_OPEN_STANDALONE, &default_callback, NULL, argv); + if (sd == 0) + exit (1); + if (STATE_MAGIC (sd) != SIM_MAGIC_NUMBER) + { + fprintf (stderr, "Internal error - bad magic number in simulator struct\n"); + abort (); + } + + /* Was there a program to run? */ + prog_argv = STATE_PROG_ARGV (sd); + prog_bfd = STATE_PROG_BFD (sd); + if (prog_argv == NULL || *prog_argv == NULL) + usage (); + + name = *prog_argv; + + /* For simulators that don't open prog during sim_open() */ + if (prog_bfd == NULL) + { + prog_bfd = bfd_openr (name, 0); + if (prog_bfd == NULL) + { + fprintf (stderr, "%s: can't open \"%s\": %s\n", + myname, name, bfd_errmsg (bfd_get_error ())); + exit (1); + } + if (!bfd_check_format (prog_bfd, bfd_object)) + { + fprintf (stderr, "%s: \"%s\" is not an object file: %s\n", + myname, name, bfd_errmsg (bfd_get_error ())); + exit (1); + } + } + + if (STATE_VERBOSE_P (sd)) + printf ("%s %s\n", myname, name); + + /* Load the program into the simulator. */ + if (sim_load (sd, name, prog_bfd, 0) == SIM_RC_FAIL) + exit (1); + + /* Prepare the program for execution. */ +#ifdef HAVE_ENVIRON + sim_create_inferior (sd, prog_bfd, prog_argv, environ); +#else + sim_create_inferior (sd, prog_bfd, prog_argv, NULL); +#endif + + /* Run/Step the program. */ + if (single_step) + { + do + { + prev_sigint = signal (SIGINT, cntrl_c); + sim_resume (sd, 1/*step*/, 0); + signal (SIGINT, prev_sigint); + sim_stop_reason (sd, &reason, &sigrc); + + if ((reason == sim_stopped) && + (sigrc == sim_signal_to_host (sd, SIM_SIGINT))) + break; /* exit on control-C */ + } + /* remain on breakpoint or signals in oe mode*/ + while (((reason == sim_signalled) && + (sigrc == sim_signal_to_host (sd, SIM_SIGTRAP))) || + ((reason == sim_stopped) && + (STATE_ENVIRONMENT (sd) == OPERATING_ENVIRONMENT))); + } + else do + { +#if defined (HAVE_SIGACTION) && defined (SA_RESTART) + struct sigaction sa, osa; + sa.sa_handler = cntrl_c; + sigemptyset (&sa.sa_mask); + sa.sa_flags = 0; + sigaction (SIGINT, &sa, &osa); + prev_sigint = osa.sa_handler; +#else + prev_sigint = signal (SIGINT, cntrl_c); +#endif + sim_resume (sd, 0, sigrc); + signal (SIGINT, prev_sigint); + sim_stop_reason (sd, &reason, &sigrc); + + if ((reason == sim_stopped) && + (sigrc == sim_signal_to_host (sd, SIM_SIGINT))) + break; /* exit on control-C */ + + /* remain on signals in oe mode */ + } while ((reason == sim_stopped) && + (STATE_ENVIRONMENT (sd) == OPERATING_ENVIRONMENT)); + + /* Print any stats the simulator collected. */ + sim_info (sd, 0); + + /* Shutdown the simulator. */ + sim_close (sd, 0); + + /* If reason is sim_exited, then sigrc holds the exit code which we want + to return. If reason is sim_stopped or sim_signalled, then sigrc holds + the signal that the simulator received; we want to return that to + indicate failure. */ + +#ifdef SIM_H8300 /* FIXME: Ugh. grep for SLEEP in compile.c */ + if (sigrc == SIGILL) + abort (); + sigrc = 0; +#else + /* Why did we stop? */ + switch (reason) + { + case sim_signalled: + case sim_stopped: + if (sigrc != 0) + fprintf (stderr, "program stopped with signal %d.\n", sigrc); + break; + + case sim_exited: + break; + + default: + fprintf (stderr, "program in undefined state (%d:%d)\n", reason, sigrc); + break; + + } +#endif + + return sigrc; +} + +static void +usage () +{ + fprintf (stderr, "Usage: %s [options] program [program args]\n", myname); + fprintf (stderr, "Run `%s --help' for full list of options.\n", myname); + exit (1); +} + + +#ifdef __CYGWIN32__ +/* no-op GUI update hook for standalone sim */ +void (*ui_loop_hook) PARAMS ((int)) = NULL; +#endif diff --git a/sim/common/run.1 b/sim/common/run.1 new file mode 100644 index 00000000000..886e20bab6b --- /dev/null +++ b/sim/common/run.1 @@ -0,0 +1,107 @@ +.\" Copyright (c) 1993 Free Software Foundation +.\" See section COPYING for conditions for redistribution +.TH run 1 "13oct1993" "GNU Tools" "GNU Tools" +.de BP +.sp +.ti -.2i +\(** +.. + +.SH NAME +run\(em\&Simulator front-end + +.SH SYNOPSIS +.hy 0 +.na +.TP +.B run +.RB "[\|" \-v "\|]" +." .RB "[\|" \-t "\|]" +.RB "[\|" \-p +.IR freq "\|]" +.RB "[\|" \-m +.IR memory "\|]" +.I program +.ad b +.hy 1 +.SH DESCRIPTION + +Use `\|\c +.BI run " program"\c +\&\|' to execute a binary by interpreting machine instructions on your +host computer. + +.B run +is the same emulator used by GDB's `\|\c +.B target sim\c +\&\|' command. You can run it directly by executing +.B run +if you just want to see your program execute, and do not need any +debugger functionality. You can also use +.B run +to generate profiling information for analysis with +.BR gprof . + +.SH OPTIONS + +.TP +.B \-v +Verbose output. Display the name of the program to run before +execution; after execution, display the number of instructions +executed, the number of machine cycles emulated, the number of +pipeline stalls, the real time taken, the emulated execution time +taken, and a summary of how much profiling information was generated. +." +." .TP +." .B \-t +." `trace', calls a sim_trace routine that does nothing. + +.TP +.BI \-p " freq" +Generate profile information (for use with +.B gprof\c +\&). +.I freq +is the profiling frequency. Write the profiling information to a file called +.BR gmon.out . + +.TP +.BI \-m " memory" +Set the memory size for the emulated machine to two to the power +.IR memory . +The default value is 19, emulating a board with 524288 bytes of memory. + +.PP + +.SH "SEE ALSO" +.RB "`\|" gprof "\|'" +entry in +.B info\c +\&; +.RB "`\|" gdb "\|'" +entry in +.B info\c +\&; +.I +Using GDB: A Guide to the GNU Source-Level Debugger\c +, Richard M. Stallman and Roland H. Pesch. + +.SH COPYING +Copyright (c) 1993 Free Software Foundation, Inc. +.PP +Permission is granted to make and distribute verbatim copies of +this manual provided the copyright notice and this permission notice +are preserved on all copies. +.PP +Permission is granted to copy and distribute modified versions of this +manual under the conditions for verbatim copying, provided that the +entire resulting derived work is distributed under the terms of a +permission notice identical to this one. +.PP +Permission is granted to copy and distribute translations of this +manual into another language, under the above conditions for modified +versions, except that this permission notice may be included in +translations approved by the Free Software Foundation instead of in +the original English. + + diff --git a/sim/common/run.c b/sim/common/run.c new file mode 100644 index 00000000000..2a701bc4900 --- /dev/null +++ b/sim/common/run.c @@ -0,0 +1,308 @@ +/* run front end support for all the simulators. + Copyright (C) 1992, 93-96, 1997 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* Steve Chamberlain sac@cygnus.com, + and others at Cygnus. */ + +#include "config.h" +#include "tconfig.h" + +#include +#include +#ifdef __STDC__ +#include +#else +#include +#endif + +#ifdef HAVE_STDLIB_H +#include +#endif + +#ifdef HAVE_STRING_H +#include +#else +#ifdef HAVE_STRINGS_H +#include +#endif +#endif + +#include "libiberty.h" +#include "bfd.h" +#include "callback.h" +#include "remote-sim.h" + +#include "../libiberty/alloca-conf.h" + +static void usage PARAMS ((void)); +extern int optind; +extern char *optarg; + +extern host_callback default_callback; + +static char *myname; + + +/* NOTE: sim_size() and sim_trace() are going away */ +extern int sim_trace PARAMS ((SIM_DESC sd)); + +extern int getopt (); + +static SIM_DESC sd; + +static RETSIGTYPE +cntrl_c (int sig) +{ + if (! sim_stop (sd)) + { + fprintf (stderr, "Quit!\n"); + exit (1); + } +} + +int +main (ac, av) + int ac; + char **av; +{ + RETSIGTYPE (*prev_sigint) (); + bfd *abfd; + int i; + int verbose = 0; + int trace = 0; + char *name; + static char *no_args[4]; + char **sim_argv = &no_args[0]; + char **prog_args; + enum sim_stop reason; + int sigrc; + + myname = av[0] + strlen (av[0]); + while (myname > av[0] && myname[-1] != '/') + --myname; + + /* The first element of sim_open's argv is the program name. */ + no_args[0] = av[0]; +#ifdef SIM_HAVE_BIENDIAN + no_args[1] = "-E"; + no_args[2] = "set-later"; +#endif + + /* FIXME: This is currently being migrated into sim_open. + Simulators that use functions such as sim_size() still require + this. */ + default_callback.init (&default_callback); + sim_set_callbacks (&default_callback); + + /* FIXME: This is currently being rewritten to have each simulator + do all argv processing. */ + +#ifdef SIM_H8300 /* FIXME: quick hack */ + while ((i = getopt (ac, av, "a:c:m:p:s:htv")) != EOF) +#else + while ((i = getopt (ac, av, "a:c:m:p:s:tv")) != EOF) +#endif + switch (i) + { + case 'a': + /* FIXME: Temporary hack. */ + { + int len = strlen (av[0]) + strlen (optarg); + char *argbuf = (char *) alloca (len + 2 + 50); + sprintf (argbuf, "%s %s", av[0], optarg); +#ifdef SIM_HAVE_BIENDIAN + /* The desired endianness must be passed to sim_open. + The value for "set-later" is set when we know what it is. + -E support isn't yet part of the published interface. */ + strcat (argbuf, " -E set-later"); +#endif + sim_argv = buildargv (argbuf); + } + break; +#ifdef SIM_HAVE_SIMCACHE + case 'c': + sim_set_simcache_size (atoi (optarg)); + break; +#endif + case 'm': + /* FIXME: Rename to sim_set_mem_size. */ + sim_size (atoi (optarg)); + break; +#ifdef SIM_HAVE_PROFILE + case 'p': + sim_set_profile (atoi (optarg)); + break; + case 's': + sim_set_profile_size (atoi (optarg)); + break; +#endif + case 't': + trace = 1; + /* FIXME: need to allow specification of what to trace. */ + /* sim_set_trace (1); */ + break; + case 'v': + /* Things that are printed with -v are the kinds of things that + gcc -v prints. This is not meant to include detailed tracing + or debugging information, just summaries. */ + verbose = 1; + /* sim_set_verbose (1); */ + break; + /* FIXME: Quick hack, to be replaced by more general facility. */ +#ifdef SIM_H8300 + case 'h': + set_h8300h (1); + break; +#endif + default: + usage (); + } + + ac -= optind; + av += optind; + if (ac <= 0) + usage (); + + name = *av; + prog_args = av; + + if (verbose) + { + printf ("%s %s\n", myname, name); + } + + abfd = bfd_openr (name, 0); + if (!abfd) + { + fprintf (stderr, "%s: can't open %s: %s\n", + myname, name, bfd_errmsg (bfd_get_error ())); + exit (1); + } + + if (!bfd_check_format (abfd, bfd_object)) + { + fprintf (stderr, "%s: can't load %s: %s\n", + myname, name, bfd_errmsg (bfd_get_error ())); + exit (1); + } + +#ifdef SIM_HAVE_BIENDIAN + /* The endianness must be passed to sim_open because one may wish to + examine/set registers before calling sim_load [which is the other + place where one can determine endianness]. We previously passed the + endianness via global `target_byte_order' but that's not a clean + interface. */ + for (i = 1; sim_argv[i + 1] != NULL; ++i) + continue; + if (bfd_big_endian (abfd)) + sim_argv[i] = "big"; + else + sim_argv[i] = "little"; +#endif + + /* Ensure that any run-time initialisation that needs to be + performed by the simulator can occur. */ + sd = sim_open (SIM_OPEN_STANDALONE, &default_callback, abfd, sim_argv); + if (sd == 0) + exit (1); + + if (sim_load (sd, name, abfd, 0) == SIM_RC_FAIL) + exit (1); + + if (sim_create_inferior (sd, abfd, prog_args, NULL) == SIM_RC_FAIL) + exit (1); + + prev_sigint = signal (SIGINT, cntrl_c); + if (trace) + { + int done = 0; + while (!done) + { + done = sim_trace (sd); + } + } + else + { + sim_resume (sd, 0, 0); + } + signal (SIGINT, prev_sigint); + + if (verbose) + sim_info (sd, 0); + + sim_stop_reason (sd, &reason, &sigrc); + + sim_close (sd, 0); + + /* If reason is sim_exited, then sigrc holds the exit code which we want + to return. If reason is sim_stopped or sim_signalled, then sigrc holds + the signal that the simulator received; we want to return that to + indicate failure. */ + +#ifdef SIM_H8300 /* FIXME: Ugh. grep for SLEEP in compile.c */ + if (sigrc == SIGILL) + abort (); + sigrc = 0; +#else + /* Why did we stop? */ + switch (reason) + { + case sim_signalled: + case sim_stopped: + if (sigrc != 0) + fprintf (stderr, "program stopped with signal %d.\n", sigrc); + break; + + case sim_exited: + break; + + case sim_running: + case sim_polling: /* these indicate a serious problem */ + abort (); + break; + + } +#endif + + return sigrc; +} + +static void +usage () +{ + fprintf (stderr, "Usage: %s [options] program [program args]\n", myname); + fprintf (stderr, "Options:\n"); + fprintf (stderr, "-a args Pass `args' to simulator.\n"); +#ifdef SIM_HAVE_SIMCACHE + fprintf (stderr, "-c size Set simulator cache size to `size'.\n"); +#endif +#ifdef SIM_H8300 + fprintf (stderr, "-h Executable is for h8/300h or h8/300s.\n"); +#endif + fprintf (stderr, "-m size Set memory size of simulator, in bytes.\n"); +#ifdef SIM_HAVE_PROFILE + fprintf (stderr, "-p freq Set profiling frequency.\n"); + fprintf (stderr, "-s size Set profiling size.\n"); +#endif + fprintf (stderr, "-t Perform instruction tracing.\n"); + fprintf (stderr, " Note: Very few simulators support tracing.\n"); + fprintf (stderr, "-v Verbose output.\n"); + fprintf (stderr, "\n"); + fprintf (stderr, "program args Arguments to pass to simulated program.\n"); + fprintf (stderr, " Note: Very few simulators support this.\n"); + exit (1); +} diff --git a/sim/common/sim-abort.c b/sim/common/sim-abort.c new file mode 100644 index 00000000000..088bf201a68 --- /dev/null +++ b/sim/common/sim-abort.c @@ -0,0 +1,60 @@ +/* Generic simulator abort. + Copyright (C) 1997 Free Software Foundation, Inc. + Contributed by Cygnus Support. + +This file is part of GDB, the GNU debugger. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include + +#include "sim-main.h" +#include "sim-assert.h" + +/* This is an implementation of sim_engine_abort that does not use + longjmp, instead it just calls sim_io_error. sim_io_error will + jump right out of the simulator. + + It is intended as a holder for simulators that have started to use + sim-core et.al. but are not yet in a position to use sim-engine + (the setjmp/longjmp code). */ + + +void +sim_engine_abort (SIM_DESC sd, + sim_cpu *cpu, + sim_cia cia, + const char *fmt, + ...) +{ + ASSERT (sd == NULL || STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); + if (sd != NULL) + { + va_list ap; + va_start(ap, fmt); + sim_io_evprintf (sd, fmt, ap); + va_end(ap); + sim_io_error (sd, "\n"); + } + else + { + va_list ap; + va_start(ap, fmt); + vfprintf (stderr, fmt, ap); + va_end(ap); + fprintf (stderr, "\n"); + abort (); + } +} diff --git a/sim/common/sim-alu.h b/sim/common/sim-alu.h new file mode 100644 index 00000000000..49d1018527a --- /dev/null +++ b/sim/common/sim-alu.h @@ -0,0 +1,1047 @@ +/* This file is part of the program psim. + + Copyright (C) 1994-1996, Andrew Cagney + Copyright (C) 1997, Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + + +#ifndef _SIM_ALU_H_ +#define _SIM_ALU_H_ + +#include "symcat.h" + + +/* INTEGER ALU MODULE: + + This module provides an implementation of 2's complement arithmetic + including the recording of carry and overflow status bits. + + + EXAMPLE: + + Code using this module includes it into sim-main.h and then, as a + convention, defines macro's ALU*_END that records the result of any + aritmetic performed. Ex: + + #include "sim-alu.h" + #define ALU32_END(RES) \ + (RES) = ALU32_OVERFLOW_RESULT; \ + carry = ALU32_HAD_CARRY_BORROW; \ + overflow = ALU32_HAD_OVERFLOW + + The macro's are then used vis: + + { + ALU32_BEGIN (GPR[i]); + ALU32_ADDC (GPR[j]); + ALU32_END (GPR[k]); + } + + + NOTES: + + Macros exist for efficiently computing 8, 16, 32 and 64 bit + arithmetic - ALU8_*, ALU16_*, .... In addition, according to + TARGET_WORD_BITSIZE a set of short-hand macros are defined - ALU_* + + Initialization: + + ALU*_BEGIN(ACC): Declare initialize the ALU accumulator with ACC. + + Results: + + The calculation of the final result may be computed a number + of different ways. Three different overflow macro's are + defined, the most efficient one to use depends on which other + outputs from the alu are being used. + + ALU*_RESULT: Generic ALU result output. + + ALU*_HAD_OVERFLOW: Returns a nonzero value if signed overflow + occured. + + ALU*_OVERFLOW_RESULT: If the macro ALU*_HAD_OVERFLOW is being + used this is the most efficient result available. Ex: + + #define ALU16_END(RES) \ + if (ALU16_HAD_OVERFLOW) \ + sim_engine_halt (...); \ + (RES) = ALU16_OVERFLOW_RESULT + + ALU*_HAD_CARRY_BORROW: Returns a nonzero value if unsigned + overflow or underflow (also refered to as carry and borrow) + occured. + + ALU*_CARRY_BORROW_RESULT: If the macro ALU*_HAD_CARRY_BORROW is being + used this is the most efficient result available. Ex: + + #define ALU64_END(RES) \ + State.carry = ALU64_HAD_CARRY_BORROW; \ + (RES) = ALU64_CARRY_BORROW_RESULT + + + Addition: + + ALU*_ADD(VAL): Add VAL to the ALU accumulator. Record any + overflow as well as the final result. + + ALU*_ADDC(VAL): Add VAL to the ALU accumulator. Record any + carry-out or overflow as well as the final result. + + ALU*_ADDC_C(VAL,CI): Add VAL and CI (carry-in). Record any + carry-out or overflow as well as the final result. + + Subtraction: + + ALU*_SUB(VAL): Subtract VAL from the ALU accumulator. Record + any underflow as well as the final result. + + ALU*_SUBC(VAL): Subtract VAL from the ALU accumulator using + negated addition. Record any underflow or carry-out as well + as the final result. + + ALU*_SUBB(VAL): Subtract VAL from the ALU accumulator using + direct subtraction (ACC+~VAL+1). Record any underflow or + borrow-out as well as the final result. + + ALU*_SUBC_X(VAL,CI): Subtract VAL and CI (carry-in) from the + ALU accumulator using extended negated addition (ACC+~VAL+CI). + Record any underflow or carry-out as well as the final result. + + ALU*_SUBB_B(VAL,BI): Subtract VAL and BI (borrow-in) from the + ALU accumulator using direct subtraction. Record any + underflow or borrow-out as well as the final result. + + + */ + + + +/* Twos complement aritmetic - addition/subtraction - carry/borrow + (or you thought you knew the answer to 0-0) + + + + Notation and Properties: + + + Xn denotes the value X stored in N bits. + + MSBn (X): The most significant (sign) bit of X treated as an N bit + value. + + SEXTn (X): The infinite sign extension of X treated as an N bit + value. + + MAXn, MINn: The upper and lower bound of a signed, two's + complement N bit value. + + UMAXn: The upper bound of an unsigned N bit value (the lower + bound is always zero). + + Un: UMAXn + 1. Unsigned arrithmetic is computed `modulo (Un)'. + + X[p]: Is bit P of X. X[0] denotes the least signifant bit. + + ~X[p]: Is the inversion of bit X[p]. Also equal to 1-X[p], + (1+X[p])mod(2). + + + + Addition - Overflow - Introduction: + + + Overflow/Overflow indicates an error in computation of signed + arrithmetic. i.e. given X,Y in [MINn..MAXn]; overflow + indicates that the result X+Y > MAXn or X+Y < MIN_INTx. + + Hardware traditionally implements overflow by computing the XOR of + carry-in/carry-out of the most significant bit of the ALU. Here + other methods need to be found. + + + + Addition - Overflow - method 1: + + + Overflow occures when the sign (most significant bit) of the two N + bit operands is identical but different to the sign of the result: + + Rn = (Xn + Yn) + V = MSBn (~(Xn ^ Yn) & (Rn ^ Xn)) + + + + Addition - Overflow - method 2: + + + The two N bit operands are sign extended to M>N bits and then + added. Overflow occures when SIGN_BIT and SIGN_BIT do not + match. + + Rm = (SEXTn (Xn) + SEXTn (Yn)) + V = MSBn ((Rm >> (M - N)) ^ Rm) + + + + Addition - Overflow - method 3: + + + The two N bit operands are sign extended to M>N bits and then + added. Overflow occures when the result is outside of the sign + extended range [MINn .. MAXn]. + + + + Addition - Overflow - method 4: + + + Given the Result and Carry-out bits, the oVerflow from the addition + of X, Y and carry-In can be computed using the equation: + + Rn = (Xn + Yn) + V = (MSBn ((Xn ^ Yn) ^ Rn)) ^ C) + + As shown in the table below: + + I X Y R C | V | X^Y ^R ^C + ---------------+---+------------- + 0 0 0 0 0 | 0 | 0 0 0 + 0 0 1 1 0 | 0 | 1 0 0 + 0 1 0 1 0 | 0 | 1 0 0 + 0 1 1 0 1 | 1 | 0 0 1 + 1 0 0 1 0 | 1 | 0 1 1 + 1 0 1 0 1 | 0 | 1 1 0 + 1 1 0 0 1 | 0 | 1 1 0 + 1 1 1 1 1 | 0 | 0 1 0 + + + + Addition - Carry - Introduction: + + + Carry (poorly named) indicates that an overflow occured for + unsigned N bit addition. i.e. given X, Y in [0..UMAXn] then + carry indicates X+Y > UMAXn or X+Y >= Un. + + The following table lists the output for all given inputs into a + full-adder. + + I X Y R | C + ------------+--- + 0 0 0 0 | 0 + 0 0 1 1 | 0 + 0 1 0 1 | 0 + 0 1 1 0 | 1 + 1 0 0 1 | 0 + 1 0 1 0 | 1 + 1 1 0 0 | 1 + 1 1 1 1 | 1 + + (carry-In, X, Y, Result, Carry-out): + + + + Addition - Carry - method 1: + + + Looking at the terms X, Y and R we want an equation for C. + + XY\R 0 1 + +------- + 00 | 0 0 + 01 | 1 0 + 11 | 1 1 + 10 | 1 0 + + This giving us the sum-of-prod equation: + + MSBn ((Xn & Yn) | (Xn & ~Rn) | (Yn & ~Rn)) + + Verifying: + + I X Y R | C | X&Y X&~R Y&~R + ------------+---+--------------- + 0 0 0 0 | 0 | 0 0 0 + 0 0 1 1 | 0 | 0 0 0 + 0 1 0 1 | 0 | 0 0 0 + 0 1 1 0 | 1 | 1 1 1 + 1 0 0 1 | 0 | 0 0 0 + 1 0 1 0 | 1 | 0 0 1 + 1 1 0 0 | 1 | 0 1 0 + 1 1 1 1 | 1 | 1 0 0 + + + + Addition - Carry - method 2: + + + Given two signed N bit numbers, a carry can be detected by treating + the numbers as N bit unsigned and adding them using M>N unsigned + arrithmetic. Carry is indicated by bit (1 << N) being set (result + >= 2**N). + + + + Addition - Carry - method 3: + + + Given the oVerflow bit. The carry can be computed from: + + (~R&V) | (R&V) + + + + Addition - Carry - method 4: + + Given two signed numbers. Treating them as unsigned we have: + + 0 <= X < Un, 0 <= Y < Un + ==> X + Y < 2 Un + + Consider Y when carry occures: + + X + Y >= Un, Y < Un + ==> (Un - X) <= Y < Un # re-arange + ==> Un <= X + Y < Un + X < 2 Un # add Xn + ==> 0 <= (X + Y) mod Un < X mod Un + + or when carry as occured: + + (X + Y) mod Un < X mod Un + + Consider Y when carry does not occure: + + X + Y < Un + have X < Un, Y >= 0 + ==> X <= X + Y < Un + ==> X mod Un <= (X + Y) mod Un + + or when carry has not occured: + + ! ( (X + Y) mod Un < X mod Un) + + hence we get carry by computing in N bit unsigned arrithmetic. + + carry <- (Xn + Yn) < Xn + + + + Subtraction - Introduction + + + There are two different ways of computing the signed two's + complement difference of two numbers. The first is based on + negative addition, the second on direct subtraction. + + + + Subtraction - Carry - Introduction - Negated Addition + + + The equation X - Y can be computed using: + + X + (-Y) + ==> X + ~Y + 1 # -Y = ~Y + 1 + + In addition to the result, the equation produces Carry-out. For + succeeding extended prrcision calculations, the more general + equation can be used: + + C[p]:R[p] = X[p] + ~Y[p] + C[p-1] + where C[0]:R[0] = X[0] + ~Y[0] + 1 + + + + Subtraction - Borrow - Introduction - Direct Subtraction + + + The alternative to negative addition is direct subtraction where + `X-Y is computed directly. In addition to the result of the + calculation, a Borrow bit is produced. In general terms: + + B[p]:R[p] = X[p] - Y[p] - B[p-1] + where B[0]:R[0] = X[0] - Y[0] + + The Borrow bit is the complement of the Carry bit produced by + Negated Addition above. A dodgy proof follows: + + Case 0: + C[0]:R[0] = X[0] + ~Y[0] + 1 + ==> C[0]:R[0] = X[0] + 1 - Y[0] + 1 # ~Y[0] = (1 - Y[0])? + ==> C[0]:R[0] = 2 + X[0] - Y[0] + ==> C[0]:R[0] = 2 + B[0]:R[0] + ==> C[0]:R[0] = (1 + B[0]):R[0] + ==> C[0] = ~B[0] # (1 + B[0]) mod 2 = ~B[0]? + + Case P: + C[p]:R[p] = X[p] + ~Y[p] + C[p-1] + ==> C[p]:R[p] = X[p] + 1 - Y[0] + 1 - B[p-1] + ==> C[p]:R[p] = 2 + X[p] - Y[0] - B[p-1] + ==> C[p]:R[p] = 2 + B[p]:R[p] + ==> C[p]:R[p] = (1 + B[p]):R[p] + ==> C[p] = ~B[p] + + The table below lists all possible inputs/outputs for a + full-subtractor: + + X Y I | R B + 0 0 0 | 0 0 + 0 0 1 | 1 1 + 0 1 0 | 1 1 + 0 1 1 | 0 1 + 1 0 0 | 1 0 + 1 0 1 | 0 0 + 1 1 0 | 0 0 + 1 1 1 | 1 1 + + + + Subtraction - Method 1 + + + Treating Xn and Yn as unsigned values then a borrow (unsigned + underflow) occures when: + + B = Xn < Yn + ==> C = Xn >= Yn + + */ + + + +/* 8 bit target expressions: + + Since the host's natural bitsize > 8 bits, carry method 2 and + overflow method 2 are used. */ + +#define ALU8_BEGIN(VAL) \ +unsigned alu8_cr = (unsigned8) (VAL); \ +signed alu8_vr = (signed8) (alu8_cr) + +#define ALU8_SET(VAL) \ +alu8_cr = (unsigned8) (VAL); \ +alu8_vr = (signed8) (alu8_cr) + +#define ALU8_SET_CARRY_BORROW(CARRY) \ +do { \ + if (CARRY) \ + alu8_cr |= ((signed)-1) << 8; \ + else \ + alu8_cr &= 0xff; \ +} while (0) + +#define ALU8_HAD_CARRY_BORROW (alu8_cr & LSBIT32(8)) +#define ALU8_HAD_OVERFLOW (((alu8_vr >> 8) ^ alu8_vr) & LSBIT32 (8-1)) + +#define ALU8_RESULT ((unsigned8) alu8_cr) +#define ALU8_CARRY_BORROW_RESULT ((unsigned8) alu8_cr) +#define ALU8_OVERFLOW_RESULT ((unsigned8) alu8_vr) + +/* #define ALU8_END ????? - target dependant */ + + + +/* 16 bit target expressions: + + Since the host's natural bitsize > 16 bits, carry method 2 and + overflow method 2 are used. */ + +#define ALU16_BEGIN(VAL) \ +signed alu16_cr = (unsigned16) (VAL); \ +unsigned alu16_vr = (signed16) (alu16_cr) + +#define ALU16_SET(VAL) \ +alu16_cr = (unsigned16) (VAL); \ +alu16_vr = (signed16) (alu16_cr) + +#define ALU16_SET_CARRY_BORROW(CARRY) \ +do { \ + if (CARRY) \ + alu16_cr |= ((signed)-1) << 16; \ + else \ + alu16_cr &= 0xffff; \ +} while (0) + +#define ALU16_HAD_CARRY_BORROW (alu16_cr & LSBIT32(16)) +#define ALU16_HAD_OVERFLOW (((alu16_vr >> 16) ^ alu16_vr) & LSBIT32 (16-1)) + +#define ALU16_RESULT ((unsigned16) alu16_cr) +#define ALU16_CARRY_BORROW_RESULT ((unsigned16) alu16_cr) +#define ALU16_OVERFLOW_RESULT ((unsigned16) alu16_vr) + +/* #define ALU16_END ????? - target dependant */ + + + +/* 32 bit target expressions: + + Since most hosts do not support 64 (> 32) bit arrithmetic, carry + method 4 and overflow method 4 are used. */ + +#define ALU32_BEGIN(VAL) \ +unsigned32 alu32_r = (VAL); \ +int alu32_c = 0; \ +int alu32_v = 0 + +#define ALU32_SET(VAL) \ +alu32_r = (VAL); \ +alu32_c = 0; \ +alu32_v = 0 + +#define ALU32_SET_CARRY_BORROW(CARRY) alu32_c = (CARRY) + +#define ALU32_HAD_CARRY_BORROW (alu32_c) +#define ALU32_HAD_OVERFLOW (alu32_v) + +#define ALU32_RESULT (alu32_r) +#define ALU32_CARRY_BORROW_RESULT (alu32_r) +#define ALU32_OVERFLOW_RESULT (alu32_r) + + + +/* 64 bit target expressions: + + Even though the host typically doesn't support native 64 bit + arrithmetic, it is still used. */ + +#define ALU64_BEGIN(VAL) \ +unsigned64 alu64_r = (VAL); \ +int alu64_c = 0; \ +int alu64_v = 0 + +#define ALU64_SET(VAL) \ +alu64_r = (VAL); \ +alu64_c = 0; \ +alu64_v = 0 + +#define ALU64_SET_CARRY_BORROW(CARRY) alu64_c = (CARRY) + +#define ALU64_HAD_CARRY_BORROW (alu64_c) +#define ALU64_HAD_OVERFLOW (alu64_v) + +#define ALU64_RESULT (alu64_r) +#define ALU64_CARRY_BORROW_RESULT (alu64_r) +#define ALU64_OVERFLOW_RESULT (alu64_r) + + + +/* Generic versions of above macros */ + +#define ALU_BEGIN XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_BEGIN) +#define ALU_SET XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_SET) +#define ALU_SET_CARRY XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_SET_CARRY) + +#define ALU_HAD_OVERFLOW XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_HAD_OVERFLOW) +#define ALU_HAD_CARRY XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_HAD_CARRY) + +#define ALU_RESULT XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_RESULT) +#define ALU_OVERFLOW_RESULT XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_OVERFLOW_RESULT) +#define ALU_CARRY_RESULT XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_CARRY_RESULT) + + + +/* Basic operation - add (overflowing) */ + +#define ALU8_ADD(VAL) \ +do { \ + unsigned8 alu8add_val = (VAL); \ + ALU8_ADDC (alu8add_val); \ +} while (0) + +#define ALU16_ADD(VAL) \ +do { \ + unsigned16 alu16add_val = (VAL); \ + ALU16_ADDC (alu8add_val); \ +} while (0) + +#define ALU32_ADD(VAL) \ +do { \ + unsigned32 alu32add_val = (VAL); \ + ALU32_ADDC (alu32add_val); \ +} while (0) + +#define ALU64_ADD(VAL) \ +do { \ + unsigned64 alu64add_val = (unsigned64) (VAL); \ + ALU64_ADDC (alu64add_val); \ +} while (0) + +#define ALU_ADD XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_ADD) + + + +/* Basic operation - add carrying (and overflowing) */ + +#define ALU8_ADDC(VAL) \ +do { \ + unsigned8 alu8addc_val = (VAL); \ + alu8_cr += (unsigned8)(alu8addc_val); \ + alu8_vr += (signed8)(alu8addc_val); \ +} while (0) + +#define ALU16_ADDC(VAL) \ +do { \ + unsigned16 alu16addc_val = (VAL); \ + alu16_cr += (unsigned16)(alu16addc_val); \ + alu16_vr += (signed16)(alu16addc_val); \ +} while (0) + +#define ALU32_ADDC(VAL) \ +do { \ + unsigned32 alu32addc_val = (VAL); \ + unsigned32 alu32addc_sign = alu32addc_val ^ alu32_r; \ + alu32_r += (alu32addc_val); \ + alu32_c = (alu32_r < alu32addc_val); \ + alu32_v = ((alu32addc_sign ^ - (unsigned32)alu32_c) ^ alu32_r) >> 31; \ +} while (0) + +#define ALU64_ADDC(VAL) \ +do { \ + unsigned64 alu64addc_val = (unsigned64) (VAL); \ + unsigned64 alu64addc_sign = alu64addc_val ^ alu64_r; \ + alu64_r += (alu64addc_val); \ + alu64_c = (alu64_r < alu64addc_val); \ + alu64_v = ((alu64addc_sign ^ - (unsigned64)alu64_c) ^ alu64_r) >> 63; \ +} while (0) + +#define ALU_ADDC XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_ADDC) + + + +/* Compound operation - add carrying (and overflowing) with carry-in */ + +#define ALU8_ADDC_C(VAL,C) \ +do { \ + unsigned8 alu8addcc_val = (VAL); \ + unsigned8 alu8addcc_c = (C); \ + alu8_cr += (unsigned)(unsigned8)alu8addcc_val + alu8addcc_c; \ + alu8_vr += (signed)(signed8)(alu8addcc_val) + alu8addcc_c; \ +} while (0) + +#define ALU16_ADDC_C(VAL,C) \ +do { \ + unsigned16 alu16addcc_val = (VAL); \ + unsigned16 alu16addcc_c = (C); \ + alu16_cr += (unsigned)(unsigned16)alu16addcc_val + alu16addcc_c; \ + alu16_vr += (signed)(signed16)(alu16addcc_val) + alu16addcc_c; \ +} while (0) + +#define ALU32_ADDC_C(VAL,C) \ +do { \ + unsigned32 alu32addcc_val = (VAL); \ + unsigned32 alu32addcc_c = (C); \ + unsigned32 alu32addcc_sign = (alu32addcc_val ^ alu32_r); \ + alu32_r += (alu32addcc_val + alu32addcc_c); \ + alu32_c = ((alu32_r < alu32addcc_val) \ + || (alu32addcc_c && alu32_r == alu32addcc_val)); \ + alu32_v = ((alu32addcc_sign ^ - (unsigned32)alu32_c) ^ alu32_r) >> 31;\ +} while (0) + +#define ALU64_ADDC_C(VAL,C) \ +do { \ + unsigned64 alu64addcc_val = (VAL); \ + unsigned64 alu64addcc_c = (C); \ + unsigned64 alu64addcc_sign = (alu64addcc_val ^ alu64_r); \ + alu64_r += (alu64addcc_val + alu64addcc_c); \ + alu64_c = ((alu64_r < alu64addcc_val) \ + || (alu64addcc_c && alu64_r == alu64addcc_val)); \ + alu64_v = ((alu64addcc_sign ^ - (unsigned64)alu64_c) ^ alu64_r) >> 63;\ +} while (0) + +#define ALU_ADDC_C XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_ADDC_C) + + + +/* Basic operation - subtract (overflowing) */ + +#define ALU8_SUB(VAL) \ +do { \ + unsigned8 alu8sub_val = (VAL); \ + ALU8_ADDC_C (~alu8sub_val, 1); \ +} while (0) + +#define ALU16_SUB(VAL) \ +do { \ + unsigned16 alu16sub_val = (VAL); \ + ALU16_ADDC_C (~alu16sub_val, 1); \ +} while (0) + +#define ALU32_SUB(VAL) \ +do { \ + unsigned32 alu32sub_val = (VAL); \ + ALU32_ADDC_C (~alu32sub_val, 1); \ +} while (0) + +#define ALU64_SUB(VAL) \ +do { \ + unsigned64 alu64sub_val = (VAL); \ + ALU64_ADDC_C (~alu64sub_val, 1); \ +} while (0) + +#define ALU_SUB XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_SUB) + + + +/* Basic operation - subtract carrying (and overflowing) */ + +#define ALU8_SUBC(VAL) \ +do { \ + unsigned8 alu8subc_val = (VAL); \ + ALU8_ADDC_C (~alu8subc_val, 1); \ +} while (0) + +#define ALU16_SUBC(VAL) \ +do { \ + unsigned16 alu16subc_val = (VAL); \ + ALU16_ADDC_C (~alu16subc_val, 1); \ +} while (0) + +#define ALU32_SUBC(VAL) \ +do { \ + unsigned32 alu32subc_val = (VAL); \ + ALU32_ADDC_C (~alu32subc_val, 1); \ +} while (0) + +#define ALU64_SUBC(VAL) \ +do { \ + unsigned64 alu64subc_val = (VAL); \ + ALU64_ADDC_C (~alu64subc_val, 1); \ +} while (0) + +#define ALU_SUBC XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_SUBC) + + + +/* Compound operation - subtract carrying (and overflowing), extended */ + +#define ALU8_SUBC_X(VAL,C) \ +do { \ + unsigned8 alu8subcx_val = (VAL); \ + unsigned8 alu8subcx_c = (C); \ + ALU8_ADDC_C (~alu8subcx_val, alu8subcx_c); \ +} while (0) + +#define ALU16_SUBC_X(VAL,C) \ +do { \ + unsigned16 alu16subcx_val = (VAL); \ + unsigned16 alu16subcx_c = (C); \ + ALU16_ADDC_C (~alu16subcx_val, alu16subcx_c); \ +} while (0) + +#define ALU32_SUBC_X(VAL,C) \ +do { \ + unsigned32 alu32subcx_val = (VAL); \ + unsigned32 alu32subcx_c = (C); \ + ALU32_ADDC_C (~alu32subcx_val, alu32subcx_c); \ +} while (0) + +#define ALU64_SUBC_X(VAL,C) \ +do { \ + unsigned64 alu64subcx_val = (VAL); \ + unsigned64 alu64subcx_c = (C); \ + ALU64_ADDC_C (~alu64subcx_val, alu64subcx_c); \ +} while (0) + +#define ALU_SUBC_X XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_SUBC_X) + + + +/* Basic operation - subtract borrowing (and overflowing) */ + +#define ALU8_SUBB(VAL) \ +do { \ + unsigned8 alu8subb_val = (VAL); \ + alu8_cr -= (unsigned)(unsigned8)alu8subb_val; \ + alu8_vr -= (signed)(signed8)alu8subb_val; \ +} while (0) + +#define ALU16_SUBB(VAL) \ +do { \ + unsigned16 alu16subb_val = (VAL); \ + alu16_cr -= (unsigned)(unsigned16)alu16subb_val; \ + alu16_vr -= (signed)(signed16)alu16subb_val; \ +} while (0) + +#define ALU32_SUBB(VAL) \ +do { \ + unsigned32 alu32subb_val = (VAL); \ + unsigned32 alu32subb_sign = alu32subb_val ^ alu32_r; \ + alu32_c = (alu32_r < alu32subb_val); \ + alu32_r -= (alu32subb_val); \ + alu32_v = ((alu32subb_sign ^ - (unsigned32)alu32_c) ^ alu32_r) >> 31; \ +} while (0) + +#define ALU64_SUBB(VAL) \ +do { \ + unsigned64 alu64subb_val = (VAL); \ + unsigned64 alu64subb_sign = alu64subb_val ^ alu64_r; \ + alu64_c = (alu64_r < alu64subb_val); \ + alu64_r -= (alu64subb_val); \ + alu64_v = ((alu64subb_sign ^ - (unsigned64)alu64_c) ^ alu64_r) >> 31; \ +} while (0) + +#define ALU_SUBB XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_SUBB) + + + +/* Compound operation - subtract borrowing (and overflowing) with borrow-in */ + +#define ALU8_SUBB_B(VAL,B) \ +do { \ + unsigned8 alu8subbb_val = (VAL); \ + unsigned8 alu8subbb_b = (B); \ + alu8_cr -= (unsigned)(unsigned8)alu8subbb_val; \ + alu8_cr -= (unsigned)(unsigned8)alu8subbb_b; \ + alu8_vr -= (signed)(signed8)alu8subbb_val + alu8subbb_b; \ +} while (0) + +#define ALU16_SUBB_B(VAL,B) \ +do { \ + unsigned16 alu16subbb_val = (VAL); \ + unsigned16 alu16subbb_b = (B); \ + alu16_cr -= (unsigned)(unsigned16)alu16subbb_val; \ + alu16_cr -= (unsigned)(unsigned16)alu16subbb_b; \ + alu16_vr -= (signed)(signed16)alu16subbb_val + alu16subbb_b; \ +} while (0) + +#define ALU32_SUBB_B(VAL,B) \ +do { \ + unsigned32 alu32subbb_val = (VAL); \ + unsigned32 alu32subbb_b = (B); \ + ALU32_ADDC_C (~alu32subbb_val, !alu32subbb_b); \ + alu32_c = !alu32_c; \ +} while (0) + +#define ALU64_SUBB_B(VAL,B) \ +do { \ + unsigned64 alu64subbb_val = (VAL); \ + unsigned64 alu64subbb_b = (B); \ + ALU64_ADDC_C (~alu64subbb_val, !alu64subbb_b); \ + alu64_c = !alu64_c; \ +} while (0) + +#define ALU_SUBB_B XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_SUBB_B) + + + +/* Basic operation - negate (overflowing) */ + +#define ALU8_NEG() \ +do { \ + signed alu8neg_val = (ALU8_RESULT); \ + ALU8_SET (1); \ + ALU8_ADDC (~alu8neg_val); \ +} while (0) + +#define ALU16_NEG() \ +do { \ + signed alu16neg_val = (ALU16_RESULT); \ + ALU16_SET (1); \ + ALU16_ADDC (~alu16neg_val); \ +} while (0) + +#define ALU32_NEG() \ +do { \ + unsigned32 alu32neg_val = (ALU32_RESULT); \ + ALU32_SET (1); \ + ALU32_ADDC (~alu32neg_val); \ +} while(0) + +#define ALU64_NEG() \ +do { \ + unsigned64 alu64neg_val = (ALU64_RESULT); \ + ALU64_SET (1); \ + ALU64_ADDC (~alu64neg_val); \ +} while (0) + +#define ALU_NEG XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_NEG) + + + + +/* Basic operation - negate carrying (and overflowing) */ + +#define ALU8_NEGC() \ +do { \ + signed alu8negc_val = (ALU8_RESULT); \ + ALU8_SET (1); \ + ALU8_ADDC (~alu8negc_val); \ +} while (0) + +#define ALU16_NEGC() \ +do { \ + signed alu16negc_val = (ALU16_RESULT); \ + ALU16_SET (1); \ + ALU16_ADDC (~alu16negc_val); \ +} while (0) + +#define ALU32_NEGC() \ +do { \ + unsigned32 alu32negc_val = (ALU32_RESULT); \ + ALU32_SET (1); \ + ALU32_ADDC (~alu32negc_val); \ +} while(0) + +#define ALU64_NEGC() \ +do { \ + unsigned64 alu64negc_val = (ALU64_RESULT); \ + ALU64_SET (1); \ + ALU64_ADDC (~alu64negc_val); \ +} while (0) + +#define ALU_NEGC XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_NEGC) + + + + +/* Basic operation - negate borrowing (and overflowing) */ + +#define ALU8_NEGB() \ +do { \ + signed alu8negb_val = (ALU8_RESULT); \ + ALU8_SET (0); \ + ALU8_SUBB (alu8negb_val); \ +} while (0) + +#define ALU16_NEGB() \ +do { \ + signed alu16negb_val = (ALU16_RESULT); \ + ALU16_SET (0); \ + ALU16_SUBB (alu16negb_val); \ +} while (0) + +#define ALU32_NEGB() \ +do { \ + unsigned32 alu32negb_val = (ALU32_RESULT); \ + ALU32_SET (0); \ + ALU32_SUBB (alu32negb_val); \ +} while(0) + +#define ALU64_NEGB() \ +do { \ + unsigned64 alu64negb_val = (ALU64_RESULT); \ + ALU64_SET (0); \ + ALU64_SUBB (alu64negb_val); \ +} while (0) + +#define ALU_NEGB XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_NEGB) + + + + +/* Other */ + +#define ALU8_OR(VAL) \ +do { \ + error("ALU16_OR"); \ +} while (0) + +#define ALU16_OR(VAL) \ +do { \ + error("ALU16_OR"); \ +} while (0) + +#define ALU32_OR(VAL) \ +do { \ + alu32_r |= (VAL); \ + alu32_c = 0; \ + alu32_v = 0; \ +} while (0) + +#define ALU64_OR(VAL) \ +do { \ + alu64_r |= (VAL); \ + alu64_c = 0; \ + alu64_v = 0; \ +} while (0) + +#define ALU_OR(VAL) XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_OR)(VAL) + + + +#define ALU16_XOR(VAL) \ +do { \ + error("ALU16_XOR"); \ +} while (0) + +#define ALU32_XOR(VAL) \ +do { \ + alu32_r ^= (VAL); \ + alu32_c = 0; \ + alu32_v = 0; \ +} while (0) + +#define ALU64_XOR(VAL) \ +do { \ + alu64_r ^= (VAL); \ + alu64_c = 0; \ + alu64_v = 0; \ +} while (0) + +#define ALU_XOR(VAL) XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_XOR)(VAL) + + + + +#define ALU16_AND(VAL) \ +do { \ + error("ALU_AND16"); \ +} while (0) + +#define ALU32_AND(VAL) \ +do { \ + alu32_r &= (VAL); \ + alu32_r = 0; \ + alu32_v = 0; \ +} while (0) + +#define ALU64_AND(VAL) \ +do { \ + alu64_r &= (VAL); \ + alu64_r = 0; \ + alu64_v = 0; \ +} while (0) + +#define ALU_AND(VAL) XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_AND)(VAL) + + + + +#define ALU16_NOT(VAL) \ +do { \ + error("ALU_NOT16"); \ +} while (0) + +#define ALU32_NOT \ +do { \ + alu32_r = ~alu32_r; \ + alu32_c = 0; \ + alu32_v = 0; \ +} while (0) + +#define ALU64_NOT \ +do { \ + alu64_r = ~alu64_r; \ + alu64_c = 0; \ + alu64_v = 0; \ +} while (0) + +#define ALU_NOT XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_NOT) + +#endif diff --git a/sim/common/sim-arange.c b/sim/common/sim-arange.c new file mode 100644 index 00000000000..d9955e687e5 --- /dev/null +++ b/sim/common/sim-arange.c @@ -0,0 +1,301 @@ +/* Address ranges. + Copyright (C) 1998 Free Software Foundation, Inc. + Contributed by Cygnus Solutions. + +This file is part of the GNU Simulators. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* Tell sim-arange.h it's us. */ +#define SIM_ARANGE_C + +#include "libiberty.h" +#include "sim-basics.h" +#include "sim-assert.h" + +#ifdef HAVE_STDLIB_H +#include +#endif + +#define DEFINE_INLINE_P (! defined (SIM_ARANGE_C_INCLUDED)) +#define DEFINE_NON_INLINE_P defined (SIM_ARANGE_C_INCLUDED) + +#if DEFINE_NON_INLINE_P + +/* Insert a range. */ + +static void +insert_range (ADDR_SUBRANGE **pos, ADDR_SUBRANGE *asr) +{ + asr->next = *pos; + *pos = asr; +} + +/* Delete a range. */ + +static void +delete_range (ADDR_SUBRANGE **thisasrp) +{ + ADDR_SUBRANGE *thisasr; + + thisasr = *thisasrp; + *thisasrp = thisasr->next; + + free (thisasr); +} + +/* Add or delete an address range. + This code was borrowed from linux's locks.c:posix_lock_file(). + ??? Todo: Given our simpler needs this could be simplified + (split into two fns). */ + +static void +frob_range (ADDR_RANGE *ar, address_word start, address_word end, int delete_p) +{ + ADDR_SUBRANGE *asr; + ADDR_SUBRANGE *new_asr, *new_asr2; + ADDR_SUBRANGE *left = NULL; + ADDR_SUBRANGE *right = NULL; + ADDR_SUBRANGE **before; + ADDR_SUBRANGE init_caller; + ADDR_SUBRANGE *caller = &init_caller; + int added_p = 0; + + memset (caller, 0, sizeof (ADDR_SUBRANGE)); + new_asr = ZALLOC (ADDR_SUBRANGE); + new_asr2 = ZALLOC (ADDR_SUBRANGE); + + caller->start = start; + caller->end = end; + before = &ar->ranges; + + while ((asr = *before) != NULL) + { + if (! delete_p) + { + /* Try next range if current range preceeds new one and not + adjacent or overlapping. */ + if (asr->end < caller->start - 1) + goto next_range; + + /* Break out if new range preceeds current one and not + adjacent or overlapping. */ + if (asr->start > caller->end + 1) + break; + + /* If we come here, the new and current ranges are adjacent or + overlapping. Make one range yielding from the lower start address + of both ranges to the higher end address. */ + if (asr->start > caller->start) + asr->start = caller->start; + else + caller->start = asr->start; + if (asr->end < caller->end) + asr->end = caller->end; + else + caller->end = asr->end; + + if (added_p) + { + delete_range (before); + continue; + } + caller = asr; + added_p = 1; + } + else /* deleting a range */ + { + /* Try next range if current range preceeds new one. */ + if (asr->end < caller->start) + goto next_range; + + /* Break out if new range preceeds current one. */ + if (asr->start > caller->end) + break; + + added_p = 1; + + if (asr->start < caller->start) + left = asr; + + /* If the next range in the list has a higher end + address than the new one, insert the new one here. */ + if (asr->end > caller->end) + { + right = asr; + break; + } + if (asr->start >= caller->start) + { + /* The new range completely replaces an old + one (This may happen several times). */ + if (added_p) + { + delete_range (before); + continue; + } + + /* Replace the old range with the new one. */ + asr->start = caller->start; + asr->end = caller->end; + caller = asr; + added_p = 1; + } + } + + /* Go on to next range. */ + next_range: + before = &asr->next; + } + + if (!added_p) + { + if (delete_p) + goto out; + new_asr->start = caller->start; + new_asr->end = caller->end; + insert_range (before, new_asr); + new_asr = NULL; + } + if (right) + { + if (left == right) + { + /* The new range breaks the old one in two pieces, + so we have to use the second new range. */ + new_asr2->start = right->start; + new_asr2->end = right->end; + left = new_asr2; + insert_range (before, left); + new_asr2 = NULL; + } + right->start = caller->end + 1; + } + if (left) + { + left->end = caller->start - 1; + } + + out: + if (new_asr) + free(new_asr); + if (new_asr2) + free(new_asr2); +} + +/* Free T and all subtrees. */ + +static void +free_search_tree (ADDR_RANGE_TREE *t) +{ + if (t != NULL) + { + free_search_tree (t->lower); + free_search_tree (t->higher); + free (t); + } +} + +/* Subroutine of build_search_tree to recursively build a balanced tree. + ??? It's not an optimum tree though. */ + +static ADDR_RANGE_TREE * +build_tree_1 (ADDR_SUBRANGE **asrtab, unsigned int n) +{ + unsigned int mid = n / 2; + ADDR_RANGE_TREE *t; + + if (n == 0) + return NULL; + t = (ADDR_RANGE_TREE *) xmalloc (sizeof (ADDR_RANGE_TREE)); + t->start = asrtab[mid]->start; + t->end = asrtab[mid]->end; + if (mid != 0) + t->lower = build_tree_1 (asrtab, mid); + else + t->lower = NULL; + if (n > mid + 1) + t->higher = build_tree_1 (asrtab + mid + 1, n - mid - 1); + else + t->higher = NULL; + return t; +} + +/* Build a search tree for address range AR. */ + +static void +build_search_tree (ADDR_RANGE *ar) +{ + /* ??? Simple version for now. */ + ADDR_SUBRANGE *asr,**asrtab; + unsigned int i, n; + + for (n = 0, asr = ar->ranges; asr != NULL; ++n, asr = asr->next) + continue; + asrtab = (ADDR_SUBRANGE **) xmalloc (n * sizeof (ADDR_SUBRANGE *)); + for (i = 0, asr = ar->ranges; i < n; ++i, asr = asr->next) + asrtab[i] = asr; + ar->range_tree = build_tree_1 (asrtab, n); + free (asrtab); +} + +void +sim_addr_range_add (ADDR_RANGE *ar, address_word start, address_word end) +{ + frob_range (ar, start, end, 0); + + /* Rebuild the search tree. */ + /* ??? Instead of rebuilding it here it could be done in a module resume + handler, say by first checking for a `changed' flag, assuming of course + this would never be done while the simulation is running. */ + free_search_tree (ar->range_tree); + build_search_tree (ar); +} + +void +sim_addr_range_delete (ADDR_RANGE *ar, address_word start, address_word end) +{ + frob_range (ar, start, end, 1); + + /* Rebuild the search tree. */ + /* ??? Instead of rebuilding it here it could be done in a module resume + handler, say by first checking for a `changed' flag, assuming of course + this would never be done while the simulation is running. */ + free_search_tree (ar->range_tree); + build_search_tree (ar); +} + +#endif /* DEFINE_NON_INLINE_P */ + +#if DEFINE_INLINE_P + +SIM_ARANGE_INLINE int +sim_addr_range_hit_p (ADDR_RANGE *ar, address_word addr) +{ + ADDR_RANGE_TREE *t = ar->range_tree; + + while (t != NULL) + { + if (addr < t->start) + t = t->lower; + else if (addr > t->end) + t = t->higher; + else + return 1; + } + return 0; +} + +#endif /* DEFINE_INLINE_P */ diff --git a/sim/common/sim-arange.h b/sim/common/sim-arange.h new file mode 100644 index 00000000000..10ba0f4e7bd --- /dev/null +++ b/sim/common/sim-arange.h @@ -0,0 +1,83 @@ +/* Address ranges. + Copyright (C) 1998 Free Software Foundation, Inc. + Contributed by Cygnus Solutions. + +This file is part of the GNU Simulators. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* This file is meant to be included by sim-basics.h. */ + +#ifndef SIM_ARANGE_H +#define SIM_ARANGE_H + +/* A list of address ranges. */ + +typedef struct _addr_subrange { + struct _addr_subrange *next; + + /* Range of addresses to be traced is [start,end]. */ + address_word start,end; +} ADDR_SUBRANGE; + +/* For speed, searching is done on a tree. */ + +typedef struct _addr_range_tree { + struct _addr_range_tree *lower; + struct _addr_range_tree *higher; + + /* Range of addresses to be traced is [start,end]. */ + address_word start,end; +} ADDR_RANGE_TREE; + +/* The top level struct. */ + +typedef struct _addr_range { + ADDR_SUBRANGE *ranges; +#define ADDR_RANGE_RANGES(ar) ((ar)->ranges) + ADDR_RANGE_TREE *range_tree; +#define ADDR_RANGE_TREE(ar) ((ar)->range_tree) +} ADDR_RANGE; + +/* Add address range START,END to AR. */ +extern void sim_addr_range_add (ADDR_RANGE * /*ar*/, + address_word /*start*/, + address_word /*end*/); + +/* Delete address range START,END from AR. */ +extern void sim_addr_range_delete (ADDR_RANGE * /*ar*/, + address_word /*start*/, + address_word /*end*/); + +/* Return non-zero if ADDR is in range AR, traversing the entire tree. + If no range is specified, that is defined to mean "everything". */ +extern INLINE int +sim_addr_range_hit_p (ADDR_RANGE * /*ar*/, address_word /*addr*/); +#define ADDR_RANGE_HIT_P(ar, addr) \ + ((ar)->range_tree == NULL || sim_addr_range_hit_p ((ar), (addr))) + +#ifdef HAVE_INLINE +#ifdef SIM_ARANGE_C +#define SIM_ARANGE_INLINE INLINE +#else +#define SIM_ARANGE_INLINE EXTERN_INLINE +#endif +#include "sim-arange.c" +#else +#define SIM_ARANGE_INLINE +#endif +#define SIM_ARANGE_C_INCLUDED + +#endif /* SIM_ARANGE_H */ diff --git a/sim/common/sim-assert.h b/sim/common/sim-assert.h new file mode 100644 index 00000000000..0274084c008 --- /dev/null +++ b/sim/common/sim-assert.h @@ -0,0 +1,90 @@ +/* This file is part of the program GDB. + + Copyright (C) 1997, Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + + +#ifndef _SIM_ASSERT_H_ +#define _SIM_ASSERT_H_ + +#define SIM_FILTER_PATH(FILE, PATH) \ +do \ + { \ + /* strip leading path */ \ + const char *p = (PATH); \ + (FILE) = p; \ + while (*p != '\0' && *p != ':') \ + { \ + if (*p == '/') \ + (FILE) = p + 1; \ + p++; \ + } \ + } \ +while (0) + +/* The subtle difference between SIM_ASSERT and ASSERT is that + SIM_ASSERT passes `sd' to sim_io_error for the SIM_DESC, + ASSERT passes NULL. */ + +#if !defined (SIM_ASSERT) +#if defined (WITH_ASSERT) +#define SIM_ASSERT(EXPRESSION) \ +do \ + { \ + if (WITH_ASSERT) \ + { \ + if (!(EXPRESSION)) \ + { \ + /* report the failure */ \ + const char *file; \ + SIM_FILTER_PATH(file, __FILE__); \ + sim_io_error (sd, "%s:%d: assertion failed - %s", \ + file, __LINE__, #EXPRESSION); \ + } \ + } \ + } \ +while (0) +#else +#define SIM_ASSERT(EXPRESSION) do { /*nothing*/; } while (0) +#endif +#endif + +#if !defined (ASSERT) +#if defined (WITH_ASSERT) +#define ASSERT(EXPRESSION) \ +do \ + { \ + if (WITH_ASSERT) \ + { \ + if (!(EXPRESSION)) \ + { \ + /* report the failure */ \ + const char *file; \ + SIM_FILTER_PATH(file, __FILE__); \ + sim_io_error (NULL, "%s:%d: assertion failed - %s", \ + file, __LINE__, #EXPRESSION); \ + } \ + } \ + } \ +while (0) +#else +#define ASSERT(EXPRESSION) do { /*nothing*/; } while (0) +#endif +#endif + +#endif diff --git a/sim/common/sim-base.h b/sim/common/sim-base.h new file mode 100644 index 00000000000..3fe01b4a98d --- /dev/null +++ b/sim/common/sim-base.h @@ -0,0 +1,252 @@ +/* Simulator pseudo baseclass. + Copyright (C) 1997-1998 Free Software Foundation, Inc. + Contributed by Cygnus Support. + +This file is part of GDB, the GNU debugger. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + + +/* Simulator state pseudo baseclass. + + Each simulator is required to have the file ``sim-main.h''. That + file includes ``sim-basics.h'', defines the base type ``sim_cia'' + (the data type that contains complete current instruction address + information), include ``sim-base.h'': + + #include "sim-basics.h" + typedef address_word sim_cia; + /-* If `sim_cia' is not an integral value (e.g. a struct), define + CIA_ADDR to return the integral value. *-/ + /-* #define CIA_ADDR(cia) (...) *-/ + #include "sim-base.h" + + finally, two data types `struct _sim_cpu' and `struct sim_state' + are defined: + + struct _sim_cpu { + ... simulator specific members ... + sim_cpu_base base; + }; + + struct sim_state { + sim_cpu cpu[MAX_NR_PROCESSORS]; + #if (WITH_SMP) + #define STATE_CPU(sd,n) (&(sd)->cpu[n]) + #else + #define STATE_CPU(sd,n) (&(sd)->cpu[0]) + #endif + ... simulator specific members ... + sim_state_base base; + }; + + Note that `base' appears last. This makes `base.magic' appear last + in the entire struct and helps catch miscompilation errors. */ + + +#ifndef SIM_BASE_H +#define SIM_BASE_H + +/* Pre-declare certain types. */ + +/* typedef sim_cia; */ +#ifndef NULL_CIA +#define NULL_CIA ((sim_cia) 0) +#endif +/* Return the current instruction address as a number. + Some targets treat the current instruction address as a struct + (e.g. for delay slot handling). */ +#ifndef CIA_ADDR +#define CIA_ADDR(cia) (cia) +#endif +#ifndef INVALID_INSTRUCTION_ADDRESS +#define INVALID_INSTRUCTION_ADDRESS ((address_word)0 - 1) +#endif + +typedef struct _sim_cpu sim_cpu; + +#include "sim-module.h" + +#include "sim-trace.h" +#include "sim-core.h" +#include "sim-events.h" +#include "sim-profile.h" +#ifdef SIM_HAVE_MODEL +#include "sim-model.h" +#endif +#include "sim-io.h" +#include "sim-engine.h" +#include "sim-watch.h" +#include "sim-memopt.h" +#ifdef SIM_HAVE_BREAKPOINTS +#include "sim-break.h" +#endif +#include "sim-cpu.h" + +/* Global pointer to current state while sim_resume is running. + On a machine with lots of registers, it might be possible to reserve + one of them for current_state. However on a machine with few registers + current_state can't permanently live in one and indirecting through it + will be slower [in which case one can have sim_resume set globals from + current_state for faster access]. + If CURRENT_STATE_REG is defined, it means current_state is living in + a global register. */ + + +#ifdef CURRENT_STATE_REG +/* FIXME: wip */ +#else +extern struct sim_state *current_state; +#endif + + +/* The simulator may provide different (and faster) definition. */ +#ifndef CURRENT_STATE +#define CURRENT_STATE current_state +#endif + + +typedef struct { + + /* Simulator's argv[0]. */ + const char *my_name; +#define STATE_MY_NAME(sd) ((sd)->base.my_name) + + /* Who opened the simulator. */ + SIM_OPEN_KIND open_kind; +#define STATE_OPEN_KIND(sd) ((sd)->base.open_kind) + + /* The host callbacks. */ + struct host_callback_struct *callback; +#define STATE_CALLBACK(sd) ((sd)->base.callback) + + /* The type of simulation environment (user/operating). */ + enum sim_environment environment; +#define STATE_ENVIRONMENT(sd) ((sd)->base.environment) + +#if 0 /* FIXME: Not ready yet. */ + /* Stuff defined in sim-config.h. */ + struct sim_config config; +#define STATE_CONFIG(sd) ((sd)->base.config) +#endif + + /* List of installed module `init' handlers. */ + struct module_list *modules; +#define STATE_MODULES(sd) ((sd)->base.modules) + + /* Supported options. */ + struct option_list *options; +#define STATE_OPTIONS(sd) ((sd)->base.options) + + /* Non-zero if -v specified. */ + int verbose_p; +#define STATE_VERBOSE_P(sd) ((sd)->base.verbose_p) + + /* Non cpu-specific trace data. See sim-trace.h. */ + TRACE_DATA trace_data; +#define STATE_TRACE_DATA(sd) (& (sd)->base.trace_data) + + /* If non NULL, the BFD architecture specified on the command line */ + const struct bfd_arch_info *architecture; +#define STATE_ARCHITECTURE(sd) ((sd)->base.architecture) + + /* If non NULL, the bfd target specified on the command line */ + const char *target; +#define STATE_TARGET(sd) ((sd)->base.target) + + /* In standalone simulator, this is the program's arguments passed + on the command line. */ + char **prog_argv; +#define STATE_PROG_ARGV(sd) ((sd)->base.prog_argv) + + /* The program's bfd. */ + struct _bfd *prog_bfd; +#define STATE_PROG_BFD(sd) ((sd)->base.prog_bfd) + + /* Symbol table for prog_bfd */ + struct symbol_cache_entry **prog_syms; +#define STATE_PROG_SYMS(sd) ((sd)->base.prog_syms) + + /* The program's text section. */ + struct sec *text_section; + /* Starting and ending text section addresses from the bfd. */ + SIM_ADDR text_start, text_end; +#define STATE_TEXT_SECTION(sd) ((sd)->base.text_section) +#define STATE_TEXT_START(sd) ((sd)->base.text_start) +#define STATE_TEXT_END(sd) ((sd)->base.text_end) + + /* Start address, set when the program is loaded from the bfd. */ + SIM_ADDR start_addr; +#define STATE_START_ADDR(sd) ((sd)->base.start_addr) + + /* Size of the simulator's cache, if any. + This is not the target's cache. It is the cache the simulator uses + to process instructions. */ + unsigned int scache_size; +#define STATE_SCACHE_SIZE(sd) ((sd)->base.scache_size) + + /* FIXME: Move to top level sim_state struct (as some struct)? */ +#ifdef SIM_HAVE_FLATMEM + unsigned int mem_size; +#define STATE_MEM_SIZE(sd) ((sd)->base.mem_size) + unsigned int mem_base; +#define STATE_MEM_BASE(sd) ((sd)->base.mem_base) + unsigned char *memory; +#define STATE_MEMORY(sd) ((sd)->base.memory) +#endif + + /* core memory bus */ +#define STATE_CORE(sd) (&(sd)->base.core) + sim_core core; + + /* Record of memory sections added via the memory-options interface. */ +#define STATE_MEMOPT(sd) ((sd)->base.memopt) + sim_memopt *memopt; + + /* event handler */ +#define STATE_EVENTS(sd) (&(sd)->base.events) + sim_events events; + + /* generic halt/resume engine */ + sim_engine engine; +#define STATE_ENGINE(sd) (&(sd)->base.engine) + + /* generic watchpoint support */ + sim_watchpoints watchpoints; +#define STATE_WATCHPOINTS(sd) (&(sd)->base.watchpoints) + + /* Pointer to list of breakpoints */ + struct sim_breakpoint *breakpoints; +#define STATE_BREAKPOINTS(sd) ((sd)->base.breakpoints) + +#if WITH_HW + struct sim_hw *hw; +#define STATE_HW(sd) ((sd)->base.hw) +#endif + + + /* Marker for those wanting to do sanity checks. + This should remain the last member of this struct to help catch + miscompilation errors. */ + int magic; +#define SIM_MAGIC_NUMBER 0x4242 +#define STATE_MAGIC(sd) ((sd)->base.magic) +} sim_state_base; + +/* Functions for allocating/freeing a sim_state. */ +SIM_DESC sim_state_alloc PARAMS ((SIM_OPEN_KIND kind, host_callback *callback)); +void sim_state_free PARAMS ((SIM_DESC)); + +#endif /* SIM_BASE_H */ diff --git a/sim/common/sim-basics.h b/sim/common/sim-basics.h new file mode 100644 index 00000000000..fc34b21618f --- /dev/null +++ b/sim/common/sim-basics.h @@ -0,0 +1,154 @@ +/* This file is part of the program psim. + + Copyright (C) 1994-1997, Andrew Cagney + Copyright (C) 1997, 1998, Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + + +#ifndef _SIM_BASICS_H_ +#define _SIM_BASICS_H_ + + +/* Basic configuration */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +/* Basic host dependant mess - hopefully + will + bring potential conflicts out in the open */ + +#include +#include +#include + +#ifdef __CYGWIN32__ +extern int vasprintf (char **result, const char *format, va_list args); +extern int asprintf (char **result, const char *format, ...); +#endif + + +#ifndef NULL +#define NULL 0 +#endif + + + +/* Some versions of GCC include an attribute operator, define it */ + +#if !defined (__attribute__) +#if (!defined(__GNUC__) || (__GNUC__ < 2) || (__GNUC__ == 2 && __GNUC_MINOR__ < 6)) +#define __attribute__(arg) +#endif +#endif + + +/* Global types that code manipulates */ + +typedef struct _device device; +struct hw; +struct _sim_fpu; + + +/* Generic address space (maps) and access attributes */ + +enum { + read_map = 0, + write_map = 1, + exec_map = 2, + io_map = 3, + nr_maps = 32, /* something small */ +}; + +enum { + access_invalid = 0, + access_read = 1 << read_map, + access_write = 1 << write_map, + access_exec = 1 << exec_map, + access_io = 1 << io_map, +}; + +enum { + access_read_write = (access_read | access_write), + access_read_exec = (access_read | access_exec), + access_write_exec = (access_write | access_exec), + access_read_write_exec = (access_read | access_write | access_exec), + access_read_io = (access_read | access_io), + access_write_io = (access_write | access_io), + access_read_write_io = (access_read | access_write | access_io), + access_exec_io = (access_exec | access_io), + access_read_exec_io = (access_read | access_exec | access_io), + access_write_exec_io = (access_write | access_exec | access_io), + access_read_write_exec_io = (access_read | access_write | access_exec | access_io), +}; + + +/* disposition of an object when things are reset */ + +typedef enum { + permenant_object, + temporary_object, +} object_disposition; + + +/* Memory transfer types */ + +typedef enum _transfer_type { + read_transfer, + write_transfer, +} transfer_type; + + +/* directions */ + +typedef enum { + bidirect_port, + input_port, + output_port, +} port_direction; + + + +/* Basic definitions - ordered so that nothing calls what comes after it. */ + +/* FIXME: conditionalizing tconfig.h on HAVE_CONFIG_H seems wrong. */ +#ifdef HAVE_CONFIG_H +#include "tconfig.h" +#endif + +#include "ansidecl.h" +#include "callback.h" +#include "remote-sim.h" + +#include "sim-config.h" + +#include "sim-inline.h" + +#include "sim-types.h" +#include "sim-bits.h" +#include "sim-endian.h" +#include "sim-signal.h" +#include "sim-arange.h" + +#include "sim-utils.h" + +/* Note: Only the simpler interfaces are defined here. More heavy + weight objects, such as core and events, are defined in the more + serious sim-base.h header. */ + +#endif /* _SIM_BASICS_H_ */ diff --git a/sim/common/sim-bits.c b/sim/common/sim-bits.c new file mode 100644 index 00000000000..ecfb73bf6b4 --- /dev/null +++ b/sim/common/sim-bits.c @@ -0,0 +1,208 @@ +/* This file is part of the program psim. + + Copyright (C) 1994-1997, Andrew Cagney + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + + +#ifndef _SIM_BITS_C_ +#define _SIM_BITS_C_ + +#include "sim-basics.h" +#include "sim-assert.h" +#include "sim-io.h" + + +INLINE_SIM_BITS\ +(unsigned_word) +LSMASKED (unsigned_word val, + int start, + int stop) +{ + /* NOTE - start, stop can wrap */ + val &= LSMASK (start, stop); + return val; +} + + +INLINE_SIM_BITS\ +(unsigned_word) +MSMASKED (unsigned_word val, + int start, + int stop) +{ + /* NOTE - start, stop can wrap */ + val &= MSMASK (start, stop); + return val; +} + + +INLINE_SIM_BITS\ +(unsigned_word) +LSEXTRACTED (unsigned_word val, + int start, + int stop) +{ + ASSERT (start >= stop); +#if (WITH_TARGET_WORD_BITSIZE == 64) + return LSEXTRACTED64 (val, start, stop); +#endif +#if (WITH_TARGET_WORD_BITSIZE == 32) + if (stop >= 32) + return 0; + else + { + if (start < 32) + val &= LSMASK (start, 0); + val >>= stop; + return val; + } +#endif +} + + +INLINE_SIM_BITS\ +(unsigned_word) +MSEXTRACTED (unsigned_word val, + int start, + int stop) +{ + ASSERT (start <= stop); +#if (WITH_TARGET_WORD_BITSIZE == 64) + return MSEXTRACTED64 (val, start, stop); +#endif +#if (WITH_TARGET_WORD_BITSIZE == 32) + if (stop < 32) + return 0; + else + { + if (start >= 32) + val &= MSMASK (start, 64 - 1); + val >>= (64 - stop - 1); + return val; + } +#endif +} + + +INLINE_SIM_BITS\ +(unsigned_word) +LSINSERTED (unsigned_word val, + int start, + int stop) +{ + ASSERT (start >= stop); +#if (WITH_TARGET_WORD_BITSIZE == 64) + return LSINSERTED64 (val, start, stop); +#endif +#if (WITH_TARGET_WORD_BITSIZE == 32) + /* Bit numbers are 63..0, even for 32 bit targets. + On 32 bit targets we ignore 63..32 */ + if (stop >= 32) + return 0; + else + { + val <<= stop; + val &= LSMASK (start, stop); + return val; + } +#endif +} + +INLINE_SIM_BITS\ +(unsigned_word) +MSINSERTED (unsigned_word val, + int start, + int stop) +{ + ASSERT (start <= stop); +#if (WITH_TARGET_WORD_BITSIZE == 64) + return MSINSERTED64 (val, start, stop); +#endif +#if (WITH_TARGET_WORD_BITSIZE == 32) + /* Bit numbers are 0..63, even for 32 bit targets. + On 32 bit targets we ignore 0..31. */ + if (stop < 32) + return 0; + else + { + val <<= ((64 - 1) - stop); + val &= MSMASK (start, stop); + return val; + } +#endif +} + + + +INLINE_SIM_BITS\ +(unsigned_word) +LSSEXT (signed_word val, + int sign_bit) +{ + ASSERT (sign_bit < 64); +#if (WITH_TARGET_WORD_BITSIZE == 64) + return LSSEXT64 (val, sign_bit); +#endif +#if (WITH_TARGET_WORD_BITSIZE == 32) + if (sign_bit >= 32) + return val; + else { + val = LSSEXT32 (val, sign_bit); + return val; + } +#endif +} + +INLINE_SIM_BITS\ +(unsigned_word) +MSSEXT (signed_word val, + int sign_bit) +{ + ASSERT (sign_bit < 64); +#if (WITH_TARGET_WORD_BITSIZE == 64) + return MSSEXT64 (val, sign_bit); +#endif +#if (WITH_TARGET_WORD_BITSIZE == 32) + if (sign_bit < 32) + return val; + else { + val = MSSEXT32 (val, sign_bit - 32); + return val; + } +#endif +} + + + +#define N 8 +#include "sim-n-bits.h" +#undef N + +#define N 16 +#include "sim-n-bits.h" +#undef N + +#define N 32 +#include "sim-n-bits.h" +#undef N + +#define N 64 +#include "sim-n-bits.h" +#undef N + +#endif /* _SIM_BITS_C_ */ diff --git a/sim/common/sim-bits.h b/sim/common/sim-bits.h new file mode 100644 index 00000000000..d111bcd4569 --- /dev/null +++ b/sim/common/sim-bits.h @@ -0,0 +1,564 @@ +/* This file is part of the program psim. + + Copyright (C) 1994-1996, Andrew Cagney + Copyright (C) 1997, Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + + +#ifndef _SIM_BITS_H_ +#define _SIM_BITS_H_ + + +/* Bit manipulation routines: + + Bit numbering: The bits are numbered according to the target ISA's + convention. That being controlled by WITH_TARGET_WORD_MSB. For + the PowerPC (WITH_TARGET_WORD_MSB == 0) the numbering is 0..31 + while for the MIPS (WITH_TARGET_WORD_MSB == 31) it is 31..0. + + Size convention: Each macro is in three forms - 32 which + operates in 32bit quantity (bits are numbered 0..31); 64 + which operates using 64bit quantites (and bits are numbered 0..63); + and which operates using the bit size of the target + architecture (bits are still numbered 0..63), with 32bit + architectures ignoring the first 32bits leaving bit 32 as the most + significant. + + NB: Use EXTRACTED, MSEXTRACTED and LSEXTRACTED as a guideline for + naming. LSMASK and LSMASKED are wrong. + + BIT*(POS): `*' bit constant with just 1 bit set. + + LSBIT*(OFFSET): `*' bit constant with just 1 bit set - LS bit is + zero. + + MSBIT*(OFFSET): `*' bit constant with just 1 bit set - MS bit is + zero. + + MASK*(FIRST, LAST): `*' bit constant with bits [FIRST .. LAST] + set. The (no size) version permits FIRST >= LAST and + generates a wrapped bit mask vis ([0..LAST] | [FIRST..LSB]). + + LSMASK*(FIRST, LAST): Like MASK - LS bit is zero. + + MSMASK*(FIRST, LAST): Like MASK - LS bit is zero. + + MASKED*(VALUE, FIRST, LAST): Masks out all but bits [FIRST + .. LAST]. + + LSMASKED*(VALUE, FIRST, LAST): Like MASKED - LS bit is zero. + + MSMASKED*(VALUE, FIRST, LAST): Like MASKED - MS bit is zero. + + EXTRACTED*(VALUE, FIRST, LAST): Masks out bits [FIRST .. LAST] but + also right shifts the masked value so that bit LAST becomes the + least significant (right most). + + LSEXTRACTED*(VALUE, FIRST, LAST): Same as extracted - LS bit is + zero. + + MSEXTRACTED*(VALUE, FIRST, LAST): Same as extracted - MS bit is + zero. + + SHUFFLED**(VALUE, OLD, NEW): Mask then move a single bit from OLD + new NEW. + + MOVED**(VALUE, OLD_FIRST, OLD_LAST, NEW_FIRST, NEW_LAST): Moves + things around so that bits OLD_FIRST..OLD_LAST are masked then + moved to NEW_FIRST..NEW_LAST. + + INSERTED*(VALUE, FIRST, LAST): Takes VALUE and `inserts' the (LAST + - FIRST + 1) least significant bits into bit positions [ FIRST + .. LAST ]. This is almost the complement to EXTRACTED. + + IEA_MASKED(SHOULD_MASK, ADDR): Convert the address to the targets + natural size. If in 32bit mode, discard the high 32bits. + + EXTEND*(VALUE): Convert the `*' bit value to the targets natural + word size. Sign extend the value if needed. + + ALIGN_*(VALUE): Round the value upwards so that it is aligned to a + `_*' byte boundary. + + FLOOR_*(VALUE): Truncate the value so that it is aligned to a `_*' + byte boundary. + + ROT*(VALUE, NR_BITS): Return the `*' bit VALUE rotated by NR_BITS + right (positive) or left (negative). + + ROTL*(VALUE, NR_BITS): Return the `*' bit value rotated by NR_BITS + left. 0 <= NR_BITS <= `*'. + + ROTR*(VALUE, NR_BITS): Return the `*' bit value rotated by NR_BITS + right. 0 <= NR_BITS <= N. + + SEXT*(VALUE, SIGN_BIT): Treat SIGN_BIT as VALUEs sign, extend it ti + `*' bits. + + Note: Only the BIT* and MASK* macros return a constant that can be + used in variable declarations. + + */ + + +/* compute the number of bits between START and STOP */ + +#if (WITH_TARGET_WORD_MSB == 0) +#define _MAKE_WIDTH(START, STOP) (STOP - START + 1) +#else +#define _MAKE_WIDTH(START, STOP) (START - STOP + 1) +#endif + + + +/* compute the number shifts required to move a bit between LSB (MSB) + and POS */ + +#if (WITH_TARGET_WORD_MSB == 0) +#define _LSB_SHIFT(WIDTH, POS) (WIDTH - 1 - POS) +#else +#define _LSB_SHIFT(WIDTH, POS) (POS) +#endif + +#if (WITH_TARGET_WORD_MSB == 0) +#define _MSB_SHIFT(WIDTH, POS) (POS) +#else +#define _MSB_SHIFT(WIDTH, POS) (WIDTH - 1 - POS) +#endif + + +/* compute the absolute bit position given the OFFSET from the MSB(LSB) + NB: _MAKE_xxx_POS (WIDTH, _MAKE_xxx_SHIFT (WIDTH, POS)) == POS */ + +#if (WITH_TARGET_WORD_MSB == 0) +#define _MSB_POS(WIDTH, SHIFT) (SHIFT) +#else +#define _MSB_POS(WIDTH, SHIFT) (WIDTH - 1 - SHIFT) +#endif + +#if (WITH_TARGET_WORD_MSB == 0) +#define _LSB_POS(WIDTH, SHIFT) (WIDTH - 1 - SHIFT) +#else +#define _LSB_POS(WIDTH, SHIFT) (SHIFT) +#endif + + +/* convert a 64 bit position into a corresponding 32bit position. MSB + pos handles the posibility that the bit lies beyond the 32bit + boundary */ + +#if (WITH_TARGET_WORD_MSB == 0) +#define _MSB_32(START, STOP) (START <= STOP \ + ? (START < 32 ? 0 : START - 32) \ + : (STOP < 32 ? 0 : STOP - 32)) +#else +#define _MSB_32(START, STOP) (START >= STOP \ + ? (START >= 32 ? 31 : START) \ + : (STOP >= 32 ? 31 : STOP)) +#endif + +#if (WITH_TARGET_WORD_MSB == 0) +#define _LSB_32(START, STOP) (START <= STOP \ + ? (STOP < 32 ? 0 : STOP - 32) \ + : (START < 32 ? 0 : START - 32)) +#else +#define _LSB_32(START, STOP) (START >= STOP \ + ? (STOP >= 32 ? 31 : STOP) \ + : (START >= 32 ? 31 : START)) +#endif + +#if (WITH_TARGET_WORD_MSB == 0) +#define _MSB(START, STOP) (START <= STOP ? START : STOP) +#else +#define _MSB(START, STOP) (START >= STOP ? START : STOP) +#endif + +#if (WITH_TARGET_WORD_MSB == 0) +#define _LSB(START, STOP) (START <= STOP ? STOP : START) +#else +#define _LSB(START, STOP) (START >= STOP ? STOP : START) +#endif + + +/* LS/MS Bit operations */ + +#define LSBIT8(POS) ((unsigned8) 1 << (POS)) +#define LSBIT16(POS) ((unsigned16)1 << (POS)) +#define LSBIT32(POS) ((unsigned32)1 << (POS)) +#define LSBIT64(POS) ((unsigned64)1 << (POS)) + +#if (WITH_TARGET_WORD_BITSIZE == 64) +#define LSBIT(POS) LSBIT64 (POS) +#else +#define LSBIT(POS) ((unsigned32)((POS) >= 32 \ + ? 0 \ + : (1 << ((POS) >= 32 ? 0 : (POS))))) +#endif + + +#define MSBIT8(POS) ((unsigned8) 1 << ( 8 - 1 - (POS))) +#define MSBIT16(POS) ((unsigned16)1 << (16 - 1 - (POS))) +#define MSBIT32(POS) ((unsigned32)1 << (32 - 1 - (POS))) +#define MSBIT64(POS) ((unsigned64)1 << (64 - 1 - (POS))) + +#if (WITH_TARGET_WORD_BITSIZE == 64) +#define MSBIT(POS) MSBIT64 (POS) +#else +#define MSBIT(POS) ((unsigned32)((POS) < 32 \ + ? 0 \ + : (1 << ((POS) < 32 ? 0 : (64 - 1) - (POS))))) +#endif + + +/* Bit operations */ + +#define BIT4(POS) (1 << _LSB_SHIFT (4, (POS))) +#define BIT5(POS) (1 << _LSB_SHIFT (5, (POS))) +#define BIT10(POS) (1 << _LSB_SHIFT (10, (POS))) + +#if (WITH_TARGET_WORD_MSB == 0) +#define BIT8 MSBIT8 +#define BIT16 MSBIT16 +#define BIT32 MSBIT32 +#define BIT64 MSBIT64 +#define BIT MSBIT +#else +#define BIT8 LSBIT8 +#define BIT16 LSBIT16 +#define BIT32 LSBIT32 +#define BIT64 LSBIT64 +#define BIT LSBIT +#endif + + + +/* multi bit mask */ + +/* 111111 -> mmll11 -> mm11ll */ +#define _MASKn(WIDTH, START, STOP) (((unsigned##WIDTH)(-1) \ + >> (_MSB_SHIFT (WIDTH, START) \ + + _LSB_SHIFT (WIDTH, STOP))) \ + << _LSB_SHIFT (WIDTH, STOP)) + +#if (WITH_TARGET_WORD_MSB == 0) +#define _POS_LE(START, STOP) (START <= STOP) +#else +#define _POS_LE(START, STOP) (STOP <= START) +#endif + +#if (WITH_TARGET_WORD_BITSIZE == 64) +#define MASK(START, STOP) \ + (_POS_LE ((START), (STOP)) \ + ? _MASKn(64, \ + _MSB ((START), (STOP)), \ + _LSB ((START), (STOP)) ) \ + : (_MASKn(64, _MSB_POS (64, 0), (STOP)) \ + | _MASKn(64, (START), _LSB_POS (64, 0)))) +#endif +#if (WITH_TARGET_WORD_BITSIZE == 32) +#define MASK(START, STOP) \ + (_POS_LE ((START), (STOP)) \ + ? (_POS_LE ((STOP), _MSB_POS (64, 31)) \ + ? 0 \ + : _MASKn (32, \ + _MSB_32 ((START), (STOP)), \ + _LSB_32 ((START), (STOP)))) \ + : (_MASKn (32, \ + _LSB_32 ((START), (STOP)), \ + _LSB_POS (32, 0)) \ + | (_POS_LE ((STOP), _MSB_POS (64, 31)) \ + ? 0 \ + : _MASKn (32, \ + _MSB_POS (32, 0), \ + _MSB_32 ((START), (STOP)))))) +#endif +#if !defined (MASK) +#error "MASK never undefined" +#endif + + +/* Multi-bit mask on least significant bits */ + +#define _LSMASKn(WIDTH, FIRST, LAST) _MASKn (WIDTH, \ + _LSB_POS (WIDTH, FIRST), \ + _LSB_POS (WIDTH, LAST)) + +#define LSMASK8(FIRST, LAST) _LSMASKn ( 8, (FIRST), (LAST)) +#define LSMASK16(FIRST, LAST) _LSMASKn (16, (FIRST), (LAST)) +#define LSMASK32(FIRST, LAST) _LSMASKn (32, (FIRST), (LAST)) +#define LSMASK64(FIRST, LAST) _LSMASKn (64, (FIRST), (LAST)) + +#define LSMASK(FIRST, LAST) (MASK (_LSB_POS (64, FIRST), _LSB_POS (64, LAST))) + + +/* Multi-bit mask on most significant bits */ + +#define _MSMASKn(WIDTH, FIRST, LAST) _MASKn (WIDTH, \ + _MSB_POS (WIDTH, FIRST), \ + _MSB_POS (WIDTH, LAST)) + +#define MSMASK8(FIRST, LAST) _MSMASKn ( 8, (FIRST), (LAST)) +#define MSMASK16(FIRST, LAST) _MSMASKn (16, (FIRST), (LAST)) +#define MSMASK32(FIRST, LAST) _MSMASKn (32, (FIRST), (LAST)) +#define MSMASK64(FIRST, LAST) _MSMASKn (64, (FIRST), (LAST)) + +#define MSMASK(FIRST, LAST) (MASK (_MSB_POS (64, FIRST), _MSB_POS (64, LAST))) + + + +#if (WITH_TARGET_WORD_MSB == 0) +#define MASK8 MSMASK8 +#define MASK16 MSMASK16 +#define MASK32 MSMASK32 +#define MASK64 MSMASK64 +#else +#define MASK8 LSMASK8 +#define MASK16 LSMASK16 +#define MASK32 LSMASK32 +#define MASK64 LSMASK64 +#endif + + + +/* mask the required bits, leaving them in place */ + +INLINE_SIM_BITS(unsigned8) LSMASKED8 (unsigned8 word, int first, int last); +INLINE_SIM_BITS(unsigned16) LSMASKED16 (unsigned16 word, int first, int last); +INLINE_SIM_BITS(unsigned32) LSMASKED32 (unsigned32 word, int first, int last); +INLINE_SIM_BITS(unsigned64) LSMASKED64 (unsigned64 word, int first, int last); + +INLINE_SIM_BITS(unsigned_word) LSMASKED (unsigned_word word, int first, int last); + +INLINE_SIM_BITS(unsigned8) MSMASKED8 (unsigned8 word, int first, int last); +INLINE_SIM_BITS(unsigned16) MSMASKED16 (unsigned16 word, int first, int last); +INLINE_SIM_BITS(unsigned32) MSMASKED32 (unsigned32 word, int first, int last); +INLINE_SIM_BITS(unsigned64) MSMASKED64 (unsigned64 word, int first, int last); + +INLINE_SIM_BITS(unsigned_word) MSMASKED (unsigned_word word, int first, int last); + +#if (WITH_TARGET_WORD_MSB == 0) +#define MASKED8 MSMASKED8 +#define MASKED16 MSMASKED16 +#define MASKED32 MSMASKED32 +#define MASKED64 MSMASKED64 +#define MASKED MSMASKED +#else +#define MASKED8 LSMASKED8 +#define MASKED16 LSMASKED16 +#define MASKED32 LSMASKED32 +#define MASKED64 LSMASKED64 +#define MASKED LSMASKED +#endif + + + +/* extract the required bits aligning them with the lsb */ + +INLINE_SIM_BITS(unsigned8) LSEXTRACTED8 (unsigned8 val, int start, int stop); +INLINE_SIM_BITS(unsigned16) LSEXTRACTED16 (unsigned16 val, int start, int stop); +INLINE_SIM_BITS(unsigned32) LSEXTRACTED32 (unsigned32 val, int start, int stop); +INLINE_SIM_BITS(unsigned64) LSEXTRACTED64 (unsigned64 val, int start, int stop); + +INLINE_SIM_BITS(unsigned_word) LSEXTRACTED (unsigned_word val, int start, int stop); + +INLINE_SIM_BITS(unsigned8) MSEXTRACTED8 (unsigned8 val, int start, int stop); +INLINE_SIM_BITS(unsigned16) MSEXTRACTED16 (unsigned16 val, int start, int stop); +INLINE_SIM_BITS(unsigned32) MSEXTRACTED32 (unsigned32 val, int start, int stop); +INLINE_SIM_BITS(unsigned64) MSEXTRACTED64 (unsigned64 val, int start, int stop); + +INLINE_SIM_BITS(unsigned_word) MSEXTRACTED (unsigned_word val, int start, int stop); + +#if (WITH_TARGET_WORD_MSB == 0) +#define EXTRACTED8 MSEXTRACTED8 +#define EXTRACTED16 MSEXTRACTED16 +#define EXTRACTED32 MSEXTRACTED32 +#define EXTRACTED64 MSEXTRACTED64 +#define EXTRACTED MSEXTRACTED +#else +#define EXTRACTED8 LSEXTRACTED8 +#define EXTRACTED16 LSEXTRACTED16 +#define EXTRACTED32 LSEXTRACTED32 +#define EXTRACTED64 LSEXTRACTED64 +#define EXTRACTED LSEXTRACTED +#endif + + + +/* move a single bit around */ +/* NB: the wierdness (N>O?N-O:0) is to stop a warning from GCC */ +#define _SHUFFLEDn(N, WORD, OLD, NEW) \ +((OLD) < (NEW) \ + ? (((unsigned##N)(WORD) \ + >> (((NEW) > (OLD)) ? ((NEW) - (OLD)) : 0)) \ + & MASK32((NEW), (NEW))) \ + : (((unsigned##N)(WORD) \ + << (((OLD) > (NEW)) ? ((OLD) - (NEW)) : 0)) \ + & MASK32((NEW), (NEW)))) + +#define SHUFFLED32(WORD, OLD, NEW) _SHUFFLEDn (32, WORD, OLD, NEW) +#define SHUFFLED64(WORD, OLD, NEW) _SHUFFLEDn (64, WORD, OLD, NEW) + +#define SHUFFLED(WORD, OLD, NEW) _SHUFFLEDn (_word, WORD, OLD, NEW) + + +/* Insert a group of bits into a bit position */ + +INLINE_SIM_BITS(unsigned8) LSINSERTED8 (unsigned8 val, int start, int stop); +INLINE_SIM_BITS(unsigned16) LSINSERTED16 (unsigned16 val, int start, int stop); +INLINE_SIM_BITS(unsigned32) LSINSERTED32 (unsigned32 val, int start, int stop); +INLINE_SIM_BITS(unsigned64) LSINSERTED64 (unsigned64 val, int start, int stop); +INLINE_SIM_BITS(unsigned_word) LSINSERTED (unsigned_word val, int start, int stop); + +INLINE_SIM_BITS(unsigned8) MSINSERTED8 (unsigned8 val, int start, int stop); +INLINE_SIM_BITS(unsigned16) MSINSERTED16 (unsigned16 val, int start, int stop); +INLINE_SIM_BITS(unsigned32) MSINSERTED32 (unsigned32 val, int start, int stop); +INLINE_SIM_BITS(unsigned64) MSINSERTED64 (unsigned64 val, int start, int stop); +INLINE_SIM_BITS(unsigned_word) MSINSERTED (unsigned_word val, int start, int stop); + +#if (WITH_TARGET_WORD_MSB == 0) +#define INSERTED8 MSINSERTED8 +#define INSERTED16 MSINSERTED16 +#define INSERTED32 MSINSERTED32 +#define INSERTED64 MSINSERTED64 +#define INSERTED MSINSERTED +#else +#define INSERTED8 LSINSERTED8 +#define INSERTED16 LSINSERTED16 +#define INSERTED32 LSINSERTED32 +#define INSERTED64 LSINSERTED64 +#define INSERTED LSINSERTED +#endif + + + +/* MOVE bits from one loc to another (combination of extract/insert) */ + +#define MOVED8(VAL,OH,OL,NH,NL) INSERTED8 (EXTRACTED8 ((VAL), OH, OL), NH, NL) +#define MOVED16(VAL,OH,OL,NH,NL) INSERTED16(EXTRACTED16((VAL), OH, OL), NH, NL) +#define MOVED32(VAL,OH,OL,NH,NL) INSERTED32(EXTRACTED32((VAL), OH, OL), NH, NL) +#define MOVED64(VAL,OH,OL,NH,NL) INSERTED64(EXTRACTED64((VAL), OH, OL), NH, NL) +#define MOVED(VAL,OH,OL,NH,NL) INSERTED (EXTRACTED ((VAL), OH, OL), NH, NL) + + + +/* Sign extend the quantity to the targets natural word size */ + +#define EXTEND4(X) (LSSEXT ((X), 3)) +#define EXTEND5(X) (LSSEXT ((X), 4)) +#define EXTEND8(X) ((signed_word)(signed8)(X)) +#define EXTEND11(X) (LSSEXT ((X), 10)) +#define EXTEND15(X) (LSSEXT ((X), 14)) +#define EXTEND16(X) ((signed_word)(signed16)(X)) +#define EXTEND24(X) (LSSEXT ((X), 23)) +#define EXTEND32(X) ((signed_word)(signed32)(X)) +#define EXTEND64(X) ((signed_word)(signed64)(X)) + +/* depending on MODE return a 64bit or 32bit (sign extended) value */ +#if (WITH_TARGET_WORD_BITSIZE == 64) +#define EXTENDED(X) ((signed64)(signed32)(X)) +#endif +#if (WITH_TARGET_WORD_BITSIZE == 32) +#define EXTENDED(X) (X) +#endif + + +/* memory alignment macro's */ +#define _ALIGNa(A,X) (((X) + ((A) - 1)) & ~((A) - 1)) +#define _FLOORa(A,X) ((X) & ~((A) - 1)) + +#define ALIGN_8(X) _ALIGNa (8, X) +#define ALIGN_16(X) _ALIGNa (16, X) + +#define ALIGN_PAGE(X) _ALIGNa (0x1000, X) +#define FLOOR_PAGE(X) ((X) & ~(0x1000 - 1)) + + +/* bit bliting macro's */ +#define BLIT32(V, POS, BIT) \ +do { \ + if (BIT) \ + V |= BIT32 (POS); \ + else \ + V &= ~BIT32 (POS); \ +} while (0) +#define MBLIT32(V, LO, HI, VAL) \ +do { \ + (V) = (((V) & ~MASK32 ((LO), (HI))) \ + | INSERTED32 (VAL, LO, HI)); \ +} while (0) + + + +/* some rotate functions. The generic macro's ROT, ROTL, ROTR are + intentionally omited. */ + + +INLINE_SIM_BITS(unsigned8) ROT8 (unsigned8 val, int shift); +INLINE_SIM_BITS(unsigned16) ROT16 (unsigned16 val, int shift); +INLINE_SIM_BITS(unsigned32) ROT32 (unsigned32 val, int shift); +INLINE_SIM_BITS(unsigned64) ROT64 (unsigned64 val, int shift); + + +INLINE_SIM_BITS(unsigned8) ROTL8 (unsigned8 val, int shift); +INLINE_SIM_BITS(unsigned16) ROTL16 (unsigned16 val, int shift); +INLINE_SIM_BITS(unsigned32) ROTL32 (unsigned32 val, int shift); +INLINE_SIM_BITS(unsigned64) ROTL64 (unsigned64 val, int shift); + + +INLINE_SIM_BITS(unsigned8) ROTR8 (unsigned8 val, int shift); +INLINE_SIM_BITS(unsigned16) ROTR16 (unsigned16 val, int shift); +INLINE_SIM_BITS(unsigned32) ROTR32 (unsigned32 val, int shift); +INLINE_SIM_BITS(unsigned64) ROTR64 (unsigned64 val, int shift); + + + +/* Sign extension operations */ + +INLINE_SIM_BITS(unsigned8) LSSEXT8 (signed8 val, int sign_bit); +INLINE_SIM_BITS(unsigned16) LSSEXT16 (signed16 val, int sign_bit); +INLINE_SIM_BITS(unsigned32) LSSEXT32 (signed32 val, int sign_bit); +INLINE_SIM_BITS(unsigned64) LSSEXT64 (signed64 val, int sign_bit); +INLINE_SIM_BITS(unsigned_word) LSSEXT (signed_word val, int sign_bit); + +INLINE_SIM_BITS(unsigned8) MSSEXT8 (signed8 val, int sign_bit); +INLINE_SIM_BITS(unsigned16) MSSEXT16 (signed16 val, int sign_bit); +INLINE_SIM_BITS(unsigned32) MSSEXT32 (signed32 val, int sign_bit); +INLINE_SIM_BITS(unsigned64) MSSEXT64 (signed64 val, int sign_bit); +INLINE_SIM_BITS(unsigned_word) MSSEXT (signed_word val, int sign_bit); + +#if (WITH_TARGET_WORD_MSB == 0) +#define SEXT8 MSSEXT8 +#define SEXT16 MSSEXT16 +#define SEXT32 MSSEXT32 +#define SEXT64 MSSEXT64 +#define SEXT MSSEXT +#else +#define SEXT8 LSSEXT8 +#define SEXT16 LSSEXT16 +#define SEXT32 LSSEXT32 +#define SEXT64 LSSEXT64 +#define SEXT LSSEXT +#endif + + + +#if H_REVEALS_MODULE_P (SIM_BITS_INLINE) +#include "sim-bits.c" +#endif + +#endif /* _SIM_BITS_H_ */ diff --git a/sim/common/sim-break.c b/sim/common/sim-break.c new file mode 100644 index 00000000000..3b89560aeb1 --- /dev/null +++ b/sim/common/sim-break.c @@ -0,0 +1,278 @@ +/* Simulator breakpoint support. + Copyright (C) 1997 Free Software Foundation, Inc. + Contributed by Cygnus Support. + +This file is part of GDB, the GNU debugger. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include + +#include "sim-main.h" +#include "sim-assert.h" +#include "sim-break.h" + +#ifndef SIM_BREAKPOINT +#define SIM_BREAKPOINT {0x00} +#define SIM_BREAKPOINT_SIZE (1) +#endif + +struct +sim_breakpoint +{ + struct sim_breakpoint *next; + SIM_ADDR addr; /* Address of this breakpoint */ + int flags; + unsigned char loc_contents[SIM_BREAKPOINT_SIZE]; /* Contents of addr while + BP is enabled */ +}; + +#define SIM_BREAK_INSERTED 0x1 /* Breakpoint has been inserted */ +#define SIM_BREAK_DISABLED 0x2 /* Breakpoint is disabled */ + +static unsigned char sim_breakpoint [] = SIM_BREAKPOINT; + +static void insert_breakpoint PARAMS ((SIM_DESC sd, + struct sim_breakpoint *bp)); +static void remove_breakpoint PARAMS ((SIM_DESC sd, + struct sim_breakpoint *bp)); +static SIM_RC resume_handler PARAMS ((SIM_DESC sd)); +static SIM_RC suspend_handler PARAMS ((SIM_DESC sd)); + + +/* Do the actual work of inserting a breakpoint into the instruction + stream. */ + +static void +insert_breakpoint (sd, bp) + SIM_DESC sd; + struct sim_breakpoint *bp; +{ + if (bp->flags & (SIM_BREAK_INSERTED | SIM_BREAK_DISABLED)) + return; + + sim_core_read_buffer (sd, NULL, exec_map, bp->loc_contents, + bp->addr, SIM_BREAKPOINT_SIZE); + sim_core_write_buffer (sd, NULL, exec_map, sim_breakpoint, + bp->addr, SIM_BREAKPOINT_SIZE); + bp->flags |= SIM_BREAK_INSERTED; +} + +/* Do the actual work of removing a breakpoint. */ + +static void +remove_breakpoint (sd, bp) + SIM_DESC sd; + struct sim_breakpoint *bp; +{ + if (!(bp->flags & SIM_BREAK_INSERTED)) + return; + + sim_core_write_buffer (sd, NULL, exec_map, bp->loc_contents, + bp->addr, SIM_BREAKPOINT_SIZE); + bp->flags &= ~SIM_BREAK_INSERTED; +} + +/* Come here when a breakpoint insn is hit. If it's really a breakpoint, we + halt things, and never return. If it's a false hit, we return to let the + caller handle things. */ + +void +sim_handle_breakpoint (sd, cpu, cia) + SIM_DESC sd; + sim_cpu *cpu; + sim_cia cia; +{ + struct sim_breakpoint *bp; + + for (bp = STATE_BREAKPOINTS (sd); bp; bp = bp->next) + if (bp->addr == CIA_ADDR (cia)) + break; + + if (!bp || !(bp->flags & SIM_BREAK_INSERTED)) + return; + + sim_engine_halt (sd, STATE_CPU (sd, 0), NULL, cia, sim_stopped, SIM_SIGTRAP); +} + +/* Handler functions for simulator resume and suspend events. */ + +static SIM_RC +resume_handler (sd) + SIM_DESC sd; +{ + struct sim_breakpoint *bp; + + for (bp = STATE_BREAKPOINTS (sd); bp; bp = bp->next) + insert_breakpoint (sd, bp); + + return SIM_RC_OK; +} + +static SIM_RC +suspend_handler (sd) + SIM_DESC sd; +{ + struct sim_breakpoint *bp; + + for (bp = STATE_BREAKPOINTS (sd); bp; bp = bp->next) + remove_breakpoint (sd, bp); + + return SIM_RC_OK; +} + +/* Called from simulator module initialization. */ + +SIM_RC +sim_break_install (sd) + SIM_DESC sd; +{ + sim_module_add_resume_fn (sd, resume_handler); + sim_module_add_suspend_fn (sd, suspend_handler); + + return SIM_RC_OK; +} + +/* Install a breakpoint. This is a user-function. The breakpoint isn't + actually installed here. We just record it. Resume_handler does the + actual work. +*/ + +SIM_RC +sim_set_breakpoint (sd, addr) + SIM_DESC sd; + SIM_ADDR addr; +{ + struct sim_breakpoint *bp; + + for (bp = STATE_BREAKPOINTS (sd); bp; bp = bp->next) + if (bp->addr == addr) + return SIM_RC_DUPLICATE_BREAKPOINT; /* Already there */ + else + break; /* FIXME: why not scan all bp's? */ + + bp = ZALLOC (struct sim_breakpoint); + + bp->addr = addr; + bp->next = STATE_BREAKPOINTS (sd); + bp->flags = 0; + STATE_BREAKPOINTS (sd) = bp; + + return SIM_RC_OK; +} + +/* Delete a breakpoint. All knowlege of the breakpoint is removed from the + simulator. +*/ + +SIM_RC +sim_clear_breakpoint (sd, addr) + SIM_DESC sd; + SIM_ADDR addr; +{ + struct sim_breakpoint *bp, *bpprev; + + for (bp = STATE_BREAKPOINTS (sd), bpprev = NULL; + bp; + bpprev = bp, bp = bp->next) + if (bp->addr == addr) + break; + + if (!bp) + return SIM_RC_UNKNOWN_BREAKPOINT; + + remove_breakpoint (sd, bp); + + if (bpprev) + bpprev->next = bp->next; + else + STATE_BREAKPOINTS (sd) = NULL; + + zfree (bp); + + return SIM_RC_OK; +} + +SIM_RC +sim_clear_all_breakpoints (sd) + SIM_DESC sd; +{ + while (STATE_BREAKPOINTS (sd)) + sim_clear_breakpoint (sd, STATE_BREAKPOINTS (sd)->addr); + + return SIM_RC_OK; +} + +SIM_RC +sim_enable_breakpoint (sd, addr) + SIM_DESC sd; + SIM_ADDR addr; +{ + struct sim_breakpoint *bp; + + for (bp = STATE_BREAKPOINTS (sd); bp; bp = bp->next) + if (bp->addr == addr) + break; + + if (!bp) + return SIM_RC_UNKNOWN_BREAKPOINT; + + bp->flags &= ~SIM_BREAK_DISABLED; + + return SIM_RC_OK; +} + +SIM_RC +sim_disable_breakpoint (sd, addr) + SIM_DESC sd; + SIM_ADDR addr; +{ + struct sim_breakpoint *bp; + + for (bp = STATE_BREAKPOINTS (sd); bp; bp = bp->next) + if (bp->addr == addr) + break; + + if (!bp) + return SIM_RC_UNKNOWN_BREAKPOINT; + + bp->flags |= SIM_BREAK_DISABLED; + + return SIM_RC_OK; +} + +SIM_RC +sim_enable_all_breakpoints (sd) + SIM_DESC sd; +{ + struct sim_breakpoint *bp; + + for (bp = STATE_BREAKPOINTS (sd); bp; bp = bp->next) + bp->flags &= ~SIM_BREAK_DISABLED; + + return SIM_RC_OK; +} + +SIM_RC +sim_disable_all_breakpoints (sd) + SIM_DESC sd; +{ + struct sim_breakpoint *bp; + + for (bp = STATE_BREAKPOINTS (sd); bp; bp = bp->next) + bp->flags |= SIM_BREAK_DISABLED; + + return SIM_RC_OK; +} diff --git a/sim/common/sim-break.h b/sim/common/sim-break.h new file mode 100644 index 00000000000..8b0338f4b38 --- /dev/null +++ b/sim/common/sim-break.h @@ -0,0 +1,38 @@ +/* Simulator breakpoint support. + Copyright (C) 1997 Free Software Foundation, Inc. + Contributed by Cygnus Support. + +This file is part of GDB, the GNU debugger. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + + +#ifndef SIM_BREAK_H +#define SIM_BREAK_H + +/* Call this to install the resume and suspend handlers for the breakpoint + module. */ + +MODULE_INSTALL_FN sim_break_install; + +/* Call this inside the simulator when we execute the potential + breakpoint insn. If the breakpoint system knows about it, the + breakpoint is handled, and this routine never returns. If this + isn't really a breakpoint, then it returns to allow the caller to + handle things. */ + +void sim_handle_breakpoint PARAMS ((SIM_DESC sd, sim_cpu *cpu, sim_cia cia)); + +#endif /* SIM_BREAK_H */ diff --git a/sim/common/sim-config.c b/sim/common/sim-config.c new file mode 100644 index 00000000000..10a19aaa205 --- /dev/null +++ b/sim/common/sim-config.c @@ -0,0 +1,377 @@ +/* This file is part of the GNU simulators. + + Copyright (C) 1994-1995,1997, Andrew Cagney + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + + +#include "sim-main.h" +#include "sim-assert.h" +#include "bfd.h" + + +int current_host_byte_order; +int current_target_byte_order; +int current_stdio; + +enum sim_alignments current_alignment; + +#if defined (WITH_FLOATING_POINT) +int current_floating_point; +#endif + + + +/* map a byte order onto a textual string */ + +static const char * +config_byte_order_to_a (int byte_order) +{ + switch (byte_order) + { + case LITTLE_ENDIAN: + return "LITTLE_ENDIAN"; + case BIG_ENDIAN: + return "BIG_ENDIAN"; + case 0: + return "0"; + } + return "UNKNOWN"; +} + + +static const char * +config_stdio_to_a (int stdio) +{ + switch (stdio) + { + case DONT_USE_STDIO: + return "DONT_USE_STDIO"; + case DO_USE_STDIO: + return "DO_USE_STDIO"; + case 0: + return "0"; + } + return "UNKNOWN"; +} + + +static const char * +config_environment_to_a (enum sim_environment environment) +{ + switch (environment) + { + case ALL_ENVIRONMENT: + return "ALL_ENVIRONMENT"; + case USER_ENVIRONMENT: + return "USER_ENVIRONMENT"; + case VIRTUAL_ENVIRONMENT: + return "VIRTUAL_ENVIRONMENT"; + case OPERATING_ENVIRONMENT: + return "OPERATING_ENVIRONMENT"; + } + return "UNKNOWN"; +} + + +static const char * +config_alignment_to_a (enum sim_alignments alignment) +{ + switch (alignment) + { + case MIXED_ALIGNMENT: + return "MIXED_ALIGNMENT"; + case NONSTRICT_ALIGNMENT: + return "NONSTRICT_ALIGNMENT"; + case STRICT_ALIGNMENT: + return "STRICT_ALIGNMENT"; + case FORCED_ALIGNMENT: + return "FORCED_ALIGNMENT"; + } + return "UNKNOWN"; +} + + +#if defined (WITH_FLOATING_POINT) +static const char * +config_floating_point_to_a (int floating_point) +{ + switch (floating_point) + { + case SOFT_FLOATING_POINT: + return "SOFT_FLOATING_POINT"; + case HARD_FLOATING_POINT: + return "HARD_FLOATING_POINT"; + case 0: + return "0"; + } + return "UNKNOWN"; +} +#endif + +/* Set the default environment, prior to parsing argv. */ + +void +sim_config_default (SIM_DESC sd) +{ + /* Set the current environment to ALL_ENVIRONMENT to indicate none has been + selected yet. This is so that after parsing argv, we know whether the + environment was explicitly specified or not. */ + STATE_ENVIRONMENT (sd) = ALL_ENVIRONMENT; +} + +/* Complete and verify the simulation environment. */ + +SIM_RC +sim_config (SIM_DESC sd) +{ + int prefered_target_byte_order; + SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); + + /* extract all relevant information */ + if (STATE_PROG_BFD (sd) == NULL) + prefered_target_byte_order = 0; + else + prefered_target_byte_order = (bfd_little_endian(STATE_PROG_BFD (sd)) + ? LITTLE_ENDIAN + : BIG_ENDIAN); + + /* set the host byte order */ + current_host_byte_order = 1; + if (*(char*)(¤t_host_byte_order)) + current_host_byte_order = LITTLE_ENDIAN; + else + current_host_byte_order = BIG_ENDIAN; + + /* verify the host byte order */ + if (CURRENT_HOST_BYTE_ORDER != current_host_byte_order) + { + sim_io_eprintf (sd, "host (%s) and configured (%s) byte order in conflict", + config_byte_order_to_a (current_host_byte_order), + config_byte_order_to_a (CURRENT_HOST_BYTE_ORDER)); + return SIM_RC_FAIL; + } + + + /* set the target byte order */ +#if (WITH_TREE_PROPERTIES) + if (current_target_byte_order == 0) + current_target_byte_order + = (tree_find_boolean_property (root, "/options/little-endian?") + ? LITTLE_ENDIAN + : BIG_ENDIAN); +#endif + if (current_target_byte_order == 0 + && prefered_target_byte_order != 0) + current_target_byte_order = prefered_target_byte_order; + if (current_target_byte_order == 0) + current_target_byte_order = WITH_TARGET_BYTE_ORDER; + if (current_target_byte_order == 0) + current_target_byte_order = WITH_DEFAULT_TARGET_BYTE_ORDER; + + /* verify the target byte order */ + if (CURRENT_TARGET_BYTE_ORDER == 0) + { + sim_io_eprintf (sd, "Target byte order unspecified\n"); + return SIM_RC_FAIL; + } + if (CURRENT_TARGET_BYTE_ORDER != current_target_byte_order) + sim_io_eprintf (sd, "Target (%s) and configured (%s) byte order in conflict\n", + config_byte_order_to_a (current_target_byte_order), + config_byte_order_to_a (CURRENT_TARGET_BYTE_ORDER)); + if (prefered_target_byte_order != 0 + && CURRENT_TARGET_BYTE_ORDER != prefered_target_byte_order) + sim_io_eprintf (sd, "Target (%s) and specified (%s) byte order in conflict\n", + config_byte_order_to_a (CURRENT_TARGET_BYTE_ORDER), + config_byte_order_to_a (prefered_target_byte_order)); + + + /* set the stdio */ + if (current_stdio == 0) + current_stdio = WITH_STDIO; + if (current_stdio == 0) + current_stdio = DO_USE_STDIO; + + /* verify the stdio */ + if (CURRENT_STDIO == 0) + { + sim_io_eprintf (sd, "Target standard IO unspecified\n"); + return SIM_RC_FAIL; + } + if (CURRENT_STDIO != current_stdio) + { + sim_io_eprintf (sd, "Target (%s) and configured (%s) standard IO in conflict\n", + config_stdio_to_a (CURRENT_STDIO), + config_stdio_to_a (current_stdio)); + return SIM_RC_FAIL; + } + + + /* check the value of MSB */ + if (WITH_TARGET_WORD_MSB != 0 + && WITH_TARGET_WORD_MSB != (WITH_TARGET_WORD_BITSIZE - 1)) + { + sim_io_eprintf (sd, "Target bitsize (%d) contradicts target most significant bit (%d)\n", + WITH_TARGET_WORD_BITSIZE, WITH_TARGET_WORD_MSB); + return SIM_RC_FAIL; + } + + + /* set the environment */ +#if (WITH_TREE_PROPERTIES) + if (STATE_ENVIRONMENT (sd) == ALL_ENVIRONMENT) + { + const char *env = + tree_find_string_property(root, "/openprom/options/env"); + STATE_ENVIRONMENT (sd) = ((strcmp(env, "user") == 0 + || strcmp(env, "uea") == 0) + ? USER_ENVIRONMENT + : (strcmp(env, "virtual") == 0 + || strcmp(env, "vea") == 0) + ? VIRTUAL_ENVIRONMENT + : (strcmp(env, "operating") == 0 + || strcmp(env, "oea") == 0) + ? OPERATING_ENVIRONMENT + : ALL_ENVIRONMENT); + } +#endif + if (STATE_ENVIRONMENT (sd) == ALL_ENVIRONMENT) + STATE_ENVIRONMENT (sd) = DEFAULT_ENVIRONMENT; + + + /* set the alignment */ +#if (WITH_TREE_PROPERTIES) + if (current_alignment == 0) + current_alignment = + (tree_find_boolean_property(root, "/openprom/options/strict-alignment?") + ? STRICT_ALIGNMENT + : NONSTRICT_ALIGNMENT); +#endif + if (current_alignment == 0) + current_alignment = WITH_ALIGNMENT; + if (current_alignment == 0) + current_alignment = WITH_DEFAULT_ALIGNMENT; + + /* verify the alignment */ + if (CURRENT_ALIGNMENT == 0) + { + sim_io_eprintf (sd, "Target alignment unspecified\n"); + return SIM_RC_FAIL; + } + if (CURRENT_ALIGNMENT != current_alignment) + { + sim_io_eprintf (sd, "Target (%s) and configured (%s) alignment in conflict\n", + config_alignment_to_a (CURRENT_ALIGNMENT), + config_alignment_to_a (current_alignment)); + return SIM_RC_FAIL; + } + +#if defined (WITH_FLOATING_POINT) + + /* set the floating point */ + if (current_floating_point == 0) + current_floating_point = WITH_FLOATING_POINT; + + /* verify the floating point */ + if (CURRENT_FLOATING_POINT == 0) + { + sim_io_eprintf (sd, "Target floating-point unspecified\n"); + return SIM_RC_FAIL; + } + if (CURRENT_FLOATING_POINT != current_floating_point) + { + sim_io_eprintf (sd, "Target (%s) and configured (%s) floating-point in conflict\n", + config_alignment_to_a (CURRENT_FLOATING_POINT), + config_alignment_to_a (current_floating_point)); + return SIM_RC_FAIL; + } + +#endif + return SIM_RC_OK; +} + + +void +print_sim_config (SIM_DESC sd) +{ +#if defined (__GNUC__) && defined (__VERSION__) + sim_io_printf (sd, "Compiled by GCC %s on %s %s\n", + __VERSION__, __DATE__, __TIME__); +#else + sim_io_printf (sd, "Compiled on %s %s\n", __DATE__, __TIME__); +#endif + + sim_io_printf (sd, "WITH_TARGET_BYTE_ORDER = %s\n", + config_byte_order_to_a (WITH_TARGET_BYTE_ORDER)); + + sim_io_printf (sd, "WITH_DEFAULT_TARGET_BYTE_ORDER = %s\n", + config_byte_order_to_a (WITH_DEFAULT_TARGET_BYTE_ORDER)); + + sim_io_printf (sd, "WITH_HOST_BYTE_ORDER = %s\n", + config_byte_order_to_a (WITH_HOST_BYTE_ORDER)); + + sim_io_printf (sd, "WITH_STDIO = %s\n", + config_stdio_to_a (WITH_STDIO)); + + sim_io_printf (sd, "WITH_TARGET_WORD_MSB = %d\n", + WITH_TARGET_WORD_MSB); + + sim_io_printf (sd, "WITH_TARGET_WORD_BITSIZE = %d\n", + WITH_TARGET_WORD_BITSIZE); + + sim_io_printf (sd, "WITH_TARGET_ADDRESS_BITSIZE = %d\n", + WITH_TARGET_ADDRESS_BITSIZE); + + sim_io_printf (sd, "WITH_TARGET_CELL_BITSIZE = %d\n", + WITH_TARGET_CELL_BITSIZE); + + sim_io_printf (sd, "WITH_TARGET_FLOATING_POINT_BITSIZE = %d\n", + WITH_TARGET_FLOATING_POINT_BITSIZE); + + sim_io_printf (sd, "WITH_ENVIRONMENT = %s\n", + config_environment_to_a (WITH_ENVIRONMENT)); + + sim_io_printf (sd, "WITH_ALIGNMENT = %s\n", + config_alignment_to_a (WITH_ALIGNMENT)); + +#if defined (WITH_DEFAULT_ALIGNMENT) + sim_io_printf (sd, "WITH_DEFAULT_ALIGNMENT = %s\n", + config_alignment_to_a (WITH_DEFAULT_ALIGNMENT)); +#endif + +#if defined (WITH_XOR_ENDIAN) + sim_io_printf (sd, "WITH_XOR_ENDIAN = %d\n", WITH_XOR_ENDIAN); +#endif + +#if defined (WITH_FLOATING_POINT) + sim_io_printf (sd, "WITH_FLOATING_POINT = %s\n", + config_floating_point_to_a (WITH_FLOATING_POINT)); +#endif + +#if defined (WITH_SMP) + sim_io_printf (sd, "WITH_SMP = %d\n", WITH_SMP); +#endif + +#if defined (WITH_RESERVED_BITS) + sim_io_printf (sd, "WITH_RESERVED_BITS = %d\n", WITH_RESERVED_BITS); +#endif + +#if defined (WITH_PROFILE) + sim_io_printf (sd, "WITH_PROFILE = %d\n", WITH_PROFILE); +#endif + +} diff --git a/sim/common/sim-config.h b/sim/common/sim-config.h new file mode 100644 index 00000000000..97207120ac2 --- /dev/null +++ b/sim/common/sim-config.h @@ -0,0 +1,594 @@ +/* This file is part of the program psim. + + Copyright (C) 1994-1995, Andrew Cagney + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + + +#ifndef SIM_CONFIG_H +#define SIM_CONFIG_H + + +/* Host dependant: + + The CPP below defines information about the compilation host. In + particular it defines the macro's: + + WITH_HOST_BYTE_ORDER The byte order of the host. Could + be any of LITTLE_ENDIAN, BIG_ENDIAN + or 0 (unknown). Those macro's also + need to be defined. + + */ + + +/* NetBSD: + + NetBSD is easy, everything you could ever want is in a header file + (well almost :-) */ + +#if defined(__NetBSD__) +# include +# if (WITH_HOST_BYTE_ORDER == 0) +# undef WITH_HOST_BYTE_ORDER +# define WITH_HOST_BYTE_ORDER BYTE_ORDER +# endif +# if (BYTE_ORDER != WITH_HOST_BYTE_ORDER) +# error "host endian incorrectly configured, check config.h" +# endif +#endif + +/* Linux is similarly easy. */ + +#if defined(__linux__) +# include +# if defined(__LITTLE_ENDIAN) && !defined(LITTLE_ENDIAN) +# define LITTLE_ENDIAN __LITTLE_ENDIAN +# endif +# if defined(__BIG_ENDIAN) && !defined(BIG_ENDIAN) +# define BIG_ENDIAN __BIG_ENDIAN +# endif +# if defined(__BYTE_ORDER) && !defined(BYTE_ORDER) +# define BYTE_ORDER __BYTE_ORDER +# endif +# if (WITH_HOST_BYTE_ORDER == 0) +# undef WITH_HOST_BYTE_ORDER +# define WITH_HOST_BYTE_ORDER BYTE_ORDER +# endif +# if (BYTE_ORDER != WITH_HOST_BYTE_ORDER) +# error "host endian incorrectly configured, check config.h" +# endif +#endif + +/* INSERT HERE - hosts that have available LITTLE_ENDIAN and + BIG_ENDIAN macro's */ + + +/* Some hosts don't define LITTLE_ENDIAN or BIG_ENDIAN, help them out */ + +#ifndef LITTLE_ENDIAN +#define LITTLE_ENDIAN 1234 +#endif +#ifndef BIG_ENDIAN +#define BIG_ENDIAN 4321 +#endif + + +/* SunOS on SPARC: + + Big endian last time I looked */ + +#if defined(sparc) || defined(__sparc__) +# if (WITH_HOST_BYTE_ORDER == 0) +# undef WITH_HOST_BYTE_ORDER +# define WITH_HOST_BYTE_ORDER BIG_ENDIAN +# endif +# if (WITH_HOST_BYTE_ORDER != BIG_ENDIAN) +# error "sun was big endian last time I looked ..." +# endif +#endif + + +/* Random x86 + + Little endian last time I looked */ + +#if defined(i386) || defined(i486) || defined(i586) || defined (i686) || defined(__i386__) || defined(__i486__) || defined(__i586__) || defined (__i686__) +# if (WITH_HOST_BYTE_ORDER == 0) +# undef WITH_HOST_BYTE_ORDER +# define WITH_HOST_BYTE_ORDER LITTLE_ENDIAN +# endif +# if (WITH_HOST_BYTE_ORDER != LITTLE_ENDIAN) +# error "x86 was little endian last time I looked ..." +# endif +#endif + +#if (defined (__i486__) || defined (__i586__) || defined (__i686__)) && defined(__GNUC__) && WITH_BSWAP +#undef htonl +#undef ntohl +#define htonl(IN) __extension__ ({ int _out; __asm__ ("bswap %0" : "=r" (_out) : "0" (IN)); _out; }) +#define ntohl(IN) __extension__ ({ int _out; __asm__ ("bswap %0" : "=r" (_out) : "0" (IN)); _out; }) +#endif + +/* Power or PowerPC running AIX */ +#if defined(_POWER) && defined(_AIX) +# if (WITH_HOST_BYTE_ORDER == 0) +# undef WITH_HOST_BYTE_ORDER +# define WITH_HOST_BYTE_ORDER BIG_ENDIAN +# endif +# if (WITH_HOST_BYTE_ORDER != BIG_ENDIAN) +# error "Power/PowerPC AIX was big endian last time I looked ..." +# endif +#endif + +/* Solaris running PowerPC */ +#if defined(__PPC) && defined(__sun__) +# if (WITH_HOST_BYTE_ORDER == 0) +# undef WITH_HOST_BYTE_ORDER +# define WITH_HOST_BYTE_ORDER LITTLE_ENDIAN +# endif +# if (WITH_HOST_BYTE_ORDER != LITTLE_ENDIAN) +# error "Solaris on PowerPCs was little endian last time I looked ..." +# endif +#endif + +/* HP/PA */ +#if defined(__hppa__) +# if (WITH_HOST_BYTE_ORDER == 0) +# undef WITH_HOST_BYTE_ORDER +# define WITH_HOST_BYTE_ORDER BIG_ENDIAN +# endif +# if (WITH_HOST_BYTE_ORDER != BIG_ENDIAN) +# error "HP/PA was big endian last time I looked ..." +# endif +#endif + +/* Big endian MIPS */ +#if defined(__MIPSEB__) +# if (WITH_HOST_BYTE_ORDER == 0) +# undef WITH_HOST_BYTE_ORDER +# define WITH_HOST_BYTE_ORDER BIG_ENDIAN +# endif +# if (WITH_HOST_BYTE_ORDER != BIG_ENDIAN) +# error "MIPSEB was big endian last time I looked ..." +# endif +#endif + +/* Little endian MIPS */ +#if defined(__MIPSEL__) +# if (WITH_HOST_BYTE_ORDER == 0) +# undef WITH_HOST_BYTE_ORDER +# define WITH_HOST_BYTE_ORDER LITTLE_ENDIAN +# endif +# if (WITH_HOST_BYTE_ORDER != LITTLE_ENDIAN) +# error "MIPSEL was little endian last time I looked ..." +# endif +#endif + +/* Windows NT */ +#if defined(__WIN32__) +# if (WITH_HOST_BYTE_ORDER == 0) +# undef WITH_HOST_BYTE_ORDER +# define WITH_HOST_BYTE_ORDER LITTLE_ENDIAN +# endif +# if (WITH_HOST_BYTE_ORDER != LITTLE_ENDIAN) +# error "Windows NT was little endian last time I looked ..." +# endif +#endif + +/* Alpha running DEC unix */ +#if defined(__osf__) && defined(__alpha__) +# if (WITH_HOST_BYTE_ORDER == 0) +# undef WITH_HOST_BYTE_ORDER +# define WITH_HOST_BYTE_ORDER LITTLE_ENDIAN +# endif +# if (WITH_HOST_BYTE_ORDER != LITTLE_ENDIAN) +# error "AXP running DEC unix was little endian last time I looked ..." +# endif +#endif + + +/* INSERT HERE - additional hosts that do not have LITTLE_ENDIAN and + BIG_ENDIAN definitions available. */ + +/* Until devices and tree properties are sorted out, tell sim-config.c + not to call the tree_find_foo fns. */ +#define WITH_TREE_PROPERTIES 0 + + +/* endianness of the host/target: + + If the build process is aware (at compile time) of the endianness + of the host/target it is able to eliminate slower generic endian + handling code. + + Possible values are 0 (unknown), LITTLE_ENDIAN, BIG_ENDIAN */ + +#ifndef WITH_HOST_BYTE_ORDER +#define WITH_HOST_BYTE_ORDER 0 /*unknown*/ +#endif + +#ifndef WITH_TARGET_BYTE_ORDER +#define WITH_TARGET_BYTE_ORDER 0 /*unknown*/ +#endif + +#ifndef WITH_DEFAULT_TARGET_BYTE_ORDER +#define WITH_DEFAULT_TARGET_BYTE_ORDER 0 /* fatal */ +#endif + +extern int current_host_byte_order; +#define CURRENT_HOST_BYTE_ORDER (WITH_HOST_BYTE_ORDER \ + ? WITH_HOST_BYTE_ORDER \ + : current_host_byte_order) +extern int current_target_byte_order; +#define CURRENT_TARGET_BYTE_ORDER (WITH_TARGET_BYTE_ORDER \ + ? WITH_TARGET_BYTE_ORDER \ + : current_target_byte_order) + + + +/* XOR endian. + + In addition to the above, the simulator can support the horrible + XOR endian mode (as found in the PowerPC and MIPS ISA). See + sim-core for more information. + + If WITH_XOR_ENDIAN is non-zero, it specifies the number of bytes + potentially involved in the XOR munge. A typical value is 8. */ + +#ifndef WITH_XOR_ENDIAN +#define WITH_XOR_ENDIAN 0 +#endif + + + +/* Intel host BSWAP support: + + Whether to use bswap on the 486 and pentiums rather than the 386 + sequence that uses xchgb/rorl/xchgb */ +#ifndef WITH_BSWAP +#define WITH_BSWAP 0 +#endif + + + +/* SMP support: + + Sets a limit on the number of processors that can be simulated. If + WITH_SMP is set to zero (0), the simulator is restricted to + suporting only one processor (and as a consequence leaves the SMP + code out of the build process). + + The actual number of processors is taken from the device + /options/smp@ */ + +#if defined (WITH_SMP) && (WITH_SMP > 0) +#define MAX_NR_PROCESSORS WITH_SMP +#endif + +#ifndef MAX_NR_PROCESSORS +#define MAX_NR_PROCESSORS 1 +#endif + + +/* Size of target word, address and OpenFirmware Cell: + + The target word size is determined by the natural size of its + reginsters. + + On most hosts, the address and cell are the same size as a target + word. */ + +#ifndef WITH_TARGET_WORD_BITSIZE +#define WITH_TARGET_WORD_BITSIZE 32 +#endif + +#ifndef WITH_TARGET_ADDRESS_BITSIZE +#define WITH_TARGET_ADDRESS_BITSIZE WITH_TARGET_WORD_BITSIZE +#endif + +#ifndef WITH_TARGET_CELL_BITSIZE +#define WITH_TARGET_CELL_BITSIZE WITH_TARGET_WORD_BITSIZE +#endif + +#ifndef WITH_TARGET_FLOATING_POINT_BITSIZE +#define WITH_TARGET_FLOATING_POINT_BITSIZE 64 +#endif + + + +/* Most significant bit of target: + + Set this according to your target's bit numbering convention. For + the PowerPC it is zero, for many other targets it is 31 or 63. + + For targets that can both have either 32 or 64 bit words and number + MSB as 31, 63. Define this to be (WITH_TARGET_WORD_BITSIZE - 1) */ + +#ifndef WITH_TARGET_WORD_MSB +#define WITH_TARGET_WORD_MSB 0 +#endif + + + +/* Program environment: + + Three environments are available - UEA (user), VEA (virtual) and + OEA (perating). The former two are environment that users would + expect to see (VEA includes things like coherency and the time + base) while OEA is what an operating system expects to see. By + setting these to specific values, the build process is able to + eliminate non relevent environment code. + + STATE_ENVIRONMENT(sd) specifies which of vea or oea is required for + the current runtime. + + ALL_ENVIRONMENT is used during configuration as a value for + WITH_ENVIRONMENT to indicate the choice is runtime selectable. + The default is then USER_ENVIRONMENT [since allowing the user to choose + the default at configure time seems like featuritis and since people using + OPERATING_ENVIRONMENT have more to worry about than selecting the + default]. + ALL_ENVIRONMENT is also used to set STATE_ENVIRONMENT to the + "uninitialized" state. */ + +enum sim_environment { + ALL_ENVIRONMENT, + USER_ENVIRONMENT, + VIRTUAL_ENVIRONMENT, + OPERATING_ENVIRONMENT +}; + +/* If the simulator specified SIM_AC_OPTION_ENVIRONMENT, indicate so. */ +#ifdef WITH_ENVIRONMENT +#define SIM_HAVE_ENVIRONMENT +#endif + +/* If the simulator doesn't specify SIM_AC_OPTION_ENVIRONMENT in its + configure.in, the only supported environment is the user environment. */ +#ifndef WITH_ENVIRONMENT +#define WITH_ENVIRONMENT USER_ENVIRONMENT +#endif + +#define DEFAULT_ENVIRONMENT (WITH_ENVIRONMENT != ALL_ENVIRONMENT \ + ? WITH_ENVIRONMENT \ + : USER_ENVIRONMENT) + + +/* Callback & Modulo Memory. + + Core includes a builtin memory type (raw_memory) that is + implemented using an array. raw_memory does not require any + additional functions etc. + + Callback memory is where the core calls a core device for the data + it requires. Callback memory can be layered using priorities. + + Modulo memory is a variation on raw_memory where ADDRESS & (MODULO + - 1) is used as the index into the memory array. + + The OEA model uses callback memory for devices. + + The VEA model uses callback memory to capture `page faults'. + + BTW, while raw_memory could have been implemented as a callback, + profiling has shown that there is a biger win (at least for the + x86) in eliminating a function call for the most common + (raw_memory) case. */ + +#ifndef WITH_CALLBACK_MEMORY +#define WITH_CALLBACK_MEMORY 1 +#endif + +#ifndef WITH_MODULO_MEMORY +#define WITH_MODULO_MEMORY 0 +#endif + + + +/* Alignment: + + A processor architecture may or may not handle miss aligned + transfers. + + As alternatives: both little and big endian modes take an exception + (STRICT_ALIGNMENT); big and little endian models handle mis aligned + transfers (NONSTRICT_ALIGNMENT); or the address is forced into + alignment using a mask (FORCED_ALIGNMENT). + + Mixed alignment should be specified when the simulator needs to be + able to change the alignment requirements on the fly (eg for + bi-endian support). */ + +enum sim_alignments { + MIXED_ALIGNMENT, + NONSTRICT_ALIGNMENT, + STRICT_ALIGNMENT, + FORCED_ALIGNMENT, +}; + +extern enum sim_alignments current_alignment; + +#if !defined (WITH_ALIGNMENT) +#define WITH_ALIGNMENT 0 +#endif + +#if !defined (WITH_DEFAULT_ALIGNMENT) +#define WITH_DEFAULT_ALIGNMENT 0 /* fatal */ +#endif + + + + +#define CURRENT_ALIGNMENT (WITH_ALIGNMENT \ + ? WITH_ALIGNMENT \ + : current_alignment) + + + +/* Floating point suport: + + Should the processor trap for all floating point instructions (as + if the hardware wasn't implemented) or implement the floating point + instructions directly. */ + +#if defined (WITH_FLOATING_POINT) + +#define SOFT_FLOATING_POINT 1 +#define HARD_FLOATING_POINT 2 + +extern int current_floating_point; +#define CURRENT_FLOATING_POINT (WITH_FLOATING_POINT \ + ? WITH_FLOATING_POINT \ + : current_floating_point) + +#endif + + + +/* Engine module. + + Use the common start/stop/restart framework (sim-engine). + Simulators using the other modules but not the engine should define + WITH_ENGINE=0. */ + +#ifndef WITH_ENGINE +#define WITH_ENGINE 1 +#endif + + + +/* Debugging: + + Control the inclusion of debugging code. + Debugging is only turned on in rare circumstances [say during development] + and is not intended to be turned on otherwise. */ + +#ifndef WITH_DEBUG +#define WITH_DEBUG 0 +#endif + +/* Include the tracing code. Disabling this eliminates all tracing + code */ + +#ifndef WITH_TRACE +#define WITH_TRACE (-1) +#endif + +/* Include the profiling code. Disabling this eliminates all profiling + code. */ + +#ifndef WITH_PROFILE +#define WITH_PROFILE (-1) +#endif + + +/* include code that checks assertions scattered through out the + program */ + +#ifndef WITH_ASSERT +#define WITH_ASSERT 1 +#endif + + +/* Whether to check instructions for reserved bits being set */ + +/* #define WITH_RESERVED_BITS 1 */ + + + +/* include monitoring code */ + +#define MONITOR_INSTRUCTION_ISSUE 1 +#define MONITOR_LOAD_STORE_UNIT 2 +/* do not define WITH_MON by default */ +#define DEFAULT_WITH_MON (MONITOR_LOAD_STORE_UNIT \ + | MONITOR_INSTRUCTION_ISSUE) + + +/* Current CPU model (models are in the generated models.h include file) */ +#ifndef WITH_MODEL +#define WITH_MODEL 0 +#endif + +#define CURRENT_MODEL (WITH_MODEL \ + ? WITH_MODEL \ + : current_model) + +#ifndef WITH_DEFAULT_MODEL +#define WITH_DEFAULT_MODEL DEFAULT_MODEL +#endif + +#define MODEL_ISSUE_IGNORE (-1) +#define MODEL_ISSUE_PROCESS 1 + +#ifndef WITH_MODEL_ISSUE +#define WITH_MODEL_ISSUE 0 +#endif + +extern int current_model_issue; +#define CURRENT_MODEL_ISSUE (WITH_MODEL_ISSUE \ + ? WITH_MODEL_ISSUE \ + : current_model_issue) + + + +/* Whether or not input/output just uses stdio, or uses printf_filtered for + output, and polling input for input. */ + +#define DONT_USE_STDIO 2 +#define DO_USE_STDIO 1 + +#ifndef WITH_STDIO +#define WITH_STDIO 0 +#endif + +extern int current_stdio; +#define CURRENT_STDIO (WITH_STDIO \ + ? WITH_STDIO \ + : current_stdio) + + + +/* Specify that configured calls pass parameters in registers when the + convention is that they are placed on the stack */ + +#ifndef WITH_REGPARM +#define WITH_REGPARM 0 +#endif + +/* Specify that configured calls use an alternative calling mechanism */ + +#ifndef WITH_STDCALL +#define WITH_STDCALL 0 +#endif + + +/* Set the default state configuration, before parsing argv. */ + +extern void sim_config_default (SIM_DESC sd); + +/* Complete and verify the simulator configuration. */ + +extern SIM_RC sim_config (SIM_DESC sd); + +/* Print the simulator configuration. */ + +extern void print_sim_config (SIM_DESC sd); + + +#endif diff --git a/sim/common/sim-core.c b/sim/common/sim-core.c new file mode 100644 index 00000000000..36627a20350 --- /dev/null +++ b/sim/common/sim-core.c @@ -0,0 +1,839 @@ +/* This file is part of the program psim. + + Copyright (C) 1994-1997, Andrew Cagney + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + + +#ifndef SIM_CORE_C +#define SIM_CORE_C + +#include "sim-main.h" +#include "sim-assert.h" + +#if (WITH_HW) +#include "sim-hw.h" +#endif + +#if (WITH_DEVICES) +/* TODO: create sim/common/device.h */ +void device_error (device *me, char* message, ...); +int device_io_read_buffer(device *me, void *dest, int space, address_word addr, unsigned nr_bytes, sim_cpu *processor, sim_cia cia); +int device_io_write_buffer(device *me, const void *source, int space, address_word addr, unsigned nr_bytes, sim_cpu *processor, sim_cia cia); +#endif + +/* "core" module install handler. + + This is called via sim_module_install to install the "core" + subsystem into the simulator. */ + +#if EXTERN_SIM_CORE_P +static MODULE_INIT_FN sim_core_init; +static MODULE_UNINSTALL_FN sim_core_uninstall; +#endif + +#if EXTERN_SIM_CORE_P +SIM_RC +sim_core_install (SIM_DESC sd) +{ + SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); + + /* establish the other handlers */ + sim_module_add_uninstall_fn (sd, sim_core_uninstall); + sim_module_add_init_fn (sd, sim_core_init); + + /* establish any initial data structures - none */ + return SIM_RC_OK; +} +#endif + + +/* Uninstall the "core" subsystem from the simulator. */ + +#if EXTERN_SIM_CORE_P +static void +sim_core_uninstall (SIM_DESC sd) +{ + sim_core *core = STATE_CORE(sd); + unsigned map; + /* blow away any mappings */ + for (map = 0; map < nr_maps; map++) { + sim_core_mapping *curr = core->common.map[map].first; + while (curr != NULL) { + sim_core_mapping *tbd = curr; + curr = curr->next; + if (tbd->free_buffer != NULL) { + SIM_ASSERT(tbd->buffer != NULL); + zfree(tbd->free_buffer); + } + zfree(tbd); + } + core->common.map[map].first = NULL; + } +} +#endif + + +#if EXTERN_SIM_CORE_P +static SIM_RC +sim_core_init (SIM_DESC sd) +{ + /* Nothing to do */ + return SIM_RC_OK; +} +#endif + + + +#ifndef SIM_CORE_SIGNAL +#define SIM_CORE_SIGNAL(SD,CPU,CIA,MAP,NR_BYTES,ADDR,TRANSFER,ERROR) \ +sim_core_signal ((SD), (CPU), (CIA), (MAP), (NR_BYTES), (ADDR), (TRANSFER), (ERROR)) +#endif + +#if EXTERN_SIM_CORE_P +void +sim_core_signal (SIM_DESC sd, + sim_cpu *cpu, + sim_cia cia, + unsigned map, + int nr_bytes, + address_word addr, + transfer_type transfer, + sim_core_signals sig) +{ + const char *copy = (transfer == read_transfer ? "read" : "write"); + address_word ip = CIA_ADDR (cia); + switch (sig) + { + case sim_core_unmapped_signal: + sim_io_eprintf (sd, "core: %d byte %s to unmapped address 0x%lx at 0x%lx\n", + nr_bytes, copy, (unsigned long) addr, (unsigned long) ip); + sim_engine_halt (sd, cpu, NULL, cia, sim_stopped, SIM_SIGSEGV); + break; + case sim_core_unaligned_signal: + sim_io_eprintf (sd, "core: %d byte misaligned %s to address 0x%lx at 0x%lx\n", + nr_bytes, copy, (unsigned long) addr, (unsigned long) ip); + sim_engine_halt (sd, cpu, NULL, cia, sim_stopped, SIM_SIGBUS); + break; + default: + sim_engine_abort (sd, cpu, cia, + "sim_core_signal - internal error - bad switch"); + } +} +#endif + + +#if EXTERN_SIM_CORE_P +static sim_core_mapping * +new_sim_core_mapping (SIM_DESC sd, + int level, + int space, + address_word addr, + address_word nr_bytes, + unsigned modulo, +#if WITH_HW + struct hw *device, +#else + device *device, +#endif + void *buffer, + void *free_buffer) +{ + sim_core_mapping *new_mapping = ZALLOC(sim_core_mapping); + /* common */ + new_mapping->level = level; + new_mapping->space = space; + new_mapping->base = addr; + new_mapping->nr_bytes = nr_bytes; + new_mapping->bound = addr + (nr_bytes - 1); + if (modulo == 0) + new_mapping->mask = (unsigned) 0 - 1; + else + new_mapping->mask = modulo - 1; + new_mapping->buffer = buffer; + new_mapping->free_buffer = free_buffer; + new_mapping->device = device; + return new_mapping; +} +#endif + + +#if EXTERN_SIM_CORE_P +static void +sim_core_map_attach (SIM_DESC sd, + sim_core_map *access_map, + int level, + int space, + address_word addr, + address_word nr_bytes, + unsigned modulo, +#if WITH_HW + struct hw *client, /*callback/default*/ +#else + device *client, /*callback/default*/ +#endif + void *buffer, /*raw_memory*/ + void *free_buffer) /*raw_memory*/ +{ + /* find the insertion point for this additional mapping and then + insert */ + sim_core_mapping *next_mapping; + sim_core_mapping **last_mapping; + + SIM_ASSERT ((client == NULL) != (buffer == NULL)); + SIM_ASSERT ((client == NULL) >= (free_buffer != NULL)); + + /* actually do occasionally get a zero size map */ + if (nr_bytes == 0) + { +#if (WITH_DEVICES) + device_error(client, "called on sim_core_map_attach with size zero"); +#endif +#if (WITH_HW) + sim_hw_abort (sd, client, "called on sim_core_map_attach with size zero"); +#endif + sim_io_error (sd, "called on sim_core_map_attach with size zero"); + } + + /* find the insertion point (between last/next) */ + next_mapping = access_map->first; + last_mapping = &access_map->first; + while(next_mapping != NULL + && (next_mapping->level < level + || (next_mapping->level == level + && next_mapping->bound < addr))) + { + /* provided levels are the same */ + /* assert: next_mapping->base > all bases before next_mapping */ + /* assert: next_mapping->bound >= all bounds before next_mapping */ + last_mapping = &next_mapping->next; + next_mapping = next_mapping->next; + } + + /* check insertion point correct */ + SIM_ASSERT (next_mapping == NULL || next_mapping->level >= level); + if (next_mapping != NULL && next_mapping->level == level + && next_mapping->base < (addr + (nr_bytes - 1))) + { +#if (WITH_DEVICES) + device_error (client, "memory map %d:0x%lx..0x%lx (%ld bytes) overlaps %d:0x%lx..0x%lx (%ld bytes)", + space, + (long) addr, + (long) nr_bytes, + (long) (addr + (nr_bytes - 1)), + next_mapping->space, + (long) next_mapping->base, + (long) next_mapping->bound, + (long) next_mapping->nr_bytes); +#endif +#if WITH_HW + sim_hw_abort (sd, client, "memory map %d:0x%lx..0x%lx (%ld bytes) overlaps %d:0x%lx..0x%lx (%ld bytes)", + space, + (long) addr, + (long) nr_bytes, + (long) (addr + (nr_bytes - 1)), + next_mapping->space, + (long) next_mapping->base, + (long) next_mapping->bound, + (long) next_mapping->nr_bytes); +#endif + sim_io_error (sd, "memory map %d:0x%lx..0x%lx (%ld bytes) overlaps %d:0x%lx..0x%lx (%ld bytes)", + space, + (long) addr, + (long) nr_bytes, + (long) (addr + (nr_bytes - 1)), + next_mapping->space, + (long) next_mapping->base, + (long) next_mapping->bound, + (long) next_mapping->nr_bytes); + } + + /* create/insert the new mapping */ + *last_mapping = new_sim_core_mapping(sd, + level, + space, addr, nr_bytes, modulo, + client, buffer, free_buffer); + (*last_mapping)->next = next_mapping; +} +#endif + + +/* Attach memory or a memory mapped device to the simulator. + See sim-core.h for a full description. */ + +#if EXTERN_SIM_CORE_P +void +sim_core_attach (SIM_DESC sd, + sim_cpu *cpu, + int level, + unsigned mapmask, + int space, + address_word addr, + address_word nr_bytes, + unsigned modulo, +#if WITH_HW + struct hw *client, +#else + device *client, +#endif + void *optional_buffer) +{ + sim_core *memory = STATE_CORE(sd); + unsigned map; + void *buffer; + void *free_buffer; + + /* check for for attempt to use unimplemented per-processor core map */ + if (cpu != NULL) + sim_io_error (sd, "sim_core_map_attach - processor specific memory map not yet supported"); + + /* verify modulo memory */ + if (!WITH_MODULO_MEMORY && modulo != 0) + { +#if (WITH_DEVICES) + device_error (client, "sim_core_attach - internal error - modulo memory disabled"); +#endif +#if (WITH_HW) + sim_hw_abort (sd, client, "sim_core_attach - internal error - modulo memory disabled"); +#endif + sim_io_error (sd, "sim_core_attach - internal error - modulo memory disabled"); + } + if (client != NULL && modulo != 0) + { +#if (WITH_DEVICES) + device_error (client, "sim_core_attach - internal error - modulo and callback memory conflict"); +#endif +#if (WITH_HW) + sim_hw_abort (sd, client, "sim_core_attach - internal error - modulo and callback memory conflict"); +#endif + sim_io_error (sd, "sim_core_attach - internal error - modulo and callback memory conflict"); + } + if (modulo != 0) + { + unsigned mask = modulo - 1; + /* any zero bits */ + while (mask >= sizeof (unsigned64)) /* minimum modulo */ + { + if ((mask & 1) == 0) + mask = 0; + else + mask >>= 1; + } + if (mask != sizeof (unsigned64) - 1) + { +#if (WITH_DEVICES) + device_error (client, "sim_core_attach - internal error - modulo %lx not power of two", (long) modulo); +#endif +#if (WITH_HW) + sim_hw_abort (sd, client, "sim_core_attach - internal error - modulo %lx not power of two", (long) modulo); +#endif + sim_io_error (sd, "sim_core_attach - internal error - modulo %lx not power of two", (long) modulo); + } + } + + /* verify consistency between device and buffer */ + if (client != NULL && optional_buffer != NULL) + { +#if (WITH_DEVICES) + device_error (client, "sim_core_attach - internal error - conflicting buffer and attach arguments"); +#endif +#if (WITH_HW) + sim_hw_abort (sd, client, "sim_core_attach - internal error - conflicting buffer and attach arguments"); +#endif + sim_io_error (sd, "sim_core_attach - internal error - conflicting buffer and attach arguments"); + } + if (client == NULL) + { + if (optional_buffer == NULL) + { + int padding = (addr % sizeof (unsigned64)); + unsigned long bytes = (modulo == 0 ? nr_bytes : modulo) + padding; + free_buffer = zalloc (bytes); + buffer = (char*) free_buffer + padding; + } + else + { + buffer = optional_buffer; + free_buffer = NULL; + } + } + else + { + /* a device */ + buffer = NULL; + free_buffer = NULL; + } + + /* attach the region to all applicable access maps */ + for (map = 0; + map < nr_maps; + map++) + { + if (mapmask & (1 << map)) + { + sim_core_map_attach (sd, &memory->common.map[map], + level, space, addr, nr_bytes, modulo, + client, buffer, free_buffer); + free_buffer = NULL; + } + } + + /* Just copy this map to each of the processor specific data structures. + FIXME - later this will be replaced by true processor specific + maps. */ + { + int i; + for (i = 0; i < MAX_NR_PROCESSORS; i++) + { + CPU_CORE (STATE_CPU (sd, i))->common = STATE_CORE (sd)->common; + } + } +} +#endif + + +/* Remove any memory reference related to this address */ +#if EXTERN_SIM_CORE_P +static void +sim_core_map_detach (SIM_DESC sd, + sim_core_map *access_map, + int level, + int space, + address_word addr) +{ + sim_core_mapping **entry; + for (entry = &access_map->first; + (*entry) != NULL; + entry = &(*entry)->next) + { + if ((*entry)->base == addr + && (*entry)->level == level + && (*entry)->space == space) + { + sim_core_mapping *dead = (*entry); + (*entry) = dead->next; + if (dead->free_buffer != NULL) + zfree (dead->free_buffer); + zfree (dead); + return; + } + } +} +#endif + +#if EXTERN_SIM_CORE_P +void +sim_core_detach (SIM_DESC sd, + sim_cpu *cpu, + int level, + int address_space, + address_word addr) +{ + sim_core *memory = STATE_CORE (sd); + unsigned map; + for (map = 0; map < nr_maps; map++) + { + sim_core_map_detach (sd, &memory->common.map[map], + level, address_space, addr); + } + /* Just copy this update to each of the processor specific data + structures. FIXME - later this will be replaced by true + processor specific maps. */ + { + int i; + for (i = 0; i < MAX_NR_PROCESSORS; i++) + { + CPU_CORE (STATE_CPU (sd, i))->common = STATE_CORE (sd)->common; + } + } +} +#endif + + +STATIC_INLINE_SIM_CORE\ +(sim_core_mapping *) +sim_core_find_mapping(sim_core_common *core, + unsigned map, + address_word addr, + unsigned nr_bytes, + transfer_type transfer, + int abort, /*either 0 or 1 - hint to inline/-O */ + sim_cpu *cpu, /* abort => cpu != NULL */ + sim_cia cia) +{ + sim_core_mapping *mapping = core->map[map].first; + ASSERT ((addr & (nr_bytes - 1)) == 0); /* must be aligned */ + ASSERT ((addr + (nr_bytes - 1)) >= addr); /* must not wrap */ + ASSERT (!abort || cpu != NULL); /* abort needs a non null CPU */ + while (mapping != NULL) + { + if (addr >= mapping->base + && (addr + (nr_bytes - 1)) <= mapping->bound) + return mapping; + mapping = mapping->next; + } + if (abort) + { + SIM_CORE_SIGNAL (CPU_STATE (cpu), cpu, cia, map, nr_bytes, addr, transfer, + sim_core_unmapped_signal); + } + return NULL; +} + + +STATIC_INLINE_SIM_CORE\ +(void *) +sim_core_translate (sim_core_mapping *mapping, + address_word addr) +{ + if (WITH_MODULO_MEMORY) + return (void *)((unsigned8 *) mapping->buffer + + ((addr - mapping->base) & mapping->mask)); + else + return (void *)((unsigned8 *) mapping->buffer + + addr - mapping->base); +} + + +#if EXTERN_SIM_CORE_P +unsigned +sim_core_read_buffer (SIM_DESC sd, + sim_cpu *cpu, + unsigned map, + void *buffer, + address_word addr, + unsigned len) +{ + sim_core_common *core = (cpu == NULL ? &STATE_CORE (sd)->common : &CPU_CORE (cpu)->common); + unsigned count = 0; + while (count < len) + { + unsigned_word raddr = addr + count; + sim_core_mapping *mapping = + sim_core_find_mapping (core, map, + raddr, /*nr-bytes*/1, + read_transfer, + 0 /*dont-abort*/, NULL, NULL_CIA); + if (mapping == NULL) + break; +#if (WITH_DEVICES) + if (mapping->device != NULL) + { + int nr_bytes = len - count; + if (raddr + nr_bytes - 1> mapping->bound) + nr_bytes = mapping->bound - raddr + 1; + if (device_io_read_buffer (mapping->device, + (unsigned_1*)buffer + count, + mapping->space, + raddr, + nr_bytes, + cpu, + CIA_GET (cpu)) != nr_bytes) + break; + count += nr_bytes; + continue; + } +#endif +#if (WITH_HW) + if (mapping->device != NULL) + { + int nr_bytes = len - count; + if (raddr + nr_bytes - 1> mapping->bound) + nr_bytes = mapping->bound - raddr + 1; + if (sim_hw_io_read_buffer (sd, mapping->device, + (unsigned_1*)buffer + count, + mapping->space, + raddr, + nr_bytes) != nr_bytes) + break; + count += nr_bytes; + continue; + } +#endif + ((unsigned_1*)buffer)[count] = + *(unsigned_1*)sim_core_translate(mapping, raddr); + count += 1; + } + return count; +} +#endif + + +#if EXTERN_SIM_CORE_P +unsigned +sim_core_write_buffer (SIM_DESC sd, + sim_cpu *cpu, + unsigned map, + const void *buffer, + address_word addr, + unsigned len) +{ + sim_core_common *core = (cpu == NULL ? &STATE_CORE (sd)->common : &CPU_CORE (cpu)->common); + unsigned count = 0; + while (count < len) + { + unsigned_word raddr = addr + count; + sim_core_mapping *mapping = + sim_core_find_mapping (core, map, + raddr, /*nr-bytes*/1, + write_transfer, + 0 /*dont-abort*/, NULL, NULL_CIA); + if (mapping == NULL) + break; +#if (WITH_DEVICES) + if (WITH_CALLBACK_MEMORY + && mapping->device != NULL) + { + int nr_bytes = len - count; + if (raddr + nr_bytes - 1 > mapping->bound) + nr_bytes = mapping->bound - raddr + 1; + if (device_io_write_buffer (mapping->device, + (unsigned_1*)buffer + count, + mapping->space, + raddr, + nr_bytes, + cpu, + CIA_GET(cpu)) != nr_bytes) + break; + count += nr_bytes; + continue; + } +#endif +#if (WITH_HW) + if (WITH_CALLBACK_MEMORY + && mapping->device != NULL) + { + int nr_bytes = len - count; + if (raddr + nr_bytes - 1 > mapping->bound) + nr_bytes = mapping->bound - raddr + 1; + if (sim_hw_io_write_buffer (sd, mapping->device, + (unsigned_1*)buffer + count, + mapping->space, + raddr, + nr_bytes) != nr_bytes) + break; + count += nr_bytes; + continue; + } +#endif + *(unsigned_1*)sim_core_translate(mapping, raddr) = + ((unsigned_1*)buffer)[count]; + count += 1; + } + return count; +} +#endif + + +#if EXTERN_SIM_CORE_P +void +sim_core_set_xor (SIM_DESC sd, + sim_cpu *cpu, + int is_xor) +{ + /* set up the XOR map if required. */ + if (WITH_XOR_ENDIAN) { + { + sim_core *core = STATE_CORE (sd); + sim_cpu_core *cpu_core = (cpu != NULL ? CPU_CORE (cpu) : NULL); + if (cpu_core != NULL) + { + int i = 1; + unsigned mask; + if (is_xor) + mask = WITH_XOR_ENDIAN - 1; + else + mask = 0; + while (i - 1 < WITH_XOR_ENDIAN) + { + cpu_core->xor[i-1] = mask; + mask = (mask << 1) & (WITH_XOR_ENDIAN - 1); + i = (i << 1); + } + } + else + { + if (is_xor) + core->byte_xor = WITH_XOR_ENDIAN - 1; + else + core->byte_xor = 0; + } + } + } + else { + if (is_xor) + sim_engine_abort (sd, NULL, NULL_CIA, + "Attempted to enable xor-endian mode when permenantly disabled."); + } +} +#endif + + +#if EXTERN_SIM_CORE_P +static void +reverse_n (unsigned_1 *dest, + const unsigned_1 *src, + int nr_bytes) +{ + int i; + for (i = 0; i < nr_bytes; i++) + { + dest [nr_bytes - i - 1] = src [i]; + } +} +#endif + + +#if EXTERN_SIM_CORE_P +unsigned +sim_core_xor_read_buffer (SIM_DESC sd, + sim_cpu *cpu, + unsigned map, + void *buffer, + address_word addr, + unsigned nr_bytes) +{ + address_word byte_xor = (cpu == NULL ? STATE_CORE (sd)->byte_xor : CPU_CORE (cpu)->xor[0]); + if (!WITH_XOR_ENDIAN || !byte_xor) + return sim_core_read_buffer (sd, cpu, map, buffer, addr, nr_bytes); + else + /* only break up transfers when xor-endian is both selected and enabled */ + { + unsigned_1 x[WITH_XOR_ENDIAN + 1]; /* +1 to avoid zero-sized array */ + unsigned nr_transfered = 0; + address_word start = addr; + unsigned nr_this_transfer = (WITH_XOR_ENDIAN - (addr & ~(WITH_XOR_ENDIAN - 1))); + address_word stop; + /* initial and intermediate transfers are broken when they cross + an XOR endian boundary */ + while (nr_transfered + nr_this_transfer < nr_bytes) + /* initial/intermediate transfers */ + { + /* since xor-endian is enabled stop^xor defines the start + address of the transfer */ + stop = start + nr_this_transfer - 1; + SIM_ASSERT (start <= stop); + SIM_ASSERT ((stop ^ byte_xor) <= (start ^ byte_xor)); + if (sim_core_read_buffer (sd, cpu, map, x, stop ^ byte_xor, nr_this_transfer) + != nr_this_transfer) + return nr_transfered; + reverse_n (&((unsigned_1*)buffer)[nr_transfered], x, nr_this_transfer); + nr_transfered += nr_this_transfer; + nr_this_transfer = WITH_XOR_ENDIAN; + start = stop + 1; + } + /* final transfer */ + nr_this_transfer = nr_bytes - nr_transfered; + stop = start + nr_this_transfer - 1; + SIM_ASSERT (stop == (addr + nr_bytes - 1)); + if (sim_core_read_buffer (sd, cpu, map, x, stop ^ byte_xor, nr_this_transfer) + != nr_this_transfer) + return nr_transfered; + reverse_n (&((unsigned_1*)buffer)[nr_transfered], x, nr_this_transfer); + return nr_bytes; + } +} +#endif + + +#if EXTERN_SIM_CORE_P +unsigned +sim_core_xor_write_buffer (SIM_DESC sd, + sim_cpu *cpu, + unsigned map, + const void *buffer, + address_word addr, + unsigned nr_bytes) +{ + address_word byte_xor = (cpu == NULL ? STATE_CORE (sd)->byte_xor : CPU_CORE (cpu)->xor[0]); + if (!WITH_XOR_ENDIAN || !byte_xor) + return sim_core_write_buffer (sd, cpu, map, buffer, addr, nr_bytes); + else + /* only break up transfers when xor-endian is both selected and enabled */ + { + unsigned_1 x[WITH_XOR_ENDIAN + 1]; /* +1 to avoid zero sized array */ + unsigned nr_transfered = 0; + address_word start = addr; + unsigned nr_this_transfer = (WITH_XOR_ENDIAN - (addr & ~(WITH_XOR_ENDIAN - 1))); + address_word stop; + /* initial and intermediate transfers are broken when they cross + an XOR endian boundary */ + while (nr_transfered + nr_this_transfer < nr_bytes) + /* initial/intermediate transfers */ + { + /* since xor-endian is enabled stop^xor defines the start + address of the transfer */ + stop = start + nr_this_transfer - 1; + SIM_ASSERT (start <= stop); + SIM_ASSERT ((stop ^ byte_xor) <= (start ^ byte_xor)); + reverse_n (x, &((unsigned_1*)buffer)[nr_transfered], nr_this_transfer); + if (sim_core_read_buffer (sd, cpu, map, x, stop ^ byte_xor, nr_this_transfer) + != nr_this_transfer) + return nr_transfered; + nr_transfered += nr_this_transfer; + nr_this_transfer = WITH_XOR_ENDIAN; + start = stop + 1; + } + /* final transfer */ + nr_this_transfer = nr_bytes - nr_transfered; + stop = start + nr_this_transfer - 1; + SIM_ASSERT (stop == (addr + nr_bytes - 1)); + reverse_n (x, &((unsigned_1*)buffer)[nr_transfered], nr_this_transfer); + if (sim_core_read_buffer (sd, cpu, map, x, stop ^ byte_xor, nr_this_transfer) + != nr_this_transfer) + return nr_transfered; + return nr_bytes; + } +} +#endif + + + +/* define the read/write 1/2/4/8/16/word functions */ + +#define N 16 +#include "sim-n-core.h" + +#define N 8 +#include "sim-n-core.h" + +#define N 7 +#define M 8 +#include "sim-n-core.h" + +#define N 6 +#define M 8 +#include "sim-n-core.h" + +#define N 5 +#define M 8 +#include "sim-n-core.h" + +#define N 4 +#include "sim-n-core.h" + +#define N 3 +#define M 4 +#include "sim-n-core.h" + +#define N 2 +#include "sim-n-core.h" + +#define N 1 +#include "sim-n-core.h" + +#endif diff --git a/sim/common/sim-core.h b/sim/common/sim-core.h new file mode 100644 index 00000000000..7bf15a3b48d --- /dev/null +++ b/sim/common/sim-core.h @@ -0,0 +1,343 @@ +/* This file is part of the program psim. + + Copyright (C) 1994-1997, Andrew Cagney + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + + +#ifndef SIM_CORE_H +#define SIM_CORE_H + + +/* core signals (error conditions) + Define SIM_CORE_SIGNAL to catch these signals - see sim-core.c for + details. */ + +typedef enum { + sim_core_unmapped_signal, + sim_core_unaligned_signal, + nr_sim_core_signals, +} sim_core_signals; + +/* Type of SIM_CORE_SIGNAL handler. */ +typedef void (SIM_CORE_SIGNAL_FN) + (SIM_DESC sd, sim_cpu *cpu, sim_cia cia, unsigned map, int nr_bytes, + address_word addr, transfer_type transfer, sim_core_signals sig); + +extern SIM_CORE_SIGNAL_FN sim_core_signal; + + +/* basic types */ + +typedef struct _sim_core_mapping sim_core_mapping; +struct _sim_core_mapping { + /* common */ + int level; + int space; + unsigned_word base; + unsigned_word bound; + unsigned_word nr_bytes; + unsigned mask; + /* memory map */ + void *free_buffer; + void *buffer; + /* callback map */ +#if (WITH_HW) + struct hw *device; +#else + device *device; +#endif + /* tracing */ + int trace; + /* growth */ + sim_core_mapping *next; +}; + +typedef struct _sim_core_map sim_core_map; +struct _sim_core_map { + sim_core_mapping *first; +}; + + +typedef struct _sim_core_common { + sim_core_map map[nr_maps]; +} sim_core_common; + + +/* Main core structure */ + +typedef struct _sim_core sim_core; +struct _sim_core { + sim_core_common common; + address_word byte_xor; /* apply xor universally */ +}; + + +/* Per CPU distributed component of the core. At present this is + mostly a clone of the global core data structure. */ + +typedef struct _sim_cpu_core { + sim_core_common common; + address_word xor[WITH_XOR_ENDIAN + 1]; /* +1 to avoid zero-sized array */ +} sim_cpu_core; + + +/* Install the "core" module. */ + +extern SIM_RC sim_core_install (SIM_DESC sd); + + + +/* Create a memory region within the core. + + CPU - when non NULL, specifes the single processor that the memory + space is to be attached to. (INIMPLEMENTED). + + LEVEL - specifies the ordering of the memory region. Lower regions + are searched first. Within a level, memory regions can not + overlap. + + MAPMASK - Bitmask specifying the memory maps that the region is to + be attached to. Typically the enums sim-basics.h:access_* are used. + + ADDRESS_SPACE - For device regions, a MAP:ADDRESS pair is + translated into ADDRESS_SPACE:OFFSET before being passed to the + client device. + + MODULO - when the simulator has been configured WITH_MODULO support + and is greater than zero, specifies that accesses to the region + [ADDR .. ADDR+NR_BYTES) should be mapped onto the sub region [ADDR + .. ADDR+MODULO). The modulo value must be a power of two. + + DEVICE - When non NULL, indicates that this is a callback memory + space and specified device's memory callback handler should be + called. + + OPTIONAL_BUFFER - when non NULL, specifies the buffer to use for + data read & written to the region. Normally a more efficient + internal structure is used. It is assumed that buffer is allocated + such that the byte alignmed of OPTIONAL_BUFFER matches ADDR vis + (OPTIONAL_BUFFER % 8) == (ADDR % 8)). It is defined to be a sub-optimal + hook that allows clients to do nasty things that the interface doesn't + accomodate. */ + +extern void sim_core_attach +(SIM_DESC sd, + sim_cpu *cpu, + int level, + unsigned mapmask, + int address_space, + address_word addr, + address_word nr_bytes, + unsigned modulo, +#if (WITH_HW) + struct hw *client, +#else + device *client, +#endif + void *optional_buffer); + + +/* Delete a memory section within the core. + + */ + +extern void sim_core_detach +(SIM_DESC sd, + sim_cpu *cpu, + int level, + int address_space, + address_word addr); + + +/* Variable sized read/write + + Transfer a variable sized block of raw data between the host and + target. Should any problems occure, the number of bytes + successfully transfered is returned. + + No host/target byte endian conversion is performed. No xor-endian + conversion is performed. + + If CPU argument, when non NULL, specifies the processor specific + address map that is to be used in the transfer. */ + + +extern unsigned sim_core_read_buffer +(SIM_DESC sd, + sim_cpu *cpu, + unsigned map, + void *buffer, + address_word addr, + unsigned nr_bytes); + +extern unsigned sim_core_write_buffer +(SIM_DESC sd, + sim_cpu *cpu, + unsigned map, + const void *buffer, + address_word addr, + unsigned nr_bytes); + + + +/* Configure the core's XOR endian transfer mode. Only applicable + when WITH_XOR_ENDIAN is enabled. + + Targets suporting XOR endian, shall notify the core of any changes + in state via this call. + + The CPU argument, when non NULL, specifes the single processor that + the xor-endian configuration is to be applied to. */ + +extern void sim_core_set_xor +(SIM_DESC sd, + sim_cpu *cpu, + int is_xor); + + +/* XOR version of variable sized read/write. + + Transfer a variable sized block of raw data between the host and + target. Should any problems occure, the number of bytes + successfully transfered is returned. + + No host/target byte endian conversion is performed. If applicable + (WITH_XOR_ENDIAN and xor-endian set), xor-endian conversion *is* + performed. + + If CPU argument, when non NULL, specifies the processor specific + address map that is to be used in the transfer. */ + +extern unsigned sim_core_xor_read_buffer +(SIM_DESC sd, + sim_cpu *cpu, + unsigned map, + void *buffer, + address_word addr, + unsigned nr_bytes); + +extern unsigned sim_core_xor_write_buffer +(SIM_DESC sd, + sim_cpu *cpu, + unsigned map, + const void *buffer, + address_word addr, + unsigned nr_bytes); + + + +/* Fixed sized, processor oriented, read/write. + + Transfer a fixed amout of memory between the host and target. The + data transfered is translated from/to host to/from target byte + order (including xor endian). Should the transfer fail, the + operation shall abort (no return). + + ALIGNED assumes yhat the specified ADDRESS is correctly alligned + for an N byte transfer (no alignment checks are made). Passing an + incorrectly aligned ADDRESS is erroneous. + + UNALIGNED checks/modifies the ADDRESS according to the requirements + of an N byte transfer. Action, as defined by WITH_ALIGNMENT, being + taken should the check fail. + + MISSALIGNED transfers the data regardless. + + Misaligned xor-endian accesses are broken into a sequence of + transfers each <= WITH_XOR_ENDIAN bytes */ + + +#define DECLARE_SIM_CORE_WRITE_N(ALIGNMENT,N,M) \ +INLINE_SIM_CORE\ +(void) sim_core_write_##ALIGNMENT##_##N \ +(sim_cpu *cpu, \ + sim_cia cia, \ + unsigned map, \ + address_word addr, \ + unsigned_##M val); + +DECLARE_SIM_CORE_WRITE_N(aligned,1,1) +DECLARE_SIM_CORE_WRITE_N(aligned,2,2) +DECLARE_SIM_CORE_WRITE_N(aligned,4,4) +DECLARE_SIM_CORE_WRITE_N(aligned,8,8) +DECLARE_SIM_CORE_WRITE_N(aligned,16,16) + +#define sim_core_write_unaligned_1 sim_core_write_aligned_1 +DECLARE_SIM_CORE_WRITE_N(unaligned,2,2) +DECLARE_SIM_CORE_WRITE_N(unaligned,4,4) +DECLARE_SIM_CORE_WRITE_N(unaligned,8,8) +DECLARE_SIM_CORE_WRITE_N(unaligned,16,16) + +DECLARE_SIM_CORE_WRITE_N(misaligned,3,4) +DECLARE_SIM_CORE_WRITE_N(misaligned,5,8) +DECLARE_SIM_CORE_WRITE_N(misaligned,6,8) +DECLARE_SIM_CORE_WRITE_N(misaligned,7,8) + +#define sim_core_write_1 sim_core_write_aligned_1 +#define sim_core_write_2 sim_core_write_aligned_2 +#define sim_core_write_4 sim_core_write_aligned_4 +#define sim_core_write_8 sim_core_write_aligned_8 +#define sim_core_write_16 sim_core_write_aligned_16 + +#define sim_core_write_unaligned_word XCONCAT2(sim_core_write_unaligned_,WITH_TARGET_WORD_BITSIZE) +#define sim_core_write_aligned_word XCONCAT2(sim_core_write_aligned_,WITH_TARGET_WORD_BITSIZE) +#define sim_core_write_word XCONCAT2(sim_core_write_,WITH_TARGET_WORD_BITSIZE) + +#undef DECLARE_SIM_CORE_WRITE_N + + +#define DECLARE_SIM_CORE_READ_N(ALIGNMENT,N,M) \ +INLINE_SIM_CORE\ +(unsigned_##M) sim_core_read_##ALIGNMENT##_##N \ +(sim_cpu *cpu, \ + sim_cia cia, \ + unsigned map, \ + address_word addr); + +DECLARE_SIM_CORE_READ_N(aligned,1,1) +DECLARE_SIM_CORE_READ_N(aligned,2,2) +DECLARE_SIM_CORE_READ_N(aligned,4,4) +DECLARE_SIM_CORE_READ_N(aligned,8,8) +DECLARE_SIM_CORE_READ_N(aligned,16,16) + +#define sim_core_read_unaligned_1 sim_core_read_aligned_1 +DECLARE_SIM_CORE_READ_N(unaligned,2,2) +DECLARE_SIM_CORE_READ_N(unaligned,4,4) +DECLARE_SIM_CORE_READ_N(unaligned,8,8) +DECLARE_SIM_CORE_READ_N(unaligned,16,16) + +DECLARE_SIM_CORE_READ_N(misaligned,3,4) +DECLARE_SIM_CORE_READ_N(misaligned,5,8) +DECLARE_SIM_CORE_READ_N(misaligned,6,8) +DECLARE_SIM_CORE_READ_N(misaligned,7,8) + + +#define sim_core_read_1 sim_core_read_aligned_1 +#define sim_core_read_2 sim_core_read_aligned_2 +#define sim_core_read_4 sim_core_read_aligned_4 +#define sim_core_read_8 sim_core_read_aligned_8 +#define sim_core_read_16 sim_core_read_aligned_16 + +#define sim_core_read_unaligned_word XCONCAT2(sim_core_read_unaligned_,WITH_TARGET_WORD_BITSIZE) +#define sim_core_read_aligned_word XCONCAT2(sim_core_read_aligned_,WITH_TARGET_WORD_BITSIZE) +#define sim_core_read_word XCONCAT2(sim_core_read_,WITH_TARGET_WORD_BITSIZE) + +#undef DECLARE_SIM_CORE_READ_N + + +#endif diff --git a/sim/common/sim-cpu.c b/sim/common/sim-cpu.c new file mode 100644 index 00000000000..0e6d52c1dd1 --- /dev/null +++ b/sim/common/sim-cpu.c @@ -0,0 +1,80 @@ +/* CPU support. + Copyright (C) 1998 Free Software Foundation, Inc. + Contributed by Cygnus Solutions. + +This file is part of GDB, the GNU debugger. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "sim-main.h" +#include "bfd.h" + +/* Allocate space for all cpus in the simulator. + Space for the cpu must currently exist prior to parsing ARGV. + EXTRA_BYTES is additional space to allocate for the sim_cpu struct. */ +/* ??? wip. better solution must wait. */ + +SIM_RC +sim_cpu_alloc_all (SIM_DESC sd, int ncpus, int extra_bytes) +{ + int c; + + for (c = 0; c < ncpus; ++c) + STATE_CPU (sd, c) = sim_cpu_alloc (sd, extra_bytes); + return SIM_RC_OK; +} + +/* Allocate space for a cpu object. + EXTRA_BYTES is additional space to allocate for the sim_cpu struct. */ + +sim_cpu * +sim_cpu_alloc (SIM_DESC sd, int extra_bytes) +{ + return zalloc (sizeof (sim_cpu) + extra_bytes); +} + +/* Free all resources held by all cpus. */ + +void +sim_cpu_free_all (SIM_DESC sd) +{ + int c; + + for (c = 0; c < MAX_NR_PROCESSORS; ++c) + if (STATE_CPU (sd, c)) + sim_cpu_free (STATE_CPU (sd, c)); +} + +/* Free all resources used by CPU. */ + +void +sim_cpu_free (sim_cpu *cpu) +{ + zfree (cpu); +} + +/* PC utilities. */ + +sim_cia +sim_pc_get (sim_cpu *cpu) +{ + return (* CPU_PC_FETCH (cpu)) (cpu); +} + +void +sim_pc_set (sim_cpu *cpu, sim_cia newval) +{ + (* CPU_PC_STORE (cpu)) (cpu, newval); +} diff --git a/sim/common/sim-cpu.h b/sim/common/sim-cpu.h new file mode 100644 index 00000000000..069fead4808 --- /dev/null +++ b/sim/common/sim-cpu.h @@ -0,0 +1,152 @@ +/* CPU support. + Copyright (C) 1998 Free Software Foundation, Inc. + Contributed by Cygnus Solutions. + +This file is part of GDB, the GNU debugger. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* This file is intended to be included by sim-base.h. + + This file provides an interface between the simulator framework and + the selected cpu. */ + +#ifndef SIM_CPU_H +#define SIM_CPU_H + +/* Type of function to return an insn name. */ +typedef const char * (CPU_INSN_NAME_FN) (sim_cpu *, int); + +/* Types for register access functions. + These routines implement the sim_{fetch,store}_register interface. */ +typedef int (CPUREG_FETCH_FN) (sim_cpu *, int, unsigned char *, int); +typedef int (CPUREG_STORE_FN) (sim_cpu *, int, unsigned char *, int); + +/* Types for PC access functions. + Some simulators require a functional interface to access the program + counter [a macro is insufficient as the PC is kept in a cpu-specific part + of the sim_cpu struct]. */ +typedef sim_cia (PC_FETCH_FN) (sim_cpu *); +typedef void (PC_STORE_FN) (sim_cpu *, sim_cia); + +/* Pseudo baseclass for each cpu. */ + +typedef struct { + + /* Backlink to main state struct. */ + SIM_DESC state; +#define CPU_STATE(cpu) ((cpu)->base.state) + + /* Processor index within the SD_DESC */ + int index; +#define CPU_INDEX(cpu) ((cpu)->base.index) + + /* The name of the cpu. */ + const char *name; +#define CPU_NAME(cpu) ((cpu)->base.name) + + /* Options specific to this cpu. */ + struct option_list *options; +#define CPU_OPTIONS(cpu) ((cpu)->base.options) + + /* Processor specific core data */ + sim_cpu_core core; +#define CPU_CORE(cpu) (& (cpu)->base.core) + + /* Number of instructions (used to iterate over CPU_INSN_NAME). */ + unsigned int max_insns; +#define CPU_MAX_INSNS(cpu) ((cpu)->base.max_insns) + + /* Function to return the name of an insn. */ + CPU_INSN_NAME_FN *insn_name; +#define CPU_INSN_NAME(cpu) ((cpu)->base.insn_name) + + /* Trace data. See sim-trace.h. */ + TRACE_DATA trace_data; +#define CPU_TRACE_DATA(cpu) (& (cpu)->base.trace_data) + + /* Maximum number of debuggable entities. + This debugging is not intended for normal use. + It is only enabled when the simulator is configured with --with-debug + which shouldn't normally be specified. */ +#ifndef MAX_DEBUG_VALUES +#define MAX_DEBUG_VALUES 4 +#endif + + /* Boolean array of specified debugging flags. */ + char debug_flags[MAX_DEBUG_VALUES]; +#define CPU_DEBUG_FLAGS(cpu) ((cpu)->base.debug_flags) + /* Standard values. */ +#define DEBUG_INSN_IDX 0 +#define DEBUG_NEXT_IDX 2 /* simulator specific debug bits begin here */ + + /* Debugging output goes to this or stderr if NULL. + We can't store `stderr' here as stderr goes through a callback. */ + FILE *debug_file; +#define CPU_DEBUG_FILE(cpu) ((cpu)->base.debug_file) + + /* Profile data. See sim-profile.h. */ + PROFILE_DATA profile_data; +#define CPU_PROFILE_DATA(cpu) (& (cpu)->base.profile_data) + +#ifdef SIM_HAVE_MODEL + /* Machine tables for this cpu. See sim-model.h. */ + const MACH *mach; +#define CPU_MACH(cpu) ((cpu)->base.mach) + /* The selected model. */ + const MODEL *model; +#define CPU_MODEL(cpu) ((cpu)->base.model) + /* Model data (profiling state, etc.). */ + void *model_data; +#define CPU_MODEL_DATA(cpu) ((cpu)->base.model_data) +#endif + + /* Routines to fetch/store registers. */ + CPUREG_FETCH_FN *reg_fetch; +#define CPU_REG_FETCH(c) ((c)->base.reg_fetch) + CPUREG_STORE_FN *reg_store; +#define CPU_REG_STORE(c) ((c)->base.reg_store) + PC_FETCH_FN *pc_fetch; +#define CPU_PC_FETCH(c) ((c)->base.pc_fetch) + PC_STORE_FN *pc_store; +#define CPU_PC_STORE(c) ((c)->base.pc_store) + +} sim_cpu_base; + +/* Create all cpus. */ +extern SIM_RC sim_cpu_alloc_all (SIM_DESC, int, int); +/* Create a cpu. */ +extern sim_cpu *sim_cpu_alloc (SIM_DESC, int); +/* Release resources held by all cpus. */ +extern void sim_cpu_free_all (SIM_DESC); +/* Release resources held by a cpu. */ +extern void sim_cpu_free (sim_cpu *); + +/* Return a pointer to the cpu data for CPU_NAME, or NULL if not found. */ +extern sim_cpu *sim_cpu_lookup (SIM_DESC, const char *); + +/* Return prefix to use in cpu specific messages. */ +extern const char *sim_cpu_msg_prefix (sim_cpu *); +/* Cover fn to sim_io_eprintf. */ +extern void sim_io_eprintf_cpu (sim_cpu *, const char *, ...); + +/* Get/set a pc value. */ +#define CPU_PC_GET(cpu) ((* CPU_PC_FETCH (cpu)) (cpu)) +#define CPU_PC_SET(cpu,newval) ((* CPU_PC_STORE (cpu)) ((cpu), (newval))) +/* External interface to accessing the pc. */ +sim_cia sim_pc_get (sim_cpu *); +void sim_pc_set (sim_cpu *, sim_cia); + +#endif /* SIM_CPU_H */ diff --git a/sim/common/sim-endian.c b/sim/common/sim-endian.c new file mode 100644 index 00000000000..36820284ffd --- /dev/null +++ b/sim/common/sim-endian.c @@ -0,0 +1,128 @@ +/* This file is part of the program psim. + + Copyright (C) 1994-1995, Andrew Cagney + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + + +#ifndef _SIM_ENDIAN_C_ +#define _SIM_ENDIAN_C_ + +#include "sim-basics.h" +#include "sim-assert.h" +#include "sim-io.h" + + +#if !defined(_SWAP_1) +#define _SWAP_1(SET,RAW) SET (RAW) +#endif + +#if !defined(_SWAP_2) && (WITH_HOST_BYTE_ORDER == LITTLE_ENDIAN) && defined(htons) +#define _SWAP_2(SET,RAW) SET htons (RAW) +#endif + +#ifndef _SWAP_2 +#define _SWAP_2(SET,RAW) SET (((RAW) >> 8) | ((RAW) << 8)) +#endif + +#if !defined(_SWAP_4) && (WITH_HOST_BYTE_ORDER == LITTLE_ENDIAN) && defined(htonl) +#define _SWAP_4(SET,RAW) SET htonl (RAW) +#endif + +#ifndef _SWAP_4 +#define _SWAP_4(SET,RAW) SET (((RAW) << 24) | (((RAW) & 0xff00) << 8) | (((RAW) & 0xff0000) >> 8) | ((RAW) >> 24)) +#endif + +#ifndef _SWAP_8 +#define _SWAP_8(SET,RAW) \ + union { unsigned_8 dword; unsigned_4 words[2]; } in, out; \ + in.dword = RAW; \ + _SWAP_4 (out.words[0] =, in.words[1]); \ + _SWAP_4 (out.words[1] =, in.words[0]); \ + SET out.dword; +#endif + +#ifndef _SWAP_16 +#define _SWAP_16(SET,RAW) \ + union { unsigned_16 word; unsigned_4 words[4]; } in, out; \ + in.word = (RAW); \ + _SWAP_4 (out.words[0] =, in.words[3]); \ + _SWAP_4 (out.words[1] =, in.words[2]); \ + _SWAP_4 (out.words[2] =, in.words[1]); \ + _SWAP_4 (out.words[3] =, in.words[0]); \ + SET out.word; +#endif + + +#define N 1 +#include "sim-n-endian.h" +#undef N + +#define N 2 +#include "sim-n-endian.h" +#undef N + +#define N 4 +#include "sim-n-endian.h" +#undef N + +#define N 8 +#include "sim-n-endian.h" +#undef N + +#define N 16 +#include "sim-n-endian.h" +#undef N + + +INLINE_SIM_ENDIAN\ +(unsigned_8) +sim_endian_split_16 (unsigned_16 word, int w) +{ + if (CURRENT_HOST_BYTE_ORDER == LITTLE_ENDIAN) + { + return word.a[1 - w]; + } + else + { + return word.a[w]; + } +} + + +INLINE_SIM_ENDIAN\ +(unsigned_16) +sim_endian_join_16 (unsigned_8 h, unsigned_8 l) + +{ + unsigned_16 word; + if (CURRENT_HOST_BYTE_ORDER == LITTLE_ENDIAN) + { + word.a[0] = l; + word.a[1] = h; + } + else + { + word.a[0] = h; + word.a[1] = l; + } + return word; +} + + + +#endif /* _SIM_ENDIAN_C_ */ diff --git a/sim/common/sim-endian.h b/sim/common/sim-endian.h new file mode 100644 index 00000000000..d733c82056f --- /dev/null +++ b/sim/common/sim-endian.h @@ -0,0 +1,414 @@ +/* This file is part of the program psim. + + Copyright (C) 1994-1995, Andrew Cagney + Copyright (C) 1997, Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + + +#ifndef _SIM_ENDIAN_H_ +#define _SIM_ENDIAN_H_ + + +/* C byte conversion functions */ + +INLINE_SIM_ENDIAN(unsigned_1) endian_h2t_1(unsigned_1 x); +INLINE_SIM_ENDIAN(unsigned_2) endian_h2t_2(unsigned_2 x); +INLINE_SIM_ENDIAN(unsigned_4) endian_h2t_4(unsigned_4 x); +INLINE_SIM_ENDIAN(unsigned_8) endian_h2t_8(unsigned_8 x); +INLINE_SIM_ENDIAN(unsigned_16) endian_h2t_16(unsigned_16 x); + +INLINE_SIM_ENDIAN(unsigned_1) endian_t2h_1(unsigned_1 x); +INLINE_SIM_ENDIAN(unsigned_2) endian_t2h_2(unsigned_2 x); +INLINE_SIM_ENDIAN(unsigned_4) endian_t2h_4(unsigned_4 x); +INLINE_SIM_ENDIAN(unsigned_8) endian_t2h_8(unsigned_8 x); +INLINE_SIM_ENDIAN(unsigned_16) endian_t2h_16(unsigned_16 x); + +INLINE_SIM_ENDIAN(unsigned_1) swap_1(unsigned_1 x); +INLINE_SIM_ENDIAN(unsigned_2) swap_2(unsigned_2 x); +INLINE_SIM_ENDIAN(unsigned_4) swap_4(unsigned_4 x); +INLINE_SIM_ENDIAN(unsigned_8) swap_8(unsigned_8 x); +INLINE_SIM_ENDIAN(unsigned_16) swap_16(unsigned_16 x); + +INLINE_SIM_ENDIAN(unsigned_1) endian_h2be_1(unsigned_1 x); +INLINE_SIM_ENDIAN(unsigned_2) endian_h2be_2(unsigned_2 x); +INLINE_SIM_ENDIAN(unsigned_4) endian_h2be_4(unsigned_4 x); +INLINE_SIM_ENDIAN(unsigned_8) endian_h2be_8(unsigned_8 x); +INLINE_SIM_ENDIAN(unsigned_16) endian_h2be_16(unsigned_16 x); + +INLINE_SIM_ENDIAN(unsigned_1) endian_be2h_1(unsigned_1 x); +INLINE_SIM_ENDIAN(unsigned_2) endian_be2h_2(unsigned_2 x); +INLINE_SIM_ENDIAN(unsigned_4) endian_be2h_4(unsigned_4 x); +INLINE_SIM_ENDIAN(unsigned_8) endian_be2h_8(unsigned_8 x); +INLINE_SIM_ENDIAN(unsigned_16) endian_be2h_16(unsigned_16 x); + +INLINE_SIM_ENDIAN(unsigned_1) endian_h2le_1(unsigned_1 x); +INLINE_SIM_ENDIAN(unsigned_2) endian_h2le_2(unsigned_2 x); +INLINE_SIM_ENDIAN(unsigned_4) endian_h2le_4(unsigned_4 x); +INLINE_SIM_ENDIAN(unsigned_8) endian_h2le_8(unsigned_8 x); +INLINE_SIM_ENDIAN(unsigned_16) endian_h2le_16(unsigned_16 x); + +INLINE_SIM_ENDIAN(unsigned_1) endian_le2h_1(unsigned_1 x); +INLINE_SIM_ENDIAN(unsigned_2) endian_le2h_2(unsigned_2 x); +INLINE_SIM_ENDIAN(unsigned_4) endian_le2h_4(unsigned_4 x); +INLINE_SIM_ENDIAN(unsigned_8) endian_le2h_8(unsigned_8 x); +INLINE_SIM_ENDIAN(unsigned_16) endian_le2h_16(unsigned_16 x); + +INLINE_SIM_ENDIAN(void*) offset_1(unsigned_1 *x, unsigned ws, unsigned w); +INLINE_SIM_ENDIAN(void*) offset_2(unsigned_2 *x, unsigned ws, unsigned w); +INLINE_SIM_ENDIAN(void*) offset_4(unsigned_4 *x, unsigned ws, unsigned w); +INLINE_SIM_ENDIAN(void*) offset_8(unsigned_8 *x, unsigned ws, unsigned w); +INLINE_SIM_ENDIAN(void*) offset_16(unsigned_16 *x, unsigned ws, unsigned w); + +INLINE_SIM_ENDIAN(unsigned_16) sim_endian_join_16 (unsigned_8 h, unsigned_8 l); +INLINE_SIM_ENDIAN(unsigned_8) sim_endian_split_16 (unsigned_16 word, int w); + + +/* SWAP */ + +#define SWAP_1(X) swap_1(X) +#define SWAP_2(X) swap_2(X) +#define SWAP_4(X) swap_4(X) +#define SWAP_8(X) swap_8(X) +#define SWAP_16(X) swap_16(X) + + +/* HOST to BE */ + +#define H2BE_1(X) endian_h2be_1(X) +#define H2BE_2(X) endian_h2be_2(X) +#define H2BE_4(X) endian_h2be_4(X) +#define H2BE_8(X) endian_h2be_8(X) +#define H2BE_16(X) endian_h2be_16(X) +#define BE2H_1(X) endian_be2h_1(X) +#define BE2H_2(X) endian_be2h_2(X) +#define BE2H_4(X) endian_be2h_4(X) +#define BE2H_8(X) endian_be2h_8(X) +#define BE2H_16(X) endian_be2h_16(X) + + +/* HOST to LE */ + +#define H2LE_1(X) endian_h2le_1(X) +#define H2LE_2(X) endian_h2le_2(X) +#define H2LE_4(X) endian_h2le_4(X) +#define H2LE_8(X) endian_h2le_8(X) +#define H2LE_16(X) endian_h2le_16(X) +#define LE2H_1(X) endian_le2h_1(X) +#define LE2H_2(X) endian_le2h_2(X) +#define LE2H_4(X) endian_le2h_4(X) +#define LE2H_8(X) endian_le2h_8(X) +#define LE2H_16(X) endian_le2h_16(X) + + +/* HOST to TARGET */ + +#define H2T_1(X) endian_h2t_1(X) +#define H2T_2(X) endian_h2t_2(X) +#define H2T_4(X) endian_h2t_4(X) +#define H2T_8(X) endian_h2t_8(X) +#define H2T_16(X) endian_h2t_16(X) +#define T2H_1(X) endian_t2h_1(X) +#define T2H_2(X) endian_t2h_2(X) +#define T2H_4(X) endian_t2h_4(X) +#define T2H_8(X) endian_t2h_8(X) +#define T2H_16(X) endian_t2h_16(X) + + +/* CONVERT IN PLACE + + These macros, given an argument of unknown size, swap its value in + place if a host/target conversion is required. */ + +#define H2T(VARIABLE) \ +do { \ + void *vp = &(VARIABLE); \ + switch (sizeof (VARIABLE)) { \ + case 1: *(unsigned_1*)vp = H2T_1(*(unsigned_1*)vp); break; \ + case 2: *(unsigned_2*)vp = H2T_2(*(unsigned_2*)vp); break; \ + case 4: *(unsigned_4*)vp = H2T_4(*(unsigned_4*)vp); break; \ + case 8: *(unsigned_8*)vp = H2T_8(*(unsigned_8*)vp); break; \ + case 16: *(unsigned_16*)vp = H2T_16(*(unsigned_16*)vp); break; \ + } \ +} while (0) + +#define T2H(VARIABLE) \ +do { \ + switch (sizeof(VARIABLE)) { \ + case 1: VARIABLE = T2H_1(VARIABLE); break; \ + case 2: VARIABLE = T2H_2(VARIABLE); break; \ + case 4: VARIABLE = T2H_4(VARIABLE); break; \ + case 8: VARIABLE = T2H_8(VARIABLE); break; \ + /*case 16: VARIABLE = T2H_16(VARIABLE); break;*/ \ + } \ +} while (0) + +#define SWAP(VARIABLE) \ +do { \ + switch (sizeof(VARIABLE)) { \ + case 1: VARIABLE = SWAP_1(VARIABLE); break; \ + case 2: VARIABLE = SWAP_2(VARIABLE); break; \ + case 4: VARIABLE = SWAP_4(VARIABLE); break; \ + case 8: VARIABLE = SWAP_8(VARIABLE); break; \ + /*case 16: VARIABLE = SWAP_16(VARIABLE); break;*/ \ + } \ +} while (0) + +#define H2BE(VARIABLE) \ +do { \ + switch (sizeof(VARIABLE)) { \ + case 1: VARIABLE = H2BE_1(VARIABLE); break; \ + case 2: VARIABLE = H2BE_2(VARIABLE); break; \ + case 4: VARIABLE = H2BE_4(VARIABLE); break; \ + case 8: VARIABLE = H2BE_8(VARIABLE); break; \ + /*case 16: VARIABLE = H2BE_16(VARIABLE); break;*/ \ + } \ +} while (0) + +#define BE2H(VARIABLE) \ +do { \ + switch (sizeof(VARIABLE)) { \ + case 1: VARIABLE = BE2H_1(VARIABLE); break; \ + case 2: VARIABLE = BE2H_2(VARIABLE); break; \ + case 4: VARIABLE = BE2H_4(VARIABLE); break; \ + case 8: VARIABLE = BE2H_8(VARIABLE); break; \ + /*case 16: VARIABLE = BE2H_16(VARIABLE); break;*/ \ + } \ +} while (0) + +#define H2LE(VARIABLE) \ +do { \ + switch (sizeof(VARIABLE)) { \ + case 1: VARIABLE = H2LE_1(VARIABLE); break; \ + case 2: VARIABLE = H2LE_2(VARIABLE); break; \ + case 4: VARIABLE = H2LE_4(VARIABLE); break; \ + case 8: VARIABLE = H2LE_8(VARIABLE); break; \ + /*case 16: VARIABLE = H2LE_16(VARIABLE); break;*/ \ + } \ +} while (0) + +#define LE2H(VARIABLE) \ +do { \ + switch (sizeof(VARIABLE)) { \ + case 1: VARIABLE = LE2H_1(VARIABLE); break; \ + case 2: VARIABLE = LE2H_2(VARIABLE); break; \ + case 4: VARIABLE = LE2H_4(VARIABLE); break; \ + case 8: VARIABLE = LE2H_8(VARIABLE); break; \ + /*case 16: VARIABLE = LE2H_16(VARIABLE); break;*/ \ + } \ +} while (0) + + + +/* TARGET WORD: + + Byte swap a quantity the size of the targets word */ + +#if (WITH_TARGET_WORD_BITSIZE == 64) +#define H2T_word(X) H2T_8(X) +#define T2H_word(X) T2H_8(X) +#define H2BE_word(X) H2BE_8(X) +#define BE2H_word(X) BE2H_8(X) +#define H2LE_word(X) H2LE_8(X) +#define LE2H_word(X) LE2H_8(X) +#define SWAP_word(X) SWAP_8(X) +#endif +#if (WITH_TARGET_WORD_BITSIZE == 32) +#define H2T_word(X) H2T_4(X) +#define T2H_word(X) T2H_4(X) +#define H2BE_word(X) H2BE_4(X) +#define BE2H_word(X) BE2H_4(X) +#define H2LE_word(X) H2LE_4(X) +#define LE2H_word(X) LE2H_4(X) +#define SWAP_word(X) SWAP_4(X) +#endif + + + +/* TARGET CELL: + + Byte swap a quantity the size of the targets IEEE 1275 memory cell */ + +#define H2T_cell(X) H2T_4(X) +#define T2H_cell(X) T2H_4(X) +#define H2BE_cell(X) H2BE_4(X) +#define BE2H_cell(X) BE2H_4(X) +#define H2LE_cell(X) H2LE_4(X) +#define LE2H_cell(X) LE2H_4(X) +#define SWAP_cell(X) SWAP_4(X) + + + +/* HOST Offsets: + + Address of high/low sub-word within a host word quantity. + + Address of sub-word N within a host word quantity. NOTE: Numbering + is BIG endian always. */ + +#define AH1_2(X) (unsigned_1*)offset_2((X), 1, 0) +#define AL1_2(X) (unsigned_1*)offset_2((X), 1, 1) + +#define AH2_4(X) (unsigned_2*)offset_4((X), 2, 0) +#define AL2_4(X) (unsigned_2*)offset_4((X), 2, 1) + +#define AH4_8(X) (unsigned_4*)offset_8((X), 4, 0) +#define AL4_8(X) (unsigned_4*)offset_8((X), 4, 1) + +#define AH8_16(X) (unsigned_8*)offset_16((X), 8, 0) +#define AL8_16(X) (unsigned_8*)offset_16((X), 8, 1) + +#if (WITH_TARGET_WORD_BITSIZE == 64) +#define AH_word(X) AH4_8(X) +#define AL_word(X) AL4_8(X) +#endif +#if (WITH_TARGET_WORD_BITSIZE == 32) +#define AH_word(X) AH2_4(X) +#define AL_word(X) AL2_4(X) +#endif + + +#define A1_2(X,N) (unsigned_1*)offset_2((X), 1, (N)) + +#define A1_4(X,N) (unsigned_1*)offset_4((X), 1, (N)) +#define A2_4(X,N) (unsigned_2*)offset_4((X), 2, (N)) + +#define A1_8(X,N) (unsigned_1*)offset_8((X), 1, (N)) +#define A2_8(X,N) (unsigned_2*)offset_8((X), 2, (N)) +#define A4_8(X,N) (unsigned_4*)offset_8((X), 4, (N)) + +#define A1_16(X,N) (unsigned_1*)offset_16((X), 1, (N)) +#define A2_16(X,N) (unsigned_2*)offset_16((X), 2, (N)) +#define A4_16(X,N) (unsigned_4*)offset_16((X), 4, (N)) +#define A8_16(X,N) (unsigned_8*)offset_16((X), 8, (N)) + + + + +/* HOST Components: + + Value of sub-word within a host word quantity */ + +#define VH1_2(X) ((unsigned_1)((unsigned_2)(X) >> 8)) +#define VL1_2(X) (unsigned_1)(X) + +#define VH2_4(X) ((unsigned_2)((unsigned_4)(X) >> 16)) +#define VL2_4(X) ((unsigned_2)(X)) + +#define VH4_8(X) ((unsigned_4)((unsigned_8)(X) >> 32)) +#define VL4_8(X) ((unsigned_4)(X)) + +#define VH8_16(X) (sim_endian_split_16 ((X), 0)) +#define VL8_16(X) (sim_endian_split_16 ((X), 1)) + +#if (WITH_TARGET_WORD_BITSIZE == 64) +#define VH_word(X) VH4_8(X) +#define VL_word(X) VL4_8(X) +#endif +#if (WITH_TARGET_WORD_BITSIZE == 32) +#define VH_word(X) VH2_4(X) +#define VL_word(X) VL2_4(X) +#endif + + +#define V1_2(X,N) ((unsigned_1)((unsigned_2)(X) >> ( 8 * (1 - (N))))) + +#define V1_4(X,N) ((unsigned_1)((unsigned_4)(X) >> ( 8 * (3 - (N))))) +#define V2_4(X,N) ((unsigned_2)((unsigned_4)(X) >> (16 * (1 - (N))))) + +#define V1_8(X,N) ((unsigned_1)((unsigned_8)(X) >> ( 8 * (7 - (N))))) +#define V2_8(X,N) ((unsigned_2)((unsigned_8)(X) >> (16 * (3 - (N))))) +#define V4_8(X,N) ((unsigned_4)((unsigned_8)(X) >> (32 * (1 - (N))))) + +#define V1_16(X,N) (*A1_16 (&(X),N)) +#define V2_16(X,N) (*A2_16 (&(X),N)) +#define V4_16(X,N) (*A4_16 (&(X),N)) +#define V8_16(X,N) (*A8_16 (&(X),N)) + + +/* Reverse - insert sub-word into word quantity */ + +#define V2_H1(X) ((unsigned_2)(unsigned_1)(X) << 8) +#define V2_L1(X) ((unsigned_2)(unsigned_1)(X)) + +#define V4_H2(X) ((unsigned_4)(unsigned_2)(X) << 16) +#define V4_L2(X) ((unsigned_4)(unsigned_2)(X)) + +#define V8_H4(X) ((unsigned_8)(unsigned_4)(X) << 32) +#define V8_L4(X) ((unsigned_8)(unsigned_4)(X)) + +#define V16_H8(X) ((unsigned_16)(unsigned_8)(X) << 64) +#define V16_L8(X) ((unsigned_16)(unsigned_8)(X)) + + +#define V2_1(X,N) ((unsigned_2)(unsigned_1)(X) << ( 8 * (1 - (N)))) + +#define V4_1(X,N) ((unsigned_4)(unsigned_1)(X) << ( 8 * (3 - (N)))) +#define V4_2(X,N) ((unsigned_4)(unsigned_2)(X) << (16 * (1 - (N)))) + +#define V8_1(X,N) ((unsigned_8)(unsigned_1)(X) << ( 8 * (7 - (N)))) +#define V8_2(X,N) ((unsigned_8)(unsigned_2)(X) << (16 * (3 - (N)))) +#define V8_4(X,N) ((unsigned_8)(unsigned_4)(X) << (32 * (1 - (N)))) + +#define V16_1(X,N) ((unsigned_16)(unsigned_1)(X) << ( 8 * (15 - (N)))) +#define V16_2(X,N) ((unsigned_16)(unsigned_2)(X) << (16 * (7 - (N)))) +#define V16_4(X,N) ((unsigned_16)(unsigned_4)(X) << (32 * (3 - (N)))) +#define V16_8(X,N) ((unsigned_16)(unsigned_8)(X) << (64 * (1 - (N)))) + + +/* Reverse - insert N sub-words into single word quantity */ + +#define U2_1(I0,I1) (V2_1(I0,0) | V2_1(I1,1)) +#define U4_1(I0,I1,I2,I3) (V4_1(I0,0) | V4_1(I1,1) | V4_1(I2,2) | V4_1(I3,3)) +#define U8_1(I0,I1,I2,I3,I4,I5,I6,I7) \ +(V8_1(I0,0) | V8_1(I1,1) | V8_1(I2,2) | V8_1(I3,3) \ + | V8_1(I4,4) | V8_1(I5,5) | V8_1(I6,6) | V8_1(I7,7)) +#define U16_1(I0,I1,I2,I3,I4,I5,I6,I7,I8,I9,I10,I11,I12,I13,I14,I15) \ +(V16_1(I0,0) | V16_1(I1,1) | V16_1(I2,2) | V16_1(I3,3) \ + | V16_1(I4,4) | V16_1(I5,5) | V16_1(I6,6) | V16_1(I7,7) \ + | V16_1(I8,8) | V16_1(I9,9) | V16_1(I10,10) | V16_1(I11,11) \ + | V16_1(I12,12) | V16_1(I13,13) | V16_1(I14,14) | V16_1(I15,15)) + +#define U4_2(I0,I1) (V4_2(I0,0) | V4_2(I1,1)) +#define U8_2(I0,I1,I2,I3) (V8_2(I0,0) | V8_2(I1,1) | V8_2(I2,2) | V8_2(I3,3)) +#define U16_2(I0,I1,I2,I3,I4,I5,I6,I7) \ +(V16_2(I0,0) | V16_2(I1,1) | V16_2(I2,2) | V16_2(I3,3) \ + | V16_2(I4,4) | V16_2(I5,5) | V16_2(I6,6) | V16_2(I7,7) ) + +#define U8_4(I0,I1) (V8_4(I0,0) | V8_4(I1,1)) +#define U16_4(I0,I1,I2,I3) (V16_4(I0,0) | V16_4(I1,1) | V16_4(I2,2) | V16_4(I3,3)) + +#define U16_8(I0,I1) (sim_endian_join_16 (I0, I1)) + + +#if (WITH_TARGET_WORD_BITSIZE == 64) +#define Vword_H(X) V8_H4(X) +#define Vword_L(X) V8_L4(X) +#endif +#if (WITH_TARGET_WORD_BITSIZE == 32) +#define Vword_H(X) V4_H2(X) +#define Vword_L(X) V4_L2(X) +#endif + + + + +#if H_REVEALS_MODULE_P (SIM_ENDIAN_INLINE) +#include "sim-endian.c" +#endif + +#endif /* _SIM_ENDIAN_H_ */ diff --git a/sim/common/sim-engine.c b/sim/common/sim-engine.c new file mode 100644 index 00000000000..9415f637cc1 --- /dev/null +++ b/sim/common/sim-engine.c @@ -0,0 +1,210 @@ +/* Generic simulator halt/restart. + Copyright (C) 1997, 1998 Free Software Foundation, Inc. + Contributed by Cygnus Support. + +This file is part of GDB, the GNU debugger. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include + +#include "sim-main.h" +#include "sim-assert.h" + +/* Get the run state. + REASON/SIGRC are the values returned by sim_stop_reason. + ??? Should each cpu have its own copy? */ + +void +sim_engine_get_run_state (SIM_DESC sd, enum sim_stop *reason, int *sigrc) +{ + sim_engine *engine = STATE_ENGINE (sd); + ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); + *reason = engine->reason; + *sigrc = engine->sigrc; +} + +/* Set the run state to REASON/SIGRC. + REASON/SIGRC are the values returned by sim_stop_reason. + ??? Should each cpu have its own copy? */ + +void +sim_engine_set_run_state (SIM_DESC sd, enum sim_stop reason, int sigrc) +{ + sim_engine *engine = STATE_ENGINE (sd); + ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); + engine->reason = reason; + engine->sigrc = sigrc; +} + +/* Generic halt */ + +void +sim_engine_halt (SIM_DESC sd, + sim_cpu *last_cpu, + sim_cpu *next_cpu, /* NULL - use default */ + sim_cia cia, + enum sim_stop reason, + int sigrc) +{ + sim_engine *engine = STATE_ENGINE (sd); + ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); + if (engine->jmpbuf != NULL) + { + jmp_buf *halt_buf = engine->jmpbuf; + engine->last_cpu = last_cpu; + engine->next_cpu = next_cpu; + engine->reason = reason; + engine->sigrc = sigrc; + + SIM_ENGINE_HALT_HOOK (sd, last_cpu, cia); + +#ifdef SIM_CPU_EXCEPTION_SUSPEND + if (last_cpu != NULL && reason != sim_exited) + SIM_CPU_EXCEPTION_SUSPEND (sd, last_cpu, sim_signal_to_host (sd, sigrc)); +#endif + + longjmp (*halt_buf, sim_engine_halt_jmpval); + } + else + sim_io_error (sd, "sim_halt - bad long jump"); +} + + +/* Generic restart */ + +void +sim_engine_restart (SIM_DESC sd, + sim_cpu *last_cpu, + sim_cpu *next_cpu, + sim_cia cia) +{ + sim_engine *engine = STATE_ENGINE (sd); + ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); + if (engine->jmpbuf != NULL) + { + jmp_buf *halt_buf = engine->jmpbuf; + engine->last_cpu = last_cpu; + engine->next_cpu = next_cpu; + SIM_ENGINE_RESTART_HOOK (sd, last_cpu, cia); + longjmp (*halt_buf, sim_engine_restart_jmpval); + } + else + sim_io_error (sd, "sim_restart - bad long jump"); +} + + +/* Generic error code */ + +void +sim_engine_vabort (SIM_DESC sd, + sim_cpu *cpu, + sim_cia cia, + const char *fmt, + va_list ap) +{ + ASSERT (sd == NULL || STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); + if (sd == NULL) + { + vfprintf (stderr, fmt, ap); + fprintf (stderr, "\nQuit\n"); + abort (); + } + else if (STATE_ENGINE (sd)->jmpbuf == NULL) + { + sim_io_evprintf (sd, fmt, ap); + sim_io_eprintf (sd, "\n"); + sim_io_error (sd, "Quit Simulator"); + } + else + { + sim_io_evprintf (sd, fmt, ap); + sim_io_eprintf (sd, "\n"); + sim_engine_halt (sd, cpu, NULL, cia, sim_stopped, SIM_SIGABRT); + } +} + +void +sim_engine_abort (SIM_DESC sd, + sim_cpu *cpu, + sim_cia cia, + const char *fmt, + ...) +{ + va_list ap; + ASSERT (sd == NULL || STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); + va_start(ap, fmt); + sim_engine_vabort (sd, cpu, cia, fmt, ap); + va_end (ap); +} + + +/* Generic next/last cpu */ + +int +sim_engine_last_cpu_nr (SIM_DESC sd) +{ + sim_engine *engine = STATE_ENGINE (sd); + if (engine->last_cpu != NULL) + return engine->last_cpu - STATE_CPU (sd, 0); + else + return MAX_NR_PROCESSORS; +} + +int +sim_engine_next_cpu_nr (SIM_DESC sd) +{ + sim_engine *engine = STATE_ENGINE (sd); + if (engine->next_cpu != NULL) + return engine->next_cpu - STATE_CPU (sd, 0); + else + return sim_engine_last_cpu_nr (sd) + 1; +} + +int +sim_engine_nr_cpus (SIM_DESC sd) +{ + sim_engine *engine = STATE_ENGINE (sd); + return engine->nr_cpus; +} + + + + +/* Initialization */ + +static SIM_RC +sim_engine_init (SIM_DESC sd) +{ + /* initialize the start/stop/resume engine */ + sim_engine *engine = STATE_ENGINE (sd); + engine->jmpbuf = NULL; + engine->last_cpu = NULL; + engine->next_cpu = NULL; + engine->nr_cpus = MAX_NR_PROCESSORS; + engine->reason = sim_running; + engine->sigrc = 0; + engine->stepper = NULL; /* sim_events_init will clean it up */ + return SIM_RC_OK; +} + + +SIM_RC +sim_engine_install (SIM_DESC sd) +{ + SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); + sim_module_add_init_fn (sd, sim_engine_init); + return SIM_RC_OK; +} diff --git a/sim/common/sim-engine.h b/sim/common/sim-engine.h new file mode 100644 index 00000000000..41aa51f9ed0 --- /dev/null +++ b/sim/common/sim-engine.h @@ -0,0 +1,161 @@ +/* Generic simulator halt/resume. + Copyright (C) 1997, 1998 Free Software Foundation, Inc. + Contributed by Cygnus Support. + +This file is part of GDB, the GNU debugger. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef SIM_ENGINE_H +#define SIM_ENGINE_H + + +typedef struct _sim_engine sim_engine; +struct _sim_engine +{ + void *jmpbuf; + sim_cpu *last_cpu; + sim_cpu *next_cpu; + int nr_cpus; + enum sim_stop reason; + sim_event *stepper; + int sigrc; +}; + + + +/* jmpval: 0 (initial use) start simulator + 1 halt simulator + 2 restart simulator + This is required by the ISO C standard (the only time 0 is returned + is at the initial call to setjmp). */ + +enum { + sim_engine_start_jmpval, + sim_engine_halt_jmpval, + sim_engine_restart_jmpval, +}; + + +/* Get/set the run state of CPU to REASON/SIGRC. + REASON/SIGRC are the values returned by sim_stop_reason. */ +void sim_engine_get_run_state (SIM_DESC sd, enum sim_stop *reason, int *sigrc); +void sim_engine_set_run_state (SIM_DESC sd, enum sim_stop reason, int sigrc); + + +/* Halt the simulator *now* */ + +extern void sim_engine_halt +(SIM_DESC sd, + sim_cpu *last_cpu, /* NULL -> in event-mgr */ + sim_cpu *next_cpu, /* NULL -> succ (last_cpu) or event-mgr */ + sim_cia cia, + enum sim_stop reason, + int sigrc); + +/* Halt hook - allow target specific operation when halting a + simulator */ + +#if !defined (SIM_ENGINE_HALT_HOOK) +#define SIM_ENGINE_HALT_HOOK(SD, LAST_CPU, CIA) \ +if ((LAST_CPU) != NULL) CIA_SET (LAST_CPU, CIA) +#endif + +/* NB: If a port uses the SIM_CPU_EXCEPTION_* hooks, the default + SIM_ENGINE_HALT_HOOK and SIM_ENGINE_RESUME_HOOK must not be used. + They conflict in that the PC set by the HALT_HOOK may overwrite the + proper one, as intended to be saved by the EXCEPTION_TRIGGER + hook. */ + + +/* restart the simulator *now* */ + +extern void sim_engine_restart +(SIM_DESC sd, + sim_cpu *last_cpu, /* NULL -> in event-mgr */ + sim_cpu *next_cpu, /* NULL -> succ (last_cpu) or event-mgr */ + sim_cia cia); + +/* Restart hook - allow target specific operation when restarting a + simulator */ + +#if !defined (SIM_ENGINE_RESTART_HOOK) +#define SIM_ENGINE_RESTART_HOOK(SD, LAST_CPU, CIA) SIM_ENGINE_HALT_HOOK(SD, LAST_CPU, CIA) +#endif + + + + +/* Abort the simulator *now*. + + This function is NULL safe. It can be called when either of SD or + CIA are NULL. + + This function is setjmp/longjmp safe. It can be called when of + the sim_engine setjmp/longjmp buffer has not been established. + + Simulators that are using components such as sim-core but are not + yet using this sim-engine module should link in file sim-abort.o + which implements a non setjmp/longjmp version of + sim_engine_abort. */ + +extern void sim_engine_abort +(SIM_DESC sd, + sim_cpu *cpu, + sim_cia cia, + const char *fmt, + ...) __attribute__ ((format (printf, 4, 5))); + +extern void sim_engine_vabort +(SIM_DESC sd, + sim_cpu *cpu, + sim_cia cia, + const char *fmt, + va_list ap); + +/* No abort hook - when possible this function exits using the + engine_halt function (and SIM_ENGINE_HALT_HOOK). */ + + + + +/* Called by the generic sim_resume to run the simulation within the + above safty net. + + An example implementation of sim_engine_run can be found in the + file sim-run.c */ + +extern void sim_engine_run +(SIM_DESC sd, + int next_cpu_nr, + int nr_cpus, + int siggnal); /* most simulators ignore siggnal */ + + + +/* Determine the state of next/last cpu when the simulator was last + halted - a value >= MAX_NR_PROCESSORS indicates that the + event-queue was next/last. */ + +extern int sim_engine_next_cpu_nr (SIM_DESC sd); +extern int sim_engine_last_cpu_nr (SIM_DESC sd); +extern int sim_engine_nr_cpus (SIM_DESC sd); + + +/* Establish the simulator engine */ +MODULE_INSTALL_FN sim_engine_install; + + +#endif diff --git a/sim/common/sim-events.c b/sim/common/sim-events.c new file mode 100644 index 00000000000..4b7d9b4b6be --- /dev/null +++ b/sim/common/sim-events.c @@ -0,0 +1,1188 @@ +/* This file is part of the program psim. + + Copyright (C) 1994-1997, Andrew Cagney + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + + +#ifndef _SIM_EVENTS_C_ +#define _SIM_EVENTS_C_ + +#include "sim-main.h" +#include "sim-assert.h" + +#ifdef HAVE_STRING_H +#include +#else +#ifdef HAVE_STRINGS_H +#include +#endif +#endif + +#ifdef HAVE_STDLIB_H +#include +#endif + +#include /* For SIGPROCMASK et.al. */ + +#if __CYGWIN32__ +/* The ui_loop_hook is called to keep the GUI alive while the simulator + is running. The counter is to make sure we do not wake it too often. +*/ + +extern void (*ui_loop_hook) PARAMS ((int)); +static unsigned int ui_loop_hook_counter = 0; +#endif + +typedef enum { + watch_invalid, + + /* core - target byte order */ + watch_core_targ_1, + watch_core_targ_2, + watch_core_targ_4, + watch_core_targ_8, + /* core - big-endian */ + watch_core_be_1, + watch_core_be_2, + watch_core_be_4, + watch_core_be_8, + /* core - little-endian */ + watch_core_le_1, + watch_core_le_2, + watch_core_le_4, + watch_core_le_8, + + /* sim - host byte order */ + watch_sim_host_1, + watch_sim_host_2, + watch_sim_host_4, + watch_sim_host_8, + /* sim - big-endian */ + watch_sim_be_1, + watch_sim_be_2, + watch_sim_be_4, + watch_sim_be_8, + /* sim - little-endian */ + watch_sim_le_1, + watch_sim_le_2, + watch_sim_le_4, + watch_sim_le_8, + + /* wallclock */ + watch_clock, + + /* timer */ + watch_timer, +} sim_event_watchpoints; + + +struct _sim_event { + sim_event_watchpoints watching; + void *data; + sim_event_handler *handler; + /* timer event */ + signed64 time_of_event; + /* watch wallclock event */ + unsigned wallclock; + /* watch core address */ + address_word core_addr; + unsigned core_map; + /* watch sim addr */ + void *host_addr; + /* watch core/sim range */ + int is_within; /* 0/1 */ + unsigned ub; + unsigned lb; + unsigned64 ub64; + unsigned64 lb64; + /* trace info (if any) */ + char *trace; + /* list */ + sim_event *next; +}; + + +/* The event queue maintains a single absolute time using two + variables. + + TIME_OF_EVENT: this holds the time at which the next event is ment + to occure. If no next event it will hold the time of the last + event. + + TIME_FROM_EVENT: The current distance from TIME_OF_EVENT. A value + <= 0 (except when poll-event is being processed) indicates that + event processing is due. This variable is decremented once for + each iteration of a clock cycle. + + Initially, the clock is started at time one (0) with TIME_OF_EVENT + == 0 and TIME_FROM_EVENT == 0 and with NR_TICKS_TO_PROCESS == 1. + + Clearly there is a bug in that this code assumes that the absolute + time counter will never become greater than 2^62. + + To avoid the need to use 64bit arithmetic, the event queue always + contains at least one event scheduled every 16 000 ticks. This + limits the time from event counter to values less than + 16 000. */ + + +#if !defined (SIM_EVENTS_POLL_RATE) +#define SIM_EVENTS_POLL_RATE 0x1000 +#endif + + +#define _ETRACE sd, NULL + +#undef ETRACE_P +#define ETRACE_P (WITH_TRACE && STATE_EVENTS (sd)->trace) + +#undef ETRACE +#define ETRACE(ARGS) \ +do \ + { \ + if (ETRACE_P) \ + { \ + if (STRACE_DEBUG_P (sd)) \ + { \ + const char *file; \ + SIM_FILTER_PATH (file, __FILE__); \ + trace_printf (sd, NULL, "%s:%d: ", file, __LINE__); \ + } \ + trace_printf ARGS; \ + } \ + } \ +while (0) + + +/* event queue iterator - don't iterate over the held queue. */ + +#if EXTERN_SIM_EVENTS_P +static sim_event ** +next_event_queue (SIM_DESC sd, + sim_event **queue) +{ + if (queue == NULL) + return &STATE_EVENTS (sd)->queue; + else if (queue == &STATE_EVENTS (sd)->queue) + return &STATE_EVENTS (sd)->watchpoints; + else if (queue == &STATE_EVENTS (sd)->watchpoints) + return &STATE_EVENTS (sd)->watchedpoints; + else if (queue == &STATE_EVENTS (sd)->watchedpoints) + return NULL; + else + sim_io_error (sd, "next_event_queue - bad queue"); + return NULL; +} +#endif + + +STATIC_INLINE_SIM_EVENTS\ +(void) +sim_events_poll (SIM_DESC sd, + void *data) +{ + /* just re-schedule in 1000 million ticks time */ + sim_events_schedule (sd, SIM_EVENTS_POLL_RATE, sim_events_poll, sd); + sim_io_poll_quit (sd); +} + + +/* "events" module install handler. + This is called via sim_module_install to install the "events" subsystem + into the simulator. */ + +#if EXTERN_SIM_EVENTS_P +STATIC_SIM_EVENTS (MODULE_UNINSTALL_FN) sim_events_uninstall; +STATIC_SIM_EVENTS (MODULE_INIT_FN) sim_events_init; +STATIC_SIM_EVENTS (MODULE_RESUME_FN) sim_events_resume; +STATIC_SIM_EVENTS (MODULE_SUSPEND_FN) sim_events_suspend; +#endif + +#if EXTERN_SIM_EVENTS_P +SIM_RC +sim_events_install (SIM_DESC sd) +{ + SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); + sim_module_add_uninstall_fn (sd, sim_events_uninstall); + sim_module_add_init_fn (sd, sim_events_init); + sim_module_add_resume_fn (sd, sim_events_resume); + sim_module_add_suspend_fn (sd, sim_events_suspend); + return SIM_RC_OK; +} +#endif + + +/* Suspend/resume the event queue manager when the simulator is not + running */ + +#if EXTERN_SIM_EVENTS_P +static SIM_RC +sim_events_resume (SIM_DESC sd) +{ + sim_events *events = STATE_EVENTS (sd); + SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); + SIM_ASSERT (events->resume_wallclock == 0); + events->resume_wallclock = sim_elapsed_time_get (); + return SIM_RC_OK; +} +#endif + +#if EXTERN_SIM_EVENTS_P +static SIM_RC +sim_events_suspend (SIM_DESC sd) +{ + sim_events *events = STATE_EVENTS (sd); + SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); + SIM_ASSERT (events->resume_wallclock != 0); + events->elapsed_wallclock += sim_elapsed_time_since (events->resume_wallclock); + events->resume_wallclock = 0; + return SIM_RC_OK; +} +#endif + + +/* Uninstall the "events" subsystem from the simulator. */ + +#if EXTERN_SIM_EVENTS_P +static void +sim_events_uninstall (SIM_DESC sd) +{ + SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); + /* FIXME: free buffers, etc. */ +} +#endif + + +/* malloc/free */ + +#if EXTERN_SIM_EVENTS_P +static sim_event * +sim_events_zalloc (SIM_DESC sd) +{ + sim_events *events = STATE_EVENTS (sd); + sim_event *new = events->free_list; + if (new != NULL) + { + events->free_list = new->next; + memset (new, 0, sizeof (*new)); + } + else + { +#if defined (HAVE_SIGPROCMASK) && defined (SIG_SETMASK) + /*-LOCK-*/ + sigset_t old_mask; + sigset_t new_mask; + sigfillset(&new_mask); + sigprocmask (SIG_SETMASK, &new_mask, &old_mask); +#endif + new = ZALLOC (sim_event); +#if defined (HAVE_SIGPROCMASK) && defined (SIG_SETMASK) + /*-UNLOCK-*/ + sigprocmask (SIG_SETMASK, &old_mask, NULL); +#endif + } + return new; +} +#endif + +STATIC_INLINE_SIM_EVENTS\ +(void) +sim_events_free (SIM_DESC sd, + sim_event *dead) +{ + sim_events *events = STATE_EVENTS (sd); + dead->next = events->free_list; + events->free_list = dead; + if (dead->trace != NULL) + { + free (dead->trace); /* NB: asprintf returns a `free' buf */ + dead->trace = NULL; + } +} + + +/* Initialize the simulator event manager */ + +#if EXTERN_SIM_EVENTS_P +SIM_RC +sim_events_init (SIM_DESC sd) +{ + sim_events *events = STATE_EVENTS (sd); + + /* drain the interrupt queue */ + events->nr_held = 0; + if (events->held == NULL) + events->held = NZALLOC (sim_event, MAX_NR_SIGNAL_SIM_EVENTS); + + /* drain the normal queues */ + { + sim_event **queue = NULL; + while ((queue = next_event_queue (sd, queue)) != NULL) + { + if (queue == NULL) break; + while (*queue != NULL) + { + sim_event *dead = *queue; + *queue = dead->next; + sim_events_free (sd, dead); + } + *queue = NULL; + } + } + + /* wind time back to zero */ + events->nr_ticks_to_process = 1; /* start by doing queue */ + events->time_of_event = 0; + events->time_from_event = 0; + events->elapsed_wallclock = 0; + events->resume_wallclock = 0; + + /* schedule our initial counter event */ + sim_events_schedule (sd, 0, sim_events_poll, sd); + + /* from now on, except when the large-int event is being processed + the event queue is non empty */ + SIM_ASSERT (events->queue != NULL); + + return SIM_RC_OK; +} +#endif + + +INLINE_SIM_EVENTS\ +(signed64) +sim_events_time (SIM_DESC sd) +{ + sim_events *events = STATE_EVENTS (sd); + return (events->time_of_event - events->time_from_event); +} + + +INLINE_SIM_EVENTS\ +(unsigned long) +sim_events_elapsed_time (SIM_DESC sd) +{ + unsigned long elapsed = STATE_EVENTS (sd)->elapsed_wallclock; + + /* Are we being called inside sim_resume? + (Is there a simulation in progress?) */ + if (STATE_EVENTS (sd)->resume_wallclock != 0) + elapsed += sim_elapsed_time_since (STATE_EVENTS (sd)->resume_wallclock); + + return elapsed; +} + + +STATIC_INLINE_SIM_EVENTS\ +(void) +update_time_from_event (SIM_DESC sd) +{ + sim_events *events = STATE_EVENTS (sd); + signed64 current_time = sim_events_time (sd); + if (events->queue != NULL) + { + events->time_of_event = events->queue->time_of_event; + events->time_from_event = (events->queue->time_of_event - current_time); + } + else + { + events->time_of_event = current_time - 1; + events->time_from_event = -1; + } + SIM_ASSERT (current_time == sim_events_time (sd)); +} + + +#if EXTERN_SIM_EVENTS_P +static void +insert_sim_event (SIM_DESC sd, + sim_event *new_event, + signed64 delta) +{ + sim_events *events = STATE_EVENTS (sd); + sim_event *curr; + sim_event **prev; + signed64 time_of_event; + + if (delta < 0) + sim_io_error (sd, "what is past is past!\n"); + + /* compute when the event should occure */ + time_of_event = sim_events_time (sd) + delta; + + /* find the queue insertion point - things are time ordered */ + prev = &events->queue; + curr = events->queue; + while (curr != NULL && time_of_event >= curr->time_of_event) + { + SIM_ASSERT (curr->next == NULL + || curr->time_of_event <= curr->next->time_of_event); + prev = &curr->next; + curr = curr->next; + } + SIM_ASSERT (curr == NULL || time_of_event < curr->time_of_event); + + /* insert it */ + new_event->next = curr; + *prev = new_event; + new_event->time_of_event = time_of_event; + + /* adjust the time until the first event */ + update_time_from_event (sd); +} +#endif + + +#if EXTERN_SIM_EVENTS_P +sim_event * +sim_events_schedule (SIM_DESC sd, + signed64 delta_time, + sim_event_handler *handler, + void *data) +{ + va_list dummy; + return sim_events_schedule_vtracef (sd, delta_time, handler, data, + NULL, dummy); +} +#endif + + +#if EXTERN_SIM_EVENTS_P +sim_event * +sim_events_schedule_tracef (SIM_DESC sd, + signed64 delta_time, + sim_event_handler *handler, + void *data, + const char *fmt, + ...) +{ + sim_event *new_event; + va_list ap; + va_start (ap, fmt); + new_event = sim_events_schedule_vtracef (sd, delta_time, handler, data, fmt, ap); + va_end (ap); + return new_event; +} +#endif + + +#if EXTERN_SIM_EVENTS_P +sim_event * +sim_events_schedule_vtracef (SIM_DESC sd, + signed64 delta_time, + sim_event_handler *handler, + void *data, + const char *fmt, + va_list ap) +{ + sim_event *new_event = sim_events_zalloc (sd); + new_event->data = data; + new_event->handler = handler; + new_event->watching = watch_timer; + if (fmt == NULL || !ETRACE_P || vasprintf (&new_event->trace, fmt, ap) < 0) + new_event->trace = NULL; + insert_sim_event(sd, new_event, delta_time); + ETRACE((_ETRACE, + "event scheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx%s%s\n", + (long)sim_events_time(sd), + (long)new_event, + (long)new_event->time_of_event, + (long)new_event->handler, + (long)new_event->data, + (new_event->trace != NULL) ? ", " : "", + (new_event->trace != NULL) ? new_event->trace : "")); + return new_event; +} +#endif + + +#if EXTERN_SIM_EVENTS_P +void +sim_events_schedule_after_signal (SIM_DESC sd, + signed64 delta_time, + sim_event_handler *handler, + void *data) +{ + sim_events *events = STATE_EVENTS (sd); + sim_event *new_event; +#if defined (HAVE_SIGPROCMASK) && defined (SIG_SETMASK) + /*-LOCK-*/ + sigset_t old_mask; + sigset_t new_mask; + sigfillset(&new_mask); + sigprocmask (SIG_SETMASK, &new_mask, &old_mask); +#endif + + /* allocate an event entry from the signal buffer */ + new_event = &events->held [events->nr_held]; + events->nr_held ++; + if (events->nr_held > MAX_NR_SIGNAL_SIM_EVENTS) + { + sim_engine_abort (NULL, NULL, NULL_CIA, + "sim_events_schedule_after_signal - buffer oveflow"); + } + + new_event->data = data; + new_event->handler = handler; + new_event->time_of_event = delta_time; /* work it out later */ + new_event->next = NULL; + + events->work_pending = 1; /* notify main process */ + +#if defined (HAVE_SIGPROCMASK) && defined (SIG_SETMASK) + /*-UNLOCK-*/ + sigprocmask (SIG_SETMASK, &old_mask, NULL); +#endif + + ETRACE ((_ETRACE, + "signal scheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx\n", + (long)sim_events_time(sd), + (long)new_event, + (long)new_event->time_of_event, + (long)new_event->handler, + (long)new_event->data)); +} +#endif + + +#if EXTERN_SIM_EVENTS_P +sim_event * +sim_events_watch_clock (SIM_DESC sd, + unsigned delta_ms_time, + sim_event_handler *handler, + void *data) +{ + sim_events *events = STATE_EVENTS (sd); + sim_event *new_event = sim_events_zalloc (sd); + /* type */ + new_event->watching = watch_clock; + /* handler */ + new_event->data = data; + new_event->handler = handler; + /* data */ + if (events->resume_wallclock == 0) + new_event->wallclock = (events->elapsed_wallclock + delta_ms_time); + else + new_event->wallclock = (events->elapsed_wallclock + + sim_elapsed_time_since (events->resume_wallclock) + + delta_ms_time); + /* insert */ + new_event->next = events->watchpoints; + events->watchpoints = new_event; + events->work_pending = 1; + ETRACE ((_ETRACE, + "event watching clock at %ld - tag 0x%lx - wallclock %ld, handler 0x%lx, data 0x%lx\n", + (long)sim_events_time (sd), + (long)new_event, + (long)new_event->wallclock, + (long)new_event->handler, + (long)new_event->data)); + return new_event; +} +#endif + + +#if EXTERN_SIM_EVENTS_P +sim_event * +sim_events_watch_sim (SIM_DESC sd, + void *host_addr, + int nr_bytes, + int byte_order, + int is_within, + unsigned64 lb, + unsigned64 ub, + sim_event_handler *handler, + void *data) +{ + sim_events *events = STATE_EVENTS (sd); + sim_event *new_event = sim_events_zalloc (sd); + /* type */ + switch (byte_order) + { + case 0: + switch (nr_bytes) + { + case 1: new_event->watching = watch_sim_host_1; break; + case 2: new_event->watching = watch_sim_host_2; break; + case 4: new_event->watching = watch_sim_host_4; break; + case 8: new_event->watching = watch_sim_host_8; break; + default: sim_io_error (sd, "sim_events_watch_sim - invalid nr bytes"); + } + break; + case BIG_ENDIAN: + switch (nr_bytes) + { + case 1: new_event->watching = watch_sim_be_1; break; + case 2: new_event->watching = watch_sim_be_2; break; + case 4: new_event->watching = watch_sim_be_4; break; + case 8: new_event->watching = watch_sim_be_8; break; + default: sim_io_error (sd, "sim_events_watch_sim - invalid nr bytes"); + } + break; + case LITTLE_ENDIAN: + switch (nr_bytes) + { + case 1: new_event->watching = watch_sim_le_1; break; + case 2: new_event->watching = watch_sim_le_2; break; + case 4: new_event->watching = watch_sim_le_4; break; + case 8: new_event->watching = watch_sim_le_8; break; + default: sim_io_error (sd, "sim_events_watch_sim - invalid nr bytes"); + } + break; + default: + sim_io_error (sd, "sim_events_watch_sim - invalid byte order"); + } + /* handler */ + new_event->data = data; + new_event->handler = handler; + /* data */ + new_event->host_addr = host_addr; + new_event->lb = lb; + new_event->lb64 = lb; + new_event->ub = ub; + new_event->ub64 = ub; + new_event->is_within = (is_within != 0); + /* insert */ + new_event->next = events->watchpoints; + events->watchpoints = new_event; + events->work_pending = 1; + ETRACE ((_ETRACE, + "event watching host at %ld - tag 0x%lx - host-addr 0x%lx, 0x%lx..0x%lx, handler 0x%lx, data 0x%lx\n", + (long)sim_events_time (sd), + (long)new_event, + (long)new_event->host_addr, + (long)new_event->lb, + (long)new_event->ub, + (long)new_event->handler, + (long)new_event->data)); + return new_event; +} +#endif + + +#if EXTERN_SIM_EVENTS_P +sim_event * +sim_events_watch_core (SIM_DESC sd, + address_word core_addr, + unsigned core_map, + int nr_bytes, + int byte_order, + int is_within, + unsigned64 lb, + unsigned64 ub, + sim_event_handler *handler, + void *data) +{ + sim_events *events = STATE_EVENTS (sd); + sim_event *new_event = sim_events_zalloc (sd); + /* type */ + switch (byte_order) + { + case 0: + switch (nr_bytes) + { + case 1: new_event->watching = watch_core_targ_1; break; + case 2: new_event->watching = watch_core_targ_2; break; + case 4: new_event->watching = watch_core_targ_4; break; + case 8: new_event->watching = watch_core_targ_8; break; + default: sim_io_error (sd, "sim_events_watch_core - invalid nr bytes"); + } + break; + case BIG_ENDIAN: + switch (nr_bytes) + { + case 1: new_event->watching = watch_core_be_1; break; + case 2: new_event->watching = watch_core_be_2; break; + case 4: new_event->watching = watch_core_be_4; break; + case 8: new_event->watching = watch_core_be_8; break; + default: sim_io_error (sd, "sim_events_watch_core - invalid nr bytes"); + } + break; + case LITTLE_ENDIAN: + switch (nr_bytes) + { + case 1: new_event->watching = watch_core_le_1; break; + case 2: new_event->watching = watch_core_le_2; break; + case 4: new_event->watching = watch_core_le_4; break; + case 8: new_event->watching = watch_core_le_8; break; + default: sim_io_error (sd, "sim_events_watch_core - invalid nr bytes"); + } + break; + default: + sim_io_error (sd, "sim_events_watch_core - invalid byte order"); + } + /* handler */ + new_event->data = data; + new_event->handler = handler; + /* data */ + new_event->core_addr = core_addr; + new_event->core_map = core_map; + new_event->lb = lb; + new_event->lb64 = lb; + new_event->ub = ub; + new_event->ub64 = ub; + new_event->is_within = (is_within != 0); + /* insert */ + new_event->next = events->watchpoints; + events->watchpoints = new_event; + events->work_pending = 1; + ETRACE ((_ETRACE, + "event watching host at %ld - tag 0x%lx - host-addr 0x%lx, 0x%lx..0x%lx, handler 0x%lx, data 0x%lx\n", + (long)sim_events_time (sd), + (long)new_event, + (long)new_event->host_addr, + (long)new_event->lb, + (long)new_event->ub, + (long)new_event->handler, + (long)new_event->data)); + return new_event; +} +#endif + + +#if EXTERN_SIM_EVENTS_P +void +sim_events_deschedule (SIM_DESC sd, + sim_event *event_to_remove) +{ + sim_events *events = STATE_EVENTS (sd); + sim_event *to_remove = (sim_event*)event_to_remove; + if (event_to_remove != NULL) + { + sim_event **queue = NULL; + while ((queue = next_event_queue (sd, queue)) != NULL) + { + sim_event **ptr_to_current; + for (ptr_to_current = queue; + *ptr_to_current != NULL && *ptr_to_current != to_remove; + ptr_to_current = &(*ptr_to_current)->next); + if (*ptr_to_current == to_remove) + { + sim_event *dead = *ptr_to_current; + *ptr_to_current = dead->next; + ETRACE ((_ETRACE, + "event/watch descheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx%s%s\n", + (long) sim_events_time (sd), + (long) event_to_remove, + (long) dead->time_of_event, + (long) dead->handler, + (long) dead->data, + (dead->trace != NULL) ? ", " : "", + (dead->trace != NULL) ? dead->trace : "")); + sim_events_free (sd, dead); + update_time_from_event (sd); + SIM_ASSERT ((events->time_from_event >= 0) == (events->queue != NULL)); + return; + } + } + } + ETRACE ((_ETRACE, + "event/watch descheduled at %ld - tag 0x%lx - not found\n", + (long) sim_events_time (sd), + (long) event_to_remove)); +} +#endif + + +STATIC_INLINE_SIM_EVENTS\ +(int) +sim_watch_valid (SIM_DESC sd, + sim_event *to_do) +{ + switch (to_do->watching) + { + +#define WATCH_CORE(N,OP,EXT) \ + int ok; \ + unsigned_##N word = 0; \ + int nr_read = sim_core_read_buffer (sd, NULL, to_do->core_map, &word, \ + to_do->core_addr, sizeof (word)); \ + OP (word); \ + ok = (nr_read == sizeof (unsigned_##N) \ + && (to_do->is_within \ + == (word >= to_do->lb##EXT \ + && word <= to_do->ub##EXT))); + + case watch_core_targ_1: + { + WATCH_CORE (1, T2H,); + return ok; + } + case watch_core_targ_2: + { + WATCH_CORE (2, T2H,); + return ok; + } + case watch_core_targ_4: + { + WATCH_CORE (4, T2H,); + return ok; + } + case watch_core_targ_8: + { + WATCH_CORE (8, T2H,64); + return ok; + } + + case watch_core_be_1: + { + WATCH_CORE (1, BE2H,); + return ok; + } + case watch_core_be_2: + { + WATCH_CORE (2, BE2H,); + return ok; + } + case watch_core_be_4: + { + WATCH_CORE (4, BE2H,); + return ok; + } + case watch_core_be_8: + { + WATCH_CORE (8, BE2H,64); + return ok; + } + + case watch_core_le_1: + { + WATCH_CORE (1, LE2H,); + return ok; + } + case watch_core_le_2: + { + WATCH_CORE (2, LE2H,); + return ok; + } + case watch_core_le_4: + { + WATCH_CORE (4, LE2H,); + return ok; + } + case watch_core_le_8: + { + WATCH_CORE (8, LE2H,64); + return ok; + } +#undef WATCH_CORE + +#define WATCH_SIM(N,OP,EXT) \ + int ok; \ + unsigned_##N word = *(unsigned_##N*)to_do->host_addr; \ + OP (word); \ + ok = (to_do->is_within \ + == (word >= to_do->lb##EXT \ + && word <= to_do->ub##EXT)); + + case watch_sim_host_1: + { + WATCH_SIM (1, word = ,); + return ok; + } + case watch_sim_host_2: + { + WATCH_SIM (2, word = ,); + return ok; + } + case watch_sim_host_4: + { + WATCH_SIM (4, word = ,); + return ok; + } + case watch_sim_host_8: + { + WATCH_SIM (8, word = ,64); + return ok; + } + + case watch_sim_be_1: + { + WATCH_SIM (1, BE2H,); + return ok; + } + case watch_sim_be_2: + { + WATCH_SIM (2, BE2H,); + return ok; + } + case watch_sim_be_4: + { + WATCH_SIM (4, BE2H,); + return ok; + } + case watch_sim_be_8: + { + WATCH_SIM (8, BE2H,64); + return ok; + } + + case watch_sim_le_1: + { + WATCH_SIM (1, LE2H,); + return ok; + } + case watch_sim_le_2: + { + WATCH_SIM (1, LE2H,); + return ok; + } + case watch_sim_le_4: + { + WATCH_SIM (1, LE2H,); + return ok; + } + case watch_sim_le_8: + { + WATCH_SIM (1, LE2H,64); + return ok; + } +#undef WATCH_SIM + + case watch_clock: /* wallclock */ + { + unsigned long elapsed_time = sim_events_elapsed_time (sd); + return (elapsed_time >= to_do->wallclock); + } + + default: + sim_io_error (sd, "sim_watch_valid - bad switch"); + break; + + } + return 1; +} + + +INLINE_SIM_EVENTS\ +(int) +sim_events_tick (SIM_DESC sd) +{ + sim_events *events = STATE_EVENTS (sd); + + /* this should only be called after the previous ticks have been + fully processed */ + + /* Advance the time but *only* if there is nothing to process */ + if (events->work_pending + || events->time_from_event == 0) + { + events->nr_ticks_to_process += 1; + return 1; + } + else + { + events->time_from_event -= 1; + return 0; + } +} + + +INLINE_SIM_EVENTS\ +(int) +sim_events_tickn (SIM_DESC sd, + int n) +{ + sim_events *events = STATE_EVENTS (sd); + SIM_ASSERT (n > 0); + + /* this should only be called after the previous ticks have been + fully processed */ + + /* Advance the time but *only* if there is nothing to process */ + if (events->work_pending || events->time_from_event < n) + { + events->nr_ticks_to_process += n; + return 1; + } + else + { + events->time_from_event -= n; + return 0; + } +} + + +INLINE_SIM_EVENTS\ +(void) +sim_events_slip (SIM_DESC sd, + int slip) +{ + sim_events *events = STATE_EVENTS (sd); + SIM_ASSERT (slip > 0); + + /* Flag a ready event with work_pending instead of number of ticks + to process so that the time continues to be correct */ + if (events->time_from_event < slip) + { + events->work_pending = 1; + } + events->time_from_event -= slip; +} + + +INLINE_SIM_EVENTS\ +(void) +sim_events_preprocess (SIM_DESC sd, + int events_were_last, + int events_were_next) +{ + sim_events *events = STATE_EVENTS(sd); + if (events_were_last) + { + /* Halted part way through event processing */ + ASSERT (events->nr_ticks_to_process != 0); + /* The external world can't tell if the event that stopped the + simulator was the last event to process. */ + ASSERT (events_were_next); + sim_events_process (sd); + } + else if (events_were_next) + { + /* Halted by the last processor */ + if (sim_events_tick (sd)) + sim_events_process (sd); + } +} + + +INLINE_SIM_EVENTS\ +(void) +sim_events_process (SIM_DESC sd) +{ + sim_events *events = STATE_EVENTS(sd); + signed64 event_time = sim_events_time(sd); + + /* Clear work_pending before checking nr_held. Clearing + work_pending after nr_held (with out a lock could loose an + event). */ + events->work_pending = 0; + + /* move any events that were asynchronously queued by any signal + handlers onto the real event queue. */ + if (events->nr_held > 0) + { + int i; + +#if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK) + /*-LOCK-*/ + sigset_t old_mask; + sigset_t new_mask; + sigfillset(&new_mask); + sigprocmask(SIG_SETMASK, &new_mask, &old_mask); +#endif + + for (i = 0; i < events->nr_held; i++) + { + sim_event *entry = &events->held [i]; + sim_events_schedule (sd, + entry->time_of_event, + entry->handler, + entry->data); + } + events->nr_held = 0; + +#if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK) + /*-UNLOCK-*/ + sigprocmask(SIG_SETMASK, &old_mask, NULL); +#endif + + } + + /* Process any watchpoints. Be careful to allow a watchpoint to + appear/disappear under our feet. + To ensure that watchpoints are processed only once per cycle, + they are moved onto a watched queue, this returned to the + watchpoint queue when all queue processing has been + completed. */ + while (events->watchpoints != NULL) + { + sim_event *to_do = events->watchpoints; + events->watchpoints = to_do->next; + if (sim_watch_valid (sd, to_do)) + { + sim_event_handler *handler = to_do->handler; + void *data = to_do->data; + ETRACE((_ETRACE, + "event issued at %ld - tag 0x%lx - handler 0x%lx, data 0x%lx%s%s\n", + (long) event_time, + (long) to_do, + (long) handler, + (long) data, + (to_do->trace != NULL) ? ", " : "", + (to_do->trace != NULL) ? to_do->trace : "")); + sim_events_free (sd, to_do); + handler (sd, data); + } + else + { + to_do->next = events->watchedpoints; + events->watchedpoints = to_do; + } + } + + /* consume all events for this or earlier times. Be careful to + allow an event to appear/disappear under our feet */ + while (events->queue->time_of_event < + (event_time + events->nr_ticks_to_process)) + { + sim_event *to_do = events->queue; + sim_event_handler *handler = to_do->handler; + void *data = to_do->data; + events->queue = to_do->next; + update_time_from_event (sd); + ETRACE((_ETRACE, + "event issued at %ld - tag 0x%lx - handler 0x%lx, data 0x%lx%s%s\n", + (long) event_time, + (long) to_do, + (long) handler, + (long) data, + (to_do->trace != NULL) ? ", " : "", + (to_do->trace != NULL) ? to_do->trace : "")); + sim_events_free (sd, to_do); + handler (sd, data); + } + + /* put things back where they belong ready for the next iteration */ + events->watchpoints = events->watchedpoints; + events->watchedpoints = NULL; + if (events->watchpoints != NULL) + events->work_pending = 1; + + /* advance the time */ + SIM_ASSERT (events->time_from_event >= events->nr_ticks_to_process); + SIM_ASSERT (events->queue != NULL); /* always poll event */ + events->time_from_event -= events->nr_ticks_to_process; + + /* this round of processing complete */ + events->nr_ticks_to_process = 0; + +#if __CYGWIN32__ + /* Now call the ui_loop_hook to give the gui a chance to + process events. */ + + if (ui_loop_hook != NULL) + { + /* attempt to limit calls to 1-10 per second */ + if (! (ui_loop_hook_counter++ & 0xf)) + (*ui_loop_hook) (-2); /* magic */ + } +#endif +} + +#endif diff --git a/sim/common/sim-events.h b/sim/common/sim-events.h new file mode 100644 index 00000000000..3bae3dfbdef --- /dev/null +++ b/sim/common/sim-events.h @@ -0,0 +1,271 @@ +/* This file is part of the program psim. + + Copyright (C) 1994-1997, Andrew Cagney + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + + +#ifndef SIM_EVENTS_H +#define SIM_EVENTS_H + + +/* Notes: + + When scheduling an event, the a delta of zero/one refers to the + timeline as follows: + + epoch 0|1 1|2 2|3 3| + **queue**|--insn--|*queue*|--insn--|*queue*|--insn--|*queue*| + | ^ ^ | ^ ^ + `- +0 ------------ +1 --.. `----- +0 ------------- +1 --.. + + When the queue is initialized, the time is set to zero with a + number of initialization events scheduled. Consequently, as also + illustrated above, the event queue should be processed before the + first instruction. That instruction being executed during tick 1. + + The simulator main loop may take a form similar to: + + if (halt-/restart-setjmp) + { + + .... // Determine who should go next + last-cpu-nr = get-last-cpu-nr (sd); + next-cpu-nr = get-next-cpu-nr (sd); + events-were-last? = (last-cpu-nr >= nr-cpus); + events-were-next? = (next-cpu-nr >= nr-cpus); + + .... // process any outstanding events + sim_events_preprocess (sd, events-were-last?, events-were-next?); + if (events-were-next) + next-cpu-nr = 0; + + .... // prime main loop + + while (1) + { + .... // model one insn of next-cpu-nr .. nr-cpus + if (sim_events_tick (sd)) + sim_events_process (sd); + next-cpu-nr = 0 + } + } + + NB. In the above pseudo code it is assumed that any cpu-nr >= + nr-cpus is a marker for the event queue. */ + + +typedef void sim_event_handler(SIM_DESC sd, void *data); + +typedef struct _sim_event sim_event; + +typedef struct _sim_events sim_events; +struct _sim_events { + int nr_ticks_to_process; + sim_event *queue; + sim_event *watchpoints; + sim_event *watchedpoints; + sim_event *free_list; + /* flag additional work needed */ + volatile int work_pending; + /* the asynchronous event queue */ +#ifndef MAX_NR_SIGNAL_SIM_EVENTS +#define MAX_NR_SIGNAL_SIM_EVENTS 2 +#endif + sim_event *held; + volatile int nr_held; + /* timekeeping */ + unsigned long elapsed_wallclock; + SIM_ELAPSED_TIME resume_wallclock; + signed64 time_of_event; + int time_from_event; + int trace; +}; + + + +/* Install the "events" module. */ + +extern SIM_RC sim_events_install (SIM_DESC sd); + + +/* Schedule an event DELTA_TIME ticks into the future */ + +extern sim_event *sim_events_schedule +(SIM_DESC sd, + signed64 delta_time, + sim_event_handler *handler, + void *data); + +extern sim_event *sim_events_schedule_tracef +(SIM_DESC sd, + signed64 delta_time, + sim_event_handler *handler, + void *data, + const char *fmt, + ...) __attribute__ ((format (printf, 5, 6))); + +extern sim_event *sim_events_schedule_vtracef +(SIM_DESC sd, + signed64 delta_time, + sim_event_handler *handler, + void *data, + const char *fmt, + va_list ap); + + +extern void sim_events_schedule_after_signal +(SIM_DESC sd, + signed64 delta_time, + sim_event_handler *handler, + void *data); + +/* NB: signal level events can't have trace strings as malloc isn't + available */ + + + +/* Schedule an event milli-seconds from NOW. The exact interpretation + of wallclock is host dependant. */ + +extern sim_event *sim_events_watch_clock +(SIM_DESC sd, + unsigned delta_ms_time, + sim_event_handler *handler, + void *data); + + +/* Schedule an event when the test (IS_WITHIN == (VAL >= LB && VAL <= + UB)) of the NR_BYTES value at HOST_ADDR with BYTE_ORDER endian is + true. + + HOST_ADDR: pointer into the host address space. + BYTE_ORDER: 0 - host endian; BIG_ENDIAN; LITTLE_ENDIAN */ + +extern sim_event *sim_events_watch_sim +(SIM_DESC sd, + void *host_addr, + int nr_bytes, + int byte_order, + int is_within, + unsigned64 lb, + unsigned64 ub, + sim_event_handler *handler, + void *data); + + +/* Schedule an event when the test (IS_WITHIN == (VAL >= LB && VAL <= + UB)) of the NR_BYTES value at CORE_ADDR in BYTE_ORDER endian is + true. + + CORE_ADDR/MAP: pointer into the target address space. + BYTE_ORDER: 0 - current target endian; BIG_ENDIAN; LITTLE_ENDIAN */ + +extern sim_event *sim_events_watch_core +(SIM_DESC sd, + address_word core_addr, + unsigned map, + int nr_bytes, + int byte_order, + int is_within, + unsigned64 lb, + unsigned64 ub, + sim_event_handler *handler, + void *data); + +/* Deschedule the specified event */ + +extern void sim_events_deschedule +(SIM_DESC sd, + sim_event *event_to_remove); + + +/* Prepare for main simulator loop. Ensure that the next thing to do + is not event processing. + + If the simulator halted part way through event processing then both + EVENTS_WERE_LAST and EVENTS_WERE_NEXT shall be true. + + If the simulator halted after processing the last cpu, then only + EVENTS_WERE_NEXT shall be true. */ + +INLINE_SIM_EVENTS\ +(void) sim_events_preprocess +(SIM_DESC sd, + int events_were_last, + int events_were_next); + + +/* Progress time. + + Separated into two parts so that the main loop can save its context + before the event queue is processed. When sim_events_tick*() + returns true, any simulation context should be saved and + sim_events_process() called. + + SIM_EVENTS_TICK advances the clock by 1 cycle. + + SIM_EVENTS_TICKN advances the clock by N cycles (1..MAXINT). */ + +INLINE_SIM_EVENTS\ +(int) sim_events_tick +(SIM_DESC sd); + +INLINE_SIM_EVENTS\ +(int) sim_events_tickn +(SIM_DESC sd, + int n); + +INLINE_SIM_EVENTS\ +(void) sim_events_process +(SIM_DESC sd); + + +/* Advance the clock by an additional SLIP cycles at the next call to + sim_events_tick*(). For multiple calls, the effect is + accumulative. */ + +INLINE_SIM_EVENTS\ +(void) sim_events_slip +(SIM_DESC sd, + int slip); + + +/* Progress time such that an event shall occure upon the next call to + sim_events tick */ + +#if 0 +INLINE_SIM_EVENTS\ +(void) sim_events_timewarp +(SIM_DESC sd); +#endif + + +/* local concept of elapsed target time */ + +INLINE_SIM_EVENTS\ +(signed64) sim_events_time +(SIM_DESC sd); + + +/* local concept of elapsed host time (milliseconds) */ + +INLINE_SIM_EVENTS\ +(unsigned long) sim_events_elapsed_time +(SIM_DESC sd); + +#endif diff --git a/sim/common/sim-fpu.c b/sim/common/sim-fpu.c new file mode 100644 index 00000000000..abf746a9b68 --- /dev/null +++ b/sim/common/sim-fpu.c @@ -0,0 +1,2578 @@ +/* This is a software floating point library which can be used instead + of the floating point routines in libgcc1.c for targets without + hardware floating point. */ + +/* Copyright (C) 1994,1997-1998 Free Software Foundation, Inc. + +This file is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +In addition to the permissions in the GNU General Public License, the +Free Software Foundation gives you unlimited permission to link the +compiled version of this file with other programs, and to distribute +those programs without any restriction coming from the use of this +file. (The General Public License restrictions do apply in other +respects; for example, they cover modification of the file, and +distribution when not linked into another program.) + +This file 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 +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* As a special exception, if you link this library with other files, + some of which are compiled with GCC, to produce an executable, + this library does not by itself cause the resulting executable + to be covered by the GNU General Public License. + This exception does not however invalidate any other reasons why + the executable file might be covered by the GNU General Public License. */ + +/* This implements IEEE 754 format arithmetic, but does not provide a + mechanism for setting the rounding mode, or for generating or handling + exceptions. + + The original code by Steve Chamberlain, hacked by Mark Eichin and Jim + Wilson, all of Cygnus Support. */ + + +#ifndef SIM_FPU_C +#define SIM_FPU_C + +#include "sim-basics.h" +#include "sim-fpu.h" + +#include "sim-io.h" +#include "sim-assert.h" + + +/* Debugging support. */ + +static void +print_bits (unsigned64 x, + int msbit, + sim_fpu_print_func print, + void *arg) +{ + unsigned64 bit = LSBIT64 (msbit); + int i = 4; + while (bit) + { + if (i == 0) + print (arg, ","); + if ((x & bit)) + print (arg, "1"); + else + print (arg, "0"); + bit >>= 1; + i = (i + 1) % 4; + } +} + + + +/* Quick and dirty conversion between a host double and host 64bit int */ + +typedef union { + double d; + unsigned64 i; +} sim_fpu_map; + + +/* A packed IEEE floating point number. + + Form is for both + 32 and 64 bit numbers. This number is interpreted as: + + Normalized (0 < BIASEDEXP && BIASEDEXP < EXPMAX): + (sign ? '-' : '+') 1. x 2 ^ (BIASEDEXP - EXPBIAS) + + Denormalized (0 == BIASEDEXP && FRAC != 0): + (sign ? "-" : "+") 0. x 2 ^ (- EXPBIAS) + + Zero (0 == BIASEDEXP && FRAC == 0): + (sign ? "-" : "+") 0.0 + + Infinity (BIASEDEXP == EXPMAX && FRAC == 0): + (sign ? "-" : "+") "infinity" + + SignalingNaN (BIASEDEXP == EXPMAX && FRAC > 0 && FRAC < QUIET_NAN): + SNaN.FRAC + + QuietNaN (BIASEDEXP == EXPMAX && FRAC > 0 && FRAC > QUIET_NAN): + QNaN.FRAC + + */ + +#define NR_EXPBITS (is_double ? 11 : 8) +#define NR_FRACBITS (is_double ? 52 : 23) +#define SIGNBIT (is_double ? MSBIT64 (0) : MSBIT64 (32)) + +#define EXPMAX32 (255) +#define EXMPAX64 (2047) +#define EXPMAX ((unsigned) (is_double ? EXMPAX64 : EXPMAX32)) + +#define EXPBIAS32 (127) +#define EXPBIAS64 (1023) +#define EXPBIAS (is_double ? EXPBIAS64 : EXPBIAS32) + +#define QUIET_NAN LSBIT64 (NR_FRACBITS - 1) + + + +/* An unpacked floating point number. + + When unpacked, the fraction of both a 32 and 64 bit floating point + number is stored using the same format: + + 64 bit - + 32 bit - */ + +#define NR_PAD32 (30) +#define NR_PAD64 (0) +#define NR_PAD (is_double ? NR_PAD64 : NR_PAD32) +#define PADMASK (is_double ? 0 : LSMASK64 (NR_PAD32 - 1, 0)) + +#define NR_GUARDS32 (7 + NR_PAD32) +#define NR_GUARDS64 (8 + NR_PAD64) +#define NR_GUARDS (is_double ? NR_GUARDS64 : NR_GUARDS32) +#define GUARDMASK LSMASK64 (NR_GUARDS - 1, 0) + +#define GUARDMSB LSBIT64 (NR_GUARDS - 1) +#define GUARDLSB LSBIT64 (NR_PAD) +#define GUARDROUND LSMASK64 (NR_GUARDS - 2, 0) + +#define NR_FRAC_GUARD (60) +#define IMPLICIT_1 LSBIT64 (NR_FRAC_GUARD) +#define IMPLICIT_2 LSBIT64 (NR_FRAC_GUARD + 1) +#define IMPLICIT_4 LSBIT64 (NR_FRAC_GUARD + 2) +#define NR_SPARE 2 + +#define FRAC32MASK LSMASK64 (63, NR_FRAC_GUARD - 32 + 1) + +#define NORMAL_EXPMIN (-(EXPBIAS)+1) + +#define NORMAL_EXPMAX32 (EXPBIAS32) +#define NORMAL_EXPMAX64 (EXPBIAS64) +#define NORMAL_EXPMAX (EXPBIAS) + + +/* Integer constants */ + +#define MAX_INT32 ((signed64) LSMASK64 (30, 0)) +#define MAX_UINT32 LSMASK64 (31, 0) +#define MIN_INT32 ((signed64) LSMASK64 (63, 31)) + +#define MAX_INT64 ((signed64) LSMASK64 (62, 0)) +#define MAX_UINT64 LSMASK64 (63, 0) +#define MIN_INT64 ((signed64) LSMASK64 (63, 63)) + +#define MAX_INT (is_64bit ? MAX_INT64 : MAX_INT32) +#define MIN_INT (is_64bit ? MIN_INT64 : MIN_INT32) +#define MAX_UINT (is_64bit ? MAX_UINT64 : MAX_UINT32) +#define NR_INTBITS (is_64bit ? 64 : 32) + +/* Squeese an unpacked sim_fpu struct into a 32/64 bit integer */ +STATIC_INLINE_SIM_FPU (unsigned64) +pack_fpu (const sim_fpu *src, + int is_double) +{ + int sign; + unsigned64 exp; + unsigned64 fraction; + unsigned64 packed; + + switch (src->class) + { + /* create a NaN */ + case sim_fpu_class_qnan: + sign = src->sign; + exp = EXPMAX; + /* force fraction to correct class */ + fraction = src->fraction; + fraction >>= NR_GUARDS; + fraction |= QUIET_NAN; + break; + case sim_fpu_class_snan: + sign = src->sign; + exp = EXPMAX; + /* force fraction to correct class */ + fraction = src->fraction; + fraction >>= NR_GUARDS; + fraction &= ~QUIET_NAN; + break; + case sim_fpu_class_infinity: + sign = src->sign; + exp = EXPMAX; + fraction = 0; + break; + case sim_fpu_class_zero: + sign = src->sign; + exp = 0; + fraction = 0; + break; + case sim_fpu_class_number: + case sim_fpu_class_denorm: + ASSERT (src->fraction >= IMPLICIT_1); + ASSERT (src->fraction < IMPLICIT_2); + if (src->normal_exp < NORMAL_EXPMIN) + { + /* This number's exponent is too low to fit into the bits + available in the number We'll denormalize the number by + storing zero in the exponent and shift the fraction to + the right to make up for it. */ + int nr_shift = NORMAL_EXPMIN - src->normal_exp; + if (nr_shift > NR_FRACBITS) + { + /* underflow, just make the number zero */ + sign = src->sign; + exp = 0; + fraction = 0; + } + else + { + sign = src->sign; + exp = 0; + /* Shift by the value */ + fraction = src->fraction; + fraction >>= NR_GUARDS; + fraction >>= nr_shift; + } + } + else if (src->normal_exp > NORMAL_EXPMAX) + { + /* Infinity */ + sign = src->sign; + exp = EXPMAX; + fraction = 0; + } + else + { + exp = (src->normal_exp + EXPBIAS); + sign = src->sign; + fraction = src->fraction; + /* FIXME: Need to round according to WITH_SIM_FPU_ROUNDING + or some such */ + /* Round to nearest: If the guard bits are the all zero, but + the first, then we're half way between two numbers, + choose the one which makes the lsb of the answer 0. */ + if ((fraction & GUARDMASK) == GUARDMSB) + { + if ((fraction & (GUARDMSB << 1))) + fraction += (GUARDMSB << 1); + } + else + { + /* Add a one to the guards to force round to nearest */ + fraction += GUARDROUND; + } + if ((fraction & IMPLICIT_2)) /* rounding resulted in carry */ + { + exp += 1; + fraction >>= 1; + } + fraction >>= NR_GUARDS; + /* When exp == EXPMAX (overflow from carry) fraction must + have been made zero */ + ASSERT ((exp == EXPMAX) <= ((fraction & ~IMPLICIT_1) == 0)); + } + break; + default: + abort (); + } + + packed = ((sign ? SIGNBIT : 0) + | (exp << NR_FRACBITS) + | LSMASKED64 (fraction, NR_FRACBITS - 1, 0)); + + /* trace operation */ +#if 0 + if (is_double) + { + } + else + { + printf ("pack_fpu: "); + printf ("-> %c%0lX.%06lX\n", + LSMASKED32 (packed, 31, 31) ? '8' : '0', + (long) LSEXTRACTED32 (packed, 30, 23), + (long) LSEXTRACTED32 (packed, 23 - 1, 0)); + } +#endif + + return packed; +} + + +/* Unpack a 32/64 bit integer into a sim_fpu structure */ +STATIC_INLINE_SIM_FPU (void) +unpack_fpu (sim_fpu *dst, unsigned64 packed, int is_double) +{ + unsigned64 fraction = LSMASKED64 (packed, NR_FRACBITS - 1, 0); + unsigned exp = LSEXTRACTED64 (packed, NR_EXPBITS + NR_FRACBITS - 1, NR_FRACBITS); + int sign = (packed & SIGNBIT) != 0; + + if (exp == 0) + { + /* Hmm. Looks like 0 */ + if (fraction == 0) + { + /* tastes like zero */ + dst->class = sim_fpu_class_zero; + dst->sign = sign; + } + else + { + /* Zero exponent with non zero fraction - it's denormalized, + so there isn't a leading implicit one - we'll shift it so + it gets one. */ + dst->normal_exp = exp - EXPBIAS + 1; + dst->class = sim_fpu_class_denorm; + dst->sign = sign; + fraction <<= NR_GUARDS; + while (fraction < IMPLICIT_1) + { + fraction <<= 1; + dst->normal_exp--; + } + dst->fraction = fraction; + } + } + else if (exp == EXPMAX) + { + /* Huge exponent*/ + if (fraction == 0) + { + /* Attached to a zero fraction - means infinity */ + dst->class = sim_fpu_class_infinity; + dst->sign = sign; + /* dst->normal_exp = EXPBIAS; */ + /* dst->fraction = 0; */ + } + else + { + /* Non zero fraction, means NaN */ + dst->sign = sign; + dst->fraction = (fraction << NR_GUARDS); + if (fraction >= QUIET_NAN) + dst->class = sim_fpu_class_qnan; + else + dst->class = sim_fpu_class_snan; + } + } + else + { + /* Nothing strange about this number */ + dst->class = sim_fpu_class_number; + dst->sign = sign; + dst->fraction = ((fraction << NR_GUARDS) | IMPLICIT_1); + dst->normal_exp = exp - EXPBIAS; + } + + /* trace operation */ +#if 0 + if (is_double) + { + } + else + { + printf ("unpack_fpu: %c%02lX.%06lX ->\n", + LSMASKED32 (packed, 31, 31) ? '8' : '0', + (long) LSEXTRACTED32 (packed, 30, 23), + (long) LSEXTRACTED32 (packed, 23 - 1, 0)); + } +#endif + + /* sanity checks */ + { + sim_fpu_map val; + val.i = pack_fpu (dst, 1); + if (is_double) + { + ASSERT (val.i == packed); + } + else + { + unsigned32 val = pack_fpu (dst, 0); + unsigned32 org = packed; + ASSERT (val == org); + } + } +} + + +/* Convert a floating point into an integer */ +STATIC_INLINE_SIM_FPU (int) +fpu2i (signed64 *i, + const sim_fpu *s, + int is_64bit, + sim_fpu_round round) +{ + unsigned64 tmp; + int shift; + int status = 0; + if (sim_fpu_is_zero (s)) + { + *i = 0; + return 0; + } + if (sim_fpu_is_snan (s)) + { + *i = MIN_INT; /* FIXME */ + return sim_fpu_status_invalid_cvi; + } + if (sim_fpu_is_qnan (s)) + { + *i = MIN_INT; /* FIXME */ + return sim_fpu_status_invalid_cvi; + } + /* map infinity onto MAX_INT... */ + if (sim_fpu_is_infinity (s)) + { + *i = s->sign ? MIN_INT : MAX_INT; + return sim_fpu_status_invalid_cvi; + } + /* it is a number, but a small one */ + if (s->normal_exp < 0) + { + *i = 0; + return sim_fpu_status_inexact; + } + /* Is the floating point MIN_INT or just close? */ + if (s->sign && s->normal_exp == (NR_INTBITS - 1)) + { + *i = MIN_INT; + ASSERT (s->fraction >= IMPLICIT_1); + if (s->fraction == IMPLICIT_1) + return 0; /* exact */ + if (is_64bit) /* can't round */ + return sim_fpu_status_invalid_cvi; /* must be overflow */ + /* For a 32bit with MAX_INT, rounding is possible */ + switch (round) + { + case sim_fpu_round_default: + abort (); + case sim_fpu_round_zero: + if ((s->fraction & FRAC32MASK) != IMPLICIT_1) + return sim_fpu_status_invalid_cvi; + else + return sim_fpu_status_inexact; + break; + case sim_fpu_round_near: + { + if ((s->fraction & FRAC32MASK) != IMPLICIT_1) + return sim_fpu_status_invalid_cvi; + else if ((s->fraction & !FRAC32MASK) >= (~FRAC32MASK >> 1)) + return sim_fpu_status_invalid_cvi; + else + return sim_fpu_status_inexact; + } + case sim_fpu_round_up: + if ((s->fraction & FRAC32MASK) == IMPLICIT_1) + return sim_fpu_status_inexact; + else + return sim_fpu_status_invalid_cvi; + case sim_fpu_round_down: + return sim_fpu_status_invalid_cvi; + } + } + /* Would right shifting result in the FRAC being shifted into + (through) the integer's sign bit? */ + if (s->normal_exp > (NR_INTBITS - 2)) + { + *i = s->sign ? MIN_INT : MAX_INT; + return sim_fpu_status_invalid_cvi; + } + /* normal number shift it into place */ + tmp = s->fraction; + shift = (s->normal_exp - (NR_FRAC_GUARD)); + if (shift > 0) + { + tmp <<= shift; + } + else + { + shift = -shift; + if (tmp & ((SIGNED64 (1) << shift) - 1)) + status |= sim_fpu_status_inexact; + tmp >>= shift; + } + *i = s->sign ? (-tmp) : (tmp); + return status; +} + +/* convert an integer into a floating point */ +STATIC_INLINE_SIM_FPU (int) +i2fpu (sim_fpu *f, signed64 i, int is_64bit) +{ + int status = 0; + if (i == 0) + { + f->class = sim_fpu_class_zero; + f->sign = 0; + } + else + { + f->class = sim_fpu_class_number; + f->sign = (i < 0); + f->normal_exp = NR_FRAC_GUARD; + + if (f->sign) + { + /* Special case for minint, since there is no corresponding + +ve integer representation for it */ + if (i == MIN_INT) + { + f->fraction = IMPLICIT_1; + f->normal_exp = NR_INTBITS - 1; + } + else + f->fraction = (-i); + } + else + f->fraction = i; + + if (f->fraction >= IMPLICIT_2) + { + do + { + f->fraction >>= 1; + f->normal_exp += 1; + } + while (f->fraction >= IMPLICIT_2); + } + else if (f->fraction < IMPLICIT_1) + { + do + { + f->fraction <<= 1; + f->normal_exp -= 1; + } + while (f->fraction < IMPLICIT_1); + } + } + + /* trace operation */ +#if 0 + { + printf ("i2fpu: 0x%08lX ->\n", (long) i); + } +#endif + + /* sanity check */ + { + signed64 val; + fpu2i (&val, f, is_64bit, sim_fpu_round_zero); + if (i >= MIN_INT32 && i <= MAX_INT32) + { + ASSERT (val == i); + } + } + + return status; +} + + +/* Convert a floating point into an integer */ +STATIC_INLINE_SIM_FPU (int) +fpu2u (unsigned64 *u, const sim_fpu *s, int is_64bit) +{ + const int is_double = 1; + unsigned64 tmp; + int shift; + if (sim_fpu_is_zero (s)) + { + *u = 0; + return 0; + } + if (sim_fpu_is_nan (s)) + { + *u = 0; + return 0; + } + /* it is a negative number */ + if (s->sign) + { + *u = 0; + return 0; + } + /* get reasonable MAX_USI_INT... */ + if (sim_fpu_is_infinity (s)) + { + *u = MAX_UINT; + return 0; + } + /* it is a number, but a small one */ + if (s->normal_exp < 0) + { + *u = 0; + return 0; + } + /* overflow */ + if (s->normal_exp > (NR_INTBITS - 1)) + { + *u = MAX_UINT; + return 0; + } + /* normal number */ + tmp = (s->fraction & ~PADMASK); + shift = (s->normal_exp - (NR_FRACBITS + NR_GUARDS)); + if (shift > 0) + { + tmp <<= shift; + } + else + { + shift = -shift; + tmp >>= shift; + } + *u = tmp; + return 0; +} + +/* Convert an unsigned integer into a floating point */ +STATIC_INLINE_SIM_FPU (int) +u2fpu (sim_fpu *f, unsigned64 u, int is_64bit) +{ + if (u == 0) + { + f->class = sim_fpu_class_zero; + f->sign = 0; + } + else + { + f->class = sim_fpu_class_number; + f->sign = 0; + f->normal_exp = NR_FRAC_GUARD; + f->fraction = u; + + while (f->fraction < IMPLICIT_1) + { + f->fraction <<= 1; + f->normal_exp -= 1; + } + } + return 0; +} + + +/* register <-> sim_fpu */ + +INLINE_SIM_FPU (void) +sim_fpu_32to (sim_fpu *f, unsigned32 s) +{ + unpack_fpu (f, s, 0); +} + + +INLINE_SIM_FPU (void) +sim_fpu_232to (sim_fpu *f, unsigned32 h, unsigned32 l) +{ + unsigned64 s = h; + s = (s << 32) | l; + unpack_fpu (f, s, 1); +} + + +INLINE_SIM_FPU (void) +sim_fpu_64to (sim_fpu *f, unsigned64 s) +{ + unpack_fpu (f, s, 1); +} + + +INLINE_SIM_FPU (void) +sim_fpu_to32 (unsigned32 *s, + const sim_fpu *f) +{ + *s = pack_fpu (f, 0); +} + + +INLINE_SIM_FPU (void) +sim_fpu_to232 (unsigned32 *h, unsigned32 *l, + const sim_fpu *f) +{ + unsigned64 s = pack_fpu (f, 1); + *l = s; + *h = (s >> 32); +} + + +INLINE_SIM_FPU (void) +sim_fpu_to64 (unsigned64 *u, + const sim_fpu *f) +{ + *u = pack_fpu (f, 1); +} + + +INLINE_SIM_FPU (void) +sim_fpu_fractionto (sim_fpu *f, + int sign, + int normal_exp, + unsigned64 fraction, + int precision) +{ + int shift = (NR_FRAC_GUARD - precision); + f->class = sim_fpu_class_number; + f->sign = sign; + f->normal_exp = normal_exp; + /* shift the fraction to where sim-fpu expects it */ + if (shift >= 0) + f->fraction = (fraction << shift); + else + f->fraction = (fraction >> -shift); + f->fraction |= IMPLICIT_1; +} + + +INLINE_SIM_FPU (unsigned64) +sim_fpu_tofraction (const sim_fpu *d, + int precision) +{ + /* we have NR_FRAC_GUARD bits, we want only PRECISION bits */ + int shift = (NR_FRAC_GUARD - precision); + unsigned64 fraction = (d->fraction & ~IMPLICIT_1); + if (shift >= 0) + return fraction >> shift; + else + return fraction << -shift; +} + + +/* Rounding */ + +STATIC_INLINE_SIM_FPU (int) +do_normal_overflow (sim_fpu *f, + int is_double, + sim_fpu_round round) +{ + switch (round) + { + case sim_fpu_round_default: + return 0; + case sim_fpu_round_near: + f->class = sim_fpu_class_infinity; + break; + case sim_fpu_round_up: + if (!f->sign) + f->class = sim_fpu_class_infinity; + break; + case sim_fpu_round_down: + if (f->sign) + f->class = sim_fpu_class_infinity; + break; + case sim_fpu_round_zero: + break; + } + f->normal_exp = NORMAL_EXPMAX; + f->fraction = LSMASK64 (NR_FRAC_GUARD, NR_GUARDS); + return (sim_fpu_status_overflow | sim_fpu_status_inexact); +} + +STATIC_INLINE_SIM_FPU (int) +do_normal_underflow (sim_fpu *f, + int is_double, + sim_fpu_round round) +{ + switch (round) + { + case sim_fpu_round_default: + return 0; + case sim_fpu_round_near: + f->class = sim_fpu_class_zero; + break; + case sim_fpu_round_up: + if (f->sign) + f->class = sim_fpu_class_zero; + break; + case sim_fpu_round_down: + if (!f->sign) + f->class = sim_fpu_class_zero; + break; + case sim_fpu_round_zero: + f->class = sim_fpu_class_zero; + break; + } + f->normal_exp = NORMAL_EXPMIN - NR_FRACBITS; + f->fraction = IMPLICIT_1; + return (sim_fpu_status_inexact | sim_fpu_status_underflow); +} + + + +/* Round a number using NR_GUARDS. + Will return the rounded number or F->FRACTION == 0 when underflow */ + +STATIC_INLINE_SIM_FPU (int) +do_normal_round (sim_fpu *f, + int nr_guards, + sim_fpu_round round) +{ + unsigned64 guardmask = LSMASK64 (nr_guards - 1, 0); + unsigned64 guardmsb = LSBIT64 (nr_guards - 1); + unsigned64 fraclsb = guardmsb << 1; + if ((f->fraction & guardmask)) + { + int status = sim_fpu_status_inexact; + switch (round) + { + case sim_fpu_round_default: + return 0; + case sim_fpu_round_near: + if ((f->fraction & guardmsb)) + { + if ((f->fraction & fraclsb)) + { + status |= sim_fpu_status_rounded; + } + else if ((f->fraction & (guardmask >> 1))) + { + status |= sim_fpu_status_rounded; + } + } + break; + case sim_fpu_round_up: + if (!f->sign) + status |= sim_fpu_status_rounded; + break; + case sim_fpu_round_down: + if (f->sign) + status |= sim_fpu_status_rounded; + break; + case sim_fpu_round_zero: + break; + } + f->fraction &= ~guardmask; + /* round if needed, handle resulting overflow */ + if ((status & sim_fpu_status_rounded)) + { + f->fraction += fraclsb; + if ((f->fraction & IMPLICIT_2)) + { + f->fraction >>= 1; + f->normal_exp += 1; + } + } + return status; + } + else + return 0; +} + + +STATIC_INLINE_SIM_FPU (int) +do_round (sim_fpu *f, + int is_double, + sim_fpu_round round, + sim_fpu_denorm denorm) +{ + switch (f->class) + { + case sim_fpu_class_qnan: + case sim_fpu_class_zero: + case sim_fpu_class_infinity: + return 0; + break; + case sim_fpu_class_snan: + /* Quieten a SignalingNaN */ + f->class = sim_fpu_class_qnan; + return sim_fpu_status_invalid_snan; + break; + case sim_fpu_class_number: + case sim_fpu_class_denorm: + { + int status; + ASSERT (f->fraction < IMPLICIT_2); + ASSERT (f->fraction >= IMPLICIT_1); + if (f->normal_exp < NORMAL_EXPMIN) + { + /* This number's exponent is too low to fit into the bits + available in the number. Round off any bits that will be + discarded as a result of denormalization. Edge case is + the implicit bit shifted to GUARD0 and then rounded + up. */ + int shift = NORMAL_EXPMIN - f->normal_exp; + if (shift + NR_GUARDS <= NR_FRAC_GUARD + 1 + && !(denorm & sim_fpu_denorm_zero)) + { + status = do_normal_round (f, shift + NR_GUARDS, round); + if (f->fraction == 0) /* rounding underflowed */ + { + status |= do_normal_underflow (f, is_double, round); + } + else if (f->normal_exp < NORMAL_EXPMIN) /* still underflow? */ + { + status |= sim_fpu_status_denorm; + /* Any loss of precision when denormalizing is + underflow. Some processors check for underflow + before rounding, some after! */ + if (status & sim_fpu_status_inexact) + status |= sim_fpu_status_underflow; + /* Flag that resultant value has been denormalized */ + f->class = sim_fpu_class_denorm; + } + else if ((denorm & sim_fpu_denorm_underflow_inexact)) + { + if ((status & sim_fpu_status_inexact)) + status |= sim_fpu_status_underflow; + } + } + else + { + status = do_normal_underflow (f, is_double, round); + } + } + else if (f->normal_exp > NORMAL_EXPMAX) + { + /* Infinity */ + status = do_normal_overflow (f, is_double, round); + } + else + { + status = do_normal_round (f, NR_GUARDS, round); + if (f->fraction == 0) + /* f->class = sim_fpu_class_zero; */ + status |= do_normal_underflow (f, is_double, round); + else if (f->normal_exp > NORMAL_EXPMAX) + /* oops! rounding caused overflow */ + status |= do_normal_overflow (f, is_double, round); + } + ASSERT ((f->class == sim_fpu_class_number + || f->class == sim_fpu_class_denorm) + <= (f->fraction < IMPLICIT_2 && f->fraction >= IMPLICIT_1)); + return status; + } + } + return 0; +} + +INLINE_SIM_FPU (int) +sim_fpu_round_32 (sim_fpu *f, + sim_fpu_round round, + sim_fpu_denorm denorm) +{ + return do_round (f, 0, round, denorm); +} + +INLINE_SIM_FPU (int) +sim_fpu_round_64 (sim_fpu *f, + sim_fpu_round round, + sim_fpu_denorm denorm) +{ + return do_round (f, 1, round, denorm); +} + + + +/* Arithmetic ops */ + +INLINE_SIM_FPU (int) +sim_fpu_add (sim_fpu *f, + const sim_fpu *l, + const sim_fpu *r) +{ + if (sim_fpu_is_snan (l)) + { + *f = *l; + f->class = sim_fpu_class_qnan; + return sim_fpu_status_invalid_snan; + } + if (sim_fpu_is_snan (r)) + { + *f = *r; + f->class = sim_fpu_class_qnan; + return sim_fpu_status_invalid_snan; + } + if (sim_fpu_is_qnan (l)) + { + *f = *l; + return 0; + } + if (sim_fpu_is_qnan (r)) + { + *f = *r; + return 0; + } + if (sim_fpu_is_infinity (l)) + { + if (sim_fpu_is_infinity (r) + && l->sign != r->sign) + { + *f = sim_fpu_qnan; + return sim_fpu_status_invalid_isi; + } + *f = *l; + return 0; + } + if (sim_fpu_is_infinity (r)) + { + *f = *r; + return 0; + } + if (sim_fpu_is_zero (l)) + { + if (sim_fpu_is_zero (r)) + { + *f = sim_fpu_zero; + f->sign = l->sign & r->sign; + } + else + *f = *r; + return 0; + } + if (sim_fpu_is_zero (r)) + { + *f = *l; + return 0; + } + { + int status = 0; + int shift = l->normal_exp - r->normal_exp; + unsigned64 lfraction; + unsigned64 rfraction; + /* use exp of larger */ + if (shift >= NR_FRAC_GUARD) + { + /* left has much bigger magnitute */ + *f = *l; + return sim_fpu_status_inexact; + } + if (shift <= - NR_FRAC_GUARD) + { + /* right has much bigger magnitute */ + *f = *r; + return sim_fpu_status_inexact; + } + lfraction = l->fraction; + rfraction = r->fraction; + if (shift > 0) + { + f->normal_exp = l->normal_exp; + if (rfraction & LSMASK64 (shift - 1, 0)) + { + status |= sim_fpu_status_inexact; + rfraction |= LSBIT64 (shift); /* stick LSBit */ + } + rfraction >>= shift; + } + else if (shift < 0) + { + f->normal_exp = r->normal_exp; + if (lfraction & LSMASK64 (- shift - 1, 0)) + { + status |= sim_fpu_status_inexact; + lfraction |= LSBIT64 (- shift); /* stick LSBit */ + } + lfraction >>= -shift; + } + else + { + f->normal_exp = r->normal_exp; + } + + /* perform the addition */ + if (l->sign) + lfraction = - lfraction; + if (r->sign) + rfraction = - rfraction; + f->fraction = lfraction + rfraction; + + /* zero? */ + if (f->fraction == 0) + { + *f = sim_fpu_zero; + return 0; + } + + /* sign? */ + f->class = sim_fpu_class_number; + if ((signed64) f->fraction >= 0) + f->sign = 0; + else + { + f->sign = 1; + f->fraction = - f->fraction; + } + + /* normalize it */ + if ((f->fraction & IMPLICIT_2)) + { + f->fraction = (f->fraction >> 1) | (f->fraction & 1); + f->normal_exp ++; + } + else if (f->fraction < IMPLICIT_1) + { + do + { + f->fraction <<= 1; + f->normal_exp --; + } + while (f->fraction < IMPLICIT_1); + } + ASSERT (f->fraction >= IMPLICIT_1 && f->fraction < IMPLICIT_2); + return status; + } +} + + +INLINE_SIM_FPU (int) +sim_fpu_sub (sim_fpu *f, + const sim_fpu *l, + const sim_fpu *r) +{ + if (sim_fpu_is_snan (l)) + { + *f = *l; + f->class = sim_fpu_class_qnan; + return sim_fpu_status_invalid_snan; + } + if (sim_fpu_is_snan (r)) + { + *f = *r; + f->class = sim_fpu_class_qnan; + return sim_fpu_status_invalid_snan; + } + if (sim_fpu_is_qnan (l)) + { + *f = *l; + return 0; + } + if (sim_fpu_is_qnan (r)) + { + *f = *r; + return 0; + } + if (sim_fpu_is_infinity (l)) + { + if (sim_fpu_is_infinity (r) + && l->sign == r->sign) + { + *f = sim_fpu_qnan; + return sim_fpu_status_invalid_isi; + } + *f = *l; + return 0; + } + if (sim_fpu_is_infinity (r)) + { + *f = *r; + f->sign = !r->sign; + return 0; + } + if (sim_fpu_is_zero (l)) + { + if (sim_fpu_is_zero (r)) + { + *f = sim_fpu_zero; + f->sign = l->sign & !r->sign; + } + else + { + *f = *r; + f->sign = !r->sign; + } + return 0; + } + if (sim_fpu_is_zero (r)) + { + *f = *l; + return 0; + } + { + int status = 0; + int shift = l->normal_exp - r->normal_exp; + unsigned64 lfraction; + unsigned64 rfraction; + /* use exp of larger */ + if (shift >= NR_FRAC_GUARD) + { + /* left has much bigger magnitute */ + *f = *l; + return sim_fpu_status_inexact; + } + if (shift <= - NR_FRAC_GUARD) + { + /* right has much bigger magnitute */ + *f = *r; + f->sign = !r->sign; + return sim_fpu_status_inexact; + } + lfraction = l->fraction; + rfraction = r->fraction; + if (shift > 0) + { + f->normal_exp = l->normal_exp; + if (rfraction & LSMASK64 (shift - 1, 0)) + { + status |= sim_fpu_status_inexact; + rfraction |= LSBIT64 (shift); /* stick LSBit */ + } + rfraction >>= shift; + } + else if (shift < 0) + { + f->normal_exp = r->normal_exp; + if (lfraction & LSMASK64 (- shift - 1, 0)) + { + status |= sim_fpu_status_inexact; + lfraction |= LSBIT64 (- shift); /* stick LSBit */ + } + lfraction >>= -shift; + } + else + { + f->normal_exp = r->normal_exp; + } + + /* perform the subtraction */ + if (l->sign) + lfraction = - lfraction; + if (!r->sign) + rfraction = - rfraction; + f->fraction = lfraction + rfraction; + + /* zero? */ + if (f->fraction == 0) + { + *f = sim_fpu_zero; + return 0; + } + + /* sign? */ + f->class = sim_fpu_class_number; + if ((signed64) f->fraction >= 0) + f->sign = 0; + else + { + f->sign = 1; + f->fraction = - f->fraction; + } + + /* normalize it */ + if ((f->fraction & IMPLICIT_2)) + { + f->fraction = (f->fraction >> 1) | (f->fraction & 1); + f->normal_exp ++; + } + else if (f->fraction < IMPLICIT_1) + { + do + { + f->fraction <<= 1; + f->normal_exp --; + } + while (f->fraction < IMPLICIT_1); + } + ASSERT (f->fraction >= IMPLICIT_1 && f->fraction < IMPLICIT_2); + return status; + } +} + + +INLINE_SIM_FPU (int) +sim_fpu_mul (sim_fpu *f, + const sim_fpu *l, + const sim_fpu *r) +{ + if (sim_fpu_is_snan (l)) + { + *f = *l; + f->class = sim_fpu_class_qnan; + return sim_fpu_status_invalid_snan; + } + if (sim_fpu_is_snan (r)) + { + *f = *r; + f->class = sim_fpu_class_qnan; + return sim_fpu_status_invalid_snan; + } + if (sim_fpu_is_qnan (l)) + { + *f = *l; + return 0; + } + if (sim_fpu_is_qnan (r)) + { + *f = *r; + return 0; + } + if (sim_fpu_is_infinity (l)) + { + if (sim_fpu_is_zero (r)) + { + *f = sim_fpu_qnan; + return sim_fpu_status_invalid_imz; + } + *f = *l; + f->sign = l->sign ^ r->sign; + return 0; + } + if (sim_fpu_is_infinity (r)) + { + if (sim_fpu_is_zero (l)) + { + *f = sim_fpu_qnan; + return sim_fpu_status_invalid_imz; + } + *f = *r; + f->sign = l->sign ^ r->sign; + return 0; + } + if (sim_fpu_is_zero (l) || sim_fpu_is_zero (r)) + { + *f = sim_fpu_zero; + f->sign = l->sign ^ r->sign; + return 0; + } + /* Calculate the mantissa by multiplying both 64bit numbers to get a + 128 bit number */ + { + unsigned64 low; + unsigned64 high; + unsigned64 nl = l->fraction & 0xffffffff; + unsigned64 nh = l->fraction >> 32; + unsigned64 ml = r->fraction & 0xffffffff; + unsigned64 mh = r->fraction >>32; + unsigned64 pp_ll = ml * nl; + unsigned64 pp_hl = mh * nl; + unsigned64 pp_lh = ml * nh; + unsigned64 pp_hh = mh * nh; + unsigned64 res2 = 0; + unsigned64 res0 = 0; + unsigned64 ps_hh__ = pp_hl + pp_lh; + if (ps_hh__ < pp_hl) + res2 += UNSIGNED64 (0x100000000); + pp_hl = (ps_hh__ << 32) & UNSIGNED64 (0xffffffff00000000); + res0 = pp_ll + pp_hl; + if (res0 < pp_ll) + res2++; + res2 += ((ps_hh__ >> 32) & 0xffffffff) + pp_hh; + high = res2; + low = res0; + + f->normal_exp = l->normal_exp + r->normal_exp; + f->sign = l->sign ^ r->sign; + f->class = sim_fpu_class_number; + + /* Input is bounded by [1,2) ; [2^60,2^61) + Output is bounded by [1,4) ; [2^120,2^122) */ + + /* Adjust the exponent according to where the decimal point ended + up in the high 64 bit word. In the source the decimal point + was at NR_FRAC_GUARD. */ + f->normal_exp += NR_FRAC_GUARD + 64 - (NR_FRAC_GUARD * 2); + + /* The high word is bounded according to the above. Consequently + it has never overflowed into IMPLICIT_2. */ + ASSERT (high < LSBIT64 (((NR_FRAC_GUARD + 1) * 2) - 64)); + ASSERT (high >= LSBIT64 ((NR_FRAC_GUARD * 2) - 64)); + ASSERT (LSBIT64 (((NR_FRAC_GUARD + 1) * 2) - 64) < IMPLICIT_1); + +#if 0 + printf ("\n"); + print_bits (high, 63, (sim_fpu_print_func*)fprintf, stdout); + printf (";"); + print_bits (low, 63, (sim_fpu_print_func*)fprintf, stdout); + printf ("\n"); +#endif + + /* normalize */ + do + { + f->normal_exp--; + high <<= 1; + if (low & LSBIT64 (63)) + high |= 1; + low <<= 1; + } + while (high < IMPLICIT_1); + +#if 0 + print_bits (high, 63, (sim_fpu_print_func*)fprintf, stdout); + printf (";"); + print_bits (low, 63, (sim_fpu_print_func*)fprintf, stdout); + printf ("\n"); +#endif + + ASSERT (high >= IMPLICIT_1 && high < IMPLICIT_2); + if (low != 0) + { + f->fraction = (high | 1); /* sticky */ + return sim_fpu_status_inexact; + } + else + { + f->fraction = high; + return 0; + } + return 0; + } +} + +INLINE_SIM_FPU (int) +sim_fpu_div (sim_fpu *f, + const sim_fpu *l, + const sim_fpu *r) +{ + if (sim_fpu_is_snan (l)) + { + *f = *l; + f->class = sim_fpu_class_qnan; + return sim_fpu_status_invalid_snan; + } + if (sim_fpu_is_snan (r)) + { + *f = *r; + f->class = sim_fpu_class_qnan; + return sim_fpu_status_invalid_snan; + } + if (sim_fpu_is_qnan (l)) + { + *f = *l; + f->class = sim_fpu_class_qnan; + return 0; + } + if (sim_fpu_is_qnan (r)) + { + *f = *r; + f->class = sim_fpu_class_qnan; + return 0; + } + if (sim_fpu_is_infinity (l)) + { + if (sim_fpu_is_infinity (r)) + { + *f = sim_fpu_qnan; + return sim_fpu_status_invalid_idi; + } + else + { + *f = *l; + f->sign = l->sign ^ r->sign; + return 0; + } + } + if (sim_fpu_is_zero (l)) + { + if (sim_fpu_is_zero (r)) + { + *f = sim_fpu_qnan; + return sim_fpu_status_invalid_zdz; + } + else + { + *f = *l; + f->sign = l->sign ^ r->sign; + return 0; + } + } + if (sim_fpu_is_infinity (r)) + { + *f = sim_fpu_zero; + f->sign = l->sign ^ r->sign; + return 0; + } + if (sim_fpu_is_zero (r)) + { + f->class = sim_fpu_class_infinity; + f->sign = l->sign ^ r->sign; + return sim_fpu_status_invalid_div0; + } + + /* Calculate the mantissa by multiplying both 64bit numbers to get a + 128 bit number */ + { + /* quotient = ( ( numerator / denominator) + x 2^(numerator exponent - denominator exponent) + */ + unsigned64 numerator; + unsigned64 denominator; + unsigned64 quotient; + unsigned64 bit; + + f->class = sim_fpu_class_number; + f->sign = l->sign ^ r->sign; + f->normal_exp = l->normal_exp - r->normal_exp; + + numerator = l->fraction; + denominator = r->fraction; + + /* Fraction will be less than 1.0 */ + if (numerator < denominator) + { + numerator <<= 1; + f->normal_exp--; + } + ASSERT (numerator >= denominator); + + /* Gain extra precision, already used one spare bit */ + numerator <<= NR_SPARE; + denominator <<= NR_SPARE; + + /* Does divide one bit at a time. Optimize??? */ + quotient = 0; + bit = (IMPLICIT_1 << NR_SPARE); + while (bit) + { + if (numerator >= denominator) + { + quotient |= bit; + numerator -= denominator; + } + bit >>= 1; + numerator <<= 1; + } + +#if 0 + printf ("\n"); + print_bits (quotient, 63, (sim_fpu_print_func*)fprintf, stdout); + printf ("\n"); + print_bits (numerator, 63, (sim_fpu_print_func*)fprintf, stdout); + printf ("\n"); + print_bits (denominator, 63, (sim_fpu_print_func*)fprintf, stdout); + printf ("\n"); +#endif + + /* discard (but save) the extra bits */ + if ((quotient & LSMASK64 (NR_SPARE -1, 0))) + quotient = (quotient >> NR_SPARE) | 1; + else + quotient = (quotient >> NR_SPARE); + + f->fraction = quotient; + ASSERT (f->fraction >= IMPLICIT_1 && f->fraction < IMPLICIT_2); + if (numerator != 0) + { + f->fraction |= 1; /* stick remaining bits */ + return sim_fpu_status_inexact; + } + else + return 0; + } +} + + +INLINE_SIM_FPU (int) +sim_fpu_max (sim_fpu *f, + const sim_fpu *l, + const sim_fpu *r) +{ + if (sim_fpu_is_snan (l)) + { + *f = *l; + f->class = sim_fpu_class_qnan; + return sim_fpu_status_invalid_snan; + } + if (sim_fpu_is_snan (r)) + { + *f = *r; + f->class = sim_fpu_class_qnan; + return sim_fpu_status_invalid_snan; + } + if (sim_fpu_is_qnan (l)) + { + *f = *l; + return 0; + } + if (sim_fpu_is_qnan (r)) + { + *f = *r; + return 0; + } + if (sim_fpu_is_infinity (l)) + { + if (sim_fpu_is_infinity (r) + && l->sign == r->sign) + { + *f = sim_fpu_qnan; + return sim_fpu_status_invalid_isi; + } + if (l->sign) + *f = *r; /* -inf < anything */ + else + *f = *l; /* +inf > anthing */ + return 0; + } + if (sim_fpu_is_infinity (r)) + { + if (r->sign) + *f = *l; /* anything > -inf */ + else + *f = *r; /* anthing < +inf */ + return 0; + } + if (l->sign > r->sign) + { + *f = *r; /* -ve < +ve */ + return 0; + } + if (l->sign < r->sign) + { + *f = *l; /* +ve > -ve */ + return 0; + } + ASSERT (l->sign == r->sign); + if (l->normal_exp > r->normal_exp + || (l->normal_exp == r->normal_exp && + l->fraction > r->fraction)) + { + /* |l| > |r| */ + if (l->sign) + *f = *r; /* -ve < -ve */ + else + *f = *l; /* +ve > +ve */ + return 0; + } + else + { + /* |l| <= |r| */ + if (l->sign) + *f = *l; /* -ve > -ve */ + else + *f = *r; /* +ve < +ve */ + return 0; + } +} + + +INLINE_SIM_FPU (int) +sim_fpu_min (sim_fpu *f, + const sim_fpu *l, + const sim_fpu *r) +{ + if (sim_fpu_is_snan (l)) + { + *f = *l; + f->class = sim_fpu_class_qnan; + return sim_fpu_status_invalid_snan; + } + if (sim_fpu_is_snan (r)) + { + *f = *r; + f->class = sim_fpu_class_qnan; + return sim_fpu_status_invalid_snan; + } + if (sim_fpu_is_qnan (l)) + { + *f = *l; + return 0; + } + if (sim_fpu_is_qnan (r)) + { + *f = *r; + return 0; + } + if (sim_fpu_is_infinity (l)) + { + if (sim_fpu_is_infinity (r) + && l->sign == r->sign) + { + *f = sim_fpu_qnan; + return sim_fpu_status_invalid_isi; + } + if (l->sign) + *f = *l; /* -inf < anything */ + else + *f = *r; /* +inf > anthing */ + return 0; + } + if (sim_fpu_is_infinity (r)) + { + if (r->sign) + *f = *r; /* anything > -inf */ + else + *f = *l; /* anything < +inf */ + return 0; + } + if (l->sign > r->sign) + { + *f = *l; /* -ve < +ve */ + return 0; + } + if (l->sign < r->sign) + { + *f = *r; /* +ve > -ve */ + return 0; + } + ASSERT (l->sign == r->sign); + if (l->normal_exp > r->normal_exp + || (l->normal_exp == r->normal_exp && + l->fraction > r->fraction)) + { + /* |l| > |r| */ + if (l->sign) + *f = *l; /* -ve < -ve */ + else + *f = *r; /* +ve > +ve */ + return 0; + } + else + { + /* |l| <= |r| */ + if (l->sign) + *f = *r; /* -ve > -ve */ + else + *f = *l; /* +ve < +ve */ + return 0; + } +} + + +INLINE_SIM_FPU (int) +sim_fpu_neg (sim_fpu *f, + const sim_fpu *r) +{ + if (sim_fpu_is_snan (r)) + { + *f = *r; + f->class = sim_fpu_class_qnan; + return sim_fpu_status_invalid_snan; + } + if (sim_fpu_is_qnan (r)) + { + *f = *r; + return 0; + } + *f = *r; + f->sign = !r->sign; + return 0; +} + + +INLINE_SIM_FPU (int) +sim_fpu_abs (sim_fpu *f, + const sim_fpu *r) +{ + if (sim_fpu_is_snan (r)) + { + *f = *r; + f->class = sim_fpu_class_qnan; + return sim_fpu_status_invalid_snan; + } + if (sim_fpu_is_qnan (r)) + { + *f = *r; + return 0; + } + *f = *r; + f->sign = 0; + return 0; +} + + +INLINE_SIM_FPU (int) +sim_fpu_inv (sim_fpu *f, + const sim_fpu *r) +{ + if (sim_fpu_is_snan (r)) + { + *f = *r; + f->class = sim_fpu_class_qnan; + return sim_fpu_status_invalid_snan; + } + if (sim_fpu_is_qnan (r)) + { + *f = *r; + f->class = sim_fpu_class_qnan; + return 0; + } + if (sim_fpu_is_infinity (r)) + { + *f = sim_fpu_zero; + f->sign = r->sign; + return 0; + } + if (sim_fpu_is_zero (r)) + { + f->class = sim_fpu_class_infinity; + f->sign = r->sign; + return sim_fpu_status_invalid_div0; + } + *f = *r; + f->normal_exp = - r->normal_exp; + return 0; +} + + +INLINE_SIM_FPU (int) +sim_fpu_sqrt (sim_fpu *f, + const sim_fpu *r) +{ + if (sim_fpu_is_snan (r)) + { + *f = sim_fpu_qnan; + return sim_fpu_status_invalid_snan; + } + if (sim_fpu_is_qnan (r)) + { + *f = sim_fpu_qnan; + return 0; + } + if (sim_fpu_is_zero (r)) + { + f->class = sim_fpu_class_zero; + f->sign = r->sign; + return 0; + } + if (sim_fpu_is_infinity (r)) + { + if (r->sign) + { + *f = sim_fpu_qnan; + return sim_fpu_status_invalid_sqrt; + } + else + { + f->class = sim_fpu_class_infinity; + f->sign = 0; + f->sign = 0; + return 0; + } + } + if (r->sign) + { + *f = sim_fpu_qnan; + return sim_fpu_status_invalid_sqrt; + } + + /* @(#)e_sqrt.c 5.1 93/09/24 */ + /* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + + /* __ieee754_sqrt(x) + * Return correctly rounded sqrt. + * ------------------------------------------ + * | Use the hardware sqrt if you have one | + * ------------------------------------------ + * Method: + * Bit by bit method using integer arithmetic. (Slow, but portable) + * 1. Normalization + * Scale x to y in [1,4) with even powers of 2: + * find an integer k such that 1 <= (y=x*2^(2k)) < 4, then + * sqrt(x) = 2^k * sqrt(y) + - + - Since: + - sqrt ( x*2^(2m) ) = sqrt(x).2^m ; m even + - sqrt ( x*2^(2m + 1) ) = sqrt(2.x).2^m ; m odd + - Define: + - y = ((m even) ? x : 2.x) + - Then: + - y in [1, 4) ; [IMPLICIT_1,IMPLICIT_4) + - And: + - sqrt (y) in [1, 2) ; [IMPLICIT_1,IMPLICIT_2) + - + * 2. Bit by bit computation + * Let q = sqrt(y) truncated to i bit after binary point (q = 1), + * i 0 + * i+1 2 + * s = 2*q , and y = 2 * ( y - q ). (1) + * i i i i + * + * To compute q from q , one checks whether + * i+1 i + * + * -(i+1) 2 + * (q + 2 ) <= y. (2) + * i + * -(i+1) + * If (2) is false, then q = q ; otherwise q = q + 2 . + * i+1 i i+1 i + * + * With some algebric manipulation, it is not difficult to see + * that (2) is equivalent to + * -(i+1) + * s + 2 <= y (3) + * i i + * + * The advantage of (3) is that s and y can be computed by + * i i + * the following recurrence formula: + * if (3) is false + * + * s = s , y = y ; (4) + * i+1 i i+1 i + * + - + - NOTE: y = 2*y + - i+1 i + - + * otherwise, + * -i -(i+1) + * s = s + 2 , y = y - s - 2 (5) + * i+1 i i+1 i i + * + - + - -(i+1) + - NOTE: y = 2 (y - s - 2 ) + - i+1 i i + - + * One may easily use induction to prove (4) and (5). + * Note. Since the left hand side of (3) contain only i+2 bits, + * it does not necessary to do a full (53-bit) comparison + * in (3). + * 3. Final rounding + * After generating the 53 bits result, we compute one more bit. + * Together with the remainder, we can decide whether the + * result is exact, bigger than 1/2ulp, or less than 1/2ulp + * (it will never equal to 1/2ulp). + * The rounding mode can be detected by checking whether + * huge + tiny is equal to huge, and whether huge - tiny is + * equal to huge for some floating point number "huge" and "tiny". + * + * Special cases: + * sqrt(+-0) = +-0 ... exact + * sqrt(inf) = inf + * sqrt(-ve) = NaN ... with invalid signal + * sqrt(NaN) = NaN ... with invalid signal for signaling NaN + * + * Other methods : see the appended file at the end of the program below. + *--------------- + */ + + { + /* generate sqrt(x) bit by bit */ + unsigned64 y; + unsigned64 q; + unsigned64 s; + unsigned64 b; + + f->class = sim_fpu_class_number; + f->sign = 0; + y = r->fraction; + f->normal_exp = (r->normal_exp >> 1); /* exp = [exp/2] */ + + /* odd exp, double x to make it even */ + ASSERT (y >= IMPLICIT_1 && y < IMPLICIT_4); + if ((r->normal_exp & 1)) + { + y += y; + } + ASSERT (y >= IMPLICIT_1 && y < (IMPLICIT_2 << 1)); + + /* Let loop determine first value of s (either 1 or 2) */ + b = IMPLICIT_1; + q = 0; + s = 0; + + while (b) + { + unsigned64 t = s + b; + if (t <= y) + { + s |= (b << 1); + y -= t; + q |= b; + } + y <<= 1; + b >>= 1; + } + + ASSERT (q >= IMPLICIT_1 && q < IMPLICIT_2); + f->fraction = q; + if (y != 0) + { + f->fraction |= 1; /* stick remaining bits */ + return sim_fpu_status_inexact; + } + else + return 0; + } +} + + +/* int/long <-> sim_fpu */ + +INLINE_SIM_FPU (int) +sim_fpu_i32to (sim_fpu *f, + signed32 i, + sim_fpu_round round) +{ + i2fpu (f, i, 0); + return 0; +} + +INLINE_SIM_FPU (int) +sim_fpu_u32to (sim_fpu *f, + unsigned32 u, + sim_fpu_round round) +{ + u2fpu (f, u, 0); + return 0; +} + +INLINE_SIM_FPU (int) +sim_fpu_i64to (sim_fpu *f, + signed64 i, + sim_fpu_round round) +{ + i2fpu (f, i, 1); + return 0; +} + +INLINE_SIM_FPU (int) +sim_fpu_u64to (sim_fpu *f, + unsigned64 u, + sim_fpu_round round) +{ + u2fpu (f, u, 1); + return 0; +} + + +INLINE_SIM_FPU (int) +sim_fpu_to32i (signed32 *i, + const sim_fpu *f, + sim_fpu_round round) +{ + signed64 i64; + int status = fpu2i (&i64, f, 0, round); + *i = i64; + return status; +} + +INLINE_SIM_FPU (int) +sim_fpu_to32u (unsigned32 *u, + const sim_fpu *f, + sim_fpu_round round) +{ + unsigned64 u64; + int status = fpu2u (&u64, f, 0); + *u = u64; + return status; +} + +INLINE_SIM_FPU (int) +sim_fpu_to64i (signed64 *i, + const sim_fpu *f, + sim_fpu_round round) +{ + return fpu2i (i, f, 1, round); +} + + +INLINE_SIM_FPU (int) +sim_fpu_to64u (unsigned64 *u, + const sim_fpu *f, + sim_fpu_round round) +{ + return fpu2u (u, f, 1); +} + + + +/* sim_fpu -> host format */ + +#if 0 +INLINE_SIM_FPU (float) +sim_fpu_2f (const sim_fpu *f) +{ + return fval.d; +} +#endif + + +INLINE_SIM_FPU (double) +sim_fpu_2d (const sim_fpu *s) +{ + sim_fpu_map val; + if (sim_fpu_is_snan (s)) + { + /* gag SNaN's */ + sim_fpu n = *s; + n.class = sim_fpu_class_qnan; + val.i = pack_fpu (&n, 1); + } + else + { + val.i = pack_fpu (s, 1); + } + return val.d; +} + + +#if 0 +INLINE_SIM_FPU (void) +sim_fpu_f2 (sim_fpu *f, + float s) +{ + sim_fpu_map val; + val.d = s; + unpack_fpu (f, val.i, 1); +} +#endif + + +INLINE_SIM_FPU (void) +sim_fpu_d2 (sim_fpu *f, + double d) +{ + sim_fpu_map val; + val.d = d; + unpack_fpu (f, val.i, 1); +} + + +/* General */ + +INLINE_SIM_FPU (int) +sim_fpu_is_nan (const sim_fpu *d) +{ + switch (d->class) + { + case sim_fpu_class_qnan: + case sim_fpu_class_snan: + return 1; + default: + return 0; + } +} + +INLINE_SIM_FPU (int) +sim_fpu_is_qnan (const sim_fpu *d) +{ + switch (d->class) + { + case sim_fpu_class_qnan: + return 1; + default: + return 0; + } +} + +INLINE_SIM_FPU (int) +sim_fpu_is_snan (const sim_fpu *d) +{ + switch (d->class) + { + case sim_fpu_class_snan: + return 1; + default: + return 0; + } +} + +INLINE_SIM_FPU (int) +sim_fpu_is_zero (const sim_fpu *d) +{ + switch (d->class) + { + case sim_fpu_class_zero: + return 1; + default: + return 0; + } +} + +INLINE_SIM_FPU (int) +sim_fpu_is_infinity (const sim_fpu *d) +{ + switch (d->class) + { + case sim_fpu_class_infinity: + return 1; + default: + return 0; + } +} + +INLINE_SIM_FPU (int) +sim_fpu_is_number (const sim_fpu *d) +{ + switch (d->class) + { + case sim_fpu_class_denorm: + case sim_fpu_class_number: + return 1; + default: + return 0; + } +} + +INLINE_SIM_FPU (int) +sim_fpu_is_denorm (const sim_fpu *d) +{ + switch (d->class) + { + case sim_fpu_class_denorm: + return 1; + default: + return 0; + } +} + + +INLINE_SIM_FPU (int) +sim_fpu_sign (const sim_fpu *d) +{ + return d->sign; +} + + +INLINE_SIM_FPU (int) +sim_fpu_exp (const sim_fpu *d) +{ + return d->normal_exp; +} + + + +INLINE_SIM_FPU (int) +sim_fpu_is (const sim_fpu *d) +{ + switch (d->class) + { + case sim_fpu_class_qnan: + return SIM_FPU_IS_QNAN; + case sim_fpu_class_snan: + return SIM_FPU_IS_SNAN; + case sim_fpu_class_infinity: + if (d->sign) + return SIM_FPU_IS_NINF; + else + return SIM_FPU_IS_PINF; + case sim_fpu_class_number: + if (d->sign) + return SIM_FPU_IS_NNUMBER; + else + return SIM_FPU_IS_PNUMBER; + case sim_fpu_class_denorm: + if (d->sign) + return SIM_FPU_IS_NDENORM; + else + return SIM_FPU_IS_PDENORM; + case sim_fpu_class_zero: + if (d->sign) + return SIM_FPU_IS_NZERO; + else + return SIM_FPU_IS_PZERO; + default: + return -1; + abort (); + } +} + +INLINE_SIM_FPU (int) +sim_fpu_cmp (const sim_fpu *l, const sim_fpu *r) +{ + sim_fpu res; + sim_fpu_sub (&res, l, r); + return sim_fpu_is (&res); +} + +INLINE_SIM_FPU (int) +sim_fpu_is_lt (const sim_fpu *l, const sim_fpu *r) +{ + int status; + sim_fpu_lt (&status, l, r); + return status; +} + +INLINE_SIM_FPU (int) +sim_fpu_is_le (const sim_fpu *l, const sim_fpu *r) +{ + int is; + sim_fpu_le (&is, l, r); + return is; +} + +INLINE_SIM_FPU (int) +sim_fpu_is_eq (const sim_fpu *l, const sim_fpu *r) +{ + int is; + sim_fpu_eq (&is, l, r); + return is; +} + +INLINE_SIM_FPU (int) +sim_fpu_is_ne (const sim_fpu *l, const sim_fpu *r) +{ + int is; + sim_fpu_ne (&is, l, r); + return is; +} + +INLINE_SIM_FPU (int) +sim_fpu_is_ge (const sim_fpu *l, const sim_fpu *r) +{ + int is; + sim_fpu_ge (&is, l, r); + return is; +} + +INLINE_SIM_FPU (int) +sim_fpu_is_gt (const sim_fpu *l, const sim_fpu *r) +{ + int is; + sim_fpu_gt (&is, l, r); + return is; +} + + +/* Compare operators */ + +INLINE_SIM_FPU (int) +sim_fpu_lt (int *is, + const sim_fpu *l, + const sim_fpu *r) +{ + if (!sim_fpu_is_nan (l) && !sim_fpu_is_nan (r)) + { + sim_fpu_map lval; + sim_fpu_map rval; + lval.i = pack_fpu (l, 1); + rval.i = pack_fpu (r, 1); + (*is) = (lval.d < rval.d); + return 0; + } + else if (sim_fpu_is_snan (l) || sim_fpu_is_snan (r)) + { + *is = 0; + return sim_fpu_status_invalid_snan; + } + else + { + *is = 0; + return sim_fpu_status_invalid_qnan; + } +} + +INLINE_SIM_FPU (int) +sim_fpu_le (int *is, + const sim_fpu *l, + const sim_fpu *r) +{ + if (!sim_fpu_is_nan (l) && !sim_fpu_is_nan (r)) + { + sim_fpu_map lval; + sim_fpu_map rval; + lval.i = pack_fpu (l, 1); + rval.i = pack_fpu (r, 1); + *is = (lval.d <= rval.d); + return 0; + } + else if (sim_fpu_is_snan (l) || sim_fpu_is_snan (r)) + { + *is = 0; + return sim_fpu_status_invalid_snan; + } + else + { + *is = 0; + return sim_fpu_status_invalid_qnan; + } +} + +INLINE_SIM_FPU (int) +sim_fpu_eq (int *is, + const sim_fpu *l, + const sim_fpu *r) +{ + if (!sim_fpu_is_nan (l) && !sim_fpu_is_nan (r)) + { + sim_fpu_map lval; + sim_fpu_map rval; + lval.i = pack_fpu (l, 1); + rval.i = pack_fpu (r, 1); + (*is) = (lval.d == rval.d); + return 0; + } + else if (sim_fpu_is_snan (l) || sim_fpu_is_snan (r)) + { + *is = 0; + return sim_fpu_status_invalid_snan; + } + else + { + *is = 0; + return sim_fpu_status_invalid_qnan; + } +} + +INLINE_SIM_FPU (int) +sim_fpu_ne (int *is, + const sim_fpu *l, + const sim_fpu *r) +{ + if (!sim_fpu_is_nan (l) && !sim_fpu_is_nan (r)) + { + sim_fpu_map lval; + sim_fpu_map rval; + lval.i = pack_fpu (l, 1); + rval.i = pack_fpu (r, 1); + (*is) = (lval.d != rval.d); + return 0; + } + else if (sim_fpu_is_snan (l) || sim_fpu_is_snan (r)) + { + *is = 0; + return sim_fpu_status_invalid_snan; + } + else + { + *is = 0; + return sim_fpu_status_invalid_qnan; + } +} + +INLINE_SIM_FPU (int) +sim_fpu_ge (int *is, + const sim_fpu *l, + const sim_fpu *r) +{ + return sim_fpu_le (is, r, l); +} + +INLINE_SIM_FPU (int) +sim_fpu_gt (int *is, + const sim_fpu *l, + const sim_fpu *r) +{ + return sim_fpu_lt (is, r, l); +} + + +/* A number of useful constants */ + +#if EXTERN_SIM_FPU_P +const sim_fpu sim_fpu_zero = { + sim_fpu_class_zero, +}; +const sim_fpu sim_fpu_qnan = { + sim_fpu_class_qnan, +}; +const sim_fpu sim_fpu_one = { + sim_fpu_class_number, 0, IMPLICIT_1, 1 +}; +const sim_fpu sim_fpu_two = { + sim_fpu_class_number, 0, IMPLICIT_1, 2 +}; +const sim_fpu sim_fpu_max32 = { + sim_fpu_class_number, 0, LSMASK64 (NR_FRAC_GUARD, NR_GUARDS32), NORMAL_EXPMAX32 +}; +const sim_fpu sim_fpu_max64 = { + sim_fpu_class_number, 0, LSMASK64 (NR_FRAC_GUARD, NR_GUARDS64), NORMAL_EXPMAX64 +}; +#endif + + +/* For debugging */ + +INLINE_SIM_FPU (void) +sim_fpu_print_fpu (const sim_fpu *f, + sim_fpu_print_func *print, + void *arg) +{ + print (arg, "%s", f->sign ? "-" : "+"); + switch (f->class) + { + case sim_fpu_class_qnan: + print (arg, "0."); + print_bits (f->fraction, NR_FRAC_GUARD - 1, print, arg); + print (arg, "*QuietNaN"); + break; + case sim_fpu_class_snan: + print (arg, "0."); + print_bits (f->fraction, NR_FRAC_GUARD - 1, print, arg); + print (arg, "*SignalNaN"); + break; + case sim_fpu_class_zero: + print (arg, "0.0"); + break; + case sim_fpu_class_infinity: + print (arg, "INF"); + break; + case sim_fpu_class_number: + case sim_fpu_class_denorm: + print (arg, "1."); + print_bits (f->fraction, NR_FRAC_GUARD - 1, print, arg); + print (arg, "*2^%+-5d", f->normal_exp); + ASSERT (f->fraction >= IMPLICIT_1); + ASSERT (f->fraction < IMPLICIT_2); + } +} + + +INLINE_SIM_FPU (void) +sim_fpu_print_status (int status, + sim_fpu_print_func *print, + void *arg) +{ + int i = 1; + char *prefix = ""; + while (status >= i) + { + switch ((sim_fpu_status) (status & i)) + { + case sim_fpu_status_denorm: + print (arg, "%sD", prefix); + break; + case sim_fpu_status_invalid_snan: + print (arg, "%sSNaN", prefix); + break; + case sim_fpu_status_invalid_qnan: + print (arg, "%sQNaN", prefix); + break; + case sim_fpu_status_invalid_isi: + print (arg, "%sISI", prefix); + break; + case sim_fpu_status_invalid_idi: + print (arg, "%sIDI", prefix); + break; + case sim_fpu_status_invalid_zdz: + print (arg, "%sZDZ", prefix); + break; + case sim_fpu_status_invalid_imz: + print (arg, "%sIMZ", prefix); + break; + case sim_fpu_status_invalid_cvi: + print (arg, "%sCVI", prefix); + break; + case sim_fpu_status_invalid_cmp: + print (arg, "%sCMP", prefix); + break; + case sim_fpu_status_invalid_sqrt: + print (arg, "%sSQRT", prefix); + break; + break; + case sim_fpu_status_inexact: + print (arg, "%sX", prefix); + break; + break; + case sim_fpu_status_overflow: + print (arg, "%sO", prefix); + break; + break; + case sim_fpu_status_underflow: + print (arg, "%sU", prefix); + break; + break; + case sim_fpu_status_invalid_div0: + print (arg, "%s/", prefix); + break; + break; + case sim_fpu_status_rounded: + print (arg, "%sR", prefix); + break; + break; + } + i <<= 1; + prefix = ","; + } +} + +#endif diff --git a/sim/common/sim-fpu.h b/sim/common/sim-fpu.h new file mode 100644 index 00000000000..05d53c250db --- /dev/null +++ b/sim/common/sim-fpu.h @@ -0,0 +1,417 @@ +/* Simulator Floating-point support. + Copyright (C) 1997-1998 Free Software Foundation, Inc. + Contributed by Cygnus Support. + +This file is part of GDB, the GNU debugger. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + + + +#ifndef SIM_FPU_H +#define SIM_FPU_H + + + +/* The FPU intermediate type - this object, passed by reference, + should be treated as opaque. + + + Pragmatics - pass struct by ref: + + The alternatives for this object/interface that were considered + were: a packed 64 bit value; an unpacked structure passed by value; + and an unpacked structure passed by reference. + + The packed 64 bit value was rejected because: it limited the + precision of intermediate values; reasonable performance would only + be achieved when the sim_fpu package was in-lined allowing repeated + unpacking operations to be eliminated. + + For unpacked structures (passed by value and reference), the code + quality of GCC-2.7 (on x86) for each alternative was compared. + Needless to say the results, while better then for a packed 64 bit + object, were still poor (GCC had only limited support for the + optimization of references to structure members). Regardless, the + struct-by-ref alternative achieved better results when compiled + with (better speed) and without (better code density) in-lining. + Here's looking forward to an improved GCC optimizer. + + + Pragmatics - avoid host FP hardware: + + FP operations can be implemented by either: the host's floating + point hardware; or by emulating the FP operations using integer + only routines. This is direct tradeoff between speed, portability + and correctness. + + The two principal reasons for selecting portability and correctness + over speed are: + + 1 - Correctness. The assumption that FP correctness wasn't an + issue for code being run on simulators was wrong. Instead of + running FP tolerant (?) code, simulator users instead typically run + very aggressive FP code sequences. The sole purpose of those + sequences being to test the target ISA's FP implementation. + + 2 - Portability. The host FP implementation is not predictable. A + simulator modeling aggressive FP code sequences using the hosts FPU + relies heavily on the correctness of the hosts FP implementation. + It turns out that such trust can be misplaced. The behavior of + host FP implementations when handling edge conditions such as SNaNs + and exceptions varied widely. + + + */ + + +typedef enum +{ + sim_fpu_class_zero, + sim_fpu_class_snan, + sim_fpu_class_qnan, + sim_fpu_class_number, + sim_fpu_class_denorm, + sim_fpu_class_infinity, +} sim_fpu_class; + +typedef struct _sim_fpu { + sim_fpu_class class; + int sign; + unsigned64 fraction; + int normal_exp; +} sim_fpu; + + + +/* Rounding options. + + The value zero (sim_fpu_round_default) for ALU operations indicates + that, when possible, rounding should be avoided. */ + +typedef enum +{ + sim_fpu_round_default = 0, + sim_fpu_round_near = 1, + sim_fpu_round_zero = 2, + sim_fpu_round_up = 3, + sim_fpu_round_down = 4, +} sim_fpu_round; + + +/* Options when handling denormalized numbers. */ + +typedef enum +{ + sim_fpu_denorm_default = 0, + sim_fpu_denorm_underflow_inexact = 1, + sim_fpu_denorm_zero = 2, +} sim_fpu_denorm; + + + +/* Status values returned by FPU operators. + + When checking the result of an FP sequence (ex 32to, add, single, + to32) the caller may either: check the return value of each FP + operator; or form the union (OR) of the returned values and examine + them once at the end. + + FIXME: This facility is still being developed. The choice of + status values returned and their exact meaning may changed in the + future. */ + +typedef enum +{ + sim_fpu_status_invalid_snan = 1, + sim_fpu_status_invalid_qnan = 2, + sim_fpu_status_invalid_isi = 4, /* (inf - inf) */ + sim_fpu_status_invalid_idi = 8, /* (inf / inf) */ + sim_fpu_status_invalid_zdz = 16, /* (0 / 0) */ + sim_fpu_status_invalid_imz = 32, /* (inf * 0) */ + sim_fpu_status_invalid_cvi = 64, /* convert to integer */ + sim_fpu_status_invalid_div0 = 128, /* (X / 0) */ + sim_fpu_status_invalid_cmp = 256, /* compare */ + sim_fpu_status_invalid_sqrt = 512, + sim_fpu_status_rounded = 1024, + sim_fpu_status_inexact = 2048, + sim_fpu_status_overflow = 4096, + sim_fpu_status_underflow = 8192, + sim_fpu_status_denorm = 16384, +} sim_fpu_status; + + + + +/* Directly map between a 32/64 bit register and the sim_fpu internal + type. + + When converting from the 32/64 bit packed format to the sim_fpu + internal type, the operation is exact. + + When converting from the sim_fpu internal type to 32/64 bit packed + format, the operation may result in a loss of precision. The + configuration macro WITH_FPU_CONVERSION controls this. By default, + silent round to nearest is performed. Alternativly, round up, + round down and round to zero can be performed. In a simulator + emulating exact FPU behavour, sim_fpu_round_{32,64} should be + called before packing the sim_fpu value. */ + +INLINE_SIM_FPU (void) sim_fpu_32to (sim_fpu *f, unsigned32 s); +INLINE_SIM_FPU (void) sim_fpu_232to (sim_fpu *f, unsigned32 h, unsigned32 l); +INLINE_SIM_FPU (void) sim_fpu_64to (sim_fpu *f, unsigned64 d); + +INLINE_SIM_FPU (void) sim_fpu_to32 (unsigned32 *s, const sim_fpu *f); +INLINE_SIM_FPU (void) sim_fpu_to232 (unsigned32 *h, unsigned32 *l, const sim_fpu *f); +INLINE_SIM_FPU (void) sim_fpu_to64 (unsigned64 *d, const sim_fpu *f); + + +/* Create a sim_fpu struct using raw information. (FRACTION & LSMASK + (PRECISION-1, 0)) is assumed to contain the fraction part of the + floating-point number. The leading bit LSBIT (PRECISION) is always + implied. The number created can be represented by: + + (SIGN ? "-" : "+") "1." FRACTION{PRECISION-1,0} X 2 ^ NORMAL_EXP> + + You can not specify zero using this function. */ + +INLINE_SIM_FPU (void) sim_fpu_fractionto (sim_fpu *f, int sign, int normal_exp, unsigned64 fraction, int precision); + +/* Reverse operaton. If S is a non-zero number, discards the implied + leading one and returns PRECISION fraction bits. No rounding is + performed. */ +INLINE_SIM_FPU (unsigned64) sim_fpu_tofraction (const sim_fpu *s, int precision); + + + +/* Rounding operators. + + Force an intermediate result to an exact 32/64 bit + representation. */ + +INLINE_SIM_FPU (int) sim_fpu_round_32 (sim_fpu *f, + sim_fpu_round round, + sim_fpu_denorm denorm); +INLINE_SIM_FPU (int) sim_fpu_round_64 (sim_fpu *f, + sim_fpu_round round, + sim_fpu_denorm denorm); + + + +/* Arrithmetic operators. + + FIXME: In the future, additional arguments ROUNDING and BITSIZE may + be added. */ + +typedef int (sim_fpu_op1) (sim_fpu *f, + const sim_fpu *l); +typedef int (sim_fpu_op2) (sim_fpu *f, + const sim_fpu *l, + const sim_fpu *r); + +INLINE_SIM_FPU (int) sim_fpu_add (sim_fpu *f, + const sim_fpu *l, const sim_fpu *r); +INLINE_SIM_FPU (int) sim_fpu_sub (sim_fpu *f, + const sim_fpu *l, const sim_fpu *r); +INLINE_SIM_FPU (int) sim_fpu_mul (sim_fpu *f, + const sim_fpu *l, const sim_fpu *r); +INLINE_SIM_FPU (int) sim_fpu_div (sim_fpu *f, + const sim_fpu *l, const sim_fpu *r); +INLINE_SIM_FPU (int) sim_fpu_max (sim_fpu *f, + const sim_fpu *l, const sim_fpu *r); +INLINE_SIM_FPU (int) sim_fpu_min (sim_fpu *f, + const sim_fpu *l, const sim_fpu *r); +INLINE_SIM_FPU (int) sim_fpu_neg (sim_fpu *f, + const sim_fpu *a); +INLINE_SIM_FPU (int) sim_fpu_abs (sim_fpu *f, + const sim_fpu *a); +INLINE_SIM_FPU (int) sim_fpu_inv (sim_fpu *f, + const sim_fpu *a); +INLINE_SIM_FPU (int) sim_fpu_sqrt (sim_fpu *f, + const sim_fpu *sqr); + + + +/* Conversion of integer <-> floating point. */ + +INLINE_SIM_FPU (int) sim_fpu_i32to (sim_fpu *f, signed32 i, + sim_fpu_round round); +INLINE_SIM_FPU (int) sim_fpu_u32to (sim_fpu *f, unsigned32 u, + sim_fpu_round round); +INLINE_SIM_FPU (int) sim_fpu_i64to (sim_fpu *f, signed64 i, + sim_fpu_round round); +INLINE_SIM_FPU (int) sim_fpu_u64to (sim_fpu *f, unsigned64 u, + sim_fpu_round round); +#if 0 +INLINE_SIM_FPU (int) sim_fpu_i232to (sim_fpu *f, signed32 h, signed32 l, + sim_fpu_round round); +#endif +#if 0 +INLINE_SIM_FPU (int) sim_fpu_u232to (sim_fpu *f, unsigned32 h, unsigned32 l, + sim_fpu_round round); +#endif + +INLINE_SIM_FPU (int) sim_fpu_to32i (signed32 *i, const sim_fpu *f, + sim_fpu_round round); +INLINE_SIM_FPU (int) sim_fpu_to32u (unsigned32 *u, const sim_fpu *f, + sim_fpu_round round); +INLINE_SIM_FPU (int) sim_fpu_to64i (signed64 *i, const sim_fpu *f, + sim_fpu_round round); +INLINE_SIM_FPU (int) sim_fpu_to64u (unsigned64 *u, const sim_fpu *f, + sim_fpu_round round); +#if 0 +INLINE_SIM_FPU (int) sim_fpu_to232i (signed64 *h, signed64 *l, const sim_fpu *f, + sim_fpu_round round); +#endif +#if 0 +INLINE_SIM_FPU (int) sim_fpu_to232u (unsigned64 *h, unsigned64 *l, const sim_fpu *f, + sim_fpu_round round); +#endif + + +/* Conversion of internal sim_fpu type to host double format. + + For debuging/tracing only. A SNaN is never returned. */ + +/* INLINE_SIM_FPU (float) sim_fpu_2f (const sim_fpu *f); */ +INLINE_SIM_FPU (double) sim_fpu_2d (const sim_fpu *d); + +/* INLINE_SIM_FPU (void) sim_fpu_f2 (sim_fpu *f, float s); */ +INLINE_SIM_FPU (void) sim_fpu_d2 (sim_fpu *f, double d); + + + +/* Specific number classes. + + NB: When either, a 32/64 bit floating points is converted to + internal format, or an internal format number is rounded to 32/64 + bit precision, a special marker is retained that indicates that the + value was normalized. For such numbers both is_number and + is_denorm return true. */ + +INLINE_SIM_FPU (int) sim_fpu_is_nan (const sim_fpu *s); /* 1 => SNaN or QNaN */ +INLINE_SIM_FPU (int) sim_fpu_is_snan (const sim_fpu *s); /* 1 => SNaN */ +INLINE_SIM_FPU (int) sim_fpu_is_qnan (const sim_fpu *s); /* 1 => QNaN */ + +INLINE_SIM_FPU (int) sim_fpu_is_zero (const sim_fpu *s); +INLINE_SIM_FPU (int) sim_fpu_is_infinity (const sim_fpu *s); +INLINE_SIM_FPU (int) sim_fpu_is_number (const sim_fpu *s); /* !zero */ +INLINE_SIM_FPU (int) sim_fpu_is_denorm (const sim_fpu *s); /* !zero */ + + + +/* Floating point fields */ + +INLINE_SIM_FPU (int) sim_fpu_sign (const sim_fpu *s); +INLINE_SIM_FPU (int) sim_fpu_exp (const sim_fpu *s); + + + +/* Specific comparison operators + + For NaNs et.al., the comparison operators will set IS to zero and + return a nonzero result. */ + +INLINE_SIM_FPU (int) sim_fpu_lt (int *is, const sim_fpu *l, const sim_fpu *r); +INLINE_SIM_FPU (int) sim_fpu_le (int *is, const sim_fpu *l, const sim_fpu *r); +INLINE_SIM_FPU (int) sim_fpu_eq (int *is, const sim_fpu *l, const sim_fpu *r); +INLINE_SIM_FPU (int) sim_fpu_ne (int *is, const sim_fpu *l, const sim_fpu *r); +INLINE_SIM_FPU (int) sim_fpu_ge (int *is, const sim_fpu *l, const sim_fpu *r); +INLINE_SIM_FPU (int) sim_fpu_gt (int *is, const sim_fpu *l, const sim_fpu *r); + +INLINE_SIM_FPU (int) sim_fpu_is_lt (const sim_fpu *l, const sim_fpu *r); +INLINE_SIM_FPU (int) sim_fpu_is_le (const sim_fpu *l, const sim_fpu *r); +INLINE_SIM_FPU (int) sim_fpu_is_eq (const sim_fpu *l, const sim_fpu *r); +INLINE_SIM_FPU (int) sim_fpu_is_ne (const sim_fpu *l, const sim_fpu *r); +INLINE_SIM_FPU (int) sim_fpu_is_ge (const sim_fpu *l, const sim_fpu *r); +INLINE_SIM_FPU (int) sim_fpu_is_gt (const sim_fpu *l, const sim_fpu *r); + + + +/* General number class and comparison operators. + + The result of the comparison is indicated by returning one of the + values below. Efficient emulation of a target FP compare + instruction can be achieved by redefining the values below to match + corresponding target FP status bits. + + For instance. SIM_FPU_QNAN may be redefined to be the bit + `INVALID' while SIM_FPU_NINF might be redefined as the bits + `NEGATIVE | INFINITY | VALID'. */ + +#ifndef SIM_FPU_IS_SNAN +enum { + SIM_FPU_IS_SNAN = 1, /* Noisy not-a-number */ + SIM_FPU_IS_QNAN = 2, /* Quite not-a-number */ + SIM_FPU_IS_NINF = 3, /* -infinity */ + SIM_FPU_IS_PINF = 4, /* +infinity */ + SIM_FPU_IS_NNUMBER = 5, /* -number - [ -MAX .. -MIN ] */ + SIM_FPU_IS_PNUMBER = 6, /* +number - [ +MIN .. +MAX ] */ + SIM_FPU_IS_NDENORM = 7, /* -denorm - ( MIN .. 0 ) */ + SIM_FPU_IS_PDENORM = 8, /* +denorm - ( 0 .. MIN ) */ + SIM_FPU_IS_NZERO = 9, /* -0 */ + SIM_FPU_IS_PZERO = 10, /* +0 */ +}; +#endif + +INLINE_SIM_FPU (int) sim_fpu_is (const sim_fpu *l); +INLINE_SIM_FPU (int) sim_fpu_cmp (const sim_fpu *l, const sim_fpu *r); + + + +/* A constant of useful numbers */ + +extern const sim_fpu sim_fpu_zero; +extern const sim_fpu sim_fpu_one; +extern const sim_fpu sim_fpu_two; +extern const sim_fpu sim_fpu_qnan; +extern const sim_fpu sim_fpu_max32; +extern const sim_fpu sim_fpu_max64; + + +/* Select the applicable functions for the fp_word type */ + +#if WITH_TARGET_FLOATING_POINT_BITSIZE == 32 +#define sim_fpu_tofp sim_fpu_to32 +#define sim_fpu_fpto sim_fpu_32to +#define sim_fpu_round_fp sim_fpu_round_32 +#define sim_fpu_maxfp sim_fpu_max32 +#endif +#if WITH_TARGET_FLOATING_POINT_BITSIZE == 64 +#define sim_fpu_tofp sim_fpu_to64 +#define sim_fpu_fpto sim_fpu_64to +#define sim_fpu_round_fp sim_fpu_round_64 +#define sim_fpu_maxfp sim_fpu_max64 +#endif + + + +/* For debugging */ + +typedef void sim_fpu_print_func (void *, char *, ...); + +INLINE_SIM_FPU (void) sim_fpu_print_fpu (const sim_fpu *f, + sim_fpu_print_func *print, + void *arg); + +INLINE_SIM_FPU (void) sim_fpu_print_status (int status, + sim_fpu_print_func *print, + void *arg); + +#if H_REVEALS_MODULE_P (SIM_FPU_INLINE) +#include "sim-fpu.c" +#endif + +#endif diff --git a/sim/common/sim-hload.c b/sim/common/sim-hload.c new file mode 100644 index 00000000000..e4016f454a6 --- /dev/null +++ b/sim/common/sim-hload.c @@ -0,0 +1,69 @@ +/* Generic load for hardware simulator models. + Copyright (C) 1997 Free Software Foundation, Inc. + Contributed by Cygnus Support. + +This file is part of GDB, the GNU debugger. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "sim-main.h" +#include "bfd.h" +#include "sim-utils.h" +#include "sim-assert.h" + + +/* Generic implementation of sim_load that works with simulators + modeling a hardware platform. */ + +SIM_RC +sim_load (sd, prog_name, prog_bfd, from_tty) + SIM_DESC sd; + char *prog_name; + struct _bfd *prog_bfd; + int from_tty; +{ + bfd *result_bfd; + + SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); + if (sim_analyze_program (sd, prog_name, prog_bfd) != SIM_RC_OK) + return SIM_RC_FAIL; + SIM_ASSERT (STATE_PROG_BFD (sd) != NULL); + + /* NOTE: For historical reasons, older hardware simulators + incorrectly write the program sections at LMA interpreted as a + virtual address. This is still accommodated for backward + compatibility reasons. */ + /* FIXME: The following simulators use this file as of 980313: + m32r, mips, v850 [grep for sim-hload in all Makefile.in's]. + Each of these should be properly using lma. When this is confirmed, + SIM_HANDLES_LMA can go away. */ +#ifndef SIM_HANDLES_LMA +#define SIM_HANDLES_LMA 0 +#endif + + result_bfd = sim_load_file (sd, STATE_MY_NAME (sd), + STATE_CALLBACK (sd), + prog_name, + STATE_PROG_BFD (sd), + STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG, + SIM_HANDLES_LMA, sim_write); + if (result_bfd == NULL) + { + bfd_close (STATE_PROG_BFD (sd)); + STATE_PROG_BFD (sd) = NULL; + return SIM_RC_FAIL; + } + return SIM_RC_OK; +} diff --git a/sim/common/sim-hrw.c b/sim/common/sim-hrw.c new file mode 100644 index 00000000000..953830259a7 --- /dev/null +++ b/sim/common/sim-hrw.c @@ -0,0 +1,41 @@ +/* Generic memory read/write for hardware simulator models. + Copyright (C) 1997 Free Software Foundation, Inc. + Contributed by Cygnus Support. + +This file is part of GDB, the GNU debugger. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "sim-main.h" +#include "sim-assert.h" + +/* Generic implementation of sim_read that works with simulators + modeling real hardware */ + +int +sim_read (SIM_DESC sd, SIM_ADDR mem, unsigned char *buf, int length) +{ + SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); + return sim_core_read_buffer (sd, NULL, read_map, + buf, mem, length); +} + +int +sim_write (SIM_DESC sd, SIM_ADDR mem, unsigned char *buf, int length) +{ + SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); + return sim_core_write_buffer (sd, NULL, write_map, + buf, mem, length); +} diff --git a/sim/common/sim-hw.c b/sim/common/sim-hw.c new file mode 100644 index 00000000000..f438462a9ba --- /dev/null +++ b/sim/common/sim-hw.c @@ -0,0 +1,508 @@ +/* Simulator hardware option handling. + Copyright (C) 1998 Free Software Foundation, Inc. + Contributed by Cygnus Support and Andrew Cagney. + +This file is part of GDB, the GNU debugger. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "sim-main.h" +#include "sim-assert.h" +#include "sim-options.h" + +#include "sim-hw.h" + +#include "hw-tree.h" +#include "hw-device.h" +#include "hw-main.h" +#include "hw-base.h" + + +#ifdef HAVE_STRING_H +#include +#else +#ifdef HAVE_STRINGS_H +#include +#endif +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#include +#include + + +struct sim_hw { + struct hw *tree; + int trace_p; + int info_p; + /* if called from a processor */ + sim_cpu *cpu; + sim_cia cia; +}; + + +struct hw * +sim_hw_parse (struct sim_state *sd, + const char *fmt, + ...) +{ + struct hw *current; + va_list ap; + va_start (ap, fmt); + current = hw_tree_vparse (STATE_HW (sd)->tree, fmt, ap); + va_end (ap); + return current; +} + +struct printer { + struct sim_state *file; + void (*print) (struct sim_state *, const char *, va_list ap); +}; + +static void +do_print (void *file, const char *fmt, ...) +{ + struct printer *p = file; + va_list ap; + va_start (ap, fmt); + p->print (p->file, fmt, ap); + va_end (ap); +} + +void +sim_hw_print (struct sim_state *sd, + void (*print) (struct sim_state *, const char *, va_list ap)) +{ + struct printer p; + p.file = sd; + p.print = print; + hw_tree_print (STATE_HW (sd)->tree, do_print, &p); +} + + + + +/* command line options. */ + +enum { + OPTION_HW_INFO = OPTION_START, + OPTION_HW_TRACE, + OPTION_HW_DEVICE, + OPTION_HW_FILE, +}; + +static DECLARE_OPTION_HANDLER (hw_option_handler); + +static const OPTION hw_options[] = +{ + { {"hw-info", no_argument, NULL, OPTION_HW_INFO }, + '\0', NULL, "List configurable hw regions", + hw_option_handler }, + { {"info-hw", no_argument, NULL, OPTION_HW_INFO }, + '\0', NULL, NULL, + hw_option_handler }, + + { {"hw-trace", optional_argument, NULL, OPTION_HW_TRACE }, + '\0', "on|off", "Trace all hardware devices", + hw_option_handler }, + { {"trace-hw", optional_argument, NULL, OPTION_HW_TRACE }, + '\0', NULL, NULL, + hw_option_handler }, + + { {"hw-device", required_argument, NULL, OPTION_HW_DEVICE }, + '\0', "DEVICE", "Add the specified device", + hw_option_handler }, + + { {"hw-file", required_argument, NULL, OPTION_HW_FILE }, + '\0', "FILE", "Add the devices listed in the file", + hw_option_handler }, + + { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL } +}; + + + +/* Copied from ../ppc/psim.c:psim_merge_device_file() */ + +static SIM_RC +merge_device_file (struct sim_state *sd, + const char *file_name) +{ + FILE *description; + struct hw *current = STATE_HW (sd)->tree; + int line_nr; + char device_path[1000]; + + /* try opening the file */ + description = fopen (file_name, "r"); + if (description == NULL) + { + perror (file_name); + return SIM_RC_FAIL; + } + + line_nr = 0; + while (fgets (device_path, sizeof(device_path), description)) + { + char *device; + /* check that a complete line was read */ + if (strchr (device_path, '\n') == NULL) + { + fclose (description); + sim_io_eprintf (sd, "%s:%d: line to long", file_name, line_nr); + return SIM_RC_FAIL; + } + *strchr (device_path, '\n') = '\0'; + line_nr++; + /* skip comments ("#" or ";") and blank lines lines */ + for (device = device_path; + *device != '\0' && isspace (*device); + device++); + if (device[0] == '#' + || device[0] == ';' + || device[0] == '\0') + continue; + /* merge any appended lines */ + while (device_path[strlen (device_path) - 1] == '\\') + { + int curlen = strlen (device_path) - 1; + /* zap the `\' at the end of the line */ + device_path[curlen] = '\0'; + /* append the next line */ + if (!fgets (device_path + curlen, + sizeof (device_path) - curlen, + description)) + { + fclose (description); + sim_io_eprintf (sd, "%s:%d: unexpected eof", file_name, line_nr); + return SIM_RC_FAIL; + } + if (strchr(device_path, '\n') == NULL) + { + fclose(description); + sim_io_eprintf (sd, "%s:%d: line to long", file_name, line_nr); + return SIM_RC_FAIL; + } + *strchr(device_path, '\n') = '\0'; + line_nr++; + } + /* parse this line */ + current = hw_tree_parse (current, "%s", device); + } + fclose (description); + return SIM_RC_OK; +} + + +static SIM_RC +hw_option_handler (struct sim_state *sd, sim_cpu *cpu, int opt, + char *arg, int is_command) +{ + switch (opt) + { + + case OPTION_HW_INFO: + { + /* delay info until after the tree is finished */ + STATE_HW (sd)->info_p = 1; + return SIM_RC_OK; + break; + } + + case OPTION_HW_TRACE: + { + if (arg == NULL) + { + STATE_HW (sd)->trace_p = 1; + } + else if (strcmp (arg, "yes") == 0 + || strcmp (arg, "on") == 0) + { + STATE_HW (sd)->trace_p = 1; + } + else if (strcmp (arg, "no") == 0 + || strcmp (arg, "off") == 0) + { + STATE_HW (sd)->trace_p = 0; + } + else + { + sim_io_eprintf (sd, "Option --hw-trace ignored\n"); + /* set tracing on all devices */ + return SIM_RC_FAIL; + } + /* FIXME: Not very nice - see also hw-base.c */ + if (STATE_HW (sd)->trace_p) + hw_tree_parse (STATE_HW (sd)->tree, "/global-trace? true"); + return SIM_RC_OK; + break; + } + + case OPTION_HW_DEVICE: + { + hw_tree_parse (STATE_HW (sd)->tree, arg); + return SIM_RC_OK; + } + + case OPTION_HW_FILE: + { + return merge_device_file (sd, arg); + } + + default: + sim_io_eprintf (sd, "Unknown hw option %d\n", opt); + return SIM_RC_FAIL; + + } + + return SIM_RC_FAIL; +} + + +/* "hw" module install handler. + + This is called via sim_module_install to install the "hw" subsystem + into the simulator. */ + +static MODULE_INIT_FN sim_hw_init; +static MODULE_UNINSTALL_FN sim_hw_uninstall; + +SIM_RC +sim_hw_install (struct sim_state *sd) +{ + SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); + sim_add_option_table (sd, NULL, hw_options); + sim_module_add_uninstall_fn (sd, sim_hw_uninstall); + sim_module_add_init_fn (sd, sim_hw_init); + STATE_HW (sd) = ZALLOC (struct sim_hw); + STATE_HW (sd)->tree = hw_tree_create (sd, "core"); + return SIM_RC_OK; +} + + +static SIM_RC +sim_hw_init (struct sim_state *sd) +{ + /* FIXME: anything needed? */ + hw_tree_finish (STATE_HW (sd)->tree); + if (STATE_HW (sd)->info_p) + sim_hw_print (sd, sim_io_vprintf); + return SIM_RC_OK; +} + +/* Uninstall the "hw" subsystem from the simulator. */ + +static void +sim_hw_uninstall (struct sim_state *sd) +{ + /* hw_tree_delete (STATE_HW (sd)->tree); */ + zfree (STATE_HW (sd)); + STATE_HW (sd) = NULL; +} + + + +/* Data transfers to/from the hardware device tree. There are several + cases. */ + + +/* CPU: The simulation is running and the current CPU/CIA + initiates a data transfer. */ + +void +sim_cpu_hw_io_read_buffer (sim_cpu *cpu, + sim_cia cia, + struct hw *hw, + void *dest, + int space, + unsigned_word addr, + unsigned nr_bytes) +{ + SIM_DESC sd = CPU_STATE (cpu); + STATE_HW (sd)->cpu = cpu; + STATE_HW (sd)->cia = cia; + if (hw_io_read_buffer (hw, dest, space, addr, nr_bytes) != nr_bytes) + sim_engine_abort (sd, cpu, cia, "broken CPU read"); +} + +void +sim_cpu_hw_io_write_buffer (sim_cpu *cpu, + sim_cia cia, + struct hw *hw, + const void *source, + int space, + unsigned_word addr, + unsigned nr_bytes) +{ + SIM_DESC sd = CPU_STATE (cpu); + STATE_HW (sd)->cpu = cpu; + STATE_HW (sd)->cia = cia; + if (hw_io_write_buffer (hw, source, space, addr, nr_bytes) != nr_bytes) + sim_engine_abort (sd, cpu, cia, "broken CPU write"); +} + + + + +/* SYSTEM: A data transfer is being initiated by the system. */ + +unsigned +sim_hw_io_read_buffer (struct sim_state *sd, + struct hw *hw, + void *dest, + int space, + unsigned_word addr, + unsigned nr_bytes) +{ + STATE_HW (sd)->cpu = NULL; + return hw_io_read_buffer (hw, dest, space, addr, nr_bytes); +} + +unsigned +sim_hw_io_write_buffer (struct sim_state *sd, + struct hw *hw, + const void *source, + int space, + unsigned_word addr, + unsigned nr_bytes) +{ + STATE_HW (sd)->cpu = NULL; + return hw_io_write_buffer (hw, source, space, addr, nr_bytes); +} + + + +/* Abort the simulation specifying HW as the reason */ + +void +hw_vabort (struct hw *me, + const char *fmt, + va_list ap) +{ + const char *name; + char *msg; + /* find an identity */ + if (me != NULL && hw_path (me) != NULL && hw_path (me) [0] != '\0') + name = hw_path (me); + else if (me != NULL && hw_name (me) != NULL && hw_name (me)[0] != '\0') + name = hw_name (me); + else if (me != NULL && hw_family (me) != NULL && hw_family (me)[0] != '\0') + name = hw_family (me); + else + name = "device"; + /* construct an updated format string */ + msg = alloca (strlen (name) + strlen (": ") + strlen (fmt) + 1); + strcpy (msg, name); + strcat (msg, ": "); + strcat (msg, fmt); + /* report the problem */ + sim_engine_vabort (hw_system (me), + STATE_HW (hw_system (me))->cpu, + STATE_HW (hw_system (me))->cia, + msg, ap); +} + +void +hw_abort (struct hw *me, + const char *fmt, + ...) +{ + va_list ap; + /* report the problem */ + va_start (ap, fmt); + hw_vabort (me, fmt, ap); + va_end (ap); +} + +void +sim_hw_abort (struct sim_state *sd, + struct hw *me, + const char *fmt, + ...) +{ + va_list ap; + va_start (ap, fmt); + if (me == NULL) + sim_engine_vabort (sd, NULL, NULL_CIA, fmt, ap); + else + hw_vabort (me, fmt, ap); + va_end (ap); +} + + +/* MISC routines to tie HW into the rest of the system */ + +void +hw_halt (struct hw *me, + int reason, + int status) +{ + struct sim_state *sd = hw_system (me); + struct sim_hw *sim = STATE_HW (sd); + sim_engine_halt (sd, sim->cpu, NULL, sim->cia, reason, status); +} + +struct _sim_cpu * +hw_system_cpu (struct hw *me) +{ + return STATE_HW (hw_system (me))->cpu; +} + +void +hw_trace (struct hw *me, + const char *fmt, + ...) +{ + if (hw_trace_p (me)) /* to be sure, to be sure */ + { + va_list ap; + va_start (ap, fmt); + sim_io_eprintf (hw_system (me), "%s: ", hw_path (me)); + sim_io_evprintf (hw_system (me), fmt, ap); + sim_io_eprintf (hw_system (me), "\n"); + va_end (ap); + } +} + + +/* Based on gdb-4.17/sim/ppc/main.c:sim_io_read_stdin() */ + +int +do_hw_poll_read (struct hw *me, + do_hw_poll_read_method *read, + int sim_io_fd, + void *buf, + unsigned sizeof_buf) +{ + int status = read (hw_system (me), sim_io_fd, buf, sizeof_buf); + if (status > 0) + return status; + else if (status == 0 && sizeof_buf == 0) + return 0; + else if (status == 0) + return HW_IO_EOF; + else /* status < 0 */ + { +#ifdef EAGAIN + if (STATE_CALLBACK (hw_system (me))->last_errno == EAGAIN) + return HW_IO_NOT_READY; + else + return HW_IO_EOF; +#else + return HW_IO_EOF; +#endif + } +} diff --git a/sim/common/sim-hw.h b/sim/common/sim-hw.h new file mode 100644 index 00000000000..1bebd1829d3 --- /dev/null +++ b/sim/common/sim-hw.h @@ -0,0 +1,98 @@ +/* Device definitions. + Copyright (C) 1998 Free Software Foundation, Inc. + Contributed by Cygnus Support. + +This file is part of GDB, the GNU debugger. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef SIM_HW_H +#define SIM_HW_H + + +/* Establish this object */ + +SIM_RC sim_hw_install +(struct sim_state *sd); + + +/* Parse a hardware definition */ + +struct hw *sim_hw_parse +(struct sim_state *sd, + const char *fmt, + ...) __attribute__ ((format (printf, 2, 3))); + + +/* Print the hardware tree */ + +void sim_hw_print +(struct sim_state *sd, + void (*print) (struct sim_state *, const char *, va_list ap)); + + +/* Abort the simulation specifying HW as the reason */ + +void sim_hw_abort +(SIM_DESC sd, + struct hw *hw, + const char *fmt, + ...) __attribute__ ((format (printf, 3, 4))); + + + +/* CPU: The simulation is running and the current CPU/CIA + initiates a data transfer. */ + +void sim_cpu_hw_io_read_buffer +(sim_cpu *cpu, + sim_cia cia, + struct hw *hw, + void *dest, + int space, + unsigned_word addr, + unsigned nr_bytes); + +void sim_cpu_hw_io_write_buffer +(sim_cpu *cpu, + sim_cia cia, + struct hw *hw, + const void *source, + int space, + unsigned_word addr, + unsigned nr_bytes); + + + +/* SYSTEM: A data transfer is being initiated by the system. */ + +unsigned sim_hw_io_read_buffer +(struct sim_state *sd, + struct hw *hw, + void *dest, + int space, + unsigned_word addr, + unsigned nr_bytes); + +unsigned sim_hw_io_write_buffer +(struct sim_state *sd, + struct hw *hw, + const void *source, + int space, + unsigned_word addr, + unsigned nr_bytes); + + +#endif diff --git a/sim/common/sim-info.c b/sim/common/sim-info.c new file mode 100644 index 00000000000..00832277315 --- /dev/null +++ b/sim/common/sim-info.c @@ -0,0 +1,32 @@ +/* Generic memory read/write for hardware simulator models. + Copyright (C) 1998 Free Software Foundation, Inc. + Contributed by Cygnus Support. + +This file is part of GDB, the GNU debugger. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "sim-main.h" +#include "sim-assert.h" + +/* Generic implementation of sim_info that works with simulators using + sim-module. */ + +void +sim_info (SIM_DESC sd, int verbose) +{ + SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); + sim_module_info (sd, verbose || STATE_VERBOSE_P (sd)); +} diff --git a/sim/common/sim-inline.c b/sim/common/sim-inline.c new file mode 100644 index 00000000000..770c65eb840 --- /dev/null +++ b/sim/common/sim-inline.c @@ -0,0 +1,96 @@ +/* This file is part of the program psim. + + Copyright (C) 1994-1997, Andrew Cagney + Copyright (C) 1997, Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + + +#ifndef SIM_INLINE_C +#define SIM_INLINE_C + +#undef SIM_INLINE_P +#define SIM_INLINE_P 1 + +#include "sim-inline.h" +#include "sim-main.h" + + +#if C_REVEALS_MODULE_P (SIM_BITS_INLINE) +#include "sim-bits.c" +#endif + + +#if C_REVEALS_MODULE_P (SIM_CORE_INLINE) +#include "sim-core.c" +#endif + + +#if C_REVEALS_MODULE_P (SIM_ENDIAN_INLINE) +#include "sim-endian.c" +#endif + + +#if C_REVEALS_MODULE_P (SIM_EVENTS_INLINE) +#include "sim-events.c" +#endif + + +#if C_REVEALS_MODULE_P (SIM_FPU_INLINE) +#include "sim-fpu.c" +#endif + + +#if C_REVEALS_MODULE_P (SIM_TYPES_INLINE) +#include "sim-types.c" +#endif + + +#if C_REVEALS_MODULE_P (SIM_MAIN_INLINE) +#include "sim-main.c" +#endif + + +#if C_REVEALS_MODULE_P (ENGINE_INLINE) +/* #include "engine.c" - handled by generator */ +#endif + + +#if C_REVEALS_MODULE_P (ICACHE_INLINE) +/* #include "icache.c" - handled by generator */ +#endif + + +#if C_REVEALS_MODULE_P (IDECODE_INLINE) +/* #include "idecode.c" - handled by generator */ +#endif + + +#if C_REVEALS_MODULE_P (SEMANTICS_INLINE) +/* #include "semantics.c" - handled by generator */ +#endif + + +#if C_REVEALS_MODULE_P (SUPPORT_INLINE) +/* #include "support.c" - handled by generator */ +#endif + + +#undef SIM_INLINE_P +#define SIM_INLINE_P 0 + +#endif diff --git a/sim/common/sim-inline.h b/sim/common/sim-inline.h new file mode 100644 index 00000000000..300658d374e --- /dev/null +++ b/sim/common/sim-inline.h @@ -0,0 +1,810 @@ +/* This file is part of the program psim. + + Copyright (C) 1994-1997, Andrew Cagney + Copyright (C) 1997, Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + + +#ifndef SIM_INLINE_H +#define SIM_INLINE_H + + +/* INLINE CODE SELECTION: + + GCC -O3 attempts to inline any function or procedure in scope. The + options below facilitate finer grained control over what is and + what is not inlined. In particular, it allows the selection of + modules for inlining. Doing this allows the compiler to both + eliminate the overhead of function calls and (as a consequence) + also eliminate further dead code. + + On a CISC (x86) I've found that I can achieve an order of magintude + speed improvement (x3-x5). In the case of RISC (sparc) while the + performance gain isn't as great it is still significant. + + Each module is controled by the macro _INLINE which can + have the values described below + + 0 (ZERO) + + Do not inline any thing for the given module + + The following bit fields values can be combined: + + H_REVEALS_MODULE: + C_REVEALS_MODULE: + + Include the C file for the module into the file being + compiled. The actual inlining is controlled separatly. + + While of no apparent benefit, this makes it possible for the + included module, when compiled, to inline its calls to what + would otherwize be external functions. + + {C_,H_} Determines where the module is inlined. A + H_REVEALS_MODULE will be included everywhere. + + INLINE_GLOBALS: + + Make external functions within the module `inline'. Thus if + the module is included into a file being compiled, calls to + the included modules funtions can be eliminated. INLINE_MODULE + implies REVEAL_MODULE. + + INLINE_LOCALS: + + Make internal (static) functions within the module `inline'. + + + CODING STYLE: + + The inline ability is enabled by specifying every data and function + declaration and definition using one of the following methods: + + + GLOBAL INLINE FUNCTIONS: + + Such functions are small and used heavily. Inlining them + will eliminate an unnecessary function call overhead. + + .h: INLINE_OURPKG (void) ourpkg_func + (int x, + int y); + + .c: INLINE_OURPKG (void) + ourpkg_func (int x, + int y) + { + ... + } + + + GLOBAL INLINE VARIABLES: + + This doesn't make much sense. + + + GLOBAL NON-INLINE (EXTERN) FUNCTIONS AND VARIABLES: + + These include functions with varargs parameters. It can + also include large rarely used functions that contribute + little when inlined. + + .h: extern int ourpkg_print + (char *fmt, ...); + extern int a_global_variable; + + .c: #if EXTERN_OURPKG_P + int + ourpkg_print (char *fmt, + ...) + { + ... + } + #endif + #if EXTERN_OURPKG_P + int a_global_variable = 1; + #endif + + + LOCAL (STATIC) FUNCTIONS: + + These can either be marked inline or just static static vis: + + .h: STATIC_INLINE_OURPKG (int) ourpkg_staticf (void); + .c: STATIC_INLINE_OURPKG (int) + ourpkg_staticf (void) + { + .. + } + + .h: STATIC_OURPKG (int) ourpkg_staticf (void); + .c: STATIC_OURPKG (int) + ourpkg_staticf (void) + { + .. + } + + + All .h files: + + + All modules must wrap their .h code in the following: + + #ifndef OURPKG_H + #define OURPKG_H + ... code proper ... + #endif + + In addition, modules that want to allow global inlining must + include the lines (below) at the end of the .h file. (FIXME: + Shouldn't be needed). + + #if H_REVEALS_MODULE_P (OURPKG_INLINE) + #include "ourpkg.c" + #endif + + + All .c files: + + All modules must wrap their .c code in the following + + #ifndef OURPKG_C + #define OURPKG_C + ... code proper ... + #endif + + + NOW IT WORKS: + + 0: + + Since no inlining is defined. All macro's get standard defaults + (extern, static, ...). + + + + H_REVEALS_MODULE (alt includes our): + + + altprog.c defines ALTPROG_C and then includes sim-inline.h. + + In sim-inline.h the expression `` H_REVEALS_MODULE_P + (OURPROG_INLINE) && ! defined (OURPROG_C) && REVEAL_MODULE_P + (OURPROG_INLINE) '' is TRUE so it defines *_OURPROG as static + and EXTERN_OURPROG_P as FALSE. + + altprog.c includes ourprog.h. + + In ourprog.h the expression ``H_REVEALS_MODULE_P + (OURPROG_INLINE)'' is TRUE so it includes ourprog.c. + + Consequently, all the code in ourprog.c is visible and static in + the file altprog.c + + + + H_REVEALS_MODULE (our includes our): + + + ourprog.c defines OURPROG_C and then includes sim-inline.h. + + In sim-inline.h the term `` ! defined (OURPROG_C) '' is FALSE so + it defines *_OURPROG as non-static and EXTERN_OURPROG_P as TRUE. + + ourprog.c includes ourprog.h. + + In ourprog.h the expression ``H_REVEALS_MODULE_P + (OURPROG_INLINE)'' is true so it includes ourprog.c. + + In ourprog.c (second include) the expression defined (OURPROG_C) + and so the body is not re-included. + + Consequently, ourprog.o will contain a non-static copy of all + the exported symbols. + + + + C_REVEALS_MODULE (alt includes our): + + + altprog.c defines ALTPROG_C and then includes sim-inline.c + + sim-inline.c defines C_INLINE_C and then includes sim-inline.h + + In sim-inline.h the expression `` defined (SIM_INLINE) && ! + defined (OURPROG_C) && REVEAL_MODULE_P (OURPROG_INLINE) '' is + true so it defines *_OURPROG as static and EXTERN_OURPROG_P as + FALSE. + + In sim-inline.c the expression ``C_REVEALS_MODULE_P + (OURPROG_INLINE)'' is true so it includes ourprog.c. + + Consequently, all the code in ourprog.c is visible and static in + the file altprog.c. + + + + C_REVEALS_MODULE (our includes our): + + + ourprog.c defines OURPROG_C and then includes sim-inline.c + + sim-inline.c defines C_INLINE_C and then includes sim-inline.h + + In sim-inline.h the term `` ! defined (OURPROG_C) '' is FALSE + so it defines *_OURPROG as non-static and EXTERN_OURPROG_P as + TRUE. + + Consequently, ourprog.o will contain a non-static copy of all + the exported symbols. + + + + REALITY CHECK: + + This is not for the faint hearted. I've seen GCC get up to 500mb + trying to compile what this can create. */ + +#define H_REVEALS_MODULE 1 +#define C_REVEALS_MODULE 2 +#define INLINE_GLOBALS 4 +#define INLINE_LOCALS 8 + +#define REGPARM_MODULE 32 + +#define ALL_H_INLINE (H_REVEALS_MODULE | INLINE_GLOBALS | INLINE_LOCALS) +#define ALL_C_INLINE (C_REVEALS_MODULE | INLINE_GLOBALS | INLINE_LOCALS) + + +/* Default macro to simplify control several of key the inlines */ + +#ifndef DEFAULT_INLINE +#define DEFAULT_INLINE INLINE_LOCALS +#endif + +#define REVEAL_MODULE_P(X) (X & (H_REVEALS_MODULE | C_REVEALS_MODULE)) +#define H_REVEALS_MODULE_P(X) ((X & H_REVEALS_MODULE)) +#define C_REVEALS_MODULE_P(X) ((X & C_REVEALS_MODULE)) + + +#ifndef HAVE_INLINE +#ifdef __GNUC__ +#define HAVE_INLINE +#endif +#endif + + +/* Your compilers inline prefix */ + +#ifndef INLINE +#if defined (__GNUC__) && defined (__OPTIMIZE__) +#define INLINE __inline__ +#else +#define INLINE /*inline*/ +#endif +#endif + +/* ??? Temporary, pending decision to always use extern inline and do a vast + cleanup of inline support. */ +#ifndef INLINE2 +#if defined (__GNUC__) +#define INLINE2 __inline__ +#else +#define INLINE2 /*inline*/ +#endif +#endif + + +/* Your compiler's static inline prefix */ + +#ifndef STATIC_INLINE +#define STATIC_INLINE static INLINE +#endif + + +/* Your compiler's extern inline prefix */ + +#ifndef EXTERN_INLINE +#define EXTERN_INLINE extern INLINE2 +#endif + + +/* Your compiler's no-return reserved word */ + +#ifndef NORETURN +#define NORETURN +#endif + + + +/* Your compilers's unused reserved word */ + +#if !defined (UNUSED) +#if (!defined (__GNUC__) \ + || (__GNUC__ < 2) \ + || (__GNUC__ == 2 && __GNUC_MINOR__ < 7)) +#define UNUSED +#else +#define UNUSED __attribute__((__unused__)) +#endif +#endif + + + + +/* Your compilers nonstandard function call mechanism prefix */ + +#if !defined REGPARM +#if defined (__GNUC__) && (defined (__i386__) || defined (__i486__) || defined (__i586__) || defined (__i686__)) +#if (WITH_REGPARM && WITH_STDCALL) +#define REGPARM __attribute__((__regparm__(WITH_REGPARM),__stdcall__)) +#else +#if (WITH_REGPARM && !WITH_STDCALL) +#define REGPARM __attribute__((__regparm__(WITH_REGPARM))) +#else +#if (!WITH_REGPARM && WITH_STDCALL) +#define REGPARM __attribute__((__stdcall__)) +#endif +#endif +#endif +#endif +#endif + +#if !defined REGPARM +#define REGPARM +#endif + + + +/* ***** + sim-bits and sim-endian are treated differently from the rest + of the modules below. Their default value is ALL_H_INLINE. + The rest are ALL_C_INLINE. Don't blink, you'll miss it! + ***** + */ + +/* sim-bits */ + +#if !defined (SIM_BITS_INLINE) && (DEFAULT_INLINE) +# define SIM_BITS_INLINE (ALL_H_INLINE) +#endif + +#if (SIM_BITS_INLINE & REGPARM_MODULE) +# define REGPARM_SIM_BITS REGPARM +#else +# define REGPARM_SIM_BITS +#endif + +#if ((H_REVEALS_MODULE_P (SIM_BITS_INLINE) || defined (SIM_INLINE_C)) \ + && !defined (SIM_BITS_C) \ + && (REVEAL_MODULE_P (SIM_BITS_INLINE))) +# if (SIM_BITS_INLINE & INLINE_GLOBALS) +# define INLINE_SIM_BITS(TYPE) static INLINE TYPE UNUSED +# define EXTERN_SIM_BITS_P 0 +# else +# define INLINE_SIM_BITS(TYPE) static TYPE UNUSED REGPARM_SIM_BITS +# define EXTERN_SIM_BITS_P 0 +# endif +#else +# define INLINE_SIM_BITS(TYPE) TYPE REGPARM_SIM_BITS +# define EXTERN_SIM_BITS_P 1 +#endif + +#if (SIM_BITS_INLINE & INLINE_LOCALS) +# define STATIC_INLINE_SIM_BITS(TYPE) static INLINE TYPE +#else +# define STATIC_INLINE_SIM_BITS(TYPE) static TYPE REGPARM_SIM_BITS +#endif + +#define STATIC_SIM_BITS(TYPE) static TYPE + + + +/* sim-core */ + +#if !defined (SIM_CORE_INLINE) && (DEFAULT_INLINE) +# define SIM_CORE_INLINE ALL_C_INLINE +#endif + +#if (SIM_CORE_INLINE & REGPARM_MODULE) +# define REGPARM_SIM_CORE REGPARM +#else +# define REGPARM_SIM_CORE +#endif + +#if ((H_REVEALS_MODULE_P (SIM_CORE_INLINE) || defined (SIM_INLINE_C)) \ + && !defined (SIM_CORE_C) \ + && (REVEAL_MODULE_P (SIM_CORE_INLINE))) +# if (SIM_CORE_INLINE & INLINE_GLOBALS) +# define INLINE_SIM_CORE(TYPE) static INLINE TYPE UNUSED +# define EXTERN_SIM_CORE_P 0 +#else +# define INLINE_SIM_CORE(TYPE) static TYPE UNUSED REGPARM_SIM_CORE +# define EXTERN_SIM_CORE_P 0 +#endif +#else +# define INLINE_SIM_CORE(TYPE) TYPE REGPARM_SIM_CORE +# define EXTERN_SIM_CORE_P 1 +#endif + +#if (SIM_CORE_INLINE & INLINE_LOCALS) +# define STATIC_INLINE_SIM_CORE(TYPE) static INLINE TYPE +#else +# define STATIC_INLINE_SIM_CORE(TYPE) static TYPE REGPARM_SIM_CORE +#endif + +#define STATIC_SIM_CORE(TYPE) static TYPE + + + +/* sim-endian */ + +#if !defined (SIM_ENDIAN_INLINE) && (DEFAULT_INLINE) +# define SIM_ENDIAN_INLINE ALL_H_INLINE +#endif + +#if (SIM_ENDIAN_INLINE & REGPARM_MODULE) +# define REGPARM_SIM_ENDIAN REGPARM +#else +# define REGPARM_SIM_ENDIAN +#endif + +#if ((H_REVEALS_MODULE_P (SIM_ENDIAN_INLINE) || defined (SIM_INLINE_C)) \ + && !defined (SIM_ENDIAN_C) \ + && (REVEAL_MODULE_P (SIM_ENDIAN_INLINE))) +# if (SIM_ENDIAN_INLINE & INLINE_GLOBALS) +# define INLINE_SIM_ENDIAN(TYPE) static INLINE TYPE UNUSED +# define EXTERN_SIM_ENDIAN_P 0 +# else +# define INLINE_SIM_ENDIAN(TYPE) static TYPE UNUSED REGPARM_SIM_ENDIAN +# define EXTERN_SIM_ENDIAN_P 0 +# endif +#else +# define INLINE_SIM_ENDIAN(TYPE) TYPE REGPARM_SIM_ENDIAN +# define EXTERN_SIM_ENDIAN_P 1 +#endif + +#if (SIM_ENDIAN_INLINE & INLINE_LOCALS) +# define STATIC_INLINE_SIM_ENDIAN(TYPE) static INLINE TYPE +#else +# define STATIC_INLINE_SIM_ENDIAN(TYPE) static TYPE REGPARM_SIM_ENDIAN +#endif + +#define STATIC_SIM_ENDIAN(TYPE) static TYPE + + + +/* sim-events */ + +#if !defined (SIM_EVENTS_INLINE) && (DEFAULT_INLINE) +# define SIM_EVENTS_INLINE ALL_C_INLINE +#endif + +#if (SIM_EVENTS_INLINE & REGPARM_MODULE) +# define REGPARM_SIM_EVENTS REGPARM +#else +# define REGPARM_SIM_EVENTS +#endif + +#if ((H_REVEALS_MODULE_P (SIM_EVENTS_INLINE) || defined (SIM_INLINE_C)) \ + && !defined (SIM_EVENTS_C) \ + && (REVEAL_MODULE_P (SIM_EVENTS_INLINE))) +# if (SIM_EVENTS_INLINE & INLINE_GLOBALS) +# define INLINE_SIM_EVENTS(TYPE) static INLINE TYPE UNUSED +# define EXTERN_SIM_EVENTS_P 0 +# else +# define INLINE_SIM_EVENTS(TYPE) static TYPE UNUSED REGPARM_SIM_EVENTS +# define EXTERN_SIM_EVENTS_P 0 +# endif +#else +# define INLINE_SIM_EVENTS(TYPE) TYPE REGPARM_SIM_EVENTS +# define EXTERN_SIM_EVENTS_P 1 +#endif + +#if (SIM_EVENTS_INLINE & INLINE_LOCALS) +# define STATIC_INLINE_SIM_EVENTS(TYPE) static INLINE TYPE +#else +# define STATIC_INLINE_SIM_EVENTS(TYPE) static TYPE REGPARM_SIM_EVENTS +#endif + +#define STATIC_SIM_EVENTS(TYPE) static TYPE + + + +/* sim-fpu */ + +#if !defined (SIM_FPU_INLINE) && (DEFAULT_INLINE) +# define SIM_FPU_INLINE ALL_C_INLINE +#endif + +#if (SIM_FPU_INLINE & REGPARM_MODULE) +# define REGPARM_SIM_FPU REGPARM +#else +# define REGPARM_SIM_FPU +#endif + +#if ((H_REVEALS_MODULE_P (SIM_FPU_INLINE) || defined (SIM_INLINE_C)) \ + && !defined (SIM_FPU_C) \ + && (REVEAL_MODULE_P (SIM_FPU_INLINE))) +# if (SIM_FPU_INLINE & INLINE_GLOBALS) +# define INLINE_SIM_FPU(TYPE) static INLINE TYPE UNUSED +# define EXTERN_SIM_FPU_P 0 +# else +# define INLINE_SIM_FPU(TYPE) static TYPE UNUSED REGPARM_SIM_FPU +# define EXTERN_SIM_FPU_P 0 +# endif +#else +# define INLINE_SIM_FPU(TYPE) TYPE REGPARM_SIM_FPU +# define EXTERN_SIM_FPU_P 1 +#endif + +#if (SIM_FPU_INLINE & INLINE_LOCALS) +# define STATIC_INLINE_SIM_FPU(TYPE) static INLINE TYPE +#else +# define STATIC_INLINE_SIM_FPU(TYPE) static TYPE REGPARM_SIM_FPU +#endif + +#define STATIC_SIM_FPU(TYPE) static TYPE + + + +/* sim-types */ + +#if (SIM_TYPES_INLINE & REGPARM_MODULE) +# define REGPARM_SIM_TYPES REGPARM +#else +# define REGPARM_SIM_TYPES +#endif + +#if ((H_REVEALS_MODULE_P (SIM_TYPES_INLINE) || defined (SIM_INLINE_C)) \ + && !defined (SIM_TYPES_C) \ + && (REVEAL_MODULE_P (SIM_TYPES_INLINE))) +# if (SIM_TYPES_INLINE & INLINE_GLOBALS) +# define INLINE_SIM_TYPES(TYPE) static INLINE TYPE UNUSED +# define EXTERN_SIM_TYPES_P 0 +# else +# define INLINE_SIM_TYPES(TYPE) static TYPE UNUSED REGPARM_SIM_TYPES +# define EXTERN_SIM_TYPES_P 0 +# endif +#else +# define INLINE_SIM_TYPES(TYPE) TYPE REGPARM_SIM_TYPES +# define EXTERN_SIM_TYPES_P 1 +#endif + +#if (SIM_TYPES_INLINE & INLINE_LOCALS) +# define STATIC_INLINE_SIM_TYPES(TYPE) static INLINE TYPE +#else +# define STATIC_INLINE_SIM_TYPES(TYPE) static TYPE REGPARM_SIM_TYPES +#endif + +#define STATIC_SIM_TYPES(TYPE) static TYPE + + + +/* sim_main */ + +#if !defined (SIM_MAIN_INLINE) && (DEFAULT_INLINE) +# define SIM_MAIN_INLINE (ALL_C_INLINE) +#endif + +#if (SIM_MAIN_INLINE & REGPARM_MODULE) +# define REGPARM_SIM_MAIN REGPARM +#else +# define REGPARM_SIM_MAIN +#endif + +#if ((H_REVEALS_MODULE_P (SIM_MAIN_INLINE) || defined (SIM_INLINE_C)) \ + && !defined (SIM_MAIN_C) \ + && (REVEAL_MODULE_P (SIM_MAIN_INLINE))) +# if (SIM_MAIN_INLINE & INLINE_GLOBALS) +# define INLINE_SIM_MAIN(TYPE) static INLINE TYPE UNUSED +# define EXTERN_SIM_MAIN_P 0 +# else +# define INLINE_SIM_MAIN(TYPE) static TYPE UNUSED REGPARM_SIM_MAIN +# define EXTERN_SIM_MAIN_P 0 +# endif +#else +# define INLINE_SIM_MAIN(TYPE) TYPE REGPARM_SIM_MAIN +# define EXTERN_SIM_MAIN_P 1 +#endif + +#if (SIM_MAIN_INLINE & INLINE_LOCALS) +# define STATIC_INLINE_SIM_MAIN(TYPE) static INLINE TYPE +#else +# define STATIC_INLINE_SIM_MAIN(TYPE) static TYPE REGPARM_SIM_MAIN +#endif + +#define STATIC_SIM_MAIN(TYPE) static TYPE + +/* engine */ + +#if (ENGINE_INLINE & REGPARM_MODULE) +# define REGPARM_ENGINE REGPARM +#else +# define REGPARM_ENGINE +#endif + +#if ((H_REVEALS_MODULE_P (ENGINE_INLINE) || defined (SIM_INLINE_C)) \ + && !defined (ENGINE_C) \ + && (REVEAL_MODULE_P (ENGINE_INLINE))) +# if (ENGINE_INLINE & INLINE_GLOBALS) +# define INLINE_ENGINE(TYPE) static INLINE TYPE UNUSED +# define EXTERN_ENGINE_P 0 +# else +# define INLINE_ENGINE(TYPE) static TYPE UNUSED REGPARM_ENGINE +# define EXTERN_ENGINE_P 0 +# endif +#else +# define INLINE_ENGINE(TYPE) TYPE REGPARM_ENGINE +# define EXTERN_ENGINE_P 1 +#endif + +#if (ENGINE_INLINE & INLINE_LOCALS) +# define STATIC_INLINE_ENGINE(TYPE) static INLINE TYPE +#else +# define STATIC_INLINE_ENGINE(TYPE) static TYPE REGPARM_ENGINE +#endif + +#define STATIC_ENGINE(TYPE) static TYPE + + + +/* icache */ + +#if (ICACHE_INLINE & REGPARM_MODULE) +# define REGPARM_ICACHE REGPARM +#else +# define REGPARM_ICACHE +#endif + +#if ((H_REVEALS_MODULE_P (ICACHE_INLINE) || defined (SIM_INLINE_C)) \ + && !defined (ICACHE_C) \ + && (REVEAL_MODULE_P (ICACHE_INLINE))) +# if (ICACHE_INLINE & INLINE_GLOBALS) +# define INLINE_ICACHE(TYPE) static INLINE TYPE UNUSED +# define EXTERN_ICACHE_P 0 +#else +# define INLINE_ICACHE(TYPE) static TYPE UNUSED REGPARM_ICACHE +# define EXTERN_ICACHE_P 0 +#endif +#else +# define INLINE_ICACHE(TYPE) TYPE REGPARM_ICACHE +# define EXTERN_ICACHE_P 1 +#endif + +#if (ICACHE_INLINE & INLINE_LOCALS) +# define STATIC_INLINE_ICACHE(TYPE) static INLINE TYPE +#else +# define STATIC_INLINE_ICACHE(TYPE) static TYPE REGPARM_ICACHE +#endif + +#define STATIC_ICACHE(TYPE) static TYPE + + + +/* idecode */ + +#if (IDECODE_INLINE & REGPARM_MODULE) +# define REGPARM_IDECODE REGPARM +#else +# define REGPARM_IDECODE +#endif + +#if ((H_REVEALS_MODULE_P (IDECODE_INLINE) || defined (SIM_INLINE_C)) \ + && !defined (IDECODE_C) \ + && (REVEAL_MODULE_P (IDECODE_INLINE))) +# if (IDECODE_INLINE & INLINE_GLOBALS) +# define INLINE_IDECODE(TYPE) static INLINE TYPE UNUSED +# define EXTERN_IDECODE_P 0 +#else +# define INLINE_IDECODE(TYPE) static TYPE UNUSED REGPARM_IDECODE +# define EXTERN_IDECODE_P 0 +#endif +#else +# define INLINE_IDECODE(TYPE) TYPE REGPARM_IDECODE +# define EXTERN_IDECODE_P 1 +#endif + +#if (IDECODE_INLINE & INLINE_LOCALS) +# define STATIC_INLINE_IDECODE(TYPE) static INLINE TYPE +#else +# define STATIC_INLINE_IDECODE(TYPE) static TYPE REGPARM_IDECODE +#endif + +#define STATIC_IDECODE(TYPE) static TYPE + + + +/* semantics */ + +#if (SEMANTICS_INLINE & REGPARM_MODULE) +# define REGPARM_SEMANTICS REGPARM +#else +# define REGPARM_SEMANTICS +#endif + +#if ((H_REVEALS_MODULE_P (SEMANTICS_INLINE) || defined (SIM_INLINE_C)) \ + && !defined (SEMANTICS_C) \ + && (REVEAL_MODULE_P (SEMANTICS_INLINE))) +# if (SEMANTICS_INLINE & INLINE_GLOBALS) +# define INLINE_SEMANTICS(TYPE) static INLINE TYPE UNUSED +# define EXTERN_SEMANTICS_P 0 +#else +# define INLINE_SEMANTICS(TYPE) static TYPE UNUSED REGPARM_SEMANTICS +# define EXTERN_SEMANTICS_P 0 +#endif +#else +# define INLINE_SEMANTICS(TYPE) TYPE REGPARM_SEMANTICS +# define EXTERN_SEMANTICS_P 1 +#endif + +#if EXTERN_SEMANTICS_P +# define EXTERN_SEMANTICS(TYPE) TYPE REGPARM_SEMANTICS +#else +# define EXTERN_SEMANTICS(TYPE) static TYPE UNUSED REGPARM_SEMANTICS +#endif + +#if (SEMANTICS_INLINE & INLINE_LOCALS) +# define STATIC_INLINE_SEMANTICS(TYPE) static INLINE TYPE +#else +# define STATIC_INLINE_SEMANTICS(TYPE) static TYPE REGPARM_SEMANTICS +#endif + +#define STATIC_SEMANTICS(TYPE) static TYPE + + + +/* support */ + +#if !defined (SUPPORT_INLINE) && (DEFAULT_INLINE) +# define SUPPORT_INLINE ALL_C_INLINE +#endif + +#if (SUPPORT_INLINE & REGPARM_MODULE) +# define REGPARM_SUPPORT REGPARM +#else +# define REGPARM_SUPPORT +#endif + +#if ((H_REVEALS_MODULE_P (SUPPORT_INLINE) || defined (SIM_INLINE_C)) \ + && !defined (SUPPORT_C) \ + && (REVEAL_MODULE_P (SUPPORT_INLINE))) +# if (SUPPORT_INLINE & INLINE_GLOBALS) +# define INLINE_SUPPORT(TYPE) static INLINE TYPE UNUSED +# define EXTERN_SUPPORT_P 0 +#else +# define INLINE_SUPPORT(TYPE) static TYPE UNUSED REGPARM_SUPPORT +# define EXTERN_SUPPORT_P 0 +#endif +#else +# define INLINE_SUPPORT(TYPE) TYPE REGPARM_SUPPORT +# define EXTERN_SUPPORT_P 1 +#endif + +#if (SUPPORT_INLINE & INLINE_LOCALS) +# define STATIC_INLINE_SUPPORT(TYPE) static INLINE TYPE +#else +# define STATIC_INLINE_SUPPORT(TYPE) static TYPE REGPARM_SUPPORT +#endif + +#define STATIC_SUPPORT(TYPE) static TYPE + + + +#endif diff --git a/sim/common/sim-io.c b/sim/common/sim-io.c new file mode 100644 index 00000000000..f3d2f674a64 --- /dev/null +++ b/sim/common/sim-io.c @@ -0,0 +1,379 @@ +/* This file is part of the program psim. + + Copyright (C) 1994-1997, Andrew Cagney + Copyright (C) 1998, Cygnus Solutions. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + + +#include "sim-main.h" +#include "sim-io.h" +#include "targ-vals.h" + +#include +#if HAVE_FCNTL_H +#include +#endif + +#if HAVE_UNISTD_H +#include +#endif + + +/* See the file include/callbacks.h for a description */ + + +int +sim_io_init(SIM_DESC sd) +{ + return STATE_CALLBACK (sd)->init (STATE_CALLBACK (sd)); +} + + +int +sim_io_shutdown(SIM_DESC sd) +{ + return STATE_CALLBACK (sd)->shutdown (STATE_CALLBACK (sd)); +} + + +int +sim_io_unlink(SIM_DESC sd, + const char *f1) +{ + return STATE_CALLBACK (sd)->unlink (STATE_CALLBACK (sd), f1); +} + + +long +sim_io_time(SIM_DESC sd, + long *t) +{ + return STATE_CALLBACK (sd)->time (STATE_CALLBACK (sd), t); +} + + +int +sim_io_system(SIM_DESC sd, const char *s) +{ + return STATE_CALLBACK (sd)->system (STATE_CALLBACK (sd), s); +} + + +int +sim_io_rename(SIM_DESC sd, + const char *f1, + const char *f2) +{ + return STATE_CALLBACK (sd)->rename (STATE_CALLBACK (sd), f1, f2); +} + + +int +sim_io_write_stdout(SIM_DESC sd, + const char *buf, + int len) +{ + switch (CURRENT_STDIO) { + case DO_USE_STDIO: + return STATE_CALLBACK (sd)->write_stdout (STATE_CALLBACK (sd), buf, len); + break; + case DONT_USE_STDIO: + return STATE_CALLBACK (sd)->write (STATE_CALLBACK (sd), 1, buf, len); + break; + default: + sim_io_error (sd, "sim_io_write_stdout: unaccounted switch\n"); + break; + } + return 0; +} + + +void +sim_io_flush_stdout(SIM_DESC sd) +{ + switch (CURRENT_STDIO) { + case DO_USE_STDIO: + STATE_CALLBACK (sd)->flush_stdout (STATE_CALLBACK (sd)); + break; + case DONT_USE_STDIO: + break; + default: + sim_io_error (sd, "sim_io_flush_stdout: unaccounted switch\n"); + break; + } +} + + +int +sim_io_write_stderr(SIM_DESC sd, + const char *buf, + int len) +{ + switch (CURRENT_STDIO) { + case DO_USE_STDIO: + return STATE_CALLBACK (sd)->write_stderr (STATE_CALLBACK (sd), buf, len); + break; + case DONT_USE_STDIO: + return STATE_CALLBACK (sd)->write (STATE_CALLBACK (sd), 2, buf, len); + break; + default: + sim_io_error (sd, "sim_io_write_stderr: unaccounted switch\n"); + break; + } + return 0; +} + + +void +sim_io_flush_stderr(SIM_DESC sd) +{ + switch (CURRENT_STDIO) { + case DO_USE_STDIO: + STATE_CALLBACK (sd)->flush_stderr (STATE_CALLBACK (sd)); + break; + case DONT_USE_STDIO: + break; + default: + sim_io_error (sd, "sim_io_flush_stderr: unaccounted switch\n"); + break; + } +} + + +int +sim_io_write(SIM_DESC sd, + int fd, + const char *buf, + int len) +{ + return STATE_CALLBACK (sd)->write (STATE_CALLBACK (sd), fd, buf, len); +} + + +int +sim_io_read_stdin(SIM_DESC sd, + char *buf, + int len) +{ + switch (CURRENT_STDIO) { + case DO_USE_STDIO: + return STATE_CALLBACK (sd)->read_stdin (STATE_CALLBACK (sd), buf, len); + break; + case DONT_USE_STDIO: + return STATE_CALLBACK (sd)->read (STATE_CALLBACK (sd), 0, buf, len); + break; + default: + sim_io_error (sd, "sim_io_read_stdin: unaccounted switch\n"); + break; + } + return 0; +} + + +int +sim_io_read(SIM_DESC sd, int fd, + char *buf, + int len) +{ + return STATE_CALLBACK (sd)->read (STATE_CALLBACK (sd), fd, buf, len); +} + + +int +sim_io_open(SIM_DESC sd, + const char *name, + int flags) +{ + return STATE_CALLBACK (sd)->open (STATE_CALLBACK (sd), name, flags); +} + + +int +sim_io_lseek(SIM_DESC sd, + int fd, + long off, + int way) +{ + return STATE_CALLBACK (sd)->lseek (STATE_CALLBACK (sd), fd, off, way); +} + + +int +sim_io_isatty(SIM_DESC sd, + int fd) +{ + return STATE_CALLBACK (sd)->isatty (STATE_CALLBACK (sd), fd); +} + + +int +sim_io_get_errno(SIM_DESC sd) +{ + return STATE_CALLBACK (sd)->get_errno (STATE_CALLBACK (sd)); +} + + +int +sim_io_close(SIM_DESC sd, + int fd) +{ + return STATE_CALLBACK (sd)->close (STATE_CALLBACK (sd), fd); +} + + +void +sim_io_printf(SIM_DESC sd, + const char *fmt, + ...) +{ + va_list ap; + va_start(ap, fmt); + STATE_CALLBACK (sd)->vprintf_filtered (STATE_CALLBACK (sd), fmt, ap); + va_end(ap); +} + + +void +sim_io_vprintf(SIM_DESC sd, + const char *fmt, + va_list ap) +{ + STATE_CALLBACK (sd)->vprintf_filtered (STATE_CALLBACK (sd), fmt, ap); +} + + +void +sim_io_eprintf(SIM_DESC sd, + const char *fmt, + ...) +{ + va_list ap; + va_start(ap, fmt); + STATE_CALLBACK (sd)->evprintf_filtered (STATE_CALLBACK (sd), fmt, ap); + va_end(ap); +} + + +void +sim_io_evprintf(SIM_DESC sd, + const char *fmt, + va_list ap) +{ + STATE_CALLBACK (sd)->evprintf_filtered (STATE_CALLBACK (sd), fmt, ap); +} + + +void +sim_io_error(SIM_DESC sd, + const char *fmt, + ...) +{ + if (sd == NULL || STATE_CALLBACK (sd) == NULL) { + va_list ap; + va_start(ap, fmt); + vfprintf (stderr, fmt, ap); + va_end(ap); + fprintf (stderr, "\n"); + abort (); + } + else { + va_list ap; + va_start(ap, fmt); + STATE_CALLBACK (sd)->evprintf_filtered (STATE_CALLBACK (sd), fmt, ap); + va_end(ap); + STATE_CALLBACK (sd)->error (STATE_CALLBACK (sd), ""); + } +} + + +void +sim_io_poll_quit(SIM_DESC sd) +{ + if (STATE_CALLBACK (sd)->poll_quit != NULL) + if (STATE_CALLBACK (sd)->poll_quit (STATE_CALLBACK (sd))) + sim_stop (sd); +} + + +/* Based on gdb-4.17/sim/ppc/main.c:sim_io_read_stdin(). + + FIXME: Should not be calling fcntl() or grubbing around inside of + ->fdmap and ->errno. + + FIXME: Some completly new mechanism for handling the general + problem of asynchronous IO is needed. + + FIXME: This function does not supress the echoing (ECHO) of input. + Consequently polled input is always displayed. + + FIXME: This function does not perform uncooked reads. + Consequently, data will not be read until an EOLN character has + been entered. A cntrl-d may force the early termination of a line */ + + +int +sim_io_poll_read (SIM_DESC sd, + int sim_io_fd, + char *buf, + int sizeof_buf) +{ +#if defined(O_NDELAY) && defined(F_GETFL) && defined(F_SETFL) + int fd = STATE_CALLBACK (sd)->fdmap[sim_io_fd]; + int flags; + int status; + int nr_read; + int result; + STATE_CALLBACK (sd)->last_errno = 0; + /* get the old status */ + flags = fcntl (fd, F_GETFL, 0); + if (flags == -1) + { + perror ("sim_io_poll_read"); + return 0; + } + /* temp, disable blocking IO */ + status = fcntl (fd, F_SETFL, flags | O_NDELAY); + if (status == -1) + { + perror ("sim_io_read_stdin"); + return 0; + } + /* try for input */ + nr_read = read (fd, buf, sizeof_buf); + if (nr_read >= 0) + { + /* printf ("\n", nr_read); */ + result = nr_read; + } + else + { /* nr_read < 0 */ + result = -1; + STATE_CALLBACK (sd)->last_errno = errno; + } + /* return to regular vewing */ + status = fcntl (fd, F_SETFL, flags); + if (status == -1) + { + perror ("sim_io_read_stdin"); + /* return 0; */ + } + return result; +#else + return sim_io_read (sd, sim_io_fd, buf, sizeof_buf); +#endif +} diff --git a/sim/common/sim-io.h b/sim/common/sim-io.h new file mode 100644 index 00000000000..995b6231e05 --- /dev/null +++ b/sim/common/sim-io.h @@ -0,0 +1,84 @@ +/* This file is part of the program psim. + + Copyright (C) 1994-1997, Andrew Cagney + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + + +#ifndef SIM_IO_H +#define SIM_IO_H + +/* See the file include/callbacks.h for a description */ + +int sim_io_init (SIM_DESC sd); + +int sim_io_shutdown (SIM_DESC sd); + +int sim_io_unlink (SIM_DESC sd, const char *); + +long sim_io_time (SIM_DESC sd, long *); + +int sim_io_system (SIM_DESC sd, const char *); + +int sim_io_rename (SIM_DESC sd, const char *, const char *); + +int sim_io_write_stdout (SIM_DESC sd, const char *, int); + +void sim_io_flush_stdout (SIM_DESC sd); + +int sim_io_write_stderr (SIM_DESC sd, const char *, int); + +void sim_io_flush_stderr (SIM_DESC sd); + +int sim_io_write (SIM_DESC sd, int, const char *, int); + +int sim_io_read_stdin (SIM_DESC sd, char *, int); + +int sim_io_read (SIM_DESC sd, int, char *, int); + +int sim_io_open (SIM_DESC sd, const char *, int); + +int sim_io_lseek (SIM_DESC sd, int, long, int); + +int sim_io_isatty (SIM_DESC sd, int); + +int sim_io_get_errno (SIM_DESC sd); + +int sim_io_close (SIM_DESC sd, int); + +void sim_io_printf (SIM_DESC sd, + const char *fmt, + ...) __attribute__ ((format (printf, 2, 3))); + +void sim_io_vprintf (SIM_DESC sd, const char *fmt, va_list ap); + +void sim_io_eprintf (SIM_DESC sd, + const char *fmt, + ...) __attribute__ ((format (printf, 2, 3))); + +void sim_io_evprintf (SIM_DESC sd, const char *fmt, va_list ap); + +void sim_io_error (SIM_DESC sd, + const char *fmt, + ...) __attribute__ ((format (printf, 2, 3))); + +void sim_io_poll_quit (SIM_DESC sd); + +/* Returns -1 and sets (host) EAGAIN if not ready. */ +int sim_io_poll_read (SIM_DESC sd, int, char *, int); + +#endif diff --git a/sim/common/sim-load.c b/sim/common/sim-load.c new file mode 100644 index 00000000000..22fb33b777b --- /dev/null +++ b/sim/common/sim-load.c @@ -0,0 +1,239 @@ +/* Utility to load a file into the simulator. + Copyright (C) 1997 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* This is a standalone loader, independent of the sim-basic.h machinery, + as it is used by simulators that don't use it [though that doesn't mean + to suggest that they shouldn't :-)]. */ + +#include "config.h" +#include "ansidecl.h" +#include /* for NULL */ +#ifdef ANSI_PROTOTYPES +#include +#else +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#include + +#include "sim-basics.h" +#include "bfd.h" +#include "sim-utils.h" + +#include "callback.h" +#include "remote-sim.h" + +static void eprintf PARAMS ((host_callback *, const char *, ...)); +static void xprintf PARAMS ((host_callback *, const char *, ...)); +static void report_transfer_performance + PARAMS ((host_callback *, unsigned long, time_t, time_t)); +static void xprintf_bfd_vma PARAMS ((host_callback *, bfd_vma)); + +/* Load program PROG into the simulator using the function DO_LOAD. + If PROG_BFD is non-NULL, the file has already been opened. + If VERBOSE_P is non-zero statistics are printed of each loaded section + and the transfer rate (for consistency with gdb). + If LMA_P is non-zero the program sections are loaded at the LMA + rather than the VMA + If this fails an error message is printed and NULL is returned. + If it succeeds the bfd is returned. + NOTE: For historical reasons, older hardware simulators incorrectly + write the program sections at LMA interpreted as a virtual address. + This is still accommodated for backward compatibility reasons. */ + + +bfd * +sim_load_file (sd, myname, callback, prog, prog_bfd, verbose_p, lma_p, do_write) + SIM_DESC sd; + const char *myname; + host_callback *callback; + char *prog; + bfd *prog_bfd; + int verbose_p; + int lma_p; + sim_write_fn do_write; +{ + asection *s; + /* Record separately as we don't want to close PROG_BFD if it was passed. */ + bfd *result_bfd; + time_t start_time = 0; /* Start and end times of download */ + time_t end_time = 0; + unsigned long data_count = 0; /* Number of bytes transferred to memory */ + int found_loadable_section; + + if (prog_bfd != NULL) + result_bfd = prog_bfd; + else + { + result_bfd = bfd_openr (prog, 0); + if (result_bfd == NULL) + { + eprintf (callback, "%s: can't open \"%s\": %s\n", + myname, prog, bfd_errmsg (bfd_get_error ())); + return NULL; + } + } + + if (!bfd_check_format (result_bfd, bfd_object)) + { + eprintf (callback, "%s: \"%s\" is not an object file: %s\n", + myname, prog, bfd_errmsg (bfd_get_error ())); + /* Only close if we opened it. */ + if (prog_bfd == NULL) + bfd_close (result_bfd); + return NULL; + } + + if (verbose_p) + start_time = time (NULL); + + found_loadable_section = 0; + for (s = result_bfd->sections; s; s = s->next) + { + if (s->flags & SEC_LOAD) + { + bfd_size_type size; + + size = bfd_get_section_size_before_reloc (s); + if (size > 0) + { + char *buffer; + bfd_vma lma; + + buffer = malloc (size); + if (buffer == NULL) + { + eprintf (callback, + "%s: insufficient memory to load \"%s\"\n", + myname, prog); + /* Only close if we opened it. */ + if (prog_bfd == NULL) + bfd_close (result_bfd); + return NULL; + } + if (lma_p) + lma = bfd_section_lma (result_bfd, s); + else + lma = bfd_section_vma (result_bfd, s); + if (verbose_p) + { + xprintf (callback, "Loading section %s, size 0x%lx %s ", + bfd_get_section_name (result_bfd, s), + (unsigned long) size, + (lma_p ? "lma" : "vma")); + xprintf_bfd_vma (callback, lma); + xprintf (callback, "\n"); + } + data_count += size; + bfd_get_section_contents (result_bfd, s, buffer, 0, size); + do_write (sd, lma, buffer, size); + found_loadable_section = 1; + free (buffer); + } + } + } + + if (!found_loadable_section) + { + eprintf (callback, + "%s: no loadable sections \"%s\"\n", + myname, prog); + return NULL; + } + + if (verbose_p) + { + end_time = time (NULL); + xprintf (callback, "Start address "); + xprintf_bfd_vma (callback, bfd_get_start_address (result_bfd)); + xprintf (callback, "\n"); + report_transfer_performance (callback, data_count, start_time, end_time); + } + + return result_bfd; +} + +static void +xprintf VPARAMS ((host_callback *callback, const char *fmt, ...)) +{ +#ifndef ANSI_PROTOTYPES + host_callback *callback; + char *fmt; +#endif + va_list ap; + + VA_START (ap, fmt); +#ifndef ANSI_PROTOTYPES + callback = va_arg (ap, host_callback *); + fmt = va_arg (ap, char *); +#endif + + (*callback->vprintf_filtered) (callback, fmt, ap); + + va_end (ap); +} + +static void +eprintf VPARAMS ((host_callback *callback, const char *fmt, ...)) +{ +#ifndef ANSI_PROTOTYPES + host_callback *callback; + char *fmt; +#endif + va_list ap; + + VA_START (ap, fmt); +#ifndef ANSI_PROTOTYPES + callback = va_arg (ap, host_callback *); + fmt = va_arg (ap, char *); +#endif + + (*callback->evprintf_filtered) (callback, fmt, ap); + + va_end (ap); +} + +/* Report how fast the transfer went. */ + +static void +report_transfer_performance (callback, data_count, start_time, end_time) + host_callback *callback; + unsigned long data_count; + time_t start_time, end_time; +{ + xprintf (callback, "Transfer rate: "); + if (end_time != start_time) + xprintf (callback, "%ld bits/sec", + (data_count * 8) / (end_time - start_time)); + else + xprintf (callback, "%ld bits in <1 sec", (data_count * 8)); + xprintf (callback, ".\n"); +} + +/* Print a bfd_vma. + This is intended to handle the vagaries of 32 vs 64 bits, etc. */ + +static void +xprintf_bfd_vma (callback, vma) + host_callback *callback; + bfd_vma vma; +{ + /* FIXME: for now */ + xprintf (callback, "0x%lx", (unsigned long) vma); +} diff --git a/sim/common/sim-memopt.c b/sim/common/sim-memopt.c new file mode 100644 index 00000000000..be52a6648f2 --- /dev/null +++ b/sim/common/sim-memopt.c @@ -0,0 +1,471 @@ +/* Simulator memory option handling. + Copyright (C) 1996-1999 Free Software Foundation, Inc. + Contributed by Cygnus Support. + +This file is part of GDB, the GNU debugger. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "sim-main.h" +#include "sim-assert.h" +#include "sim-options.h" + +#ifdef HAVE_STRING_H +#include +#else +#ifdef HAVE_STRINGS_H +#include +#endif +#endif +#ifdef HAVE_STDLIB_H +#include +#endif + +/* Memory fill byte */ +static unsigned8 fill_byte_value; +static int fill_byte_flag = 0; + +/* Memory command line options. */ + +enum { + OPTION_MEMORY_DELETE = OPTION_START, + OPTION_MEMORY_REGION, + OPTION_MEMORY_SIZE, + OPTION_MEMORY_INFO, + OPTION_MEMORY_ALIAS, + OPTION_MEMORY_CLEAR, + OPTION_MEMORY_FILL +}; + +static DECLARE_OPTION_HANDLER (memory_option_handler); + +static const OPTION memory_options[] = +{ + { {"memory-delete", required_argument, NULL, OPTION_MEMORY_DELETE }, + '\0', "ADDRESS|all", "Delete memory at ADDRESS (all addresses)", + memory_option_handler }, + { {"delete-memory", required_argument, NULL, OPTION_MEMORY_DELETE }, + '\0', "ADDRESS", NULL, + memory_option_handler }, + + { {"memory-region", required_argument, NULL, OPTION_MEMORY_REGION }, + '\0', "ADDRESS,SIZE[,MODULO]", "Add a memory region", + memory_option_handler }, + + { {"memory-alias", required_argument, NULL, OPTION_MEMORY_ALIAS }, + '\0', "ADDRESS,SIZE{,ADDRESS}", "Add memory shadow", + memory_option_handler }, + + { {"memory-size", required_argument, NULL, OPTION_MEMORY_SIZE }, + '\0', "SIZE", "Add memory at address zero", + memory_option_handler }, + + { {"memory-fill", required_argument, NULL, OPTION_MEMORY_FILL }, + '\0', "VALUE", "Fill subsequently added memory regions", + memory_option_handler }, + + { {"memory-clear", no_argument, NULL, OPTION_MEMORY_CLEAR }, + '\0', NULL, "Clear subsequently added memory regions", + memory_option_handler }, + + { {"memory-info", no_argument, NULL, OPTION_MEMORY_INFO }, + '\0', NULL, "List configurable memory regions", + memory_option_handler }, + { {"info-memory", no_argument, NULL, OPTION_MEMORY_INFO }, + '\0', NULL, NULL, + memory_option_handler }, + + { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL } +}; + + +static sim_memopt * +do_memopt_add (SIM_DESC sd, + int level, + int space, + address_word addr, + address_word nr_bytes, + unsigned modulo, + sim_memopt **entry, + void *buffer) +{ + void *fill_buffer; + unsigned fill_length; + void *free_buffer; + + if (buffer != NULL) + { + /* Buffer already given. sim_memory_uninstall will free it. */ + sim_core_attach (sd, NULL, + level, access_read_write_exec, space, + addr, nr_bytes, modulo, NULL, buffer); + + free_buffer = buffer; + fill_buffer = buffer; + fill_length = (modulo == 0) ? nr_bytes : modulo; + } + else + { + /* Allocate new well-aligned buffer, just as sim_core_attach(). */ + void *aligned_buffer; + int padding = (addr % sizeof (unsigned64)); + unsigned long bytes = (modulo == 0 ? nr_bytes : modulo) + padding; + + /* If filling with non-zero value, do not use clearing allocator. */ + + if (fill_byte_flag && fill_byte_value != 0) + free_buffer = xmalloc (bytes); /* don't clear */ + else + free_buffer = zalloc (bytes); /* clear */ + + aligned_buffer = (char*) free_buffer + padding; + + sim_core_attach (sd, NULL, + level, access_read_write_exec, space, + addr, nr_bytes, modulo, NULL, aligned_buffer); + + fill_buffer = aligned_buffer; + fill_length = (modulo == 0) ? nr_bytes : modulo; + + /* If we just used a clearing allocator, and are about to fill with + zero, truncate the redundant fill operation. */ + + if (fill_byte_flag && fill_byte_value == 0) + fill_length = 1; /* avoid boundary length=0 case */ + } + + if (fill_byte_flag) + { + ASSERT (fill_buffer != 0); + memset ((char*) fill_buffer, fill_byte_value, fill_length); + } + + while ((*entry) != NULL) + entry = &(*entry)->next; + (*entry) = ZALLOC (sim_memopt); + (*entry)->level = level; + (*entry)->space = space; + (*entry)->addr = addr; + (*entry)->nr_bytes = nr_bytes; + (*entry)->modulo = modulo; + (*entry)->buffer = free_buffer; + + return (*entry); +} + +static SIM_RC +do_memopt_delete (SIM_DESC sd, + int level, + int space, + address_word addr) +{ + sim_memopt **entry = &STATE_MEMOPT (sd); + sim_memopt *alias; + while ((*entry) != NULL + && ((*entry)->level != level + || (*entry)->space != space + || (*entry)->addr != addr)) + entry = &(*entry)->next; + if ((*entry) == NULL) + { + sim_io_eprintf (sd, "Memory at 0x%lx not found, not deleted\n", + (long) addr); + return SIM_RC_FAIL; + } + /* delete any buffer */ + if ((*entry)->buffer != NULL) + zfree ((*entry)->buffer); + /* delete it and its aliases */ + alias = *entry; + *entry = (*entry)->next; + while (alias != NULL) + { + sim_memopt *dead = alias; + alias = alias->alias; + sim_core_detach (sd, NULL, dead->level, dead->space, dead->addr); + zfree (dead); + } + return SIM_RC_OK; +} + + +static char * +parse_size (char *chp, + address_word *nr_bytes, + unsigned *modulo) +{ + /* [ "%" ] */ + *nr_bytes = strtoul (chp, &chp, 0); + if (*chp == '%') + { + *modulo = strtoul (chp + 1, &chp, 0); + } + return chp; +} + +static char * +parse_ulong_value (char *chp, + unsigned long *value) +{ + *value = strtoul (chp, &chp, 0); + return chp; +} + +static char * +parse_addr (char *chp, + int *level, + int *space, + address_word *addr) +{ + /* [ ": " ] [ "@" ] */ + *addr = (unsigned long) strtoul (chp, &chp, 0); + if (*chp == ':') + { + *space = *addr; + *addr = (unsigned long) strtoul (chp + 1, &chp, 0); + } + if (*chp == '@') + { + *level = strtoul (chp + 1, &chp, 0); + } + return chp; +} + + +static SIM_RC +memory_option_handler (SIM_DESC sd, sim_cpu *cpu, int opt, + char *arg, int is_command) +{ + switch (opt) + { + + case OPTION_MEMORY_DELETE: + if (strcasecmp (arg, "all") == 0) + { + while (STATE_MEMOPT (sd) != NULL) + do_memopt_delete (sd, + STATE_MEMOPT (sd)->level, + STATE_MEMOPT (sd)->space, + STATE_MEMOPT (sd)->addr); + return SIM_RC_OK; + } + else + { + int level = 0; + int space = 0; + address_word addr = 0; + parse_addr (arg, &level, &space, &addr); + return do_memopt_delete (sd, level, space, addr); + } + + case OPTION_MEMORY_REGION: + { + char *chp = arg; + int level = 0; + int space = 0; + address_word addr = 0; + address_word nr_bytes = 0; + unsigned modulo = 0; + /* parse the arguments */ + chp = parse_addr (chp, &level, &space, &addr); + if (*chp != ',') + { + sim_io_eprintf (sd, "Missing size for memory-region\n"); + return SIM_RC_FAIL; + } + chp = parse_size (chp + 1, &nr_bytes, &modulo); + /* old style */ + if (*chp == ',') + modulo = strtoul (chp + 1, &chp, 0); + /* try to attach/insert it */ + do_memopt_add (sd, level, space, addr, nr_bytes, modulo, + &STATE_MEMOPT (sd), NULL); + return SIM_RC_OK; + } + + case OPTION_MEMORY_ALIAS: + { + char *chp = arg; + int level = 0; + int space = 0; + address_word addr = 0; + address_word nr_bytes = 0; + unsigned modulo = 0; + sim_memopt *entry; + /* parse the arguments */ + chp = parse_addr (chp, &level, &space, &addr); + if (*chp != ',') + { + sim_io_eprintf (sd, "Missing size for memory-region\n"); + return SIM_RC_FAIL; + } + chp = parse_size (chp + 1, &nr_bytes, &modulo); + /* try to attach/insert the main record */ + entry = do_memopt_add (sd, level, space, addr, nr_bytes, modulo, + &STATE_MEMOPT (sd), + NULL); + /* now attach all the aliases */ + while (*chp == ',') + { + int a_level = level; + int a_space = space; + address_word a_addr = addr; + chp = parse_addr (chp + 1, &a_level, &a_space, &a_addr); + do_memopt_add (sd, a_level, a_space, a_addr, nr_bytes, modulo, + &entry->alias, entry->buffer); + } + return SIM_RC_OK; + } + + case OPTION_MEMORY_SIZE: + { + int level = 0; + int space = 0; + address_word addr = 0; + address_word nr_bytes = 0; + unsigned modulo = 0; + /* parse the arguments */ + parse_size (arg, &nr_bytes, &modulo); + /* try to attach/insert it */ + do_memopt_add (sd, level, space, addr, nr_bytes, modulo, + &STATE_MEMOPT (sd), NULL); + return SIM_RC_OK; + } + + case OPTION_MEMORY_CLEAR: + { + fill_byte_value = (unsigned8) 0; + fill_byte_flag = 1; + return SIM_RC_OK; + break; + } + + case OPTION_MEMORY_FILL: + { + unsigned long fill_value; + parse_ulong_value (arg, &fill_value); + if (fill_value > 255) + { + sim_io_eprintf (sd, "Missing fill value between 0 and 255\n"); + return SIM_RC_FAIL; + } + fill_byte_value = (unsigned8) fill_value; + fill_byte_flag = 1; + return SIM_RC_OK; + break; + } + + case OPTION_MEMORY_INFO: + { + sim_memopt *entry; + sim_io_printf (sd, "Memory maps:\n"); + for (entry = STATE_MEMOPT (sd); entry != NULL; entry = entry->next) + { + sim_memopt *alias; + sim_io_printf (sd, " memory"); + if (entry->alias == NULL) + sim_io_printf (sd, " region "); + else + sim_io_printf (sd, " alias "); + if (entry->space != 0) + sim_io_printf (sd, "0x%lx:", (long) entry->space); + sim_io_printf (sd, "0x%08lx", (long) entry->addr); + if (entry->level != 0) + sim_io_printf (sd, "@0x%lx", (long) entry->level); + sim_io_printf (sd, ",0x%lx", + (long) entry->nr_bytes); + if (entry->modulo != 0) + sim_io_printf (sd, "%%0x%lx", (long) entry->modulo); + for (alias = entry->alias; + alias != NULL; + alias = alias->next) + { + if (alias->space != 0) + sim_io_printf (sd, "0x%lx:", (long) alias->space); + sim_io_printf (sd, ",0x%08lx", (long) alias->addr); + if (alias->level != 0) + sim_io_printf (sd, "@0x%lx", (long) alias->level); + } + sim_io_printf (sd, "\n"); + } + return SIM_RC_OK; + break; + } + + default: + sim_io_eprintf (sd, "Unknown memory option %d\n", opt); + return SIM_RC_FAIL; + + } + + return SIM_RC_FAIL; +} + + +/* "memory" module install handler. + + This is called via sim_module_install to install the "memory" subsystem + into the simulator. */ + +static MODULE_INIT_FN sim_memory_init; +static MODULE_UNINSTALL_FN sim_memory_uninstall; + +SIM_RC +sim_memopt_install (SIM_DESC sd) +{ + SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); + sim_add_option_table (sd, NULL, memory_options); + sim_module_add_uninstall_fn (sd, sim_memory_uninstall); + sim_module_add_init_fn (sd, sim_memory_init); + return SIM_RC_OK; +} + + +/* Uninstall the "memory" subsystem from the simulator. */ + +static void +sim_memory_uninstall (SIM_DESC sd) +{ + sim_memopt **entry = &STATE_MEMOPT (sd); + sim_memopt *alias; + + while ((*entry) != NULL) + { + /* delete any buffer */ + if ((*entry)->buffer != NULL) + zfree ((*entry)->buffer); + + /* delete it and its aliases */ + alias = *entry; + while (alias != NULL) + { + sim_memopt *dead = alias; + alias = alias->alias; + sim_core_detach (sd, NULL, dead->level, dead->space, dead->addr); + zfree (dead); + } + + /* next victim */ + *entry = (*entry)->next; + } +} + + +static SIM_RC +sim_memory_init (SIM_DESC sd) +{ + /* FIXME: anything needed? */ + return SIM_RC_OK; +} diff --git a/sim/common/sim-memopt.h b/sim/common/sim-memopt.h new file mode 100644 index 00000000000..287c576f1b7 --- /dev/null +++ b/sim/common/sim-memopt.h @@ -0,0 +1,46 @@ +/* Header file for simulator memory argument handling. + Copyright (C) 1997 Free Software Foundation, Inc. + Contributed by Cygnus Support. + +This file is part of GDB, the GNU debugger. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef SIM_MEMOPT_H +#define SIM_MEMOPT_H + +/* Provides a command line interface for manipulating the memory core */ + +typedef struct _sim_memopt sim_memopt; +struct _sim_memopt { + int level; + int space; + unsigned_word addr; + unsigned_word nr_bytes; + unsigned modulo; + void *buffer; + sim_memopt *alias; /* linked list */ + sim_memopt *next; +}; + + +/* Install the "memopt" module. */ + +SIM_RC sim_memopt_install (SIM_DESC sd); + + +/* Was there a memory command? */ + +#endif diff --git a/sim/common/sim-model.c b/sim/common/sim-model.c new file mode 100644 index 00000000000..a126fb16c66 --- /dev/null +++ b/sim/common/sim-model.c @@ -0,0 +1,208 @@ +/* Model support. + Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. + Contributed by Cygnus Support. + +This file is part of GDB, the GNU debugger. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "sim-main.h" +#include "libiberty.h" +#include "sim-options.h" +#include "sim-io.h" +#include "sim-assert.h" +#include "bfd.h" + +static void model_set (sim_cpu *, const MODEL *); + +static DECLARE_OPTION_HANDLER (model_option_handler); + +static MODULE_INIT_FN sim_model_init; + +#define OPTION_MODEL (OPTION_START + 0) + +static const OPTION model_options[] = { + { {"model", required_argument, NULL, OPTION_MODEL}, + '\0', "MODEL", "Specify model to simulate", + model_option_handler }, + { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL } +}; + +static SIM_RC +model_option_handler (SIM_DESC sd, sim_cpu *cpu, int opt, + char *arg, int is_command) +{ + switch (opt) + { + case OPTION_MODEL : + { + const MODEL *model = sim_model_lookup (arg); + if (! model) + { + sim_io_eprintf (sd, "unknown model `%s'", arg); + return SIM_RC_FAIL; + } + sim_model_set (sd, cpu, model); + break; + } + } + + return SIM_RC_OK; +} + +SIM_RC +sim_model_install (SIM_DESC sd) +{ + SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); + + sim_add_option_table (sd, NULL, model_options); + sim_module_add_init_fn (sd, sim_model_init); + + return SIM_RC_OK; +} + +/* Subroutine of sim_model_set to set the model for one cpu. */ + +static void +model_set (sim_cpu *cpu, const MODEL *model) +{ + CPU_MACH (cpu) = MODEL_MACH (model); + CPU_MODEL (cpu) = model; + (* MACH_INIT_CPU (MODEL_MACH (model))) (cpu); + (* MODEL_INIT (model)) (cpu); +} + +/* Set the current model of CPU to MODEL. + If CPU is NULL, all cpus are set to MODEL. */ + +void +sim_model_set (SIM_DESC sd, sim_cpu *cpu, const MODEL *model) +{ + if (! cpu) + { + int c; + + for (c = 0; c < MAX_NR_PROCESSORS; ++c) + if (STATE_CPU (sd, c)) + model_set (STATE_CPU (sd, c), model); + } + else + { + model_set (cpu, model); + } +} + +/* Look up model named NAME. + Result is pointer to MODEL entry or NULL if not found. */ + +const MODEL * +sim_model_lookup (const char *name) +{ + const MACH **machp; + const MODEL *model; + + for (machp = & sim_machs[0]; *machp != NULL; ++machp) + { + for (model = MACH_MODELS (*machp); MODEL_NAME (model) != NULL; ++model) + { + if (strcmp (MODEL_NAME (model), name) == 0) + return model; + } + } + return NULL; +} + +/* Look up machine named NAME. + Result is pointer to MACH entry or NULL if not found. */ + +const MACH * +sim_mach_lookup (const char *name) +{ + const MACH **machp; + + for (machp = & sim_machs[0]; *machp != NULL; ++machp) + { + if (strcmp (MACH_NAME (*machp), name) == 0) + return *machp; + } + return NULL; +} + +/* Look up a machine via its bfd name. + Result is pointer to MACH entry or NULL if not found. */ + +const MACH * +sim_mach_lookup_bfd_name (const char *name) +{ + const MACH **machp; + + for (machp = & sim_machs[0]; *machp != NULL; ++machp) + { + if (strcmp (MACH_BFD_NAME (*machp), name) == 0) + return *machp; + } + return NULL; +} + +/* Initialize model support. */ + +static SIM_RC +sim_model_init (SIM_DESC sd) +{ + SIM_CPU *cpu; + + /* If both cpu model and state architecture are set, ensure they're + compatible. If only one is set, set the other. If neither are set, + use the default model. STATE_ARCHITECTURE is the bfd_arch_info data + for the selected "mach" (bfd terminology). */ + + /* Only check cpu 0. STATE_ARCHITECTURE is for that one only. */ + /* ??? At present this only supports homogeneous multiprocessors. */ + cpu = STATE_CPU (sd, 0); + + if (! STATE_ARCHITECTURE (sd) + && ! CPU_MACH (cpu)) + { + /* Set the default model. */ + const MODEL *model = sim_model_lookup (WITH_DEFAULT_MODEL); + sim_model_set (sd, NULL, model); + } + + if (STATE_ARCHITECTURE (sd) + && CPU_MACH (cpu)) + { + if (strcmp (STATE_ARCHITECTURE (sd)->printable_name, + MACH_BFD_NAME (CPU_MACH (cpu))) != 0) + { + sim_io_eprintf (sd, "invalid model `%s' for `%s'\n", + MODEL_NAME (CPU_MODEL (cpu)), + STATE_ARCHITECTURE (sd)->printable_name); + return SIM_RC_FAIL; + } + } + else if (STATE_ARCHITECTURE (sd)) + { + /* Use the default model for the selected machine. + The default model is the first one in the list. */ + const MACH *mach = sim_mach_lookup_bfd_name (STATE_ARCHITECTURE (sd)->printable_name); + sim_model_set (sd, NULL, MACH_MODELS (mach)); + } + else + { + STATE_ARCHITECTURE (sd) = bfd_scan_arch (MACH_BFD_NAME (CPU_MACH (cpu))); + } + + return SIM_RC_OK; +} diff --git a/sim/common/sim-model.h b/sim/common/sim-model.h new file mode 100644 index 00000000000..6f7769af787 --- /dev/null +++ b/sim/common/sim-model.h @@ -0,0 +1,138 @@ +/* Architecture, machine, and model support. + Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc. + Contributed by Cygnus Support. + +This file is part of GDB, the GNU debugger. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* Nomenclature: + architecture = one of sparc, mips, sh, etc. + in the sparc architecture, mach = one of v6, v7, v8, sparclite, etc. + in the v8 mach, model = one of supersparc, etc. +*/ + +/* This file is intended to be included by sim-basics.h. */ + +#ifndef SIM_MODEL_H +#define SIM_MODEL_H + +/* Function unit and instruction timing support. + ??? This is obviously insufficiently general. + It's useful but it needs elaborating upon. */ + +typedef struct { + unsigned char name; /* actually a UNIT_TYPE enum */ + unsigned char issue; + unsigned char done; +} UNIT; + +#ifndef MAX_UNITS +#define MAX_UNITS 1 +#endif + +typedef int (MODEL_FN) (sim_cpu *, void *); + +typedef struct { + /* This is an integer that identifies this insn. + How this works is up to the target. */ + int num; + + /* Function to handle insn-specific profiling. */ + MODEL_FN *model_fn; + + /* Array of function units used by this insn. */ + UNIT units[MAX_UNITS]; +} INSN_TIMING; + +/* Struct to describe various implementation properties of a cpu. + When multiple cpu variants are supported, the sizes of some structs + can vary. */ + +typedef struct { + /* The size of the SIM_CPU struct. */ + int sim_cpu_size; +#define IMP_PROPS_SIM_CPU_SIZE(cpu_props) ((cpu_props)->sim_cpu_size) + /* An SCACHE element can vary in size, depending on the selected cpu. + This is zero if the SCACHE isn't in use for this variant. */ + int scache_elm_size; +#define IMP_PROPS_SCACHE_ELM_SIZE(cpu_props) ((cpu_props)->scache_elm_size) +} MACH_IMP_PROPERTIES; + +/* A machine variant. */ + +typedef struct { + const char *name; +#define MACH_NAME(m) ((m)->name) + /* This is the argument to bfd_scan_arch. */ + const char *bfd_name; +#define MACH_BFD_NAME(m) ((m)->bfd_name) + int word_bitsize; +#define MACH_WORD_BITSIZE(m) ((m)->word_bitsize) + int addr_bitsize; +#define MACH_ADDR_BITSIZE(m) ((m)->addr_bitsize) + + /* Pointer to null-entry terminated table of models of this mach. + The default is the first one. */ + const struct model *models; +#define MACH_MODELS(m) ((m)->models) + + /* Pointer to the implementation properties of this mach. */ + const MACH_IMP_PROPERTIES *imp_props; +#define MACH_IMP_PROPS(m) ((m)->imp_props) + + /* Called by sim_model_set when the model of a cpu is set. */ + void (* init_cpu) (sim_cpu *); +#define MACH_INIT_CPU(m) ((m)->init_cpu) + + /* Initialize the simulator engine for this cpu. + Used by cgen simulators to initialize the insn descriptor table. */ + void (* prepare_run) (sim_cpu *); +#define MACH_PREPARE_RUN(m) ((m)->prepare_run) +} MACH; + +/* A model (implementation) of a machine. */ + +typedef struct model { + const char *name; +#define MODEL_NAME(m) ((m)->name) + const MACH *mach; +#define MODEL_MACH(m) ((m)->mach) + /* An enum that distinguished the model. */ + int num; +#define MODEL_NUM(m) ((m)->num) + /* Pointer to timing table for this model. */ + const INSN_TIMING *timing; +#define MODEL_TIMING(m) ((m)->timing) + void (* init) (sim_cpu *); +#define MODEL_INIT(m) ((m)->init) +} MODEL; + +/* Tables of supported machines. */ +/* ??? In a simulator of multiple architectures, will need multiple copies of + this. Have an `archs' array that contains a pointer to the machs array + for each (which in turn has a pointer to the models array for each). */ +extern const MACH *sim_machs[]; + +/* Model module handlers. */ +extern MODULE_INSTALL_FN sim_model_install; + +/* Support routines. */ +extern void sim_model_set (SIM_DESC sd_, sim_cpu *cpu_, const MODEL *model_); +extern const MODEL * sim_model_lookup (const char *name_); +extern const MACH * sim_mach_lookup (const char *name_); +extern const MACH * sim_mach_lookup_bfd_name (const char *bfd_name_); + +#endif /* SIM_MODEL_H */ diff --git a/sim/common/sim-module.c b/sim/common/sim-module.c new file mode 100644 index 00000000000..35eb32a65ff --- /dev/null +++ b/sim/common/sim-module.c @@ -0,0 +1,399 @@ +/* Module support. + Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. + Contributed by Cygnus Support. + +This file is part of GDB, the GNU debugger. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "sim-main.h" +#include "sim-io.h" +#include "sim-options.h" +#include "sim-assert.h" + +#if WITH_HW +#include "sim-hw.h" +#endif + +#include "libiberty.h" + +/* List of all modules. */ +static MODULE_INSTALL_FN * const modules[] = { + standard_install, + sim_events_install, +#ifdef SIM_HAVE_MODEL + sim_model_install, +#endif +#if WITH_ENGINE + sim_engine_install, +#endif +#if WITH_TRACE + trace_install, +#endif +#if WITH_PROFILE + profile_install, +#endif + sim_core_install, +#ifndef SIM_HAVE_FLATMEM + /* FIXME: should handle flatmem as well FLATMEM */ + sim_memopt_install, +#endif +#if WITH_WATCHPOINTS + sim_watchpoint_install, +#endif +#if WITH_SCACHE + scache_install, +#endif +#ifdef SIM_HAVE_BREAKPOINTS + sim_break_install, +#endif +#if WITH_HW + sim_hw_install, +#endif + /* Configured in [simulator specific] additional modules. */ +#ifdef MODULE_LIST + MODULE_LIST +#endif + 0 +}; + +/* Functions called from sim_open. */ + +/* Initialize common parts before argument processing. */ + +SIM_RC +sim_pre_argv_init (SIM_DESC sd, const char *myname) +{ + SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); + SIM_ASSERT (STATE_MODULES (sd) == NULL); + + STATE_MY_NAME (sd) = myname + strlen (myname); + while (STATE_MY_NAME (sd) > myname && STATE_MY_NAME (sd)[-1] != '/') + --STATE_MY_NAME (sd); + + /* Set the cpu names to default values. */ + { + int i; + for (i = 0; i < MAX_NR_PROCESSORS; ++i) + { + char *name; + asprintf (&name, "cpu%d", i); + CPU_NAME (STATE_CPU (sd, i)) = name; + } + } + + sim_config_default (sd); + + /* Install all configured in modules. */ + if (sim_module_install (sd) != SIM_RC_OK) + return SIM_RC_FAIL; + + return SIM_RC_OK; +} + +/* Initialize common parts after argument processing. */ + +SIM_RC +sim_post_argv_init (SIM_DESC sd) +{ + int i; + SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); + SIM_ASSERT (STATE_MODULES (sd) != NULL); + + /* Set the cpu->state backlinks for each cpu. */ + for (i = 0; i < MAX_NR_PROCESSORS; ++i) + { + CPU_STATE (STATE_CPU (sd, i)) = sd; + CPU_INDEX (STATE_CPU (sd, i)) = i; + } + + if (sim_module_init (sd) != SIM_RC_OK) + return SIM_RC_FAIL; + + return SIM_RC_OK; +} + +/* Install all modules. + If this fails, no modules are left installed. */ + +SIM_RC +sim_module_install (SIM_DESC sd) +{ + MODULE_INSTALL_FN * const *modp; + + SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); + SIM_ASSERT (STATE_MODULES (sd) == NULL); + + STATE_MODULES (sd) = ZALLOC (struct module_list); + for (modp = modules; *modp != NULL; ++modp) + { + if ((*modp) (sd) != SIM_RC_OK) + { + sim_module_uninstall (sd); + SIM_ASSERT (STATE_MODULES (sd) == NULL); + return SIM_RC_FAIL; + } + } + return SIM_RC_OK; +} + +/* Called after all modules have been installed and after argv + has been processed. */ + +SIM_RC +sim_module_init (SIM_DESC sd) +{ + struct module_list *modules = STATE_MODULES (sd); + MODULE_INIT_LIST *modp; + + SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); + SIM_ASSERT (STATE_MODULES (sd) != NULL); + + for (modp = modules->init_list; modp != NULL; modp = modp->next) + { + if ((*modp->fn) (sd) != SIM_RC_OK) + return SIM_RC_FAIL; + } + return SIM_RC_OK; +} + +/* Called when ever the simulator is resumed */ + +SIM_RC +sim_module_resume (SIM_DESC sd) +{ + struct module_list *modules = STATE_MODULES (sd); + MODULE_RESUME_LIST *modp; + + SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); + SIM_ASSERT (STATE_MODULES (sd) != NULL); + + for (modp = modules->resume_list; modp != NULL; modp = modp->next) + { + if ((*modp->fn) (sd) != SIM_RC_OK) + return SIM_RC_FAIL; + } + return SIM_RC_OK; +} + +/* Called when ever the simulator is suspended */ + +SIM_RC +sim_module_suspend (SIM_DESC sd) +{ + struct module_list *modules = STATE_MODULES (sd); + MODULE_SUSPEND_LIST *modp; + + SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); + SIM_ASSERT (STATE_MODULES (sd) != NULL); + + for (modp = modules->suspend_list; modp != NULL; modp = modp->next) + { + if ((*modp->fn) (sd) != SIM_RC_OK) + return SIM_RC_FAIL; + } + return SIM_RC_OK; +} + +/* Uninstall installed modules, called by sim_close. */ + +void +sim_module_uninstall (SIM_DESC sd) +{ + struct module_list *modules = STATE_MODULES (sd); + MODULE_UNINSTALL_LIST *modp; + + SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); + SIM_ASSERT (STATE_MODULES (sd) != NULL); + + /* Uninstall the modules. */ + for (modp = modules->uninstall_list; modp != NULL; modp = modp->next) + (*modp->fn) (sd); + + /* clean-up init list */ + { + MODULE_INIT_LIST *n, *d; + for (d = modules->init_list; d != NULL; d = n) + { + n = d->next; + zfree (d); + } + } + + /* clean-up resume list */ + { + MODULE_RESUME_LIST *n, *d; + for (d = modules->resume_list; d != NULL; d = n) + { + n = d->next; + zfree (d); + } + } + + /* clean-up suspend list */ + { + MODULE_SUSPEND_LIST *n, *d; + for (d = modules->suspend_list; d != NULL; d = n) + { + n = d->next; + zfree (d); + } + } + + /* clean-up uninstall list */ + { + MODULE_UNINSTALL_LIST *n, *d; + for (d = modules->uninstall_list; d != NULL; d = n) + { + n = d->next; + zfree (d); + } + } + + /* clean-up info list */ + { + MODULE_INFO_LIST *n, *d; + for (d = modules->info_list; d != NULL; d = n) + { + n = d->next; + zfree (d); + } + } + + zfree (modules); + STATE_MODULES (sd) = NULL; +} + +/* Called when ever simulator info is needed */ + +void +sim_module_info (SIM_DESC sd, int verbose) +{ + struct module_list *modules = STATE_MODULES (sd); + MODULE_INFO_LIST *modp; + + SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); + SIM_ASSERT (STATE_MODULES (sd) != NULL); + + for (modp = modules->info_list; modp != NULL; modp = modp->next) + { + (*modp->fn) (sd, verbose); + } +} + +/* Add FN to the init handler list. + init in the same order as the install. */ + +void +sim_module_add_init_fn (SIM_DESC sd, MODULE_INIT_FN fn) +{ + struct module_list *modules = STATE_MODULES (sd); + MODULE_INIT_LIST *l = ZALLOC (MODULE_INIT_LIST); + MODULE_INIT_LIST **last; + + SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); + SIM_ASSERT (STATE_MODULES (sd) != NULL); + + last = &modules->init_list; + while (*last != NULL) + last = &((*last)->next); + + l->fn = fn; + l->next = NULL; + *last = l; +} + +/* Add FN to the resume handler list. + resume in the same order as the install. */ + +void +sim_module_add_resume_fn (SIM_DESC sd, MODULE_RESUME_FN fn) +{ + struct module_list *modules = STATE_MODULES (sd); + MODULE_RESUME_LIST *l = ZALLOC (MODULE_RESUME_LIST); + MODULE_RESUME_LIST **last; + + SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); + SIM_ASSERT (STATE_MODULES (sd) != NULL); + + last = &modules->resume_list; + while (*last != NULL) + last = &((*last)->next); + + l->fn = fn; + l->next = NULL; + *last = l; +} + +/* Add FN to the init handler list. + suspend in the reverse order to install. */ + +void +sim_module_add_suspend_fn (SIM_DESC sd, MODULE_SUSPEND_FN fn) +{ + struct module_list *modules = STATE_MODULES (sd); + MODULE_SUSPEND_LIST *l = ZALLOC (MODULE_SUSPEND_LIST); + MODULE_SUSPEND_LIST **last; + + SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); + SIM_ASSERT (STATE_MODULES (sd) != NULL); + + last = &modules->suspend_list; + while (*last != NULL) + last = &((*last)->next); + + l->fn = fn; + l->next = modules->suspend_list; + modules->suspend_list = l; +} + +/* Add FN to the uninstall handler list. + Uninstall in reverse order to install. */ + +void +sim_module_add_uninstall_fn (SIM_DESC sd, MODULE_UNINSTALL_FN fn) +{ + struct module_list *modules = STATE_MODULES (sd); + MODULE_UNINSTALL_LIST *l = ZALLOC (MODULE_UNINSTALL_LIST); + + SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); + SIM_ASSERT (STATE_MODULES (sd) != NULL); + + l->fn = fn; + l->next = modules->uninstall_list; + modules->uninstall_list = l; +} + +/* Add FN to the info handler list. + Report info in the same order as the install. */ + +void +sim_module_add_info_fn (SIM_DESC sd, MODULE_INFO_FN fn) +{ + struct module_list *modules = STATE_MODULES (sd); + MODULE_INFO_LIST *l = ZALLOC (MODULE_INFO_LIST); + MODULE_INFO_LIST **last; + + SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); + SIM_ASSERT (STATE_MODULES (sd) != NULL); + + last = &modules->info_list; + while (*last != NULL) + last = &((*last)->next); + + l->fn = fn; + l->next = NULL; + *last = l; +} diff --git a/sim/common/sim-module.h b/sim/common/sim-module.h new file mode 100644 index 00000000000..cbba3506e2c --- /dev/null +++ b/sim/common/sim-module.h @@ -0,0 +1,125 @@ +/* Module support. + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + Contributed by Cygnus Support. + +This file is part of GDB, the GNU debugger. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* This file is intended to be included by sim-base.h. */ + +#ifndef SIM_MODULES_H +#define SIM_MODULES_H + +/* Modules are addons to the simulator that perform a specific function + (e.g. tracing, profiling, memory subsystem, etc.). Some modules are + builtin, and others are added at configure time. The intent is to + provide a uniform framework for all of the pieces that make up the + simulator. + + TODO: Add facilities for saving/restoring state to/from a file. */ + + +/* Various function types. */ + +typedef SIM_RC (MODULE_INSTALL_FN) (SIM_DESC); +typedef SIM_RC (MODULE_INIT_FN) (SIM_DESC); +typedef SIM_RC (MODULE_RESUME_FN) (SIM_DESC); +typedef SIM_RC (MODULE_SUSPEND_FN) (SIM_DESC); +typedef void (MODULE_UNINSTALL_FN) (SIM_DESC); +typedef void (MODULE_INFO_FN) (SIM_DESC, int); + + +/* Lists of installed handlers. */ + +typedef struct module_init_list { + struct module_init_list *next; + MODULE_INIT_FN *fn; +} MODULE_INIT_LIST; + +typedef struct module_resume_list { + struct module_resume_list *next; + MODULE_RESUME_FN *fn; +} MODULE_RESUME_LIST; + +typedef struct module_suspend_list { + struct module_suspend_list *next; + MODULE_SUSPEND_FN *fn; +} MODULE_SUSPEND_LIST; + +typedef struct module_uninstall_list { + struct module_uninstall_list *next; + MODULE_UNINSTALL_FN *fn; +} MODULE_UNINSTALL_LIST; + +typedef struct module_info_list { + struct module_info_list *next; + MODULE_INFO_FN *fn; +} MODULE_INFO_LIST; + + +/* Functions to register module with various handler lists */ + +SIM_RC sim_module_install (SIM_DESC); +void sim_module_uninstall (SIM_DESC); +void sim_module_add_init_fn (SIM_DESC sd, MODULE_INIT_FN fn); +void sim_module_add_resume_fn (SIM_DESC sd, MODULE_RESUME_FN fn); +void sim_module_add_suspend_fn (SIM_DESC sd, MODULE_SUSPEND_FN fn); +void sim_module_add_uninstall_fn (SIM_DESC sd, MODULE_UNINSTALL_FN fn); +void sim_module_add_info_fn (SIM_DESC sd, MODULE_INFO_FN fn); + + +/* Initialize installed modules before argument processing. + Called by sim_open. */ +SIM_RC sim_pre_argv_init (SIM_DESC sd, const char *myname); + +/* Initialize installed modules after argument processing. + Called by sim_open. */ +SIM_RC sim_post_argv_init (SIM_DESC sd); + +/* Re-initialize the module. Called by sim_create_inferior. */ +SIM_RC sim_module_init (SIM_DESC sd); + +/* Suspend/resume modules. Called by sim_run or sim_resume */ +SIM_RC sim_module_suspend (SIM_DESC sd); +SIM_RC sim_module_resume (SIM_DESC sd); + +/* Report general information on module */ +void sim_module_info (SIM_DESC sd, int verbose); + + +/* Module private data */ + +struct module_list { + + /* List of installed module `init' handlers */ + MODULE_INIT_LIST *init_list; + + /* List of installed module `uninstall' handlers. */ + MODULE_UNINSTALL_LIST *uninstall_list; + + /* List of installed module `resume' handlers. */ + MODULE_RESUME_LIST *resume_list; + + /* List of installed module `suspend' handlers. */ + MODULE_SUSPEND_LIST *suspend_list; + + /* List of installed module `info' handlers. */ + MODULE_INFO_LIST *info_list; + +}; + + +#endif /* SIM_MODULES_H */ diff --git a/sim/common/sim-n-bits.h b/sim/common/sim-n-bits.h new file mode 100644 index 00000000000..83157fff05a --- /dev/null +++ b/sim/common/sim-n-bits.h @@ -0,0 +1,218 @@ +/* This file is part of the program psim. + + Copyright (C) 1994-1996, Andrew Cagney + Copyright (C) 1997, Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + + +#ifndef N +#error "N must be #defined" +#endif + +#include "symcat.h" + +#if defined(__STDC__) && defined(signed) +/* If signed were defined to be say __signed (ie, some versions of Linux), + then the signedN macro would not work correctly. If we have a standard + compiler, we have signed. */ +#undef signed +#endif + +/* NOTE: See end of file for #undef */ +#define unsignedN XCONCAT2(unsigned,N) +#define signedN XCONCAT2(signed,N) +#define LSMASKn XCONCAT2(LSMASK,N) +#define MSMASKn XCONCAT2(MSMASK,N) +#define LSMASKEDn XCONCAT2(LSMASKED,N) +#define MSMASKEDn XCONCAT2(MSMASKED,N) +#define LSEXTRACTEDn XCONCAT2(LSEXTRACTED,N) +#define MSEXTRACTEDn XCONCAT2(MSEXTRACTED,N) +#define LSINSERTEDn XCONCAT2(LSINSERTED,N) +#define MSINSERTEDn XCONCAT2(MSINSERTED,N) +#define ROTn XCONCAT2(ROT,N) +#define ROTLn XCONCAT2(ROTL,N) +#define ROTRn XCONCAT2(ROTR,N) +#define MSSEXTn XCONCAT2(MSSEXT,N) +#define LSSEXTn XCONCAT2(LSSEXT,N) + +/* TAGS: LSMASKED16 LSMASKED32 LSMASKED64 */ + +INLINE_SIM_BITS\ +(unsignedN) +LSMASKEDn (unsignedN word, + int start, + int stop) +{ + word &= LSMASKn (start, stop); + return word; +} + +/* TAGS: MSMASKED16 MSMASKED32 MSMASKED64 */ + +INLINE_SIM_BITS\ +(unsignedN) +MSMASKEDn (unsignedN word, + int start, + int stop) +{ + word &= MSMASKn (start, stop); + return word; +} + +/* TAGS: LSEXTRACTED16 LSEXTRACTED32 LSEXTRACTED64 */ + +INLINE_SIM_BITS\ +(unsignedN) +LSEXTRACTEDn (unsignedN val, + int start, + int stop) +{ + val <<= (N - 1 - start); /* drop high bits */ + val >>= (N - 1 - start) + (stop); /* drop low bits */ + return val; +} + +/* TAGS: MSEXTRACTED16 MSEXTRACTED32 MSEXTRACTED64 */ + +INLINE_SIM_BITS\ +(unsignedN) +MSEXTRACTEDn (unsignedN val, + int start, + int stop) +{ + val <<= (start); /* drop high bits */ + val >>= (start) + (N - 1 - stop); /* drop low bits */ + return val; +} + +/* TAGS: LSINSERTED16 LSINSERTED32 LSINSERTED64 */ + +INLINE_SIM_BITS\ +(unsignedN) +LSINSERTEDn (unsignedN val, + int start, + int stop) +{ + val <<= stop; + val &= LSMASKn (start, stop); + return val; +} + +/* TAGS: MSINSERTED16 MSINSERTED32 MSINSERTED64 */ + +INLINE_SIM_BITS\ +(unsignedN) +MSINSERTEDn (unsignedN val, + int start, + int stop) +{ + val <<= ((N - 1) - stop); + val &= MSMASKn (start, stop); + return val; +} + +/* TAGS: ROT16 ROT32 ROT64 */ + +INLINE_SIM_BITS\ +(unsignedN) +ROTn (unsignedN val, + int shift) +{ + if (shift > 0) + return ROTRn (val, shift); + else if (shift < 0) + return ROTLn (val, -shift); + else + return val; +} + +/* TAGS: ROTL16 ROTL32 ROTL64 */ + +INLINE_SIM_BITS\ +(unsignedN) +ROTLn (unsignedN val, + int shift) +{ + unsignedN result; + ASSERT (shift <= N); + result = (((val) << (shift)) | ((val) >> ((N)-(shift)))); + return result; +} + +/* TAGS: ROTR16 ROTR32 ROTR64 */ + +INLINE_SIM_BITS\ +(unsignedN) +ROTRn (unsignedN val, + int shift) +{ + unsignedN result; + ASSERT (shift <= N); + result = (((val) >> (shift)) | ((val) << ((N)-(shift)))); + return result; +} + +/* TAGS: LSSEXT16 LSSEXT32 LSSEXT64 */ + +INLINE_SIM_BITS\ +(unsignedN) +LSSEXTn (signedN val, + int sign_bit) +{ + int shift; + /* make the sign-bit most significant and then smear it back into + position */ + ASSERT (sign_bit < N); + shift = ((N - 1) - sign_bit); + val <<= shift; + val >>= shift; + return val; +} + +/* TAGS: MSSEXT16 MSSEXT32 MSSEXT64 */ + +INLINE_SIM_BITS\ +(unsignedN) +MSSEXTn (signedN val, + int sign_bit) +{ + /* make the sign-bit most significant and then smear it back into + position */ + ASSERT (sign_bit < N); + val <<= sign_bit; + val >>= sign_bit; + return val; +} + + +/* NOTE: See start of file for #define */ +#undef LSSEXTn +#undef MSSEXTn +#undef ROTLn +#undef ROTRn +#undef ROTn +#undef LSINSERTEDn +#undef MSINSERTEDn +#undef LSEXTRACTEDn +#undef MSEXTRACTEDn +#undef LSMASKEDn +#undef LSMASKn +#undef MSMASKEDn +#undef MSMASKn +#undef signedN +#undef unsignedN diff --git a/sim/common/sim-n-core.h b/sim/common/sim-n-core.h new file mode 100644 index 00000000000..46eca0355fd --- /dev/null +++ b/sim/common/sim-n-core.h @@ -0,0 +1,417 @@ +/* This file is part of the program psim. + + Copyright (C) 1994-1997, Andrew Cagney + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + + +#ifndef N +#error "N must be #defined" +#endif +#ifndef M +#define M N +#endif + +/* N: The number of bytes of data to transfer. + M: The number of bytes in the type used to transfer the data */ + +#if (N > M) +#error "N (nr bytes of data) must be <= M (nr of bytes in data type)" +#endif + + +#include "symcat.h" + +/* NOTE: see end of file for #undef of these macros */ + +#define unsigned_M XCONCAT2(unsigned_,M) + +#define T2H_M XCONCAT2(T2H_,M) +#define H2T_M XCONCAT2(H2T_,M) +#define SWAP_M XCONCAT2(SWAP_,M) + +#define sim_core_read_aligned_N XCONCAT2(sim_core_read_aligned_,N) +#define sim_core_read_unaligned_N XCONCAT2(sim_core_read_unaligned_,N) +#define sim_core_read_misaligned_N XCONCAT2(sim_core_read_misaligned_,N) +#define sim_core_write_aligned_N XCONCAT2(sim_core_write_aligned_,N) +#define sim_core_write_unaligned_N XCONCAT2(sim_core_write_unaligned_,N) +#define sim_core_write_misaligned_N XCONCAT2(sim_core_write_misaligned_,N) +#define sim_core_trace_M XCONCAT2(sim_core_trace_,M) +#define sim_core_dummy_M XCONCAT2(sim_core_dummy_,M) + + +#if (M == N && N > 1) +/* dummy variable used as a return value when nothing else is + available and the compiler is complaining */ +static unsigned_M sim_core_dummy_M; +#endif + + +/* TAGS: sim_core_trace_1 sim_core_trace_2 */ +/* TAGS: sim_core_trace_4 sim_core_trace_8 */ +/* TAGS: sim_core_trace_16 */ + +#if (M == N) +STATIC_SIM_CORE(void) +sim_core_trace_M (sim_cpu *cpu, + sim_cia cia, + int line_nr, + transfer_type type, + unsigned map, + address_word addr, + unsigned_M val, + int nr_bytes) +{ + const char *transfer = (type == read_transfer ? "read" : "write"); + const char *direction = (type == read_transfer ? "->" : "<-"); + + if (TRACE_DEBUG_P (cpu)) + trace_printf (CPU_STATE (cpu), cpu, "sim-n-core.h:%d: ", line_nr); + +#if (M == 16) + trace_printf (CPU_STATE (cpu), cpu, + "%s-%d %s:0x%08lx %s 0x%08lx%08lx%08lx%08lx\n", + transfer, nr_bytes, + map_to_str (map), + (unsigned long) addr, + direction, + (unsigned long) V4_16 (val, 0), + (unsigned long) V4_16 (val, 1), + (unsigned long) V4_16 (val, 2), + (unsigned long) V4_16 (val, 3)); +#endif +#if (M == 8) + trace_printf (CPU_STATE (cpu), cpu, + "%s-%d %s:0x%08lx %s 0x%08lx%08lx\n", + transfer, nr_bytes, + map_to_str (map), + (unsigned long) addr, + direction, + (unsigned long) V4_8 (val, 0), + (unsigned long) V4_8 (val, 1)); +#endif +#if (M == 4) + trace_printf (CPU_STATE (cpu), cpu, + "%s-%d %s:0x%08lx %s 0x%08lx\n", + transfer, + nr_bytes, + map_to_str (map), + (unsigned long) addr, + direction, + (unsigned long) val); +#endif +#if (M == 2) + trace_printf (CPU_STATE (cpu), cpu, + "%s-%d %s:0x%08lx %s 0x%04lx\n", + transfer, + nr_bytes, + map_to_str (map), + (unsigned long) addr, + direction, + (unsigned long) val); +#endif +#if (M == 1) + trace_printf (CPU_STATE (cpu), cpu, + "%s-%d %s:0x%08lx %s 0x%02lx\n", + transfer, + nr_bytes, + map_to_str (map), + (unsigned long) addr, + direction, + (unsigned long) val); +#endif +} +#endif + + +/* TAGS: sim_core_read_aligned_1 sim_core_read_aligned_2 */ +/* TAGS: sim_core_read_aligned_4 sim_core_read_aligned_8 */ +/* TAGS: sim_core_read_aligned_16 */ + +#if (M == N) +INLINE_SIM_CORE(unsigned_M) +sim_core_read_aligned_N(sim_cpu *cpu, + sim_cia cia, + unsigned map, + address_word xaddr) +{ + sim_cpu_core *cpu_core = CPU_CORE (cpu); + sim_core_common *core = &cpu_core->common; + unsigned_M val; + sim_core_mapping *mapping; + address_word addr; +#if WITH_XOR_ENDIAN != 0 + if (WITH_XOR_ENDIAN) + addr = xaddr ^ cpu_core->xor[(N - 1) % WITH_XOR_ENDIAN]; + else +#endif + addr = xaddr; + mapping = sim_core_find_mapping (core, map, addr, N, read_transfer, 1 /*abort*/, cpu, cia); + do + { +#if (WITH_DEVICES) + if (WITH_CALLBACK_MEMORY && mapping->device != NULL) + { + unsigned_M data; + if (device_io_read_buffer (mapping->device, &data, mapping->space, addr, N, cpu, cia) != N) + device_error (mapping->device, "internal error - %s - io_read_buffer should not fail", + XSTRING (sim_core_read_aligned_N)); + val = T2H_M (data); + break; + } +#endif +#if (WITH_HW) + if (WITH_CALLBACK_MEMORY && mapping->device != NULL) + { + unsigned_M data; + sim_cpu_hw_io_read_buffer (cpu, cia, mapping->device, &data, mapping->space, addr, N); + val = T2H_M (data); + break; + } +#endif + val = T2H_M (*(unsigned_M*) sim_core_translate (mapping, addr)); + } + while (0); + PROFILE_COUNT_CORE (cpu, addr, N, map); + if (TRACE_P (cpu, TRACE_CORE_IDX)) + sim_core_trace_M (cpu, cia, __LINE__, read_transfer, map, addr, val, N); + return val; +} +#endif + +/* TAGS: sim_core_read_unaligned_1 sim_core_read_unaligned_2 */ +/* TAGS: sim_core_read_unaligned_4 sim_core_read_unaligned_8 */ +/* TAGS: sim_core_read_unaligned_16 */ + +#if (M == N && N > 1) +INLINE_SIM_CORE(unsigned_M) +sim_core_read_unaligned_N(sim_cpu *cpu, + sim_cia cia, + unsigned map, + address_word addr) +{ + int alignment = N - 1; + /* if hardwired to forced alignment just do it */ + if (WITH_ALIGNMENT == FORCED_ALIGNMENT) + return sim_core_read_aligned_N (cpu, cia, map, addr & ~alignment); + else if ((addr & alignment) == 0) + return sim_core_read_aligned_N (cpu, cia, map, addr); + else + switch (CURRENT_ALIGNMENT) + { + case STRICT_ALIGNMENT: + SIM_CORE_SIGNAL (CPU_STATE (cpu), cpu, cia, map, N, addr, + read_transfer, sim_core_unaligned_signal); + case NONSTRICT_ALIGNMENT: + { + unsigned_M val; + if (sim_core_xor_read_buffer (CPU_STATE (cpu), cpu, map, &val, addr, N) != N) + SIM_CORE_SIGNAL (CPU_STATE (cpu), cpu, cia, map, N, addr, + read_transfer, sim_core_unaligned_signal); + val = T2H_M(val); + PROFILE_COUNT_CORE (cpu, addr, N, map); + if (TRACE_P (cpu, TRACE_CORE_IDX)) + sim_core_trace_M (cpu, cia, __LINE__, read_transfer, map, addr, val, N); + return val; + } + case FORCED_ALIGNMENT: + return sim_core_read_aligned_N (cpu, cia, map, addr & ~alignment); + case MIXED_ALIGNMENT: + sim_engine_abort (CPU_STATE (cpu), cpu, cia, + "internal error - %s - mixed alignment", + XSTRING (sim_core_read_unaligned_N)); + default: + sim_engine_abort (CPU_STATE (cpu), cpu, cia, + "internal error - %s - bad switch", + XSTRING (sim_core_read_unaligned_N)); + /* to keep some compilers happy, we return a dummy */ + return sim_core_dummy_M; + } +} +#endif + +/* TAGS: sim_core_read_misaligned_3 sim_core_read_misaligned_5 */ +/* TAGS: sim_core_read_misaligned_6 sim_core_read_misaligned_7 */ + +#if (M != N) +INLINE_SIM_CORE(unsigned_M) +sim_core_read_misaligned_N(sim_cpu *cpu, + sim_cia cia, + unsigned map, + address_word addr) +{ + unsigned_M val = 0; + if (sim_core_xor_read_buffer (CPU_STATE (cpu), cpu, map, &val, addr, N) != N) + SIM_CORE_SIGNAL (CPU_STATE (cpu), cpu, cia, map, N, addr, + read_transfer, sim_core_unaligned_signal); + if (CURRENT_HOST_BYTE_ORDER != CURRENT_TARGET_BYTE_ORDER) + val = SWAP_M (val); + if (CURRENT_TARGET_BYTE_ORDER == BIG_ENDIAN) + val >>= (M - N) * 8; + PROFILE_COUNT_CORE (cpu, addr, N, map); + if (TRACE_P (cpu, TRACE_CORE_IDX)) + sim_core_trace_M (cpu, cia, __LINE__, read_transfer, map, addr, val, N); + return val; +} +#endif + +/* TAGS: sim_core_write_aligned_1 sim_core_write_aligned_2 */ +/* TAGS: sim_core_write_aligned_4 sim_core_write_aligned_8 */ +/* TAGS: sim_core_write_aligned_16 */ + +#if (M == N) +INLINE_SIM_CORE(void) +sim_core_write_aligned_N(sim_cpu *cpu, + sim_cia cia, + unsigned map, + address_word xaddr, + unsigned_M val) +{ + sim_cpu_core *cpu_core = CPU_CORE (cpu); + sim_core_common *core = &cpu_core->common; + sim_core_mapping *mapping; + address_word addr; +#if WITH_XOR_ENDIAN != 0 + if (WITH_XOR_ENDIAN) + addr = xaddr ^ cpu_core->xor[(N - 1) % WITH_XOR_ENDIAN]; + else +#endif + addr = xaddr; + mapping = sim_core_find_mapping (core, map, addr, N, write_transfer, 1 /*abort*/, cpu, cia); + do + { +#if (WITH_DEVICES) + if (WITH_CALLBACK_MEMORY && mapping->device != NULL) + { + unsigned_M data = H2T_M (val); + if (device_io_write_buffer (mapping->device, &data, mapping->space, addr, N, cpu, cia) != N) + device_error (mapping->device, "internal error - %s - io_write_buffer should not fail", + XSTRING (sim_core_write_aligned_N)); + break; + } +#endif +#if (WITH_HW) + if (WITH_CALLBACK_MEMORY && mapping->device != NULL) + { + unsigned_M data = H2T_M (val); + sim_cpu_hw_io_write_buffer (cpu, cia, mapping->device, &data, mapping->space, addr, N); + break; + } +#endif + *(unsigned_M*) sim_core_translate (mapping, addr) = H2T_M (val); + } + while (0); + PROFILE_COUNT_CORE (cpu, addr, N, map); + if (TRACE_P (cpu, TRACE_CORE_IDX)) + sim_core_trace_M (cpu, cia, __LINE__, write_transfer, map, addr, val, N); +} +#endif + +/* TAGS: sim_core_write_unaligned_1 sim_core_write_unaligned_2 */ +/* TAGS: sim_core_write_unaligned_4 sim_core_write_unaligned_8 */ +/* TAGS: sim_core_write_unaligned_16 */ + +#if (M == N && N > 1) +INLINE_SIM_CORE(void) +sim_core_write_unaligned_N(sim_cpu *cpu, + sim_cia cia, + unsigned map, + address_word addr, + unsigned_M val) +{ + int alignment = N - 1; + /* if hardwired to forced alignment just do it */ + if (WITH_ALIGNMENT == FORCED_ALIGNMENT) + sim_core_write_aligned_N (cpu, cia, map, addr & ~alignment, val); + else if ((addr & alignment) == 0) + sim_core_write_aligned_N (cpu, cia, map, addr, val); + else + switch (CURRENT_ALIGNMENT) + { + case STRICT_ALIGNMENT: + SIM_CORE_SIGNAL (CPU_STATE (cpu), cpu, cia, map, N, addr, + write_transfer, sim_core_unaligned_signal); + break; + case NONSTRICT_ALIGNMENT: + { + unsigned_M data = H2T_M (val); + if (sim_core_xor_write_buffer (CPU_STATE (cpu), cpu, map, &data, addr, N) != N) + SIM_CORE_SIGNAL (CPU_STATE (cpu), cpu, cia, map, N, addr, + write_transfer, sim_core_unaligned_signal); + PROFILE_COUNT_CORE (cpu, addr, N, map); + if (TRACE_P (cpu, TRACE_CORE_IDX)) + sim_core_trace_M (cpu, cia, __LINE__, write_transfer, map, addr, val, N); + break; + } + case FORCED_ALIGNMENT: + sim_core_write_aligned_N (cpu, cia, map, addr & ~alignment, val); + break; + case MIXED_ALIGNMENT: + sim_engine_abort (CPU_STATE (cpu), cpu, cia, + "internal error - %s - mixed alignment", + XSTRING (sim_core_write_unaligned_N)); + break; + default: + sim_engine_abort (CPU_STATE (cpu), cpu, cia, + "internal error - %s - bad switch", + XSTRING (sim_core_write_unaligned_N)); + break; + } +} +#endif + +/* TAGS: sim_core_write_misaligned_3 sim_core_write_misaligned_5 */ +/* TAGS: sim_core_write_misaligned_6 sim_core_write_misaligned_7 */ + +#if (M != N) +INLINE_SIM_CORE(void) +sim_core_write_misaligned_N(sim_cpu *cpu, + sim_cia cia, + unsigned map, + address_word addr, + unsigned_M val) +{ + unsigned_M data = val; + if (CURRENT_TARGET_BYTE_ORDER == BIG_ENDIAN) + data <<= (M - N) * 8; + if (CURRENT_HOST_BYTE_ORDER != CURRENT_TARGET_BYTE_ORDER) + data = SWAP_M (data); + if (sim_core_xor_write_buffer (CPU_STATE (cpu), cpu, map, &data, addr, N) != N) + SIM_CORE_SIGNAL (CPU_STATE (cpu), cpu, cia, map, N, addr, + write_transfer, sim_core_unaligned_signal); + PROFILE_COUNT_CORE (cpu, addr, N, map); + if (TRACE_P (cpu, TRACE_CORE_IDX)) + sim_core_trace_M (cpu, cia, __LINE__, write_transfer, map, addr, val, N); +} +#endif + + +/* NOTE: see start of file for #define of these macros */ +#undef unsigned_M +#undef T2H_M +#undef H2T_M +#undef SWAP_M +#undef sim_core_read_aligned_N +#undef sim_core_read_unaligned_N +#undef sim_core_read_misaligned_N +#undef sim_core_write_aligned_N +#undef sim_core_write_unaligned_N +#undef sim_core_write_misaligned_N +#undef sim_core_trace_M +#undef sim_core_dummy_M +#undef M +#undef N diff --git a/sim/common/sim-n-endian.h b/sim/common/sim-n-endian.h new file mode 100644 index 00000000000..c53e05a9a17 --- /dev/null +++ b/sim/common/sim-n-endian.h @@ -0,0 +1,169 @@ +/* This file is part of the program psim. + + Copyright (C) 1994-1995, Andrew Cagney + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + + +#ifndef N +#error "N must be #defined" +#endif + +#include "symcat.h" + +/* NOTE: See end of file for #undef */ +#define unsigned_N XCONCAT2(unsigned_,N) +#define endian_t2h_N XCONCAT2(endian_t2h_,N) +#define endian_h2t_N XCONCAT2(endian_h2t_,N) +#define _SWAP_N XCONCAT2(_SWAP_,N) +#define swap_N XCONCAT2(swap_,N) +#define endian_h2be_N XCONCAT2(endian_h2be_,N) +#define endian_be2h_N XCONCAT2(endian_be2h_,N) +#define endian_h2le_N XCONCAT2(endian_h2le_,N) +#define endian_le2h_N XCONCAT2(endian_le2h_,N) +#define offset_N XCONCAT2(offset_,N) + +/* TAGS: endian_t2h_1 endian_t2h_2 endian_t2h_4 endian_t2h_8 endian_t2h_16 */ + +INLINE_SIM_ENDIAN\ +(unsigned_N) +endian_t2h_N(unsigned_N raw_in) +{ + if (CURRENT_TARGET_BYTE_ORDER == CURRENT_HOST_BYTE_ORDER) { + return raw_in; + } + else { + _SWAP_N(return,raw_in); + } +} + +/* TAGS: endian_h2t_1 endian_h2t_2 endian_h2t_4 endian_h2t_8 endian_h2t_16 */ + +INLINE_SIM_ENDIAN\ +(unsigned_N) +endian_h2t_N(unsigned_N raw_in) +{ + if (CURRENT_TARGET_BYTE_ORDER == CURRENT_HOST_BYTE_ORDER) { + return raw_in; + } + else { + _SWAP_N(return,raw_in); + } +} + +/* TAGS: swap_1 swap_2 swap_4 swap_8 swap_16 */ + +INLINE_SIM_ENDIAN\ +(unsigned_N) +swap_N(unsigned_N raw_in) +{ + _SWAP_N(return,raw_in); +} + +/* TAGS: endian_h2be_1 endian_h2be_2 endian_h2be_4 endian_h2be_8 endian_h2be_16 */ + +INLINE_SIM_ENDIAN\ +(unsigned_N) +endian_h2be_N(unsigned_N raw_in) +{ + if (CURRENT_HOST_BYTE_ORDER == BIG_ENDIAN) { + return raw_in; + } + else { + _SWAP_N(return,raw_in); + } +} + +/* TAGS: endian_be2h_1 endian_be2h_2 endian_be2h_4 endian_be2h_8 endian_be2h_16 */ + +INLINE_SIM_ENDIAN\ +(unsigned_N) +endian_be2h_N(unsigned_N raw_in) +{ + if (CURRENT_HOST_BYTE_ORDER == BIG_ENDIAN) { + return raw_in; + } + else { + _SWAP_N(return,raw_in); + } +} + +/* TAGS: endian_h2le_1 endian_h2le_2 endian_h2le_4 endian_h2le_8 endian_h2le_16 */ + +INLINE_SIM_ENDIAN\ +(unsigned_N) +endian_h2le_N(unsigned_N raw_in) +{ + if (CURRENT_HOST_BYTE_ORDER == LITTLE_ENDIAN) { + return raw_in; + } + else { + _SWAP_N(return,raw_in); + } +} + +/* TAGS: endian_le2h_1 endian_le2h_2 endian_le2h_4 endian_le2h_8 endian_le2h_16 */ + +INLINE_SIM_ENDIAN\ +(unsigned_N) +endian_le2h_N(unsigned_N raw_in) +{ + if (CURRENT_HOST_BYTE_ORDER == LITTLE_ENDIAN) { + return raw_in; + } + else { + _SWAP_N(return,raw_in); + } +} + +/* TAGS: offset_1 offset_2 offset_4 offset_8 offset_16 */ + +INLINE_SIM_ENDIAN\ +(void*) +offset_N (unsigned_N *x, + unsigned sizeof_word, + unsigned word) +{ + char *in = (char*)x; + char *out; + unsigned offset = sizeof_word * word; + ASSERT (offset + sizeof_word <= sizeof(unsigned_N)); + ASSERT (word < (sizeof (unsigned_N) / sizeof_word)); + ASSERT ((sizeof (unsigned_N) % sizeof_word) == 0); + if (WITH_HOST_BYTE_ORDER == LITTLE_ENDIAN) + { + out = in + sizeof (unsigned_N) - offset - sizeof_word; + } + else + { + out = in + offset; + } + return out; +} + + +/* NOTE: See start of file for #define */ +#undef unsigned_N +#undef endian_t2h_N +#undef endian_h2t_N +#undef _SWAP_N +#undef swap_N +#undef endian_h2be_N +#undef endian_be2h_N +#undef endian_h2le_N +#undef endian_le2h_N +#undef offset_N diff --git a/sim/common/sim-options.c b/sim/common/sim-options.c new file mode 100644 index 00000000000..b49256b1b2d --- /dev/null +++ b/sim/common/sim-options.c @@ -0,0 +1,936 @@ +/* Simulator option handling. + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + Contributed by Cygnus Support. + +This file is part of GDB, the GNU debugger. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "sim-main.h" +#ifdef HAVE_STRING_H +#include +#else +#ifdef HAVE_STRINGS_H +#include +#endif +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#include +#include "libiberty.h" +#include "sim-options.h" +#include "sim-io.h" +#include "sim-assert.h" + +#include "bfd.h" + +/* Add a set of options to the simulator. + TABLE is an array of OPTIONS terminated by a NULL `opt.name' entry. + This is intended to be called by modules in their `install' handler. */ + +SIM_RC +sim_add_option_table (SIM_DESC sd, sim_cpu *cpu, const OPTION *table) +{ + struct option_list *ol = ((struct option_list *) + xmalloc (sizeof (struct option_list))); + + /* Note: The list is constructed in the reverse order we're called so + later calls will override earlier ones (in case that ever happens). + This is the intended behaviour. */ + + if (cpu) + { + ol->next = CPU_OPTIONS (cpu); + ol->options = table; + CPU_OPTIONS (cpu) = ol; + } + else + { + ol->next = STATE_OPTIONS (sd); + ol->options = table; + STATE_OPTIONS (sd) = ol; + } + + return SIM_RC_OK; +} + +/* Standard option table. + Modules may specify additional ones. + The caller of sim_parse_args may also specify additional options + by calling sim_add_option_table first. */ + +static DECLARE_OPTION_HANDLER (standard_option_handler); + +/* FIXME: We shouldn't print in --help output options that aren't usable. + Some fine tuning will be necessary. One can either move less general + options to another table or use a HAVE_FOO macro to ifdef out unavailable + options. */ + +/* ??? One might want to conditionally compile out the entries that + aren't enabled. There's a distinction, however, between options a + simulator can't support and options that haven't been configured in. + Certainly options a simulator can't support shouldn't appear in the + output of --help. Whether the same thing applies to options that haven't + been configured in or not isn't something I can get worked up over. + [Note that conditionally compiling them out might simply involve moving + the option to another table.] + If you decide to conditionally compile them out as well, delete this + comment and add a comment saying that that is the rule. */ + +typedef enum { + OPTION_DEBUG_INSN = OPTION_START, + OPTION_DEBUG_FILE, + OPTION_DO_COMMAND, + OPTION_ARCHITECTURE, + OPTION_TARGET, + OPTION_ARCHITECTURE_INFO, + OPTION_ENVIRONMENT, + OPTION_ALIGNMENT, + OPTION_VERBOSE, +#if defined (SIM_HAVE_BIENDIAN) + OPTION_ENDIAN, +#endif + OPTION_DEBUG, +#ifdef SIM_HAVE_FLATMEM + OPTION_MEM_SIZE, +#endif + OPTION_HELP, +#ifdef SIM_H8300 /* FIXME: Should be movable to h8300 dir. */ + OPTION_H8300, +#endif +} STANDARD_OPTIONS; + +static const OPTION standard_options[] = +{ + { {"verbose", no_argument, NULL, OPTION_VERBOSE}, + 'v', NULL, "Verbose output", + standard_option_handler }, + +#if defined (SIM_HAVE_BIENDIAN) /* ??? && WITH_TARGET_BYTE_ORDER == 0 */ + { {"endian", required_argument, NULL, OPTION_ENDIAN}, + 'E', "big|little", "Set endianness", + standard_option_handler }, +#endif + +#ifdef SIM_HAVE_ENVIRONMENT + /* This option isn't supported unless all choices are supported in keeping + with the goal of not printing in --help output things the simulator can't + do [as opposed to things that just haven't been configured in]. */ + { {"environment", required_argument, NULL, OPTION_ENVIRONMENT}, + '\0', "user|virtual|operating", "Set running environment", + standard_option_handler }, +#endif + + { {"alignment", required_argument, NULL, OPTION_ALIGNMENT}, + '\0', "strict|nonstrict|forced", "Set memory access alignment", + standard_option_handler }, + + { {"debug", no_argument, NULL, OPTION_DEBUG}, + 'D', NULL, "Print debugging messages", + standard_option_handler }, + { {"debug-insn", no_argument, NULL, OPTION_DEBUG_INSN}, + '\0', NULL, "Print instruction debugging messages", + standard_option_handler }, + { {"debug-file", required_argument, NULL, OPTION_DEBUG_FILE}, + '\0', "FILE NAME", "Specify debugging output file", + standard_option_handler }, + +#ifdef SIM_H8300 /* FIXME: Should be movable to h8300 dir. */ + { {"h8300h", no_argument, NULL, OPTION_H8300}, + 'h', NULL, "Indicate the CPU is h8/300h or h8/300s", + standard_option_handler }, +#endif + +#ifdef SIM_HAVE_FLATMEM + { {"mem-size", required_argument, NULL, OPTION_MEM_SIZE}, + 'm', "MEMORY SIZE", "Specify memory size", + standard_option_handler }, +#endif + + { {"do-command", required_argument, NULL, OPTION_DO_COMMAND}, + '\0', "COMMAND", ""/*undocumented*/, + standard_option_handler }, + + { {"help", no_argument, NULL, OPTION_HELP}, + 'H', NULL, "Print help information", + standard_option_handler }, + + { {"architecture", required_argument, NULL, OPTION_ARCHITECTURE}, + '\0', "MACHINE", "Specify the architecture to use", + standard_option_handler }, + { {"architecture-info", no_argument, NULL, OPTION_ARCHITECTURE_INFO}, + '\0', NULL, "List supported architectures", + standard_option_handler }, + { {"info-architecture", no_argument, NULL, OPTION_ARCHITECTURE_INFO}, + '\0', NULL, NULL, + standard_option_handler }, + + { {"target", required_argument, NULL, OPTION_TARGET}, + '\0', "BFDNAME", "Specify the object-code format for the object files", + standard_option_handler }, + + { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL } +}; + +static SIM_RC +standard_option_handler (SIM_DESC sd, sim_cpu *cpu, int opt, + char *arg, int is_command) +{ + int i,n; + + switch ((STANDARD_OPTIONS) opt) + { + case OPTION_VERBOSE: + STATE_VERBOSE_P (sd) = 1; + break; + +#ifdef SIM_HAVE_BIENDIAN + case OPTION_ENDIAN: + if (strcmp (arg, "big") == 0) + { + if (WITH_TARGET_BYTE_ORDER == LITTLE_ENDIAN) + { + sim_io_eprintf (sd, "Simulator compiled for little endian only.\n"); + return SIM_RC_FAIL; + } + /* FIXME:wip: Need to set something in STATE_CONFIG. */ + current_target_byte_order = BIG_ENDIAN; + } + else if (strcmp (arg, "little") == 0) + { + if (WITH_TARGET_BYTE_ORDER == BIG_ENDIAN) + { + sim_io_eprintf (sd, "Simulator compiled for big endian only.\n"); + return SIM_RC_FAIL; + } + /* FIXME:wip: Need to set something in STATE_CONFIG. */ + current_target_byte_order = LITTLE_ENDIAN; + } + else + { + sim_io_eprintf (sd, "Invalid endian specification `%s'\n", arg); + return SIM_RC_FAIL; + } + break; +#endif + + case OPTION_ENVIRONMENT: + if (strcmp (arg, "user") == 0) + STATE_ENVIRONMENT (sd) = USER_ENVIRONMENT; + else if (strcmp (arg, "virtual") == 0) + STATE_ENVIRONMENT (sd) = VIRTUAL_ENVIRONMENT; + else if (strcmp (arg, "operating") == 0) + STATE_ENVIRONMENT (sd) = OPERATING_ENVIRONMENT; + else + { + sim_io_eprintf (sd, "Invalid environment specification `%s'\n", arg); + return SIM_RC_FAIL; + } + if (WITH_ENVIRONMENT != ALL_ENVIRONMENT + && WITH_ENVIRONMENT != STATE_ENVIRONMENT (sd)) + { + char *type; + switch (WITH_ENVIRONMENT) + { + case USER_ENVIRONMENT: type = "user"; break; + case VIRTUAL_ENVIRONMENT: type = "virtual"; break; + case OPERATING_ENVIRONMENT: type = "operating"; break; + } + sim_io_eprintf (sd, "Simulator compiled for the %s environment only.\n", + type); + return SIM_RC_FAIL; + } + break; + + case OPTION_ALIGNMENT: + if (strcmp (arg, "strict") == 0) + { + if (WITH_ALIGNMENT == 0 || WITH_ALIGNMENT == STRICT_ALIGNMENT) + { + current_alignment = STRICT_ALIGNMENT; + break; + } + } + else if (strcmp (arg, "nonstrict") == 0) + { + if (WITH_ALIGNMENT == 0 || WITH_ALIGNMENT == NONSTRICT_ALIGNMENT) + { + current_alignment = NONSTRICT_ALIGNMENT; + break; + } + } + else if (strcmp (arg, "forced") == 0) + { + if (WITH_ALIGNMENT == 0 || WITH_ALIGNMENT == FORCED_ALIGNMENT) + { + current_alignment = FORCED_ALIGNMENT; + break; + } + } + else + { + sim_io_eprintf (sd, "Invalid alignment specification `%s'\n", arg); + return SIM_RC_FAIL; + } + switch (WITH_ALIGNMENT) + { + case STRICT_ALIGNMENT: + sim_io_eprintf (sd, "Simulator compiled for strict alignment only.\n"); + break; + case NONSTRICT_ALIGNMENT: + sim_io_eprintf (sd, "Simulator compiled for nonstrict alignment only.\n"); + break; + case FORCED_ALIGNMENT: + sim_io_eprintf (sd, "Simulator compiled for forced alignment only.\n"); + break; + } + return SIM_RC_FAIL; + + case OPTION_DEBUG: + if (! WITH_DEBUG) + sim_io_eprintf (sd, "Debugging not compiled in, `-D' ignored\n"); + else + { + for (n = 0; n < MAX_NR_PROCESSORS; ++n) + for (i = 0; i < MAX_DEBUG_VALUES; ++i) + CPU_DEBUG_FLAGS (STATE_CPU (sd, n))[i] = 1; + } + break; + + case OPTION_DEBUG_INSN : + if (! WITH_DEBUG) + sim_io_eprintf (sd, "Debugging not compiled in, `--debug-insn' ignored\n"); + else + { + for (n = 0; n < MAX_NR_PROCESSORS; ++n) + CPU_DEBUG_FLAGS (STATE_CPU (sd, n))[DEBUG_INSN_IDX] = 1; + } + break; + + case OPTION_DEBUG_FILE : + if (! WITH_DEBUG) + sim_io_eprintf (sd, "Debugging not compiled in, `--debug-file' ignored\n"); + else + { + FILE *f = fopen (arg, "w"); + + if (f == NULL) + { + sim_io_eprintf (sd, "Unable to open debug output file `%s'\n", arg); + return SIM_RC_FAIL; + } + for (n = 0; n < MAX_NR_PROCESSORS; ++n) + CPU_DEBUG_FILE (STATE_CPU (sd, n)) = f; + } + break; + +#ifdef SIM_H8300 /* FIXME: Can be moved to h8300 dir. */ + case OPTION_H8300: + set_h8300h (1); + break; +#endif + +#ifdef SIM_HAVE_FLATMEM + case OPTION_MEM_SIZE: + { + unsigned long ul = strtol (arg, NULL, 0); + /* 16384: some minimal amount */ + if (! isdigit (arg[0]) || ul < 16384) + { + sim_io_eprintf (sd, "Invalid memory size `%s'", arg); + return SIM_RC_FAIL; + } + STATE_MEM_SIZE (sd) = ul; + } + break; +#endif + + case OPTION_DO_COMMAND: + sim_do_command (sd, arg); + break; + + case OPTION_ARCHITECTURE: + { + const struct bfd_arch_info *ap = bfd_scan_arch (arg); + if (ap == NULL) + { + sim_io_eprintf (sd, "Architecture `%s' unknown\n", arg); + return SIM_RC_FAIL; + } + STATE_ARCHITECTURE (sd) = ap; + break; + } + + case OPTION_ARCHITECTURE_INFO: + { + const char **list = bfd_arch_list(); + const char **lp; + if (list == NULL) + abort (); + sim_io_printf (sd, "Possible architectures:"); + for (lp = list; *lp != NULL; lp++) + sim_io_printf (sd, " %s", *lp); + sim_io_printf (sd, "\n"); + free (list); + break; + } + + case OPTION_TARGET: + { + STATE_TARGET (sd) = xstrdup (arg); + break; + } + + case OPTION_HELP: + sim_print_help (sd, is_command); + if (STATE_OPEN_KIND (sd) == SIM_OPEN_STANDALONE) + exit (0); + /* FIXME: 'twould be nice to do something similar if gdb. */ + break; + } + + return SIM_RC_OK; +} + +/* Add the standard option list to the simulator. */ + +SIM_RC +standard_install (SIM_DESC sd) +{ + SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); + if (sim_add_option_table (sd, NULL, standard_options) != SIM_RC_OK) + return SIM_RC_FAIL; + return SIM_RC_OK; +} + +/* Return non-zero if arg is a duplicate argument. + If ARG is NULL, initialize. */ + +#define ARG_HASH_SIZE 97 +#define ARG_HASH(a) ((256 * (unsigned char) a[0] + (unsigned char) a[1]) % ARG_HASH_SIZE) + +static int +dup_arg_p (arg) + char *arg; +{ + int hash; + static char **arg_table = NULL; + + if (arg == NULL) + { + if (arg_table == NULL) + arg_table = (char **) xmalloc (ARG_HASH_SIZE * sizeof (char *)); + memset (arg_table, 0, ARG_HASH_SIZE * sizeof (char *)); + return 0; + } + + hash = ARG_HASH (arg); + while (arg_table[hash] != NULL) + { + if (strcmp (arg, arg_table[hash]) == 0) + return 1; + /* We assume there won't be more than ARG_HASH_SIZE arguments so we + don't check if the table is full. */ + if (++hash == ARG_HASH_SIZE) + hash = 0; + } + arg_table[hash] = arg; + return 0; +} + +/* Called by sim_open to parse the arguments. */ + +SIM_RC +sim_parse_args (sd, argv) + SIM_DESC sd; + char **argv; +{ + int c, i, argc, num_opts; + char *p, *short_options; + /* The `val' option struct entry is dynamically assigned for options that + only come in the long form. ORIG_VAL is used to get the original value + back. */ + int *orig_val; + struct option *lp, *long_options; + const struct option_list *ol; + const OPTION *opt; + OPTION_HANDLER **handlers; + sim_cpu **opt_cpu; + + /* Count the number of arguments. */ + for (argc = 0; argv[argc] != NULL; ++argc) + continue; + + /* Count the number of options. */ + num_opts = 0; + for (ol = STATE_OPTIONS (sd); ol != NULL; ol = ol->next) + for (opt = ol->options; OPTION_VALID_P (opt); ++opt) + ++num_opts; + for (i = 0; i < MAX_NR_PROCESSORS; ++i) + for (ol = CPU_OPTIONS (STATE_CPU (sd, i)); ol != NULL; ol = ol->next) + for (opt = ol->options; OPTION_VALID_P (opt); ++opt) + ++num_opts; + + /* Initialize duplicate argument checker. */ + (void) dup_arg_p (NULL); + + /* Build the option table for getopt. */ + + long_options = NZALLOC (struct option, num_opts + 1); + lp = long_options; + short_options = NZALLOC (char, num_opts * 3 + 1); + p = short_options; + handlers = NZALLOC (OPTION_HANDLER *, OPTION_START + num_opts); + orig_val = NZALLOC (int, OPTION_START + num_opts); + opt_cpu = NZALLOC (sim_cpu *, OPTION_START + num_opts); + + /* Set '+' as first char so argument permutation isn't done. This + is done to stop getopt_long returning options that appear after + the target program. Such options should be passed unchanged into + the program image. */ + *p++ = '+'; + + for (i = OPTION_START, ol = STATE_OPTIONS (sd); ol != NULL; ol = ol->next) + for (opt = ol->options; OPTION_VALID_P (opt); ++opt) + { + if (dup_arg_p (opt->opt.name)) + continue; + if (opt->shortopt != 0) + { + *p++ = opt->shortopt; + if (opt->opt.has_arg == required_argument) + *p++ = ':'; + else if (opt->opt.has_arg == optional_argument) + { *p++ = ':'; *p++ = ':'; } + handlers[(unsigned char) opt->shortopt] = opt->handler; + if (opt->opt.val != 0) + orig_val[(unsigned char) opt->shortopt] = opt->opt.val; + else + orig_val[(unsigned char) opt->shortopt] = opt->shortopt; + } + if (opt->opt.name != NULL) + { + *lp = opt->opt; + /* Dynamically assign `val' numbers for long options. */ + lp->val = i++; + handlers[lp->val] = opt->handler; + orig_val[lp->val] = opt->opt.val; + opt_cpu[lp->val] = NULL; + ++lp; + } + } + + for (c = 0; c < MAX_NR_PROCESSORS; ++c) + { + sim_cpu *cpu = STATE_CPU (sd, c); + for (ol = CPU_OPTIONS (cpu); ol != NULL; ol = ol->next) + for (opt = ol->options; OPTION_VALID_P (opt); ++opt) + { +#if 0 /* Each option is prepended with --- so this greatly cuts down + on the need for dup_arg_p checking. Maybe in the future it'll be + needed so this is just commented out, and not deleted. */ + if (dup_arg_p (opt->opt.name)) + continue; +#endif + /* Don't allow short versions of cpu specific options for now. */ + if (opt->shortopt != 0) + { + sim_io_eprintf (sd, "internal error, short cpu specific option"); + return SIM_RC_FAIL; + } + if (opt->opt.name != NULL) + { + char *name; + *lp = opt->opt; + /* Prepend --- to the option. */ + asprintf (&name, "%s-%s", CPU_NAME (cpu), lp->name); + lp->name = name; + /* Dynamically assign `val' numbers for long options. */ + lp->val = i++; + handlers[lp->val] = opt->handler; + orig_val[lp->val] = opt->opt.val; + opt_cpu[lp->val] = cpu; + ++lp; + } + } + } + + /* Terminate the short and long option lists. */ + *p = 0; + lp->name = NULL; + + /* Ensure getopt is initialized. */ + optind = 0; + + while (1) + { + int longind, optc; + + optc = getopt_long (argc, argv, short_options, long_options, &longind); + if (optc == -1) + { + if (STATE_OPEN_KIND (sd) == SIM_OPEN_STANDALONE) + STATE_PROG_ARGV (sd) = dupargv (argv + optind); + break; + } + if (optc == '?') + return SIM_RC_FAIL; + + if ((*handlers[optc]) (sd, opt_cpu[optc], orig_val[optc], optarg, 0/*!is_command*/) == SIM_RC_FAIL) + return SIM_RC_FAIL; + } + + return SIM_RC_OK; +} + +/* Utility of sim_print_help to print a list of option tables. */ + +static void +print_help (SIM_DESC sd, sim_cpu *cpu, const struct option_list *ol, int is_command) +{ + const OPTION *opt; + + for ( ; ol != NULL; ol = ol->next) + for (opt = ol->options; OPTION_VALID_P (opt); ++opt) + { + const int indent = 30; + int comma, len; + const OPTION *o; + + if (dup_arg_p (opt->opt.name)) + continue; + + if (opt->doc == NULL) + continue; + + if (opt->doc_name != NULL && opt->doc_name [0] == '\0') + continue; + + sim_io_printf (sd, " "); + + comma = 0; + len = 2; + + /* list any short options (aliases) for the current OPT */ + if (!is_command) + { + o = opt; + do + { + if (o->shortopt != '\0') + { + sim_io_printf (sd, "%s-%c", comma ? ", " : "", o->shortopt); + len += (comma ? 2 : 0) + 2; + if (o->arg != NULL) + { + if (o->opt.has_arg == optional_argument) + { + sim_io_printf (sd, "[%s]", o->arg); + len += 1 + strlen (o->arg) + 1; + } + else + { + sim_io_printf (sd, " %s", o->arg); + len += 1 + strlen (o->arg); + } + } + comma = 1; + } + ++o; + } + while (OPTION_VALID_P (o) && o->doc == NULL); + } + + /* list any long options (aliases) for the current OPT */ + o = opt; + do + { + const char *name; + const char *cpu_prefix = cpu ? CPU_NAME (cpu) : NULL; + if (o->doc_name != NULL) + name = o->doc_name; + else + name = o->opt.name; + if (name != NULL) + { + sim_io_printf (sd, "%s%s%s%s%s", + comma ? ", " : "", + is_command ? "" : "--", + cpu ? cpu_prefix : "", + cpu ? "-" : "", + name); + len += ((comma ? 2 : 0) + + (is_command ? 0 : 2) + + strlen (name)); + if (o->arg != NULL) + { + if (o->opt.has_arg == optional_argument) + { + sim_io_printf (sd, " [%s]", o->arg); + len += 2 + strlen (o->arg) + 1; + } + else + { + sim_io_printf (sd, " %s", o->arg); + len += 1 + strlen (o->arg); + } + } + comma = 1; + } + ++o; + } + while (OPTION_VALID_P (o) && o->doc == NULL); + + if (len >= indent) + { + sim_io_printf (sd, "\n%*s", indent, ""); + } + else + sim_io_printf (sd, "%*s", indent - len, ""); + + /* print the description, word wrap long lines */ + { + const char *chp = opt->doc; + unsigned doc_width = 80 - indent; + while (strlen (chp) >= doc_width) /* some slack */ + { + const char *end = chp + doc_width - 1; + while (end > chp && !isspace (*end)) + end --; + if (end == chp) + end = chp + doc_width - 1; + sim_io_printf (sd, "%.*s\n%*s", end - chp, chp, indent, ""); + chp = end; + while (isspace (*chp) && *chp != '\0') + chp++; + } + sim_io_printf (sd, "%s\n", chp); + } + } +} + +/* Print help messages for the options. */ + +void +sim_print_help (sd, is_command) + SIM_DESC sd; + int is_command; +{ + if (STATE_OPEN_KIND (sd) == SIM_OPEN_STANDALONE) + sim_io_printf (sd, "Usage: %s [options] program [program args]\n", + STATE_MY_NAME (sd)); + + /* Initialize duplicate argument checker. */ + (void) dup_arg_p (NULL); + + if (STATE_OPEN_KIND (sd) == SIM_OPEN_STANDALONE) + sim_io_printf (sd, "Options:\n"); + else + sim_io_printf (sd, "Commands:\n"); + + print_help (sd, NULL, STATE_OPTIONS (sd), is_command); + sim_io_printf (sd, "\n"); + + /* Print cpu-specific options. */ + { + int i; + + for (i = 0; i < MAX_NR_PROCESSORS; ++i) + { + sim_cpu *cpu = STATE_CPU (sd, i); + if (CPU_OPTIONS (cpu) == NULL) + continue; + sim_io_printf (sd, "CPU %s specific options:\n", CPU_NAME (cpu)); + print_help (sd, cpu, CPU_OPTIONS (cpu), is_command); + sim_io_printf (sd, "\n"); + } + } + + sim_io_printf (sd, "Note: Depending on the simulator configuration some %ss\n", + STATE_OPEN_KIND (sd) == SIM_OPEN_STANDALONE ? "option" : "command"); + sim_io_printf (sd, " may not be applicable\n"); + + if (STATE_OPEN_KIND (sd) == SIM_OPEN_STANDALONE) + { + sim_io_printf (sd, "\n"); + sim_io_printf (sd, "program args Arguments to pass to simulated program.\n"); + sim_io_printf (sd, " Note: Very few simulators support this.\n"); + } +} + +/* Utility of sim_args_command to find the closest match for a command. + Commands that have "-" in them can be specified as separate words. + e.g. sim memory-region 0x800000,0x4000 + or sim memory region 0x800000,0x4000 + If CPU is non-null, use its option table list, otherwise use the main one. + *PARGI is where to start looking in ARGV. It is updated to point past + the found option. */ + +static const OPTION * +find_match (SIM_DESC sd, sim_cpu *cpu, char *argv[], int *pargi) +{ + const struct option_list *ol; + const OPTION *opt; + /* most recent option match */ + const OPTION *matching_opt = NULL; + int matching_argi = -1; + + if (cpu) + ol = CPU_OPTIONS (cpu); + else + ol = STATE_OPTIONS (sd); + + /* Skip passed elements specified by *PARGI. */ + argv += *pargi; + + for ( ; ol != NULL; ol = ol->next) + for (opt = ol->options; OPTION_VALID_P (opt); ++opt) + { + int argi = 0; + const char *name = opt->opt.name; + if (name == NULL) + continue; + while (argv [argi] != NULL + && strncmp (name, argv [argi], strlen (argv [argi])) == 0) + { + name = &name [strlen (argv[argi])]; + if (name [0] == '-') + { + /* leading match ...-d-e-f - continue search */ + name ++; /* skip `-' */ + argi ++; + continue; + } + else if (name [0] == '\0') + { + /* exact match ... - better than before? */ + if (argi > matching_argi) + { + matching_argi = argi; + matching_opt = opt; + } + break; + } + else + break; + } + } + + *pargi = matching_argi; + return matching_opt; +} + +SIM_RC +sim_args_command (SIM_DESC sd, char *cmd) +{ + /* something to do? */ + if (cmd == NULL) + return SIM_RC_OK; /* FIXME - perhaphs help would be better */ + + if (cmd [0] == '-') + { + /* user specified - ... form? */ + char **argv = buildargv (cmd); + SIM_RC rc = sim_parse_args (sd, argv); + freeargv (argv); + return rc; + } + else + { + char **argv = buildargv (cmd); + const OPTION *matching_opt = NULL; + int matching_argi; + sim_cpu *cpu; + + if (argv [0] == NULL) + return SIM_RC_OK; /* FIXME - perhaphs help would be better */ + + /* First check for a cpu selector. */ + { + char *cpu_name = xstrdup (argv[0]); + char *hyphen = strchr (cpu_name, '-'); + if (hyphen) + *hyphen = 0; + cpu = sim_cpu_lookup (sd, cpu_name); + if (cpu) + { + /* If -, point argv[0] at . */ + if (hyphen) + { + matching_argi = 0; + argv[0] += hyphen - cpu_name + 1; + } + else + matching_argi = 1; + matching_opt = find_match (sd, cpu, argv, &matching_argi); + /* If hyphen found restore argv[0]. */ + if (hyphen) + argv[0] -= hyphen - cpu_name + 1; + } + free (cpu_name); + } + + /* If that failed, try the main table. */ + if (matching_opt == NULL) + { + matching_argi = 0; + matching_opt = find_match (sd, NULL, argv, &matching_argi); + } + + if (matching_opt != NULL) + { + switch (matching_opt->opt.has_arg) + { + case no_argument: + if (argv [matching_argi + 1] == NULL) + matching_opt->handler (sd, cpu, matching_opt->opt.val, + NULL, 1/*is_command*/); + else + sim_io_eprintf (sd, "Command `%s' takes no arguments\n", + matching_opt->opt.name); + break; + case optional_argument: + if (argv [matching_argi + 1] == NULL) + matching_opt->handler (sd, cpu, matching_opt->opt.val, + NULL, 1/*is_command*/); + else if (argv [matching_argi + 2] == NULL) + matching_opt->handler (sd, cpu, matching_opt->opt.val, + argv [matching_argi + 1], 1/*is_command*/); + else + sim_io_eprintf (sd, "Command `%s' requires no more than one argument\n", + matching_opt->opt.name); + break; + case required_argument: + if (argv [matching_argi + 1] == NULL) + sim_io_eprintf (sd, "Command `%s' requires an argument\n", + matching_opt->opt.name); + else if (argv [matching_argi + 2] == NULL) + matching_opt->handler (sd, cpu, matching_opt->opt.val, + argv [matching_argi + 1], 1/*is_command*/); + else + sim_io_eprintf (sd, "Command `%s' requires only one argument\n", + matching_opt->opt.name); + } + freeargv (argv); + return SIM_RC_OK; + } + + freeargv (argv); + } + + /* didn't find anything that remotly matched */ + return SIM_RC_FAIL; +} diff --git a/sim/common/sim-options.h b/sim/common/sim-options.h new file mode 100644 index 00000000000..78cad567602 --- /dev/null +++ b/sim/common/sim-options.h @@ -0,0 +1,149 @@ +/* Header file for simulator argument handling. + Copyright (C) 1997, 1998 Free Software Foundation, Inc. + Contributed by Cygnus Support. + +This file is part of GDB, the GNU debugger. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef SIM_OPTIONS_H +#define SIM_OPTIONS_H + +#include "getopt.h" + +/* ARGV option support. + + Options for the standalone simulator are parsed by sim_open since + sim_open handles the large majority of them and it also parses the + options when invoked by gdb [or any external program]. + + For OPTION_HANDLER: arg#2 is the processor to apply to option to + (all if NULL); arg#3 is the option index; arg#4 is the option's + argument, NULL if optional and missing; arg#5 is nonzero if a + command is being interpreted. */ + +typedef SIM_RC (OPTION_HANDLER) PARAMS ((SIM_DESC, sim_cpu *, int, char *, int)); + +/* Declare option handlers with a macro so it's usable on k&r systems. */ +#define DECLARE_OPTION_HANDLER(fn) SIM_RC fn PARAMS ((SIM_DESC, sim_cpu *, int, char *, int)) + +typedef struct { + + /* The long option information. */ + + struct option opt; + + /* The short option with the same meaning ('\0' if none). + + For short options, when OPT.VAL is non-zero, it, instead of + SHORTOPT is passed to HANDLER. + + For example, for the below: + + { {"dc", no_argument, NULL, OPTION_VALUE}, + 'd', NULL, "<>", HANDLER}, + { {NULL, no_argument, NULL, OPTION_VALUE}, + 'e', NULL, "<>", HANDLER}, + + the options --dc, -d and -e all result in OPTION_VALUE being + passed into HANDLER. */ + + char shortopt; + + /* The name of the argument (NULL if none). */ + + const char *arg; + + /* The documentation string. + + If DOC is NULL, this option name is listed as a synonym for the + previous option. + + If DOC and DOC_NAME are the empty string (i.e. ""), this option + is not listed in usage and help messages. + + For example, given the aliased options --dc, --dp and -d, then: + + { {"dc", no_argument, NULL, OPTION_DC}, + 'd', NULL, "<>", HANDLER}, + { {"dp", no_argument, NULL, OPTION_DP}, + '\0', NULL, NULL, HANDLER}, + + will list ``-d, --dc, --dp <>'' */ + + const char *doc; + + /* A function to process the option. */ + + OPTION_HANDLER *handler; + + /* The documentation name. Used when generating usage and help + messages. + + If DOC and DOC_NAME are the empty string (i.e. ""), this option + is not listed in usage and help messages. + + If DOC_NAME is a non-empty string then it, insted of OPT.NAME, is + listed as the name of the option in usage and help messages. + + For example, given the options --set-pc and --set-sp, then: + + { {"set-pc", no_argument, NULL, OPTION_SET_PC}, + '\0', NULL, "<>", HANDLER, "--set-REGNAME" }, + { {"set-sp", no_argument, NULL, OPTION_SET_SP}, + '\0', NULL, "", HANDLER, "" }, + + will list ``--set-REGNAME <>". */ + + const char *doc_name; + +} OPTION; + +/* All options that don't have a short form equivalent begin with this for + `val'. 130 isn't special, just some non-ASCII value to begin at. + Modules needn't worry about collisions here, the code dynamically assigned + the actual numbers used and then passes the original value to the option + handler. */ +#define OPTION_START 130 + +/* Identify valid option in the table */ +#define OPTION_VALID_P(O) ((O)->opt.name != NULL || (O)->shortopt != '\0') + +/* List of options added by various modules. */ +typedef struct option_list { + struct option_list *next; + const OPTION *options; +} OPTION_LIST; + +/* Add a set of options to the simulator. + CPU is the cpu the options apply to or NULL for all cpus. + TABLE is an array of OPTIONS terminated by a NULL `opt.name' entry. */ +SIM_RC sim_add_option_table PARAMS ((SIM_DESC sd, sim_cpu *cpu, const OPTION *table)); + +/* Install handler for the standard options. */ +MODULE_INSTALL_FN standard_install; + +/* Called by sim_open to parse the arguments. */ +SIM_RC sim_parse_args PARAMS ((SIM_DESC sd, char **argv)); + +/* Print help messages for the options. IS_COMMAND is non-zero when + this function is called from the command line interpreter. */ +void sim_print_help PARAMS ((SIM_DESC sd, int is_command)); + +/* Try to parse the command as if it is an option, Only fail when + totally unsuccessful */ +SIM_RC sim_args_command PARAMS ((SIM_DESC sd, char *cmd)); + +#endif /* SIM_OPTIONS_H */ diff --git a/sim/common/sim-profile.c b/sim/common/sim-profile.c new file mode 100644 index 00000000000..5d075d15bd1 --- /dev/null +++ b/sim/common/sim-profile.c @@ -0,0 +1,1175 @@ +/* Default profiling support. + Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. + Contributed by Cygnus Support. + +This file is part of GDB, the GNU debugger. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "sim-main.h" +#include "sim-io.h" +#include "sim-options.h" +#include "sim-assert.h" + +#ifdef HAVE_STDLIB_H +#include +#endif + +#ifdef HAVE_STRING_H +#include +#else +#ifdef HAVE_STRINGS_H +#include +#endif +#endif + +#define COMMAS(n) sim_add_commas (comma_buf, sizeof (comma_buf), (n)) + +static MODULE_INIT_FN profile_init; +static MODULE_UNINSTALL_FN profile_uninstall; + +static DECLARE_OPTION_HANDLER (profile_option_handler); + +enum { + OPTION_PROFILE_INSN = OPTION_START, + OPTION_PROFILE_MEMORY, + OPTION_PROFILE_MODEL, + OPTION_PROFILE_FILE, + OPTION_PROFILE_CORE, + OPTION_PROFILE_PC, + OPTION_PROFILE_PC_RANGE, + OPTION_PROFILE_PC_GRANULARITY, + OPTION_PROFILE_RANGE, + OPTION_PROFILE_FUNCTION +}; + +static const OPTION profile_options[] = { + { {"profile", optional_argument, NULL, 'p'}, + 'p', "on|off", "Perform profiling", + profile_option_handler }, + { {"profile-insn", optional_argument, NULL, OPTION_PROFILE_INSN}, + '\0', "on|off", "Perform instruction profiling", + profile_option_handler }, + { {"profile-memory", optional_argument, NULL, OPTION_PROFILE_MEMORY}, + '\0', "on|off", "Perform memory profiling", + profile_option_handler }, + { {"profile-core", optional_argument, NULL, OPTION_PROFILE_CORE}, + '\0', "on|off", "Perform CORE profiling", + profile_option_handler }, + { {"profile-model", optional_argument, NULL, OPTION_PROFILE_MODEL}, + '\0', "on|off", "Perform model profiling", + profile_option_handler }, + + { {"profile-file", required_argument, NULL, OPTION_PROFILE_FILE}, + '\0', "FILE NAME", "Specify profile output file", + profile_option_handler }, + + { {"profile-pc", optional_argument, NULL, OPTION_PROFILE_PC}, + '\0', "on|off", "Perform PC profiling", + profile_option_handler }, + { {"profile-pc-frequency", required_argument, NULL, 'F'}, + 'F', "PC PROFILE FREQUENCY", "Specified PC profiling frequency", + profile_option_handler }, + { {"profile-pc-size", required_argument, NULL, 'S'}, + 'S', "PC PROFILE SIZE", "Specify PC profiling size", + profile_option_handler }, + { {"profile-pc-granularity", required_argument, NULL, OPTION_PROFILE_PC_GRANULARITY}, + '\0', "PC PROFILE GRANULARITY", "Specify PC profiling sample coverage", + profile_option_handler }, + { {"profile-pc-range", required_argument, NULL, OPTION_PROFILE_PC_RANGE}, + '\0', "BASE,BOUND", "Specify PC profiling address range", + profile_option_handler }, + +#ifdef SIM_HAVE_ADDR_RANGE + { {"profile-range", required_argument, NULL, OPTION_PROFILE_RANGE}, + '\0', "START,END", "Specify range of addresses for instruction and model profiling", + profile_option_handler }, +#if 0 /*wip*/ + { {"profile-function", required_argument, NULL, OPTION_PROFILE_FUNCTION}, + '\0', "FUNCTION", "Specify function to profile", + profile_option_handler }, +#endif +#endif + + { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL } +}; + +/* Set/reset the profile options indicated in MASK. */ + +static SIM_RC +set_profile_option_mask (SIM_DESC sd, const char *name, int mask, const char *arg) +{ + int profile_nr; + int cpu_nr; + int profile_val = 1; + + if (arg != NULL) + { + if (strcmp (arg, "yes") == 0 + || strcmp (arg, "on") == 0 + || strcmp (arg, "1") == 0) + profile_val = 1; + else if (strcmp (arg, "no") == 0 + || strcmp (arg, "off") == 0 + || strcmp (arg, "0") == 0) + profile_val = 0; + else + { + sim_io_eprintf (sd, "Argument `%s' for `--profile%s' invalid, one of `on', `off', `yes', `no' expected\n", arg, name); + return SIM_RC_FAIL; + } + } + + /* update applicable profile bits */ + for (profile_nr = 0; profile_nr < MAX_PROFILE_VALUES; ++profile_nr) + { + if ((mask & (1 << profile_nr)) == 0) + continue; + +#if 0 /* see sim-trace.c, set flags in STATE here if/when there are any */ + /* Set non-cpu specific values. */ + switch (profile_nr) + { + case ??? : + break; + } +#endif + + /* Set cpu values. */ + for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; cpu_nr++) + { + CPU_PROFILE_FLAGS (STATE_CPU (sd, cpu_nr))[profile_nr] = profile_val; + } + } + + /* Re-compute the cpu profile summary. */ + if (profile_val) + { + for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; cpu_nr++) + CPU_PROFILE_DATA (STATE_CPU (sd, cpu_nr))->profile_any_p = 1; + } + else + { + for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; cpu_nr++) + { + CPU_PROFILE_DATA (STATE_CPU (sd, cpu_nr))->profile_any_p = 0; + for (profile_nr = 0; profile_nr < MAX_PROFILE_VALUES; ++profile_nr) + { + if (CPU_PROFILE_FLAGS (STATE_CPU (sd, cpu_nr))[profile_nr]) + { + CPU_PROFILE_DATA (STATE_CPU (sd, cpu_nr))->profile_any_p = 1; + break; + } + } + } + } + + return SIM_RC_OK; +} + +/* Set one profile option based on its IDX value. + Not static as cgen-scache.c uses it. */ + +SIM_RC +sim_profile_set_option (SIM_DESC sd, const char *name, int idx, const char *arg) +{ + return set_profile_option_mask (sd, name, 1 << idx, arg); +} + +static SIM_RC +profile_option_handler (SIM_DESC sd, + sim_cpu *cpu, + int opt, + char *arg, + int is_command) +{ + int cpu_nr,prof_nr; + + /* FIXME: Need to handle `cpu' arg. */ + + switch (opt) + { + case 'p' : + if (! WITH_PROFILE) + sim_io_eprintf (sd, "Profiling not compiled in, `-p' ignored\n"); + else + return set_profile_option_mask (sd, "profile", PROFILE_USEFUL_MASK, + arg); + break; + + case OPTION_PROFILE_INSN : + if (WITH_PROFILE_INSN_P) + return sim_profile_set_option (sd, "-insn", PROFILE_INSN_IDX, arg); + else + sim_io_eprintf (sd, "Instruction profiling not compiled in, `--profile-insn' ignored\n"); + break; + + case OPTION_PROFILE_MEMORY : + if (WITH_PROFILE_MEMORY_P) + return sim_profile_set_option (sd, "-memory", PROFILE_MEMORY_IDX, arg); + else + sim_io_eprintf (sd, "Memory profiling not compiled in, `--profile-memory' ignored\n"); + break; + + case OPTION_PROFILE_CORE : + if (WITH_PROFILE_CORE_P) + return sim_profile_set_option (sd, "-core", PROFILE_CORE_IDX, arg); + else + sim_io_eprintf (sd, "CORE profiling not compiled in, `--profile-core' ignored\n"); + break; + + case OPTION_PROFILE_MODEL : + if (WITH_PROFILE_MODEL_P) + return sim_profile_set_option (sd, "-model", PROFILE_MODEL_IDX, arg); + else + sim_io_eprintf (sd, "Model profiling not compiled in, `--profile-model' ignored\n"); + break; + + case OPTION_PROFILE_FILE : + /* FIXME: Might want this to apply to pc profiling only, + or have two profile file options. */ + if (! WITH_PROFILE) + sim_io_eprintf (sd, "Profiling not compiled in, `--profile-file' ignored\n"); + else + { + FILE *f = fopen (arg, "w"); + + if (f == NULL) + { + sim_io_eprintf (sd, "Unable to open profile output file `%s'\n", arg); + return SIM_RC_FAIL; + } + for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; ++cpu_nr) + PROFILE_FILE (CPU_PROFILE_DATA (STATE_CPU (sd, cpu_nr))) = f; + } + break; + + case OPTION_PROFILE_PC: + if (WITH_PROFILE_PC_P) + return sim_profile_set_option (sd, "-pc", PROFILE_PC_IDX, arg); + else + sim_io_eprintf (sd, "PC profiling not compiled in, `--profile-pc' ignored\n"); + break; + + case 'F' : + if (WITH_PROFILE_PC_P) + { + /* FIXME: Validate arg. */ + int val = atoi (arg); + for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; ++cpu_nr) + PROFILE_PC_FREQ (CPU_PROFILE_DATA (STATE_CPU (sd, cpu_nr))) = val; + for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; ++cpu_nr) + CPU_PROFILE_FLAGS (STATE_CPU (sd, cpu_nr))[PROFILE_PC_IDX] = 1; + } + else + sim_io_eprintf (sd, "PC profiling not compiled in, `--profile-pc-frequency' ignored\n"); + break; + + case 'S' : + if (WITH_PROFILE_PC_P) + { + /* FIXME: Validate arg. */ + int val = atoi (arg); + for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; ++cpu_nr) + PROFILE_PC_NR_BUCKETS (CPU_PROFILE_DATA (STATE_CPU (sd, cpu_nr))) = val; + for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; ++cpu_nr) + CPU_PROFILE_FLAGS (STATE_CPU (sd, cpu_nr))[PROFILE_PC_IDX] = 1; + } + else + sim_io_eprintf (sd, "PC profiling not compiled in, `--profile-pc-size' ignored\n"); + break; + + case OPTION_PROFILE_PC_GRANULARITY: + if (WITH_PROFILE_PC_P) + { + int shift; + int val = atoi (arg); + /* check that the granularity is a power of two */ + shift = 0; + while (val > (1 << shift)) + { + shift += 1; + } + if (val != (1 << shift)) + { + sim_io_eprintf (sd, "PC profiling granularity not a power of two\n"); + return SIM_RC_FAIL; + } + if (shift == 0) + { + sim_io_eprintf (sd, "PC profiling granularity too small"); + return SIM_RC_FAIL; + } + for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; ++cpu_nr) + PROFILE_PC_SHIFT (CPU_PROFILE_DATA (STATE_CPU (sd, cpu_nr))) = shift; + for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; ++cpu_nr) + CPU_PROFILE_FLAGS (STATE_CPU (sd, cpu_nr))[PROFILE_PC_IDX] = 1; + } + else + sim_io_eprintf (sd, "PC profiling not compiled in, `--profile-pc-granularity' ignored\n"); + break; + + case OPTION_PROFILE_PC_RANGE: + if (WITH_PROFILE_PC_P) + { + /* FIXME: Validate args */ + char *chp = arg; + unsigned long base; + unsigned long bound; + base = strtoul (chp, &chp, 0); + if (*chp != ',') + { + sim_io_eprintf (sd, "--profile-pc-range missing BOUND argument\n"); + return SIM_RC_FAIL; + } + bound = strtoul (chp + 1, NULL, 0); + for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; ++cpu_nr) + { + PROFILE_PC_START (CPU_PROFILE_DATA (STATE_CPU (sd, cpu_nr))) = base; + PROFILE_PC_END (CPU_PROFILE_DATA (STATE_CPU (sd, cpu_nr))) = bound; + } + for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; ++cpu_nr) + CPU_PROFILE_FLAGS (STATE_CPU (sd, cpu_nr))[PROFILE_PC_IDX] = 1; + } + else + sim_io_eprintf (sd, "PC profiling not compiled in, `--profile-pc-range' ignored\n"); + break; + +#ifdef SIM_HAVE_ADDR_RANGE + case OPTION_PROFILE_RANGE : + if (WITH_PROFILE) + { + char *chp = arg; + unsigned long start,end; + start = strtoul (chp, &chp, 0); + if (*chp != ',') + { + sim_io_eprintf (sd, "--profile-range missing END argument\n"); + return SIM_RC_FAIL; + } + end = strtoul (chp + 1, NULL, 0); + /* FIXME: Argument validation. */ + if (cpu != NULL) + sim_addr_range_add (PROFILE_RANGE (CPU_PROFILE_DATA (cpu)), + start, end); + else + for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; ++cpu_nr) + sim_addr_range_add (PROFILE_RANGE (CPU_PROFILE_DATA (STATE_CPU (sd, cpu_nr))), + start, end); + } + else + sim_io_eprintf (sd, "Profiling not compiled in, `--profile-range' ignored\n"); + break; + + case OPTION_PROFILE_FUNCTION : + if (WITH_PROFILE) + { + /*wip: need to compute function range given name*/ + } + else + sim_io_eprintf (sd, "Profiling not compiled in, `--profile-function' ignored\n"); + break; +#endif /* SIM_HAVE_ADDR_RANGE */ + } + + return SIM_RC_OK; +} + +/* PC profiling support */ + +#if WITH_PROFILE_PC_P + +static void +profile_pc_cleanup (SIM_DESC sd) +{ + int n; + for (n = 0; n < MAX_NR_PROCESSORS; n++) + { + sim_cpu *cpu = STATE_CPU (sd, n); + PROFILE_DATA *data = CPU_PROFILE_DATA (cpu); + if (PROFILE_PC_COUNT (data) != NULL) + zfree (PROFILE_PC_COUNT (data)); + PROFILE_PC_COUNT (data) = NULL; + if (PROFILE_PC_EVENT (data) != NULL) + sim_events_deschedule (sd, PROFILE_PC_EVENT (data)); + PROFILE_PC_EVENT (data) = NULL; + } +} + + +static void +profile_pc_uninstall (SIM_DESC sd) +{ + profile_pc_cleanup (sd); +} + +static void +profile_pc_event (SIM_DESC sd, + void *data) +{ + sim_cpu *cpu = (sim_cpu*) data; + PROFILE_DATA *profile = CPU_PROFILE_DATA (cpu); + address_word pc; + unsigned i; + switch (STATE_WATCHPOINTS (sd)->sizeof_pc) + { + case 2: pc = *(unsigned_2*)(STATE_WATCHPOINTS (sd)->pc) ; break; + case 4: pc = *(unsigned_4*)(STATE_WATCHPOINTS (sd)->pc) ; break; + case 8: pc = *(unsigned_8*)(STATE_WATCHPOINTS (sd)->pc) ; break; + default: pc = 0; + } + i = (pc - PROFILE_PC_START (profile)) >> PROFILE_PC_SHIFT (profile); + if (i < PROFILE_PC_NR_BUCKETS (profile)) + PROFILE_PC_COUNT (profile) [i] += 1; /* Overflow? */ + else + PROFILE_PC_COUNT (profile) [PROFILE_PC_NR_BUCKETS (profile)] += 1; + PROFILE_PC_EVENT (profile) = + sim_events_schedule (sd, PROFILE_PC_FREQ (profile), profile_pc_event, cpu); +} + +static SIM_RC +profile_pc_init (SIM_DESC sd) +{ + int n; + profile_pc_cleanup (sd); + for (n = 0; n < MAX_NR_PROCESSORS; n++) + { + sim_cpu *cpu = STATE_CPU (sd, n); + PROFILE_DATA *data = CPU_PROFILE_DATA (cpu); + if (CPU_PROFILE_FLAGS (STATE_CPU (sd, n))[PROFILE_PC_IDX] + && STATE_WATCHPOINTS (sd)->pc != NULL) + { + int bucket_size; + /* fill in the frequency if not specified */ + if (PROFILE_PC_FREQ (data) == 0) + PROFILE_PC_FREQ (data) = 256; + /* fill in the start/end if not specified */ + if (PROFILE_PC_END (data) == 0) + { + PROFILE_PC_START (data) = STATE_TEXT_START (sd); + PROFILE_PC_END (data) = STATE_TEXT_END (sd); + } + /* Compute the number of buckets if not specified. */ + if (PROFILE_PC_NR_BUCKETS (data) == 0) + { + if (PROFILE_PC_BUCKET_SIZE (data) == 0) + PROFILE_PC_NR_BUCKETS (data) = 16; + else + { + if (PROFILE_PC_END (data) == 0) + { + /* nr_buckets = (full-address-range / 2) / (bucket_size / 2) */ + PROFILE_PC_NR_BUCKETS (data) = + ((1 << (STATE_WATCHPOINTS (sd)->sizeof_pc) * (8 - 1)) + / (PROFILE_PC_BUCKET_SIZE (data) / 2)); + } + else + { + PROFILE_PC_NR_BUCKETS (data) = + ((PROFILE_PC_END (data) + - PROFILE_PC_START (data) + + PROFILE_PC_BUCKET_SIZE (data) - 1) + / PROFILE_PC_BUCKET_SIZE (data)); + } + } + } + /* Compute the bucket size if not specified. Ensure that it + is rounded up to the next power of two */ + if (PROFILE_PC_BUCKET_SIZE (data) == 0) + { + if (PROFILE_PC_END (data) == 0) + /* bucket_size = (full-address-range / 2) / (nr_buckets / 2) */ + bucket_size = ((1 << ((STATE_WATCHPOINTS (sd)->sizeof_pc * 8) - 1)) + / (PROFILE_PC_NR_BUCKETS (data) / 2)); + else + bucket_size = ((PROFILE_PC_END (data) + - PROFILE_PC_START (data) + + PROFILE_PC_NR_BUCKETS (data) - 1) + / PROFILE_PC_NR_BUCKETS (data)); + PROFILE_PC_SHIFT (data) = 0; + while (bucket_size < PROFILE_PC_BUCKET_SIZE (data)) + { + PROFILE_PC_SHIFT (data) += 1; + } + } + /* Align the end address with bucket size */ + if (PROFILE_PC_END (data) != 0) + PROFILE_PC_END (data) = (PROFILE_PC_START (data) + + (PROFILE_PC_BUCKET_SIZE (data) + * PROFILE_PC_NR_BUCKETS (data))); + /* create the relevant buffers */ + PROFILE_PC_COUNT (data) = + NZALLOC (unsigned, PROFILE_PC_NR_BUCKETS (data) + 1); + PROFILE_PC_EVENT (data) = + sim_events_schedule (sd, + PROFILE_PC_FREQ (data), + profile_pc_event, + cpu); + } + } + return SIM_RC_OK; +} + +static void +profile_print_pc (sim_cpu *cpu, int verbose) +{ + SIM_DESC sd = CPU_STATE (cpu); + PROFILE_DATA *profile = CPU_PROFILE_DATA (cpu); + char comma_buf[20]; + unsigned max_val; + unsigned total; + unsigned i; + + if (PROFILE_PC_COUNT (profile) == 0) + return; + + sim_io_printf (sd, "Program Counter Statistics:\n\n"); + + /* First pass over data computes various things. */ + max_val = 0; + total = 0; + for (i = 0; i <= PROFILE_PC_NR_BUCKETS (profile); ++i) + { + total += PROFILE_PC_COUNT (profile) [i]; + if (PROFILE_PC_COUNT (profile) [i] > max_val) + max_val = PROFILE_PC_COUNT (profile) [i]; + } + + sim_io_printf (sd, " Total samples: %s\n", + COMMAS (total)); + sim_io_printf (sd, " Granularity: %s bytes per bucket\n", + COMMAS (PROFILE_PC_BUCKET_SIZE (profile))); + sim_io_printf (sd, " Size: %s buckets\n", + COMMAS (PROFILE_PC_NR_BUCKETS (profile))); + sim_io_printf (sd, " Frequency: %s cycles per sample\n", + COMMAS (PROFILE_PC_FREQ (profile))); + + if (PROFILE_PC_END (profile) != 0) + sim_io_printf (sd, " Range: 0x%lx 0x%lx\n", + (long) PROFILE_PC_START (profile), + (long) PROFILE_PC_END (profile)); + + if (verbose && max_val != 0) + { + /* Now we can print the histogram. */ + sim_io_printf (sd, "\n"); + for (i = 0; i <= PROFILE_PC_NR_BUCKETS (profile); ++i) + { + if (PROFILE_PC_COUNT (profile) [i] != 0) + { + sim_io_printf (sd, " "); + if (i == PROFILE_PC_NR_BUCKETS (profile)) + sim_io_printf (sd, "%10s:", "overflow"); + else + sim_io_printf (sd, "0x%08lx:", + (long) (PROFILE_PC_START (profile) + + (i * PROFILE_PC_BUCKET_SIZE (profile)))); + sim_io_printf (sd, " %*s", + max_val < 10000 ? 5 : 10, + COMMAS (PROFILE_PC_COUNT (profile) [i])); + sim_io_printf (sd, " %4.1f", + (PROFILE_PC_COUNT (profile) [i] * 100.0) / total); + sim_io_printf (sd, ": "); + sim_profile_print_bar (sd, PROFILE_HISTOGRAM_WIDTH, + PROFILE_PC_COUNT (profile) [i], + max_val); + sim_io_printf (sd, "\n"); + } + } + } + + /* dump the histogram to the file "gmon.out" using BSD's gprof file + format */ + /* Since a profile data file is in the native format of the host on + which the profile is being, endian issues are not considered in + the code below. */ + /* FIXME: Is this the best place for this code? */ + { + FILE *pf = fopen ("gmon.out", "wb"); + + if (pf == NULL) + sim_io_eprintf (sd, "Failed to open \"gmon.out\" profile file\n"); + else + { + int ok; + /* FIXME: what if the target has a 64 bit PC? */ + unsigned32 header[3]; + unsigned loop; + if (PROFILE_PC_END (profile) != 0) + { + header[0] = PROFILE_PC_START (profile); + header[1] = PROFILE_PC_END (profile); + } + else + { + header[0] = 0; + header[1] = 0; + } + /* size of sample buffer (+ header) */ + header[2] = PROFILE_PC_NR_BUCKETS (profile) * 2 + sizeof (header); + ok = fwrite (&header, sizeof (header), 1, pf); + for (loop = 0; + ok && (loop < PROFILE_PC_NR_BUCKETS (profile)); + loop++) + { + signed16 sample; + if (PROFILE_PC_COUNT (profile) [loop] >= 0xffff) + sample = 0xffff; + else + sample = PROFILE_PC_COUNT (profile) [loop]; + ok = fwrite (&sample, sizeof (sample), 1, pf); + } + if (ok == 0) + sim_io_eprintf (sd, "Failed to write to \"gmon.out\" profile file\n"); + fclose(pf); + } + } + + sim_io_printf (sd, "\n"); +} + +#endif + +/* Summary printing support. */ + +#if WITH_PROFILE_INSN_P + +static SIM_RC +profile_insn_init (SIM_DESC sd) +{ + int c; + + for (c = 0; c < MAX_NR_PROCESSORS; ++c) + { + sim_cpu *cpu = STATE_CPU (sd, c); + + if (CPU_MAX_INSNS (cpu) > 0) + PROFILE_INSN_COUNT (CPU_PROFILE_DATA (cpu)) = NZALLOC (unsigned int, CPU_MAX_INSNS (cpu)); + } + + return SIM_RC_OK; +} + +static void +profile_print_insn (sim_cpu *cpu, int verbose) +{ + unsigned int i, n, total, max_val, max_name_len; + SIM_DESC sd = CPU_STATE (cpu); + PROFILE_DATA *data = CPU_PROFILE_DATA (cpu); + char comma_buf[20]; + + /* If MAX_INSNS not set, insn profiling isn't supported. */ + if (CPU_MAX_INSNS (cpu) == 0) + return; + + sim_io_printf (sd, "Instruction Statistics"); +#ifdef SIM_HAVE_ADDR_RANGE + if (PROFILE_RANGE (data)->ranges) + sim_io_printf (sd, " (for selected address range(s))"); +#endif + sim_io_printf (sd, "\n\n"); + + /* First pass over data computes various things. */ + max_val = 0; + total = 0; + max_name_len = 0; + for (i = 0; i < CPU_MAX_INSNS (cpu); ++i) + { + const char *name = (*CPU_INSN_NAME (cpu)) (cpu, i); + + if (name == NULL) + continue; + total += PROFILE_INSN_COUNT (data) [i]; + if (PROFILE_INSN_COUNT (data) [i] > max_val) + max_val = PROFILE_INSN_COUNT (data) [i]; + n = strlen (name); + if (n > max_name_len) + max_name_len = n; + } + /* set the total insn count, in case client is being lazy */ + if (! PROFILE_TOTAL_INSN_COUNT (data)) + PROFILE_TOTAL_INSN_COUNT (data) = total; + + sim_io_printf (sd, " Total: %s insns\n", COMMAS (total)); + + if (verbose && max_val != 0) + { + /* Now we can print the histogram. */ + sim_io_printf (sd, "\n"); + for (i = 0; i < CPU_MAX_INSNS (cpu); ++i) + { + const char *name = (*CPU_INSN_NAME (cpu)) (cpu, i); + + if (name == NULL) + continue; + if (PROFILE_INSN_COUNT (data) [i] != 0) + { + sim_io_printf (sd, " %*s: %*s: ", + max_name_len, name, + max_val < 10000 ? 5 : 10, + COMMAS (PROFILE_INSN_COUNT (data) [i])); + sim_profile_print_bar (sd, PROFILE_HISTOGRAM_WIDTH, + PROFILE_INSN_COUNT (data) [i], + max_val); + sim_io_printf (sd, "\n"); + } + } + } + + sim_io_printf (sd, "\n"); +} + +#endif + +#if WITH_PROFILE_MEMORY_P + +static void +profile_print_memory (sim_cpu *cpu, int verbose) +{ + unsigned int i, n; + unsigned int total_read, total_write; + unsigned int max_val, max_name_len; + /* FIXME: Need to add smp support. */ + SIM_DESC sd = CPU_STATE (cpu); + PROFILE_DATA *data = CPU_PROFILE_DATA (cpu); + char comma_buf[20]; + + sim_io_printf (sd, "Memory Access Statistics\n\n"); + + /* First pass over data computes various things. */ + max_val = total_read = total_write = max_name_len = 0; + for (i = 0; i < MODE_TARGET_MAX; ++i) + { + total_read += PROFILE_READ_COUNT (data) [i]; + total_write += PROFILE_WRITE_COUNT (data) [i]; + if (PROFILE_READ_COUNT (data) [i] > max_val) + max_val = PROFILE_READ_COUNT (data) [i]; + if (PROFILE_WRITE_COUNT (data) [i] > max_val) + max_val = PROFILE_WRITE_COUNT (data) [i]; + n = strlen (MODE_NAME (i)); + if (n > max_name_len) + max_name_len = n; + } + + /* One could use PROFILE_LABEL_WIDTH here. I chose not to. */ + sim_io_printf (sd, " Total read: %s accesses\n", + COMMAS (total_read)); + sim_io_printf (sd, " Total write: %s accesses\n", + COMMAS (total_write)); + + if (verbose && max_val != 0) + { + /* FIXME: Need to separate instruction fetches from data fetches + as the former swamps the latter. */ + /* Now we can print the histogram. */ + sim_io_printf (sd, "\n"); + for (i = 0; i < MODE_TARGET_MAX; ++i) + { + if (PROFILE_READ_COUNT (data) [i] != 0) + { + sim_io_printf (sd, " %*s read: %*s: ", + max_name_len, MODE_NAME (i), + max_val < 10000 ? 5 : 10, + COMMAS (PROFILE_READ_COUNT (data) [i])); + sim_profile_print_bar (sd, PROFILE_HISTOGRAM_WIDTH, + PROFILE_READ_COUNT (data) [i], + max_val); + sim_io_printf (sd, "\n"); + } + if (PROFILE_WRITE_COUNT (data) [i] != 0) + { + sim_io_printf (sd, " %*s write: %*s: ", + max_name_len, MODE_NAME (i), + max_val < 10000 ? 5 : 10, + COMMAS (PROFILE_WRITE_COUNT (data) [i])); + sim_profile_print_bar (sd, PROFILE_HISTOGRAM_WIDTH, + PROFILE_WRITE_COUNT (data) [i], + max_val); + sim_io_printf (sd, "\n"); + } + } + } + + sim_io_printf (sd, "\n"); +} + +#endif + +#if WITH_PROFILE_CORE_P + +static void +profile_print_core (sim_cpu *cpu, int verbose) +{ + unsigned int total; + unsigned int max_val; + /* FIXME: Need to add smp support. */ + SIM_DESC sd = CPU_STATE (cpu); + PROFILE_DATA *data = CPU_PROFILE_DATA (cpu); + char comma_buf[20]; + + sim_io_printf (sd, "CORE Statistics\n\n"); + + /* First pass over data computes various things. */ + { + unsigned map; + total = 0; + max_val = 0; + for (map = 0; map < nr_maps; map++) + { + total += PROFILE_CORE_COUNT (data) [map]; + if (PROFILE_CORE_COUNT (data) [map] > max_val) + max_val = PROFILE_CORE_COUNT (data) [map]; + } + } + + /* One could use PROFILE_LABEL_WIDTH here. I chose not to. */ + sim_io_printf (sd, " Total: %s accesses\n", + COMMAS (total)); + + if (verbose && max_val != 0) + { + unsigned map; + /* Now we can print the histogram. */ + sim_io_printf (sd, "\n"); + for (map = 0; map < nr_maps; map++) + { + if (PROFILE_CORE_COUNT (data) [map] != 0) + { + sim_io_printf (sd, "%10s:", map_to_str (map)); + sim_io_printf (sd, "%*s: ", + max_val < 10000 ? 5 : 10, + COMMAS (PROFILE_CORE_COUNT (data) [map])); + sim_profile_print_bar (sd, PROFILE_HISTOGRAM_WIDTH, + PROFILE_CORE_COUNT (data) [map], + max_val); + sim_io_printf (sd, "\n"); + } + } + } + + sim_io_printf (sd, "\n"); +} + +#endif + +#if WITH_PROFILE_MODEL_P + +static void +profile_print_model (sim_cpu *cpu, int verbose) +{ + SIM_DESC sd = CPU_STATE (cpu); + PROFILE_DATA *data = CPU_PROFILE_DATA (cpu); + unsigned long cti_stall_cycles = PROFILE_MODEL_CTI_STALL_CYCLES (data); + unsigned long load_stall_cycles = PROFILE_MODEL_LOAD_STALL_CYCLES (data); + unsigned long total_cycles = PROFILE_MODEL_TOTAL_CYCLES (data); + char comma_buf[20]; + + sim_io_printf (sd, "Model %s Timing Information", + MODEL_NAME (CPU_MODEL (cpu))); +#ifdef SIM_HAVE_ADDR_RANGE + if (PROFILE_RANGE (data)->ranges) + sim_io_printf (sd, " (for selected address range(s))"); +#endif + sim_io_printf (sd, "\n\n"); + sim_io_printf (sd, " %-*s %s\n", + PROFILE_LABEL_WIDTH, "Taken branches:", + COMMAS (PROFILE_MODEL_TAKEN_COUNT (data))); + sim_io_printf (sd, " %-*s %s\n", + PROFILE_LABEL_WIDTH, "Untaken branches:", + COMMAS (PROFILE_MODEL_UNTAKEN_COUNT (data))); + sim_io_printf (sd, " %-*s %s\n", + PROFILE_LABEL_WIDTH, "Cycles stalled due to branches:", + COMMAS (cti_stall_cycles)); + sim_io_printf (sd, " %-*s %s\n", + PROFILE_LABEL_WIDTH, "Cycles stalled due to loads:", + COMMAS (load_stall_cycles)); + sim_io_printf (sd, " %-*s %s\n", + PROFILE_LABEL_WIDTH, "Total cycles (*approximate*):", + COMMAS (total_cycles)); + sim_io_printf (sd, "\n"); +} + +#endif + +void +sim_profile_print_bar (SIM_DESC sd, unsigned int width, + unsigned int val, unsigned int max_val) +{ + unsigned int i, count; + + count = ((double) val / (double) max_val) * (double) width; + + for (i = 0; i < count; ++i) + sim_io_printf (sd, "*"); +} + +/* Print the simulator's execution speed for CPU. */ + +static void +profile_print_speed (sim_cpu *cpu) +{ + SIM_DESC sd = CPU_STATE (cpu); + PROFILE_DATA *data = CPU_PROFILE_DATA (cpu); + unsigned long milliseconds = sim_events_elapsed_time (sd); + unsigned long total = PROFILE_TOTAL_INSN_COUNT (data); + char comma_buf[20]; + + sim_io_printf (sd, "Simulator Execution Speed\n\n"); + + if (total != 0) + sim_io_printf (sd, " Total instructions: %s\n", COMMAS (total)); + + if (milliseconds < 1000) + sim_io_printf (sd, " Total execution time: < 1 second\n\n"); + else + { + /* The printing of the time rounded to 2 decimal places makes the speed + calculation seem incorrect [even though it is correct]. So round + MILLISECONDS first. This can marginally affect the result, but it's + better that the user not perceive there's a math error. */ + double secs = (double) milliseconds / 1000; + secs = ((double) (unsigned long) (secs * 100 + .5)) / 100; + sim_io_printf (sd, " Total execution time: %.2f seconds\n", secs); + /* Don't confuse things with data that isn't useful. + If we ran for less than 2 seconds, only use the data if we + executed more than 100,000 insns. */ + if (secs >= 2 || total >= 100000) + sim_io_printf (sd, " Simulator speed: %s insns/second\n\n", + COMMAS ((unsigned long) ((double) total / secs))); + } +} + +/* Print selected address ranges. */ + +static void +profile_print_addr_ranges (sim_cpu *cpu) +{ + ADDR_SUBRANGE *asr = PROFILE_RANGE (CPU_PROFILE_DATA (cpu))->ranges; + SIM_DESC sd = CPU_STATE (cpu); + + if (asr) + { + sim_io_printf (sd, "Selected address ranges\n\n"); + while (asr != NULL) + { + sim_io_printf (sd, " 0x%lx - 0x%lx\n", + (long) asr->start, (long) asr->end); + asr = asr->next; + } + sim_io_printf (sd, "\n"); + } +} + +/* Top level function to print all summary profile information. + It is [currently] intended that all such data is printed by this function. + I'd rather keep it all in one place for now. To that end, MISC_CPU and + MISC are callbacks used to print any miscellaneous data. + + One might want to add a user option that allows printing by type or by cpu + (i.e. print all insn data for each cpu first, or print data cpu by cpu). + This may be a case of featuritis so it's currently left out. + + Note that results are indented two spaces to distinguish them from + section titles. */ + +static void +profile_info (SIM_DESC sd, int verbose) +{ + int i,c; + int print_title_p = 0; + + /* Only print the title if some data has been collected. */ + /* ??? Why don't we just exit if no data collected? */ + /* FIXME: If the number of processors can be selected on the command line, + then MAX_NR_PROCESSORS will need to take an argument of `sd'. */ + + for (c = 0; c < MAX_NR_PROCESSORS; ++c) + { + sim_cpu *cpu = STATE_CPU (sd, c); + PROFILE_DATA *data = CPU_PROFILE_DATA (cpu); + + for (i = 0; i < MAX_PROFILE_VALUES; ++i) + if (PROFILE_FLAGS (data) [i]) + print_title_p = 1; + /* One could break out early if print_title_p is set. */ + } + if (print_title_p) + sim_io_printf (sd, "Summary profiling results:\n\n"); + + /* Loop, cpu by cpu, printing results. */ + + for (c = 0; c < MAX_NR_PROCESSORS; ++c) + { + sim_cpu *cpu = STATE_CPU (sd, c); + PROFILE_DATA *data = CPU_PROFILE_DATA (cpu); + + if (MAX_NR_PROCESSORS > 1 + && (0 +#if WITH_PROFILE_INSN_P + || PROFILE_FLAGS (data) [PROFILE_INSN_IDX] +#endif +#if WITH_PROFILE_MEMORY_P + || PROFILE_FLAGS (data) [PROFILE_MEMORY_IDX] +#endif +#if WITH_PROFILE_CORE_P + || PROFILE_FLAGS (data) [PROFILE_CORE_IDX] +#endif +#if WITH_PROFILE_MODEL_P + || PROFILE_FLAGS (data) [PROFILE_MODEL_IDX] +#endif +#if WITH_PROFILE_SCACHE_P && WITH_SCACHE + || PROFILE_FLAGS (data) [PROFILE_SCACHE_IDX] +#endif +#if WITH_PROFILE_PC_P + || PROFILE_FLAGS (data) [PROFILE_PC_IDX] +#endif + )) + { + sim_io_printf (sd, "CPU %d\n\n", c); + } + +#ifdef SIM_HAVE_ADDR_RANGE + if (print_title_p + && (PROFILE_INSN_P (cpu) + || PROFILE_MODEL_P (cpu))) + profile_print_addr_ranges (cpu); +#endif + +#if WITH_PROFILE_INSN_P + if (PROFILE_FLAGS (data) [PROFILE_INSN_IDX]) + profile_print_insn (cpu, verbose); +#endif + +#if WITH_PROFILE_MEMORY_P + if (PROFILE_FLAGS (data) [PROFILE_MEMORY_IDX]) + profile_print_memory (cpu, verbose); +#endif + +#if WITH_PROFILE_CORE_P + if (PROFILE_FLAGS (data) [PROFILE_CORE_IDX]) + profile_print_core (cpu, verbose); +#endif + +#if WITH_PROFILE_MODEL_P + if (PROFILE_FLAGS (data) [PROFILE_MODEL_IDX]) + profile_print_model (cpu, verbose); +#endif + +#if WITH_PROFILE_SCACHE_P && WITH_SCACHE + if (PROFILE_FLAGS (data) [PROFILE_SCACHE_IDX]) + scache_print_profile (cpu, verbose); +#endif + +#if WITH_PROFILE_PC_P + if (PROFILE_FLAGS (data) [PROFILE_PC_IDX]) + profile_print_pc (cpu, verbose); +#endif + + /* Print cpu-specific data before the execution speed. */ + if (PROFILE_INFO_CPU_CALLBACK (data) != NULL) + PROFILE_INFO_CPU_CALLBACK (data) (cpu, verbose); + + /* Always try to print execution time and speed. */ + if (verbose + || PROFILE_FLAGS (data) [PROFILE_INSN_IDX]) + profile_print_speed (cpu); + } + + /* Finally print non-cpu specific miscellaneous data. */ + if (STATE_PROFILE_INFO_CALLBACK (sd)) + STATE_PROFILE_INFO_CALLBACK (sd) (sd, verbose); + +} + +/* Install profiling support in the simulator. */ + +SIM_RC +profile_install (SIM_DESC sd) +{ + int i; + + SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); + sim_add_option_table (sd, NULL, profile_options); + for (i = 0; i < MAX_NR_PROCESSORS; ++i) + memset (CPU_PROFILE_DATA (STATE_CPU (sd, i)), 0, + sizeof (* CPU_PROFILE_DATA (STATE_CPU (sd, i)))); +#if WITH_PROFILE_INSN_P + sim_module_add_init_fn (sd, profile_insn_init); +#endif +#if WITH_PROFILE_PC_P + sim_module_add_uninstall_fn (sd, profile_pc_uninstall); + sim_module_add_init_fn (sd, profile_pc_init); +#endif + sim_module_add_init_fn (sd, profile_init); + sim_module_add_uninstall_fn (sd, profile_uninstall); + sim_module_add_info_fn (sd, profile_info); + return SIM_RC_OK; +} + +static SIM_RC +profile_init (SIM_DESC sd) +{ +#ifdef SIM_HAVE_ADDR_RANGE + /* Check if a range has been specified without specifying what to + collect. */ + { + int i; + + for (i = 0; i < MAX_NR_PROCESSORS; ++i) + { + sim_cpu *cpu = STATE_CPU (sd, i); + + if (ADDR_RANGE_RANGES (PROFILE_RANGE (CPU_PROFILE_DATA (cpu))) + && ! (PROFILE_INSN_P (cpu) + || PROFILE_MODEL_P (cpu))) + { + sim_io_eprintf_cpu (cpu, "Profiling address range specified without --profile-insn or --profile-model.\n"); + sim_io_eprintf_cpu (cpu, "Address range ignored.\n"); + sim_addr_range_delete (PROFILE_RANGE (CPU_PROFILE_DATA (cpu)), + 0, ~ (address_word) 0); + } + } + } +#endif + + return SIM_RC_OK; +} + +static void +profile_uninstall (SIM_DESC sd) +{ + int i,j; + + for (i = 0; i < MAX_NR_PROCESSORS; ++i) + { + sim_cpu *cpu = STATE_CPU (sd, i); + PROFILE_DATA *data = CPU_PROFILE_DATA (cpu); + + if (PROFILE_FILE (data) != NULL) + { + /* If output from different cpus is going to the same file, + avoid closing the file twice. */ + for (j = 0; j < i; ++j) + if (PROFILE_FILE (CPU_PROFILE_DATA (STATE_CPU (sd, j))) + == PROFILE_FILE (data)) + break; + if (i == j) + fclose (PROFILE_FILE (data)); + } + + if (PROFILE_INSN_COUNT (data) != NULL) + zfree (PROFILE_INSN_COUNT (data)); + } +} diff --git a/sim/common/sim-profile.h b/sim/common/sim-profile.h new file mode 100644 index 00000000000..8f8d95f43a1 --- /dev/null +++ b/sim/common/sim-profile.h @@ -0,0 +1,289 @@ +/* Profile header for simulators using common framework. + Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. + Contributed by Cygnus Support. + +This file is part of GDB, the GNU debugger. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef SIM_PROFILE_H +#define SIM_PROFILE_H + +#ifndef WITH_PROFILE +Error, WITH_PROFILE not defined. +#endif + +/* Standard profilable entities. */ + +enum { + /* Profile insn usage. */ + PROFILE_INSN_IDX = 1, + + /* Profile memory usage. */ + PROFILE_MEMORY_IDX, + + /* Profile the cpu model (cycles, etc.). */ + PROFILE_MODEL_IDX, + + /* Profile the simulator's execution cache. */ + PROFILE_SCACHE_IDX, + + /* Profile the PC. */ + PROFILE_PC_IDX, + + /* Profile sim-core.c stuff. */ + /* ??? The difference between this and PROFILE_MEMORY_IDX is ... ? */ + PROFILE_CORE_IDX, + + /* Simulator specific profile bits begin here. */ + PROFILE_NEXT_IDX +}; + +/* Maximum number of profilable entities. */ +#ifndef MAX_PROFILE_VALUES +#define MAX_PROFILE_VALUES 32 +#endif + +/* The -p option only prints useful values. It's easy to type and shouldn't + splat on the screen everything under the sun making nothing easy to + find. */ +#define PROFILE_USEFUL_MASK \ +((1 << PROFILE_INSN_IDX) \ + | (1 << PROFILE_MEMORY_IDX) \ + | (1 << PROFILE_MODEL_IDX) \ + | (1 << PROFILE_CORE_IDX)) + +/* Utility to parse a --profile- option. */ +/* ??? On the one hand all calls could be confined to sim-profile.c, but + on the other hand keeping a module's profiling option with the module's + source is cleaner. */ + +SIM_RC sim_profile_set_option (SIM_DESC sd_, const char *name_, int idx_, + const char *arg_); + +/* Masks so WITH_PROFILE can have symbolic values. + The case choice here is on purpose. The lowercase parts are args to + --with-profile. */ +#define PROFILE_insn (1 << PROFILE_INSN_IDX) +#define PROFILE_memory (1 << PROFILE_MEMORY_IDX) +#define PROFILE_model (1 << PROFILE_MODEL_IDX) +#define PROFILE_scache (1 << PROFILE_SCACHE_IDX) +#define PROFILE_pc (1 << PROFILE_PC_IDX) +#define PROFILE_core (1 << PROFILE_CORE_IDX) + +/* Preprocessor macros to simplify tests of WITH_PROFILE. */ +#define WITH_PROFILE_INSN_P (WITH_PROFILE & PROFILE_insn) +#define WITH_PROFILE_MEMORY_P (WITH_PROFILE & PROFILE_memory) +#define WITH_PROFILE_MODEL_P (WITH_PROFILE & PROFILE_model) +#define WITH_PROFILE_SCACHE_P (WITH_PROFILE & PROFILE_scache) +#define WITH_PROFILE_PC_P (WITH_PROFILE & PROFILE_pc) +#define WITH_PROFILE_CORE_P (WITH_PROFILE & PROFILE_core) + +/* If MAX_TARGET_MODES isn't defined, we can't do memory profiling. + ??? It is intended that this is a temporary occurence. Normally + MAX_TARGET_MODES is defined. */ +#ifndef MAX_TARGET_MODES +#undef WITH_PROFILE_MEMORY_P +#define WITH_PROFILE_MEMORY_P 0 +#endif + +/* Only build MODEL code when the target simulator has support for it */ +#ifndef SIM_HAVE_MODEL +#undef WITH_PROFILE_MODEL_P +#define WITH_PROFILE_MODEL_P 0 +#endif + +/* Profiling install handler. */ +MODULE_INSTALL_FN profile_install; + +/* Output format macros. */ +#ifndef PROFILE_HISTOGRAM_WIDTH +#define PROFILE_HISTOGRAM_WIDTH 40 +#endif +#ifndef PROFILE_LABEL_WIDTH +#define PROFILE_LABEL_WIDTH 32 +#endif + +/* Callbacks for internal profile_info. + The callbacks may be NULL meaning there isn't one. + Note that results are indented two spaces to distinguish them from + section titles. + If non-NULL, PROFILE_CALLBACK is called to print extra non-cpu related data. + If non-NULL, PROFILE_CPU_CALLBACK is called to print extra cpu related data. + */ + +typedef void (PROFILE_INFO_CALLBACK_FN) (SIM_DESC, int); +struct _sim_cpu; /* forward reference */ +typedef void (PROFILE_INFO_CPU_CALLBACK_FN) (struct _sim_cpu *cpu, int verbose); + + +/* Struct containing most profiling data. + It doesn't contain all profiling data because for example scache data + is kept with the rest of scache support. */ + +typedef struct { + /* Global summary of all the current profiling options. */ + char profile_any_p; + + /* Boolean array of specified profiling flags. */ + char profile_flags[MAX_PROFILE_VALUES]; +#define PROFILE_FLAGS(p) ((p)->profile_flags) + + /* The total insn count is tracked separately. + It is always computed, regardless of insn profiling. */ + unsigned long total_insn_count; +#define PROFILE_TOTAL_INSN_COUNT(p) ((p)->total_insn_count) + +#if WITH_PROFILE_INSN_P + unsigned int *insn_count; +#define PROFILE_INSN_COUNT(p) ((p)->insn_count) +#endif + +#if WITH_PROFILE_MEMORY_P + unsigned int read_count[MAX_TARGET_MODES]; +#define PROFILE_READ_COUNT(p) ((p)->read_count) + unsigned int write_count[MAX_TARGET_MODES]; +#define PROFILE_WRITE_COUNT(p) ((p)->write_count) +#endif + +#if WITH_PROFILE_CORE_P + /* Count read/write/exec accesses separatly. */ + unsigned int core_count[nr_maps]; +#define PROFILE_CORE_COUNT(p) ((p)->core_count) +#endif + +#if WITH_PROFILE_MODEL_P + /* ??? Quick hack until more elaborate scheme is finished. */ + /* Total cycle count, including stalls. */ + unsigned long total_cycles; +#define PROFILE_MODEL_TOTAL_CYCLES(p) ((p)->total_cycles) + /* Stalls due to branches. */ + unsigned long cti_stall_cycles; +#define PROFILE_MODEL_CTI_STALL_CYCLES(p) ((p)->cti_stall_cycles) + unsigned long load_stall_cycles; +#define PROFILE_MODEL_LOAD_STALL_CYCLES(p) ((p)->load_stall_cycles) + /* Number of cycles the current instruction took. */ + unsigned long cur_insn_cycles; +#define PROFILE_MODEL_CUR_INSN_CYCLES(p) ((p)->cur_insn_cycles) + + /* Taken and not-taken branches (and other cti's). */ + unsigned long taken_count, untaken_count; +#define PROFILE_MODEL_TAKEN_COUNT(p) ((p)->taken_count) +#define PROFILE_MODEL_UNTAKEN_COUNT(p) ((p)->untaken_count) +#endif + +#if WITH_PROFILE_PC_P + /* PC profiling attempts to determine function usage by sampling the PC + every so many instructions. */ + unsigned int profile_pc_freq; +#define PROFILE_PC_FREQ(p) ((p)->profile_pc_freq) + unsigned int profile_pc_nr_buckets; +#define PROFILE_PC_NR_BUCKETS(p) ((p)->profile_pc_nr_buckets) + address_word profile_pc_start; +#define PROFILE_PC_START(p) ((p)->profile_pc_start) + address_word profile_pc_end; +#define PROFILE_PC_END(p) ((p)->profile_pc_end) + unsigned profile_pc_shift; +#define PROFILE_PC_SHIFT(p) ((p)->profile_pc_shift) +#define PROFILE_PC_BUCKET_SIZE(p) (PROFILE_PC_SHIFT (p) ? (1 << PROFILE_PC_SHIFT (p)) : 0) + unsigned *profile_pc_count; +#define PROFILE_PC_COUNT(p) ((p)->profile_pc_count) + sim_event *profile_pc_event; +#define PROFILE_PC_EVENT(p) ((p)->profile_pc_event) +#endif + + /* Profile output goes to this or stderr if NULL. + We can't store `stderr' here as stderr goes through a callback. */ + FILE *profile_file; +#define PROFILE_FILE(p) ((p)->profile_file) + + /* When reporting a profile summary, hook to include per-processor + target specific profile information */ + PROFILE_INFO_CPU_CALLBACK_FN *info_cpu_callback; +#define PROFILE_INFO_CPU_CALLBACK(p) ((p)->info_cpu_callback) + + /* When reporting a profile summary, hook to include common target + specific profile information */ + PROFILE_INFO_CALLBACK_FN *info_callback; +#define STATE_PROFILE_INFO_CALLBACK(sd) \ +(CPU_PROFILE_DATA (STATE_CPU (sd, 0))->info_callback) + + /* Profile range. + ??? Not all cpu's support this. */ + ADDR_RANGE range; +#define PROFILE_RANGE(p) (& (p)->range) +} PROFILE_DATA; + +/* Predicates. */ + +#define CPU_PROFILE_FLAGS(cpu) PROFILE_FLAGS (CPU_PROFILE_DATA (cpu)) + +/* Return non-zero if tracing of IDX is enabled for CPU. */ +#define PROFILE_P(cpu,idx) \ +((WITH_PROFILE & (1 << (idx))) != 0 \ + && CPU_PROFILE_FLAGS (cpu)[idx] != 0) + +/* Non-zero if --profile- was specified for CPU. */ +#define PROFILE_ANY_P(cpu) ((WITH_PROFILE) && (CPU_PROFILE_DATA (cpu)->profile_any_p)) +#define PROFILE_INSN_P(cpu) PROFILE_P (cpu, PROFILE_INSN_IDX) +#define PROFILE_MEMORY_P(cpu) PROFILE_P (cpu, PROFILE_MEMORY_IDX) +#define PROFILE_MODEL_P(cpu) PROFILE_P (cpu, PROFILE_MODEL_IDX) +#define PROFILE_SCACHE_P(cpu) PROFILE_P (cpu, PROFILE_SCACHE_IDX) +#define PROFILE_PC_P(cpu) PROFILE_P (cpu, PROFILE_PC_IDX) +#define PROFILE_CORE_P(cpu) PROFILE_P (cpu, PROFILE_CORE_IDX) + +/* Usage macros. */ + +#if WITH_PROFILE_INSN_P +#define PROFILE_COUNT_INSN(cpu, pc, insn_num) \ +do { \ + if (PROFILE_INSN_P (cpu)) \ + ++ PROFILE_INSN_COUNT (CPU_PROFILE_DATA (cpu)) [insn_num]; \ +} while (0) +#else +#define PROFILE_COUNT_INSN(cpu, pc, insn_num) +#endif /* ! insn */ + +#if WITH_PROFILE_MEMORY_P +#define PROFILE_COUNT_READ(cpu, addr, mode_num) \ +do { \ + if (PROFILE_MEMORY_P (cpu)) \ + ++ PROFILE_READ_COUNT (CPU_PROFILE_DATA (cpu)) [mode_num]; \ +} while (0) +#define PROFILE_COUNT_WRITE(cpu, addr, mode_num) \ +do { \ + if (PROFILE_MEMORY_P (cpu)) \ + ++ PROFILE_WRITE_COUNT (CPU_PROFILE_DATA (cpu)) [mode_num]; \ +} while (0) +#else +#define PROFILE_COUNT_READ(cpu, addr, mode_num) +#define PROFILE_COUNT_WRITE(cpu, addr, mode_num) +#endif /* ! memory */ + +#if WITH_PROFILE_CORE_P +#define PROFILE_COUNT_CORE(cpu, addr, size, map) \ +do { \ + if (PROFILE_CORE_P (cpu)) \ + PROFILE_CORE_COUNT (CPU_PROFILE_DATA (cpu)) [map] += 1; \ +} while (0) +#else +#define PROFILE_COUNT_CORE(cpu, addr, size, map) +#endif /* ! core */ + +/* Misc. utilities. */ + +extern void sim_profile_print_bar (SIM_DESC, unsigned int, unsigned int, unsigned int); + +#endif /* SIM_PROFILE_H */ diff --git a/sim/common/sim-reason.c b/sim/common/sim-reason.c new file mode 100644 index 00000000000..b540df32f6e --- /dev/null +++ b/sim/common/sim-reason.c @@ -0,0 +1,57 @@ +/* Generic simulator stop_reason. + Copyright (C) 1997 Free Software Foundation, Inc. + Contributed by Cygnus Support. + +This file is part of GDB, the GNU debugger. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "sim-main.h" +#include "sim-assert.h" + +/* Generic implementation of sim_stop_reason */ + +void +sim_stop_reason (SIM_DESC sd, enum sim_stop *reason, int *sigrc) +{ + sim_engine *engine = NULL; + SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); + engine = STATE_ENGINE (sd); + *reason = engine->reason; + switch (*reason) + { + case sim_exited : + *sigrc = engine->sigrc; + break; + case sim_signalled : + /* ??? See the comment below case `sim_signalled' in + gdb/remote-sim.c:gdbsim_wait. + ??? Consider the case of the target requesting that it + kill(2) itself with SIGNAL. That SIGNAL, being target + specific, will not correspond to either of the SIM_SIGNAL + enum nor the HOST_SIGNAL. A mapping from TARGET_SIGNAL to + HOST_SIGNAL is needed. */ + *sigrc = sim_signal_to_host (sd, engine->sigrc); + break; + case sim_stopped : + /* The gdb/simulator interface calls for us to return the host + version of the signal which gdb then converts into the + target's version. This is obviously a bit clumsy. */ + *sigrc = sim_signal_to_host (sd, engine->sigrc); + break; + default : + abort (); + } +} diff --git a/sim/common/sim-reg.c b/sim/common/sim-reg.c new file mode 100644 index 00000000000..3f3dc41cd47 --- /dev/null +++ b/sim/common/sim-reg.c @@ -0,0 +1,52 @@ +/* Generic register read/write. + Copyright (C) 1998 Free Software Foundation, Inc. + Contributed by Cygnus Solutions. + +This file is part of GDB, the GNU debugger. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "sim-main.h" +#include "sim-assert.h" + +/* Generic implementation of sim_fetch_register for simulators using + CPU_REG_FETCH. + The contents of BUF are in target byte order. */ +/* ??? Obviously the interface needs to be extended to handle multiple + cpus. */ + +int +sim_fetch_register (SIM_DESC sd, int rn, unsigned char *buf, int length) +{ + SIM_CPU *cpu = STATE_CPU (sd, 0); + + SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); + return (* CPU_REG_FETCH (cpu)) (cpu, rn, buf, length); +} + +/* Generic implementation of sim_fetch_register for simulators using + CPU_REG_FETCH. + The contents of BUF are in target byte order. */ +/* ??? Obviously the interface needs to be extended to handle multiple + cpus. */ + +int +sim_store_register (SIM_DESC sd, int rn, unsigned char *buf, int length) +{ + SIM_CPU *cpu = STATE_CPU (sd, 0); + + SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); + return (* CPU_REG_STORE (cpu)) (cpu, rn, buf, length); +} diff --git a/sim/common/sim-resume.c b/sim/common/sim-resume.c new file mode 100644 index 00000000000..09b475ec5c8 --- /dev/null +++ b/sim/common/sim-resume.c @@ -0,0 +1,85 @@ +/* Generic simulator resume. + Copyright (C) 1997 Free Software Foundation, Inc. + Contributed by Cygnus Support. + +This file is part of GDB, the GNU debugger. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "sim-main.h" +#include "sim-assert.h" + +/* Halt the simulator after just one instruction */ + +static void +has_stepped (SIM_DESC sd, + void *data) +{ + ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); + sim_engine_halt (sd, NULL, NULL, NULL_CIA, sim_stopped, SIM_SIGTRAP); +} + + +/* Generic resume - assumes the existance of sim_engine_run */ + +void +sim_resume (SIM_DESC sd, + int step, + int siggnal) +{ + sim_engine *engine = STATE_ENGINE (sd); + jmp_buf buf; + int jmpval; + + ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); + + /* we only want to be single stepping the simulator once */ + if (engine->stepper != NULL) + { + sim_events_deschedule (sd, engine->stepper); + engine->stepper = NULL; + } + if (step) + engine->stepper = sim_events_schedule (sd, 1, has_stepped, sd); + + sim_module_resume (sd); + + /* run/resume the simulator */ + engine->jmpbuf = &buf; + jmpval = setjmp (buf); + if (jmpval == sim_engine_start_jmpval + || jmpval == sim_engine_restart_jmpval) + { + int last_cpu_nr = sim_engine_last_cpu_nr (sd); + int next_cpu_nr = sim_engine_next_cpu_nr (sd); + int nr_cpus = sim_engine_nr_cpus (sd); + + sim_events_preprocess (sd, last_cpu_nr >= nr_cpus, next_cpu_nr >= nr_cpus); + if (next_cpu_nr >= nr_cpus) + next_cpu_nr = 0; + +#ifdef SIM_CPU_EXCEPTION_RESUME + { + sim_cpu* cpu = STATE_CPU (sd, next_cpu_nr); + SIM_CPU_EXCEPTION_RESUME(sd, cpu, siggnal); + } +#endif + + sim_engine_run (sd, next_cpu_nr, nr_cpus, siggnal); + } + engine->jmpbuf = NULL; + + sim_module_suspend (sd); +} diff --git a/sim/common/sim-run.c b/sim/common/sim-run.c new file mode 100644 index 00000000000..55f72909d82 --- /dev/null +++ b/sim/common/sim-run.c @@ -0,0 +1,51 @@ +/* Generic simulator run. + Copyright (C) 1997 Free Software Foundation, Inc. + Contributed by Cygnus Support. + +This file is part of GDB, the GNU debugger. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "sim-main.h" +#include "sim-assert.h" + +/* Generic implementation of sim_engine_run that works within the + sim_engine setjmp/longjmp framework. */ + +#define IMEM XCONCAT + +void +sim_engine_run (SIM_DESC sd, + int next_cpu_nr, /* ignore */ + int nr_cpus, /* ignore */ + int siggnal) /* ignore */ +{ + sim_cia cia; + sim_cpu *cpu; + SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); + cpu = STATE_CPU (sd, 0); + cia = CIA_GET (cpu); + while (1) + { + instruction_word insn = IMEM32 (cia); + cia = idecode_issue (sd, insn, cia); + /* process any events */ + if (sim_events_tick (sd)) + { + CIA_SET (cpu, cia); + sim_events_process (sd); + } + } +} diff --git a/sim/common/sim-signal.c b/sim/common/sim-signal.c new file mode 100644 index 00000000000..77709b17e7a --- /dev/null +++ b/sim/common/sim-signal.c @@ -0,0 +1,96 @@ +/* Simulator signal support + Copyright (C) 1997 Free Software Foundation, Inc. + Contributed by Cygnus Support + +This file is part of the GNU Simulators. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include +#include "sim-main.h" + +/* Convert SIM_SIGFOO to SIGFOO. + What to do when the host doesn't have SIGFOO is handled on a case by case + basis. Generally, in the case of passing a value back to gdb, we want gdb + to not think the process has died (so it can be debugged at the point of + failure). */ + +#ifdef _MSC_VER +#ifndef SIGTRAP +#define SIGTRAP 5 +#endif +#ifndef SIGBUS +#define SIGBUS 10 +#endif +#ifndef SIGQUIT +#define SIGQUIT 3 +#endif +#endif + +int +sim_signal_to_host (SIM_DESC sd, SIM_SIGNAL sig) +{ + switch (sig) + { + case SIM_SIGINT : + return SIGINT; + + case SIM_SIGABRT : + return SIGABRT; + + case SIM_SIGILL : +#ifdef SIGILL + return SIGILL; +#else + return SIGSEGV; +#endif + + case SIM_SIGTRAP : + return SIGTRAP; + + case SIM_SIGBUS : +#ifdef SIGBUS + return SIGBUS; +#else + return SIGSEGV; +#endif + + case SIM_SIGSEGV : + return SIGSEGV; + + case SIM_SIGXCPU : +#ifdef SIGXCPU + return SIGXCPU; +#endif + break; + + case SIM_SIGFPE: +#ifdef SIGXCPU + return SIGFPE; +#endif + break; + + case SIM_SIGNONE: + return 0; + break; + } + + sim_io_eprintf (sd, "sim_signal_to_host: unknown signal: %d\n", sig); +#ifdef SIGHUP + return SIGHUP; /* FIXME: Suggestions? */ +#else + return 1; +#endif +} diff --git a/sim/common/sim-signal.h b/sim/common/sim-signal.h new file mode 100644 index 00000000000..272e17dad05 --- /dev/null +++ b/sim/common/sim-signal.h @@ -0,0 +1,49 @@ +/* Simulator signal support + Copyright (C) 1997 Free Software Foundation, Inc. + Contributed by Cygnus Support + +This file is part of the GNU Simulators. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef SIM_SIGNAL_H +#define SIM_SIGNAL_H + +/* Signals we use. + This provides a layer between our values and host/target values. */ + +typedef enum { + SIM_SIGNONE = 64, + /* illegal insn */ + SIM_SIGILL, + /* breakpoint */ + SIM_SIGTRAP, + /* misaligned memory access */ + SIM_SIGBUS, + /* tried to read/write memory that's not readable/writable */ + SIM_SIGSEGV, + /* cpu limit exceeded */ + SIM_SIGXCPU, + /* simulation interrupted (sim_stop called) */ + SIM_SIGINT, + /* Floating point or integer divide */ + SIM_SIGFPE, + /* simulation aborted */ + SIM_SIGABRT +} SIM_SIGNAL; + +int sim_signal_to_host (SIM_DESC sd, SIM_SIGNAL); + +#endif /* SIM_SIGNAL_H */ diff --git a/sim/common/sim-stop.c b/sim/common/sim-stop.c new file mode 100644 index 00000000000..cde93151ed8 --- /dev/null +++ b/sim/common/sim-stop.c @@ -0,0 +1,43 @@ +/* Generic simulator stop. + Copyright (C) 1997 Free Software Foundation, Inc. + Contributed by Cygnus Support. + +This file is part of GDB, the GNU debugger. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "sim-main.h" +#include "sim-assert.h" + +/* Generic implementation of sim_stop. */ + +static void +control_c_simulation (SIM_DESC sd, + void *data) +{ + ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); + sim_engine_halt (sd, NULL, NULL, NULL_CIA, sim_stopped, SIM_SIGINT); +} + +int +sim_stop (SIM_DESC sd) +{ + ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); + sim_events_schedule_after_signal(sd, + 0 /*NOW*/, + control_c_simulation, + sd /*data*/); + return 1; +} diff --git a/sim/common/sim-trace.c b/sim/common/sim-trace.c new file mode 100644 index 00000000000..0fa2313f166 --- /dev/null +++ b/sim/common/sim-trace.c @@ -0,0 +1,1341 @@ +/* Simulator tracing/debugging support. + Copyright (C) 1997, 1998 Free Software Foundation, Inc. + Contributed by Cygnus Support. + +This file is part of GDB, the GNU debugger. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "sim-main.h" +#include "sim-io.h" +#include "sim-options.h" +#include "sim-fpu.h" + +#include "bfd.h" +#include "libiberty.h" + +#include "sim-assert.h" + +#ifdef HAVE_STRING_H +#include +#else +#ifdef HAVE_STRINGS_H +#include +#endif +#endif +#ifdef HAVE_STDLIB_H +#include +#endif + +#ifndef SIZE_PHASE +#define SIZE_PHASE 8 +#endif + +#ifndef SIZE_LOCATION +#define SIZE_LOCATION 20 +#endif + +#ifndef SIZE_PC +#define SIZE_PC 6 +#endif + +#ifndef SIZE_LINE_NUMBER +#define SIZE_LINE_NUMBER 4 +#endif + +static MODULE_INIT_FN trace_init; +static MODULE_UNINSTALL_FN trace_uninstall; + +static DECLARE_OPTION_HANDLER (trace_option_handler); + +enum { + OPTION_TRACE_INSN = OPTION_START, + OPTION_TRACE_DECODE, + OPTION_TRACE_EXTRACT, + OPTION_TRACE_LINENUM, + OPTION_TRACE_MEMORY, + OPTION_TRACE_MODEL, + OPTION_TRACE_ALU, + OPTION_TRACE_CORE, + OPTION_TRACE_EVENTS, + OPTION_TRACE_FPU, + OPTION_TRACE_BRANCH, + OPTION_TRACE_SEMANTICS, + OPTION_TRACE_RANGE, + OPTION_TRACE_FUNCTION, + OPTION_TRACE_DEBUG, + OPTION_TRACE_FILE +}; + +static const OPTION trace_options[] = +{ + /* This table is organized to group related instructions together. */ + { {"trace", optional_argument, NULL, 't'}, + 't', "on|off", "Trace useful things", + trace_option_handler }, + { {"trace-insn", optional_argument, NULL, OPTION_TRACE_INSN}, + '\0', "on|off", "Perform instruction tracing", + trace_option_handler }, + { {"trace-decode", optional_argument, NULL, OPTION_TRACE_DECODE}, + '\0', "on|off", "Trace instruction decoding", + trace_option_handler }, + { {"trace-extract", optional_argument, NULL, OPTION_TRACE_EXTRACT}, + '\0', "on|off", "Trace instruction extraction", + trace_option_handler }, + { {"trace-linenum", optional_argument, NULL, OPTION_TRACE_LINENUM}, + '\0', "on|off", "Perform line number tracing (implies --trace-insn)", + trace_option_handler }, + { {"trace-memory", optional_argument, NULL, OPTION_TRACE_MEMORY}, + '\0', "on|off", "Trace memory operations", + trace_option_handler }, + { {"trace-alu", optional_argument, NULL, OPTION_TRACE_ALU}, + '\0', "on|off", "Trace ALU operations", + trace_option_handler }, + { {"trace-fpu", optional_argument, NULL, OPTION_TRACE_FPU}, + '\0', "on|off", "Trace FPU operations", + trace_option_handler }, + { {"trace-branch", optional_argument, NULL, OPTION_TRACE_BRANCH}, + '\0', "on|off", "Trace branching", + trace_option_handler }, + { {"trace-semantics", optional_argument, NULL, OPTION_TRACE_SEMANTICS}, + '\0', "on|off", "Perform ALU, FPU, MEMORY, and BRANCH tracing", + trace_option_handler }, + { {"trace-model", optional_argument, NULL, OPTION_TRACE_MODEL}, + '\0', "on|off", "Include model performance data", + trace_option_handler }, + { {"trace-core", optional_argument, NULL, OPTION_TRACE_CORE}, + '\0', "on|off", "Trace core operations", + trace_option_handler }, + { {"trace-events", optional_argument, NULL, OPTION_TRACE_EVENTS}, + '\0', "on|off", "Trace events", + trace_option_handler }, +#ifdef SIM_HAVE_ADDR_RANGE + { {"trace-range", required_argument, NULL, OPTION_TRACE_RANGE}, + '\0', "START,END", "Specify range of addresses for instruction tracing", + trace_option_handler }, +#if 0 /*wip*/ + { {"trace-function", required_argument, NULL, OPTION_TRACE_FUNCTION}, + '\0', "FUNCTION", "Specify function to trace", + trace_option_handler }, +#endif +#endif + { {"trace-debug", optional_argument, NULL, OPTION_TRACE_DEBUG}, + '\0', "on|off", "Add information useful for debugging the simulator to the tracing output", + trace_option_handler }, + { {"trace-file", required_argument, NULL, OPTION_TRACE_FILE}, + '\0', "FILE NAME", "Specify tracing output file", + trace_option_handler }, + { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL } +}; + +/* Set/reset the trace options indicated in MASK. */ + +static SIM_RC +set_trace_option_mask (sd, name, mask, arg) + SIM_DESC sd; + const char *name; + int mask; + const char *arg; +{ + int trace_nr; + int cpu_nr; + int trace_val = 1; + + if (arg != NULL) + { + if (strcmp (arg, "yes") == 0 + || strcmp (arg, "on") == 0 + || strcmp (arg, "1") == 0) + trace_val = 1; + else if (strcmp (arg, "no") == 0 + || strcmp (arg, "off") == 0 + || strcmp (arg, "0") == 0) + trace_val = 0; + else + { + sim_io_eprintf (sd, "Argument `%s' for `--trace%s' invalid, one of `on', `off', `yes', `no' expected\n", arg, name); + return SIM_RC_FAIL; + } + } + + /* update applicable trace bits */ + for (trace_nr = 0; trace_nr < MAX_TRACE_VALUES; ++trace_nr) + { + if ((mask & (1 << trace_nr)) == 0) + continue; + + /* Set non-cpu specific values. */ + switch (trace_nr) + { + case TRACE_EVENTS_IDX: + STATE_EVENTS (sd)->trace = trace_val; + break; + case TRACE_DEBUG_IDX: + STATE_TRACE_FLAGS (sd)[trace_nr] = trace_val; + break; + } + + /* Set cpu values. */ + for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; cpu_nr++) + { + CPU_TRACE_FLAGS (STATE_CPU (sd, cpu_nr))[trace_nr] = trace_val; + } + } + + /* Re-compute the cpu trace summary. */ + if (trace_val) + { + for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; cpu_nr++) + CPU_TRACE_DATA (STATE_CPU (sd, cpu_nr))->trace_any_p = 1; + } + else + { + for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; cpu_nr++) + { + CPU_TRACE_DATA (STATE_CPU (sd, cpu_nr))->trace_any_p = 0; + for (trace_nr = 0; trace_nr < MAX_TRACE_VALUES; ++trace_nr) + { + if (CPU_TRACE_FLAGS (STATE_CPU (sd, cpu_nr))[trace_nr]) + { + CPU_TRACE_DATA (STATE_CPU (sd, cpu_nr))->trace_any_p = 1; + break; + } + } + } + } + + return SIM_RC_OK; +} + +/* Set one trace option based on its IDX value. */ + +static SIM_RC +set_trace_option (sd, name, idx, arg) + SIM_DESC sd; + const char *name; + int idx; + const char *arg; +{ + return set_trace_option_mask (sd, name, 1 << idx, arg); +} + + +static SIM_RC +trace_option_handler (SIM_DESC sd, sim_cpu *cpu, int opt, + char *arg, int is_command) +{ + int n; + int cpu_nr; + + switch (opt) + { + case 't' : + if (! WITH_TRACE) + sim_io_eprintf (sd, "Tracing not compiled in, `-t' ignored\n"); + else + return set_trace_option_mask (sd, "trace", TRACE_USEFUL_MASK, arg); + break; + + case OPTION_TRACE_INSN : + if (WITH_TRACE_INSN_P) + return set_trace_option (sd, "-insn", TRACE_INSN_IDX, arg); + else + sim_io_eprintf (sd, "Instruction tracing not compiled in, `--trace-insn' ignored\n"); + break; + + case OPTION_TRACE_DECODE : + if (WITH_TRACE_DECODE_P) + return set_trace_option (sd, "-decode", TRACE_DECODE_IDX, arg); + else + sim_io_eprintf (sd, "Decode tracing not compiled in, `--trace-decode' ignored\n"); + break; + + case OPTION_TRACE_EXTRACT : + if (WITH_TRACE_EXTRACT_P) + return set_trace_option (sd, "-extract", TRACE_EXTRACT_IDX, arg); + else + sim_io_eprintf (sd, "Extract tracing not compiled in, `--trace-extract' ignored\n"); + break; + + case OPTION_TRACE_LINENUM : + if (WITH_TRACE_LINENUM_P && WITH_TRACE_INSN_P) + { + if (set_trace_option (sd, "-linenum", TRACE_LINENUM_IDX, arg) != SIM_RC_OK + || set_trace_option (sd, "-linenum", TRACE_INSN_IDX, arg) != SIM_RC_OK) + return SIM_RC_FAIL; + } + else + sim_io_eprintf (sd, "Line number or instruction tracing not compiled in, `--trace-linenum' ignored\n"); + break; + + case OPTION_TRACE_MEMORY : + if (WITH_TRACE_MEMORY_P) + return set_trace_option (sd, "-memory", TRACE_MEMORY_IDX, arg); + else + sim_io_eprintf (sd, "Memory tracing not compiled in, `--trace-memory' ignored\n"); + break; + + case OPTION_TRACE_MODEL : + if (WITH_TRACE_MODEL_P) + return set_trace_option (sd, "-model", TRACE_MODEL_IDX, arg); + else + sim_io_eprintf (sd, "Model tracing not compiled in, `--trace-model' ignored\n"); + break; + + case OPTION_TRACE_ALU : + if (WITH_TRACE_ALU_P) + return set_trace_option (sd, "-alu", TRACE_ALU_IDX, arg); + else + sim_io_eprintf (sd, "ALU tracing not compiled in, `--trace-alu' ignored\n"); + break; + + case OPTION_TRACE_CORE : + if (WITH_TRACE_CORE_P) + return set_trace_option (sd, "-core", TRACE_CORE_IDX, arg); + else + sim_io_eprintf (sd, "CORE tracing not compiled in, `--trace-core' ignored\n"); + break; + + case OPTION_TRACE_EVENTS : + if (WITH_TRACE_EVENTS_P) + return set_trace_option (sd, "-events", TRACE_EVENTS_IDX, arg); + else + sim_io_eprintf (sd, "EVENTS tracing not compiled in, `--trace-events' ignored\n"); + break; + + case OPTION_TRACE_FPU : + if (WITH_TRACE_FPU_P) + return set_trace_option (sd, "-fpu", TRACE_FPU_IDX, arg); + else + sim_io_eprintf (sd, "FPU tracing not compiled in, `--trace-fpu' ignored\n"); + break; + + case OPTION_TRACE_BRANCH : + if (WITH_TRACE_BRANCH_P) + return set_trace_option (sd, "-branch", TRACE_BRANCH_IDX, arg); + else + sim_io_eprintf (sd, "Branch tracing not compiled in, `--trace-branch' ignored\n"); + break; + + case OPTION_TRACE_SEMANTICS : + if (WITH_TRACE_ALU_P + && WITH_TRACE_FPU_P + && WITH_TRACE_MEMORY_P + && WITH_TRACE_BRANCH_P) + { + if (set_trace_option (sd, "-semantics", TRACE_ALU_IDX, arg) != SIM_RC_OK + || set_trace_option (sd, "-semantics", TRACE_FPU_IDX, arg) != SIM_RC_OK + || set_trace_option (sd, "-semantics", TRACE_MEMORY_IDX, arg) != SIM_RC_OK + || set_trace_option (sd, "-semantics", TRACE_BRANCH_IDX, arg) != SIM_RC_OK) + return SIM_RC_FAIL; + } + else + sim_io_eprintf (sd, "Alu, fpu, memory, and/or branch tracing not compiled in, `--trace-semantics' ignored\n"); + break; + +#ifdef SIM_HAVE_ADDR_RANGE + case OPTION_TRACE_RANGE : + if (WITH_TRACE) + { + char *chp = arg; + unsigned long start,end; + start = strtoul (chp, &chp, 0); + if (*chp != ',') + { + sim_io_eprintf (sd, "--trace-range missing END argument\n"); + return SIM_RC_FAIL; + } + end = strtoul (chp + 1, NULL, 0); + /* FIXME: Argument validation. */ + if (cpu != NULL) + sim_addr_range_add (TRACE_RANGE (CPU_PROFILE_DATA (cpu)), + start, end); + else + for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; ++cpu_nr) + sim_addr_range_add (TRACE_RANGE (CPU_TRACE_DATA (STATE_CPU (sd, cpu_nr))), + start, end); + } + else + sim_io_eprintf (sd, "Tracing not compiled in, `--trace-range' ignored\n"); + break; + + case OPTION_TRACE_FUNCTION : + if (WITH_TRACE) + { + /*wip: need to compute function range given name*/ + } + else + sim_io_eprintf (sd, "Tracing not compiled in, `--trace-function' ignored\n"); + break; +#endif /* SIM_HAVE_ADDR_RANGE */ + + case OPTION_TRACE_DEBUG : + if (WITH_TRACE_DEBUG_P) + return set_trace_option (sd, "-debug", TRACE_DEBUG_IDX, arg); + else + sim_io_eprintf (sd, "Tracing debug support not compiled in, `--trace-debug' ignored\n"); + break; + + case OPTION_TRACE_FILE : + if (! WITH_TRACE) + sim_io_eprintf (sd, "Tracing not compiled in, `--trace-file' ignored\n"); + else + { + FILE *f = fopen (arg, "w"); + + if (f == NULL) + { + sim_io_eprintf (sd, "Unable to open trace output file `%s'\n", arg); + return SIM_RC_FAIL; + } + for (n = 0; n < MAX_NR_PROCESSORS; ++n) + TRACE_FILE (CPU_TRACE_DATA (STATE_CPU (sd, n))) = f; + TRACE_FILE (STATE_TRACE_DATA (sd)) = f; + } + break; + } + + return SIM_RC_OK; +} + +/* Install tracing support. */ + +SIM_RC +trace_install (SIM_DESC sd) +{ + int i; + + SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); + + sim_add_option_table (sd, NULL, trace_options); + memset (STATE_TRACE_DATA (sd), 0, sizeof (* STATE_TRACE_DATA (sd))); + for (i = 0; i < MAX_NR_PROCESSORS; ++i) + memset (CPU_TRACE_DATA (STATE_CPU (sd, i)), 0, + sizeof (* CPU_TRACE_DATA (STATE_CPU (sd, i)))); + sim_module_add_init_fn (sd, trace_init); + sim_module_add_uninstall_fn (sd, trace_uninstall); + return SIM_RC_OK; +} + +static SIM_RC +trace_init (SIM_DESC sd) +{ +#ifdef SIM_HAVE_ADDR_RANGE + /* Check if a range has been specified without specifying what to + collect. */ + { + int i; + + for (i = 0; i < MAX_NR_PROCESSORS; ++i) + { + sim_cpu *cpu = STATE_CPU (sd, i); + + if (ADDR_RANGE_RANGES (TRACE_RANGE (CPU_TRACE_DATA (cpu))) + && ! TRACE_INSN_P (cpu)) + { + sim_io_eprintf_cpu (cpu, "Tracing address range specified without --trace-insn.\n"); + sim_io_eprintf_cpu (cpu, "Address range ignored.\n"); + sim_addr_range_delete (TRACE_RANGE (CPU_TRACE_DATA (cpu)), + 0, ~ (address_word) 0); + } + } + } +#endif + + return SIM_RC_OK; +} + +static void +trace_uninstall (SIM_DESC sd) +{ + int i,j; + FILE *sfile = TRACE_FILE (STATE_TRACE_DATA (sd)); + + if (sfile != NULL) + fclose (sfile); + + for (i = 0; i < MAX_NR_PROCESSORS; ++i) + { + FILE *cfile = TRACE_FILE (CPU_TRACE_DATA (STATE_CPU (sd, i))); + if (cfile != NULL && cfile != sfile) + { + /* If output from different cpus is going to the same file, + avoid closing the file twice. */ + for (j = 0; j < i; ++j) + if (TRACE_FILE (CPU_TRACE_DATA (STATE_CPU (sd, j))) == cfile) + break; + if (i == j) + fclose (cfile); + } + } +} + +typedef enum { + trace_fmt_invalid, + trace_fmt_word, + trace_fmt_fp, + trace_fmt_fpu, + trace_fmt_string, + trace_fmt_bool, + trace_fmt_addr, + trace_fmt_instruction_incomplete, +} data_fmt; + +/* compute the nr of trace data units consumed by data */ +static int +save_data_size (TRACE_DATA *data, + long size) +{ + return ((size + sizeof (TRACE_INPUT_DATA (data) [0]) - 1) + / sizeof (TRACE_INPUT_DATA (data) [0])); +} + + +/* Archive DATA into the trace buffer */ +static void +save_data (SIM_DESC sd, + TRACE_DATA *data, + data_fmt fmt, + long size, + void *buf) +{ + int i = TRACE_INPUT_IDX (data); + if (i == sizeof (TRACE_INPUT_FMT (data))) + sim_io_error (sd, "trace buffer overflow"); + TRACE_INPUT_FMT (data) [i] = fmt; + TRACE_INPUT_SIZE (data) [i] = size; + memcpy (&TRACE_INPUT_DATA (data) [i], buf, size); + i += save_data_size (data, size); + TRACE_INPUT_IDX (data) = i; +} + +static void +print_data (SIM_DESC sd, + sim_cpu *cpu, + data_fmt fmt, + long size, + void *data) +{ + switch (fmt) + { + case trace_fmt_instruction_incomplete: + trace_printf (sd, cpu, " (instruction incomplete)"); + break; + case trace_fmt_word: + case trace_fmt_addr: + { + switch (size) + { + case sizeof (unsigned32): + trace_printf (sd, cpu, " 0x%08lx", (long) * (unsigned32*) data); + break; + case sizeof (unsigned64): + trace_printf (sd, cpu, " 0x%08lx%08lx", + (long) ((* (unsigned64*) data) >> 32), + (long) * (unsigned64*) data); + break; + default: + abort (); + } + break; + } + case trace_fmt_bool: + { + SIM_ASSERT (size == sizeof (int)); + trace_printf (sd, cpu, " %-8s", + (* (int*) data) ? "true" : "false"); + break; + } + case trace_fmt_fp: + { + sim_fpu fp; + switch (size) + { + /* FIXME: Assumes sizeof float == 4; sizeof double == 8 */ + case 4: + sim_fpu_32to (&fp, *(unsigned32*)data); + break; + case 8: + sim_fpu_64to (&fp, *(unsigned64*)data); + break; + default: + abort (); + } + trace_printf (sd, cpu, " %8g", sim_fpu_2d (&fp)); + switch (size) + { + case 4: + trace_printf (sd, cpu, " (0x%08lx)", + (long) *(unsigned32*)data); + break; + case 8: + trace_printf (sd, cpu, " (0x%08lx%08lx)", + (long) (*(unsigned64*)data >> 32), + (long) (*(unsigned64*)data)); + break; + default: + abort (); + } + break; + } + case trace_fmt_fpu: + /* FIXME: At present sim_fpu data is stored as a double */ + trace_printf (sd, cpu, " %8g", * (double*) data); + break; + case trace_fmt_string: + trace_printf (sd, cpu, " %-8s", (char*) data); + break; + default: + abort (); + } +} + +static const char * +trace_idx_to_str (int trace_idx) +{ + static char num[8]; + switch (trace_idx) + { + case TRACE_ALU_IDX: return "alu: "; + case TRACE_INSN_IDX: return "insn: "; + case TRACE_DECODE_IDX: return "decode: "; + case TRACE_EXTRACT_IDX: return "extract: "; + case TRACE_MEMORY_IDX: return "memory: "; + case TRACE_CORE_IDX: return "core: "; + case TRACE_EVENTS_IDX: return "events: "; + case TRACE_FPU_IDX: return "fpu: "; + case TRACE_BRANCH_IDX: return "branch: "; + default: + sprintf (num, "?%d?", trace_idx); + return num; + } +} + +static void +trace_results (SIM_DESC sd, + sim_cpu *cpu, + int trace_idx, + int last_input) +{ + TRACE_DATA *data = CPU_TRACE_DATA (cpu); + int nr_out; + int i; + + /* cross check trace_idx against TRACE_IDX (data)? */ + + /* prefix */ + trace_printf (sd, cpu, "%s %s", + trace_idx_to_str (TRACE_IDX (data)), + TRACE_PREFIX (data)); + TRACE_IDX (data) = 0; + + for (i = 0, nr_out = 0; + i < TRACE_INPUT_IDX (data); + i += save_data_size (data, TRACE_INPUT_SIZE (data) [i]), nr_out++) + { + if (i == last_input) + { + int pad = (strlen (" 0x") + sizeof (unsigned_word) * 2); + int padding = pad * (3 - nr_out); + if (padding < 0) + padding = 0; + padding += strlen (" ::"); + trace_printf (sd, cpu, "%*s", padding, " ::"); + } + print_data (sd, cpu, + TRACE_INPUT_FMT (data) [i], + TRACE_INPUT_SIZE (data) [i], + &TRACE_INPUT_DATA (data) [i]); + } + trace_printf (sd, cpu, "\n"); +} + +void +trace_prefix (SIM_DESC sd, + sim_cpu *cpu, + sim_cia cia, + address_word pc, + int line_p, + const char *filename, + int linenum, + const char *fmt, + ...) +{ + TRACE_DATA *data = CPU_TRACE_DATA (cpu); + va_list ap; + char *prefix = TRACE_PREFIX (data); + char *chp; + /* FIXME: The TRACE_PREFIX_WIDTH should be determined at build time using + known information about the disassembled instructions. */ +#ifndef TRACE_PREFIX_WIDTH +#define TRACE_PREFIX_WIDTH 48 +#endif + int width = TRACE_PREFIX_WIDTH; + + /* if the previous trace data wasn't flushed, flush it now with a + note indicating that the trace was incomplete. */ + if (TRACE_IDX (data) != 0) + { + int last_input = TRACE_INPUT_IDX (data); + save_data (sd, data, trace_fmt_instruction_incomplete, 1, ""); + trace_results (sd, cpu, TRACE_IDX (data), last_input); + } + TRACE_IDX (data) = 0; + TRACE_INPUT_IDX (data) = 0; + + /* Create the text prefix for this new instruction: */ + if (!line_p) + { + if (filename) + { + sprintf (prefix, "%s:%-*d 0x%.*lx ", + filename, + SIZE_LINE_NUMBER, linenum, + SIZE_PC, (long) pc); + } + else + { + sprintf (prefix, "0x%.*lx ", + SIZE_PC, (long) pc); + /* Shrink the width by the amount that we didn't print. */ + width -= SIZE_LINE_NUMBER + SIZE_PC + 8; + } + chp = strchr (prefix, '\0'); + va_start (ap, fmt); + vsprintf (chp, fmt, ap); + va_end (ap); + } + else + { + char buf[256]; + buf[0] = 0; + if (STATE_TEXT_SECTION (CPU_STATE (cpu)) + && pc >= STATE_TEXT_START (CPU_STATE (cpu)) + && pc < STATE_TEXT_END (CPU_STATE (cpu))) + { + const char *pc_filename = (const char *)0; + const char *pc_function = (const char *)0; + unsigned int pc_linenum = 0; + bfd *abfd; + asymbol **asymbols; + + abfd = STATE_PROG_BFD (CPU_STATE (cpu)); + asymbols = STATE_PROG_SYMS (CPU_STATE (cpu)); + if (asymbols == NULL) + { + long symsize; + long symbol_count; + + symsize = bfd_get_symtab_upper_bound (abfd); + if (symsize < 0) + { + sim_engine_abort (sd, cpu, cia, "could not read symbols"); + } + asymbols = (asymbol **) xmalloc (symsize); + symbol_count = bfd_canonicalize_symtab (abfd, asymbols); + if (symbol_count < 0) + { + sim_engine_abort (sd, cpu, cia, "could not canonicalize symbols"); + } + STATE_PROG_SYMS (CPU_STATE (cpu)) = asymbols; + } + + if (bfd_find_nearest_line (abfd, + STATE_TEXT_SECTION (CPU_STATE (cpu)), + asymbols, + pc - STATE_TEXT_START (CPU_STATE (cpu)), + &pc_filename, &pc_function, &pc_linenum)) + { + char *p = buf; + if (pc_linenum) + { + sprintf (p, "#%-*d ", SIZE_LINE_NUMBER, pc_linenum); + p += strlen (p); + } + else + { + sprintf (p, "%-*s ", SIZE_LINE_NUMBER+1, "---"); + p += SIZE_LINE_NUMBER+2; + } + + if (pc_function) + { + sprintf (p, "%s ", pc_function); + p += strlen (p); + } + else if (pc_filename) + { + char *q = (char *) strrchr (pc_filename, '/'); + sprintf (p, "%s ", (q) ? q+1 : pc_filename); + p += strlen (p); + } + + if (*p == ' ') + *p = '\0'; + } + } + + sprintf (prefix, "0x%.*x %-*.*s ", + SIZE_PC, (unsigned) pc, + SIZE_LOCATION, SIZE_LOCATION, buf); + chp = strchr (prefix, '\0'); + va_start (ap, fmt); + vsprintf (chp, fmt, ap); + va_end (ap); + } + + /* Pad it out to TRACE_PREFIX_WIDTH. */ + chp = strchr (prefix, '\0'); + if (chp - prefix < width) + { + memset (chp, ' ', width - (chp - prefix)); + chp = &prefix [width]; + *chp = '\0'; + } + strcpy (chp, " -"); + + /* check that we've not over flowed the prefix buffer */ + if (strlen (prefix) >= sizeof (TRACE_PREFIX (data))) + abort (); +} + +void +trace_generic (SIM_DESC sd, + sim_cpu *cpu, + int trace_idx, + const char *fmt, + ...) +{ + va_list ap; + trace_printf (sd, cpu, "%s %s", + trace_idx_to_str (trace_idx), + TRACE_PREFIX (CPU_TRACE_DATA (cpu))); + va_start (ap, fmt); + trace_vprintf (sd, cpu, fmt, ap); + va_end (ap); + trace_printf (sd, cpu, "\n"); +} + +void +trace_input0 (SIM_DESC sd, + sim_cpu *cpu, + int trace_idx) +{ + TRACE_DATA *data = CPU_TRACE_DATA (cpu); + TRACE_IDX (data) = trace_idx; +} + +void +trace_input_word1 (SIM_DESC sd, + sim_cpu *cpu, + int trace_idx, + unsigned_word d0) +{ + TRACE_DATA *data = CPU_TRACE_DATA (cpu); + TRACE_IDX (data) = trace_idx; + save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &d0); +} + +void +trace_input_word2 (SIM_DESC sd, + sim_cpu *cpu, + int trace_idx, + unsigned_word d0, + unsigned_word d1) +{ + TRACE_DATA *data = CPU_TRACE_DATA (cpu); + TRACE_IDX (data) = trace_idx; + save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &d0); + save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &d1); +} + +void +trace_input_word3 (SIM_DESC sd, + sim_cpu *cpu, + int trace_idx, + unsigned_word d0, + unsigned_word d1, + unsigned_word d2) +{ + TRACE_DATA *data = CPU_TRACE_DATA (cpu); + TRACE_IDX (data) = trace_idx; + save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &d0); + save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &d1); + save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &d2); +} + +void +trace_input_word4 (SIM_DESC sd, + sim_cpu *cpu, + int trace_idx, + unsigned_word d0, + unsigned_word d1, + unsigned_word d2, + unsigned_word d3) +{ + TRACE_DATA *data = CPU_TRACE_DATA (cpu); + TRACE_IDX (data) = trace_idx; + save_data (sd, data, trace_fmt_word, sizeof (d0), &d0); + save_data (sd, data, trace_fmt_word, sizeof (d1), &d1); + save_data (sd, data, trace_fmt_word, sizeof (d2), &d2); + save_data (sd, data, trace_fmt_word, sizeof (d3), &d3); +} + +void +trace_input_bool1 (SIM_DESC sd, + sim_cpu *cpu, + int trace_idx, + int d0) +{ + TRACE_DATA *data = CPU_TRACE_DATA (cpu); + TRACE_IDX (data) = trace_idx; + save_data (sd, data, trace_fmt_bool, sizeof (d0), &d0); +} + +void +trace_input_addr1 (SIM_DESC sd, + sim_cpu *cpu, + int trace_idx, + address_word d0) +{ + TRACE_DATA *data = CPU_TRACE_DATA (cpu); + TRACE_IDX (data) = trace_idx; + save_data (sd, data, trace_fmt_addr, sizeof (d0), &d0); +} + +void +trace_input_fp1 (SIM_DESC sd, + sim_cpu *cpu, + int trace_idx, + fp_word f0) +{ + TRACE_DATA *data = CPU_TRACE_DATA (cpu); + TRACE_IDX (data) = trace_idx; + save_data (sd, data, trace_fmt_fp, sizeof (fp_word), &f0); +} + +void +trace_input_fp2 (SIM_DESC sd, + sim_cpu *cpu, + int trace_idx, + fp_word f0, + fp_word f1) +{ + TRACE_DATA *data = CPU_TRACE_DATA (cpu); + TRACE_IDX (data) = trace_idx; + save_data (sd, data, trace_fmt_fp, sizeof (fp_word), &f0); + save_data (sd, data, trace_fmt_fp, sizeof (fp_word), &f1); +} + +void +trace_input_fp3 (SIM_DESC sd, + sim_cpu *cpu, + int trace_idx, + fp_word f0, + fp_word f1, + fp_word f2) +{ + TRACE_DATA *data = CPU_TRACE_DATA (cpu); + TRACE_IDX (data) = trace_idx; + save_data (sd, data, trace_fmt_fp, sizeof (fp_word), &f0); + save_data (sd, data, trace_fmt_fp, sizeof (fp_word), &f1); + save_data (sd, data, trace_fmt_fp, sizeof (fp_word), &f2); +} + +void +trace_input_fpu1 (SIM_DESC sd, + sim_cpu *cpu, + int trace_idx, + sim_fpu *f0) +{ + double d; + TRACE_DATA *data = CPU_TRACE_DATA (cpu); + TRACE_IDX (data) = trace_idx; + d = sim_fpu_2d (f0); + save_data (sd, data, trace_fmt_fp, sizeof (double), &d); +} + +void +trace_input_fpu2 (SIM_DESC sd, + sim_cpu *cpu, + int trace_idx, + sim_fpu *f0, + sim_fpu *f1) +{ + double d; + TRACE_DATA *data = CPU_TRACE_DATA (cpu); + TRACE_IDX (data) = trace_idx; + d = sim_fpu_2d (f0); + save_data (sd, data, trace_fmt_fp, sizeof (double), &d); + d = sim_fpu_2d (f1); + save_data (sd, data, trace_fmt_fp, sizeof (double), &d); +} + +void +trace_input_fpu3 (SIM_DESC sd, + sim_cpu *cpu, + int trace_idx, + sim_fpu *f0, + sim_fpu *f1, + sim_fpu *f2) +{ + double d; + TRACE_DATA *data = CPU_TRACE_DATA (cpu); + TRACE_IDX (data) = trace_idx; + d = sim_fpu_2d (f0); + save_data (sd, data, trace_fmt_fp, sizeof (double), &d); + d = sim_fpu_2d (f1); + save_data (sd, data, trace_fmt_fp, sizeof (double), &d); + d = sim_fpu_2d (f2); + save_data (sd, data, trace_fmt_fp, sizeof (double), &d); +} + +void +trace_result_word1 (SIM_DESC sd, + sim_cpu *cpu, + int trace_idx, + unsigned_word r0) +{ + TRACE_DATA *data = CPU_TRACE_DATA (cpu); + int last_input; + + /* Append any results to the end of the inputs */ + last_input = TRACE_INPUT_IDX (data); + save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &r0); + + trace_results (sd, cpu, trace_idx, last_input); +} + +void +trace_result0 (SIM_DESC sd, + sim_cpu *cpu, + int trace_idx) +{ + TRACE_DATA *data = CPU_TRACE_DATA (cpu); + int last_input; + + /* Append any results to the end of the inputs */ + last_input = TRACE_INPUT_IDX (data); + + trace_results (sd, cpu, trace_idx, last_input); +} + +void +trace_result_word2 (SIM_DESC sd, + sim_cpu *cpu, + int trace_idx, + unsigned_word r0, + unsigned_word r1) +{ + TRACE_DATA *data = CPU_TRACE_DATA (cpu); + int last_input; + + /* Append any results to the end of the inputs */ + last_input = TRACE_INPUT_IDX (data); + save_data (sd, data, trace_fmt_word, sizeof (r0), &r0); + save_data (sd, data, trace_fmt_word, sizeof (r1), &r1); + + trace_results (sd, cpu, trace_idx, last_input); +} + +void +trace_result_word4 (SIM_DESC sd, + sim_cpu *cpu, + int trace_idx, + unsigned_word r0, + unsigned_word r1, + unsigned_word r2, + unsigned_word r3) +{ + TRACE_DATA *data = CPU_TRACE_DATA (cpu); + int last_input; + + /* Append any results to the end of the inputs */ + last_input = TRACE_INPUT_IDX (data); + save_data (sd, data, trace_fmt_word, sizeof (r0), &r0); + save_data (sd, data, trace_fmt_word, sizeof (r1), &r1); + save_data (sd, data, trace_fmt_word, sizeof (r2), &r2); + save_data (sd, data, trace_fmt_word, sizeof (r3), &r3); + + trace_results (sd, cpu, trace_idx, last_input); +} + +void +trace_result_bool1 (SIM_DESC sd, + sim_cpu *cpu, + int trace_idx, + int r0) +{ + TRACE_DATA *data = CPU_TRACE_DATA (cpu); + int last_input; + + /* Append any results to the end of the inputs */ + last_input = TRACE_INPUT_IDX (data); + save_data (sd, data, trace_fmt_bool, sizeof (r0), &r0); + + trace_results (sd, cpu, trace_idx, last_input); +} + +void +trace_result_addr1 (SIM_DESC sd, + sim_cpu *cpu, + int trace_idx, + address_word r0) +{ + TRACE_DATA *data = CPU_TRACE_DATA (cpu); + int last_input; + + /* Append any results to the end of the inputs */ + last_input = TRACE_INPUT_IDX (data); + save_data (sd, data, trace_fmt_addr, sizeof (r0), &r0); + + trace_results (sd, cpu, trace_idx, last_input); +} + +void +trace_result_fp1 (SIM_DESC sd, + sim_cpu *cpu, + int trace_idx, + fp_word f0) +{ + TRACE_DATA *data = CPU_TRACE_DATA (cpu); + int last_input; + + /* Append any results to the end of the inputs */ + last_input = TRACE_INPUT_IDX (data); + save_data (sd, data, trace_fmt_fp, sizeof (fp_word), &f0); + + trace_results (sd, cpu, trace_idx, last_input); +} + +void +trace_result_fp2 (SIM_DESC sd, + sim_cpu *cpu, + int trace_idx, + fp_word f0, + fp_word f1) +{ + TRACE_DATA *data = CPU_TRACE_DATA (cpu); + int last_input; + + /* Append any results to the end of the inputs */ + last_input = TRACE_INPUT_IDX (data); + save_data (sd, data, trace_fmt_fp, sizeof (f0), &f0); + save_data (sd, data, trace_fmt_fp, sizeof (f1), &f1); + + trace_results (sd, cpu, trace_idx, last_input); +} + +void +trace_result_fpu1 (SIM_DESC sd, + sim_cpu *cpu, + int trace_idx, + sim_fpu *f0) +{ + double d; + TRACE_DATA *data = CPU_TRACE_DATA (cpu); + int last_input; + + /* Append any results to the end of the inputs */ + last_input = TRACE_INPUT_IDX (data); + d = sim_fpu_2d (f0); + save_data (sd, data, trace_fmt_fp, sizeof (double), &d); + + trace_results (sd, cpu, trace_idx, last_input); +} + +void +trace_result_string1 (SIM_DESC sd, + sim_cpu *cpu, + int trace_idx, + char *s0) +{ + TRACE_DATA *data = CPU_TRACE_DATA (cpu); + int last_input; + + /* Append any results to the end of the inputs */ + last_input = TRACE_INPUT_IDX (data); + save_data (sd, data, trace_fmt_string, strlen (s0) + 1, s0); + + trace_results (sd, cpu, trace_idx, last_input); +} + +void +trace_result_word1_string1 (SIM_DESC sd, + sim_cpu *cpu, + int trace_idx, + unsigned_word r0, + char *s0) +{ + TRACE_DATA *data = CPU_TRACE_DATA (cpu); + int last_input; + + /* Append any results to the end of the inputs */ + last_input = TRACE_INPUT_IDX (data); + save_data (sd, data, trace_fmt_word, sizeof (unsigned_word), &r0); + save_data (sd, data, trace_fmt_string, strlen (s0) + 1, s0); + + trace_results (sd, cpu, trace_idx, last_input); +} + +void +trace_vprintf (SIM_DESC sd, sim_cpu *cpu, const char *fmt, va_list ap) +{ + if (cpu != NULL) + { + if (TRACE_FILE (CPU_TRACE_DATA (cpu)) != NULL) + vfprintf (TRACE_FILE (CPU_TRACE_DATA (cpu)), fmt, ap); + else + sim_io_evprintf (sd, fmt, ap); + } + else + { + if (TRACE_FILE (STATE_TRACE_DATA (sd)) != NULL) + vfprintf (TRACE_FILE (STATE_TRACE_DATA (sd)), fmt, ap); + else + sim_io_evprintf (sd, fmt, ap); + } +} + +/* The function trace_one_insn has been replaced by the function pair + trace_prefix() + trace_generic(). It is still used. */ +void +trace_one_insn (SIM_DESC sd, sim_cpu *cpu, address_word pc, + int line_p, const char *filename, int linenum, + const char *phase_wo_colon, const char *fmt, + ...) +{ + va_list ap; + char phase[SIZE_PHASE+2]; + + strncpy (phase, phase_wo_colon, SIZE_PHASE); + strcat (phase, ":"); + + if (!line_p) + { + trace_printf (sd, cpu, "%-*s %s:%-*d 0x%.*lx ", + SIZE_PHASE+1, phase, + filename, + SIZE_LINE_NUMBER, linenum, + SIZE_PC, (long)pc); + va_start (ap, fmt); + trace_vprintf (sd, cpu, fmt, ap); + va_end (ap); + trace_printf (sd, cpu, "\n"); + } + else + { + char buf[256]; + + buf[0] = 0; + if (STATE_TEXT_SECTION (CPU_STATE (cpu)) + && pc >= STATE_TEXT_START (CPU_STATE (cpu)) + && pc < STATE_TEXT_END (CPU_STATE (cpu))) + { + const char *pc_filename = (const char *)0; + const char *pc_function = (const char *)0; + unsigned int pc_linenum = 0; + + if (bfd_find_nearest_line (STATE_PROG_BFD (CPU_STATE (cpu)), + STATE_TEXT_SECTION (CPU_STATE (cpu)), + (struct symbol_cache_entry **) 0, + pc - STATE_TEXT_START (CPU_STATE (cpu)), + &pc_filename, &pc_function, &pc_linenum)) + { + char *p = buf; + if (pc_linenum) + { + sprintf (p, "#%-*d ", SIZE_LINE_NUMBER, pc_linenum); + p += strlen (p); + } + else + { + sprintf (p, "%-*s ", SIZE_LINE_NUMBER+1, "---"); + p += SIZE_LINE_NUMBER+2; + } + + if (pc_function) + { + sprintf (p, "%s ", pc_function); + p += strlen (p); + } + else if (pc_filename) + { + char *q = (char *) strrchr (pc_filename, '/'); + sprintf (p, "%s ", (q) ? q+1 : pc_filename); + p += strlen (p); + } + + if (*p == ' ') + *p = '\0'; + } + } + + trace_printf (sd, cpu, "%-*s 0x%.*x %-*.*s ", + SIZE_PHASE+1, phase, + SIZE_PC, (unsigned) pc, + SIZE_LOCATION, SIZE_LOCATION, buf); + va_start (ap, fmt); + trace_vprintf (sd, cpu, fmt, ap); + va_end (ap); + trace_printf (sd, cpu, "\n"); + } +} + +void +trace_printf VPARAMS ((SIM_DESC sd, sim_cpu *cpu, const char *fmt, ...)) +{ +#if !defined __STDC__ && !defined ALMOST_STDC + SIM_DESC sd; + sim_cpu *cpu; + const char *fmt; +#endif + va_list ap; + + VA_START (ap, fmt); +#if !defined __STDC__ && !defined ALMOST_STDC + sd = va_arg (ap, SIM_DESC); + cpu = va_arg (ap, sim_cpu *); + fmt = va_arg (ap, const char *); +#endif + + trace_vprintf (sd, cpu, fmt, ap); + + va_end (ap); +} + +void +debug_printf VPARAMS ((sim_cpu *cpu, const char *fmt, ...)) +{ +#if !defined __STDC__ && !defined ALMOST_STDC + sim_cpu *cpu; + const char *fmt; +#endif + va_list ap; + + VA_START (ap, fmt); +#if !defined __STDC__ && !defined ALMOST_STDC + cpu = va_arg (ap, sim_cpu *); + fmt = va_arg (ap, const char *); +#endif + + if (CPU_DEBUG_FILE (cpu) == NULL) + (* STATE_CALLBACK (CPU_STATE (cpu))->evprintf_filtered) + (STATE_CALLBACK (CPU_STATE (cpu)), fmt, ap); + else + vfprintf (CPU_DEBUG_FILE (cpu), fmt, ap); + + va_end (ap); +} diff --git a/sim/common/sim-trace.h b/sim/common/sim-trace.h new file mode 100644 index 00000000000..14d277e2e9e --- /dev/null +++ b/sim/common/sim-trace.h @@ -0,0 +1,551 @@ +/* Simulator tracing/debugging support. + Copyright (C) 1997, 1998 Free Software Foundation, Inc. + Contributed by Cygnus Support. + +This file is part of GDB, the GNU debugger. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* This file is meant to be included by sim-basics.h. */ + +#ifndef SIM_TRACE_H +#define SIM_TRACE_H + +/* Standard traceable entities. */ + +enum { + /* Trace insn execution. */ + TRACE_INSN_IDX = 1, + + /* Trace insn decoding. + ??? This is more of a simulator debugging operation and might best be + moved to --debug-decode. */ + TRACE_DECODE_IDX, + + /* Trace insn extraction. + ??? This is more of a simulator debugging operation and might best be + moved to --debug-extract. */ + TRACE_EXTRACT_IDX, + + /* Trace insn execution but include line numbers. */ + TRACE_LINENUM_IDX, + + /* Trace memory operations. + The difference between this and TRACE_CORE_IDX is (I think) that this + is intended to apply to a higher level. TRACE_CORE_IDX applies to the + low level core operations. */ + TRACE_MEMORY_IDX, + + /* Include model performance data in tracing output. */ + TRACE_MODEL_IDX, + + /* Trace ALU operations. */ + TRACE_ALU_IDX, + + /* Trace memory core operations. */ + TRACE_CORE_IDX, + + /* Trace events. */ + TRACE_EVENTS_IDX, + + /* Trace fpu operations. */ + TRACE_FPU_IDX, + + /* Trace branching. */ + TRACE_BRANCH_IDX, + + /* Add information useful for debugging the simulator to trace output. */ + TRACE_DEBUG_IDX, + + /* Simulator specific trace bits begin here. */ + TRACE_NEXT_IDX, + +}; +/* Maximum number of traceable entities. */ +#ifndef MAX_TRACE_VALUES +#define MAX_TRACE_VALUES 32 +#endif + +/* The -t option only prints useful values. It's easy to type and shouldn't + splat on the screen everything under the sun making nothing easy to + find. */ +#define TRACE_USEFUL_MASK \ +((1 << TRACE_INSN_IDX) \ + | (1 << TRACE_LINENUM_IDX) \ + | (1 << TRACE_MEMORY_IDX) \ + | (1 << TRACE_MODEL_IDX) \ + | (1 << TRACE_EVENTS_IDX)) + +/* Masks so WITH_TRACE can have symbolic values. + The case choice here is on purpose. The lowercase parts are args to + --with-trace. */ +#define TRACE_insn (1 << TRACE_INSN_IDX) +#define TRACE_decode (1 << TRACE_DECODE_IDX) +#define TRACE_extract (1 << TRACE_EXTRACT_IDX) +#define TRACE_linenum (1 << TRACE_LINENUM_IDX) +#define TRACE_memory (1 << TRACE_MEMORY_IDX) +#define TRACE_model (1 << TRACE_MODEL_IDX) +#define TRACE_alu (1 << TRACE_ALU_IDX) +#define TRACE_core (1 << TRACE_CORE_IDX) +#define TRACE_events (1 << TRACE_EVENTS_IDX) +#define TRACE_fpu (1 << TRACE_FPU_IDX) +#define TRACE_branch (1 << TRACE_BRANCH_IDX) +#define TRACE_debug (1 << TRACE_DEBUG_IDX) + +/* Preprocessor macros to simplify tests of WITH_TRACE. */ +#define WITH_TRACE_INSN_P (WITH_TRACE & TRACE_insn) +#define WITH_TRACE_DECODE_P (WITH_TRACE & TRACE_decode) +#define WITH_TRACE_EXTRACT_P (WITH_TRACE & TRACE_extract) +#define WITH_TRACE_LINENUM_P (WITH_TRACE & TRACE_linenum) +#define WITH_TRACE_MEMORY_P (WITH_TRACE & TRACE_memory) +#define WITH_TRACE_MODEL_P (WITH_TRACE & TRACE_model) +#define WITH_TRACE_ALU_P (WITH_TRACE & TRACE_alu) +#define WITH_TRACE_CORE_P (WITH_TRACE & TRACE_core) +#define WITH_TRACE_EVENTS_P (WITH_TRACE & TRACE_events) +#define WITH_TRACE_FPU_P (WITH_TRACE & TRACE_fpu) +#define WITH_TRACE_BRANCH_P (WITH_TRACE & TRACE_branch) +#define WITH_TRACE_DEBUG_P (WITH_TRACE & TRACE_debug) + +/* Tracing install handler. */ +MODULE_INSTALL_FN trace_install; + +/* Struct containing all system and cpu trace data. + + System trace data is stored with the associated module. + System and cpu tracing must share the same space of bitmasks as they + are arguments to --with-trace. One could have --with-trace and + --with-cpu-trace or some such but that's an over-complication at this point + in time. Also, there may be occasions where system and cpu tracing may + wish to share a name. */ + +typedef struct _trace_data { + + /* Global summary of all the current trace options */ + char trace_any_p; + + /* Boolean array of specified tracing flags. */ + /* ??? It's not clear that using an array vs a bit mask is faster. + Consider the case where one wants to test whether any of several bits + are set. */ + char trace_flags[MAX_TRACE_VALUES]; +#define TRACE_FLAGS(t) ((t)->trace_flags) + + /* Tracing output goes to this or stderr if NULL. + We can't store `stderr' here as stderr goes through a callback. */ + FILE *trace_file; +#define TRACE_FILE(t) ((t)->trace_file) + + /* Buffer to store the prefix to be printed before any trace line. */ + char trace_prefix[256]; +#define TRACE_PREFIX(t) ((t)->trace_prefix) + + /* Buffer to save the inputs for the current instruction. Use a + union to force the buffer into correct alignment */ + union { + unsigned8 i8; + unsigned16 i16; + unsigned32 i32; + unsigned64 i64; + } trace_input_data[16]; + unsigned8 trace_input_fmt[16]; + unsigned8 trace_input_size[16]; + int trace_input_idx; +#define TRACE_INPUT_DATA(t) ((t)->trace_input_data) +#define TRACE_INPUT_FMT(t) ((t)->trace_input_fmt) +#define TRACE_INPUT_SIZE(t) ((t)->trace_input_size) +#define TRACE_INPUT_IDX(t) ((t)->trace_input_idx) + + /* Category of trace being performed */ + int trace_idx; +#define TRACE_IDX(t) ((t)->trace_idx) + + /* Trace range. + ??? Not all cpu's support this. */ + ADDR_RANGE range; +#define TRACE_RANGE(t) (& (t)->range) +} TRACE_DATA; + +/* System tracing support. */ + +#define STATE_TRACE_FLAGS(sd) TRACE_FLAGS (STATE_TRACE_DATA (sd)) + +/* Return non-zero if tracing of IDX is enabled for non-cpu specific + components. The "S" in "STRACE" refers to "System". */ +#define STRACE_P(sd,idx) \ +((WITH_TRACE & (1 << (idx))) != 0 \ + && STATE_TRACE_FLAGS (sd)[idx] != 0) + +/* Non-zero if --trace- was specified for SD. */ +#define STRACE_DEBUG_P(sd) STRACE_P (sd, TRACE_DEBUG_IDX) + +/* CPU tracing support. */ + +#define CPU_TRACE_FLAGS(cpu) TRACE_FLAGS (CPU_TRACE_DATA (cpu)) + +/* Return non-zero if tracing of IDX is enabled for CPU. */ +#define TRACE_P(cpu,idx) \ +((WITH_TRACE & (1 << (idx))) != 0 \ + && CPU_TRACE_FLAGS (cpu)[idx] != 0) + +/* Non-zero if --trace- was specified for CPU. */ +#define TRACE_ANY_P(cpu) ((WITH_TRACE) && (CPU_TRACE_DATA (cpu)->trace_any_p)) +#define TRACE_INSN_P(cpu) TRACE_P (cpu, TRACE_INSN_IDX) +#define TRACE_DECODE_P(cpu) TRACE_P (cpu, TRACE_DECODE_IDX) +#define TRACE_EXTRACT_P(cpu) TRACE_P (cpu, TRACE_EXTRACT_IDX) +#define TRACE_LINENUM_P(cpu) TRACE_P (cpu, TRACE_LINENUM_IDX) +#define TRACE_MEMORY_P(cpu) TRACE_P (cpu, TRACE_MEMORY_IDX) +#define TRACE_MODEL_P(cpu) TRACE_P (cpu, TRACE_MODEL_IDX) +#define TRACE_ALU_P(cpu) TRACE_P (cpu, TRACE_ALU_IDX) +#define TRACE_CORE_P(cpu) TRACE_P (cpu, TRACE_CORE_IDX) +#define TRACE_EVENTS_P(cpu) TRACE_P (cpu, TRACE_EVENTS_IDX) +#define TRACE_FPU_P(cpu) TRACE_P (cpu, TRACE_FPU_IDX) +#define TRACE_BRANCH_P(cpu) TRACE_P (cpu, TRACE_BRANCH_IDX) +#define TRACE_DEBUG_P(cpu) TRACE_P (cpu, TRACE_DEBUG_IDX) + +/* Traceing functions. + + */ + +/* Prime the trace buffers ready for any trace output. + Must be called prior to any other trace operation */ +extern void trace_prefix PARAMS ((SIM_DESC sd, + sim_cpu *cpu, + sim_cia cia, + address_word pc, + int print_linenum_p, + const char *file_name, + int line_nr, + const char *fmt, + ...)) + __attribute__((format (printf, 8, 9))); + +/* Generic trace print, assumes trace_prefix() has been called */ + +extern void trace_generic PARAMS ((SIM_DESC sd, + sim_cpu *cpu, + int trace_idx, + const char *fmt, + ...)) + __attribute__((format (printf, 4, 5))); + +/* Trace a varying number of word sized inputs/outputs. trace_result* + must be called to close the trace operation. */ + +extern void trace_input0 PARAMS ((SIM_DESC sd, + sim_cpu *cpu, + int trace_idx)); + +extern void trace_input_word1 PARAMS ((SIM_DESC sd, + sim_cpu *cpu, + int trace_idx, + unsigned_word d0)); + +extern void trace_input_word2 PARAMS ((SIM_DESC sd, + sim_cpu *cpu, + int trace_idx, + unsigned_word d0, + unsigned_word d1)); + +extern void trace_input_word3 PARAMS ((SIM_DESC sd, + sim_cpu *cpu, + int trace_idx, + unsigned_word d0, + unsigned_word d1, + unsigned_word d2)); + +extern void trace_input_word4 PARAMS ((SIM_DESC sd, + sim_cpu *cpu, + int trace_idx, + unsigned_word d0, + unsigned_word d1, + unsigned_word d2, + unsigned_word d3)); + +extern void trace_input_addr1 PARAMS ((SIM_DESC sd, + sim_cpu *cpu, + int trace_idx, + address_word d0)); + +extern void trace_input_bool1 PARAMS ((SIM_DESC sd, + sim_cpu *cpu, + int trace_idx, + int d0)); + +extern void trace_input_fp1 PARAMS ((SIM_DESC sd, + sim_cpu *cpu, + int trace_idx, + fp_word f0)); + +extern void trace_input_fp2 PARAMS ((SIM_DESC sd, + sim_cpu *cpu, + int trace_idx, + fp_word f0, + fp_word f1)); + +extern void trace_input_fp3 PARAMS ((SIM_DESC sd, + sim_cpu *cpu, + int trace_idx, + fp_word f0, + fp_word f1, + fp_word f2)); + +extern void trace_input_fpu1 PARAMS ((SIM_DESC sd, + sim_cpu *cpu, + int trace_idx, + struct _sim_fpu *f0)); + +extern void trace_input_fpu2 PARAMS ((SIM_DESC sd, + sim_cpu *cpu, + int trace_idx, + struct _sim_fpu *f0, + struct _sim_fpu *f1)); + +extern void trace_input_fpu3 PARAMS ((SIM_DESC sd, + sim_cpu *cpu, + int trace_idx, + struct _sim_fpu *f0, + struct _sim_fpu *f1, + struct _sim_fpu *f2)); + +/* Other trace_input{_} functions can go here */ + +extern void trace_result0 PARAMS ((SIM_DESC sd, + sim_cpu *cpu, + int trace_idx)); + +extern void trace_result_word1 PARAMS ((SIM_DESC sd, + sim_cpu *cpu, + int trace_idx, + unsigned_word r0)); + +extern void trace_result_word2 PARAMS ((SIM_DESC sd, + sim_cpu *cpu, + int trace_idx, + unsigned_word r0, + unsigned_word r1)); + +extern void trace_result_word4 PARAMS ((SIM_DESC sd, + sim_cpu *cpu, + int trace_idx, + unsigned_word r0, + unsigned_word r1, + unsigned_word r2, + unsigned_word r3)); + +extern void trace_result_bool1 PARAMS ((SIM_DESC sd, + sim_cpu *cpu, + int trace_idx, + int r0)); + +extern void trace_result_addr1 PARAMS ((SIM_DESC sd, + sim_cpu *cpu, + int trace_idx, + address_word r0)); + +extern void trace_result_fp1 PARAMS ((SIM_DESC sd, + sim_cpu *cpu, + int trace_idx, + fp_word f0)); + +extern void trace_result_fp2 PARAMS ((SIM_DESC sd, + sim_cpu *cpu, + int trace_idx, + fp_word f0, + fp_word f1)); + +extern void trace_result_fpu1 PARAMS ((SIM_DESC sd, + sim_cpu *cpu, + int trace_idx, + struct _sim_fpu *f0)); + +extern void trace_result_string1 PARAMS ((SIM_DESC sd, + sim_cpu *cpu, + int trace_idx, + char *str0)); + +extern void trace_result_word1_string1 PARAMS ((SIM_DESC sd, + sim_cpu *cpu, + int trace_idx, + unsigned_word r0, + char *s0)); + +/* Other trace_result{_} */ + + +/* Macro's for tracing ALU instructions */ + +#define TRACE_ALU_INPUT0() \ +do { \ + if (TRACE_ALU_P (CPU)) \ + trace_input0 (SD, CPU, TRACE_ALU_IDX); \ +} while (0) + +#define TRACE_ALU_INPUT1(V0) \ +do { \ + if (TRACE_ALU_P (CPU)) \ + trace_input_word1 (SD, CPU, TRACE_ALU_IDX, (V0)); \ +} while (0) + +#define TRACE_ALU_INPUT2(V0,V1) \ +do { \ + if (TRACE_ALU_P (CPU)) \ + trace_input_word2 (SD, CPU, TRACE_ALU_IDX, (V0), (V1)); \ +} while (0) + +#define TRACE_ALU_INPUT3(V0,V1,V2) \ +do { \ + if (TRACE_ALU_P (CPU)) \ + trace_input_word3 (SD, CPU, TRACE_ALU_IDX, (V0), (V1), (V2)); \ +} while (0) + +#define TRACE_ALU_INPUT4(V0,V1,V2,V3) \ +do { \ + if (TRACE_ALU_P (CPU)) \ + trace_input_word4 (SD, CPU, TRACE_ALU_IDX, (V0), (V1), (V2), (V3)); \ +} while (0) + +#define TRACE_ALU_RESULT(R0) TRACE_ALU_RESULT1(R0) + +#define TRACE_ALU_RESULT0() \ +do { \ + if (TRACE_ALU_P (CPU)) \ + trace_result0 (SD, CPU, TRACE_ALU_IDX); \ +} while (0) + +#define TRACE_ALU_RESULT1(R0) \ +do { \ + if (TRACE_ALU_P (CPU)) \ + trace_result_word1 (SD, CPU, TRACE_ALU_IDX, (R0)); \ +} while (0) + +#define TRACE_ALU_RESULT2(R0,R1) \ +do { \ + if (TRACE_ALU_P (CPU)) \ + trace_result_word2 (SD, CPU, TRACE_ALU_IDX, (R0), (R1)); \ +} while (0) + +#define TRACE_ALU_RESULT4(R0,R1,R2,R3) \ +do { \ + if (TRACE_ALU_P (CPU)) \ + trace_result_word4 (SD, CPU, TRACE_ALU_IDX, (R0), (R1), (R2), (R3)); \ +} while (0) + + +/* Macro's for tracing FPU instructions */ + +#define TRACE_FP_INPUT0() \ +do { \ + if (TRACE_FPU_P (CPU)) \ + trace_input0 (SD, CPU, TRACE_FPU_IDX); \ +} while (0) + +#define TRACE_FP_INPUT1(V0) \ +do { \ + if (TRACE_FPU_P (CPU)) \ + trace_input_fp1 (SD, CPU, TRACE_FPU_IDX, (V0)); \ +} while (0) + +#define TRACE_FP_INPUT2(V0,V1) \ +do { \ + if (TRACE_FPU_P (CPU)) \ + trace_input_fp2 (SD, CPU, TRACE_FPU_IDX, (V0), (V1)); \ +} while (0) + +#define TRACE_FP_INPUT3(V0,V1,V2) \ +do { \ + if (TRACE_FPU_P (CPU)) \ + trace_input_fp3 (SD, CPU, TRACE_FPU_IDX, (V0), (V1), (V2)); \ +} while (0) + +#define TRACE_FP_INPUT_WORD1(V0) \ +do { \ + if (TRACE_FPU_P (CPU)) \ + trace_input_word1 (SD, CPU, TRACE_FPU_IDX, (V0)); \ +} while (0) + +#define TRACE_FP_RESULT(R0) \ +do { \ + if (TRACE_FPU_P (CPU)) \ + trace_result_fp1 (SD, CPU, TRACE_FPU_IDX, (R0)); \ +} while (0) + +#define TRACE_FP_RESULT2(R0,R1) \ +do { \ + if (TRACE_FPU_P (CPU)) \ + trace_result_fp2 (SD, CPU, TRACE_FPU_IDX, (R0), (R1)); \ +} while (0) + +#define TRACE_FP_RESULT_BOOL(R0) \ +do { \ + if (TRACE_FPU_P (CPU)) \ + trace_result_bool1 (SD, CPU, TRACE_FPU_IDX, (R0)); \ +} while (0) + +#define TRACE_FP_RESULT_WORD(R0) \ +do { \ + if (TRACE_FPU_P (CPU)) \ + trace_result_word1 (SD, CPU, TRACE_FPU_IDX, (R0)); \ +} while (0) + + +/* Macros for tracing branches */ + +#define TRACE_BRANCH_INPUT(COND) \ +do { \ + if (TRACE_BRANCH_P (CPU)) \ + trace_input_bool1 (SD, CPU, TRACE_BRANCH_IDX, (COND)); \ +} while (0) + +#define TRACE_BRANCH_RESULT(DEST) \ +do { \ + if (TRACE_BRANCH_P (CPU)) \ + trace_result_addr1 (SD, CPU, TRACE_BRANCH_IDX, (DEST)); \ +} while (0) + + +/* The function trace_one_insn has been replaced by the function pair + trace_prefix() + trace_generic() */ +extern void trace_one_insn PARAMS ((SIM_DESC sd, + sim_cpu * cpu, + address_word cia, + int print_linenum_p, + const char *file_name, + int line_nr, + const char *unit, + const char *fmt, + ...)) + __attribute__((format (printf, 8, 9))); + +extern void trace_printf PARAMS ((SIM_DESC, sim_cpu *, const char *, ...)) + __attribute__((format (printf, 3, 4))); + +extern void trace_vprintf PARAMS ((SIM_DESC, sim_cpu *, const char *, va_list)); + +/* Debug support. + This is included here because there isn't enough of it to justify + a sim-debug.h. */ + +/* Return non-zero if debugging of IDX for CPU is enabled. */ +#define DEBUG_P(cpu, idx) \ +((WITH_DEBUG & (1 << (idx))) != 0 \ + && CPU_DEBUG_FLAGS (cpu)[idx] != 0) + +/* Non-zero if "--debug-insn" specified. */ +#define DEBUG_INSN_P(cpu) DEBUG_P (cpu, DEBUG_INSN_IDX) + +extern void debug_printf PARAMS ((sim_cpu *, const char *, ...)) + __attribute__((format (printf, 2, 3))); + +#endif /* SIM_TRACE_H */ diff --git a/sim/common/sim-types.h b/sim/common/sim-types.h new file mode 100644 index 00000000000..babc59814b0 --- /dev/null +++ b/sim/common/sim-types.h @@ -0,0 +1,201 @@ +/* This file is part of psim (model of the PowerPC(tm) architecture) + + Copyright (C) 1994-1997, Andrew Cagney + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License + as published by the Free Software Foundation; either version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library 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. + + -- + + PowerPC is a trademark of International Business Machines Corporation. */ + + +#ifndef SIM_TYPES_H +/* #define SIM_TYPES_H */ + +/* INTEGER QUANTITIES: + + TYPES: + + signed* signed type of the given size + unsigned* The corresponding insigned type + + SIZES + + *NN Size based on the number of bits + *_NN Size according to the number of bytes + *_word Size based on the target architecture's word + word size (32/64 bits) + *_cell Size based on the target architecture's + IEEE 1275 cell size (almost always 32 bits) + +*/ + + +#if !defined (SIM_TYPES_H) && defined (__GNUC__) +#define SIM_TYPES_H + +/* bit based */ + +#define UNSIGNED32(X) ((unsigned32) X##UL) +#define UNSIGNED64(X) ((unsigned64) X##ULL) + +#define SIGNED32(X) ((signed32) X##L) +#define SIGNED64(X) ((signed64) X##LL) + +typedef signed int signed8 __attribute__ ((__mode__ (__QI__))); +typedef signed int signed16 __attribute__ ((__mode__ (__HI__))); +typedef signed int signed32 __attribute__ ((__mode__ (__SI__))); +typedef signed int signed64 __attribute__ ((__mode__ (__DI__))); + +typedef unsigned int unsigned8 __attribute__ ((__mode__ (__QI__))); +typedef unsigned int unsigned16 __attribute__ ((__mode__ (__HI__))); +typedef unsigned int unsigned32 __attribute__ ((__mode__ (__SI__))); +typedef unsigned int unsigned64 __attribute__ ((__mode__ (__DI__))); + +typedef struct { unsigned64 a[2]; } unsigned128; +typedef struct { signed64 a[2]; } signed128; + +#endif + + +#if !defined (SIM_TYPES_H) && defined (_MSC_VER) +#define SIM_TYPES_H + +/* bit based */ + +#define UNSIGNED32(X) (X##ui32) +#define UNSIGNED64(X) (X##ui64) + +#define SIGNED32(X) (X##i32) +#define SIGNED64(X) (X##i64) + +typedef signed char signed8; +typedef signed short signed16; +typedef signed int signed32; +typedef signed __int64 signed64; + +typedef unsigned int unsigned8; +typedef unsigned int unsigned16; +typedef unsigned int unsigned32; +typedef unsigned __int64 unsigned64; + +typedef struct { unsigned64 a[2]; } unsigned128; +typedef struct { signed64 a[2]; } signed128; + +#endif /* _MSC_VER */ + + +#if !defined (SIM_TYPES_H) +#define SIM_TYPES_H + +/* bit based */ + +#define UNSIGNED32(X) (X##UL) +#define UNSIGNED64(X) (X##ULL) + +#define SIGNED32(X) (X##L) +#define SIGNED64(X) (X##LL) + +typedef signed char signed8; +typedef signed short signed16; +#if defined (__ALPHA__) +typedef signed int unsigned32; +typedef signed long unsigned64; +#else +typedef signed long unsigned32; +typedef signed long long unsigned64; +#endif + +typedef unsigned char unsigned8; +typedef unsigned short unsigned16; +#if defined (__ALPHA__) +typedef unsigned int unsigned32; +typedef unsigned long unsigned64; +#else +typedef unsigned long unsigned32; +typedef unsigned long long unsigned64; +#endif + +typedef struct { unsigned64 a[2]; } unsigned128; +typedef struct { signed64 a[2]; } signed128; + +#endif + + +/* byte based */ + +typedef signed8 signed_1; +typedef signed16 signed_2; +typedef signed32 signed_4; +typedef signed64 signed_8; +typedef signed128 signed_16; + +typedef unsigned8 unsigned_1; +typedef unsigned16 unsigned_2; +typedef unsigned32 unsigned_4; +typedef unsigned64 unsigned_8; +typedef unsigned128 unsigned_16; + + +/* for general work, the following are defined */ +/* unsigned: >= 32 bits */ +/* signed: >= 32 bits */ +/* long: >= 32 bits, sign undefined */ +/* int: small indicator */ + +/* target architecture based */ +#if (WITH_TARGET_WORD_BITSIZE == 64) +typedef unsigned64 unsigned_word; +typedef signed64 signed_word; +#endif +#if (WITH_TARGET_WORD_BITSIZE == 32) +typedef unsigned32 unsigned_word; +typedef signed32 signed_word; +#endif + + +/* Other instructions */ +#if (WITH_TARGET_ADDRESS_BITSIZE == 64) +typedef unsigned64 unsigned_address; +typedef signed64 signed_address; +#endif +#if (WITH_TARGET_ADDRESS_BITSIZE == 32) +typedef unsigned32 unsigned_address; +typedef signed32 signed_address; +#endif +typedef unsigned_address address_word; + + +/* IEEE 1275 cell size */ +#if (WITH_TARGET_CELL_BITSIZE == 64) +typedef unsigned64 unsigned_cell; +typedef signed64 signed_cell; +#endif +#if (WITH_TARGET_CELL_BITSIZE == 32) +typedef unsigned32 unsigned_cell; +typedef signed32 signed_cell; +#endif +typedef signed_cell cell_word; /* cells are normally signed */ + + +/* Floating point registers */ +#if (WITH_TARGET_FLOATING_POINT_BITSIZE == 64) +typedef unsigned64 fp_word; +#endif +#if (WITH_TARGET_FLOATING_POINT_BITSIZE == 32) +typedef unsigned32 fp_word; +#endif + +#endif diff --git a/sim/common/sim-utils.c b/sim/common/sim-utils.c new file mode 100644 index 00000000000..3adbae5bbd4 --- /dev/null +++ b/sim/common/sim-utils.c @@ -0,0 +1,411 @@ +/* Miscellaneous simulator utilities. + Copyright (C) 1997, 1998 Free Software Foundation, Inc. + Contributed by Cygnus Support. + +This file is part of GDB, the GNU debugger. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "sim-main.h" +#include "sim-assert.h" + +#ifdef HAVE_STDLIB_H +#include +#endif + +#ifdef HAVE_TIME_H +#include +#endif + +#ifdef HAVE_SYS_TIME_H +#include /* needed by sys/resource.h */ +#endif + +#ifdef HAVE_SYS_RESOURCE_H +#include +#endif + +#ifdef HAVE_STRING_H +#include +#else +#ifdef HAVE_STRINGS_H +#include +#endif +#endif + +#include "libiberty.h" +#include "bfd.h" +#include "sim-utils.h" + +/* Global pointer to all state data. + Set by sim_resume. */ +struct sim_state *current_state; + +/* Allocate zero filled memory with xmalloc - xmalloc aborts of the + allocation fails. */ + +void * +zalloc (unsigned long size) +{ + void *memory = (void *) xmalloc (size); + memset (memory, 0, size); + return memory; +} + +void +zfree (void *data) +{ + free (data); +} + +/* Allocate a sim_state struct. */ + +SIM_DESC +sim_state_alloc (SIM_OPEN_KIND kind, + host_callback *callback) +{ + SIM_DESC sd = ZALLOC (struct sim_state); + + STATE_MAGIC (sd) = SIM_MAGIC_NUMBER; + STATE_CALLBACK (sd) = callback; + STATE_OPEN_KIND (sd) = kind; + +#if 0 + { + int cpu_nr; + + /* Initialize the back link from the cpu struct to the state struct. */ + /* ??? I can envision a design where the state struct contains an array + of pointers to cpu structs, rather than an array of structs themselves. + Implementing this is trickier as one may not know what to allocate until + one has parsed the args. Parsing the args twice wouldn't be unreasonable, + IMHO. If the state struct ever does contain an array of pointers then we + can't do this here. + ??? See also sim_post_argv_init*/ + for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; cpu_nr++) + { + CPU_STATE (STATE_CPU (sd, cpu_nr)) = sd; + CPU_INDEX (STATE_CPU (sd, cpu_nr)) = cpu_nr; + } + } +#endif + +#ifdef SIM_STATE_INIT + SIM_STATE_INIT (sd); +#endif + + return sd; +} + +/* Free a sim_state struct. */ + +void +sim_state_free (SIM_DESC sd) +{ + ASSERT (sd->base.magic == SIM_MAGIC_NUMBER); + +#ifdef SIM_STATE_FREE + SIM_STATE_FREE (sd); +#endif + + zfree (sd); +} + +/* Return a pointer to the cpu data for CPU_NAME, or NULL if not found. */ + +sim_cpu * +sim_cpu_lookup (SIM_DESC sd, const char *cpu_name) +{ + int i; + + for (i = 0; i < MAX_NR_PROCESSORS; ++i) + if (strcmp (cpu_name, CPU_NAME (STATE_CPU (sd, i))) == 0) + return STATE_CPU (sd, i); + return NULL; +} + +/* Return the prefix to use for a CPU specific message (typically an + error message). */ + +const char * +sim_cpu_msg_prefix (sim_cpu *cpu) +{ +#if MAX_NR_PROCESSORS == 1 + return ""; +#else + static char *prefix; + + if (prefix == NULL) + { + int maxlen = 0; + for (i = 0; i < MAX_NR_PROCESSORS; ++i) + { + int len = strlen (CPU_NAME (STATE_CPU (sd, i))); + if (len > maxlen) + maxlen = len; + } + prefix = (char *) xmalloc (maxlen + 5); + } + sprintf (prefix, "%s: ", CPU_NAME (cpu)); + return prefix; +#endif +} + +/* Cover fn to sim_io_eprintf. */ + +void +sim_io_eprintf_cpu (sim_cpu *cpu, const char *fmt, ...) +{ + SIM_DESC sd = CPU_STATE (cpu); + va_list ap; + + va_start (ap, fmt); + sim_io_eprintf (sd, sim_cpu_msg_prefix (cpu)); + sim_io_evprintf (sd, fmt, ap); + va_end (ap); +} + +/* Turn VALUE into a string with commas. */ + +char * +sim_add_commas (char *buf, int sizeof_buf, unsigned long value) +{ + int comma = 3; + char *endbuf = buf + sizeof_buf - 1; + + *--endbuf = '\0'; + do { + if (comma-- == 0) + { + *--endbuf = ','; + comma = 2; + } + + *--endbuf = (value % 10) + '0'; + } while ((value /= 10) != 0); + + return endbuf; +} + +/* Analyze PROG_NAME/PROG_BFD and set these fields in the state struct: + STATE_ARCHITECTURE, if not set already and can be determined from the bfd + STATE_PROG_BFD + STATE_START_ADDR + STATE_TEXT_SECTION + STATE_TEXT_START + STATE_TEXT_END + + PROG_NAME is the file name of the executable or NULL. + PROG_BFD is its bfd or NULL. + + If both PROG_NAME and PROG_BFD are NULL, this function returns immediately. + If PROG_BFD is not NULL, PROG_NAME is ignored. + + Implicit inputs: STATE_MY_NAME(sd), STATE_TARGET(sd), + STATE_ARCHITECTURE(sd). + + A new bfd is created so the app isn't required to keep its copy of the + bfd open. */ + +SIM_RC +sim_analyze_program (sd, prog_name, prog_bfd) + SIM_DESC sd; + char *prog_name; + bfd *prog_bfd; +{ + asection *s; + SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); + + if (prog_bfd != NULL) + { + if (prog_bfd == STATE_PROG_BFD (sd)) + /* already analyzed */ + return SIM_RC_OK; + else + /* duplicate needed, save the name of the file to be re-opened */ + prog_name = bfd_get_filename (prog_bfd); + } + + /* do we need to duplicate anything? */ + if (prog_name == NULL) + return SIM_RC_OK; + + /* open a new copy of the prog_bfd */ + prog_bfd = bfd_openr (prog_name, STATE_TARGET (sd)); + if (prog_bfd == NULL) + { + sim_io_eprintf (sd, "%s: can't open \"%s\": %s\n", + STATE_MY_NAME (sd), + prog_name, + bfd_errmsg (bfd_get_error ())); + return SIM_RC_FAIL; + } + if (!bfd_check_format (prog_bfd, bfd_object)) + { + sim_io_eprintf (sd, "%s: \"%s\" is not an object file: %s\n", + STATE_MY_NAME (sd), + prog_name, + bfd_errmsg (bfd_get_error ())); + bfd_close (prog_bfd); + return SIM_RC_FAIL; + } + if (STATE_ARCHITECTURE (sd) != NULL) + bfd_set_arch_info (prog_bfd, STATE_ARCHITECTURE (sd)); + else + { + if (bfd_get_arch (prog_bfd) != bfd_arch_unknown + && bfd_get_arch (prog_bfd) != bfd_arch_obscure) + { + STATE_ARCHITECTURE (sd) = bfd_get_arch_info (prog_bfd); + } + } + + /* update the sim structure */ + if (STATE_PROG_BFD (sd) != NULL) + bfd_close (STATE_PROG_BFD (sd)); + STATE_PROG_BFD (sd) = prog_bfd; + STATE_START_ADDR (sd) = bfd_get_start_address (prog_bfd); + + for (s = prog_bfd->sections; s; s = s->next) + if (strcmp (bfd_get_section_name (prog_bfd, s), ".text") == 0) + { + STATE_TEXT_SECTION (sd) = s; + STATE_TEXT_START (sd) = bfd_get_section_vma (prog_bfd, s); + STATE_TEXT_END (sd) = STATE_TEXT_START (sd) + bfd_section_size (prog_bfd, s); + break; + } + + return SIM_RC_OK; +} + +/* Simulator timing support. */ + +/* Called before sim_elapsed_time_since to get a reference point. */ + +SIM_ELAPSED_TIME +sim_elapsed_time_get () +{ +#ifdef HAVE_GETRUSAGE + struct rusage mytime; + if (getrusage (RUSAGE_SELF, &mytime) == 0) + return 1 + (SIM_ELAPSED_TIME) (((double) mytime.ru_utime.tv_sec * 1000) + (((double) mytime.ru_utime.tv_usec + 500) / 1000)); + return 1; +#else +#ifdef HAVE_TIME + return 1 + (SIM_ELAPSED_TIME) time ((time_t) 0); +#else + return 1; +#endif +#endif +} + +/* Return the elapsed time in milliseconds since START. + The actual time may be cpu usage (prefered) or wall clock. */ + +unsigned long +sim_elapsed_time_since (start) + SIM_ELAPSED_TIME start; +{ +#ifdef HAVE_GETRUSAGE + return sim_elapsed_time_get () - start; +#else +#ifdef HAVE_TIME + return (sim_elapsed_time_get () - start) * 1000; +#else + return 0; +#endif +#endif +} + + + +/* do_command but with printf style formatting of the arguments */ +void +sim_do_commandf (SIM_DESC sd, + const char *fmt, + ...) +{ + va_list ap; + char *buf; + va_start (ap, fmt); + vasprintf (&buf, fmt, ap); + sim_do_command (sd, buf); + va_end (ap); + free (buf); +} + + +/* sim-basics.h defines a number of enumerations, convert each of them + to a string representation */ +const char * +map_to_str (unsigned map) +{ + switch (map) + { + case read_map: return "read"; + case write_map: return "write"; + case exec_map: return "exec"; + case io_map: return "io"; + default: + { + static char str[10]; + sprintf (str, "(%ld)", (long) map); + return str; + } + } +} + +const char * +access_to_str (unsigned access) +{ + switch (access) + { + case access_invalid: return "invalid"; + case access_read: return "read"; + case access_write: return "write"; + case access_exec: return "exec"; + case access_io: return "io"; + case access_read_write: return "read_write"; + case access_read_exec: return "read_exec"; + case access_write_exec: return "write_exec"; + case access_read_write_exec: return "read_write_exec"; + case access_read_io: return "read_io"; + case access_write_io: return "write_io"; + case access_read_write_io: return "read_write_io"; + case access_exec_io: return "exec_io"; + case access_read_exec_io: return "read_exec_io"; + case access_write_exec_io: return "write_exec_io"; + case access_read_write_exec_io: return "read_write_exec_io"; + default: + { + static char str[10]; + sprintf (str, "(%ld)", (long) access); + return str; + } + } +} + +const char * +transfer_to_str (unsigned transfer) +{ + switch (transfer) + { + case read_transfer: return "read"; + case write_transfer: return "write"; + default: return "(error)"; + } +} + + diff --git a/sim/common/sim-utils.h b/sim/common/sim-utils.h new file mode 100644 index 00000000000..8e80e6a2cbe --- /dev/null +++ b/sim/common/sim-utils.h @@ -0,0 +1,90 @@ +/* Miscellaneous simulator utilities. + Copyright (C) 1997 Free Software Foundation, Inc. + Contributed by Cygnus Support. + +This file is part of GDB, the GNU debugger. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef SIM_UTILS_H +#define SIM_UTILS_H + +/* Memory management with an allocator that clears memory before use. */ + +void *zalloc (unsigned long size); + +#define ZALLOC(TYPE) (TYPE*)zalloc(sizeof (TYPE)) +#define NZALLOC(TYPE,N) (TYPE*)zalloc(sizeof (TYPE) * (N)) + +void zfree(void*); + +/* Turn VALUE into a string with commas. */ +char *sim_add_commas (char *, int, unsigned long); + +/* Utilities for elapsed time reporting. */ + +/* Opaque type, known only inside sim_elapsed_time_foo fns. Externally + it is known to never have the value zero. */ +typedef unsigned long SIM_ELAPSED_TIME; + + +/* Get reference point for future call to sim_time_elapsed. */ +SIM_ELAPSED_TIME sim_elapsed_time_get (void); + +/* Elapsed time in milliseconds since START. */ +unsigned long sim_elapsed_time_since (SIM_ELAPSED_TIME start); + +/* Utilities for manipulating the load image. */ + +SIM_RC sim_analyze_program (SIM_DESC sd, char *prog_name, + struct _bfd *prog_bfd); + +/* Load program PROG into the simulator using the function DO_LOAD. + If PROG_BFD is non-NULL, the file has already been opened. + If VERBOSE_P is non-zero statistics are printed of each loaded section + and the transfer rate (for consistency with gdb). + If LMA_P is non-zero the program sections are loaded at the LMA + rather than the VMA + If this fails an error message is printed and NULL is returned. + If it succeeds the bfd is returned. + NOTE: For historical reasons, older hardware simulators incorrectly + write the program sections at LMA interpreted as a virtual address. + This is still accommodated for backward compatibility reasons. */ + +typedef int sim_write_fn PARAMS ((SIM_DESC sd, SIM_ADDR mem, + unsigned char *buf, int length)); +struct _bfd *sim_load_file (SIM_DESC sd, const char *myname, + host_callback *callback, char *prog, + struct _bfd *prog_bfd, int verbose_p, + int lma_p, sim_write_fn do_load); + +/* Internal version of sim_do_command, include formatting */ +void sim_do_commandf (SIM_DESC sd, const char *fmt, ...); + + +/* These are defined in callback.c as cover functions to the vprintf + callbacks. */ + +void sim_cb_printf (host_callback *, const char *, ...); +void sim_cb_eprintf (host_callback *, const char *, ...); + + +/* sim-basics.h defines a number of enumerations, convert each of them + to a string representation */ +const char *map_to_str (unsigned map); +const char *access_to_str (unsigned access); +const char *transfer_to_str (unsigned transfer); + +#endif diff --git a/sim/common/sim-watch.c b/sim/common/sim-watch.c new file mode 100644 index 00000000000..75c9ad19f02 --- /dev/null +++ b/sim/common/sim-watch.c @@ -0,0 +1,458 @@ +/* Generic simulator watchpoint support. + Copyright (C) 1997 Free Software Foundation, Inc. + Contributed by Cygnus Support. + +This file is part of GDB, the GNU debugger. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "sim-main.h" +#include "sim-options.h" + +#include "sim-assert.h" + +#include + +#ifdef HAVE_STRING_H +#include +#else +#ifdef HAVE_STRINGS_H +#include +#endif +#endif + +#ifdef HAVE_STDLIB_H +#include +#endif + +enum { + OPTION_WATCH_DELETE = OPTION_START, + + OPTION_WATCH_INFO, + OPTION_WATCH_CLOCK, + OPTION_WATCH_CYCLES, + OPTION_WATCH_PC, + + OPTION_WATCH_OP, +}; + + +/* Break an option number into its op/int-nr */ +static watchpoint_type +option_to_type (SIM_DESC sd, + int option) +{ + sim_watchpoints *watch = STATE_WATCHPOINTS (sd); + watchpoint_type type = ((option - OPTION_WATCH_OP) + / (watch->nr_interrupts + 1)); + SIM_ASSERT (type >= 0 && type < nr_watchpoint_types); + return type; +} + +static int +option_to_interrupt_nr (SIM_DESC sd, + int option) +{ + sim_watchpoints *watch = STATE_WATCHPOINTS (sd); + int interrupt_nr = ((option - OPTION_WATCH_OP) + % (watch->nr_interrupts + 1)); + return interrupt_nr; +} + +static int +type_to_option (SIM_DESC sd, + watchpoint_type type, + int interrupt_nr) +{ + sim_watchpoints *watch = STATE_WATCHPOINTS (sd); + return ((type * (watch->nr_interrupts + 1)) + + interrupt_nr + + OPTION_WATCH_OP); +} + + +/* Delete one or more watchpoints. Fail if no watchpoints were found */ + +static SIM_RC +do_watchpoint_delete (SIM_DESC sd, + int ident, + watchpoint_type type) +{ + sim_watchpoints *watch = STATE_WATCHPOINTS (sd); + sim_watch_point **entry = &watch->points; + SIM_RC status = SIM_RC_FAIL; + while ((*entry) != NULL) + { + if ((*entry)->ident == ident + || (*entry)->type == type) + { + sim_watch_point *dead = (*entry); + (*entry) = (*entry)->next; + sim_events_deschedule (sd, dead->event); + zfree (dead); + status = SIM_RC_OK; + } + else + entry = &(*entry)->next; + } + return status; +} + +static char * +watchpoint_type_to_str (SIM_DESC sd, + watchpoint_type type) +{ + switch (type) + { + case pc_watchpoint: + return "pc"; + case clock_watchpoint: + return "clock"; + case cycles_watchpoint: + return "cycles"; + case invalid_watchpoint: + case nr_watchpoint_types: + return "(invalid-type)"; + } + return NULL; +} + +static char * +interrupt_nr_to_str (SIM_DESC sd, + int interrupt_nr) +{ + sim_watchpoints *watch = STATE_WATCHPOINTS (sd); + if (interrupt_nr < 0) + return "(invalid-interrupt)"; + else if (interrupt_nr >= watch->nr_interrupts) + return "breakpoint"; + else + return watch->interrupt_names[interrupt_nr]; +} + + +static void +do_watchpoint_info (SIM_DESC sd) +{ + sim_watchpoints *watch = STATE_WATCHPOINTS (sd); + sim_watch_point *point; + sim_io_printf (sd, "Watchpoints:\n"); + for (point = watch->points; point != NULL; point = point->next) + { + sim_io_printf (sd, "%3d: watch %s %s ", + point->ident, + watchpoint_type_to_str (sd, point->type), + interrupt_nr_to_str (sd, point->interrupt_nr)); + if (point->is_periodic) + sim_io_printf (sd, "+"); + if (!point->is_within) + sim_io_printf (sd, "!"); + sim_io_printf (sd, "0x%lx", point->arg0); + if (point->arg1 != point->arg0) + sim_io_printf (sd, ",0x%lx", point->arg1); + sim_io_printf (sd, "\n"); + } +} + + + +static sim_event_handler handle_watchpoint; + +static SIM_RC +schedule_watchpoint (SIM_DESC sd, + sim_watch_point *point) +{ + sim_watchpoints *watch = STATE_WATCHPOINTS (sd); + switch (point->type) + { + case pc_watchpoint: + point->event = sim_events_watch_sim (sd, + watch->pc, + watch->sizeof_pc, + 0/* host-endian */, + point->is_within, + point->arg0, point->arg1, + /* PC in arg0..arg1 */ + handle_watchpoint, + point); + return SIM_RC_OK; + case clock_watchpoint: + point->event = sim_events_watch_clock (sd, + point->arg0, /* ms time */ + handle_watchpoint, + point); + return SIM_RC_OK; + case cycles_watchpoint: + point->event = sim_events_schedule (sd, + point->arg0, /* time */ + handle_watchpoint, + point); + return SIM_RC_OK; + default: + sim_engine_abort (sd, NULL, NULL_CIA, + "handle_watchpoint - internal error - bad switch"); + return SIM_RC_FAIL; + } + return SIM_RC_OK; +} + + +static void +handle_watchpoint (SIM_DESC sd, void *data) +{ + sim_watchpoints *watch = STATE_WATCHPOINTS (sd); + sim_watch_point *point = (sim_watch_point *) data; + int interrupt_nr = point->interrupt_nr; + + if (point->is_periodic) + /* reschedule this event before processing it */ + schedule_watchpoint (sd, point); + else + do_watchpoint_delete (sd, point->ident, invalid_watchpoint); + + if (point->interrupt_nr == watch->nr_interrupts) + sim_engine_halt (sd, NULL, NULL, NULL_CIA, sim_stopped, SIM_SIGINT); + else + watch->interrupt_handler (sd, &watch->interrupt_names[interrupt_nr]); +} + + +static SIM_RC +do_watchpoint_create (SIM_DESC sd, + watchpoint_type type, + int opt, + char *arg) +{ + sim_watchpoints *watch = STATE_WATCHPOINTS (sd); + sim_watch_point **point; + + /* create the watchpoint */ + point = &watch->points; + while ((*point) != NULL) + point = &(*point)->next; + (*point) = ZALLOC (sim_watch_point); + + /* fill in the details */ + (*point)->ident = ++(watch->last_point_nr); + (*point)->type = option_to_type (sd, opt); + (*point)->interrupt_nr = option_to_interrupt_nr (sd, opt); + /* prefixes to arg - +== periodic, !==not or outside */ + (*point)->is_within = 1; + while (1) + { + if (arg[0] == '+') + (*point)->is_periodic = 1; + else if (arg[0] == '!') + (*point)->is_within = 0; + else + break; + arg++; + } + + (*point)->arg0 = strtoul (arg, &arg, 0); + if (arg[0] == ',') + (*point)->arg0 = strtoul (arg, NULL, 0); + else + (*point)->arg1 = (*point)->arg0; + + /* schedule it */ + schedule_watchpoint (sd, (*point)); + + return SIM_RC_OK; +} + + +static SIM_RC +watchpoint_option_handler (SIM_DESC sd, sim_cpu *cpu, int opt, + char *arg, int is_command) +{ + if (opt >= OPTION_WATCH_OP) + return do_watchpoint_create (sd, clock_watchpoint, opt, arg); + else + switch (opt) + { + + case OPTION_WATCH_DELETE: + if (isdigit ((int) arg[0])) + { + int ident = strtol (arg, NULL, 0); + if (do_watchpoint_delete (sd, ident, invalid_watchpoint) + != SIM_RC_OK) + { + sim_io_eprintf (sd, "Watchpoint %d not found\n", ident); + return SIM_RC_FAIL; + } + return SIM_RC_OK; + } + else if (strcasecmp (arg, "all") == 0) + { + watchpoint_type type; + for (type = invalid_watchpoint + 1; + type < nr_watchpoint_types; + type++) + { + do_watchpoint_delete (sd, 0, type); + } + return SIM_RC_OK; + } + else if (strcasecmp (arg, "pc") == 0) + { + if (do_watchpoint_delete (sd, 0, pc_watchpoint) + != SIM_RC_OK) + { + sim_io_eprintf (sd, "No PC watchpoints found\n"); + return SIM_RC_FAIL; + } + return SIM_RC_OK; + } + else if (strcasecmp (arg, "clock") == 0) + { + if (do_watchpoint_delete (sd, 0, clock_watchpoint) != SIM_RC_OK) + { + sim_io_eprintf (sd, "No CLOCK watchpoints found\n"); + return SIM_RC_FAIL; + } + return SIM_RC_OK; + } + else if (strcasecmp (arg, "cycles") == 0) + { + if (do_watchpoint_delete (sd, 0, cycles_watchpoint) != SIM_RC_OK) + { + sim_io_eprintf (sd, "No CYCLES watchpoints found\n"); + return SIM_RC_FAIL; + } + return SIM_RC_OK; + } + sim_io_eprintf (sd, "Unknown watchpoint type `%s'\n", arg); + return SIM_RC_FAIL; + + case OPTION_WATCH_INFO: + { + do_watchpoint_info (sd); + return SIM_RC_OK; + } + + default: + sim_io_eprintf (sd, "Unknown watch option %d\n", opt); + return SIM_RC_FAIL; + + } + +} + + +static SIM_RC +sim_watchpoint_init (SIM_DESC sd) +{ + sim_watchpoints *watch = STATE_WATCHPOINTS (sd); + sim_watch_point *point; + /* NOTE: Do not need to de-schedule any previous watchpoints as + sim-events has already done this */ + /* schedule any watchpoints enabled by command line options */ + for (point = watch->points; point != NULL; point = point->next) + { + schedule_watchpoint (sd, point); + } + return SIM_RC_OK; +} + + +static const OPTION watchpoint_options[] = +{ + { {"watch-delete", required_argument, NULL, OPTION_WATCH_DELETE }, + '\0', "IDENT|all|pc|cycles|clock", "Delete a watchpoint", + watchpoint_option_handler }, + + { {"watch-info", no_argument, NULL, OPTION_WATCH_INFO }, + '\0', NULL, "List scheduled watchpoints", + watchpoint_option_handler }, + + { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL } +}; + +static char *default_interrupt_names[] = { "int", 0, }; + + + +SIM_RC +sim_watchpoint_install (SIM_DESC sd) +{ + sim_watchpoints *watch = STATE_WATCHPOINTS (sd); + SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); + /* the basic command set */ + sim_module_add_init_fn (sd, sim_watchpoint_init); + sim_add_option_table (sd, NULL, watchpoint_options); + /* fill in some details */ + if (watch->interrupt_names == NULL) + watch->interrupt_names = default_interrupt_names; + watch->nr_interrupts = 0; + while (watch->interrupt_names[watch->nr_interrupts] != NULL) + watch->nr_interrupts++; + /* generate more advansed commands */ + { + OPTION *int_options = NZALLOC (OPTION, 1 + (watch->nr_interrupts + 1) * nr_watchpoint_types); + int interrupt_nr; + for (interrupt_nr = 0; interrupt_nr <= watch->nr_interrupts; interrupt_nr++) + { + watchpoint_type type; + for (type = 0; type < nr_watchpoint_types; type++) + { + char *name; + int nr = interrupt_nr * nr_watchpoint_types + type; + OPTION *option = &int_options[nr]; + asprintf (&name, "watch-%s-%s", + watchpoint_type_to_str (sd, type), + interrupt_nr_to_str (sd, interrupt_nr)); + option->opt.name = name; + option->opt.has_arg = required_argument; + option->opt.val = type_to_option (sd, type, interrupt_nr); + option->doc = ""; + option->doc_name = ""; + option->handler = watchpoint_option_handler; + } + } + /* adjust first few entries so that they contain real + documentation, the first entry includes a list of actions. */ + { + char *prefix = + "Watch the simulator, take ACTION in COUNT cycles (`+' for every COUNT cycles), ACTION is"; + char *doc; + int len = strlen (prefix) + 1; + for (interrupt_nr = 0; interrupt_nr <= watch->nr_interrupts; interrupt_nr++) + len += strlen (interrupt_nr_to_str (sd, interrupt_nr)) + 1; + doc = NZALLOC (char, len); + strcpy (doc, prefix); + for (interrupt_nr = 0; interrupt_nr <= watch->nr_interrupts; interrupt_nr++) + { + strcat (doc, " "); + strcat (doc, interrupt_nr_to_str (sd, interrupt_nr)); + } + int_options[0].doc_name = "watch-cycles-ACTION"; + int_options[0].arg = "[+]COUNT"; + int_options[0].doc = doc; + } + int_options[1].doc_name = "watch-pc-ACTION"; + int_options[1].arg = "[!]ADDRESS"; + int_options[1].doc = + "Watch the PC, take ACTION when matches ADDRESS (in range ADDRESS,ADDRESS), `!' negates test"; + int_options[2].doc_name = "watch-clock-ACTION"; + int_options[2].arg = "[+]MILLISECONDS"; + int_options[2].doc = + "Watch the clock, take ACTION after MILLISECONDS (`+' for every MILLISECONDS)"; + + sim_add_option_table (sd, NULL, int_options); + } + return SIM_RC_OK; +} diff --git a/sim/common/sim-watch.h b/sim/common/sim-watch.h new file mode 100644 index 00000000000..ad920d3ecf2 --- /dev/null +++ b/sim/common/sim-watch.h @@ -0,0 +1,78 @@ +/* Simulator watchpoint support. + Copyright (C) 1997 Free Software Foundation, Inc. + Contributed by Cygnus Support. + +This file is part of GDB, the GNU debugger. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + + +#ifndef SIM_WATCH_H +#define SIM_WATCH_H + +typedef enum { + invalid_watchpoint = -1, + pc_watchpoint, + clock_watchpoint, + cycles_watchpoint, + nr_watchpoint_types, +} watchpoint_type; + +typedef struct _sim_watch_point sim_watch_point; +struct _sim_watch_point { + int ident; + watchpoint_type type; + int interrupt_nr; /* == nr_interrupts -> breakpoint */ + int is_periodic; + int is_within; + unsigned long arg0; + unsigned long arg1; + sim_event *event; + sim_watch_point *next; +}; + + +typedef struct _sim_watchpoints { + + /* Pointer into the host's data structures specifying the + address/size of the program-counter */ + /* FIXME: In the future this shall be generalized so that any of the + N processors M registers can be watched */ + void *pc; + int sizeof_pc; + + /* Pointer to the handler for interrupt watchpoints */ + /* FIXME: can this be done better? */ + /* NOTE: For the DATA arg, the handler is passed a (char**) pointer + that is an offset into the INTERRUPT_NAMES vector. Use + arithmetic to determine the interrupt-nr. */ + sim_event_handler *interrupt_handler; + + /* Pointer to a null terminated list of interrupt names */ + /* FIXME: can this be done better? Look at the PPC's interrupt + mechanism and table for a rough idea of where it will go next */ + int nr_interrupts; + char **interrupt_names; + + /* active watchpoints */ + int last_point_nr; + sim_watch_point *points; + +} sim_watchpoints; + +/* Watch install handler. */ +MODULE_INSTALL_FN sim_watchpoint_install; + +#endif /* SIM_WATCH_H */ diff --git a/sim/common/syscall.c b/sim/common/syscall.c new file mode 100644 index 00000000000..e0a3b880b84 --- /dev/null +++ b/sim/common/syscall.c @@ -0,0 +1,482 @@ +/* Remote target system call support. + Copyright 1997, 1998 Free Software Foundation, Inc. + Contributed by Cygnus Solutions. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GAS; see the file COPYING. If not, write to the Free Software + Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* This interface isn't intended to be specific to any particular kind + of remote (hardware, simulator, whatever). As such, support for it + (e.g. sim/common/callback.c) should *not* live in the simulator source + tree, nor should it live in the gdb source tree. K&R C must be + supported. */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "ansidecl.h" +#include "libiberty.h" +#ifdef ANSI_PROTOTYPES +#include +#else +#include +#endif +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#include +#include +#include +#include +#include +#include "callback.h" +#include "targ-vals.h" + +#ifndef ENOSYS +#define ENOSYS EINVAL +#endif +#ifndef ENAMETOOLONG +#define ENAMETOOLONG EINVAL +#endif + +/* Maximum length of a path name. */ +#ifndef MAX_PATH_LEN +#define MAX_PATH_LEN 1024 +#endif + +/* When doing file read/writes, do this many bytes at a time. */ +#define FILE_XFR_SIZE 4096 + +/* FIXME: for now, need to consider target word size. */ +#define TWORD long +#define TADDR unsigned long + +/* Utility of cb_syscall to fetch a path name or other string from the target. + The result is 0 for success or a host errno value. */ + +static int +get_string (cb, sc, buf, buflen, addr) + host_callback *cb; + CB_SYSCALL *sc; + char *buf; + int buflen; + TADDR addr; +{ + char *p, *pend; + + for (p = buf, pend = buf + buflen; p < pend; ++p, ++addr) + { + /* No, it isn't expected that this would cause one transaction with + the remote target for each byte. The target could send the + path name along with the syscall request, and cache the file + name somewhere (or otherwise tweak this as desired). */ + unsigned int count = (*sc->read_mem) (cb, sc, addr, p, 1); + + if (count != 1) + return EINVAL; + if (*p == 0) + break; + } + if (p == pend) + return ENAMETOOLONG; + return 0; +} + +/* Utility of cb_syscall to fetch a path name. + The buffer is malloc'd and the address is stored in BUFP. + The result is that of get_string. + If an error occurs, no buffer is left malloc'd. */ + +static int +get_path (cb, sc, addr, bufp) + host_callback *cb; + CB_SYSCALL *sc; + TADDR addr; + char **bufp; +{ + char *buf = xmalloc (MAX_PATH_LEN); + int result; + + result = get_string (cb, sc, buf, MAX_PATH_LEN, addr); + if (result == 0) + *bufp = buf; + else + free (buf); + return result; +} + +/* Perform a system call on behalf of the target. */ + +CB_RC +cb_syscall (cb, sc) + host_callback *cb; + CB_SYSCALL *sc; +{ + TWORD result = 0, errcode = 0; + + if (sc->magic != CB_SYSCALL_MAGIC) + abort (); + + switch (cb_target_to_host_syscall (cb, sc->func)) + { +#if 0 /* FIXME: wip */ + case CB_SYS_argvlen : + { + /* Compute how much space is required to store the argv,envp + strings so that the program can allocate the space and then + call SYS_argv to fetch the values. */ + int addr_size = cb->addr_size; + int argc,envc,arglen,envlen; + const char **argv = cb->init_argv; + const char **envp = cb->init_envp; + + argc = arglen = 0; + if (argv) + { + for ( ; argv[argc]; ++argc) + arglen += strlen (argv[argc]) + 1; + } + envc = envlen = 0; + if (envp) + { + for ( ; envp[envc]; ++envc) + envlen += strlen (envp[envc]) + 1; + } + result = arglen + envlen; + break; + } + + case CB_SYS_argv : + { + /* Pointer to target's buffer. */ + TADDR tbuf = sc->arg1; + /* Buffer size. */ + int bufsize = sc->arg2; + /* Q is the target address of where all the strings go. */ + TADDR q; + int word_size = cb->word_size; + int i,argc,envc,len; + const char **argv = cb->init_argv; + const char **envp = cb->init_envp; + + argc = 0; + if (argv) + { + for ( ; argv[argc]; ++argc) + { + int len = strlen (argv[argc]); + int written = (*sc->write_mem) (cb, sc, tbuf, argv[argc], len + 1); + if (written != len) + { + result = -1; + errcode = EINVAL; + goto FinishSyscall; + } + tbuf = len + 1; + } + } + if ((*sc->write_mem) (cb, sc, tbuf, "", 1) != 1) + { + result = -1; + errcode = EINVAL; + goto FinishSyscall; + } + tbuf++; + envc = 0; + if (envp) + { + for ( ; envp[envc]; ++envc) + { + int len = strlen (envp[envc]); + int written = (*sc->write_mem) (cb, sc, tbuf, envp[envc], len + 1); + if (written != len) + { + result = -1; + errcode = EINVAL; + goto FinishSyscall; + } + tbuf = len + 1; + } + } + if ((*sc->write_mem) (cb, sc, tbuf, "", 1) != 1) + { + result = -1; + errcode = EINVAL; + goto FinishSyscall; + } + result = argc; + sc->result2 = envc; + break; + } +#endif /* wip */ + + case CB_SYS_exit : + /* Caller must catch and handle. */ + break; + + case CB_SYS_open : + { + char *path; + + errcode = get_path (cb, sc, sc->arg1, &path); + if (errcode != 0) + { + result = -1; + goto FinishSyscall; + } + result = (*cb->open) (cb, path, sc->arg2 /*, sc->arg3*/); + free (path); + if (result < 0) + goto ErrorFinish; + } + break; + + case CB_SYS_close : + result = (*cb->close) (cb, sc->arg1); + if (result < 0) + goto ErrorFinish; + break; + + case CB_SYS_read : + { + /* ??? Perfect handling of error conditions may require only one + call to cb->read. One can't assume all the data is + contiguously stored in host memory so that would require + malloc'ing/free'ing the space. Maybe later. */ + char buf[FILE_XFR_SIZE]; + int fd = sc->arg1; + TADDR addr = sc->arg2; + size_t count = sc->arg3; + size_t bytes_read = 0; + int bytes_written; + + while (count > 0) + { + if (fd == 0) + result = (int) (*cb->read_stdin) (cb, buf, + (count < FILE_XFR_SIZE + ? count : FILE_XFR_SIZE)); + else + result = (int) (*cb->read) (cb, fd, buf, + (count < FILE_XFR_SIZE + ? count : FILE_XFR_SIZE)); + if (result == -1) + goto ErrorFinish; + if (result == 0) /* EOF */ + break; + bytes_written = (*sc->write_mem) (cb, sc, addr, buf, result); + if (bytes_written != result) + { + result = -1; + errcode = EINVAL; + goto FinishSyscall; + } + bytes_read += result; + count -= result; + addr += result; + /* If this is a short read, don't go back for more */ + if (result != FILE_XFR_SIZE) + break; + } + result = bytes_read; + } + break; + + case CB_SYS_write : + { + /* ??? Perfect handling of error conditions may require only one + call to cb->write. One can't assume all the data is + contiguously stored in host memory so that would require + malloc'ing/free'ing the space. Maybe later. */ + char buf[FILE_XFR_SIZE]; + int fd = sc->arg1; + TADDR addr = sc->arg2; + size_t count = sc->arg3; + int bytes_read; + size_t bytes_written = 0; + + while (count > 0) + { + int bytes_to_read = count < FILE_XFR_SIZE ? count : FILE_XFR_SIZE; + bytes_read = (*sc->read_mem) (cb, sc, addr, buf, bytes_to_read); + if (bytes_read != bytes_to_read) + { + result = -1; + errcode = EINVAL; + goto FinishSyscall; + } + if (fd == 1) + { + result = (int) (*cb->write_stdout) (cb, buf, bytes_read); + (*cb->flush_stdout) (cb); + } + else if (fd == 2) + { + result = (int) (*cb->write_stderr) (cb, buf, bytes_read); + (*cb->flush_stderr) (cb); + } + else + result = (int) (*cb->write) (cb, fd, buf, bytes_read); + if (result == -1) + goto ErrorFinish; + bytes_written += result; + count -= result; + addr += result; + } + result = bytes_written; + } + break; + + case CB_SYS_lseek : + { + int fd = sc->arg1; + unsigned long offset = sc->arg2; + int whence = sc->arg3; + + result = (*cb->lseek) (cb, fd, offset, whence); + if (result < 0) + goto ErrorFinish; + } + break; + + case CB_SYS_unlink : + { + char *path; + + errcode = get_path (cb, sc, sc->arg1, &path); + if (errcode != 0) + { + result = -1; + goto FinishSyscall; + } + result = (*cb->unlink) (cb, path); + free (path); + if (result < 0) + goto ErrorFinish; + } + break; + + case CB_SYS_stat : + { + char *path,*buf; + int buflen; + struct stat statbuf; + TADDR addr = sc->arg2; + + errcode = get_path (cb, sc, sc->arg1, &path); + if (errcode != 0) + { + result = -1; + goto FinishSyscall; + } + result = (*cb->stat) (cb, path, &statbuf); + free (path); + if (result < 0) + goto ErrorFinish; + buflen = cb_host_to_target_stat (cb, NULL, NULL); + buf = xmalloc (buflen); + if (cb_host_to_target_stat (cb, &statbuf, buf) != buflen) + { + /* The translation failed. This is due to an internal + host program error, not the target's fault. */ + free (buf); + errcode = ENOSYS; + result = -1; + goto FinishSyscall; + } + if ((*sc->write_mem) (cb, sc, addr, buf, buflen) != buflen) + { + free (buf); + errcode = EINVAL; + result = -1; + goto FinishSyscall; + } + free (buf); + } + break; + + case CB_SYS_fstat : + { + char *buf; + int buflen; + struct stat statbuf; + TADDR addr = sc->arg2; + + result = (*cb->fstat) (cb, sc->arg1, &statbuf); + if (result < 0) + goto ErrorFinish; + buflen = cb_host_to_target_stat (cb, NULL, NULL); + buf = xmalloc (buflen); + if (cb_host_to_target_stat (cb, &statbuf, buf) != buflen) + { + /* The translation failed. This is due to an internal + host program error, not the target's fault. */ + free (buf); + errcode = ENOSYS; + result = -1; + goto FinishSyscall; + } + if ((*sc->write_mem) (cb, sc, addr, buf, buflen) != buflen) + { + free (buf); + errcode = EINVAL; + result = -1; + goto FinishSyscall; + } + free (buf); + } + break; + + case CB_SYS_time : + { + /* FIXME: May wish to change CB_SYS_time to something else. + We might also want gettimeofday or times, but if system calls + can be built on others, we can keep the number we have to support + here down. */ + time_t t = (*cb->time) (cb, (time_t *) 0); + result = t; + /* It is up to target code to process the argument to time(). */ + } + break; + + case CB_SYS_chdir : + case CB_SYS_chmod : + case CB_SYS_utime : + /* fall through for now */ + + default : + result = -1; + errcode = ENOSYS; + break; + } + + FinishSyscall: + sc->result = result; + if (errcode == 0) + sc->errcode = 0; + else + sc->errcode = cb_host_to_target_errno (cb, errcode); + return CB_RC_OK; + + ErrorFinish: + sc->result = result; + sc->errcode = (*cb->get_errno) (cb); + return CB_RC_OK; +} diff --git a/sim/common/tconfig.in b/sim/common/tconfig.in new file mode 100644 index 00000000000..fd8b5be47fe --- /dev/null +++ b/sim/common/tconfig.in @@ -0,0 +1,19 @@ +/* Default target configuration file. + To override this, create file `tconfig.in' in the simulator's + source directory. */ + +/* Define this if the simulator supports profiling. + See the mips simulator for an example. + This enables the `-p foo' and `-s bar' options. + The target is required to provide sim_set_profile{,_size}. */ +/* #define SIM_HAVE_PROFILE */ + +/* Define this if the simulator uses an instruction cache. + See the h8/300 simulator for an example. + This enables the `-c size' option to set the size of the cache. + The target is required to provide sim_set_simcache_size. */ +/* #define SIM_HAVE_SIMCACHE */ + +/* Define this if the target cpu is bi-endian + and the simulator supports it. */ +/* #define SIM_HAVE_BIENDIAN */ diff --git a/sim/configure b/sim/configure new file mode 100755 index 00000000000..9257de97d74 --- /dev/null +++ b/sim/configure @@ -0,0 +1,1917 @@ +#! /bin/sh + +# Guess values for system-dependent variables and create Makefiles. +# Generated automatically using autoconf version 2.13 +# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc. +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. + +# Defaults: +ac_help= +ac_default_prefix=/usr/local +# Any additions from configure.in: +ac_help="$ac_help + --enable-sim " +ac_help="$ac_help +" + +# Initialize some variables set by options. +# The variables have the same names as the options, with +# dashes changed to underlines. +build=NONE +cache_file=./config.cache +exec_prefix=NONE +host=NONE +no_create= +nonopt=NONE +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +target=NONE +verbose= +x_includes=NONE +x_libraries=NONE +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +# Initialize some other variables. +subdirs= +MFLAGS= MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} +# Maximum number of lines to put in a shell here document. +ac_max_here_lines=12 + +ac_prev= +for ac_option +do + + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval "$ac_prev=\$ac_option" + ac_prev= + continue + fi + + case "$ac_option" in + -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) ac_optarg= ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case "$ac_option" in + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir="$ac_optarg" ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build="$ac_optarg" ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file="$ac_optarg" ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir="$ac_optarg" ;; + + -disable-* | --disable-*) + ac_feature=`echo $ac_option|sed -e 's/-*disable-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + eval "enable_${ac_feature}=no" ;; + + -enable-* | --enable-*) + ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "enable_${ac_feature}='$ac_optarg'" ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix="$ac_optarg" ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he) + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat << EOF +Usage: configure [options] [host] +Options: [defaults in brackets after descriptions] +Configuration: + --cache-file=FILE cache test results in FILE + --help print this message + --no-create do not create output files + --quiet, --silent do not print \`checking...' messages + --version print the version of autoconf that created configure +Directory and file names: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [same as prefix] + --bindir=DIR user executables in DIR [EPREFIX/bin] + --sbindir=DIR system admin executables in DIR [EPREFIX/sbin] + --libexecdir=DIR program executables in DIR [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data in DIR + [PREFIX/share] + --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data in DIR + [PREFIX/com] + --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var] + --libdir=DIR object code libraries in DIR [EPREFIX/lib] + --includedir=DIR C header files in DIR [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include] + --infodir=DIR info documentation in DIR [PREFIX/info] + --mandir=DIR man documentation in DIR [PREFIX/man] + --srcdir=DIR find the sources in DIR [configure dir or ..] + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM + run sed PROGRAM on installed program names +EOF + cat << EOF +Host type: + --build=BUILD configure for building on BUILD [BUILD=HOST] + --host=HOST configure for HOST [guessed] + --target=TARGET configure for TARGET [TARGET=HOST] +Features and packages: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --x-includes=DIR X include files are in DIR + --x-libraries=DIR X library files are in DIR +EOF + if test -n "$ac_help"; then + echo "--enable and --with options recognized:$ac_help" + fi + exit 0 ;; + + -host | --host | --hos | --ho) + ac_prev=host ;; + -host=* | --host=* | --hos=* | --ho=*) + host="$ac_optarg" ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir="$ac_optarg" ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir="$ac_optarg" ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir="$ac_optarg" ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir="$ac_optarg" ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + localstatedir="$ac_optarg" ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir="$ac_optarg" ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir="$ac_optarg" ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix="$ac_optarg" ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix="$ac_optarg" ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix="$ac_optarg" ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name="$ac_optarg" ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir="$ac_optarg" ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir="$ac_optarg" ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site="$ac_optarg" ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir="$ac_optarg" ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir="$ac_optarg" ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target="$ac_optarg" ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers) + echo "configure generated by autoconf version 2.13" + exit 0 ;; + + -with-* | --with-*) + ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "with_${ac_package}='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`echo $ac_option|sed -e 's/-*without-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + eval "with_${ac_package}=no" ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes="$ac_optarg" ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries="$ac_optarg" ;; + + -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; } + ;; + + *) + if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then + echo "configure: warning: $ac_option: invalid host type" 1>&2 + fi + if test "x$nonopt" != xNONE; then + { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } + fi + nonopt="$ac_option" + ;; + + esac +done + +if test -n "$ac_prev"; then + { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; } +fi + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +# File descriptor usage: +# 0 standard input +# 1 file creation +# 2 errors and warnings +# 3 some systems may open it to /dev/tty +# 4 used on the Kubota Titan +# 6 checking for... messages and results +# 5 compiler messages saved in config.log +if test "$silent" = yes; then + exec 6>/dev/null +else + exec 6>&1 +fi +exec 5>./config.log + +echo "\ +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. +" 1>&5 + +# Strip out --no-create and --no-recursion so they do not pile up. +# Also quote any args containing shell metacharacters. +ac_configure_args= +for ac_arg +do + case "$ac_arg" in + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) ;; + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) + ac_configure_args="$ac_configure_args '$ac_arg'" ;; + *) ac_configure_args="$ac_configure_args $ac_arg" ;; + esac +done + +# NLS nuisances. +# Only set these to C if already set. These must not be set unconditionally +# because not all systems understand e.g. LANG=C (notably SCO). +# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'! +# Non-C LC_CTYPE values break the ctype check. +if test "${LANG+set}" = set; then LANG=C; export LANG; fi +if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi +if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi +if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo > confdefs.h + +# A filename unique to this package, relative to the directory that +# configure is in, which we can look for to find out if srcdir is correct. +ac_unique_file=Makefile.in + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then its parent. + ac_prog=$0 + ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'` + test "x$ac_confdir" = "x$ac_prog" && ac_confdir=. + srcdir=$ac_confdir + if test ! -r $srcdir/$ac_unique_file; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r $srcdir/$ac_unique_file; then + if test "$ac_srcdir_defaulted" = yes; then + { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; } + else + { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; } + fi +fi +srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'` + +# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + echo "loading site script $ac_site_file" + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + echo "loading cache $cache_file" + . $cache_file +else + echo "creating cache $cache_file" + > $cache_file +fi + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +ac_exeext= +ac_objext=o +if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then + # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. + if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then + ac_n= ac_c=' +' ac_t=' ' + else + ac_n=-n ac_c= ac_t= + fi +else + ac_n= ac_c='\c' ac_t= +fi + + + +# Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:533: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CC="gcc" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:563: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_prog_rejected=no + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + break + fi + done + IFS="$ac_save_ifs" +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# -gt 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + set dummy "$ac_dir/$ac_word" "$@" + shift + ac_cv_prog_CC="$@" + fi +fi +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + if test -z "$CC"; then + case "`uname -s`" in + *win32* | *WIN32*) + # Extract the first word of "cl", so it can be a program name with args. +set dummy cl; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:614: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CC="cl" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + ;; + esac + fi + test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; } +fi + +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 +echo "configure:646: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +cat > conftest.$ac_ext << EOF + +#line 657 "configure" +#include "confdefs.h" + +main(){return(0);} +EOF +if { (eval echo configure:662: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + ac_cv_prog_cc_works=yes + # If we can't run a trivial program, we are probably using a cross compiler. + if (./conftest; exit) 2>/dev/null; then + ac_cv_prog_cc_cross=no + else + ac_cv_prog_cc_cross=yes + fi +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + ac_cv_prog_cc_works=no +fi +rm -fr conftest* +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +echo "$ac_t""$ac_cv_prog_cc_works" 1>&6 +if test $ac_cv_prog_cc_works = no; then + { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } +fi +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 +echo "configure:688: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 +cross_compiling=$ac_cv_prog_cc_cross + +echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 +echo "configure:693: checking whether we are using GNU C" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.c <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then + ac_cv_prog_gcc=yes +else + ac_cv_prog_gcc=no +fi +fi + +echo "$ac_t""$ac_cv_prog_gcc" 1>&6 + +if test $ac_cv_prog_gcc = yes; then + GCC=yes +else + GCC= +fi + +ac_test_CFLAGS="${CFLAGS+set}" +ac_save_CFLAGS="$CFLAGS" +CFLAGS= +echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 +echo "configure:721: checking whether ${CC-cc} accepts -g" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + echo 'void f(){}' > conftest.c +if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then + ac_cv_prog_cc_g=yes +else + ac_cv_prog_cc_g=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_prog_cc_g" 1>&6 +if test "$ac_test_CFLAGS" = set; then + CFLAGS="$ac_save_CFLAGS" +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi + +ac_aux_dir= +for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do + if test -f $ac_dir/install-sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f $ac_dir/install.sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + fi +done +if test -z "$ac_aux_dir"; then + { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; } +fi +ac_config_guess=$ac_aux_dir/config.guess +ac_config_sub=$ac_aux_dir/config.sub +ac_configure=$ac_aux_dir/configure # This should be Cygnus configure. + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# ./install, which can be erroneously created by make from ./install.sh. +echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 +echo "configure:783: checking for a BSD compatible install" >&5 +if test -z "$INSTALL"; then +if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":" + for ac_dir in $PATH; do + # Account for people who put trailing slashes in PATH elements. + case "$ac_dir/" in + /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + if test -f $ac_dir/$ac_prog; then + if test $ac_prog = install && + grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + else + ac_cv_path_install="$ac_dir/$ac_prog -c" + break 2 + fi + fi + done + ;; + esac + done + IFS="$ac_save_IFS" + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL="$ac_cv_path_install" + else + # As a last resort, use the slow shell script. We don't cache a + # path for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the path is relative. + INSTALL="$ac_install_sh" + fi +fi +echo "$ac_t""$INSTALL" 1>&6 + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + + +# Make sure we can run config.sub. +if ${CONFIG_SHELL-/bin/sh} $ac_config_sub sun4 >/dev/null 2>&1; then : +else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; } +fi + +echo $ac_n "checking host system type""... $ac_c" 1>&6 +echo "configure:842: checking host system type" >&5 + +host_alias=$host +case "$host_alias" in +NONE) + case $nonopt in + NONE) + if host_alias=`${CONFIG_SHELL-/bin/sh} $ac_config_guess`; then : + else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; } + fi ;; + *) host_alias=$nonopt ;; + esac ;; +esac + +host=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $host_alias` +host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` +echo "$ac_t""$host" 1>&6 + +echo $ac_n "checking build system type""... $ac_c" 1>&6 +echo "configure:863: checking build system type" >&5 + +build_alias=$build +case "$build_alias" in +NONE) + case $nonopt in + NONE) build_alias=$host_alias ;; + *) build_alias=$nonopt ;; + esac ;; +esac + +build=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $build_alias` +build_cpu=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +build_vendor=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +build_os=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` +echo "$ac_t""$build" 1>&6 + +if test $host != $build; then + ac_tool_prefix=${host_alias}- +else + ac_tool_prefix= +fi + +# Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args. +set dummy ${ac_tool_prefix}ar; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:889: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_AR'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$AR"; then + ac_cv_prog_AR="$AR" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_AR="${ac_tool_prefix}ar" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_prog_AR" && ac_cv_prog_AR="ar" +fi +fi +AR="$ac_cv_prog_AR" +if test -n "$AR"; then + echo "$ac_t""$AR" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + + +# Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. +set dummy ${ac_tool_prefix}ranlib; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:921: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +RANLIB="$ac_cv_prog_RANLIB" +if test -n "$RANLIB"; then + echo "$ac_t""$RANLIB" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + +if test -z "$ac_cv_prog_RANLIB"; then +if test -n "$ac_tool_prefix"; then + # Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:953: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_RANLIB="ranlib" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":" +fi +fi +RANLIB="$ac_cv_prog_RANLIB" +if test -n "$RANLIB"; then + echo "$ac_t""$RANLIB" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +else + RANLIB=":" +fi +fi + + +ac_aux_dir= +for ac_dir in `cd $srcdir;pwd`/.. $srcdir/`cd $srcdir;pwd`/..; do + if test -f $ac_dir/install-sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f $ac_dir/install.sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + fi +done +if test -z "$ac_aux_dir"; then + { echo "configure: error: can not find install-sh or install.sh in `cd $srcdir;pwd`/.. $srcdir/`cd $srcdir;pwd`/.." 1>&2; exit 1; } +fi +ac_config_guess=$ac_aux_dir/config.guess +ac_config_sub=$ac_aux_dir/config.sub +ac_configure=$ac_aux_dir/configure # This should be Cygnus configure. + + +# Do some error checking and defaulting for the host and target type. +# The inputs are: +# configure --host=HOST --target=TARGET --build=BUILD NONOPT +# +# The rules are: +# 1. You are not allowed to specify --host, --target, and nonopt at the +# same time. +# 2. Host defaults to nonopt. +# 3. If nonopt is not specified, then host defaults to the current host, +# as determined by config.guess. +# 4. Target and build default to nonopt. +# 5. If nonopt is not specified, then target and build default to host. + +# The aliases save the names the user supplied, while $host etc. +# will get canonicalized. +case $host---$target---$nonopt in +NONE---*---* | *---NONE---* | *---*---NONE) ;; +*) { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } ;; +esac + + +# Make sure we can run config.sub. +if ${CONFIG_SHELL-/bin/sh} $ac_config_sub sun4 >/dev/null 2>&1; then : +else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; } +fi + +echo $ac_n "checking host system type""... $ac_c" 1>&6 +echo "configure:1033: checking host system type" >&5 + +host_alias=$host +case "$host_alias" in +NONE) + case $nonopt in + NONE) + if host_alias=`${CONFIG_SHELL-/bin/sh} $ac_config_guess`; then : + else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; } + fi ;; + *) host_alias=$nonopt ;; + esac ;; +esac + +host=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $host_alias` +host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` +echo "$ac_t""$host" 1>&6 + +echo $ac_n "checking target system type""... $ac_c" 1>&6 +echo "configure:1054: checking target system type" >&5 + +target_alias=$target +case "$target_alias" in +NONE) + case $nonopt in + NONE) target_alias=$host_alias ;; + *) target_alias=$nonopt ;; + esac ;; +esac + +target=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $target_alias` +target_cpu=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +target_vendor=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +target_os=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` +echo "$ac_t""$target" 1>&6 + +echo $ac_n "checking build system type""... $ac_c" 1>&6 +echo "configure:1072: checking build system type" >&5 + +build_alias=$build +case "$build_alias" in +NONE) + case $nonopt in + NONE) build_alias=$host_alias ;; + *) build_alias=$nonopt ;; + esac ;; +esac + +build=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $build_alias` +build_cpu=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +build_vendor=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +build_os=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` +echo "$ac_t""$build" 1>&6 + +test "$host_alias" != "$target_alias" && + test "$program_prefix$program_suffix$program_transform_name" = \ + NONENONEs,x,x, && + program_prefix=${target_alias}- + +if test "$program_transform_name" = s,x,x,; then + program_transform_name= +else + # Double any \ or $. echo might interpret backslashes. + cat <<\EOF_SED > conftestsed +s,\\,\\\\,g; s,\$,$$,g +EOF_SED + program_transform_name="`echo $program_transform_name|sed -f conftestsed`" + rm -f conftestsed +fi +test "$program_prefix" != NONE && + program_transform_name="s,^,${program_prefix},; $program_transform_name" +# Use a double $ so make ignores it. +test "$program_suffix" != NONE && + program_transform_name="s,\$\$,${program_suffix},; $program_transform_name" + +# sed with no file args requires a program. +test "$program_transform_name" = "" && program_transform_name="s,x,x," + +# Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1116: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CC="gcc" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1146: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_prog_rejected=no + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + break + fi + done + IFS="$ac_save_ifs" +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# -gt 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + set dummy "$ac_dir/$ac_word" "$@" + shift + ac_cv_prog_CC="$@" + fi +fi +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + if test -z "$CC"; then + case "`uname -s`" in + *win32* | *WIN32*) + # Extract the first word of "cl", so it can be a program name with args. +set dummy cl; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1197: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CC="cl" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + ;; + esac + fi + test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; } +fi + +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 +echo "configure:1229: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +cat > conftest.$ac_ext << EOF + +#line 1240 "configure" +#include "confdefs.h" + +main(){return(0);} +EOF +if { (eval echo configure:1245: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + ac_cv_prog_cc_works=yes + # If we can't run a trivial program, we are probably using a cross compiler. + if (./conftest; exit) 2>/dev/null; then + ac_cv_prog_cc_cross=no + else + ac_cv_prog_cc_cross=yes + fi +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + ac_cv_prog_cc_works=no +fi +rm -fr conftest* +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +echo "$ac_t""$ac_cv_prog_cc_works" 1>&6 +if test $ac_cv_prog_cc_works = no; then + { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } +fi +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 +echo "configure:1271: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 +cross_compiling=$ac_cv_prog_cc_cross + +echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 +echo "configure:1276: checking whether we are using GNU C" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.c <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then + ac_cv_prog_gcc=yes +else + ac_cv_prog_gcc=no +fi +fi + +echo "$ac_t""$ac_cv_prog_gcc" 1>&6 + +if test $ac_cv_prog_gcc = yes; then + GCC=yes +else + GCC= +fi + +ac_test_CFLAGS="${CFLAGS+set}" +ac_save_CFLAGS="$CFLAGS" +CFLAGS= +echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 +echo "configure:1304: checking whether ${CC-cc} accepts -g" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + echo 'void f(){}' > conftest.c +if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then + ac_cv_prog_cc_g=yes +else + ac_cv_prog_cc_g=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_prog_cc_g" 1>&6 +if test "$ac_test_CFLAGS" = set; then + CFLAGS="$ac_save_CFLAGS" +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi + + + +AR=${AR-ar} + +# Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1342: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_RANLIB="ranlib" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":" +fi +fi +RANLIB="$ac_cv_prog_RANLIB" +if test -n "$RANLIB"; then + echo "$ac_t""$RANLIB" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + +# Put a plausible default for CC_FOR_BUILD in Makefile. + +if test "x$cross_compiling" = "xno"; then + CC_FOR_BUILD='$(CC)' +else + CC_FOR_BUILD=gcc +fi + + +# If a cpu ever has more than one simulator to choose from, use +# --enable-sim=... to choose. +# Check whether --enable-sim or --disable-sim was given. +if test "${enable_sim+set}" = set; then + enableval="$enable_sim" + case "${enableval}" in +yes | no) ;; +*) { echo "configure: error: bad value ${enableval} given for --enable-sim option" 1>&2; exit 1; } ;; +esac +fi + + +# Assume simulator can be built with cc. +# If the user passes --enable-sim built it regardless of $(CC). +only_if_gcc=no +only_if_enabled=no +extra_subdirs=common + +# WHEN ADDING ENTRIES TO THIS MATRIX: +# Make sure that the left side always has two dashes. Otherwise you +# can get spurious matches. Even for unambiguous cases, do this as a +# convention, else the table becomes a real mess to understand and maintain. + +case "${target}" in + arm*-*-*) sim_target=arm ;; + strongarm*-*-*) sim_target=arm ;; + thumb*-*-*) sim_target=arm ;; + d10v-*-*) sim_target=d10v ;; + d30v-*-*) + sim_target=d30v + only_if_gcc=yes + extra_subdirs="${extra_subdirs} igen" + ;; + fr30-*-*) sim_target=fr30 ;; + h8300*-*-*) sim_target=h8300 ;; + h8500-*-*) sim_target=h8500 ;; + i960-*-*) sim_target=i960 ;; + m32r-*-*) sim_target=m32r ;; + mips*-*-*) + # The MIPS simulator can only be compiled by gcc. + sim_target=mips + only_if_gcc=yes + extra_subdirs="${extra_subdirs} igen" + ;; + mn10300*-*-*) + # The mn10300 simulator can only be compiled by gcc. + sim_target=mn10300 + only_if_gcc=yes + extra_subdirs="${extra_subdirs} igen" + ;; + mn10200*-*-*) + sim_target=mn10200 + ;; + sh*-*-*) sim_target=sh ;; + powerpc*-*-eabi* | powerpc*-*-solaris* | powerpc*-*-sysv4* | powerpc*-*-elf* | powerpc*-*-linux* ) + # The PowerPC simulator uses the GCC extension long long as well as + # ANSI prototypes, so don't enable it for random host compilers + # unless asked to. + sim_target=ppc + only_if_gcc=yes + #extra_subdirs="${extra_subdirs}" + ;; + v850-*-*) + # The V850 simulator can only be compiled by gcc. + sim_target=v850 + extra_subdirs="${extra_subdirs} igen" + only_if_gcc=yes + ;; + v850e-*-*) + # The V850 simulator can only be compiled by gcc. + sim_target=v850 + extra_subdirs="${extra_subdirs} igen" + only_if_gcc=yes + ;; + v850ea-*-*) + # The V850 simulator can only be compiled by gcc. + sim_target=v850 + extra_subdirs="${extra_subdirs} igen" + only_if_gcc=yes + ;; + w65-*-*) + sim_target=w65 + # The w65 is suffering from gradual decay. + only_if_enabled=yes + ;; + z8k*-*-*) sim_target=z8k ;; + sparc64-*-*) + only_if_gcc=yes + if test "x${with_cgen}" = xyes -o "x${with_cgen_sim}" = xyes ; then + sim_target=sparc + extra_subdirs="${extra_subdirs} testsuite" + else + sim_target=none # Don't build erc32 if sparc64. + fi + ;; + sparclite*-*-* | sparc86x*-*-*) + # The SPARC simulator can only be compiled by gcc. + only_if_gcc=yes + if test "x${with_cgen}" = xyes -o "x${with_cgen_sim}" = xyes ; then + sim_target=sparc + extra_subdirs="${extra_subdirs} testsuite" + else + sim_target=erc32 + fi + ;; + sparc*-*-*) + # The SPARC simulator can only be compiled by gcc. + only_if_gcc=yes + if test "x${with_cgen}" = xyes -o "x${with_cgen_sim}" = xyes ; then + sim_target=sparc + extra_subdirs="${extra_subdirs} testsuite" + else + # Unfortunately erc32 won't build on many hosts, so only enable + # it if the user really really wants it. + only_if_enabled=yes + sim_target=erc32 + fi + ;; + *) sim_target=none ;; +esac + + + + +# Is there a testsuite directory for the target? +testdir=`echo ${target} | sed -e 's/-.*-/-/'` +if test -r ${srcdir}/testsuite/${testdir}/configure ; then + extra_subdirs="${extra_subdirs} testsuite" +fi + + +case "${enable_sim}" in +no) sim_target=none ;; +yes) + if test ${only_if_gcc} = yes ; then + if test "${GCC}" != yes ; then + echo "Can't enable simulator since not compiling with GCC." + sim_target=none + fi + fi + ;; +*) + if test ${only_if_enabled} = yes ; then + sim_target=none + else + if test ${only_if_gcc} = yes ; then + if test "${GCC}" != yes ; then + sim_target=none + fi + fi + fi + ;; +esac + +if test x"${sim_target}" != xnone ; then + configdirs="${extra_subdirs} ${sim_target}" + subdirs="$configdirs" + +fi + +trap '' 1 2 15 +cat > confcache <<\EOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs. It is not useful on other systems. +# If it contains results you don't want to keep, you may remove or edit it. +# +# By default, configure uses ./config.cache as the cache file, +# creating it if it does not exist already. You can give configure +# the --cache-file=FILE option to use a different cache file; that is +# what configure does when it calls configure scripts in +# subdirectories, so they share the cache. +# Giving --cache-file=/dev/null disables caching, for debugging configure. +# config.status only pays attention to the cache file if you give it the +# --recheck option to rerun configure. +# +EOF +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +(set) 2>&1 | + case `(ac_space=' '; set | grep ac_space) 2>&1` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote substitution + # turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + -e "s/'/'\\\\''/g" \ + -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' + ;; + esac >> confcache +if cmp -s $cache_file confcache; then + : +else + if test -w $cache_file; then + echo "updating cache $cache_file" + cat confcache > $cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# Any assignment to VPATH causes Sun make to only execute +# the first set of double-colon rules, so remove it if not needed. +# If there is a colon in the path, we need to keep it. +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d' +fi + +trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15 + +# Transform confdefs.h into DEFS. +# Protect against shell expansion while executing Makefile rules. +# Protect against Makefile macro expansion. +cat > conftest.defs <<\EOF +s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%-D\1=\2%g +s%[ `~#$^&*(){}\\|;'"<>?]%\\&%g +s%\[%\\&%g +s%\]%\\&%g +s%\$%$$%g +EOF +DEFS=`sed -f conftest.defs confdefs.h | tr '\012' ' '` +rm -f conftest.defs + + +# Without the "./", some shells look in PATH for config.status. +: ${CONFIG_STATUS=./config.status} + +echo creating $CONFIG_STATUS +rm -f $CONFIG_STATUS +cat > $CONFIG_STATUS </dev/null | sed 1q`: +# +# $0 $ac_configure_args +# +# Compiler output produced by configure, useful for debugging +# configure, is in ./config.log if it exists. + +ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]" +for ac_option +do + case "\$ac_option" in + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion" + exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;; + -version | --version | --versio | --versi | --vers | --ver | --ve | --v) + echo "$CONFIG_STATUS generated by autoconf version 2.13" + exit 0 ;; + -help | --help | --hel | --he | --h) + echo "\$ac_cs_usage"; exit 0 ;; + *) echo "\$ac_cs_usage"; exit 1 ;; + esac +done + +ac_given_srcdir=$srcdir +ac_given_INSTALL="$INSTALL" + +trap 'rm -fr `echo "Makefile" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 +EOF +cat >> $CONFIG_STATUS < conftest.subs <<\\CEOF +$ac_vpsub +$extrasub +s%@SHELL@%$SHELL%g +s%@CFLAGS@%$CFLAGS%g +s%@CPPFLAGS@%$CPPFLAGS%g +s%@CXXFLAGS@%$CXXFLAGS%g +s%@FFLAGS@%$FFLAGS%g +s%@DEFS@%$DEFS%g +s%@LDFLAGS@%$LDFLAGS%g +s%@LIBS@%$LIBS%g +s%@exec_prefix@%$exec_prefix%g +s%@prefix@%$prefix%g +s%@program_transform_name@%$program_transform_name%g +s%@bindir@%$bindir%g +s%@sbindir@%$sbindir%g +s%@libexecdir@%$libexecdir%g +s%@datadir@%$datadir%g +s%@sysconfdir@%$sysconfdir%g +s%@sharedstatedir@%$sharedstatedir%g +s%@localstatedir@%$localstatedir%g +s%@libdir@%$libdir%g +s%@includedir@%$includedir%g +s%@oldincludedir@%$oldincludedir%g +s%@infodir@%$infodir%g +s%@mandir@%$mandir%g +s%@CC@%$CC%g +s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g +s%@INSTALL_SCRIPT@%$INSTALL_SCRIPT%g +s%@INSTALL_DATA@%$INSTALL_DATA%g +s%@host@%$host%g +s%@host_alias@%$host_alias%g +s%@host_cpu@%$host_cpu%g +s%@host_vendor@%$host_vendor%g +s%@host_os@%$host_os%g +s%@build@%$build%g +s%@build_alias@%$build_alias%g +s%@build_cpu@%$build_cpu%g +s%@build_vendor@%$build_vendor%g +s%@build_os@%$build_os%g +s%@AR@%$AR%g +s%@RANLIB@%$RANLIB%g +s%@target@%$target%g +s%@target_alias@%$target_alias%g +s%@target_cpu@%$target_cpu%g +s%@target_vendor@%$target_vendor%g +s%@target_os@%$target_os%g +s%@HDEFINES@%$HDEFINES%g +s%@CC_FOR_BUILD@%$CC_FOR_BUILD%g +s%@subdirs@%$subdirs%g + +CEOF +EOF + +cat >> $CONFIG_STATUS <<\EOF + +# Split the substitutions into bite-sized pieces for seds with +# small command number limits, like on Digital OSF/1 and HP-UX. +ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script. +ac_file=1 # Number of current file. +ac_beg=1 # First line for current file. +ac_end=$ac_max_sed_cmds # Line after last line for current file. +ac_more_lines=: +ac_sed_cmds="" +while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file + else + sed "${ac_end}q" conftest.subs > conftest.s$ac_file + fi + if test ! -s conftest.s$ac_file; then + ac_more_lines=false + rm -f conftest.s$ac_file + else + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f conftest.s$ac_file" + else + ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file" + fi + ac_file=`expr $ac_file + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_cmds` + fi +done +if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat +fi +EOF + +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories. + + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`" + # A "../" for each directory in $ac_dir_suffix. + ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'` + else + ac_dir_suffix= ac_dots= + fi + + case "$ac_given_srcdir" in + .) srcdir=. + if test -z "$ac_dots"; then top_srcdir=. + else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;; + /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;; + *) # Relative path. + srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix" + top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + + case "$ac_given_INSTALL" in + [/$]*) INSTALL="$ac_given_INSTALL" ;; + *) INSTALL="$ac_dots$ac_given_INSTALL" ;; + esac + + echo creating "$ac_file" + rm -f "$ac_file" + configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure." + case "$ac_file" in + *Makefile*) ac_comsub="1i\\ +# $configure_input" ;; + *) ac_comsub= ;; + esac + + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + sed -e "$ac_comsub +s%@configure_input@%$configure_input%g +s%@srcdir@%$srcdir%g +s%@top_srcdir@%$top_srcdir%g +s%@INSTALL@%$INSTALL%g +" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file +fi; done +rm -f conftest.s* + +EOF +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF + +exit 0 +EOF +chmod +x $CONFIG_STATUS +rm -fr confdefs* $ac_clean_files +test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1 + +if test "$no_recursion" != yes; then + + # Remove --cache-file and --srcdir arguments so they do not pile up. + ac_sub_configure_args= + ac_prev= + for ac_arg in $ac_configure_args; do + if test -n "$ac_prev"; then + ac_prev= + continue + fi + case "$ac_arg" in + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + ;; + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + ;; + *) ac_sub_configure_args="$ac_sub_configure_args $ac_arg" ;; + esac + done + + for ac_config_dir in $configdirs; do + + # Do not complain, so a configure script can configure whichever + # parts of a large source tree are present. + if test ! -d $srcdir/$ac_config_dir; then + continue + fi + + echo configuring in $ac_config_dir + + case "$srcdir" in + .) ;; + *) + if test -d ./$ac_config_dir || mkdir ./$ac_config_dir; then :; + else + { echo "configure: error: can not create `pwd`/$ac_config_dir" 1>&2; exit 1; } + fi + ;; + esac + + ac_popdir=`pwd` + cd $ac_config_dir + + # A "../" for each directory in /$ac_config_dir. + ac_dots=`echo $ac_config_dir|sed -e 's%^\./%%' -e 's%[^/]$%&/%' -e 's%[^/]*/%../%g'` + + case "$srcdir" in + .) # No --srcdir option. We are building in place. + ac_sub_srcdir=$srcdir ;; + /*) # Absolute path. + ac_sub_srcdir=$srcdir/$ac_config_dir ;; + *) # Relative path. + ac_sub_srcdir=$ac_dots$srcdir/$ac_config_dir ;; + esac + + # Check for guested configure; otherwise get Cygnus style configure. + if test -f $ac_sub_srcdir/configure; then + ac_sub_configure=$ac_sub_srcdir/configure + elif test -f $ac_sub_srcdir/configure.in; then + ac_sub_configure=$ac_configure + else + echo "configure: warning: no configuration information is in $ac_config_dir" 1>&2 + ac_sub_configure= + fi + + # The recursion is here. + if test -n "$ac_sub_configure"; then + + # Make the cache file name correct relative to the subdirectory. + case "$cache_file" in + /*) ac_sub_cache_file=$cache_file ;; + *) # Relative path. + ac_sub_cache_file="$ac_dots$cache_file" ;; + esac + case "$ac_given_INSTALL" in + [/$]*) INSTALL="$ac_given_INSTALL" ;; + *) INSTALL="$ac_dots$ac_given_INSTALL" ;; + esac + + echo "running ${CONFIG_SHELL-/bin/sh} $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_sub_srcdir" + # The eval makes quoting arguments work. + if eval ${CONFIG_SHELL-/bin/sh} $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_sub_srcdir + then : + else + { echo "configure: error: $ac_sub_configure failed for $ac_config_dir" 1>&2; exit 1; } + fi + fi + + cd $ac_popdir + done +fi + + +exit 0 diff --git a/sim/configure.in b/sim/configure.in new file mode 100644 index 00000000000..5e316da9ece --- /dev/null +++ b/sim/configure.in @@ -0,0 +1,187 @@ +dnl Process this file with autoconf to produce a configure script. +AC_PREREQ(2.12.1)dnl +AC_INIT(Makefile.in) + +AC_PROG_CC +AC_PROG_INSTALL +AC_CHECK_TOOL(AR, ar) +AC_CHECK_TOOL(RANLIB, ranlib, :) + +AC_CONFIG_AUX_DIR(`cd $srcdir;pwd`/..) +AC_CANONICAL_SYSTEM +AC_ARG_PROGRAM +AC_PROG_CC +AC_SUBST(CFLAGS) +AC_SUBST(HDEFINES) +AR=${AR-ar} +AC_SUBST(AR) +AC_PROG_RANLIB + +# Put a plausible default for CC_FOR_BUILD in Makefile. +AC_C_CROSS +if test "x$cross_compiling" = "xno"; then + CC_FOR_BUILD='$(CC)' +else + CC_FOR_BUILD=gcc +fi +AC_SUBST(CC_FOR_BUILD) + +# If a cpu ever has more than one simulator to choose from, use +# --enable-sim=... to choose. +AC_ARG_ENABLE(sim, +[ --enable-sim ], +[case "${enableval}" in +yes | no) ;; +*) AC_MSG_ERROR(bad value ${enableval} given for --enable-sim option) ;; +esac]) + +# Assume simulator can be built with cc. +# If the user passes --enable-sim built it regardless of $(CC). +only_if_gcc=no +only_if_enabled=no +extra_subdirs=common + +# WHEN ADDING ENTRIES TO THIS MATRIX: +# Make sure that the left side always has two dashes. Otherwise you +# can get spurious matches. Even for unambiguous cases, do this as a +# convention, else the table becomes a real mess to understand and maintain. + +case "${target}" in + arm*-*-*) sim_target=arm ;; + strongarm*-*-*) sim_target=arm ;; + thumb*-*-*) sim_target=arm ;; + d10v-*-*) sim_target=d10v ;; + d30v-*-*) + sim_target=d30v + only_if_gcc=yes + extra_subdirs="${extra_subdirs} igen" + ;; + fr30-*-*) sim_target=fr30 ;; + h8300*-*-*) sim_target=h8300 ;; + h8500-*-*) sim_target=h8500 ;; + i960-*-*) sim_target=i960 ;; + m32r-*-*) sim_target=m32r ;; + mips*-*-*) + # The MIPS simulator can only be compiled by gcc. + sim_target=mips + only_if_gcc=yes + extra_subdirs="${extra_subdirs} igen" + ;; + mn10300*-*-*) + # The mn10300 simulator can only be compiled by gcc. + sim_target=mn10300 + only_if_gcc=yes + extra_subdirs="${extra_subdirs} igen" + ;; + mn10200*-*-*) + sim_target=mn10200 + ;; + sh*-*-*) sim_target=sh ;; + powerpc*-*-eabi* | powerpc*-*-solaris* | powerpc*-*-sysv4* | powerpc*-*-elf* | powerpc*-*-linux* ) + # The PowerPC simulator uses the GCC extension long long as well as + # ANSI prototypes, so don't enable it for random host compilers + # unless asked to. + sim_target=ppc + only_if_gcc=yes + #extra_subdirs="${extra_subdirs}" + ;; + v850-*-*) + # The V850 simulator can only be compiled by gcc. + sim_target=v850 + extra_subdirs="${extra_subdirs} igen" + only_if_gcc=yes + ;; + v850e-*-*) + # The V850 simulator can only be compiled by gcc. + sim_target=v850 + extra_subdirs="${extra_subdirs} igen" + only_if_gcc=yes + ;; + v850ea-*-*) + # The V850 simulator can only be compiled by gcc. + sim_target=v850 + extra_subdirs="${extra_subdirs} igen" + only_if_gcc=yes + ;; + w65-*-*) + sim_target=w65 + # The w65 is suffering from gradual decay. + only_if_enabled=yes + ;; + z8k*-*-*) sim_target=z8k ;; + sparc64-*-*) + only_if_gcc=yes + if test "x${with_cgen}" = xyes -o "x${with_cgen_sim}" = xyes ; then + sim_target=sparc + extra_subdirs="${extra_subdirs} testsuite" + else + sim_target=none # Don't build erc32 if sparc64. + fi + ;; + sparclite*-*-* | sparc86x*-*-*) + # The SPARC simulator can only be compiled by gcc. + only_if_gcc=yes + if test "x${with_cgen}" = xyes -o "x${with_cgen_sim}" = xyes ; then + sim_target=sparc + extra_subdirs="${extra_subdirs} testsuite" + else + sim_target=erc32 + fi + ;; + sparc*-*-*) + # The SPARC simulator can only be compiled by gcc. + only_if_gcc=yes + if test "x${with_cgen}" = xyes -o "x${with_cgen_sim}" = xyes ; then + sim_target=sparc + extra_subdirs="${extra_subdirs} testsuite" + else + # Unfortunately erc32 won't build on many hosts, so only enable + # it if the user really really wants it. + only_if_enabled=yes + sim_target=erc32 + fi + ;; + *) sim_target=none ;; +esac + + + + +# Is there a testsuite directory for the target? +testdir=`echo ${target} | sed -e 's/-.*-/-/'` +if test -r ${srcdir}/testsuite/${testdir}/configure ; then + extra_subdirs="${extra_subdirs} testsuite" +fi + + +case "${enable_sim}" in +no) sim_target=none ;; +yes) + if test ${only_if_gcc} = yes ; then + if test "${GCC}" != yes ; then + echo "Can't enable simulator since not compiling with GCC." + sim_target=none + fi + fi + ;; +*) + if test ${only_if_enabled} = yes ; then + sim_target=none + else + if test ${only_if_gcc} = yes ; then + if test "${GCC}" != yes ; then + sim_target=none + fi + fi + fi + ;; +esac + +if test x"${sim_target}" != xnone ; then + configdirs="${extra_subdirs} ${sim_target}" + AC_CONFIG_SUBDIRS($configdirs) +fi + +AC_OUTPUT(Makefile) + +exit 0 diff --git a/sim/d10v/ChangeLog b/sim/d10v/ChangeLog new file mode 100644 index 00000000000..73b8c9287a6 --- /dev/null +++ b/sim/d10v/ChangeLog @@ -0,0 +1,974 @@ +1999-01-26 Jason Molenda (jsm@bugshack.cygnus.com) + + * simops.c (OP_5607): Correct saturation comparison/assignment. + (OP_1201, OP_1203, OP_17001200, OP_17001202, + OP_2A00, OP_2800, OP_2C00, OP_3200, OP_3201, + OP_1001, OP_1003, OP_17001000, OP_17001002): Ditto. + +1999-01-26 Jason Molenda (jsm@bugshack.cygnus.com) + + * simops.c (OP_5605): Sign extend MIN32 and MAX32 before saturation + comparison. + (OP_5607): Ditto. + (OP_2A00): Ditto. + (OP_2800): Ditto. + +1999-01-13 Jason Molenda (jsm@bugshack.cygnus.com) + + * simops.c (OP_1223): Sign extend MIN32 and MAX32 before saturation + comparison. + +Tue Nov 24 17:04:43 1998 Andrew Cagney + + * simops.c (sys/syscall.h): Include targ-vals.h instead. + (SYS_*): Replace with TARGET_SYS_*. + + * Makefile.in: Add dependency on targ-vals.h. + (NL_TARGET): Define as NL_TARGET_d10v. + +Wed Sep 30 00:06:32 1998 Andrew Cagney + + * interp.c (xfer_mem): Missing break, instruction memory case + flowed into unified memory case. + +Wed Sep 30 10:14:18 1998 Nick Clifton + + * simops.c: If load instruction with auto increment/decrement + addressing is used when the destination register is the same as + the address register, then ignore the auto increment/decrement. + +Tue Apr 28 18:33:31 1998 Geoffrey Noer + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Sun Apr 26 15:31:55 1998 Tom Tromey + + * configure: Regenerated to track ../common/aclocal.m4 changes. + * config.in: Ditto. + +Sun Apr 26 15:20:23 1998 Tom Tromey + + * acconfig.h: New file. + * configure.in: Reverted change of Apr 24; use sinclude again. + +Fri Apr 24 14:16:40 1998 Tom Tromey + + * configure: Regenerated to track ../common/aclocal.m4 changes. + * config.in: Ditto. + +Fri Apr 24 11:20:06 1998 Tom Tromey + + * configure.in: Don't call sinclude. + +Fri Apr 24 11:04:46 1998 Andrew Cagney + + * interp.c (struct hash_entry): OPCODE and MASK are unsigned. + + * d10v_sim.h (remote-sim.h, sim-config.h): Include. + +Sat Apr 4 20:36:25 1998 Andrew Cagney + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Wed Apr 1 12:59:17 1998 Andrew Cagney + + * simops.c (trace_input_func): Use move_from_cr / CREGS to obtain + up-to-date CR value. + (OP_OP_1000000, add3): Trace inputs before performing add. + (OP_5F00, <*>): Trace input registers before making system call. + (OP_5F00, ): Trace R0, R1 not REGn. + (OP_5F00, ): Always return 47. + + * d10v_sim.h (SLOT, SLOT_NR, SLOT_PEND_MASK, SLOT_PEND, + SLOT_DISCARD, SLOT_FLUSH): Define. An implementation of write + back slots. + (struct _state): Add struct slot slot to global state variable. + (struct _state): Delete fields SM, EA, DB, DM, IE, RP, MD, FX, ST, + F0, F1, C from global State variable. + (struct _state): Add struct trace to global State variable. + (GPR, SET_GPR): Define. SET_GPR uses SLOT_PEND. + (PSW*, SET_PSW*): Define. SET_PSW* uses SET_CREG. + (CREG, SET_CREG, SET_*): Define. SET_CREG uses func move_to_cr. + (INC_ADDR): Re-implement. Use SET_GPR to update registers. + (JMP): Re-implement. Use SET_* to update registers. + + * interp.c: Use new SET_* et.al. macros to fetch / store + registers. + (get_operands): Squirrel away trace values at start of each + operand decode. + (do_2_short): Flush pending writes before issuing second + instruction. + (sim_resume): Flush pending writes at end of instruction cycle. + (sim_fetch_register, sim_store_register, sim_create_inferior): + After scheduling updates to registers using SET_*, flush updates. + (sim_resume): Re-order handling of RPT/repeat and IBA/hbreak so + that each sets pc using SET_* and last SET_* eventually winds out. + + * simops.c: Use new SET_* et.al. macros to fetch / store + registers. + (move_to_cr): Add MASK argument for selective update of CREG bits. + Re-implement using new SET_* macros. + (trace_output_func, trace_output): Delete. Replace with. + (do_trace_output_flush, trace_output_finish, trace_output_40, + trace_output_32, trace_output_16, trace_output_void, + trace_output_flag): New functions. Handle specific trace cases. + (OP_*): Re-write tracing to use new trace_output_* functions. + (OP_*): Re-write to use new SET_* et.al. macros. + (FUNC, PARM[1-4], RETVAL, RETVAL32): Redo definition. + (RETVAL_HIGH, RETVAL_LOW): Delete, use RETVAL32. + +Wed Apr 1 12:55:18 1998 Andrew Cagney + + * configure.in (SIM_AC_OPTION_WARNINGS): Add. + configure: Re-generate. + +Fri Mar 27 16:15:52 1998 Andrew Cagney + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Wed Mar 25 12:35:29 1998 Andrew Cagney + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Wed Mar 18 12:38:12 1998 Andrew Cagney + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Tue Feb 17 12:38:42 1998 Andrew Cagney + + * interp.c (sim_store_register, sim_fetch_register): Pass in + length parameter. Return -1. + +Mon Oct 27 14:43:33 1997 Fred Fish + + * (dmem_addr): If address is illegal or in I/O space, signal a bus + error. Allocate unified memory on demand. Fix DMEM address + calculations. + +Mon Feb 16 10:27:53 1998 Andrew Cagney + + * simops.c (OP_5F20): Implement "dbt". + (OP_5F60): Implement "rtd". + + * d10v_sim.h (DPC_CR): Define enum. + (DBT_VECTOR_START): Define + (DPSW, DPC): Define. + +Fri Feb 13 15:15:58 1998 Andrew Cagney + + * simops.c (move_to_cr): Sync regs[SP_IDX] with State.sp according + to PSW:SM. + + * d10v_sim.h (struct _state): Add sp, as holding area for SPI/SPU. + (SP_IDX): Define. + +Wed Feb 11 16:53:49 1998 Andrew Cagney + + * simops.c (OP_5F00): Call error instead of abort for unknown + syscalls. + + * d10v_sim.h (enum): Define DPSW_CR. + + * simops.c (move_to_cr): Mask out hardwired zero bits in DPSW. + +Tue Feb 10 18:28:38 1998 Andrew Cagney + + * interp.c (sim_write_phys): Delete. + (sim_load): Call sim_load_file with sim_write and LMA. + +Mon Feb 9 12:05:01 1998 Andrew Cagney + + * interp.c: Rewrite xfer_mem so that it translates addresses as - + 0x00... - DMAP translated memory, 0x01... IMAP translated memory, + 0x10... - on-chip data, 0x11... - on-chip insn, 0x12... - unified + memory. + (pc_addr): Delete. + (imem_addr): New function - translate IMEM address. + (sim_resume): Use imem_addr to translate insn address, abort if + translation failed. + (sim_create_inferior): Write ARGV to memory using sim_write. Pass + argc/argv using r0/r1 not r2/r3. + (sim_size): Do not initialize IMAP/DMAP here. + (sim_open): Call sim_create_inferior and sim_size to initialize + the system. + (sim_create_inferior): Initialize IMAP/DMAP to hardware reset + defaults. + (init_system): Delete. + (xfer_mem, sim_fetch_register, sim_store_register): Do not call + init_system. + (decode_pc): Check prog_bfd is defined before looking up .text + section. + +Sun Feb 1 16:47:51 1998 Andrew Cagney + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Sat Jan 31 18:15:41 1998 Andrew Cagney + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Sun Jan 25 22:23:01 1998 Michael Meissner + + * interp.c (sim_stop_reason): Exit status is now in r0, not r2. + +Sat Jan 24 19:00:30 1998 Michael Meissner + + * d10v_sim.h (DEBUG_TRAP): New debug flag. + + * simops.c (OP_5F00): If DEBUG_TRAP is on, turn traps 0-14 into + printing the registers. + +Thu Jan 22 17:54:01 1998 Michael Meissner + + * simops.c (op_types): New ABI, args are r0..r3, system call # is + in r4. + (trace_{in,out}put_func): Ditto. + (OP_4900): Ditto. + (OP_24800000): Ditto. + (OP_4D00): Ditto. + (OP_5F00): Ditto. + +Thu Jan 22 14:30:36 1998 Fred Fish + + * interp.c (UMEM_SEGMENTS): New define, set to 128. + (sim_size): Use UMEM_SEGMENTS rather than hardwired constant. + (sim_close): Reset prog_bfd to NULL after closing it. Also + reset prog_bfd_was_opened_p after closing prog_bfd. + (sim_load): Reset prog_bfd_was_opened_p after closing prog_bfd. + (sim_create_inferior): Get start address from abfd not prog_bfd. + (xfer_mem): Do bounds checking on addresses and return zero length + read/write on bad addresses, rather than aborting. Prepare to + be able to handle xfers that cross segment boundaries, but not + yet implemented. Only emit debug message when d10v_debug is + set as well as DEBUG being defined. + +Mon Jan 19 22:26:29 1998 Doug Evans + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Mon Dec 15 23:17:11 1997 Andrew Cagney + + * configure: Regenerated to track ../common/aclocal.m4 changes. + * config.in: Ditto. + +Tue Dec 9 10:28:31 1997 Andrew Cagney + + * d10v_sim.h (RPT_S): Index cregs with RPT_S_CR not RPT_E_CR. + (BPSW): Ditto for BPSW_CR and not PSW_CR. + + * simops.c (OP_5F40): JMP to BPC instead of assigning PC directly. + +Mon Dec 8 12:58:33 1997 Andrew Cagney + + * simops.c (OP_5F00): From Martin Hunt . Change + reserved trap from 0 to 15. Add trap emulation code for 0-14. + + * interp.c (sim_resume): From Martin Hunt . Check + IBA for SDBT. + + * d10v_sim.h (AE_VECTOR_START, RIE_VECTOR_START, + SDBT_VECTOR_START, TRAP_VECTOR_START): Define. + + * simops.c (OP_5F00): For "trap", mask out all but SM bit in PSW, + use move_to_cr. + (OP_5F00): For "trap", update BPSW with move_to_cr. + +Fri Dec 5 15:31:17 1997 Andrew Cagney + + * d10v_sim.h (enum): Enumerate CR register names. + (enum): Enumerate PSW bit values. + (PSW): Obtain value uing move_from_cr. + (MOD_S, MOD_E, BPSW): Make r-values. + (move_from_cr, move_to_cr): Declare functions. + + * interp.c (sim_fetch_register, sim_store_register): Use + move_from_cr and move_to_cr for CR register transfers. + + * simops.c (move_from_cr, move_to_cr): New functions. + (OP_5F40): Move BPSW to PSW using move_to_cr and move_from_cr. + (OP_5600): For "mvtc", use function move_to_cr. + (OP_5200): For "mvfc", use function move_from_cr. + +Fri Dec 5 13:33:14 1997 Andrew Cagney + + * simops.c (OP_5600): For "mvtc" MOD_E and MOD_S, ensure that the + LSbit is zero. + +Thu Dec 4 09:21:05 1997 Doug Evans + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Thu Dec 4 16:51:02 1997 Andrew Cagney + + * d10v_sim.h (struct _state): Add DM - PSW debug mask. + + * simops.c (OP_5600): For "mvtc", save PSW.DM. + (OP_5200): Ditto for "mvfc". + +Wed Dec 3 17:27:06 1997 Andrew Cagney + + * d10v_sim.h (SEXT56): Define. + + * simops.c (OP_4201): For "rac", sign extend 56 bit value before + it is shifted. + + * d10v_sim.h (MAX32, MIN32, MASK32, MASK40): Re-define using + SIGNED64 macro. + +Tue Dec 2 15:38:34 1997 Fred Fish + + * interp.c (sim_resume): Call do_2_short with LEFT_FIRST or + RIGHT_FIRST, as appropriate, instead of hardcoded ints that + don't match enum values. + +Tue Dec 2 15:01:08 1997 Andrew Cagney + + * simops.c (OP_3A00): For "macu", perform multiply stage using 32 + bit rather than 16 bit precision. + (OP_3C00): For "mulxu", store unsigned product in ACC. + (OP_3800): For "msbu", subtract unsigned product from ACC, + (OP_0): For "sub", compute carry by comparing inputs. + +Tue Dec 2 11:04:37 1997 Andrew Cagney + + * simops.c (OP_1000): For "sub2w", compute carry by comparing + inputs. + +Mon Nov 17 20:57:21 1997 Andrew Cagney + + * simops.c (OP_1): Use 32 bit unsigned arithmetic for subtract, + carry indicated by value > 0xffff. + +Fri Nov 14 12:51:20 1997 Andrew Cagney + + * interp.c (sim_resume): Don't set up SIGINT handler using signal, + handled by client. + (sim_resume): Fix race condition of a direct assignment to + stop_simulator, conditionally call sim_stop. + (sim_stop_reason): Check stop_simulator returning SIGINT. Clear + stop_simulator ready for next sim_resume call. + (sim_ctrl_c): Delete function. + +Thu Nov 13 19:29:34 1997 Andrew Cagney + + * interp.c (sim_resume): For "REP", only check/update the PC when + a branch instruction has not been executed. + +Mon Nov 10 17:50:18 1997 Andrew Cagney + + * simops.c (OP_4201): "rachi". Sign extend bit 40 of ACC. Sign + extend bit 44 all constants. + (OP_4201): Replace GCC specific 0x..LL with SIGNED64 macro. + +Fri Oct 24 10:26:29 1997 Andrew Cagney + + * d10v_sim.h: Include sim-types.h. + (uint8, in816, uiny16, int32, uint32, int64, uint64): Typedef + using unsigned8 et.al. from sim-types.h. + (SEXT32, SEXT40, SEXT44, SEXT60): Replace GCC specific 0x..LL with + SIGNED64 macro. + +Wed Oct 22 14:43:00 1997 Andrew Cagney + + * interp.c (sim_write_phys): New function, write to physical + instead of virtual memory. + + * interp.c (sim_load): Pass lma_p and sim_write_phys to + sim_load_file. + +Mon Oct 13 10:55:07 1997 Fred Fish + + * simops.c (OP_6A01): Change OP_POSTDEC to OP_POSTINC and move + exception generation code to OP_6E01. + (OP_6E01): Change OP_POSTINC to OP_POSTDEC and insert exception + generation code. + +Sat Oct 11 09:02:08 1997 Fred Fish + + * simops.c (OP_6401): postdecrement on r15 is OK, remove exception. + (OP_6601): Ditto. + +Fri Oct 3 09:28:00 1997 Andrew Cagney + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Sat Sep 27 12:51:34 1997 Fred Fish + + * interp.c (pc_addr): Discard upper bit(s) of PC in case + IMAP1 selects unified memory. + * d10v_sim.h (INC_ADDR): Align MOD_E to increment before testing + for end condition. + +Wed Sep 24 17:38:57 1997 Andrew Cagney + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Tue Sep 23 11:04:38 1997 Andrew Cagney + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Mon Sep 22 11:46:20 1997 Andrew Cagney + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Fri Sep 19 17:45:25 1997 Andrew Cagney + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Mon Sep 15 17:36:15 1997 Andrew Cagney + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Wed Sep 10 22:30:24 1997 Martin M. Hunt + + * interp.c (sim_resume): Increment PC at end of rep + loop. + + * simops.c (OP_4201): Fix rachi instruction. + +Thu Sep 4 17:21:23 1997 Doug Evans + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Wed Aug 27 18:13:22 1997 Andrew Cagney + + * configure: Regenerated to track ../common/aclocal.m4 changes. + * config.in: Ditto. + +Tue Aug 26 10:37:49 1997 Andrew Cagney + + * interp.c (sim_kill): Delete. + (sim_create_inferior): Add ABFD argument. + (sim_load): Move setting of PC from here. + (sim_create_inferior): To here. + (start_address): Delete variable. + +Mon Aug 25 17:50:22 1997 Andrew Cagney + + * configure: Regenerated to track ../common/aclocal.m4 changes. + * config.in: Ditto. + +Mon Aug 25 15:39:29 1997 Andrew Cagney + + * interp.c (sim_open): Add ABFD argument. + +Tue May 20 10:14:45 1997 Andrew Cagney + + * interp.c (sim_open): Add callback argument. + (sim_set_callbacks): Remove SIM_DESC argument. + +Thu Apr 24 00:39:51 1997 Doug Evans + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Tue Apr 22 10:29:23 1997 Doug Evans + + * interp.c (sim_open): Undo patch to add -E support. + +Fri Apr 18 13:39:01 1997 Andrew Cagney + + * interp.c (sim_stop): New function. + +Thu Apr 17 02:42:00 1997 Doug Evans + + * Makefile.in (SIM_OBJS): Add sim-load.o. + * d10v_sim.h (exec_bfd): Rename to prog_bfd. + * interp.c: #include bfd.h. + (myname, sim_kind, start_address): New static locals. + (prog_bfd_was_opened_p, prog_bfd): New static locals. + (decode_pc): Update to use prog_bfd. + (sim_open): Set sim_kind, myname. Ignore -E arg. + (sim_close): Close prog_bfd if simulator opened it. + (sim_create_inferior): Return SIM_RC. Delete arg start_address. + (sim_load): Return SIM_RC. New arg abfd. Set start address from bfd. + Call sim_load_file to load file into simulator. + * simops.c (trace_input_func): exec_bfd renamed to prog_bfd. + +Wed Apr 16 16:12:03 1997 Andrew Cagney + + * simops.c (OP_5F00): Only provide system calls SYS_execv, + SYS_wait, SYS_wait, SYS_utime, SYS_time if defined by the host. + +Mon Apr 7 15:45:02 1997 Andrew Cagney + + * configure: Regenerated to track ../common/aclocal.m4 changes. + * config.in: Ditto. + +Wed Apr 2 15:06:28 1997 Doug Evans + + * interp.c (sim_open): New arg `kind'. + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Wed Apr 2 14:34:19 1997 Andrew Cagney + + * configure: Regenerated to track ../common/aclocal.m4 changes. + +Mon Mar 17 15:10:07 1997 Andrew Cagney + + * configure: Re-generate. + +Fri Mar 14 10:34:11 1997 Michael Meissner + + * configure: Regenerate to track ../common/aclocal.m4 changes. + + * simops.c (OP_5F00): Remove old traps 1-3. Make trap 15 the same + as trap 0, which will be deprecated. Only set errno, if an error + in fact was returned. + +Thu Mar 13 12:41:20 1997 Doug Evans + + * interp.c: Delete redundant prototypes of sim_foo fns. + (sim_open): New SIM_DESC result. Argument is now in argv form. + (other sim_*): New SIM_DESC argument. + +Thu Mar 13 10:29:04 1997 Michael Meissner + + * simops.c (trace_{input,output}_func): Call flush_stdout from the + callback functions. + (OP_5F00): Ditto. + (OP_6{4,6,C,A}01): Test for post decrement on the stack pointer. + (OP_{1200,1000000,201,5FE0,1003,17001002}): Fix problems in + setting the carry bit after an add or a subtract. + +Wed Feb 12 16:04:15 1997 Michael Meissner + + * simops.c (OP_{1403,15002A02,3{0,4}0{0,1}}): Only use the bottom + 40 bits of accumulators. Sign/zero extend as appropriate. + +Tue Feb 4 13:33:30 1997 Doug Evans + + * Makefile.in (@COMMON_MAKEFILE_FRAG): Use + COMMON_{PRE,POST}_CONFIG_FRAG instead. + * configure.in: sinclude ../common/aclocal.m4. + * configure: Regenerated. + +Thu Jan 23 11:46:23 1997 Stu Grossman (grossman@critters.cygnus.com) + + * configure configure.in Makefile.in: Update to new configure + scheme which is more compatible with WinGDB builds. + * configure.in: Improve comment on how to run autoconf. + * configure: Re-run autoconf to get new ../common/aclocal.m4. + * Makefile.in: Use autoconf substitution to install common + makefile fragment. + +Fri Dec 27 22:54:05 1996 Angela Marie Thomas (angela@cygnus.com) + + * gencode.c: patch to not #include "d10v_sim.h" which + unecessarily includes bfd.h and causes wingdb configure + to fail. + +Mon Dec 16 13:39:03 1996 Martin M. Hunt + + * interp.c (xfer_mem): Change unified memory to 0x0. + +Thu Nov 28 20:42:56 1996 Michael Meissner + + * simops.c (OP_3E01): Fix tracing information. + (OP_300{0,1}): Do not propigate sign. + +Mon Nov 25 19:47:40 1996 Doug Evans + + * config.in (WORDS_BIGENDIAN): Add. + * configure: Regenerated. + * d10v_sim.h: #include "config.h" + +Sat Nov 23 09:34:50 1996 Michael Meissner + + * gencode.c (write_opcodes): Eliminate warnings when generated + table.c is compiled. + +Wed Nov 20 19:41:40 1996 Michael Meissner + + * interp.c (sim_open): Cast result of calloc, and make sure NULL + was not returned. + (dmem_addr): If address is illegal or in I/O space, signal a bus + error. + (pc_addr): Signal bus error, not illegal instruction for bogus + pc. + +Wed Nov 20 01:23:03 1996 Doug Evans + + * Makefile.in: Delete all stuff moved to ../common/Make-common.in. + (SIM_OBJS,SIM_EXTRA_CFLAGS,SIM_EXTRA_CLEAN): Define. + * configure.in: Simplify using macros in ../common/aclocal.m4. + Call AC_CHECK_HEADERS(unistd.h). + * configure: Regenerated. + * config.in: New file. + * interp.c: #include "callback.h". + * simops.c: #include "config.h". #include if present. + +Fri Nov 8 16:19:55 1996 Martin M. Hunt + + * d10v-sim.h (simops): Add flag is_long. + (State): Add pc_changed. Instructions which update the PC should + use the JMP macro which sets this. + (JMP): New macro. Sets the PC and the pc_changed flag. + + * gencode.c (write_opcodes): Add is_long field. + + * interp.c (lookup_hash): If we blindly apply a short opcode's mask + to a long opcode we could get a false match. Check the opcode size. + (hash): Add a size field to the hash table. + (sim_open): Initialize size field in hash table. + (sim_resume): Change to logic for setting the PC. Used to increment the + PC if it had not been changed. This didn't allow single-instruction loops. + Now checks the flag State.pc_changed. Also now stops when ^C is received. + (dmem_addr): Fix translation of data segments to unified memory. + (sim_ctrl_c): New function. When ^C is received, set stop_simulator flag. + + * simops.c: Changed all branch and jump instructions to use new JMP macro. + (OP_20000000): Corrected trace information to show this is a ldi.l, not + a ldi.s instruction. + +Thu Oct 31 19:13:55 1996 Martin M. Hunt + + * interp.c (sim_fetch_register, sim_store_register): Fix bug where + updating the accumulators was overwriting other parts of the global + State variable. + +Wed Oct 30 17:35:14 1996 Michael Meissner + + * interp.c (bfd.h) Don't include it here any more. + (text{,_start,_end}): Move here from simops.c and make extern. + (decode_pc): New function to return the PC as an address that the + debugger can use. + (dmem_addr): Print decoded PC in error message. + (pc_addr): Ditto. + + * simops.c (bfd.h) Don't include it here any more. + (text{,_start,_end}): Move to simops.c. + (trace_input_func): Move decoding of PC, and looking up .text + start to decode_pc. + + * d10v_sim.h (bfd.h): Include it here. + (text{,_start,_end}): Add external declarations. + (exec_bfd): Ditto. + (decode_pc): Ditto. + +Tue Oct 29 12:13:52 1996 Martin M. Hunt + + * interp.c (sim_size): Now allocates unified memory for imap segments + 0,1,2, and 127. Initializes imap0 and imap1 to 0x1000. Initializes dmap to 0. + (sim_write): Just call xfer_mem(). + (sim_read): Just call xfer_mem(). + (xfer_mem): New function. Does appropriate memory mapping and copies bytes. + (dmem_addr): New function. Reads dmap register and translates data + addresses to local addresses. + (pc_addr): New function. Reads imap register and computes local address + corresponding to contents of the PC. + (sim_resume): Change to use pc_addr(). + (sim_create_inferior): Change reinitialization code. Also reinitializes + imap[01] and dmap. + (sim_fetch_register): Add fake registers 32,33,34 for imap0, imap1, and dmap. + (sim_store_register): Add fake registers 32,33,34 for imap0, imap1, and dmap. + + * simops.c (MEMPTR): Redefine to use dmem_addr(). + (OP_5F00): Replace references to STate.imem with dmem_addr(). + + * d10v-sim.h (State): Remove mem_min and mem_max. Add umem[128]. + (RB,SW,RW,SLW,RLW): Redefine to use dmem_addr(). + (IMAP0,IMAP1,DMAP,SET_IMAP,SET_IMAP1,SET_DMAP): Define. + +Tue Oct 22 15:22:33 1996 Michael Meissner + + * d10v_sim.h (_ins_type): Reorganize, so that we can provide + better statistics, like not counting NOPS as parallel + instructions, and printing total cycles. + (ins_type_counters): Make unsigned long. + (left_nops,right_nops): Fold into ins_type_counters. + + * simops.c (trace_input_func): Print new instruction types. + Handle OP_R2R3 as input types. + (OP_{38000000,7000}): Correctly sign extend bytes. + (OP_5E00): Don't count NOPs as parallel instructions. + (OP_460B): Remove unused variable. + (OP_5F00): Ditto. + + * interp.c (ins_type_counters): Make unsigned long. + (left_nops,right_nops): Delete. + (most functions): Add prototypes. + (INLINE): If GCC and optimize define as __inline__. + ({,lookup_}hash,get_operands): Declare as INLINE. + (do_parallel): Count conditional operations. + (add_commas): New function, to add commas every 3 digits. + (sim_size): Call add_commas to print numbers. + (sim_{open,resume}): Delete unused variables. + (sim_info): Provide better statistics. + (sim_read): Add int return type. + +Mon Oct 21 16:16:26 1996 Martin M. Hunt + + * interp.c (sim_resume): Change the way single-stepping and exceptions + are handled so single-stepping works again. + +Thu Oct 17 12:24:16 1996 Michael Meissner + + * endian.c: Optimize simulated loads/stores on x86, AIX, and big + endian hosts. + + * configure.in (--enable-sim-bswap): New switch to enable using + the BSWAP instruction on x86's. + * configure: Regenerate. + + * Makefile.in ({SWAP,CONFIG}_CFLAGS): Add --enable-sim-bswap + support. + +Wed Oct 16 13:50:06 1996 Michael Meissner + + * endian.c: New file. Move endian functions here from interp.c. + Optimize code, and make it work as either inline functions or as a + separate file. + + * interp.c: Move endian functions from here to endian.c. + + * Makefile.in (INCLUDE): Add endian.c. + (run,libsim.a): Add dependency on endian.o. + (endian.o): Add dependency. + + * d10v_sim.h (read/write support): Always go through the machine + independent endian functions. If compiling with GCC and + optimizing, include endian.c so the endian functions are inlined. + + * simops.c (OP_5F00): Correct tracing of accumulators. + +Tue Oct 15 10:57:50 1996 Michael Meissner + + * simops.c (OP_5F00): Add support for getpid, kill system calls. + + * interp.c (do_{2_short,parallel}): If an exception is raised, + don't execute the second instruction. + +Sat Oct 12 22:17:43 1996 Michael Meissner + + * simops.c (OP_{31000000,6601,6201,6200}): Store address in a + temporary in case the register is overriden when loading. + (OP_6200): Output type is OP_DREG for tracing. + +Fri Oct 4 23:46:18 1996 Michael Meissner + + * d10v_sim.h (struct _state): Add mem_{min,max} fields. + + * interp.c (sim_size): Initialize mem_{min,max} fields. + (sim_write): Update mem_{min,max} fields. + (sim_resume): If PC is not in the minimum/maximum memory range, + abort. + (sim_create_inferior): Preserve mem_{min,max} fields. + +Fri Sep 27 13:11:58 1996 Mark Alexander + + * simops.c (OP_5F00): Add support for time() system call. + +Wed Sep 25 16:31:41 1996 Michael Meissner + + * simops.c (OP_{6E01,6A01,6E1F,6A00}): Print both words being + stored if tracing. + (OP_5F00,trace_{in,out}put_func): Add finer grain tracing for + system calls. + +Mon Sep 23 17:55:30 1996 Michael Meissner + + * simops.c (op_types): Add OP_{CONSTANT8,R2,R3}. + (trace_input_func): Add support for OP_{CONSTANT8,R2,R3}. + (OP_{4900,24800000,4800,4A00,4B00,4D00,4C00}): Add OP_R2 and OP_R3 + to call/subroutine returns to trace the first two arguments and + the return value. For small jumps, use CONSTANT8, not CONSTANT16. + +Fri Sep 20 15:36:45 1996 Martin M. Hunt + + * interp.c (sim_create_inferior): Reinitialize State every time + sim_create_inferior() is called. + +Thu Sep 19 21:38:20 1996 Michael Meissner + + * simops.c (OP_{401,2000000,601,3000000,23000000}): Get sign right + on comparisons. + (OP_401): Fix tracing information. + +Thu Sep 19 10:30:22 1996 Michael Meissner + + * simops.c (SIZE_{PC,LINE_NUMBER}): New default sizes for output. + (trace_input_func): Use them. + (trace_input_func): Make sure there is a trailing space after the + instruction. + (OP_6200): Fix tracing info. + + * Makefile.in (run): Add dependencies on libbfd.a and + libiberity.a. + +Wed Sep 18 09:13:25 1996 Michael Meissner + + * d10v_sim.h (DEBUG_INSTRUCTION): New debug value to include line + numbers and function names in debug trace. + (DEBUG): If not defined, set to DEBUG_TRACE, DEBUG_VALUES, and + DEBUG_LINE_NUMBER. + (SIG_D10V_{STOP,EXIT}): Values to represent the stop instruction + and exit system call trap being executed. + + * interp.c (sim_stop_reason): Set exit code correctly for stop + instruction and exit system call trap. + + * configure.in (--enable-sim-cflags): Remove trace case. + (--enable-sim-debug): New switch to set the debug values. + * configure: Regenerate. + + * simops.c (trace_{input,output}_func): Rename from + trace_{input,output}. + (trace_{input,output}): Call trace_{input,output}_func if + d10v_debug is non-zero. + (SIZE_INSTRUCTION): Cut down to 8. + (SIZE_OPERANDS): Cut down to 18. + (SIZE_LOCATION): New value for size of line number, function name + field. + (init_text_p,text{,_start,_end}): New static variables for + printing line number and function name. + (exec_bfd): New external that run.c sets. + (trace_input_func): Print line number and function name if + available and if desired. + (OP_4E09): Don't print out DBT message. + (OP_5FE0): Set exception field to SIG_D10V_STOP. + (OP_5F00): Set exception field to SIG_D10V_EXIT. + +Sat Sep 14 22:18:43 1996 Michael Meissner + + * interp.c (do_2_short): If the instruction encodes jump->ins, + don't do the second instruction if the jump succeeds. + +Fri Sep 13 22:35:19 1996 Michael Meissner + + * simops.c (OP_5F00): Use unknown traps to print all GPRs, + accumulators, PC, and F0/F1/C flags. + +Thu Sep 12 12:50:11 1996 Mark Alexander + + * simops.c (OP_5F00): Fix problems with system calls. + +Thu Sep 12 12:19:28 1996 Michael Meissner + + * simops.c (OP_5F00): Correct tracing information for trap. + +Wed Sep 11 18:55:50 1996 Michael Meissner + + * Makefile.in (CSEARCH): Correctly find opcodes directory. + +Mon Sep 9 13:27:26 1996 Michael Meissner + + * simops.c (trace_output): Properly align accumulator output. + (OP_3{0,2,4}00): Properly parenthesize test expression. Add error + if shift count is too high. + (OP_4E{00,02,04,20,22,40,42}): Make tests agree with book. + (OP_4E09): Make cpfg properly trace the input flags. + (op_types): Add OP_FLAG_OUTPUT. + (trace_{input,output}): Support OP_FLAG_OUTPUT. + (OP_31000000): This ld2w varient is a 16-bit memory reference, not + an 8-bit memory reference instruction for tracing purposes. + (OP_201): Addi needs to set the carry. + +Fri Sep 6 17:56:17 1996 Martin M. Hunt + + * simops.c (OP_2600, OP_2601): Changed min and max comparisons + to use signed register values. + +Wed Sep 4 11:35:17 1996 Michael Meissner + + * d10v_sim.h (DEBUG_*): Add bit flags for controlling debug + output. + (_ins_type): New enumeration to specify which container an + instruction is in, and whether it is part of a parallel operation. + (_state): Add ins_type field. + ({,u}int{8,16,32,64}): Use limits.h to size the appropriate types. + (ins_type_counters): Counters for the various instruction types. + ({left,right}_nops): Counters for the number of nops in each + container. + (d10v_debug): New variable to indicate whether debugging is turned + on. + + * simops.c: (all functions): Change all #ifdef DEBUG code so that + the input and output values can be traced, along with the + instruction type. Make the -t option enable tracing. + (all functions): Change printf calls to use the printf_filtered + function in the callback table. + + * interp.c (_leftright): New enumeration to say whether 2 short + instructions are done left first or right first. + (do_{long,2_short,parallel}): Indicate in the machine state which + type of instruction this is. Count each of the types of + instructions executed. + (sim_size): Only print the memory sizes if DEBUG_MEMSIZE debug + flag is set. + (sim_resume): Pass left/right indication to do_2_short. + (all functions): Change printf calls to use the printf_filtered + function in the callback table. + (sim_trace): Turn on debug flag if DEBUG was defined, and call + sim_resume. + (sim_info): Print out statistics on instructions. + (sim_{trace,create_inferior}): Eliminate extraneous output unless + debugging. + (sim_open): If args == -t and DEBUG was defined, set d10v_debug. + Only initialize the hash table the first time sim_open is called. + + * Makefile.in: Make objects depend on d10v_sim.h. + ({,SIM_}CFLAGS): Include configure dependent switches. Setting + CFLAGS does not override host/target defines or SIM_CFLAGS. + (CC_FOR_BUILD,gencode): Use CC_FOR_BUILD to compile gencode. + (run): By default, the math library is not needed to be linked + in. + ({BFD,LIBIBERTY}_LIB): Define as variables so they can be + overridden. + (VPATH): Don't set to anything but @srcdir@ to work with non-GNU + makes. + ({run,callback}.o): Provide explicit paths to their appropriate + source directories. + (gencode{,.o},d10v-opc.o): Split compilation into creating object + and linking. Instead of linking in libopcodes.a, just compile + d10v-opc.o directly to handle canadian cross. + (CSEARCH): Add opcodes directory. + + * configure.in (--enable-sim-cflags): New switch to allow user to + set the defaults. + (CC_FOR_BUILD): Deal with canadian crosses. + * configure: Regenerate. + +Wed Sep 04 04:45:34 1996 Mark Alexander + + * simops.c: Include correct syscall.h for d10v, not host's. + Fix #ifdef SYS_stat. + +Tue Sep 3 14:00:04 1996 Michael Meissner + + * simops.c (OP_5F00): Wrap all SYS_xxx traps with #ifdef. + Add trap 2 to be printf and trap 3 to be putchar. + +Wed Aug 28 21:42:34 1996 Mark Alexander + + * Makefile.in, d10v_sim.h, interp.c, simops.c: Add support + for low-level system calls. + +Wed Aug 28 17:33:19 1996 Martin M. Hunt + + * Makefile.in, d10v_sim.h, interp.c: Fix byte-order problems. + +Mon Aug 26 18:30:28 1996 Martin M. Hunt + + * d10v_sim.h (SEXT32): Added. + * interp.c: Commented out printfs. + * simops.c: Fixed error in sb and st2w. + +Thu Aug 15 13:30:03 1996 Martin M. Hunt + + * Makefile.in, d10v_sim.h, interp.c, simops.c: Added remaining + DSP instructions. Added modulo addressing. + +Sun Aug 11 12:57:15 1996 Martin M. Hunt + + * Makefile.in, d10v_sim.h, interp.c, simops.c: Snapshot. + +Fri Aug 2 17:44:24 1996 Martin M. Hunt + + * d10v_sim.h, simops.c: Snapshot. + +Thu Aug 1 17:05:24 1996 Martin M. Hunt + + * ChangeLog, Makefile.in, configure, configure.in, d10v_sim.h, + gencode.c, interp.c, simops.c: Created. + diff --git a/sim/d10v/Makefile.in b/sim/d10v/Makefile.in new file mode 100644 index 00000000000..07323275dec --- /dev/null +++ b/sim/d10v/Makefile.in @@ -0,0 +1,52 @@ +# Makefile template for Configure for the D10v sim library. +# Copyright (C) 1996, 1997 Free Software Foundation, Inc. +# Written by Cygnus Support. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +## COMMON_PRE_CONFIG_FRAG + +SIM_OBJS = interp.o table.o simops.o endian.o sim-load.o +SIM_EXTRA_CLEAN = clean-extra + +INCLUDE = d10v_sim.h $(srcroot)/include/callback.h targ-vals.h endian.c + +# This selects the d10v newlib/libgloss syscall definitions. +NL_TARGET = -DNL_TARGET_d10v + +## COMMON_POST_CONFIG_FRAG + +simops.h: gencode + ./gencode -h >$@ + +table.c: gencode simops.h + ./gencode >$@ + +gencode.o: gencode.c $(INCLUDE) + $(CC_FOR_BUILD) $(BUILD_CFLAGS) -c $(srcdir)/gencode.c + +d10v-opc.o: $(srcdir)/../../opcodes/d10v-opc.c + $(CC_FOR_BUILD) $(BUILD_CFLAGS) -c $(srcdir)/../../opcodes/d10v-opc.c + +gencode: gencode.o d10v-opc.o + $(CC_FOR_BUILD) $(BUILD_CFLAGS) -o gencode gencode.o d10v-opc.o $(BUILD_LIB) + +clean-extra: + rm -f table.c simops.h gencode + +interp.o: interp.c table.c $(INCLUDE) +simops.o: simops.c $(INCLUDE) +endian.o: endian.c $(INCLUDE) +table.o: table.c diff --git a/sim/d10v/acconfig.h b/sim/d10v/acconfig.h new file mode 100644 index 00000000000..f9b87a10c60 --- /dev/null +++ b/sim/d10v/acconfig.h @@ -0,0 +1,15 @@ + +/* Define to 1 if NLS is requested. */ +#undef ENABLE_NLS + +/* Define as 1 if you have catgets and don't want to use GNU gettext. */ +#undef HAVE_CATGETS + +/* Define as 1 if you have gettext and don't want to use GNU gettext. */ +#undef HAVE_GETTEXT + +/* Define as 1 if you have the stpcpy function. */ +#undef HAVE_STPCPY + +/* Define if your locale.h file contains LC_MESSAGES. */ +#undef HAVE_LC_MESSAGES diff --git a/sim/d10v/config.in b/sim/d10v/config.in new file mode 100644 index 00000000000..1f87a2bee4e --- /dev/null +++ b/sim/d10v/config.in @@ -0,0 +1,158 @@ +/* config.in. Generated automatically from configure.in by autoheader. */ + +/* Define if using alloca.c. */ +#undef C_ALLOCA + +/* Define to empty if the keyword does not work. */ +#undef const + +/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems. + This function is required for alloca.c support on those systems. */ +#undef CRAY_STACKSEG_END + +/* Define if you have alloca, as a function or macro. */ +#undef HAVE_ALLOCA + +/* Define if you have and it should be used (not on Ultrix). */ +#undef HAVE_ALLOCA_H + +/* Define if you have a working `mmap' system call. */ +#undef HAVE_MMAP + +/* Define as __inline if that's what the C compiler calls it. */ +#undef inline + +/* Define to `long' if doesn't define. */ +#undef off_t + +/* Define if you need to in order for stat and other things to work. */ +#undef _POSIX_SOURCE + +/* Define as the return type of signal handlers (int or void). */ +#undef RETSIGTYPE + +/* Define to `unsigned' if doesn't define. */ +#undef size_t + +/* If using the C implementation of alloca, define if you know the + direction of stack growth for your system; otherwise it will be + automatically deduced at run-time. + STACK_DIRECTION > 0 => grows toward higher addresses + STACK_DIRECTION < 0 => grows toward lower addresses + STACK_DIRECTION = 0 => direction of growth unknown + */ +#undef STACK_DIRECTION + +/* Define if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Define to 1 if NLS is requested. */ +#undef ENABLE_NLS + +/* Define as 1 if you have gettext and don't want to use GNU gettext. */ +#undef HAVE_GETTEXT + +/* Define as 1 if you have the stpcpy function. */ +#undef HAVE_STPCPY + +/* Define if your locale.h file contains LC_MESSAGES. */ +#undef HAVE_LC_MESSAGES + +/* Define if you have the __argz_count function. */ +#undef HAVE___ARGZ_COUNT + +/* Define if you have the __argz_next function. */ +#undef HAVE___ARGZ_NEXT + +/* Define if you have the __argz_stringify function. */ +#undef HAVE___ARGZ_STRINGIFY + +/* Define if you have the __setfpucw function. */ +#undef HAVE___SETFPUCW + +/* Define if you have the dcgettext function. */ +#undef HAVE_DCGETTEXT + +/* Define if you have the getcwd function. */ +#undef HAVE_GETCWD + +/* Define if you have the getpagesize function. */ +#undef HAVE_GETPAGESIZE + +/* Define if you have the getrusage function. */ +#undef HAVE_GETRUSAGE + +/* Define if you have the munmap function. */ +#undef HAVE_MUNMAP + +/* Define if you have the putenv function. */ +#undef HAVE_PUTENV + +/* Define if you have the setenv function. */ +#undef HAVE_SETENV + +/* Define if you have the setlocale function. */ +#undef HAVE_SETLOCALE + +/* Define if you have the sigaction function. */ +#undef HAVE_SIGACTION + +/* Define if you have the stpcpy function. */ +#undef HAVE_STPCPY + +/* Define if you have the strcasecmp function. */ +#undef HAVE_STRCASECMP + +/* Define if you have the strchr function. */ +#undef HAVE_STRCHR + +/* Define if you have the time function. */ +#undef HAVE_TIME + +/* Define if you have the header file. */ +#undef HAVE_ARGZ_H + +/* Define if you have the header file. */ +#undef HAVE_FCNTL_H + +/* Define if you have the header file. */ +#undef HAVE_FPU_CONTROL_H + +/* Define if you have the header file. */ +#undef HAVE_LIMITS_H + +/* Define if you have the header file. */ +#undef HAVE_LOCALE_H + +/* Define if you have the header file. */ +#undef HAVE_MALLOC_H + +/* Define if you have the header file. */ +#undef HAVE_NL_TYPES_H + +/* Define if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define if you have the header file. */ +#undef HAVE_STRING_H + +/* Define if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_PARAM_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_RESOURCE_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_TIME_H + +/* Define if you have the header file. */ +#undef HAVE_TIME_H + +/* Define if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define if you have the header file. */ +#undef HAVE_VALUES_H diff --git a/sim/d10v/configure b/sim/d10v/configure new file mode 100755 index 00000000000..c3b96cfd20e --- /dev/null +++ b/sim/d10v/configure @@ -0,0 +1,3917 @@ +#! /bin/sh + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +sim_inline="-DDEFAULT_INLINE=0" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +# This file is derived from `gettext.m4'. The difference is that the +# included macros assume Cygnus-style source and build trees. + +# Macro to add for using GNU gettext. +# Ulrich Drepper , 1995. +# +# This file file be copied and used freely without restrictions. It can +# be used in projects which are not available under the GNU Public License +# but which still want to provide support for the GNU gettext functionality. +# Please note that the actual code is *not* freely available. + +# serial 3 + + + + + +# Search path for a program which passes the given test. +# Ulrich Drepper , 1996. +# +# This file file be copied and used freely without restrictions. It can +# be used in projects which are not available under the GNU Public License +# but which still want to provide support for the GNU gettext functionality. +# Please note that the actual code is *not* freely available. + +# serial 1 + + + +# Check whether LC_MESSAGES is available in . +# Ulrich Drepper , 1995. +# +# This file file be copied and used freely without restrictions. It can +# be used in projects which are not available under the GNU Public License +# but which still want to provide support for the GNU gettext functionality. +# Please note that the actual code is *not* freely available. + +# serial 1 + + + +# Check to see if we're running under Cygwin32, without using +# AC_CANONICAL_*. If so, set output variable CYGWIN32 to "yes". +# Otherwise set it to "no". + + + +# Check to see if we're running under Win32, without using +# AC_CANONICAL_*. If so, set output variable EXEEXT to ".exe". +# Otherwise set it to "". + + + + +# Guess values for system-dependent variables and create Makefiles. +# Generated automatically using autoconf version 2.12.2 +# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc. +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. + +# Defaults: +ac_help= +ac_default_prefix=/usr/local +# Any additions from configure.in: +ac_help="$ac_help + --disable-nls do not use Native Language Support" +ac_help="$ac_help + --with-included-gettext use the GNU gettext library included here" +ac_help="$ac_help + --enable-maintainer-mode Enable developer functionality." +ac_help="$ac_help + --enable-sim-bswap Use Host specific BSWAP instruction." +ac_help="$ac_help + --enable-sim-cflags=opts Extra CFLAGS for use in building simulator" +ac_help="$ac_help + --enable-sim-debug=opts Enable debugging flags" +ac_help="$ac_help + --enable-sim-stdio Specify whether to use stdio for console input/output." +ac_help="$ac_help + --enable-sim-trace=opts Enable tracing flags" +ac_help="$ac_help + --enable-sim-profile=opts Enable profiling flags" +ac_help="$ac_help + --enable-build-warnings[=LIST] Enable build-time compiler warnings" + +# Initialize some variables set by options. +# The variables have the same names as the options, with +# dashes changed to underlines. +build=NONE +cache_file=./config.cache +exec_prefix=NONE +host=NONE +no_create= +nonopt=NONE +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +target=NONE +verbose= +x_includes=NONE +x_libraries=NONE +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +# Initialize some other variables. +subdirs= +MFLAGS= MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} +# Maximum number of lines to put in a shell here document. +ac_max_here_lines=12 + +ac_prev= +for ac_option +do + + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval "$ac_prev=\$ac_option" + ac_prev= + continue + fi + + case "$ac_option" in + -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) ac_optarg= ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case "$ac_option" in + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir="$ac_optarg" ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build="$ac_optarg" ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file="$ac_optarg" ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir="$ac_optarg" ;; + + -disable-* | --disable-*) + ac_feature=`echo $ac_option|sed -e 's/-*disable-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + eval "enable_${ac_feature}=no" ;; + + -enable-* | --enable-*) + ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "enable_${ac_feature}='$ac_optarg'" ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix="$ac_optarg" ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he) + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat << EOF +Usage: configure [options] [host] +Options: [defaults in brackets after descriptions] +Configuration: + --cache-file=FILE cache test results in FILE + --help print this message + --no-create do not create output files + --quiet, --silent do not print \`checking...' messages + --version print the version of autoconf that created configure +Directory and file names: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [same as prefix] + --bindir=DIR user executables in DIR [EPREFIX/bin] + --sbindir=DIR system admin executables in DIR [EPREFIX/sbin] + --libexecdir=DIR program executables in DIR [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data in DIR + [PREFIX/share] + --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data in DIR + [PREFIX/com] + --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var] + --libdir=DIR object code libraries in DIR [EPREFIX/lib] + --includedir=DIR C header files in DIR [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include] + --infodir=DIR info documentation in DIR [PREFIX/info] + --mandir=DIR man documentation in DIR [PREFIX/man] + --srcdir=DIR find the sources in DIR [configure dir or ..] + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM + run sed PROGRAM on installed program names +EOF + cat << EOF +Host type: + --build=BUILD configure for building on BUILD [BUILD=HOST] + --host=HOST configure for HOST [guessed] + --target=TARGET configure for TARGET [TARGET=HOST] +Features and packages: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --x-includes=DIR X include files are in DIR + --x-libraries=DIR X library files are in DIR +EOF + if test -n "$ac_help"; then + echo "--enable and --with options recognized:$ac_help" + fi + exit 0 ;; + + -host | --host | --hos | --ho) + ac_prev=host ;; + -host=* | --host=* | --hos=* | --ho=*) + host="$ac_optarg" ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir="$ac_optarg" ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir="$ac_optarg" ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir="$ac_optarg" ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir="$ac_optarg" ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + localstatedir="$ac_optarg" ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir="$ac_optarg" ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir="$ac_optarg" ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix="$ac_optarg" ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix="$ac_optarg" ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix="$ac_optarg" ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name="$ac_optarg" ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir="$ac_optarg" ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir="$ac_optarg" ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site="$ac_optarg" ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir="$ac_optarg" ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir="$ac_optarg" ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target="$ac_optarg" ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers) + echo "configure generated by autoconf version 2.12.2" + exit 0 ;; + + -with-* | --with-*) + ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "with_${ac_package}='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`echo $ac_option|sed -e 's/-*without-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + eval "with_${ac_package}=no" ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes="$ac_optarg" ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries="$ac_optarg" ;; + + -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; } + ;; + + *) + if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then + echo "configure: warning: $ac_option: invalid host type" 1>&2 + fi + if test "x$nonopt" != xNONE; then + { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } + fi + nonopt="$ac_option" + ;; + + esac +done + +if test -n "$ac_prev"; then + { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; } +fi + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +# File descriptor usage: +# 0 standard input +# 1 file creation +# 2 errors and warnings +# 3 some systems may open it to /dev/tty +# 4 used on the Kubota Titan +# 6 checking for... messages and results +# 5 compiler messages saved in config.log +if test "$silent" = yes; then + exec 6>/dev/null +else + exec 6>&1 +fi +exec 5>./config.log + +echo "\ +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. +" 1>&5 + +# Strip out --no-create and --no-recursion so they do not pile up. +# Also quote any args containing shell metacharacters. +ac_configure_args= +for ac_arg +do + case "$ac_arg" in + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) ;; + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) + ac_configure_args="$ac_configure_args '$ac_arg'" ;; + *) ac_configure_args="$ac_configure_args $ac_arg" ;; + esac +done + +# NLS nuisances. +# Only set these to C if already set. These must not be set unconditionally +# because not all systems understand e.g. LANG=C (notably SCO). +# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'! +# Non-C LC_CTYPE values break the ctype check. +if test "${LANG+set}" = set; then LANG=C; export LANG; fi +if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi +if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi +if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo > confdefs.h + +# A filename unique to this package, relative to the directory that +# configure is in, which we can look for to find out if srcdir is correct. +ac_unique_file=Makefile.in + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then its parent. + ac_prog=$0 + ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'` + test "x$ac_confdir" = "x$ac_prog" && ac_confdir=. + srcdir=$ac_confdir + if test ! -r $srcdir/$ac_unique_file; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r $srcdir/$ac_unique_file; then + if test "$ac_srcdir_defaulted" = yes; then + { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; } + else + { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; } + fi +fi +srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'` + +# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + echo "loading site script $ac_site_file" + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + echo "loading cache $cache_file" + . $cache_file +else + echo "creating cache $cache_file" + > $cache_file +fi + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +ac_exeext= +ac_objext=o +if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then + # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. + if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then + ac_n= ac_c=' +' ac_t=' ' + else + ac_n=-n ac_c= ac_t= + fi +else + ac_n= ac_c='\c' ac_t= +fi + + + +echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 +echo "configure:679: checking how to run the C preprocessor" >&5 +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then +if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + # This must be in double quotes, not single quotes, because CPP may get + # substituted into the Makefile and "${CC-cc}" will confuse make. + CPP="${CC-cc} -E" + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. + cat > conftest.$ac_ext < +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:700: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP="${CC-cc} -E -traditional-cpp" + cat > conftest.$ac_ext < +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:717: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP="${CC-cc} -nologo -E" + cat > conftest.$ac_ext < +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:734: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP=/lib/cpp +fi +rm -f conftest* +fi +rm -f conftest* +fi +rm -f conftest* + ac_cv_prog_CPP="$CPP" +fi + CPP="$ac_cv_prog_CPP" +else + ac_cv_prog_CPP="$CPP" +fi +echo "$ac_t""$CPP" 1>&6 + +echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6 +echo "configure:759: checking whether ${MAKE-make} sets \${MAKE}" >&5 +set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftestmake <<\EOF +all: + @echo 'ac_maketemp="${MAKE}"' +EOF +# GNU make sometimes prints "make[1]: Entering...", which would confuse us. +eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=` +if test -n "$ac_maketemp"; then + eval ac_cv_prog_make_${ac_make}_set=yes +else + eval ac_cv_prog_make_${ac_make}_set=no +fi +rm -f conftestmake +fi +if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then + echo "$ac_t""yes" 1>&6 + SET_MAKE= +else + echo "$ac_t""no" 1>&6 + SET_MAKE="MAKE=${MAKE-make}" +fi + +echo $ac_n "checking for POSIXized ISC""... $ac_c" 1>&6 +echo "configure:786: checking for POSIXized ISC" >&5 +if test -d /etc/conf/kconfig.d && + grep _POSIX_VERSION /usr/include/sys/unistd.h >/dev/null 2>&1 +then + echo "$ac_t""yes" 1>&6 + ISC=yes # If later tests want to check for ISC. + cat >> confdefs.h <<\EOF +#define _POSIX_SOURCE 1 +EOF + + if test "$GCC" = yes; then + CC="$CC -posix" + else + CC="$CC -Xp" + fi +else + echo "$ac_t""no" 1>&6 + ISC= +fi + +echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6 +echo "configure:807: checking for ANSI C header files" >&5 +if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#include +#include +#include +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:820: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + ac_cv_header_stdc=yes +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_header_stdc=no +fi +rm -f conftest* + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. +cat > conftest.$ac_ext < +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "memchr" >/dev/null 2>&1; then + : +else + rm -rf conftest* + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. +cat > conftest.$ac_ext < +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "free" >/dev/null 2>&1; then + : +else + rm -rf conftest* + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. +if test "$cross_compiling" = yes; then + : +else + cat > conftest.$ac_ext < +#define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int main () { int i; for (i = 0; i < 256; i++) +if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); +exit (0); } + +EOF +if { (eval echo configure:887: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +then + : +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_header_stdc=no +fi +rm -fr conftest* +fi + +fi +fi + +echo "$ac_t""$ac_cv_header_stdc" 1>&6 +if test $ac_cv_header_stdc = yes; then + cat >> confdefs.h <<\EOF +#define STDC_HEADERS 1 +EOF + +fi + +echo $ac_n "checking for working const""... $ac_c" 1>&6 +echo "configure:911: checking for working const" >&5 +if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <j = 5; +} +{ /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ + const int foo = 10; +} + +; return 0; } +EOF +if { (eval echo configure:965: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_c_const=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_c_const=no +fi +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_c_const" 1>&6 +if test $ac_cv_c_const = no; then + cat >> confdefs.h <<\EOF +#define const +EOF + +fi + +echo $ac_n "checking for inline""... $ac_c" 1>&6 +echo "configure:986: checking for inline" >&5 +if eval "test \"`echo '$''{'ac_cv_c_inline'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_cv_c_inline=no +for ac_kw in inline __inline__ __inline; do + cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_c_inline=$ac_kw; break +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 +fi +rm -f conftest* +done + +fi + +echo "$ac_t""$ac_cv_c_inline" 1>&6 +case "$ac_cv_c_inline" in + inline | yes) ;; + no) cat >> confdefs.h <<\EOF +#define inline +EOF + ;; + *) cat >> confdefs.h <&6 +echo "configure:1026: checking for off_t" >&5 +if eval "test \"`echo '$''{'ac_cv_type_off_t'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#if STDC_HEADERS +#include +#include +#endif +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "off_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then + rm -rf conftest* + ac_cv_type_off_t=yes +else + rm -rf conftest* + ac_cv_type_off_t=no +fi +rm -f conftest* + +fi +echo "$ac_t""$ac_cv_type_off_t" 1>&6 +if test $ac_cv_type_off_t = no; then + cat >> confdefs.h <<\EOF +#define off_t long +EOF + +fi + +echo $ac_n "checking for size_t""... $ac_c" 1>&6 +echo "configure:1059: checking for size_t" >&5 +if eval "test \"`echo '$''{'ac_cv_type_size_t'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#if STDC_HEADERS +#include +#include +#endif +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "size_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then + rm -rf conftest* + ac_cv_type_size_t=yes +else + rm -rf conftest* + ac_cv_type_size_t=no +fi +rm -f conftest* + +fi +echo "$ac_t""$ac_cv_type_size_t" 1>&6 +if test $ac_cv_type_size_t = no; then + cat >> confdefs.h <<\EOF +#define size_t unsigned +EOF + +fi + +# The Ultrix 4.2 mips builtin alloca declared by alloca.h only works +# for constant arguments. Useless! +echo $ac_n "checking for working alloca.h""... $ac_c" 1>&6 +echo "configure:1094: checking for working alloca.h" >&5 +if eval "test \"`echo '$''{'ac_cv_header_alloca_h'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +int main() { +char *p = alloca(2 * sizeof(int)); +; return 0; } +EOF +if { (eval echo configure:1106: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + ac_cv_header_alloca_h=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_header_alloca_h=no +fi +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_header_alloca_h" 1>&6 +if test $ac_cv_header_alloca_h = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_ALLOCA_H 1 +EOF + +fi + +echo $ac_n "checking for alloca""... $ac_c" 1>&6 +echo "configure:1127: checking for alloca" >&5 +if eval "test \"`echo '$''{'ac_cv_func_alloca_works'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +# define alloca _alloca +# else +# if HAVE_ALLOCA_H +# include +# else +# ifdef _AIX + #pragma alloca +# else +# ifndef alloca /* predefined by HP cc +Olibcalls */ +char *alloca (); +# endif +# endif +# endif +# endif +#endif + +int main() { +char *p = (char *) alloca(1); +; return 0; } +EOF +if { (eval echo configure:1160: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + ac_cv_func_alloca_works=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_func_alloca_works=no +fi +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_func_alloca_works" 1>&6 +if test $ac_cv_func_alloca_works = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_ALLOCA 1 +EOF + +fi + +if test $ac_cv_func_alloca_works = no; then + # The SVR3 libPW and SVR4 libucb both contain incompatible functions + # that cause trouble. Some versions do not even contain alloca or + # contain a buggy version. If you still want to use their alloca, + # use ar to extract alloca.o from them instead of compiling alloca.c. + ALLOCA=alloca.${ac_objext} + cat >> confdefs.h <<\EOF +#define C_ALLOCA 1 +EOF + + +echo $ac_n "checking whether alloca needs Cray hooks""... $ac_c" 1>&6 +echo "configure:1192: checking whether alloca needs Cray hooks" >&5 +if eval "test \"`echo '$''{'ac_cv_os_cray'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <&5 | + egrep "webecray" >/dev/null 2>&1; then + rm -rf conftest* + ac_cv_os_cray=yes +else + rm -rf conftest* + ac_cv_os_cray=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_os_cray" 1>&6 +if test $ac_cv_os_cray = yes; then +for ac_func in _getb67 GETB67 getb67; do + echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:1222: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:1250: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + cat >> confdefs.h <&6 +fi + +done +fi + +echo $ac_n "checking stack direction for C alloca""... $ac_c" 1>&6 +echo "configure:1277: checking stack direction for C alloca" >&5 +if eval "test \"`echo '$''{'ac_cv_c_stack_direction'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$cross_compiling" = yes; then + ac_cv_c_stack_direction=0 +else + cat > conftest.$ac_ext < addr) ? 1 : -1; +} +main () +{ + exit (find_stack_direction() < 0); +} +EOF +if { (eval echo configure:1304: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +then + ac_cv_c_stack_direction=1 +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_c_stack_direction=-1 +fi +rm -fr conftest* +fi + +fi + +echo "$ac_t""$ac_cv_c_stack_direction" 1>&6 +cat >> confdefs.h <&6 +echo "configure:1329: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1339: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <&6 +fi +done + +for ac_func in getpagesize +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:1368: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:1396: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <&6 +fi +done + +echo $ac_n "checking for working mmap""... $ac_c" 1>&6 +echo "configure:1421: checking for working mmap" >&5 +if eval "test \"`echo '$''{'ac_cv_func_mmap_fixed_mapped'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$cross_compiling" = yes; then + ac_cv_func_mmap_fixed_mapped=no +else + cat > conftest.$ac_ext < +#include +#include + +/* This mess was copied from the GNU getpagesize.h. */ +#ifndef HAVE_GETPAGESIZE +# ifdef HAVE_UNISTD_H +# include +# endif + +/* Assume that all systems that can run configure have sys/param.h. */ +# ifndef HAVE_SYS_PARAM_H +# define HAVE_SYS_PARAM_H 1 +# endif + +# ifdef _SC_PAGESIZE +# define getpagesize() sysconf(_SC_PAGESIZE) +# else /* no _SC_PAGESIZE */ +# ifdef HAVE_SYS_PARAM_H +# include +# ifdef EXEC_PAGESIZE +# define getpagesize() EXEC_PAGESIZE +# else /* no EXEC_PAGESIZE */ +# ifdef NBPG +# define getpagesize() NBPG * CLSIZE +# ifndef CLSIZE +# define CLSIZE 1 +# endif /* no CLSIZE */ +# else /* no NBPG */ +# ifdef NBPC +# define getpagesize() NBPC +# else /* no NBPC */ +# ifdef PAGESIZE +# define getpagesize() PAGESIZE +# endif /* PAGESIZE */ +# endif /* no NBPC */ +# endif /* no NBPG */ +# endif /* no EXEC_PAGESIZE */ +# else /* no HAVE_SYS_PARAM_H */ +# define getpagesize() 8192 /* punt totally */ +# endif /* no HAVE_SYS_PARAM_H */ +# endif /* no _SC_PAGESIZE */ + +#endif /* no HAVE_GETPAGESIZE */ + +#ifdef __cplusplus +extern "C" { void *malloc(unsigned); } +#else +char *malloc(); +#endif + +int +main() +{ + char *data, *data2, *data3; + int i, pagesize; + int fd; + + pagesize = getpagesize(); + + /* + * First, make a file with some known garbage in it. + */ + data = malloc(pagesize); + if (!data) + exit(1); + for (i = 0; i < pagesize; ++i) + *(data + i) = rand(); + umask(0); + fd = creat("conftestmmap", 0600); + if (fd < 0) + exit(1); + if (write(fd, data, pagesize) != pagesize) + exit(1); + close(fd); + + /* + * Next, try to mmap the file at a fixed address which + * already has something else allocated at it. If we can, + * also make sure that we see the same garbage. + */ + fd = open("conftestmmap", O_RDWR); + if (fd < 0) + exit(1); + data2 = malloc(2 * pagesize); + if (!data2) + exit(1); + data2 += (pagesize - ((int) data2 & (pagesize - 1))) & (pagesize - 1); + if (data2 != mmap(data2, pagesize, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_FIXED, fd, 0L)) + exit(1); + for (i = 0; i < pagesize; ++i) + if (*(data + i) != *(data2 + i)) + exit(1); + + /* + * Finally, make sure that changes to the mapped area + * do not percolate back to the file as seen by read(). + * (This is a bug on some variants of i386 svr4.0.) + */ + for (i = 0; i < pagesize; ++i) + *(data2 + i) = *(data2 + i) + 1; + data3 = malloc(pagesize); + if (!data3) + exit(1); + if (read(fd, data3, pagesize) != pagesize) + exit(1); + for (i = 0; i < pagesize; ++i) + if (*(data + i) != *(data3 + i)) + exit(1); + close(fd); + unlink("conftestmmap"); + exit(0); +} + +EOF +if { (eval echo configure:1569: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +then + ac_cv_func_mmap_fixed_mapped=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_func_mmap_fixed_mapped=no +fi +rm -fr conftest* +fi + +fi + +echo "$ac_t""$ac_cv_func_mmap_fixed_mapped" 1>&6 +if test $ac_cv_func_mmap_fixed_mapped = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_MMAP 1 +EOF + +fi + + +# autoconf.info says this should be called right after AC_INIT. + + +ac_aux_dir= +for ac_dir in `cd $srcdir;pwd`/../.. $srcdir/`cd $srcdir;pwd`/../..; do + if test -f $ac_dir/install-sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f $ac_dir/install.sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + fi +done +if test -z "$ac_aux_dir"; then + { echo "configure: error: can not find install-sh or install.sh in `cd $srcdir;pwd`/../.. $srcdir/`cd $srcdir;pwd`/../.." 1>&2; exit 1; } +fi +ac_config_guess=$ac_aux_dir/config.guess +ac_config_sub=$ac_aux_dir/config.sub +ac_configure=$ac_aux_dir/configure # This should be Cygnus configure. + + +# Do some error checking and defaulting for the host and target type. +# The inputs are: +# configure --host=HOST --target=TARGET --build=BUILD NONOPT +# +# The rules are: +# 1. You are not allowed to specify --host, --target, and nonopt at the +# same time. +# 2. Host defaults to nonopt. +# 3. If nonopt is not specified, then host defaults to the current host, +# as determined by config.guess. +# 4. Target and build default to nonopt. +# 5. If nonopt is not specified, then target and build default to host. + +# The aliases save the names the user supplied, while $host etc. +# will get canonicalized. +case $host---$target---$nonopt in +NONE---*---* | *---NONE---* | *---*---NONE) ;; +*) { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } ;; +esac + + +# Make sure we can run config.sub. +if ${CONFIG_SHELL-/bin/sh} $ac_config_sub sun4 >/dev/null 2>&1; then : +else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; } +fi + +echo $ac_n "checking host system type""... $ac_c" 1>&6 +echo "configure:1642: checking host system type" >&5 + +host_alias=$host +case "$host_alias" in +NONE) + case $nonopt in + NONE) + if host_alias=`${CONFIG_SHELL-/bin/sh} $ac_config_guess`; then : + else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; } + fi ;; + *) host_alias=$nonopt ;; + esac ;; +esac + +host=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $host_alias` +host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` +echo "$ac_t""$host" 1>&6 + +echo $ac_n "checking target system type""... $ac_c" 1>&6 +echo "configure:1663: checking target system type" >&5 + +target_alias=$target +case "$target_alias" in +NONE) + case $nonopt in + NONE) target_alias=$host_alias ;; + *) target_alias=$nonopt ;; + esac ;; +esac + +target=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $target_alias` +target_cpu=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +target_vendor=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +target_os=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` +echo "$ac_t""$target" 1>&6 + +echo $ac_n "checking build system type""... $ac_c" 1>&6 +echo "configure:1681: checking build system type" >&5 + +build_alias=$build +case "$build_alias" in +NONE) + case $nonopt in + NONE) build_alias=$host_alias ;; + *) build_alias=$nonopt ;; + esac ;; +esac + +build=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $build_alias` +build_cpu=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +build_vendor=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +build_os=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` +echo "$ac_t""$build" 1>&6 + +test "$host_alias" != "$target_alias" && + test "$program_prefix$program_suffix$program_transform_name" = \ + NONENONEs,x,x, && + program_prefix=${target_alias}- + +if test "$program_transform_name" = s,x,x,; then + program_transform_name= +else + # Double any \ or $. echo might interpret backslashes. + cat <<\EOF_SED > conftestsed +s,\\,\\\\,g; s,\$,$$,g +EOF_SED + program_transform_name="`echo $program_transform_name|sed -f conftestsed`" + rm -f conftestsed +fi +test "$program_prefix" != NONE && + program_transform_name="s,^,${program_prefix},; $program_transform_name" +# Use a double $ so make ignores it. +test "$program_suffix" != NONE && + program_transform_name="s,\$\$,${program_suffix},; $program_transform_name" + +# sed with no file args requires a program. +test "$program_transform_name" = "" && program_transform_name="s,x,x," + +# Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1725: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CC="gcc" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1754: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_prog_rejected=no + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + break + fi + done + IFS="$ac_save_ifs" +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# -gt 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + set dummy "$ac_dir/$ac_word" "$@" + shift + ac_cv_prog_CC="$@" + fi +fi +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + if test -z "$CC"; then + case "`uname -s`" in + *win32* | *WIN32*) + # Extract the first word of "cl", so it can be a program name with args. +set dummy cl; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1804: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CC="cl" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + ;; + esac + fi + test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; } +fi + +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 +echo "configure:1835: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + ac_cv_prog_cc_works=yes + # If we can't run a trivial program, we are probably using a cross compiler. + if (./conftest; exit) 2>/dev/null; then + ac_cv_prog_cc_cross=no + else + ac_cv_prog_cc_cross=yes + fi +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + ac_cv_prog_cc_works=no +fi +rm -fr conftest* + +echo "$ac_t""$ac_cv_prog_cc_works" 1>&6 +if test $ac_cv_prog_cc_works = no; then + { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } +fi +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 +echo "configure:1869: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 +cross_compiling=$ac_cv_prog_cc_cross + +echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 +echo "configure:1874: checking whether we are using GNU C" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.c <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then + ac_cv_prog_gcc=yes +else + ac_cv_prog_gcc=no +fi +fi + +echo "$ac_t""$ac_cv_prog_gcc" 1>&6 + +if test $ac_cv_prog_gcc = yes; then + GCC=yes +else + GCC= +fi + +ac_test_CFLAGS="${CFLAGS+set}" +ac_save_CFLAGS="$CFLAGS" +CFLAGS= +echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 +echo "configure:1902: checking whether ${CC-cc} accepts -g" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + echo 'void f(){}' > conftest.c +if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then + ac_cv_prog_cc_g=yes +else + ac_cv_prog_cc_g=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_prog_cc_g" 1>&6 +if test "$ac_test_CFLAGS" = set; then + CFLAGS="$ac_save_CFLAGS" +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# ./install, which can be erroneously created by make from ./install.sh. +echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 +echo "configure:1945: checking for a BSD compatible install" >&5 +if test -z "$INSTALL"; then +if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":" + for ac_dir in $PATH; do + # Account for people who put trailing slashes in PATH elements. + case "$ac_dir/" in + /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + if test -f $ac_dir/$ac_prog; then + if test $ac_prog = install && + grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + else + ac_cv_path_install="$ac_dir/$ac_prog -c" + break 2 + fi + fi + done + ;; + esac + done + IFS="$ac_save_IFS" + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL="$ac_cv_path_install" + else + # As a last resort, use the slow shell script. We don't cache a + # path for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the path is relative. + INSTALL="$ac_install_sh" + fi +fi +echo "$ac_t""$INSTALL" 1>&6 + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + + +# Put a plausible default for CC_FOR_BUILD in Makefile. +if test "x$cross_compiling" = "xno"; then + CC_FOR_BUILD='$(CC)' +else + CC_FOR_BUILD=gcc +fi + + + + +AR=${AR-ar} + +# Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:2011: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_RANLIB="ranlib" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":" +fi +fi +RANLIB="$ac_cv_prog_RANLIB" +if test -n "$RANLIB"; then + echo "$ac_t""$RANLIB" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + +ALL_LINGUAS= + + for ac_hdr in argz.h limits.h locale.h nl_types.h malloc.h string.h \ +unistd.h values.h sys/param.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:2045: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:2055: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <&6 +fi +done + + for ac_func in getcwd munmap putenv setenv setlocale strchr strcasecmp \ +__argz_count __argz_stringify __argz_next +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:2085: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:2113: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <&6 +fi +done + + + if test "${ac_cv_func_stpcpy+set}" != "set"; then + for ac_func in stpcpy +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:2142: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:2170: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <&6 +fi +done + + fi + if test "${ac_cv_func_stpcpy}" = "yes"; then + cat >> confdefs.h <<\EOF +#define HAVE_STPCPY 1 +EOF + + fi + + if test $ac_cv_header_locale_h = yes; then + echo $ac_n "checking for LC_MESSAGES""... $ac_c" 1>&6 +echo "configure:2204: checking for LC_MESSAGES" >&5 +if eval "test \"`echo '$''{'am_cv_val_LC_MESSAGES'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +int main() { +return LC_MESSAGES +; return 0; } +EOF +if { (eval echo configure:2216: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + am_cv_val_LC_MESSAGES=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + am_cv_val_LC_MESSAGES=no +fi +rm -f conftest* +fi + +echo "$ac_t""$am_cv_val_LC_MESSAGES" 1>&6 + if test $am_cv_val_LC_MESSAGES = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_LC_MESSAGES 1 +EOF + + fi + fi + echo $ac_n "checking whether NLS is requested""... $ac_c" 1>&6 +echo "configure:2237: checking whether NLS is requested" >&5 + # Check whether --enable-nls or --disable-nls was given. +if test "${enable_nls+set}" = set; then + enableval="$enable_nls" + USE_NLS=$enableval +else + USE_NLS=yes +fi + + echo "$ac_t""$USE_NLS" 1>&6 + + + USE_INCLUDED_LIBINTL=no + + if test "$USE_NLS" = "yes"; then + cat >> confdefs.h <<\EOF +#define ENABLE_NLS 1 +EOF + + echo $ac_n "checking whether included gettext is requested""... $ac_c" 1>&6 +echo "configure:2257: checking whether included gettext is requested" >&5 + # Check whether --with-included-gettext or --without-included-gettext was given. +if test "${with_included_gettext+set}" = set; then + withval="$with_included_gettext" + nls_cv_force_use_gnu_gettext=$withval +else + nls_cv_force_use_gnu_gettext=no +fi + + echo "$ac_t""$nls_cv_force_use_gnu_gettext" 1>&6 + + nls_cv_use_gnu_gettext="$nls_cv_force_use_gnu_gettext" + if test "$nls_cv_force_use_gnu_gettext" != "yes"; then + nls_cv_header_intl= + nls_cv_header_libgt= + CATOBJEXT=NONE + + ac_safe=`echo "libintl.h" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for libintl.h""... $ac_c" 1>&6 +echo "configure:2276: checking for libintl.h" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:2286: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + echo $ac_n "checking for gettext in libc""... $ac_c" 1>&6 +echo "configure:2303: checking for gettext in libc" >&5 +if eval "test \"`echo '$''{'gt_cv_func_gettext_libc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +int main() { +return (int) gettext ("") +; return 0; } +EOF +if { (eval echo configure:2315: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + gt_cv_func_gettext_libc=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + gt_cv_func_gettext_libc=no +fi +rm -f conftest* +fi + +echo "$ac_t""$gt_cv_func_gettext_libc" 1>&6 + + if test "$gt_cv_func_gettext_libc" != "yes"; then + echo $ac_n "checking for bindtextdomain in -lintl""... $ac_c" 1>&6 +echo "configure:2331: checking for bindtextdomain in -lintl" >&5 +ac_lib_var=`echo intl'_'bindtextdomain | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lintl $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + echo $ac_n "checking for gettext in libintl""... $ac_c" 1>&6 +echo "configure:2366: checking for gettext in libintl" >&5 +if eval "test \"`echo '$''{'gt_cv_func_gettext_libintl'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + gt_cv_func_gettext_libintl=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + gt_cv_func_gettext_libintl=no +fi +rm -f conftest* +fi + +echo "$ac_t""$gt_cv_func_gettext_libintl" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + fi + + if test "$gt_cv_func_gettext_libc" = "yes" \ + || test "$gt_cv_func_gettext_libintl" = "yes"; then + cat >> confdefs.h <<\EOF +#define HAVE_GETTEXT 1 +EOF + + # Extract the first word of "msgfmt", so it can be a program name with args. +set dummy msgfmt; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:2406: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_MSGFMT'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$MSGFMT" in + /*) + ac_cv_path_MSGFMT="$MSGFMT" # Let the user override the test with a path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"; then + ac_cv_path_MSGFMT="$ac_dir/$ac_word" + break + fi + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_MSGFMT" && ac_cv_path_MSGFMT="no" + ;; +esac +fi +MSGFMT="$ac_cv_path_MSGFMT" +if test -n "$MSGFMT"; then + echo "$ac_t""$MSGFMT" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + if test "$MSGFMT" != "no"; then + for ac_func in dcgettext +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:2440: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:2468: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <&6 +fi +done + + # Extract the first word of "gmsgfmt", so it can be a program name with args. +set dummy gmsgfmt; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:2495: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_GMSGFMT'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$GMSGFMT" in + /*) + ac_cv_path_GMSGFMT="$GMSGFMT" # Let the user override the test with a path. + ;; + ?:/*) + ac_cv_path_GMSGFMT="$GMSGFMT" # Let the user override the test with a dos path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_path_GMSGFMT="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_GMSGFMT" && ac_cv_path_GMSGFMT="$MSGFMT" + ;; +esac +fi +GMSGFMT="$ac_cv_path_GMSGFMT" +if test -n "$GMSGFMT"; then + echo "$ac_t""$GMSGFMT" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + # Extract the first word of "xgettext", so it can be a program name with args. +set dummy xgettext; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:2530: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_XGETTEXT'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$XGETTEXT" in + /*) + ac_cv_path_XGETTEXT="$XGETTEXT" # Let the user override the test with a path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"; then + ac_cv_path_XGETTEXT="$ac_dir/$ac_word" + break + fi + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_XGETTEXT" && ac_cv_path_XGETTEXT=":" + ;; +esac +fi +XGETTEXT="$ac_cv_path_XGETTEXT" +if test -n "$XGETTEXT"; then + echo "$ac_t""$XGETTEXT" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + CATOBJEXT=.gmo + DATADIRNAME=share +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CATOBJEXT=.mo + DATADIRNAME=lib +fi +rm -f conftest* + INSTOBJEXT=.mo + fi + fi + +else + echo "$ac_t""no" 1>&6 +fi + + + + if test "$CATOBJEXT" = "NONE"; then + nls_cv_use_gnu_gettext=yes + fi + fi + + if test "$nls_cv_use_gnu_gettext" = "yes"; then + INTLOBJS="\$(GETTOBJS)" + # Extract the first word of "msgfmt", so it can be a program name with args. +set dummy msgfmt; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:2602: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_MSGFMT'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$MSGFMT" in + /*) + ac_cv_path_MSGFMT="$MSGFMT" # Let the user override the test with a path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"; then + ac_cv_path_MSGFMT="$ac_dir/$ac_word" + break + fi + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_MSGFMT" && ac_cv_path_MSGFMT="msgfmt" + ;; +esac +fi +MSGFMT="$ac_cv_path_MSGFMT" +if test -n "$MSGFMT"; then + echo "$ac_t""$MSGFMT" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + # Extract the first word of "gmsgfmt", so it can be a program name with args. +set dummy gmsgfmt; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:2636: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_GMSGFMT'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$GMSGFMT" in + /*) + ac_cv_path_GMSGFMT="$GMSGFMT" # Let the user override the test with a path. + ;; + ?:/*) + ac_cv_path_GMSGFMT="$GMSGFMT" # Let the user override the test with a dos path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_path_GMSGFMT="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_GMSGFMT" && ac_cv_path_GMSGFMT="$MSGFMT" + ;; +esac +fi +GMSGFMT="$ac_cv_path_GMSGFMT" +if test -n "$GMSGFMT"; then + echo "$ac_t""$GMSGFMT" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + # Extract the first word of "xgettext", so it can be a program name with args. +set dummy xgettext; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:2671: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_XGETTEXT'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$XGETTEXT" in + /*) + ac_cv_path_XGETTEXT="$XGETTEXT" # Let the user override the test with a path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"; then + ac_cv_path_XGETTEXT="$ac_dir/$ac_word" + break + fi + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_XGETTEXT" && ac_cv_path_XGETTEXT=":" + ;; +esac +fi +XGETTEXT="$ac_cv_path_XGETTEXT" +if test -n "$XGETTEXT"; then + echo "$ac_t""$XGETTEXT" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + + USE_INCLUDED_LIBINTL=yes + CATOBJEXT=.gmo + INSTOBJEXT=.mo + DATADIRNAME=share + INTLDEPS='$(top_builddir)/../intl/libintl.a' + INTLLIBS=$INTLDEPS + LIBS=`echo $LIBS | sed -e 's/-lintl//'` + nls_cv_header_intl=libintl.h + nls_cv_header_libgt=libgettext.h + fi + + if test "$XGETTEXT" != ":"; then + if $XGETTEXT --omit-header /dev/null 2> /dev/null; then + : ; + else + echo "$ac_t""found xgettext programs is not GNU xgettext; ignore it" 1>&6 + XGETTEXT=":" + fi + fi + + # We need to process the po/ directory. + POSUB=po + else + DATADIRNAME=share + nls_cv_header_intl=libintl.h + nls_cv_header_libgt=libgettext.h + fi + + # If this is used in GNU gettext we have to set USE_NLS to `yes' + # because some of the sources are only built for this goal. + if test "$PACKAGE" = gettext; then + USE_NLS=yes + USE_INCLUDED_LIBINTL=yes + fi + + for lang in $ALL_LINGUAS; do + GMOFILES="$GMOFILES $lang.gmo" + POFILES="$POFILES $lang.po" + done + + + + + + + + + + + + + + + if test "x$CATOBJEXT" != "x"; then + if test "x$ALL_LINGUAS" = "x"; then + LINGUAS= + else + echo $ac_n "checking for catalogs to be installed""... $ac_c" 1>&6 +echo "configure:2761: checking for catalogs to be installed" >&5 + NEW_LINGUAS= + for lang in ${LINGUAS=$ALL_LINGUAS}; do + case "$ALL_LINGUAS" in + *$lang*) NEW_LINGUAS="$NEW_LINGUAS $lang" ;; + esac + done + LINGUAS=$NEW_LINGUAS + echo "$ac_t""$LINGUAS" 1>&6 + fi + + if test -n "$LINGUAS"; then + for lang in $LINGUAS; do CATALOGS="$CATALOGS $lang$CATOBJEXT"; done + fi + fi + + if test $ac_cv_header_locale_h = yes; then + INCLUDE_LOCALE_H="#include " + else + INCLUDE_LOCALE_H="\ +/* The system does not provide the header . Take care yourself. */" + fi + + + if test -f $srcdir/po2tbl.sed.in; then + if test "$CATOBJEXT" = ".cat"; then + ac_safe=`echo "linux/version.h" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for linux/version.h""... $ac_c" 1>&6 +echo "configure:2789: checking for linux/version.h" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:2799: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + msgformat=linux +else + echo "$ac_t""no" 1>&6 +msgformat=xopen +fi + + + sed -e '/^#/d' $srcdir/$msgformat-msg.sed > po2msg.sed + fi + sed -e '/^#.*[^\\]$/d' -e '/^#$/d' \ + $srcdir/po2tbl.sed.in > po2tbl.sed + fi + + if test "$PACKAGE" = "gettext"; then + GT_NO="#NO#" + GT_YES= + else + GT_NO= + GT_YES="#YES#" + fi + + + + MKINSTALLDIRS="\$(srcdir)/../../mkinstalldirs" + + + l= + + + if test -d $srcdir/po; then + test -d po || mkdir po + if test "x$srcdir" != "x."; then + if test "x`echo $srcdir | sed 's@/.*@@'`" = "x"; then + posrcprefix="$srcdir/" + else + posrcprefix="../$srcdir/" + fi + else + posrcprefix="../" + fi + rm -f po/POTFILES + sed -e "/^#/d" -e "/^\$/d" -e "s,.*, $posrcprefix& \\\\," -e "\$s/\(.*\) \\\\/\1/" \ + < $srcdir/po/POTFILES.in > po/POTFILES + fi + + +# Check for common headers. +# FIXME: Seems to me this can cause problems for i386-windows hosts. +# At one point there were hardcoded AC_DEFINE's if ${host} = i386-*-windows*. +for ac_hdr in stdlib.h string.h strings.h unistd.h time.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:2868: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:2878: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <&6 +fi +done + +for ac_hdr in sys/time.h sys/resource.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:2908: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:2918: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <&6 +fi +done + +for ac_hdr in fcntl.h fpu_control.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:2948: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:2958: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <&6 +fi +done + +for ac_func in getrusage time sigaction __setfpucw +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:2987: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:3015: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <&6 +fi +done + + +# Check for socket libraries +echo $ac_n "checking for bind in -lsocket""... $ac_c" 1>&6 +echo "configure:3042: checking for bind in -lsocket" >&5 +ac_lib_var=`echo socket'_'bind | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lsocket $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_lib=HAVE_LIB`echo socket | sed -e 's/[^a-zA-Z0-9_]/_/g' \ + -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'` + cat >> confdefs.h <&6 +fi + +echo $ac_n "checking for gethostbyname in -lnsl""... $ac_c" 1>&6 +echo "configure:3089: checking for gethostbyname in -lnsl" >&5 +ac_lib_var=`echo nsl'_'gethostbyname | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lnsl $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_lib=HAVE_LIB`echo nsl | sed -e 's/[^a-zA-Z0-9_]/_/g' \ + -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'` + cat >> confdefs.h <&6 +fi + + +. ${srcdir}/../../bfd/configure.host + + + +USE_MAINTAINER_MODE=no +# Check whether --enable-maintainer-mode or --disable-maintainer-mode was given. +if test "${enable_maintainer_mode+set}" = set; then + enableval="$enable_maintainer_mode" + case "${enableval}" in + yes) MAINT="" USE_MAINTAINER_MODE=yes ;; + no) MAINT="#" ;; + *) { echo "configure: error: "--enable-maintainer-mode does not take a value"" 1>&2; exit 1; }; MAINT="#" ;; +esac +if test x"$silent" != x"yes" && test x"$MAINT" = x""; then + echo "Setting maintainer mode" 6>&1 +fi +else + MAINT="#" +fi + + + +# Check whether --enable-sim-bswap or --disable-sim-bswap was given. +if test "${enable_sim_bswap+set}" = set; then + enableval="$enable_sim_bswap" + case "${enableval}" in + yes) sim_bswap="-DWITH_BSWAP=1 -DUSE_BSWAP=1";; + no) sim_bswap="-DWITH_BSWAP=0";; + *) { echo "configure: error: "--enable-sim-bswap does not take a value"" 1>&2; exit 1; }; sim_bswap="";; +esac +if test x"$silent" != x"yes" && test x"$sim_bswap" != x""; then + echo "Setting bswap flags = $sim_bswap" 6>&1 +fi +else + sim_bswap="" +fi + + + +# Check whether --enable-sim-cflags or --disable-sim-cflags was given. +if test "${enable_sim_cflags+set}" = set; then + enableval="$enable_sim_cflags" + case "${enableval}" in + yes) sim_cflags="-O2 -fomit-frame-pointer";; + trace) { echo "configure: error: "Please use --enable-sim-debug instead."" 1>&2; exit 1; }; sim_cflags="";; + no) sim_cflags="";; + *) sim_cflags=`echo "${enableval}" | sed -e "s/,/ /g"`;; +esac +if test x"$silent" != x"yes" && test x"$sim_cflags" != x""; then + echo "Setting sim cflags = $sim_cflags" 6>&1 +fi +else + sim_cflags="" +fi + + + +# Check whether --enable-sim-debug or --disable-sim-debug was given. +if test "${enable_sim_debug+set}" = set; then + enableval="$enable_sim_debug" + case "${enableval}" in + yes) sim_debug="-DDEBUG=7 -DWITH_DEBUG=7";; + no) sim_debug="-DDEBUG=0 -DWITH_DEBUG=0";; + *) sim_debug="-DDEBUG='(${enableval})' -DWITH_DEBUG='(${enableval})'";; +esac +if test x"$silent" != x"yes" && test x"$sim_debug" != x""; then + echo "Setting sim debug = $sim_debug" 6>&1 +fi +else + sim_debug="" +fi + + + +# Check whether --enable-sim-stdio or --disable-sim-stdio was given. +if test "${enable_sim_stdio+set}" = set; then + enableval="$enable_sim_stdio" + case "${enableval}" in + yes) sim_stdio="-DWITH_STDIO=DO_USE_STDIO";; + no) sim_stdio="-DWITH_STDIO=DONT_USE_STDIO";; + *) { echo "configure: error: "Unknown value $enableval passed to --enable-sim-stdio"" 1>&2; exit 1; }; sim_stdio="";; +esac +if test x"$silent" != x"yes" && test x"$sim_stdio" != x""; then + echo "Setting stdio flags = $sim_stdio" 6>&1 +fi +else + sim_stdio="" +fi + + + +# Check whether --enable-sim-trace or --disable-sim-trace was given. +if test "${enable_sim_trace+set}" = set; then + enableval="$enable_sim_trace" + case "${enableval}" in + yes) sim_trace="-DTRACE=1 -DWITH_TRACE=-1";; + no) sim_trace="-DTRACE=0 -DWITH_TRACE=0";; + [-0-9]*) + sim_trace="-DTRACE='(${enableval})' -DWITH_TRACE='(${enableval})'";; + [a-z]*) + sim_trace="" + for x in `echo "$enableval" | sed -e "s/,/ /g"`; do + if test x"$sim_trace" = x; then + sim_trace="-DWITH_TRACE='(TRACE_$x" + else + sim_trace="${sim_trace}|TRACE_$x" + fi + done + sim_trace="$sim_trace)'" ;; +esac +if test x"$silent" != x"yes" && test x"$sim_trace" != x""; then + echo "Setting sim trace = $sim_trace" 6>&1 +fi +else + sim_trace="" +fi + + + +# Check whether --enable-sim-profile or --disable-sim-profile was given. +if test "${enable_sim_profile+set}" = set; then + enableval="$enable_sim_profile" + case "${enableval}" in + yes) sim_profile="-DPROFILE=1 -DWITH_PROFILE=-1";; + no) sim_profile="-DPROFILE=0 -DWITH_PROFILE=0";; + [-0-9]*) + sim_profile="-DPROFILE='(${enableval})' -DWITH_PROFILE='(${enableval})'";; + [a-z]*) + sim_profile="" + for x in `echo "$enableval" | sed -e "s/,/ /g"`; do + if test x"$sim_profile" = x; then + sim_profile="-DWITH_PROFILE='(PROFILE_$x" + else + sim_profile="${sim_profile}|PROFILE_$x" + fi + done + sim_profile="$sim_profile)'" ;; +esac +if test x"$silent" != x"yes" && test x"$sim_profile" != x""; then + echo "Setting sim profile = $sim_profile" 6>&1 +fi +else + sim_profile="" +fi + + + +echo $ac_n "checking return type of signal handlers""... $ac_c" 1>&6 +echo "configure:3284: checking return type of signal handlers" >&5 +if eval "test \"`echo '$''{'ac_cv_type_signal'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#include +#ifdef signal +#undef signal +#endif +#ifdef __cplusplus +extern "C" void (*signal (int, void (*)(int)))(int); +#else +void (*signal ()) (); +#endif + +int main() { +int i; +; return 0; } +EOF +if { (eval echo configure:3306: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_type_signal=void +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_type_signal=int +fi +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_type_signal" 1>&6 +cat >> confdefs.h <&6 +echo "configure:3326: checking for executable suffix" >&5 +if eval "test \"`echo '$''{'am_cv_exeext'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$CYGWIN32" = yes; then +am_cv_exeext=.exe +else +cat > am_c_test.c << 'EOF' +int main() { +/* Nothing needed here */ +} +EOF +${CC-cc} -o am_c_test $CFLAGS $CPPFLAGS $LDFLAGS am_c_test.c $LIBS 1>&5 +am_cv_exeext=`ls am_c_test.* | grep -v am_c_test.c | sed -e s/am_c_test//` +rm -f am_c_test* +fi + +test x"${am_cv_exeext}" = x && am_cv_exeext=no +fi +EXEEXT="" +test x"${am_cv_exeext}" != xno && EXEEXT=${am_cv_exeext} +echo "$ac_t""${am_cv_exeext}" 1>&6 + + +sim_link_files= +sim_link_links= + +sim_link_links=tconfig.h +if test -f ${srcdir}/tconfig.in +then + sim_link_files=tconfig.in +else + sim_link_files=../common/tconfig.in +fi + +# targ-vals.def points to the libc macro description file. +case "${target}" in +*-*-*) TARG_VALS_DEF=../common/nltvals.def ;; +esac +sim_link_files="${sim_link_files} ${TARG_VALS_DEF}" +sim_link_links="${sim_link_links} targ-vals.def" + + + + +# Check whether --enable-build-warnings or --disable-build-warnings was given. +if test "${enable_build_warnings+set}" = set; then + enableval="$enable_build_warnings" + build_warnings="-Wall -Wpointer-arith -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations" +case "${enableval}" in + yes) ;; + no) build_warnings="-w";; + ,*) t=`echo "${enableval}" | sed -e "s/,/ /g"` + build_warnings="${build_warnings} ${t}";; + *,) t=`echo "${enableval}" | sed -e "s/,/ /g"` + build_warnings="${t} ${build_warnings}";; + *) build_warnings=`echo "${enableval}" | sed -e "s/,/ /g"`;; +esac +if test x"$silent" != x"yes" && test x"$build_warnings" != x""; then + echo "Setting warning flags = $build_warnings" 6>&1 +fi +else + build_warnings="" +fi + + +for ac_hdr in unistd.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:3396: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:3406: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <&6 +fi +done + + + + + +trap '' 1 2 15 +cat > confcache <<\EOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs. It is not useful on other systems. +# If it contains results you don't want to keep, you may remove or edit it. +# +# By default, configure uses ./config.cache as the cache file, +# creating it if it does not exist already. You can give configure +# the --cache-file=FILE option to use a different cache file; that is +# what configure does when it calls configure scripts in +# subdirectories, so they share the cache. +# Giving --cache-file=/dev/null disables caching, for debugging configure. +# config.status only pays attention to the cache file if you give it the +# --recheck option to rerun configure. +# +EOF +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +(set) 2>&1 | + case `(ac_space=' '; set) 2>&1 | grep ac_space` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote substitution + # turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + -e "s/'/'\\\\''/g" \ + -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' + ;; + esac >> confcache +if cmp -s $cache_file confcache; then + : +else + if test -w $cache_file; then + echo "updating cache $cache_file" + cat confcache > $cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# Any assignment to VPATH causes Sun make to only execute +# the first set of double-colon rules, so remove it if not needed. +# If there is a colon in the path, we need to keep it. +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d' +fi + +trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15 + +DEFS=-DHAVE_CONFIG_H + +# Without the "./", some shells look in PATH for config.status. +: ${CONFIG_STATUS=./config.status} + +echo creating $CONFIG_STATUS +rm -f $CONFIG_STATUS +cat > $CONFIG_STATUS </dev/null | sed 1q`: +# +# $0 $ac_configure_args +# +# Compiler output produced by configure, useful for debugging +# configure, is in ./config.log if it exists. + +ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]" +for ac_option +do + case "\$ac_option" in + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion" + exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;; + -version | --version | --versio | --versi | --vers | --ver | --ve | --v) + echo "$CONFIG_STATUS generated by autoconf version 2.12.2" + exit 0 ;; + -help | --help | --hel | --he | --h) + echo "\$ac_cs_usage"; exit 0 ;; + *) echo "\$ac_cs_usage"; exit 1 ;; + esac +done + +ac_given_srcdir=$srcdir +ac_given_INSTALL="$INSTALL" + +trap 'rm -fr `echo "Makefile.sim:Makefile.in Make-common.sim:../common/Make-common.in .gdbinit:../common/gdbinit.in config.h:config.in" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 +EOF +cat >> $CONFIG_STATUS < conftest.subs <<\\CEOF +$ac_vpsub +$extrasub +s%@sim_environment@%$sim_environment%g +s%@sim_alignment@%$sim_alignment%g +s%@sim_assert@%$sim_assert%g +s%@sim_bitsize@%$sim_bitsize%g +s%@sim_endian@%$sim_endian%g +s%@sim_hostendian@%$sim_hostendian%g +s%@sim_float@%$sim_float%g +s%@sim_scache@%$sim_scache%g +s%@sim_default_model@%$sim_default_model%g +s%@sim_hw_cflags@%$sim_hw_cflags%g +s%@sim_hw_objs@%$sim_hw_objs%g +s%@sim_hw@%$sim_hw%g +s%@sim_inline@%$sim_inline%g +s%@sim_packages@%$sim_packages%g +s%@sim_regparm@%$sim_regparm%g +s%@sim_reserved_bits@%$sim_reserved_bits%g +s%@sim_smp@%$sim_smp%g +s%@sim_stdcall@%$sim_stdcall%g +s%@sim_xor_endian@%$sim_xor_endian%g +s%@build_warnings@%$build_warnings%g +s%@SHELL@%$SHELL%g +s%@CFLAGS@%$CFLAGS%g +s%@CPPFLAGS@%$CPPFLAGS%g +s%@CXXFLAGS@%$CXXFLAGS%g +s%@DEFS@%$DEFS%g +s%@LDFLAGS@%$LDFLAGS%g +s%@LIBS@%$LIBS%g +s%@exec_prefix@%$exec_prefix%g +s%@prefix@%$prefix%g +s%@program_transform_name@%$program_transform_name%g +s%@bindir@%$bindir%g +s%@sbindir@%$sbindir%g +s%@libexecdir@%$libexecdir%g +s%@datadir@%$datadir%g +s%@sysconfdir@%$sysconfdir%g +s%@sharedstatedir@%$sharedstatedir%g +s%@localstatedir@%$localstatedir%g +s%@libdir@%$libdir%g +s%@includedir@%$includedir%g +s%@oldincludedir@%$oldincludedir%g +s%@infodir@%$infodir%g +s%@mandir@%$mandir%g +s%@host@%$host%g +s%@host_alias@%$host_alias%g +s%@host_cpu@%$host_cpu%g +s%@host_vendor@%$host_vendor%g +s%@host_os@%$host_os%g +s%@target@%$target%g +s%@target_alias@%$target_alias%g +s%@target_cpu@%$target_cpu%g +s%@target_vendor@%$target_vendor%g +s%@target_os@%$target_os%g +s%@build@%$build%g +s%@build_alias@%$build_alias%g +s%@build_cpu@%$build_cpu%g +s%@build_vendor@%$build_vendor%g +s%@build_os@%$build_os%g +s%@CC@%$CC%g +s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g +s%@INSTALL_DATA@%$INSTALL_DATA%g +s%@CC_FOR_BUILD@%$CC_FOR_BUILD%g +s%@HDEFINES@%$HDEFINES%g +s%@AR@%$AR%g +s%@RANLIB@%$RANLIB%g +s%@SET_MAKE@%$SET_MAKE%g +s%@CPP@%$CPP%g +s%@ALLOCA@%$ALLOCA%g +s%@USE_NLS@%$USE_NLS%g +s%@MSGFMT@%$MSGFMT%g +s%@GMSGFMT@%$GMSGFMT%g +s%@XGETTEXT@%$XGETTEXT%g +s%@USE_INCLUDED_LIBINTL@%$USE_INCLUDED_LIBINTL%g +s%@CATALOGS@%$CATALOGS%g +s%@CATOBJEXT@%$CATOBJEXT%g +s%@DATADIRNAME@%$DATADIRNAME%g +s%@GMOFILES@%$GMOFILES%g +s%@INSTOBJEXT@%$INSTOBJEXT%g +s%@INTLDEPS@%$INTLDEPS%g +s%@INTLLIBS@%$INTLLIBS%g +s%@INTLOBJS@%$INTLOBJS%g +s%@POFILES@%$POFILES%g +s%@POSUB@%$POSUB%g +s%@INCLUDE_LOCALE_H@%$INCLUDE_LOCALE_H%g +s%@GT_NO@%$GT_NO%g +s%@GT_YES@%$GT_YES%g +s%@MKINSTALLDIRS@%$MKINSTALLDIRS%g +s%@l@%$l%g +s%@MAINT@%$MAINT%g +s%@sim_bswap@%$sim_bswap%g +s%@sim_cflags@%$sim_cflags%g +s%@sim_debug@%$sim_debug%g +s%@sim_stdio@%$sim_stdio%g +s%@sim_trace@%$sim_trace%g +s%@sim_profile@%$sim_profile%g +s%@EXEEXT@%$EXEEXT%g + +CEOF +EOF + +cat >> $CONFIG_STATUS <<\EOF + +# Split the substitutions into bite-sized pieces for seds with +# small command number limits, like on Digital OSF/1 and HP-UX. +ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script. +ac_file=1 # Number of current file. +ac_beg=1 # First line for current file. +ac_end=$ac_max_sed_cmds # Line after last line for current file. +ac_more_lines=: +ac_sed_cmds="" +while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file + else + sed "${ac_end}q" conftest.subs > conftest.s$ac_file + fi + if test ! -s conftest.s$ac_file; then + ac_more_lines=false + rm -f conftest.s$ac_file + else + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f conftest.s$ac_file" + else + ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file" + fi + ac_file=`expr $ac_file + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_cmds` + fi +done +if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat +fi +EOF + +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories. + + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`" + # A "../" for each directory in $ac_dir_suffix. + ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'` + else + ac_dir_suffix= ac_dots= + fi + + case "$ac_given_srcdir" in + .) srcdir=. + if test -z "$ac_dots"; then top_srcdir=. + else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;; + /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;; + *) # Relative path. + srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix" + top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + + case "$ac_given_INSTALL" in + [/$]*) INSTALL="$ac_given_INSTALL" ;; + *) INSTALL="$ac_dots$ac_given_INSTALL" ;; + esac + + echo creating "$ac_file" + rm -f "$ac_file" + configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure." + case "$ac_file" in + *Makefile*) ac_comsub="1i\\ +# $configure_input" ;; + *) ac_comsub= ;; + esac + + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + sed -e "$ac_comsub +s%@configure_input@%$configure_input%g +s%@srcdir@%$srcdir%g +s%@top_srcdir@%$top_srcdir%g +s%@INSTALL@%$INSTALL%g +" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file +fi; done +rm -f conftest.s* + +# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where +# NAME is the cpp macro being defined and VALUE is the value it is being given. +# +# ac_d sets the value in "#define NAME VALUE" lines. +ac_dA='s%^\([ ]*\)#\([ ]*define[ ][ ]*\)' +ac_dB='\([ ][ ]*\)[^ ]*%\1#\2' +ac_dC='\3' +ac_dD='%g' +# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE". +ac_uA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_uB='\([ ]\)%\1#\2define\3' +ac_uC=' ' +ac_uD='\4%g' +# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE". +ac_eA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_eB='$%\1#\2define\3' +ac_eC=' ' +ac_eD='%g' + +if test "${CONFIG_HEADERS+set}" != set; then +EOF +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +fi +for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + echo creating $ac_file + + rm -f conftest.frag conftest.in conftest.out + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + cat $ac_file_inputs > conftest.in + +EOF + +# Transform confdefs.h into a sed script conftest.vals that substitutes +# the proper values into config.h.in to produce config.h. And first: +# Protect against being on the right side of a sed subst in config.status. +# Protect against being in an unquoted here document in config.status. +rm -f conftest.vals +cat > conftest.hdr <<\EOF +s/[\\&%]/\\&/g +s%[\\$`]%\\&%g +s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp +s%ac_d%ac_u%gp +s%ac_u%ac_e%gp +EOF +sed -n -f conftest.hdr confdefs.h > conftest.vals +rm -f conftest.hdr + +# This sed command replaces #undef with comments. This is necessary, for +# example, in the case of _POSIX_SOURCE, which is predefined and required +# on some systems where configure will not decide to define it. +cat >> conftest.vals <<\EOF +s%^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */% +EOF + +# Break up conftest.vals because some shells have a limit on +# the size of here documents, and old seds have small limits too. + +rm -f conftest.tail +while : +do + ac_lines=`grep -c . conftest.vals` + # grep -c gives empty output for an empty file on some AIX systems. + if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi + # Write a limited-size here document to conftest.frag. + echo ' cat > conftest.frag <> $CONFIG_STATUS + sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS + echo 'CEOF + sed -f conftest.frag conftest.in > conftest.out + rm -f conftest.in + mv conftest.out conftest.in +' >> $CONFIG_STATUS + sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail + rm -f conftest.vals + mv conftest.tail conftest.vals +done +rm -f conftest.vals + +cat >> $CONFIG_STATUS <<\EOF + rm -f conftest.frag conftest.h + echo "/* $ac_file. Generated automatically by configure. */" > conftest.h + cat conftest.in >> conftest.h + rm -f conftest.in + if cmp -s $ac_file conftest.h 2>/dev/null; then + echo "$ac_file is unchanged" + rm -f conftest.h + else + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + fi + rm -f $ac_file + mv conftest.h $ac_file + fi +fi; done + +EOF + +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +srcdir=$ac_given_srcdir +while test -n "$ac_sources"; do + set $ac_dests; ac_dest=$1; shift; ac_dests=$* + set $ac_sources; ac_source=$1; shift; ac_sources=$* + + echo "linking $srcdir/$ac_source to $ac_dest" + + if test ! -r $srcdir/$ac_source; then + { echo "configure: error: $srcdir/$ac_source: File not found" 1>&2; exit 1; } + fi + rm -f $ac_dest + + # Make relative symlinks. + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dest_dir=`echo $ac_dest|sed 's%/[^/][^/]*$%%'` + if test "$ac_dest_dir" != "$ac_dest" && test "$ac_dest_dir" != .; then + # The dest file is in a subdirectory. + test ! -d "$ac_dest_dir" && mkdir "$ac_dest_dir" + ac_dest_dir_suffix="/`echo $ac_dest_dir|sed 's%^\./%%'`" + # A "../" for each directory in $ac_dest_dir_suffix. + ac_dots=`echo $ac_dest_dir_suffix|sed 's%/[^/]*%../%g'` + else + ac_dest_dir_suffix= ac_dots= + fi + + case "$srcdir" in + [/$]*) ac_rel_source="$srcdir/$ac_source" ;; + *) ac_rel_source="$ac_dots$srcdir/$ac_source" ;; + esac + + # Make a symlink if possible; otherwise try a hard link. + if ln -s $ac_rel_source $ac_dest 2>/dev/null || + ln $srcdir/$ac_source $ac_dest; then : + else + { echo "configure: error: can not link $ac_dest to $srcdir/$ac_source" 1>&2; exit 1; } + fi +done +EOF +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +case "x$CONFIG_FILES" in + xMakefile*) + echo "Merging Makefile.sim+Make-common.sim into Makefile ..." + rm -f Makesim1.tmp Makesim2.tmp Makefile + sed -n -e '/^## COMMON_PRE_/,/^## End COMMON_PRE_/ p' Makesim1.tmp + sed -n -e '/^## COMMON_POST_/,/^## End COMMON_POST_/ p' Makesim2.tmp + sed -e '/^## COMMON_PRE_/ r Makesim1.tmp' \ + -e '/^## COMMON_POST_/ r Makesim2.tmp' \ + Makefile + rm -f Makefile.sim Make-common.sim Makesim1.tmp Makesim2.tmp + ;; + esac + case "x$CONFIG_HEADERS" in xconfig.h:config.in) echo > stamp-h ;; esac + +exit 0 +EOF +chmod +x $CONFIG_STATUS +rm -fr confdefs* $ac_clean_files +test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1 + + diff --git a/sim/d10v/configure.in b/sim/d10v/configure.in new file mode 100644 index 00000000000..5debf66c23d --- /dev/null +++ b/sim/d10v/configure.in @@ -0,0 +1,13 @@ +dnl Process this file with autoconf to produce a configure script. +sinclude(../common/aclocal.m4) +AC_PREREQ(2.5)dnl +AC_INIT(Makefile.in) + +SIM_AC_COMMON + +SIM_AC_OPTION_WARNINGS + +AC_CHECK_HEADERS(unistd.h) + + +SIM_AC_OUTPUT diff --git a/sim/d10v/d10v_sim.h b/sim/d10v/d10v_sim.h new file mode 100644 index 00000000000..ca7e02ec9c5 --- /dev/null +++ b/sim/d10v/d10v_sim.h @@ -0,0 +1,452 @@ +#include "config.h" +#include +#include +#include +#include "ansidecl.h" +#include "callback.h" +#include "opcode/d10v.h" +#include "bfd.h" + +#define DEBUG_TRACE 0x00000001 +#define DEBUG_VALUES 0x00000002 +#define DEBUG_LINE_NUMBER 0x00000004 +#define DEBUG_MEMSIZE 0x00000008 +#define DEBUG_INSTRUCTION 0x00000010 +#define DEBUG_TRAP 0x00000020 + +#ifndef DEBUG +#define DEBUG (DEBUG_TRACE | DEBUG_VALUES | DEBUG_LINE_NUMBER) +#endif + +extern int d10v_debug; + +#include "remote-sim.h" +#include "sim-config.h" +#include "sim-types.h" + +typedef unsigned8 uint8; +typedef unsigned16 uint16; +typedef signed16 int16; +typedef unsigned32 uint32; +typedef signed32 int32; +typedef unsigned64 uint64; +typedef signed64 int64; + +/* FIXME: D10V defines */ +typedef uint16 reg_t; + +struct simops +{ + long opcode; + int is_long; + long mask; + int format; + int cycles; + int unit; + int exec_type; + void (*func)(); + int numops; + int operands[9]; +}; + +enum _ins_type +{ + INS_UNKNOWN, /* unknown instruction */ + INS_COND_TRUE, /* # times EXExxx executed other instruction */ + INS_COND_FALSE, /* # times EXExxx did not execute other instruction */ + INS_COND_JUMP, /* # times JUMP skipped other instruction */ + INS_CYCLES, /* # cycles */ + INS_LONG, /* long instruction (both containers, ie FM == 11) */ + INS_LEFTRIGHT, /* # times instruction encoded as L -> R (ie, FM == 01) */ + INS_RIGHTLEFT, /* # times instruction encoded as L <- R (ie, FM == 10) */ + INS_PARALLEL, /* # times instruction encoded as L || R (ie, RM == 00) */ + + INS_LEFT, /* normal left instructions */ + INS_LEFT_PARALLEL, /* left side of || */ + INS_LEFT_COND_TEST, /* EXExx test on left side */ + INS_LEFT_COND_EXE, /* execution after EXExxx test on right side succeeded */ + INS_LEFT_NOPS, /* NOP on left side */ + + INS_RIGHT, /* normal right instructions */ + INS_RIGHT_PARALLEL, /* right side of || */ + INS_RIGHT_COND_TEST, /* EXExx test on right side */ + INS_RIGHT_COND_EXE, /* execution after EXExxx test on left side succeeded */ + INS_RIGHT_NOPS, /* NOP on right side */ + + INS_MAX +}; + +extern unsigned long ins_type_counters[ (int)INS_MAX ]; + +enum { + SP_IDX = 15, +}; + +/* Write-back slots */ +union slot_data { + unsigned_1 _1; + unsigned_2 _2; + unsigned_4 _4; + unsigned_8 _8; +}; +struct slot { + void *dest; + int size; + union slot_data data; + union slot_data mask; +}; +enum { + NR_SLOTS = 16, +}; +#define SLOT (State.slot) +#define SLOT_NR (State.slot_nr) +#define SLOT_PEND_MASK(DEST, MSK, VAL) \ + do \ + { \ + SLOT[SLOT_NR].dest = &(DEST); \ + SLOT[SLOT_NR].size = sizeof (DEST); \ + switch (sizeof (DEST)) \ + { \ + case 1: \ + SLOT[SLOT_NR].data._1 = (unsigned_1) (VAL); \ + SLOT[SLOT_NR].mask._1 = (unsigned_1) (MSK); \ + break; \ + case 2: \ + SLOT[SLOT_NR].data._2 = (unsigned_2) (VAL); \ + SLOT[SLOT_NR].mask._2 = (unsigned_2) (MSK); \ + break; \ + case 4: \ + SLOT[SLOT_NR].data._4 = (unsigned_4) (VAL); \ + SLOT[SLOT_NR].mask._4 = (unsigned_4) (MSK); \ + break; \ + case 8: \ + SLOT[SLOT_NR].data._8 = (unsigned_8) (VAL); \ + SLOT[SLOT_NR].mask._8 = (unsigned_8) (MSK); \ + break; \ + } \ + SLOT_NR = (SLOT_NR + 1); \ + } \ + while (0) +#define SLOT_PEND(DEST, VAL) SLOT_PEND_MASK(DEST, 0, VAL) +#define SLOT_DISCARD() (SLOT_NR = 0) +#define SLOT_FLUSH() \ + do \ + { \ + int i; \ + for (i = 0; i < SLOT_NR; i++) \ + { \ + switch (SLOT[i].size) \ + { \ + case 1: \ + *(unsigned_1*) SLOT[i].dest &= SLOT[i].mask._1; \ + *(unsigned_1*) SLOT[i].dest |= SLOT[i].data._1; \ + break; \ + case 2: \ + *(unsigned_2*) SLOT[i].dest &= SLOT[i].mask._2; \ + *(unsigned_2*) SLOT[i].dest |= SLOT[i].data._2; \ + break; \ + case 4: \ + *(unsigned_4*) SLOT[i].dest &= SLOT[i].mask._4; \ + *(unsigned_4*) SLOT[i].dest |= SLOT[i].data._4; \ + break; \ + case 8: \ + *(unsigned_8*) SLOT[i].dest &= SLOT[i].mask._8; \ + *(unsigned_8*) SLOT[i].dest |= SLOT[i].data._8; \ + break; \ + } \ + } \ + SLOT_NR = 0; \ + } \ + while (0) +#define SLOT_DUMP() \ + do \ + { \ + int i; \ + for (i = 0; i < SLOT_NR; i++) \ + { \ + switch (SLOT[i].size) \ + { \ + case 1: \ + printf ("SLOT %d *0x%08lx & 0x%02x | 0x%02x\n", i, \ + (long) SLOT[i].dest, \ + (unsigned) SLOT[i].mask._1, \ + (unsigned) SLOT[i].data._1); \ + break; \ + case 2: \ + printf ("SLOT %d *0x%08lx & 0x%04x | 0x%04x\n", i, \ + (long) SLOT[i].dest, \ + (unsigned) SLOT[i].mask._2, \ + (unsigned) SLOT[i].data._2); \ + break; \ + case 4: \ + printf ("SLOT %d *0x%08lx & 0x%08x | 0x%08x\n", i, \ + (long) SLOT[i].dest, \ + (unsigned) SLOT[i].mask._4, \ + (unsigned) SLOT[i].data._4); \ + break; \ + case 8: \ + printf ("SLOT %d *0x%08lx & 0x%08x%08x | 0x%08x%08x\n", i, \ + (long) SLOT[i].dest, \ + (unsigned) (SLOT[i].mask._8 >> 32), \ + (unsigned) SLOT[i].mask._8, \ + (unsigned) (SLOT[i].data._8 >> 32), \ + (unsigned) SLOT[i].data._8); \ + break; \ + } \ + } \ + } \ + while (0) + +struct _state +{ + reg_t regs[16]; /* general-purpose registers */ +#define GPR(N) (State.regs[(N)] + 0) +#define SET_GPR(N,VAL) SLOT_PEND (State.regs[(N)], (VAL)) + +#define GPR32(N) ((((uint32) State.regs[(N) + 0]) << 16) \ + | (uint16) State.regs[(N) + 1]) +#define SET_GPR32(N,VAL) do { SET_GPR (OP[0] + 0, (VAL) >> 16); SET_GPR (OP[0] + 1, (VAL)); } while (0) + + reg_t cregs[16]; /* control registers */ +#define CREG(N) (State.cregs[(N)] + 0) +#define SET_CREG(N,VAL) move_to_cr ((N), 0, (VAL)) + + reg_t sp[2]; /* holding area for SPI(0)/SPU(1) */ +#define HELD_SP(N) (State.sp[(N)] + 0) +#define SET_HELD_SP(N,VAL) SLOT_PEND (State.sp[(N)], (VAL)) + + int64 a[2]; /* accumulators */ +#define ACC(N) (State.a[(N)] + 0) +#define SET_ACC(N,VAL) SLOT_PEND (State.a[(N)], (VAL) & MASK40) + + /* writeback info */ + struct slot slot[NR_SLOTS]; + int slot_nr; + + /* trace data */ + struct { + uint16 psw; + } trace; + + uint8 exe; + int exception; + int pc_changed; + + /* NOTE: everything below this line is not reset by sim_create_inferior() */ + uint8 *imem; + uint8 *dmem; + uint8 *umem[128]; + enum _ins_type ins_type; + +} State; + + +extern host_callback *d10v_callback; +extern uint16 OP[4]; +extern struct simops Simops[]; +extern asection *text; +extern bfd_vma text_start; +extern bfd_vma text_end; +extern bfd *prog_bfd; + +enum +{ + PSW_CR = 0, + BPSW_CR = 1, + PC_CR = 2, + BPC_CR = 3, + DPSW_CR = 4, + DPC_CR = 5, + RPT_C_CR = 7, + RPT_S_CR = 8, + RPT_E_CR = 9, + MOD_S_CR = 10, + MOD_E_CR = 11, + IBA_CR = 14, +}; + +enum +{ + PSW_SM_BIT = 0x8000, + PSW_EA_BIT = 0x2000, + PSW_DB_BIT = 0x1000, + PSW_DM_BIT = 0x0800, + PSW_IE_BIT = 0x0400, + PSW_RP_BIT = 0x0200, + PSW_MD_BIT = 0x0100, + PSW_FX_BIT = 0x0080, + PSW_ST_BIT = 0x0040, + PSW_F0_BIT = 0x0008, + PSW_F1_BIT = 0x0004, + PSW_C_BIT = 0x0001, +}; + +#define PSW CREG (PSW_CR) +#define SET_PSW(VAL) SET_CREG (PSW_CR, (VAL)) +#define SET_PSW_BIT(MASK,VAL) move_to_cr (PSW_CR, ~(MASK), (VAL) ? (MASK) : 0) + +#define PSW_SM ((PSW & PSW_SM_BIT) != 0) +#define SET_PSW_SM(VAL) SET_PSW_BIT (PSW_SM_BIT, (VAL)) + +#define PSW_EA ((PSW & PSW_EA_BIT) != 0) +#define SET_PSW_EA(VAL) SET_PSW_BIT (PSW_EA_BIT, (VAL)) + +#define PSW_DB ((PSW & PSW_DB_BIT) != 0) +#define SET_PSW_DB(VAL) SET_PSW_BIT (PSW_DB_BIT, (VAL)) + +#define PSW_DM ((PSW & PSW_DM_BIT) != 0) +#define SET_PSW_DM(VAL) SET_PSW_BIT (PSW_DM_BIT, (VAL)) + +#define PSW_IE ((PSW & PSW_IE_BIT) != 0) +#define SET_PSW_IE(VAL) SET_PSW_BIT (PSW_IE_BIT, (VAL)) + +#define PSW_RP ((PSW & PSW_RP_BIT) != 0) +#define SET_PSW_RP(VAL) SET_PSW_BIT (PSW_RP_BIT, (VAL)) + +#define PSW_MD ((PSW & PSW_MD_BIT) != 0) +#define SET_PSW_MD(VAL) SET_PSW_BIT (PSW_MD_BIT, (VAL)) + +#define PSW_FX ((PSW & PSW_FX_BIT) != 0) +#define SET_PSW_FX(VAL) SET_PSW_BIT (PSW_FX_BIT, (VAL)) + +#define PSW_ST ((PSW & PSW_ST_BIT) != 0) +#define SET_PSW_ST(VAL) SET_PSW_BIT (PSW_ST_BIT, (VAL)) + +#define PSW_F0 ((PSW & PSW_F0_BIT) != 0) +#define SET_PSW_F0(VAL) SET_PSW_BIT (PSW_F0_BIT, (VAL)) + +#define PSW_F1 ((PSW & PSW_F1_BIT) != 0) +#define SET_PSW_F1(VAL) SET_PSW_BIT (PSW_F1_BIT, (VAL)) + +#define PSW_C ((PSW & PSW_C_BIT) != 0) +#define SET_PSW_C(VAL) SET_PSW_BIT (PSW_C_BIT, (VAL)) + +/* See simopsc.:move_to_cr() for registers that can not be read-from + or assigned-to directly */ + +#define PC CREG (PC_CR) +#define SET_PC(VAL) SET_CREG (PC_CR, (VAL)) + +#define BPSW CREG (BPSW_CR) +#define SET_BPSW(VAL) SET_CREG (BPSW_CR, (VAL)) + +#define BPC CREG (BPC_CR) +#define SET_BPC(VAL) SET_CREG (BPC_CR, (VAL)) + +#define DPSW CREG (DPSW_CR) +#define SET_DPSW(VAL) SET_CREG (DPSW_CR, (VAL)) + +#define DPC CREG (DPC_CR) +#define SET_DPC(VAL) SET_CREG (DPC_CR, (VAL)) + +#define RPT_C CREG (RPT_C_CR) +#define SET_RPT_C(VAL) SET_CREG (RPT_C_CR, (VAL)) + +#define RPT_S CREG (RPT_S_CR) +#define SET_RPT_S(VAL) SET_CREG (RPT_S_CR, (VAL)) + +#define RPT_E CREG (RPT_E_CR) +#define SET_RPT_E(VAL) SET_CREG (RPT_E_CR, (VAL)) + +#define MOD_S CREG (MOD_S_CR) +#define SET_MOD_S(VAL) SET_CREG (MOD_S_CR, (VAL)) + +#define MOD_E CREG (MOD_E_CR) +#define SET_MOD_E(VAL) SET_CREG (MOD_E_CR, (VAL)) + +#define IBA CREG (IBA_CR) +#define SET_IBA(VAL) SET_CREG (IBA_CR, (VAL)) + + +#define SIG_D10V_STOP -1 +#define SIG_D10V_EXIT -2 + +#define SEXT3(x) ((((x)&0x7)^(~3))+4) + +/* sign-extend a 4-bit number */ +#define SEXT4(x) ((((x)&0xf)^(~7))+8) + +/* sign-extend an 8-bit number */ +#define SEXT8(x) ((((x)&0xff)^(~0x7f))+0x80) + +/* sign-extend a 16-bit number */ +#define SEXT16(x) ((((x)&0xffff)^(~0x7fff))+0x8000) + +/* sign-extend a 32-bit number */ +#define SEXT32(x) ((((x)&SIGNED64(0xffffffff))^(~SIGNED64(0x7fffffff)))+SIGNED64(0x80000000)) + +/* sign extend a 40 bit number */ +#define SEXT40(x) ((((x)&SIGNED64(0xffffffffff))^(~SIGNED64(0x7fffffffff)))+SIGNED64(0x8000000000)) + +/* sign extend a 44 bit number */ +#define SEXT44(x) ((((x)&SIGNED64(0xfffffffffff))^(~SIGNED64(0x7ffffffffff)))+SIGNED64(0x80000000000)) + +/* sign extend a 56 bit number */ +#define SEXT56(x) ((((x)&SIGNED64(0xffffffffffffff))^(~SIGNED64(0x7fffffffffffff)))+SIGNED64(0x80000000000000)) + +/* sign extend a 60 bit number */ +#define SEXT60(x) ((((x)&SIGNED64(0xfffffffffffffff))^(~SIGNED64(0x7ffffffffffffff)))+SIGNED64(0x800000000000000)) + +#define MAX32 SIGNED64(0x7fffffff) +#define MIN32 SIGNED64(0xff80000000) +#define MASK32 SIGNED64(0xffffffff) +#define MASK40 SIGNED64(0xffffffffff) + +/* The alignment of MOD_E in the following macro depends upon "i" + always being a power of 2. */ +#define INC_ADDR(x,i) \ +do \ + { \ + if (PSW_MD && GPR (x) == (MOD_E & ~((i) - 1))) \ + SET_GPR (x, MOD_S); \ + else \ + SET_GPR (x, GPR (x) + (i)); \ + } \ +while (0) + +extern uint8 *dmem_addr PARAMS ((uint32)); +extern uint8 *imem_addr PARAMS ((uint32)); +extern bfd_vma decode_pc PARAMS ((void)); + +#define RB(x) (*(dmem_addr(x))) +#define SB(addr,data) ( RB(addr) = (data & 0xff)) + +#if defined(__GNUC__) && defined(__OPTIMIZE__) && !defined(NO_ENDIAN_INLINE) +#define ENDIAN_INLINE static __inline__ +#include "endian.c" +#undef ENDIAN_INLINE + +#else +extern uint32 get_longword PARAMS ((uint8 *)); +extern uint16 get_word PARAMS ((uint8 *)); +extern int64 get_longlong PARAMS ((uint8 *)); +extern void write_word PARAMS ((uint8 *addr, uint16 data)); +extern void write_longword PARAMS ((uint8 *addr, uint32 data)); +extern void write_longlong PARAMS ((uint8 *addr, int64 data)); +#endif + +#define SW(addr,data) write_word(dmem_addr(addr),data) +#define RW(x) get_word(dmem_addr(x)) +#define SLW(addr,data) write_longword(dmem_addr(addr),data) +#define RLW(x) get_longword(dmem_addr(x)) +#define READ_16(x) get_word(x) +#define WRITE_16(addr,data) write_word(addr,data) +#define READ_64(x) get_longlong(x) +#define WRITE_64(addr,data) write_longlong(addr,data) + +#define IMAP0 RW(0xff00) +#define IMAP1 RW(0xff02) +#define DMAP RW(0xff04) +#define SET_IMAP0(x) SW(0xff00,x) +#define SET_IMAP1(x) SW(0xff02,x) +#define SET_DMAP(x) SW(0xff04,x) + +#define JMP(x) do { SET_PC (x); State.pc_changed = 1; } while (0) + +#define RIE_VECTOR_START 0xffc2 +#define AE_VECTOR_START 0xffc3 +#define TRAP_VECTOR_START 0xffc4 /* vector for trap 0 */ +#define DBT_VECTOR_START 0xffd4 +#define SDBT_VECTOR_START 0xffd5 + +extern reg_t move_to_cr PARAMS ((int cr, reg_t mask, reg_t val)); diff --git a/sim/d10v/endian.c b/sim/d10v/endian.c new file mode 100644 index 00000000000..9ef503eb0e2 --- /dev/null +++ b/sim/d10v/endian.c @@ -0,0 +1,137 @@ +/* If we're being compiled as a .c file, rather than being included in + d10v_sim.h, then ENDIAN_INLINE won't be defined yet. */ + +#ifndef ENDIAN_INLINE +#define NO_ENDIAN_INLINE +#include "d10v_sim.h" +#define ENDIAN_INLINE +#endif + +ENDIAN_INLINE uint16 +get_word (x) + uint8 *x; +{ +#if (defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__)) && defined(__GNUC__) + + unsigned short word = *(unsigned short *)x; + __asm__ ("xchgb %b0,%h0" : "=q" (word) : "0" (word)); + return word; + +#elif defined(WORDS_BIGENDIAN) + /* It is safe to do this on big endian hosts, since the d10v requires that words be + aligned on 16-bit boundaries. */ + return *(uint16 *)x; + +#else + return ((uint16)x[0]<<8) + x[1]; +#endif +} + +ENDIAN_INLINE uint32 +get_longword (x) + uint8 *x; +{ +#if (defined(__i486__) || defined(__i586__) || defined(__i686__)) && defined(__GNUC__) && defined(USE_BSWAP) + + unsigned int long_word = *(unsigned *)x; + __asm__ ("bswap %0" : "=r" (long_word) : "0" (long_word)); + return long_word; + +#elif (defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__)) && defined(__GNUC__) + + unsigned int long_word = *(unsigned *)x; + __asm__("xchgb %b0,%h0\n\t" /* swap lower bytes */ + "rorl $16,%0\n\t" /* swap words */ + "xchgb %b0,%h0" /* swap higher bytes */ + :"=q" (long_word) + : "0" (long_word)); + + return long_word; + +#elif (defined(_POWER) && defined(_AIX)) || (defined(__PPC__) && defined(__BIG_ENDIAN__)) + /* Power & PowerPC computers in big endian mode can handle unaligned loads&stores */ + return *(uint32 *)x; + +#elif defined(WORDS_BIGENDIAN) + /* long words must be aligned on at least 16-bit boundaries, so this should be safe. */ + return (((uint32) *(uint16 *)x)<<16) | ((uint32) *(uint16 *)(x+2)); + +#else + return ((uint32)x[0]<<24) + ((uint32)x[1]<<16) + ((uint32)x[2]<<8) + ((uint32)x[3]); +#endif +} + +ENDIAN_INLINE int64 +get_longlong (x) + uint8 *x; +{ + uint32 top = get_longword (x); + uint32 bottom = get_longword (x+4); + return (((int64)top)<<32) | (int64)bottom; +} + +ENDIAN_INLINE void +write_word (addr, data) + uint8 *addr; + uint16 data; +{ +#if (defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__)) && defined(__GNUC__) + + __asm__ ("xchgb %b0,%h0" : "=q" (data) : "0" (data)); + *(uint16 *)addr = data; + +#elif defined(WORDS_BIGENDIAN) + /* It is safe to do this on big endian hosts, since the d10v requires that words be + aligned on 16-bit boundaries. */ + *(uint16 *)addr = data; + +#else + addr[0] = (data >> 8) & 0xff; + addr[1] = data & 0xff; +#endif +} + +ENDIAN_INLINE void +write_longword (addr, data) + uint8 *addr; + uint32 data; +{ +#if (defined(__i486__) || defined(__i586__) || defined(__i686__)) && defined(__GNUC__) && defined(USE_BSWAP) + + __asm__ ("bswap %0" : "=r" (data) : "0" (data)); + *(uint32 *)addr = data; + +#elif (defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__)) && defined(__GNUC__) + + __asm__("xchgb %b0,%h0\n\t" /* swap lower bytes */ + "rorl $16,%0\n\t" /* swap words */ + "xchgb %b0,%h0" /* swap higher bytes */ + :"=q" (data) + : "0" (data)); + + *(uint32 *)addr = data; + +#elif (defined(_POWER) && defined(_AIX)) || (defined(__PPC__) && defined(__BIG_ENDIAN__)) + /* Power & PowerPC computers in big endian mode can handle unaligned loads&stores */ + *(uint32 *)addr = data; + +#elif defined(WORDS_BIGENDIAN) + *(uint16 *)addr = (uint16)(data >> 16); + *(uint16 *)(addr + 2) = (uint16)data; + +#else + addr[0] = (data >> 24) & 0xff; + addr[1] = (data >> 16) & 0xff; + addr[2] = (data >> 8) & 0xff; + addr[3] = data & 0xff; +#endif +} + +ENDIAN_INLINE void +write_longlong (addr, data) + uint8 *addr; + int64 data; +{ + write_longword (addr, (uint32)(data >> 32)); + write_longword (addr+4, (uint32)data); +} diff --git a/sim/d10v/gencode.c b/sim/d10v/gencode.c new file mode 100644 index 00000000000..2d1269be996 --- /dev/null +++ b/sim/d10v/gencode.c @@ -0,0 +1,156 @@ +#include "config.h" +#include +#include +#include +#include "ansidecl.h" +#include "callback.h" +#include "opcode/d10v.h" + +static void write_header PARAMS ((void)); +static void write_opcodes PARAMS ((void)); +static void write_template PARAMS ((void)); + +int +main (argc, argv) + int argc; + char *argv[]; +{ + if ((argc > 1) && (strcmp (argv[1],"-h") == 0)) + write_header(); + else if ((argc > 1) && (strcmp (argv[1],"-t") == 0)) + write_template (); + else + write_opcodes(); + return 0; +} + + +static void +write_header () +{ + struct d10v_opcode *opcode; + + for (opcode = (struct d10v_opcode *)d10v_opcodes; opcode->name; opcode++) + if (opcode->format != OPCODE_FAKE) + printf("void OP_%X PARAMS ((void));\t\t/* %s */\n",opcode->opcode, opcode->name); +} + + +/* write_template creates a file all required functions, ready */ +/* to be filled out */ + +static void +write_template () +{ + struct d10v_opcode *opcode; + int i,j; + + printf ("#include \"d10v_sim.h\"\n"); + printf ("#include \"simops.h\"\n"); + + for (opcode = (struct d10v_opcode *)d10v_opcodes; opcode->name; opcode++) + { + if (opcode->format != OPCODE_FAKE) + { + printf("/* %s */\nvoid\nOP_%X ()\n{\n",opcode->name,opcode->opcode); + + /* count operands */ + j = 0; + for (i=0;i<6;i++) + { + int flags = d10v_operands[opcode->operands[i]].flags; + if ((flags & OPERAND_REG) || (flags & OPERAND_NUM) || (flags & OPERAND_ADDR)) + j++; + } + switch (j) + { + case 0: + printf ("printf(\" %s\\n\");\n",opcode->name); + break; + case 1: + printf ("printf(\" %s\\t%%x\\n\",OP[0]);\n",opcode->name); + break; + case 2: + printf ("printf(\" %s\\t%%x,%%x\\n\",OP[0],OP[1]);\n",opcode->name); + break; + case 3: + printf ("printf(\" %s\\t%%x,%%x,%%x\\n\",OP[0],OP[1],OP[2]);\n",opcode->name); + break; + default: + fprintf (stderr,"Too many operands: %d\n",j); + } + printf ("}\n\n"); + } + } +} + + +long Opcodes[512]; +static int curop=0; + +check_opcodes( long op) +{ + int i; + + for (i=0;iname; opcode++) + { + if (opcode->format != OPCODE_FAKE) + { + printf (" { %ld,%d,%ld,%d,%d,%d,%d,OP_%X,", opcode->opcode, + (opcode->format & LONG_OPCODE) ? 1 : 0, opcode->mask, opcode->format, + opcode->cycles, opcode->unit, opcode->exec_type, opcode->opcode); + + /* REMOVE ME */ + check_opcodes (opcode->opcode); + Opcodes[curop++] = opcode->opcode; + + j = 0; + for (i=0;i<6;i++) + { + int flags = d10v_operands[opcode->operands[i]].flags; + if ((flags & OPERAND_REG) || (flags & OPERAND_NUM) || (flags & OPERAND_ADDR)) + j++; + } + printf ("%d,",j); + + j = 0; + for (i=0;i<6;i++) + { + int flags = d10v_operands[opcode->operands[i]].flags; + int shift = d10v_operands[opcode->operands[i]].shift; + if ((flags & OPERAND_REG) || (flags & OPERAND_NUM)|| (flags & OPERAND_ADDR)) + { + if (j == 0) + printf ("{"); + else + printf (", "); + if ((flags & OPERAND_REG) && (opcode->format == LONG_L)) + shift += 15; + printf ("%d,%d,%d",shift,d10v_operands[opcode->operands[i]].bits,flags); + j = 1; + } + } + if (j) + printf ("}"); + printf ("},\n"); + } + } + printf ("{ 0,0,0,0,0,0,0,(void (*)(void))0,0,{0,0,0}},\n};\n"); +} diff --git a/sim/d10v/interp.c b/sim/d10v/interp.c new file mode 100644 index 00000000000..17c964f8d55 --- /dev/null +++ b/sim/d10v/interp.c @@ -0,0 +1,1086 @@ +#include +#include "sysdep.h" +#include "bfd.h" +#include "callback.h" +#include "remote-sim.h" + +#include "d10v_sim.h" + +#define IMEM_SIZE 18 /* D10V instruction memory size is 18 bits */ +#define DMEM_SIZE 16 /* Data memory is 64K (but only 32K internal RAM) */ +#define UMEM_SIZE 17 /* Each unified memory segment is 17 bits */ +#define UMEM_SEGMENTS 128 /* Number of segments in unified memory region */ + +enum _leftright { LEFT_FIRST, RIGHT_FIRST }; + +static char *myname; +static SIM_OPEN_KIND sim_kind; +int d10v_debug; +host_callback *d10v_callback; +unsigned long ins_type_counters[ (int)INS_MAX ]; + +uint16 OP[4]; + +static int init_text_p = 0; +/* non-zero if we opened prog_bfd */ +static int prog_bfd_was_opened_p; +bfd *prog_bfd; +asection *text; +bfd_vma text_start; +bfd_vma text_end; + +static long hash PARAMS ((long insn, int format)); +static struct hash_entry *lookup_hash PARAMS ((uint32 ins, int size)); +static void get_operands PARAMS ((struct simops *s, uint32 ins)); +static void do_long PARAMS ((uint32 ins)); +static void do_2_short PARAMS ((uint16 ins1, uint16 ins2, enum _leftright leftright)); +static void do_parallel PARAMS ((uint16 ins1, uint16 ins2)); +static char *add_commas PARAMS ((char *buf, int sizeof_buf, unsigned long value)); +extern void sim_set_profile PARAMS ((int n)); +extern void sim_set_profile_size PARAMS ((int n)); + +#ifndef INLINE +#if defined(__GNUC__) && defined(__OPTIMIZE__) +#define INLINE __inline__ +#else +#define INLINE +#endif +#endif + +#define MAX_HASH 63 +struct hash_entry +{ + struct hash_entry *next; + uint32 opcode; + uint32 mask; + int size; + struct simops *ops; +}; + +struct hash_entry hash_table[MAX_HASH+1]; + +INLINE static long +hash(insn, format) + long insn; + int format; +{ + if (format & LONG_OPCODE) + return ((insn & 0x3F000000) >> 24); + else + return((insn & 0x7E00) >> 9); +} + +INLINE static struct hash_entry * +lookup_hash (ins, size) + uint32 ins; + int size; +{ + struct hash_entry *h; + + if (size) + h = &hash_table[(ins & 0x3F000000) >> 24]; + else + h = &hash_table[(ins & 0x7E00) >> 9]; + + while ((ins & h->mask) != h->opcode || h->size != size) + { + if (h->next == NULL) + { + (*d10v_callback->printf_filtered) (d10v_callback, "ERROR looking up hash for %x at PC %x\n",ins, PC); + exit (1); + } + h = h->next; + } + return (h); +} + +INLINE static void +get_operands (struct simops *s, uint32 ins) +{ + int i, shift, bits, flags; + uint32 mask; + for (i=0; i < s->numops; i++) + { + shift = s->operands[3*i]; + bits = s->operands[3*i+1]; + flags = s->operands[3*i+2]; + mask = 0x7FFFFFFF >> (31 - bits); + OP[i] = (ins >> shift) & mask; + } + /* FIXME: for tracing, update values that need to be updated each + instruction decode cycle */ + State.trace.psw = PSW; +} + +bfd_vma +decode_pc () +{ + asection *s; + if (!init_text_p && prog_bfd != NULL) + { + init_text_p = 1; + for (s = prog_bfd->sections; s; s = s->next) + if (strcmp (bfd_get_section_name (prog_bfd, s), ".text") == 0) + { + text = s; + text_start = bfd_get_section_vma (prog_bfd, s); + text_end = text_start + bfd_section_size (prog_bfd, s); + break; + } + } + + return (PC << 2) + text_start; +} + +static void +do_long (ins) + uint32 ins; +{ + struct hash_entry *h; +#ifdef DEBUG + if ((d10v_debug & DEBUG_INSTRUCTION) != 0) + (*d10v_callback->printf_filtered) (d10v_callback, "do_long 0x%x\n", ins); +#endif + h = lookup_hash (ins, 1); + get_operands (h->ops, ins); + State.ins_type = INS_LONG; + ins_type_counters[ (int)State.ins_type ]++; + (h->ops->func)(); +} + +static void +do_2_short (ins1, ins2, leftright) + uint16 ins1, ins2; + enum _leftright leftright; +{ + struct hash_entry *h; + enum _ins_type first, second; + +#ifdef DEBUG + if ((d10v_debug & DEBUG_INSTRUCTION) != 0) + (*d10v_callback->printf_filtered) (d10v_callback, "do_2_short 0x%x (%s) -> 0x%x\n", + ins1, (leftright) ? "left" : "right", ins2); +#endif + + if (leftright == LEFT_FIRST) + { + first = INS_LEFT; + second = INS_RIGHT; + ins_type_counters[ (int)INS_LEFTRIGHT ]++; + } + else + { + first = INS_RIGHT; + second = INS_LEFT; + ins_type_counters[ (int)INS_RIGHTLEFT ]++; + } + + /* Issue the first instruction */ + h = lookup_hash (ins1, 0); + get_operands (h->ops, ins1); + State.ins_type = first; + ins_type_counters[ (int)State.ins_type ]++; + (h->ops->func)(); + + /* Issue the second instruction (if the PC hasn't changed) */ + if (!State.pc_changed && !State.exception) + { + /* finish any existing instructions */ + SLOT_FLUSH (); + h = lookup_hash (ins2, 0); + get_operands (h->ops, ins2); + State.ins_type = second; + ins_type_counters[ (int)State.ins_type ]++; + ins_type_counters[ (int)INS_CYCLES ]++; + (h->ops->func)(); + } + else if (!State.exception) + ins_type_counters[ (int)INS_COND_JUMP ]++; +} + +static void +do_parallel (ins1, ins2) + uint16 ins1, ins2; +{ + struct hash_entry *h1, *h2; +#ifdef DEBUG + if ((d10v_debug & DEBUG_INSTRUCTION) != 0) + (*d10v_callback->printf_filtered) (d10v_callback, "do_parallel 0x%x || 0x%x\n", ins1, ins2); +#endif + ins_type_counters[ (int)INS_PARALLEL ]++; + h1 = lookup_hash (ins1, 0); + h2 = lookup_hash (ins2, 0); + + if (h1->ops->exec_type == PARONLY) + { + get_operands (h1->ops, ins1); + State.ins_type = INS_LEFT_COND_TEST; + ins_type_counters[ (int)State.ins_type ]++; + (h1->ops->func)(); + if (State.exe) + { + ins_type_counters[ (int)INS_COND_TRUE ]++; + get_operands (h2->ops, ins2); + State.ins_type = INS_RIGHT_COND_EXE; + ins_type_counters[ (int)State.ins_type ]++; + (h2->ops->func)(); + } + else + ins_type_counters[ (int)INS_COND_FALSE ]++; + } + else if (h2->ops->exec_type == PARONLY) + { + get_operands (h2->ops, ins2); + State.ins_type = INS_RIGHT_COND_TEST; + ins_type_counters[ (int)State.ins_type ]++; + (h2->ops->func)(); + if (State.exe) + { + ins_type_counters[ (int)INS_COND_TRUE ]++; + get_operands (h1->ops, ins1); + State.ins_type = INS_LEFT_COND_EXE; + ins_type_counters[ (int)State.ins_type ]++; + (h1->ops->func)(); + } + else + ins_type_counters[ (int)INS_COND_FALSE ]++; + } + else + { + get_operands (h1->ops, ins1); + State.ins_type = INS_LEFT_PARALLEL; + ins_type_counters[ (int)State.ins_type ]++; + (h1->ops->func)(); + if (!State.exception) + { + get_operands (h2->ops, ins2); + State.ins_type = INS_RIGHT_PARALLEL; + ins_type_counters[ (int)State.ins_type ]++; + (h2->ops->func)(); + } + } +} + +static char * +add_commas(buf, sizeof_buf, value) + char *buf; + int sizeof_buf; + unsigned long value; +{ + int comma = 3; + char *endbuf = buf + sizeof_buf - 1; + + *--endbuf = '\0'; + do { + if (comma-- == 0) + { + *--endbuf = ','; + comma = 2; + } + + *--endbuf = (value % 10) + '0'; + } while ((value /= 10) != 0); + + return endbuf; +} + +void +sim_size (power) + int power; + +{ + int i; + + if (State.imem) + { + for (i=0;iprintf_filtered) (d10v_callback, "Memory allocation failed.\n"); + exit(1); + } + +#ifdef DEBUG + if ((d10v_debug & DEBUG_MEMSIZE) != 0) + { + char buffer[20]; + (*d10v_callback->printf_filtered) (d10v_callback, + "Allocated %s bytes instruction memory and\n", + add_commas (buffer, sizeof (buffer), (1UL<printf_filtered) (d10v_callback, " %s bytes data memory.\n", + add_commas (buffer, sizeof (buffer), (1UL<> 24) & 0xff); + addr = (addr & 0x00ffffff); + +#ifdef DEBUG + if ((d10v_debug & DEBUG_INSTRUCTION) != 0) + { + if (write_p) + { + (*d10v_callback->printf_filtered) (d10v_callback, "sim_write %d bytes to 0x%02x:%06x\n", size, segment, addr); + } + else + { + (*d10v_callback->printf_filtered) (d10v_callback, "sim_read %d bytes from 0x%2x:%6x\n", size, segment, addr); + } + } +#endif + + /* to access data, we use the following mapping + 0x00xxxxxx: Logical data address segment (DMAP translated memory) + 0x01xxxxxx: Logical instruction address segment (IMAP translated memory) + 0x10xxxxxx: Physical data memory segment (On-chip data memory) + 0x11xxxxxx: Physical instruction memory segment (On-chip insn memory) + 0x12xxxxxx: Phisical unified memory segment (Unified memory) + */ + + switch (segment) + { + case 0x00: /* DMAP translated memory */ + { + int byte; + for (byte = 0; byte < size; byte++) + { + uint8 *mem = dmem_addr (addr + byte); + if (mem == NULL) + return byte; + else if (write_p) + *mem = buffer[byte]; + else + buffer[byte] = *mem; + } + return byte; + } + + case 0x01: /* IMAP translated memory */ + { + int byte; + for (byte = 0; byte < size; byte++) + { + uint8 *mem = imem_addr (addr + byte); + if (mem == NULL) + return byte; + else if (write_p) + *mem = buffer[byte]; + else + buffer[byte] = *mem; + } + return byte; + } + + case 0x10: /* On-chip data memory */ + { + addr &= ((1 << DMEM_SIZE) - 1); + if ((addr + size) > (1 << DMEM_SIZE)) + { + (*d10v_callback->printf_filtered) (d10v_callback, "ERROR: data address 0x%x is outside range 0-0x%x.\n", + addr + size - 1, (1 << DMEM_SIZE) - 1); + return (0); + } + memory = State.dmem + addr; + break; + } + + case 0x11: /* On-chip insn memory */ + { + addr &= ((1 << IMEM_SIZE) - 1); + if ((addr + size) > (1 << IMEM_SIZE)) + { + (*d10v_callback->printf_filtered) (d10v_callback, "ERROR: instruction address 0x%x is outside range 0-0x%x.\n", + addr + size - 1, (1 << IMEM_SIZE) - 1); + return (0); + } + memory = State.imem + addr; + break; + } + + case 0x12: /* Unified memory */ + { + int startsegment, startoffset; /* Segment and offset within segment where xfer starts */ + int endsegment, endoffset; /* Segment and offset within segment where xfer ends */ + + startsegment = addr >> UMEM_SIZE; + startoffset = addr & ((1 << UMEM_SIZE) - 1); + endsegment = (addr + size) >> UMEM_SIZE; + endoffset = (addr + size) & ((1 << UMEM_SIZE) - 1); + + /* FIXME: We do not currently implement xfers across segments, + so detect this case and fail gracefully. */ + + if ((startsegment != endsegment) && !((endsegment == (startsegment + 1)) && endoffset == 0)) + { + (*d10v_callback->printf_filtered) (d10v_callback, "ERROR: Unimplemented support for transfers across unified memory segment boundaries\n"); + return (0); + } + if (!State.umem[startsegment]) + { +#ifdef DEBUG + if ((d10v_debug & DEBUG_MEMSIZE) != 0) + { + (*d10v_callback->printf_filtered) (d10v_callback,"Allocating %s bytes unified memory to region %d\n", + add_commas (buffer, sizeof (buffer), (1UL<printf_filtered) (d10v_callback, "ERROR: Memory allocation of 0x%x bytes failed.\n", 1<printf_filtered) (d10v_callback, "ERROR: address 0x%lx is not in valid range\n", (long) addr); + (*d10v_callback->printf_filtered) (d10v_callback, "0x00xxxxxx: Logical data address segment (DMAP translated memory)\n"); + (*d10v_callback->printf_filtered) (d10v_callback, "0x01xxxxxx: Logical instruction address segment (IMAP translated memory)\n"); + (*d10v_callback->printf_filtered) (d10v_callback, "0x10xxxxxx: Physical data memory segment (On-chip data memory)\n"); + (*d10v_callback->printf_filtered) (d10v_callback, "0x11xxxxxx: Physical instruction memory segment (On-chip insn memory)\n"); + (*d10v_callback->printf_filtered) (d10v_callback, "0x12xxxxxx: Phisical unified memory segment (Unified memory)\n"); + return (0); + } + } + + if (write_p) + { + memcpy (memory, buffer, size); + } + else + { + memcpy (buffer, memory, size); + } + + return size; +} + + +int +sim_write (sd, addr, buffer, size) + SIM_DESC sd; + SIM_ADDR addr; + unsigned char *buffer; + int size; +{ + /* FIXME: this should be performing a virtual transfer */ + return xfer_mem( addr, buffer, size, 1); +} + +int +sim_read (sd, addr, buffer, size) + SIM_DESC sd; + SIM_ADDR addr; + unsigned char *buffer; + int size; +{ + /* FIXME: this should be performing a virtual transfer */ + return xfer_mem( addr, buffer, size, 0); +} + + +SIM_DESC +sim_open (kind, callback, abfd, argv) + SIM_OPEN_KIND kind; + host_callback *callback; + struct _bfd *abfd; + char **argv; +{ + struct simops *s; + struct hash_entry *h; + static int init_p = 0; + char **p; + + sim_kind = kind; + d10v_callback = callback; + myname = argv[0]; + + for (p = argv + 1; *p; ++p) + { +#ifdef DEBUG + if (strcmp (*p, "-t") == 0) + d10v_debug = DEBUG; + else +#endif + (*d10v_callback->printf_filtered) (d10v_callback, "ERROR: unsupported option(s): %s\n",*p); + } + + /* put all the opcodes in the hash table */ + if (!init_p++) + { + for (s = Simops; s->func; s++) + { + h = &hash_table[hash(s->opcode,s->format)]; + + /* go to the last entry in the chain */ + while (h->next) + h = h->next; + + if (h->ops) + { + h->next = (struct hash_entry *) calloc(1,sizeof(struct hash_entry)); + if (!h->next) + perror ("malloc failure"); + + h = h->next; + } + h->ops = s; + h->mask = s->mask; + h->opcode = s->opcode; + h->size = s->is_long; + } + } + + /* reset the processor state */ + if (!State.imem) + sim_size(1); + sim_create_inferior ((SIM_DESC) 1, NULL, NULL, NULL); + + /* Fudge our descriptor. */ + return (SIM_DESC) 1; +} + + +void +sim_close (sd, quitting) + SIM_DESC sd; + int quitting; +{ + if (prog_bfd != NULL && prog_bfd_was_opened_p) + { + bfd_close (prog_bfd); + prog_bfd = NULL; + prog_bfd_was_opened_p = 0; + } +} + +void +sim_set_profile (n) + int n; +{ + (*d10v_callback->printf_filtered) (d10v_callback, "sim_set_profile %d\n",n); +} + +void +sim_set_profile_size (n) + int n; +{ + (*d10v_callback->printf_filtered) (d10v_callback, "sim_set_profile_size %d\n",n); +} + + +uint8 * +dmem_addr( addr ) + uint32 addr; +{ + int seg; + + addr &= 0xffff; + + if (addr > 0xbfff) + { + if ( (addr & 0xfff0) != 0xff00) + { + (*d10v_callback->printf_filtered) (d10v_callback, "Data address 0x%lx is in I/O space, pc = 0x%lx.\n", + (long)addr, (long)decode_pc ()); + State.exception = SIGBUS; + } + + return State.dmem + addr; + } + + if (addr > 0x7fff) + { + if (DMAP & 0x1000) + { + /* instruction memory */ + return (DMAP & 0xf) * 0x4000 + State.imem + (addr - 0x8000); + } + else + { + /* unified memory */ + /* this is ugly because we allocate unified memory in 128K segments and */ + /* dmap addresses 16k segments */ + seg = (DMAP & 0x3ff) >> 3; + if (State.umem[seg] == NULL) + { +#ifdef DEBUG + (*d10v_callback->printf_filtered) (d10v_callback,"Allocating %d bytes unified memory to region %d\n", 1<printf_filtered) (d10v_callback, + "ERROR: alloc failed. unified memory region %d unmapped, pc = 0x%lx\n", + seg, (long)decode_pc ()); + State.exception = SIGBUS; + } + } + return State.umem[seg] + (DMAP & 7) * 0x4000 + (addr - 0x8000); + } + } + return State.dmem + addr; +} + + +uint8 * +imem_addr (uint32 pc) +{ + uint16 imap; + + if (pc & 0x20000) + imap = IMAP1; + else + imap = IMAP0; + + if (imap & 0x1000) + return State.imem + pc; + + if (State.umem[imap & 0xff] == NULL) + return 0; + + /* Discard upper bit(s) of PC in case IMAP1 selects unified memory. */ + pc &= (1 << UMEM_SIZE) - 1; + + return State.umem[imap & 0xff] + pc; +} + + +static int stop_simulator = 0; + +int +sim_stop (sd) + SIM_DESC sd; +{ + stop_simulator = 1; + return 1; +} + + +/* Run (or resume) the program. */ +void +sim_resume (sd, step, siggnal) + SIM_DESC sd; + int step, siggnal; +{ + uint32 inst; + uint8 *iaddr; + +/* (*d10v_callback->printf_filtered) (d10v_callback, "sim_resume (%d,%d) PC=0x%x\n",step,siggnal,PC); */ + State.exception = 0; + if (step) + sim_stop (sd); + + do + { + iaddr = imem_addr ((uint32)PC << 2); + if (iaddr == NULL) + { + State.exception = SIGBUS; + break; + } + + inst = get_longword( iaddr ); + + State.pc_changed = 0; + ins_type_counters[ (int)INS_CYCLES ]++; + + switch (inst & 0xC0000000) + { + case 0xC0000000: + /* long instruction */ + do_long (inst & 0x3FFFFFFF); + break; + case 0x80000000: + /* R -> L */ + do_2_short ( inst & 0x7FFF, (inst & 0x3FFF8000) >> 15, RIGHT_FIRST); + break; + case 0x40000000: + /* L -> R */ + do_2_short ((inst & 0x3FFF8000) >> 15, inst & 0x7FFF, LEFT_FIRST); + break; + case 0: + do_parallel ((inst & 0x3FFF8000) >> 15, inst & 0x7FFF); + break; + } + + /* If the PC of the current instruction matches RPT_E then + schedule a branch to the loop start. If one of those + instructions happens to be a branch, than that instruction + will be ignored */ + if (!State.pc_changed) + { + if (PSW_RP && PC == RPT_E) + { + /* Note: The behavour of a branch instruction at RPT_E + is implementation dependant, this simulator takes the + branch. Branching to RPT_E is valid, the instruction + must be executed before the loop is taken. */ + if (RPT_C == 1) + { + SET_PSW_RP (0); + SET_RPT_C (0); + SET_PC (PC + 1); + } + else + { + SET_RPT_C (RPT_C - 1); + SET_PC (RPT_S); + } + } + else + SET_PC (PC + 1); + } + + /* Check for a breakpoint trap on this instruction. This + overrides any pending branches or loops */ + if (PSW_DB && PC == IBA) + { + SET_BPC (PC); + SET_BPSW (PSW); + SET_PSW (PSW & PSW_SM_BIT); + SET_PC (SDBT_VECTOR_START); + } + + /* Writeback all the DATA / PC changes */ + SLOT_FLUSH (); + + } + while ( !State.exception && !stop_simulator); + + if (step && !State.exception) + State.exception = SIGTRAP; +} + +int +sim_trace (sd) + SIM_DESC sd; +{ +#ifdef DEBUG + d10v_debug = DEBUG; +#endif + sim_resume (sd, 0, 0); + return 1; +} + +void +sim_info (sd, verbose) + SIM_DESC sd; + int verbose; +{ + char buf1[40]; + char buf2[40]; + char buf3[40]; + char buf4[40]; + char buf5[40]; + unsigned long left = ins_type_counters[ (int)INS_LEFT ] + ins_type_counters[ (int)INS_LEFT_COND_EXE ]; + unsigned long left_nops = ins_type_counters[ (int)INS_LEFT_NOPS ]; + unsigned long left_parallel = ins_type_counters[ (int)INS_LEFT_PARALLEL ]; + unsigned long left_cond = ins_type_counters[ (int)INS_LEFT_COND_TEST ]; + unsigned long left_total = left + left_parallel + left_cond + left_nops; + + unsigned long right = ins_type_counters[ (int)INS_RIGHT ] + ins_type_counters[ (int)INS_RIGHT_COND_EXE ]; + unsigned long right_nops = ins_type_counters[ (int)INS_RIGHT_NOPS ]; + unsigned long right_parallel = ins_type_counters[ (int)INS_RIGHT_PARALLEL ]; + unsigned long right_cond = ins_type_counters[ (int)INS_RIGHT_COND_TEST ]; + unsigned long right_total = right + right_parallel + right_cond + right_nops; + + unsigned long unknown = ins_type_counters[ (int)INS_UNKNOWN ]; + unsigned long ins_long = ins_type_counters[ (int)INS_LONG ]; + unsigned long parallel = ins_type_counters[ (int)INS_PARALLEL ]; + unsigned long leftright = ins_type_counters[ (int)INS_LEFTRIGHT ]; + unsigned long rightleft = ins_type_counters[ (int)INS_RIGHTLEFT ]; + unsigned long cond_true = ins_type_counters[ (int)INS_COND_TRUE ]; + unsigned long cond_false = ins_type_counters[ (int)INS_COND_FALSE ]; + unsigned long cond_jump = ins_type_counters[ (int)INS_COND_JUMP ]; + unsigned long cycles = ins_type_counters[ (int)INS_CYCLES ]; + unsigned long total = (unknown + left_total + right_total + ins_long); + + int size = strlen (add_commas (buf1, sizeof (buf1), total)); + int parallel_size = strlen (add_commas (buf1, sizeof (buf1), + (left_parallel > right_parallel) ? left_parallel : right_parallel)); + int cond_size = strlen (add_commas (buf1, sizeof (buf1), (left_cond > right_cond) ? left_cond : right_cond)); + int nop_size = strlen (add_commas (buf1, sizeof (buf1), (left_nops > right_nops) ? left_nops : right_nops)); + int normal_size = strlen (add_commas (buf1, sizeof (buf1), (left > right) ? left : right)); + + (*d10v_callback->printf_filtered) (d10v_callback, + "executed %*s left instruction(s), %*s normal, %*s parallel, %*s EXExxx, %*s nops\n", + size, add_commas (buf1, sizeof (buf1), left_total), + normal_size, add_commas (buf2, sizeof (buf2), left), + parallel_size, add_commas (buf3, sizeof (buf3), left_parallel), + cond_size, add_commas (buf4, sizeof (buf4), left_cond), + nop_size, add_commas (buf5, sizeof (buf5), left_nops)); + + (*d10v_callback->printf_filtered) (d10v_callback, + "executed %*s right instruction(s), %*s normal, %*s parallel, %*s EXExxx, %*s nops\n", + size, add_commas (buf1, sizeof (buf1), right_total), + normal_size, add_commas (buf2, sizeof (buf2), right), + parallel_size, add_commas (buf3, sizeof (buf3), right_parallel), + cond_size, add_commas (buf4, sizeof (buf4), right_cond), + nop_size, add_commas (buf5, sizeof (buf5), right_nops)); + + if (ins_long) + (*d10v_callback->printf_filtered) (d10v_callback, + "executed %*s long instruction(s)\n", + size, add_commas (buf1, sizeof (buf1), ins_long)); + + if (parallel) + (*d10v_callback->printf_filtered) (d10v_callback, + "executed %*s parallel instruction(s)\n", + size, add_commas (buf1, sizeof (buf1), parallel)); + + if (leftright) + (*d10v_callback->printf_filtered) (d10v_callback, + "executed %*s instruction(s) encoded L->R\n", + size, add_commas (buf1, sizeof (buf1), leftright)); + + if (rightleft) + (*d10v_callback->printf_filtered) (d10v_callback, + "executed %*s instruction(s) encoded R->L\n", + size, add_commas (buf1, sizeof (buf1), rightleft)); + + if (unknown) + (*d10v_callback->printf_filtered) (d10v_callback, + "executed %*s unknown instruction(s)\n", + size, add_commas (buf1, sizeof (buf1), unknown)); + + if (cond_true) + (*d10v_callback->printf_filtered) (d10v_callback, + "executed %*s instruction(s) due to EXExxx condition being true\n", + size, add_commas (buf1, sizeof (buf1), cond_true)); + + if (cond_false) + (*d10v_callback->printf_filtered) (d10v_callback, + "skipped %*s instruction(s) due to EXExxx condition being false\n", + size, add_commas (buf1, sizeof (buf1), cond_false)); + + if (cond_jump) + (*d10v_callback->printf_filtered) (d10v_callback, + "skipped %*s instruction(s) due to conditional branch succeeding\n", + size, add_commas (buf1, sizeof (buf1), cond_jump)); + + (*d10v_callback->printf_filtered) (d10v_callback, + "executed %*s cycle(s)\n", + size, add_commas (buf1, sizeof (buf1), cycles)); + + (*d10v_callback->printf_filtered) (d10v_callback, + "executed %*s total instructions\n", + size, add_commas (buf1, sizeof (buf1), total)); +} + +SIM_RC +sim_create_inferior (sd, abfd, argv, env) + SIM_DESC sd; + struct _bfd *abfd; + char **argv; + char **env; +{ + bfd_vma start_address; + + /* reset all state information */ + memset (&State.regs, 0, (int)&State.imem - (int)&State.regs[0]); + + if (argv) + { + /* a hack to set r0/r1 with argc/argv */ + /* some high memory that won't be overwritten by the stack soon */ + bfd_vma addr = 0x7C00; + int p = 20; + int i = 0; + while (argv[i]) + { + int size = strlen (argv[i]) + 1; + SW (addr + 2*i, addr + p); + sim_write (sd, addr + 0, argv[i], size); + p += size; + i++; + } + SET_GPR (0, addr); + SET_GPR (1, i); + } + + /* set PC */ + if (abfd != NULL) + start_address = bfd_get_start_address (abfd); + else + start_address = 0xffc0 << 2; +#ifdef DEBUG + if (d10v_debug) + (*d10v_callback->printf_filtered) (d10v_callback, "sim_create_inferior: PC=0x%lx\n", (long) start_address); +#endif + SET_CREG (PC_CR, start_address >> 2); + + /* cpu resets imap0 to 0 and imap1 to 0x7f, but D10V-EVA board */ + /* resets imap0 and imap1 to 0x1000. */ + if (1) + { + SET_IMAP0 (0x0000); + SET_IMAP1 (0x007f); + SET_DMAP (0x0000); + } + else + { + SET_IMAP0 (0x1000); + SET_IMAP1 (0x1000); + SET_DMAP(0); + } + + SLOT_FLUSH (); + return SIM_RC_OK; +} + + +void +sim_set_callbacks (p) + host_callback *p; +{ + d10v_callback = p; +} + +void +sim_stop_reason (sd, reason, sigrc) + SIM_DESC sd; + enum sim_stop *reason; + int *sigrc; +{ +/* (*d10v_callback->printf_filtered) (d10v_callback, "sim_stop_reason: PC=0x%x\n",PC<<2); */ + + switch (State.exception) + { + case SIG_D10V_STOP: /* stop instruction */ + *reason = sim_exited; + *sigrc = 0; + break; + + case SIG_D10V_EXIT: /* exit trap */ + *reason = sim_exited; + *sigrc = GPR (0); + break; + + default: /* some signal */ + *reason = sim_stopped; + if (stop_simulator && !State.exception) + *sigrc = SIGINT; + else + *sigrc = State.exception; + break; + } + + stop_simulator = 0; +} + +int +sim_fetch_register (sd, rn, memory, length) + SIM_DESC sd; + int rn; + unsigned char *memory; + int length; +{ + if (rn > 34) + WRITE_64 (memory, ACC (rn-35)); + else if (rn == 32) + WRITE_16 (memory, IMAP0); + else if (rn == 33) + WRITE_16 (memory, IMAP1); + else if (rn == 34) + WRITE_16 (memory, DMAP); + else if (rn >= 16) + WRITE_16 (memory, CREG (rn - 16)); + else + WRITE_16 (memory, GPR (rn)); + return -1; +} + +int +sim_store_register (sd, rn, memory, length) + SIM_DESC sd; + int rn; + unsigned char *memory; + int length; +{ + if (rn > 34) + SET_ACC (rn-35, READ_64 (memory) & MASK40); + else if (rn == 34) + SET_DMAP( READ_16(memory) ); + else if (rn == 33) + SET_IMAP1( READ_16(memory) ); + else if (rn == 32) + SET_IMAP0( READ_16(memory) ); + else if (rn >= 16) + SET_CREG (rn - 16, READ_16 (memory)); + else + SET_GPR (rn, READ_16 (memory)); + SLOT_FLUSH (); + return -1; +} + + +void +sim_do_command (sd, cmd) + SIM_DESC sd; + char *cmd; +{ + (*d10v_callback->printf_filtered) (d10v_callback, "sim_do_command: %s\n",cmd); +} + +SIM_RC +sim_load (sd, prog, abfd, from_tty) + SIM_DESC sd; + char *prog; + bfd *abfd; + int from_tty; +{ + extern bfd *sim_load_file (); /* ??? Don't know where this should live. */ + + if (prog_bfd != NULL && prog_bfd_was_opened_p) + { + bfd_close (prog_bfd); + prog_bfd_was_opened_p = 0; + } + prog_bfd = sim_load_file (sd, myname, d10v_callback, prog, abfd, + sim_kind == SIM_OPEN_DEBUG, + 1/*LMA*/, sim_write); + if (prog_bfd == NULL) + return SIM_RC_FAIL; + prog_bfd_was_opened_p = abfd == NULL; + return SIM_RC_OK; +} diff --git a/sim/d10v/simops.c b/sim/d10v/simops.c new file mode 100644 index 00000000000..c64ba425d16 --- /dev/null +++ b/sim/d10v/simops.c @@ -0,0 +1,3252 @@ +#include "config.h" + +#include +#include +#include +#include +#ifdef HAVE_UNISTD_H +#include +#endif + +#include "d10v_sim.h" +#include "simops.h" +#include "targ-vals.h" + +extern char *strrchr (); + +enum op_types { + OP_VOID, + OP_REG, + OP_REG_OUTPUT, + OP_DREG, + OP_DREG_OUTPUT, + OP_ACCUM, + OP_ACCUM_OUTPUT, + OP_ACCUM_REVERSE, + OP_CR, + OP_CR_OUTPUT, + OP_CR_REVERSE, + OP_FLAG, + OP_FLAG_OUTPUT, + OP_CONSTANT16, + OP_CONSTANT8, + OP_CONSTANT3, + OP_CONSTANT4, + OP_MEMREF, + OP_MEMREF2, + OP_POSTDEC, + OP_POSTINC, + OP_PREDEC, + OP_R0, + OP_R1, + OP_R2, +}; + + +enum { + PSW_MASK = (PSW_SM_BIT + | PSW_EA_BIT + | PSW_DB_BIT + | PSW_DM_BIT + | PSW_IE_BIT + | PSW_RP_BIT + | PSW_MD_BIT + | PSW_FX_BIT + | PSW_ST_BIT + | PSW_F0_BIT + | PSW_F1_BIT + | PSW_C_BIT), +}; + +reg_t +move_to_cr (int cr, reg_t mask, reg_t val) +{ + /* A MASK bit is set when the corresponding bit in the CR should + be left alone */ + /* This assumes that (VAL & MASK) == 0 */ + switch (cr) + { + case PSW_CR: + val &= PSW_MASK; + if ((mask & PSW_SM_BIT) == 0) + { + int new_sm = (val & PSW_SM_BIT) != 0; + SET_HELD_SP (PSW_SM, GPR (SP_IDX)); /* save old SP */ + if (PSW_SM != new_sm) + SET_GPR (SP_IDX, HELD_SP (new_sm)); /* restore new SP */ + } + if ((mask & (PSW_ST_BIT | PSW_FX_BIT)) == 0) + { + if (val & PSW_ST_BIT && !(val & PSW_FX_BIT)) + { + (*d10v_callback->printf_filtered) + (d10v_callback, + "ERROR at PC 0x%x: ST can only be set when FX is set.\n", + PC<<2); + State.exception = SIGILL; + } + } + /* keep an up-to-date psw around for tracing */ + State.trace.psw = (State.trace.psw & mask) | val; + break; + case BPSW_CR: + case DPSW_CR: + val &= PSW_MASK; + break; + case MOD_S_CR: + case MOD_E_CR: + val &= ~1; + break; + default: + break; + } + /* only issue an update if the register is being changed */ + if ((State.cregs[cr] & ~mask) != val) + SLOT_PEND_MASK (State.cregs[cr], mask, val); + return val; +} + +#ifdef DEBUG +static void trace_input_func PARAMS ((char *name, + enum op_types in1, + enum op_types in2, + enum op_types in3)); + +#define trace_input(name, in1, in2, in3) do { if (d10v_debug) trace_input_func (name, in1, in2, in3); } while (0) + +#ifndef SIZE_INSTRUCTION +#define SIZE_INSTRUCTION 8 +#endif + +#ifndef SIZE_OPERANDS +#define SIZE_OPERANDS 18 +#endif + +#ifndef SIZE_VALUES +#define SIZE_VALUES 13 +#endif + +#ifndef SIZE_LOCATION +#define SIZE_LOCATION 20 +#endif + +#ifndef SIZE_PC +#define SIZE_PC 6 +#endif + +#ifndef SIZE_LINE_NUMBER +#define SIZE_LINE_NUMBER 4 +#endif + +static void +trace_input_func (name, in1, in2, in3) + char *name; + enum op_types in1; + enum op_types in2; + enum op_types in3; +{ + char *comma; + enum op_types in[3]; + int i; + char buf[1024]; + char *p; + long tmp; + char *type; + const char *filename; + const char *functionname; + unsigned int linenumber; + bfd_vma byte_pc; + + if ((d10v_debug & DEBUG_TRACE) == 0) + return; + + switch (State.ins_type) + { + default: + case INS_UNKNOWN: type = " ?"; break; + case INS_LEFT: type = " L"; break; + case INS_RIGHT: type = " R"; break; + case INS_LEFT_PARALLEL: type = "*L"; break; + case INS_RIGHT_PARALLEL: type = "*R"; break; + case INS_LEFT_COND_TEST: type = "?L"; break; + case INS_RIGHT_COND_TEST: type = "?R"; break; + case INS_LEFT_COND_EXE: type = "&L"; break; + case INS_RIGHT_COND_EXE: type = "&R"; break; + case INS_LONG: type = " B"; break; + } + + if ((d10v_debug & DEBUG_LINE_NUMBER) == 0) + (*d10v_callback->printf_filtered) (d10v_callback, + "0x%.*x %s: %-*s ", + SIZE_PC, (unsigned)PC, + type, + SIZE_INSTRUCTION, name); + + else + { + buf[0] = '\0'; + byte_pc = decode_pc (); + if (text && byte_pc >= text_start && byte_pc < text_end) + { + filename = (const char *)0; + functionname = (const char *)0; + linenumber = 0; + if (bfd_find_nearest_line (prog_bfd, text, (struct symbol_cache_entry **)0, byte_pc - text_start, + &filename, &functionname, &linenumber)) + { + p = buf; + if (linenumber) + { + sprintf (p, "#%-*d ", SIZE_LINE_NUMBER, linenumber); + p += strlen (p); + } + else + { + sprintf (p, "%-*s ", SIZE_LINE_NUMBER+1, "---"); + p += SIZE_LINE_NUMBER+2; + } + + if (functionname) + { + sprintf (p, "%s ", functionname); + p += strlen (p); + } + else if (filename) + { + char *q = strrchr (filename, '/'); + sprintf (p, "%s ", (q) ? q+1 : filename); + p += strlen (p); + } + + if (*p == ' ') + *p = '\0'; + } + } + + (*d10v_callback->printf_filtered) (d10v_callback, + "0x%.*x %s: %-*.*s %-*s ", + SIZE_PC, (unsigned)PC, + type, + SIZE_LOCATION, SIZE_LOCATION, buf, + SIZE_INSTRUCTION, name); + } + + in[0] = in1; + in[1] = in2; + in[2] = in3; + comma = ""; + p = buf; + for (i = 0; i < 3; i++) + { + switch (in[i]) + { + case OP_VOID: + case OP_R0: + case OP_R1: + case OP_R2: + break; + + case OP_REG: + case OP_REG_OUTPUT: + case OP_DREG: + case OP_DREG_OUTPUT: + sprintf (p, "%sr%d", comma, OP[i]); + p += strlen (p); + comma = ","; + break; + + case OP_CR: + case OP_CR_OUTPUT: + case OP_CR_REVERSE: + sprintf (p, "%scr%d", comma, OP[i]); + p += strlen (p); + comma = ","; + break; + + case OP_ACCUM: + case OP_ACCUM_OUTPUT: + case OP_ACCUM_REVERSE: + sprintf (p, "%sa%d", comma, OP[i]); + p += strlen (p); + comma = ","; + break; + + case OP_CONSTANT16: + sprintf (p, "%s%d", comma, OP[i]); + p += strlen (p); + comma = ","; + break; + + case OP_CONSTANT8: + sprintf (p, "%s%d", comma, SEXT8(OP[i])); + p += strlen (p); + comma = ","; + break; + + case OP_CONSTANT4: + sprintf (p, "%s%d", comma, SEXT4(OP[i])); + p += strlen (p); + comma = ","; + break; + + case OP_CONSTANT3: + sprintf (p, "%s%d", comma, SEXT3(OP[i])); + p += strlen (p); + comma = ","; + break; + + case OP_MEMREF: + sprintf (p, "%s@r%d", comma, OP[i]); + p += strlen (p); + comma = ","; + break; + + case OP_MEMREF2: + sprintf (p, "%s@(%d,r%d)", comma, (int16)OP[i], OP[i+1]); + p += strlen (p); + comma = ","; + break; + + case OP_POSTINC: + sprintf (p, "%s@r%d+", comma, OP[i]); + p += strlen (p); + comma = ","; + break; + + case OP_POSTDEC: + sprintf (p, "%s@r%d-", comma, OP[i]); + p += strlen (p); + comma = ","; + break; + + case OP_PREDEC: + sprintf (p, "%s@-r%d", comma, OP[i]); + p += strlen (p); + comma = ","; + break; + + case OP_FLAG: + case OP_FLAG_OUTPUT: + if (OP[i] == 0) + sprintf (p, "%sf0", comma); + + else if (OP[i] == 1) + sprintf (p, "%sf1", comma); + + else + sprintf (p, "%sc", comma); + + p += strlen (p); + comma = ","; + break; + } + } + + if ((d10v_debug & DEBUG_VALUES) == 0) + { + *p++ = '\n'; + *p = '\0'; + (*d10v_callback->printf_filtered) (d10v_callback, "%s", buf); + } + else + { + *p = '\0'; + (*d10v_callback->printf_filtered) (d10v_callback, "%-*s", SIZE_OPERANDS, buf); + + p = buf; + for (i = 0; i < 3; i++) + { + buf[0] = '\0'; + switch (in[i]) + { + case OP_VOID: + (*d10v_callback->printf_filtered) (d10v_callback, "%*s", SIZE_VALUES, ""); + break; + + case OP_REG_OUTPUT: + case OP_DREG_OUTPUT: + case OP_CR_OUTPUT: + case OP_ACCUM_OUTPUT: + case OP_FLAG_OUTPUT: + (*d10v_callback->printf_filtered) (d10v_callback, "%*s", SIZE_VALUES, "---"); + break; + + case OP_REG: + case OP_MEMREF: + case OP_POSTDEC: + case OP_POSTINC: + case OP_PREDEC: + (*d10v_callback->printf_filtered) (d10v_callback, "%*s0x%.4x", SIZE_VALUES-6, "", + (uint16) GPR (OP[i])); + break; + + case OP_DREG: + tmp = (long)((((uint32) GPR (OP[i])) << 16) | ((uint32) GPR (OP[i] + 1))); + (*d10v_callback->printf_filtered) (d10v_callback, "%*s0x%.8lx", SIZE_VALUES-10, "", tmp); + break; + + case OP_CR: + case OP_CR_REVERSE: + (*d10v_callback->printf_filtered) (d10v_callback, "%*s0x%.4x", SIZE_VALUES-6, "", + (uint16) CREG (OP[i])); + break; + + case OP_ACCUM: + case OP_ACCUM_REVERSE: + (*d10v_callback->printf_filtered) (d10v_callback, "%*s0x%.2x%.8lx", SIZE_VALUES-12, "", + ((int)(ACC (OP[i]) >> 32) & 0xff), + ((unsigned long) ACC (OP[i])) & 0xffffffff); + break; + + case OP_CONSTANT16: + (*d10v_callback->printf_filtered) (d10v_callback, "%*s0x%.4x", SIZE_VALUES-6, "", + (uint16)OP[i]); + break; + + case OP_CONSTANT4: + (*d10v_callback->printf_filtered) (d10v_callback, "%*s0x%.4x", SIZE_VALUES-6, "", + (uint16)SEXT4(OP[i])); + break; + + case OP_CONSTANT8: + (*d10v_callback->printf_filtered) (d10v_callback, "%*s0x%.4x", SIZE_VALUES-6, "", + (uint16)SEXT8(OP[i])); + break; + + case OP_CONSTANT3: + (*d10v_callback->printf_filtered) (d10v_callback, "%*s0x%.4x", SIZE_VALUES-6, "", + (uint16)SEXT3(OP[i])); + break; + + case OP_FLAG: + if (OP[i] == 0) + (*d10v_callback->printf_filtered) (d10v_callback, "%*sF0 = %d", SIZE_VALUES-6, "", + PSW_F0 != 0); + + else if (OP[i] == 1) + (*d10v_callback->printf_filtered) (d10v_callback, "%*sF1 = %d", SIZE_VALUES-6, "", + PSW_F1 != 0); + + else + (*d10v_callback->printf_filtered) (d10v_callback, "%*sC = %d", SIZE_VALUES-5, "", + PSW_C != 0); + + break; + + case OP_MEMREF2: + (*d10v_callback->printf_filtered) (d10v_callback, "%*s0x%.4x", SIZE_VALUES-6, "", + (uint16)OP[i]); + (*d10v_callback->printf_filtered) (d10v_callback, "%*s0x%.4x", SIZE_VALUES-6, "", + (uint16)GPR (OP[i + 1])); + i++; + break; + + case OP_R0: + (*d10v_callback->printf_filtered) (d10v_callback, "%*s0x%.4x", SIZE_VALUES-6, "", + (uint16) GPR (0)); + break; + + case OP_R1: + (*d10v_callback->printf_filtered) (d10v_callback, "%*s0x%.4x", SIZE_VALUES-6, "", + (uint16) GPR (1)); + break; + + case OP_R2: + (*d10v_callback->printf_filtered) (d10v_callback, "%*s0x%.4x", SIZE_VALUES-6, "", + (uint16) GPR (2)); + break; + + } + } + } + + (*d10v_callback->flush_stdout) (d10v_callback); +} + +static void +do_trace_output_flush (void) +{ + (*d10v_callback->flush_stdout) (d10v_callback); +} + +static void +do_trace_output_finish (void) +{ + (*d10v_callback->printf_filtered) (d10v_callback, + " F0=%d F1=%d C=%d\n", + (State.trace.psw & PSW_F0_BIT) != 0, + (State.trace.psw & PSW_F1_BIT) != 0, + (State.trace.psw & PSW_C_BIT) != 0); + (*d10v_callback->flush_stdout) (d10v_callback); +} + +static void +trace_output_40 (uint64 val) +{ + if ((d10v_debug & (DEBUG_TRACE | DEBUG_VALUES)) == (DEBUG_TRACE | DEBUG_VALUES)) + { + (*d10v_callback->printf_filtered) (d10v_callback, + " :: %*s0x%.2x%.8lx", + SIZE_VALUES - 12, + "", + ((int)(val >> 32) & 0xff), + ((unsigned long) val) & 0xffffffff); + do_trace_output_finish (); + } +} + +static void +trace_output_32 (uint32 val) +{ + if ((d10v_debug & (DEBUG_TRACE | DEBUG_VALUES)) == (DEBUG_TRACE | DEBUG_VALUES)) + { + (*d10v_callback->printf_filtered) (d10v_callback, + " :: %*s0x%.8x", + SIZE_VALUES - 10, + "", + (int) val); + do_trace_output_finish (); + } +} + +static void +trace_output_16 (uint16 val) +{ + if ((d10v_debug & (DEBUG_TRACE | DEBUG_VALUES)) == (DEBUG_TRACE | DEBUG_VALUES)) + { + (*d10v_callback->printf_filtered) (d10v_callback, + " :: %*s0x%.4x", + SIZE_VALUES - 6, + "", + (int) val); + do_trace_output_finish (); + } +} + +static void +trace_output_void () +{ + if ((d10v_debug & (DEBUG_TRACE | DEBUG_VALUES)) == (DEBUG_TRACE | DEBUG_VALUES)) + { + (*d10v_callback->printf_filtered) (d10v_callback, "\n"); + do_trace_output_flush (); + } +} + +static void +trace_output_flag () +{ + if ((d10v_debug & (DEBUG_TRACE | DEBUG_VALUES)) == (DEBUG_TRACE | DEBUG_VALUES)) + { + (*d10v_callback->printf_filtered) (d10v_callback, + " :: %*s", + SIZE_VALUES, + ""); + do_trace_output_finish (); + } +} + + + + +#else +#define trace_input(NAME, IN1, IN2, IN3) +#define trace_output(RESULT) +#endif + +/* abs */ +void +OP_4607 () +{ + int16 tmp; + trace_input ("abs", OP_REG, OP_VOID, OP_VOID); + SET_PSW_F1 (PSW_F0); + tmp = GPR(OP[0]); + if (tmp < 0) + { + tmp = - tmp; + SET_PSW_F0 (1); + } + else + SET_PSW_F0 (0); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* abs */ +void +OP_5607 () +{ + int64 tmp; + trace_input ("abs", OP_ACCUM, OP_VOID, OP_VOID); + SET_PSW_F1 (PSW_F0); + + tmp = SEXT40 (ACC (OP[0])); + if (tmp < 0 ) + { + tmp = - tmp; + if (PSW_ST) + { + if (tmp > SEXT40(MAX32)) + tmp = (MAX32); + else if (tmp < SEXT40(MIN32)) + tmp = (MIN32); + else + tmp = (tmp & MASK40); + } + else + tmp = (tmp & MASK40); + SET_PSW_F0 (1); + } + else + { + tmp = (tmp & MASK40); + SET_PSW_F0 (0); + } + SET_ACC (OP[0], tmp); + trace_output_40 (tmp); +} + +/* add */ +void +OP_200 () +{ + uint16 a = GPR (OP[0]); + uint16 b = GPR (OP[1]); + uint16 tmp = (a + b); + trace_input ("add", OP_REG, OP_REG, OP_VOID); + SET_PSW_C (a > tmp); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* add */ +void +OP_1201 () +{ + int64 tmp; + tmp = SEXT40(ACC (OP[0])) + (SEXT16 (GPR (OP[1])) << 16 | GPR (OP[1] + 1)); + + trace_input ("add", OP_ACCUM, OP_REG, OP_VOID); + if (PSW_ST) + { + if (tmp > SEXT40(MAX32)) + tmp = (MAX32); + else if (tmp < SEXT40(MIN32)) + tmp = (MIN32); + else + tmp = (tmp & MASK40); + } + else + tmp = (tmp & MASK40); + SET_ACC (OP[0], tmp); + trace_output_40 (tmp); +} + +/* add */ +void +OP_1203 () +{ + int64 tmp; + tmp = SEXT40(ACC (OP[0])) + SEXT40(ACC (OP[1])); + + trace_input ("add", OP_ACCUM, OP_ACCUM, OP_VOID); + if (PSW_ST) + { + if (tmp > SEXT40(MAX32)) + tmp = (MAX32); + else if (tmp < SEXT40(MIN32)) + tmp = (MIN32); + else + tmp = (tmp & MASK40); + } + else + tmp = (tmp & MASK40); + SET_ACC (OP[0], tmp); + trace_output_40 (tmp); +} + +/* add2w */ +void +OP_1200 () +{ + uint32 tmp; + uint32 a = (GPR (OP[0])) << 16 | GPR (OP[0] + 1); + uint32 b = (GPR (OP[1])) << 16 | GPR (OP[1] + 1); + trace_input ("add2w", OP_DREG, OP_DREG, OP_VOID); + tmp = a + b; + SET_PSW_C (tmp < a); + SET_GPR (OP[0] + 0, (tmp >> 16)); + SET_GPR (OP[0] + 1, (tmp & 0xFFFF)); + trace_output_32 (tmp); +} + +/* add3 */ +void +OP_1000000 () +{ + uint16 a = GPR (OP[1]); + uint16 b = OP[2]; + uint16 tmp = (a + b); + trace_input ("add3", OP_REG_OUTPUT, OP_REG, OP_CONSTANT16); + SET_PSW_C (tmp < a); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* addac3 */ +void +OP_17000200 () +{ + int64 tmp; + tmp = SEXT40(ACC (OP[2])) + SEXT40 ((GPR (OP[1]) << 16) | GPR (OP[1] + 1)); + + trace_input ("addac3", OP_DREG_OUTPUT, OP_DREG, OP_ACCUM); + SET_GPR (OP[0] + 0, ((tmp >> 16) & 0xffff)); + SET_GPR (OP[0] + 1, (tmp & 0xffff)); + trace_output_32 (tmp); +} + +/* addac3 */ +void +OP_17000202 () +{ + int64 tmp; + tmp = SEXT40(ACC (OP[1])) + SEXT40(ACC (OP[2])); + + trace_input ("addac3", OP_DREG_OUTPUT, OP_ACCUM, OP_ACCUM); + SET_GPR (OP[0] + 0, (tmp >> 16) & 0xffff); + SET_GPR (OP[0] + 1, tmp & 0xffff); + trace_output_32 (tmp); +} + +/* addac3s */ +void +OP_17001200 () +{ + int64 tmp; + SET_PSW_F1 (PSW_F0); + + trace_input ("addac3s", OP_DREG_OUTPUT, OP_DREG, OP_ACCUM); + tmp = SEXT40 (ACC (OP[2])) + SEXT40 ((GPR (OP[1]) << 16) | GPR (OP[1] + 1)); + if (tmp > SEXT40(MAX32)) + { + tmp = (MAX32); + SET_PSW_F0 (1); + } + else if (tmp < SEXT40(MIN32)) + { + tmp = (MIN32); + SET_PSW_F0 (1); + } + else + { + SET_PSW_F0 (0); + } + SET_GPR (OP[0] + 0, (tmp >> 16) & 0xffff); + SET_GPR (OP[0] + 1, (tmp & 0xffff)); + trace_output_32 (tmp); +} + +/* addac3s */ +void +OP_17001202 () +{ + int64 tmp; + SET_PSW_F1 (PSW_F0); + + trace_input ("addac3s", OP_DREG_OUTPUT, OP_ACCUM, OP_ACCUM); + tmp = SEXT40(ACC (OP[1])) + SEXT40(ACC (OP[2])); + if (tmp > SEXT40(MAX32)) + { + tmp = (MAX32); + SET_PSW_F0 (1); + } + else if (tmp < SEXT40(MIN32)) + { + tmp = (MIN32); + SET_PSW_F0 (1); + } + else + { + SET_PSW_F0 (0); + } + SET_GPR (OP[0] + 0, (tmp >> 16) & 0xffff); + SET_GPR (OP[0] + 1, (tmp & 0xffff)); + trace_output_32 (tmp); +} + +/* addi */ +void +OP_201 () +{ + uint16 a = GPR (OP[0]); + uint16 b; + uint16 tmp; + if (OP[1] == 0) + OP[1] = 16; + b = OP[1]; + tmp = (a + b); + trace_input ("addi", OP_REG, OP_CONSTANT16, OP_VOID); + SET_PSW_C (tmp < a); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* and */ +void +OP_C00 () +{ + uint16 tmp = GPR (OP[0]) & GPR (OP[1]); + trace_input ("and", OP_REG, OP_REG, OP_VOID); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* and3 */ +void +OP_6000000 () +{ + uint16 tmp = GPR (OP[1]) & OP[2]; + trace_input ("and3", OP_REG_OUTPUT, OP_REG, OP_CONSTANT16); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* bclri */ +void +OP_C01 () +{ + int16 tmp; + trace_input ("bclri", OP_REG, OP_CONSTANT16, OP_VOID); + tmp = (GPR (OP[0]) &~(0x8000 >> OP[1])); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* bl.s */ +void +OP_4900 () +{ + trace_input ("bl.s", OP_CONSTANT8, OP_R0, OP_R1); + SET_GPR (13, PC + 1); + JMP( PC + SEXT8 (OP[0])); + trace_output_void (); +} + +/* bl.l */ +void +OP_24800000 () +{ + trace_input ("bl.l", OP_CONSTANT16, OP_R0, OP_R1); + SET_GPR (13, (PC + 1)); + JMP (PC + OP[0]); + trace_output_void (); +} + +/* bnoti */ +void +OP_A01 () +{ + int16 tmp; + trace_input ("bnoti", OP_REG, OP_CONSTANT16, OP_VOID); + tmp = (GPR (OP[0]) ^ (0x8000 >> OP[1])); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* bra.s */ +void +OP_4800 () +{ + trace_input ("bra.s", OP_CONSTANT8, OP_VOID, OP_VOID); + JMP (PC + SEXT8 (OP[0])); + trace_output_void (); +} + +/* bra.l */ +void +OP_24000000 () +{ + trace_input ("bra.l", OP_CONSTANT16, OP_VOID, OP_VOID); + JMP (PC + OP[0]); + trace_output_void (); +} + +/* brf0f.s */ +void +OP_4A00 () +{ + trace_input ("brf0f.s", OP_CONSTANT8, OP_VOID, OP_VOID); + if (!PSW_F0) + JMP (PC + SEXT8 (OP[0])); + trace_output_flag (); +} + +/* brf0f.l */ +void +OP_25000000 () +{ + trace_input ("brf0f.l", OP_CONSTANT16, OP_VOID, OP_VOID); + if (!PSW_F0) + JMP (PC + OP[0]); + trace_output_flag (); +} + +/* brf0t.s */ +void +OP_4B00 () +{ + trace_input ("brf0t.s", OP_CONSTANT8, OP_VOID, OP_VOID); + if (PSW_F0) + JMP (PC + SEXT8 (OP[0])); + trace_output_flag (); +} + +/* brf0t.l */ +void +OP_25800000 () +{ + trace_input ("brf0t.l", OP_CONSTANT16, OP_VOID, OP_VOID); + if (PSW_F0) + JMP (PC + OP[0]); + trace_output_flag (); +} + +/* bseti */ +void +OP_801 () +{ + int16 tmp; + trace_input ("bseti", OP_REG, OP_CONSTANT16, OP_VOID); + tmp = (GPR (OP[0]) | (0x8000 >> OP[1])); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* btsti */ +void +OP_E01 () +{ + trace_input ("btsti", OP_REG, OP_CONSTANT16, OP_VOID); + SET_PSW_F1 (PSW_F0); + SET_PSW_F0 ((GPR (OP[0]) & (0x8000 >> OP[1])) ? 1 : 0); + trace_output_flag (); +} + +/* clrac */ +void +OP_5601 () +{ + trace_input ("clrac", OP_ACCUM_OUTPUT, OP_VOID, OP_VOID); + SET_ACC (OP[0], 0); + trace_output_40 (0); +} + +/* cmp */ +void +OP_600 () +{ + trace_input ("cmp", OP_REG, OP_REG, OP_VOID); + SET_PSW_F1 (PSW_F0); + SET_PSW_F0 (((int16)(GPR (OP[0])) < (int16)(GPR (OP[1]))) ? 1 : 0); + trace_output_flag (); +} + +/* cmp */ +void +OP_1603 () +{ + trace_input ("cmp", OP_ACCUM, OP_ACCUM, OP_VOID); + SET_PSW_F1 (PSW_F0); + SET_PSW_F0 ((SEXT40(ACC (OP[0])) < SEXT40(ACC (OP[1]))) ? 1 : 0); + trace_output_flag (); +} + +/* cmpeq */ +void +OP_400 () +{ + trace_input ("cmpeq", OP_REG, OP_REG, OP_VOID); + SET_PSW_F1 (PSW_F0); + SET_PSW_F0 ((GPR (OP[0]) == GPR (OP[1])) ? 1 : 0); + trace_output_flag (); +} + +/* cmpeq */ +void +OP_1403 () +{ + trace_input ("cmpeq", OP_ACCUM, OP_ACCUM, OP_VOID); + SET_PSW_F1 (PSW_F0); + SET_PSW_F0 (((ACC (OP[0]) & MASK40) == (ACC (OP[1]) & MASK40)) ? 1 : 0); + trace_output_flag (); +} + +/* cmpeqi.s */ +void +OP_401 () +{ + trace_input ("cmpeqi.s", OP_REG, OP_CONSTANT4, OP_VOID); + SET_PSW_F1 (PSW_F0); + SET_PSW_F0 ((GPR (OP[0]) == (reg_t) SEXT4 (OP[1])) ? 1 : 0); + trace_output_flag (); +} + +/* cmpeqi.l */ +void +OP_2000000 () +{ + trace_input ("cmpeqi.l", OP_REG, OP_CONSTANT16, OP_VOID); + SET_PSW_F1 (PSW_F0); + SET_PSW_F0 ((GPR (OP[0]) == (reg_t)OP[1]) ? 1 : 0); + trace_output_flag (); +} + +/* cmpi.s */ +void +OP_601 () +{ + trace_input ("cmpi.s", OP_REG, OP_CONSTANT4, OP_VOID); + SET_PSW_F1 (PSW_F0); + SET_PSW_F0 (((int16)(GPR (OP[0])) < (int16)SEXT4(OP[1])) ? 1 : 0); + trace_output_flag (); +} + +/* cmpi.l */ +void +OP_3000000 () +{ + trace_input ("cmpi.l", OP_REG, OP_CONSTANT16, OP_VOID); + SET_PSW_F1 (PSW_F0); + SET_PSW_F0 (((int16)(GPR (OP[0])) < (int16)(OP[1])) ? 1 : 0); + trace_output_flag (); +} + +/* cmpu */ +void +OP_4600 () +{ + trace_input ("cmpu", OP_REG, OP_REG, OP_VOID); + SET_PSW_F1 (PSW_F0); + SET_PSW_F0 ((GPR (OP[0]) < GPR (OP[1])) ? 1 : 0); + trace_output_flag (); +} + +/* cmpui */ +void +OP_23000000 () +{ + trace_input ("cmpui", OP_REG, OP_CONSTANT16, OP_VOID); + SET_PSW_F1 (PSW_F0); + SET_PSW_F0 ((GPR (OP[0]) < (reg_t)OP[1]) ? 1 : 0); + trace_output_flag (); +} + +/* cpfg */ +void +OP_4E09 () +{ + uint8 val; + + trace_input ("cpfg", OP_FLAG_OUTPUT, OP_FLAG, OP_VOID); + + if (OP[1] == 0) + val = PSW_F0; + else if (OP[1] == 1) + val = PSW_F1; + else + val = PSW_C; + if (OP[0] == 0) + SET_PSW_F0 (val); + else + SET_PSW_F1 (val); + + trace_output_flag (); +} + +/* dbt */ +void +OP_5F20 () +{ + /* d10v_callback->printf_filtered(d10v_callback, "***** DBT ***** PC=%x\n",PC); */ + + /* GDB uses the instruction pair ``dbt || nop'' as a break-point. + The conditional below is for either of the instruction pairs + ``dbt -> XXX'' or ``dbt <- XXX'' and treats them as as cases + where the dbt instruction should be interpreted. + + The module `sim-break' provides a more effective mechanism for + detecting GDB planted breakpoints. The code below may, + eventually, be changed to use that mechanism. */ + + if (State.ins_type == INS_LEFT + || State.ins_type == INS_RIGHT) + { + trace_input ("dbt", OP_VOID, OP_VOID, OP_VOID); + SET_DPC (PC + 1); + SET_DPSW (PSW); + SET_PSW (PSW_DM_BIT | (PSW & (PSW_F0_BIT | PSW_F1_BIT | PSW_C_BIT))); + JMP (DBT_VECTOR_START); + trace_output_void (); + } + else + { + State.exception = SIGTRAP; + } +} + +/* divs */ +void +OP_14002800 () +{ + uint16 foo, tmp, tmpf; + uint16 hi; + uint16 lo; + + trace_input ("divs", OP_DREG, OP_REG, OP_VOID); + foo = (GPR (OP[0]) << 1) | (GPR (OP[0] + 1) >> 15); + tmp = (int16)foo - (int16)(GPR (OP[1])); + tmpf = (foo >= GPR (OP[1])) ? 1 : 0; + hi = ((tmpf == 1) ? tmp : foo); + lo = ((GPR (OP[0] + 1) << 1) | tmpf); + SET_GPR (OP[0] + 0, hi); + SET_GPR (OP[0] + 1, lo); + trace_output_32 (((uint32) hi << 16) | lo); +} + +/* exef0f */ +void +OP_4E04 () +{ + trace_input ("exef0f", OP_VOID, OP_VOID, OP_VOID); + State.exe = (PSW_F0 == 0); + trace_output_flag (); +} + +/* exef0t */ +void +OP_4E24 () +{ + trace_input ("exef0t", OP_VOID, OP_VOID, OP_VOID); + State.exe = (PSW_F0 != 0); + trace_output_flag (); +} + +/* exef1f */ +void +OP_4E40 () +{ + trace_input ("exef1f", OP_VOID, OP_VOID, OP_VOID); + State.exe = (PSW_F1 == 0); + trace_output_flag (); +} + +/* exef1t */ +void +OP_4E42 () +{ + trace_input ("exef1t", OP_VOID, OP_VOID, OP_VOID); + State.exe = (PSW_F1 != 0); + trace_output_flag (); +} + +/* exefaf */ +void +OP_4E00 () +{ + trace_input ("exefaf", OP_VOID, OP_VOID, OP_VOID); + State.exe = (PSW_F0 == 0) & (PSW_F1 == 0); + trace_output_flag (); +} + +/* exefat */ +void +OP_4E02 () +{ + trace_input ("exefat", OP_VOID, OP_VOID, OP_VOID); + State.exe = (PSW_F0 == 0) & (PSW_F1 != 0); + trace_output_flag (); +} + +/* exetaf */ +void +OP_4E20 () +{ + trace_input ("exetaf", OP_VOID, OP_VOID, OP_VOID); + State.exe = (PSW_F0 != 0) & (PSW_F1 == 0); + trace_output_flag (); +} + +/* exetat */ +void +OP_4E22 () +{ + trace_input ("exetat", OP_VOID, OP_VOID, OP_VOID); + State.exe = (PSW_F0 != 0) & (PSW_F1 != 0); + trace_output_flag (); +} + +/* exp */ +void +OP_15002A00 () +{ + uint32 tmp, foo; + int i; + + trace_input ("exp", OP_REG_OUTPUT, OP_DREG, OP_VOID); + if (((int16)GPR (OP[1])) >= 0) + tmp = (GPR (OP[1]) << 16) | GPR (OP[1] + 1); + else + tmp = ~((GPR (OP[1]) << 16) | GPR (OP[1] + 1)); + + foo = 0x40000000; + for (i=1;i<17;i++) + { + if (tmp & foo) + { + SET_GPR (OP[0], (i - 1)); + trace_output_16 (i - 1); + return; + } + foo >>= 1; + } + SET_GPR (OP[0], 16); + trace_output_16 (16); +} + +/* exp */ +void +OP_15002A02 () +{ + int64 tmp, foo; + int i; + + trace_input ("exp", OP_REG_OUTPUT, OP_ACCUM, OP_VOID); + tmp = SEXT40(ACC (OP[1])); + if (tmp < 0) + tmp = ~tmp & MASK40; + + foo = 0x4000000000LL; + for (i=1;i<25;i++) + { + if (tmp & foo) + { + SET_GPR (OP[0], i - 9); + trace_output_16 (i - 9); + return; + } + foo >>= 1; + } + SET_GPR (OP[0], 16); + trace_output_16 (16); +} + +/* jl */ +void +OP_4D00 () +{ + trace_input ("jl", OP_REG, OP_R0, OP_R1); + SET_GPR (13, PC + 1); + JMP (GPR (OP[0])); + trace_output_void (); +} + +/* jmp */ +void +OP_4C00 () +{ + trace_input ("jmp", OP_REG, + (OP[0] == 13) ? OP_R0 : OP_VOID, + (OP[0] == 13) ? OP_R1 : OP_VOID); + + JMP (GPR (OP[0])); + trace_output_void (); +} + +/* ld */ +void +OP_30000000 () +{ + uint16 tmp; + trace_input ("ld", OP_REG_OUTPUT, OP_MEMREF2, OP_VOID); + tmp = RW (OP[1] + GPR (OP[2])); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* ld */ +void +OP_6401 () +{ + uint16 tmp; + trace_input ("ld", OP_REG_OUTPUT, OP_POSTDEC, OP_VOID); + tmp = RW (GPR (OP[1])); + SET_GPR (OP[0], tmp); + if (OP[0] != OP[1]) + INC_ADDR (OP[1], -2); + trace_output_16 (tmp); +} + +/* ld */ +void +OP_6001 () +{ + uint16 tmp; + trace_input ("ld", OP_REG_OUTPUT, OP_POSTINC, OP_VOID); + tmp = RW (GPR (OP[1])); + SET_GPR (OP[0], tmp); + if (OP[0] != OP[1]) + INC_ADDR (OP[1], 2); + trace_output_16 (tmp); +} + +/* ld */ +void +OP_6000 () +{ + uint16 tmp; + trace_input ("ld", OP_REG_OUTPUT, OP_MEMREF, OP_VOID); + tmp = RW (GPR (OP[1])); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* ld2w */ +void +OP_31000000 () +{ + int32 tmp; + uint16 addr = GPR (OP[2]); + trace_input ("ld2w", OP_REG_OUTPUT, OP_MEMREF2, OP_VOID); + tmp = RLW (OP[1] + addr); + SET_GPR32 (OP[0], tmp); + trace_output_32 (tmp); +} + +/* ld2w */ +void +OP_6601 () +{ + uint16 addr = GPR (OP[1]); + int32 tmp; + trace_input ("ld2w", OP_REG_OUTPUT, OP_POSTDEC, OP_VOID); + tmp = RLW (addr); + SET_GPR32 (OP[0], tmp); + INC_ADDR (OP[1], -4); + trace_output_32 (tmp); +} + +/* ld2w */ +void +OP_6201 () +{ + int32 tmp; + uint16 addr = GPR (OP[1]); + trace_input ("ld2w", OP_REG_OUTPUT, OP_POSTINC, OP_VOID); + tmp = RLW (addr); + SET_GPR32 (OP[0], tmp); + INC_ADDR (OP[1], 4); + trace_output_32 (tmp); +} + +/* ld2w */ +void +OP_6200 () +{ + uint16 addr = GPR (OP[1]); + int32 tmp; + trace_input ("ld2w", OP_REG_OUTPUT, OP_MEMREF, OP_VOID); + tmp = RLW (addr + 0); + SET_GPR32 (OP[0], tmp); + trace_output_32 (tmp); +} + +/* ldb */ +void +OP_38000000 () +{ + int16 tmp; + trace_input ("ldb", OP_REG_OUTPUT, OP_MEMREF2, OP_VOID); + tmp = SEXT8 (RB (OP[1] + GPR (OP[2]))); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* ldb */ +void +OP_7000 () +{ + int16 tmp; + trace_input ("ldb", OP_REG_OUTPUT, OP_MEMREF, OP_VOID); + tmp = SEXT8 (RB (GPR (OP[1]))); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* ldi.s */ +void +OP_4001 () +{ + int16 tmp; + trace_input ("ldi.s", OP_REG_OUTPUT, OP_CONSTANT4, OP_VOID); + tmp = SEXT4 (OP[1]); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* ldi.l */ +void +OP_20000000 () +{ + int16 tmp; + trace_input ("ldi.l", OP_REG_OUTPUT, OP_CONSTANT16, OP_VOID); + tmp = OP[1]; + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* ldub */ +void +OP_39000000 () +{ + int16 tmp; + trace_input ("ldub", OP_REG_OUTPUT, OP_MEMREF2, OP_VOID); + tmp = RB (OP[1] + GPR (OP[2])); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* ldub */ +void +OP_7200 () +{ + int16 tmp; + trace_input ("ldub", OP_REG_OUTPUT, OP_MEMREF, OP_VOID); + tmp = RB (GPR (OP[1])); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* mac */ +void +OP_2A00 () +{ + int64 tmp; + + trace_input ("mac", OP_ACCUM, OP_REG, OP_REG); + tmp = SEXT40 ((int16)(GPR (OP[1])) * (int16)(GPR (OP[2]))); + + if (PSW_FX) + tmp = SEXT40( (tmp << 1) & MASK40); + + if (PSW_ST && tmp > SEXT40(MAX32)) + tmp = (MAX32); + + tmp += SEXT40 (ACC (OP[0])); + if (PSW_ST) + { + if (tmp > SEXT40(MAX32)) + tmp = (MAX32); + else if (tmp < SEXT40(MIN32)) + tmp = (MIN32); + else + tmp = (tmp & MASK40); + } + else + tmp = (tmp & MASK40); + SET_ACC (OP[0], tmp); + trace_output_40 (tmp); +} + +/* macsu */ +void +OP_1A00 () +{ + int64 tmp; + + trace_input ("macsu", OP_ACCUM, OP_REG, OP_REG); + tmp = SEXT40 ((int16) GPR (OP[1]) * GPR (OP[2])); + if (PSW_FX) + tmp = SEXT40 ((tmp << 1) & MASK40); + tmp = ((SEXT40 (ACC (OP[0])) + tmp) & MASK40); + SET_ACC (OP[0], tmp); + trace_output_40 (tmp); +} + +/* macu */ +void +OP_3A00 () +{ + uint64 tmp; + uint32 src1; + uint32 src2; + + trace_input ("macu", OP_ACCUM, OP_REG, OP_REG); + src1 = (uint16) GPR (OP[1]); + src2 = (uint16) GPR (OP[2]); + tmp = src1 * src2; + if (PSW_FX) + tmp = (tmp << 1); + tmp = ((ACC (OP[0]) + tmp) & MASK40); + SET_ACC (OP[0], tmp); + trace_output_40 (tmp); +} + +/* max */ +void +OP_2600 () +{ + int16 tmp; + trace_input ("max", OP_REG, OP_REG, OP_VOID); + SET_PSW_F1 (PSW_F0); + if ((int16) GPR (OP[1]) > (int16)GPR (OP[0])) + { + tmp = GPR (OP[1]); + SET_PSW_F0 (1); + } + else + { + tmp = GPR (OP[0]); + SET_PSW_F0 (0); + } + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* max */ +void +OP_3600 () +{ + int64 tmp; + + trace_input ("max", OP_ACCUM, OP_DREG, OP_VOID); + SET_PSW_F1 (PSW_F0); + tmp = SEXT16 (GPR (OP[1])) << 16 | GPR (OP[1] + 1); + if (tmp > SEXT40 (ACC (OP[0]))) + { + tmp = (tmp & MASK40); + SET_PSW_F0 (1); + } + else + { + tmp = ACC (OP[0]); + SET_PSW_F0 (0); + } + SET_ACC (OP[0], tmp); + trace_output_40 (tmp); +} + +/* max */ +void +OP_3602 () +{ + int64 tmp; + trace_input ("max", OP_ACCUM, OP_ACCUM, OP_VOID); + SET_PSW_F1 (PSW_F0); + if (SEXT40 (ACC (OP[1])) > SEXT40 (ACC (OP[0]))) + { + tmp = ACC (OP[1]); + SET_PSW_F0 (1); + } + else + { + tmp = ACC (OP[0]); + SET_PSW_F0 (0); + } + SET_ACC (OP[0], tmp); + trace_output_40 (tmp); +} + + +/* min */ +void +OP_2601 () +{ + int16 tmp; + trace_input ("min", OP_REG, OP_REG, OP_VOID); + SET_PSW_F1 (PSW_F0); + if ((int16)GPR (OP[1]) < (int16)GPR (OP[0])) + { + tmp = GPR (OP[1]); + SET_PSW_F0 (1); + } + else + { + tmp = GPR (OP[0]); + SET_PSW_F0 (0); + } + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* min */ +void +OP_3601 () +{ + int64 tmp; + + trace_input ("min", OP_ACCUM, OP_DREG, OP_VOID); + SET_PSW_F1 (PSW_F0); + tmp = SEXT16 (GPR (OP[1])) << 16 | GPR (OP[1] + 1); + if (tmp < SEXT40(ACC (OP[0]))) + { + tmp = (tmp & MASK40); + SET_PSW_F0 (1); + } + else + { + tmp = ACC (OP[0]); + SET_PSW_F0 (0); + } + SET_ACC (OP[0], tmp); + trace_output_40 (tmp); +} + +/* min */ +void +OP_3603 () +{ + int64 tmp; + trace_input ("min", OP_ACCUM, OP_ACCUM, OP_VOID); + SET_PSW_F1 (PSW_F0); + if (SEXT40(ACC (OP[1])) < SEXT40(ACC (OP[0]))) + { + tmp = ACC (OP[1]); + SET_PSW_F0 (1); + } + else + { + tmp = ACC (OP[0]); + SET_PSW_F0 (0); + } + SET_ACC (OP[0], tmp); + trace_output_40 (tmp); +} + +/* msb */ +void +OP_2800 () +{ + int64 tmp; + + trace_input ("msb", OP_ACCUM, OP_REG, OP_REG); + tmp = SEXT40 ((int16)(GPR (OP[1])) * (int16)(GPR (OP[2]))); + + if (PSW_FX) + tmp = SEXT40 ((tmp << 1) & MASK40); + + if (PSW_ST && tmp > SEXT40(MAX32)) + tmp = (MAX32); + + tmp = SEXT40(ACC (OP[0])) - tmp; + if (PSW_ST) + { + if (tmp > SEXT40(MAX32)) + tmp = (MAX32); + else if (tmp < SEXT40(MIN32)) + tmp = (MIN32); + else + tmp = (tmp & MASK40); + } + else + { + tmp = (tmp & MASK40); + } + SET_ACC (OP[0], tmp); + trace_output_40 (tmp); +} + +/* msbsu */ +void +OP_1800 () +{ + int64 tmp; + + trace_input ("msbsu", OP_ACCUM, OP_REG, OP_REG); + tmp = SEXT40 ((int16)GPR (OP[1]) * GPR (OP[2])); + if (PSW_FX) + tmp = SEXT40( (tmp << 1) & MASK40); + tmp = ((SEXT40 (ACC (OP[0])) - tmp) & MASK40); + SET_ACC (OP[0], tmp); + trace_output_40 (tmp); +} + +/* msbu */ +void +OP_3800 () +{ + uint64 tmp; + uint32 src1; + uint32 src2; + + trace_input ("msbu", OP_ACCUM, OP_REG, OP_REG); + src1 = (uint16) GPR (OP[1]); + src2 = (uint16) GPR (OP[2]); + tmp = src1 * src2; + if (PSW_FX) + tmp = (tmp << 1); + tmp = ((ACC (OP[0]) - tmp) & MASK40); + SET_ACC (OP[0], tmp); + trace_output_40 (tmp); +} + +/* mul */ +void +OP_2E00 () +{ + int16 tmp; + trace_input ("mul", OP_REG, OP_REG, OP_VOID); + tmp = GPR (OP[0]) * GPR (OP[1]); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* mulx */ +void +OP_2C00 () +{ + int64 tmp; + + trace_input ("mulx", OP_ACCUM_OUTPUT, OP_REG, OP_REG); + tmp = SEXT40 ((int16)(GPR (OP[1])) * (int16)(GPR (OP[2]))); + + if (PSW_FX) + tmp = SEXT40 ((tmp << 1) & MASK40); + + if (PSW_ST && tmp > SEXT40(MAX32)) + tmp = (MAX32); + else + tmp = (tmp & MASK40); + SET_ACC (OP[0], tmp); + trace_output_40 (tmp); +} + +/* mulxsu */ +void +OP_1C00 () +{ + int64 tmp; + + trace_input ("mulxsu", OP_ACCUM_OUTPUT, OP_REG, OP_REG); + tmp = SEXT40 ((int16)(GPR (OP[1])) * GPR (OP[2])); + + if (PSW_FX) + tmp <<= 1; + tmp = (tmp & MASK40); + SET_ACC (OP[0], tmp); + trace_output_40 (tmp); +} + +/* mulxu */ +void +OP_3C00 () +{ + uint64 tmp; + uint32 src1; + uint32 src2; + + trace_input ("mulxu", OP_ACCUM_OUTPUT, OP_REG, OP_REG); + src1 = (uint16) GPR (OP[1]); + src2 = (uint16) GPR (OP[2]); + tmp = src1 * src2; + if (PSW_FX) + tmp <<= 1; + tmp = (tmp & MASK40); + SET_ACC (OP[0], tmp); + trace_output_40 (tmp); +} + +/* mv */ +void +OP_4000 () +{ + int16 tmp; + trace_input ("mv", OP_REG_OUTPUT, OP_REG, OP_VOID); + tmp = GPR (OP[1]); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* mv2w */ +void +OP_5000 () +{ + int32 tmp; + trace_input ("mv2w", OP_DREG_OUTPUT, OP_DREG, OP_VOID); + tmp = GPR32 (OP[1]); + SET_GPR32 (OP[0], tmp); + trace_output_32 (tmp); +} + +/* mv2wfac */ +void +OP_3E00 () +{ + int32 tmp; + trace_input ("mv2wfac", OP_DREG_OUTPUT, OP_ACCUM, OP_VOID); + tmp = ACC (OP[1]); + SET_GPR32 (OP[0], tmp); + trace_output_32 (tmp); +} + +/* mv2wtac */ +void +OP_3E01 () +{ + int64 tmp; + trace_input ("mv2wtac", OP_DREG, OP_ACCUM_OUTPUT, OP_VOID); + tmp = ((SEXT16 (GPR (OP[0])) << 16 | GPR (OP[0] + 1)) & MASK40); + SET_ACC (OP[1], tmp); + trace_output_40 (tmp); +} + +/* mvac */ +void +OP_3E03 () +{ + int64 tmp; + trace_input ("mvac", OP_ACCUM_OUTPUT, OP_ACCUM, OP_VOID); + tmp = ACC (OP[1]); + SET_ACC (OP[0], tmp); + trace_output_40 (tmp); +} + +/* mvb */ +void +OP_5400 () +{ + int16 tmp; + trace_input ("mvb", OP_REG_OUTPUT, OP_REG, OP_VOID); + tmp = SEXT8 (GPR (OP[1]) & 0xff); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* mvf0f */ +void +OP_4400 () +{ + int16 tmp; + trace_input ("mf0f", OP_REG_OUTPUT, OP_REG, OP_VOID); + if (PSW_F0 == 0) + { + tmp = GPR (OP[1]); + SET_GPR (OP[0], tmp); + } + else + tmp = GPR (OP[0]); + trace_output_16 (tmp); +} + +/* mvf0t */ +void +OP_4401 () +{ + int16 tmp; + trace_input ("mf0t", OP_REG_OUTPUT, OP_REG, OP_VOID); + if (PSW_F0) + { + tmp = GPR (OP[1]); + SET_GPR (OP[0], tmp); + } + else + tmp = GPR (OP[0]); + trace_output_16 (tmp); +} + +/* mvfacg */ +void +OP_1E04 () +{ + int16 tmp; + trace_input ("mvfacg", OP_REG_OUTPUT, OP_ACCUM, OP_VOID); + tmp = ((ACC (OP[1]) >> 32) & 0xff); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* mvfachi */ +void +OP_1E00 () +{ + int16 tmp; + trace_input ("mvfachi", OP_REG_OUTPUT, OP_ACCUM, OP_VOID); + tmp = (ACC (OP[1]) >> 16); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* mvfaclo */ +void +OP_1E02 () +{ + int16 tmp; + trace_input ("mvfaclo", OP_REG_OUTPUT, OP_ACCUM, OP_VOID); + tmp = ACC (OP[1]); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* mvfc */ +void +OP_5200 () +{ + int16 tmp; + trace_input ("mvfc", OP_REG_OUTPUT, OP_CR, OP_VOID); + tmp = CREG (OP[1]); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* mvtacg */ +void +OP_1E41 () +{ + int64 tmp; + trace_input ("mvtacg", OP_REG, OP_ACCUM, OP_VOID); + tmp = ((ACC (OP[1]) & MASK32) + | ((int64)(GPR (OP[0]) & 0xff) << 32)); + SET_ACC (OP[1], tmp); + trace_output_40 (tmp); +} + +/* mvtachi */ +void +OP_1E01 () +{ + uint64 tmp; + trace_input ("mvtachi", OP_REG, OP_ACCUM, OP_VOID); + tmp = ACC (OP[1]) & 0xffff; + tmp = ((SEXT16 (GPR (OP[0])) << 16 | tmp) & MASK40); + SET_ACC (OP[1], tmp); + trace_output_40 (tmp); +} + +/* mvtaclo */ +void +OP_1E21 () +{ + int64 tmp; + trace_input ("mvtaclo", OP_REG, OP_ACCUM, OP_VOID); + tmp = ((SEXT16 (GPR (OP[0]))) & MASK40); + SET_ACC (OP[1], tmp); + trace_output_40 (tmp); +} + +/* mvtc */ +void +OP_5600 () +{ + int16 tmp; + trace_input ("mvtc", OP_REG, OP_CR_OUTPUT, OP_VOID); + tmp = GPR (OP[0]); + tmp = SET_CREG (OP[1], tmp); + trace_output_16 (tmp); +} + +/* mvub */ +void +OP_5401 () +{ + int16 tmp; + trace_input ("mvub", OP_REG_OUTPUT, OP_REG, OP_VOID); + tmp = (GPR (OP[1]) & 0xff); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* neg */ +void +OP_4605 () +{ + int16 tmp; + trace_input ("neg", OP_REG, OP_VOID, OP_VOID); + tmp = - GPR (OP[0]); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* neg */ +void +OP_5605 () +{ + int64 tmp; + + trace_input ("neg", OP_ACCUM, OP_VOID, OP_VOID); + tmp = -SEXT40(ACC (OP[0])); + if (PSW_ST) + { + if (tmp > SEXT40(MAX32)) + tmp = (MAX32); + else if (tmp < SEXT40(MIN32)) + tmp = (MIN32); + else + tmp = (tmp & MASK40); + } + else + tmp = (tmp & MASK40); + SET_ACC (OP[0], tmp); + trace_output_40 (tmp); +} + + +/* nop */ +void +OP_5E00 () +{ + trace_input ("nop", OP_VOID, OP_VOID, OP_VOID); + + ins_type_counters[ (int)State.ins_type ]--; /* don't count nops as normal instructions */ + switch (State.ins_type) + { + default: + ins_type_counters[ (int)INS_UNKNOWN ]++; + break; + + case INS_LEFT_PARALLEL: + /* Don't count a parallel op that includes a NOP as a true parallel op */ + ins_type_counters[ (int)INS_RIGHT_PARALLEL ]--; + ins_type_counters[ (int)INS_RIGHT ]++; + ins_type_counters[ (int)INS_LEFT_NOPS ]++; + break; + + case INS_LEFT: + case INS_LEFT_COND_EXE: + ins_type_counters[ (int)INS_LEFT_NOPS ]++; + break; + + case INS_RIGHT_PARALLEL: + /* Don't count a parallel op that includes a NOP as a true parallel op */ + ins_type_counters[ (int)INS_LEFT_PARALLEL ]--; + ins_type_counters[ (int)INS_LEFT ]++; + ins_type_counters[ (int)INS_RIGHT_NOPS ]++; + break; + + case INS_RIGHT: + case INS_RIGHT_COND_EXE: + ins_type_counters[ (int)INS_RIGHT_NOPS ]++; + break; + } + + trace_output_void (); +} + +/* not */ +void +OP_4603 () +{ + int16 tmp; + trace_input ("not", OP_REG, OP_VOID, OP_VOID); + tmp = ~GPR (OP[0]); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* or */ +void +OP_800 () +{ + int16 tmp; + trace_input ("or", OP_REG, OP_REG, OP_VOID); + tmp = (GPR (OP[0]) | GPR (OP[1])); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* or3 */ +void +OP_4000000 () +{ + int16 tmp; + trace_input ("or3", OP_REG_OUTPUT, OP_REG, OP_CONSTANT16); + tmp = (GPR (OP[1]) | OP[2]); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* rac */ +void +OP_5201 () +{ + int64 tmp; + int shift = SEXT3 (OP[2]); + + trace_input ("rac", OP_DREG_OUTPUT, OP_ACCUM, OP_CONSTANT3); + if (OP[1] != 0) + { + (*d10v_callback->printf_filtered) (d10v_callback, + "ERROR at PC 0x%x: instruction only valid for A0\n", + PC<<2); + State.exception = SIGILL; + } + + SET_PSW_F1 (PSW_F0); + tmp = SEXT56 ((ACC (0) << 16) | (ACC (1) & 0xffff)); + if (shift >=0) + tmp <<= shift; + else + tmp >>= -shift; + tmp += 0x8000; + tmp >>= 16; /* look at bits 0:43 */ + if (tmp > SEXT44 (SIGNED64 (0x0007fffffff))) + { + tmp = 0x7fffffff; + SET_PSW_F0 (1); + } + else if (tmp < SEXT44 (SIGNED64 (0xfff80000000))) + { + tmp = 0x80000000; + SET_PSW_F0 (1); + } + else + { + SET_PSW_F0 (0); + } + SET_GPR32 (OP[0], tmp); + trace_output_32 (tmp); +} + +/* rachi */ +void +OP_4201 () +{ + signed64 tmp; + int shift = SEXT3 (OP[2]); + + trace_input ("rachi", OP_REG_OUTPUT, OP_ACCUM, OP_CONSTANT3); + SET_PSW_F1 (PSW_F0); + if (shift >=0) + tmp = SEXT40 (ACC (OP[1])) << shift; + else + tmp = SEXT40 (ACC (OP[1])) >> -shift; + tmp += 0x8000; + + if (tmp > SEXT44 (SIGNED64 (0x0007fffffff))) + { + tmp = 0x7fff; + SET_PSW_F0 (1); + } + else if (tmp < SEXT44 (SIGNED64 (0xfff80000000))) + { + tmp = 0x8000; + SET_PSW_F0 (1); + } + else + { + tmp = (tmp >> 16); + SET_PSW_F0 (0); + } + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* rep */ +void +OP_27000000 () +{ + trace_input ("rep", OP_REG, OP_CONSTANT16, OP_VOID); + SET_RPT_S (PC + 1); + SET_RPT_E (PC + OP[1]); + SET_RPT_C (GPR (OP[0])); + SET_PSW_RP (1); + if (GPR (OP[0]) == 0) + { + (*d10v_callback->printf_filtered) (d10v_callback, "ERROR: rep with count=0 is illegal.\n"); + State.exception = SIGILL; + } + if (OP[1] < 4) + { + (*d10v_callback->printf_filtered) (d10v_callback, "ERROR: rep must include at least 4 instructions.\n"); + State.exception = SIGILL; + } + trace_output_void (); +} + +/* repi */ +void +OP_2F000000 () +{ + trace_input ("repi", OP_CONSTANT16, OP_CONSTANT16, OP_VOID); + SET_RPT_S (PC + 1); + SET_RPT_E (PC + OP[1]); + SET_RPT_C (OP[0]); + SET_PSW_RP (1); + if (OP[0] == 0) + { + (*d10v_callback->printf_filtered) (d10v_callback, "ERROR: repi with count=0 is illegal.\n"); + State.exception = SIGILL; + } + if (OP[1] < 4) + { + (*d10v_callback->printf_filtered) (d10v_callback, "ERROR: repi must include at least 4 instructions.\n"); + State.exception = SIGILL; + } + trace_output_void (); +} + +/* rtd */ +void +OP_5F60 () +{ + trace_input ("rtd", OP_VOID, OP_VOID, OP_VOID); + SET_CREG (PSW_CR, DPSW); + JMP(DPC); + trace_output_void (); +} + +/* rte */ +void +OP_5F40 () +{ + trace_input ("rte", OP_VOID, OP_VOID, OP_VOID); + SET_CREG (PSW_CR, BPSW); + JMP(BPC); + trace_output_void (); +} + +/* sadd */ +void +OP_1223 () +{ + int64 tmp; + + trace_input ("sadd", OP_ACCUM, OP_ACCUM, OP_VOID); + tmp = SEXT40(ACC (OP[0])) + (SEXT40(ACC (OP[1])) >> 16); + if (PSW_ST) + { + if (tmp > SEXT40(MAX32)) + tmp = (MAX32); + else if (tmp < SEXT40(MIN32)) + tmp = (MIN32); + else + tmp = (tmp & MASK40); + } + else + tmp = (tmp & MASK40); + SET_ACC (OP[0], tmp); + trace_output_40 (tmp); +} + +/* setf0f */ +void +OP_4611 () +{ + int16 tmp; + trace_input ("setf0f", OP_REG_OUTPUT, OP_VOID, OP_VOID); + tmp = ((PSW_F0 == 0) ? 1 : 0); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* setf0t */ +void +OP_4613 () +{ + int16 tmp; + trace_input ("setf0t", OP_REG_OUTPUT, OP_VOID, OP_VOID); + tmp = ((PSW_F0 == 1) ? 1 : 0); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* sleep */ +void +OP_5FC0 () +{ + trace_input ("sleep", OP_VOID, OP_VOID, OP_VOID); + SET_PSW_IE (1); + trace_output_void (); +} + +/* sll */ +void +OP_2200 () +{ + int16 tmp; + trace_input ("sll", OP_REG, OP_REG, OP_VOID); + tmp = (GPR (OP[0]) << (GPR (OP[1]) & 0xf)); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* sll */ +void +OP_3200 () +{ + int64 tmp; + trace_input ("sll", OP_ACCUM, OP_REG, OP_VOID); + if ((GPR (OP[1]) & 31) <= 16) + tmp = SEXT40 (ACC (OP[0])) << (GPR (OP[1]) & 31); + else + { + (*d10v_callback->printf_filtered) (d10v_callback, "ERROR: shift value %d too large.\n", GPR (OP[1]) & 31); + State.exception = SIGILL; + return; + } + + if (PSW_ST) + { + if (tmp > SEXT40(MAX32)) + tmp = (MAX32); + else if (tmp < SEXT40(MIN32)) + tmp = (MIN32); + else + tmp = (tmp & MASK40); + } + else + tmp = (tmp & MASK40); + SET_ACC (OP[0], tmp); + trace_output_40 (tmp); +} + +/* slli */ +void +OP_2201 () +{ + int16 tmp; + trace_input ("slli", OP_REG, OP_CONSTANT16, OP_VOID); + tmp = (GPR (OP[0]) << OP[1]); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* slli */ +void +OP_3201 () +{ + int64 tmp; + + if (OP[1] == 0) + OP[1] = 16; + + trace_input ("slli", OP_ACCUM, OP_CONSTANT16, OP_VOID); + tmp = SEXT40(ACC (OP[0])) << OP[1]; + + if (PSW_ST) + { + if (tmp > SEXT40(MAX32)) + tmp = (MAX32); + else if (tmp < SEXT40(MIN32)) + tmp = (MIN32); + else + tmp = (tmp & MASK40); + } + else + tmp = (tmp & MASK40); + SET_ACC (OP[0], tmp); + trace_output_40 (tmp); +} + +/* slx */ +void +OP_460B () +{ + int16 tmp; + trace_input ("slx", OP_REG, OP_FLAG, OP_VOID); + tmp = ((GPR (OP[0]) << 1) | PSW_F0); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* sra */ +void +OP_2400 () +{ + int16 tmp; + trace_input ("sra", OP_REG, OP_REG, OP_VOID); + tmp = (((int16)(GPR (OP[0]))) >> (GPR (OP[1]) & 0xf)); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* sra */ +void +OP_3400 () +{ + trace_input ("sra", OP_ACCUM, OP_REG, OP_VOID); + if ((GPR (OP[1]) & 31) <= 16) + { + int64 tmp = ((SEXT40(ACC (OP[0])) >> (GPR (OP[1]) & 31)) & MASK40); + SET_ACC (OP[0], tmp); + trace_output_40 (tmp); + } + else + { + (*d10v_callback->printf_filtered) (d10v_callback, "ERROR: shift value %d too large.\n", GPR (OP[1]) & 31); + State.exception = SIGILL; + return; + } +} + +/* srai */ +void +OP_2401 () +{ + int16 tmp; + trace_input ("srai", OP_REG, OP_CONSTANT16, OP_VOID); + tmp = (((int16)(GPR (OP[0]))) >> OP[1]); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* srai */ +void +OP_3401 () +{ + int64 tmp; + if (OP[1] == 0) + OP[1] = 16; + + trace_input ("srai", OP_ACCUM, OP_CONSTANT16, OP_VOID); + tmp = ((SEXT40(ACC (OP[0])) >> OP[1]) & MASK40); + SET_ACC (OP[0], tmp); + trace_output_40 (tmp); +} + +/* srl */ +void +OP_2000 () +{ + int16 tmp; + trace_input ("srl", OP_REG, OP_REG, OP_VOID); + tmp = (GPR (OP[0]) >> (GPR (OP[1]) & 0xf)); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* srl */ +void +OP_3000 () +{ + trace_input ("srl", OP_ACCUM, OP_REG, OP_VOID); + if ((GPR (OP[1]) & 31) <= 16) + { + int64 tmp = ((uint64)((ACC (OP[0]) & MASK40) >> (GPR (OP[1]) & 31))); + SET_ACC (OP[0], tmp); + trace_output_40 (tmp); + } + else + { + (*d10v_callback->printf_filtered) (d10v_callback, "ERROR: shift value %d too large.\n", GPR (OP[1]) & 31); + State.exception = SIGILL; + return; + } + +} + +/* srli */ +void +OP_2001 () +{ + int16 tmp; + trace_input ("srli", OP_REG, OP_CONSTANT16, OP_VOID); + tmp = (GPR (OP[0]) >> OP[1]); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* srli */ +void +OP_3001 () +{ + int64 tmp; + if (OP[1] == 0) + OP[1] = 16; + + trace_input ("srli", OP_ACCUM, OP_CONSTANT16, OP_VOID); + tmp = ((uint64)(ACC (OP[0]) & MASK40) >> OP[1]); + SET_ACC (OP[0], tmp); + trace_output_40 (tmp); +} + +/* srx */ +void +OP_4609 () +{ + uint16 tmp; + trace_input ("srx", OP_REG, OP_FLAG, OP_VOID); + tmp = PSW_F0 << 15; + tmp = ((GPR (OP[0]) >> 1) | tmp); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* st */ +void +OP_34000000 () +{ + trace_input ("st", OP_REG, OP_MEMREF2, OP_VOID); + SW (OP[1] + GPR (OP[2]), GPR (OP[0])); + trace_output_void (); +} + +/* st */ +void +OP_6800 () +{ + trace_input ("st", OP_REG, OP_MEMREF, OP_VOID); + SW (GPR (OP[1]), GPR (OP[0])); + trace_output_void (); +} + +/* st */ +void +OP_6C1F () +{ + uint16 addr = GPR (OP[1]) - 2; + trace_input ("st", OP_REG, OP_PREDEC, OP_VOID); + if (OP[1] != 15) + { + (*d10v_callback->printf_filtered) (d10v_callback, "ERROR: cannot pre-decrement any registers but r15 (SP).\n"); + State.exception = SIGILL; + return; + } + SW (addr, GPR (OP[0])); + SET_GPR (OP[1], addr); + trace_output_void (); +} + +/* st */ +void +OP_6801 () +{ + trace_input ("st", OP_REG, OP_POSTINC, OP_VOID); + SW (GPR (OP[1]), GPR (OP[0])); + INC_ADDR (OP[1], 2); + trace_output_void (); +} + +/* st */ +void +OP_6C01 () +{ + trace_input ("st", OP_REG, OP_POSTDEC, OP_VOID); + if ( OP[1] == 15 ) + { + (*d10v_callback->printf_filtered) (d10v_callback, "ERROR: cannot post-decrement register r15 (SP).\n"); + State.exception = SIGILL; + return; + } + SW (GPR (OP[1]), GPR (OP[0])); + INC_ADDR (OP[1], -2); + trace_output_void (); +} + +/* st2w */ +void +OP_35000000 () +{ + trace_input ("st2w", OP_DREG, OP_MEMREF2, OP_VOID); + SW (GPR (OP[2])+ OP[1] + 0, GPR (OP[0] + 0)); + SW (GPR (OP[2])+ OP[1] + 2, GPR (OP[0] + 1)); + trace_output_void (); +} + +/* st2w */ +void +OP_6A00 () +{ + trace_input ("st2w", OP_DREG, OP_MEMREF, OP_VOID); + SW (GPR (OP[1]) + 0, GPR (OP[0] + 0)); + SW (GPR (OP[1]) + 2, GPR (OP[0] + 1)); + trace_output_void (); +} + +/* st2w */ +void +OP_6E1F () +{ + uint16 addr = GPR (OP[1]) - 4; + trace_input ("st2w", OP_DREG, OP_PREDEC, OP_VOID); + if ( OP[1] != 15 ) + { + (*d10v_callback->printf_filtered) (d10v_callback, "ERROR: cannot pre-decrement any registers but r15 (SP).\n"); + State.exception = SIGILL; + return; + } + SW (addr + 0, GPR (OP[0] + 0)); + SW (addr + 2, GPR (OP[0] + 1)); + SET_GPR (OP[1], addr); + trace_output_void (); +} + +/* st2w */ +void +OP_6A01 () +{ + trace_input ("st2w", OP_DREG, OP_POSTINC, OP_VOID); + SW (GPR (OP[1]) + 0, GPR (OP[0] + 0)); + SW (GPR (OP[1]) + 2, GPR (OP[0] + 1)); + INC_ADDR (OP[1], 4); + trace_output_void (); +} + +/* st2w */ +void +OP_6E01 () +{ + trace_input ("st2w", OP_DREG, OP_POSTDEC, OP_VOID); + if ( OP[1] == 15 ) + { + (*d10v_callback->printf_filtered) (d10v_callback, "ERROR: cannot post-decrement register r15 (SP).\n"); + State.exception = SIGILL; + return; + } + SW (GPR (OP[1]) + 0, GPR (OP[0] + 0)); + SW (GPR (OP[1]) + 2, GPR (OP[0] + 1)); + INC_ADDR (OP[1], -4); + trace_output_void (); +} + +/* stb */ +void +OP_3C000000 () +{ + trace_input ("stb", OP_REG, OP_MEMREF2, OP_VOID); + SB (GPR (OP[2]) + OP[1], GPR (OP[0])); + trace_output_void (); +} + +/* stb */ +void +OP_7800 () +{ + trace_input ("stb", OP_REG, OP_MEMREF, OP_VOID); + SB (GPR (OP[1]), GPR (OP[0])); + trace_output_void (); +} + +/* stop */ +void +OP_5FE0 () +{ + trace_input ("stop", OP_VOID, OP_VOID, OP_VOID); + State.exception = SIG_D10V_STOP; + trace_output_void (); +} + +/* sub */ +void +OP_0 () +{ + uint16 a = GPR (OP[0]); + uint16 b = GPR (OP[1]); + uint16 tmp = (a - b); + trace_input ("sub", OP_REG, OP_REG, OP_VOID); + /* see ../common/sim-alu.h for a more extensive discussion on how to + compute the carry/overflow bits. */ + SET_PSW_C (a >= b); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* sub */ +void +OP_1001 () +{ + int64 tmp; + + trace_input ("sub", OP_ACCUM, OP_DREG, OP_VOID); + tmp = SEXT40(ACC (OP[0])) - (SEXT16 (GPR (OP[1])) << 16 | GPR (OP[1] + 1)); + if (PSW_ST) + { + if (tmp > SEXT40(MAX32)) + tmp = (MAX32); + else if (tmp < SEXT40(MIN32)) + tmp = (MIN32); + else + tmp = (tmp & MASK40); + } + else + tmp = (tmp & MASK40); + SET_ACC (OP[0], tmp); + + trace_output_40 (tmp); +} + +/* sub */ + +void +OP_1003 () +{ + int64 tmp; + + trace_input ("sub", OP_ACCUM, OP_ACCUM, OP_VOID); + tmp = SEXT40(ACC (OP[0])) - SEXT40(ACC (OP[1])); + if (PSW_ST) + { + if (tmp > SEXT40(MAX32)) + tmp = (MAX32); + else if (tmp < SEXT40(MIN32)) + tmp = (MIN32); + else + tmp = (tmp & MASK40); + } + else + tmp = (tmp & MASK40); + SET_ACC (OP[0], tmp); + + trace_output_40 (tmp); +} + +/* sub2w */ +void +OP_1000 () +{ + uint32 tmp, a, b; + + trace_input ("sub2w", OP_DREG, OP_DREG, OP_VOID); + a = (uint32)((GPR (OP[0]) << 16) | GPR (OP[0] + 1)); + b = (uint32)((GPR (OP[1]) << 16) | GPR (OP[1] + 1)); + /* see ../common/sim-alu.h for a more extensive discussion on how to + compute the carry/overflow bits */ + tmp = a - b; + SET_PSW_C (a >= b); + SET_GPR32 (OP[0], tmp); + trace_output_32 (tmp); +} + +/* subac3 */ +void +OP_17000000 () +{ + int64 tmp; + + trace_input ("subac3", OP_DREG_OUTPUT, OP_DREG, OP_ACCUM); + tmp = SEXT40 ((GPR (OP[1]) << 16) | GPR (OP[1] + 1)) - SEXT40 (ACC (OP[2])); + SET_GPR32 (OP[0], tmp); + trace_output_32 (tmp); +} + +/* subac3 */ +void +OP_17000002 () +{ + int64 tmp; + + trace_input ("subac3", OP_DREG_OUTPUT, OP_ACCUM, OP_ACCUM); + tmp = SEXT40 (ACC (OP[1])) - SEXT40(ACC (OP[2])); + SET_GPR32 (OP[0], tmp); + trace_output_32 (tmp); +} + +/* subac3s */ +void +OP_17001000 () +{ + int64 tmp; + + trace_input ("subac3s", OP_DREG_OUTPUT, OP_DREG, OP_ACCUM); + SET_PSW_F1 (PSW_F0); + tmp = SEXT40 ((GPR (OP[1]) << 16) | GPR (OP[1] + 1)) - SEXT40(ACC (OP[2])); + if (tmp > SEXT40(MAX32)) + { + tmp = (MAX32); + SET_PSW_F0 (1); + } + else if (tmp < SEXT40(MIN32)) + { + tmp = (MIN32); + SET_PSW_F0 (1); + } + else + { + SET_PSW_F0 (0); + } + SET_GPR32 (OP[0], tmp); + trace_output_32 (tmp); +} + +/* subac3s */ +void +OP_17001002 () +{ + int64 tmp; + + trace_input ("subac3s", OP_DREG_OUTPUT, OP_ACCUM, OP_ACCUM); + SET_PSW_F1 (PSW_F0); + tmp = SEXT40(ACC (OP[1])) - SEXT40(ACC (OP[2])); + if (tmp > SEXT40(MAX32)) + { + tmp = (MAX32); + SET_PSW_F0 (1); + } + else if (tmp < SEXT40(MIN32)) + { + tmp = (MIN32); + SET_PSW_F0 (1); + } + else + { + SET_PSW_F0 (0); + } + SET_GPR32 (OP[0], tmp); + trace_output_32 (tmp); +} + +/* subi */ +void +OP_1 () +{ + unsigned tmp; + if (OP[1] == 0) + OP[1] = 16; + + trace_input ("subi", OP_REG, OP_CONSTANT16, OP_VOID); + /* see ../common/sim-alu.h for a more extensive discussion on how to + compute the carry/overflow bits. */ + /* since OP[1] is never <= 0, -OP[1] == ~OP[1]+1 can never overflow */ + tmp = ((unsigned)(unsigned16) GPR (OP[0]) + + (unsigned)(unsigned16) ( - OP[1])); + SET_PSW_C (tmp >= (1 << 16)); + SET_GPR (OP[0], tmp); + trace_output_16 (tmp); +} + +/* trap */ +void +OP_5F00 () +{ + trace_input ("trap", OP_CONSTANT4, OP_VOID, OP_VOID); + trace_output_void (); + + switch (OP[0]) + { + default: +#if (DEBUG & DEBUG_TRAP) == 0 + { + uint16 vec = OP[0] + TRAP_VECTOR_START; + SET_BPC (PC + 1); + SET_BPSW (PSW); + SET_PSW (PSW & PSW_SM_BIT); + JMP (vec); + break; + } +#else /* if debugging use trap to print registers */ + { + int i; + static int first_time = 1; + + if (first_time) + { + first_time = 0; + (*d10v_callback->printf_filtered) (d10v_callback, "Trap # PC "); + for (i = 0; i < 16; i++) + (*d10v_callback->printf_filtered) (d10v_callback, " %sr%d", (i > 9) ? "" : " ", i); + (*d10v_callback->printf_filtered) (d10v_callback, " a0 a1 f0 f1 c\n"); + } + + (*d10v_callback->printf_filtered) (d10v_callback, "Trap %2d 0x%.4x:", (int)OP[0], (int)PC); + + for (i = 0; i < 16; i++) + (*d10v_callback->printf_filtered) (d10v_callback, " %.4x", (int) GPR (i)); + + for (i = 0; i < 2; i++) + (*d10v_callback->printf_filtered) (d10v_callback, " %.2x%.8lx", + ((int)(ACC (i) >> 32) & 0xff), + ((unsigned long) ACC (i)) & 0xffffffff); + + (*d10v_callback->printf_filtered) (d10v_callback, " %d %d %d\n", + PSW_F0 != 0, PSW_F1 != 0, PSW_C != 0); + (*d10v_callback->flush_stdout) (d10v_callback); + break; + } +#endif + case 15: /* new system call trap */ + /* Trap 15 is used for simulating low-level I/O */ + { + unsigned32 result = 0; + errno = 0; + +/* Registers passed to trap 0 */ + +#define FUNC GPR (4) /* function number */ +#define PARM1 GPR (0) /* optional parm 1 */ +#define PARM2 GPR (1) /* optional parm 2 */ +#define PARM3 GPR (2) /* optional parm 3 */ +#define PARM4 GPR (3) /* optional parm 3 */ + +/* Registers set by trap 0 */ + +#define RETVAL(X) do { result = (X); SET_GPR (0, result); } while (0) +#define RETVAL32(X) do { result = (X); SET_GPR (0, result >> 16); SET_GPR (1, result); } while (0) +#define RETERR(X) SET_GPR (4, (X)) /* return error code */ + +/* Turn a pointer in a register into a pointer into real memory. */ + +#define MEMPTR(x) ((char *)(dmem_addr(x))) + + switch (FUNC) + { +#if !defined(__GO32__) && !defined(_WIN32) + case TARGET_SYS_fork: + trace_input ("", OP_VOID, OP_VOID, OP_VOID); + RETVAL (fork ()); + trace_output_16 (result); + break; + +#define getpid() 47 + case TARGET_SYS_getpid: + trace_input ("", OP_VOID, OP_VOID, OP_VOID); + RETVAL (getpid ()); + trace_output_16 (result); + break; + + case TARGET_SYS_kill: + trace_input ("", OP_R0, OP_R1, OP_VOID); + if (PARM1 == getpid ()) + { + trace_output_void (); + State.exception = PARM2; + } + else + { + int os_sig = -1; + switch (PARM2) + { +#ifdef SIGHUP + case 1: os_sig = SIGHUP; break; +#endif +#ifdef SIGINT + case 2: os_sig = SIGINT; break; +#endif +#ifdef SIGQUIT + case 3: os_sig = SIGQUIT; break; +#endif +#ifdef SIGILL + case 4: os_sig = SIGILL; break; +#endif +#ifdef SIGTRAP + case 5: os_sig = SIGTRAP; break; +#endif +#ifdef SIGABRT + case 6: os_sig = SIGABRT; break; +#elif defined(SIGIOT) + case 6: os_sig = SIGIOT; break; +#endif +#ifdef SIGEMT + case 7: os_sig = SIGEMT; break; +#endif +#ifdef SIGFPE + case 8: os_sig = SIGFPE; break; +#endif +#ifdef SIGKILL + case 9: os_sig = SIGKILL; break; +#endif +#ifdef SIGBUS + case 10: os_sig = SIGBUS; break; +#endif +#ifdef SIGSEGV + case 11: os_sig = SIGSEGV; break; +#endif +#ifdef SIGSYS + case 12: os_sig = SIGSYS; break; +#endif +#ifdef SIGPIPE + case 13: os_sig = SIGPIPE; break; +#endif +#ifdef SIGALRM + case 14: os_sig = SIGALRM; break; +#endif +#ifdef SIGTERM + case 15: os_sig = SIGTERM; break; +#endif +#ifdef SIGURG + case 16: os_sig = SIGURG; break; +#endif +#ifdef SIGSTOP + case 17: os_sig = SIGSTOP; break; +#endif +#ifdef SIGTSTP + case 18: os_sig = SIGTSTP; break; +#endif +#ifdef SIGCONT + case 19: os_sig = SIGCONT; break; +#endif +#ifdef SIGCHLD + case 20: os_sig = SIGCHLD; break; +#elif defined(SIGCLD) + case 20: os_sig = SIGCLD; break; +#endif +#ifdef SIGTTIN + case 21: os_sig = SIGTTIN; break; +#endif +#ifdef SIGTTOU + case 22: os_sig = SIGTTOU; break; +#endif +#ifdef SIGIO + case 23: os_sig = SIGIO; break; +#elif defined (SIGPOLL) + case 23: os_sig = SIGPOLL; break; +#endif +#ifdef SIGXCPU + case 24: os_sig = SIGXCPU; break; +#endif +#ifdef SIGXFSZ + case 25: os_sig = SIGXFSZ; break; +#endif +#ifdef SIGVTALRM + case 26: os_sig = SIGVTALRM; break; +#endif +#ifdef SIGPROF + case 27: os_sig = SIGPROF; break; +#endif +#ifdef SIGWINCH + case 28: os_sig = SIGWINCH; break; +#endif +#ifdef SIGLOST + case 29: os_sig = SIGLOST; break; +#endif +#ifdef SIGUSR1 + case 30: os_sig = SIGUSR1; break; +#endif +#ifdef SIGUSR2 + case 31: os_sig = SIGUSR2; break; +#endif + } + + if (os_sig == -1) + { + trace_output_void (); + (*d10v_callback->printf_filtered) (d10v_callback, "Unknown signal %d\n", PARM2); + (*d10v_callback->flush_stdout) (d10v_callback); + State.exception = SIGILL; + } + else + { + RETVAL (kill (PARM1, PARM2)); + trace_output_16 (result); + } + } + break; + + case TARGET_SYS_execve: + trace_input ("", OP_R0, OP_R1, OP_R2); + RETVAL (execve (MEMPTR (PARM1), (char **) MEMPTR (PARM2), + (char **)MEMPTR (PARM3))); + trace_output_16 (result); + break; + +#ifdef TARGET_SYS_execv + case TARGET_SYS_execv: + trace_input ("", OP_R0, OP_R1, OP_VOID); + RETVAL (execve (MEMPTR (PARM1), (char **) MEMPTR (PARM2), NULL)); + trace_output_16 (result); + break; +#endif + + case TARGET_SYS_pipe: + { + reg_t buf; + int host_fd[2]; + + trace_input ("", OP_R0, OP_VOID, OP_VOID); + buf = PARM1; + RETVAL (pipe (host_fd)); + SW (buf, host_fd[0]); + buf += sizeof(uint16); + SW (buf, host_fd[1]); + trace_output_16 (result); + } + break; + +#if 0 +#ifdef TARGET_SYS_wait + case TARGET_SYS_wait: + { + int status; + trace_input ("", OP_R0, OP_VOID, OP_VOID); + RETVAL (wait (&status)); + if (PARM1) + SW (PARM1, status); + trace_output_16 (result); + } + break; +#endif +#endif +#else + case TARGET_SYS_getpid: + trace_input ("", OP_VOID, OP_VOID, OP_VOID); + RETVAL (1); + trace_output_16 (result); + break; + + case TARGET_SYS_kill: + trace_input ("", OP_REG, OP_REG, OP_VOID); + trace_output_void (); + State.exception = PARM2; + break; +#endif + + case TARGET_SYS_read: + trace_input ("", OP_R0, OP_R1, OP_R2); + RETVAL (d10v_callback->read (d10v_callback, PARM1, MEMPTR (PARM2), + PARM3)); + trace_output_16 (result); + break; + + case TARGET_SYS_write: + trace_input ("", OP_R0, OP_R1, OP_R2); + if (PARM1 == 1) + RETVAL ((int)d10v_callback->write_stdout (d10v_callback, + MEMPTR (PARM2), PARM3)); + else + RETVAL ((int)d10v_callback->write (d10v_callback, PARM1, + MEMPTR (PARM2), PARM3)); + trace_output_16 (result); + break; + + case TARGET_SYS_lseek: + trace_input ("", OP_R0, OP_R1, OP_R2); + RETVAL32 (d10v_callback->lseek (d10v_callback, PARM1, + ((((unsigned long) PARM2) << 16) + || (unsigned long) PARM3), + PARM4)); + trace_output_32 (result); + break; + + case TARGET_SYS_close: + trace_input ("", OP_R0, OP_VOID, OP_VOID); + RETVAL (d10v_callback->close (d10v_callback, PARM1)); + trace_output_16 (result); + break; + + case TARGET_SYS_open: + trace_input ("", OP_R0, OP_R1, OP_R2); + RETVAL (d10v_callback->open (d10v_callback, MEMPTR (PARM1), PARM2)); + trace_output_16 (result); + break; + + case TARGET_SYS_exit: + trace_input ("", OP_R0, OP_VOID, OP_VOID); + State.exception = SIG_D10V_EXIT; + trace_output_void (); + break; + + case TARGET_SYS_stat: + trace_input ("", OP_R0, OP_R1, OP_VOID); + /* stat system call */ + { + struct stat host_stat; + reg_t buf; + + RETVAL (stat (MEMPTR (PARM1), &host_stat)); + + buf = PARM2; + + /* The hard-coded offsets and sizes were determined by using + * the D10V compiler on a test program that used struct stat. + */ + SW (buf, host_stat.st_dev); + SW (buf+2, host_stat.st_ino); + SW (buf+4, host_stat.st_mode); + SW (buf+6, host_stat.st_nlink); + SW (buf+8, host_stat.st_uid); + SW (buf+10, host_stat.st_gid); + SW (buf+12, host_stat.st_rdev); + SLW (buf+16, host_stat.st_size); + SLW (buf+20, host_stat.st_atime); + SLW (buf+28, host_stat.st_mtime); + SLW (buf+36, host_stat.st_ctime); + } + trace_output_16 (result); + break; + + case TARGET_SYS_chown: + trace_input ("", OP_R0, OP_R1, OP_R2); + RETVAL (chown (MEMPTR (PARM1), PARM2, PARM3)); + trace_output_16 (result); + break; + + case TARGET_SYS_chmod: + trace_input ("", OP_R0, OP_R1, OP_R2); + RETVAL (chmod (MEMPTR (PARM1), PARM2)); + trace_output_16 (result); + break; + +#if 0 +#ifdef TARGET_SYS_utime + case TARGET_SYS_utime: + trace_input ("", OP_R0, OP_R1, OP_R2); + /* Cast the second argument to void *, to avoid type mismatch + if a prototype is present. */ + RETVAL (utime (MEMPTR (PARM1), (void *) MEMPTR (PARM2))); + trace_output_16 (result); + break; +#endif +#endif + +#if 0 +#ifdef TARGET_SYS_time + case TARGET_SYS_time: + trace_input ("