aboutsummaryrefslogtreecommitdiff
path: root/sim/common
diff options
context:
space:
mode:
authorStan Shebs <shebs@codesourcery.com>1999-04-16 01:35:26 +0000
committerStan Shebs <shebs@codesourcery.com>1999-04-16 01:35:26 +0000
commitc906108c21474dfb4ed285bcc0ac6fe02cd400cc (patch)
treea0015aa5cedc19ccbab307251353a41722a3ae13 /sim/common
parentcd946cff9ede3f30935803403f06f6ed30cad136 (diff)
downloadgdb-c906108c21474dfb4ed285bcc0ac6fe02cd400cc.zip
gdb-c906108c21474dfb4ed285bcc0ac6fe02cd400cc.tar.gz
gdb-c906108c21474dfb4ed285bcc0ac6fe02cd400cc.tar.bz2
Initial creation of sourceware repositorygdb-4_18-branchpoint
Diffstat (limited to 'sim/common')
-rw-r--r--sim/common/ChangeLog4005
-rw-r--r--sim/common/Make-common.in642
-rw-r--r--sim/common/Makefile.in139
-rw-r--r--sim/common/acconfig.h15
-rw-r--r--sim/common/aclocal.m41259
-rw-r--r--sim/common/callback.c810
-rw-r--r--sim/common/cgen-cpu.h98
-rw-r--r--sim/common/cgen-defs.h174
-rw-r--r--sim/common/cgen-engine.h473
-rw-r--r--sim/common/cgen-mem.h203
-rw-r--r--sim/common/cgen-ops.h897
-rw-r--r--sim/common/cgen-run.c233
-rw-r--r--sim/common/cgen-scache.c471
-rw-r--r--sim/common/cgen-scache.h162
-rw-r--r--sim/common/cgen-sim.h34
-rw-r--r--sim/common/cgen-trace.c414
-rw-r--r--sim/common/cgen-trace.h91
-rw-r--r--sim/common/cgen-types.h116
-rw-r--r--sim/common/cgen-utils.c328
-rw-r--r--sim/common/config.in167
-rwxr-xr-xsim/common/configure3902
-rw-r--r--sim/common/configure.in40
-rw-r--r--sim/common/dv-core.c118
-rw-r--r--sim/common/dv-glue.c373
-rw-r--r--sim/common/dv-pal.c605
-rw-r--r--sim/common/dv-sockser.c386
-rw-r--r--sim/common/dv-sockser.h32
-rw-r--r--sim/common/gdbinit.in10
-rw-r--r--sim/common/genmloop.sh1122
-rw-r--r--sim/common/gennltvals.sh67
-rw-r--r--sim/common/gentmap.c125
-rw-r--r--sim/common/gentvals.sh74
-rw-r--r--sim/common/hw-alloc.c99
-rw-r--r--sim/common/hw-alloc.h49
-rw-r--r--sim/common/hw-base.c571
-rw-r--r--sim/common/hw-base.h109
-rw-r--r--sim/common/hw-device.c66
-rw-r--r--sim/common/hw-device.h535
-rw-r--r--sim/common/hw-events.c263
-rw-r--r--sim/common/hw-events.h61
-rw-r--r--sim/common/hw-handles.c237
-rw-r--r--sim/common/hw-handles.h63
-rw-r--r--sim/common/hw-instances.c285
-rw-r--r--sim/common/hw-instances.h157
-rw-r--r--sim/common/hw-main.h73
-rw-r--r--sim/common/hw-ports.c339
-rw-r--r--sim/common/hw-ports.h129
-rw-r--r--sim/common/hw-properties.c905
-rw-r--r--sim/common/hw-properties.h244
-rw-r--r--sim/common/hw-tree.c1344
-rw-r--r--sim/common/hw-tree.h119
-rw-r--r--sim/common/nltvals.def418
-rw-r--r--sim/common/nrun.c214
-rw-r--r--sim/common/run.1107
-rw-r--r--sim/common/run.c308
-rw-r--r--sim/common/sim-abort.c60
-rw-r--r--sim/common/sim-alu.h1047
-rw-r--r--sim/common/sim-arange.c301
-rw-r--r--sim/common/sim-arange.h83
-rw-r--r--sim/common/sim-assert.h90
-rw-r--r--sim/common/sim-base.h252
-rw-r--r--sim/common/sim-basics.h154
-rw-r--r--sim/common/sim-bits.c208
-rw-r--r--sim/common/sim-bits.h564
-rw-r--r--sim/common/sim-break.c278
-rw-r--r--sim/common/sim-break.h38
-rw-r--r--sim/common/sim-config.c377
-rw-r--r--sim/common/sim-config.h594
-rw-r--r--sim/common/sim-core.c839
-rw-r--r--sim/common/sim-core.h343
-rw-r--r--sim/common/sim-cpu.c80
-rw-r--r--sim/common/sim-cpu.h152
-rw-r--r--sim/common/sim-endian.c128
-rw-r--r--sim/common/sim-endian.h414
-rw-r--r--sim/common/sim-engine.c210
-rw-r--r--sim/common/sim-engine.h161
-rw-r--r--sim/common/sim-events.c1188
-rw-r--r--sim/common/sim-events.h271
-rw-r--r--sim/common/sim-fpu.c2578
-rw-r--r--sim/common/sim-fpu.h417
-rw-r--r--sim/common/sim-hload.c69
-rw-r--r--sim/common/sim-hrw.c41
-rw-r--r--sim/common/sim-hw.c508
-rw-r--r--sim/common/sim-hw.h98
-rw-r--r--sim/common/sim-info.c32
-rw-r--r--sim/common/sim-inline.c96
-rw-r--r--sim/common/sim-inline.h810
-rw-r--r--sim/common/sim-io.c379
-rw-r--r--sim/common/sim-io.h84
-rw-r--r--sim/common/sim-load.c239
-rw-r--r--sim/common/sim-memopt.c471
-rw-r--r--sim/common/sim-memopt.h46
-rw-r--r--sim/common/sim-model.c208
-rw-r--r--sim/common/sim-model.h138
-rw-r--r--sim/common/sim-module.c399
-rw-r--r--sim/common/sim-module.h125
-rw-r--r--sim/common/sim-n-bits.h218
-rw-r--r--sim/common/sim-n-core.h417
-rw-r--r--sim/common/sim-n-endian.h169
-rw-r--r--sim/common/sim-options.c936
-rw-r--r--sim/common/sim-options.h149
-rw-r--r--sim/common/sim-profile.c1175
-rw-r--r--sim/common/sim-profile.h289
-rw-r--r--sim/common/sim-reason.c57
-rw-r--r--sim/common/sim-reg.c52
-rw-r--r--sim/common/sim-resume.c85
-rw-r--r--sim/common/sim-run.c51
-rw-r--r--sim/common/sim-signal.c96
-rw-r--r--sim/common/sim-signal.h49
-rw-r--r--sim/common/sim-stop.c43
-rw-r--r--sim/common/sim-trace.c1341
-rw-r--r--sim/common/sim-trace.h551
-rw-r--r--sim/common/sim-types.h201
-rw-r--r--sim/common/sim-utils.c411
-rw-r--r--sim/common/sim-utils.h90
-rw-r--r--sim/common/sim-watch.c458
-rw-r--r--sim/common/sim-watch.h78
-rw-r--r--sim/common/syscall.c482
-rw-r--r--sim/common/tconfig.in19
119 files changed, 46267 insertions, 0 deletions
diff --git a/sim/common/ChangeLog b/sim/common/ChangeLog
new file mode 100644
index 0000000..bde0710
--- /dev/null
+++ b/sim/common/ChangeLog
@@ -0,0 +1,4005 @@
+1999-02-09 Doug Evans <devans@casey.cygnus.com>
+
+ * 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 <cpu>-decode.c.
+ (struct idesc): Moved to here from <cpu>-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 <fche@cygnus.com>
+
+ * sim-memopt.c (memory_option_handler): Avoid memset() calls
+ if redundant with allocator functions.
+
+Wed Jan 27 17:19:09 1999 Doug Evans <devans@canuck.cygnus.com>
+
+ * 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 <fche@cygnus.com>
+
+ * 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 <rth@cygnus.com>
+
+ * 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 <devans@casey.cygnus.com>
+
+ * 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 <devans@casey.cygnus.com>
+
+ * 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 <devans@casey.cygnus.com>
+
+ * 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 <fche@cygnus.com>
+
+ * 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 <devans@casey.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * hw-properties.c, hw-instances.c, hw-tree.c: Include
+ "sim-assert.h".
+
+1998-12-09 Doug Evans <devans@casey.cygnus.com>
+
+ * 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 <wilson@wilson-pc.cygnus.com>
+
+ * gennltvals.sh: Add i960.
+ * nltvals.def: Rebuild.
+
+1998-12-04 Doug Evans <devans@casey.cygnus.com>
+
+ * 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 <fche@cygnus.com>
+
+ * sim-memopt.c (sim_memory_uninstall): Deallocate all memory
+ regions.
+
+1998-12-01 Doug Evans <devans@casey.cygnus.com>
+
+ * sim-inline.c (SIM_INLINE_P): Fix typo.
+
+1998-11-30 Doug Evans <devans@casey.cygnus.com>
+
+ * cgen-utils.c (cgen_virtual_opcode_table): Update.
+
+Tue Nov 24 18:40:03 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * gennltvals.sh: Add v850 and d10v. Sort alphabetically.
+ * nltvals.def: Re-generate.
+
+Mon Nov 23 13:28:38 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * 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 <devans@tobor.to.cygnus.com>
+
+ * genmloop.sh (${cpu}_pbb_chain): Watch for Ctrl-C's.
+ (${cpu}_pbb_cti_chain): Ditto.
+
+1998-11-18 Doug Evans <devans@casey.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <fche@elastic.org>
+
+ * aclocal.m4: Add tests for dlopen family.
+ * config.in: Regenerated.
+
+Wed Nov 11 14:02:25 1998 Doug Evans <devans@canuck.cygnus.com>
+
+ * sim-hload.c (sim_load): Pass `prog_name' to sim_load_file, not NULL.
+
+Wed Nov 4 23:51:19 1998 Doug Evans <devans@seba.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <devans@seba.cygnus.com>
+
+ * 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 <devans@seba.cygnus.com>
+
+ * 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 <devans@seba.cygnus.com>
+
+ * cgen-run.c: New file.
+ * sim-reg.c: New file.
+
+Mon Sep 14 10:58:19 1998 Frank Ch. Eigler <fche@cygnus.com>
+
+ * 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 <fche@cygnus.com>
+
+ * sim-config.h: Remove reference to linux kernel header.
+
+Tue Aug 25 12:45:27 1998 Frank Ch. Eigler <fche@cygnus.com>
+
+ * dv-sockser.c (sockser_addr): Make variable non-static.
+
+Mon Aug 24 11:47:37 1998 Joyce Janczyn <janczyn@cygnus.com>
+
+ * sim-hw.{c,h} (sim_hw_parse): Return struct hw pointer.
+
+Tue Aug 11 18:12:19 1998 Doug Evans <devans@canuck.cygnus.com>
+
+ * sim-events.c (sim_events_elapsed_time): Fix calculation.
+
+Tue Aug 4 20:36:46 1998 Jeff Holcomb <jeffh@cygnus.com>
+
+ * Make-common.in (install-common): Add $(EXEEXT) when installing
+ run.
+
+Mon Aug 3 11:46:01 1998 Doug Evans <devans@seba.cygnus.com>
+
+ * 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 <devans@canuck.cygnus.com>
+
+ * 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 <devans@seba.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <devans@seba.cygnus.com>
+
+ * 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 <devans@seba.cygnus.com>
+
+ * 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 <marka@cygnus.com>
+
+ * gennltvals.def (mn10200): Add entry.
+ * nltvals.def: Regenerate with MN10200 additions.
+
+Wed Jun 17 13:18:28 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * 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 <devans@fallis.cygnus.com>
+
+ * 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 <devans@seba.cygnus.com>
+
+ * 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 <devans@seba.cygnus.com>
+
+ * 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 <devans@seba.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * hw-base.h (set_*): Move set method macros from here.
+ * hw-device.h: To here.
+
+Mon May 25 18:21:38 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * sim-hw.c: Include ctype.h.
+ (do_hw_poll_read): Do not assume EAGAIN.
+
+Wed May 20 04:37:57 1998 Doug Evans <devans@seba.cygnus.com>
+
+ * 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 <devans@seba.cygnus.com>
+
+ * cgen-ops.h (ADDCFSI): Fix typo.
+
+Sat May 16 12:44:52 1998 Doug Evans <devans@seba.cygnus.com>
+
+ * 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 <devans@seba.cygnus.com>
+
+ * 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 <janczyn@cygnus.com>
+
+ * Make-common.in (install-common): Run ranlib on installed copy of
+ libsim.a.
+
+Fri May 15 15:03:00 1998 Joyce Janczyn <janczyn@cygnus.com>
+
+ * Make-common.in (install-common): Rename and install libsim.a.
+
+Tue May 12 15:23:57 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * sim-io.c (unistd.h): Include.
+
+Wed May 6 16:04:18 1998 Doug Evans <devans@seba.cygnus.com>
+
+ * 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 <errno.h>.
+
+Wed May 6 12:39:15 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <noer@cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * sim-types.h (cell_word): New type.
+ (natural_cell): Delete type.
+
+Sun Apr 26 15:31:55 1998 Tom Tromey <tromey@creche>
+
+ * configure: Regenerated to track ../common/aclocal.m4 changes.
+ * config.in: Ditto.
+
+Sun Apr 26 15:25:07 1998 Tom Tromey <tromey@cygnus.com>
+
+ * acconfig.h (NEED_DECLARATION_PRINTF): Removed.
+
+Fri Apr 24 14:16:40 1998 Tom Tromey <tromey@creche>
+
+ * configure: Regenerated to track ../common/aclocal.m4 changes.
+ * config.in: Ditto.
+
+Fri Apr 24 11:38:08 1998 Tom Tromey <tromey@cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * sim-config.h: Discard leading _ from macros.
+ * sim-types.h: Ditto.
+
+Wed Apr 22 14:14:19 1998 Michael Meissner <meissner@cygnus.com>
+
+ * 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 <devans@canuck.cygnus.com>
+
+ * cgen-types.h (GETHIDI,MAKEDI): Tweak.
+
+ * cgen-ops.h (ADDCFSI): Fix.
+ (SUBCFSI): Tweak.
+
+Tue Apr 21 13:18:41 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * sim-types.h (signed_address, unsigned_address): Define.
+
+Mon Apr 20 21:47:54 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * sim-bits.h (EXTEND4): Define.
+ (EXTEND4, EXTEND15, EXTEND11): Ditto.
+
+Tue Apr 14 16:31:35 1998 John Metzler <jmetzler@cygnus.com>
+
+ * 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 <devans@canuck.cygnus.com>
+
+ * Make-common.in (RUNTESTFLAGS): Define.
+ (check): Pass RUNTESTFLAGS to recursive make.
+
+Tue Apr 14 15:09:19 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * sim-info.c (sim_info): Be verbose when either VERBOSE or
+ STATE_VERBOSE_P.
+
+Sat Apr 4 23:24:17 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * aclocal.m4 (sim-inline): By default, disable sim-inline when
+ cross compiling.
+
+Sat Apr 4 20:36:25 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * run.c (main): Handle all alternatives of enum sim_stop.
+ (main): Delete unused `asection *s'.
+
+Fri Mar 27 16:15:52 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <grossman@bhuna.cygnus.co.uk>
+
+ * aclocal.m4 (sim_hw_obj): Fix sed expression to generate
+ properly formatted lists.
+
+Thu Mar 26 10:37:22 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <iancarm@cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * configure: Regenerated to track ../common/aclocal.m4 changes.
+
+Mon Mar 23 10:25:08 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * 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 <grossman@bhuna.cygnus.co.uk>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * sim-options.h: Document additional CPU arg to OPTION_HANDLER.
+
+Wed Mar 18 14:13:02 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <devans@seba.cygnus.com>
+
+ * 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 <fnf@cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <devans@seba.cygnus.com>
+
+ * 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 <wilson@cygnus.com>
+
+ * sim-fpu.c (NR_GUARDS64): Change NR_PAD32 to NR_PAD64.
+
+Tue Mar 3 10:53:05 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * 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 <devans@seba.cygnus.com>
+
+ * Make-common.in (TAGS): Make smarter.
+ * Makefile.in (TAGS): Ditto.
+
+Fri Feb 27 19:09:57 1998 Doug Evans <devans@canuck.cygnus.com>
+
+ * sim-module.c (*): Fix typos in assertion tests.
+
+Sat Feb 28 13:54:10 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <devans@canuck.cygnus.com>
+
+ * 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 <devans@canuck.cygnus.com>
+
+ * Make-common.in (check): Run `make check' in testsuite dir.
+
+Wed Feb 25 14:40:24 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * 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 <devans@seba.cygnus.com>
+
+ * 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 <marka@cygnus.com>
+
+ * nltvals.def: Regenerate with MN10300 additions.
+
+Tue Feb 24 13:18:42 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * 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 <devans@canuck.cygnus.com>
+
+ * 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 <meissner@cygnus.com>
+
+ * syscall.c (cb_syscall): Handle short reads, and EOF.
+
+Tue Feb 24 00:29:57 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * sim-fpu.c (sim_fpu_cmp): New function.
+
+Wed Feb 18 16:29:21 1998 Doug Evans <devans@canuck.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * sim-basics.h: Declare struct _sim_fpu.
+
+Tue Feb 17 16:27:46 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * 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 <devans@seba.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * sim-load.c (sim_load_file): Print LMA/VMA according to value
+ used.
+
+Tue Feb 10 14:56:23 1998 Ian Carmichael <iancarm@cygnus.com>
+
+ * 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 <devans@canuck.cygnus.com>
+
+ * 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 <devans@seba.cygnus.com>
+
+ * cgen-sim.h (EX_FN_NAME): _exc_ -> _ex_.
+ (SEM_INSN): New macro.
+
+Tue Feb 3 16:31:56 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * sim-run.c (sim_engine_run): Assume IMEM is 32 bit.
+
+Sun Feb 1 16:47:51 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * configure: Regenerated to track ../common/aclocal.m4 changes.
+
+Sun Feb 1 16:16:57 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * sim-profile.c (profile_print): Only print CPU <N> if other
+ output is going to appear.
+
+Sat Jan 31 18:15:41 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * configure: Regenerated to track ../common/aclocal.m4 changes.
+
+Sat Jan 31 18:03:55 1998 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <devans@canuck.cygnus.com>
+
+ * cgen.sh: Portably read parms past $9.
+
+Fri Jan 23 14:20:54 1998 Doug Evans <devans@seba.cygnus.com>
+
+ * 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 <meissner@cygnus.com>
+
+ * 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 <devans@seba>
+
+ * configure: Regenerated to track ../common/aclocal.m4 changes.
+ * aclocal.m4: Recognize --enable-maintainer-mode.
+
+Mon Jan 19 12:45:45 1998 Doug Evans <devans@seba.cygnus.com>
+
+ * 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 <nickc@cygnus.com>
+
+ * cgen-trace.c (trace_insn): Call CGEN_INSN_MNEMONIC() rather than
+ CGEN_INSN_SYNTAX().
+
+Mon Dec 15 23:17:11 1997 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * configure: Regenerated to track ../common/aclocal.m4 changes.
+ * config.in: Ditto.
+
+Mon Dec 15 23:16:03 1997 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * aclocal.m4 (AR): Check for sigaction.
+
+Thu Dec 4 09:21:05 1997 Doug Evans <devans@canuck.cygnus.com>
+
+ * 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 <devans@canuck.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <meissner@cygnus.com>
+
+ * 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 <meissner@cygnus.com>
+
+ * 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 <devans@canuck.cygnus.com>
+
+ * gennltvals.sh: Redo syscall support.
+ * nltvals.def: Regenerated.
+
+Wed Nov 26 16:49:38 1997 Michael Meissner <meissner@cygnus.com>
+
+ * syscall.c (cb_syscall): If writing to stdout or stderr, flush
+ the stream immediately.
+
+Wed Nov 26 12:32:11 1997 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * 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 <devans@canuck.cygnus.com>
+
+ * 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 <meissner@cygnus.com>
+
+ * sim-io.c (sim_io_syscalls): Disable lseek.
+
+Tue Nov 25 00:12:38 1997 Doug Evans <devans@seba.cygnus.com>
+
+ * 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", <sys/types.h>, <sys/stat.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 <meissner@cygnus.com>
+
+ * 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 <devans@seba.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * sim-signal.c (sim_signal_to_host): Return 0 for SIM_SIGNONE.
+
+Thu Nov 20 20:35:20 1997 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * 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 <devans@seba.cygnus.com>
+
+ * 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 <signal.h>.
+ (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 <meissner@cygnus.com>
+
+ * 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 <devans@canuck.cygnus.com>
+
+ * 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 <signal.h>.
+ * sim-basics.h: #include "sim-signal.h".
+ * sim-break.c: Don't include <signal.h>.
+ (sim_handle_breakpoint): Replace SIGTRAP with SIM_SIGTRAP.
+ * sim-core.c: Don't include <signal.h>.
+ (SIGBUS): Delete definition.
+ (sim_core_signal): Replace SIGSEGV,SIGBUS with SIM_SIGSEGV,SIM_SIGBUS.
+ * sim-engine.c: Don't include <signal.h>.
+ (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 <signal.h>.
+ (SIGTRAP): Delete definition.
+ (has_stepped): Replace SIGTRAP with SIM_SIGTRAP.
+ * sim-stop.c: Don't include <signal.h>.
+ (control_c_simulation): Replace SIGINT with SIM_SIGINT.
+ * sim-watch.c: Don't include <signal.h>.
+ (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 <devans@seba.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * sim-core.c (sim_core_signal): Print the address of the
+ instruction.
+
+Thu Nov 13 11:49:41 1997 Doug Evans <devans@seba.cygnus.com>
+
+ * 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 <flee@cygnus.com>
+
+ * 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 <devans@canuck.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * callback.c (os_poll_quit): Replace _WIN32 with _MSC_VER.
+
+Fri Nov 7 00:37:36 1997 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <devans@seba.cygnus.com>
+
+ * sim-core.h (sim_core_write_8): Define.
+
+Tue Oct 28 12:29:22 1997 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * 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 <devans@canuck.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <devans@canuck.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * configure: Regenerated to track ../common/aclocal.m4 changes.
+
+Thu Oct 2 19:43:52 1997 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * aclocal.m4 (sim-bitsize): Fix typo, WITH_TARGET_WORD_BITSIZE not
+ WITH_TARGET_BITSIZE.
+
+Thu Sep 25 23:20:20 1997 Felix Lee <flee@yin.cygnus.com>
+
+ * sim-profile.c (profile_print_core): label needs empty statement.
+
+Thu Sep 25 11:20:47 1997 Stu Grossman <grossman@babylon-5.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * configure: Regenerated to track ../common/aclocal.m4 changes.
+
+Wed Sep 24 17:23:31 1997 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * 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 <grossman@babylon-5.cygnus.com>
+
+ * 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 <flee@yin.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * Make-common.in (SIM_SCACHE, SIM_DEFAULT_MODEL): Assign
+ configured values.
+ (CONFIG_CFLAGS): Add same.
+
+Mon Sep 22 17:20:27 1997 Felix Lee <flee@cygnus.com>
+
+ * sim-types.h (SIGNED64): ##i64 when _MSC_VER, not _WIN32.
+ (SIGNED32): use ##i32.
+
+Tue Sep 23 11:04:38 1997 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * configure: Regenerated to track ../common/aclocal.m4 changes.
+
+Tue Sep 23 10:07:47 1997 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * configure: Regenerated to track ../common/aclocal.m4 changes.
+
+Mon Sep 22 11:45:00 1997 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * aclocal.m4 (sim_alignment): Simplify logic for selecting the
+ configured alignment.
+
+Fri Sep 19 17:45:25 1997 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * configure: Regenerated to track ../common/aclocal.m4 changes.
+
+Fri Sep 19 17:26:14 1997 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * sim-utils.c (sim_analyze_program): Set STATE_ARCHITECTURE from
+ BFD if known.
+
+Tue Sep 9 21:46:46 1997 Felix Lee <flee@cygnus.com>
+
+ * callback.c (os_write): divert stdout and stderr to their
+ respective hooks.
+
+Thu Sep 11 10:08:48 1997 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * sim-options.c (OPTION_ARCHITECTURE_INFO): New option.
+ (standard_option_handler): Handle --architecture-info.
+
+Tue Sep 9 21:46:46 1997 Felix Lee <flee@cygnus.com>
+
+ * 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 <dje@canuck.cygnus.com>
+
+ * nltvals.def: Regenerate.
+
+Tue Sep 9 02:10:36 1997 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * sim-fpu.c (DP_FRACHIGH2): Define LL using SIGNED64.
+
+Mon Sep 8 12:22:20 1997 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <dje@seba.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * sim-core.c (sim_core_map_attach): Clarify memory overlap error
+ message.
+
+Tue Sep 2 14:57:06 1997 Doug Evans <dje@canuck.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <dje@canuck.cygnus.com>
+
+ * sim-options.c (standard_option_handler): Use xstrdup, not strdup.
+
+Thu Aug 28 12:09:15 1997 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * configure: Regenerated to track ../common/aclocal.m4 changes.
+ * config.in: Ditto.
+
+Wed Aug 27 18:11:30 1997 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * configure: Regenerated to track ../common/aclocal.m4 changes.
+ * config.in: Ditto.
+
+Mon Aug 25 12:11:06 1997 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * 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 <dje@canuck.cygnus.com>
+
+ * 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 <dje@canuck.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * nrun.c (main): Verify the structure returned before using it.
+
+Wed Jun 4 11:44:06 1997 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b2.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * sim-engine.h: Update below so that it is using an enumerated
+ type.
+
+Thu May 22 09:12:16 1997 Gavin Koch <gavin@cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b2.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * sim-fpu.c (is_ufpu_number): Comment out - currently unused.
+
+Mon May 19 11:23:03 1997 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * callback.c (os_open): Type of arg flags is int.
+
+Fri May 16 22:26:43 1997 Michael Meissner <meissner@cygnus.com>
+
+ * 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 <manson@charmed.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b2.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <dje@canuck.cygnus.com>
+
+ * 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 <meissner@cygnus.com>
+
+ * 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 <meissner@cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b2.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * callback.c (default_callback): Missing initialisers.
+
+Thu May 1 10:40:47 1997 Doug Evans <dje@canuck.cygnus.com>
+
+ * 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 <dje@canuck.cygnus.com>
+
+ * 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 <meissner@cygnus.com>
+
+ * 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 <dje@canuck.cygnus.com>
+
+ * 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 <dje@canuck.cygnus.com>
+
+ * run.c: Undo last exec_bfd patch.
+ (main): Only pass -E ifdef SIM_HAVE_BIENDIAN.
+
+Wed Apr 23 17:54:27 1997 Mike Meissner <meissner@cygnus.com>
+
+ * run.c (exec_bfd): Add back in.
+ (main): Set exec_bfd.
+
+Tue Apr 22 14:43:46 1997 Doug Evans <dje@canuck.cygnus.com>
+
+ * sim-load.c (sim_load_file): #include <stdio.h> for NULL.
+
+Wed Apr 23 02:55:54 1997 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * 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 <dje@canuck.cygnus.com>
+
+ * sim-options.c (standard_options): Add --endian.
+ (standard_option_handler): Likewise.
+
+ * nrun.c: #include <signal.h>.
+ (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 <cagney@b1.cygnus.com>
+
+ * 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 <dje@canuck.cygnus.com>
+
+ * 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 <endian> 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 <ian@cygnus.com>
+
+ * 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 <cagney@b1.cygnus.com>
+
+ * sim-assert.h (SIM_ASSERT, ASSERT): Allow these macros to
+ be overriden.
+
+Wed Apr 9 16:06:44 1997 Andrew Cagney <cagney@kremvax.cygnus.com>
+
+ * sim-basics.h: Only bring in config.h and tconfig.h if
+ HAVE_CONFIG_H.
+
+Mon Apr 7 11:39:45 1997 Andrew Cagney <cagney@kremvax.cygnus.com>
+
+ * 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 <ian@cygnus.com>
+
+ * Makefile.in (INSTALL): Change install.sh to install-sh.
+
+Mon Apr 7 10:46:38 1997 Doug Evans <dje@canuck.cygnus.com>
+
+ * sim-base.h (sim_state_base): Move `magic' to end of struct.
+
+Mon Apr 7 15:53:21 1997 Andrew Cagney <cagney@kremvax.cygnus.com>
+
+ * run.c (main): Check that a program to run was specified.
+
+Mon Apr 7 15:45:02 1997 Andrew Cagney <cagney@kremvax.cygnus.com>
+
+ * 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 <dje@canuck.cygnus.com>
+
+ * 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 <cagney@kremvax.cygnus.com>
+
+ * configure: Regenerated to track ../common/aclocal.m4 changes.
+
+Wed Apr 2 11:08:11 1997 Andrew Cagney <cagney@kremvax.cygnus.com>
+
+ * 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 <meissner@cygnus.com>
+
+ * 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 <cagney@kremvax.cygnus.com>
+
+ * 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 <cagney@kremvax.cygnus.com>
+
+ * 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 <cagney@kremvax.cygnus.com>
+
+ * 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 <cagney@kremvax.cygnus.com>
+
+ * sim-alu.h: Include sim-xcat.h.
+
+Tue Mar 18 13:58:18 1997 Andrew Cagney <cagney@kremvax.cygnus.com>
+
+ * 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 <cagney@kremvax.cygnus.com>
+
+ * sim-bits.h (LSMASK): New macro. Create mask of LS bits.
+
+Mon Mar 17 18:10:05 1997 Andrew Cagney <cagney@kremvax.cygnus.com>
+
+ * 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 <cagney@kremvax.cygnus.com>
+
+ * sim-events.h: Remove defunct reference to callback struct.
+
+Mon Mar 17 15:10:07 1997 Andrew Cagney <cagney@kremvax.cygnus.com>
+
+ * configure: Re-generate.
+
+Mon Mar 17 15:04:47 1997 Andrew Cagney <cagney@kremvax.cygnus.com>
+
+ * Make-common.in (CSEARCH): Do not include the gdb directory in
+ the search path.
+
+Mon Mar 17 13:16:26 1997 Andrew Cagney <cagney@kremvax.cygnus.com>
+
+ * 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 <cagney@kremvax.cygnus.com>
+
+ * 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 <dje@canuck.cygnus.com>
+
+ * 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 <meissner@cygnus.com>
+
+ * callback.c (os_printf_filtered): Do not call exit(1) or print a
+ final newline.
+
+Thu Mar 6 15:50:28 1997 Andrew Cagney <cagney@kremvax.cygnus.com>
+
+ * 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 <cagney@kremvax.cygnus.com>
+
+ * 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 <cagney@kremvax.cygnus.com>
+
+ * 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 <cagney@kremvax.cygnus.com>
+
+ * 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 <cagney@kremvax.cygnus.com>
+
+ * 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 <cagney@kremvax.cygnus.com>
+
+ * 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 <cagney@kremvax.cygnus.com>
+
+ * 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 <cagney@critters.cygnus.com>
+
+ * 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 <cagney@critters.cygnus.com>
+
+ * 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 <cagney@critters.cygnus.com>
+
+ * 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 <meissner@tiktok.cygnus.com>
+
+ * 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 <dje@canuck.cygnus.com>
+
+ * 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 <dje@canuck.cygnus.com>
+
+ * 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 <ian@cygnus.com>
+
+ * 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 <wilson@cygnus.com>
+
+ * run.c (main): Set target_byte_order before call to sim_open.
+
+Sun Dec 8 18:22:06 1996 Doug Evans <dje@canuck.cygnus.com>
+
+ * callback.c: #include <stdlib.h>
+ (os_error): New function.
+ (default_callback): Add os_error.
+
+Mon Nov 25 19:44:35 1996 Doug Evans <dje@canuck.cygnus.com>
+
+ * 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 <dje@canuck.cygnus.com>
+
+ * 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 <dawn@cygnus.com>
+
+ * 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 <meissner@tiktok.cygnus.com>
+
+ * run.c (main): Print out if the program raised a signal.
+
+Wed Sep 18 09:52:14 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * 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 <jsmith@cygnus.co.uk>
+
+ * run.c (main): Explicitly cast malloc() parameter.
+
+Thu Sep 12 11:27:21 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * 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 <ian@cygnus.com>
+
+ * run.c (main): Use new bfd_big_endian macro.
+
+Wed Nov 8 15:49:49 1995 James G. Smith <jsmith@pasanda.cygnus.co.uk>
+
+ * 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 <wilson@chestnut.cygnus.com>
+
+ * run.c (main): Always return sigrc at end.
+
+Tue Oct 10 12:03:13 1995 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * 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 <sac@slash.cygnus.com>
+
+ * 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 0000000..71b4f69
--- /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 0000000..dd7c5e0
--- /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 0000000..f9b87a1
--- /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 0000000..e3b595a
--- /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' <Make-common.sim >Makesim1.tmp
+ sed -n -e '/^## COMMON_POST_/,/^## End COMMON_POST_/ p' <Make-common.sim >Makesim2.tmp
+ sed -e '/^## COMMON_PRE_/ r Makesim1.tmp' \
+ -e '/^## COMMON_POST_/ r Makesim2.tmp' \
+ <Makefile.sim >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 <drepper@cygnus.com>, 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 <libintl.h>], [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 <locale.h> in the installed <libintl.h> 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 <locale.h>"
+ else
+ INCLUDE_LOCALE_H="\
+/* The system does not provide the header <locale.h>. 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 <drepper@cygnus.com>, 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 <locale.h>.
+# Ulrich Drepper <drepper@cygnus.com>, 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 <locale.h>], [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 0000000..e8a28c4
--- /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 <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#endif
+#include <errno.h>
+#include <fcntl.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "callback.h"
+#include "targ-vals.h"
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#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 0000000..b212100
--- /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 0000000..d3c9a8a
--- /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 0000000..9421332
--- /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 0000000..c91ccb3
--- /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<mode>: 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<mode>: 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 0000000..1ec0e6c
--- /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 0000000..07ee191
--- /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 0000000..c5ea075
--- /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 <stdlib.h>
+#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 0000000..7ca4e65
--- /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 0000000..748015f
--- /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 0000000..9b7d1fa
--- /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 <errno.h>
+#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 0000000..5e796fb
--- /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 0000000..e57e601
--- /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 0000000..2faff5c
--- /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 0000000..4df9560
--- /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 <alloca.h> 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 <sys/types.h> 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 <sys/types.h> 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 <argz.h> header file. */
+#undef HAVE_ARGZ_H
+
+/* Define if you have the <dlfcn.h> header file. */
+#undef HAVE_DLFCN_H
+
+/* Define if you have the <errno.h> header file. */
+#undef HAVE_ERRNO_H
+
+/* Define if you have the <fcntl.h> header file. */
+#undef HAVE_FCNTL_H
+
+/* Define if you have the <fpu_control.h> header file. */
+#undef HAVE_FPU_CONTROL_H
+
+/* Define if you have the <limits.h> header file. */
+#undef HAVE_LIMITS_H
+
+/* Define if you have the <locale.h> header file. */
+#undef HAVE_LOCALE_H
+
+/* Define if you have the <malloc.h> header file. */
+#undef HAVE_MALLOC_H
+
+/* Define if you have the <nl_types.h> header file. */
+#undef HAVE_NL_TYPES_H
+
+/* Define if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define if you have the <sys/param.h> header file. */
+#undef HAVE_SYS_PARAM_H
+
+/* Define if you have the <sys/resource.h> header file. */
+#undef HAVE_SYS_RESOURCE_H
+
+/* Define if you have the <sys/time.h> header file. */
+#undef HAVE_SYS_TIME_H
+
+/* Define if you have the <sys/times.h> header file. */
+#undef HAVE_SYS_TIMES_H
+
+/* Define if you have the <time.h> header file. */
+#undef HAVE_TIME_H
+
+/* Define if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define if you have the <values.h> header file. */
+#undef HAVE_VALUES_H
diff --git a/sim/common/configure b/sim/common/configure
new file mode 100755
index 0000000..4dc7670
--- /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 <drepper@cygnus.com>, 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 <drepper@cygnus.com>, 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 <locale.h>.
+# Ulrich Drepper <drepper@cygnus.com>, 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 <<EOF
+#line 692 "configure"
+#include "confdefs.h"
+#include <assert.h>
+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 <<EOF
+#line 709 "configure"
+#include "confdefs.h"
+#include <assert.h>
+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 <<EOF
+#line 726 "configure"
+#include "confdefs.h"
+#include <assert.h>
+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 <<EOF
+#line 810 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+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
+#line 835 "configure"
+#include "confdefs.h"
+#include <string.h>
+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
+#line 853 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+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 <<EOF
+#line 874 "configure"
+#include "confdefs.h"
+#include <ctype.h>
+#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 <<EOF
+#line 914 "configure"
+#include "confdefs.h"
+
+int main() {
+
+/* Ultrix mips cc rejects this. */
+typedef int charset[2]; const charset x;
+/* SunOS 4.1.1 cc rejects this. */
+char const *const *ccp;
+char **p;
+/* NEC SVR4.0.2 mips cc rejects this. */
+struct point {int x, y;};
+static struct point const zero = {0,0};
+/* AIX XL C 1.02.0.0 rejects this.
+ It does not let you subtract one const X* pointer from another in an arm
+ of an if-expression whose if-part is not a constant expression */
+const char *g = "string";
+ccp = &g + (g ? g-g : 0);
+/* HPUX 7.0 cc rejects these. */
+++ccp;
+p = (char**) ccp;
+ccp = (char const *const *) p;
+{ /* SCO 3.2v4 cc rejects this. */
+ char *t;
+ char const *s = 0 ? (char *) 0 : (char const *) 0;
+
+ *t++ = 0;
+}
+{ /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */
+ int x[] = {25, 17};
+ const int *foo = &x[0];
+ ++foo;
+}
+{ /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
+ typedef const int *iptr;
+ iptr p = 0;
+ ++p;
+}
+{ /* AIX XL C 1.02.0.0 rejects this saying
+ "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
+ struct s { int j; const int *ap[3]; };
+ struct s *b; b->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 <<EOF
+#line 991 "configure"
+#include "confdefs.h"
+
+int main() {
+} $ac_kw foo() {
+; return 0; }
+EOF
+if { (eval echo configure:998: \"$ac_compile\") 1>&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 <<EOF
+#define inline $ac_cv_c_inline
+EOF
+ ;;
+esac
+
+echo $ac_n "checking for off_t""... $ac_c" 1>&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 <<EOF
+#line 1029 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#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 <<EOF
+#line 1062 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#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 <<EOF
+#line 1097 "configure"
+#include "confdefs.h"
+#include <alloca.h>
+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 <<EOF
+#line 1130 "configure"
+#include "confdefs.h"
+
+#ifdef __GNUC__
+# define alloca __builtin_alloca
+#else
+# ifdef _MSC_VER
+# include <malloc.h>
+# define alloca _alloca
+# else
+# if HAVE_ALLOCA_H
+# include <alloca.h>
+# 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 <<EOF
+#line 1195 "configure"
+#include "confdefs.h"
+#if defined(CRAY) && ! defined(CRAY2)
+webecray
+#else
+wenotbecray
+#endif
+
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&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 <<EOF
+#line 1225 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* 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 <<EOF
+#define CRAY_STACKSEG_END $ac_func
+EOF
+
+ break
+else
+ echo "$ac_t""no" 1>&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 <<EOF
+#line 1283 "configure"
+#include "confdefs.h"
+find_stack_direction ()
+{
+ static char *addr = 0;
+ auto char dummy;
+ if (addr == 0)
+ {
+ addr = &dummy;
+ return find_stack_direction ();
+ }
+ else
+ return (&dummy > 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 <<EOF
+#define STACK_DIRECTION $ac_cv_c_stack_direction
+EOF
+
+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: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
+#line 1332 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+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 <<EOF
+#define $ac_tr_hdr 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&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 <<EOF
+#line 1371 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* 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 <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&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 <<EOF
+#line 1427 "configure"
+#include "confdefs.h"
+
+/* Thanks to Mike Haertel and Jim Avera for this test.
+ Here is a matrix of mmap possibilities:
+ mmap private not fixed
+ mmap private fixed at somewhere currently unmapped
+ mmap private fixed at somewhere already mapped
+ mmap shared not fixed
+ mmap shared fixed at somewhere currently unmapped
+ mmap shared fixed at somewhere already mapped
+ For private mappings, we should verify that changes cannot be read()
+ back from the file, nor mmap's back from the file at a different
+ address. (There have been systems where private was not correctly
+ implemented like the infamous i386 svr4.0, and systems where the
+ VM page cache was not coherent with the filesystem buffer cache
+ like early versions of FreeBSD and possibly contemporary NetBSD.)
+ For shared mappings, we should conversely verify that changes get
+ propogated back to all the places they're supposed to be.
+
+ Grep wants private fixed already mapped.
+ The main things grep needs to know about mmap are:
+ * does it exist and is it safe to write into the mmap'd area
+ * how to use it (BSD variants) */
+#include <sys/types.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+
+/* This mess was copied from the GNU getpagesize.h. */
+#ifndef HAVE_GETPAGESIZE
+# ifdef HAVE_UNISTD_H
+# include <unistd.h>
+# 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 <sys/param.h>
+# 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 <<EOF
+#line 1843 "configure"
+#include "confdefs.h"
+main(){return(0);}
+EOF
+if { (eval echo configure:1847: \"$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*
+
+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 <<EOF
+#ifdef __GNUC__
+ yes;
+#endif
+EOF
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1881: \"$ac_try\") 1>&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
+#line 2048 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+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 <<EOF
+#define $ac_tr_hdr 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&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 <<EOF
+#line 2088 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* 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 <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&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 <<EOF
+#line 2145 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* 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 <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&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 <<EOF
+#line 2207 "configure"
+#include "confdefs.h"
+#include <locale.h>
+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
+#line 2279 "configure"
+#include "confdefs.h"
+#include <libintl.h>
+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 <<EOF
+#line 2306 "configure"
+#include "confdefs.h"
+#include <libintl.h>
+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 <<EOF
+#line 2337 "configure"
+#include "confdefs.h"
+/* 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 bindtextdomain();
+
+int main() {
+bindtextdomain()
+; return 0; }
+EOF
+if { (eval echo configure:2348: \"$ac_link\") 1>&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 <<EOF
+#line 2369 "configure"
+#include "confdefs.h"
+
+int main() {
+return (int) gettext ("")
+; return 0; }
+EOF
+if { (eval echo configure:2376: \"$ac_link\") 1>&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 <<EOF
+#line 2443 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* 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 <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&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 <<EOF
+#line 2560 "configure"
+#include "confdefs.h"
+
+int main() {
+extern int _nl_msg_cat_cntr;
+ return _nl_msg_cat_cntr
+; return 0; }
+EOF
+if { (eval echo configure:2568: \"$ac_link\") 1>&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 <locale.h>"
+ else
+ INCLUDE_LOCALE_H="\
+/* The system does not provide the header <locale.h>. 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
+#line 2792 "configure"
+#include "confdefs.h"
+#include <linux/version.h>
+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
+#line 2871 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+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 <<EOF
+#define $ac_tr_hdr 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&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
+#line 2911 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+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 <<EOF
+#define $ac_tr_hdr 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&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
+#line 2951 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+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 <<EOF
+#define $ac_tr_hdr 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&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
+#line 2991 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+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 <<EOF
+#define $ac_tr_hdr 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&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 <<EOF
+#line 3030 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* 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 <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&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 <<EOF
+#line 3088 "configure"
+#include "confdefs.h"
+/* 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 bind();
+
+int main() {
+bind()
+; return 0; }
+EOF
+if { (eval echo configure:3099: \"$ac_link\") 1>&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 <<EOF
+#define $ac_tr_lib 1
+EOF
+
+ LIBS="-lsocket $LIBS"
+
+else
+ echo "$ac_t""no" 1>&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 <<EOF
+#line 3135 "configure"
+#include "confdefs.h"
+/* 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 gethostbyname();
+
+int main() {
+gethostbyname()
+; return 0; }
+EOF
+if { (eval echo configure:3146: \"$ac_link\") 1>&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 <<EOF
+#define $ac_tr_lib 1
+EOF
+
+ LIBS="-lnsl $LIBS"
+
+else
+ echo "$ac_t""no" 1>&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 <<EOF
+#line 3327 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <signal.h>
+#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 <<EOF
+#define RETSIGTYPE $ac_cv_type_signal
+EOF
+
+
+
+echo $ac_n "checking for executable suffix""... $ac_c" 1>&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
+#line 3446 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+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 <<EOF
+#define $ac_tr_hdr 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&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 <<EOF
+#! /bin/sh
+# Generated automatically by configure.
+# Run this file to recreate the current configuration.
+# This directory was configured as follows,
+# on host `(hostname || uname -n) 2>/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 <<EOF
+
+# Protect against being on the right side of a sed subst in config.status.
+sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
+ s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > 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 <<EOF
+
+CONFIG_FILES=\${CONFIG_FILES-"Makefile"}
+EOF
+cat >> $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 <<EOF
+ CONFIG_HEADERS="cconfig.h:config.in"
+EOF
+cat >> $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 <<CEOF' >> $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 <<EOF
+
+EOF
+cat >> $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 0000000..b8ea538
--- /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 0000000..1bf4f68
--- /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 <cagney@highland.com.au>
+
+ 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 0000000..a235531
--- /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 <cagney@highland.com.au>
+
+ 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 <string.h>
+#else
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#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 <<output>>
+ 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 <<output>> 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:
+
+ <<glue>>: In addition to driving its output interrupt port with any
+ value written to an interrupt input port is stored in the
+ corresponding <<output>> register. Such input interrupts, however,
+ are not propogated to an output interrupt port.
+
+ <<glue-and>>: The bit-wise AND of the interrupt inputs is computed
+ and then both stored in <<output>> register zero and propogated to
+ output interrupt output port zero.
+
+
+ PROPERTIES
+
+
+ reg = <address> <size> (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 = <int-number> <range> (optional)
+
+ If present, this specifies the number of valid interrupt inputs (up
+ to the maximum of 2048). By default, <<int-number>> is zero and
+ range is determined by the <<reg>> 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 <<C>> 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 0000000..421bde7
--- /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 <cagney@highland.com.au>
+
+ 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 <string.h>
+#else
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#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 = <address> <size> (required)
+
+ Specify the address (within the parent bus) that this device is to
+ be located.
+
+ poll? = <boolean>
+
+ 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 0000000..c95288c
--- /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 <string.h>
+#else
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#endif
+#include <signal.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <sys/socket.h>
+
+#ifndef __CYGWIN32__
+#include <netinet/tcp.h>
+#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 0000000..ef0a7a9
--- /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 0000000..ddda344
--- /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 0000000..865fe72
--- /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 <cpu-family>
+#
+# Specify the cpu family name.
+#
+# -infile <input-file>
+#
+# 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 0000000..63ff662
--- /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 0000000..e4f5d0d
--- /dev/null
+++ b/sim/common/gentmap.c
@@ -0,0 +1,125 @@
+/* Generate targ-vals.h and targ-map.c. */
+
+#include <stdio.h>
+
+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 <errno.h>\n");
+ printf ("#include <fcntl.h>\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 0000000..6dd7315
--- /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.list | uniq >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 0000000..e64ae82
--- /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 <stdlib.h>
+#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 0000000..48b03f2
--- /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 0000000..a13ac64
--- /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 <cagney@highland.com.au>
+
+ 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 <string.h>
+#else
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#endif
+
+#if HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#include <ctype.h>
+
+#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);
+ reg_entry++)
+ {
+ unsigned_word attach_address;
+ int attach_space;
+ unsigned attach_size;
+ if (!hw_unit_address_to_attach_address (hw_parent (hw),
+ &reg.address,
+ &attach_space,
+ &attach_address,
+ hw))
+ continue;
+ if (!hw_unit_size_to_attach_size (hw_parent (hw),
+ &reg.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 0000000..d6452d1
--- /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 <cagney@highland.com.au>
+
+ 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 0000000..c7f50e3
--- /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 <cagney@highland.com.au>
+
+ 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 <stdlib.h>
+#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 0000000..2cbdc5a
--- /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 <cagney@highland.com.au>
+
+ 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 <<hw_ioctl()>>.
+
+ */
+
+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 <<hw_abort()>> 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 0000000..31c5a40
--- /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/<cpu> directory*/
+
+#if defined (MAIN)
+#include "sim-main.h"
+#include <string.h>
+#include <stdio.h>
+
+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 0000000..a9b6f8b
--- /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 0000000..9400ca8
--- /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 <cagney@highland.com.au>
+
+ 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 0000000..087c9d02
--- /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 <cagney@highland.com.au>
+
+ 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 0000000..613f819
--- /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 <cagney@highland.com.au>
+
+ 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 0000000..6d27b11
--- /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 <cagney@highland.com.au>
+
+ 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 0000000..3c086c1
--- /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 0000000..b7dc985
--- /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 <stdlib.h>
+#endif
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#endif
+
+#include <ctype.h>
+
+#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 0000000..566895a
--- /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 0000000..a1e9291
--- /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 <cagney@highland.com.au>
+
+ 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 <string.h>
+#else
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#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 = &regs[i];
+ /* copy the address */
+ cell = unit_address_to_cells (&reg->address, cell,
+ hw_unit_nr_address_cells (hw_parent (me)));
+ /* copy the size */
+ cell = unit_address_to_cells (&reg->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, &reg->address,
+ hw_unit_nr_address_cells (hw_parent (me)));
+
+ /* copy the size out - converting as we go */
+ cells = cells_to_unit_address (cells, &reg->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 0000000..511fba3
--- /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 <cagney@highland.com.au>
+
+ 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_<type>_property(struct hw *, const char *, <type>)
+ void hw_add_*_array_property(struct hw *, const char *, const <type>*, int)
+ void hw_set_*_property(struct hw *, const char *, <type>)
+ void hw_set_*_array_property(struct hw *, const char *, const <type>*, int)
+ <type> hw_find_*_property(struct hw *, const char *)
+ int hw_find_*_array_property(struct hw *, const char *, int, <type>*)
+
+ */
+
+
+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 0000000..1a55835
--- /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 <cagney@highland.com.au>
+
+ 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 <stdlib.h>
+#endif
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#endif
+
+#include <ctype.h>
+
+/* 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;
+}
+
+
+/* <non-white-space> */
+
+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: <address> ::= <token> ; 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: <size> ::= <number> { "," <number> } ; */
+
+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 <size> %s", chp);
+ nr += 1;
+ if (next[0] != ',')
+ break;
+ if (nr == size->nr_cells)
+ hw_abort (current, "Too many values in <size> %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: <reg> ::= { <address> <size> } ; */
+
+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, &regs[reg_nr].address);
+ chp = parse_size (current, hw_parent(current),
+ chp, &regs[reg_nr].size);
+ }
+
+ /* create it */
+ hw_add_reg_array_property (current, property_name,
+ regs, nr_regs);
+
+ zfree (regs);
+}
+
+
+/* { <child-address> <parent-address> <child-size> }* */
+
+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);
+}
+
+
+/* <integer> ... */
+
+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);
+ }
+}
+
+
+/* <string> ... */
+
+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);
+}
+
+
+/* <path-to-ihandle-device> */
+
+#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);
+ reg_nr++) {
+ print_address (hw_parent (me), &reg.address, p);
+ print_size (me, &reg.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 0000000..bfa5681
--- /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 <cagney@highland.com.au>
+
+ 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
+ <<device_tree_traverse()>> 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 <<hw_tree_find_device()>> 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 0000000..b5e82fc
--- /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 0000000..42be33e
--- /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 <signal.h>
+#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 0000000..886e20b
--- /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 0000000..2a701bc
--- /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 <signal.h>
+#include <stdio.h>
+#ifdef __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#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 0000000..088bf20
--- /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 <stdio.h>
+
+#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 0000000..49d1018
--- /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 <cagney@highland.com.au>
+ 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<n> and SIGN_BIT<m> 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 0000000..d9955e6
--- /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 <stdlib.h>
+#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 0000000..10ba0f4
--- /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 0000000..0274084
--- /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 0000000..3fe01b4
--- /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 <target-dependant> 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 0000000..fc34b21
--- /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 <cagney@highland.com.au>
+ 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 <stdio.h> + <stdarg.h> will
+ bring potential conflicts out in the open */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <setjmp.h>
+
+#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 0000000..ecfb73b
--- /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 <cagney@highland.com.au>
+
+ 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 0000000..d111bcd
--- /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 <cagney@highland.com.au>
+ 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 - <MACRO>32 which
+ operates in 32bit quantity (bits are numbered 0..31); <MACRO>64
+ which operates using 64bit quantites (and bits are numbered 0..63);
+ and <MACRO> 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 <MACRO> (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 0000000..3b89560
--- /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 <stdio.h>
+
+#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 0000000..8b0338f
--- /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 0000000..10a19aa
--- /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 <cagney@highland.com.au>
+
+ 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*)(&current_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 0000000..9720712
--- /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 <cagney@highland.com.au>
+
+ 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 <machine/endian.h>
+# 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 <endian.h>
+# 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@<nr-cpu> */
+
+#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 0000000..36627a2
--- /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 <cagney@highland.com.au>
+
+ 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 0000000..7bf15a3
--- /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 <cagney@highland.com.au>
+
+ 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 0000000..0e6d52c
--- /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 0000000..069fead
--- /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 0000000..3682028
--- /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 <cagney@highland.com.au>
+
+ 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 0000000..d733c82
--- /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 <cagney@highland.com.au>
+ 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 0000000..9415f63
--- /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 <stdio.h>
+
+#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 0000000..41aa51f
--- /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 0000000..4b7d9b4
--- /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 <cagney@highland.com.au>
+
+ 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 <string.h>
+#else
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#endif
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#include <signal.h> /* 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 0000000..3bae3df
--- /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 <cagney@highland.com.au>
+
+ 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 0000000..abf746a
--- /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 <SIGN:1><BIASEDEXP:NR_EXPBITS><FRAC:NR_FRACBITS> for both
+ 32 and 64 bit numbers. This number is interpreted as:
+
+ Normalized (0 < BIASEDEXP && BIASEDEXP < EXPMAX):
+ (sign ? '-' : '+') 1.<FRAC> x 2 ^ (BIASEDEXP - EXPBIAS)
+
+ Denormalized (0 == BIASEDEXP && FRAC != 0):
+ (sign ? "-" : "+") 0.<FRAC> 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 - <IMPLICIT_1:1><FRACBITS:52><GUARDS:8><PAD:00>
+ 32 bit - <IMPLICIT_1:1><FRACBITS:23><GUARDS:7><PAD:30> */
+
+#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 0000000..05d53c2
--- /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 0000000..e4016f4
--- /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 0000000..9538302
--- /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 0000000..f438462
--- /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 <string.h>
+#else
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <ctype.h>
+#include <sys/errno.h>
+
+
+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 0000000..1bebd18
--- /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 0000000..0083227
--- /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 0000000..770c65e
--- /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 <cagney@highland.com.au>
+ 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 0000000..300658d
--- /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 <cagney@highland.com.au>
+ 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 <module>_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 0000000..f3d2f67
--- /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 <cagney@highland.com.au>
+ 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 <errno.h>
+#if HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#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 ("<nr-read=%d>\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 0000000..995b623
--- /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 <cagney@highland.com.au>
+
+ 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 0000000..22fb33b
--- /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 <stdio.h> /* for NULL */
+#ifdef ANSI_PROTOTYPES
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <time.h>
+
+#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 0000000..be52a66
--- /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 <string.h>
+#else
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#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> [ "%" <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)
+{
+ /* [ <space> ": " ] <addr> [ "@" <level> ] */
+ *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 0000000..287c576
--- /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 0000000..a126fb1
--- /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 0000000..6f7769a
--- /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 0000000..35eb32a
--- /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 0000000..cbba350
--- /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 0000000..83157ff
--- /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 <cagney@highland.com.au>
+ 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 0000000..46eca03
--- /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 <cagney@highland.com.au>
+
+ 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 0000000..c53e05a
--- /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 <cagney@highland.com.au>
+
+ 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 0000000..b49256b
--- /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 <string.h>
+#else
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <ctype.h>
+#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 --<cpuname>- 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 --<cpuname>- 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 ...<a-b-c>-d-e-f - continue search */
+ name ++; /* skip `-' */
+ argi ++;
+ continue;
+ }
+ else if (name [0] == '\0')
+ {
+ /* exact match ...<a-b-c-d-e-f> - 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 -<opt> ... 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 <cpuname>-<command>, point argv[0] at <command>. */
+ 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 0000000..78cad56
--- /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, "<<description>>", HANDLER},
+ { {NULL, no_argument, NULL, OPTION_VALUE},
+ 'e', NULL, "<<description>>", 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, "<<description>>", HANDLER},
+ { {"dp", no_argument, NULL, OPTION_DP},
+ '\0', NULL, NULL, HANDLER},
+
+ will list ``-d, --dc, --dp <<description>>'' */
+
+ 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, "<<description>>", HANDLER, "--set-REGNAME" },
+ { {"set-sp", no_argument, NULL, OPTION_SET_SP},
+ '\0', NULL, "", HANDLER, "" },
+
+ will list ``--set-REGNAME <<description>>". */
+
+ 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 0000000..5d075d1
--- /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 <stdlib.h>
+#endif
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#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 0000000..8f8d95f
--- /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-<foo> 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-<xxxx> 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 0000000..b540df3
--- /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 0000000..3f3dc41
--- /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 0000000..09b475e
--- /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 0000000..55f7290
--- /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 0000000..77709b1
--- /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 <signal.h>
+#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 0000000..272e17d
--- /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 0000000..cde9315
--- /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 0000000..0fa2313
--- /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 <string.h>
+#else
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#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 0000000..14d277e
--- /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-<xxxx> 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-<xxxx> 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{_<fmt><nr-inputs>} 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{_<type><nr-results>} */
+
+
+/* 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 0000000..babc598
--- /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 <cagney@highland.com.au>
+
+ 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 0000000..3adbae5
--- /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 <stdlib.h>
+#endif
+
+#ifdef HAVE_TIME_H
+#include <time.h>
+#endif
+
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h> /* needed by sys/resource.h */
+#endif
+
+#ifdef HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#endif
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#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 0000000..8e80e6a
--- /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 0000000..75c9ad1
--- /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 <ctype.h>
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#endif
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#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 0000000..ad920d3
--- /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 0000000..e0a3b88
--- /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 <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <errno.h>
+#include <fcntl.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#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 0000000..fd8b5be
--- /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 */