summaryrefslogtreecommitdiff
path: root/gnu
diff options
context:
space:
mode:
authorthorpej <thorpej@NetBSD.org>1998-02-01 08:01:23 +0000
committerthorpej <thorpej@NetBSD.org>1998-02-01 08:01:23 +0000
commite642dff4e09e204bfebc5fc55106e32c85954a80 (patch)
treed75ef6a46080a90c0bb09f3ca1b5c72189b28e44 /gnu
parent74ab5e80061a6cb89b7009711a1b263403edbaf0 (diff)
Import the psim-970703 (PowerPC Simulator) snapshot.
Diffstat (limited to 'gnu')
-rw-r--r--gnu/dist/sim/ppc/BUGS133
-rw-r--r--gnu/dist/sim/ppc/COPYING7
-rw-r--r--gnu/dist/sim/ppc/ChangeLog4029
-rw-r--r--gnu/dist/sim/ppc/ChangeLog.002168
-rw-r--r--gnu/dist/sim/ppc/Makefile.in353
-rw-r--r--gnu/dist/sim/ppc/README2
-rw-r--r--gnu/dist/sim/ppc/basics.h41
-rw-r--r--gnu/dist/sim/ppc/bits.c21
-rw-r--r--gnu/dist/sim/ppc/bits.h9
-rw-r--r--gnu/dist/sim/ppc/cap.c78
-rw-r--r--gnu/dist/sim/ppc/cap.h16
-rw-r--r--gnu/dist/sim/ppc/config.in212
-rw-r--r--gnu/dist/sim/ppc/configure2443
-rw-r--r--gnu/dist/sim/ppc/configure.in744
-rw-r--r--gnu/dist/sim/ppc/corefile-n.h4
-rw-r--r--gnu/dist/sim/ppc/corefile.c293
-rw-r--r--gnu/dist/sim/ppc/corefile.h154
-rw-r--r--gnu/dist/sim/ppc/cpu.c182
-rw-r--r--gnu/dist/sim/ppc/cpu.h91
-rw-r--r--gnu/dist/sim/ppc/dc-complex58
-rw-r--r--gnu/dist/sim/ppc/dc-simple25
-rw-r--r--gnu/dist/sim/ppc/dc-stupid58
-rw-r--r--gnu/dist/sim/ppc/dc-test.0124
-rw-r--r--gnu/dist/sim/ppc/dc-test.0224
-rw-r--r--gnu/dist/sim/ppc/debug.c34
-rw-r--r--gnu/dist/sim/ppc/debug.h111
-rw-r--r--gnu/dist/sim/ppc/device.c2333
-rw-r--r--gnu/dist/sim/ppc/device.h960
-rw-r--r--gnu/dist/sim/ppc/device_table.c2247
-rw-r--r--gnu/dist/sim/ppc/device_table.h203
-rw-r--r--gnu/dist/sim/ppc/dgen.c39
-rw-r--r--gnu/dist/sim/ppc/emul_bugapi.c340
-rw-r--r--gnu/dist/sim/ppc/emul_chirp.c1107
-rw-r--r--gnu/dist/sim/ppc/emul_chirp.h2
-rw-r--r--gnu/dist/sim/ppc/emul_generic.c147
-rw-r--r--gnu/dist/sim/ppc/emul_generic.h8
-rw-r--r--gnu/dist/sim/ppc/emul_netbsd.c258
-rw-r--r--gnu/dist/sim/ppc/emul_unix.c2809
-rw-r--r--gnu/dist/sim/ppc/emul_unix.h28
-rw-r--r--gnu/dist/sim/ppc/events.c239
-rw-r--r--gnu/dist/sim/ppc/events.h8
-rw-r--r--gnu/dist/sim/ppc/filter.c150
-rw-r--r--gnu/dist/sim/ppc/filter.h43
-rw-r--r--gnu/dist/sim/ppc/filter_filename.c8
-rw-r--r--gnu/dist/sim/ppc/filter_filename.h4
-rw-r--r--gnu/dist/sim/ppc/gen-icache.c675
-rw-r--r--gnu/dist/sim/ppc/gen-icache.h68
-rw-r--r--gnu/dist/sim/ppc/gen-idecode.c1545
-rw-r--r--gnu/dist/sim/ppc/gen-idecode.h40
-rw-r--r--gnu/dist/sim/ppc/gen-itable.c122
-rw-r--r--gnu/dist/sim/ppc/gen-itable.h28
-rw-r--r--gnu/dist/sim/ppc/gen-model.c393
-rw-r--r--gnu/dist/sim/ppc/gen-model.h30
-rw-r--r--gnu/dist/sim/ppc/gen-semantics.c250
-rw-r--r--gnu/dist/sim/ppc/gen-semantics.h81
-rw-r--r--gnu/dist/sim/ppc/gen-support.c132
-rw-r--r--gnu/dist/sim/ppc/gen-support.h29
-rw-r--r--gnu/dist/sim/ppc/hw_com.c559
-rw-r--r--gnu/dist/sim/ppc/hw_core.c143
-rw-r--r--gnu/dist/sim/ppc/hw_cpu.c167
-rw-r--r--gnu/dist/sim/ppc/hw_cpu.h34
-rw-r--r--gnu/dist/sim/ppc/hw_disk.c557
-rw-r--r--gnu/dist/sim/ppc/hw_eeprom.c839
-rw-r--r--gnu/dist/sim/ppc/hw_glue.c371
-rw-r--r--gnu/dist/sim/ppc/hw_htab.c683
-rw-r--r--gnu/dist/sim/ppc/hw_ide.c869
-rw-r--r--gnu/dist/sim/ppc/hw_init.c721
-rw-r--r--gnu/dist/sim/ppc/hw_iobus.c100
-rw-r--r--gnu/dist/sim/ppc/hw_memory.c538
-rw-r--r--gnu/dist/sim/ppc/hw_nvram.c261
-rw-r--r--gnu/dist/sim/ppc/hw_opic.c1827
-rw-r--r--gnu/dist/sim/ppc/hw_pal.c366
-rw-r--r--gnu/dist/sim/ppc/hw_phb.c1068
-rw-r--r--gnu/dist/sim/ppc/hw_phb.h40
-rw-r--r--gnu/dist/sim/ppc/hw_register.c131
-rw-r--r--gnu/dist/sim/ppc/hw_trace.c103
-rw-r--r--gnu/dist/sim/ppc/hw_vm.c275
-rw-r--r--gnu/dist/sim/ppc/idecode_expression.h63
-rw-r--r--gnu/dist/sim/ppc/idecode_fields.h3
-rw-r--r--gnu/dist/sim/ppc/igen.c3552
-rw-r--r--gnu/dist/sim/ppc/igen.h199
-rw-r--r--gnu/dist/sim/ppc/inline.c4
-rw-r--r--gnu/dist/sim/ppc/inline.h92
-rw-r--r--gnu/dist/sim/ppc/interrupts.c214
-rw-r--r--gnu/dist/sim/ppc/interrupts.h43
-rw-r--r--gnu/dist/sim/ppc/ld-cache.c115
-rw-r--r--gnu/dist/sim/ppc/ld-cache.h81
-rw-r--r--gnu/dist/sim/ppc/ld-decode.c155
-rw-r--r--gnu/dist/sim/ppc/ld-decode.h143
-rw-r--r--gnu/dist/sim/ppc/ld-insn.c925
-rw-r--r--gnu/dist/sim/ppc/ld-insn.h281
-rw-r--r--gnu/dist/sim/ppc/lf.c235
-rw-r--r--gnu/dist/sim/ppc/lf.h84
-rw-r--r--gnu/dist/sim/ppc/main.c198
-rw-r--r--gnu/dist/sim/ppc/misc.c141
-rw-r--r--gnu/dist/sim/ppc/misc.h46
-rw-r--r--gnu/dist/sim/ppc/mkinstalldirs36
-rw-r--r--gnu/dist/sim/ppc/mon.c127
-rw-r--r--gnu/dist/sim/ppc/mon.h5
-rw-r--r--gnu/dist/sim/ppc/options.c76
-rw-r--r--gnu/dist/sim/ppc/os_emul.c7
-rw-r--r--gnu/dist/sim/ppc/pk_disklabel.c401
-rw-r--r--gnu/dist/sim/ppc/ppc-cache-rules127
-rw-r--r--gnu/dist/sim/ppc/ppc-instructions756
-rw-r--r--gnu/dist/sim/ppc/psim.c687
-rw-r--r--gnu/dist/sim/ppc/psim.h42
-rw-r--r--gnu/dist/sim/ppc/psim.texinfo1105
-rw-r--r--gnu/dist/sim/ppc/registers.c15
-rw-r--r--gnu/dist/sim/ppc/registers.h8
-rw-r--r--gnu/dist/sim/ppc/sim-endian-n.h31
-rw-r--r--gnu/dist/sim/ppc/sim-endian.h141
-rw-r--r--gnu/dist/sim/ppc/sim_callbacks.h73
-rw-r--r--gnu/dist/sim/ppc/sim_calls.c147
-rw-r--r--gnu/dist/sim/ppc/std-config.h118
-rw-r--r--gnu/dist/sim/ppc/table.c8
-rw-r--r--gnu/dist/sim/ppc/table.h4
-rw-r--r--gnu/dist/sim/ppc/tree.c1256
-rw-r--r--gnu/dist/sim/ppc/tree.h139
-rw-r--r--gnu/dist/sim/ppc/vm.c102
-rw-r--r--gnu/dist/sim/ppc/vm.h19
-rw-r--r--gnu/dist/sim/ppc/vm_n.h22
-rw-r--r--gnu/dist/sim/ppc/words.h7
122 files changed, 35773 insertions, 11552 deletions
diff --git a/gnu/dist/sim/ppc/BUGS b/gnu/dist/sim/ppc/BUGS
index d88daa4a2f0..362b079e90c 100644
--- a/gnu/dist/sim/ppc/BUGS
+++ b/gnu/dist/sim/ppc/BUGS
@@ -1,34 +1,123 @@
- See the ChangeLog file looking for lines taged with the word FIXME.
+ChangeLog
- COREFILE.C: The implementation of corefile.c (defined by
- corefile.h) isn't the best. It is intended to be functionaly
- correct rather than fast. One option being considered
- is to add a data cache to reduce the overhead of the most
- common case of data read/writes.
+See the ChangeLog file looking for lines taged with the word FIXME.
- HTAB (page) code for OEA model untested. Some of the vm code
- instructions unimplemented.
- Lacks PowerOpen (a.k.a. XCOFF a.k.a. AIX) and NT startups. The
- PowerOpen worked until I added the ELF one.
+COREFILE.C:
- Missing VEA system calls.
+The implementation of corefile.c (defined by corefile.h) isn't the
+best. It is intended to be functionaly correct rather than fast. One
+option being considered is to add a data cache to reduce the overhead
+of the most common case of data read/writes.
- Missing or commented out instructions.
- 64bit target untested.
+VEA:
- 64bit host broken. For instance use of scanf "%x", &long long.
+Missing VEA system calls.
- Event code for pending events from within signal handlers not
- finished/tested.
+ppc-instructions:
- Better and more devices.
+Missing or commented out instructions.
- PORTABILITY (Notes taken from Michael Meissner): Heavy use of the ##
- operator - fix using the clasic X/**/Y hack; Use of the signed
- keyword. In particular, signed char has no analogue in classic C
- (though most implementations of classic C use signed chars); Use of
- long long which restricts the target compiler to be GCC.
+64bit:
+64bit target untested. 64bit host broken. For instance use of scanf
+"%x", &long long.
+
+
+
+hw_*.c:
+
+Better and more devices.
+
+PORTABILITY:
+
+(Notes taken from Michael Meissner): Heavy use of the ## operator -
+fix using the clasic X/**/Y hack; Use of the signed keyword. In
+particular, signed char has no analogue in classic C (though most
+implementations of classic C use signed chars); Use of long long which
+restricts the target compiler to be GCC.
+
+
+TRACING:
+
+debug.c: Macro's should be extended to include:
+
+ IS_*TRACE: True if tracing enabled
+ *TRACE_PREFIX: Outputs just the prefix line
+
+hw_trace.c: Flush, replace with a psim_set_tracing or some
+ such program.
+
+
+CIA/NIA:
+
+Replace with functions to return/increment the CIA?
+
+
+
+SMP & GDB:
+
+GDB doesn't understand SMP!
+
+
+
+
+OVERALL STRUCTURE:
+
+A new file pstruct.h is to be created that contains a single flat data
+structure containing:
+
+ pstruct {
+ events;
+ core;
+ processor[nr_cpus];
+ monitor;
+ devices;
+ trace;
+ }
+
+The CPU's structure, in turn would contain the VM sub structures.
+
+When SMP==0, everything would have PSTRUCT passed. In SMP mode,
+however, there are two choices: PSTRUCT + CPU_NR or PROCESSOR. I
+suspect the latter is better.
+
+It is believed that this would significantly improve performance (at
+the price of reduced control over object scope).
+
+
+
+
+IGEN:
+
+Igen at present can't do the following:
+
+ o duplication is an all or nothing afair.
+
+ It should be configurable according to
+ the instruction or the sub-table.
+
+
+ o Due to the naming, only a single generated
+ simulator can be included in a program.
+
+ IGEN should be able to generate multiple
+ engines that can all be included in a program
+
+ o handle alternate architectures.
+
+
+ o Igen should support the generation of a
+ disasembler and posibly an assembler.
+
+ I suggest that the table be extended to
+ include, for each instruction, additional
+ lines describing the extual format of the
+ instruction.
+
+ One possible format is:
+
+ "mtlr %RS":SPR.something
+ "mtspr %SPR, %RS"
diff --git a/gnu/dist/sim/ppc/COPYING b/gnu/dist/sim/ppc/COPYING
index a43ea2126fb..60549be514a 100644
--- a/gnu/dist/sim/ppc/COPYING
+++ b/gnu/dist/sim/ppc/COPYING
@@ -2,7 +2,7 @@
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
- 675 Mass Ave, Cambridge, MA 02139, USA
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
@@ -279,7 +279,7 @@ POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
- Appendix: How to Apply These Terms to Your New Programs
+ How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
@@ -305,7 +305,8 @@ the "copyright" line and a pointer to where the full notice is found.
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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
Also add information on how to contact you by electronic and paper mail.
diff --git a/gnu/dist/sim/ppc/ChangeLog b/gnu/dist/sim/ppc/ChangeLog
index a95acbcc047..c2adb7d28de 100644
--- a/gnu/dist/sim/ppc/ChangeLog
+++ b/gnu/dist/sim/ppc/ChangeLog
@@ -1,2163 +1,2916 @@
-Thu Apr 4 15:17:22 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+Thu Jul 3 10:18:06 1997 Andrew Cagney <cagney@b1.cygnus.com>
- * INSTALL: Fix some long lines and remove x86 specific options in
- the examples.
+ * ppc-instructions (PPC_INSN_INT): From Michael Thies - Monitoring
+ CR register updates dependant on RC value had logic backwards.
-Sun Mar 31 15:47:33 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
+ * ppc-instructions (Load String Word Immediate): From Brad Parker
+ - sense of wrap test in check for overwriting RA wrong.
+ (Load String Word Indexed): Ditto.
+
+ * configure.in: From Erik Landry - set sim_default_model not
+ sim_model for sim-default-model option.
+ * configure: Regenerate.
+
+ * interrupts.c (check_masked_interrupts): Schedule a hardware
+ interrupt delivery when FP interrupts get enabled.
+ (program_interrupt): Generate FP exceptions instead of aborting.
+ (deliver_hardware_interrupt): Deliver a FP exception if so
+ enabled.
+
+ * registers.h: Add definition of fpscr_vx_bits.
+
+ * idecode_expression.h (FPSCR_END): Always update FEX and VX bits
+ in FPSCR.
+ (FPSCR_END): Explicitly check for possible floating point
+ exception conditions.
+ (FPSCR_BEGIN): Simplify.
+
+ * ppc-instructions (Move From FPSCR): Enable.
+ (Move To FPSCR Bit 1): Ditto.
+ (Move To FPSCR Bit 0): Ditto.
+ (Move To FPSCR Field Immediate): Ditto.
+ (Move to Condition Register from FPSCR): Simplify.
+ (invalid_arithemetic_operation): Generate a QNaN when invalid
+ operation exception disabled.
+
+ * mkinstalldirs: New file.
+
+Tue Apr 15 14:57:18 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * Makefile.in (INSTALL): Set to @INSTALL@.
+ (INSTALL_XFORM, INSTALL_XFORM1): Remove.
+ (install): Depend upon installdirs. Use $(program_transform_name)
+ directly, rather than using $(INSTALL_XFORM).
+ (installdirs): New target.
+
+Fri Apr 4 17:54:36 1997 Jim Wilson <wilson@cygnus.com>
+
+ * Makefile.in (tmp-hw, tmp-pk): Use for loop to eliminate duplicates
+ rather than the non-portable cat -n.
+
+Wed Apr 2 14:51:17 1997 Ian Lance Taylor <ian@cygnus.com>
+
+ * COPYING: Update FSF address.
- * INSTALL: Update to reflect gdb-4.16.
+Tue Apr 1 18:15:14 1997 Jim Wilson <wilson@cygnus.com>
- * RUN: Update to reflect gdb-4.16. Review notes on building a BSD
- runtime environment.
+ * ppc-instructions: Change milhwu to mulhwu.
- * README: Point out copyright status of simulator in introduction.
+Tue Mar 25 16:17:59 1997 Andrew Cagney <cagney@kremvax.cygnus.com>
-Thu Mar 7 19:53:49 1996 Michael Meissner <meissner@cygnus.com>
+ * main.c (sim_io_read_stdin): Only compile unbuffered IO code if
+ all the required features are supported by the host OS.
- * emul_netbsd.c: Only include sys/mount.h if HAVE_SYS_MOUNT_H is
- defined.
- * configure.in: Test for sys/mount.h.
- * configure,config.in: Regenerate.
+Tue Mar 25 12:13:02 1997 Andrew Cagney <cagney@kremvax.cygnus.com>
-Thu Feb 22 22:48:57 1996 Andrew Cagney <cagney@highland.com.au>
+ * emul_bugapi.c (emul_bugapi_create): Guard against NULL images.
- * README, RUN, INSTALL: Update to reflect announcement
- * psim: PSIM 1.0.1 released
+ * configure.in (enable-sim-endain): Correct typo in usage (from
+ Erik Landry <landry@ENGR.ORST.EDU>).
+ * configure: Re-generate.
-Thu Feb 22 14:01:56 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+Fri Mar 14 18:23:02 1997 Andrew Cagney <cagney@kremvax.cygnus.com>
- * emul_bugapi.c (emul_bugapi_do_read): New function to handle
- reads.
- (emul_bugapi_instruction_call): Add support for .INCHR/.INLN
- system calls.
+ * Makefile.in (targ-vals.def): Re-do rule so that it works with
+ FreeBSD's make. Didn't like $<.
- * emul_bugapi.c (emul_bugapi_do_write): Call flush_stdoutput.
- * emul_netbsd.c (do_write): Call flush_stdoutput.
+Thu Mar 13 12:55:48 1997 Doug Evans <dje@canuck.cygnus.com>
- * main.c (flush_stdoutput): Do fflush (stdout).
- * sim_calls.c (flush_stdoutput): Do gdb_flush (gdb_stdout);
- * sim_callbacks.h (flush_stdoutput): Declare.
+ * sim_calls.c (sim_open): New SIM_DESC result. Argument is now
+ in argv form.
+ (other sim_*): New SIM_DESC argument.
-Wed Feb 21 10:39:35 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+Thu Feb 13 10:35:14 1997 Andrew Cagney <cagney@phydeaux.cygnus.com>
- * emul_bugapi.c (bug_mapping): New structure to map bug system
- call numbers to a string.
- (toplevel): Add remaining bugapi system calls.
- (emul_bugapi_instruction_name): Map bugapi system call number to a
- string.
- (emul_bugapi_do_write): Common code to process write system calls.
- (emul_bugapi_instruction_call): If os-emul tracing is on, trace
- the system call. Use the name to print unknown system call.
- Correct implementation of _OUTLN. Add support for _OUTSTR and
- _PCRLR system calls.
+ * ppc-opcode-simple-array, ppc-opcode-simple-goto,
+ ppc-opcode-simple-switch, ppc-opcode-complex-array,
+ ppc-opcode-complex-goto, ppc-opcode-complex-switch,
+ ppc-opcode-jump, ppc-opcode-goto, ppc-opcode-flat: Delete,
+ superseeded by --sim-decode-mechanism option.
-Wed Feb 21 17:07:27 1996 Andrew Cagney <cagney@highland.com.au>
+ * ppc-opcode-simple, dc-simple: Rename to be 8.3
+ * ppc-opcode-complex, dc-complex: Ditto.
+ * ppc-opcode-stupid, dc-stupid: Ditto.
+ * ppc-opcode-test-1, dc-test.01: Ditto.
+ * ppc-opcode-test-2, dc-test.02: Ditto.
- * NOTES: New file. Ramblings on why things were done they way
- they were.
+ * configure.in (--enable-sim-opcode): Change prefix to dc- instead
+ of ppc-opcode-.
+
+Wed Feb 12 19:33:45 1997 Andrew Cagney <cagney@phydeaux.cygnus.com>
+
+ * Many of the ppc-opcode-* files are identical baring the type of
+ lookup table. Instead of having multiple tables, igen can do this
+ via an additional option.
- * psim.c (psim_options): Didn't enter the model value into the
- device tree as a string.
+ * ld-decode.h, ld-decode.c (force_decode_gen_type): New function,
+ allow the type of generated table specified in the decode file to
+ be overridden.
+
+ * ld-decode.c (load_decode_table): Allow the table type to be
+ overridden.
+
+ * igen.c (main): Add -T <mechanism> option so that an overriding
+ instruction decode mechanism can be specified.
+
+ * configure.in: New option --sim-decode-mechanism to control
+ igen's new -T <mechanism> flag.
+ * Makefile.in (IGEN_FLAGS): Add IGEN_IDECODE_MECHANISM set by the
+ configure script.
+ * configure: Regenerate.
- * cpu.c (cpu_synchronize_context): Wrong test for conditional
- flush of cache.
+Tue Feb 11 13:49:10 1997 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * events.c (event_queue_create): Don't use NULL to initialize an
+ integer field.
+ (even_queue_{init,schedule_after_signal,tick}): Conditionalize use
+ of sigprocmask to appropriate autoconf test.
+
+ * main.c ({cntrl_c,main}): Use RETSIGTYPE for signal return type,
+ don't assume void.
+ * sim_calls.c (sim_{ctrl_c,resume}): Ditto.
+
+ * Makefile.in (callback.o): Define HAVE_CONFIG_H, so callback.c
+ includes our config.h.
+
+Tue Feb 4 13:42:59 1997 Doug Evans <dje@canuck.cygnus.com>
- * emul_generic.c (emul_add_tree_hardware): reg value didn't match
- bus address.
+ * configure.in: Fix typo in test for callback.c.
+ * configure: Regenerated.
+
+Fri Feb 7 10:04:25 1997 Andrew Cagney <cagney@kremvax.tpgi.com.au>
+
+ * emul_chirp.c (emul_chirp_create): Handle a virtbase of -1 being
+ found in the device tree.
+
+Wed Feb 5 10:56:27 1997 Andrew Cagney <cagney@kremvax.tpgi.com.au>
+
+ * Property create/initialization still wasn't correctly ordered.
+ Should be delaying everything related to ihandle creation until
+ after the rest of the tree has been established.
- * ppc-opcode-flat: new file. Generate an instruction decode
- function like ppc-opcode-complex but use switch statements.
+ * device.c (device_find_ihandle_runtime_property): Update.
+ (device_add_ihandle_runtime_property): Update.
- * INSTALL: document new opcode file, add example configurations.
+ * tree.c (parse_ihandle_property): Delay lookup of the device to
+ be opened until the ihandle initialization phase.
+ * tree.c (print_properties): Update.
-Tue Feb 20 18:42:31 1996 Andrew Cagney <cagney@highland.com.au>
+Wed Feb 5 10:56:27 1997 Andrew Cagney <cagney@kremvax.tpgi.com.au>
+
+ * gen-icache.c (print_icache_extraction): Add a reason parameter.
+ Augment each extracted field with a comment citing the codes
+ origin. Should simplify tracking down incorrect cache
+ extractions.
- * main.c (main): rename psim instance (system) to simulation and
- make global.
- * main.c (error): print out performance even when an error occures.
+Tue Feb 4 17:44:51 1997 Andrew Cagney <cagney@kremvax.tpgi.com.au>
- * emul_bugapi.c (emul_bugapi_create): Fix argument passing.
+ * gen-icache.c: Generalize code handling XXX_is_NNN so that it
+ works for normal and boolean table entries.
- * emul_generic.c (emul_add_tree_hardware): Move hardware devices
- to 0x80000000 from 0x400000.
+ * psim.c (psim_write_memory): last_cpu == -1 or nr_cpus is now
+ valid. Handle this just like *_{read,write}_register now handles
+ it.
-Mon Feb 19 22:54:40 1996 Andrew Cagney <cagney@highland.com.au>
+Mon Feb 3 17:18:16 1997 Andrew Cagney <cagney@kremvax.tpgi.com.au>
- * ppc-instructions (TLB Invalidate Entry, TLB Invalidate ALL):
- Implement by passing on request to all processors.
- * ppc-instructions (TLB Synchronize): Implement as empty, processor
- tlb's are always in sync.
+ * events.c (insert_event_entry): Correct loop termination
+ assertions.
- * cpu.c (cpu_page_tlb_invalidate_all): New function. Pass on TLB
- invalidate request to processors VM sub-system.
- * cpu.c (cpu_page_tlb_invalidate_entry): Ditto.
+Fri Jan 31 16:20:26 1997 Andrew Cagney <cagney@kremvax.tpgi.com.au>
- * vm.c (vm_page_tlb_invalidate_all): New function. Mark all page
- TLB entries as invalid.
- * vm.c (vm_page_tlb_invalidate_entry): New function. Ditt but only
- invalidate one TLB entry.
+ * psim.c (psim_options): Add new option -c for max-iterations or
+ count.
+ (psim_usage): Document.
+ (psim_max_iterations_exceeded): New function, abort simulation if
+ max iterations exceeded.
- * psim.c (psim_init): Invalidate TLB's before (re)starting.
+ * gen-idecode.c: Re-work the table lookup code so that it assumes
+ that the entry is a leaf by default. Simplify the boolean table
+ entry code so that it involves a mask + test instead of shift +
+ shift + mask + test.
-Mon Feb 19 21:25:56 1996 Andrew Cagney <cagney@highland.com.au>
+ * gen-idecode.c: Correct generated igen body so that it no drops
+ or doubles clock interrupts.
- * emul_generic.c (emul_add_tree_options): Add argument
- oea_interrupt_prefix (0 or 1) that specifies the prefix MSR[IP]
- and hence the location of the interrupt vectors. Add this to the
- device tree.
+
+Thu Jan 30 11:23:20 1997 Andrew Cagney <cagney@kremvax.tpgi.com.au>
- * emul_chirp.c (emul_chirp_create): Allow configuration of
- floating-point and interrupt prefix (default 0) using the above.
+ * Makefile.in (BUILT_SRC_WO_CONFIG): Change targ-vals.* to
+ @sim_targ_vals@
- * emul_netbsd.c (emul_netbsd_create): Pass dummy arg for
- interrupt-prefix.
+ * configure.in (sim_callback, sim_targ_vals): Set sim_targ_valls
+ if common callback is present.
- * emul_bugapi.c (emul_bugapi_create): Allow configuration of
- interrupt prefix (default 1) and configure interrupt table traps
- accordingly.
+Wed Jan 29 12:32:41 1997 Michael Meissner <meissner@tiktok.cygnus.com>
- * emul_generic.c (emul_add_tree_hardware): Include a small eeprom
- in the list of devices.
+ * configure.in (sim_callback): If the gdb is post 4.16, configure
+ callback support from the common directory.
+ * configure: Regenerate.
- * device_table.c: For moment fake eeprom device by a memory
- device. In future will need a proper eeprom device.
+ * Makefile.in (BUILT_SRC_WO_CONFIG): Add targ-vals.{h,def} and
+ targ-map.c.
+ (GDB_OBJ): Add callback support configured in.
+ (gentmap,targ-vals.def): Build from common directory.
+ (targ-vals.h,targ-map.c): Build by running gentmap.
+ (callback.o): Build from source in common directory.
+ (targ-map.o): Add dependency.
+ (clean): Remove gentmap.
-Tue Feb 20 17:01:26 1996 J.T. Conklin <jtc@rtl.cygnus.com>
+Wed Jan 29 12:14:19 1997 Andrew Cagney <cagney@kremvax.tpgi.com.au>
- * config.in: Regenerated.
+ * igen wasn't aborting if the opcode table contained no valid
+ fields.
+
+ * misc.c (name2i): Possibly abort if an invalid name is
+ encountered.
+ * ld-decode.c: Abort if the table type isn't found.
-Fri Feb 16 10:42:27 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+Wed Jan 29 12:14:19 1997 Andrew Cagney <cagney@kremvax.tpgi.com.au>
- * psim.c: Include options.h so print_options is declared.
+ * When performance monitoring is disabled, it is still possible to
+ determine the simulation speed by looking at the number of elapsed
+ ticks recorded by the event queue.
+
+ * psim.c (psim_write_register, psim_read_register): Force the cpu
+ to zero when it is either of `-1' or `nr_cpus'. In both cases the
+ next cpu would be zero any way.
-Thu Feb 15 18:10:13 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+ * mon.c (mon_print_info): If possible, print the system cycle
+ performance. This is an indication of the number of instructions
+ per second.
- * emul_netbsd.c (toplevel): Do not include sys/resource.h if the
- system doesn't have it, and turn off getrusage processing.
- (write_rusage): #ifdef out if we don't have getrusage.
- (do_getrusage): Define as 0 if we don't have getrusage.
+Wed Jan 29 12:14:19 1997 Andrew Cagney <cagney@kremvax.tpgi.com.au>
-Wed Feb 14 17:38:12 1996 J. T. Conklin <jtc@cygnus.com>
+ * The code to allow an event queue to be updated during a signal
+ was missing. For main.c, a cntrl-c simulation termination wasn't
+ handled cleanly.
+
+ * The simulation would not correctly restart if an event requested
+ that the simulation be halted.
+
+ * psim.c (psim_options): Add hack to -i option to optionally
+ include a level vis -i2.
+ (psim_usage): Document.
+
+ * main.c (cntrl_c, cntrl_c_simulation): New functions. When a
+ cntrl-c occures schedule an event to halt the simulation.
+ (main): Catch CNTRL-C signals with the function cntrl_c.
+
+ * events.c (event_queue_process): Mask interrupts while
+ manipulating the async event queue.
+ (event_queue_init): Ditto.
+ (event_queue_schedule_after_signal): Ditto.
+
+ * events.c (event_queue_process): Mark the event queue as being in
+ the processing state when processing has started. Adjust code
+ so that it is tolerant of halts.
+ (event_queue_init): Start the event queue out with processing
+ false.
+ (event_queue_tick): Check that processing isn't still being
+ performed.
+
+ * gen-idecode.c (print_run_until_stop_body): Call
+ event_queue_process_events to clear possibly pending events before
+ starting a simulation run. Re-arange main loop so that simulator
+ is correctly restarted when an event halts the simulation.
- * configure.in (AC_HEADER_DIRENT): Add, so that we can figure out
- where the directory functions are declared.
- * configure: Regenerate
+ * psim.c (psim_halt): Handle an event halting the simulation.
+ * psim.c (psim_init): Adjust initial cpu - == -1 - to match
+ reworked idecode.
- * emul_netbsd.c: Use the macros defined by configure to find the
- appropriate directory functions.
+Wed Jan 29 12:14:19 1997 Andrew Cagney <cagney@kremvax.tpgi.com.au>
-Thu Feb 8 00:53:13 1996 Andrew Cagney <cagney@highland.com.au>
+ * ppc-opcode-complex: Correct typo - was expanding ORA instead of
+ RA. Based on instruction frequency stats, expand additional
+ instructions.
+ * ppc-instructions: Change all `RA == 0' to RA_is_0.
+
+ * ppc-opcode-stupid: Move all but the basic table in -complex into
+ here. Update to new format.
+
+ * Makefile.in (tmp-defines): New target. Force defines.h to always
+ be built. Hence get ppc-opcode-goto to build.
- * configure.in (xor_endian): Trace setting of xor-endian flag.
+Tue Jan 28 13:00:19 1997 Andrew Cagney <cagney@kremvax.tpgi.com.au>
-Wed Feb 7 18:20:56 1996 Andrew Cagney <cagney@highland.com.au>
+ * hw_com.c (hw_com_instance_read, hw_com_instance_write):
+ Implement.
+
+Thu Jan 23 09:07:26 1997 Andrew Cagney <cagney@kremvax.tpgi.com.au>
- * psim.c (psim_usage): Extend documentation.
+ * hw_trace.c (hw_trace_init_data): Delete. The trace options need
+ to be initialized independant of the rest of the simulation
+ initalization. Otherwize a trace option explictly set from gdb
+ could be overridden by hw_trace.
- * ppc-instructions (model-print): fix typo.
+ * psim.c (psim_options): Clarify reason why the trace ioctl occures.
-Sun Feb 4 23:58:02 1996 Andrew Cagney <cagney@highland.com.au>
+ * FIXME: The trace code is too scattered - hw_trace.c, psim.c,
+ debug.c. It could be much simpler.
- * configure.in (with-smp): Default configuration allow up to
- five processors (but enable only one).
+Thu Jan 23 09:07:26 1997 Andrew Cagney <cagney@kremvax.tpgi.com.au>
+
+ * Some devices support removable media. Add hooks to the disk
+ device so that it supports this.
+
+ * device.c (device_add_string_array_property,
+ device_find_string_array_property): New functions, manipulate
+ properties containing an array of strings.
+ (device_find_string_property): Allow a string array.
+ (device_init_static_properties): Update.
+ (device_init_runtime_properties): Update.
+
+ * hw_disk.c (hw_disk_ioctl): Add ioctl for changing the disk
+ media. If no file image is specified, use the next one in the
+ image property list.
+ (hw_disk_init_address): Change the file property so that it is a
+ string array - use the first entry for the initial file image.
+
+ * tree.c (print_string_aray_property): New function - print a
+ string array.
+ (print_properties): Adjust.
+ (print_string): Write a string, handling double quotes.
+
+ * device.h: Define an ioctl to `change-media' with an optional new
+ media image.
+
+ * hw_disk.c: Allow floppy disk devices to be specified.
- * emul_bugapi.c (emul_bugapi_create): If floating-point is
- allowed, enable the floating point instruction set in the
- msr.
+ * psim.c (psim_command): New function, parse more complex psim
+ commands such as "change-media" and "trace".
+ * sim_calls.c (sim_do_command): Use.
-Tue Jan 30 22:52:32 1996 Andrew Cagney <cagney@highland.com.au>
+Wed Jan 22 09:38:33 1997 Andrew Cagney <cagney@kremvax.tpgi.com.au>
- * emul_chirp.c (chirp_emul_seek, chirp_emul_read,
- chirp_emul_write): Tolerate invalid ihandles.
+ * For expressions like (RA == 0) that are entered in to the cache
+ as RA_is_0. If possible generate the result of the expression so
+ that the compiler gets a better chance of eliminating dead
+ branches.
- * device.c (device_instance_create, device_instance_delete):
- init/delete instance name
+ * gen-icache.c (print_icache_extraction): For a cache entry of
+ the form <name>_is_<const> where it is a boolean field, generate
+ the result of the expression instead of the expression its self.
+ (print_icache_body): Remove code that was looking for *_is_0 and
+ then generating corresponding definitions.
- * emul_chirp.c (emul_chirp_instruction_call): Read the nr args and
- returns when determining the service.
+ * gen-icache.c (print_icache_struct): If there is no cache, do not
+ output expressions in idecode.h file.
+
+ * gen-icache.c (print_icache_body): Output them here.
+
+ * ppc-opcode-complex: Clarify constant values for SPR==LR register
+ expansion.
- * emul_chirp.c (chirp_read_t2h_args): Allow variable number of
- args for the method "call-method".
+ * ppc-cache-rules (RA_is_0, SPR_is_256): Two new cache entries.
- * emul_chirp.c (chirp_emul_getprop): Tolerate a n_returns of zero
- - should be one. Some OpenBoot code doesn't pass correct arg.
+Wed Jan 22 12:24:52 1997 Andrew Cagney <cagney@kremvax.tpgi.com.au>
- * emul_chirp.c (chirp_emul_getprop): Trace more property types.
+ * The code that put values in and extracted values from the cache
+ was too compilicated. The cache table did not allow values to be
+ computed from cache entries. #defines could only be used when a
+ cache was present, remove the restriction.
-Tue Jan 30 19:12:29 1996 Andrew Cagney <cagney@highland.com.au>
+ * ld-cache.h, ld-cache.c: Add a new cache entry type - SCRATCH. A
+ scratch variable is defined when a cache entry is beinf
+ filled. Change the definition of a COMPUTE variable to be defined
+ when the cache entry is being used.
+ * gen-icache.c: Update.
+
+ * ld-cache.h, ld-cache.c: Change field names so that their meaning
+ is more obvious. old_name->field_name, new_name->derived_name.
+ * gen-icache.c: Update
+
+ * gen-icache.h, gen-icache.c (print_icache_body): Make the three
+ different types of cache code - put into cache, extract from
+ cache, no cache - an explicit argument to print_icache_body.
+ * gen-icache.c (print_icache_extraction): Ditto.
+
+ * gen-semantics.c (print_c_semantic): Update use.
+ * gen-idecode.c (print_jump_insn): Update use.
+ * gen-icache.c (print_icache_function): Update use.
+
+ * igen.c (main): Change 'R' option so that it does not force the
+ cache.
+
+ * configure.in (enable-sim-icache): Clarify description. Make
+ #define one of the defaults regardless of the cache. Probably
+ should revamp and add a separate option.
+
+Tue Jan 21 13:26:10 1997 Andrew Cagney <cagney@kremvax.tpgi.com.au>
+
+ * pk_disklabel.c (block_is_fdisk): Tidy up traces - use dos
+ partition numbering.
+ (pk_disklabel_create_instance): Partition 1..4 are valid - not
+ 1..3.
+ (is_iso9660): New function, verify a CD9660 File system.
+ (pk_disklabel_create_instance): Start expanding so that active
+ partition selection is supported.
+
+Mon Jan 20 11:20:15 1997 Andrew Cagney <cagney@kremvax.tpgi.com.au>
+
+ * The cap object was retaining a reference to the instance of a
+ device after it was deleted. Instead add and remove cap's from the
+ cap db as they are created and deleted. This ensuring that a
+ capibility is only used during the lifetime of the corresponding
+ object.
+
+ * cap.h, cap.c: Correct cap type - was signed32 should be
+ signed_cell.
+
+ * cap.c (cap_add, cap_remove): New methods for cap object that
+ allow the explicit addition and removal of internal objects that
+ the cap knows about.
+
+ * cap.c (cap_init): Rewrite. Verify that the only objects
+ remaining in the cap data base are those that were entered first.
+ Thse objects will be the permenant ones.
+ * device.c (device_init_address): Remember to initialize the cap
+ database.
+
+ * device.c (device_create_instance_from): Explicitly add device
+ instances to the cap database. Simplify create code.
+ (device_instance_delete): Explicitly remove device instances from
+ the cap database.
+
+ * device.c (device_create_from): Explicitly add a device to the
+ cap data base.
+
+ * device.c (device_create_from): Always set the cap members.
- * RUN: New file. Describe how to run PSIM
- * INSTALL: New file. Describe how to install PSIM
- * README: New file. Overview PSIM.
- * BUGS: New file. Briefly discuss bugs and limitations
+ * hw_disk.c: Output the instance when tracing.
-Wed Jan 24 20:28:08 1996 Andrew Cagney <cagney@highland.com.au>
+Sun Jan 19 16:44:29 1997 Andrew Cagney <cagney@kremvax.tpgi.com.au>
- * emul_bugapi.c (OEA_START_ADDRESS): Put it back to 0x100000,
- wasn't correctly using GLD.
+ * tree.c (split_device_specifier): Add support for aliases when
+ looking up a device. Now needs a device as an argument.
+ (split_property_specifier): Ditto.
-Mon Jan 22 22:44:13 1996 Andrew Cagney <cagney@highland.com.au>
+Sun Jan 19 15:28:23 1997 Andrew Cagney <cagney@kremvax.tpgi.com.au>
- * emul_generic.c (emul_add_tree_options): Make default number of
- active processors 1 (even when SMP enabled).
+ * The memory "claim" and "release" methods take an address and
+ size as arguments. These may be multi cell values. Initially fix
+ the memory code so that they check/detect this. Leave the
+ adjustment of any clients to later.
+
+ * hw_memory.c (hw_memory_instance_claim,
+ hw_memory_instance_release): Handle multi-cell memory devices.
+
+ * hw_memory.c (hw_memory_instance_claim): Be tolerant towards the
+ release of memory regions that were not claimed.
-Mon Jan 22 22:37:34 1996 Andrew Cagney <cagney@highland.com.au>
+Fri Jan 17 12:01:07 1997 Andrew Cagney <cagney@kremvax.tpgi.com.au>
- * device_table.c (icu_io_read_buffer_callback): Add extra register
- (at addr + 4) that returns number of processors.
+ * device.h, device.c (device_instance_call_method): Correct return
+ type - can return either 0 or -1, hence should be a signed type.
+ * device_table.h: Ditto.
+
+ * hw_memory.c (hw_memory_instance_claim,
+ hw_memory_instance_release): Update.
+ * hw_disk.c (hw_disk_max_transfer, hw_disk_block_size,
+ hw_disk_nr_blocks): Ditto.
+
+Fri Jan 17 11:50:13 1997 Andrew Cagney <cagney@kremvax.tpgi.com.au>
- * emul_generic.c (emul_add_tree_hardware): Update device node to
- match.
+ * emul_chirp.c (chirp_emul_claim): Implement using the "claim"
+ method belonging to "/chosen/memory".
+ (chirm_emul_release): Ditto.
+
+ * Makefile.in (LIB_INLINE_SRC): Remove emul_* from list of files
+ that are inlined. These modules are called via a table and are
+ not made inline.
-Mon Jan 22 22:00:42 1996 Andrew Cagney <cagney@highland.com.au>
+ * hw_init.c (update_for_binary_section): Fix failure to allocate
+ memory used by the binary in real-mode executions. If "claim"
+ property is present, allocate memory from the "/chosen/memory"
+ device.
- * emul_bugapi.c (OEA_START_ADDRESS): Change to 0x4000 so that it
- matches gas-960116/ld.
+ * emul_chirp.c (emul_chirp_create): Specify that memory should be
+ claimed when loading a real image.
-Fri Jan 19 00:32:27 1996 Andrew Cagney <cagney@highland.com.au>
+ * hw_memory.c (hw_memory_instance_claim): Don't page align memory
+ allocations.
- * psim-960119 released - psim-1.0b01.
+ * hw_memory.c (hw_memory_instance_release): Avoid infinite loop
+ when merging adjacent memory chunks.
-Fri Jan 19 00:32:27 1996 Andrew Cagney - aka Noid <cagney@highland.au.com>
+Thu Jan 16 08:51:25 1997 Andrew Cagney <cagney@kremvax.tpgi.com.au>
- * psim.c (psim_create): Re-order so that all options are set
- before the CPU's are created. Was breaking mon_create();
+ * vm.h (vm_data_map_read_buffer, vm_data_map_write_buffer): Add
+ optional PROCESSOR & CIA args so that this routine also abort an
+ access.
- * psim.c (psim_create): Tidy up conflicting configuration errors.
+ * vm_n.h (vm_data_map_read_N, vm_data_map_write_N): For a
+ miss-aligned access when a transfer fails abort.
+
+ * emul_bugapi.c (emul_bugapi_do_write): Use emul_read_buffer
+ instead of the vm_read_buffer.
+ * emul_netbsd.c (do_write): Ditto.
+ * emul_unix.c (do_unix_write): Ditto.
- * debug.c: Add missing print-info entry to trace table.
+Wed Jan 15 14:38:25 1997 Andrew Cagney <cagney@kremvax.tpgi.com.au>
- * os_emul.c (os_emul_create): Fix `-e' option. Was looking under
- wrong name.
+ * configure.in (--enable-sim-jump): Default is NULL and not -E.
+ * configure: Regenerate.
+
+ * basics.h (__attribute__): Enable attributes if GCC >= 2.6.
+ (UNUSED): Only enable UNUSED if GCC >= 2.7.
+
+ * gen-icache.c (print_icache_extraction): Print UNUSED macro
+ instead of explicit __unused__ attribute.
+ (print_icache_body): Ditto.
+ * idecode_expression.h (FPSCR_BEGIN): Use UNUSED.
- * psim.c (psim_options): Fix `-r' option. Was entering under wrong
- name.
+Wed Jan 15 13:54:50 1997 Andrew Cagney <cagney@kremvax.tpgi.com.au>
-Thu Jan 18 20:33:48 1996 Andrew Cagney <cagney@highland.com.au>
+ * cpu.h, cpu.c (cpu_synchronize_context): Add CIA argument as
+ reference point.
- * vm.c (om_unpack_bats): Fix checking of bat bits.
+ * vm.c (vm_synchronize_context): Add PROCESSOR and CIA as
+ arguments so that there is a reference point for recovery.
+ (vm_synchronize_context): Pass processor+cia for errors.
+ (om_unpack_sr): Ditto.
+ (om_unpack_srs): Ditto.
+ * vm.c (vm_create): Review error messages.
- * emul_chirp.c (emul_chirp_create): Store address of OB in memory
- in the os_emul_data structure.
+ * vm.c: Include "cpu.h" so that cpu_error is visible.
- * emul_bugapi.c (emul_bugapi_create): Store the address of the
- bugapi code (in main memory) in the os_emul_data structure.
+ * ppc-instructions (Return From Interrupt): Pass CIA.
+ (Instruction Synchronize): Ditto.
+ * psim.c (psim_init): Ditto.
-Thu Jan 18 01:14:55 1996 Andrew Cagney <cagney@highland.com.au>
+Wed Jan 15 12:25:11 1997 Andrew Cagney <cagney@kremvax.tpgi.com.au>
- * vm.c (om_translate_effective_to_real): Fix trace output.
+ * cpu.h, cpu.c (cpu_error): Aborts simulation with error message,
+ but also saves current processor state.
+
+ * basics.h: Move #include <stdarg.h> to here from device_table.h.
+
+ * interrupts.c (perform_oea_interrupt): Use. No longer loose CIA
+ when simulation aborted.
+ (program_interrupt): Ditto.
+ (floating_point_unavailable_interrupt): Ditto.
+ (alignment_interrupt): Ditto.
+ (floating_point_assist_interrupt): Ditto.
+ (perform_oea_interrupt): Ditto.
+ (machine_check_interrupt): Ditto.
+
+Tue Jan 14 12:19:10 1997 Andrew Cagney <cagney@kremvax.tpgi.com.au>
+
+ * ppc-instructions (Move from Special Purpose Register): Support
+ move from DEC.
+
+Mon Jan 13 16:58:12 1997 Andrew Cagney <cagney@kremvax.tpgi.com.au>
+
+ * debug.h, debug.c: Add "interrupts" trace option.
+
+ * interrupts.c (data_storage_interrupt): Add tracing.
+ (machine_check_interrupt): Ditto.
+ (instruction_storage_interrupt): Ditto.
+ (alignment_interrupt): Ditto.
+ (program_interrupt): Ditto.
+ (floating_point_unavailable_interrupt): Ditto.
+ (system_call_interrupt): Ditto.
+ (floating_point_assist_interrupt): Ditto.
+ (deliver_hardware_interrupt): Ditto.
+
+ * interrupts.c (program_interrupt): For UEA mode, halt the
+ processor - so that the current state is saved - instead of
+ aborting.
+ (floating_point_unavailable_interrupt): Ditto.
+ (floating_point_assist_interrupt): Ditto.
-Wed Jan 17 22:21:55 1996 Andrew Cagney <cagney@highland.com.au>
+Thu Jan 2 09:10:41 1997 Andrew Cagney <cagney@kremvax.tpgi.com.au>
- * device_table.c (generic_device_init_address): Create memory from
- information obtained from `reg' property.
- * device_table.c (vm_init_address_callback): Use information
- obtained from properties.
- * emul_netbsd.c (emul_netbsd_create): Update to create device and
- property entries to match
+ * interrupts.c (perform_oea_interrupt): Halt rather than abort on
+ a double interrupt.
-Tue Jan 16 09:50:53 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+Wed Jan 1 22:54:52 1997 Andrew Cagney <cagney@kremvax.tpgi.com.au>
- * idecode_expression.h (ALU_END): Add ITRACE of the result.
+ * ppc-instructions (Store Multiple Word, Load Multiple Word):
+ Enable.
- * ppc-instructions (Equivalent): Enable this instruction.
- (Add to Minus One Extended): Ditto.
- (Subtract from Minus One Extended): Ditto.
- (Add/And/Or/Xor Immediate): Add alu trace of result.
- (Add/And/Or/Xor Shifted Immediate): Ditto.
- (And/Or/Equivalent/Nand/Nor): Ditto.
- (And/Or with Complement): Ditto.
- (Extend Sign Byte/Half Word): Ditto.
- (Count Leading Zeros): Ditto.
- (Shift Right Algerbraic Word): Ditto.
- (Shift Right Algerbraic Word Immediate): Ditto.
+ * tree.c (print_properties): For an array consider printing it out
+ as an integer array.
-Tue Jan 9 15:10:27 1996 Andrew Cagney <cagney@highland.com.au>
+ * hw_memory.c (hw_memory_init_address): If an "available" property
+ is present, use that to initialize the available memory instead of
+ using the reg property.
- * emul_bugapi.c (emul_bugapi_instruction_call) : Make format type
- correct.
- * emul_chirp.c (map_over_chirp_note) : Ditto
- * emul_chirp.c (chirp_emul_test) : Ditto
- * device_table.c (register_init): Ditto
+ * emul_generic.c (emul_add_tree_hardware): Add "available"
+ property to memory device.
-Tue Jan 9 14:16:26 1996 Andrew Cagney <cagney@highland.com.au>
+Fri Dec 20 13:19:07 1996 Andrew Cagney <cagney@kremvax.tpgi.com.au>
- * configure.in: Make disable-sim-switch default. Switch only
- useful if using --enable-sim-opcode=ppc-opcode-stupid and then
- only marginally so.
+ * ppc-instructions (Rotate Left Word then AND with Mask): Enable.
-Mon Jan 8 12:17:22 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+ * device.c (device_instance_call_method): Was only looking at the
+ first method.
- * device_table.c (register_init): Make format type correct.
+ * hw_disk.c (hw_disk_nr_blocks): Implement #blocks method.
+ (hw_disk_block_size): Implement block-size method.
+ (hw_disk_max_transfer): Implement max-transfer method.
-Wed Jan 3 19:21:46 1996 Andrew Cagney <cagney@highland.com.au>
+ * hw_phb.c (hw_phb_init_address): Reinit the rest of the PHB.
- * emul_bugapi.c (emul_bugapi_create): Add nodes to init the
- system-call trap to the emul instruction call instruction (Along
- with an rfi and infinate loop).
+ * emul_chirp.c (chirp_emul_instance_to_path): Recover from an
+ invalid ihandle.
+ (chirp_emul_instance_to_package): Ditto.
+ (chirp_emul_method): Ditto.
+ (chirp_emul_read): Ditto.
+ (chirp_emul_write): Ditto.
+ (chirp_emul_close): Ditto.
+ (chirp_emul_seek): Ditto.
+ (chirp_emul_package_to_path): Ditto (for phandle).
+ (chirp_emul_package_to_path): Return the length.
- * emul_bugapi.c (emul_bugapi_instruction_call): Expand to include
- a few real PPC bug calls. Test with simple hello world.
+ * psim.c (psim_merge_device_file): Allow continuation lines.
-Tue Jan 2 20:51:19 1996 Andrew Cagney - aka Noid <cagney@highland.com.au>
+Thu Dec 19 11:09:43 1996 Andrew Cagney <cagney@kremvax.tpgi.com.au>
- * device.h, device.c (device_child, device_sibling): New
- functions. Return corresponding device value.
+ * emul_chirp.c (chirp_emul_boot): Implement. Well report the new
+ string and exit.
+
+ * emul_chirp.c (chirp_emul_exit): Correct type of args struct
+ members - *_cell not host dependant int.
- * emul_chirp.c (chirp_emul_child, chirp_emul_peer,
- chirp_emul_parent): New functions - emulate corresponding OpenBoot
- interfaces.
+Wed Dec 18 17:49:59 1996 Andrew Cagney <cagney@kremvax.tpgi.com.au>
- * device_table.c (register_init): Extend properties attached to
- register init node to allow a specific processor's register to be
- specified.
+ * interrupts.c (perform_oea_interrupt): Print additional
+ information if a double interrupt is encountered.
- * emul_chirp.c (emul_chirp_create): Init SMP correctly - the
- initial PC for all processors is an infinate loop but then, for
- processor zero, is quickly changed to be the correct code starting
- address.
+Wed Dec 18 17:49:59 1996 Andrew Cagney <cagney@kremvax.tpgi.com.au>
+
+ * psim.c (psim_merge_device_file): Tolerate an incorrect file-name
+ being specified with the -f option.
+ (psim_merge_device_file): Correct check for end of string.
+
+Wed Dec 18 17:49:59 1996 Andrew Cagney <cagney@kremvax.tpgi.com.au>
+
+ * emul_chirp.c (chirp_emul_peer): Was falling off the end of the
+ list of devices. Return zero to the client instead.
+ * emul_chirp.c (chirp_emul_child): Ditto
+ * emul_chirp.c (chirp_emul_parent): Ditto
+
+ * device.c (device_root): Assert assumption about the device being
+ valid.
+
+Tue Dec 17 15:12:38 1996 Andrew Cagney <cagney@kremvax.tpgi.com.au>
+
+ * emul_chirp.c (emul_chirp_create): Add description property to
+ each significant node in the device tree.
+ * emul_bugapi.c (emul_bugapi_create): Ditto.
+
+Fri Dec 13 14:30:31 1996 Andrew Cagney <cagney@kremvax.tpgi.com.au>
+
+ * main.c (sim_io_read_stdin): For a single byte STDIO read, use a
+ tempoary two byte buffer. Single byte read with fgets will not
+ work.
+ * main.c: Include errno.h.
+ (sim_io_read_stdin): For non-STDIO, make it work.
+
+ * emul_chirp.c (chirp_emul_read): Return the correct error status.
- * emul_chirp.c (emul_chirp_create): Add fake bootpath
- et.al. properties to tree.
+Fri Dec 13 14:30:31 1996 Andrew Cagney <cagney@kremvax.tpgi.com.au>
- * emul_chirp.c (chirp_emul_getproplen): New function. Emulate the
- getproplen OpenBoot call.
+ * std-config.h (WITH_STDIO): Don't hard-wire the STDIO mechanism.
+ Instead have each emulation default it to DO_USE_STDIO.
- * emul_chirp.c (emul_chirp_instruction_call): Document other
- possible chirp emulation internal states.
+ * emul_generic.c (emul_add_tree_options): Select the STDIO I/O
+ mechanism as the default if enabled or if nothing selected.
- * emul_chirp.c (emul_chirp_instruction_call): Trace failed lookups
- as well as successful ones.
+ * sim_calls.c (sim_io_read_stdin): Passify GCC's desire for a
+ return value.
+ (sim_io_write_stdout): Ditto.
+ (sim_io_write_stderr): Ditto.
+ * main.c (sim_io_write_stdout): Ditto.
+ (sim_io_write_stderr): Ditto.
+ (sim_io_read_stdin): Ditto.
+
+Tue Dec 10 10:31:48 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * emul_chirp.c (emul_chirp_instruction_call): Make *printf calls
+ type correct.
+ * vm.c (om_effective_to_virtual): Ditto.
+ * events.c (event_queue_schedule{,_after_signal}): Ditto.
+ (event_queue_{deschedule,process}): Ditto.
+ * hw_htab.c (htab_decode_hash_table): Ditto.
+ (htab_map_{page,binary}): Ditto.
+ * hw_opic.c (hw_opic_init_data): Ditto.
+ (handle_interrupt): Ditto.
+ (do_processor_init_register_{read,write}): Ditto.
+ (write_vector_priority_register): Ditto.
+ ({read,write}_destination_register): Ditto.
+ (do_suprious_vector_register_{read,write}): Ditto.
+ (do_current_task_priority_register_N_{read,write}): Ditto.
+ (do_timer_frequency_reporting_register_{read,write}): Ditto.
+ (do_timer_N_{current,base}_count_register_{read,write}): Ditto.
+ (do_ipi_N_dispatch_register_write): Ditto.
+ (do_vendor_identification_register_read): Ditto.
+ (do_feature_reporting_register_N_read): Ditto.
+ (do_global_configuration_register_N_{read,write}): Ditto.
+ * hw_phb.c (hw_phb_attach_address): Ditto.
+ (hw_phb_unit_decode): Ditto.
+ (hw_phb_address_to_attach_address): Ditto.
+ (hw_phb_io_{read,write}_buffer): Ditto.
+ * hw_ide.c (setup_fifo): Ditto.
+
+ * sim_calls.c ({defs,callback,remote-sim}.h): Find gdb include
+ files via -I<dir> instead of using "../../gdb/" prefixes.
+
+Tue Dec 10 10:12:44 1996 Andrew Cagney <cagney@kremvax.tpgi.com.au>
+
+ * debug.h: Add tracing for the pal device.
+ * hw_pal.c: Update.
+
+ * emul_chirp.c (chirp_emul_getprop): More tracing.
+
+Tue Dec 10 10:12:44 1996 Andrew Cagney <cagney@kremvax.tpgi.com.au>
+
+ * device.h, device.c (device_find_ihandle_runtime_property): New
+ function. Reverse of add_ihandle_runtime property.
+ (device_init_runtime_properties): Use it.
+
+ * device.c (find_property_entry): New function returns the
+ internal property spec.
+ (device_set_property): Use.
+ (device_find_property): Use.
+
+Tue Dec 10 10:12:44 1996 Andrew Cagney <cagney@kremvax.tpgi.com.au>
+
+ * psim.c (psim_merge_device_file): Strip newline from device
+ specs.
- * emul_chirp.c (emul_chirp_open): New function - handle open
- client call.
+Tue Dec 10 10:12:44 1996 Andrew Cagney <cagney@kremvax.tpgi.com.au>
- * Makefile.in (maintainer-clean): Proper rule that eliminates more
- junk.
+ * hw_htab.c (htab_map_binary): For overlapping text / data maps
+ merge the two. Also check that the merge is safe.
-Tue Dec 19 13:00:11 1995 Andrew Cagney <cagney@highland.com.au>
+ * emul_chirp.c (emul_chirp_create): Add a description property to
+ the pte's so that they are easier to identify.
+
+ (emul_chirp_create): Don't specify a load address for the CHRP
+ image. Always use the values specified by the executable.
- * emul_chirp.c (chirp_emul_exit): Full out call.
+ * hw_htab.c (htab_map_page): Abort if a duplicate map is
+ encountered.
- * device_table.c (htab_map_page): Wasn't handling byte swap when
- creating entries in the hash table.
+Mon Dec 9 12:08:46 1996 Andrew Cagney <cagney@kremvax.tpgi.com.au>
- * device.c (device_tree_find_node): Allow primative wild-card match
- of device names with the path.
+ * hw_htab.c (htab_map_page): Formatting.
- FIXME: As mentioned earlier, the device stuff needs work to bring
- it into line with OpenBoot. Part of this work is rewriting the
- find_node function so that it behaves as specified in p1275.
+ * emul_chirp.c (emul_chirp_instruction_call): Check for a NULL
+ method name when handling the client call. Also check for other
+ bad call arguments.
+
+ * emul_chirp.c (emul_chirp_create): Allow real-mode?, real-base,
+ etc to be overriden.
-Mon Dec 18 19:58:56 1995 Andrew Cagney <cagney@highland.com.au>
+Mon Dec 9 12:08:46 1996 Andrew Cagney <cagney@kremvax.tpgi.com.au>
- * emul_chrp.c (chirp_emul_write, chirp_emul_finddevice): add
- better tracing.
+ * os_emul.c (os_emul_create): Use tree find property instead of
+ device find property - sigh.
- * emul_chrp.c: Change return type of emul functions to int. Emul
- functions either return -1 or zero so unsigned was a bit
- dangerous.
+Thu Dec 5 10:46:42 1996 Andrew Cagney <cagney@kremvax.tpgi.com.au>
+
+ * 961205: Release snapshot 961205.
- * inline.h (*), igen.c, dgen.c, *: Update INLINE macros so that
- they are paramaterised with the type of the function. Gets around
- the problem of `static' needing to come first with `attribute'
- comming last. Format declarations and definitions so that emacs
- doesn't get confused.
+Thu Dec 5 10:46:42 1996 Andrew Cagney <cagney@kremvax.tpgi.com.au>
+
+ * configure.in (hostbitsize, bitsize): Fix typo in error message -
+ cannot contain a comma.
+ (sim-warnings): Check for more potential errors.
-Fri Dec 15 17:06:44 1995 Andrew Cagney <cagney@highland.com.au>
+ * psim.c (psim_usage): Add -f <file> option. Specifies a file
+ containing device tree specifications that should be merged into
+ the device tree.
- * std-config.h (PSIM_INLINE): Add missing inline configuration
- control for the main loop.
+ * configure.in: Sort options.
+ * configure: Rebuild
+
+Wed Dec 4 13:57:31 1996 Andrew Cagney <cagney@kremvax.tpgi.com.au>
- * mon.c (mon_print_info): If monitoring disabled still print out
- the number seconds used.
+ * psim.c (psim_usage): Add -n option - specify number of
+ processors.
- * psim.c (run_until_stop): Don't monitor the cache misses when
- monitoring is disabled.
+ * emul_chirp.c: Add description.
+ * emul_bugapi.c: Ditto.
+ * emul_unix.c: Ditto.
+ * emul_netbsd.c: Ditto.
- * configure.in (sim_mon, sim_monitor): Correct typo - sim_mon ->
- sim_monitor for shell variable (or should that have been the other
- way around?).
+Fri Nov 29 11:12:22 1996 Andrew Cagney <cagney@kremvax.tpgi.com.au>
- * vm.c (vm_synchronize_context): Fix wrong test for unsuported
- change in endian-mode.
+ * hw_pal.c (hw_pal_attach_address): New function, if an attach is
+ encountered, assume that it is the single disk.
+ * hw_pal.c: Add generic device/size decode methods.
- * std-config.h (WITH_REGPARM), inline.h (IDECODE_INLINE,
- SEMANTICS_INLINE): Add -DWITH_REGPARM=<n> option. Enables the
- __attribute__((__regparm(WITH_REGPARM))) for some functions.
- configure with --enable-sim-cflags="-DWITH_REGPARAM=3" (say).
- Unfortunatly it tickles a bug (gcc?) and can't be used.
+ * hw_nvram.c (hw_nvram_init_address): Use the first nonzero reg
+ property entry when determining the nvram size.
-Mon Dec 18 13:36:06 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+ * hw_core.c: Add generic address/size decode methods.
- * device.c (device_tree_add_device): Make trace fprintf arguments
- type correct.
- * device_table.c (htab_decode_hash_table): Ditto.
- (htab_map_binary): Ditto.
- (htab_init_callback): Ditto.
- * vm.c (om_virtual_to_real): Ditto.
+ * emul_chirp.c (emul_chirp_instruction_call): Return and trace
+ nonzero status from client functions.
+
+ * main.c (error): Always include a cariage return when writing out
+ errors.
+
+Wed Nov 20 00:36:55 1996 Doug Evans <dje@canuck.cygnus.com>
-Sat Dec 16 09:54:18 1995 Michael Meissner <meissner@wogglebug.tiac.net>
+ * sim_calls.c (sim_resume): Reset sim_should_run if single
+ stepping.
- * emul_netbsd.c (emul_netbsd_create): Deal with new BFD that
- changed how big/little endian support is recorded, while remaining
- compatible with the old BFD with #ifdefs.
+Thu Nov 28 13:19:46 1996 Andrew Cagney <cagney@kremvax.tpgi.com.au>
+
+ * emul_bugapi.c (emul_bugapi_do_diskio): Add support for multiple
+ optional disks.
+
+ * emul_generic.c (emul_add_tree_hardware): Drop the dummy eeprom.
+ Attach the pal - for I/O - as a pseudo device haning from the
+ firmware sub tree.
+
+ * emul_bugapi.c (emul_bugapi_create): Add a small memory device to
+ the device tree at the address of the hi-mem interrupt vector
+ addreses. Used by bugapi to establish its trap instructions.
+
+ * debug.h: Add a new macro DITRACE for tracing device instances.
+
+ * debug.h: Extend the DTRACE macro so that it can also tests for
+ device specific tracint.
+
+ * device.h, device.c (device_trace): Add method to determine
+ device specific tracing.
+ (device_init_address): Set the devices tracing level.
+
+Thu Nov 21 12:05:32 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
+
+ * tree.h, tree.c (tree_device): New files - separate out the
+ device parser and other tree operations from the device.
+
+ * inline.h, inline.c (INLINE_TREE): Add.
+ * device.h, device.c (device_tree_add_parsed): Delete.
+ * Makefile.in (tree.c): Add rules for new file.
+ * Makefile.in: Better order the emul_* files.
+
+ * emul_generic.c (emul_add_tree_hardware): Update.
+ * emul_netbsd.c (emul_netbsd_create): Update.
+ * emul_unix.c (emul_unix_create): Ditto.
* emul_chirp.c (emul_chirp_create): Ditto.
* emul_bugapi.c (emul_bugapi_create): Ditto.
+ * psim.c (psim_tree): Ditto.
+ * hw_init.c: Ditto.
+
+ * emul_generic.h: Include tree.h
+ * Makefile.in: Add to EMUL_GENERIC_H dependencies.
+
+ * device.h, device.c (device_root): New function - returns the
+ root of the tree.
+ * corefile.c: Use.
+
+ * device.h, device.c (device_clean): New function, clean up device
+ ready for next simulation run. This includes things like deleting
+ interrupt edges and properties created during the simulation and
+ also scrubbing any pre-defined properties.
+ * tree.c (tree_init): Use.
+
+ * device.h, device.c (device_init_static_properties): New
+ function. Initialize any static predefined properties. By static
+ we mean those that have values that can be determined before the
+ device tree initialization has started.
+ * tree.c (tree_init): Use.
+
+ * device.h, device.c (device_init_address): Add code to
+ check/verify the devices #address-cells and #size-cells.
+ (device_add_integer_property): Delete corresponding code.
+ (device_nr_address_cells, device_nr_data_cells): Check for
+ property when returning value.
+
+ * device.h, device.c (device_init_runtime_properties): New
+ function. Initialize those properties that are not `static'. At
+ present the only such property is the ihandle.
+ * tree.c (tree_init): Use.
+
+ * device.h, device.c (reg, ranges): Rework these so that they use
+ an array of the fundamental type - single reg or single range
+ entry.
+
+ * device.h, device.c (device_add_ihandle_runtime_property):
+ Re-implement the adding of an ihandle during tree construction so
+ that it better fits in with device initialization.
+
+Thu Nov 21 12:05:32 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
-Fri Dec 15 15:55:56 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+ * device.h, device.c (device_ioctl): Add additional argument -
+ request - so that the caller must always specify the type of
+ the ioctl request.
- * std-config.h (MODEL_INLINE): Turn off INLINE_MODULE by default.
+ * device_table.h: Update.
+ * hw_trace.c (hw_trace_ioctl): Ditto.
+ * hw_vm.c (hw_vm_ioctl_callback): Ditto.
+ * hw_init.c (hw_stack_ioctl_callback): Ditto.
+ * psim.c (psim_options): Ditto.
+
+Thu Nov 21 12:05:32 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
+
+ * BUGS: Updated a bit.
- * corefile.h: Delete declarations for unknown functions.
- * device.h: Ditto.
- * interrupts.h: Ditto.
- * interrupts.c: Ditto.
+Wed Nov 20 14:06:37 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
-Thu Dec 14 18:49:34 1995 Andrew Cagney <cagney@highland.com.au>
+ * hw_opic.c: Finish - third round.
- * lf.c (lf_print_function_type): New function. Munges a function
- type so that the prefix (eg INLINE...) is inserted after the type
- but before any `*'.
+Wed Nov 20 12:02:08 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
- * igen.c: Change to output functions using this.
+ * hw_glue.c (hw_glue_io_read_buffer_callback): Fix miscalc of glue
+ reg index.
+ (hw_glue_io_write_buffer_callback): Ditto.
-Wed Dec 13 23:47:00 1995 Andrew Cagney <cagney@highland.com.au>
+Tue Nov 19 21:17:08 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
- FIXME: Emul CHIRP does not correctly implement the find device
- function.
+ * events.c (event_queue_process): Was incorrectly consuming future
+ events on the queue when they should be left alone.
- FIXME: Emul CHIRP and device do not implement device instance
- operations.
+ * debug.h, debug.c (events): Add support for event queue tracing.
+ * events.c: Add event tracing.
+
+ * debug.h, debug.c: Order device trace options.
+
+Fri Nov 15 15:23:39 1996 Michael Meissner <meissner@tiktok.cygnus.com>
-Wed Dec 13 23:47:00 1995 Andrew Cagney <cagney@highland.com.au>
+ * pk_disklabel.c (pk_disklabel_create_instance): Fix up some
+ warnings generated by GCC.
- * options.c (options_inline): Function to output meaningful
- description of the INLINE options.
+Sun Nov 17 17:59:14 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
- * configure.in (inline): Replace inline magic numbers with macro
- names. Map 1->LOCALS_INLINE and 2->ALL_INLINE.
+ * sim-endian.h: Add LE versions of byte swap macros. Needed for
+ PCI devices which are little-endian.
+
+ * sim-endian-n.h (endian_le2h_N, endian_h2le_N): Ditto
- * inline.h, inline.c: update to use inline method.
+Sun Nov 17 17:59:14 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
- * std-config.h (CPU_INLINE), cpu.h, inline.h, inline.c: make cpu.h
- inline always.
+ * hw_iobus.c (hw_iobus_attach_address_callback): Change the iobus
+ so that it is implementing a 1-1 address map.
+
+ * emul_generic.c (emul_add_tree_hardware): Adjust.
- * std-config.h (EVENTS_INLINE): Inline events in psim.
+ * emul_generic.c (emul_add_tree_hardware): Don't add the nvram as
+ a default.
-Wed Dec 13 22:01:21 1995 Andrew Cagney <cagney@highland.com.au>
+Sun Nov 17 17:59:14 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
+
+ * device.c (split_find_device): Be tolerant of missing unit
+ addresses.
- * device_table.c (htab_sum_binary): DMA binaries to correct byte
- within a page.
+Fri Nov 15 16:49:49 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
-Tue Dec 12 22:51:18 1995 Andrew Cagney <cagney@highland.com.au>
+ * basics.h (port_direction): New type, specify the direction of
+ any `port'.
+
+ * device.h, device.c (device_interrupt_decode): Include
+ specification of port direction in operations.
+ (device_interrupt_encode): Ditto.
+
+ * device_table.h: Add a direction field to the interrupt port
+ table.
- * psim.c (psim_merge_device_file): Change `=' to `==', was this an
- error?
+ * device.c (device_tree_add_parsed): Specify port direction.
+
+Thu Nov 14 21:38:13 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
-Tue Dec 5 11:56:14 1995 Andrew Cagney <cagney@highland.com.au>
+ * hw_opic.c: Finish - second round.
- * ppc-instructions (ppc_nr_mtcrf_crs, ppc_branch_conditional_name,
- ppc_function_unit_name): Simplify by declaring these arrays as
- pure and simple static (instead of STATIC_MODEL).
+Thu Nov 7 00:18:59 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
-Tue Dec 5 00:45:34 1995 Andrew Cagney <cagney@highland.com.au>
+ * hw_htab.c (htab_init_data_callback): Allow the virtual-address
+ to be specified as an array which allows 64bit addresses.
- * sim_calls.c (sim_create, sim_load), main.c (main), psim.c: Pass
- an options device into psim_create() so that options can be merged
- into the tree.
+ * device.c (device_find_integer_array_property): New function.
+ Simplify the querying of elements of an integer array.
+ (device_add_integer_property, device_find_integer_property):
+ Update to correctly use the cell type.
- * device.c (*add*): Change semantics so the add functions only add
- when the new device (or property) doesn't already exist. This
- allows merging of options and data.
+ * vm.c (om_unpack_sr): Clarify shifting comment.
+ (om_pte_0_masked_vsid): Ditto. Add 64bit version.
-Mon Dec 4 17:12:13 1995 Andrew Cagney <cagney@highland.com.au>
+ * emul_chirp.c (emul_chirp_create): Initialize the segment
+ registers.
- * Makefile.in (BASICS_H): Didn't include basics.h in the list of
- header files to depend on.
+ * vm.c (om_effective_to_virtual): Trace segment register use.
-Mon Dec 4 17:12:13 1995 Andrew Cagney <cagney@highland.com.au>
+ * hw_htab.c (htab_map_page): Print out the pteg base address to
+ simplify cross checking between vm and the htab.
+ (htab_decode_hash_table): Use device_error instead of error.
+ (htab_map_page): Ditto.
+ (htab_dma_binary): Ditto.
+ (htab_map_binary): Ditto.
+ (htab_init_data_callback): Ditto.
- * std-config.h: (*_MODULE): Extend the <module>_inline macro's so
- that they also allow control over static functions. Rewrite
- document to reflect this.
+Wed Nov 6 20:20:58 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
- * std-config.h: (INLINE): Simplify definition, the above and
- earlier changes to igen.h eliminate the need to be defensive about
- enabling the inline of static functions.
+ * interrupts.h: Clarify what the optional instruction program
+ interrupt is - a subset of illegal instruction program interrupt.
+
+ * interrupts.c (program_interrupt): For UEA mode, clarify what an
+ optional instruction program interrupt is.
+ (program_interrupt): For OEA mode, as per spec, generate an
+ illegal instruction program interrupt when an optional instruction
+ is encountered.
+
+ * gen-semantics.c (print_semantic_body): Delete code
+ differentiating between an unimplemented floating point and normal
+ instruction. Instead, such a case can be handled explicitly.
+
+ * ppc-instructions (store floating-point as integer word indexed):
+ Mark as optional.
+ (Floating Convert to Integer Doubleword): Make the floating point
+ assist interrupt explicit.
+ (Floating Convert To Integer Doubleword with round towards Zero):
+ Ditto.
+ (Floating Convert To Integer Word): Ditto
+ (Move From FPSCR): Ditto.
+ (Move to Condition Register from FPSCR): Ditto.
+ (Move To FPSCR Fields): Ditto.
+ (Move To FPSCR Field Immediate): Ditto.
+ (Move To FPSCR Bit 0): Ditto.
+ (Move To FPSCR Bit 1): Ditto.
+
+Mon Nov 4 12:49:13 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
- * std-config.h: (SIM_ENDIAN_INLINE, BITS_INLINE): Document limited
- suport for inlineing of modules for all callers. Adjust relevant
- macro's so that DEFAULT_INLINE will enable this.
+ * corefile.c (core_map_read_buffer, core_map_write_buffer): Avoid
+ breaking up transfers.
- * basics.h: Re-order #includes and definitions so that c-code for
- basic include files does not call functions delcared in later
- #includes.
+ * corefile.c: Adjust arguments so that the client server
+ relationship is clarified.
+
+ * hw_glue.c (hw_glue_init_address): Update so it can be attached
+ to a PCI bus.
- * basics.h (__attribute__), sim_callbacks.h: Move attribute macro
- to basics.h and add hack (include <stdio.h>) to try and bring that
- and other possible conflicting macros into scope much earler.
+ * hw_disk.c (hw_disk_instance_write): Add more checks to disk IO -
+ looking for things like overflow/underflow.
- * sim-endian.h,c (SIM_ENDIAN_INLINE) bits.h,c (BITS_INLINE):
- Change to use the updated inline definitions. If enabled
- immediatly include the corresponding c-code so that it will inline
- for all modules.
+Sun Nov 3 18:45:20 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
- * inline.h, inline.c (SIM_ENDIAN_INLINE, BITS_INLINE): Remove
- these cases, moved to module specific header files.
+ * emul_generic.c (emul_add_tree_hardware): Hang the disk off the
+ PAL device instead of the IOBUS. The disk must be attached to a
+ logical bus.
-Sat Dec 2 18:37:51 1995 Andrew Cagney <cagney@highland.com.au>
+ * hw_disk.c (hw_disk_init_address): Just use the unit address
+ directly in the attach - the rest isn't relevant.
- * vm.c, vm_n.c: Fix htab code.
+Sat Nov 2 21:48:57 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
- * vm.c (vm_data_map_read_buffer): Was using EA not RA when reading
- the data from core.
+ * configure.in (sim-hardware, sim-packages): Allow additional
+ hardware and packages to be prefixed as well as appended.
- * device.c: Fix htab create code.
+ * Makefile.in (tmp-hw, tmp-pk): Retain the user specified order of
+ packages when building them. Consequently, a user can override a
+ standard device by prefixing their own version.
+
+ * Makefile.in (hw_opic.o, hw_pci.o, hw_ide.o): Add dependencies.
-Fri Nov 24 23:10:09 1995 Andrew Cagney <cagney@highland.com.au>
+Fri Nov 1 14:42:57 1996 Michael Meissner <meissner@tiktok.cygnus.com>
- * bits.h, bits.c (EXTRACTED): Convert to function, fix - had &&
- instead of &.
+ * mon.c (_cpu_mon): Add fields for counting 1, 2, 4, and 8 byte
+ reads and writes.
+ (mon_{read,write}): Count 1, 2, 4, and 8 byte reads/writes.
+ (mon_print_info): Correct typo regarding # of unaligned reads and
+ writes. Print out how many 1, 2, 4, and 8 byte reads/writes there
+ are.
- * sim-endian.h (SWAP_N), sim-endian-n.h, sim-endian.c: How
- embarasing - fix yet another bug in the swap code! Simplify
- everything by using more functions. Add host to big-endian byte
- swapping support.
+Tue Oct 29 17:55:43 1996 Michael Meissner <meissner@tiktok.cygnus.com>
-Fri Nov 24 23:10:09 1995 Andrew Cagney <cagney@highland.com.au>
+ * configure.in (AC_CHECK_FUNCS): Add access.
+ * config{.in,ure}: Regenerate.
- * devices.h, devices.c: delete, replaced by the files
- device_table.[ch] and device.[ch].
- * device_tree.h, device_tree.c: ditto
+ * emul_unix.c (do_unix_nop): System call that always succeeds.
+ (do_unix_access): Support access system call.
+ (solaris_descriptors): Make sigaltstack and sigaction nops.
+ ({solaris,linux}_descriptors): Add support for access.
- * device_table.h, device_table.c: New files. Contain a table of
- devices.
+Tue, 8 Oct 18:42:26 1996 Jason Molenda <crash@cygnus.co.jp>
+
+ * Makefile.in (clean): Move config.log to distclean.
- * device.h, device.c, Makefile.in, std-config.h (DEVICE_INLINE),
- options.c (print_options): New files. Define the device object
- along with any attached properties.
+Fri Nov 1 16:44:28 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
- * device_tree.h, device_tree.c: Update to use new device object.
- For convenience, change the printd functions into device_tree_add
- functions.
+ * corefile-n.h (core_map_write_N): Improve abort messages.
- * psim.c (create_*_tree): Use new device_tree create functions.
+ * device.h, device.c (device_attach_address): Remove unused name
+ parameter.
+ (device_detach_address): Ditto.
+ * device_table.h, device_table.c: Update.
+ * hw_iobus.c (hw_iobus_attach_address_callback): Ditto.
+ * hw_nvram.c (hw_nvram_init_address): Ditto.
+ * hw_memory.c (hw_memory_init_address): Ditto.
+ * hw_vm.c (hw_vm_init_address_callback): Ditto.
+ (hw_vm_attach_address): Ditto.
+ (hw_vm_add_space): Ditto.
+ * hw_init.c (update_for_binary_section): Ditto.
+ * hw_core.c (hw_core_attach_address_callback): Ditto.
- * corefile.h, corefile.c corefile-n.h (core_n.h): Update to use
- the new device.h / device_table.h interface. Rename core_n.h to
- corefile-n.h to be consistent with other n files.
+ * hw_iobus.c (hw_iobus_attach_address_callback): Rewrite to handle
+ configurable parent busses.
- * Makefile.in (run): add corefile-n.h to dependencies for
- corefile.
+Wed Oct 30 18:46:32 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
- * basics.h (device_instance), device.h, device.c, device_table.h,
- device_table.c: Add the concept of a device instance and operators
- on these instances - corresponds to ihandle in OpenBoot speak.
- Don't yet implement it.
+ * device_table.c (generic_device_size_to_attach_size): Provide
+ limited support for multi-cell sizes.
+ (generic_device_address_to_attach_address): Ditto for addresses.
-Tue Nov 14 12:27:08 1995 Andrew Cagney <cagney@highland.com.au>
+Tue Oct 29 02:01:29 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
- * emul_generic.h, emul_generic.c (emul_syscall_enter,
- emul_syscall_exit): rename from emul_enter_call /
- emul_exit_call. As only used by emul_do_system_call simplify
- associated code.
+ * device.c (device_add_integer_property): Check for setting of
+ #address-cells and #size-cells properties. For these, update the
+ corresponding device values.
+ (device_nr_address_cells, device_nr_size_cells): Use the value
+ from the device instead of the property.
- * os_emul.h, os_emul.c, emul_generic.h: Correct and fill an
- os_emul interface.
+ * hw_core.c: Use generic address and size conversions for the top
+ bus.
- * os_emul.c, emul_bugapi.h, emul_bugapi.c, Makefile.in: Add
- preliminary hooks for a kernel mode rom emulation.
-
- * cap.h (new), cap.c (new): Capability data base. Some emulations
- pass object identifiers (capabilities?) to/from the simulated code
- (for instance the phandle in OpenBoot). The cap object is able to
- check/map between internal and external (target program)
- representations of each identifier.
+ * hw_memory.c (hw_memory_init_address): Tolerate case where
+ #address and #size cells is greater than 1.
+
+ * device.c (device_tree_print_device): Clean out printing of
+ properties.
- * os_emul.c, emul_chirp.h, emul_chirp.c, Makefile.in: Add
- preliminary hooks for a kernel mode IEEE-1275 emulation.
+ * device.c (split_device_specifier): Don't detect comments here -
+ "#" can be a valid prefix - eg #size-cells.
+
+ * psim.c (psim_merge_device_file): Suppress comments and blank
+ lines here.
+
+ * emul_generic.c (emul_add_tree_hardware): Fix typo of incorrect
+ pal unit address. Add the property /#address-cells to the root of
+ the tree.
+
+ * device.c (device_template_create_device): Check that the unit
+ address was successfully parsed.
+
+ * device_table.c (generic_device_unit_decode): Rewrite to better
+ handle multi-cell addresses.
+ (generic_device_unit_encode): Ditto.
+
+ * emul_generic.c (emul_add_tree_hardware): "reg" properties no
+ longer need the explicit array type - the parser takes care of it.
- * cpu.h, cpu.c (cpu_create, cpu_os_emulation, cpu): Add os_emul to
- list of arguments passed in when creating a cpu. Grant access to
- the element.
+ * pk_disklabel.c (pk_disklabel_create_instance): Add NULL return
+ to keep GCC happy.
- * std-config.h (OS_EMUL_INLINE), options.c (print_options),
- inline.h, inline.c: New to allow control over inline of
- corresponding code files.
+Mon Oct 28 22:55:48 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
- * ppc-instructions (instruction_call): Add illegal instruction to
- call the instruction-call emulation handler.
+ * hw_ide.c: New file. Model of a basic IDE interface attached to
+ a PCI bus.
- * interrupts.c (system_call_interrupt): Call renamed
- os_emul_system_call function().
+ * configure.in (hardware): Add the ide device to the default
+ configuration.
+ * configure: Regenerate.
+
+ * debug.h, debug.c: Add tracing option for the IDE device.
+
+Fri Oct 25 21:28:25 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
- * emul_netbsd.c: Update to interface to generic emulation. Since
- all its functions are called via a table don't worry about any
- inline.
+ * hw_phb.c, hw_phb.h: New files - implement a PHB.
- * emul_generic.h, emul_generic.c, spa-*(delete): Remove references
- and code for spa, no longer to be used.
+ * configure.in (hardware): Add the phb to the list of devices to
+ build by default.
- * psim.c (create_chirp_device_tree): Fill out what was previously
- the openboot create function so that it starts to create a full
- OpenBoot device tree.
+Fri Oct 25 21:28:25 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
-Tue Nov 28 21:48:06 1995 Andrew Cagney <cagney@highland.com.au>
+ * hw_com.c: Review description.
+ * hw_disk.c: Ditto.
+ * hw_htab.c: Ditto.
+ * hw_eeprom.c: Ditto.
+ * hw_init.c: Ditto.
+ * hw_cpu.c: Ditto.
+
+ * hw_com.c: Update event handling.
- * debug.h, debug.c: pte trace is made redundant by htab trace,
- delete it. Add vm to list of options. Simplify tracing output so
- lines are not as long.
+ * hw_disk.c: Implement tracing.
+
+Fri Oct 25 21:28:25 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
-Tue Nov 14 12:27:08 1995 Andrew Cagney <cagney@highland.com.au>
+ * device_table.c (generic_device_init_address): Use
+ assigned-addresses property in preference to any other reg
+ property.
- * events.h, events.c (event_queue_init), psim.c (psim_init): (re)
- initialize the event queue.
+Fri Oct 25 21:28:25 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
+ * device.h, device.c (device_find_ranges_property): New function.
+ Simplify the manipulation of "ranges" properties.
+
+ * device.c (device_add_parsed): Extend to include support for the
+ ranges property.
+ * device.c (device_add_parsed): Add assigned-addresses to the list
+ of reg type properties.
+
+ * device.c (device_tree_print_device): Add code to format and
+ print a ranges property.
+
+ * device.h, device.c (device_nr_address_cells,
+ device_nr_size_cells): New functions. Determine the values of the
+ standard properties #address-cells and #size-cells. Both of which
+ are optional and have default values of two and one respectfuly.
+ Previously, code that determined #address-cells was incorrectly
+ using a value of one.
+Fri Oct 25 21:28:25 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
+ * debug.h, debug.c: Sort debug options, Add entries for the
+ comming PHB device.
+
+Fri Oct 18 12:12:21 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * ppc-instructions (Floating Select): Add support for fsel unless
+ model is 601. Allow user to filter out instruction unless -Fs is
+ passed to igen.
+ (Store Floating-Point as Integer Word Indexed): Raise optional
+ instruction program abort. Allow user to filter out instruction
+ unless -Fs is passed to igen.
+ (Floating Square Root{, Single}): Ditto.
+ (Floating Reciprocal Estimate Single): Ditto.
+ (Floating Reciprocal Square Root Estimate): Ditto.
+
+ * configure.in (--enable-sim-filter): If not passed, pass 32,f,s
+ to igen.
+ * configure: Regenerate.
+ * interrupts.h (program_interrupt_reasons): Add
+ optional_instruction_program_interrupt.
-Tue Nov 28 13:38:26 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+ * interrupts.c (program_interrupt): Call error with more detailed
+ information on program interrupts, particularly in user mode. Add
+ support for optional_instruction_program_interrupt.
- * sim-endian.h: Look at WORDS_BIGENDIAN to determine if the host
- is big endian or little endian. For SWAP_n, use htonl/htons if
- host is little endian, not big endian and if WITH_NTOH is defined.
+Wed Sep 25 10:20:29 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
- * configure{,.in} (--enable-sim-model-issue): Instead of defining
- 0/1, define it to be MODEL_ISSUE_{PROCESS,IGNORE}. Add
- AC_C_BIGENDIAN to determine if the host is big endian or not.
- * config.in: Regenerate.
+ * hw_glue.c: New device. Hooks for manipulating interrupt ports.
- * std-config.h (WITH_MODEL_ISSUE): Default to 0.
- (CURRENT_MODEL_ISSUE): Reference WITH_MODEL_ISSUE, and if that is
- 0, use current_model_issue.
- (MODEL_ISSUE_{PROCESS,IGNORE}): Define as -1/1.
+ * debug.h, debug.c (trace_glue_device): Add tracing support for
+ the interrupt glue logic device.
- * psim.c (current_model_issue): New global variable.
+ * configure.in (hardware): Add glue device.
+ * configure: Regenerate.
- * cpu.c (cpu_create): Use CURRENT_MODEL_ISSUE > 0 instead of
- WITH_MODEL_ISSUE.
- (cpu_{init,halt}): Ditto.
- * mon.c (mon_print_info): Ditto.
- * ppc-instructions (PPC_INSN_* macros, branch handling): Ditto.
+Tue Sep 24 20:55:38 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
- * mon.c (mon_print_info): Print instructions/second if verbose > 0,
- rather than > 1.
+ * device.c (device_tree_parse_integer_property): New function,
+ parse a list of integers as an array property.
+ (device_tree_add_parsed): Call it.
- * main.c (main): Set current_model_issue to MODEL_ISSUE_PROCESS if
- the -I switch is used.
- * sim_calls (sim_open): Ditto.
+ * device.c (device_tree_parse_string_property): New function,
+ parse a list of strings as a string property (with embeded
+ null's). For moment, don't try to implement a complext string
+ parser.
+ (device_tree_add_parsed): Call it.
- * ppc-instructions (model support): Add support for determining
- when we don't have enough writeback slots. Add tracing for the
- beginning of each cycle.
+Tue Sep 24 16:30:48 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
-Mon Nov 27 17:46:33 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+ * hw_opic.c: New file. OpenPIC interrupt controller.
- * mon.c: Check for whether to include sys/types.h and sys/time.h.
+ * configure.in (hardware): Add opic device.
+ * configure: re-generate.
- * configure.in: Check for include files sys/types.h and
- sys/time.h.
- * configure: Regenerate.
- * config.in: Regenerate.
+ * hw_pic.c: Delete, replaced with hw_opic.c.
- * cpu.h (CONST_ATTRIBUTE): Define as __attribute__((__const__)) if
- not already defined.
- (cpu_system): Use CONST_ATTRIBUTE, so that when we're not inlining
- the world, the optimizer has a fair chance of CSE'ing function
- calls.
- (cpu_{monitor,nr,registers,model}): Ditto.
-
- * std-config.h (MODEL_INLINE): If not defined, define as 1 if
- DEFAULT_INLINE is non-zero, 0 otherwise, rather than just the
- value of DEFAULT_INLINE.
-
-Fri Nov 24 11:24:34 1995 Michael Meissner <meissner@tiktok.cygnus.com>
-
- * lf.h (__attribute__): If not GCC and at least 2.7.0, define as
- nothing.
- (lf_printf): Add printf __attribute__, so the compiler will
- automatically check the format string.
-
- * configure{,.in} (--enable-sim-icache): If argument is define,
- add -R to flags passed to igen.
-
- * igen.c (stdlib.h): Include if the system supplies one.
- (semantics_use_cache_struct): New global for -R flag to say
- semantics is to use the cache structure directly rather than
- putting the values into local variables.
- (first_undef, last_undef): New structures to remember names to
- #undef if -R.
- (lf_print_c_extraction): If -R and this is semantics, emit names
- as #defines pointing to the cache structure, rather than loading
- the values into local variables.
- (lf_print_c_semantic_function): If -R, #undef all of the names
- defined in lf_print_c_extraction.
- (main): Recognize -R.
-
- * idecode_fields.h (SPR_*): Redefine spr_* macros as SPR_* to
- avoid a name confict if -R passed to igen.
-
- * ppc-instructions (mfspr, mtspr): Rename spr field to SPR.
- (model_data): Add field to count the various # of CRs that the
- mtcrf instruction used.
- (model_mon_info): Return structures counting the # of CRs that the
- mtcrf instruction used.
- (branches, sync instructions): Do not call model functions if
- WITH_MODEL_ISSUE is 0.
-
- * mon.c (stdlib.h): Include if the system supplies one.
- (mon_sort_instruction_names): New function to sort instruction
- names alphabetically.
- (mon_print_info): Call qsort with mon_sort_instruction_names to
- sort instruction names. Don't abort if WITH_MODEL_ISSUE is 0.
-
- * debug.h (ITRACE): Make printf_filtered arguments type correct.
- * idecode_expression.h (CR0_COMPARE): Ditto.
- * psim.c (psim_read_register): Ditto.
-
- * igen.c (lf_print_my_prefix): Use __attribute__((__unused__)) to
- silence compiler warnings about unused automatically generated
- variables.
- (lf_print_c_extraction): Ditto.
- * idecode_expression.h (FPSCR_BEGIN): Ditto.
-
- * ppc-cache-rules: Define rules for making a bitmask for all
- registers.
-
- * ppc-instructions: Rewrite model specific functions to use the
- bitmask of the register number, instead of using the register
- pointer to get the register number, and then making the bitmask.
-
-Wed Nov 22 15:24:27 1995 Michael Meissner <meissner@tiktok.cygnus.com>
-
- * ppc-instructions (model_branches): Add conditional argument to
- count the number of times each type of conditional branch is used.
- (conditional branches): Pass B0 or -1 to model_branches.
- (model_mon_info): Print out conditional branch counts.
- (model-data): Add support for printing out conditional branch
- types.
-
-Tue Nov 21 16:31:25 1995 Michael Meissner <meissner@tiktok.cygnus.com>
-
- * igen.c (insn_table_load_insns): Add support for model-static for
- internal functions that should not be inlined.
- (lf_print_c_semantic): Remove model_cleanup.
- (gen_model_{c,h}): Ditto.
-
- * ppc-instructions: Redo model specific support once again. Add
- floating point support to the model specific information. Flesh
- out all of the floating mutiply add/subtract instructions. Add
- better tracing support to the model specific information.
-
-Sun Nov 19 23:00:52 1995 Michael Meissner <meissner@tiktok.cygnus.com>
-
- * ppc-instructions (model data, model_busy): Rather than using a
- bit mask for the busy units, just use a char array. Also, only
- support 2 function units an insn can use, rather than a loop.
-
-Fri Nov 17 14:08:08 1995 Michael Meissner <meissner@tiktok.cygnus.com>
-
- * table.c (table_entry_read): Move setting entry->line_nr to after
- the model specific fields so the line numbers for the annex are
- correct.
-
- * cpu.c (cpu_{create,init,halt}): Check for WITH_MODEL_ISSUE
- before calling the model functions.
-
- * debug.c (trace_descriptor): Add trace_model support.
- * debug.h (trace_options): Ditto.
-
- * igen.c (gen_icache_h): Create type idecode_cache as void if not
- caching instructions.
- (gen_model_{c,h}): Drop model_issue support. Add support for
- model_cleanup.
- (lf_print_my_prefix): Initialize a const itable_index with the
- current index.
- (lf_print_c_semantic): Call model_cleanup at the end of the
- function to check for instructions that aren't supported yet by
- the scheduling code.
-
- * mon.h (count_type): New type for counters.
- * mon.c: Use count_type instead of unsigned.
-
- * ppc-instructions: Redo scheduling code once again. Make it all
- inline friendly. Instead of having general code emitted by igen,
- go the route of having each semantic routine call the appropriate
- module.
-
-Thu Nov 16 09:52:26 1995 Michael Meissner <meissner@tiktok.cygnus.com>
-
- * table.c (table_entry_read): Allow the annex to have blank lines.
-
- * ppc-instructions: Change lines in model stuff that just have a
- tab to just newline. Add 601 support. Document most instructions
- in terms of model specific timing information. Drop 'FUNCTION'
- from PPC_FUNCTION_UNIT_xxx enums. Change PPC_UNIT_UNKNOWN ->
- PPC_UNIT_BAD. Add TRACE(trace_tbd) for all data cache
- instruction.s. Signal illegal instruciton if data cache block
- invalidate is issued from problem state.
-
- * igen.c (max_model_fields_len): New static to keep track of the
- max size for the model specific fields.
- (model_c_insn): Use max_model_fields_len to size fields.
- (insn_table_insert_insn): Set max_model_fields_len.
- (model_table_insert): Ditto.
- (gen_model_{c,h}): Model_issue is now called with a processor
- argument.
-
- * debug.c (trace_description): Add support for trace_tbd.
-
- * mon.c (mon_issue): Pass processor argument to model_issue.
-
- * Makefile.in: Delete all function unit support, since the newer
- table driven model support replaces it.
- * cpu.{c,h}: Ditto.
- * mon.c: Ditto.
- * inline.{c,h}: Ditto.
- * std-config.h: Ditto.
- * options.c: Ditto.
- * configure{,.in}: Ditto.
- * Makefile.in: Ditto.
- * psim.c: Ditto.
- * function_unit.{c,h}: Delete these now usused files.
-
- * std-config.h (WITH_MODEL_ISSUE): Add new macro on whether to
- trace instructions in a model specific manor.
- * options.c (print_options): Print it out.
- * configure{,.in}: Add --enable-sim-model-issue option.
- * Makefile.in: Add --enable-sim-model-issue flags.
- * igen.c (lf_print_c_semantic): Add call to mon_issue here. Check
- for WITH_MODEL_ISSUE.
- * mon.c (mon_issue): Remove call to mon_issue_here.
-
- * ppc-instructions: Move branch tracing to the actual branch
- instructions, rather than testing it in model_issue. Add code to
- code successful/unsuccessful branch predictions, and the number of
- conditional branches that fell through.
-
-Wed Nov 15 17:32:13 1995 Michael Meissner <meissner@tiktok.cygnus.com>
-
- * cpu.h (cpu_model): Add declaration.
-
- * cpu.c (struct _cpu): Add model_ptr to hold model specific
- information.
- (cpu_model): Return the model internal pointer.
- (cpu_{create,init,halt}): Call the appropriate model function.
-
- * inline.c (mon.c): Move include of mon.c after model.c.
-
- * mon.c (_cpu_mon): Add fields to count unaligned memory
- references.
- (mon_issue): Call model_issue, not function_unit_issue.
- (mon_{read,write}): Count # of unaligned memory accesses.
- (mon_print_info): Switch to calling model_mon_info and
- model_mon_info_free instead of function_unit version. Print out
- number of unaligned reads/writes.
-
- * {ppc-instructions,igen.c}: More global changes to add model
- specific features.
-
- * inline.{c,h}: Provide for inlining options.c.
- * options.{c,h}: Ditto.
- * std-config.h: Add OPTIONS_INLINE.
-
-Tue Nov 14 04:47:25 1995 Michael Meissner <meissner@tiktok.cygnus.com>
-
- * Makefile.in (devices.o, main.o): Update dependency.
-
- * igen.c (gen_model_h): Use correct variable in loop.
- (gen_model_c): Use strcmp, strcasecmp.
- (gen_model_c): Use EXTERN_MODEL for arrays.
- (gen_model_h): Use STATIC_MODEL for arrays.
- (lf_print_c_semantic_function_header): Delete unused function.
-
- * main.c (cpu.h): Include cpu.h to get model.h.
-
- * inline.h ({EXTERN,STATIC}_MODEL): Define.
-
-Mon Nov 13 09:14:13 1995 Michael Meissner <meissner@tiktok.cygnus.com>
-
- * igen.c ({insn,model}_table_fields): Spell mnemonic correctly.
- (gen_itable_h,itable_c_insn): Ditto.
- (model support): Move model support around, add support for
- model-data, model-internal. Use annex field for model-macros
- now.
-
- * configure.in (--enable-sim-inline): If --enable-sim-inline=no,
- also define INLINE as nothing.
- * configure: Regenerate.
+ * debug.h, debug.c: Add debug option for OpenPIC device. -
+ opic-device.
- * std-config.h (INLINE): Rather than nuking INLINE, only define it
- as __inline__ if any of the INLINE flags are non-zero.
+Tue Sep 24 16:30:48 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
- * options.c (print_options): Print out WITH_XOR_ENDAIN.
+ * Makefile.in (psim.o, idecode.o): Since idecode and not psim is
+ now the file that does all the inlining.
-Mon Nov 13 23:03:45 1995 Andrew Cagney <cagneyhighland.com.au>
+ * Makefile.in (LIB_SRC, LIB_INLINE_SRC, idecode.o): Break out the
+ library source code that could be involved in an inlining. Make
+ idecode.o only dependant on the inlined library source code.
- * ppc-instructions (rfi): Add missing code.
+ * Makefile.in (LIB_OBJ): Put options last on the list so that it
+ is compiled last.
- * cpu.c (cpu_get_time_base): Fix calculation of current value of
- time base register.
+ * std-config.h (DEVICE_INLINE): Only inline locals when the
+ default is to inline.
- * ppc-spr-table (TBL, TBU): Fix TBL/TBU entries - was confusing
- m[tf]tb with m[tf]spr.
+Mon Sep 23 00:37:49 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
- * ppc-instructions (mtspr, mfspr): Fix mttbl - wasn't storing
- lower word.
+ * hw_htab.c (htab_sum_binary): Determine the real-base for the
+ binary.
-Mon Nov 13 21:35:37 1995 Andrew Cagney <cagneyhighland.com.au>
+ * hw_htab.c (htab_map_binary): Depending on the value of the
+ load-base, either map the program in as a contiguous section or as
+ separate sections controled by th binaries lma values.
+ (htab_init_data_callback): Ditto.
- * std-config.h (INLINE, STATIC_INLINE): Was being set to static
- inline.. Only problem being that with ppc-opcode-simple this gave
- it the chance to inline all the idecode functions with potentially
- disasterous results on a 16mb PC. For moment hobble INLINE.
+Sun Sep 22 15:56:22 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
- * configure.in, std-config.h (WITH_SMP): Make that 5 processors by
- default ...
+ * emul_generic.c (emul_add_tree_options): Remove load-base option.
- * configure.in: Tweek flags passed to gcc for --with-sim-warnings.
- Firstly make them errors and secondly remove the options gcc-245
- doesn't reconize.
+ * emul_chirp.c (map_over_chirp_note): Add load_base field to note
+ struct. Don't require the load_base field to be present - just
+ issue warning - it is a recent addition.
+ (emul_chirp_create): Support both virtual and physical modes.
-Mon Nov 13 17:57:24 1995 Andrew Cagney <cagney@highland.com.au>
+ * emul_chirp.c (emul_chirp_create): Add a stack initialization
+ property so that any arguments specified on the command line can
+ be passed on to user programs.
- * misc.c (zalloc), cpu.c (cpu_init), devices
- (console_io_read_buffer_callback, icu_io_read_buffer_callback,
- vm_io_read_buffer_callback), main.c (zalloc), mon.c (memset),
- sim_calls.c (zalloc) : replace bzero() with memset().
+ * hw_init.c (create_ppc_chirp_bootargs): Add support for chirp
+ argument passing to the pseudo device stack.
- * emul_netbsd.c (write_direntries), psim.c (psim_read_register,
- psim_write_register): replace bcopy() with memcpy().
-
-Sun Nov 12 20:55:41 1995 Andrew Cagney <cagneyhighland.com.au>
+Sat Sep 21 19:39:56 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
- * configure.in: for --disable-sim-inline (--enable-sim-inline=no),
- force DEFAULT_INLINE to 0 rather then trusting the std
- configuration.
+ * device.c (device_error): Make it more tolerant to incomplete
+ devices.
-Sun Nov 12 20:55:41 1995 Andrew Cagney <cagneyhighland.com.au>
+ * hw_init.c (hw_data_init_data_callback): Extend the data device
+ so that it can perform initialization operations either dma or a
+ more complex instance open, seek, write operation.
+ * hw_init.c: Update the description of the data device to reflect
+ this.
- * igen.c (lf_print_idecode_table, idecode_table_leaf): Fix
- generation of switch entries in tables - treat the same as
- cracking/semantic functions.
+Sat Sep 21 00:13:02 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
- * igen.c (idecode_switch_end, idecode_switch_leaf): Fix generation
- of a boolean switch statement (field zero or non-zero).
+ * device.c (device_event_queue_schedule,
+ device_event_queue_deschedule, device_event_queue_time): Have the
+ device object export the event operations. Making these available
+ from the device object should hopefully simplify writing device
+ models.
- * ppc-opcode-test-1, ppc-opcode-test-2: New files. These test the
- switch/table generation ability of igen.
+Fri Sep 20 14:04:40 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
- * igen.c (idecode_switch_leaf): Fix code output when a switch
- statement needs to look up a table.
+ * configure.in (sim-hardware): Add eeprom device to default build.
- * igen.c (idecode_declare_if_switch): New function called from
- gen_idecode_c - need to declare any idecode switch functions
- before they are used in idecode tables.
+ * hw_eeprom.c: Rewrite so it works.
- * igen.c (lf_print_c_cracker_function, idecode_crack_leaf,
- idecode_crack_insn): Add is_inline_function argument to code
- printing cracker functions which indicates if STATIC_IDECODE or
- STATIC_INLINE_IDECODE should be used for definition. For
- idecode_crack_insn (which implies not duplicating/expanding) don't
- declare function as inline - we assume that the only time this is
- code is generated is when things are being tested. For
- idecode_crack_leaf, make static (instead of INLINE) if the
- instructions parent is a table as function will always be called
- via a table.
+ * debug.h, debug.c: Add tracing support for the eeprom and com
+ devices.
- * igen.c (idecode_expand_if_switch): Declare as STATIC_IDECODE not
- STATIC_INLINE_IDECODE. Only the outermost idecode switch will be
- called directly, all others are called via a table.
+Thu Sep 19 14:40:40 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
- * igen.c (lf_print_semantic_function_header, semantics_h_leaf,
- semantics_h_insn, semantics_h_function,
- lf_print_c_semantic_function, semantics_c_function): Add
- is_inline_function argument to lf_print_semantic_function_header
- to indicate if an inline or static function declaration/definition
- should be output. Depending on situtation call accordingly:
- functions (not instruction semantic routines) are always inline;
- Semantic routines are made inline when there is no icache (cache
- will contain the function address) and are duplicating (see above)
- and the parent of the instruction is a switch statement.
+ * debug.h: Add disklabel-package and disk-device trace options.
+ debug.h (PTRACE): Add macro to simplify tracing in packages.
- * igen.c (opcode_field_new): Delete. Code changed to use ZALLOC
- and moved to insn_table_find_opcode_field.
+Thu Sep 19 14:40:40 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
- * table.c (table_open): Fix typo (nr_model_fields vs nr_fields).
+ * device.c (device_create_instance_from): Tighten up loop
+ searching for device instances.
+ (device_instance_delete): Ditto.
+ (device_instance_delete): Only leaf instances need to be removed
+ from a devices list of active instances.
- * igen.c (model_c_insn): Suggestion - document the name of the
- instruction on each line of the instruction model table.
+Thu Sep 19 14:40:40 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
-Fri Nov 10 00:44:38 1995 Andrew Cagney <cagneyhighland.com.au>
+ * hw_disk.c: Add the cdrom as an alias.
- * emul_netbsd.c (do_ioctl): Cleanup compilation.
+ * pk_disklabel.c (disklabel_delete): Implement, remembering to
+ delete the raw disk instance while we're at it.
- * sim_callbacks.h (__attribute__): Only define if not defined (was
- already defined on NetBSD host).
+ * pk_disklabel.c (pk_disklabel_create_instance): Implement a
+ little bit more - still a long way to go.
-Wed Nov 8 21:49:52 1995 Andrew Cagney <cagneyhighland.com.au>
+ * pk_disklabel.c (disklabel_write, disklabel_read): Remember the
+ new head position after a read or write.
- * std-config.h (WITH_XOR_ENDIAN), configure.in, Makefile.in: New
- macro, indicates if the PowerPC's horrible XOR endian mode should
- be suported. Add to configure and make.
+Thu Sep 19 13:05:40 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
- * vm_n.h (vm_data_map_read_N, vm_data_map_write_N), vm.c
- (vm_instruction_map_read): If XOR endian, xor the address
- with a value from an xor table (indexed by size of access).
+ * emul_chirp.c (chirp_emul_read): Allow reads to be longer then
+ the internal buffer.
- * vm.c (vm_synchronize_context), cpu.c (cpu_synchronize_context):
- set up xor table to xor if there is a conflict between the
- CURRENT_TARGET_ENDIAN and the endian indicated in the MSR. Move
- check of suported change of endian mode from cpu.c to vm.c.
+Thu Sep 19 13:05:40 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
- * vm.c (vm_data_map_write_buffer, vm_data_map_read_buffer):
- Hopefully added correct hack to handle XOR endian mode.
+ * emul_chirp.c (chirp_read_t2h_args): Call memset-0 with the args
+ in the correct order.
- FIXME: If NONSTRICT alignment and XOR ENDIAN and MSR indicates
- little endian mode, the model accepts miss aligned transfers.
+ * emul_chirp.c (chirp_emul_call_method): Correct computation for
+ the address of the first stack argument passed in from the client
+ program.
- FIXME: Need to create an `init' device that, during
- initializatioin for XOR mode, it mushes (XOR address) all the dma
- data before passing it on to the core for storage. Just like the
- real thing really.
+Wed Sep 18 19:33:54 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
-Wed Nov 8 21:49:52 1995 Andrew Cagney <cagneyhighland.com.au>
+ * words.h: Add new types signed_cell and unsigned_cell which
+ correspond to the signed and unsigned IEEE 1275 memory locations.
+ * device.h, device.c, emul_chirp.c: Where refering to an IEEE 1275
+ memory cell, replace uses of unsigned32 with unsigned_cell.
+ * device_table.h: Ditto.
- * devices.c (halt_io_write_buffer_callback): Use value written to
- halt device to determine exit status. Thus allowing
- success/failure of OEA tests.
+ * sim-endian.h: Add new macros H2BE_cell and BE2H_cell which
+ convert cell sized values to from big endian.
+ * device.c, emul_chirp.c: Where refering to IEEE 1275 memory cells
+ use these new macros.
-Wed Nov 8 00:10:38 1995 Andrew Cagney <cagneyhighland.com.au>
+Tue Sep 17 15:57:44 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
- * ppc-instructions (icbi): If icache present flush it.
+ * device.c (device_tree_add_parsed): Detect and report an
+ interrupt being attached to an invalid device. Was dumping core.
-Tue Nov 7 23:36:31 1995 Andrew Cagney <cagneyhighland.com.au>
+Mon Sep 16 23:09:12 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
- * devices.c (htab_init_callback): Add code to create htab/pte.
+ * device.h, device.c (device_address_to_attach_address,
+ device_size_to_attach_size): New functions. Convert a devices
+ unit address or unit size structure into a form suitable for
+ passing on to the attach and detach functions.
+ * device_table.h: Add extra methods to device table.
- * devices.c (dma_file, file_init_callback, htab_init_callback):
- New function - Dma the named file into memory at the specified
- address. Use.
+ * device.h, device.c (device_find_reg_property): New function.
+ For a reg type property, return the selected address + size
+ tupple, along with a positive success status. Add a reg_property
+ to the list of property types.
+ * (device_tree_add_parsed): Make array properties with the name
+ reg or alternate-reg of type reg_property.
- * device_tree.h, device_tree.c (scand_*): New functions.
+ * hw_memory.c (hw_memory_init_address): Rewrite to use new
+ find_reg_property method.
+ * hw_nvram.c (hw_nvram_init_address): Ditto.
-Tue Nov 7 23:36:31 1995 Andrew Cagney <cagneyhighland.com.au>
+ * device.c (device_tree_print_device): Add code to print out a reg
+ property.
- * filter_filename.c, Makefile.in: Change so that only dependant on
- a very limited nr of files. Stops an unnecessary dependency.
+ * device_table.c (generic_device_address_to_attach_address,
+ generic_device_size_to_attach_size ): New functions. Generic
+ functions for converting between unit and attach address or size.
-Tue Nov 7 15:44:33 1995 Andrew Cagney <cagney@highland.com.au>
+ * device_table.c (generic_device_init_address): Rewrite to use the
+ new find_reg and address convert functions. Look for both reg and
+ alternate-reg properties.
- * core.c (core_map_find_mapping): Use cpu_halt rather than error
- to abort an access to an undefined address.
+Mon Sep 16 23:09:12 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
-Sun Nov 12 07:58:09 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+ * hw_com.c: New file. A '550 serial device that can quickly be
+ attached to any bus.
+ * configure.in (enable-sim-hardware): Add the com device.
+ * configure: re-generate.
- * igen.c (model_table_insert_{macro,function}): New functions.
- (insn_table_load_insns): Call them.
- (gen_model_h): Move section emiting model-macros to be first.
- (model_{c,h}_function): New functions cloned from semantic
- functions to print out the prototype and function for
- model-functions.
- (gen_model_{c,h}): Print out model-functions.
+Thu Sep 12 17:30:56 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
- * ppc-instructions (model_{start,halt,print_info}): Add dummy
- model-functions.
+ * device.c (device_tree_verify_reg_unit_address): New
+ function. Check that the unit address as specified by the reg
+ property correctly corresponds to any unit address previously
+ specified by the devices name.
+ (device_tree_add_parsed): When adding a reg property, verify
+ that the unit-address - first value of property - correctly
+ matches any previous value specified when creating the device
+ node.
- * options.c (print_options): Print out WITH_{,DEFAULT_}MODEL, not
- WITH_PPC_{,DEFAULT_}_MODEL.
- (options_ppc): Delete now unused function.
- (cpu.h): Include cpu.h, not just basics.h.
+Thu Sep 12 17:30:56 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
- * std-config.h (WITH_{,DEFAULT_}MODEL): Define.
+ * mon.c (mon_event): Remove assertion that an unsigned is >= 0.
- * igen.c (model_macros, last_model_macro): New statics to keep
- track of macros to go in model.h.
- (insn_table_load_insns): Add model-macros to model_macros linked
- list.
- (model_table_fields): Add field for printable name.
- (gen_model_h): If there are model macros defined, print them out.
- Print out DEFAULT_MODEL as the first model if there any models
- specified, otherwise MODEL_NONE. Print out external decl for
- current_model. Print out decl for model_set.
- (gen_model_c): Add function model_set. Switch to use printable
- name for the model, not the internal identifier used.
+Fri Aug 16 12:05:24 1996 Michael Meissner <meissner@tiktok.cygnus.com>
- * psim.c (current_model): New global variable.
+ * device.c (device_full_name): Cast strdup to char *, since AIX
+ 3.2.5 mistakenly declares the function to be const char *.
+ (device_create_from): Ditto.
+ (device_create_instance_from): Ditto.
+ (device_add_property): Ditto.
- * ppc-instructions: Add macros for flag defines. Switch first
- model so 604 is first.
+Tue Aug 13 11:40:14 1996 Michael Meissner <meissner@tiktok.cygnus.com>
- * main.c (main): Call model_set, not function_unit_model.
- * sim_calls.c (sim_open): Ditto.
- * sim_calls.c, Makefile.in: sim_calls.c now includes cpu.h.
+ * debug.c (trace_option): For -t all, do not set the
+ trace_dump_device_tree flag, so that the simulator is run.
-Sat Nov 11 07:27:41 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+Tue Aug 13 11:40:14 1996 Michael Meissner <meissner@tiktok.cygnus.com>
- * mon.h (mon_events): New enumeration for other events we want to
- handle.
- (mon_event): Add declaration for function.
+ * Makefile.in (options.o): Depend on defines.h.
+ (defines.h): New rule, go through config.h and make strings of all
+ of the #define HAVE_xxx macros.
+ (distclean): Remove defines.h.
- * mon.c (mon_event): New function.
- (mon_print_info): Print icache misses.
+ * options.c (print_options): Print whether many of the
+ configuration macros are defined.
- * psim.c (run_until_stop): Monitor icache misses.
+ * main.c (main): If -t options and no filename, just print the
+ options, and don't print the usage message.
- * configure.in (--enable-sim-inline): Fix typos in handling comma
- separated inline options.
- (--enable-sim-icache): Echo icache size.
- * configure: Regenerate.
+Mon Aug 12 18:42:37 1996 Michael Meissner <meissner@tiktok.cygnus.com>
- * igen.c (semantics_h_print_function): Emit STATIC_SEMANTICS
- instead of INLINE_SEMANTICS so that the compiler won't keep all of
- the semantic functions as inline RTL, given that the address of
- the function is taken which forces outline calls anyway.
- (lf_print_c_semantic_function_header): Ditto.
- (gen_semantics_h): Define STATIC_SEMANTICS as nothing if not
- defined.
- (lf_print_c_cracker_function): Emit STATIC_IDECODE instead of
- STATIC_INLINE_IDECODE.
- (gen_idecode_c): Define STATIC_IDECODE if not defined.
- (gen_model_h): Use #ifdefs to define types to hold model units,
- cycles, and flags.
- (model_table_insert): Add a sentinel functional unit at the end to
- simplify loop processing.
- (model_c_insn): Use <function-unit>_SENTINAL instead of 0 for any
- instruction not specifing a function unit for the current model.
- (gen_model_{c,h}): Provide bounds for model_time_mapping.
-
- * inline.h (STATIC_SEMANTICS): Define to be static if
- SEMANTICS_INLINE is defined.
- (STATIC_IDECODE): Define to be static if IDECODE_INLINE is
- defined.
-
- * options.c (print_options): Fix typo.
-
-Fri Nov 10 06:39:46 1995 Michael Meissner <meissner@tiktok.cygnus.com>
-
- * configure.in (--enable-sim-{opcode,config}): Use $srcdir when
- check for the existence of files.
+ * configure.in: Test whether /dev/zero works on the system, and if
+ it does, define HAVE_DEVZERO.
* configure: Regenerate.
- * table.c (table): New field nr_model_fields.
- (table_open): New parameter nr_model_fields.
- (table_entry_read): Parse model fields that begin with a '*' after
- each instruction.
- * igen.c, dgen.c: Change callers of table_open.
-
- * igen.c: Add support for dumping model specific information in
- model.h and model.c.
- (insn_field_name): Delete unused array.
- (global variables): Make global variables static, so we can tell
- when they are no longer used.
- (cache_semantic_actual): Delete unused variable.
- (insn_table_load_insns): If the insn is really a machine model,
- call model_table_insert instead of other processing.
- (model_table_insert): New function to handle defining the
- functional units of a particular machine model.
- (insn_table): Add last_function field so we can add functions at
- the end.
- (insn_table_insert_function): Use last_function field when
- appending new function.
-
- * ppc-instructions: Add a few model specific information for 603,
- 603e, and 604 for testing purposes.
-
- * table.h (table_model_entry): New linked list to hold model
- specific information, one per line.
- (table_entry): Add model_first, model_last fields.
-
- * configure.in (--enable-sim-inline): If gcc is found and
- --enable-sim-inline is not specified, defaine DEFAULT_INLINE to 1,
- not 2.
- (--enable-sim-reserved-bits): New switch to check whether reserved
- bits are set in the instruction.
- (--enable-sim-opcode): Make complex the default.
- (all switches): Add appropriate checks and error messages.
- * configure: Regenerate.
+ * emul_generic.c (emul_add_tree_hardware): Do not add /iobus/disk
+ if we don't have a working /dev/zero on the system.
- * Makefile.in (RESERVED_CFLAGS): New variable set by
- --enable-sim-reserved-bits.
- (CONFIG_CFLAGS): Include RESERVED_CFLAGS.
- (BUILT_SRC): igen now generates model.c and model.h.
- (LIB_OBJ): Include table.o.
- (tmp-igen): Add -m/-M options to write model.c/model.h.
- (model.o): New object.
- (CPU_H): Include model.h.
+ * emul_bugapi.c (emul_bugapi_init): If HAVE_DEVZERO is not
+ defined, don't add disk support.
+ (emul_bugapi_do_diskio): Ditto.
+ (emul_bugapi_instruction_call): Ditto.
- * cpu.h: Include model.h.
+Wed Aug 7 14:34:20 1996 Michael Meissner <meissner@tiktok.cygnus.com>
- * std-config.h (WITH_RESERVED_BITS): Define.
- (MODEL_INLINE): Ditto.
+ * emul_unix.c (HAVE_TCGETATTR): If HAVE_TERMIOS_STRUCTURE is not
+ defined, make sure HAVE_TCGETATTR is #undef'ed
- * options.c (print_options): Print out WITH_RESERVED_BITS.
+Wed Aug 7 14:34:20 1996 Michael Meissner <meissner@tiktok.cygnus.com>
-Thu Nov 9 12:22:15 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+ * std-config.h (REGPARM): Only define REGPARM attributes if using
+ GNU C. Test for __i686__ in case GCC ever defines it. If not on
+ a x86 platform, define REGPARM as nothing.
- * configure.in: If --silent, don't output information messages.
- * configure: Regenerate.
+ * sim-endian.h (WITH_HOST_BYTE_ORDER): Test for i686 and __i686__
+ also.
- * configure.in (--enable-sim-alignment): Fix typo in specifing non
- strict alignment.
- (--enable-sim-switch): Make default on.
- (--enable-sim-duplicate): Make default on.
- (--enable-sim-smp): Make default 0.
- (--enable-sim-mon): Don't set sim_float if not set.
- (--enable-sim-inline): If gcc is found and --enable-sim-inline is
- not specified, define DEFAULT_INLINE to be 2.
- (all --enable-sim-* rules): Echo rules set to non empty to file
- descriptor 6.
- * configure: Regenerate.
+Wed Aug 7 20:19:55 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
- * options.c (options_env): Fix typo if WITH_ENV is 0.
- (print_options): Print GCC compiler version if available and
- date/time options was compiled. If OPCODE_RULES, IGEN_FLAGS,
- and/or DGEN_FLAGS are defined, print them.
+ * ld-decode.h, ld-decode.c: Rename goto_gen to the more correct
+ goto_switch_gen.
+ * gen-idecode.c: Ditto.
- * Makefile.in (all link actions): Pass SIM_CFLAGS as well as
- CFLAGS.
- (options.o): Compile options.o with OPCODE_RULES, IGEN_FLAGS, and
- DGEN_FLAGS defined, so they can be printed out.
+ * gen-idecode.c (print_idecode_table): Comment out check for
+ switch/table combination until a bug with it is fixed.
- * igen.c (lf_print_c_validate): Check for WITH_ASSERT, so that
- this test can be compiled away if the user really wants a fast
- simulator by not doing assertion failures.
+ * ppc-opcode-goto: New file. Like complex and flat but uses
+ goto-switch instead of padded-switch for the tables.
-Wed Nov 8 13:19:47 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+ * gen-idecode.c (print_goto_switch_name): New function.
+ (print_goto_switch_table_leaf): New function.
+ (print_goto_switch_break): New function.
+ (print_goto_switch_table): New function. Prints a jump table
+ that can be jumped into instead of a switch statement.
- * options.c: New file to print out all of the WITH_ options.
- * options.h: New include file to declare print_options.
- * debug.h (trace_options): Add trace_opts to call print_options.
- * debug.c (trace_description): Add trace_opts support.
- * main.c (main): If user requested options, print them.
- * sim_calls.c (sim_open): Ditto.
+ * gen-idecode.c (*switch_*): As an option output a switch that is
+ implemented using a jump table but only if the switch is not
+ boolean.
- * igen.c (opcode_field_new): Add void to make it a proper prototype.
+Tue Aug 6 09:28:22 1996 Michael Meissner <meissner@tiktok.cygnus.com>
- * emul_generic.c (emul_enter_call): Make printf_filtered arguments
- type correct.
- * emul_netbsd.c (do_kill): Ditto.
- * registers.c (registers_dump): Ditto.
- * vm.c (om_translate_effective_to_real): Ditto.
- * vm_n.h (vm_data_map_read_N): Ditto.
- (vm_data_map_write_N): Ditto.
- * devices.h (DTRACE_INIT): Ditto.
- (DTRACE_{ATTACH,DETACH}_ADDRESS): Ditto.
- (DTRACE_IO_{READ,WRITE}_BUFFER): Ditto.
- (DTRACE_DMA_{READ,WRITE}_BUFFER): Ditto.
- * devices.c (update_for_binary_section): Ditto.
- (write_stack_arguments): Ditto.
- (stack_ioctl_callback): Ditto.
- * device_tree.c (device_tree_add_passthrough): Ditto.
- (device_tree_{add,find}_device): Ditto.
- (device_tree_{add,find}_integer): Ditto.
- (device_tree_find_{string,boolean}): Ditto.
- (device_tree_init{,_device}): Ditto.
- (device_tree_dump): Ditto.
- * sim_calls.c (sim_{read,write}): Ditto.
- (sim_{fetch,store}_register): Ditto.
- (sim_stop_reason): Ditto.
-
- * sim_callbacks.h (printf_filtered): Declare with attribute
- printf, so we can enable format checks.
-
- * devices.c (console_io_{read,write}_buffer_callback): Cast swtich
- argument to int, since ANSI doesn't allow long switch values.
- * emul_netbsd.c (do___sysctl): Ditto.
-
- * emul_netbsd.c (do___sysctl): Fix up printf call.
-
- * corefile.c (core_translate): Don't do arithmetic with void *
- pointers. Cast to char * first.
-
- * function_unit.c (FUNC_{LOAD,STORE}): Rename from {LOAD,STORE}
- and change all uses.
-
- * Makefile.in ({FUNC,MODEL,WARNING}_CFLAGS): New flags set by
- configure --enable switches.
- (CONFIG_CFLAGS): Include FUNC_CFLAGS and MODE_CFLAGS.
- (.c.o): Include WARNING_CFLAGS.
- (CPU_H): Include function_unit.h.
- (LIB_OBJ): Include function_unit.o.
- (BUILT_SRC_WO_CONFIG): Split from BUILT_SRC and do not include
- config.h or ppc-config.h.
- (BUILT_SRC): Include BUILT_SRC_WO_CONFIG, config.h and
- ppc-config.h.
- (filter_filename.o): Include config.h/ppc-config.h dependencies.
- (idecode.o, semantics.o, psim.o): Specify CC line without
- WARNING_CFLAGS so that we don't get all of the unused variable
- warnings that are generated.
- (function_unit.o): Add rule to build.
- (main.o, sim_calls.o): Add function_unit.h, itable.h dependencies.
- (mon.o): Include mon.c dependency.
- (TAGS): Depend on BUILT_SRC.
- (clean): Don't delete config.h or ppc-config.h
-
- * basics.h (sim_callbacks.h): Move include after the include of
- config.h and ppc-config.h.
-
- * bits.{h,c} (ROTL32,ROTL64): Move these functions to bits.c. Add
- support for BITS_INLINE to inline these. Add declarations to
- bits.h.
-
- * configure.in (--enable-sim-warnings): Add new option to specify
- compiler warnings for all modules except idecode.o and semantics.o
- which have lots of unused variables because they are machine
- generated.
- (--enable-sim-function-unit): New switch to configure whether
- function unit support is compiled in or not.
- (--enable-sim-{,default-}mode): New switches to control which cpu
- model is used.
+ * configure.in (--enable-sim-{hardware,packages}): Fix typos.
* configure: Regenerate.
- * corefile.c (core_attach_address_callback): Delete unused
- variable device_address.
+ * device.c (device_instance_call_method): Fixup format message in
+ error case. Return 0 in case of error to shut up compiler
+ warnings.
+
+Wed Aug 7 00:17:37 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
+
+ * device_table.c (generic_device_unit_decode): Require a comma
+ between elements of a unit address.
+
+ * device.c (device_tree_print_device): For reg, alternate-reg and
+ ranges properties use special print functions.
+ (device_print_ranges_property): Print formatted ranges property.
+ (device_print_reg_property): Print formatted reg property.
+
+Tue Aug 6 21:35:18 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
+
+ * device.c (device_tree_add_parsed): For reg, ranges and
+ alternate-reg properties use a special parser.
+ (device_tree_parse_reg_property): New function to parse a reg
+ property.
+ (device_tree_parse_ranges_property): New function to parse a
+ ranges property.
+ (device_encode_unit): Wrapper for encode_unit callback.
+ (device_decoce_unit): Wrapper for decode_unit callback.
+
+Wed Jul 31 00:02:30 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
+
+ * device_table.h (device_instance_callbacks): Relace the claim and
+ release methods with a more general table mapping from method-name
+ to method-function.
+
+ * device.c (device_instance_call_method): New function. Implement
+ the OpenBoot call-method client interface. Attempts to locate the
+ instances method in the callback table.
+ (device_instance_claim, device_instance_release): Delete.
+ Replaced with call-method and a lookup table.
+
+ * emul_chirp.c (chirp_emul_call_method): Use the new device
+ instance call method and let that handle a client claim call.
+
+ * hw_htab.c (claim_memory): Wrapper function to call the memory
+ devices "claim" method using the new device-instance call-method
+ interface. Replaces the previous direct calls to claim.
+ (htab_map_region): Use claim_memory.
+ (htab_init_data_callback): Ditto.
+
+ * hw_memory.c (hw_memory_instance_claim): Update function
+ interface so that it is compatible with call-method.
+ (hw_memory_instance_release): Ditto.
+ (hw_memory_instance_methods): New table of memory specific
+ methods claim and release. Add to the hw_memory_callback
+ table.
+
+Tue Jul 30 21:26:14 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
+
+ * psim.c (psim_init): Back out of change to initial value of
+ system->last_cpu.
+
+Tue Jul 30 21:12:24 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
+
+ * sim_callbacks.h (sim_io_printf_filtered): Replace
+ printf_filtered with a local simulator specific version. Add
+ #define printf_filtered to simplify updating of existing code.
+
+ * sim_callbacks.h (sim_io_write_stdout, sim_io_read_stdin,
+ sim_io_write_stderr): New functions. Read / write to the
+ simulations stdin and stdout and stderr interfaces. Merge in code
+ from hw_pal that previously handled async I/O.
+ (sim_io_flush_stdoutput): Rename flush_stdoutput. Add #define
+ flush_stdoutput to simplify updating of existing code.
+
+ * hw_pal.c (scan_hw_pal, write_hw_pal,
+ hw_pal_instance_write_callback): Use the new sim_io functions.
+
+ * main.c: Implement standalone versions of the new sim_io
+ functions. Include support for async I/O.
+ * sim_calls.c: Ditto. This time using the gdb callback table.
+
+ * std-config.h (CURRENT_STDIO, current_stdio): New macro. Set up
+ stdio configuration so that it works in the same way as the rest
+ of the simulation.
+ * psim.c (psim_create): Initialize current_stdio from the device
+ tree.
+ * emul_generic.c (emul_add_tree_options): Enter a default value
+ for use-stdio in the device tree.
+
+Fri Jul 26 19:43:03 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
+
+ * gen-idecode.c (print_jump): Was always generating a jump back to
+ idecode. Only necessary at tail of semantic code.
+ (print_jump): Was always setting the processor's cia, even during
+ startup when the processor was still undefined.
+ (print_jump): For safety, restart smp loop when cpu_nr >= nr_cpus,
+ not just equal.
+
+ * options.c (print_options): Add printing of WITH_REGPARM and
+ WITH_STDCALL.
+
+ * std-config.h (WITH_REGPARM, WITH_STDCALL): Provide default
+ (disabled) values if not defined.
- * cpu.c (struct _cpu): Add function unit pointer field func_unit.
- (cpu_create): If WITH_FUNCTION_UNIT, call function_unit_create.
- (cpu_init): If WITH_FUNCTION_UNIT, call function_unit_init.
- (cpu_halt): If WITH_FUNCTION_UNIT, call function_unit_halt.
- (cpu_function_unit): New function to return func_unit field.
+Fri Jul 26 00:36:35 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
- * cpu.h (function_unit.h): Include new include file.
- (cpu_function_unit): Declare.
+ * ppc-cache-rules (cache): Change RS and RB to cache instead of
+ compute. The block move instructions use them.
- * debug.c (stdlib.h): Test HAVE_STDLIB_H, not HAVE_STDLIB.
- (config.h): Include config.h.
+ * idecode_expression.h (FPSCR_SET): New macro, set specific FPSCR
+ register.
+ (CR_FIELD): New macro, extract specific CR register.
+ (FPSCR_FIELD): New macro, extract specific FPSCR register.
- * devices.c (icu_io_write_buffer_callback): Delete unused variable
- system.
+ * registers.h (GPR): New macro, simplify accesses to GPR[i].
- * emul_generic.c (emul_exit_call): Print out status value.
+ * bits.c (INSERTED): Covert INSERTED macro into a function.
+ (EXTRACTED): Conditionally compile on correct bit size macro.
- * emul_netbsd.c (do_read): Delete unused variable nr_moved.
+ * bits.h (BIT8): New macro, set a single bit in an 8 bit byte.
- * filter_filename.h (includes): Include config.h, ppc-config.h,
- not basics.h.
+ * ppc-instructions: With hints from Paul Martin, type in missing
+ some instruction semantics. Leave disabled for the moment.
+ (Load Multiple Word): Ditto.
+ (Store Multiple Word): Ditto.
+ (Load String Word Immediate): Ditto.
+ (Load String Word Indexed): Ditto.
+ (Store String Word Immedate): Ditto.
+ (Store String Word Indexed): Ditto.
+ (Move to Condition Register from XER): Ditto.
+ (Move From Condition Register): Ditto.
+ (Move From FPSCR): Ditto.
+ (Move to Condition Register from FPSCR): Ditto.
+ (Move To FPSCR Field Immediate): Ditto.
+ (Move To FPSCR Fields): Ditto.
+ (Move To FPSCR Bit 0): Ditto.
+ (Move To FPSCR Bit 1): Ditto.
- * inline.c: Include bits.c if BITS_INLINE. Include
- function_unit.c if FUNCTION_UNIT_INLINE.
+Thu Jul 25 22:10:40 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
- * inline.h (INLINE_BITS): Define if BITS_INLINE.
- (INLINE_FUNCTION_UNIT): Define if FUNCTION_UNIT_INLINE.
+ * std-config.h (SEMANTICS_INLINE): By default, mask out the
+ inlining of semantic functions from DEFAULT_INLINE. Almost all
+ configurations call the semantic code via a pointer so there is
+ little benefit.
- * interrupts.c (instruction_storage_interrupt): Delete unused
- variable nia.
+ * std-config.h (ICACHE_INLINE): Ditto.
- * lf.h (config.h): Include config.h.
+Thu Jul 25 20:07:30 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
- * main.c (includes): Include function_unit.c. If HAVE_UNISTD_H,
- include unistd.h.
- (usage): Update for -m model, -i, and -I options.
- (main): Delete unused variables stack_pointer and i. Add support
- for -i, -m model arguments. Call psim_print_info with verbose ==
- 1 if -i, and verbose == 2 if -I.
+ * configure.in (sim_regparm): Add configuration option for
+ enabling GCC's regparm attribute.
+ * (sim_stdcall): Add configuration option for enabling GCC's
+ stdcall attribute.
- * mon.c (stdio.h): Include stdio.h to pick up sprintf prototype.
- (mon_issue): Call function_unit_issue if function units are
- supported.
- (mon_print_info): Take psim * argument. Print out information
- from function_unit if available. Move read/write stats to always
- print, instead of printing if verbose > 1. Fix up plural
- vs. singular usage.
+ * Makefile.in (REGPARM_CFLAGS): Pass regparam configuration onto
+ compilations.
+ * (STDCALL_CFLAGS): Pass stdcall configuration onto compilations.
- * mon.h (mon_print_info): Update prototype.
+ * std-config.h (REGPARM): Extend construction of REGPARM macro so
+ that it can include __stdcall__ function attribute.
- * psim.c (current_ppc_model): Add global variable.
- (psim_print_info): Pass system argument to mon_print_info.
+Wed Jul 24 19:04:20 1996 Andrew Cagney <cagney@sawnoff>
- * sim_calls.c (function_unit.h): Include.
- (sim_open): Add support for -i and -m model options. If -i call
- psim_print_info with verbose == 1, if -I, with verbose == 2.
- (sim_resume): Delete unused variable program_counter.
+ * options.c (print_options): Include SUPPORT_INLINE in information
+ dump.
- * std-config.h (WITH_FUNCTION_UNIT): Define.
- (ppc_model): Add enumeration giving all PowerPC models currently
- known about.
- ({WITH,CURRENT}_PPC_MODEL): Define.
- (FUNCTION_UNIT_INLINE): Define.
+ * gen-idecode.c (print_run_until_stop_body): Only generate loop
+ termination test if creating idecode_run_until_stop. Push the
+ loop termination test back into each alternative branch.
- * table.c (config.h): Include config.h.
+Wed Jul 24 15:47:09 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
- * vm.c (om_virtual_to_real): Print pte_word_{0,1} so the compiler
- doesn't complain that they're unused.
+ * gen-icache.c (print_icache_function): Have the cache function
+ always update the cache_entries semantic and address fields.
- * vm_n.h (vm_data_map_read_N): Delete unused variable rval.
-
-Mon Nov 6 23:15:54 1995 Andrew Cagney <cagney@highland.com.au>
+ * gen-idecode.c (print_idecode_switch_illegal): Include a break
+ when generating illegal instructions. This was commented out
+ which is a hangover from looking a at switch statements generated
+ using indirect jumps.
- * sim-endian.c (ppc-endian.c), sim-endian.h (ppc-endian.h):
- renameed. These files are target independant.
- * Makefile.in, basics.h: update for new name.
+Tue Jul 23 20:57:01 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
- * sim-endian.h (SWAP_N), sim-endian.c (_SWAP_1): Rename existing
- SWAP_<N> to _SWAP_<N> so that sim-endian.h can contain SWAP_N
- macro's as required.
+ * igen.c (print_my_defines): Replaces print_define_my_index.
+ Print both a definition for MY_INDEX and MY_PREFIX.
+ * gen-icache.c (print_icache_function): Adjust.
+ * gen-idecode.c (print_jump_insn): Adjust.
+ * gen-semantics.c (print_c_semantic): Adjust.
- * sim-endian.c, sim-endian-n.h (new file): Move endian code into a
- debugable header file.
+ * gen-support.c (gen_support_h): Add optional include to created
+ support.h so that, like cpu, it is optionally inlined for all
+ modules that include it.
+ * inline.h, inline.c: Adjust so that support.[hc] is handled the
+ same as cpu.[hc].
- * ppc-instructions (Byte-Reverse): Enable byte reverse
- instructions using SWAP_N macros.
+ * idecode_fields.h (LABEL, GOTO): Macro's that create a unique
+ name for a lable and then branch to it.
-Mon Nov 6 10:39:28 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+ * ppc-instructions (convert_to_integer, Floating Round to
+ Single-Precision, Floating Convert from Integer Doubleword): Use
+ LABEL and GOTO instead of the recently added switch statements.
- * Makefile.in (config.status): Remove references to config.make
- and config.hdr.
+Wed Jul 24 14:02:42 1996 Andrew Cagney <cagney@sawnoff.highland.com.au>
- * config.{make,hdr}: Delete, no longer used.
- * build-psim: Ditto.
+ * gen-idecode.c (print_run_until_stop_body): Too many rparen in
+ generated code.
-Mon Nov 6 20:49:56 1995 Andrew Cagney <cagney@highland.com.au>
+Tue Jul 23 20:57:01 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
- * sim_calls.c (sim_open): Fix parsing of `target sim' options.
+ * configure.in (--enable-sim-line-nr): Typo - sim_line-nr.
+ * (--enable-sim-inline): Reorder patern matching of arguments so
+ that SUPPORT=ALL_INLINE is reconized as *=* and not *_INLINE.
- * device_tree.c (device_tree_add_string): Wasn't saving the value
- of the string being entered into the tree.
+ * configure: rebuild.
- * psim.c (create_filed_device_tree): Not terminating string device
- names with a null.
-
- * psim.c (psim_create): Use `env' instead of
- `environment-architecture' to be consistent with configure.
- Reconize user/uea, virtual/vea and operating/oea.
+Mon Jul 22 23:25:08 1996 Andrew Cagney <cagney@highland.com.au>
-Sat Nov 4 12:29:45 1995 Fred Fish <fnf@cygnus.com>
+ * configure.in (--enable-sim-hardware, --enable-sim-packages): New
+ configuration options. Let the user specify the packages or
+ hardware devices that are to be included in the build. Makes it
+ possible for user packages to be specified.
- * core.c: Rename to corefile.c
- * core.h: Rename to corefile.h
- * inline.c: Include corefile.h, renamed from core.h.
- * cpu.h: Include corefile.h, renamed from core.h
- * vm.c: Include corefile.h, renamed from core.h
- * corefile.c: Include corefile.h rather than core.h
- * README.psim (KNOWN PROBLEMS): Change core.* references to corefile.*
- references.
- * Makefile.in (CPU_H): Change core.h to corefile.h
- (vm.o): Change dependency to corefile.h
- (LIB_SRC): Change core.c to corefile.c.
- (LIB_OBJ): Change core.o to corefile.o.
- (corefile.o): Change dependencies to corefile.c, corefile.h.
+ * Makefile.in (tmp-pk, tmp-hw): Just use the list of packages and
+ hardware instead of checking it using ls. configure.in should
+ have taken care of any problems.
+ (HW_SRC, HW_OBJ, PACKAGE_SRC, PACKAGE_OBJ): Set by configure.
-Fri Nov 3 11:37:24 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+Mon Jul 22 22:38:59 1996 Andrew Cagney <cagney@highland.com.au>
- * ppc-instructions (data cache instructions): Make all data cache
- instructions nops instead of invalid instructions.
+ * psim.c (psim_options): Enter the argument to the memory size
+ option directly into the device tree. Was using atol() which is
+ dangerously non portable.
- * Makefile.in (CONFIG_CFLAGS): Add ALIGNMENT_CFLAGS and
- TIMEBASE_CFLAGS which weren't included.
+Mon Jul 22 22:17:08 1996 Andrew Cagney <cagney@highland.com.au>
-Thu Nov 2 08:54:04 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+ * configure.in (icache): Extend icache flag to include an insn
+ option. If specifyed the insn - aka instruction - is included in
+ the instruction cache. Make this the default.
+ * configure: re-generate.
- * Makefile.in: Uncomment built file dependencies.
-
- * configure.in: Rewrite --enable-sim switch handling to use the
- autoconf builtins so it works correctly if the configure or
- Makefile.in files are modified and make decides to rebuild
- Makefile. Also document all of the --enable-sim switches
- supported. Check whether getrusage and sys/resource.h are
- supported.
- * config.in: Regenerate.
- * configure: Regenerate.
- * Makefile.in: Add support for all of the variables set with
- --enable-sim switches.
-
- * Makefile.in (clean): make clean now removes all built sources as
- well.
-
- * cpu.c: Use HAVE_STRING_H, HAVE_STRINGS_H, HAVE_UNISTD_H,
- HAVE_TIME_H, HAVE_SYS_TIMES_H, HAVE_SYS_RESOURCE_H defined in
- the generated config.h.
- * debug.c: Ditto.
- * device_tree.c: Ditto.
- * devices.c: Ditto.
- * dgen.c: Ditto.
- * emul_netbsd.c: Ditto.
- * igen.c: Ditto.
- * lf.c: Ditto.
- * misc.c: Ditto.
- * psim.c: Ditto.
- * registers.c: Ditto.
- * sim_calls.c: Ditt.
- * table.c: Ditto.
+ * igen.c (main), igen.h: Add option -S - inSn - for specifying
+ that the instruction should be included in the icache.
+ * gen-icache.c (print_icache_body): If enabled, output code to put
+ the instruction into the icache.
+ (print_icache_struct): If enabled, add insn to the icache struct.
- * main.c (main): Call psim_print_info with verbose == 2.
+Mon Jul 22 20:46:12 1996 Andrew Cagney <cagney@highland.com.au>
- * mon.c (mon_print_info): Align the cpu number and number of
- instructions fields. Do not print an instruction category if the
- CPU did not execute any of those instructions. Print out number
- of reads and writes. If getrusage is supported, print out number
- of simulated instructins per second.
-
- * configure.in: Add support for --enable-sim-opcode=stupid.
+ * Makefile.in (BUILD_CFLAGS): Include -g when building the
+ generators.
+
+Mon Jul 22 20:00:25 1996 Andrew Cagney <cagney@highland.com.au>
+
+ * emul_generic.c (emul_add_tree_options): Was incorrectly setting
+ the strict-alignment option when hardwired for non-strict
+ alignment.
+
+Sun Jul 21 21:18:05 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
+
+ * gen-semantics.c: Make the my_index variable a macro MY_INDEX.
+
+ * ppc-instructions: Adjust so that references are to MY_INDEX and
+ not my_index.
+
+Sun Jul 21 21:18:05 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
+
+ * gen-idecode.c: Output the complete run_until_stop function
+ instead of just the code to handle a single instruction issue.
+ * : Have the generated idecode.c include inline.c (instead of psim.c).
+
+ * std-config.h: Change psim.c so that it isn't inlined (as this is
+ no longer needed).
+
+ * psim.c (run_until_stop): Delete the old run_until_stop function
+ instead calling the idecode_run and idecode_run_until_stop
+ functions that gen-idecode.c is now creating.
+
+Sun Jul 21 21:18:05 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
+
+ * dgen.c: Maintenance - update to use new features found in lf.c.
+
+ * filter_filename.c (filter_filename): Maintenance - make the
+ string constant.
+
+Sun Jul 21 21:18:05 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
+
+ * debug.c (TRACE, ITRACE, DTRACE): Have GCC instead of CPP
+ eliminate trace statements.
+
+ * debug.c: Change trace format so that it is consistent
+ (file:line-nr) with CC's error output.
+
+ * gen-itable.c (itable_c_insn): Add the source file name and
+ source line number to the instruction's informational entry.
+
+ * debug.c (ITRACE): Use the itable (and my_index) to get the
+ current instructions name and source line number.
+
+ * gen-semantics.c, gen-icache.c: Adjust generated ITRACE calls to
+ match new interface.
+
+ * emul_bugapi.c (emul_bugapi_instruction_call): Adjust
+ corresponding call to ITRACE so that it still matches.
+
+ * idecode_expression.h (ALU_END, CR0_COMPARE): Use TRACE instead
+ of ITRACE. The CPP line directives would have previously set the
+ line-nr and file name so ITRACE isn't needed.
+
+Sun Jul 21 21:18:05 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
+
+ * gen-idecode.c (print_jump_until_stop_body): New function and
+ idecode generation option. Instead of generating and calling
+ separate functions containing the semantic and icache code
+ generate a single monolythic function and use goto's (and GCC's
+ indirect jump) to move between code blocks.
+
+ * Makefile.in: Add sim_jump flag to those passed to igen.
+
+ * configure.in: New option --enable-sim-jump (default disabled)
+
+ * ppc-instructions: Eliminate any uses of labels and goto's.
+ These result in duplicate declarations when a single flat function
+ is being create.
+
+ * ppc-opcode-jump: New file. Set of opcode rules useful when
+ testing jumping idecodes.
+
+Sun Jul 21 21:18:05 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
+
+ * gen-idecode.c: Optionally include the semantic code for an
+ instruction in the function that is doing the decoding.
+
+ * igen.c: Add option (-C) to generate semantics in the instruction
+ decode functions.
+
+ * configure.in (--enable-sim-icache): Accept an option list such
+ as 1024,define. Add a new choice to the list - semantic - which
+ will cause igen to generate instruction decode functions that
+ include the corresponding semantic code.
+
+Sun Jul 21 21:18:05 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
+
+ * configure.in: New option --enable-sim-line-nr (default enabled).
+ Enable/disable the inclusion of CPP line directives in the
+ generated files. Such directives refer back to the source files
+ used when generating the simulator code.
+
+ * Makefile.in (sim_line_nr): Pass to igen.
+
+Sun Jul 21 21:18:05 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
+
+ * igen.c (main): Revamp the options so that more letters are
+ available.
+
+ * configure.in: Adjust to match igen's revamped options
+
+Sun Jul 21 21:18:05 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
+
+ * Makefile.in (pk.h, hw.h): Rewrite depenencies for hw.h (etc) so
+ that they use the same technique as igen (ie a dummy targets
+ tmp-pk and tmp-hw are created).
+
+Mon Jun 24 22:28:00 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
+
+ * Makefile.in (BUILD_CFLAGS): Include WARNING_CFLAGS.
+
+Wed Jun 19 21:45:28 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
+
+ * ld-cache.[hc], ld-decode.[hc], ld-insn.[hc]: New files. Separate
+ out the loading of each of the tables from the rest of igen.
+ * Makefile.in: Adjust.
+ * igen.c: Adjust.
+
+ * gen-icache.[hc], gen-idecode.[hc], gen-itable.[hc],
+ gen-model.[hc], gen-semantics.[hc]: New files. Separate out the
+ code creating each separate set of generated files.
+ * Makefile.in: Adjust.
+ * igen.c: Adjust.
+
+ * gen-support.[ch]: New files. Output the support functions (found
+ in the ppc-instructions file) into a separate file.
+ * Makefile.in: Add.
+ * inline.h, inline.c: Add.
+ * std-config.h: Add.
+
+ * ld-cache.c: Re-design the cache table format.
+ * ppc-cache-rules: Update to new format.
+
+ * ld-decode.c: Re-design the decode table format.
+ * ppc-opcode-simple: Update to new format
+ * ppc-opcode-complex: Ditto
+ * ppc-opcode-flat: Ditto
+
+ * filter.h, filter.c: New files. Separate the opcode filter table
+ reading code from the rest of igen.c. Re-design the filter so that
+ it works inclusivly not exclusivly.
+ * igen.c: Remove the opcode filter table loading code.
+ * Makefile.in (filter.o): Adjust
+ * configure.in: Adjust filter flag so that default includes 32bit
+ and floating point.
+ * ppc-instructions: Clean up filter fields so that only in use
+ entries are specifed (ie delete `be').
+
+ * misc.c (name2i, i2name): New function. Map between a string and
+ an integer value.
+
+Mon Jun 17 20:08:03 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
+
+ * sim_calls.c (sim_close): If simulator not created, skip printing
+ of run information.
+
+Mon Jun 17 20:08:03 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
+
+ * registers.c (register_description): Typo, insns not insn.
+
+ * ppc-instructions (model_get_number_of_stalls): New model function,
+ returns number of stalls for the specified processor.
+ * psim.c (psim_read_register): Add call to new function
+ model_get_number_of_stalls().
+
+ * ppc-instructions (model_get_number_of_cycles): New model function,
+ returns number of stalls for the specified processor.
+ * psim.c (psim_read_register): Add call to new function
+ model_get_number_of_cycles().
+
+Fri Jun 14 00:11:56 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
+
+ * device_table.h: Don't pass the parent device into a devices
+ create function. This makes the create function consistent with
+ the documentation.
+ * device.c (device_template_create_device): Ditto
+ * hw_pal.c (hw_pal_create): Ditto
+ * hw_core.c (hw_core_create): Ditto
+ * hw_vm.c (hw_vm_create): Ditto
+ * hw_disk.c (hw_disk_create): Ditto
+ * hw_nvram.c (hw_nvram_create): Ditto
+ * hw_memory.c (hw_memory_create): Ditto
+ * hw_cpu.c (hw_cpu_create): Ditto.
+
+ * device.c (split_find_device): Allow a null initial parent device.
+ (device_template_create_device): Ditto.
+
+ * device.c (device_create_from): Make local (static) only used
+ within device.c.
+ * device_table.h: typedef device_callbacks moved here (from
+ device.h) where it belongs.
+
+ * hw_core.c: New file. Implements just the core device using the
+ core object.
+
+ * corefile.c: Moved all core device functions into the new
+ hw_core.c file. core_device_create() disapears.
+
+ * psim.c (psim_tree): Use device_tree_add_parsed() to create the
+ core device.
+
+Thu Jun 13 00:09:29 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
+
+ * hw_init.c: Correct typo in comment.
+
+ * corefile.c (core_init): Remove any remaining references to a
+ default map.
+ (core_map_find_mapping): Ditto.
+
+Wed Jun 12 22:30:32 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
+
+ * corefile.c (core_init): Make function global so that other
+ devices are able to use the full core object.
+
+ * corefile.c (core_create, core_from_device): Break core_create
+ into two functions. The first creates a core object, the second
+ returns the core object associated with a core device.
+
+ * corefile.c (core_device_create): Use core_create to make the
+ core object.
+
+ * psim.c (psim_create): Use core_from_device() instead of
+ core_create().
+
+ * device.c (device_template_create_device): Make static as only
+ needed by functions internal to device.c.
+
+Fri Jun 7 23:47:18 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
+
+ * ppc-opcode-test-2: Remove description of fields.
+ * ppc-opcode-complex: Ditto
+ * ppc-opcode-flat: Ditto
+ * ppc-opcode-simple: Ditto
+ * ppc-opcode-stupid: Ditto
+ * ppc-opcode-test-1: Ditto
+ * ppc-cache-rules: Ditto
+
+ * igen.c: Add description of files as a comment at the front.
+
+Wed Jun 26 12:50:33 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * configure.in: Check for whether the termios and termio
+ structures are really defined, and whether or not, they define the
+ c_line field.
* configure: Regenerate.
-Wed Nov 1 23:46:59 1995 Andrew Cagney <cagney@highland.com.au>
+ * Makefile.in ({,TERMIO_}CFLAGS): Add TERMIO_CFLAGS options set by
+ configure.
- * std-config (INLINE_DEVICE_TREE): Don't inline either of
- device_tree.c or devices.c. There is no significant gain.
+ * emul_unix.c: Various changes to allow for building on systems
+ with different termio and termios structures. If host has both
+ termio and termios, just use termios. No longer include
+ sys/ioctl.h.
- * configure.in, Makefile.in: add --enable-sim-icache=[0-9]* and
- IGEN_ICACHE macro.
-
-Wed Nov 1 23:46:59 1995 Andrew Cagney <cagney@highland.com.au>
+Wed Jun 26 12:26:55 1996 Jason Molenda (crash@godzilla.cygnus.co.jp)
- * igen.c (main), misc.h (target_a2i, i2target), misc.c: Add
- functions to convert between target and igen internal bit numbers.
- Make IO go through these functions. Add -b (bit size) and -h (high
- bit nr) options to igen. Typical usage would be: ./igen -b 16 -h
- 15 for a 16 bit instruction format with the msb given a number 15.
+ * Makefile.in (bindir, libdir, datadir, mandir, infodir, includedir,
+ INSTALL_PROGRAM, INSTALL_DATA): Use autoconf-set values.
+ (docdir): Removed.
+ * configure.in (AC_PREREQ): autoconf 2.5 or higher.
+ (AC_PROG_INSTALL): Added.
+ * configure: Rebuilt.
-Wed Nov 1 22:17:32 1995 Andrew Cagney <cagney@highland.com.au>
+Wed Jun 5 23:53:42 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
- * dgen.c (main): Was outputting optarg even when it was NULL.
+ * corefile.h: Rewrite documentation so that it can be extracted and
+ converted into texinfo (and hence ready for translation into html,
+ tex or nroff).
+ * device.h: Ditto
-Tue Oct 31 23:48:33 1995 Andrew Cagney <cagney@highland.com.au>
+Thu Jun 6 09:52:37 1996 Michael Meissner <meissner@tiktok.cygnus.com>
- * vm_n.h (vm_data_map_load_N, vm_data_map_store_n), debug.h,
- debug.c: Add tracing of load/store unit (virtual) with -t
- load-store.
+ * hw_disk.c (SEEK_SET): If SEEK_SET is not defined, define as 0.
-Tue Oct 31 21:44:01 1995 Andrew Cagney <cagney@highland.com.au>
+Wed Jun 5 11:46:52 1996 Andrew Cagney <cagney@puddin>
- * std-config.h (WITH_ENVIRONMENT): Add USER_ENVIRONMENT which does
- not include things such as the time base and events.
+ * hw_disk.c: Include <unistd.h> if available. Under SunOS, that
+ is the source of SEEK_SET.
- * interrupt.c, sim_calls.c, cpu.h, vm.c, configure.in: Add UEA to
- all environment switches for above.
+Wed Jun 5 01:39:07 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
- * psim.c (psim_create): ditto - new device tree node name is
- /options/environment-architecture with values user, virtual and
- operating.
+ * psim.c (psim_options): Correct type of dummy arguments being
+ passed to a device_ioctl call.
-Tue Oct 31 21:31:32 1995 Andrew Cagney <cagney@highland.com.au>
+ * hw_init.c (hw_data_init_data_callback): Adjust printf arguments.
+ (write_stack_arguments): Ditto.
+ * hw_trace.c: Instance callback entry no longer a table.
- * ppc-opcode-stupid: Third example of use of opcode table - this
- one expands all mtspr/mfspr and branch instructions. Appears to
- give about a 10% gain in performance if everything enabled. Also
- takes about 150mb of swap to build.
+Wed Jun 5 01:39:07 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
-Wed Nov 1 10:49:48 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+ * emul_unix.c (do_unix_umask): Cast printf argument.
+ (convert_to_linux_termios): Use LINUX_VSWTC not LINUX_VSWCH
- * emul_netbsd.c (do_exit): Print arguments and close parenthesis
- if tracing, since exit doesn't go through emul_exit_call.
- (do_read): Print arguments if tracing.
- (do_write): Ditto.
- (do_open): Ditto.
- (do_break): Ditto.
- (do_kill): Ditto.
- (do_dup): Ditto.
- (do_sigprocmask): Replace trace with printing arguments if
- tracing.
- (do_ioctl): Print arguments if tracing.
- (do_umask): Ditto.
- (do_dup2): Ditto.
- (do_fcntl): Ditto.
- (do_gettimeofday): Ditto.
- (do_getrusage): Ditto.
- (do_fstatfs): Ditto.
+Mon Jun 3 15:02:04 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * hw_init.c (update_for_binary_section): Abort if we find an
+ .interp section, which indicates the need for shared libraries to
+ be loaded.
- * filter_filename.c: New file to provide filter_filename to strip
- the directory prefix from a file.
- * filter_filename.h: New include file to declare filter_filename.
+Mon Jun 3 15:02:04 1996 Michael Meissner <meissner@tiktok.cygnus.com>
- * debug.h: Include filter_filename.h.
- (TRACE,DTRACE,ERROR): Use filter_filename on __FILE__.
+ * emul_unix.c (do_unix_{time,gettimeofday,getrusage}): Add support
+ for time, gettimeofday, and getrusage system calls.
+ ({solaris,linux}_descriptors): Add new system calls.
+ (do_get{,e}{uid,gid}): Use gid_t/uid_t types.
+ (do_get{,p}pid): Use pic_t types.
- * misc.h: Include filter_filename.h.
- (ASSERT): Use filter_filename on __FILE__.
+ * configure.in (AC_TYPE_{GETGROUPS,SIGNAL}): Define.
+ (AC_TYPE_{MODE,OFF,PID,SIZE,UID}_T): Define.
+ * config{.in,ure}: Regenerate.
- * igen.c (lf_print_my_prefix): Use filter_filename on the filename
- argument.
+Mon Jun 3 23:19:57 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
+
+ * emul_netbsd.c (emul_netbsd_create): Use the more specific names
+ `ppc-elf' and `ppc-xcoff' for the stack-type.
+ * emul_unix.c (emul_unix_create): Ditto.
+ * emul_bugapi.c (emul_bugapi_create): Ditto.
+ * hw_init.c: Reconize the new names.
- * Makefile.in: Add filter_filename support.
+ * emul_unix.c (do_unix_break): Adjust so that the updated ioctl
+ call is used (no system parameter).
- * ppc-instructions (dcbi, icbi): Make these NOPs rather than
- invalid instructions.
+Sun Jun 2 11:21:17 1996 Michael Meissner <meissner@tiktok.cygnus.com>
- * configure.in: Add support for more --enable-sim-* switches.
- Use config.make and config.hdr to write to Makefile and config.h
- respectively. Don't rewrite Makefile, just append to it.
+ * emul_unix.{h,c}: New files to provide Solaris and Linux system
+ call emulations.
+
+ * Makefile.in (LIB_{SRC,OBJ}): Add emul_unix.{c,o}.
+ (os_emul.o): Depend on emul_unix.h.
+ (emul_unix.o): New dependency.
+
+ * configure.in (--enable-sim-alignment): Add 0|default to mean set
+ alignment to 0, which means use appropriate alignment for mode.
+ (AC_CHECK_FUNCS): Add new functions needed by emul_unix.c.
+ (AC_CHECK_HEADERS): Add new include files needed by emul_unix.c.
+ * config.in: Regenerate.
* configure: Regenerate.
- * config.{make,hdr}: New shell scripts.
-
- * Makefile.in: Remove all variables set by configure.in.
- (psim.o): Depend on $(BUILT_SRC) also.
- * emul_netbsd.c (do_gettimeofday,do_getrusage): When comparing an
- integer, use 0, not NULL.
+ * emul_generic.c (emul_write2_status): New function to return
+ results in r3 and r4 for Solaris system calls.
+ (emul_do_system_call): If the system call is not support, but
+ there is a string for the system call name, print out the string
+ instead of the system call number.
-Tue Oct 31 15:20:04 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+ * emul_generic.h (emul_write2_status): Declare it.
- * configure.in: Add support for --enable-sim-inline,
- --enable-sim-bswap, --enable-sim-cflags, --enable-sim-complex,
- --enable-sim-switch, --enable-sim-duplicate, --enable-sim-filter,
- and --enable-sim-endian switch to control various Makefile
- variables.
- * configure: Regenerate from configure.in.
- * Makefile.in: Add various Make variables that the various
- switches alter.
+ * emul_netbsd.c: Use /* */ around comment on #endif.
- * std-config.h (DEFAULT_INLINE): Don't set this to 2 if using GCC
- and optimizing by default.
+ * os_emul.c: Include emul_unix.h.
+ (os_emulations): Add emulations for Solaris, and Linux.
-Fri Oct 27 19:26:27 1995 Andrew Cagney <cagney@highland.com.au>
+ * psim.c (psim_usage): Add message about solaris, linux
+ emulations.
- * bits.h (ROTL32, ROTL64): Were functions, made them macros, now
- make them functions again. Appears 2.6.3 is confused by just a
- macro.
+Thu May 30 00:00:10 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
-Thu Oct 26 18:31:58 1995 Andrew Cagney <cagney@highland.com.au>
+ * hw_iobus.c: Tidy up notes so that they can be auto-extracted.
- * ppc-endian.c (SWAP_8): Fix 8 byte swap!
+ * README: Correct PSIM's title
- * psim.c (psim_create): Not correctly checking that runtime
- configuration of things like ENDIAN, ENVIRONMENT and ALIGNMENT
- matched the compiled in ones.
+Wed May 29 23:50:26 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
- * debug.h (ITRACE), igen.c: Tidy up more tracing flags -
- trace_semantics is now different to trace_idecode, the former
- checks the cache.
-
-Tue Oct 24 21:54:13 1995 Andrew Cagney <cagney@highland.com.au>
+ * basics.h: New global type object_disposition, used to indicate
+ the status of objects when things are restarted.
+
+Fri May 17 17:28:52 1996 Andrew Cagney <cagney@benjimen.highland.com.au>
- * ppc-instructions (mtsrin): Missing instruction
- * ppc-instructions (mfsrin): Missing instruction
- * ppc-instructions (eieio): Missing instruction
+ * device_table.h: Change the interrupt descriptor structure so
+ that it includes an additional member - an upper bound on the
+ interrupts by that name.
-Tue Oct 24 20:55:29 1995 Andrew Cagney <cagney@highland.com.au>
+ * device.c (device_interrupt_decode): Allow a range of interrupt
+ ports (eg rst0 .. rst6) if the port descriptors bound is non zero.
- * build-psim: New shell script - see internals for usage,
- simplifies the process of building custom simulators.
+ * device.c (device_tree_print_device): Include a list of valid
+ interrupt ports when listing supported devices.
-Mon Oct 23 23:48:59 1995 Andrew Cagney <cagney@highland.com.au>
+ * device.h, device.c (device_child_interrupt_*): Delete. Not used.
- * std-config.h (SEMANTICS_INLINE): Tidy up notes on each of the
- INLINE macros. Make SEMANTICS_INLINE == 1 if DEFAULT_INLINE == 2.
- Don't use DEFAULT_INLINE to define REGISTERS_INLINE DEVICES_INLINE
- DEVICE_TREE_INLINE or INTERRUPTS_INLINE as none of these are on
- the instruction or data critical paths.
-
- * FIXME: devices.c/emul_netbsd.c would benefit (slightly) from
- the inclusion of device_tree.c/emul_generic.c.
+ * emul_generic.c (emul_add_tree_hardware): Modify the creation of
+ the interrupt net so that it uses int0 .. intN.
-Mon Oct 23 00:31:50 1995 Andrew Cagney <cagney@highland.com.au>
+Tue May 14 23:03:53 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
- * os_emul.[hc], emul_generic.[hc], emul_netbsd.[hc]: replace
- system.[hc]. Start of suport for multiple emulations and
- emulation state (os_emul object).
+ * device.h, device.c (device_ioctl): Drop the system argument.
+ Devices can not obtain this using the device_system() call.
+ * device_table.h: Adjust accordingly.
+ * hw_*.c: Adjust accordingly.
+ * emul_netbsd.c (do_break): Adjust call to vm device accordingly.
+ * psim.c (psim_options): Use a device_ioctl call to force the
+ hw_trace device to update the trace options.
+ * hw_trace.c: Replace the init function with an ioctl call. Adjust
+ doc accordingly.
- * emul_generic.[hc]: Start of code to implement proper system call
- tracing (from spy).
+ * psim.c (psim_init): Re-order initialization so that the
+ os-emulation is initialized after the device tree. Without this,
+ os-emul's are not able to create instances or access properties
+ that contain an instance handle.
-Sun Oct 22 21:33:51 1995 Andrew Cagney <cagney@highland.com.au>
+ * device.h, device.c (device_add_*_property): Make these functions
+ internal to device.c. The user has access to the more generic
+ device_tree_add_parsed function. Differentiate between the initial
+ and current value for each property.
+ * (clean_device_properties): New function that deletes any
+ properties created after the start of a simulation and restores
+ the initial value of any others (ignoring ihandles).
+ * (init_device_properties): (Re)Initialize any properties that
+ contain ihandles. create
- * cpu.h, cpu.c (cpu_init): New function, zero the registers before
- the processor is started. Fixes problem of registers being
- undefined when restarting from within gdb.
+ * (device_tree_init): Include calls to clean the device tree's
+ properties and then initialize them. Document this in the device.h
+ file.
- * cpu.h, cpu.c (cpu_flush_icache): New function, flushes the
- instruction cache (if present). Fixes problem of cpu caching gdb
- breakpoint instructions.
+Mon May 6 17:36:15 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
- FIXME: PSIM sometimes aborts calling error(), it should instead
- call sim_error() say which takes care of housekeeping such as
- saving the CIA before calling error.
+ * interrupts.c (decrementer_interrupt): Always pend a decrementer
+ interrupt even if it is not yet possible to deliver it.
+
+Wed May 1 12:26:51 1996 Andrew Cagney <cagney@benjimen>
+
+ * mon.h, mon.c (mon_get_number_of_insns): Make this externally
+ visable adjusting the arguments so that the interface is correct.
+ (mon_print_info): Adjust calls.
- * NOTE: cpu_flush_cache() instead of cpu_synchronize_context() is
- used when restarting a simulation because the latter has the
- unwanted side effect (well I as a kernel hacker think it is) of
- performing an isync when the instruction stream doesn't contain
- one.
+ * registers.h, registers.c (register_description): Add phony
+ cycle, insn and stall registers.
+
+ * psim.c (psim_read_register): Return nr of instructions for given
+ processor.
+
+Tue Apr 30 22:09:09 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
+
+ * hw_htab.c: New file. Extract contents from disk_table.c.
+ Contains a device that, during initialization will create a
+ PowerPC htab in memory.
+ * hw_register.c: New file. Extract contents from disk_table.c.
+ Contains a device that, during initialization, will parse its
+ property list and use that to initialize various processor
+ registers (not target specific).
+ * hw_vm.c: New file. Extract contents from disk_table.c. Contains
+ a device that handles accesses to invalid virtual memory addresses
+ (in user mode).
+ * hw_init.c: New file. Extract contents from disk_table.c. Misc
+ devices that can initialize memory from a file.
+ * hw_trace.c: New file. Extract contents from disk_table.c.
+ Configure trace options from property values.
-Sun Oct 22 19:27:48 1995 Andrew Cagney <cagney@highland.com.au>
+ * Makefile.in (hw_htab.o, hw_register.o, hw_vm.o, hw_init.o,
+ hw_trace.c): Add new device files.
- * mon.h (new), mon.c (new), std-config.h (WITH_MON): Performance
- monitoring module. Counts both instructions issued and
- load/stores.
+ * device_table.c: Remove above code, now in separate independant
+ files.
- * NOTE: mon does not contain to count instruction loads as this
- information is already available from the mon_issue() hook.
+Fri Apr 26 00:00:07 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
- * igen.c (lf_print_c_semantic), vm_n.h: Add counting code.
+ * hw_disk.c: New file. Disk and CDROM device.
- * psim.h, psim.c (psim_create), cpu.h, cpu.c (cpu_create): Attach
- a common monitor to each of the cpus. Delete
- cpu_increment_number_of_insns() and cpu_get_number_of_insns()
- replaced by copied code in mon.[hc].
+ * Makefile.in (hw_disk.o): Add device hw_disk.c.
-Sun Oct 22 18:42:45 1995 Andrew Cagney <cagney@highland.com.au>
+ * pk_disklabel.c: New file. Implement the miss-named disk-label
+ package.
- * sim_calls.c, main.c, psim.c (psim_create): always create
- `WITH_SMP' cpus. The actual number of CPU's active in a
- simulation run is taken from the device node: /init/smp (an
- integer). WITH_SMP changed to 2 (remember to put it back to 0).
+ * Makefile.in (pk.h): Create the file pk.h that contains a list of all
+ the packages.
-Fri Oct 20 17:26:54 1995 Andrew Cagney <cagney@highland.com.au>
+ * Makefile.in (hw.h, hw.c): Add dependancy on Makefile so that
+ they are re-created when the makefile is updated.
- * system.c: More system call emulation. If code appears NetBSD
- specific, make conditional to being compiled on a NetBSD system
- (sigh).
+ * emul_generic.c (emul_add_tree_hardware): Add a disk device
+ (below the iobus) to the device tree. Include an ihandle of
+ the disk as /chosen/disk.
-Wed Oct 18 23:02:20 1995 Andrew Cagney <cagney@highland.com.au>
-
- * Makefile.in, gen.c(delete), igen.c(new), dgen.c(new),
- lf.[ch](new), table.[ch](new): Split into two generators - igen
- that outputs the instruction tables and dgen that outputs the spr
- tables. Add -f (filter out) flag to igen to filter out certain
- instructions (ex 64 bit ones) from the created tables. Include
- $(LIBIBERTY_LIB) in link options in case host lacks some libc
- functions.
+ * emul_bugapi.c (emul_bugapi_create): Don't initialize the input,
+ output and (new) disk handles yet.
+ * (emul_bugapi_init): Initialize the input, output (and just added)
+ disk ihandles here.
+ * (emul_bugapi_do_diskio): New. Performs disk i/o (well at least
+ what I think the behavour is).
+ * emul_bugapi.c (emul_bugapi_instruction_call): Add hook to disk
+ i/o bug call. For RETURN call, exit using gpr[3]'s status even
+ though this isn't part of the spec - makes it possible for machine
+ code to signal the aporting of a simulation run.
- * NOTE: igen, since it was originally written for the
- PowerPC/RS6000, things the MSB is 0 and the LSB is 63{31}.
-
- * Makefile.in, std-config.h, ppc-cache-rules(new),
- ppc-opcode-complex(new), ppc-opcode-simple(new): (for igen) Create
- cache-rule and opcode-rule tables from macros found std-config.h.
- Delete corresponding macro's from std-config.h.
-
- * igen.c (gen_itable_c, gen_itable_h), Makefile.in: code to output
- an table of all the instructions. Code to output a type
- enumerating all the instructin names.
+ * emul_chirp.c (chirp_emul_call_method): Add support for the
+ claim/release methods.
+ * (chirp_emul_exit): Add an optional exit status argument to
+ the exit method. Makes it possible for chirp emul simulations
+ to abort upon an error.
+ * device.h, device.c (device_instance_claim,
+ device_instance_release): New methods for claiming and releasing
+ memory.
+ * hw_memory.c: add claim and release memory methods.
+ * hw_*: Use the claim memory method when allocating physical
+ memory.
- * igen.c(lf_print_c_semantic): Move call to increment instruction
- counter so that it occures _after_ the instruction has been fully
- validated, was double counting illegal/invalid instructions. Add
- conditional so only compiled in when WITH_PROFILE enabled (enabled
- by default).
-
- * igen.c, cpu.h, cpu.c(cpu_increment_number_of_insns): Include
- itable.h, count individual instruction types not just total,
- adjust reporting functions to output this.
-
- * ppc-instructions (64 bit Load Doubleword with Update Indexed):
- Had 32./ instead of 31./
+Thu Apr 18 23:38:10 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
+
+ * hw_nvram.c (hw_nvram_update_clock): Use the current not previous
+ time when updating the clock.
+
+ * hw_nvram.c: Tidy up documentation
+
+Fri May 24 10:08:10 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * configure.in (AC_STRUCT_ST_{BLKSIZE,BLOCKS,RDEV}): Use these
+ macros to determine whether or not the appropriate st_<xxx> fields
+ exist in the stat structure.
+ (AC_CHECK_FUNCS): Check for all unix system calls used, except for
+ the real basic ones like open, read, write, etc.
+ * config{.in,ure}: Regenerate.
+
+ * emul_netbsd.c: Add support for missing system calls, and/or
+ missing stat fields.
+ (MAXPATHLEN): Undefine if including unistd.h, since sys/param.h
+ might define it.
+
+ * hw_pal.c (WITH_STDIO): Redefine if O_NDELAY, F_GETFL, or F_SETFL
+ are not defined.
+ (scan_hw_pal): Do not cause syntax error if O_NDELAY, F_GETFL, or
+ F_SETFL not defined.
+
+Tue May 21 17:24:45 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * emul_netbsd.c (write_stat): Don't convert st_blocks unless the
+ host is netbsd.
+
+Thu May 16 10:56:45 1996 Michael Meissner <meissner@tiktok.cygnus.com>
- * ppc-instructions (64 bit Store Double Word Conditional Indexed):
- bitrot - updated to use newer CR register operators.
+ * configure.in (AC_CHECK_HEADERS): Add sys/ioctl.h.
+ * config{.in,ure}: Regenerate.
+ * emul_netbsd.c: If HAVE_SYS_IOCTL_H is not defined, don't include
+ sys/ioctl.h.
- * ppc-instructions (64bit Floating Convert from Integer
- Doubleword): Correct call to Round_Float().
+Tue May 7 17:28:12 1996 Michael Meissner <meissner@tiktok.cygnus.com>
-Mon Oct 16 00:31:20 1995 Andrew Cagney <cagney@highland.com.au>
+ * hw_pal.c (hw_pal_instance_read_callback): Remove unused
+ variable.
- * basics.h: #include "sim_callbacks.h" earlier so that its
- prototypes are declared in all other header files.
+ * misc.c ({,target_}a2i): Rewrite to not use strtoul.
- * bits.h, bits.c, idecode_expression.h (ROTL32, ROTL64): Update
- doc in bits.h, remove dead code in bits.c, move ROTL32/ROTL64 into
- bits.h.
+ * Makefile.in ({spreg,misc}.o): Add dependency on .c file.
+ ({i,d}gen): Don't link in liberity. Use BUILD_LIBS instead of
+ LIBS.
- * cpu.c(cpu_add_commas), device_tree.h, device_tree.c(scand_*):
- Add size of buffer argument to functions writing a string into a
- buffer. Check for buffer overflow.
+Mon May 6 11:31:43 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * hw_pal.c (hw_pal_instance_read_callback): If using stdio, use
+ fgets to read line. If not using stdio, do a simple blocking read
+ of len bytes.
+
+Fri May 3 15:07:42 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * Makefile.in: Correctly build simulator for build machine != host
+ machine.
+
+Tue Apr 30 18:46:05 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * configure.in (--enable-hostendian): Rework so the default uses
+ the AC_C_BIGENDIAN results. Only run AC_C_BIGENDIAN if not cross
+ compiling.
+ * configure: Regenerate.
-Sun Oct 15 22:16:11 1995 Andrew Cagney <cagney@highland.com.au>
+ * sim-endian.h: Add more tests for host endian to support more
+ platforms in a cross compilation environment.
- * devices.h, devices.c, debug.h, debug.c: add macro's for tracing
- of each device. Make parameter names consistent so macros work.
- Use macro's in device functions.
+Wed Apr 17 14:38:06 1996 Michael Meissner <meissner@tiktok.cygnus.com>
- * device_tree.c, devices.h, devices.c: include path to device in a
- devices node when creating it.
+ * hw_pal.c ({scan,write}_hw_pal): If WITH_STDIO == DO_USE_STDIO,
+ use stdio, instead of unpended read/printf_filtered.
+ (hw_pal_instance_write_callback): If WITH_STDIO == DO_USE_STDIO,
+ flush stdout after writing the characters.
- * device_tree.c, debug.h, debug.c: Add tracing of `device-tree'.
+ * options.c (print_options): Print out WITH_STDIO.
- * core.c: add tracing of core-device, adjust parameter names in
- core functions to be consistent with those in devices*.
+ * Makefile.in (STDIO_CFLAGS): Pass on result of @sim_stdio@
+ configuration variable.
+ (CONFIG_CFLAGS): Include STDIO_CFLAGS.
+ (hw.{c,h}): Allow for source dir != build dir, and for HW_SRC
+ files to contain directory pieces.
-Sun Oct 15 20:33:20 1995 Andrew Cagney <cagney@highland.com.au>
+ * std-config.h (DO{,NT}_USE_STDIO): New flags for whether we
+ should use stdio for console input.
+ (WITH_STDIO): If not defined, define as DONT_USE_STDIO.
- * debug.h, debug.c (trace_option): New function. Parses the trace
- option, updating the trace array.
+ * configure.in (--enable-sim-stdio): Add new switch to control
+ whether stdio is used for console I/O.
+ * configure: Regenerate.
- * debug.h, debug.c (trace_usage): New function. Outputs the list
- of all possible trace options.
+ * interrupts.c (external_interrupt): Declare it to be
+ INLINE_INTERRUPTS, not INLINE_CPU.
- * sim_calls.c (sim_open), main.c (main): Use new trace_option() to
- parse trace options specified with the simpler -t flag. Adjust
- usage.
+Mon Apr 15 23:30:56 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
- * FIXME: basic parsing of command line options is still duplicated
- by main.c and sim_calls.c
+ * events.c (insert_event_entry): Allow events to be scheduled
+ *NOW* (at delta time 0). Add assertions to clarify behavour of
+ event queue.
-Thu Oct 26 10:42:28 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+ * events.c (update_time_from_event): New function. Calculates the
+ number of ticks from the next event. Use this.
- * Makefile.in (clean): Delete *.i and *.out files.
+Sun Apr 14 21:39:45 1996 Andrew Cagney <cagney@highland.com.au>
- * ppc-endian.c (SWAP_n): Add SET argument to allow use of SWAP
- macros for either assignment or return. Fix SWAP_8 to use a
- union, and two SWAP_4's. Delete SWAP_N, since nobody uses it now.
- (ENDIAN_N): Add SET argument to SWAP_n calls. Delete macro defs
- that hardwired swapping on/off, let optimizer delete dead code.
+ * emul_netbsd.c (do_break): Return 0 if success (instead of
+ adjusted break).
- * main.c (main): Add printf that we caught a signal and print out
- the failing address.
+ * device_table.c (vm_ioctl_callback): Don't return adjusted break
+ (isn't needed).
-Thu Oct 19 21:43:39 1995 Fred Fish <fnf@fishfood.amigalib.com>
+Sun Apr 14 21:32:41 1996 Andrew Cagney <cagney@highland.com.au>
- * Makefile.in: Remove tabs from otherwise empty line.
- Confuses many non-GNU versions of "make".
+ * device_table.h: Change type of the device ioctl so that it
+ returns an int (status).
+ * device.h (device_ioctl): Ditto.
+ * device.c (device_ioctl): Ditto.
-Wed Oct 18 08:51:25 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+ * device_table.c (stack_ioctl_callback): Return 0 status.
+ (vm_ioctl_callback): Ditto
- * Makefile.in (clean): Delete files produced by gen.
+Sat Apr 13 00:00:24 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
-Mon Oct 16 17:34:24 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+ * emul_netbsd.c (do_read): Correctly set the return value.
+ (do_getpid): Ditto.
+ (do_getuid): Ditto.
+ (do_geteuid): Ditto.
+ (do_dup): Ditto.
+ (do_getegid): Ditto.
+ (do_getgid): Ditto.
+ (do_sigprocmask): Ditto.
+ (do_umask): Ditto.
+ (do_dup2): Ditto.
+ (do_gettimeofday): Ditto.
+ (do_getrusage): Ditto.
+ (do_fstat): Ditto.
+ (do_stat): Ditto.
+ (do_lseek): Ditto.
+ (do___sysctl): Ditto.
- * gen.c (lf_print_c_semantic_function): Move counting # of
- instructions here so it works with caching.
- (gen_idecode_c): Move from here.
+Fri Apr 12 20:56:47 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
-Wed Oct 11 17:13:15 1995 Andrew Cagney <cagney@highland.com.au>
+ * device_table.c (vm_ioctl_callback): Don't access the processor
+ registers directly, instead leave it to the caller to handle this.
- * gen.c, ppc-instructions, psim.c: Fix code for generating
- cracking instruction cache. Delete the code that cached just the
- result from doing an instruction lookup - this ran slower than no
- cache at all.
+ * emul_netbsd.c (do_break): Which calls vm_ioctl_callback to
+ perform a break. Pass in the new break value and set the
+ registers according to the result.
-Fri Oct 13 09:58:43 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+ * emul_generic.c (emul_write_status): Change so that r3 contains
+ either status or errno and failure is indicated by SO.
- * Makefile.in (gen.o): Include $(INLINE_CFLAGS).
+Thu Apr 4 23:03:38 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
- * debug.h (ppc_trace): Rename from trace, to avoid a conflict with
- TCL when gdb is linked with the simulator.
- * debug.c (ppc_trace): Ditto.
- * sim_calls.c (sim_open): Change trace -> ppc_trace.
- * main.c (main): Ditto.
+ * emul_bugapi.c (emul_bugapi_create): More strict check of OEA
+ address.
- * cpu.c (cpu_add_commas): Remove extra static.
+Thu Apr 4 20:58:05 1996 Andrew Cagney <cagney@highland.com.au>
-Thu Oct 12 11:35:53 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+ * interrupts.h (interrupts): New structure contains state of
+ pending interrupts.
- * Makefile.in (psim.o): Now that inlines are turned on, make
- psim.o depend on all sources.
+ * cpu.c (cpu_interrupts): New function. Pending interrupt status
+ in the cpu and grant access to it. Add interrupts to cpu
+ structure.
- * cpu.c (cpu_add_commas): New function to format a long with
- commas.
- (cpu_print_info): Use it to print number_of_insns.
-
- * ppc-endian.c (SWAP_n): New macros to speed up byte swapping for
- 2, 4, and 8 bytes.
- (ENDIAN_N): If both target and host byte orders are known, don't
- bother testing CURRENT_{TARGET,HOST}_BYTE_ORDER.
+Fri Mar 29 22:09:25 1996 Andrew Cagney <cagney@highland.com.au>
- * ppc-endian.h (target specific H2T_n/T2H_n macros): Remove #if 0
- to allow target specific H2T_n/T2H_n macros to be used.
- (htonl, ntohl): If compiled on a 486 by GCC and WITH_BSWAP is
- non-zero, redefine the htonl/ntohl macros to use the BSWAP instead
- of the 3 instruction sequence that runs on 386s.
+ * device.c (device_tree_add_parsed): Check that the creation of a
+ device instance worked before using it.
- * std-config.h (WITH_{HOST,TARGET}_BYTE_ORDER): Don't override if
- specified on the compile line.
- (WITH_BSWAP): If not defined, define as 0.
+ * psim.c (psim_halt): Remove cia argument from psim_halt. This
+ function does not save the CIA so do not pass it in.
- * Makefile.in (INLINE_CFLAGS): Add -DDEFAULT_INLINE=2 to add
- default inline support. Pass INLINE_CFLAGS when compiling.
+Fri Mar 29 21:30:56 1996 Andrew Cagney <cagney@highland.com.au>
- * devices.{h,c} (unimp_device_ioctl): Use STATIC_DEVICES, not
- INLINE_DEVICES since GCC doesn't like inline functions that
- accept variable arguments.
- (stack_ioctl_callback): Make function just static because GCC
- doesn't like inline functions that accept variable arguments.
+ * hw_pal.c (hw_pal): Merge the halt and icu and console devices
+ found in device_table.c into a single hack pal.
- * devices.h (STATIC_DEVICES): Define as empty if not defined.
+ * device_table.c (halt, icu, console): Delete.
- * inline.c: Correct pathnames of included C files to match current
- implementation.
+ * Makefile.in (hw_pal.o): New dependency.
- * inline.h (STATIC_DEVICES): If DEVICES_INLINE is defined to be
- non-zero, define STATIC_DEVICES to be static.
+ * emul_generic.c (emul_add_tree_hardware): Re-arange device tree
+ so that it uses the pal instead of the icu/halt/console devices.
+ Wire the pal's interrupt ports up to the cpu nodes.
- * std-config.h (INLINE): If GNU C and optimizing, define this as
- __inline__.
- (DEFAULT_INLINE): If not defined, define as 0.
- (ENDIAN_INLINE): If not defined, define as DEFAULT_INLINE.
- ({CORE,VM,CPU,EVENTS,REGISTERS,INTERRUPTS}_INLINE): Ditto.
- ({SPREG,IDECODE}_INLINE): Ditto.
-
-Wed Oct 11 17:13:15 1995 Andrew Cagney <cagney@highland.com.au>
+Fri Mar 29 20:17:17 1996 Andrew Cagney <cagney@highland.com.au>
- * ppc-instructions: Initial cut of floating point suport added.
- Of note include - use of host IEEE floating point instructions,
- use of PowerPC manual pseudo code to handle the FPSCR. It is not
- currently a pretty sight.
-
- * memory_map.h, memory_map.c, memory_map_n.h, core.h, core.c:
- merge into core.h, core.c, core_n.h. The type memory_map replaced
- with core_map. This removes a level of pointer indirection when
- translating an address.
+ * hw_iobus.c (hw_iobus_attach_address_callback): Move from
+ device_table.c to here.
- * memory_map.h, memory_map.c, memory_map_n.h: delete.
+ * Makefile.in (hw_iobus.o): New dependency.
- * Makefile.in et.al (sorry): tweek to use new core, core_map and
- core.h.
-
-Wed Oct 11 12:10:26 1995 Andrew Cagney <cagney@highland.com.au>
+Fri Mar 29 12:17:58 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
- * sim_calls.c, main.c: Add -g (trace_gdb) option, add tracing to
- most of the other functions in sim_calls.c.
+ * emul_bugapi.c (_os_emul_data): Add fields for output, input.
+ (emul_bugapi_create): Create input, output from /chosen/stdin and
+ /chosen/stdout.
+ (emul_bugapi_do_{read,write}): Switch to use device_instance
+ interface.
+ (emul_bugapi_instruction_call): Change calls to
+ emul_bugapi_do_{read,write} to pass device instance argument.
- * basics.h (CONCAT3), memory_map.c, memory_map_n.h, Makefile.in:
- Add macros to better cover up `generic' code. Makes it possible
- to step through the generic code!
+Tue Mar 26 14:57:58 1996 Michael Meissner <meissner@tiktok.cygnus.com>
- * vm.c, vm_n.h, Makefile.in: ditto
-
-Tue Oct 10 15:42:59 1995 Andrew Cagney <cagney@highland.com.au>
+ * igen.c (idecode_switch_end): Fix 2/26 change so that an extra
+ default is not written out if a default was already written.
- * devices.h, devices.c, memory_map.h, memory_map.c: Changed
- callback interface so that there is a read/write buffer but no
- read/write_word. VEA default memory read/write handler sometimes
- couldn't resolve an access and of those some were for a memory
- fault and some were because gdb was making a bogus request.
+ * psim.c (psim_{read,write}_register): Use sizeof unsigned_8 to
+ size cooked_buf, not sizeof natural_word, since floating point
+ registers are 8 bytes.
- * devices.h, devices.c, memory_map.h, memory_map.c, vm.h, vm.c:
- eliminate transfer_mode (raw or cooked) parameter from read/write
- buffer.
-
-Fri Oct 6 20:23:56 1995 Andrew Cagney <cagney@highland.com.au>
+Mon Mar 25 22:07:13 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
- * ppc-instructions (fmul, fmuls): correct instruction format - had
- FRB instead of FRC.
+ * configure: Regenerate with autoconf 2.9.
-Wed Oct 4 17:31:12 1995 Andrew Cagney <cagney@highland.com.au>
+Thu Mar 21 00:14:26 1996 Andrew Cagney <cagney@highland.com.au>
- * psim.c, device_tree.h, device_tree.c, devices.c (printd_*,
- scand_*): new functions to parse/print fields in device names
- while hiding any machine dependency.
+ * device_table.h: Always include string headers.
- * devices.c, psim.c: Change the stack init code so that it is
- handled by a device. Arguments passed across using a device ioctl
- (hack).
+Thu Mar 21 00:06:09 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
- * devices.h, devices.c: device ioctl callback changed to allow a
- variable number of arguments. This gives greater flexability and
- greater chance of bugs.
+ * main.c (error): Be careful to not try to print out statistics
+ when the simulation was never created.
-Tue Oct 3 22:01:56 1995 Andrew Cagney <cagney@highland.com.au>
+Sun Mar 17 22:40:57 1996 Andrew Cagney <cagney@highland.com.au>
- * main.c (printf_filtered, error): Missing va_end() to close off
- variable argument use.
+ * basics.h: Move the event queue's definition to here so that it
+ can be refered to globally with out importing all of events.h.
- * Makefile.in (tmp-gencode): comment out hack to get around some
- versions of make not handling files being created as side-effects.
+ * psim.h, psim.c (psim_event_queue): New function. Grant access
+ to the simulation event queue. Will make this the single point of
+ access (there is after all only one event queue in the
+ simulation).
- * gen.c (lf_open): Add -n (real_file_name) option. Specifies an
- alternative file name to use in output files for things like #line
- macros.
+ * cpu.c (cpu_create): Use psim_event_queue to obtain the event
+ queue instead of it being passed in. No longer allow access to
+ the cpu's copy of the event queue.
- Makefile.in (tmp-gencode): Use gen -n so that debug info is
- correct.
+Sun Mar 17 22:40:57 1996 Andrew Cagney <cagney@highland.com.au>
- * Makefile.in (TARGETLIB): Use this instead of libsim.a in the
- Makefile.
+ * events.h, events.c (event_handler): Remove event_queue from
+ arguments passed to an event handler. That argument is redundant
+ - the `data' should refer to a data structure that contains the
+ event queue if queing is needed.
-Sat Oct 7 22:40:59 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+ * cpu.c (cpu_decrement_event): adjust
- * sim_calls.c (sim_set_callbacks): Define new function.
+ * events.c (event_queue_process): adjust
-Fri Oct 6 17:23:10 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+Sun Mar 17 22:40:57 1996 Andrew Cagney <cagney@highland.com.au>
- * psim.c (psim_print_info): Print exit status or signal number.
+ * device.h, device.c (device_system): New, returns a handle for
+ the system given the device.
-Mon Oct 2 11:46:37 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+ * device.c (device_address_init): Store a pointer back to the
+ system in each devices node.
- * cpu.c (struct _cpu): Add number_of_insns field to trace how many
- instructions are executed.
- (cpu_increment_number_of_insns): New function to increment the
- number of instructions issued.
- (cpu_get_number_of_insns): New function to return the number of
- instructions issued.
- (cpu_print_info): New function to print cpu related information.
- At present, print the number of instructions executed.
+ * device_table.h: Don't pass `system' into each device when it is
+ being initialized, this is now available using device_system(me).
- * gen_idecode_c: Emit call to cpu_increment_number_of_insns within
- idecode_issue.
+ * device.c (device_address_init, device_data_init): Adjust.
- * psim.c (psim_print_info): New function to iterate over each of
- the CPU's calling cpu_print_info.
-
- * psim.h,cpu.h: Add new declarations.
+ * hw_cpu.c, hw_nvram.c, hw_memory.c, hw_eeprom.c, device_table.c:
+ Adjust.
- * sim_calls.c (sim_open): Add argument processing to add the same
- switches main.c accepts for the standalone processor.
- (sim_close): Call psim_print_info if -I.
+Sun Mar 17 22:40:57 1996 Andrew Cagney <cagney@highland.com.au>
- * main.c (main): Add comment saying to update sim_calls.c when
- adding switches. Add -I to call psim_print_info when done.
- (usage): Update usage message.
+ * interrupts.c (decrementer_interrupt, external_interrupt):
+ Remember that an interrupt wasn't delivered so that it can be
+ tried again later.
-Sun Oct 1 13:52:59 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+ * interrupts.c (check_masked_interrupt): New function. (re)
+ checks for the posibility that a recent change to the MSR may have
+ made it possible to deliver an interrupt that was previously
+ masked be the EE bit.
- * main.c (printf_filtered): Correct to match new prototype.
+ * ppc-instructions (mtmsr, mfmsr, rfi): Check for posibility of
+ a pending interrupt being delivered using check_masked_interrupt().
-Sat Sep 30 20:47:05 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+ * cpu.c (cpu_decrement_event): Just call decrementer_interrupt()
+ leaving it to that module to handle both interrupt synchronization
+ and masking.
- * sim_callbacks.h (printf_filtered): Correct prototype.
+ * cpu.c (struct _cpu): remove variables that were going to record
+ pending decrementer and external interrupts.
-Thu Sep 21 16:26:49 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+Sun Mar 17 22:40:57 1996 Andrew Cagney <cagney@highland.com.au>
- * device_tree.c (OEA_MEMORY_SIZE): Define if not defined to
- 0x100000.
- (clayton_memory_size): Define as OEA_MEMORY_SIZE.
+ * hw_cpu.c, hw_cpu.h: New files. Implement a device that sits
+ between the interrupt controller and the simulators internal
+ processor model. Maps device interrupts onto the processor
+ interrupt function calls.
- * std-config.h (WITH_TRACE): Default to 1 now.
+Mon Mar 4 06:06:54 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
- * psim.c (write_stack_arguments): Don't write any stack arguments
- if OEA.
+ * hw_nvram.c: NVRAM device that includes a real-time clock that is
+ updated each second.
- * main.c (main): Switch to using getopt. Make -p also set
- trace_semantics. Make -a turn on all trace flags. Make -C turn
- on console tracing.
+Mon Mar 4 04:18:50 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
- * device_tree.c (create_option_device_node): Assume a program is
- OEA if the start address is < 4096, not just == 0.
+ * device.h (attach_type): Remove attach_default type address
+ spaces. Will replace with levels of callback memory.
-Wed Sep 20 13:36:06 1995 Ian Lance Taylor <ian@cygnus.com>
+ * corefile.h, corefile.c (new_core_mapping), corefile.c
+ (core_map_attach): Replace default attach with a layerd callback
+ approach.
- * Makefile.in (maintainer-clean): New synonym for realclean.
+Sun Mar 3 03:58:46 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
-Sun Sep 10 10:23:56 1995 Michael Tiemann <tiemann@axon.cygnus.com>
+ * device.c (split_property_specifier): ensure that only a single
+ property is found.
+ (split_value): New function, parses the value part of a device
+ spec.
- * registers.c (register_description): Add gdb synonyms for cr
- (cnd) and msr (ps).
+ * device.c (device_tree_add_parsed): Use the interrupt conversion
+ functions to determine the interrupt port numbers.
-Fri Sep 8 13:16:10 1995 Ian Lance Taylor <ian@cygnus.com>
+ * device_table.h: Add table that maps between an interrupts
+ symbolic name and its port number.
- * Makefile.in (install): Don't install in $(tooldir).
+ * device.h, device.c (device_interrupt_decode,
+ device_interrupt_encode): new functions use the recently added
+ interrupt port name/number tables to perform conversion.
- * configure.in: Call AC_CONFIG_HEADER. Don't try to use
- bfd/hosts/*.h file or bfd/config/*.mh file. Call AC_PROG_CC and
- AC_PROG_RANLIB. Substitute in values for CFLAGS, HDEFINES, AR,
- and CC_FOR_BUILD. Call AC_CHECK_HEADERS for various header files.
- Touch stamp.h if creating config.h.
- * configure: Rebuild.
- * config.in: New file, created by autoheader.
- * Makefile.in (AR): Define as @AR@.
- (CC): New variable, defined as @CC@.
- (CFLAGS): Define as @CFLAGS@.
- (CC_FOR_BUILD): New variable, defined as @CC_FOR_BUILD@.
- (RANLIB): Define as @RANLIB@.
- (HDEFINES, TDEFINES): New variables.
- (@host_makefile_frag@): Remove.
- (mostlyclean): Make the same as clean, not distclean.
- (clean): Remove config.log.
- (distclean): Remove config.h and stamp-h.
- (Makefile): Don't depend upon @frags@. Just rebuild Makefile when
- invoking config.status.
- (config.h, stamp-h): New targets.
- (gen, gen.o): Build with CC_FOR_BUILD, not CC.
- (ppc-config.h): Rename from old config.h build.
- * (basics.h,gen.c,ppc-endian.c,psim.c): Include ppc-config.h.
-
-Fri Sep 8 09:51:03 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+Sun Mar 3 03:23:59 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
+
+ * device.h, device.c (device_set_array_property,
+ device_set_boolean_property, device_set_ihandle_property,
+ device_set_integer_property, device_set_string_property): New
+ functions - allow the value of a given property to be changed.
+
+ * device.h, device.c: Re-order declaration and definition of
+ property functions.
+
+Sun Mar 3 03:10:22 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
+
+ * device.c (device_tree_print_device, device_tree_add_parsed):
+ Remove references to phandle properties.
+
+Wed Feb 28 00:43:07 1996 Andrew Cagney - aka Noid <cagney@highland.com.au>
+
+ * Makefile.in (corefile.o): missing dependency on device_table.h
+ etc.
+
+Tue Feb 27 23:59:35 1996 Andrew Cagney - aka Noid <cagney@highland.com.au>
+
+ * device_table.h: Revamp device init callbacks so that they are a
+ sub structure.
+ * device.c (device_init_data, device_init_address): If an init
+ callback is NULL assume it should do nothing.
+ * device_table.c (ignore_device_init, unimp_device_init): delete
+ as redundant.
+ * device_table.c, hw_memory.c: adjust.
+
+ * (io): ditto.
+ * (dma): ditto.
+ * (device_instance): ditto.
+ * (ioctl): ditto.
+ * (address nee config_address): ditto.
+ * (interrupt): ditto.
+
+Mon Feb 26 21:11:20 1996 Andrew Cagney - aka Noid <cagney@highland.com.au>
+
+ * igen.c (idecode_switch_end): Output a default entry when the
+ switch statement is perfect. Firstly stops GCC complaining about
+ an incomplete switch and secondly it will be eliminated by a good
+ compiler any way.
+
+Mon Feb 26 22:47:15 1996 Andrew Cagney - aka Noid <cagney@highland.com.au>
+
+ * Makefile.in (hw.h, hw.c): New targets. Create from the list of
+ hw_*.c files. hw.h declares a device descriptor table for each hw
+ device while hw.c lists those tables in a form suitable for the
+ construction of a top leveltable in device_table.c.
+
+ * Makefile.in (device_table.o): now depends on hw.c a generated
+ table of hw.
+
+ * device_table.c (device_table): Re-arange the table of devices so
+ that two levels are possible. Make use of hw.c.
+ * device_table.h: ditto.
+
+ * device.c (device_template_create_device): Handle new two level
+ device lookup table.
+ * device.c (device_usage): ditto.
+
+Mon Feb 26 22:24:00 1996 Andrew Cagney - aka Noid <cagney@highland.com.au>
+
+ * device_table.c: Delete the memory device (moved to hw_memory.c).
+
+ * hw_memory.c: New file. Just an OpenBoot memory device.
+
+Wed Jan 17 21:47:34 1996 Andrew Cagney <cagney@highland.com.au>
- * configure{,.in}: Don't include sysdep.h from bfd, since bfd no
- longer provides it.
- * basics.h (sysdep.h): Don't include it.
- * Makefile.in (BASICS_H): Remove sysdep.h.
+ * device.c (device_init_address): New. Split initialization into
+ two stages, address and address spaces
+ * device.c (device_init_data): New. ... and data or other work.
+ With out this, devices try to modify memory before it as been
+ attached.
-Wed Sep 6 13:25:42 1995 Andrew Cagney <cagney@highland.com.au>
-
- * core.c (core_add_data): First growth of bss was being put at
- wrong address (0) instead of &end.
-
- * core.c (core_add_stack, core_add_data): Was not handling case
- where bss/stack is grown across the current end-of-{bss,stack}.
+ * device.c (device_tree_init): Update to perform staged
+ initialization.
-Wed Sep 6 00:46:10 1995 Andrew Cagney <cagney@highland.com.au>
+ * device.c (device_init): Delete.
- * system.c (system_call): Fix SYS_break - was aligning bss to a
- page boundary instead of just an 8 byte one; On first call sbrk(0)
- != sbrk(0).
+Wed Jan 17 21:43:09 1996 Andrew Cagney <cagney@highland.com.au>
-Thu Aug 24 14:48:54 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+ * device_table.c (data_*): Rewrite to make heaver use of property
+ nodes. Allow initialization by different data types.
+ * device_table.c (htab_* pte_*): Rewrite to use properties.
- * Makefile.in (install): Fix install rule.
+ * emul_chirp.c (emul_chirp_create): Use
+ * emul_bugapi.c (emul_bugapi_create): Ditto
+ * emul_netbsd.c (emul_netbsd_create): Ditto
-Tue Aug 22 09:31:18 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+Wed Jan 17 21:24:50 1996 Andrew Cagney <cagney@highland.com.au>
- * system.c (system_call): Add read support.
+ * emul_generic.c (emul_add_tree_options): Annotate existing tree
+ with options that haven't yet been specified.
+ * emul_generic.c (emul_add_tree_hardware): Annotate existing tree
+ with demo devices and properties.
- * main.c (main): -t sets trace_device_tree. Correct usage message
- to current reality.
+ * emul_chirp.c (emul_chirp_create): Update to use new
+ device_tree_add_parsed call and additional information now
+ included in the device tree. Use emul_add_tree* functions to add
+ any missing details.
+ * emul_bugapi.c (emul_bugapi_create): Ditto
+ * emul_netbsd.c (emul_netbsd_create): Ditto
- * device_tree.c (update_memory_node_for_section): Make tracing
- output line up. If not code or readonly, assume that the section
- is a data section and has read/write permissions. Add readonly
- support.
+Wed Jan 17 21:18:27 1996 Andrew Cagney <cagney@highland.com.au>
- * core.c (create_core_from_addresses): Print end address in traces
- and make tracing output line up.
+ * device.c (device_instance_create): New. Create/delete and
+ operate on instances of a device.
+ * device.c (device_instance_delete): Ditto
+ * device.c (device_instance_read): Ditto
+ * device.c (device_instance_write): Ditto
+ * device.c (device_instance_seek): Ditto
+ * device.c (device_instance_data): Ditto
+ * device.c (device_instance_name): Ditto
+ * device.c (device_instance_path): Ditto
- * Makefile.in: Rewrite from Makefile to work with the Cygnus
- environment, and support compiling in a different directory than
- the sources reside in.
+ * emul_chirp.c (chirp_emul_open): Implement using device_instance.
+ * emul_chirp.c (chirp_emul_close): Ditto
+ * emul_chirp.c (chirp_emul_read): Ditto
+ * emul_chirp.c (chirp_emul_write): Ditto
+ * emul_chirp.c (chirp_emul_seek): Ditto
- * ppc-endian.h: Rename from endian.h so that it doesn't get
- confused with /usr/include/sys/endian.h on Linux. Add Linux
- endian support.
+ * emul_chirp.c (chirp_read_t2h_args): Read arguments from device.
+ Being careful to convert all from target to host byte order.
+ * emul_chirp.c (chirp_write_h2t_args): Converse.
- * ppc-endian.c: Rename to be consistant with ppc-endian.h.
- Include ppc-endian.h, not endian.h.
+Wed Jan 17 20:07:15 1996 Andrew Cagney <cagney@highland.com.au>
- * basics.h (sysdep.h): Include sysdep.h that configure makes.
- Include ppc-endian.h, not endian.h.
+ * device.c (device_tree_add_parsed): New. Rewrite code to add
+ devices to the device tree so that a single printf style function
+ is used.
- * std-config.h: Rename from ppc-config. Put #ifndefs around most
- configuration macros, so they can be overridden via CFLAGS. By
- default, turn off tracing.
+ * device.c (device_tree_add_*): Delete. Replaced by above.
+
+ * device.c (split_device_specifier): Functions to manipulate a
+ device specifier (path) breaking it into its components
+ * device.c (split_property_specifier): Ditto
+ * device.c (split_device_name): Ditto
+ * device.c (split_find_device): Ditto
+
+ * device.c (scan_*): Delete
+
+ * device.c (device_tree_find_device): Rewrite to use above.
+ * device.c (device_add_property): Ditto
+
+Wed Jan 17 19:51:56 1996 Andrew Cagney <cagney@highland.com.au>
+
+ * psim.c(psim_options): Parse the psim options, installing their
+ value in the device tree. Options are now first entered into a
+ device tree and then extracted out again when needed. This allows
+ greater flexability in configuration.
+
+ * psim.c (psim_tree): Returns a basic device tree ready for
+ parsing by psim_options.
+ * psim.c (psim_usage): New. Give usage to varing levels of detail
+ according to the verbosity. In turn output device and trace
+ usage.
+
+ * main.c (main): Update to use new system
+ * sim_calls.c (sim_open, sim_do_command): Ditto
+
+ * psim.c (psim_options): Add `r' option - ram size.
+ * psim.c (psim_options): Add `o' option - openboot tree entry.
+ * psim.c (psim_options): Add `h'/`H' options - more help.
+
+ * debug.c (trace_usage): Add more detailed help.
+ * device.c (device_usage): New. Output help including a list of
+ the devices currently available in the device table.
+ * device_table.c: Add usage operator to each device.
+
+ * corefile.c (core_create, core_device_create): Adjust so that the
+ core device is created earlier for psim_tree(). Core can later be
+ created from it.
+
+ * psim.c (psim_create): Update to handle above way of creating
+ things. Extract all information from the device tree.
+
+ * device_tree.c (trace_*): New device node, its properties are
+ used to set the value of the trace options. Init this device (in
+ psim_options) when ever the options are updated.
+
+Wed Jan 17 19:46:07 1996 Andrew Cagney <cagney@highland.com.au>
+
+ * debug.h: Add trace_print_info, trace_print_device_tree and
+ trace_dump_device_tree. The first is a replacement for the
+ variable `print_info' found in main.c and sim_calls.c. The latter
+ two enable the dumping of the entire device tree.
+
+ * debug.c: Add to trace_description table.
+
+ * main.c (main): Use above trace instead of local variable
+ * sim_calls.c (sim_close): Ditto
+
+ * device.c (device_tree_print_device): New. Prints the device
+ tree in a format that is consistent with what can be parsed by the
+ device tree load from file code.
+
+ * psim.c (psim_create): Dump device tree if enabled. If nump
+ selected, exit psim immediatly.
+
+Wed Jan 17 19:36:52 1996 Andrew Cagney <cagney@highland.com.au>
+
+ * corefile-n.h (core_map_read_N): When mapping from an address to
+ a device, do not subtract the devices base. The device its self
+ can do this. Brings the behavour into line with OpenBoot.
+ * corefile-n.h (core_map_write_N): Ditto
+ * corefile.c (core_map_read_buffer): Ditto
+ * corefile.c (core_map_write_buffer): Ditto
+
+ * device_table.c (console_io_read_buffer_callback): Adjust to
+ handle biased address.
+ * device_table.c (console_io_write_buffer_callback): Ditto
+
+Wed Jan 17 18:36:09 1996 Andrew Cagney <cagney@highland.com.au>
+
+ * device.c (attach_device_interrupt_edge): New. Interrupt model
+ did not allow interrupts to be wired up as a general net (edges).
+ Re-implement so that interrupt events can be passed to multiple
+ controllers and interrupt controllers can further propogate
+ interrupt events.
+
+ * device.c (attach_device_interrupt_edge) : New, Ditto
+ * device.c (detach_device_interrupt_edge) : New, Ditto
+ * device.c (clean_device_interrupt_edges) : New, Ditto
+ * device.c (device_interrupt_event) : New, Ditto
+ * device.c (device_interrupt_attach) : New, Ditto
+ * device.c (device_interrupt_detach) : New, Ditto
+ * device.c (device_child_interrupt_attach) : New, Ditto
+ * device.c (device_child_interrupt_detach) : New, Ditto
+
+ * device.c (device_attach_interrupt) : Delete old
+ * device.c (device_detach_interrupt) : Delete old
+ * device.c (device_interrupt) : Delete old
+ * device.c (device_interrupt_ack) : Delete old
+
+ * device_table.c (unimp_*) : Update to match
+
+ * device_table.c (icu_io_write_buffer_callback) : Update to use
+ interface.
+ * device_table.c (icu_interrupt_event_callback) : Ditto
- * configure.in: Clone from other simulator targets.
- * configure: Generate via autoconf from configure.in.
+Wed Jan 17 18:18:40 1996 Andrew Cagney <cagney@highland.com.au>
-Sat Aug 19 09:05:32 1995 Andrew Cagney <cagney@highland.com.au>
+ * device.c (external_to_device) : New function that provides a
+ standard mapping between a devices internal representation (a
+ pointer) and its external (or what is passed to a client)
+ representation (a phandle). Implement using the cap object
+ attached to the root node.
- * ppc-instructions: fix srawi (was geting XER[CA] real wrong).
+ * device.c (device_to_external) : Ditto
+ * device.c (external_to_device_instance) : Ditto but for ihandle
+ and device instance.
+ * device.c (device_instance_to_external) : Ditto
- * interrupts.c (data_storage_interrupt): allow stack to grow by
- upto one MB per increment.
+ * Makefile (device.o): Add dependency on cap.
- * ppc-instructions: divw was computing rA / rA not rA / rB
+ * emul_chirp.c (struct _emul_chirp_data) : Elimate use of cap. Code
+ needing to translate between internal and external representations
+ changed to use the external_to_device et.al. device operations.
+ * emul_chirp.c (chirp_emul_*) : Ditto
- * main.c (main): really stupid. Wasn't exiting with correct status
+ * Makefile (emul_chirp.o): Remove dependency on cap
-Fri Aug 18 00:38:01 1995 Andrew Cagney <cagney@highland.com.au>
+Sat Jan 6 10:13:26 1996 Andrew Cagney - aka Noid <cagney@highland.com.au>
- * system.c (system_call): add system calls kill(2) and getpid(2).
+ * emul_chirp.c (map_over_chirp_note): Tighten up (and fix) checks
+ on OpenBoot note section.
- * main.c (main): Check/return exit status when simulation
- finishes.
+Fri Jan 5 20:28:53 1996 Andrew Cagney <cagney@hignland.com.au>
-Thu Aug 17 14:29:18 1995 Andrew Cagney <cagney@highland.com.au>
+ * emul_generic.c (emul_write_buffer): Use vm faulting byte
+ read/write calls for buffer transfers. This will cause a fault to
+ occure if the transfer fails. CHRP catches the fault while the
+ others suffer the consequences.
+ (emul_read_buffer): Ditto.
+ (emul_write_word): Ditto.
+ (emul_read_word): Ditto.
+ (emul_read_string): Ditto.
- * device_tree.c (create_option_device_node): Alignment rules (at
- least for the moment) now are for strict alignment only for LE OEA
- mode. (Because of compiler problems).
+Fri Jan 5 18:55:34 1996 Andrew Cagney <cagney@highland.com.au>
- * system.c (system_call) SYS_exit: Wasn't exiting with correct status.
+ * emul_chirp.c (emul_chirp_create, emul_chirp_instruction_call),
+ emul_generic (emul_blr_instruction): Use a real blr instruction to
+ return from a client service call.
-Thu Aug 17 01:16:38 1995 Andrew Cagney <cagney@highland.com.au>
+ * emul_chirp.c (services): Add all OpenBoot services to table.
- * vm.c (DEFINE_VM_DATA_MAP_WRITE_N): For miss aligned transfer
- forgot to return.
+ * emul_generic.h, emul_bugapi.c (emul_bugapi_create), emul_chirp.c
+ (emul_chirp_create) : Use names instead of numbers for
+ instructions being stored in memory.
- * system.c (system_call): didn't page align break argument before
- determining increment break increment.
+Fri Jan 5 18:52:28 1996 Andrew Cagney <cagney@highland.com.au>
- * psim/ppc: Re-arange entire directory structure so that
- everything lives in the one directory. While a pain for cleaning,
- makes building across multiple architectures much simpler.
+ * Makefile.in (maintainer-clean): Remove .log, core and *.core
+ (From NetBSD) files.
- * devices.c, device_tree.c: Added code that provides a simple
- illustration of how an interrupt control device could be
- implemented.
+Wed May 29 22:57:40 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
- * devices.c: Added code so that the dumb console device can read
- (from stdin) as well as write to stdout.
+ * ChangeLog.00, ChangeLog: ChangeLog from gdb-4.16 becomes
+ ChangeLog.00
diff --git a/gnu/dist/sim/ppc/ChangeLog.00 b/gnu/dist/sim/ppc/ChangeLog.00
new file mode 100644
index 00000000000..8b8be820fc7
--- /dev/null
+++ b/gnu/dist/sim/ppc/ChangeLog.00
@@ -0,0 +1,2168 @@
+Wed May 29 22:57:40 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
+
+ * ChangeLog.00, ChangeLog: ChangeLog from gdb-4.16 becomes
+ ChangeLog.00
+
+Thu Apr 4 15:17:22 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * INSTALL: Fix some long lines and remove x86 specific options in
+ the examples.
+
+Sun Mar 31 15:47:33 1996 Andrew Cagney <cagney@kremvax.highland.com.au>
+
+ * INSTALL: Update to reflect gdb-4.16.
+
+ * RUN: Update to reflect gdb-4.16. Review notes on building a BSD
+ runtime environment.
+
+ * README: Point out copyright status of simulator in introduction.
+
+Thu Mar 7 19:53:49 1996 Michael Meissner <meissner@cygnus.com>
+
+ * emul_netbsd.c: Only include sys/mount.h if HAVE_SYS_MOUNT_H is
+ defined.
+ * configure.in: Test for sys/mount.h.
+ * configure,config.in: Regenerate.
+
+Thu Feb 22 22:48:57 1996 Andrew Cagney <cagney@highland.com.au>
+
+ * README, RUN, INSTALL: Update to reflect announcement
+ * psim: PSIM 1.0.1 released
+
+Thu Feb 22 14:01:56 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * emul_bugapi.c (emul_bugapi_do_read): New function to handle
+ reads.
+ (emul_bugapi_instruction_call): Add support for .INCHR/.INLN
+ system calls.
+
+ * emul_bugapi.c (emul_bugapi_do_write): Call flush_stdoutput.
+ * emul_netbsd.c (do_write): Call flush_stdoutput.
+
+ * main.c (flush_stdoutput): Do fflush (stdout).
+ * sim_calls.c (flush_stdoutput): Do gdb_flush (gdb_stdout);
+ * sim_callbacks.h (flush_stdoutput): Declare.
+
+Wed Feb 21 10:39:35 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * emul_bugapi.c (bug_mapping): New structure to map bug system
+ call numbers to a string.
+ (toplevel): Add remaining bugapi system calls.
+ (emul_bugapi_instruction_name): Map bugapi system call number to a
+ string.
+ (emul_bugapi_do_write): Common code to process write system calls.
+ (emul_bugapi_instruction_call): If os-emul tracing is on, trace
+ the system call. Use the name to print unknown system call.
+ Correct implementation of _OUTLN. Add support for _OUTSTR and
+ _PCRLR system calls.
+
+Wed Feb 21 17:07:27 1996 Andrew Cagney <cagney@highland.com.au>
+
+ * NOTES: New file. Ramblings on why things were done they way
+ they were.
+
+ * psim.c (psim_options): Didn't enter the model value into the
+ device tree as a string.
+
+ * cpu.c (cpu_synchronize_context): Wrong test for conditional
+ flush of cache.
+
+ * emul_generic.c (emul_add_tree_hardware): reg value didn't match
+ bus address.
+
+ * ppc-opcode-flat: new file. Generate an instruction decode
+ function like ppc-opcode-complex but use switch statements.
+
+ * INSTALL: document new opcode file, add example configurations.
+
+Tue Feb 20 18:42:31 1996 Andrew Cagney <cagney@highland.com.au>
+
+ * main.c (main): rename psim instance (system) to simulation and
+ make global.
+ * main.c (error): print out performance even when an error occures.
+
+ * emul_bugapi.c (emul_bugapi_create): Fix argument passing.
+
+ * emul_generic.c (emul_add_tree_hardware): Move hardware devices
+ to 0x80000000 from 0x400000.
+
+Mon Feb 19 22:54:40 1996 Andrew Cagney <cagney@highland.com.au>
+
+ * ppc-instructions (TLB Invalidate Entry, TLB Invalidate ALL):
+ Implement by passing on request to all processors.
+ * ppc-instructions (TLB Synchronize): Implement as empty, processor
+ tlb's are always in sync.
+
+ * cpu.c (cpu_page_tlb_invalidate_all): New function. Pass on TLB
+ invalidate request to processors VM sub-system.
+ * cpu.c (cpu_page_tlb_invalidate_entry): Ditto.
+
+ * vm.c (vm_page_tlb_invalidate_all): New function. Mark all page
+ TLB entries as invalid.
+ * vm.c (vm_page_tlb_invalidate_entry): New function. Ditt but only
+ invalidate one TLB entry.
+
+ * psim.c (psim_init): Invalidate TLB's before (re)starting.
+
+Mon Feb 19 21:25:56 1996 Andrew Cagney <cagney@highland.com.au>
+
+ * emul_generic.c (emul_add_tree_options): Add argument
+ oea_interrupt_prefix (0 or 1) that specifies the prefix MSR[IP]
+ and hence the location of the interrupt vectors. Add this to the
+ device tree.
+
+ * emul_chirp.c (emul_chirp_create): Allow configuration of
+ floating-point and interrupt prefix (default 0) using the above.
+
+ * emul_netbsd.c (emul_netbsd_create): Pass dummy arg for
+ interrupt-prefix.
+
+ * emul_bugapi.c (emul_bugapi_create): Allow configuration of
+ interrupt prefix (default 1) and configure interrupt table traps
+ accordingly.
+
+ * emul_generic.c (emul_add_tree_hardware): Include a small eeprom
+ in the list of devices.
+
+ * device_table.c: For moment fake eeprom device by a memory
+ device. In future will need a proper eeprom device.
+
+Tue Feb 20 17:01:26 1996 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * config.in: Regenerated.
+
+Fri Feb 16 10:42:27 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * psim.c: Include options.h so print_options is declared.
+
+Thu Feb 15 18:10:13 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * emul_netbsd.c (toplevel): Do not include sys/resource.h if the
+ system doesn't have it, and turn off getrusage processing.
+ (write_rusage): #ifdef out if we don't have getrusage.
+ (do_getrusage): Define as 0 if we don't have getrusage.
+
+Wed Feb 14 17:38:12 1996 J. T. Conklin <jtc@cygnus.com>
+
+ * configure.in (AC_HEADER_DIRENT): Add, so that we can figure out
+ where the directory functions are declared.
+ * configure: Regenerate
+
+ * emul_netbsd.c: Use the macros defined by configure to find the
+ appropriate directory functions.
+
+Thu Feb 8 00:53:13 1996 Andrew Cagney <cagney@highland.com.au>
+
+ * configure.in (xor_endian): Trace setting of xor-endian flag.
+
+Wed Feb 7 18:20:56 1996 Andrew Cagney <cagney@highland.com.au>
+
+ * psim.c (psim_usage): Extend documentation.
+
+ * ppc-instructions (model-print): fix typo.
+
+Sun Feb 4 23:58:02 1996 Andrew Cagney <cagney@highland.com.au>
+
+ * configure.in (with-smp): Default configuration allow up to
+ five processors (but enable only one).
+
+ * emul_bugapi.c (emul_bugapi_create): If floating-point is
+ allowed, enable the floating point instruction set in the
+ msr.
+
+Tue Jan 30 22:52:32 1996 Andrew Cagney <cagney@highland.com.au>
+
+ * emul_chirp.c (chirp_emul_seek, chirp_emul_read,
+ chirp_emul_write): Tolerate invalid ihandles.
+
+ * device.c (device_instance_create, device_instance_delete):
+ init/delete instance name
+
+ * emul_chirp.c (emul_chirp_instruction_call): Read the nr args and
+ returns when determining the service.
+
+ * emul_chirp.c (chirp_read_t2h_args): Allow variable number of
+ args for the method "call-method".
+
+ * emul_chirp.c (chirp_emul_getprop): Tolerate a n_returns of zero
+ - should be one. Some OpenBoot code doesn't pass correct arg.
+
+ * emul_chirp.c (chirp_emul_getprop): Trace more property types.
+
+Tue Jan 30 19:12:29 1996 Andrew Cagney <cagney@highland.com.au>
+
+ * RUN: New file. Describe how to run PSIM
+ * INSTALL: New file. Describe how to install PSIM
+ * README: New file. Overview PSIM.
+ * BUGS: New file. Briefly discuss bugs and limitations
+
+Wed Jan 24 20:28:08 1996 Andrew Cagney <cagney@highland.com.au>
+
+ * emul_bugapi.c (OEA_START_ADDRESS): Put it back to 0x100000,
+ wasn't correctly using GLD.
+
+Mon Jan 22 22:44:13 1996 Andrew Cagney <cagney@highland.com.au>
+
+ * emul_generic.c (emul_add_tree_options): Make default number of
+ active processors 1 (even when SMP enabled).
+
+Mon Jan 22 22:37:34 1996 Andrew Cagney <cagney@highland.com.au>
+
+ * device_table.c (icu_io_read_buffer_callback): Add extra register
+ (at addr + 4) that returns number of processors.
+
+ * emul_generic.c (emul_add_tree_hardware): Update device node to
+ match.
+
+Mon Jan 22 22:00:42 1996 Andrew Cagney <cagney@highland.com.au>
+
+ * emul_bugapi.c (OEA_START_ADDRESS): Change to 0x4000 so that it
+ matches gas-960116/ld.
+
+Fri Jan 19 00:32:27 1996 Andrew Cagney <cagney@highland.com.au>
+
+ * psim-960119 released - psim-1.0b01.
+
+Fri Jan 19 00:32:27 1996 Andrew Cagney - aka Noid <cagney@highland.au.com>
+
+ * psim.c (psim_create): Re-order so that all options are set
+ before the CPU's are created. Was breaking mon_create();
+
+ * psim.c (psim_create): Tidy up conflicting configuration errors.
+
+ * debug.c: Add missing print-info entry to trace table.
+
+ * os_emul.c (os_emul_create): Fix `-e' option. Was looking under
+ wrong name.
+
+ * psim.c (psim_options): Fix `-r' option. Was entering under wrong
+ name.
+
+Thu Jan 18 20:33:48 1996 Andrew Cagney <cagney@highland.com.au>
+
+ * vm.c (om_unpack_bats): Fix checking of bat bits.
+
+ * emul_chirp.c (emul_chirp_create): Store address of OB in memory
+ in the os_emul_data structure.
+
+ * emul_bugapi.c (emul_bugapi_create): Store the address of the
+ bugapi code (in main memory) in the os_emul_data structure.
+
+Thu Jan 18 01:14:55 1996 Andrew Cagney <cagney@highland.com.au>
+
+ * vm.c (om_translate_effective_to_real): Fix trace output.
+
+Wed Jan 17 22:21:55 1996 Andrew Cagney <cagney@highland.com.au>
+
+ * device_table.c (generic_device_init_address): Create memory from
+ information obtained from `reg' property.
+ * device_table.c (vm_init_address_callback): Use information
+ obtained from properties.
+ * emul_netbsd.c (emul_netbsd_create): Update to create device and
+ property entries to match
+
+Tue Jan 16 09:50:53 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * idecode_expression.h (ALU_END): Add ITRACE of the result.
+
+ * ppc-instructions (Equivalent): Enable this instruction.
+ (Add to Minus One Extended): Ditto.
+ (Subtract from Minus One Extended): Ditto.
+ (Add/And/Or/Xor Immediate): Add alu trace of result.
+ (Add/And/Or/Xor Shifted Immediate): Ditto.
+ (And/Or/Equivalent/Nand/Nor): Ditto.
+ (And/Or with Complement): Ditto.
+ (Extend Sign Byte/Half Word): Ditto.
+ (Count Leading Zeros): Ditto.
+ (Shift Right Algerbraic Word): Ditto.
+ (Shift Right Algerbraic Word Immediate): Ditto.
+
+Tue Jan 9 15:10:27 1996 Andrew Cagney <cagney@highland.com.au>
+
+ * emul_bugapi.c (emul_bugapi_instruction_call) : Make format type
+ correct.
+ * emul_chirp.c (map_over_chirp_note) : Ditto
+ * emul_chirp.c (chirp_emul_test) : Ditto
+ * device_table.c (register_init): Ditto
+
+Tue Jan 9 14:16:26 1996 Andrew Cagney <cagney@highland.com.au>
+
+ * configure.in: Make disable-sim-switch default. Switch only
+ useful if using --enable-sim-opcode=ppc-opcode-stupid and then
+ only marginally so.
+
+Mon Jan 8 12:17:22 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * device_table.c (register_init): Make format type correct.
+
+Wed Jan 3 19:21:46 1996 Andrew Cagney <cagney@highland.com.au>
+
+ * emul_bugapi.c (emul_bugapi_create): Add nodes to init the
+ system-call trap to the emul instruction call instruction (Along
+ with an rfi and infinate loop).
+
+ * emul_bugapi.c (emul_bugapi_instruction_call): Expand to include
+ a few real PPC bug calls. Test with simple hello world.
+
+Tue Jan 2 20:51:19 1996 Andrew Cagney - aka Noid <cagney@highland.com.au>
+
+ * device.h, device.c (device_child, device_sibling): New
+ functions. Return corresponding device value.
+
+ * emul_chirp.c (chirp_emul_child, chirp_emul_peer,
+ chirp_emul_parent): New functions - emulate corresponding OpenBoot
+ interfaces.
+
+ * device_table.c (register_init): Extend properties attached to
+ register init node to allow a specific processor's register to be
+ specified.
+
+ * emul_chirp.c (emul_chirp_create): Init SMP correctly - the
+ initial PC for all processors is an infinate loop but then, for
+ processor zero, is quickly changed to be the correct code starting
+ address.
+
+ * emul_chirp.c (emul_chirp_create): Add fake bootpath
+ et.al. properties to tree.
+
+ * emul_chirp.c (chirp_emul_getproplen): New function. Emulate the
+ getproplen OpenBoot call.
+
+ * emul_chirp.c (emul_chirp_instruction_call): Document other
+ possible chirp emulation internal states.
+
+ * emul_chirp.c (emul_chirp_instruction_call): Trace failed lookups
+ as well as successful ones.
+
+ * emul_chirp.c (emul_chirp_open): New function - handle open
+ client call.
+
+ * Makefile.in (maintainer-clean): Proper rule that eliminates more
+ junk.
+
+Tue Dec 19 13:00:11 1995 Andrew Cagney <cagney@highland.com.au>
+
+ * emul_chirp.c (chirp_emul_exit): Full out call.
+
+ * device_table.c (htab_map_page): Wasn't handling byte swap when
+ creating entries in the hash table.
+
+ * device.c (device_tree_find_node): Allow primative wild-card match
+ of device names with the path.
+
+ FIXME: As mentioned earlier, the device stuff needs work to bring
+ it into line with OpenBoot. Part of this work is rewriting the
+ find_node function so that it behaves as specified in p1275.
+
+Mon Dec 18 19:58:56 1995 Andrew Cagney <cagney@highland.com.au>
+
+ * emul_chrp.c (chirp_emul_write, chirp_emul_finddevice): add
+ better tracing.
+
+ * emul_chrp.c: Change return type of emul functions to int. Emul
+ functions either return -1 or zero so unsigned was a bit
+ dangerous.
+
+ * inline.h (*), igen.c, dgen.c, *: Update INLINE macros so that
+ they are paramaterised with the type of the function. Gets around
+ the problem of `static' needing to come first with `attribute'
+ comming last. Format declarations and definitions so that emacs
+ doesn't get confused.
+
+Fri Dec 15 17:06:44 1995 Andrew Cagney <cagney@highland.com.au>
+
+ * std-config.h (PSIM_INLINE): Add missing inline configuration
+ control for the main loop.
+
+ * mon.c (mon_print_info): If monitoring disabled still print out
+ the number seconds used.
+
+ * psim.c (run_until_stop): Don't monitor the cache misses when
+ monitoring is disabled.
+
+ * configure.in (sim_mon, sim_monitor): Correct typo - sim_mon ->
+ sim_monitor for shell variable (or should that have been the other
+ way around?).
+
+ * vm.c (vm_synchronize_context): Fix wrong test for unsuported
+ change in endian-mode.
+
+ * std-config.h (WITH_REGPARM), inline.h (IDECODE_INLINE,
+ SEMANTICS_INLINE): Add -DWITH_REGPARM=<n> option. Enables the
+ __attribute__((__regparm(WITH_REGPARM))) for some functions.
+ configure with --enable-sim-cflags="-DWITH_REGPARAM=3" (say).
+ Unfortunatly it tickles a bug (gcc?) and can't be used.
+
+Mon Dec 18 13:36:06 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * device.c (device_tree_add_device): Make trace fprintf arguments
+ type correct.
+ * device_table.c (htab_decode_hash_table): Ditto.
+ (htab_map_binary): Ditto.
+ (htab_init_callback): Ditto.
+ * vm.c (om_virtual_to_real): Ditto.
+
+Sat Dec 16 09:54:18 1995 Michael Meissner <meissner@wogglebug.tiac.net>
+
+ * emul_netbsd.c (emul_netbsd_create): Deal with new BFD that
+ changed how big/little endian support is recorded, while remaining
+ compatible with the old BFD with #ifdefs.
+ * emul_chirp.c (emul_chirp_create): Ditto.
+ * emul_bugapi.c (emul_bugapi_create): Ditto.
+
+Fri Dec 15 15:55:56 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * std-config.h (MODEL_INLINE): Turn off INLINE_MODULE by default.
+
+ * corefile.h: Delete declarations for unknown functions.
+ * device.h: Ditto.
+ * interrupts.h: Ditto.
+ * interrupts.c: Ditto.
+
+Thu Dec 14 18:49:34 1995 Andrew Cagney <cagney@highland.com.au>
+
+ * lf.c (lf_print_function_type): New function. Munges a function
+ type so that the prefix (eg INLINE...) is inserted after the type
+ but before any `*'.
+
+ * igen.c: Change to output functions using this.
+
+Wed Dec 13 23:47:00 1995 Andrew Cagney <cagney@highland.com.au>
+
+ FIXME: Emul CHIRP does not correctly implement the find device
+ function.
+
+ FIXME: Emul CHIRP and device do not implement device instance
+ operations.
+
+Wed Dec 13 23:47:00 1995 Andrew Cagney <cagney@highland.com.au>
+
+ * options.c (options_inline): Function to output meaningful
+ description of the INLINE options.
+
+ * configure.in (inline): Replace inline magic numbers with macro
+ names. Map 1->LOCALS_INLINE and 2->ALL_INLINE.
+
+ * inline.h, inline.c: update to use inline method.
+
+ * std-config.h (CPU_INLINE), cpu.h, inline.h, inline.c: make cpu.h
+ inline always.
+
+ * std-config.h (EVENTS_INLINE): Inline events in psim.
+
+Wed Dec 13 22:01:21 1995 Andrew Cagney <cagney@highland.com.au>
+
+ * device_table.c (htab_sum_binary): DMA binaries to correct byte
+ within a page.
+
+Tue Dec 12 22:51:18 1995 Andrew Cagney <cagney@highland.com.au>
+
+ * psim.c (psim_merge_device_file): Change `=' to `==', was this an
+ error?
+
+Tue Dec 5 11:56:14 1995 Andrew Cagney <cagney@highland.com.au>
+
+ * ppc-instructions (ppc_nr_mtcrf_crs, ppc_branch_conditional_name,
+ ppc_function_unit_name): Simplify by declaring these arrays as
+ pure and simple static (instead of STATIC_MODEL).
+
+Tue Dec 5 00:45:34 1995 Andrew Cagney <cagney@highland.com.au>
+
+ * sim_calls.c (sim_create, sim_load), main.c (main), psim.c: Pass
+ an options device into psim_create() so that options can be merged
+ into the tree.
+
+ * device.c (*add*): Change semantics so the add functions only add
+ when the new device (or property) doesn't already exist. This
+ allows merging of options and data.
+
+Mon Dec 4 17:12:13 1995 Andrew Cagney <cagney@highland.com.au>
+
+ * Makefile.in (BASICS_H): Didn't include basics.h in the list of
+ header files to depend on.
+
+Mon Dec 4 17:12:13 1995 Andrew Cagney <cagney@highland.com.au>
+
+ * std-config.h: (*_MODULE): Extend the <module>_inline macro's so
+ that they also allow control over static functions. Rewrite
+ document to reflect this.
+
+ * std-config.h: (INLINE): Simplify definition, the above and
+ earlier changes to igen.h eliminate the need to be defensive about
+ enabling the inline of static functions.
+
+ * std-config.h: (SIM_ENDIAN_INLINE, BITS_INLINE): Document limited
+ suport for inlineing of modules for all callers. Adjust relevant
+ macro's so that DEFAULT_INLINE will enable this.
+
+ * basics.h: Re-order #includes and definitions so that c-code for
+ basic include files does not call functions delcared in later
+ #includes.
+
+ * basics.h (__attribute__), sim_callbacks.h: Move attribute macro
+ to basics.h and add hack (include <stdio.h>) to try and bring that
+ and other possible conflicting macros into scope much earler.
+
+ * sim-endian.h,c (SIM_ENDIAN_INLINE) bits.h,c (BITS_INLINE):
+ Change to use the updated inline definitions. If enabled
+ immediatly include the corresponding c-code so that it will inline
+ for all modules.
+
+ * inline.h, inline.c (SIM_ENDIAN_INLINE, BITS_INLINE): Remove
+ these cases, moved to module specific header files.
+
+Sat Dec 2 18:37:51 1995 Andrew Cagney <cagney@highland.com.au>
+
+ * vm.c, vm_n.c: Fix htab code.
+
+ * vm.c (vm_data_map_read_buffer): Was using EA not RA when reading
+ the data from core.
+
+ * device.c: Fix htab create code.
+
+Fri Nov 24 23:10:09 1995 Andrew Cagney <cagney@highland.com.au>
+
+ * bits.h, bits.c (EXTRACTED): Convert to function, fix - had &&
+ instead of &.
+
+ * sim-endian.h (SWAP_N), sim-endian-n.h, sim-endian.c: How
+ embarasing - fix yet another bug in the swap code! Simplify
+ everything by using more functions. Add host to big-endian byte
+ swapping support.
+
+Fri Nov 24 23:10:09 1995 Andrew Cagney <cagney@highland.com.au>
+
+ * devices.h, devices.c: delete, replaced by the files
+ device_table.[ch] and device.[ch].
+ * device_tree.h, device_tree.c: ditto
+
+ * device_table.h, device_table.c: New files. Contain a table of
+ devices.
+
+ * device.h, device.c, Makefile.in, std-config.h (DEVICE_INLINE),
+ options.c (print_options): New files. Define the device object
+ along with any attached properties.
+
+ * device_tree.h, device_tree.c: Update to use new device object.
+ For convenience, change the printd functions into device_tree_add
+ functions.
+
+ * psim.c (create_*_tree): Use new device_tree create functions.
+
+ * corefile.h, corefile.c corefile-n.h (core_n.h): Update to use
+ the new device.h / device_table.h interface. Rename core_n.h to
+ corefile-n.h to be consistent with other n files.
+
+ * Makefile.in (run): add corefile-n.h to dependencies for
+ corefile.
+
+ * basics.h (device_instance), device.h, device.c, device_table.h,
+ device_table.c: Add the concept of a device instance and operators
+ on these instances - corresponds to ihandle in OpenBoot speak.
+ Don't yet implement it.
+
+Tue Nov 14 12:27:08 1995 Andrew Cagney <cagney@highland.com.au>
+
+ * emul_generic.h, emul_generic.c (emul_syscall_enter,
+ emul_syscall_exit): rename from emul_enter_call /
+ emul_exit_call. As only used by emul_do_system_call simplify
+ associated code.
+
+ * os_emul.h, os_emul.c, emul_generic.h: Correct and fill an
+ os_emul interface.
+
+ * os_emul.c, emul_bugapi.h, emul_bugapi.c, Makefile.in: Add
+ preliminary hooks for a kernel mode rom emulation.
+
+ * cap.h (new), cap.c (new): Capability data base. Some emulations
+ pass object identifiers (capabilities?) to/from the simulated code
+ (for instance the phandle in OpenBoot). The cap object is able to
+ check/map between internal and external (target program)
+ representations of each identifier.
+
+ * os_emul.c, emul_chirp.h, emul_chirp.c, Makefile.in: Add
+ preliminary hooks for a kernel mode IEEE-1275 emulation.
+
+ * cpu.h, cpu.c (cpu_create, cpu_os_emulation, cpu): Add os_emul to
+ list of arguments passed in when creating a cpu. Grant access to
+ the element.
+
+ * std-config.h (OS_EMUL_INLINE), options.c (print_options),
+ inline.h, inline.c: New to allow control over inline of
+ corresponding code files.
+
+ * ppc-instructions (instruction_call): Add illegal instruction to
+ call the instruction-call emulation handler.
+
+ * interrupts.c (system_call_interrupt): Call renamed
+ os_emul_system_call function().
+
+ * emul_netbsd.c: Update to interface to generic emulation. Since
+ all its functions are called via a table don't worry about any
+ inline.
+
+ * emul_generic.h, emul_generic.c, spa-*(delete): Remove references
+ and code for spa, no longer to be used.
+
+ * psim.c (create_chirp_device_tree): Fill out what was previously
+ the openboot create function so that it starts to create a full
+ OpenBoot device tree.
+
+Tue Nov 28 21:48:06 1995 Andrew Cagney <cagney@highland.com.au>
+
+ * debug.h, debug.c: pte trace is made redundant by htab trace,
+ delete it. Add vm to list of options. Simplify tracing output so
+ lines are not as long.
+
+Tue Nov 14 12:27:08 1995 Andrew Cagney <cagney@highland.com.au>
+
+ * events.h, events.c (event_queue_init), psim.c (psim_init): (re)
+ initialize the event queue.
+
+
+
+
+
+
+Tue Nov 28 13:38:26 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * sim-endian.h: Look at WORDS_BIGENDIAN to determine if the host
+ is big endian or little endian. For SWAP_n, use htonl/htons if
+ host is little endian, not big endian and if WITH_NTOH is defined.
+
+ * configure{,.in} (--enable-sim-model-issue): Instead of defining
+ 0/1, define it to be MODEL_ISSUE_{PROCESS,IGNORE}. Add
+ AC_C_BIGENDIAN to determine if the host is big endian or not.
+ * config.in: Regenerate.
+
+ * std-config.h (WITH_MODEL_ISSUE): Default to 0.
+ (CURRENT_MODEL_ISSUE): Reference WITH_MODEL_ISSUE, and if that is
+ 0, use current_model_issue.
+ (MODEL_ISSUE_{PROCESS,IGNORE}): Define as -1/1.
+
+ * psim.c (current_model_issue): New global variable.
+
+ * cpu.c (cpu_create): Use CURRENT_MODEL_ISSUE > 0 instead of
+ WITH_MODEL_ISSUE.
+ (cpu_{init,halt}): Ditto.
+ * mon.c (mon_print_info): Ditto.
+ * ppc-instructions (PPC_INSN_* macros, branch handling): Ditto.
+
+ * mon.c (mon_print_info): Print instructions/second if verbose > 0,
+ rather than > 1.
+
+ * main.c (main): Set current_model_issue to MODEL_ISSUE_PROCESS if
+ the -I switch is used.
+ * sim_calls (sim_open): Ditto.
+
+ * ppc-instructions (model support): Add support for determining
+ when we don't have enough writeback slots. Add tracing for the
+ beginning of each cycle.
+
+Mon Nov 27 17:46:33 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * mon.c: Check for whether to include sys/types.h and sys/time.h.
+
+ * configure.in: Check for include files sys/types.h and
+ sys/time.h.
+ * configure: Regenerate.
+ * config.in: Regenerate.
+
+ * cpu.h (CONST_ATTRIBUTE): Define as __attribute__((__const__)) if
+ not already defined.
+ (cpu_system): Use CONST_ATTRIBUTE, so that when we're not inlining
+ the world, the optimizer has a fair chance of CSE'ing function
+ calls.
+ (cpu_{monitor,nr,registers,model}): Ditto.
+
+ * std-config.h (MODEL_INLINE): If not defined, define as 1 if
+ DEFAULT_INLINE is non-zero, 0 otherwise, rather than just the
+ value of DEFAULT_INLINE.
+
+Fri Nov 24 11:24:34 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * lf.h (__attribute__): If not GCC and at least 2.7.0, define as
+ nothing.
+ (lf_printf): Add printf __attribute__, so the compiler will
+ automatically check the format string.
+
+ * configure{,.in} (--enable-sim-icache): If argument is define,
+ add -R to flags passed to igen.
+
+ * igen.c (stdlib.h): Include if the system supplies one.
+ (semantics_use_cache_struct): New global for -R flag to say
+ semantics is to use the cache structure directly rather than
+ putting the values into local variables.
+ (first_undef, last_undef): New structures to remember names to
+ #undef if -R.
+ (lf_print_c_extraction): If -R and this is semantics, emit names
+ as #defines pointing to the cache structure, rather than loading
+ the values into local variables.
+ (lf_print_c_semantic_function): If -R, #undef all of the names
+ defined in lf_print_c_extraction.
+ (main): Recognize -R.
+
+ * idecode_fields.h (SPR_*): Redefine spr_* macros as SPR_* to
+ avoid a name confict if -R passed to igen.
+
+ * ppc-instructions (mfspr, mtspr): Rename spr field to SPR.
+ (model_data): Add field to count the various # of CRs that the
+ mtcrf instruction used.
+ (model_mon_info): Return structures counting the # of CRs that the
+ mtcrf instruction used.
+ (branches, sync instructions): Do not call model functions if
+ WITH_MODEL_ISSUE is 0.
+
+ * mon.c (stdlib.h): Include if the system supplies one.
+ (mon_sort_instruction_names): New function to sort instruction
+ names alphabetically.
+ (mon_print_info): Call qsort with mon_sort_instruction_names to
+ sort instruction names. Don't abort if WITH_MODEL_ISSUE is 0.
+
+ * debug.h (ITRACE): Make printf_filtered arguments type correct.
+ * idecode_expression.h (CR0_COMPARE): Ditto.
+ * psim.c (psim_read_register): Ditto.
+
+ * igen.c (lf_print_my_prefix): Use __attribute__((__unused__)) to
+ silence compiler warnings about unused automatically generated
+ variables.
+ (lf_print_c_extraction): Ditto.
+ * idecode_expression.h (FPSCR_BEGIN): Ditto.
+
+ * ppc-cache-rules: Define rules for making a bitmask for all
+ registers.
+
+ * ppc-instructions: Rewrite model specific functions to use the
+ bitmask of the register number, instead of using the register
+ pointer to get the register number, and then making the bitmask.
+
+Wed Nov 22 15:24:27 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * ppc-instructions (model_branches): Add conditional argument to
+ count the number of times each type of conditional branch is used.
+ (conditional branches): Pass B0 or -1 to model_branches.
+ (model_mon_info): Print out conditional branch counts.
+ (model-data): Add support for printing out conditional branch
+ types.
+
+Tue Nov 21 16:31:25 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * igen.c (insn_table_load_insns): Add support for model-static for
+ internal functions that should not be inlined.
+ (lf_print_c_semantic): Remove model_cleanup.
+ (gen_model_{c,h}): Ditto.
+
+ * ppc-instructions: Redo model specific support once again. Add
+ floating point support to the model specific information. Flesh
+ out all of the floating mutiply add/subtract instructions. Add
+ better tracing support to the model specific information.
+
+Sun Nov 19 23:00:52 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * ppc-instructions (model data, model_busy): Rather than using a
+ bit mask for the busy units, just use a char array. Also, only
+ support 2 function units an insn can use, rather than a loop.
+
+Fri Nov 17 14:08:08 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * table.c (table_entry_read): Move setting entry->line_nr to after
+ the model specific fields so the line numbers for the annex are
+ correct.
+
+ * cpu.c (cpu_{create,init,halt}): Check for WITH_MODEL_ISSUE
+ before calling the model functions.
+
+ * debug.c (trace_descriptor): Add trace_model support.
+ * debug.h (trace_options): Ditto.
+
+ * igen.c (gen_icache_h): Create type idecode_cache as void if not
+ caching instructions.
+ (gen_model_{c,h}): Drop model_issue support. Add support for
+ model_cleanup.
+ (lf_print_my_prefix): Initialize a const itable_index with the
+ current index.
+ (lf_print_c_semantic): Call model_cleanup at the end of the
+ function to check for instructions that aren't supported yet by
+ the scheduling code.
+
+ * mon.h (count_type): New type for counters.
+ * mon.c: Use count_type instead of unsigned.
+
+ * ppc-instructions: Redo scheduling code once again. Make it all
+ inline friendly. Instead of having general code emitted by igen,
+ go the route of having each semantic routine call the appropriate
+ module.
+
+Thu Nov 16 09:52:26 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * table.c (table_entry_read): Allow the annex to have blank lines.
+
+ * ppc-instructions: Change lines in model stuff that just have a
+ tab to just newline. Add 601 support. Document most instructions
+ in terms of model specific timing information. Drop 'FUNCTION'
+ from PPC_FUNCTION_UNIT_xxx enums. Change PPC_UNIT_UNKNOWN ->
+ PPC_UNIT_BAD. Add TRACE(trace_tbd) for all data cache
+ instruction.s. Signal illegal instruciton if data cache block
+ invalidate is issued from problem state.
+
+ * igen.c (max_model_fields_len): New static to keep track of the
+ max size for the model specific fields.
+ (model_c_insn): Use max_model_fields_len to size fields.
+ (insn_table_insert_insn): Set max_model_fields_len.
+ (model_table_insert): Ditto.
+ (gen_model_{c,h}): Model_issue is now called with a processor
+ argument.
+
+ * debug.c (trace_description): Add support for trace_tbd.
+
+ * mon.c (mon_issue): Pass processor argument to model_issue.
+
+ * Makefile.in: Delete all function unit support, since the newer
+ table driven model support replaces it.
+ * cpu.{c,h}: Ditto.
+ * mon.c: Ditto.
+ * inline.{c,h}: Ditto.
+ * std-config.h: Ditto.
+ * options.c: Ditto.
+ * configure{,.in}: Ditto.
+ * Makefile.in: Ditto.
+ * psim.c: Ditto.
+ * function_unit.{c,h}: Delete these now usused files.
+
+ * std-config.h (WITH_MODEL_ISSUE): Add new macro on whether to
+ trace instructions in a model specific manor.
+ * options.c (print_options): Print it out.
+ * configure{,.in}: Add --enable-sim-model-issue option.
+ * Makefile.in: Add --enable-sim-model-issue flags.
+ * igen.c (lf_print_c_semantic): Add call to mon_issue here. Check
+ for WITH_MODEL_ISSUE.
+ * mon.c (mon_issue): Remove call to mon_issue_here.
+
+ * ppc-instructions: Move branch tracing to the actual branch
+ instructions, rather than testing it in model_issue. Add code to
+ code successful/unsuccessful branch predictions, and the number of
+ conditional branches that fell through.
+
+Wed Nov 15 17:32:13 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * cpu.h (cpu_model): Add declaration.
+
+ * cpu.c (struct _cpu): Add model_ptr to hold model specific
+ information.
+ (cpu_model): Return the model internal pointer.
+ (cpu_{create,init,halt}): Call the appropriate model function.
+
+ * inline.c (mon.c): Move include of mon.c after model.c.
+
+ * mon.c (_cpu_mon): Add fields to count unaligned memory
+ references.
+ (mon_issue): Call model_issue, not function_unit_issue.
+ (mon_{read,write}): Count # of unaligned memory accesses.
+ (mon_print_info): Switch to calling model_mon_info and
+ model_mon_info_free instead of function_unit version. Print out
+ number of unaligned reads/writes.
+
+ * {ppc-instructions,igen.c}: More global changes to add model
+ specific features.
+
+ * inline.{c,h}: Provide for inlining options.c.
+ * options.{c,h}: Ditto.
+ * std-config.h: Add OPTIONS_INLINE.
+
+Tue Nov 14 04:47:25 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * Makefile.in (devices.o, main.o): Update dependency.
+
+ * igen.c (gen_model_h): Use correct variable in loop.
+ (gen_model_c): Use strcmp, strcasecmp.
+ (gen_model_c): Use EXTERN_MODEL for arrays.
+ (gen_model_h): Use STATIC_MODEL for arrays.
+ (lf_print_c_semantic_function_header): Delete unused function.
+
+ * main.c (cpu.h): Include cpu.h to get model.h.
+
+ * inline.h ({EXTERN,STATIC}_MODEL): Define.
+
+Mon Nov 13 09:14:13 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * igen.c ({insn,model}_table_fields): Spell mnemonic correctly.
+ (gen_itable_h,itable_c_insn): Ditto.
+ (model support): Move model support around, add support for
+ model-data, model-internal. Use annex field for model-macros
+ now.
+
+ * configure.in (--enable-sim-inline): If --enable-sim-inline=no,
+ also define INLINE as nothing.
+ * configure: Regenerate.
+
+ * std-config.h (INLINE): Rather than nuking INLINE, only define it
+ as __inline__ if any of the INLINE flags are non-zero.
+
+ * options.c (print_options): Print out WITH_XOR_ENDAIN.
+
+Mon Nov 13 23:03:45 1995 Andrew Cagney <cagneyhighland.com.au>
+
+ * ppc-instructions (rfi): Add missing code.
+
+ * cpu.c (cpu_get_time_base): Fix calculation of current value of
+ time base register.
+
+ * ppc-spr-table (TBL, TBU): Fix TBL/TBU entries - was confusing
+ m[tf]tb with m[tf]spr.
+
+ * ppc-instructions (mtspr, mfspr): Fix mttbl - wasn't storing
+ lower word.
+
+Mon Nov 13 21:35:37 1995 Andrew Cagney <cagneyhighland.com.au>
+
+ * std-config.h (INLINE, STATIC_INLINE): Was being set to static
+ inline.. Only problem being that with ppc-opcode-simple this gave
+ it the chance to inline all the idecode functions with potentially
+ disasterous results on a 16mb PC. For moment hobble INLINE.
+
+ * configure.in, std-config.h (WITH_SMP): Make that 5 processors by
+ default ...
+
+ * configure.in: Tweek flags passed to gcc for --with-sim-warnings.
+ Firstly make them errors and secondly remove the options gcc-245
+ doesn't reconize.
+
+Mon Nov 13 17:57:24 1995 Andrew Cagney <cagney@highland.com.au>
+
+ * misc.c (zalloc), cpu.c (cpu_init), devices
+ (console_io_read_buffer_callback, icu_io_read_buffer_callback,
+ vm_io_read_buffer_callback), main.c (zalloc), mon.c (memset),
+ sim_calls.c (zalloc) : replace bzero() with memset().
+
+ * emul_netbsd.c (write_direntries), psim.c (psim_read_register,
+ psim_write_register): replace bcopy() with memcpy().
+
+Sun Nov 12 20:55:41 1995 Andrew Cagney <cagneyhighland.com.au>
+
+ * configure.in: for --disable-sim-inline (--enable-sim-inline=no),
+ force DEFAULT_INLINE to 0 rather then trusting the std
+ configuration.
+
+Sun Nov 12 20:55:41 1995 Andrew Cagney <cagneyhighland.com.au>
+
+ * igen.c (lf_print_idecode_table, idecode_table_leaf): Fix
+ generation of switch entries in tables - treat the same as
+ cracking/semantic functions.
+
+ * igen.c (idecode_switch_end, idecode_switch_leaf): Fix generation
+ of a boolean switch statement (field zero or non-zero).
+
+ * ppc-opcode-test-1, ppc-opcode-test-2: New files. These test the
+ switch/table generation ability of igen.
+
+ * igen.c (idecode_switch_leaf): Fix code output when a switch
+ statement needs to look up a table.
+
+ * igen.c (idecode_declare_if_switch): New function called from
+ gen_idecode_c - need to declare any idecode switch functions
+ before they are used in idecode tables.
+
+ * igen.c (lf_print_c_cracker_function, idecode_crack_leaf,
+ idecode_crack_insn): Add is_inline_function argument to code
+ printing cracker functions which indicates if STATIC_IDECODE or
+ STATIC_INLINE_IDECODE should be used for definition. For
+ idecode_crack_insn (which implies not duplicating/expanding) don't
+ declare function as inline - we assume that the only time this is
+ code is generated is when things are being tested. For
+ idecode_crack_leaf, make static (instead of INLINE) if the
+ instructions parent is a table as function will always be called
+ via a table.
+
+ * igen.c (idecode_expand_if_switch): Declare as STATIC_IDECODE not
+ STATIC_INLINE_IDECODE. Only the outermost idecode switch will be
+ called directly, all others are called via a table.
+
+ * igen.c (lf_print_semantic_function_header, semantics_h_leaf,
+ semantics_h_insn, semantics_h_function,
+ lf_print_c_semantic_function, semantics_c_function): Add
+ is_inline_function argument to lf_print_semantic_function_header
+ to indicate if an inline or static function declaration/definition
+ should be output. Depending on situtation call accordingly:
+ functions (not instruction semantic routines) are always inline;
+ Semantic routines are made inline when there is no icache (cache
+ will contain the function address) and are duplicating (see above)
+ and the parent of the instruction is a switch statement.
+
+ * igen.c (opcode_field_new): Delete. Code changed to use ZALLOC
+ and moved to insn_table_find_opcode_field.
+
+ * table.c (table_open): Fix typo (nr_model_fields vs nr_fields).
+
+ * igen.c (model_c_insn): Suggestion - document the name of the
+ instruction on each line of the instruction model table.
+
+Fri Nov 10 00:44:38 1995 Andrew Cagney <cagneyhighland.com.au>
+
+ * emul_netbsd.c (do_ioctl): Cleanup compilation.
+
+ * sim_callbacks.h (__attribute__): Only define if not defined (was
+ already defined on NetBSD host).
+
+Wed Nov 8 21:49:52 1995 Andrew Cagney <cagneyhighland.com.au>
+
+ * std-config.h (WITH_XOR_ENDIAN), configure.in, Makefile.in: New
+ macro, indicates if the PowerPC's horrible XOR endian mode should
+ be suported. Add to configure and make.
+
+ * vm_n.h (vm_data_map_read_N, vm_data_map_write_N), vm.c
+ (vm_instruction_map_read): If XOR endian, xor the address
+ with a value from an xor table (indexed by size of access).
+
+ * vm.c (vm_synchronize_context), cpu.c (cpu_synchronize_context):
+ set up xor table to xor if there is a conflict between the
+ CURRENT_TARGET_ENDIAN and the endian indicated in the MSR. Move
+ check of suported change of endian mode from cpu.c to vm.c.
+
+ * vm.c (vm_data_map_write_buffer, vm_data_map_read_buffer):
+ Hopefully added correct hack to handle XOR endian mode.
+
+ FIXME: If NONSTRICT alignment and XOR ENDIAN and MSR indicates
+ little endian mode, the model accepts miss aligned transfers.
+
+ FIXME: Need to create an `init' device that, during
+ initializatioin for XOR mode, it mushes (XOR address) all the dma
+ data before passing it on to the core for storage. Just like the
+ real thing really.
+
+Wed Nov 8 21:49:52 1995 Andrew Cagney <cagneyhighland.com.au>
+
+ * devices.c (halt_io_write_buffer_callback): Use value written to
+ halt device to determine exit status. Thus allowing
+ success/failure of OEA tests.
+
+Wed Nov 8 00:10:38 1995 Andrew Cagney <cagneyhighland.com.au>
+
+ * ppc-instructions (icbi): If icache present flush it.
+
+Tue Nov 7 23:36:31 1995 Andrew Cagney <cagneyhighland.com.au>
+
+ * devices.c (htab_init_callback): Add code to create htab/pte.
+
+ * devices.c (dma_file, file_init_callback, htab_init_callback):
+ New function - Dma the named file into memory at the specified
+ address. Use.
+
+ * device_tree.h, device_tree.c (scand_*): New functions.
+
+Tue Nov 7 23:36:31 1995 Andrew Cagney <cagneyhighland.com.au>
+
+ * filter_filename.c, Makefile.in: Change so that only dependant on
+ a very limited nr of files. Stops an unnecessary dependency.
+
+Tue Nov 7 15:44:33 1995 Andrew Cagney <cagney@highland.com.au>
+
+ * core.c (core_map_find_mapping): Use cpu_halt rather than error
+ to abort an access to an undefined address.
+
+Sun Nov 12 07:58:09 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * igen.c (model_table_insert_{macro,function}): New functions.
+ (insn_table_load_insns): Call them.
+ (gen_model_h): Move section emiting model-macros to be first.
+ (model_{c,h}_function): New functions cloned from semantic
+ functions to print out the prototype and function for
+ model-functions.
+ (gen_model_{c,h}): Print out model-functions.
+
+ * ppc-instructions (model_{start,halt,print_info}): Add dummy
+ model-functions.
+
+ * options.c (print_options): Print out WITH_{,DEFAULT_}MODEL, not
+ WITH_PPC_{,DEFAULT_}_MODEL.
+ (options_ppc): Delete now unused function.
+ (cpu.h): Include cpu.h, not just basics.h.
+
+ * std-config.h (WITH_{,DEFAULT_}MODEL): Define.
+
+ * igen.c (model_macros, last_model_macro): New statics to keep
+ track of macros to go in model.h.
+ (insn_table_load_insns): Add model-macros to model_macros linked
+ list.
+ (model_table_fields): Add field for printable name.
+ (gen_model_h): If there are model macros defined, print them out.
+ Print out DEFAULT_MODEL as the first model if there any models
+ specified, otherwise MODEL_NONE. Print out external decl for
+ current_model. Print out decl for model_set.
+ (gen_model_c): Add function model_set. Switch to use printable
+ name for the model, not the internal identifier used.
+
+ * psim.c (current_model): New global variable.
+
+ * ppc-instructions: Add macros for flag defines. Switch first
+ model so 604 is first.
+
+ * main.c (main): Call model_set, not function_unit_model.
+ * sim_calls.c (sim_open): Ditto.
+ * sim_calls.c, Makefile.in: sim_calls.c now includes cpu.h.
+
+Sat Nov 11 07:27:41 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * mon.h (mon_events): New enumeration for other events we want to
+ handle.
+ (mon_event): Add declaration for function.
+
+ * mon.c (mon_event): New function.
+ (mon_print_info): Print icache misses.
+
+ * psim.c (run_until_stop): Monitor icache misses.
+
+ * configure.in (--enable-sim-inline): Fix typos in handling comma
+ separated inline options.
+ (--enable-sim-icache): Echo icache size.
+ * configure: Regenerate.
+
+ * igen.c (semantics_h_print_function): Emit STATIC_SEMANTICS
+ instead of INLINE_SEMANTICS so that the compiler won't keep all of
+ the semantic functions as inline RTL, given that the address of
+ the function is taken which forces outline calls anyway.
+ (lf_print_c_semantic_function_header): Ditto.
+ (gen_semantics_h): Define STATIC_SEMANTICS as nothing if not
+ defined.
+ (lf_print_c_cracker_function): Emit STATIC_IDECODE instead of
+ STATIC_INLINE_IDECODE.
+ (gen_idecode_c): Define STATIC_IDECODE if not defined.
+ (gen_model_h): Use #ifdefs to define types to hold model units,
+ cycles, and flags.
+ (model_table_insert): Add a sentinel functional unit at the end to
+ simplify loop processing.
+ (model_c_insn): Use <function-unit>_SENTINAL instead of 0 for any
+ instruction not specifing a function unit for the current model.
+ (gen_model_{c,h}): Provide bounds for model_time_mapping.
+
+ * inline.h (STATIC_SEMANTICS): Define to be static if
+ SEMANTICS_INLINE is defined.
+ (STATIC_IDECODE): Define to be static if IDECODE_INLINE is
+ defined.
+
+ * options.c (print_options): Fix typo.
+
+Fri Nov 10 06:39:46 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * configure.in (--enable-sim-{opcode,config}): Use $srcdir when
+ check for the existence of files.
+ * configure: Regenerate.
+
+ * table.c (table): New field nr_model_fields.
+ (table_open): New parameter nr_model_fields.
+ (table_entry_read): Parse model fields that begin with a '*' after
+ each instruction.
+ * igen.c, dgen.c: Change callers of table_open.
+
+ * igen.c: Add support for dumping model specific information in
+ model.h and model.c.
+ (insn_field_name): Delete unused array.
+ (global variables): Make global variables static, so we can tell
+ when they are no longer used.
+ (cache_semantic_actual): Delete unused variable.
+ (insn_table_load_insns): If the insn is really a machine model,
+ call model_table_insert instead of other processing.
+ (model_table_insert): New function to handle defining the
+ functional units of a particular machine model.
+ (insn_table): Add last_function field so we can add functions at
+ the end.
+ (insn_table_insert_function): Use last_function field when
+ appending new function.
+
+ * ppc-instructions: Add a few model specific information for 603,
+ 603e, and 604 for testing purposes.
+
+ * table.h (table_model_entry): New linked list to hold model
+ specific information, one per line.
+ (table_entry): Add model_first, model_last fields.
+
+ * configure.in (--enable-sim-inline): If gcc is found and
+ --enable-sim-inline is not specified, defaine DEFAULT_INLINE to 1,
+ not 2.
+ (--enable-sim-reserved-bits): New switch to check whether reserved
+ bits are set in the instruction.
+ (--enable-sim-opcode): Make complex the default.
+ (all switches): Add appropriate checks and error messages.
+ * configure: Regenerate.
+
+ * Makefile.in (RESERVED_CFLAGS): New variable set by
+ --enable-sim-reserved-bits.
+ (CONFIG_CFLAGS): Include RESERVED_CFLAGS.
+ (BUILT_SRC): igen now generates model.c and model.h.
+ (LIB_OBJ): Include table.o.
+ (tmp-igen): Add -m/-M options to write model.c/model.h.
+ (model.o): New object.
+ (CPU_H): Include model.h.
+
+ * cpu.h: Include model.h.
+
+ * std-config.h (WITH_RESERVED_BITS): Define.
+ (MODEL_INLINE): Ditto.
+
+ * options.c (print_options): Print out WITH_RESERVED_BITS.
+
+Thu Nov 9 12:22:15 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * configure.in: If --silent, don't output information messages.
+ * configure: Regenerate.
+
+ * configure.in (--enable-sim-alignment): Fix typo in specifing non
+ strict alignment.
+ (--enable-sim-switch): Make default on.
+ (--enable-sim-duplicate): Make default on.
+ (--enable-sim-smp): Make default 0.
+ (--enable-sim-mon): Don't set sim_float if not set.
+ (--enable-sim-inline): If gcc is found and --enable-sim-inline is
+ not specified, define DEFAULT_INLINE to be 2.
+ (all --enable-sim-* rules): Echo rules set to non empty to file
+ descriptor 6.
+ * configure: Regenerate.
+
+ * options.c (options_env): Fix typo if WITH_ENV is 0.
+ (print_options): Print GCC compiler version if available and
+ date/time options was compiled. If OPCODE_RULES, IGEN_FLAGS,
+ and/or DGEN_FLAGS are defined, print them.
+
+ * Makefile.in (all link actions): Pass SIM_CFLAGS as well as
+ CFLAGS.
+ (options.o): Compile options.o with OPCODE_RULES, IGEN_FLAGS, and
+ DGEN_FLAGS defined, so they can be printed out.
+
+ * igen.c (lf_print_c_validate): Check for WITH_ASSERT, so that
+ this test can be compiled away if the user really wants a fast
+ simulator by not doing assertion failures.
+
+Wed Nov 8 13:19:47 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * options.c: New file to print out all of the WITH_ options.
+ * options.h: New include file to declare print_options.
+ * debug.h (trace_options): Add trace_opts to call print_options.
+ * debug.c (trace_description): Add trace_opts support.
+ * main.c (main): If user requested options, print them.
+ * sim_calls.c (sim_open): Ditto.
+
+ * igen.c (opcode_field_new): Add void to make it a proper prototype.
+
+ * emul_generic.c (emul_enter_call): Make printf_filtered arguments
+ type correct.
+ * emul_netbsd.c (do_kill): Ditto.
+ * registers.c (registers_dump): Ditto.
+ * vm.c (om_translate_effective_to_real): Ditto.
+ * vm_n.h (vm_data_map_read_N): Ditto.
+ (vm_data_map_write_N): Ditto.
+ * devices.h (DTRACE_INIT): Ditto.
+ (DTRACE_{ATTACH,DETACH}_ADDRESS): Ditto.
+ (DTRACE_IO_{READ,WRITE}_BUFFER): Ditto.
+ (DTRACE_DMA_{READ,WRITE}_BUFFER): Ditto.
+ * devices.c (update_for_binary_section): Ditto.
+ (write_stack_arguments): Ditto.
+ (stack_ioctl_callback): Ditto.
+ * device_tree.c (device_tree_add_passthrough): Ditto.
+ (device_tree_{add,find}_device): Ditto.
+ (device_tree_{add,find}_integer): Ditto.
+ (device_tree_find_{string,boolean}): Ditto.
+ (device_tree_init{,_device}): Ditto.
+ (device_tree_dump): Ditto.
+ * sim_calls.c (sim_{read,write}): Ditto.
+ (sim_{fetch,store}_register): Ditto.
+ (sim_stop_reason): Ditto.
+
+ * sim_callbacks.h (printf_filtered): Declare with attribute
+ printf, so we can enable format checks.
+
+ * devices.c (console_io_{read,write}_buffer_callback): Cast swtich
+ argument to int, since ANSI doesn't allow long switch values.
+ * emul_netbsd.c (do___sysctl): Ditto.
+
+ * emul_netbsd.c (do___sysctl): Fix up printf call.
+
+ * corefile.c (core_translate): Don't do arithmetic with void *
+ pointers. Cast to char * first.
+
+ * function_unit.c (FUNC_{LOAD,STORE}): Rename from {LOAD,STORE}
+ and change all uses.
+
+ * Makefile.in ({FUNC,MODEL,WARNING}_CFLAGS): New flags set by
+ configure --enable switches.
+ (CONFIG_CFLAGS): Include FUNC_CFLAGS and MODE_CFLAGS.
+ (.c.o): Include WARNING_CFLAGS.
+ (CPU_H): Include function_unit.h.
+ (LIB_OBJ): Include function_unit.o.
+ (BUILT_SRC_WO_CONFIG): Split from BUILT_SRC and do not include
+ config.h or ppc-config.h.
+ (BUILT_SRC): Include BUILT_SRC_WO_CONFIG, config.h and
+ ppc-config.h.
+ (filter_filename.o): Include config.h/ppc-config.h dependencies.
+ (idecode.o, semantics.o, psim.o): Specify CC line without
+ WARNING_CFLAGS so that we don't get all of the unused variable
+ warnings that are generated.
+ (function_unit.o): Add rule to build.
+ (main.o, sim_calls.o): Add function_unit.h, itable.h dependencies.
+ (mon.o): Include mon.c dependency.
+ (TAGS): Depend on BUILT_SRC.
+ (clean): Don't delete config.h or ppc-config.h
+
+ * basics.h (sim_callbacks.h): Move include after the include of
+ config.h and ppc-config.h.
+
+ * bits.{h,c} (ROTL32,ROTL64): Move these functions to bits.c. Add
+ support for BITS_INLINE to inline these. Add declarations to
+ bits.h.
+
+ * configure.in (--enable-sim-warnings): Add new option to specify
+ compiler warnings for all modules except idecode.o and semantics.o
+ which have lots of unused variables because they are machine
+ generated.
+ (--enable-sim-function-unit): New switch to configure whether
+ function unit support is compiled in or not.
+ (--enable-sim-{,default-}mode): New switches to control which cpu
+ model is used.
+ * configure: Regenerate.
+
+ * corefile.c (core_attach_address_callback): Delete unused
+ variable device_address.
+
+ * cpu.c (struct _cpu): Add function unit pointer field func_unit.
+ (cpu_create): If WITH_FUNCTION_UNIT, call function_unit_create.
+ (cpu_init): If WITH_FUNCTION_UNIT, call function_unit_init.
+ (cpu_halt): If WITH_FUNCTION_UNIT, call function_unit_halt.
+ (cpu_function_unit): New function to return func_unit field.
+
+ * cpu.h (function_unit.h): Include new include file.
+ (cpu_function_unit): Declare.
+
+ * debug.c (stdlib.h): Test HAVE_STDLIB_H, not HAVE_STDLIB.
+ (config.h): Include config.h.
+
+ * devices.c (icu_io_write_buffer_callback): Delete unused variable
+ system.
+
+ * emul_generic.c (emul_exit_call): Print out status value.
+
+ * emul_netbsd.c (do_read): Delete unused variable nr_moved.
+
+ * filter_filename.h (includes): Include config.h, ppc-config.h,
+ not basics.h.
+
+ * inline.c: Include bits.c if BITS_INLINE. Include
+ function_unit.c if FUNCTION_UNIT_INLINE.
+
+ * inline.h (INLINE_BITS): Define if BITS_INLINE.
+ (INLINE_FUNCTION_UNIT): Define if FUNCTION_UNIT_INLINE.
+
+ * interrupts.c (instruction_storage_interrupt): Delete unused
+ variable nia.
+
+ * lf.h (config.h): Include config.h.
+
+ * main.c (includes): Include function_unit.c. If HAVE_UNISTD_H,
+ include unistd.h.
+ (usage): Update for -m model, -i, and -I options.
+ (main): Delete unused variables stack_pointer and i. Add support
+ for -i, -m model arguments. Call psim_print_info with verbose ==
+ 1 if -i, and verbose == 2 if -I.
+
+ * mon.c (stdio.h): Include stdio.h to pick up sprintf prototype.
+ (mon_issue): Call function_unit_issue if function units are
+ supported.
+ (mon_print_info): Take psim * argument. Print out information
+ from function_unit if available. Move read/write stats to always
+ print, instead of printing if verbose > 1. Fix up plural
+ vs. singular usage.
+
+ * mon.h (mon_print_info): Update prototype.
+
+ * psim.c (current_ppc_model): Add global variable.
+ (psim_print_info): Pass system argument to mon_print_info.
+
+ * sim_calls.c (function_unit.h): Include.
+ (sim_open): Add support for -i and -m model options. If -i call
+ psim_print_info with verbose == 1, if -I, with verbose == 2.
+ (sim_resume): Delete unused variable program_counter.
+
+ * std-config.h (WITH_FUNCTION_UNIT): Define.
+ (ppc_model): Add enumeration giving all PowerPC models currently
+ known about.
+ ({WITH,CURRENT}_PPC_MODEL): Define.
+ (FUNCTION_UNIT_INLINE): Define.
+
+ * table.c (config.h): Include config.h.
+
+ * vm.c (om_virtual_to_real): Print pte_word_{0,1} so the compiler
+ doesn't complain that they're unused.
+
+ * vm_n.h (vm_data_map_read_N): Delete unused variable rval.
+
+Mon Nov 6 23:15:54 1995 Andrew Cagney <cagney@highland.com.au>
+
+ * sim-endian.c (ppc-endian.c), sim-endian.h (ppc-endian.h):
+ renameed. These files are target independant.
+ * Makefile.in, basics.h: update for new name.
+
+ * sim-endian.h (SWAP_N), sim-endian.c (_SWAP_1): Rename existing
+ SWAP_<N> to _SWAP_<N> so that sim-endian.h can contain SWAP_N
+ macro's as required.
+
+ * sim-endian.c, sim-endian-n.h (new file): Move endian code into a
+ debugable header file.
+
+ * ppc-instructions (Byte-Reverse): Enable byte reverse
+ instructions using SWAP_N macros.
+
+Mon Nov 6 10:39:28 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * Makefile.in (config.status): Remove references to config.make
+ and config.hdr.
+
+ * config.{make,hdr}: Delete, no longer used.
+ * build-psim: Ditto.
+
+Mon Nov 6 20:49:56 1995 Andrew Cagney <cagney@highland.com.au>
+
+ * sim_calls.c (sim_open): Fix parsing of `target sim' options.
+
+ * device_tree.c (device_tree_add_string): Wasn't saving the value
+ of the string being entered into the tree.
+
+ * psim.c (create_filed_device_tree): Not terminating string device
+ names with a null.
+
+ * psim.c (psim_create): Use `env' instead of
+ `environment-architecture' to be consistent with configure.
+ Reconize user/uea, virtual/vea and operating/oea.
+
+Sat Nov 4 12:29:45 1995 Fred Fish <fnf@cygnus.com>
+
+ * core.c: Rename to corefile.c
+ * core.h: Rename to corefile.h
+ * inline.c: Include corefile.h, renamed from core.h.
+ * cpu.h: Include corefile.h, renamed from core.h
+ * vm.c: Include corefile.h, renamed from core.h
+ * corefile.c: Include corefile.h rather than core.h
+ * README.psim (KNOWN PROBLEMS): Change core.* references to corefile.*
+ references.
+ * Makefile.in (CPU_H): Change core.h to corefile.h
+ (vm.o): Change dependency to corefile.h
+ (LIB_SRC): Change core.c to corefile.c.
+ (LIB_OBJ): Change core.o to corefile.o.
+ (corefile.o): Change dependencies to corefile.c, corefile.h.
+
+Fri Nov 3 11:37:24 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * ppc-instructions (data cache instructions): Make all data cache
+ instructions nops instead of invalid instructions.
+
+ * Makefile.in (CONFIG_CFLAGS): Add ALIGNMENT_CFLAGS and
+ TIMEBASE_CFLAGS which weren't included.
+
+Thu Nov 2 08:54:04 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * Makefile.in: Uncomment built file dependencies.
+
+ * configure.in: Rewrite --enable-sim switch handling to use the
+ autoconf builtins so it works correctly if the configure or
+ Makefile.in files are modified and make decides to rebuild
+ Makefile. Also document all of the --enable-sim switches
+ supported. Check whether getrusage and sys/resource.h are
+ supported.
+ * config.in: Regenerate.
+ * configure: Regenerate.
+ * Makefile.in: Add support for all of the variables set with
+ --enable-sim switches.
+
+ * Makefile.in (clean): make clean now removes all built sources as
+ well.
+
+ * cpu.c: Use HAVE_STRING_H, HAVE_STRINGS_H, HAVE_UNISTD_H,
+ HAVE_TIME_H, HAVE_SYS_TIMES_H, HAVE_SYS_RESOURCE_H defined in
+ the generated config.h.
+ * debug.c: Ditto.
+ * device_tree.c: Ditto.
+ * devices.c: Ditto.
+ * dgen.c: Ditto.
+ * emul_netbsd.c: Ditto.
+ * igen.c: Ditto.
+ * lf.c: Ditto.
+ * misc.c: Ditto.
+ * psim.c: Ditto.
+ * registers.c: Ditto.
+ * sim_calls.c: Ditt.
+ * table.c: Ditto.
+
+
+ * main.c (main): Call psim_print_info with verbose == 2.
+
+ * mon.c (mon_print_info): Align the cpu number and number of
+ instructions fields. Do not print an instruction category if the
+ CPU did not execute any of those instructions. Print out number
+ of reads and writes. If getrusage is supported, print out number
+ of simulated instructins per second.
+
+ * configure.in: Add support for --enable-sim-opcode=stupid.
+ * configure: Regenerate.
+
+Wed Nov 1 23:46:59 1995 Andrew Cagney <cagney@highland.com.au>
+
+ * std-config (INLINE_DEVICE_TREE): Don't inline either of
+ device_tree.c or devices.c. There is no significant gain.
+
+ * configure.in, Makefile.in: add --enable-sim-icache=[0-9]* and
+ IGEN_ICACHE macro.
+
+Wed Nov 1 23:46:59 1995 Andrew Cagney <cagney@highland.com.au>
+
+ * igen.c (main), misc.h (target_a2i, i2target), misc.c: Add
+ functions to convert between target and igen internal bit numbers.
+ Make IO go through these functions. Add -b (bit size) and -h (high
+ bit nr) options to igen. Typical usage would be: ./igen -b 16 -h
+ 15 for a 16 bit instruction format with the msb given a number 15.
+
+Wed Nov 1 22:17:32 1995 Andrew Cagney <cagney@highland.com.au>
+
+ * dgen.c (main): Was outputting optarg even when it was NULL.
+
+Tue Oct 31 23:48:33 1995 Andrew Cagney <cagney@highland.com.au>
+
+ * vm_n.h (vm_data_map_load_N, vm_data_map_store_n), debug.h,
+ debug.c: Add tracing of load/store unit (virtual) with -t
+ load-store.
+
+Tue Oct 31 21:44:01 1995 Andrew Cagney <cagney@highland.com.au>
+
+ * std-config.h (WITH_ENVIRONMENT): Add USER_ENVIRONMENT which does
+ not include things such as the time base and events.
+
+ * interrupt.c, sim_calls.c, cpu.h, vm.c, configure.in: Add UEA to
+ all environment switches for above.
+
+ * psim.c (psim_create): ditto - new device tree node name is
+ /options/environment-architecture with values user, virtual and
+ operating.
+
+Tue Oct 31 21:31:32 1995 Andrew Cagney <cagney@highland.com.au>
+
+ * ppc-opcode-stupid: Third example of use of opcode table - this
+ one expands all mtspr/mfspr and branch instructions. Appears to
+ give about a 10% gain in performance if everything enabled. Also
+ takes about 150mb of swap to build.
+
+Wed Nov 1 10:49:48 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * emul_netbsd.c (do_exit): Print arguments and close parenthesis
+ if tracing, since exit doesn't go through emul_exit_call.
+ (do_read): Print arguments if tracing.
+ (do_write): Ditto.
+ (do_open): Ditto.
+ (do_break): Ditto.
+ (do_kill): Ditto.
+ (do_dup): Ditto.
+ (do_sigprocmask): Replace trace with printing arguments if
+ tracing.
+ (do_ioctl): Print arguments if tracing.
+ (do_umask): Ditto.
+ (do_dup2): Ditto.
+ (do_fcntl): Ditto.
+ (do_gettimeofday): Ditto.
+ (do_getrusage): Ditto.
+ (do_fstatfs): Ditto.
+
+ * filter_filename.c: New file to provide filter_filename to strip
+ the directory prefix from a file.
+ * filter_filename.h: New include file to declare filter_filename.
+
+ * debug.h: Include filter_filename.h.
+ (TRACE,DTRACE,ERROR): Use filter_filename on __FILE__.
+
+ * misc.h: Include filter_filename.h.
+ (ASSERT): Use filter_filename on __FILE__.
+
+ * igen.c (lf_print_my_prefix): Use filter_filename on the filename
+ argument.
+
+ * Makefile.in: Add filter_filename support.
+
+ * ppc-instructions (dcbi, icbi): Make these NOPs rather than
+ invalid instructions.
+
+ * configure.in: Add support for more --enable-sim-* switches.
+ Use config.make and config.hdr to write to Makefile and config.h
+ respectively. Don't rewrite Makefile, just append to it.
+ * configure: Regenerate.
+ * config.{make,hdr}: New shell scripts.
+
+ * Makefile.in: Remove all variables set by configure.in.
+ (psim.o): Depend on $(BUILT_SRC) also.
+
+ * emul_netbsd.c (do_gettimeofday,do_getrusage): When comparing an
+ integer, use 0, not NULL.
+
+Tue Oct 31 15:20:04 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * configure.in: Add support for --enable-sim-inline,
+ --enable-sim-bswap, --enable-sim-cflags, --enable-sim-complex,
+ --enable-sim-switch, --enable-sim-duplicate, --enable-sim-filter,
+ and --enable-sim-endian switch to control various Makefile
+ variables.
+ * configure: Regenerate from configure.in.
+ * Makefile.in: Add various Make variables that the various
+ switches alter.
+
+ * std-config.h (DEFAULT_INLINE): Don't set this to 2 if using GCC
+ and optimizing by default.
+
+Fri Oct 27 19:26:27 1995 Andrew Cagney <cagney@highland.com.au>
+
+ * bits.h (ROTL32, ROTL64): Were functions, made them macros, now
+ make them functions again. Appears 2.6.3 is confused by just a
+ macro.
+
+Thu Oct 26 18:31:58 1995 Andrew Cagney <cagney@highland.com.au>
+
+ * ppc-endian.c (SWAP_8): Fix 8 byte swap!
+
+ * psim.c (psim_create): Not correctly checking that runtime
+ configuration of things like ENDIAN, ENVIRONMENT and ALIGNMENT
+ matched the compiled in ones.
+
+ * debug.h (ITRACE), igen.c: Tidy up more tracing flags -
+ trace_semantics is now different to trace_idecode, the former
+ checks the cache.
+
+Tue Oct 24 21:54:13 1995 Andrew Cagney <cagney@highland.com.au>
+
+ * ppc-instructions (mtsrin): Missing instruction
+ * ppc-instructions (mfsrin): Missing instruction
+ * ppc-instructions (eieio): Missing instruction
+
+Tue Oct 24 20:55:29 1995 Andrew Cagney <cagney@highland.com.au>
+
+ * build-psim: New shell script - see internals for usage,
+ simplifies the process of building custom simulators.
+
+Mon Oct 23 23:48:59 1995 Andrew Cagney <cagney@highland.com.au>
+
+ * std-config.h (SEMANTICS_INLINE): Tidy up notes on each of the
+ INLINE macros. Make SEMANTICS_INLINE == 1 if DEFAULT_INLINE == 2.
+ Don't use DEFAULT_INLINE to define REGISTERS_INLINE DEVICES_INLINE
+ DEVICE_TREE_INLINE or INTERRUPTS_INLINE as none of these are on
+ the instruction or data critical paths.
+
+ * FIXME: devices.c/emul_netbsd.c would benefit (slightly) from
+ the inclusion of device_tree.c/emul_generic.c.
+
+Mon Oct 23 00:31:50 1995 Andrew Cagney <cagney@highland.com.au>
+
+ * os_emul.[hc], emul_generic.[hc], emul_netbsd.[hc]: replace
+ system.[hc]. Start of suport for multiple emulations and
+ emulation state (os_emul object).
+
+ * emul_generic.[hc]: Start of code to implement proper system call
+ tracing (from spy).
+
+Sun Oct 22 21:33:51 1995 Andrew Cagney <cagney@highland.com.au>
+
+ * cpu.h, cpu.c (cpu_init): New function, zero the registers before
+ the processor is started. Fixes problem of registers being
+ undefined when restarting from within gdb.
+
+ * cpu.h, cpu.c (cpu_flush_icache): New function, flushes the
+ instruction cache (if present). Fixes problem of cpu caching gdb
+ breakpoint instructions.
+
+ FIXME: PSIM sometimes aborts calling error(), it should instead
+ call sim_error() say which takes care of housekeeping such as
+ saving the CIA before calling error.
+
+ * NOTE: cpu_flush_cache() instead of cpu_synchronize_context() is
+ used when restarting a simulation because the latter has the
+ unwanted side effect (well I as a kernel hacker think it is) of
+ performing an isync when the instruction stream doesn't contain
+ one.
+
+Sun Oct 22 19:27:48 1995 Andrew Cagney <cagney@highland.com.au>
+
+ * mon.h (new), mon.c (new), std-config.h (WITH_MON): Performance
+ monitoring module. Counts both instructions issued and
+ load/stores.
+
+ * NOTE: mon does not contain to count instruction loads as this
+ information is already available from the mon_issue() hook.
+
+ * igen.c (lf_print_c_semantic), vm_n.h: Add counting code.
+
+ * psim.h, psim.c (psim_create), cpu.h, cpu.c (cpu_create): Attach
+ a common monitor to each of the cpus. Delete
+ cpu_increment_number_of_insns() and cpu_get_number_of_insns()
+ replaced by copied code in mon.[hc].
+
+Sun Oct 22 18:42:45 1995 Andrew Cagney <cagney@highland.com.au>
+
+ * sim_calls.c, main.c, psim.c (psim_create): always create
+ `WITH_SMP' cpus. The actual number of CPU's active in a
+ simulation run is taken from the device node: /init/smp (an
+ integer). WITH_SMP changed to 2 (remember to put it back to 0).
+
+Fri Oct 20 17:26:54 1995 Andrew Cagney <cagney@highland.com.au>
+
+ * system.c: More system call emulation. If code appears NetBSD
+ specific, make conditional to being compiled on a NetBSD system
+ (sigh).
+
+Wed Oct 18 23:02:20 1995 Andrew Cagney <cagney@highland.com.au>
+
+ * Makefile.in, gen.c(delete), igen.c(new), dgen.c(new),
+ lf.[ch](new), table.[ch](new): Split into two generators - igen
+ that outputs the instruction tables and dgen that outputs the spr
+ tables. Add -f (filter out) flag to igen to filter out certain
+ instructions (ex 64 bit ones) from the created tables. Include
+ $(LIBIBERTY_LIB) in link options in case host lacks some libc
+ functions.
+
+ * NOTE: igen, since it was originally written for the
+ PowerPC/RS6000, things the MSB is 0 and the LSB is 63{31}.
+
+ * Makefile.in, std-config.h, ppc-cache-rules(new),
+ ppc-opcode-complex(new), ppc-opcode-simple(new): (for igen) Create
+ cache-rule and opcode-rule tables from macros found std-config.h.
+ Delete corresponding macro's from std-config.h.
+
+ * igen.c (gen_itable_c, gen_itable_h), Makefile.in: code to output
+ an table of all the instructions. Code to output a type
+ enumerating all the instructin names.
+
+ * igen.c(lf_print_c_semantic): Move call to increment instruction
+ counter so that it occures _after_ the instruction has been fully
+ validated, was double counting illegal/invalid instructions. Add
+ conditional so only compiled in when WITH_PROFILE enabled (enabled
+ by default).
+
+ * igen.c, cpu.h, cpu.c(cpu_increment_number_of_insns): Include
+ itable.h, count individual instruction types not just total,
+ adjust reporting functions to output this.
+
+ * ppc-instructions (64 bit Load Doubleword with Update Indexed):
+ Had 32./ instead of 31./
+
+ * ppc-instructions (64 bit Store Double Word Conditional Indexed):
+ bitrot - updated to use newer CR register operators.
+
+ * ppc-instructions (64bit Floating Convert from Integer
+ Doubleword): Correct call to Round_Float().
+
+Mon Oct 16 00:31:20 1995 Andrew Cagney <cagney@highland.com.au>
+
+ * basics.h: #include "sim_callbacks.h" earlier so that its
+ prototypes are declared in all other header files.
+
+ * bits.h, bits.c, idecode_expression.h (ROTL32, ROTL64): Update
+ doc in bits.h, remove dead code in bits.c, move ROTL32/ROTL64 into
+ bits.h.
+
+ * cpu.c(cpu_add_commas), device_tree.h, device_tree.c(scand_*):
+ Add size of buffer argument to functions writing a string into a
+ buffer. Check for buffer overflow.
+
+Sun Oct 15 22:16:11 1995 Andrew Cagney <cagney@highland.com.au>
+
+ * devices.h, devices.c, debug.h, debug.c: add macro's for tracing
+ of each device. Make parameter names consistent so macros work.
+ Use macro's in device functions.
+
+ * device_tree.c, devices.h, devices.c: include path to device in a
+ devices node when creating it.
+
+ * device_tree.c, debug.h, debug.c: Add tracing of `device-tree'.
+
+ * core.c: add tracing of core-device, adjust parameter names in
+ core functions to be consistent with those in devices*.
+
+Sun Oct 15 20:33:20 1995 Andrew Cagney <cagney@highland.com.au>
+
+ * debug.h, debug.c (trace_option): New function. Parses the trace
+ option, updating the trace array.
+
+ * debug.h, debug.c (trace_usage): New function. Outputs the list
+ of all possible trace options.
+
+ * sim_calls.c (sim_open), main.c (main): Use new trace_option() to
+ parse trace options specified with the simpler -t flag. Adjust
+ usage.
+
+ * FIXME: basic parsing of command line options is still duplicated
+ by main.c and sim_calls.c
+
+Thu Oct 26 10:42:28 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * Makefile.in (clean): Delete *.i and *.out files.
+
+ * ppc-endian.c (SWAP_n): Add SET argument to allow use of SWAP
+ macros for either assignment or return. Fix SWAP_8 to use a
+ union, and two SWAP_4's. Delete SWAP_N, since nobody uses it now.
+ (ENDIAN_N): Add SET argument to SWAP_n calls. Delete macro defs
+ that hardwired swapping on/off, let optimizer delete dead code.
+
+ * main.c (main): Add printf that we caught a signal and print out
+ the failing address.
+
+Thu Oct 19 21:43:39 1995 Fred Fish <fnf@fishfood.amigalib.com>
+
+ * Makefile.in: Remove tabs from otherwise empty line.
+ Confuses many non-GNU versions of "make".
+
+Wed Oct 18 08:51:25 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * Makefile.in (clean): Delete files produced by gen.
+
+Mon Oct 16 17:34:24 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * gen.c (lf_print_c_semantic_function): Move counting # of
+ instructions here so it works with caching.
+ (gen_idecode_c): Move from here.
+
+Wed Oct 11 17:13:15 1995 Andrew Cagney <cagney@highland.com.au>
+
+ * gen.c, ppc-instructions, psim.c: Fix code for generating
+ cracking instruction cache. Delete the code that cached just the
+ result from doing an instruction lookup - this ran slower than no
+ cache at all.
+
+Fri Oct 13 09:58:43 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * Makefile.in (gen.o): Include $(INLINE_CFLAGS).
+
+ * debug.h (ppc_trace): Rename from trace, to avoid a conflict with
+ TCL when gdb is linked with the simulator.
+ * debug.c (ppc_trace): Ditto.
+ * sim_calls.c (sim_open): Change trace -> ppc_trace.
+ * main.c (main): Ditto.
+
+ * cpu.c (cpu_add_commas): Remove extra static.
+
+Thu Oct 12 11:35:53 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * Makefile.in (psim.o): Now that inlines are turned on, make
+ psim.o depend on all sources.
+
+ * cpu.c (cpu_add_commas): New function to format a long with
+ commas.
+ (cpu_print_info): Use it to print number_of_insns.
+
+ * ppc-endian.c (SWAP_n): New macros to speed up byte swapping for
+ 2, 4, and 8 bytes.
+ (ENDIAN_N): If both target and host byte orders are known, don't
+ bother testing CURRENT_{TARGET,HOST}_BYTE_ORDER.
+
+ * ppc-endian.h (target specific H2T_n/T2H_n macros): Remove #if 0
+ to allow target specific H2T_n/T2H_n macros to be used.
+ (htonl, ntohl): If compiled on a 486 by GCC and WITH_BSWAP is
+ non-zero, redefine the htonl/ntohl macros to use the BSWAP instead
+ of the 3 instruction sequence that runs on 386s.
+
+ * std-config.h (WITH_{HOST,TARGET}_BYTE_ORDER): Don't override if
+ specified on the compile line.
+ (WITH_BSWAP): If not defined, define as 0.
+
+ * Makefile.in (INLINE_CFLAGS): Add -DDEFAULT_INLINE=2 to add
+ default inline support. Pass INLINE_CFLAGS when compiling.
+
+ * devices.{h,c} (unimp_device_ioctl): Use STATIC_DEVICES, not
+ INLINE_DEVICES since GCC doesn't like inline functions that
+ accept variable arguments.
+ (stack_ioctl_callback): Make function just static because GCC
+ doesn't like inline functions that accept variable arguments.
+
+ * devices.h (STATIC_DEVICES): Define as empty if not defined.
+
+ * inline.c: Correct pathnames of included C files to match current
+ implementation.
+
+ * inline.h (STATIC_DEVICES): If DEVICES_INLINE is defined to be
+ non-zero, define STATIC_DEVICES to be static.
+
+ * std-config.h (INLINE): If GNU C and optimizing, define this as
+ __inline__.
+ (DEFAULT_INLINE): If not defined, define as 0.
+ (ENDIAN_INLINE): If not defined, define as DEFAULT_INLINE.
+ ({CORE,VM,CPU,EVENTS,REGISTERS,INTERRUPTS}_INLINE): Ditto.
+ ({SPREG,IDECODE}_INLINE): Ditto.
+
+Wed Oct 11 17:13:15 1995 Andrew Cagney <cagney@highland.com.au>
+
+ * ppc-instructions: Initial cut of floating point suport added.
+ Of note include - use of host IEEE floating point instructions,
+ use of PowerPC manual pseudo code to handle the FPSCR. It is not
+ currently a pretty sight.
+
+ * memory_map.h, memory_map.c, memory_map_n.h, core.h, core.c:
+ merge into core.h, core.c, core_n.h. The type memory_map replaced
+ with core_map. This removes a level of pointer indirection when
+ translating an address.
+
+ * memory_map.h, memory_map.c, memory_map_n.h: delete.
+
+ * Makefile.in et.al (sorry): tweek to use new core, core_map and
+ core.h.
+
+Wed Oct 11 12:10:26 1995 Andrew Cagney <cagney@highland.com.au>
+
+ * sim_calls.c, main.c: Add -g (trace_gdb) option, add tracing to
+ most of the other functions in sim_calls.c.
+
+ * basics.h (CONCAT3), memory_map.c, memory_map_n.h, Makefile.in:
+ Add macros to better cover up `generic' code. Makes it possible
+ to step through the generic code!
+
+ * vm.c, vm_n.h, Makefile.in: ditto
+
+Tue Oct 10 15:42:59 1995 Andrew Cagney <cagney@highland.com.au>
+
+ * devices.h, devices.c, memory_map.h, memory_map.c: Changed
+ callback interface so that there is a read/write buffer but no
+ read/write_word. VEA default memory read/write handler sometimes
+ couldn't resolve an access and of those some were for a memory
+ fault and some were because gdb was making a bogus request.
+
+ * devices.h, devices.c, memory_map.h, memory_map.c, vm.h, vm.c:
+ eliminate transfer_mode (raw or cooked) parameter from read/write
+ buffer.
+
+Fri Oct 6 20:23:56 1995 Andrew Cagney <cagney@highland.com.au>
+
+ * ppc-instructions (fmul, fmuls): correct instruction format - had
+ FRB instead of FRC.
+
+Wed Oct 4 17:31:12 1995 Andrew Cagney <cagney@highland.com.au>
+
+ * psim.c, device_tree.h, device_tree.c, devices.c (printd_*,
+ scand_*): new functions to parse/print fields in device names
+ while hiding any machine dependency.
+
+ * devices.c, psim.c: Change the stack init code so that it is
+ handled by a device. Arguments passed across using a device ioctl
+ (hack).
+
+ * devices.h, devices.c: device ioctl callback changed to allow a
+ variable number of arguments. This gives greater flexability and
+ greater chance of bugs.
+
+Tue Oct 3 22:01:56 1995 Andrew Cagney <cagney@highland.com.au>
+
+ * main.c (printf_filtered, error): Missing va_end() to close off
+ variable argument use.
+
+ * Makefile.in (tmp-gencode): comment out hack to get around some
+ versions of make not handling files being created as side-effects.
+
+ * gen.c (lf_open): Add -n (real_file_name) option. Specifies an
+ alternative file name to use in output files for things like #line
+ macros.
+
+ Makefile.in (tmp-gencode): Use gen -n so that debug info is
+ correct.
+
+ * Makefile.in (TARGETLIB): Use this instead of libsim.a in the
+ Makefile.
+
+Sat Oct 7 22:40:59 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * sim_calls.c (sim_set_callbacks): Define new function.
+
+Fri Oct 6 17:23:10 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * psim.c (psim_print_info): Print exit status or signal number.
+
+Mon Oct 2 11:46:37 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * cpu.c (struct _cpu): Add number_of_insns field to trace how many
+ instructions are executed.
+ (cpu_increment_number_of_insns): New function to increment the
+ number of instructions issued.
+ (cpu_get_number_of_insns): New function to return the number of
+ instructions issued.
+ (cpu_print_info): New function to print cpu related information.
+ At present, print the number of instructions executed.
+
+ * gen_idecode_c: Emit call to cpu_increment_number_of_insns within
+ idecode_issue.
+
+ * psim.c (psim_print_info): New function to iterate over each of
+ the CPU's calling cpu_print_info.
+
+ * psim.h,cpu.h: Add new declarations.
+
+ * sim_calls.c (sim_open): Add argument processing to add the same
+ switches main.c accepts for the standalone processor.
+ (sim_close): Call psim_print_info if -I.
+
+ * main.c (main): Add comment saying to update sim_calls.c when
+ adding switches. Add -I to call psim_print_info when done.
+ (usage): Update usage message.
+
+Sun Oct 1 13:52:59 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * main.c (printf_filtered): Correct to match new prototype.
+
+Sat Sep 30 20:47:05 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * sim_callbacks.h (printf_filtered): Correct prototype.
+
+Thu Sep 21 16:26:49 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * device_tree.c (OEA_MEMORY_SIZE): Define if not defined to
+ 0x100000.
+ (clayton_memory_size): Define as OEA_MEMORY_SIZE.
+
+ * std-config.h (WITH_TRACE): Default to 1 now.
+
+ * psim.c (write_stack_arguments): Don't write any stack arguments
+ if OEA.
+
+ * main.c (main): Switch to using getopt. Make -p also set
+ trace_semantics. Make -a turn on all trace flags. Make -C turn
+ on console tracing.
+
+ * device_tree.c (create_option_device_node): Assume a program is
+ OEA if the start address is < 4096, not just == 0.
+
+Wed Sep 20 13:36:06 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * Makefile.in (maintainer-clean): New synonym for realclean.
+
+Sun Sep 10 10:23:56 1995 Michael Tiemann <tiemann@axon.cygnus.com>
+
+ * registers.c (register_description): Add gdb synonyms for cr
+ (cnd) and msr (ps).
+
+Fri Sep 8 13:16:10 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * Makefile.in (install): Don't install in $(tooldir).
+
+ * configure.in: Call AC_CONFIG_HEADER. Don't try to use
+ bfd/hosts/*.h file or bfd/config/*.mh file. Call AC_PROG_CC and
+ AC_PROG_RANLIB. Substitute in values for CFLAGS, HDEFINES, AR,
+ and CC_FOR_BUILD. Call AC_CHECK_HEADERS for various header files.
+ Touch stamp.h if creating config.h.
+ * configure: Rebuild.
+ * config.in: New file, created by autoheader.
+ * Makefile.in (AR): Define as @AR@.
+ (CC): New variable, defined as @CC@.
+ (CFLAGS): Define as @CFLAGS@.
+ (CC_FOR_BUILD): New variable, defined as @CC_FOR_BUILD@.
+ (RANLIB): Define as @RANLIB@.
+ (HDEFINES, TDEFINES): New variables.
+ (@host_makefile_frag@): Remove.
+ (mostlyclean): Make the same as clean, not distclean.
+ (clean): Remove config.log.
+ (distclean): Remove config.h and stamp-h.
+ (Makefile): Don't depend upon @frags@. Just rebuild Makefile when
+ invoking config.status.
+ (config.h, stamp-h): New targets.
+ (gen, gen.o): Build with CC_FOR_BUILD, not CC.
+ (ppc-config.h): Rename from old config.h build.
+ * (basics.h,gen.c,ppc-endian.c,psim.c): Include ppc-config.h.
+
+Fri Sep 8 09:51:03 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * configure{,.in}: Don't include sysdep.h from bfd, since bfd no
+ longer provides it.
+ * basics.h (sysdep.h): Don't include it.
+ * Makefile.in (BASICS_H): Remove sysdep.h.
+
+Wed Sep 6 13:25:42 1995 Andrew Cagney <cagney@highland.com.au>
+
+ * core.c (core_add_data): First growth of bss was being put at
+ wrong address (0) instead of &end.
+
+ * core.c (core_add_stack, core_add_data): Was not handling case
+ where bss/stack is grown across the current end-of-{bss,stack}.
+
+Wed Sep 6 00:46:10 1995 Andrew Cagney <cagney@highland.com.au>
+
+ * system.c (system_call): Fix SYS_break - was aligning bss to a
+ page boundary instead of just an 8 byte one; On first call sbrk(0)
+ != sbrk(0).
+
+Thu Aug 24 14:48:54 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * Makefile.in (install): Fix install rule.
+
+Tue Aug 22 09:31:18 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * system.c (system_call): Add read support.
+
+ * main.c (main): -t sets trace_device_tree. Correct usage message
+ to current reality.
+
+ * device_tree.c (update_memory_node_for_section): Make tracing
+ output line up. If not code or readonly, assume that the section
+ is a data section and has read/write permissions. Add readonly
+ support.
+
+ * core.c (create_core_from_addresses): Print end address in traces
+ and make tracing output line up.
+
+ * Makefile.in: Rewrite from Makefile to work with the Cygnus
+ environment, and support compiling in a different directory than
+ the sources reside in.
+
+ * ppc-endian.h: Rename from endian.h so that it doesn't get
+ confused with /usr/include/sys/endian.h on Linux. Add Linux
+ endian support.
+
+ * ppc-endian.c: Rename to be consistant with ppc-endian.h.
+ Include ppc-endian.h, not endian.h.
+
+ * basics.h (sysdep.h): Include sysdep.h that configure makes.
+ Include ppc-endian.h, not endian.h.
+
+ * std-config.h: Rename from ppc-config. Put #ifndefs around most
+ configuration macros, so they can be overridden via CFLAGS. By
+ default, turn off tracing.
+
+ * configure.in: Clone from other simulator targets.
+ * configure: Generate via autoconf from configure.in.
+
+Sat Aug 19 09:05:32 1995 Andrew Cagney <cagney@highland.com.au>
+
+ * ppc-instructions: fix srawi (was geting XER[CA] real wrong).
+
+ * interrupts.c (data_storage_interrupt): allow stack to grow by
+ upto one MB per increment.
+
+ * ppc-instructions: divw was computing rA / rA not rA / rB
+
+ * main.c (main): really stupid. Wasn't exiting with correct status
+
+Fri Aug 18 00:38:01 1995 Andrew Cagney <cagney@highland.com.au>
+
+ * system.c (system_call): add system calls kill(2) and getpid(2).
+
+ * main.c (main): Check/return exit status when simulation
+ finishes.
+
+Thu Aug 17 14:29:18 1995 Andrew Cagney <cagney@highland.com.au>
+
+ * device_tree.c (create_option_device_node): Alignment rules (at
+ least for the moment) now are for strict alignment only for LE OEA
+ mode. (Because of compiler problems).
+
+ * system.c (system_call) SYS_exit: Wasn't exiting with correct status.
+
+Thu Aug 17 01:16:38 1995 Andrew Cagney <cagney@highland.com.au>
+
+ * vm.c (DEFINE_VM_DATA_MAP_WRITE_N): For miss aligned transfer
+ forgot to return.
+
+ * system.c (system_call): didn't page align break argument before
+ determining increment break increment.
+
+ * psim/ppc: Re-arange entire directory structure so that
+ everything lives in the one directory. While a pain for cleaning,
+ makes building across multiple architectures much simpler.
+
+ * devices.c, device_tree.c: Added code that provides a simple
+ illustration of how an interrupt control device could be
+ implemented.
+
+ * devices.c: Added code so that the dumb console device can read
+ (from stdin) as well as write to stdout.
+
diff --git a/gnu/dist/sim/ppc/Makefile.in b/gnu/dist/sim/ppc/Makefile.in
index 379ac763b05..81933f0175b 100644
--- a/gnu/dist/sim/ppc/Makefile.in
+++ b/gnu/dist/sim/ppc/Makefile.in
@@ -1,7 +1,7 @@
#
# This file is part of the program psim.
#
-# Copyright (C) 1994-1996, Andrew Cagney <cagney@highland.com.au>
+# 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
@@ -30,12 +30,12 @@ exec_prefix = @exec_prefix@
host_alias = @host_alias@
target_alias = @target_alias@
program_transform_name = @program_transform_name@
-bindir = $(exec_prefix)/bin
-libdir = $(exec_prefix)/lib
+bindir = @bindir@
+libdir = @libdir@
tooldir = $(libdir)/$(target_alias)
-datadir = $(prefix)/lib
-mandir = $(prefix)/man
+datadir = @datadir@
+mandir = @mandir@
man1dir = $(mandir)/man1
man2dir = $(mandir)/man2
man3dir = $(mandir)/man3
@@ -45,17 +45,14 @@ man6dir = $(mandir)/man6
man7dir = $(mandir)/man7
man8dir = $(mandir)/man8
man9dir = $(mandir)/man9
-infodir = $(prefix)/info
-includedir = $(prefix)/include
-docdir = $(datadir)/doc
+infodir = @infodir@
+includedir = @includedir@
SHELL = /bin/sh
-INSTALL = $(srcroot)/install.sh -c
-INSTALL_PROGRAM = $(INSTALL)
-INSTALL_DATA = $(INSTALL)
-INSTALL_XFORM = $(INSTALL) -t='$(program_transform_name)'
-INSTALL_XFORM1= $(INSTALL_XFORM) -b=.1
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
AR = @AR@
AR_FLAGS = rc
@@ -70,6 +67,8 @@ SIM_CFLAGS = @sim_cflags@
INLINE_CFLAGS = @sim_inline@
BSWAP_CFLAGS = @sim_bswap@
ENDIAN_CFLAGS = @sim_endian@
+REGPARM_CFLAGS = @sim_regparm@
+STDCALL_CFLAGS = @sim_stdcall@
HOSTENDIAN_CFLAGS = @sim_hostendian@
SMP_CFLAGS = @sim_smp@
XOR_ENDIAN_CFLAGS = @sim_xor_endian@
@@ -84,9 +83,14 @@ ASSERT_CFLAGS = @sim_assert@
RESERVED_CFLAGS = @sim_reserved@
MONITOR_CFLAGS = @sim_monitor@
MODEL_CFLAGS = @sim_model@ @sim_default_model@ @sim_model_issue@
+STDIO_CFLAGS = @sim_stdio@
+TERMIO_CFLAGS = @sim_termio@
WARNING_CFLAGS = @sim_warnings@
+DEVZERO_CFLAGS = @sim_devzero@
CONFIG_CFLAGS = $(BSWAP_CFLAGS) \
$(ENDIAN_CFLAGS) \
+ $(REGPARM_CFLAGS) \
+ $(STDCALL_CFLAGS) \
$(HOSTENDIAN_CFLAGS) \
$(SMP_CFLAGS) \
$(XOR_ENDIAN_CFLAGS) \
@@ -100,21 +104,38 @@ CONFIG_CFLAGS = $(BSWAP_CFLAGS) \
$(ASSERT_CFLAGS) \
$(RESERVED_CFLAGS) \
$(MONITOR_CFLAGS) \
- $(MODEL_CFLAGS)
+ $(MODEL_CFLAGS) \
+ $(STDIO_CFLAGS) \
+ $(TERMIO_CFLAGS) \
+ $(DEVZERO_CFLAGS)
STD_CFLAGS = $(CFLAGS) $(INLINE_CFLAGS) $(CONFIG_CFLAGS) $(WARNING_CFLAGS) $(SIM_CFLAGS) $(HDEFINES) $(TDEFINES) $(INCLUDES)
NOWARN_CFLAGS = $(CFLAGS) $(INLINE_CFLAGS) $(CONFIG_CFLAGS) $(SIM_CFLAGS) $(HDEFINES) $(TDEFINES) $(INCLUDES)
+BUILD_CFLAGS = -g -O $(INCLUDES) $(WARNING_CFLAGS)
+
+BUILD_LDFLAGS =
CONFIG_FILE = @sim_config@
IGEN_OPCODE_RULES = @sim_opcode@
+IGEN_DECODE_MECHANISM = @sim_decode_mechanism@
IGEN_DUPLICATE = @sim_dup@
+IGEN_JUMP = @sim_jump@
IGEN_FILTER = @sim_filter@
IGEN_ICACHE = @sim_icache@
+IGEN_SMP = @sim_igen_smp@
+IGEN_LINE_NR = @sim_line_nr@
DGEN_FLAGS = @sim_switch@
HDEFINES = @HDEFINES@
TDEFINES =
-IGEN_FLAGS = $(IGEN_DUPLICATE) $(IGEN_FILTER) $(IGEN_ICACHE)
+IGEN_FLAGS = \
+ $(IGEN_DECODE_MECHANISM) \
+ $(IGEN_DUPLICATE) \
+ $(IGEN_JUMP) \
+ $(IGEN_FILTER) \
+ $(IGEN_ICACHE) \
+ $(IGEN_SMP) \
+ $(IGEN_LINE_NR)
.NOEXPORT:
MAKEOVERRIDES=
@@ -166,13 +187,13 @@ CPU_H = \
cpu.h \
$(BASICS_H) \
$(REGISTERS_H) \
+ $(IDECODE_H) \
device.h \
corefile.h \
vm.h \
events.h \
interrupts.h \
psim.h \
- icache.h \
itable.h \
mon.h \
model.h
@@ -180,12 +201,15 @@ CPU_H = \
DEVICE_TABLE_H = \
$(BASICS_H) \
device_table.h \
- device.h
+ device.h \
+ tree.h \
+ hw.h
EMUL_GENERIC_H = \
$(CPU_H) \
$(IDECODE_H) \
emul_generic.h \
+ tree.h \
os_emul.h
@@ -194,19 +218,25 @@ INLINE = \
inline.c
BUILT_SRC_WO_CONFIG = \
- icache.h \
+ icache.h icache.c \
+ support.h support.c \
idecode.h idecode.c \
semantics.h semantics.c \
itable.h itable.c \
spreg.h spreg.c \
- model.h model.c
+ model.h model.c \
+ support.h support.c \
+ pk.h \
+ hw.h hw.c \
+ filter_host.c \
+ @sim_targ_vals@
BUILT_SRC = \
$(BUILT_SRC_WO_CONFIG) \
config.h \
ppc-config.h
-LIB_SRC = \
+LIB_INLINE_SRC = \
psim.c \
bits.c \
debug.c \
@@ -218,19 +248,21 @@ LIB_SRC = \
corefile.c \
events.c \
os_emul.c \
- emul_generic.c \
- emul_netbsd.c \
- emul_chirp.c \
- emul_bugapi.c \
registers.c \
cpu.c \
interrupts.c \
device.c \
+ tree.c \
device_table.c \
cap.c \
mon.c \
options.c
+LIB_SRC = \
+ $(PACKAGE_SRC) \
+ $(HW_SRC) \
+ $(LIB_INLINE_SRC)
+
MAIN_SRC = \
main.c \
sim_calls.c
@@ -245,9 +277,10 @@ LIB_OBJ = \
sim-endian.o \
os_emul.o \
emul_generic.o \
- emul_netbsd.o \
- emul_chirp.o \
emul_bugapi.o \
+ emul_chirp.o \
+ emul_netbsd.o \
+ emul_unix.o \
registers.o \
vm.o \
corefile.o \
@@ -258,16 +291,27 @@ LIB_OBJ = \
events.o \
cap.o \
device.o \
+ tree.o \
device_table.o \
itable.o \
mon.o \
+ icache.o \
semantics.o \
idecode.o \
+ support.o \
psim.o \
+ $(PACKAGE_OBJ) \
+ $(HW_OBJ) \
options.o
-GDB_OBJ = sim_calls.o
+GDB_OBJ = sim_calls.o @sim_callback@
+
+HW_SRC = @sim_hw_src@
+HW_OBJ = @sim_hw_obj@
+
+PACKAGE_SRC = @sim_pk_src@
+PACKAGE_OBJ = @sim_pk_obj@
psim: $(TARGETLIB) main.o $(LIBIBERTY_LIB) $(BFD_LIB) $(LIBS)
@@ -277,14 +321,12 @@ run: psim
rm -f run
ln psim run
-$(TARGETLIB): tmp-igen tmp-dgen $(LIB_OBJ) $(GDB_OBJ)
+$(TARGETLIB): tmp-igen tmp-dgen tmp-hw tmp-pk tmp-defines $(LIB_OBJ) $(GDB_OBJ)
rm -f $(TARGETLIB)
$(AR) $(AR_FLAGS) $(TARGETLIB) $(LIB_OBJ) $(GDB_OBJ)
$(RANLIB) $(TARGETLIB)
-# Given that inlines are turned on now, rebuild psim whenever
-# anything changes.
-psim.o: psim.c psim.h $(CPU_H) $(IDECODE_H) $(INLINE) $(LIB_SRC) $(BUILT_SRC)
+psim.o: psim.c psim.h tree.h $(CPU_H) $(IDECODE_H)
bits.o: bits.c $(BASICS_H)
@@ -293,12 +335,13 @@ filter_filename.o: filter_filename.c filter_filename.h config.h ppc-config.h
sim-endian.o: sim-endian.c sim-endian-n.h $(BASICS_H)
-os_emul.o: os_emul.c emul_netbsd.h emul_chirp.h emul_bugapi.h $(EMUL_GENERIC_H)
+os_emul.o: os_emul.c emul_netbsd.h emul_unix.h emul_chirp.h emul_bugapi.h $(EMUL_GENERIC_H)
emul_generic.o: emul_generic.c $(EMUL_GENERIC_H)
-emul_netbsd.o: emul_netbsd.c emul_netbsd.h $(EMUL_GENERIC_H)
-emul_chirp.o: emul_chirp.c emul_chirp.h $(EMUL_GENERIC_H)
emul_bugapi.o: emul_bugapi.c emul_bugapi.h $(EMUL_GENERIC_H)
+emul_chirp.o: emul_chirp.c emul_chirp.h $(EMUL_GENERIC_H)
+emul_netbsd.o: emul_netbsd.c emul_netbsd.h $(EMUL_GENERIC_H)
+emul_unix.o: emul_unix.c emul_unix.h $(EMUL_GENERIC_H)
registers.o: registers.c $(REGISTERS_H) $(BASICS_H)
@@ -306,15 +349,16 @@ cpu.o: cpu.c $(CPU_H) $(IDECODE_H)
interrupts.o: interrupts.c $(CPU_H) $(IDECODE_H) os_emul.h
-idecode.o: idecode.c $(CPU_H) $(IDECODE_H) semantics.h
+# Given that inlines are turned on now, rebuild idecode whenever
+# anything changes.
+idecode.o: idecode.c $(CPU_H) $(IDECODE_H) semantics.h $(LIB_INLINE_SRC) $(BUILT_SRC)
$(CC) -c $(NOWARN_CFLAGS) $<
# double.o: double.c dp-bit.c
-vm.o: vm.c vm.h vm_n.h $(BASICS_H) $(REGISTERS_H) \
- device.h corefile.h interrupts.h itable.h mon.h
+vm.o: vm.c vm.h vm_n.h $(CPU_H)
-corefile.o: corefile.c corefile.h corefile-n.h $(BASICS_H) device.h
+corefile.o: corefile.c corefile.h corefile-n.h $(BASICS_H) $(DEVICE_TABLE_H)
model.o: model.c $(CPU_H)
@@ -322,27 +366,64 @@ events.o: events.c events.h $(BASICS_H)
sim_calls.o: sim_calls.c $(PSIM_H) itable.h ../../gdb/tm.h options.h
-spreg.o: spreg.h spreg.c $(BASICS_H)
+spreg.o: spreg.c spreg.h spreg.c $(BASICS_H)
main.o: main.c $(PSIM_H) itable.h options.h
device.o: device.c $(DEVICE_TABLE_H) cap.h
-device_table.o: device_table.c $(DEVICE_TABLE_H) events.h
+tree.o: tree.c tree.h device.h $(DEVICE_TABLE_H)
+
+device_table.o: device_table.c $(DEVICE_TABLE_H) events.h hw.c
cap.o: cap.c cap.h $(BASICS_H)
semantics.o: semantics.c semantics.h $(CPU_H) $(IDECODE_H)
$(CC) -c $(NOWARN_CFLAGS) $<
+icache.o: icache.c icache.h $(IDECODE_H) $(CPU_H)
+ $(CC) -c $(NOWARN_CFLAGS) $<
+
+support.o: support.c support.h $(IDECODE_H) $(CPU_H)
+
itable.o: itable.c itable.h
mon.o: mon.c $(CPU_H)
+# GDB after 4.16 expects the default_callback structure to be setup.
+# As a kludge, build the common stuff here for now.
+gentmap: ../common/gentmap.c Makefile targ-vals.def
+ $(CC_FOR_BUILD) $(BUILD_FLAGS) -I. -I../common -I$(srcdir)/../common -o gentmap $< $(BUILD_LIBS)
+
+targ-vals.def: $(srcdir)/../common/nltvals.def
+ rm -f targ-vals.def tmp-def
+ cat $(srcdir)/../common/nltvals.def > tmp-vals.def
+ $(srcdir)/../../move-if-change tmp-vals.def targ-vals.def
+
+targ-vals.h: Makefile gentmap $(srcdir)/../../move-if-change
+ rm -f tmp-vals.h
+ ./gentmap -h > tmp-vals.h
+ $(srcdir)/../../move-if-change tmp-vals.h targ-vals.h
+
+targ-map.c: Makefile gentmap $(srcdir)/../../move-if-change
+ rm -f tmp-map.c
+ ./gentmap -c > tmp-map.c
+ $(srcdir)/../../move-if-change tmp-map.c targ-map.c
+
+callback.o: ../common/callback.c targ-vals.h config.h
+ $(CC) -c $(STD_CFLAGS) -DHAVE_CONFIG_H $<
+
+targ-map.o: targ-map.c targ-vals.h
+
# Rebuild options whenever something changes so the date/time is up to date.
-options.o: options.c $(BASICS_H) $(CPU_H) $(IDECODE_H) $(INLINE) $(LIB_SRC) $(BUILT_SRC) config.status Makefile
+options.o: options.c $(BASICS_H) $(CPU_H) $(IDECODE_H) $(INLINE) $(LIB_SRC) $(BUILT_SRC) config.status Makefile defines.h
$(CC) -c $(STD_CFLAGS) '-DOPCODE_RULES="@sim_opcode@"' '-DIGEN_FLAGS="$(IGEN_FLAGS)"' '-DDGEN_FLAGS="$(DGEN_FLAGS)"' $<
+tmp-defines: config.h Makefile
+ sed -n -e '/^#define HAVE_/s/ 1$$/",/' -e '/^#define HAVE_/s//"HAVE_/p' < config.h > tmp-defines.h
+ $(srcdir)/../../move-if-change tmp-defines.h defines.h
+ touch tmp-defines
+
#
# Rules to create the built c source code files
#
@@ -354,28 +435,32 @@ ppc-config.h: $(CONFIG_FILE)
tmp-dgen: dgen ppc-spr-table $(srcdir)/../../move-if-change
./dgen $(DGEN_FLAGS) \
-r $(srcdir)/ppc-spr-table \
- -n spreg.h -P tmp-spreg.h \
- -n spreg.c -p tmp-spreg.c
+ -n spreg.h -hp tmp-spreg.h \
+ -n spreg.c -p tmp-spreg.c
$(srcdir)/../../move-if-change tmp-spreg.h spreg.h
$(srcdir)/../../move-if-change tmp-spreg.c spreg.c
touch tmp-dgen
-tmp-igen: igen ppc-instructions $(IGEN_OPCODE_RULES) ppc-cache-rules $(srcdir)/../../move-if-change
+tmp-igen: igen ppc-instructions $(IGEN_OPCODE_RULES) ppc-cache-rules $(srcdir)/../../move-if-change tmp-ld-decode tmp-ld-cache tmp-ld-insn tmp-filter
./igen $(IGEN_FLAGS) \
-o $(srcdir)/$(IGEN_OPCODE_RULES) \
-k $(srcdir)/ppc-cache-rules \
-i $(srcdir)/ppc-instructions \
- -n icache.h -C tmp-icache.h \
- -n semantics.h -S tmp-semantics.h \
- -n semantics.c -s tmp-semantics.c \
- -n idecode.h -D tmp-idecode.h \
- -n idecode.c -d tmp-idecode.c \
- -n itable.h -T tmp-itable.h \
- -n itable.c -t tmp-itable.c \
- -n model.h -M tmp-model.h \
- -n model.c -m tmp-model.c
+ -n icache.h -hc tmp-icache.h \
+ -n icache.c -c tmp-icache.c \
+ -n semantics.h -hs tmp-semantics.h \
+ -n semantics.c -s tmp-semantics.c \
+ -n idecode.h -hd tmp-idecode.h \
+ -n idecode.c -d tmp-idecode.c \
+ -n itable.h -ht tmp-itable.h \
+ -n itable.c -t tmp-itable.c \
+ -n model.h -hm tmp-model.h \
+ -n model.c -m tmp-model.c \
+ -n support.h -hf tmp-support.h \
+ -n support.c -f tmp-support.c
$(srcdir)/../../move-if-change tmp-icache.h icache.h
+ $(srcdir)/../../move-if-change tmp-icache.c icache.c
$(srcdir)/../../move-if-change tmp-idecode.h idecode.h
$(srcdir)/../../move-if-change tmp-idecode.c idecode.c
$(srcdir)/../../move-if-change tmp-semantics.h semantics.h
@@ -384,26 +469,157 @@ tmp-igen: igen ppc-instructions $(IGEN_OPCODE_RULES) ppc-cache-rules $(srcdir)/.
$(srcdir)/../../move-if-change tmp-itable.c itable.c
$(srcdir)/../../move-if-change tmp-model.h model.h
$(srcdir)/../../move-if-change tmp-model.c model.c
+ $(srcdir)/../../move-if-change tmp-support.h support.h
+ $(srcdir)/../../move-if-change tmp-support.c support.c
touch tmp-igen
# NOTE: Some versions of make don't handle files created as side-effects
# uncomment the below if that is the case.
$(TARGETLIB): tmp-igen tmp-dgen
-itable.h itable.c icache.h idecode.h idecode.c semantics.h semantics.c model.h model.c: tmp-igen
+itable.h itable.c icache.h icache.c idecode.h idecode.c semantics.h semantics.c model.h model.c support.h support.c: tmp-igen
spreg.h spreg.c: tmp-dgen
-dgen: dgen.o table.o lf.o misc.o filter_filename.o
- $(CC_FOR_BUILD) $(CFLAGS) $(SIM_CFLAGS) $(LDFLAGS) -o dgen dgen.o table.o lf.o misc.o filter_filename.o $(LIBIBERTY_LIB) $(LIBS)
+dgen: dgen.o table.o lf.o misc.o filter_host.o
+ $(CC_FOR_BUILD) $(BUILD_CFLAGS) -o dgen dgen.o table.o lf.o misc.o filter_host.o $(BUILD_LIBS)
+
+igen: igen.o table.o lf.o misc.o filter_host.o ld-decode.o ld-cache.o filter.o ld-insn.o gen-model.o gen-itable.o gen-icache.o gen-semantics.o gen-idecode.o gen-support.o
+ $(CC_FOR_BUILD) $(BUILD_CFLAGS) $(BUILD_LDFLAGS) -o igen igen.o table.o lf.o misc.o filter_host.o ld-decode.o ld-cache.o filter.o ld-insn.o gen-model.o gen-itable.o gen-icache.o gen-semantics.o gen-idecode.o gen-support.o $(BUILD_LIBS)
+
+filter_host.c: filter_filename.c
+ cat $(srcdir)/filter_filename.c > filter_host.c
+
+filter_host.o: filter_host.c filter_filename.h config.h ppc-config.h
+ $(CC_FOR_BUILD) $(BUILD_CFLAGS) -c filter_host.c
+
+table.o: table.c misc.h filter_filename.h lf.h table.h
+ $(CC_FOR_BUILD) $(BUILD_CFLAGS) -c $(srcdir)/table.c
+
+lf.o: lf.c misc.h filter_filename.h lf.h
+ $(CC_FOR_BUILD) $(BUILD_CFLAGS) -c $(srcdir)/lf.c
+
+filter.o: filter.c misc.h lf.h table.h filter.h
+ $(CC_FOR_BUILD) $(BUILD_CFLAGS) -c $(srcdir)/filter.c
+tmp-filter: filter.c misc.h misc.o
+ $(CC_FOR_BUILD) $(BUILD_CFLAGS) $(BUILD_LDFLAGS) -o tmp-filter -DMAIN $(srcdir)/filter.c misc.o $(BUILD_LIBS)
+
+ld-decode.o: ld-decode.c misc.h lf.h table.h ld-decode.h
+ $(CC_FOR_BUILD) $(BUILD_CFLAGS) -c $(srcdir)/ld-decode.c
+tmp-ld-decode: ld-decode.o misc.o lf.o table.o filter_host.o
+ $(CC_FOR_BUILD) $(BUILD_CFLAGS) $(BUILD_LDFLAGS) -o tmp-ld-decode -DMAIN $(srcdir)/ld-decode.c misc.o lf.o table.o filter_host.o $(BUILD_LIBS)
+
+ld-cache.o: ld-cache.c misc.h lf.h table.h ld-cache.h
+ $(CC_FOR_BUILD) $(BUILD_CFLAGS) -c $(srcdir)/ld-cache.c
+tmp-ld-cache: ld-cache.o misc.o lf.o table.o filter_host.o
+ $(CC_FOR_BUILD) $(BUILD_CFLAGS) $(BUILD_LDFLAGS) -o tmp-ld-cache -DMAIN $(srcdir)/ld-cache.c misc.o lf.o table.o filter_host.o $(BUILD_LIBS)
+
+ld-insn.o: ld-insn.c misc.h lf.h table.h ld-insn.h ld-decode.h igen.h
+ $(CC_FOR_BUILD) $(BUILD_CFLAGS) -c $(srcdir)/ld-insn.c
+tmp-ld-insn: ld-insn.o misc.o lf.o table.o ld-decode.o filter_host.o filter.o
+ $(CC_FOR_BUILD) $(BUILD_CFLAGS) $(BUILD_LDFLAGS) -o tmp-ld-insn -DMAIN $(srcdir)/ld-insn.c misc.o lf.o table.o ld-decode.o filter_host.o filter.o $(BUILD_LIBS)
+
+gen-model.o: gen-model.c misc.h lf.h table.h gen-model.h ld-decode.h igen.h ld-insn.h
+ $(CC_FOR_BUILD) $(BUILD_CFLAGS) -c $(srcdir)/gen-model.c
+
+gen-itable.o: gen-itable.c misc.h lf.h table.h gen-itable.h ld-decode.h igen.h ld-insn.h igen.h
+ $(CC_FOR_BUILD) $(BUILD_CFLAGS) -c $(srcdir)/gen-itable.c
+
+gen-icache.o: gen-icache.c misc.h lf.h table.h gen-icache.h ld-decode.h igen.h ld-insn.h gen-semantics.h gen-idecode.h
+ $(CC_FOR_BUILD) $(BUILD_CFLAGS) -c $(srcdir)/gen-icache.c
+
+gen-semantics.o: gen-semantics.c misc.h lf.h table.h gen-semantics.h ld-decode.h igen.h ld-insn.h
+ $(CC_FOR_BUILD) $(BUILD_CFLAGS) -c $(srcdir)/gen-semantics.c
+
+gen-idecode.o: gen-idecode.c misc.h lf.h table.h gen-idecode.h gen-icache.h gen-semantics.h ld-decode.h igen.h ld-insn.h
+ $(CC_FOR_BUILD) $(BUILD_CFLAGS) -c $(srcdir)/gen-idecode.c
+
+gen-support.o: gen-support.c misc.h lf.h table.h gen-support.h ld-decode.h igen.h ld-insn.h
+ $(CC_FOR_BUILD) $(BUILD_CFLAGS) -c $(srcdir)/gen-support.c
+
+dgen.o: dgen.c misc.h filter_filename.h lf.h table.h
+ $(CC_FOR_BUILD) $(BUILD_CFLAGS) -c $(srcdir)/dgen.c
+
+igen.o: igen.c misc.h filter_filename.h lf.h table.h ld-decode.h ld-cache.h ld-insn.h filter.h gen-model.h gen-itable.h gen-icache.h gen-idecode.h gen-semantics.h gen-support.h igen.h
+ $(CC_FOR_BUILD) $(BUILD_CFLAGS) -c $(srcdir)/igen.c
+
+misc.o: misc.c misc.h filter_filename.h
+ $(CC_FOR_BUILD) $(BUILD_CFLAGS) -c $(srcdir)/misc.c
+
+
+
+# real hardware
+tmp-hw: Makefile $(HW_SRC) $(srcdir)/../../move-if-change
+ # The first for loop is to remove duplicates.
+ f=""; \
+ for i in $(HW_SRC) ; do \
+ case " $$f " in \
+ *" $$i "*) ;; \
+ *) f="$$f $$i" ;; \
+ esac ; \
+ done ; \
+ for hw in $$f ; do echo $$hw ; done \
+ | sed -e 's/^.*\(hw_.*\)\.c/\1/' \
+ -e 's/^/extern const device_descriptor /' \
+ -e 's/$$/_device_descriptor\[\];/' \
+ > tmp-hw.h
+ f=""; \
+ for i in $(HW_SRC) ; do \
+ case " $$f " in \
+ *" $$i "*) ;; \
+ *) f="$$f $$i" ;; \
+ esac ; \
+ done ; \
+ for hw in $$f ; do echo $$hw ; done \
+ | sed -e 's/^.*\(hw_.*\)\.c/\1/' \
+ -e 's/^/ /' \
+ -e 's/$$/_device_descriptor,/' \
+ > tmp-hw.c
+ $(srcdir)/../../move-if-change tmp-hw.h hw.h
+ $(srcdir)/../../move-if-change tmp-hw.c hw.c
+ touch tmp-hw
+
+hw_cpu.o: hw_cpu.c $(DEVICE_TABLE_H)
+hw_core.o: hw_core.c $(DEVICE_TABLE_H)
+hw_disk.o: hw_disk.c $(DEVICE_TABLE_H) pk.h
+hw_glue.o: hw_glue.c $(DEVICE_TABLE_H)
+hw_htab.o: hw_htab.c $(DEVICE_TABLE_H)
+hw_ide.o: hw_ide.c $(DEVICE_TABLE_H)
+hw_init.o: hw_init.c $(DEVICE_TABLE_H)
+hw_iobus.o: hw_iobus.c $(DEVICE_TABLE_H)
+hw_memory.o: hw_memory.c $(DEVICE_TABLE_H)
+hw_nvram.o: hw_nvram.c $(DEVICE_TABLE_H)
+hw_opic.o: hw_opic.c $(DEVICE_TABLE_H)
+hw_pal.o: hw_pal.c $(DEVICE_TABLE_H)
+hw_phb.o: hw_phb.c $(DEVICE_TABLE_H) hw_phb.h
+hw_register.o: hw_register.c $(DEVICE_TABLE_H)
+hw_trace.o: hw_trace.c $(DEVICE_TABLE_H)
+hw_vm.o: hw_vm.c $(DEVICE_TABLE_H)
+# ignore this line, it stops make from getting confused
+
+
+
+# real packages
+tmp-pk: Makefile $(PACKAGE_SRC) $(srcdir)/../../move-if-change
+ # The first for loop is to remove duplicates.
+ f=""; \
+ for i in $(PACKAGE_SRC) ; do \
+ case " $$f " in \
+ *" $$i "*) ;; \
+ *) f="$$f $$i" ;; \
+ esac ; \
+ done ; \
+ for pk in $$f ; do echo $$pk ; done \
+ | sed -e 's/^.*pk_\(.*\)\.c/\1/' \
+ -e 's/^/extern package_create_instance_callback pk_/' \
+ -e 's/$$/_create_instance;/' \
+ > tmp-pk.h
+ $(srcdir)/../../move-if-change tmp-pk.h pk.h
+ touch tmp-pk
+
+pk_disklabel.o: pk.h $(DEVICE_TABLE_H)
+# ignore this line, it stops make from getting confused
-igen: igen.o table.o lf.o misc.o filter_filename.o
- $(CC_FOR_BUILD) $(CFLAGS) $(SIM_CFLAGS) $(LDFLAGS) -o igen igen.o table.o lf.o misc.o filter_filename.o $(LIBIBERTY_LIB) $(LIBS)
-table.o: misc.h filter_filename.h lf.h table.h
-lf.o: misc.h filter_filename.h lf.h
-dgen.o igen.o: misc.h filter_filename.h lf.h table.h
-misc.o: misc.h filter_filename.h
-# With out this #, make thinks that misc.o doesn't have a rule
tags etags: TAGS
@@ -411,10 +627,10 @@ TAGS: $(BUILT_SRC)
etags $(srcdir)/*.h $(srcdir)/*.c $(BUILT_SRC)
clean mostlyclean:
- rm -f tmp-* *.[oasi] core psim run igen dgen config.log $(BUILT_SRC_WO_CONFIG)
+ rm -f tmp-* *.[oasi] core psim run igen dgen $(BUILT_SRC_WO_CONFIG) gentmap
distclean realclean: clean
- rm -f TAGS Makefile config.cache config.status config.h stamp-h
+ rm -f TAGS Makefile config.cache config.status config.h defines.h stamp-h config.log
maintainer-clean: distclean
rm -f *~ *.log ppc-config.h core *.core
@@ -429,6 +645,9 @@ stamp-h: config.in config.status
config.status: configure
$(SHELL) ./config.status --recheck
-install:
- $(INSTALL_XFORM) run $(bindir)/run
+install: installdirs
+ n=`echo run | sed '$(program_transform_name)'`; \
+ $(INSTALL_PROGRAM) run $(bindir)/$$n
+installdirs:
+ $(SHELL) $(srcdir)/mkinstalldirs $(bindir)
diff --git a/gnu/dist/sim/ppc/README b/gnu/dist/sim/ppc/README
index 196476da2ce..ff3fbd2b349 100644
--- a/gnu/dist/sim/ppc/README
+++ b/gnu/dist/sim/ppc/README
@@ -1,6 +1,6 @@
- PSIM 1.0.1 - Model of the PowerPC Environment
+ PSIM 1.0.1 - Model of the PowerPC Environments
Copyright (C) 1994-1996, Andrew Cagney <cagney@highland.com.au>.
diff --git a/gnu/dist/sim/ppc/basics.h b/gnu/dist/sim/ppc/basics.h
index 7dc05af31f5..314986f06e5 100644
--- a/gnu/dist/sim/ppc/basics.h
+++ b/gnu/dist/sim/ppc/basics.h
@@ -1,6 +1,6 @@
/* This file is part of the program psim.
- Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
+ 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
@@ -47,6 +47,8 @@ typedef struct _cpu cpu;
typedef struct _psim psim;
typedef struct _device device;
typedef struct _device_instance device_instance;
+typedef struct _event_queue event_queue;
+typedef struct _event_entry_tag *event_entry_tag;
/* many things are moving data between the host and target */
@@ -56,6 +58,7 @@ typedef enum {
raw_transfer,
} transfer_mode;
+
/* possible exit statuses */
typedef enum {
@@ -63,6 +66,24 @@ typedef enum {
} stop_reason;
+/* disposition of an object when things are next restarted */
+
+typedef enum {
+ permenant_object,
+ tempoary_object,
+} object_disposition;
+
+
+/* directions */
+
+typedef enum {
+ bidirect_port,
+ input_port,
+ output_port,
+} port_direction;
+
+
+
/* Basic configuration */
#include "config.h"
@@ -70,11 +91,13 @@ typedef enum {
#include "inline.h"
-/* Basic host dependant mess - hopefully <stdio.h> will bring
- potential conflicts out in the open */
+/* Basic host dependant mess - hopefully <stdio.h> + <stdarg.h> will
+ bring potential conflicts out in the open */
+#include <stdarg.h>
#include <stdio.h>
+
#ifndef NORETURN
#define NORETURN
#endif
@@ -83,13 +106,23 @@ typedef enum {
#define NULL 0
#endif
-#if !defined (__attribute__) && (!defined(__GNUC__) || __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7))
+#if !defined (__attribute__)
+#if (!defined(__GNUC__) \
+ || (__GNUC__ < 2) \
+ || (__GNUC__ == 2 && __GNUC_MINOR__ < 6))
#define __attribute__(arg)
#endif
+#endif
#if !defined (UNUSED)
+#if (!defined(__GNUC__) \
+ || (__GNUC__ < 2) \
+ || (__GNUC__ == 2 && __GNUC_MINOR__ < 7))
+#define UNUSED
+#else
#define UNUSED __attribute__((__unused__))
#endif
+#endif
/* Basic definitions - ordered so that nothing calls what comes after
diff --git a/gnu/dist/sim/ppc/bits.c b/gnu/dist/sim/ppc/bits.c
index 4f640739175..00bba518aac 100644
--- a/gnu/dist/sim/ppc/bits.c
+++ b/gnu/dist/sim/ppc/bits.c
@@ -61,7 +61,7 @@ EXTRACTED(unsigned_word word,
unsigned stop)
{
ASSERT(start <= stop);
-#if (WITH_64BITS_TARGET)
+#if (WITH_TARGET_WORD_BITSIZE == 64)
return _EXTRACTEDn(64, word, start, stop);
#else
if (stop < 32)
@@ -74,6 +74,25 @@ EXTRACTED(unsigned_word word,
INLINE_BITS\
+(unsigned_word)
+INSERTED(unsigned_word word,
+ unsigned start,
+ unsigned stop)
+{
+ ASSERT(start <= stop);
+#if (WITH_TARGET_WORD_BITSIZE == 64)
+ return _INSERTEDn(64, word, start, stop);
+#else
+ if (stop < 32)
+ return 0;
+ else
+ return ((word & MASK(start+(63-stop), 63))
+ << (63 - stop));
+#endif
+}
+
+
+INLINE_BITS\
(unsigned32)
ROTL32(unsigned32 val,
long shift)
diff --git a/gnu/dist/sim/ppc/bits.h b/gnu/dist/sim/ppc/bits.h
index 7dd81662cb5..06898e07e9b 100644
--- a/gnu/dist/sim/ppc/bits.h
+++ b/gnu/dist/sim/ppc/bits.h
@@ -83,6 +83,7 @@
#define BIT4(POS) (1 << _MAKE_SHIFT(4, POS))
#define BIT5(POS) (1 << _MAKE_SHIFT(5, POS))
+#define BIT8(POS) (1 << _MAKE_SHIFT(8, POS))
#define BIT10(POS) (1 << _MAKE_SHIFT(10, POS))
#define BIT32(POS) _BITn(32, POS)
#define BIT64(POS) _BITn(64, POS)
@@ -189,9 +190,11 @@ INLINE_BITS\
#define INSERTED32(WORD, START, STOP) _INSERTEDn(32, WORD, START, STOP)
#define INSERTED64(WORD, START, STOP) _INSERTEDn(64, WORD, START, STOP)
-#define INSERTED(WORD, START, STOP) \
-_INSERTEDn(WITH_TARGET_WORD_BITSIZE, WORD, START, STOP)
-
+INLINE_BITS\
+(unsigned_word) INSERTED
+(unsigned_word val,
+ unsigned start,
+ unsigned stop);
/* depending on MODE return a 64bit or 32bit (sign extended) value */
diff --git a/gnu/dist/sim/ppc/cap.c b/gnu/dist/sim/ppc/cap.c
index 2eb7ae37abe..a3be304c81f 100644
--- a/gnu/dist/sim/ppc/cap.c
+++ b/gnu/dist/sim/ppc/cap.c
@@ -1,6 +1,6 @@
/* This file is part of the program psim.
- Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
+ 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
@@ -26,7 +26,7 @@
typedef struct _cap_mapping cap_mapping;
struct _cap_mapping {
- unsigned32 external;
+ unsigned_cell external;
void *internal;
cap_mapping *next;
};
@@ -45,22 +45,31 @@ cap_create(const char *key)
INLINE_CAP\
(void)
-cap_init(cap *map)
+cap_init(cap *db)
{
- cap_mapping *current_mapping = map->mappings;
- while (current_mapping != NULL) {
- cap_mapping *tbd = current_mapping;
- current_mapping = tbd->next;
- zfree(tbd);
+ cap_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("cap: cap database possibly corrupt");
+ current_map = current_map->next;
+ }
+ ASSERT(current_map->next == NULL);
+ if (current_map->external != 1)
+ error("cap: cap database possibly currupt");
+ }
+ else {
+ db->nr_mappings = 0;
}
- map->nr_mappings = 0;
- map->mappings = (cap_mapping*)0;
}
INLINE_CAP\
(void *)
cap_internal(cap *db,
- signed32 external)
+ signed_cell external)
{
cap_mapping *current_map = db->mappings;
while (current_map != NULL) {
@@ -72,7 +81,7 @@ cap_internal(cap *db,
}
INLINE_CAP\
-(signed32)
+(signed_cell)
cap_external(cap *db,
void *internal)
{
@@ -82,13 +91,44 @@ cap_external(cap *db,
return current_map->external;
current_map = current_map->next;
}
- current_map = ZALLOC(cap_mapping);
- current_map->next = db->mappings;
- current_map->internal = internal;
- db->nr_mappings += 1;
- current_map->external = db->nr_mappings;
- db->mappings = current_map;
- return current_map->external;
+ return 0;
+}
+
+INLINE_CAP\
+(void)
+cap_add(cap *db,
+ void *internal)
+{
+ if (cap_external(db, internal) != 0) {
+ error("cap: attempting to add an object already in the data base");
+ }
+ else {
+ /* insert at the front making things in decending order */
+ cap_mapping *new_map = ZALLOC(cap_mapping);
+ new_map->next = db->mappings;
+ new_map->internal = internal;
+ db->nr_mappings += 1;
+ new_map->external = db->nr_mappings;
+ db->mappings = new_map;
+ }
+}
+
+INLINE_CAP\
+(void)
+cap_remove(cap *db,
+ void *internal)
+{
+ cap_mapping **current_map = &db->mappings;
+ while (*current_map != NULL) {
+ if ((*current_map)->internal == internal) {
+ cap_mapping *delete = *current_map;
+ *current_map = delete->next;
+ zfree(delete);
+ return;
+ }
+ current_map = &(*current_map)->next;
+ }
+ error("cap: attempt to remove nonexistant internal object");
}
#endif
diff --git a/gnu/dist/sim/ppc/cap.h b/gnu/dist/sim/ppc/cap.h
index 3c121525d65..6c91752af8d 100644
--- a/gnu/dist/sim/ppc/cap.h
+++ b/gnu/dist/sim/ppc/cap.h
@@ -1,6 +1,6 @@
/* This file is part of the program psim.
- Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
+ 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
@@ -38,13 +38,23 @@ INLINE_CAP\
(cap *db);
INLINE_CAP\
-(signed32) cap_external
+(signed_cell) cap_external
(cap *db,
void *internal);
INLINE_CAP\
(void *) cap_internal
(cap *db,
- signed32 external);
+ signed_cell external);
+
+INLINE_CAP\
+(void) cap_add
+(cap *db,
+ void *internal);
+
+INLINE_CAP\
+(void) cap_remove
+(cap *db,
+ void *internal);
#endif
diff --git a/gnu/dist/sim/ppc/config.in b/gnu/dist/sim/ppc/config.in
index 434f0ff8344..34b4fc18bdd 100644
--- a/gnu/dist/sim/ppc/config.in
+++ b/gnu/dist/sim/ppc/config.in
@@ -1,18 +1,209 @@
/* config.in. Generated automatically from configure.in by autoheader. */
-#ifndef CONFIG_H
-#define CONFIG_H
+/* Define to the type of elements in the array set by `getgroups'.
+ Usually this is either `int' or `gid_t'. */
+#undef GETGROUPS_T
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+#undef gid_t
+
+/* Define if your struct stat has st_blksize. */
+#undef HAVE_ST_BLKSIZE
+
+/* Define if your struct stat has st_blocks. */
+#undef HAVE_ST_BLOCKS
+
+/* Define if your struct stat has st_rdev. */
+#undef HAVE_ST_RDEV
+
+/* Define if your struct tm has tm_zone. */
+#undef HAVE_TM_ZONE
+
+/* Define if you don't have tm_zone but do have the external array
+ tzname. */
+#undef HAVE_TZNAME
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+#undef mode_t
+
+/* Define to `long' if <sys/types.h> doesn't define. */
+#undef off_t
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+#undef pid_t
+
+/* 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
+
+/* Define if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Define if your <sys/time.h> declares struct tm. */
+#undef TM_IN_SYS_TIME
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+#undef uid_t
/* Define if your processor stores words with the most significant
byte first (like Motorola and SPARC, unlike Intel and VAX). */
#undef WORDS_BIGENDIAN
+/* Define if you have the access function. */
+#undef HAVE_ACCESS
+
+/* Define if you have the cfgetispeed function. */
+#undef HAVE_CFGETISPEED
+
+/* Define if you have the cfgetospeed function. */
+#undef HAVE_CFGETOSPEED
+
+/* Define if you have the cfsetispeed function. */
+#undef HAVE_CFSETISPEED
+
+/* Define if you have the cfsetospeed function. */
+#undef HAVE_CFSETOSPEED
+
+/* Define if you have the chdir function. */
+#undef HAVE_CHDIR
+
+/* Define if you have the chmod function. */
+#undef HAVE_CHMOD
+
+/* Define if you have the chown function. */
+#undef HAVE_CHOWN
+
+/* Define if you have the dup function. */
+#undef HAVE_DUP
+
+/* Define if you have the dup2 function. */
+#undef HAVE_DUP2
+
+/* Define if you have the fchmod function. */
+#undef HAVE_FCHMOD
+
+/* Define if you have the fchown function. */
+#undef HAVE_FCHOWN
+
+/* Define if you have the fcntl function. */
+#undef HAVE_FCNTL
+
+/* Define if you have the fstat function. */
+#undef HAVE_FSTAT
+
+/* Define if you have the fstatfs function. */
+#undef HAVE_FSTATFS
+
+/* Define if you have the getdirentries function. */
+#undef HAVE_GETDIRENTRIES
+
+/* Define if you have the getegid function. */
+#undef HAVE_GETEGID
+
+/* Define if you have the geteuid function. */
+#undef HAVE_GETEUID
+
+/* Define if you have the getgid function. */
+#undef HAVE_GETGID
+
+/* Define if you have the getpid function. */
+#undef HAVE_GETPID
+
+/* Define if you have the getppid function. */
+#undef HAVE_GETPPID
+
/* Define if you have the getrusage function. */
#undef HAVE_GETRUSAGE
+/* Define if you have the gettimeofday function. */
+#undef HAVE_GETTIMEOFDAY
+
+/* Define if you have the getuid function. */
+#undef HAVE_GETUID
+
+/* Define if you have the ioctl function. */
+#undef HAVE_IOCTL
+
+/* Define if you have the kill function. */
+#undef HAVE_KILL
+
+/* Define if you have the link function. */
+#undef HAVE_LINK
+
+/* Define if you have the lseek function. */
+#undef HAVE_LSEEK
+
+/* Define if you have the lstat function. */
+#undef HAVE_LSTAT
+
+/* Define if you have the mkdir function. */
+#undef HAVE_MKDIR
+
+/* Define if you have the pipe function. */
+#undef HAVE_PIPE
+
+/* Define if you have the readlink function. */
+#undef HAVE_READLINK
+
+/* Define if you have the rmdir function. */
+#undef HAVE_RMDIR
+
+/* Define if you have the setregid function. */
+#undef HAVE_SETREGID
+
+/* Define if you have the setreuid function. */
+#undef HAVE_SETREUID
+
+/* Define if you have the sigprocmask function. */
+#undef HAVE_SIGPROCMASK
+
+/* Define if you have the stat function. */
+#undef HAVE_STAT
+
+/* Define if you have the symlink function. */
+#undef HAVE_SYMLINK
+
+/* Define if you have the tcdrain function. */
+#undef HAVE_TCDRAIN
+
+/* Define if you have the tcflow function. */
+#undef HAVE_TCFLOW
+
+/* Define if you have the tcflush function. */
+#undef HAVE_TCFLUSH
+
+/* Define if you have the tcgetattr function. */
+#undef HAVE_TCGETATTR
+
+/* Define if you have the tcgetpgrp function. */
+#undef HAVE_TCGETPGRP
+
+/* Define if you have the tcsendbreak function. */
+#undef HAVE_TCSENDBREAK
+
+/* Define if you have the tcsetattr function. */
+#undef HAVE_TCSETATTR
+
+/* Define if you have the tcsetpgrp function. */
+#undef HAVE_TCSETPGRP
+
+/* Define if you have the time function. */
+#undef HAVE_TIME
+
+/* Define if you have the umask function. */
+#undef HAVE_UMASK
+
+/* Define if you have the unlink function. */
+#undef HAVE_UNLINK
+
/* Define if you have the <dirent.h> header file. */
#undef HAVE_DIRENT_H
+/* Define if you have the <fcntl.h> header file. */
+#undef HAVE_FCNTL_H
+
/* Define if you have the <ndir.h> header file. */
#undef HAVE_NDIR_H
@@ -28,15 +219,30 @@
/* Define if you have the <sys/dir.h> header file. */
#undef HAVE_SYS_DIR_H
+/* Define if you have the <sys/ioctl.h> header file. */
+#undef HAVE_SYS_IOCTL_H
+
/* Define if you have the <sys/mount.h> header file. */
#undef HAVE_SYS_MOUNT_H
/* Define if you have the <sys/ndir.h> header file. */
#undef HAVE_SYS_NDIR_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/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define if you have the <sys/termio.h> header file. */
+#undef HAVE_SYS_TERMIO_H
+
+/* Define if you have the <sys/termios.h> header file. */
+#undef HAVE_SYS_TERMIOS_H
+
/* Define if you have the <sys/time.h> header file. */
#undef HAVE_SYS_TIME_H
@@ -51,5 +257,3 @@
/* Define if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
-
-#endif
diff --git a/gnu/dist/sim/ppc/configure b/gnu/dist/sim/ppc/configure
index a01429aa3b6..376895d250c 100644
--- a/gnu/dist/sim/ppc/configure
+++ b/gnu/dist/sim/ppc/configure
@@ -1,8 +1,8 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated automatically using autoconf version 2.7
-# Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc.
+# Generated automatically using autoconf version 2.12
+# 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.
@@ -12,59 +12,75 @@ ac_help=
ac_default_prefix=/usr/local
# Any additions from configure.in:
ac_help="$ac_help
- --enable-sim-cflags=opts Extra CFLAGS for use in building simulator"
+ --enable-sim-alignment=align Specify strict or nonstrict alignment."
ac_help="$ac_help
- --enable-sim-warnings=opts Extra CFLAGS for turning on compiler warnings except for idecode.o, semantics.o and psim.o"
+ --enable-sim-assert Specify whether to perform random assertions."
+ac_help="$ac_help
+ --enable-sim-bitsize=n Specify target bitsize (32 or 64)."
+ac_help="$ac_help
+ --enable-sim-bswap Use the BSWAP instruction on Intel 486s and Pentiums."
+ac_help="$ac_help
+ --enable-sim-cflags=opts Extra CFLAGS for use in building simulator"
ac_help="$ac_help
--enable-sim-config=file Override default config file"
ac_help="$ac_help
- --enable-sim-opcode=which Override default opcode lookup."
+ --enable-sim-decode-mechanism=which Specify the instruction decode mechanism."
ac_help="$ac_help
- --enable-sim-switch Use a switch instead of a table for instruction call."
+ --enable-sim-default-model=which Specify default PowerPC to model."
ac_help="$ac_help
--enable-sim-duplicate Expand (duplicate) semantic functions."
ac_help="$ac_help
+ --enable-sim-endian=endian Specify target byte endian orientation."
+ac_help="$ac_help
+ --enable-sim-env=env Specify target environment (operating, virtual, user)."
+ac_help="$ac_help
--enable-sim-filter=rule Specify filter rules."
ac_help="$ac_help
- --enable-sim-icache=size Specify instruction cache size."
+ --enable-sim-float Specify whether to use host floating point or simulate."
ac_help="$ac_help
- --enable-sim-inline=inlines Specify which functions should be inlined."
+ --enable-sim-hardware=list Specify the hardware to be included in the build."
ac_help="$ac_help
- --enable-sim-bswap Use the BSWAP instruction on Intel 486s and Pentiums."
+ --enable-sim-hostbitsize=32|64 Specify host bitsize (32 or 64)."
ac_help="$ac_help
- --enable-sim-endian=endian Specify target byte endian orientation."
+ --enable-sim-hostendian=end Specify host byte endian orientation."
ac_help="$ac_help
- --enable-sim-hostendain=end Specify host byte endian orientation."
+ --enable-sim-icache=size Specify instruction-decode cache size and type."
ac_help="$ac_help
- --enable-sim-smp=n Specify number of processors to configure for."
+ --enable-sim-inline=inlines Specify which functions should be inlined."
ac_help="$ac_help
- --enable-sim-xor-endian=n Specify number bytes involved in PowerPC XOR bi-endian mode (default 8)."
+ --enable-sim-jump Jump between semantic code (instead of call/return)."
ac_help="$ac_help
- --enable-sim-bitsize=n Specify target bitsize (32 or 64)."
+ --enable-sim-line-nr=opts Generate extra CPP code that references source rather than generated code"
ac_help="$ac_help
- --enable-sim-hostbitsize=32|64 Specify host bitsize (32 or 64)."
+ --enable-sim-model=which Specify PowerPC to model."
ac_help="$ac_help
- --enable-sim-env=env Specify target environment (operating, virtual, user)."
+ --enable-sim-model-issue Specify whether to simulate model specific actions"
ac_help="$ac_help
- --enable-sim-timebase Specify whether the PPC timebase is supported."
+ --enable-sim-monitor=mon Specify whether to enable monitoring events."
ac_help="$ac_help
- --enable-sim-alignment=align Specify strict or nonstrict alignment."
+ --enable-sim-opcode=which Override default opcode lookup."
ac_help="$ac_help
- --enable-sim-trace Specify whether tracing is supported."
+ --enable-sim-packages=list Specify the packages to be included in the build."
ac_help="$ac_help
- --enable-sim-assert Specify whether to perform random assertions."
+ --enable-sim-regparm=nr-parm Pass parameters in registers instead of on the stack - x86/GCC specific."
ac_help="$ac_help
--enable-sim-reserved-bits Specify whether to check reserved bits in instruction."
ac_help="$ac_help
- --enable-sim-float Specify whether to use host floating point or simulate."
+ --enable-sim-smp=n Specify number of processors to configure for."
ac_help="$ac_help
- --enable-sim-monitor=mon Specify whether to enable monitoring events."
+ --enable-sim-stdcall=type Use an alternative function call/return mechanism - x86/GCC specific."
ac_help="$ac_help
- --enable-sim-model=which Specify PowerPC to model."
+ --enable-sim-stdio Specify whether to use stdio for console input/output."
ac_help="$ac_help
- --enable-sim-default-model=which Specify default PowerPC to model."
+ --enable-sim-switch Use a switch instead of a table for instruction call."
ac_help="$ac_help
- --enable-sim-model-issue Specify whether to simulate model specific actions"
+ --enable-sim-timebase Specify whether the PPC timebase is supported."
+ac_help="$ac_help
+ --enable-sim-trace Specify whether tracing is supported."
+ac_help="$ac_help
+ --enable-sim-warnings=opts Extra CFLAGS for turning on compiler warnings except for idecode.o, semantics.o and psim.o"
+ac_help="$ac_help
+ --enable-sim-xor-endian=n Specify number bytes involved in PowerPC XOR bi-endian mode (default 8)."
# Initialize some variables set by options.
# The variables have the same names as the options, with
@@ -103,6 +119,8 @@ mandir='${prefix}/man'
# Initialize some other variables.
subdirs=
MFLAGS= MAKEFLAGS=
+# Maximum number of lines to put in a shell here document.
+ac_max_here_lines=12
ac_prev=
for ac_option
@@ -384,7 +402,7 @@ EOF
verbose=yes ;;
-version | --version | --versio | --versi | --vers)
- echo "configure generated by autoconf version 2.7"
+ echo "configure generated by autoconf version 2.12"
exit 0 ;;
-with-* | --with-*)
@@ -486,11 +504,14 @@ do
done
# NLS nuisances.
-# Only set LANG and LC_ALL to C if already set.
-# These must not be set unconditionally because not all systems understand
-# e.g. LANG=C (notably SCO).
-if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
+# 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
@@ -549,12 +570,10 @@ fi
ac_ext=c
# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
-ac_cpp='echo $CPP $CPPFLAGS 1>&5;
-$CPP $CPPFLAGS'
-ac_compile='echo ${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5;
-${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5 2>&5'
-ac_link='echo ${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5;
-${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5 2>&5'
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
# Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
@@ -570,6 +589,329 @@ fi
+ac_aux_dir=
+for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
+ if test -f $ac_dir/install-sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install-sh -c"
+ break
+ elif test -f $ac_dir/install.sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; }
+fi
+ac_config_guess=$ac_aux_dir/config.guess
+ac_config_sub=$ac_aux_dir/config.sub
+ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
+
+# Find a good install program. We prefer a C program (faster),
+# so one script is as good as another. But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# 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:623: 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="${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.
+ for ac_prog in ginstall installbsd 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.
+ # OSF/1 installbsd also uses dspmsg, but is usable.
+ :
+ 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'
+
+# 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:675: 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="${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:704: 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="${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
+
+ 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:752: 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 $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+cat > conftest.$ac_ext <<EOF
+#line 762 "configure"
+#include "confdefs.h"
+main(){return(0);}
+EOF
+if { (eval echo configure:766: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; 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:786: 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:791: 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:800: \"$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
+ 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:815: 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
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-O2"
+ fi
+else
+ GCC=
+ test "${CFLAGS+set}" = set || CFLAGS="-g"
+fi
+
+
+# Put a plausible default for CC_FOR_BUILD in Makefile.
+
+if test "x$cross_compiling" = "xno"; then
+ CC_FOR_BUILD='$(CC)'
+else
+ CC_FOR_BUILD=gcc
+fi
+
+
+# Check whether --enable-sim-alignment or --disable-sim-alignment was given.
+if test "${enable_sim_alignment+set}" = set; then
+ enableval="$enable_sim_alignment"
+ case "${enableval}" in
+ yes | strict | STRICT) sim_alignment="-DWITH_ALIGNMENT=STRICT_ALIGNMENT";;
+ no | nonstrict | NONSTRICT) sim_alignment="-DWITH_ALIGNMENT=NONSTRICT_ALIGNMENT";;
+ 0 | default | DEFAULT) sim_alignment="-DWITH_ALIGNMENT=0";;
+ *) { echo "configure: error: "Unknown value $enableval passed to --enable-sim-alignment"" 1>&2; exit 1; }; sim_alignment="";;
+esac
+if test x"$silent" != x"yes" && test x"$sim_alignment" != x""; then
+ echo "Setting alignment flags = $sim_alignment" 6>&1
+fi
+else
+ sim_alignment=""
+fi
+
+
+# Check whether --enable-sim-assert or --disable-sim-assert was given.
+if test "${enable_sim_assert+set}" = set; then
+ enableval="$enable_sim_assert"
+ case "${enableval}" in
+ yes) sim_assert="-DWITH_ASSERT=1";;
+ no) sim_assert="-DWITH_ASSERT=0";;
+ *) { echo "configure: error: "--enable-sim-assert does not take a value"" 1>&2; exit 1; }; sim_assert="";;
+esac
+if test x"$silent" != x"yes" && test x"$sim_assert" != x""; then
+ echo "Setting assert flags = $sim_assert" 6>&1
+fi
+else
+ sim_assert=""
+fi
+
+
+# Check whether --enable-sim-bitsize or --disable-sim-bitsize was given.
+if test "${enable_sim_bitsize+set}" = set; then
+ enableval="$enable_sim_bitsize"
+ case "${enableval}" in
+ 32|64) sim_bitsize="-DWITH_TARGET_WORD_BITSIZE=$enableval";;
+ *) { echo "configure: error: "--enable-sim-bitsize was given $enableval. Expected 32 or 64"" 1>&2; exit 1; }; sim_bitsize="";;
+esac
+if test x"$silent" != x"yes" && test x"$sim_bitsize" != x""; then
+ echo "Setting bitsize flags = $sim_bitsize" 6>&1
+fi
+else
+ sim_bitsize=""
+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";;
+ 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"
@@ -585,20 +927,6 @@ else
sim_cflags=""
fi
-# Check whether --enable-sim-warnings or --disable-sim-warnings was given.
-if test "${enable_sim_warnings+set}" = set; then
- enableval="$enable_sim_warnings"
- case "${enableval}" in
- yes) sim_warnings="-Werror -Wall -Wpointer-arith -Wmissing-prototypes";;
- no) sim_warnings="-w";;
- *) sim_warnings=`echo "${enableval}" | sed -e "s/,/ /g"`;;
-esac
-if test x"$silent" != x"yes" && test x"$sim_warnings" != x""; then
- echo "Setting warning flags = $sim_warnings" 6>&1
-fi
-else
- sim_warnings=""
-fi
# Check whether --enable-sim-config or --disable-sim-config was given.
if test "${enable_sim_config+set}" = set; then
@@ -624,53 +952,47 @@ if test x"$silent" != x"yes"; then
fi
fi
-# Check whether --enable-sim-opcode or --disable-sim-opcode was given.
-if test "${enable_sim_opcode+set}" = set; then
- enableval="$enable_sim_opcode"
+
+# Check whether --enable-sim-decode-mechanism or --disable-sim-decode-mechanism was given.
+if test "${enable_sim_decode_mechanism+set}" = set; then
+ enableval="$enable_sim_decode_mechanism"
case "${enableval}" in
- yes|no) { echo "configure: error: "No value supplied for --enable-sim-opcode=file"" 1>&2; exit 1; };;
- *) if test -f "${srcdir}/${enableval}"; then
- sim_opcode="${enableval}"
- elif test -f "${srcdir}/ppc-opcode-${enableval}"; then
- sim_opcode="ppc-opcode-${enableval}"
- else
- { echo "configure: error: "File $enableval is not an opcode rules file"" 1>&2; exit 1; };
- sim_opcode="ppc-opcode-complex"
- fi;;
+ yes|no) { echo "configure: error: "No value supplied for --enable-sim-decode-mechanism=file"" 1>&2; exit 1; };;
+ array|switch|padded-switch|goto-switch) sim_decode_mechanism="-T ${enableval}";;
+ *) { echo "configure: error: "File $enableval is not an opcode rules file"" 1>&2; exit 1; };
+ sim_decode_mechanism="switch";;
esac
-if test x"$silent" != x"yes" && test x"$sim_opcode" != x""; then
- echo "Setting opcode flags = $sim_opcode" 6>&1
+if test x"$silent" != x"yes" && test x"$sim_decode_mechanism" != x""; then
+ echo "Setting decode mechanism flags = $sim_decode_mechanism" 6>&1
fi
else
- sim_opcode="ppc-opcode-complex"
+ sim_decode_mechanism=""
if test x"$silent" != x"yes"; then
- echo "Setting opcode flags = $sim_opcode"
+ echo "Setting decode mechanism flags = $sim_decode_mechanism"
fi
fi
-# Check whether --enable-sim-switch or --disable-sim-switch was given.
-if test "${enable_sim_switch+set}" = set; then
- enableval="$enable_sim_switch"
+
+# Check whether --enable-sim-default-model or --disable-sim-default-model was given.
+if test "${enable_sim_default_model+set}" = set; then
+ enableval="$enable_sim_default_model"
case "${enableval}" in
- yes) sim_switch="-s";;
- no) sim_switch="";;
- *) { echo "configure: error: "--enable-sim-switch does not take a value"" 1>&2; exit 1; }; sim_switch="";;
+ yes|no) { echo "configure: error: "No value supplied for --enable-sim-default-model=model"" 1>&2; exit 1; };;
+ *) sim_default_model="-DWITH_DEFAULT_MODEL=${enableval}";;
esac
-if test x"$silent" != x"yes" && test x"$sim_switch" != x""; then
- echo "Setting switch flags = $sim_switch" 6>&1
+if test x"$silent" != x"yes" && test x"$sim_default_model" != x""; then
+ echo "Setting default-model flags = $sim_default_model" 6>&1
fi
else
- sim_switch="";
-if test x"$silent" != x"yes"; then
- echo "Setting switch flags = $sim_switch" 6>&1
-fi
+ sim_default_model=""
fi
+
# Check whether --enable-sim-duplicate or --disable-sim-duplicate was given.
if test "${enable_sim_duplicate+set}" = set; then
enableval="$enable_sim_duplicate"
case "${enableval}" in
- yes) sim_dup="-e";;
+ yes) sim_dup="-E";;
no) sim_dup="";;
*) { echo "configure: error: "--enable-sim-duplicate does not take a value"" 1>&2; exit 1; }; sim_dup="";;
esac
@@ -678,50 +1000,276 @@ if test x"$silent" != x"yes" && test x"$sim_dup" != x""; then
echo "Setting duplicate flags = $sim_dup" 6>&1
fi
else
- sim_dup="-e"
+ sim_dup="-E"
if test x"$silent" != x"yes"; then
echo "Setting duplicate flags = $sim_dup" 6>&1
fi
fi
+
+# Check whether --enable-sim-endian or --disable-sim-endian was given.
+if test "${enable_sim_endian+set}" = set; then
+ enableval="$enable_sim_endian"
+ case "${enableval}" in
+ yes) case "$target" in
+ *powerpc-*) sim_endian="-DWITH_TARGET_BYTE_ORDER=BIG_ENDIAN";;
+ *powerpcle-*) sim_endian="-DWITH_TARGET_BYTE_ORDER=LITTLE_ENDIAN";;
+ *) echo "Unknown target $target" 1>&6; sim_endian="-DWITH_TARGET_BYTE_ORDER=0";;
+ esac;;
+ no) sim_endian="-DWITH_TARGET_BYTE_ORDER=0";;
+ b*|B*) sim_endian="-DWITH_TARGET_BYTE_ORDER=BIG_ENDIAN";;
+ l*|L*) sim_endian="-DWITH_TARGET_BYTE_ORDER=LITTLE_ENDIAN";;
+ *) { echo "configure: error: "Unknown value $enableval for --enable-sim-endian"" 1>&2; exit 1; }; sim_endian="";;
+esac
+if test x"$silent" != x"yes" && test x"$sim_endian" != x""; then
+ echo "Setting endian flags = $sim_endian" 6>&1
+fi
+else
+ sim_endian=""
+fi
+
+
+# Check whether --enable-sim-env or --disable-sim-env was given.
+if test "${enable_sim_env+set}" = set; then
+ enableval="$enable_sim_env"
+ case "${enableval}" in
+ operating | os | oea) sim_env="-DWITH_ENVIRONMENT=OPERATING_ENVIRONMENT";;
+ virtual | vea) sim_env="-DWITH_ENVIRONMENT=VIRTUAL_ENVIRONMENT";;
+ user | uea) sim_env="-DWITH_ENVIRONMENT=USER_ENVIRONMENT";;
+ no) sim_env="-DWITH_ENVIRONMENT=0";;
+ *) { echo "configure: error: "Unknown value $enableval passed to --enable-sim-env"" 1>&2; exit 1; }; sim_env="";;
+esac
+if test x"$silent" != x"yes" && test x"$sim_env" != x""; then
+ echo "Setting env flags = $sim_env" 6>&1
+fi
+else
+ sim_env=""
+fi
+
+
# Check whether --enable-sim-filter or --disable-sim-filter was given.
if test "${enable_sim_filter+set}" = set; then
enableval="$enable_sim_filter"
case "${enableval}" in
yes) { echo "configure: error: "--enable-sim-filter must be specified with a rule to filter or no"" 1>&2; exit 1; }; sim_filter="";;
no) sim_filter="";;
- *) sim_filter="-f $enableval";;
+ *) sim_filter="-F $enableval";;
esac
if test x"$silent" != x"yes" && test x"$sim_filter" != x""; then
echo "Setting filter flags = $sim_filter" 6>&1
fi
else
- sim_filter="-f 64"
+ sim_filter="-F 32,f,o"
if test x"$silent" != x"yes"; then
echo "Setting filter flags = $sim_filter" 6>&1
fi
fi
+
+# Check whether --enable-sim-float or --disable-sim-float was given.
+if test "${enable_sim_float+set}" = set; then
+ enableval="$enable_sim_float"
+ case "${enableval}" in
+ yes | hard) sim_float="-DWITH_FLOATING_POINT=HARD_FLOATING_POINT";;
+ no | soft) sim_float="-DWITH_FLOATING_POINT=SOFT_FLOATING_POINT";;
+ *) { echo "configure: error: "Unknown value $enableval passed to --enable-sim-float"" 1>&2; exit 1; }; sim_float="";;
+esac
+if test x"$silent" != x"yes" && test x"$sim_float" != x""; then
+ echo "Setting float flags = $sim_float" 6>&1
+fi
+else
+ sim_float=""
+fi
+
+
+# Check whether --enable-sim-hardware or --disable-sim-hardware was given.
+if test "${enable_sim_hardware+set}" = set; then
+ enableval="$enable_sim_hardware"
+ hardware="cpu,memory,nvram,iobus,htab,disk,trace,register,vm,init,core,pal,com,eeprom,opic,glue,phb,ide"
+case "${enableval}" in
+ yes) ;;
+ no) { echo "configure: error: "List of hardware must be specified for --enable-sim-hardware"" 1>&2; exit 1; }; hardware="";;
+ ,*) hardware="${hardware}${enableval}";;
+ *,) hardware="${enableval}${hardware}";;
+ *) hardware="${enableval}"'';;
+esac
+sim_hw_src=`echo $hardware | sed -e 's/,/.c hw_/g' -e 's/^/hw_/' -e s'/$/.c/'`
+sim_hw_obj=`echo $sim_hw_src | sed -e 's/\.c/.o/g'`
+if test x"$silent" != x"yes" && test x"$hardware" != x""; then
+ echo "Setting hardware to $sim_hw_src, $sim_hw_obj"
+fi
+else
+ hardware="cpu,memory,nvram,iobus,htab,disk,trace,register,vm,init,core,pal,com,eeprom,opic,glue,phb,ide"
+sim_hw_src=`echo $hardware | sed -e 's/,/.c hw_/g' -e 's/^/hw_/' -e s'/$/.c/'`
+sim_hw_obj=`echo $sim_hw_src | sed -e 's/\.c/.o/g'`
+if test x"$silent" != x"yes"; then
+ echo "Setting hardware to $sim_hw_src, $sim_hw_obj"
+fi
+fi
+
+
+# Check whether --enable-sim-hostbitsize or --disable-sim-hostbitsize was given.
+if test "${enable_sim_hostbitsize+set}" = set; then
+ enableval="$enable_sim_hostbitsize"
+ case "${enableval}" in
+ 32|64) sim_hostbitsize="-DWITH_HOST_WORD_BITSIZE=$enableval";;
+ *) { echo "configure: error: "--enable-sim-hostbitsize was given $enableval. Expected 32 or 64"" 1>&2; exit 1; }; sim_hostbitsize="";;
+esac
+if test x"$silent" != x"yes" && test x"$sim_hostbitsize" != x""; then
+ echo "Setting hostbitsize flags = $sim_hostbitsize" 6>&1
+fi
+else
+ sim_hostbitsize=""
+fi
+
+
+# Check whether --enable-sim-hostendian or --disable-sim-hostendian was given.
+if test "${enable_sim_hostendian+set}" = set; then
+ enableval="$enable_sim_hostendian"
+ 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";;
+ *) { echo "configure: error: "Unknown value $enableval for --enable-sim-hostendian"" 1>&2; exit 1; }; sim_hostendian="";;
+esac
+if test x"$silent" != x"yes" && test x"$sim_hostendian" != x""; then
+ echo "Setting hostendian flags = $sim_hostendian" 6>&1
+fi
+else
+
+if test "x$cross_compiling" = "xno"; then
+ echo $ac_n "checking whether byte ordering is bigendian""... $ac_c" 1>&6
+echo "configure:1143: checking whether byte ordering is bigendian" >&5
+if eval "test \"`echo '$''{'ac_cv_c_bigendian'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_cv_c_bigendian=unknown
+# See if sys/param.h defines the BYTE_ORDER macro.
+cat > conftest.$ac_ext <<EOF
+#line 1150 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/param.h>
+int main() {
+
+#if !BYTE_ORDER || !BIG_ENDIAN || !LITTLE_ENDIAN
+ bogus endian macros
+#endif
+; return 0; }
+EOF
+if { (eval echo configure:1161: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ # It does; now see whether it defined to BIG_ENDIAN or not.
+cat > conftest.$ac_ext <<EOF
+#line 1165 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/param.h>
+int main() {
+
+#if BYTE_ORDER != BIG_ENDIAN
+ not big endian
+#endif
+; return 0; }
+EOF
+if { (eval echo configure:1176: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_c_bigendian=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_c_bigendian=no
+fi
+rm -f conftest*
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+fi
+rm -f conftest*
+if test $ac_cv_c_bigendian = unknown; then
+if test "$cross_compiling" = yes; then
+ { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1196 "configure"
+#include "confdefs.h"
+main () {
+ /* Are we little or big endian? From Harbison&Steele. */
+ union
+ {
+ long l;
+ char c[sizeof (long)];
+ } u;
+ u.l = 1;
+ exit (u.c[sizeof (long) - 1] == 1);
+}
+EOF
+if { (eval echo configure:1209: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
+then
+ ac_cv_c_bigendian=no
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_c_bigendian=yes
+fi
+rm -fr conftest*
+fi
+
+fi
+fi
+
+echo "$ac_t""$ac_cv_c_bigendian" 1>&6
+if test $ac_cv_c_bigendian = yes; then
+ cat >> confdefs.h <<\EOF
+#define WORDS_BIGENDIAN 1
+EOF
+
+fi
+
+ 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
+fi
+
+
# Check whether --enable-sim-icache or --disable-sim-icache was given.
if test "${enable_sim_icache+set}" = set; then
enableval="$enable_sim_icache"
- icache=""
-case "${enableval}" in
- yes) sim_icache="-r 1024"; icache="1024";;
- define) sim_icache="-r 1024 -R"; icache="1024";;
- no) sim_icache="";;
- *) sim_icache="-r ${enableval}"; icache="${enableval}";;
+ icache="-R"
+ case "${enableval}" in
+ yes) icache="1024"; sim_icache="-I $icache";;
+ no) sim_icache="-R";;
+ *) icache=1024
+ sim_icache="-"
+ for x in `echo "${enableval}" | sed -e "s/,/ /g"`; do
+ case "$x" in
+ define) sim_icache="${sim_icache}R";;
+ semantic) sim_icache="${sim_icache}C";;
+ insn) sim_icache="${sim_icache}S";;
+ 0*|1*|2*|3*|4*|5*|6*|7*|8*|9*) icache=$x;;
+ *) { echo "configure: error: "Unknown value $x for --enable-sim-icache"" 1>&2; exit 1; }; sim_icache="";;
+ esac
+ done
+ sim_icache="${sim_icache}I $icache";;
esac
if test x"$silent" != x"yes" && test x"$icache" != x""; then
- echo "Setting instruction cache size to $icache"
+ echo "Setting instruction cache size to $icache ($sim_icache)"
fi
else
- sim_icache="-r 1024"
+ sim_icache="-CSRI 1024"
if test x"$silent" != x"yes"; then
- echo "Setting instruction cache size to 1024"
+ echo "Setting instruction cache size to 1024 ($sim_icache)"
fi
fi
+
# Check whether --enable-sim-inline or --disable-sim-inline was given.
if test "${enable_sim_inline+set}" = set; then
enableval="$enable_sim_inline"
@@ -735,8 +1283,8 @@ case "$enableval" in
new_flag=""
case "$x" in
*_INLINE=*) new_flag="-D$x";;
- *_INLINE) new_flag="-D$x=ALL_INLINE";;
*=*) new_flag=`echo "$x" | sed -e "s/=/_INLINE=/" -e "s/^/-D/"`;;
+ *_INLINE) new_flag="-D$x=ALL_INLINE";;
*) new_flag="-D$x""_INLINE=ALL_INLINE";;
esac
if test x"$sim_inline" = x""; then
@@ -760,286 +1308,310 @@ else
fi
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";;
- 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-endian or --disable-sim-endian was given.
-if test "${enable_sim_endian+set}" = set; then
- enableval="$enable_sim_endian"
+# Check whether --enable-sim-jump or --disable-sim-jump was given.
+if test "${enable_sim_jump+set}" = set; then
+ enableval="$enable_sim_jump"
case "${enableval}" in
- yes) case "$target" in
- *powerpc-*) sim_endian="-DWITH_TARGET_BYTE_ORDER=BIG_ENDIAN";;
- *powerpcle-*) sim_endian="-DWITH_TARGET_BYTE_ORDER=LITTLE_ENDIAN";;
- *) echo "Unknown target $target" 1>&6; sim_endian="-DWITH_TARGET_BYTE_ORDER=0";;
- esac;;
- no) sim_endian="-DWITH_TARGET_BYTE_ORDER=0";;
- b*|B*) sim_endian="-DWITH_TARGET_BYTE_ORDER=BIG_ENDIAN";;
- l*|L*) sim_endian="-DWITH_TARGET_BYTE_ORDER=LITTLE_ENDIAN";;
- *) { echo "configure: error: "Unknown value $enableval for --enable-sim-endian"" 1>&2; exit 1; }; sim_endian="";;
+ yes) sim_jump="-J";;
+ no) sim_jump="";;
+ *) { echo "configure: error: "--enable-sim-jump does not take a value"" 1>&2; exit 1; }; sim_jump="";;
esac
-if test x"$silent" != x"yes" && test x"$sim_endian" != x""; then
- echo "Setting endian flags = $sim_endian" 6>&1
+if test x"$silent" != x"yes" && test x"$sim_jump" != x""; then
+ echo "Setting jump flag = $sim_jump" 6>&1
fi
else
- sim_endian=""
+ sim_jump=""
+if test x"$silent" != x"yes"; then
+ echo "Setting jump flag = $sim_jump" 6>&1
+fi
fi
-# Check whether --enable-sim-hostendian or --disable-sim-hostendian was given.
-if test "${enable_sim_hostendian+set}" = set; then
- enableval="$enable_sim_hostendian"
+
+# Check whether --enable-sim-line-nr or --disable-sim-line-nr was given.
+if test "${enable_sim_line_nr+set}" = set; then
+ enableval="$enable_sim_line_nr"
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";;
- *) { echo "configure: error: "Unknown value $enableval for --enable-sim-hostendian"" 1>&2; exit 1; }; sim_hostendian="";;
+ yes) sim_line_nr="";;
+ no) sim_line_nr="-L";;
+ *) { echo "configure: error: "--enable-sim-line-nr does not take a value"" 1>&2; exit 1; }; sim_line_nr="";;
esac
-if test x"$silent" != x"yes" && test x"$sim_hostendian" != x""; then
- echo "Setting hostendian flags = $sim_hostendian" 6>&1
+if test x"$silent" != x"yes" && test x"$sim_line_nr" != x""; then
+ echo "Setting warning flags = $sim_line_nr" 6>&1
fi
else
- sim_hostendian=""
+ sim_line_nr=""
fi
-# Check whether --enable-sim-smp or --disable-sim-smp was given.
-if test "${enable_sim_smp+set}" = set; then
- enableval="$enable_sim_smp"
+
+# Check whether --enable-sim-model or --disable-sim-model was given.
+if test "${enable_sim_model+set}" = set; then
+ enableval="$enable_sim_model"
case "${enableval}" in
- yes) sim_smp="-DWITH_SMP=5";;
- no) sim_smp="-DWITH_SMP=0";;
- *) sim_smp="-DWITH_SMP=$enableval";;
+ yes|no) { echo "configure: error: "No value supplied for --enable-sim-model=model"" 1>&2; exit 1; };;
+ *) sim_model="-DWITH_MODEL=${enableval}";;
esac
-if test x"$silent" != x"yes" && test x"$sim_smp" != x""; then
- echo "Setting smp flags = $sim_smp" 6>&1
+if test x"$silent" != x"yes" && test x"$sim_model" != x""; then
+ echo "Setting model flags = $sim_model" 6>&1
fi
else
- sim_smp="-DWITH_SMP=5"
-if test x"$silent" != x"yes"; then
- echo "Setting smp flags = $sim_smp" 6>&1
-fi
+ sim_model=""
fi
-# Check whether --enable-sim-xor-endian or --disable-sim-xor-endian was given.
-if test "${enable_sim_xor_endian+set}" = set; then
- enableval="$enable_sim_xor_endian"
+
+# Check whether --enable-sim-model-issue or --disable-sim-model-issue was given.
+if test "${enable_sim_model_issue+set}" = set; then
+ enableval="$enable_sim_model_issue"
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";;
+ yes) sim_model_issue="-DWITH_MODEL_ISSUE=MODEL_ISSUE_PROCESS";;
+ no) sim_model_issue="-DWITH_MODEL_ISSUE=MODEL_ISSUE_IGNORE";;
+ *) { echo "configure: error: "--enable-sim-model-issue does not take a value"" 1>&2; exit 1; }; sim_model_issue="";;
esac
-if test x"$silent" != x"yes" && test x"$sim_xor_endian" != x""; then
- echo "Setting xor-endian flag = $sim_xor_endian" 6>&1
+if test x"$silent" != x"yes"; then
+ echo "Setting model-issue flags = $sim_model_issue" 6>&1
fi
else
- sim_xor_endian=""
+ sim_model_issue=""
fi
-# Check whether --enable-sim-bitsize or --disable-sim-bitsize was given.
-if test "${enable_sim_bitsize+set}" = set; then
- enableval="$enable_sim_bitsize"
+
+# Check whether --enable-sim-monitor or --disable-sim-monitor was given.
+if test "${enable_sim_monitor+set}" = set; then
+ enableval="$enable_sim_monitor"
case "${enableval}" in
- 32|64) sim_bitsize="-DWITH_TARGET_WORD_BITSIZE=$enableval";;
- *) { echo "configure: error: "--enable-sim-bitsize was given $enableval" 1>&2; exit 1; }; sim_bitsize="";;
+ yes) sim_monitor="-DWITH_MON='MONITOR_INSTRUCTION_ISSUE | MONITOR_LOAD_STORE_UNIT'";;
+ no) sim_monitor="-DWITH_MON=0";;
+ instruction) sim_monitor="-DWITH_MON=MONITOR_INSTRUCTION_ISSUE";;
+ memory) sim_monitor="-DWITH_MON=MONITOR_LOAD_STORE_UNIT";;
+ *) { echo "configure: error: "Unknown value $enableval passed to --enable-sim-mon"" 1>&2; exit 1; }; sim_env="";;
esac
-if test x"$silent" != x"yes" && test x"$sim_bitsize" != x""; then
- echo "Setting bitsize flags = $sim_bitsize" 6>&1
+if test x"$silent" != x"yes" && test x"$sim_monitor" != x""; then
+ echo "Setting monitor flags = $sim_monitor" 6>&1
fi
else
- sim_bitsize=""
+ sim_monitor=""
fi
-# Check whether --enable-sim-hostbitsize or --disable-sim-hostbitsize was given.
-if test "${enable_sim_hostbitsize+set}" = set; then
- enableval="$enable_sim_hostbitsize"
+
+# Check whether --enable-sim-opcode or --disable-sim-opcode was given.
+if test "${enable_sim_opcode+set}" = set; then
+ enableval="$enable_sim_opcode"
case "${enableval}" in
- 32|64) sim_hostbitsize="-DWITH_HOST_WORD_BITSIZE=$enableval";;
- *) { echo "configure: error: "--enable-sim-hostbitsize was given $enableval" 1>&2; exit 1; }; sim_hostbitsize="";;
+ yes|no) { echo "configure: error: "No value supplied for --enable-sim-opcode=file"" 1>&2; exit 1; };;
+ *) if test -f "${srcdir}/${enableval}"; then
+ sim_opcode="${enableval}"
+ elif test -f "${srcdir}/dc-${enableval}"; then
+ sim_opcode="dc-${enableval}"
+ else
+ { echo "configure: error: "File $enableval is not an opcode rules file"" 1>&2; exit 1; };
+ sim_opcode="dc-complex"
+ fi;;
esac
-if test x"$silent" != x"yes" && test x"$sim_hostbitsize" != x""; then
- echo "Setting hostbitsize flags = $sim_hostbitsize" 6>&1
+if test x"$silent" != x"yes" && test x"$sim_opcode" != x""; then
+ echo "Setting opcode flags = $sim_opcode" 6>&1
fi
else
- sim_hostbitsize=""
+ sim_opcode="dc-complex"
+if test x"$silent" != x"yes"; then
+ echo "Setting opcode flags = $sim_opcode"
+fi
fi
-# Check whether --enable-sim-env or --disable-sim-env was given.
-if test "${enable_sim_env+set}" = set; then
- enableval="$enable_sim_env"
- case "${enableval}" in
- operating | os | oea) sim_env="-DWITH_ENVIRONMENT=OPERATING_ENVIRONMENT";;
- virtual | vea) sim_env="-DWITH_ENVIRONMENT=VIRTUAL_ENVIRONMENT";;
- user | uea) sim_env="-DWITH_ENVIRONMENT=USER_ENVIRONMENT";;
- no) sim_env="-DWITH_ENVIRONMENT=0";;
- *) { echo "configure: error: "Unknown value $enableval passed to --enable-sim-env"" 1>&2; exit 1; }; sim_env="";;
+
+# Check whether --enable-sim-packages or --disable-sim-packages was given.
+if test "${enable_sim_packages+set}" = set; then
+ enableval="$enable_sim_packages"
+ packages=disklabel
+case "${enableval}" in
+ yes) ;;
+ no) { echo "configure: error: "List of packages must be specified for --enable-sim-packages"" 1>&2; exit 1; }; packages="";;
+ ,*) packages="${packages}${enableval}";;
+ *,) packages="${enableval}${packages}";;
+ *) packages="${enableval}"'';;
esac
-if test x"$silent" != x"yes" && test x"$sim_env" != x""; then
- echo "Setting env flags = $sim_env" 6>&1
+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
else
- sim_env=""
+ 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
fi
-# Check whether --enable-sim-timebase or --disable-sim-timebase was given.
-if test "${enable_sim_timebase+set}" = set; then
- enableval="$enable_sim_timebase"
+
+# Check whether --enable-sim-regparm or --disable-sim-regparm was given.
+if test "${enable_sim_regparm+set}" = set; then
+ enableval="$enable_sim_regparm"
case "${enableval}" in
- yes) sim_timebase="-DWITH_TIME_BASE=1";;
- no) sim_timebase="-DWITH_TIME_BASE=0";;
- *) { echo "configure: error: "--enable-sim-timebase does not take a value"" 1>&2; exit 1; }; sim_timebase="";;
+ 0*|1*|2*|3*|4*|5*|6*|7*|8*|9*) sim_regparm="-DWITH_REGPARM=${enableval}";;
+ no) sim_regparm="" ;;
+ yes) sim_regparm="-DWITH_REGPARM=3";;
+ *) { echo "configure: error: "Unknown value $enableval for --enable-sim-regparm"" 1>&2; exit 1; }; sim_regparm="";;
esac
-if test x"$silent" != x"yes" && test x"$sim_timebase" != x""; then
- echo "Setting timebase flags = $sim_timebase" 6>&1
+if test x"$silent" != x"yes" && test x"$sim_regparm" != x""; then
+ echo "Setting regparm flags = $sim_regparm" 6>&1
fi
else
- sim_timebase=""
+ sim_regparm=""
fi
-# Check whether --enable-sim-alignment or --disable-sim-alignment was given.
-if test "${enable_sim_alignment+set}" = set; then
- enableval="$enable_sim_alignment"
+
+# Check whether --enable-sim-reserved-bits or --disable-sim-reserved-bits was given.
+if test "${enable_sim_reserved_bits+set}" = set; then
+ enableval="$enable_sim_reserved_bits"
case "${enableval}" in
- yes | strict | STRICT) sim_alignment="-DWITH_ALIGNMENT=STRICT_ALIGNMENT";;
- no | nonstrict | NONSTRICT) sim_alignment="-DWITH_ALIGNMENT=NONSTRICT_ALIGNMENT";;
- *) { echo "configure: error: "Unknown value $enableval passed to --enable-sim-alignment"" 1>&2; exit 1; }; sim_alignment="";;
+ yes) sim_reserved="-DWITH_RESERVED_BITS=1";;
+ no) sim_reserved="-DWITH_RESERVED_BITS=0";;
+ *) { echo "configure: error: "--enable-sim-reserved-bits does not take a value"" 1>&2; exit 1; }; sim_reserved="";;
esac
-if test x"$silent" != x"yes" && test x"$sim_alignment" != x""; then
- echo "Setting alignment flags = $sim_alignment" 6>&1
+if test x"$silent" != x"yes" && test x"$sim_reserved" != x""; then
+ echo "Setting reserved flags = $sim_reserved" 6>&1
fi
else
- sim_alignment=""
+ sim_reserved=""
fi
-# Check whether --enable-sim-trace or --disable-sim-trace was given.
-if test "${enable_sim_trace+set}" = set; then
- enableval="$enable_sim_trace"
+
+# Check whether --enable-sim-smp or --disable-sim-smp was given.
+if test "${enable_sim_smp+set}" = set; then
+ enableval="$enable_sim_smp"
case "${enableval}" in
- yes) sim_trace="-DWITH_TRACE=1";;
- no) sim_trace="-DWITH_TRACE=0";;
- *) { echo "configure: error: "--enable-sim-trace does not take a value"" 1>&2; exit 1; }; sim_trace="";;
+ 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_trace" != x""; then
- echo "Setting trace flags = $sim_trace" 6>&1
+if test x"$silent" != x"yes" && test x"$sim_smp" != x""; then
+ echo "Setting smp flags = $sim_smp" 6>&1
fi
else
- sim_trace=""
+ sim_smp="-DWITH_SMP=5" ; sim_igen_smp="-N 5"
+if test x"$silent" != x"yes"; then
+ echo "Setting smp flags = $sim_smp" 6>&1
+fi
fi
-# Check whether --enable-sim-assert or --disable-sim-assert was given.
-if test "${enable_sim_assert+set}" = set; then
- enableval="$enable_sim_assert"
+
+# Check whether --enable-sim-stdcall or --disable-sim-stdcall was given.
+if test "${enable_sim_stdcall+set}" = set; then
+ enableval="$enable_sim_stdcall"
case "${enableval}" in
- yes) sim_assert="-DWITH_ASSERT=1";;
- no) sim_assert="-DWITH_ASSERT=0";;
- *) { echo "configure: error: "--enable-sim-assert does not take a value"" 1>&2; exit 1; }; sim_assert="";;
+ no) sim_stdcall="" ;;
+ std*) sim_stdcall="-DWITH_STDCALL=1";;
+ yes) sim_stdcall="-DWITH_STDCALL=1";;
+ *) { echo "configure: error: "Unknown value $enableval for --enable-sim-stdcall"" 1>&2; exit 1; }; sim_stdcall="";;
esac
-if test x"$silent" != x"yes" && test x"$sim_assert" != x""; then
- echo "Setting assert flags = $sim_assert" 6>&1
+if test x"$silent" != x"yes" && test x"$sim_stdcall" != x""; then
+ echo "Setting function call flags = $sim_stdcall" 6>&1
fi
else
- sim_assert=""
+ sim_stdcall=""
fi
-# Check whether --enable-sim-reserved-bits or --disable-sim-reserved-bits was given.
-if test "${enable_sim_reserved_bits+set}" = set; then
- enableval="$enable_sim_reserved_bits"
+
+# 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_reserved="-DWITH_RESERVED_BITS=1";;
- no) sim_reserved="-DWITH_RESERVED_BITS=0";;
- *) { echo "configure: error: "--enable-sim-reserved-bits does not take a value"" 1>&2; exit 1; }; sim_reserved="";;
+ 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_reserved" != x""; then
- echo "Setting reserved flags = $sim_reserved" 6>&1
+if test x"$silent" != x"yes" && test x"$sim_stdio" != x""; then
+ echo "Setting stdio flags = $sim_stdio" 6>&1
fi
else
- sim_reserved=""
+ sim_stdio=""
fi
-# Check whether --enable-sim-float or --disable-sim-float was given.
-if test "${enable_sim_float+set}" = set; then
- enableval="$enable_sim_float"
+
+# Check whether --enable-sim-switch or --disable-sim-switch was given.
+if test "${enable_sim_switch+set}" = set; then
+ enableval="$enable_sim_switch"
case "${enableval}" in
- yes | hard) sim_float="-DWITH_FLOATING_POINT=HARD_FLOATING_POINT";;
- no | soft) sim_float="-DWITH_FLOATING_POINT=SOFT_FLOATING_POINT";;
- *) { echo "configure: error: "Unknown value $enableval passed to --enable-sim-float"" 1>&2; exit 1; }; sim_float="";;
+ yes) sim_switch="-s";;
+ no) sim_switch="";;
+ *) { echo "configure: error: "--enable-sim-switch does not take a value"" 1>&2; exit 1; }; sim_switch="";;
esac
-if test x"$silent" != x"yes" && test x"$sim_float" != x""; then
- echo "Setting float flags = $sim_float" 6>&1
+if test x"$silent" != x"yes" && test x"$sim_switch" != x""; then
+ echo "Setting switch flags = $sim_switch" 6>&1
fi
else
- sim_float=""
+ sim_switch="";
+if test x"$silent" != x"yes"; then
+ echo "Setting switch flags = $sim_switch" 6>&1
+fi
fi
-# Check whether --enable-sim-monitor or --disable-sim-monitor was given.
-if test "${enable_sim_monitor+set}" = set; then
- enableval="$enable_sim_monitor"
+
+# Check whether --enable-sim-timebase or --disable-sim-timebase was given.
+if test "${enable_sim_timebase+set}" = set; then
+ enableval="$enable_sim_timebase"
case "${enableval}" in
- yes) sim_monitor="-DWITH_MON='MONITOR_INSTRUCTION_ISSUE | MONITOR_LOAD_STORE_UNIT'";;
- no) sim_monitor="-DWITH_MON=0";;
- instruction) sim_monitor="-DWITH_MON=MONITOR_INSTRUCTION_ISSUE";;
- memory) sim_monitor="-DWITH_MON=MONITOR_LOAD_STORE_UNIT";;
- *) { echo "configure: error: "Unknown value $enableval passed to --enable-sim-mon"" 1>&2; exit 1; }; sim_env="";;
+ yes) sim_timebase="-DWITH_TIME_BASE=1";;
+ no) sim_timebase="-DWITH_TIME_BASE=0";;
+ *) { echo "configure: error: "--enable-sim-timebase does not take a value"" 1>&2; exit 1; }; sim_timebase="";;
esac
-if test x"$silent" != x"yes" && test x"$sim_monitor" != x""; then
- echo "Setting monitor flags = $sim_monitor" 6>&1
+if test x"$silent" != x"yes" && test x"$sim_timebase" != x""; then
+ echo "Setting timebase flags = $sim_timebase" 6>&1
fi
else
- sim_monitor=""
+ sim_timebase=""
fi
-# Check whether --enable-sim-model or --disable-sim-model was given.
-if test "${enable_sim_model+set}" = set; then
- enableval="$enable_sim_model"
+
+# 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|no) { echo "configure: error: "No value supplied for --enable-sim-model=model"" 1>&2; exit 1; };;
- *) sim_model="-DWITH_MODEL=${enableval}";;
+ yes) sim_trace="-DWITH_TRACE=1";;
+ no) sim_trace="-DWITH_TRACE=0";;
+ *) { echo "configure: error: "--enable-sim-trace does not take a value"" 1>&2; exit 1; }; sim_trace="";;
esac
-if test x"$silent" != x"yes" && test x"$sim_model" != x""; then
- echo "Setting model flags = $sim_model" 6>&1
+if test x"$silent" != x"yes" && test x"$sim_trace" != x""; then
+ echo "Setting trace flags = $sim_trace" 6>&1
fi
else
- sim_model=""
+ sim_trace=""
fi
-# Check whether --enable-sim-default-model or --disable-sim-default-model was given.
-if test "${enable_sim_default_model+set}" = set; then
- enableval="$enable_sim_default_model"
+
+# Check whether --enable-sim-warnings or --disable-sim-warnings was given.
+if test "${enable_sim_warnings+set}" = set; then
+ enableval="$enable_sim_warnings"
case "${enableval}" in
- yes|no) { echo "configure: error: "No value supplied for --enable-sim-default-model=model"" 1>&2; exit 1; };;
- *) sim_default_model="-DWITH_DEFAULT_MODEL=${enableval}";;
+ yes) sim_warnings="-Werror -Wall -Wpointer-arith -Wmissing-prototypes -Wmissing-declarations ";;
+ no) sim_warnings="-w";;
+ *) sim_warnings=`echo "${enableval}" | sed -e "s/,/ /g"`;;
esac
-if test x"$silent" != x"yes" && test x"$sim_default_model" != x""; then
- echo "Setting default-model flags = $sim_default_model" 6>&1
+if test x"$silent" != x"yes" && test x"$sim_warnings" != x""; then
+ echo "Setting warning flags = $sim_warnings" 6>&1
fi
else
- sim_model=""
+ sim_warnings=""
fi
-# Check whether --enable-sim-model-issue or --disable-sim-model-issue was given.
-if test "${enable_sim_model_issue+set}" = set; then
- enableval="$enable_sim_model_issue"
+
+# Check whether --enable-sim-xor-endian or --disable-sim-xor-endian was given.
+if test "${enable_sim_xor_endian+set}" = set; then
+ enableval="$enable_sim_xor_endian"
case "${enableval}" in
- yes) sim_model_issue="-DWITH_MODEL_ISSUE=MODEL_ISSUE_PROCESS";;
- no) sim_model_issue="-DWITH_MODEL_ISSUE=MODEL_ISSUE_IGNORE";;
- *) { echo "configure: error: "--enable-sim-model-issue does not take a value"" 1>&2; exit 1; }; sim_model_issue="";;
+ 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"; then
- echo "Setting model-issue flags = $sim_model_issue" 6>&1
+if test x"$silent" != x"yes" && test x"$sim_xor_endian" != x""; then
+ echo "Setting xor-endian flag = $sim_xor_endian" 6>&1
fi
else
- sim_model_issue=""
+ sim_xor_endian=""
fi
+
ac_aux_dir=
for ac_dir in `cd $srcdir;pwd`/../.. $srcdir/`cd $srcdir;pwd`/../..; do
if test -f $ac_dir/install-sh; then
@@ -1087,6 +1659,7 @@ 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:1663: checking host system type" >&5
host_alias=$host
case "$host_alias" in
@@ -1101,12 +1674,13 @@ NONE)
esac
host=`$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/'`
+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:1684: checking target system type" >&5
target_alias=$target
case "$target_alias" in
@@ -1118,12 +1692,13 @@ NONE)
esac
target=`$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/'`
+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:1702: checking build system type" >&5
build_alias=$build
case "$build_alias" in
@@ -1135,9 +1710,9 @@ NONE)
esac
build=`$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/'`
+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" &&
@@ -1169,386 +1744,772 @@ 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
-if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+echo $ac_n "checking for st_blksize in struct stat""... $ac_c" 1>&6
+echo "configure:1749: checking for st_blksize in struct stat" >&5
+if eval "test \"`echo '$''{'ac_cv_struct_st_blksize'+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.
+ cat > conftest.$ac_ext <<EOF
+#line 1754 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+int main() {
+struct stat s; s.st_blksize;
+; return 0; }
+EOF
+if { (eval echo configure:1762: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_struct_st_blksize=yes
else
- 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
- ac_cv_prog_CC="gcc"
- break
- fi
- done
- IFS="$ac_save_ifs"
- test -z "$ac_cv_prog_CC" && ac_cv_prog_CC="cc"
-fi
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_struct_st_blksize=no
fi
-CC="$ac_cv_prog_CC"
-if test -n "$CC"; then
- echo "$ac_t""$CC" 1>&6
-else
- echo "$ac_t""no" 1>&6
+rm -f conftest*
fi
+echo "$ac_t""$ac_cv_struct_st_blksize" 1>&6
+if test $ac_cv_struct_st_blksize = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_ST_BLKSIZE 1
+EOF
-echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
-if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
+fi
+
+echo $ac_n "checking for st_blocks in struct stat""... $ac_c" 1>&6
+echo "configure:1783: checking for st_blocks in struct stat" >&5
+if eval "test \"`echo '$''{'ac_cv_struct_st_blocks'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
- cat > conftest.c <<EOF
-#ifdef __GNUC__
- yes;
-#endif
+ cat > conftest.$ac_ext <<EOF
+#line 1788 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+int main() {
+struct stat s; s.st_blocks;
+; return 0; }
EOF
-if ${CC-cc} -E conftest.c 2>&5 | egrep yes >/dev/null 2>&1; then
- ac_cv_prog_gcc=yes
+if { (eval echo configure:1796: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_struct_st_blocks=yes
else
- ac_cv_prog_gcc=no
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_struct_st_blocks=no
fi
+rm -f conftest*
fi
-echo "$ac_t""$ac_cv_prog_gcc" 1>&6
-if test $ac_cv_prog_gcc = yes; then
- GCC=yes
- if test "${CFLAGS+set}" != set; then
- echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
-if eval "test \"`echo '$''{'ac_cv_prog_gcc_g'+set}'`\" = set"; then
+echo "$ac_t""$ac_cv_struct_st_blocks" 1>&6
+if test $ac_cv_struct_st_blocks = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_ST_BLOCKS 1
+EOF
+
+else
+ LIBOBJS="$LIBOBJS fileblocks.o"
+fi
+
+echo $ac_n "checking for st_rdev in struct stat""... $ac_c" 1>&6
+echo "configure:1819: checking for st_rdev in struct stat" >&5
+if eval "test \"`echo '$''{'ac_cv_struct_st_rdev'+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_gcc_g=yes
+ cat > conftest.$ac_ext <<EOF
+#line 1824 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+int main() {
+struct stat s; s.st_rdev;
+; return 0; }
+EOF
+if { (eval echo configure:1832: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_struct_st_rdev=yes
else
- ac_cv_prog_gcc_g=no
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_struct_st_rdev=no
fi
rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_struct_st_rdev" 1>&6
+if test $ac_cv_struct_st_rdev = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_ST_RDEV 1
+EOF
fi
-echo "$ac_t""$ac_cv_prog_gcc_g" 1>&6
- if test $ac_cv_prog_gcc_g = yes; then
- CFLAGS="-g -O"
- else
- CFLAGS="-O"
- fi
- fi
+echo $ac_n "checking whether struct tm is in sys/time.h or time.h""... $ac_c" 1>&6
+echo "configure:1853: checking whether struct tm is in sys/time.h or time.h" >&5
+if eval "test \"`echo '$''{'ac_cv_struct_tm'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
else
- GCC=
- test "${CFLAGS+set}" = set || CFLAGS="-g"
+ cat > conftest.$ac_ext <<EOF
+#line 1858 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <time.h>
+int main() {
+struct tm *tp; tp->tm_sec;
+; return 0; }
+EOF
+if { (eval echo configure:1866: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_struct_tm=time.h
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_struct_tm=sys/time.h
+fi
+rm -f conftest*
fi
+echo "$ac_t""$ac_cv_struct_tm" 1>&6
+if test $ac_cv_struct_tm = sys/time.h; then
+ cat >> confdefs.h <<\EOF
+#define TM_IN_SYS_TIME 1
+EOF
+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
-if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
+echo $ac_n "checking for tm_zone in struct tm""... $ac_c" 1>&6
+echo "configure:1887: checking for tm_zone in struct tm" >&5
+if eval "test \"`echo '$''{'ac_cv_struct_tm_zone'+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.
+ cat > conftest.$ac_ext <<EOF
+#line 1892 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <$ac_cv_struct_tm>
+int main() {
+struct tm tm; tm.tm_zone;
+; return 0; }
+EOF
+if { (eval echo configure:1900: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_struct_tm_zone=yes
else
- 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
- ac_cv_prog_RANLIB="ranlib"
- break
- fi
- done
- IFS="$ac_save_ifs"
- test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":"
-fi
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_struct_tm_zone=no
fi
-RANLIB="$ac_cv_prog_RANLIB"
-if test -n "$RANLIB"; then
- echo "$ac_t""$RANLIB" 1>&6
-else
- echo "$ac_t""no" 1>&6
+rm -f conftest*
fi
+echo "$ac_t""$ac_cv_struct_tm_zone" 1>&6
+if test "$ac_cv_struct_tm_zone" = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_TM_ZONE 1
+EOF
+else
+ echo $ac_n "checking for tzname""... $ac_c" 1>&6
+echo "configure:1920: checking for tzname" >&5
+if eval "test \"`echo '$''{'ac_cv_var_tzname'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1925 "configure"
+#include "confdefs.h"
+#include <time.h>
+#ifndef tzname /* For SGI. */
+extern char *tzname[]; /* RS6000 and others reject char **tzname. */
+#endif
+int main() {
+atoi(*tzname);
+; return 0; }
+EOF
+if { (eval echo configure:1935: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ ac_cv_var_tzname=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_var_tzname=no
+fi
+rm -f conftest*
+fi
+echo "$ac_t""$ac_cv_var_tzname" 1>&6
+ if test $ac_cv_var_tzname = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_TZNAME 1
+EOF
+ fi
+fi
+echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
+echo "configure:1958: 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 1973 "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:1979: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out`
+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 1990 "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:1996: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out`
+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*
+ 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 for uid_t in sys/types.h""... $ac_c" 1>&6
+echo "configure:2019: checking for uid_t in sys/types.h" >&5
+if eval "test \"`echo '$''{'ac_cv_type_uid_t'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2024 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "uid_t" >/dev/null 2>&1; then
+ rm -rf conftest*
+ ac_cv_type_uid_t=yes
+else
+ rm -rf conftest*
+ ac_cv_type_uid_t=no
+fi
+rm -f conftest*
+fi
+echo "$ac_t""$ac_cv_type_uid_t" 1>&6
+if test $ac_cv_type_uid_t = no; then
+ cat >> confdefs.h <<\EOF
+#define uid_t int
+EOF
+ cat >> confdefs.h <<\EOF
+#define gid_t int
+EOF
+fi
+echo $ac_n "checking type of array argument to getgroups""... $ac_c" 1>&6
+echo "configure:2053: checking type of array argument to getgroups" >&5
+if eval "test \"`echo '$''{'ac_cv_type_getgroups'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ ac_cv_type_getgroups=cross
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2061 "configure"
+#include "confdefs.h"
+/* Thanks to Mike Rendell for this test. */
+#include <sys/types.h>
+#define NGID 256
+#undef MAX
+#define MAX(x, y) ((x) > (y) ? (x) : (y))
+main()
+{
+ gid_t gidset[NGID];
+ int i, n;
+ union { gid_t gval; long lval; } val;
+
+ val.lval = -1;
+ for (i = 0; i < NGID; i++)
+ gidset[i] = val.gval;
+ n = getgroups (sizeof (gidset) / MAX (sizeof (int), sizeof (gid_t)) - 1,
+ gidset);
+ /* Exit non-zero if getgroups seems to require an array of ints. This
+ happens when gid_t is short but getgroups modifies an array of ints. */
+ exit ((n > 0 && gidset[n] != val.gval) ? 1 : 0);
+}
+EOF
+if { (eval echo configure:2086: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
+then
+ ac_cv_type_getgroups=gid_t
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_type_getgroups=int
+fi
+rm -fr conftest*
+fi
+if test $ac_cv_type_getgroups = cross; then
+ cat > conftest.$ac_ext <<EOF
+#line 2100 "configure"
+#include "confdefs.h"
+#include <unistd.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "getgroups.*int.*gid_t" >/dev/null 2>&1; then
+ rm -rf conftest*
+ ac_cv_type_getgroups=gid_t
+else
+ rm -rf conftest*
+ ac_cv_type_getgroups=int
+fi
+rm -f conftest*
+fi
+fi
+echo "$ac_t""$ac_cv_type_getgroups" 1>&6
+cat >> confdefs.h <<EOF
+#define GETGROUPS_T $ac_cv_type_getgroups
+EOF
+echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
+echo "configure:2124: 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 2129 "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:2137: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out`
+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 2154 "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 2172 "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 2193 "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:2204: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./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
-for ac_func in getrusage
-do
-echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+echo $ac_n "checking for mode_t""... $ac_c" 1>&6
+echo "configure:2228: checking for mode_t" >&5
+if eval "test \"`echo '$''{'ac_cv_type_mode_t'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1315 "configure"
+#line 2233 "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. */
-char $ac_func();
-
-int main() { return 0; }
-int t() {
-
-/* 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();
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
#endif
-
-; return 0; }
EOF
-if eval $ac_link; then
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "mode_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
rm -rf conftest*
- eval "ac_cv_func_$ac_func=yes"
+ ac_cv_type_mode_t=yes
else
rm -rf conftest*
- eval "ac_cv_func_$ac_func=no"
+ ac_cv_type_mode_t=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
+echo "$ac_t""$ac_cv_type_mode_t" 1>&6
+if test $ac_cv_type_mode_t = no; then
+ cat >> confdefs.h <<\EOF
+#define mode_t int
EOF
-
-else
- echo "$ac_t""no" 1>&6
-fi
-done
+fi
-# Put a plausible default for CC_FOR_BUILD in Makefile.
-# If we cannot run a trivial program, we must be cross compiling.
-echo $ac_n "checking whether cross-compiling""... $ac_c" 1>&6
-if eval "test \"`echo '$''{'ac_cv_c_cross'+set}'`\" = set"; then
+echo $ac_n "checking for off_t""... $ac_c" 1>&6
+echo "configure:2261: 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
- if test "$cross_compiling" = yes; then
- ac_cv_c_cross=yes
-else
-cat > conftest.$ac_ext <<EOF
-#line 1370 "configure"
+ cat > conftest.$ac_ext <<EOF
+#line 2266 "configure"
#include "confdefs.h"
-main(){return(0);}
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
EOF
-eval $ac_link
-if test -s conftest && (./conftest; exit) 2>/dev/null; then
- ac_cv_c_cross=no
+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
- ac_cv_c_cross=yes
-fi
+ rm -rf conftest*
+ ac_cv_type_off_t=no
fi
-rm -fr conftest*
+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
-echo "$ac_t""$ac_cv_c_cross" 1>&6
-cross_compiling=$ac_cv_c_cross
+fi
-if test "x$cross_compiling" = "xno"; then
- CC_FOR_BUILD='$(CC)'
+echo $ac_n "checking for pid_t""... $ac_c" 1>&6
+echo "configure:2294: checking for pid_t" >&5
+if eval "test \"`echo '$''{'ac_cv_type_pid_t'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
else
- CC_FOR_BUILD=gcc
+ cat > conftest.$ac_ext <<EOF
+#line 2299 "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 "pid_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
+ rm -rf conftest*
+ ac_cv_type_pid_t=yes
+else
+ rm -rf conftest*
+ ac_cv_type_pid_t=no
+fi
+rm -f conftest*
+
fi
+echo "$ac_t""$ac_cv_type_pid_t" 1>&6
+if test $ac_cv_type_pid_t = no; then
+ cat >> confdefs.h <<\EOF
+#define pid_t int
+EOF
+fi
-echo $ac_n "checking whether byte ordering is bigendian""... $ac_c" 1>&6
-if eval "test \"`echo '$''{'ac_cv_c_bigendian'+set}'`\" = set"; then
+echo $ac_n "checking return type of signal handlers""... $ac_c" 1>&6
+echo "configure:2327: 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
- ac_cv_c_bigendian=unknown
-# See if sys/param.h defines the BYTE_ORDER macro.
-cat > conftest.$ac_ext <<EOF
-#line 1401 "configure"
+ cat > conftest.$ac_ext <<EOF
+#line 2332 "configure"
#include "confdefs.h"
#include <sys/types.h>
-#include <sys/param.h>
-int main() { return 0; }
-int t() {
-
-#if !BYTE_ORDER || !BIG_ENDIAN || !LITTLE_ENDIAN
- bogus endian macros
+#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 $ac_compile; then
+if { (eval echo configure:2349: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
- # It does; now see whether it defined to BIG_ENDIAN or not.
-cat > conftest.$ac_ext <<EOF
-#line 1417 "configure"
+ 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 size_t""... $ac_c" 1>&6
+echo "configure:2368: 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 2373 "configure"
#include "confdefs.h"
#include <sys/types.h>
-#include <sys/param.h>
-int main() { return 0; }
-int t() {
-
-#if BYTE_ORDER != BIG_ENDIAN
- not big endian
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
#endif
-; return 0; }
EOF
-if eval $ac_compile; then
+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_c_bigendian=yes
+ ac_cv_type_size_t=yes
else
rm -rf conftest*
- ac_cv_c_bigendian=no
+ ac_cv_type_size_t=no
fi
rm -f conftest*
fi
-rm -f conftest*
+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
-if test $ac_cv_c_bigendian = unknown; then
-if test "$cross_compiling" = yes; then
- { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking for uid_t in sys/types.h""... $ac_c" 1>&6
+echo "configure:2401: checking for uid_t in sys/types.h" >&5
+if eval "test \"`echo '$''{'ac_cv_type_uid_t'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
else
-cat > conftest.$ac_ext <<EOF
-#line 1446 "configure"
+ cat > conftest.$ac_ext <<EOF
+#line 2406 "configure"
#include "confdefs.h"
-main () {
- /* Are we little or big endian? From Harbison&Steele. */
- union
- {
- long l;
- char c[sizeof (long)];
- } u;
- u.l = 1;
- exit (u.c[sizeof (long) - 1] == 1);
-}
+#include <sys/types.h>
EOF
-eval $ac_link
-if test -s conftest && (./conftest; exit) 2>/dev/null; then
- ac_cv_c_bigendian=no
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "uid_t" >/dev/null 2>&1; then
+ rm -rf conftest*
+ ac_cv_type_uid_t=yes
else
- ac_cv_c_bigendian=yes
-fi
-fi
-rm -fr conftest*
+ rm -rf conftest*
+ ac_cv_type_uid_t=no
fi
+rm -f conftest*
+
fi
-echo "$ac_t""$ac_cv_c_bigendian" 1>&6
-if test $ac_cv_c_bigendian = yes; then
+echo "$ac_t""$ac_cv_type_uid_t" 1>&6
+if test $ac_cv_type_uid_t = no; then
cat >> confdefs.h <<\EOF
-#define WORDS_BIGENDIAN 1
+#define uid_t int
EOF
-fi
+ cat >> confdefs.h <<\EOF
+#define gid_t int
+EOF
+fi
-echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
-# 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
+for ac_func in access cfgetispeed cfgetospeed cfsetispeed cfsetospeed chdir chmod chown dup dup2 fchmod fchown fcntl fstat fstatfs getdirentries getegid geteuid getgid getpid getppid getrusage gettimeofday getuid ioctl kill link lseek lstat mkdir pipe readlink rmdir setreuid setregid stat sigprocmask stat symlink tcgetattr tcsetattr tcsendbreak tcdrain tcflush tcflow tcgetpgrp tcsetpgrp time umask unlink
+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
- # 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 1495 "configure"
+#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>
-Syntax Error
+/* 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
-eval "$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-ac_err=`grep -v '^ *+' conftest.out`
-if test -z "$ac_err"; then
- :
-else
- echo "$ac_err" >&5
+if { (eval echo configure:2466: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
rm -rf conftest*
- CPP="${CC-cc} -E -traditional-cpp"
- cat > conftest.$ac_ext <<EOF
-#line 1509 "configure"
-#include "confdefs.h"
-#include <assert.h>
-Syntax Error
-EOF
-eval "$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-ac_err=`grep -v '^ *+' conftest.out`
-if test -z "$ac_err"; then
- :
+ eval "ac_cv_func_$ac_func=yes"
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*
+ eval "ac_cv_func_$ac_func=no"
fi
rm -f conftest*
- ac_cv_prog_CPP="$CPP"
fi
- CPP="$ac_cv_prog_CPP"
+
+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
- ac_cv_prog_CPP="$CPP"
+ echo "$ac_t""no" 1>&6
fi
-echo "$ac_t""$CPP" 1>&6
+done
+
-for ac_hdr in string.h strings.h stdlib.h time.h sys/mount.h sys/types.h sys/time.h sys/times.h unistd.h sys/resource.h
+for ac_hdr in fcntl.h stdlib.h string.h strings.h sys/ioctl.h sys/mount.h sys/param.h sys/resource.h sys/stat.h sys/termio.h sys/termios.h sys/time.h sys/times.h sys/types.h time.h unistd.h
do
-ac_safe=`echo "$ac_hdr" | tr './\055' '___'`
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:2495: 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 1542 "configure"
+#line 2500 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
-eval "$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:2505: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out`
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
@@ -1556,7 +2517,7 @@ 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 | tr 'abcdefghijklmnopqrstuvwxyz./\055' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ___'`
+ ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
cat >> confdefs.h <<EOF
#define $ac_tr_hdr 1
EOF
@@ -1569,34 +2530,35 @@ done
ac_header_dirent=no
for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h
do
-ac_safe=`echo "$ac_hdr" | tr './\055' '___'`
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr that defines DIR""... $ac_c" 1>&6
+echo "configure:2536: checking for $ac_hdr that defines DIR" >&5
if eval "test \"`echo '$''{'ac_cv_header_dirent_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1579 "configure"
+#line 2541 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <$ac_hdr>
-int main() { return 0; }
-int t() {
+int main() {
DIR *dirp = 0;
; return 0; }
EOF
-if eval $ac_compile; then
+if { (eval echo configure:2549: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
eval "ac_cv_header_dirent_$ac_safe=yes"
else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
rm -rf conftest*
eval "ac_cv_header_dirent_$ac_safe=no"
fi
rm -f conftest*
-
fi
if eval "test \"`echo '$ac_cv_header_dirent_'$ac_safe`\" = yes"; then
echo "$ac_t""yes" 1>&6
- ac_tr_hdr=HAVE_`echo $ac_hdr | tr 'abcdedfghijklmnopqrstuvwxyz./\055' 'ABCDEDFGHIJKLMNOPQRSTUVWXYZ___'`
+ ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
cat >> confdefs.h <<EOF
#define $ac_tr_hdr 1
EOF
@@ -1607,26 +2569,32 @@ fi
done
# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix.
if test $ac_header_dirent = dirent.h; then
-echo $ac_n "checking for -ldir""... $ac_c" 1>&6
-ac_lib_var=`echo dir | tr '.-/+' '___p'`
+echo $ac_n "checking for opendir in -ldir""... $ac_c" 1>&6
+echo "configure:2574: checking for opendir in -ldir" >&5
+ac_lib_var=`echo dir'_'opendir | 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="-ldir $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 1619 "configure"
+#line 2582 "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 opendir();
-int main() { return 0; }
-int t() {
+int main() {
opendir()
; return 0; }
EOF
-if eval $ac_link; then
+if { (eval echo configure:2593: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; 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
@@ -1642,26 +2610,32 @@ else
fi
else
-echo $ac_n "checking for -lx""... $ac_c" 1>&6
-ac_lib_var=`echo x | tr '.-/+' '___p'`
+echo $ac_n "checking for opendir in -lx""... $ac_c" 1>&6
+echo "configure:2615: checking for opendir in -lx" >&5
+ac_lib_var=`echo x'_'opendir | 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="-lx $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 1654 "configure"
+#line 2623 "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 opendir();
-int main() { return 0; }
-int t() {
+int main() {
opendir()
; return 0; }
EOF
-if eval $ac_link; then
+if { (eval echo configure:2634: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; 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
@@ -1679,6 +2653,294 @@ fi
fi
+sim_termio=""
+echo $ac_n "checking for struct termios""... $ac_c" 1>&6
+echo "configure:2659: checking for struct termios" >&5
+if eval "test \"`echo '$''{'ac_cv_termios_struct'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2664 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/termios.h>
+int main() {
+static struct termios x;
+ x.c_iflag = 0;
+ x.c_oflag = 0;
+ x.c_cflag = 0;
+ x.c_lflag = 0;
+ x.c_cc[NCCS] = 0;
+; return 0; }
+EOF
+if { (eval echo configure:2677: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_termios_struct=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_termios_struct=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_termios_struct" 1>&6
+if test $ac_cv_termios_struct = yes; then
+ sim_termio="$sim_termio -DHAVE_TERMIOS_STRUCTURE"
+fi
+
+if test "$ac_cv_termios_struct" = "yes"; then
+ echo $ac_n "checking for c_line field in struct termios""... $ac_c" 1>&6
+echo "configure:2696: checking for c_line field in struct termios" >&5
+ if eval "test \"`echo '$''{'ac_cv_termios_cline'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2701 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/termios.h>
+int main() {
+static struct termios x; x.c_line = 0;
+; return 0; }
+EOF
+if { (eval echo configure:2709: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_termios_cline=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_termios_cline=no
+fi
+rm -f conftest*
+fi
+
+
+ echo "$ac_t""$ac_cv_termios_cline" 1>&6
+ if test $ac_cv_termios_cline = yes; then
+ sim_termio="$sim_termio -DHAVE_TERMIOS_CLINE"
+ fi
+else
+ ac_cv_termios_cline=no
+fi
+
+if test "$ac_cv_termios_struct" != "yes"; then
+ echo $ac_n "checking for struct termio""... $ac_c" 1>&6
+echo "configure:2732: checking for struct termio" >&5
+ if eval "test \"`echo '$''{'ac_cv_termio_struct'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2737 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/termio.h>
+int main() {
+static struct termio x;
+ x.c_iflag = 0;
+ x.c_oflag = 0;
+ x.c_cflag = 0;
+ x.c_lflag = 0;
+ x.c_cc[NCC] = 0;
+; return 0; }
+EOF
+if { (eval echo configure:2750: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_termio_struct=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_termio_struct=no
+fi
+rm -f conftest*
+fi
+
+ echo "$ac_t""$ac_cv_termio_struct" 1>&6
+ if test $ac_cv_termio_struct = yes; then
+ sim_termio="$sim_termio -DHAVE_TERMIO_STRUCTURE"
+ fi
+else
+ ac_cv_termio_struct=no
+fi
+
+if test "$ac_cv_termio_struct" = "yes"; then
+ echo $ac_n "checking for c_line field in struct termio""... $ac_c" 1>&6
+echo "configure:2772: checking for c_line field in struct termio" >&5
+ if eval "test \"`echo '$''{'ac_cv_termio_cline'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2777 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/termio.h>
+int main() {
+static struct termio x; x.c_line = 0;
+; return 0; }
+EOF
+if { (eval echo configure:2785: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_termio_cline=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_termio_cline=no
+fi
+rm -f conftest*
+fi
+
+
+ echo "$ac_t""$ac_cv_termio_cline" 1>&6
+ if test $ac_cv_termio_cline = yes; then
+ sim_termio="$sim_termio -DHAVE_TERMIO_CLINE"
+ fi
+else
+ ac_cv_termio_cline=no
+fi
+
+sim_devzero=""
+echo $ac_n "checking for /dev/zero""... $ac_c" 1>&6
+echo "configure:2808: checking for /dev/zero" >&5
+if eval "test \"`echo '$''{'ac_cv_devzero'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ ac_cv_devzero=no
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2816 "configure"
+#include "confdefs.h"
+#include <fcntl.h>
+main () {
+ char buf[2048];
+ int i;
+ int fd = open ("/dev/zero", O_RDONLY);
+ if (fd < 0)
+ return 1;
+ for (i = 0; i < sizeof (buf); i++)
+ buf[i] = 1;
+ if (read (fd, buf, sizeof (buf)) != sizeof (buf))
+ return 1;
+ for (i = 0; i < sizeof (buf); i++)
+ if (buf[i])
+ return 1;
+ return 0;
+}
+EOF
+if { (eval echo configure:2835: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
+then
+ ac_cv_devzero=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_devzero=no
+fi
+rm -fr conftest*
+fi
+
+fi
+
+echo "$ac_t""$ac_cv_devzero" 1>&6
+if test $ac_cv_devzero = yes; then
+ sim_devzero="-DHAVE_DEVZERO"
+else
+ sim_devzero=""
+fi
+
+echo $ac_n "checking for common simulator directory""... $ac_c" 1>&6
+echo "configure:2857: checking for common simulator directory" >&5
+if test -f "${srcdir}/../common/callback.c"; then
+ echo "$ac_t""yes" 1>&6
+ sim_callback="callback.o targ-map.o"
+ sim_targ_vals="targ-vals.h targ-map.c targ-vals.def"
+else
+ echo "$ac_t""no" 1>&6
+ sim_callback=""
+ sim_targ_vals=""
+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:2876: 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="${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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
trap '' 1 2 15
cat > confcache <<\EOF
# This file is a shell script that caches the results of configure
@@ -1696,11 +2958,25 @@ cat > confcache <<\EOF
# --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 |
- sed -n "s/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=\${\1='\2'}/p" \
- >> confcache
+ case `(ac_space=' '; set) 2>&1` in
+ *ac_space=\ *)
+ # `set' does not quote correctly, so add quotes (double-quote substitution
+ # turns \\\\ into \\, and sed turns \\ into \).
+ sed -n \
+ -e "s/'/'\\\\''/g" \
+ -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
+ ;;
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
+ ;;
+ esac >> confcache
if cmp -s $cache_file confcache; then
:
else
@@ -1755,7 +3031,7 @@ do
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.7"
+ echo "$CONFIG_STATUS generated by autoconf version 2.12"
exit 0 ;;
-help | --help | --hel | --he | --h)
echo "\$ac_cs_usage"; exit 0 ;;
@@ -1764,6 +3040,7 @@ do
done
ac_given_srcdir=$srcdir
+ac_given_INSTALL="$INSTALL"
trap 'rm -fr `echo "Makefile config.h:config.in" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
EOF
@@ -1795,6 +3072,9 @@ s%@includedir@%$includedir%g
s%@oldincludedir@%$oldincludedir%g
s%@infodir@%$infodir%g
s%@mandir@%$mandir%g
+s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g
+s%@INSTALL_DATA@%$INSTALL_DATA%g
+s%@CC@%$CC%g
s%@host@%$host%g
s%@host_alias@%$host_alias%g
s%@host_cpu@%$host_cpu%g
@@ -1810,24 +3090,36 @@ 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%@LIBOBJS@%$LIBOBJS%g
+s%@CPP@%$CPP%g
+s%@CC_FOR_BUILD@%$CC_FOR_BUILD%g
s%@HDEFINES@%$HDEFINES%g
s%@AR@%$AR%g
s%@RANLIB@%$RANLIB%g
s%@sim_cflags@%$sim_cflags%g
s%@sim_warnings@%$sim_warnings%g
+s%@sim_line_nr@%$sim_line_nr%g
s%@sim_config@%$sim_config%g
s%@sim_opcode@%$sim_opcode%g
s%@sim_switch@%$sim_switch%g
s%@sim_dup@%$sim_dup%g
+s%@sim_decode_mechanism@%$sim_decode_mechanism%g
+s%@sim_jump@%$sim_jump%g
s%@sim_filter@%$sim_filter%g
s%@sim_icache@%$sim_icache%g
+s%@sim_hw_src@%$sim_hw_src%g
+s%@sim_hw_obj@%$sim_hw_obj%g
+s%@sim_pk_src@%$sim_pk_src%g
+s%@sim_pk_obj@%$sim_pk_obj%g
s%@sim_inline@%$sim_inline%g
s%@sim_bswap@%$sim_bswap%g
s%@sim_endian@%$sim_endian%g
+s%@sim_regparm@%$sim_regparm%g
+s%@sim_stdcall@%$sim_stdcall%g
s%@sim_xor_endian@%$sim_xor_endian%g
s%@sim_hostendian@%$sim_hostendian%g
s%@sim_smp@%$sim_smp%g
+s%@sim_igen_smp@%$sim_igen_smp%g
s%@sim_bitsize@%$sim_bitsize%g
s%@sim_hostbitsize@%$sim_hostbitsize%g
s%@sim_env@%$sim_env%g
@@ -1841,26 +3133,64 @@ s%@sim_monitor@%$sim_monitor%g
s%@sim_model@%$sim_model%g
s%@sim_default_model@%$sim_default_model%g
s%@sim_model_issue@%$sim_model_issue%g
-s%@CC_FOR_BUILD@%$CC_FOR_BUILD%g
-s%@WORDS_BIGENDIAN@%$WORDS_BIGENDIAN%g
-s%@CPP@%$CPP%g
+s%@sim_stdio@%$sim_stdio%g
+s%@sim_termio@%$sim_termio%g
+s%@sim_devzero@%$sim_devzero%g
+s%@sim_callback@%$sim_callback%g
+s%@sim_targ_vals@%$sim_targ_vals%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]", defaulting infile="outfile.in".
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
case "$ac_file" in
- *:*) ac_file_in=`echo "$ac_file"|sed 's%.*:%%'`
+ *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
*) ac_file_in="${ac_file}.in" ;;
esac
- # Adjust relative srcdir, etc. for subdirectories.
+ # 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%/[^/][^/]*$%%'`
@@ -1884,6 +3214,11 @@ for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
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."
@@ -1892,13 +3227,16 @@ for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
# $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
-" -f conftest.subs $ac_given_srcdir/$ac_file_in > $ac_file
+s%@INSTALL@%$INSTALL%g
+" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
fi; done
-rm -f conftest.subs
+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.
@@ -1919,11 +3257,17 @@ ac_eB='$%\1#\2define\3'
ac_eC=' '
ac_eD='%g'
-CONFIG_HEADERS=${CONFIG_HEADERS-"config.h:config.in"}
+if test "${CONFIG_HEADERS+set}" != set; then
+EOF
+cat >> $CONFIG_STATUS <<EOF
+ CONFIG_HEADERS="config.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]", defaulting infile="outfile.in".
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
case "$ac_file" in
- *:*) ac_file_in=`echo "$ac_file"|sed 's%.*:%%'`
+ *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
*) ac_file_in="${ac_file}.in" ;;
esac
@@ -1931,7 +3275,8 @@ for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then
echo creating $ac_file
rm -f conftest.frag conftest.in conftest.out
- cp $ac_given_srcdir/$ac_file_in conftest.in
+ 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
@@ -1943,7 +3288,7 @@ 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%#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
@@ -1959,8 +3304,6 @@ EOF
# Break up conftest.vals because some shells have a limit on
# the size of here documents, and old seds have small limits too.
-# Maximum number of lines to put in a single here document.
-ac_max_here_lines=12
rm -f conftest.tail
while :
@@ -1991,12 +3334,22 @@ cat >> $CONFIG_STATUS <<\EOF
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 xconfig.h:config.in) echo > stamp-h ;; esac
exit 0
EOF
diff --git a/gnu/dist/sim/ppc/configure.in b/gnu/dist/sim/ppc/configure.in
index 7df389f4b19..06e8d114dea 100644
--- a/gnu/dist/sim/ppc/configure.in
+++ b/gnu/dist/sim/ppc/configure.in
@@ -1,7 +1,67 @@
dnl Process this file with autoconf to produce a configure script.
-AC_PREREQ(2.3)dnl
+AC_PREREQ(2.5)dnl
AC_INIT(Makefile.in)
+AC_PROG_INSTALL
+AC_PROG_CC
+
+# Put a plausible default for CC_FOR_BUILD in Makefile.
+AC_C_CROSS
+if test "x$cross_compiling" = "xno"; then
+ CC_FOR_BUILD='$(CC)'
+else
+ CC_FOR_BUILD=gcc
+fi
+
+
+AC_ARG_ENABLE(sim-alignment,
+[ --enable-sim-alignment=align Specify strict or nonstrict alignment.],
+[case "${enableval}" in
+ yes | strict | STRICT) sim_alignment="-DWITH_ALIGNMENT=STRICT_ALIGNMENT";;
+ no | nonstrict | NONSTRICT) sim_alignment="-DWITH_ALIGNMENT=NONSTRICT_ALIGNMENT";;
+ 0 | default | DEFAULT) sim_alignment="-DWITH_ALIGNMENT=0";;
+ *) 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],[sim_alignment=""])dnl
+
+
+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_ARG_ENABLE(sim-bitsize,
+[ --enable-sim-bitsize=n Specify target bitsize (32 or 64).],
+[case "${enableval}" in
+ 32|64) sim_bitsize="-DWITH_TARGET_WORD_BITSIZE=$enableval";;
+ *) AC_MSG_ERROR("--enable-sim-bitsize was given $enableval. Expected 32 or 64"); sim_bitsize="";;
+esac
+if test x"$silent" != x"yes" && test x"$sim_bitsize" != x""; then
+ echo "Setting bitsize flags = $sim_bitsize" 6>&1
+fi],[sim_bitsize=""])dnl
+
+
+AC_ARG_ENABLE(sim-bswap,
+[ --enable-sim-bswap Use the BSWAP instruction on Intel 486s and Pentiums.],
+[case "${enableval}" in
+ yes) sim_bswap="-DWITH_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_ARG_ENABLE(sim-cflags,
[ --enable-sim-cflags=opts Extra CFLAGS for use in building simulator],
[case "${enableval}" in
@@ -13,16 +73,6 @@ 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_ARG_ENABLE(sim-warnings,
-[ --enable-sim-warnings=opts Extra CFLAGS for turning on compiler warnings except for idecode.o, semantics.o and psim.o],
-[case "${enableval}" in
- yes) sim_warnings="-Werror -Wall -Wpointer-arith -Wmissing-prototypes";;
- no) sim_warnings="-w";;
- *) sim_warnings=`echo "${enableval}" | sed -e "s/,/ /g"`;;
-esac
-if test x"$silent" != x"yes" && test x"$sim_warnings" != x""; then
- echo "Setting warning flags = $sim_warnings" 6>&1
-fi],[sim_warnings=""])dnl
AC_ARG_ENABLE(sim-config,
[ --enable-sim-config=file Override default config file],
@@ -44,84 +94,191 @@ if test x"$silent" != x"yes"; then
echo "Setting config flags = $sim_config" 6>&1
fi])dnl
-AC_ARG_ENABLE(sim-opcode,
-[ --enable-sim-opcode=which Override default opcode lookup.],
+
+AC_ARG_ENABLE(sim-decode-mechanism,
+[ --enable-sim-decode-mechanism=which Specify the instruction decode mechanism.],
[case "${enableval}" in
- yes|no) AC_MSG_ERROR("No value supplied for --enable-sim-opcode=file");;
- *) if test -f "${srcdir}/${enableval}"; then
- sim_opcode="${enableval}"
- elif test -f "${srcdir}/ppc-opcode-${enableval}"; then
- sim_opcode="ppc-opcode-${enableval}"
- else
- AC_MSG_ERROR("File $enableval is not an opcode rules file");
- sim_opcode="ppc-opcode-complex"
- fi;;
+ yes|no) AC_MSG_ERROR("No value supplied for --enable-sim-decode-mechanism=file");;
+ array|switch|padded-switch|goto-switch) sim_decode_mechanism="-T ${enableval}";;
+ *) AC_MSG_ERROR("File $enableval is not an opcode rules file");
+ sim_decode_mechanism="switch";;
esac
-if test x"$silent" != x"yes" && test x"$sim_opcode" != x""; then
- echo "Setting opcode flags = $sim_opcode" 6>&1
-fi],[sim_opcode="ppc-opcode-complex"
+if test x"$silent" != x"yes" && test x"$sim_decode_mechanism" != x""; then
+ echo "Setting decode mechanism flags = $sim_decode_mechanism" 6>&1
+fi],[sim_decode_mechanism=""
if test x"$silent" != x"yes"; then
- echo "Setting opcode flags = $sim_opcode"
+ echo "Setting decode mechanism flags = $sim_decode_mechanism"
fi])dnl
-AC_ARG_ENABLE(sim-switch,
-[ --enable-sim-switch Use a switch instead of a table for instruction call.],
+
+AC_ARG_ENABLE(sim-default-model,
+[ --enable-sim-default-model=which Specify default PowerPC to model.],
[case "${enableval}" in
- yes) sim_switch="-s";;
- no) sim_switch="";;
- *) AC_MSG_ERROR("--enable-sim-switch does not take a value"); sim_switch="";;
+ yes|no) AC_MSG_ERROR("No value supplied for --enable-sim-default-model=model");;
+ *) sim_default_model="-DWITH_DEFAULT_MODEL=${enableval}";;
esac
-if test x"$silent" != x"yes" && test x"$sim_switch" != x""; then
- echo "Setting switch flags = $sim_switch" 6>&1
-fi],[sim_switch="";
-if test x"$silent" != x"yes"; then
- echo "Setting switch flags = $sim_switch" 6>&1
-fi])dnl
+if test x"$silent" != x"yes" && test x"$sim_default_model" != x""; then
+ echo "Setting default-model flags = $sim_default_model" 6>&1
+fi],[sim_default_model=""])dnl
+
AC_ARG_ENABLE(sim-duplicate,
[ --enable-sim-duplicate Expand (duplicate) semantic functions.],
[case "${enableval}" in
- yes) sim_dup="-e";;
+ yes) sim_dup="-E";;
no) sim_dup="";;
*) AC_MSG_ERROR("--enable-sim-duplicate does not take a value"); sim_dup="";;
esac
if test x"$silent" != x"yes" && test x"$sim_dup" != x""; then
echo "Setting duplicate flags = $sim_dup" 6>&1
-fi],[sim_dup="-e"
+fi],[sim_dup="-E"
if test x"$silent" != x"yes"; then
echo "Setting duplicate flags = $sim_dup" 6>&1
fi])dnl
+
+AC_ARG_ENABLE(sim-endian,
+[ --enable-sim-endian=endian Specify target byte endian orientation.],
+[case "${enableval}" in
+ yes) case "$target" in
+ *powerpc-*) sim_endian="-DWITH_TARGET_BYTE_ORDER=BIG_ENDIAN";;
+ *powerpcle-*) sim_endian="-DWITH_TARGET_BYTE_ORDER=LITTLE_ENDIAN";;
+ *) echo "Unknown target $target" 1>&6; sim_endian="-DWITH_TARGET_BYTE_ORDER=0";;
+ esac;;
+ no) sim_endian="-DWITH_TARGET_BYTE_ORDER=0";;
+ b*|B*) sim_endian="-DWITH_TARGET_BYTE_ORDER=BIG_ENDIAN";;
+ l*|L*) sim_endian="-DWITH_TARGET_BYTE_ORDER=LITTLE_ENDIAN";;
+ *) 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],[sim_endian=""])dnl
+
+
+AC_ARG_ENABLE(sim-env,
+[ --enable-sim-env=env Specify target environment (operating, virtual, user).],
+[case "${enableval}" in
+ operating | os | oea) sim_env="-DWITH_ENVIRONMENT=OPERATING_ENVIRONMENT";;
+ virtual | vea) sim_env="-DWITH_ENVIRONMENT=VIRTUAL_ENVIRONMENT";;
+ user | uea) sim_env="-DWITH_ENVIRONMENT=USER_ENVIRONMENT";;
+ no) sim_env="-DWITH_ENVIRONMENT=0";;
+ *) AC_MSG_ERROR("Unknown value $enableval passed to --enable-sim-env"); sim_env="";;
+esac
+if test x"$silent" != x"yes" && test x"$sim_env" != x""; then
+ echo "Setting env flags = $sim_env" 6>&1
+fi],[sim_env=""])dnl
+
+
AC_ARG_ENABLE(sim-filter,
[ --enable-sim-filter=rule Specify filter rules.],
[case "${enableval}" in
yes) AC_MSG_ERROR("--enable-sim-filter must be specified with a rule to filter or no"); sim_filter="";;
no) sim_filter="";;
- *) sim_filter="-f $enableval";;
+ *) sim_filter="-F $enableval";;
esac
if test x"$silent" != x"yes" && test x"$sim_filter" != x""; then
echo "Setting filter flags = $sim_filter" 6>&1
-fi],[sim_filter="-f 64"
+fi],[sim_filter="-F 32,f,o"
if test x"$silent" != x"yes"; then
echo "Setting filter flags = $sim_filter" 6>&1
fi])dnl
-AC_ARG_ENABLE(sim-icache,
-[ --enable-sim-icache=size Specify instruction cache size.],
-icache=""
+
+AC_ARG_ENABLE(sim-float,
+[ --enable-sim-float Specify whether to use host floating point or simulate.],
+[case "${enableval}" in
+ yes | hard) sim_float="-DWITH_FLOATING_POINT=HARD_FLOATING_POINT";;
+ no | soft) sim_float="-DWITH_FLOATING_POINT=SOFT_FLOATING_POINT";;
+ *) 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=""])dnl
+
+
+AC_ARG_ENABLE(sim-hardware,
+[ --enable-sim-hardware=list Specify the hardware to be included in the build.],
+[hardware="cpu,memory,nvram,iobus,htab,disk,trace,register,vm,init,core,pal,com,eeprom,opic,glue,phb,ide"
+case "${enableval}" in
+ yes) ;;
+ no) AC_MSG_ERROR("List of hardware must be specified for --enable-sim-hardware"); hardware="";;
+ ,*) hardware="${hardware}${enableval}";;
+ *,) hardware="${enableval}${hardware}";;
+ *) hardware="${enableval}"'';;
+esac
+sim_hw_src=`echo $hardware | sed -e 's/,/.c hw_/g' -e 's/^/hw_/' -e s'/$/.c/'`
+sim_hw_obj=`echo $sim_hw_src | sed -e 's/\.c/.o/g'`
+if test x"$silent" != x"yes" && test x"$hardware" != x""; then
+ echo "Setting hardware to $sim_hw_src, $sim_hw_obj"
+fi],[hardware="cpu,memory,nvram,iobus,htab,disk,trace,register,vm,init,core,pal,com,eeprom,opic,glue,phb,ide"
+sim_hw_src=`echo $hardware | sed -e 's/,/.c hw_/g' -e 's/^/hw_/' -e s'/$/.c/'`
+sim_hw_obj=`echo $sim_hw_src | sed -e 's/\.c/.o/g'`
+if test x"$silent" != x"yes"; then
+ echo "Setting hardware to $sim_hw_src, $sim_hw_obj"
+fi])dnl
+
+
+AC_ARG_ENABLE(sim-hostbitsize,
+[ --enable-sim-hostbitsize=32|64 Specify host bitsize (32 or 64).],
+[case "${enableval}" in
+ 32|64) sim_hostbitsize="-DWITH_HOST_WORD_BITSIZE=$enableval";;
+ *) AC_MSG_ERROR("--enable-sim-hostbitsize was given $enableval. Expected 32 or 64"); sim_hostbitsize="";;
+esac
+if test x"$silent" != x"yes" && test x"$sim_hostbitsize" != x""; then
+ echo "Setting hostbitsize flags = $sim_hostbitsize" 6>&1
+fi],[sim_hostbitsize=""])dnl
+
+
+AC_ARG_ENABLE(sim-hostendian,
+[ --enable-sim-hostendian=end Specify host byte endian orientation.],
[case "${enableval}" in
- yes) sim_icache="-r 1024"; icache="1024";;
- define) sim_icache="-r 1024 -R"; icache="1024";;
- no) sim_icache="";;
- *) sim_icache="-r ${enableval}"; icache="${enableval}";;
+ 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_ARG_ENABLE(sim-icache,
+[ --enable-sim-icache=size Specify instruction-decode cache size and type.],
+[icache="-R"
+ case "${enableval}" in
+ yes) icache="1024"; sim_icache="-I $icache";;
+ no) sim_icache="-R";;
+ *) icache=1024
+ sim_icache="-"
+ for x in `echo "${enableval}" | sed -e "s/,/ /g"`; do
+ case "$x" in
+ define) sim_icache="${sim_icache}R";;
+ semantic) sim_icache="${sim_icache}C";;
+ insn) sim_icache="${sim_icache}S";;
+ 0*|1*|2*|3*|4*|5*|6*|7*|8*|9*) icache=$x;;
+ *) AC_MSG_ERROR("Unknown value $x for --enable-sim-icache"); sim_icache="";;
+ esac
+ done
+ sim_icache="${sim_icache}I $icache";;
esac
if test x"$silent" != x"yes" && test x"$icache" != x""; then
- echo "Setting instruction cache size to $icache"
-fi],[sim_icache="-r 1024"
+ echo "Setting instruction cache size to $icache ($sim_icache)"
+fi],[sim_icache="-CSRI 1024"
if test x"$silent" != x"yes"; then
- echo "Setting instruction cache size to 1024"
+ echo "Setting instruction cache size to 1024 ($sim_icache)"
fi])dnl
+
AC_ARG_ENABLE(sim-inline,
[ --enable-sim-inline=inlines Specify which functions should be inlined.],
[sim_inline=""
@@ -134,8 +291,8 @@ case "$enableval" in
new_flag=""
case "$x" in
*_INLINE=*) new_flag="-D$x";;
- *_INLINE) new_flag="-D$x=ALL_INLINE";;
*=*) new_flag=`echo "$x" | sed -e "s/=/_INLINE=/" -e "s/^/-D/"`;;
+ *_INLINE) new_flag="-D$x=ALL_INLINE";;
*) new_flag="-D$x""_INLINE=ALL_INLINE";;
esac
if test x"$sim_inline" = x""; then
@@ -156,103 +313,193 @@ else
sim_inline=""
fi])dnl
-AC_ARG_ENABLE(sim-bswap,
-[ --enable-sim-bswap Use the BSWAP instruction on Intel 486s and Pentiums.],
+
+AC_ARG_ENABLE(sim-jump,
+[ --enable-sim-jump Jump between semantic code (instead of call/return).],
[case "${enableval}" in
- yes) sim_bswap="-DWITH_BSWAP=1";;
- no) sim_bswap="-DWITH_BSWAP=0";;
- *) AC_MSG_ERROR("--enable-sim-bswap does not take a value"); sim_bswap="";;
+ yes) sim_jump="-J";;
+ no) sim_jump="";;
+ *) AC_MSG_ERROR("--enable-sim-jump does not take a value"); sim_jump="";;
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
+if test x"$silent" != x"yes" && test x"$sim_jump" != x""; then
+ echo "Setting jump flag = $sim_jump" 6>&1
+fi],[sim_jump=""
+if test x"$silent" != x"yes"; then
+ echo "Setting jump flag = $sim_jump" 6>&1
+fi])dnl
-AC_ARG_ENABLE(sim-endian,
-[ --enable-sim-endian=endian Specify target byte endian orientation.],
+
+AC_ARG_ENABLE(sim-line-nr,
+[ --enable-sim-line-nr=opts Generate extra CPP code that references source rather than generated code],
[case "${enableval}" in
- yes) case "$target" in
- *powerpc-*) sim_endian="-DWITH_TARGET_BYTE_ORDER=BIG_ENDIAN";;
- *powerpcle-*) sim_endian="-DWITH_TARGET_BYTE_ORDER=LITTLE_ENDIAN";;
- *) echo "Unknown target $target" 1>&6; sim_endian="-DWITH_TARGET_BYTE_ORDER=0";;
- esac;;
- no) sim_endian="-DWITH_TARGET_BYTE_ORDER=0";;
- b*|B*) sim_endian="-DWITH_TARGET_BYTE_ORDER=BIG_ENDIAN";;
- l*|L*) sim_endian="-DWITH_TARGET_BYTE_ORDER=LITTLE_ENDIAN";;
- *) AC_MSG_ERROR("Unknown value $enableval for --enable-sim-endian"); sim_endian="";;
+ yes) sim_line_nr="";;
+ no) sim_line_nr="-L";;
+ *) AC_MSG_ERROR("--enable-sim-line-nr does not take a value"); sim_line_nr="";;
esac
-if test x"$silent" != x"yes" && test x"$sim_endian" != x""; then
- echo "Setting endian flags = $sim_endian" 6>&1
-fi],[sim_endian=""])dnl
+if test x"$silent" != x"yes" && test x"$sim_line_nr" != x""; then
+ echo "Setting warning flags = $sim_line_nr" 6>&1
+fi],[sim_line_nr=""])dnl
-AC_ARG_ENABLE(sim-hostendian,
-[ --enable-sim-hostendain=end Specify host byte endian orientation.],
+
+AC_ARG_ENABLE(sim-model,
+[ --enable-sim-model=which Specify PowerPC to model.],
[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="";;
+ yes|no) AC_MSG_ERROR("No value supplied for --enable-sim-model=model");;
+ *) sim_model="-DWITH_MODEL=${enableval}";;
esac
-if test x"$silent" != x"yes" && test x"$sim_hostendian" != x""; then
- echo "Setting hostendian flags = $sim_hostendian" 6>&1
-fi],[sim_hostendian=""])dnl
+if test x"$silent" != x"yes" && test x"$sim_model" != x""; then
+ echo "Setting model flags = $sim_model" 6>&1
+fi],[sim_model=""])dnl
+
+
+AC_ARG_ENABLE(sim-model-issue,
+[ --enable-sim-model-issue Specify whether to simulate model specific actions],
+[case "${enableval}" in
+ yes) sim_model_issue="-DWITH_MODEL_ISSUE=MODEL_ISSUE_PROCESS";;
+ no) sim_model_issue="-DWITH_MODEL_ISSUE=MODEL_ISSUE_IGNORE";;
+ *) AC_MSG_ERROR("--enable-sim-model-issue does not take a value"); sim_model_issue="";;
+esac
+if test x"$silent" != x"yes"; then
+ echo "Setting model-issue flags = $sim_model_issue" 6>&1
+fi],[sim_model_issue=""])dnl
+
+
+AC_ARG_ENABLE(sim-monitor,
+[ --enable-sim-monitor=mon Specify whether to enable monitoring events.],
+[case "${enableval}" in
+ yes) sim_monitor="-DWITH_MON='MONITOR_INSTRUCTION_ISSUE | MONITOR_LOAD_STORE_UNIT'";;
+ no) sim_monitor="-DWITH_MON=0";;
+ instruction) sim_monitor="-DWITH_MON=MONITOR_INSTRUCTION_ISSUE";;
+ memory) sim_monitor="-DWITH_MON=MONITOR_LOAD_STORE_UNIT";;
+ *) AC_MSG_ERROR("Unknown value $enableval passed to --enable-sim-mon"); sim_env="";;
+esac
+if test x"$silent" != x"yes" && test x"$sim_monitor" != x""; then
+ echo "Setting monitor flags = $sim_monitor" 6>&1
+fi],[sim_monitor=""])dnl
+
+
+AC_ARG_ENABLE(sim-opcode,
+[ --enable-sim-opcode=which Override default opcode lookup.],
+[case "${enableval}" in
+ yes|no) AC_MSG_ERROR("No value supplied for --enable-sim-opcode=file");;
+ *) if test -f "${srcdir}/${enableval}"; then
+ sim_opcode="${enableval}"
+ elif test -f "${srcdir}/dc-${enableval}"; then
+ sim_opcode="dc-${enableval}"
+ else
+ AC_MSG_ERROR("File $enableval is not an opcode rules file");
+ sim_opcode="dc-complex"
+ fi;;
+esac
+if test x"$silent" != x"yes" && test x"$sim_opcode" != x""; then
+ echo "Setting opcode flags = $sim_opcode" 6>&1
+fi],[sim_opcode="dc-complex"
+if test x"$silent" != x"yes"; then
+ echo "Setting opcode flags = $sim_opcode"
+fi])dnl
+
+
+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_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_ARG_ENABLE(sim-reserved-bits,
+[ --enable-sim-reserved-bits Specify whether to check reserved bits in instruction.],
+[case "${enableval}" in
+ yes) sim_reserved="-DWITH_RESERVED_BITS=1";;
+ no) sim_reserved="-DWITH_RESERVED_BITS=0";;
+ *) AC_MSG_ERROR("--enable-sim-reserved-bits does not take a value"); sim_reserved="";;
+esac
+if test x"$silent" != x"yes" && test x"$sim_reserved" != x""; then
+ echo "Setting reserved flags = $sim_reserved" 6>&1
+fi],[sim_reserved=""])dnl
+
AC_ARG_ENABLE(sim-smp,
[ --enable-sim-smp=n Specify number of processors to configure for.],
[case "${enableval}" in
- yes) sim_smp="-DWITH_SMP=5";;
- no) sim_smp="-DWITH_SMP=0";;
- *) sim_smp="-DWITH_SMP=$enableval";;
+ 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=5"
+fi],[sim_smp="-DWITH_SMP=5" ; sim_igen_smp="-N 5"
if test x"$silent" != x"yes"; then
echo "Setting smp flags = $sim_smp" 6>&1
fi])dnl
-AC_ARG_ENABLE(sim-xor-endian,
-[ --enable-sim-xor-endian=n Specify number bytes involved in PowerPC XOR bi-endian mode (default 8).],
-[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=""])dnl
-AC_ARG_ENABLE(sim-bitsize,
-[ --enable-sim-bitsize=n Specify target bitsize (32 or 64).],
+AC_ARG_ENABLE(sim-stdcall,
+[ --enable-sim-stdcall=type Use an alternative function call/return mechanism - x86/GCC specific.],
[case "${enableval}" in
- 32|64) sim_bitsize="-DWITH_TARGET_WORD_BITSIZE=$enableval";;
- *) AC_MSG_ERROR("--enable-sim-bitsize was given $enableval, expected 32 or 64"); sim_bitsize="";;
+ 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_bitsize" != x""; then
- echo "Setting bitsize flags = $sim_bitsize" 6>&1
-fi],[sim_bitsize=""])dnl
+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_ARG_ENABLE(sim-hostbitsize,
-[ --enable-sim-hostbitsize=32|64 Specify host bitsize (32 or 64).],
+
+AC_ARG_ENABLE(sim-stdio,
+[ --enable-sim-stdio Specify whether to use stdio for console input/output.],
[case "${enableval}" in
- 32|64) sim_hostbitsize="-DWITH_HOST_WORD_BITSIZE=$enableval";;
- *) AC_MSG_ERROR("--enable-sim-hostbitsize was given $enableval, expected 32 or 64"); sim_hostbitsize="";;
+ 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_hostbitsize" != x""; then
- echo "Setting hostbitsize flags = $sim_hostbitsize" 6>&1
-fi],[sim_hostbitsize=""])dnl
+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_ARG_ENABLE(sim-env,
-[ --enable-sim-env=env Specify target environment (operating, virtual, user).],
+
+AC_ARG_ENABLE(sim-switch,
+[ --enable-sim-switch Use a switch instead of a table for instruction call.],
[case "${enableval}" in
- operating | os | oea) sim_env="-DWITH_ENVIRONMENT=OPERATING_ENVIRONMENT";;
- virtual | vea) sim_env="-DWITH_ENVIRONMENT=VIRTUAL_ENVIRONMENT";;
- user | uea) sim_env="-DWITH_ENVIRONMENT=USER_ENVIRONMENT";;
- no) sim_env="-DWITH_ENVIRONMENT=0";;
- *) AC_MSG_ERROR("Unknown value $enableval passed to --enable-sim-env"); sim_env="";;
+ yes) sim_switch="-s";;
+ no) sim_switch="";;
+ *) AC_MSG_ERROR("--enable-sim-switch does not take a value"); sim_switch="";;
esac
-if test x"$silent" != x"yes" && test x"$sim_env" != x""; then
- echo "Setting env flags = $sim_env" 6>&1
-fi],[sim_env=""])dnl
+if test x"$silent" != x"yes" && test x"$sim_switch" != x""; then
+ echo "Setting switch flags = $sim_switch" 6>&1
+fi],[sim_switch="";
+if test x"$silent" != x"yes"; then
+ echo "Setting switch flags = $sim_switch" 6>&1
+fi])dnl
+
AC_ARG_ENABLE(sim-timebase,
[ --enable-sim-timebase Specify whether the PPC timebase is supported.],
@@ -265,16 +512,6 @@ if test x"$silent" != x"yes" && test x"$sim_timebase" != x""; then
echo "Setting timebase flags = $sim_timebase" 6>&1
fi],[sim_timebase=""])dnl
-AC_ARG_ENABLE(sim-alignment,
-[ --enable-sim-alignment=align Specify strict or nonstrict alignment.],
-[case "${enableval}" in
- yes | strict | STRICT) sim_alignment="-DWITH_ALIGNMENT=STRICT_ALIGNMENT";;
- no | nonstrict | NONSTRICT) sim_alignment="-DWITH_ALIGNMENT=NONSTRICT_ALIGNMENT";;
- *) 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],[sim_alignment=""])dnl
AC_ARG_ENABLE(sim-trace,
[ --enable-sim-trace Specify whether tracing is supported.],
@@ -287,82 +524,30 @@ if test x"$silent" != x"yes" && test x"$sim_trace" != x""; then
echo "Setting trace flags = $sim_trace" 6>&1
fi],[sim_trace=""])dnl
-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_ARG_ENABLE(sim-reserved-bits,
-[ --enable-sim-reserved-bits Specify whether to check reserved bits in instruction.],
-[case "${enableval}" in
- yes) sim_reserved="-DWITH_RESERVED_BITS=1";;
- no) sim_reserved="-DWITH_RESERVED_BITS=0";;
- *) AC_MSG_ERROR("--enable-sim-reserved-bits does not take a value"); sim_reserved="";;
-esac
-if test x"$silent" != x"yes" && test x"$sim_reserved" != x""; then
- echo "Setting reserved flags = $sim_reserved" 6>&1
-fi],[sim_reserved=""])dnl
-AC_ARG_ENABLE(sim-float,
-[ --enable-sim-float Specify whether to use host floating point or simulate.],
-[case "${enableval}" in
- yes | hard) sim_float="-DWITH_FLOATING_POINT=HARD_FLOATING_POINT";;
- no | soft) sim_float="-DWITH_FLOATING_POINT=SOFT_FLOATING_POINT";;
- *) 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=""])dnl
-
-AC_ARG_ENABLE(sim-monitor,
-[ --enable-sim-monitor=mon Specify whether to enable monitoring events.],
+AC_ARG_ENABLE(sim-warnings,
+[ --enable-sim-warnings=opts Extra CFLAGS for turning on compiler warnings except for idecode.o, semantics.o and psim.o],
[case "${enableval}" in
- yes) sim_monitor="-DWITH_MON='MONITOR_INSTRUCTION_ISSUE | MONITOR_LOAD_STORE_UNIT'";;
- no) sim_monitor="-DWITH_MON=0";;
- instruction) sim_monitor="-DWITH_MON=MONITOR_INSTRUCTION_ISSUE";;
- memory) sim_monitor="-DWITH_MON=MONITOR_LOAD_STORE_UNIT";;
- *) AC_MSG_ERROR("Unknown value $enableval passed to --enable-sim-mon"); sim_env="";;
+ yes) sim_warnings="-Werror -Wall -Wpointer-arith -Wmissing-prototypes -Wmissing-declarations ";;
+ no) sim_warnings="-w";;
+ *) sim_warnings=`echo "${enableval}" | sed -e "s/,/ /g"`;;
esac
-if test x"$silent" != x"yes" && test x"$sim_monitor" != x""; then
- echo "Setting monitor flags = $sim_monitor" 6>&1
-fi],[sim_monitor=""])dnl
+if test x"$silent" != x"yes" && test x"$sim_warnings" != x""; then
+ echo "Setting warning flags = $sim_warnings" 6>&1
+fi],[sim_warnings=""])dnl
-AC_ARG_ENABLE(sim-model,
-[ --enable-sim-model=which Specify PowerPC to model.],
-[case "${enableval}" in
- yes|no) AC_MSG_ERROR("No value supplied for --enable-sim-model=model");;
- *) sim_model="-DWITH_MODEL=${enableval}";;
-esac
-if test x"$silent" != x"yes" && test x"$sim_model" != x""; then
- echo "Setting model flags = $sim_model" 6>&1
-fi],[sim_model=""])dnl
-AC_ARG_ENABLE(sim-default-model,
-[ --enable-sim-default-model=which Specify default PowerPC to model.],
+AC_ARG_ENABLE(sim-xor-endian,
+[ --enable-sim-xor-endian=n Specify number bytes involved in PowerPC XOR bi-endian mode (default 8).],
[case "${enableval}" in
- yes|no) AC_MSG_ERROR("No value supplied for --enable-sim-default-model=model");;
- *) sim_default_model="-DWITH_DEFAULT_MODEL=${enableval}";;
+ 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_default_model" != x""; then
- echo "Setting default-model flags = $sim_default_model" 6>&1
-fi],[sim_model=""])dnl
+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=""])dnl
-AC_ARG_ENABLE(sim-model-issue,
-[ --enable-sim-model-issue Specify whether to simulate model specific actions],
-[case "${enableval}" in
- yes) sim_model_issue="-DWITH_MODEL_ISSUE=MODEL_ISSUE_PROCESS";;
- no) sim_model_issue="-DWITH_MODEL_ISSUE=MODEL_ISSUE_IGNORE";;
- *) AC_MSG_ERROR("--enable-sim-model-issue does not take a value"); sim_model_issue="";;
-esac
-if test x"$silent" != x"yes"; then
- echo "Setting model-issue flags = $sim_model_issue" 6>&1
-fi],[sim_model_issue=""])dnl
AC_CONFIG_AUX_DIR(`cd $srcdir;pwd`/../..)
AC_CANONICAL_SYSTEM
@@ -372,7 +557,134 @@ AC_ARG_PROGRAM
AC_CONFIG_HEADER(config.h:config.in)
-AC_PROG_CC
+AC_STRUCT_ST_BLKSIZE
+AC_STRUCT_ST_BLOCKS
+AC_STRUCT_ST_RDEV
+AC_STRUCT_TIMEZONE
+
+AC_TYPE_GETGROUPS
+AC_TYPE_MODE_T
+AC_TYPE_OFF_T
+AC_TYPE_PID_T
+AC_TYPE_SIGNAL
+AC_TYPE_SIZE_T
+AC_TYPE_UID_T
+
+AC_CHECK_FUNCS(access cfgetispeed cfgetospeed cfsetispeed cfsetospeed chdir chmod chown dup dup2 fchmod fchown fcntl fstat fstatfs getdirentries getegid geteuid getgid getpid getppid getrusage gettimeofday getuid ioctl kill link lseek lstat mkdir pipe readlink rmdir setreuid setregid stat sigprocmask stat symlink tcgetattr tcsetattr tcsendbreak tcdrain tcflush tcflow tcgetpgrp tcsetpgrp time umask unlink)
+
+AC_CHECK_HEADERS(fcntl.h stdlib.h string.h strings.h sys/ioctl.h sys/mount.h sys/param.h sys/resource.h sys/stat.h sys/termio.h sys/termios.h sys/time.h sys/times.h sys/types.h time.h unistd.h)
+AC_HEADER_DIRENT
+
+dnl Figure out what type of termio/termios support there is
+sim_termio=""
+AC_MSG_CHECKING(for struct termios)
+AC_CACHE_VAL(ac_cv_termios_struct,
+[AC_TRY_COMPILE([#include <sys/types.h>
+#include <sys/termios.h>],
+[static struct termios x;
+ x.c_iflag = 0;
+ x.c_oflag = 0;
+ x.c_cflag = 0;
+ x.c_lflag = 0;
+ x.c_cc[NCCS] = 0;],
+ac_cv_termios_struct=yes, ac_cv_termios_struct=no)])
+AC_MSG_RESULT($ac_cv_termios_struct)
+if test $ac_cv_termios_struct = yes; then
+ sim_termio="$sim_termio -DHAVE_TERMIOS_STRUCTURE"
+fi
+
+if test "$ac_cv_termios_struct" = "yes"; then
+ AC_MSG_CHECKING(for c_line field in struct termios)
+ AC_CACHE_VAL(ac_cv_termios_cline,
+ [AC_TRY_COMPILE([#include <sys/types.h>
+#include <sys/termios.h>],
+[static struct termios x; x.c_line = 0;],
+ ac_cv_termios_cline=yes, ac_cv_termios_cline=no)])
+
+ AC_MSG_RESULT($ac_cv_termios_cline)
+ if test $ac_cv_termios_cline = yes; then
+ sim_termio="$sim_termio -DHAVE_TERMIOS_CLINE"
+ fi
+else
+ ac_cv_termios_cline=no
+fi
+
+if test "$ac_cv_termios_struct" != "yes"; then
+ AC_MSG_CHECKING(for struct termio)
+ AC_CACHE_VAL(ac_cv_termio_struct,
+ [AC_TRY_COMPILE([#include <sys/types.h>
+#include <sys/termio.h>],
+[static struct termio x;
+ x.c_iflag = 0;
+ x.c_oflag = 0;
+ x.c_cflag = 0;
+ x.c_lflag = 0;
+ x.c_cc[NCC] = 0;],
+ac_cv_termio_struct=yes, ac_cv_termio_struct=no)])
+ AC_MSG_RESULT($ac_cv_termio_struct)
+ if test $ac_cv_termio_struct = yes; then
+ sim_termio="$sim_termio -DHAVE_TERMIO_STRUCTURE"
+ fi
+else
+ ac_cv_termio_struct=no
+fi
+
+if test "$ac_cv_termio_struct" = "yes"; then
+ AC_MSG_CHECKING(for c_line field in struct termio)
+ AC_CACHE_VAL(ac_cv_termio_cline,
+ [AC_TRY_COMPILE([#include <sys/types.h>
+#include <sys/termio.h>],
+[static struct termio x; x.c_line = 0;],
+ ac_cv_termio_cline=yes, ac_cv_termio_cline=no)])
+
+ AC_MSG_RESULT($ac_cv_termio_cline)
+ if test $ac_cv_termio_cline = yes; then
+ sim_termio="$sim_termio -DHAVE_TERMIO_CLINE"
+ fi
+else
+ ac_cv_termio_cline=no
+fi
+
+dnl Figure out if /dev/zero exists or not
+sim_devzero=""
+AC_MSG_CHECKING(for /dev/zero)
+AC_CACHE_VAL(ac_cv_devzero,
+[AC_TRY_RUN([#include <fcntl.h>
+main () {
+ char buf[2048];
+ int i;
+ int fd = open ("/dev/zero", O_RDONLY);
+ if (fd < 0)
+ return 1;
+ for (i = 0; i < sizeof (buf); i++)
+ buf[i] = 1;
+ if (read (fd, buf, sizeof (buf)) != sizeof (buf))
+ return 1;
+ for (i = 0; i < sizeof (buf); i++)
+ if (buf[i])
+ return 1;
+ return 0;
+}],[ac_cv_devzero=yes],[ac_cv_devzero=no],[ac_cv_devzero=no])])
+AC_MSG_RESULT($ac_cv_devzero)
+if test $ac_cv_devzero = yes; then
+ sim_devzero="-DHAVE_DEVZERO"
+else
+ sim_devzero=""
+fi
+
+dnl Figure out if we are in the new Cygnus tree with a common directory or not
+AC_MSG_CHECKING(for common simulator directory)
+if test -f "${srcdir}/../common/callback.c"; then
+ AC_MSG_RESULT(yes)
+ sim_callback="callback.o targ-map.o"
+ sim_targ_vals="targ-vals.h targ-map.c targ-vals.def"
+else
+ AC_MSG_RESULT(no)
+ sim_callback=""
+ sim_targ_vals=""
+fi
+
+AC_SUBST(CC_FOR_BUILD)
AC_SUBST(CFLAGS)
AC_SUBST(HDEFINES)
AR=${AR-ar}
@@ -380,18 +692,28 @@ AC_SUBST(AR)
AC_PROG_RANLIB
AC_SUBST(sim_cflags)
AC_SUBST(sim_warnings)
+AC_SUBST(sim_line_nr)
AC_SUBST(sim_config)
AC_SUBST(sim_opcode)
AC_SUBST(sim_switch)
AC_SUBST(sim_dup)
+AC_SUBST(sim_decode_mechanism)
+AC_SUBST(sim_jump)
AC_SUBST(sim_filter)
AC_SUBST(sim_icache)
+AC_SUBST(sim_hw_src)
+AC_SUBST(sim_hw_obj)
+AC_SUBST(sim_pk_src)
+AC_SUBST(sim_pk_obj)
AC_SUBST(sim_inline)
AC_SUBST(sim_bswap)
AC_SUBST(sim_endian)
+AC_SUBST(sim_regparm)
+AC_SUBST(sim_stdcall)
AC_SUBST(sim_xor_endian)
AC_SUBST(sim_hostendian)
AC_SUBST(sim_smp)
+AC_SUBST(sim_igen_smp)
AC_SUBST(sim_bitsize)
AC_SUBST(sim_hostbitsize)
AC_SUBST(sim_env)
@@ -405,23 +727,11 @@ AC_SUBST(sim_monitor)
AC_SUBST(sim_model)
AC_SUBST(sim_default_model)
AC_SUBST(sim_model_issue)
-
-AC_CHECK_FUNCS(getrusage)
-
-# Put a plausible default for CC_FOR_BUILD in Makefile.
-AC_C_CROSS
-if test "x$cross_compiling" = "xno"; then
- CC_FOR_BUILD='$(CC)'
-else
- CC_FOR_BUILD=gcc
-fi
-AC_SUBST(CC_FOR_BUILD)
-
-AC_C_BIGENDIAN
-AC_SUBST(WORDS_BIGENDIAN)
-
-AC_CHECK_HEADERS(string.h strings.h stdlib.h time.h sys/mount.h sys/types.h sys/time.h sys/times.h unistd.h sys/resource.h)
-AC_HEADER_DIRENT
+AC_SUBST(sim_stdio)
+AC_SUBST(sim_termio)
+AC_SUBST(sim_devzero)
+AC_SUBST(sim_callback)
+AC_SUBST(sim_targ_vals)
AC_OUTPUT(Makefile,
[case x$CONFIG_HEADERS in xconfig.h:config.in) echo > stamp-h ;; esac])
diff --git a/gnu/dist/sim/ppc/corefile-n.h b/gnu/dist/sim/ppc/corefile-n.h
index d93ed7e09cf..0e4cae8fcbc 100644
--- a/gnu/dist/sim/ppc/corefile-n.h
+++ b/gnu/dist/sim/ppc/corefile-n.h
@@ -52,7 +52,7 @@ core_map_read_N(core_map *map,
sizeof(unsigned_N), /* nr_bytes */
processor,
cia) != sizeof(unsigned_N))
- error("core_read_,N() reader should not fail\n");
+ device_error(mapping->device, "internal error - core_read_N() - io_read_buffer should not fail");
return T2H_N(data);
}
else
@@ -83,7 +83,7 @@ core_map_write_N(core_map *map,
sizeof(unsigned_N), /* nr_bytes */
processor,
cia) != sizeof(unsigned_N))
- error("core_read_,N() writer should not fail\n");
+ device_error(mapping->device, "internal error - core_write_N() - io_write_buffer should not fail");
}
else
*(unsigned_N*)core_translate(mapping, addr) = H2T_N(val);
diff --git a/gnu/dist/sim/ppc/corefile.c b/gnu/dist/sim/ppc/corefile.c
index a33434898ec..835625e6e6e 100644
--- a/gnu/dist/sim/ppc/corefile.c
+++ b/gnu/dist/sim/ppc/corefile.c
@@ -26,25 +26,25 @@
#include "device_table.h"
#include "corefile.h"
-
typedef struct _core_mapping core_mapping;
struct _core_mapping {
- /* ram map */
- int free_buffer;
- void *buffer;
- /* device map */
- device *device;
/* common */
+ int level;
int space;
unsigned_word base;
unsigned_word bound;
unsigned nr_bytes;
+ /* memory map */
+ int free_buffer;
+ void *buffer;
+ /* callback map */
+ device *device;
+ /* growth */
core_mapping *next;
};
struct _core_map {
core_mapping *first;
- core_mapping *default_map;
};
typedef enum {
@@ -61,15 +61,23 @@ struct _core {
INLINE_CORE\
(core *)
-core_create(device *root)
+core_create(void)
{
- root = device_tree_find_device(root, "/");
+ return ZALLOC(core);
+}
+
+
+INLINE_CORE\
+(core *)
+core_from_device(device *root)
+{
+ root = device_root(root);
ASSERT(strcmp(device_name(root), "core") == 0);
return device_data(root);
}
-STATIC_INLINE_CORE\
+INLINE_CORE\
(void)
core_init(core *memory)
{
@@ -90,12 +98,6 @@ core_init(core *memory)
zfree(tbd);
}
map->first = NULL;
- /* blow away the default */
- if (map->default_map != NULL) {
- ASSERT(map->default_map->buffer == NULL);
- zfree(map->default_map);
- }
- map->default_map = NULL;
}
}
@@ -138,24 +140,23 @@ new_core_mapping(attach_type attach,
int free_buffer)
{
core_mapping *new_mapping = ZALLOC(core_mapping);
- switch (attach) {
- case attach_default:
- case attach_callback:
- new_mapping->device = device;
- break;
- case attach_raw_memory:
- new_mapping->buffer = buffer;
- new_mapping->free_buffer = free_buffer;
- break;
- default:
- error("new_core_mapping() - internal error - unknown attach type %d\n",
- attach);
- }
/* common */
+ new_mapping->level = attach;
new_mapping->space = space;
new_mapping->base = addr;
new_mapping->nr_bytes = nr_bytes;
new_mapping->bound = addr + (nr_bytes - 1);
+ if (attach == attach_raw_memory) {
+ new_mapping->buffer = buffer;
+ new_mapping->free_buffer = free_buffer;
+ }
+ else if (attach >= attach_callback) {
+ new_mapping->device = device;
+ }
+ else {
+ error("new_core_mapping() - internal error - unknown attach type %d\n",
+ attach);
+ }
return new_mapping;
}
@@ -167,48 +168,46 @@ core_map_attach(core_map *access_map,
int space,
unsigned_word addr,
unsigned nr_bytes, /* host limited */
- device *device, /*callback/default*/
+ device *client, /*callback/default*/
void *buffer, /*raw_memory*/
int free_buffer) /*raw_memory*/
{
- if (attach == attach_default) {
- if (access_map->default_map != NULL)
- error("core_map_attach() default mapping already in place\n");
- ASSERT(buffer == NULL);
- access_map->default_map = new_core_mapping(attach,
- space, addr, nr_bytes,
- device, buffer, free_buffer);
+ /* find the insertion point for this additional mapping and insert */
+ core_mapping *next_mapping;
+ core_mapping **last_mapping;
+
+ /* actually do occasionally get a zero size map */
+ if (nr_bytes == 0) {
+ device_error(client, "called on core_map_attach() with size zero");
}
- else {
- /* find the insertion point for this additional mapping and insert */
- core_mapping *next_mapping;
- core_mapping **last_mapping;
-
- /* actually do occasionally get a zero size map */
- if (nr_bytes == 0)
- error("core_map_attach() size == 0\n");
-
- /* find the insertion point (between last/next) */
- next_mapping = access_map->first;
- last_mapping = &access_map->first;
- while(next_mapping != NULL && next_mapping->bound < addr) {
- /* 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 */
- if (next_mapping != NULL && next_mapping->base < (addr + (nr_bytes - 1))) {
- error("core_map_attach() map overlap\n");
- }
+ /* find the insertion point (between last/next) */
+ next_mapping = access_map->first;
+ last_mapping = &access_map->first;
+ while(next_mapping != NULL
+ && (next_mapping->level < attach
+ || (next_mapping->level == attach
+ && 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;
+ }
- /* create/insert the new mapping */
- *last_mapping = new_core_mapping(attach,
- space, addr, nr_bytes,
- device, buffer, free_buffer);
- (*last_mapping)->next = next_mapping;
+ /* check insertion point correct */
+ ASSERT(next_mapping == NULL || next_mapping->level >= attach);
+ if (next_mapping != NULL && next_mapping->level == attach
+ && next_mapping->base < (addr + (nr_bytes - 1))) {
+ device_error(client, "map overlap when attaching %d:0x%lx (%ld)",
+ space, (long)addr, (long)nr_bytes);
}
+
+ /* create/insert the new mapping */
+ *last_mapping = new_core_mapping(attach,
+ space, addr, nr_bytes,
+ client, buffer, free_buffer);
+ (*last_mapping)->next = next_mapping;
}
@@ -220,12 +219,11 @@ core_attach(core *memory,
access_type access,
unsigned_word addr,
unsigned nr_bytes, /* host limited */
- device *device) /*callback/default*/
+ device *client) /*callback/default*/
{
core_map_types access_map;
int free_buffer = 0;
void *buffer = NULL;
- ASSERT(attach == attach_default || nr_bytes > 0);
if (attach == attach_raw_memory)
buffer = zalloc(nr_bytes);
for (access_map = 0;
@@ -237,7 +235,7 @@ core_attach(core *memory,
core_map_attach(memory->map + access_map,
attach,
space, addr, nr_bytes,
- device, buffer, !free_buffer);
+ client, buffer, !free_buffer);
free_buffer ++;
break;
case core_write_map:
@@ -245,7 +243,7 @@ core_attach(core *memory,
core_map_attach(memory->map + access_map,
attach,
space, addr, nr_bytes,
- device, buffer, !free_buffer);
+ client, buffer, !free_buffer);
free_buffer ++;
break;
case core_execute_map:
@@ -253,7 +251,7 @@ core_attach(core *memory,
core_map_attach(memory->map + access_map,
attach,
space, addr, nr_bytes,
- device, buffer, !free_buffer);
+ client, buffer, !free_buffer);
free_buffer ++;
break;
default:
@@ -283,8 +281,6 @@ core_map_find_mapping(core_map *map,
return mapping;
mapping = mapping->next;
}
- if (map->default_map != NULL)
- return map->default_map;
if (abort)
error("core_find_mapping() - access to unmaped address, attach a default map to handle this - addr=0x%x nr_bytes=0x%x processor=0x%x cia=0x%x\n",
addr, nr_bytes, processor, cia);
@@ -308,9 +304,8 @@ core_map_read_buffer(core_map *map,
unsigned_word addr,
unsigned len)
{
- unsigned count;
- unsigned_1 byte;
- for (count = 0; count < len; count++) {
+ unsigned count = 0;
+ while (count < len) {
unsigned_word raddr = addr + count;
core_mapping *mapping =
core_map_find_mapping(map,
@@ -321,19 +316,24 @@ core_map_read_buffer(core_map *map,
if (mapping == NULL)
break;
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,
- &byte,
+ (unsigned_1*)buffer + count,
mapping->space,
raddr,
- 1, /* nr_bytes */
+ nr_bytes,
0, /*processor*/
- 0 /*cpu*/) != 1)
+ 0 /*cpu*/) != nr_bytes)
break;
+ count += nr_bytes;
+ }
+ else {
+ ((unsigned_1*)buffer)[count] =
+ *(unsigned_1*)core_translate(mapping, raddr);
+ count += 1;
}
- else
- byte = *(unsigned_1*)core_translate(mapping,
- raddr);
- ((unsigned_1*)buffer)[count] = T2H_1(byte);
}
return count;
}
@@ -346,9 +346,8 @@ core_map_write_buffer(core_map *map,
unsigned_word addr,
unsigned len)
{
- unsigned count;
- unsigned_1 byte;
- for (count = 0; count < len; count++) {
+ unsigned count = 0;
+ while (count < len) {
unsigned_word raddr = addr + count;
core_mapping *mapping = core_map_find_mapping(map,
raddr, 1,
@@ -357,19 +356,25 @@ core_map_write_buffer(core_map *map,
0); /*dont-abort*/
if (mapping == NULL)
break;
- byte = H2T_1(((unsigned_1*)buffer)[count]);
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_write_buffer(mapping->device,
- &byte,
+ (unsigned_1*)buffer + count,
mapping->space,
raddr,
- 1, /*nr_bytes*/
+ nr_bytes,
0, /*processor*/
- 0 /*cpu*/) != 1)
+ 0 /*cpu*/) != nr_bytes)
break;
+ count += nr_bytes;
+ }
+ else {
+ *(unsigned_1*)core_translate(mapping, raddr) =
+ ((unsigned_1*)buffer)[count];
+ count += 1;
}
- else
- *(unsigned_1*)core_translate(mapping, raddr) = byte;
}
return count;
}
@@ -397,112 +402,4 @@ core_map_write_buffer(core_map *map,
#include "corefile-n.h"
#undef N
-
-/* Top level core(root) device: core@garbage
-
- The core device captures incomming dma requests and changes them to
- outgoing io requests. */
-
-STATIC_INLINE_CORE\
-(void)
-core_init_address_callback(device *me,
- psim *system)
-{
- core *memory = (core*)device_data(me);
- core_init(memory);
-}
-
-
-STATIC_INLINE_CORE\
-(void)
-core_attach_address_callback(device *me,
- const char *name,
- attach_type attach,
- int space,
- unsigned_word addr,
- unsigned nr_bytes,
- access_type access,
- device *who) /*callback/default*/
-{
- core *memory = (core*)device_data(me);
- if (space != 0)
- error("core_attach_address_callback() invalid address space\n");
- core_attach(memory,
- attach,
- space,
- access,
- addr,
- nr_bytes,
- who);
-}
-
-
-STATIC_INLINE_CORE\
-(unsigned)
-core_dma_read_buffer_callback(device *me,
- void *dest,
- int space,
- unsigned_word addr,
- unsigned nr_bytes)
-{
- core *memory = (core*)device_data(me);
- return core_map_read_buffer(core_readable(memory),
- dest,
- addr,
- nr_bytes);
-}
-
-
-STATIC_INLINE_CORE\
-(unsigned)
-core_dma_write_buffer_callback(device *me,
- const void *source,
- int space,
- unsigned_word addr,
- unsigned nr_bytes,
- int violate_read_only_section)
-{
- core *memory = (core*)device_data(me);
- core_map *map = (violate_read_only_section
- ? core_readable(memory)
- : core_writeable(memory));
- return core_map_write_buffer(map,
- source,
- addr,
- nr_bytes);
-}
-
-static device_callbacks const core_callbacks = {
- core_init_address_callback,
- ignore_device_init,
- core_attach_address_callback,
- unimp_device_detach_address,
- unimp_device_io_read_buffer,
- unimp_device_io_write_buffer,
- core_dma_read_buffer_callback,
- core_dma_write_buffer_callback,
- unimp_device_interrupt_event,
- unimp_device_child_interrupt_event,
- generic_device_unit_decode,
- generic_device_unit_encode,
- unimp_device_instance_create,
- unimp_device_instance_delete,
- unimp_device_instance_read,
- unimp_device_instance_write,
- unimp_device_instance_seek,
- unimp_device_ioctl,
-};
-
-
-INLINE_CORE\
-(device *)
-core_device_create(void)
-{
- core *memory = ZALLOC(core);
- device_unit unit_address = { 0 };
- return device_create_from("core", &unit_address,
- memory, &core_callbacks, NULL);
-}
-
-
#endif /* _CORE_C_ */
diff --git a/gnu/dist/sim/ppc/corefile.h b/gnu/dist/sim/ppc/corefile.h
index fb2d7fafdf7..726470ca3f3 100644
--- a/gnu/dist/sim/ppc/corefile.h
+++ b/gnu/dist/sim/ppc/corefile.h
@@ -22,6 +22,37 @@
#ifndef _CORE_H_
#define _CORE_H_
+/* Introduction:
+
+ The core device, positioned at the top of the device tree that
+ models the architecure being simulated, acts as an interface
+ between the processor engines and the modeled devices.
+
+ On the one side the processor engines issue read and write requests
+ to the core (each request further catagorised as being for an
+ instruction or data subunit) while on the other side, the core is
+ receiving address configuration and DMA requests from child
+ devices.
+
+ In the below a synopsis of the core object and device in PSIM is
+ given, details of the object can be found in the files
+ <<corefile.h>> and <<corefile.c>>.
+
+ */
+
+/* Core::
+
+ At the heart of the interface between devices and processor engines
+ is a single core object. This object, in turn, has two children:
+
+ o a core device which exists in the device tree and provides
+ an interface to the core object to child devices.
+
+ o a set of access maps which provide an efficient
+ interface to the core object for the processor engines.
+
+ */
+
/* basic types */
typedef struct _core core;
@@ -31,56 +62,45 @@ typedef struct _core_map core_map;
INLINE_CORE\
(core *) core_create
-(device *root);
-
-INLINE_CORE\
-(device *) core_device_create
(void);
-
-
-/* the core has three sub mappings that the more efficient
- read/write fixed quantity functions use */
-
INLINE_CORE\
-(core_map *) core_readable
-(core *memory);
-
-INLINE_CORE\
-(core_map *) core_writeable
-(core *memory);
+(core *) core_from_device
+(device *root);
INLINE_CORE\
-(core_map *) core_executable
+(void) core_init
(core *memory);
+/* Core map management:::
+ The core ojbect manages two different types of address maps:
-/* operators to add/remove a mapping in the core
-
- callback-memory:
-
- All access are passed onto the specified devices callback routines
- after being `translated'. DEFAULT indicates that the specified
- memory should be called if all other mappings fail.
-
- For callback-memory, the device must be specified.
-
- raw-memory:
-
- While RAM could be implemented using the callback interface
- core instead treats it as the common case including the code
- directly in the read/write operators.
+ o raw-memory - the address range can be implemented using
+ a simple byte array. No device needs to be notifed of
+ any accesses to the specified memory range.
+
+ o callback - Any access to the specified address range
+ should be passed on to the associated device. That device
+ can in turn resolve the access - handling or aborting or
+ restarting it.
- For raw-memory, the device is ignored and the core alloc's a
- block to act as the memory.
+ For callback maps it is possible to further order them by
+ specifiying specifying a callback level (eg callback + 1).
- default-memory:
+ When the core is resolving an access it searches each of the maps
+ in order. First raw-memory and then callback maps (in assending
+ order of level). This search order makes it possible for latter
+ maps to overlap earlier ones. For instance, a device that wants to
+ be notified of all accesses that are not covered by raw-memory maps
+ could attach its self with an address range of the entire address
+ space.
- Should, for the core, there be no defined mapping for a given
- address then the default map (if present) is called.
+ In addition, each attached address map as an associated set of
+ access attributes (readable, writeable, executable) which are
+ verified as part of resolving each access.
- For default-memory, the device must be specified. */
+ */
INLINE_CORE\
(void) core_attach
@@ -92,7 +112,63 @@ INLINE_CORE\
unsigned nr_bytes, /* host limited */
device *device); /*callback/default*/
-/* Variable sized read/write:
+/* Bugs:::
+
+ At present there is no method for removing address maps. That will
+ be implemented in a future release.
+
+ The operation of mapping between an address and its destination
+ device or memory array is currently implemented using a simple
+ linked list. The posibility of replacing this list with a more
+ powerfull data structure exists.
+
+ */
+
+
+/* Device::
+
+ The device that corresponds to the core object is described
+ separatly in the devices section.
+
+ */
+
+/* Access maps::
+
+ Providing an interface between the processor engines and the core
+ object are the access maps (core_map). Three access maps are
+ provided, one for each of the possible access requests that can be
+ generated by a processor.
+
+ o read
+
+ o write
+
+ o execute
+
+ A processor being able to request a read (or write) or write
+ operation to any of the maps. Those operations can either be
+ highly efficient (by specifying a specific transfer size) or
+ generic (specifying a parameterized number of bytes).
+
+ Internally the core object takes the request, determines the
+ approperiate attached address space that it should handle it passes
+ it on.
+
+ */
+
+INLINE_CORE\
+(core_map *) core_readable
+(core *memory);
+
+INLINE_CORE\
+(core_map *) core_writeable
+(core *memory);
+
+INLINE_CORE\
+(core_map *) core_executable
+(core *memory);
+
+/* Variable sized read/write
Transfer (zero) a variable size block of data between the host and
target (possibly byte swapping it). Should any problems occure,
@@ -113,7 +189,7 @@ INLINE_CORE\
unsigned nr_bytes);
-/* Fixed sized read/write:
+/* Fixed sized read/write
Transfer a fixed amout of memory between the host and target. The
memory always being translated and the operation always aborting
diff --git a/gnu/dist/sim/ppc/cpu.c b/gnu/dist/sim/ppc/cpu.c
index f4501d49ee2..bce82f1d141 100644
--- a/gnu/dist/sim/ppc/cpu.c
+++ b/gnu/dist/sim/ppc/cpu.c
@@ -1,6 +1,6 @@
/* This file is part of the program psim.
- Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
+ 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
@@ -49,9 +49,6 @@ struct _cpu {
vm_instruction_map *instruction_map; /* instructions */
vm_data_map *data_map; /* data */
- /* current state of interrupt inputs */
- int external_exception_pending;
-
/* the system this processor is contained within */
cpu_mon *monitor;
os_emul *os_emulation;
@@ -67,6 +64,9 @@ struct _cpu {
idecode_cache icache[WITH_IDECODE_CACHE_SIZE];
#endif
+ /* any interrupt state */
+ interrupts ints;
+
/* address reservation: keep the physical address and the contents
of memory at that address */
memory_reservation reservation;
@@ -82,7 +82,6 @@ INLINE_CPU\
(cpu *)
cpu_create(psim *system,
core *memory,
- event_queue *events,
cpu_mon *monitor,
os_emul *os_emulation,
int cpu_nr)
@@ -100,7 +99,7 @@ cpu_create(psim *system,
/* link back to core system */
processor->system = system;
- processor->events = events;
+ processor->events = psim_event_queue(system);
processor->cpu_nr = cpu_nr;
processor->monitor = monitor;
processor->os_emulation = os_emulation;
@@ -138,13 +137,6 @@ cpu_nr(cpu *processor)
}
INLINE_CPU\
-(event_queue *)
-cpu_event_queue(cpu *processor)
-{
- return processor->events;
-}
-
-INLINE_CPU\
(cpu_mon *)
cpu_monitor(cpu *processor)
{
@@ -165,6 +157,79 @@ cpu_model(cpu *processor)
return processor->model_ptr;
}
+
+/* program counter manipulation */
+
+INLINE_CPU\
+(void)
+cpu_set_program_counter(cpu *processor,
+ unsigned_word new_program_counter)
+{
+ processor->program_counter = new_program_counter;
+}
+
+INLINE_CPU\
+(unsigned_word)
+cpu_get_program_counter(cpu *processor)
+{
+ return processor->program_counter;
+}
+
+
+INLINE_CPU\
+(void)
+cpu_restart(cpu *processor,
+ unsigned_word nia)
+{
+ ASSERT(processor != NULL);
+ cpu_set_program_counter(processor, nia);
+ psim_restart(processor->system, processor->cpu_nr);
+}
+
+INLINE_CPU\
+(void)
+cpu_halt(cpu *processor,
+ unsigned_word nia,
+ stop_reason reason,
+ int signal)
+{
+ ASSERT(processor != NULL);
+ if (CURRENT_MODEL_ISSUE > 0)
+ model_halt(processor->model_ptr);
+ cpu_set_program_counter(processor, nia);
+ psim_halt(processor->system, processor->cpu_nr, reason, signal);
+}
+
+EXTERN_CPU\
+(void)
+cpu_error(cpu *processor,
+ unsigned_word cia,
+ const char *fmt,
+ ...)
+{
+ char message[1024];
+ va_list ap;
+
+ /* format the message */
+ va_start(ap, fmt);
+ vsprintf(message, fmt, ap);
+ va_end(ap);
+
+ /* sanity check */
+ if (strlen(message) >= sizeof(message))
+ error("cpu_error: buffer overflow");
+
+ if (processor != NULL) {
+ printf_filtered("cpu %d, cia 0x%lx: %s\n",
+ processor->cpu_nr + 1, (unsigned long)cia, message);
+ cpu_halt(processor, cia, was_signalled, -1);
+ }
+ else {
+ error("cpu: %s", message);
+ }
+}
+
+
/* The processors local concept of time */
INLINE_CPU\
@@ -194,16 +259,11 @@ cpu_get_decrementer(cpu *processor)
STATIC_INLINE_CPU\
(void)
-cpu_decrement_event(event_queue *queue,
- void *data)
+cpu_decrement_event(void *data)
{
cpu *processor = (cpu*)data;
- if (!decrementer_interrupt(processor)) {
- processor->decrementer_event = event_queue_schedule(processor->events,
- 1, /* NOW! */
- cpu_decrement_event,
- processor);
- }
+ processor->decrementer_event = NULL;
+ decrementer_interrupt(processor);
}
INLINE_CPU\
@@ -211,18 +271,16 @@ INLINE_CPU\
cpu_set_decrementer(cpu *processor,
signed32 decrementer)
{
- signed64 old_decrementer = (processor->decrementer_local_time
- - event_queue_time(processor->events));
+ signed64 old_decrementer = cpu_get_decrementer(processor);
event_queue_deschedule(processor->events, processor->decrementer_event);
+ processor->decrementer_event = NULL;
processor->decrementer_local_time = (event_queue_time(processor->events)
+ decrementer);
if (decrementer < 0 && old_decrementer >= 0)
- /* dec interrupt occures if the sign of the decrement reg is
- changed by the load operation */
- processor->decrementer_event = event_queue_schedule(processor->events,
- 1, /* NOW! */
- cpu_decrement_event,
- processor);
+ /* A decrementer interrupt occures if the sign of the decrement
+ register is changed from positive to negative by the load
+ instruction */
+ decrementer_interrupt(processor);
else if (decrementer >= 0)
processor->decrementer_event = event_queue_schedule(processor->events,
decrementer,
@@ -231,55 +289,6 @@ cpu_set_decrementer(cpu *processor,
}
-/* program counter manipulation */
-
-INLINE_CPU\
-(void)
-cpu_set_program_counter(cpu *processor,
- unsigned_word new_program_counter)
-{
- processor->program_counter = new_program_counter;
-}
-
-INLINE_CPU\
-(unsigned_word)
-cpu_get_program_counter(cpu *processor)
-{
- return processor->program_counter;
-}
-
-INLINE_CPU\
-(void)
-cpu_restart(cpu *processor,
- unsigned_word nia)
-{
- processor->program_counter = nia;
- psim_restart(processor->system, processor->cpu_nr);
-}
-
-INLINE_CPU\
-(void)
-cpu_halt(cpu *processor,
- unsigned_word cia,
- stop_reason reason,
- int signal)
-{
- if (processor == NULL) {
- error("cpu_halt() processor=NULL, cia=0x%x, reason=%d, signal=%d\n",
- cia,
- reason,
- signal);
- }
- else {
- if (CURRENT_MODEL_ISSUE > 0)
- model_halt(processor->model_ptr);
-
- processor->program_counter = cia;
- psim_halt(processor->system, processor->cpu_nr, cia, reason, signal);
- }
-}
-
-
#if WITH_IDECODE_CACHE_SIZE
/* allow access to the cpu's instruction cache */
INLINE_CPU\
@@ -335,6 +344,17 @@ cpu_page_tlb_invalidate_all(cpu *processor)
}
+/* interrupt access */
+
+INLINE_CPU\
+(interrupts *)
+cpu_interrupts(cpu *processor)
+{
+ return &processor->ints;
+}
+
+
+
/* reservation access */
INLINE_CPU\
@@ -356,7 +376,8 @@ cpu_registers(cpu *processor)
INLINE_CPU\
(void)
-cpu_synchronize_context(cpu *processor)
+cpu_synchronize_context(cpu *processor,
+ unsigned_word cia)
{
#if (WITH_IDECODE_CACHE_SIZE)
/* kill of the cache */
@@ -367,7 +388,8 @@ cpu_synchronize_context(cpu *processor)
vm_synchronize_context(processor->virtual,
processor->regs.spr,
processor->regs.sr,
- processor->regs.msr);
+ processor->regs.msr,
+ processor, cia);
}
diff --git a/gnu/dist/sim/ppc/cpu.h b/gnu/dist/sim/ppc/cpu.h
index cca0e7144ae..840f5815742 100644
--- a/gnu/dist/sim/ppc/cpu.h
+++ b/gnu/dist/sim/ppc/cpu.h
@@ -1,6 +1,6 @@
/* This file is part of the program psim.
- Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
+ 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
@@ -30,7 +30,7 @@
#include "events.h"
#include "interrupts.h"
#include "psim.h"
-#include "icache.h"
+#include "idecode.h"
#include "itable.h"
#include "os_emul.h"
#include "mon.h"
@@ -52,7 +52,6 @@ INLINE_CPU\
(cpu *) cpu_create
(psim *system,
core *memory,
- event_queue *events,
cpu_mon *monitor,
os_emul *cpu_emulation,
int cpu_nr);
@@ -79,33 +78,8 @@ INLINE_CPU\
(int) cpu_nr
(cpu *processor) CONST_ATTRIBUTE;
-INLINE_CPU\
-(event_queue *) cpu_event_queue
-(cpu *processor);
-
-
-/* The processors local concept of time */
-
-INLINE_CPU\
-(signed64) cpu_get_time_base
-(cpu *processor);
-
-INLINE_CPU\
-(void) cpu_set_time_base
-(cpu *processor,
- signed64 time_base);
-
-INLINE_CPU\
-(signed32) cpu_get_decrementer
-(cpu *processor);
-
-INLINE_CPU\
-(void) cpu_set_decrementer
-(cpu *processor,
- signed32 decrementer);
-
-/* manipulate the program counter
+/* manipulate the processors program counter and execution state.
The program counter is not included in the register file. Instead
it is extracted and then later restored (set, reset, halt). This
@@ -134,6 +108,34 @@ INLINE_CPU\
stop_reason reason,
int signal);
+EXTERN_CPU\
+(void) cpu_error
+(cpu *processor,
+ unsigned_word cia,
+ const char *fmt,
+ ...) __attribute__ ((format (printf, 3, 4)));
+
+
+/* The processors local concept of time */
+
+INLINE_CPU\
+(signed64) cpu_get_time_base
+(cpu *processor);
+
+INLINE_CPU\
+(void) cpu_set_time_base
+(cpu *processor,
+ signed64 time_base);
+
+INLINE_CPU\
+(signed32) cpu_get_decrementer
+(cpu *processor);
+
+INLINE_CPU\
+(void) cpu_set_decrementer
+(cpu *processor,
+ signed32 decrementer);
+
#if WITH_IDECODE_CACHE_SIZE
/* Return the cache entry that matches the given CIA. No guarentee
@@ -180,6 +182,13 @@ INLINE_CPU\
(cpu *processor);
+/* reveal the processors interrupt state */
+
+INLINE_CPU\
+(interrupts *) cpu_interrupts
+(cpu *processor);
+
+
/* grant access to the reservation information */
typedef struct _memory_reservation {
@@ -193,12 +202,6 @@ INLINE_CPU\
(cpu *processor);
-INLINE_CPU\
-(void) cpu_print_info
-(cpu *processor,
- int verbose);
-
-
/* Registers:
This model exploits the PowerPC's requirement for a synchronization
@@ -212,11 +215,8 @@ INLINE_CPU\
INLINE_CPU\
(void) cpu_synchronize_context
-(cpu *processor);
-
-INLINE_CPU\
-(model_data *) cpu_model
-(cpu *processor) CONST_ATTRIBUTE;
+(cpu *processor,
+ unsigned_word cia);
#define IS_PROBLEM_STATE(PROCESSOR) \
(CURRENT_ENVIRONMENT == OPERATING_ENVIRONMENT \
@@ -236,6 +236,17 @@ INLINE_CPU\
: 1)
+
+INLINE_CPU\
+(void) cpu_print_info
+(cpu *processor,
+ int verbose);
+
+INLINE_CPU\
+(model_data *) cpu_model
+(cpu *processor) CONST_ATTRIBUTE;
+
+
#if (CPU_INLINE & INCLUDE_MODULE)
# include "cpu.c"
#endif
diff --git a/gnu/dist/sim/ppc/dc-complex b/gnu/dist/sim/ppc/dc-complex
new file mode 100644
index 00000000000..13361ecd525
--- /dev/null
+++ b/gnu/dist/sim/ppc/dc-complex
@@ -0,0 +1,58 @@
+#
+# 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.
+#
+array,normal: 0: 5: 0: 5:
+array,normal: 21:31:32:-1:OE,LR,AA,Rc,LK:
+##
+## Branch Conditional instruction - Expand BO{0:4} only, ignore BO{5}
+##
+array,expand-forced: 6: 9: 6: 9:BO: 0xfc000000:0x40000000
+##
+## Expand RA on equality with 0 in Add instructions were if(RA==0) appears.
+##
+# Add Immediate
+array,boolean: 11:15:11:15:RA: 0xfc000000:0x38000000:0
+# Add Immediate Shifted
+array,boolean: 11:15:11:15:RA: 0xfc000000:0x3c000000:0
+##
+## Ditto for high frequency load/store instructions.
+##
+# Store Byte
+#array,boolean: 11:15:11:15:RA: 0xfc000000:0x98000000:0
+# Store Word
+#array,boolean: 11:15:11:15:RA: 0xfc000000:0x90000000:0
+# Load Word and Zero
+#array,boolean: 11:15:11:15:RA: 0xfc000000:0x80000000:0
+##
+## Move to/from SPR instructions - LR=8 is munged into 0x100 == 256
+##
+#array,boolean: 11:20:11:20:SPR: 0xfc0007ff:0x7c0003a6:256
+#array,boolean: 11:20:11:20:SPR: 0xfc0007ff:0x7c0002a6:256
+##
+## Compare Immediate instruction - separate out L == 0 and L == 1
+##
+# Compare Immediate
+#array,normal: 10:11:10:11:L: 0xfc000000:0x2c000000:0
+##
+## Move to/from SPR instructions - separate out LR case
+##
+# Move to SPR
+array,boolean: 11:20:11:20:SPR: 0xfc0007ff:0x7c0003a6:256
+# Move from SPR
+array,boolean: 11:20:11:20:SPR: 0xfc0007ff:0x7c0002a6:256
diff --git a/gnu/dist/sim/ppc/dc-simple b/gnu/dist/sim/ppc/dc-simple
new file mode 100644
index 00000000000..9ea823e66c0
--- /dev/null
+++ b/gnu/dist/sim/ppc/dc-simple
@@ -0,0 +1,25 @@
+#
+# 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.
+#
+#
+# Create a two level switch statement. The first level branches on bits
+# 0..5 while the second level branches on bits 21..31
+#
+switch: 0: 5: 0: 5
+switch:21:31
diff --git a/gnu/dist/sim/ppc/dc-stupid b/gnu/dist/sim/ppc/dc-stupid
new file mode 100644
index 00000000000..4238bdb9c09
--- /dev/null
+++ b/gnu/dist/sim/ppc/dc-stupid
@@ -0,0 +1,58 @@
+#
+# 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.
+#
+array,normal: 0: 5: 0: 5:
+array,normal:21:31:32:-1:OE,LR,AA,Rc,LK:
+##
+## Branch Conditional instruction - Expand BO{0:4} only, ignore BO{5}
+##
+array,expand-forced: 6: 9: 6: 9:BO: 0xfc000000:0x40000000
+##
+## Expand RA on equality with 0 in Add instructions were if(RA==0) appears.
+##
+# Add Immediate
+#array,boolean: 11:15:11:15:RA: 0xfc000000:0x38000000:0
+# Add Immediate Shifted
+#array,boolean: 11:15:11:15:RA: 0xfc000000:0x3c000000:0
+##
+## Ditto for high frequency load/store instructions.
+##
+# Store Byte
+#array,boolean: 11:15:11:15:RA: 0xfc000000:0x98000000:0
+# Store Word
+#array,boolean: 11:15:11:15:RA: 0xfc000000:0x90000000:0
+# Load Word and Zero
+#array,boolean: 11:15:11:15:RA: 0xfc000000:0x80000000:0
+##
+## Move to/from SPR instructions - LR=8 is munged into 0x100 == 256
+##
+#array,boolean: 11:20:11:20:SPR: 0xfc0007ff:0x7c0003a6:256
+#array,boolean: 11:20:11:20:SPR: 0xfc0007ff:0x7c0002a6:256
+##
+## Compare Immediate instruction - separate out L == 0 and L == 1
+##
+# Compare Immediate
+#array,boolean: 10:11:10:11:L: 0xfc000000:0x2c000000:0
+##
+## Move to/from SPR instructions - separate out LR case
+##
+# Move to SPR
+#array,boolean: 11:20:11:20:SPR: 0xfc0007ff:0x7c0003a6:256
+# Move from SPR
+#array,boolean: 11:20:11:20:SPR: 0xfc0007ff:0x7c0002a6:256
diff --git a/gnu/dist/sim/ppc/dc-test.01 b/gnu/dist/sim/ppc/dc-test.01
new file mode 100644
index 00000000000..df8c175cc0d
--- /dev/null
+++ b/gnu/dist/sim/ppc/dc-test.01
@@ -0,0 +1,24 @@
+#
+# 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.
+#
+ 0: 5: 0: 5:0:: 2:0x00000000:0x00000000:0
+21:31:32:-1:0:OE,LR,AA,Rc,LK:0:0x00000000:0x00000000:0
+ 6: 9: 6: 9:0:BO: 0:0xfc000000:0x40000000:1
+11:15:11:15:0:RA: 1:0xfc000000:0x38000000:2
+11:15:11:15:0:RA: 1:0xfc000000:0x3c000000:2
diff --git a/gnu/dist/sim/ppc/dc-test.02 b/gnu/dist/sim/ppc/dc-test.02
new file mode 100644
index 00000000000..a98d0a78e2c
--- /dev/null
+++ b/gnu/dist/sim/ppc/dc-test.02
@@ -0,0 +1,24 @@
+#
+# 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.
+#
+ 0: 5: 0: 5:0:: 0:0x00000000:0x00000000:0
+21:31:32:-1:0:OE,LR,AA,Rc,LK:0:0x00000000:0x00000000:0
+ 6: 9: 6: 9:0:BO: 0:0xfc000000:0x40000000:1
+11:15:11:15:0:RA: 1:0xfc000000:0x38000000:2
+11:15:11:15:0:RA: 1:0xfc000000:0x3c000000:2
diff --git a/gnu/dist/sim/ppc/debug.c b/gnu/dist/sim/ppc/debug.c
index 88cc8b73cb2..5931d1e338a 100644
--- a/gnu/dist/sim/ppc/debug.c
+++ b/gnu/dist/sim/ppc/debug.c
@@ -1,6 +1,6 @@
/* This file is part of the program psim.
- Copyright (C) 1994-1996, Andrew Cagney <cagney@highland.com.au>
+ 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
@@ -40,6 +40,7 @@ typedef struct _trace_option_descriptor {
static trace_option_descriptor trace_description[] = {
{ trace_gdb, "gdb", "calls made by gdb to the sim_calls.c file" },
{ trace_os_emul, "os-emul", "VEA mode sytem calls - like strace" },
+ { trace_events, "events", "event queue handling" },
/* decode/issue */
{ trace_semantics, "semantics", "Instruction execution (issue)" },
{ trace_idecode, "idecode", "instruction decode (when miss in icache)" },
@@ -47,21 +48,32 @@ static trace_option_descriptor trace_description[] = {
{ trace_vm, "vm", "OEA address translation" },
{ trace_load_store, "load-store", "transfers between registers and memory" },
{ trace_model, "model", "model specific information" },
+ { trace_interrupts, "interrupts", "interrupt handling" },
/* devices */
{ trace_device_tree, "device-tree", },
{ trace_devices, "devices" },
- { trace_pass_device, "pass-device" },
+ { trace_binary_device, "binary-device" },
+ { trace_com_device, "com-device" },
{ trace_console_device, "console-device" },
- { trace_icu_device, "icu-device" },
+ { trace_core_device, "core-device" },
+ { trace_disk_device, "disk-device" },
+ { trace_eeprom_device, "eeprom-device" },
+ { trace_file_device, "file-device" },
+ { trace_glue_device, "glue-device" },
{ trace_halt_device, "halt-device" },
- { trace_register_device, "register-device", "Device initializing registers" },
- { trace_vm_device, "vm-device" },
- { trace_memory_device, "memory-device" },
{ trace_htab_device, "htab-device" },
- { trace_binary_device, "binary-device" },
- { trace_file_device, "file-device" },
- { trace_core_device, "core-device" },
+ { trace_icu_device, "icu-device" },
+ { trace_ide_device, "ide-device" },
+ { trace_memory_device, "memory-device" },
+ { trace_opic_device, "opic-device" },
+ { trace_pal_device, "pal-device" },
+ { trace_pass_device, "pass-device" },
+ { trace_phb_device, "phb-device" },
+ { trace_register_device, "register-device", "Device initializing registers" },
{ trace_stack_device, "stack-device" },
+ { trace_vm_device, "vm-device" },
+ /* packages */
+ { trace_disklabel_package, "disklabel-package" },
/* misc */
{ trace_print_info, "print-info", "Print performance analysis information" },
{ trace_opts, "options", "Print options simulator was compiled with" },
@@ -79,7 +91,9 @@ trace_option(const char *option,
if (strcmp(option, "all") == 0) {
trace_options i;
for (i = 0; i < nr_trace_options; i++)
- ppc_trace[i] = setting;
+ if (i != trace_dump_device_tree) {
+ ppc_trace[i] = setting;
+ }
}
else {
int i = 0;
diff --git a/gnu/dist/sim/ppc/debug.h b/gnu/dist/sim/ppc/debug.h
index 132631b8890..1fdb36ebac3 100644
--- a/gnu/dist/sim/ppc/debug.h
+++ b/gnu/dist/sim/ppc/debug.h
@@ -1,6 +1,6 @@
/* This file is part of the program psim.
- Copyright (C) 1994-1996, Andrew Cagney <cagney@highland.com.au>
+ 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
@@ -31,20 +31,31 @@ typedef enum {
trace_gdb,
trace_os_emul,
/**/
+ trace_events,
trace_device_tree,
trace_devices,
- trace_pass_device,
+ trace_binary_device,
+ trace_com_device,
trace_console_device,
- trace_icu_device,
+ trace_core_device,
+ trace_disk_device,
+ trace_eeprom_device,
+ trace_file_device,
+ trace_glue_device,
trace_halt_device,
- trace_register_device,
- trace_vm_device,
- trace_memory_device,
trace_htab_device,
- trace_binary_device,
- trace_file_device,
- trace_core_device,
+ trace_icu_device,
+ trace_ide_device,
+ trace_memory_device,
+ trace_opic_device,
+ trace_pal_device,
+ trace_pass_device,
+ trace_phb_device,
trace_stack_device,
+ trace_register_device,
+ trace_vm_device,
+ /**/
+ trace_disklabel_package,
/**/
trace_semantics,
trace_idecode,
@@ -54,6 +65,7 @@ typedef enum {
/**/
trace_vm,
trace_core,
+ trace_interrupts,
trace_psim,
trace_device_init,
trace_cpu,
@@ -69,47 +81,84 @@ typedef enum {
extern int ppc_trace[nr_trace_options];
-#if WITH_TRACE
+/* simple */
#define TRACE(OBJECT, ARGS) \
do { \
- if (ppc_trace[OBJECT]) { \
- printf_filtered("%s:%d: ", filter_filename(__FILE__), __LINE__); \
- printf_filtered ARGS; \
+ if (WITH_TRACE) { \
+ if (ppc_trace[OBJECT]) { \
+ printf_filtered("%s:%d: ", filter_filename(__FILE__), __LINE__); \
+ printf_filtered ARGS; \
+ } \
} \
} while (0)
+
/* issue */
#define ITRACE(OBJECT, ARGS) \
do { \
- if (ppc_trace[OBJECT]) { \
- printf_filtered("%s:%d:0x%lx", my_prefix, cpu_nr(processor) + 1, (unsigned long)cia); \
- printf_filtered ARGS; \
+ if (WITH_TRACE) { \
+ if (ppc_trace[OBJECT]) { \
+ printf_filtered("%s:%d:0x%08lx:%s ", itable[MY_INDEX].file, itable[MY_INDEX].line_nr, (long)cia, itable[MY_INDEX].name); \
+ printf_filtered ARGS; \
+ } \
} \
} while (0)
+
/* device */
#define DTRACE(OBJECT, ARGS) \
do { \
- if (ppc_trace[trace_devices] || ppc_trace[trace_##OBJECT##_device]) { \
- printf_filtered("%s:%d:%s: ", filter_filename(__FILE__), __LINE__, #OBJECT); \
- printf_filtered ARGS; \
+ if (WITH_TRACE) { \
+ int trace_device = device_trace(me); \
+ if (ppc_trace[trace_devices] \
+ || ppc_trace[trace_##OBJECT##_device] \
+ || trace_device) { \
+ printf_filtered("%s:%d:%s:%s%s ", \
+ filter_filename(__FILE__), __LINE__, #OBJECT, \
+ trace_device ? device_path(me) : "", \
+ trace_device ? ":" : ""); \
+ printf_filtered ARGS; \
+ } \
+ } \
+} while (0)
+
+/* device instance */
+#define DITRACE(OBJECT, ARGS) \
+do { \
+ if (WITH_TRACE) { \
+ device *me = device_instance_device(instance); \
+ int trace_device = device_trace(me); \
+ if (ppc_trace[trace_devices] \
+ || ppc_trace[trace_##OBJECT##_device] \
+ || trace_device) { \
+ printf_filtered("%s:%d:%s:%s%s ", \
+ filter_filename(__FILE__), __LINE__, #OBJECT, \
+ trace_device ? device_path(me) : "", \
+ trace_device ? ":" : ""); \
+ printf_filtered ARGS; \
+ } \
} \
} while (0)
-#else
-#define TRACE(OBJECT, ARGS)
-#define ITRACE(OBJECT, ARGS)
-#define DTRACE(OBJECT, ARGS)
-#endif
-#if WITH_ASSERT
+/* package */
+#define PTRACE(OBJECT, ARGS) \
+do { \
+ if (WITH_TRACE) { \
+ if (ppc_trace[trace_##OBJECT##_package]) { \
+ printf_filtered("%s:%d:%s: ", filter_filename(__FILE__), __LINE__, #OBJECT); \
+ printf_filtered ARGS; \
+ } \
+ } \
+} while (0)
+
+
#define ASSERT(EXPRESSION) \
do { \
- if (!(EXPRESSION)) { \
- error("%s:%d: assertion failed - %s\n", \
- filter_filename(__FILE__), __LINE__, #EXPRESSION); \
+ if (WITH_ASSERT) { \
+ if (!(EXPRESSION)) { \
+ error("%s:%d: assertion failed - %s\n", \
+ filter_filename(__FILE__), __LINE__, #EXPRESSION); \
+ } \
} \
} while (0)
-#else
-#define ASSERT(EXPRESSION)
-#endif
/* Parse OPTION updating the trace array */
extern void
diff --git a/gnu/dist/sim/ppc/device.c b/gnu/dist/sim/ppc/device.c
index faa1c7b1a96..ffb094324c4 100644
--- a/gnu/dist/sim/ppc/device.c
+++ b/gnu/dist/sim/ppc/device.c
@@ -1,6 +1,6 @@
/* This file is part of the program psim.
- Copyright (C) 1994-1996, Andrew Cagney <cagney@highland.com.au>
+ 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
@@ -27,6 +27,9 @@
#include "device_table.h"
#include "cap.h"
+#include "events.h"
+#include "psim.h"
+
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
@@ -41,6 +44,7 @@
#include <ctype.h>
+STATIC_INLINE_DEVICE (void) clean_device_properties(device *);
/* property entries */
@@ -48,6 +52,8 @@ typedef struct _device_property_entry device_property_entry;
struct _device_property_entry {
device_property_entry *next;
device_property *value;
+ const void *init_array;
+ unsigned sizeof_init_array;
};
@@ -59,7 +65,7 @@ struct _device_interrupt_edge {
device *dest;
int dest_port;
device_interrupt_edge *next;
- int permenant;
+ object_disposition disposition;
};
STATIC_INLINE_DEVICE\
@@ -68,20 +74,21 @@ attach_device_interrupt_edge(device_interrupt_edge **list,
int my_port,
device *dest,
int dest_port,
- int permenant)
+ object_disposition disposition)
{
device_interrupt_edge *new_edge = ZALLOC(device_interrupt_edge);
new_edge->my_port = my_port;
new_edge->dest = dest;
new_edge->dest_port = dest_port;
new_edge->next = *list;
- new_edge->permenant = permenant;
+ new_edge->disposition = disposition;
*list = new_edge;
}
STATIC_INLINE_DEVICE\
(void)
-detach_device_interrupt_edge(device_interrupt_edge **list,
+detach_device_interrupt_edge(device *me,
+ device_interrupt_edge **list,
int my_port,
device *dest,
int dest_port)
@@ -91,14 +98,14 @@ detach_device_interrupt_edge(device_interrupt_edge **list,
if (old_edge->dest == dest
&& old_edge->dest_port == dest_port
&& old_edge->my_port == my_port) {
- if (old_edge->permenant)
- error("attempt to delete permenant interrupt\n");
+ if (old_edge->disposition == permenant_object)
+ device_error(me, "attempt to delete permenant interrupt");
*list = old_edge->next;
zfree(old_edge);
return;
}
}
- error("detach_device_interrupt_edge: interrupt not attached\n");
+ device_error(me, "attempt to delete unattached interrupt");
}
STATIC_INLINE_DEVICE\
@@ -107,12 +114,14 @@ clean_device_interrupt_edges(device_interrupt_edge **list)
{
while (*list != NULL) {
device_interrupt_edge *old_edge = *list;
- if (old_edge->permenant) {
+ switch (old_edge->disposition) {
+ case permenant_object:
list = &old_edge->next;
- }
- else {
+ break;
+ case tempoary_object:
*list = old_edge->next;
zfree(old_edge);
+ break;
}
}
}
@@ -126,6 +135,8 @@ struct _device {
const char *name;
device_unit unit_address;
const char *path;
+ int nr_address_cells;
+ int nr_size_cells;
/* device tree */
device *parent;
@@ -141,93 +152,43 @@ struct _device {
/* interrupts */
device_interrupt_edge *interrupt_destinations;
- device_interrupt_edge *child_interrupt_destinations;
/* any open instances of this device */
device_instance *instances;
- /* the internal/external mappings */
+ /* the internal/external mappings and other global requirements */
cap *ihandles;
cap *phandles;
+ psim *system;
+
+ /* debugging */
+ int trace;
};
/* an instance of a device */
struct _device_instance {
- device *owner;
void *data;
char *args;
- char *name;
char *path;
- int permenant;
+ const device_instance_callbacks *callback;
+ /* the root instance */
+ device *owner;
device_instance *next;
+ /* interposed instance */
+ device_instance *parent;
+ device_instance *child;
};
-/* Device node: */
-
-INLINE_DEVICE\
-(device *)
-device_parent(device *me)
-{
- return me->parent;
-}
-
-INLINE_DEVICE\
-(device *)
-device_sibling(device *me)
-{
- return me->sibling;
-}
-
-INLINE_DEVICE\
-(device *)
-device_child(device *me)
-{
- return me->children;
-}
-
-INLINE_DEVICE\
-(const char *)
-device_name(device *me)
-{
- return me->name;
-}
-
-INLINE_DEVICE\
-(const char *)
-device_path(device *me)
-{
- return me->path;
-}
-
-INLINE_DEVICE\
-(void *)
-device_data(device *me)
-{
- return me->data;
-}
-
-INLINE_DEVICE\
-(const device_unit *)
-device_unit_address(device *me)
-{
- return &me->unit_address;
-}
-
-
-
-/* device template: */
-
-/* determine the full name of the device. If buf is specified it is
- stored in there. Failing that, a safe area of memory is allocated */
+/* creation */
STATIC_INLINE_DEVICE\
(const char *)
device_full_name(device *leaf,
- char *buf,
- unsigned sizeof_buf)
+ char *buf,
+ unsigned sizeof_buf)
{
/* get a buffer */
char full_name[1024];
@@ -239,23 +200,23 @@ device_full_name(device *leaf,
/* construct a name */
if (leaf->parent == NULL) {
if (sizeof_buf < 1)
- error("device_full_name() buffer overflow\n");
+ error("device_full_name: buffer overflow");
*buf = '\0';
}
else {
char unit[1024];
device_full_name(leaf->parent, buf, sizeof_buf);
if (leaf->parent != NULL
- && leaf->parent->callback->encode_unit(leaf->parent,
- &leaf->unit_address,
- unit+1,
- sizeof(unit)-1) > 0)
+ && device_encode_unit(leaf->parent,
+ &leaf->unit_address,
+ unit+1,
+ sizeof(unit)-1) > 0)
unit[0] = '@';
else
unit[0] = '\0';
if (strlen(buf) + strlen("/") + strlen(leaf->name) + strlen(unit)
- >= sizeof_buf)
- error("device_full_name() buffer overflow\n");
+ >= sizeof_buf)
+ error("device_full_name: buffer overflow");
strcat(buf, "/");
strcat(buf, leaf->name);
strcat (buf, unit);
@@ -263,299 +224,282 @@ device_full_name(device *leaf,
/* return it usefully */
if (buf == full_name)
- buf = strdup(full_name);
+ buf = (char *) strdup(full_name);
return buf;
}
-/* manipulate/lookup device names */
-
-typedef struct _name_specifier {
- /* components in the full length name */
- char *path;
- char *property;
- char *value;
- /* current device */
- char *name;
- char *unit;
- char *args;
- /* previous device */
- char *last_name;
- char *last_unit;
- char *last_args;
- /* work area */
- char buf[1024];
-} name_specifier;
-
-/* perform basic processing of a full name to give a specifier */
STATIC_INLINE_DEVICE\
-(int)
-split_device_specifier(const char *device_specifier,
- name_specifier *spec)
+(device *)
+device_create_from(const char *name,
+ const device_unit *unit_address,
+ void *data,
+ const device_callbacks *callbacks,
+ device *parent)
{
- char *chp;
- if (strlen(device_specifier) >= sizeof(spec->buf))
- error("device-specifier %s too long\n", device_specifier);
+ device *new_device = ZALLOC(device);
- /* expand aliases (later) */
- strcpy(spec->buf, device_specifier);
+ /* insert it into the device tree */
+ new_device->parent = parent;
+ new_device->children = NULL;
+ if (parent != NULL) {
+ device **sibling = &parent->children;
+ while ((*sibling) != NULL)
+ sibling = &(*sibling)->sibling;
+ *sibling = new_device;
+ }
- /* strip the leading spaces and check that remainder isn't a comment */
- chp = spec->buf;
- while (*chp != '\0' && isspace(*chp))
- chp++;
- if (*chp == '\0' || *chp == '#')
- return 0;
+ /* give it a name */
+ new_device->name = (char *) strdup(name);
+ new_device->unit_address = *unit_address;
+ new_device->path = device_full_name(new_device, NULL, 0);
- /* find the path and terminate it with null */
- spec->path = chp;
- while (*chp != '\0' && !isspace(*chp))
- chp++;
- if (*chp != '\0') {
- *chp = '\0';
- chp++;
- }
+ /* its template */
+ new_device->data = data;
+ new_device->callback = callbacks;
- /* and any value */
- while (*chp != '\0' && isspace(*chp))
- chp++;
- spec->value = chp;
+ /* its properties - already null */
+ /* interrupts - already null */
- /* 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;
+ /* mappings - if needed */
+ if (parent == NULL) {
+ new_device->ihandles = cap_create(name);
+ new_device->phandles = cap_create(name);
}
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;
- }
+ new_device->ihandles = device_root(parent)->ihandles;
+ new_device->phandles = device_root(parent)->phandles;
}
- /* and mark the rest as invalid */
- spec->name = NULL;
- spec->unit = NULL;
- spec->args = NULL;
- spec->last_name = NULL;
- spec->last_unit = NULL;
- spec->last_args = NULL;
-
- return 1;
+ cap_add(new_device->phandles, new_device);
+ return new_device;
}
-/* parse the last device name on the path assuming that it is a
- property name */
-STATIC_INLINE_DEVICE\
-(int)
-split_property_specifier(const char *property_specifier,
- name_specifier *spec)
-{
- if (split_device_specifier(property_specifier, spec)) {
- 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;
+
+
+INLINE_DEVICE\
+(device *)
+device_create(device *parent,
+ const char *base,
+ const char *name,
+ const char *unit_address,
+ const char *args)
+{
+ const device_descriptor *const *table;
+ for (table = device_table; *table != NULL; table++) {
+ const device_descriptor *descr;
+ for (descr = *table; descr->name != NULL; descr++) {
+ if (strcmp(base, descr->name) == 0) {
+ device_unit address = { 0 };
+ void *data = NULL;
+ if (parent != NULL)
+ if (device_decode_unit(parent, unit_address, &address) < 0)
+ device_error(parent, "invalid address %s for device %s",
+ unit_address, name);
+ if (descr->creator != NULL)
+ data = descr->creator(name, &address, args);
+ return device_create_from(name, &address, data,
+ descr->callbacks, parent);
+ }
}
- return 1;
}
- else
- return 0;
+ device_error(parent, "attempt to attach unknown device %s", name);
+ return NULL;
}
-/* parse the next device name and split it up */
-STATIC_INLINE_DEVICE\
-(int)
-split_device_name(name_specifier *spec)
-{
- char *chp;
- /* remember what came before */
- spec->last_name = spec->name;
- spec->last_unit = spec->unit;
- spec->last_args = spec->args;
- /* finished? */
- if (spec->path[0] == '\0') {
- spec->name = NULL;
- spec->unit = NULL;
- spec->args = NULL;
- return 0;
- }
- /* break the device name 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';
- }
- /* 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;
-}
-STATIC_INLINE_DEVICE\
-(device *)
-split_find_device(device *current,
- name_specifier *spec)
-{
- /* skip leading `.' etc */
- while (1) {
- if (strncmp(spec->path, "/", strlen("/")) == 0) {
- /* cd /... */
- while (current != NULL && current->parent != NULL)
- current = current->parent;
- 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 && current->parent != NULL)
- current = current->parent;
- 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 && current->parent != NULL)
- current = current->parent;
- spec->path += strlen("..");
+
+INLINE_DEVICE\
+(void)
+device_usage(int verbose)
+{
+ const device_descriptor *const *table;
+ if (verbose == 1) {
+ int pos = 0;
+ for (table = device_table; *table != NULL; table++) {
+ const device_descriptor *descr;
+ for (descr = *table; descr->name != NULL; descr++) {
+ pos += strlen(descr->name) + 2;
+ if (pos > 75) {
+ pos = strlen(descr->name) + 2;
+ printf_filtered("\n");
+ }
+ printf_filtered(" %s", descr->name);
+ }
+ printf_filtered("\n");
}
- else
- break;
}
-
- /* now go through the path proper */
- while (split_device_name(spec)) {
- device_unit phys;
- device *child;
- current->callback->decode_unit(current, spec->unit, &phys);
- for (child = current->children; child != NULL; child = child->sibling) {
- if (strcmp(spec->name, child->name) == 0) {
- if (phys.nr_cells == 0
- || memcmp(&phys, &child->unit_address, sizeof(device_unit)) == 0)
- break;
+ if (verbose > 1) {
+ for (table = device_table; *table != NULL; table++) {
+ const device_descriptor *descr;
+ for (descr = *table; descr->name != NULL; descr++) {
+ printf_filtered(" %s:\n", descr->name);
+ /* interrupt ports */
+ if (descr->callbacks->interrupt.ports != NULL) {
+ const device_interrupt_port_descriptor *ports =
+ descr->callbacks->interrupt.ports;
+ printf_filtered(" interrupt ports:");
+ while (ports->name != NULL) {
+ printf_filtered(" %s", ports->name);
+ ports++;
+ }
+ printf_filtered("\n");
+ }
+ /* general info */
+ if (descr->callbacks->usage != NULL)
+ descr->callbacks->usage(verbose);
}
}
- if (child == NULL)
- return current; /* search failed */
- current = child;
}
+}
+
- return current;
+
+
+
+/* Device node: */
+
+INLINE_DEVICE\
+(device *)
+device_parent(device *me)
+{
+ return me->parent;
}
+INLINE_DEVICE\
+(device *)
+device_root(device *me)
+{
+ ASSERT(me != NULL);
+ while (me->parent != NULL)
+ me = me->parent;
+ return me;
+}
INLINE_DEVICE\
(device *)
-device_template_create_device(device *parent,
- const char *name,
- const char *unit_address,
- const char *args)
+device_sibling(device *me)
{
- device_descriptor *descr;
- int name_len;
- char *chp;
- chp = strchr(name, '@');
- name_len = (chp == NULL ? strlen(name) : chp - name);
- for (descr = device_table; descr->name != NULL; descr++) {
- if (strncmp(name, descr->name, name_len) == 0
- && (descr->name[name_len] == '\0'
- || descr->name[name_len] == '@')) {
- device_unit address = { 0 };
- void *data = NULL;
- if (parent->callback->decode_unit != NULL)
- parent->callback->decode_unit(parent,
- unit_address,
- &address);
- if (descr->creator != NULL)
- data = descr->creator(name, &address, args, parent);
- return device_create_from(name, &address, data,
- descr->callbacks, parent);
- }
- }
- error("device_template_create_device() unknown device %s\n", name);
- return NULL;
- error("not implenented\n");
+ return me->sibling;
}
INLINE_DEVICE\
(device *)
-device_create_from(const char *name,
- const device_unit *unit_address,
- void *data,
- const device_callbacks *callbacks,
- device *parent)
+device_child(device *me)
{
- device *new_device = ZALLOC(device);
+ return me->children;
+}
- /* insert it into the device tree */
- new_device->parent = parent;
- new_device->children = NULL;
- if (parent != NULL) {
- device **sibling = &parent->children;
- while ((*sibling) != NULL)
- sibling = &(*sibling)->sibling;
- *sibling = new_device;
- }
+INLINE_DEVICE\
+(const char *)
+device_name(device *me)
+{
+ return me->name;
+}
- /* give it a name */
- new_device->name = strdup(name);
- new_device->unit_address = *unit_address;
- new_device->path = device_full_name(new_device, NULL, 0);
+INLINE_DEVICE\
+(const char *)
+device_path(device *me)
+{
+ return me->path;
+}
- /* its template */
- new_device->data = data;
- new_device->callback = callbacks;
+INLINE_DEVICE\
+(void *)
+device_data(device *me)
+{
+ return me->data;
+}
- /* its properties - already null */
- /* interrupts - already null */
+INLINE_DEVICE\
+(psim *)
+device_system(device *me)
+{
+ return me->system;
+}
- /* mappings - if needed */
- if (parent == NULL) {
- new_device->ihandles = cap_create(name);
- new_device->phandles = cap_create(name);
+INLINE_DEVICE\
+(const device_unit *)
+device_unit_address(device *me)
+{
+ return &me->unit_address;
+}
+
+
+INLINE_DEVICE\
+(int)
+device_address_to_attach_address(device *me,
+ const device_unit *address,
+ int *attach_space,
+ unsigned_word *attach_address,
+ device *client)
+{
+ if (me->callback->convert.address_to_attach_address == NULL)
+ device_error(me, "no convert.address_to_attach_address method");
+ return me->callback->convert.address_to_attach_address(me, address, attach_space, attach_address, client);
+}
+
+
+INLINE_DEVICE\
+(int)
+device_size_to_attach_size(device *me,
+ const device_unit *size,
+ unsigned *nr_bytes,
+ device *client)
+{
+ if (me->callback->convert.size_to_attach_size == NULL)
+ device_error(me, "no convert.size_to_attach_size method");
+ return me->callback->convert.size_to_attach_size(me, size, nr_bytes, client);
+}
+
+
+INLINE_DEVICE\
+(int)
+device_decode_unit(device *bus,
+ const char *unit,
+ device_unit *address)
+{
+ if (bus->callback->convert.decode_unit == NULL)
+ device_error(bus, "no convert.decode_unit method");
+ return bus->callback->convert.decode_unit(bus, unit, address);
+}
+
+
+INLINE_DEVICE\
+(int)
+device_encode_unit(device *bus,
+ const device_unit *unit_address,
+ char *buf,
+ int sizeof_buf)
+{
+ if (bus->callback->convert.encode_unit == NULL)
+ device_error(bus, "no convert.encode_unit method");
+ return bus->callback->convert.encode_unit(bus, unit_address, buf, sizeof_buf);
+}
+
+INLINE_DEVICE\
+(unsigned)
+device_nr_address_cells(device *me)
+{
+ if (me->nr_address_cells == 0) {
+ if (device_find_property(me, "#address-cells") != NULL)
+ me->nr_address_cells = device_find_integer_property(me, "#address-cells");
+ else
+ me->nr_address_cells = 2;
}
+ return me->nr_address_cells;
+}
- return new_device;
+INLINE_DEVICE\
+(unsigned)
+device_nr_size_cells(device *me)
+{
+ if (me->nr_size_cells == 0) {
+ if (device_find_property(me, "#size-cells") != NULL)
+ me->nr_size_cells = device_find_integer_property(me, "#size-cells");
+ else
+ me->nr_size_cells = 1;
+ }
+ return me->nr_size_cells;
}
@@ -564,37 +508,66 @@ device_create_from(const char *name,
INLINE_DEVICE\
(device_instance *)
-device_instance_create(device *me,
- const char *device_specifier,
- int permenant)
-{
- void *data = NULL;
- device_instance *instance;
- /* find the device node */
- name_specifier spec;
- if (!split_device_specifier(device_specifier, &spec))
- return NULL;
- me = split_find_device(me, &spec);
- if (spec.name != NULL)
- return NULL;
- /* create the instance */
- data = me->callback->instance_create(me, spec.last_args);
- if (data == NULL)
- return NULL;
- instance = ZALLOC(device_instance);
- instance->owner = me;
- instance->data = data;
- instance->args = (spec.last_args == NULL ? NULL : strdup(spec.last_args));
- instance->path = strdup(device_specifier);
- instance->name = strdup(spec.last_name);
- instance->permenant = permenant;
+device_create_instance_from(device *me,
+ device_instance *parent,
+ void *data,
+ const char *path,
+ const char *args,
+ const device_instance_callbacks *callbacks)
+{
+ device_instance *instance = ZALLOC(device_instance);
+ if ((me == NULL) == (parent == NULL))
+ device_error(me, "can't have both parent instance and parent device");
/*instance->unit*/
- /*instance->parent*/
- instance->next = me->instances;
- me->instances = instance;
+ /* link this instance into the devices list */
+ if (me != NULL) {
+ ASSERT(parent == NULL);
+ instance->owner = me;
+ instance->parent = NULL;
+ /* link this instance into the front of the devices instance list */
+ instance->next = me->instances;
+ me->instances = instance;
+ }
+ if (parent != NULL) {
+ device_instance **previous;
+ ASSERT(parent->child == NULL);
+ parent->child = instance;
+ ASSERT(me == NULL);
+ instance->owner = parent->owner;
+ instance->parent = 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));
+ instance->callback = callbacks;
+ cap_add(instance->owner->ihandles, instance);
return instance;
}
+
+INLINE_DEVICE\
+(device_instance *)
+device_create_instance(device *me,
+ const char *path,
+ const char *args)
+{
+ /* create the instance */
+ if (me->callback->instance_create == NULL)
+ device_error(me, "no instance_create method");
+ return me->callback->instance_create(me, path, args);
+}
+
+
STATIC_INLINE_DEVICE\
(void)
clean_device_instances(device *me)
@@ -602,36 +575,45 @@ clean_device_instances(device *me)
device_instance **instance = &me->instances;
while (*instance != NULL) {
device_instance *old_instance = *instance;
- if (old_instance->permenant) {
- instance = &old_instance->next;
- }
- else {
- device_instance_delete(old_instance);
- instance = &me->instances;
- }
+ device_instance_delete(old_instance);
+ instance = &me->instances;
}
}
+
INLINE_DEVICE\
(void)
device_instance_delete(device_instance *instance)
{
device *me = instance->owner;
- device_instance **curr;
- if (instance->permenant)
- error("device_instance_delete: attempt to delete a permenant instance\n");
- me->callback->instance_delete(instance);
+ if (instance->callback->delete == NULL)
+ device_error(me, "no delete method");
+ instance->callback->delete(instance);
if (instance->args != NULL)
zfree(instance->args);
if (instance->path != NULL)
zfree(instance->path);
- if (instance->name != NULL)
- zfree(instance->name);
- curr = &me->instances;
- while (*curr != NULL && *curr != instance)
- curr = &(*curr)->next;
- ASSERT(*curr != NULL);
- *curr = instance->next;
+ if (instance->child == NULL) {
+ /* only remove leaf nodes */
+ device_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 */
+ device_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);
}
@@ -641,9 +623,10 @@ device_instance_read(device_instance *instance,
void *addr,
unsigned_word len)
{
- return instance->owner->callback->instance_read(instance,
- addr,
- len);
+ device *me = instance->owner;
+ if (instance->callback->read == NULL)
+ device_error(me, "no read method");
+ return instance->callback->read(instance, addr, len);
}
INLINE_DEVICE\
@@ -652,9 +635,10 @@ device_instance_write(device_instance *instance,
const void *addr,
unsigned_word len)
{
- return instance->owner->callback->instance_write(instance,
- addr,
- len);
+ device *me = instance->owner;
+ if (instance->callback->write == NULL)
+ device_error(me, "no write method");
+ return instance->callback->write(instance, addr, len);
}
INLINE_DEVICE\
@@ -663,23 +647,44 @@ device_instance_seek(device_instance *instance,
unsigned_word pos_hi,
unsigned_word pos_lo)
{
- return instance->owner->callback->instance_seek(instance,
- pos_hi,
- pos_lo);
+ device *me = instance->owner;
+ if (instance->callback->seek == NULL)
+ device_error(me, "no seek method");
+ return instance->callback->seek(instance, pos_hi, pos_lo);
}
INLINE_DEVICE\
-(device *)
-device_instance_device(device_instance *instance)
+(int)
+device_instance_call_method(device_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*/])
{
- return instance->owner;
+ device *me = instance->owner;
+ const device_instance_methods *method = instance->callback->methods;
+ if (method == NULL) {
+ device_error(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++;
+ }
+ device_error(me, "no %s method", method_name);
+ return 0;
}
+
INLINE_DEVICE\
-(const char *)
-device_instance_name(device_instance *instance)
+(device *)
+device_instance_device(device_instance *instance)
{
- return instance->name;
+ return instance->owner;
}
INLINE_DEVICE\
@@ -698,77 +703,221 @@ device_instance_data(device_instance *instance)
-/* Device initialization: */
+/* Device Properties: */
-INLINE_DEVICE\
-(void)
-device_init_address(device *me,
- psim *system)
+STATIC_INLINE_DEVICE\
+(device_property_entry *)
+find_property_entry(device *me,
+ const char *property)
{
- TRACE(trace_device_init, ("device_init_address() initializing device=0x%lx (%s)\n",
- (long)me, me->path));
- me->callback->init_address(me, system);
+ device_property_entry *entry;
+ ASSERT(property != NULL);
+ entry = me->properties;
+ while (entry != NULL) {
+ if (strcmp(entry->value->name, property) == 0)
+ return entry;
+ entry = entry->next;
+ }
+ return NULL;
}
-INLINE_DEVICE\
+STATIC_INLINE_DEVICE\
(void)
-device_init_data(device *me,
- psim *system)
+device_add_property(device *me,
+ const char *property,
+ device_property_type type,
+ const void *init_array,
+ unsigned sizeof_init_array,
+ const void *array,
+ unsigned sizeof_array,
+ const device_property *original,
+ object_disposition disposition)
{
- TRACE(trace_device_init, ("device_init_data() initializing device=0x%lx (%s)\n",
- (long)me, me->path));
- me->callback->init_data(me, system);
+ device_property_entry *new_entry = NULL;
+ device_property *new_value = NULL;
+
+ /* find the list end */
+ device_property_entry **insertion_point = &me->properties;
+ while (*insertion_point != NULL) {
+ if (strcmp((*insertion_point)->value->name, property) == 0)
+ return;
+ insertion_point = &(*insertion_point)->next;
+ }
+
+ /* create a new value */
+ new_value = ZALLOC(device_property);
+ new_value->name = (char *) strdup(property);
+ new_value->type = type;
+ if (sizeof_array > 0) {
+ void *new_array = zalloc(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 = ZALLOC(device_property_entry);
+ *insertion_point = new_entry;
+ if (sizeof_init_array > 0) {
+ void *new_init_array = zalloc(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->value = new_value;
}
+
+/* local - not available externally */
STATIC_INLINE_DEVICE\
(void)
-clean_device(device *root,
- void *data)
-{
- psim *system;
- system = (psim*)data;
- clean_device_interrupt_edges(&root->interrupt_destinations);
- clean_device_interrupt_edges(&root->child_interrupt_destinations);
- clean_device_instances(root);
+device_set_property(device *me,
+ const char *property,
+ device_property_type type,
+ const void *array,
+ int sizeof_array)
+{
+ /* find the property */
+ device_property_entry *entry = find_property_entry(me, property);
+ if (entry != NULL) {
+ /* existing property - update it */
+ void *new_array = 0;
+ device_property *value = entry->value;
+ /* check the type matches */
+ if (value->type != type)
+ device_error(me, "conflict between type of new and old value for property %s", property);
+ /* replace its value */
+ if (value->array != NULL)
+ zfree((void*)value->array);
+ new_array = (sizeof_array > 0
+ ? zalloc(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 */
+ device_add_property(me, property, type,
+ NULL, 0, array, sizeof_array,
+ NULL, tempoary_object);
+ }
}
+
STATIC_INLINE_DEVICE\
(void)
-init_device_address(device *root,
- void *data)
-{
- psim *system = (psim*)data;
- device_init_address(root, system);
+clean_device_properties(device *me)
+{
+ device_property_entry **delete_point = &me->properties;
+ while (*delete_point != NULL) {
+ device_property_entry *current = *delete_point;
+ switch (current->value->disposition) {
+ case permenant_object:
+ /* zap the current value, will be initialized later */
+ ASSERT(current->init_array != NULL);
+ if (current->value->array != NULL) {
+ zfree((void*)current->value->array);
+ current->value->array = NULL;
+ }
+ delete_point = &(*delete_point)->next;
+ break;
+ case tempoary_object:
+ /* zap the actual property, was created during simulation run */
+ ASSERT(current->init_array == NULL);
+ *delete_point = current->next;
+ if (current->value->array != NULL)
+ zfree((void*)current->value->array);
+ zfree(current->value);
+ zfree(current);
+ break;
+ }
+ }
}
-STATIC_INLINE_DEVICE\
+
+INLINE_DEVICE\
(void)
-init_device_data(device *root,
- void *data)
+device_init_static_properties(device *me,
+ void *data)
{
- psim *system = (psim*)data;
- device_init_data(root, system);
+ device_property_entry *property;
+ for (property = me->properties;
+ property != NULL;
+ property = property->next) {
+ ASSERT(property->init_array != NULL);
+ ASSERT(property->value->array == NULL);
+ ASSERT(property->value->disposition == permenant_object);
+ switch (property->value->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 */
+ device_set_property(me, property->value->name,
+ property->value->type,
+ property->init_array,
+ property->sizeof_init_array);
+ break;
+ case ihandle_property:
+ break;
+ }
+ }
}
+
INLINE_DEVICE\
(void)
-device_tree_init(device *root,
- psim *system)
+device_init_runtime_properties(device *me,
+ void *data)
{
- TRACE(trace_device_tree, ("device_tree_init(root=0x%lx, system=0x%lx)\n",
- (long)root,
- (long)system));
- /* remove the old, rebuild the new */
- device_tree_traverse(root, clean_device, NULL, system);
- device_tree_traverse(root, init_device_address, NULL, system);
- device_tree_traverse(root, init_device_data, NULL, system);
- TRACE(trace_device_tree, ("device_tree_init() = void\n"));
+ device_property_entry *property;
+ for (property = me->properties;
+ property != NULL;
+ property = property->next) {
+ switch (property->value->disposition) {
+ case permenant_object:
+ switch (property->value->type) {
+ case ihandle_property:
+ {
+ device_instance *ihandle;
+ ihandle_runtime_property_spec spec;
+ ASSERT(property->init_array != NULL);
+ ASSERT(property->value->array == NULL);
+ device_find_ihandle_runtime_property(me, property->value->name, &spec);
+ ihandle = tree_instance(me, spec.full_path);
+ device_set_ihandle_property(me, property->value->name, ihandle);
+ break;
+ }
+ 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->value->array != NULL);
+ break;
+ }
+ break;
+ case tempoary_object:
+ ASSERT(property->init_array == NULL);
+ ASSERT(property->value->array != NULL);
+ break;
+ }
+ }
}
-
-/* Device Properties: */
-
INLINE_DEVICE\
(const device_property *)
device_next_property(const device_property *property)
@@ -786,12 +935,12 @@ device_next_property(const device_property *property)
return NULL;
}
+
INLINE_DEVICE\
(const device_property *)
device_find_property(device *me,
const char *property)
{
- name_specifier spec;
if (me == NULL) {
return NULL;
}
@@ -801,266 +950,579 @@ device_find_property(device *me,
else
return me->properties->value;
}
- else if (split_property_specifier(property, &spec)) {
- me = split_find_device(me, &spec);
- if (spec.name == NULL) { /*got to root*/
- device_property_entry *entry = me->properties;
- while (entry != NULL) {
- if (strcmp(entry->value->name, spec.property) == 0)
- return entry->value;
- entry = entry->next;
- }
- }
+ else {
+ device_property_entry *entry = find_property_entry(me, property);
+ if (entry != NULL)
+ return entry->value;
}
return NULL;
}
-/* return NULL if fail */
+
+INLINE_DEVICE\
+(void)
+device_add_array_property(device *me,
+ const char *property,
+ const void *array,
+ int sizeof_array)
+{
+ device_add_property(me, property, array_property,
+ array, sizeof_array, array, sizeof_array,
+ NULL, permenant_object);
+}
+
+INLINE_DEVICE\
+(void)
+device_set_array_property(device *me,
+ const char *property,
+ const void *array,
+ int sizeof_array)
+{
+ device_set_property(me, property, array_property, array, sizeof_array);
+}
+
INLINE_DEVICE\
(const device_property *)
device_find_array_property(device *me,
const char *property)
{
const device_property *node;
- TRACE(trace_devices,
- ("device_find_integer(me=0x%lx, property=%s)\n",
- (long)me, property));
node = device_find_property(me, property);
if (node == (device_property*)0
|| node->type != array_property)
- error("%s property %s not found or of wrong type\n",
- me->name, property);
+ device_error(me, "property %s not found or of wrong type", property);
return node;
}
INLINE_DEVICE\
+(void)
+device_add_boolean_property(device *me,
+ const char *property,
+ int boolean)
+{
+ signed32 new_boolean = (boolean ? -1 : 0);
+ device_add_property(me, property, boolean_property,
+ &new_boolean, sizeof(new_boolean),
+ &new_boolean, sizeof(new_boolean),
+ NULL, permenant_object);
+}
+
+INLINE_DEVICE\
(int)
device_find_boolean_property(device *me,
const char *property)
{
const device_property *node;
- unsigned32 boolean;
- TRACE(trace_devices,
- ("device_find_boolean(me=0x%lx, property=%s)\n",
- (long)me, property));
+ unsigned_cell boolean;
node = device_find_property(me, property);
if (node == (device_property*)0
|| node->type != boolean_property)
- error("%s property %s not found or of wrong type\n",
- me->name, property);
+ device_error(me, "property %s not found or of wrong type", property);
ASSERT(sizeof(boolean) == node->sizeof_array);
memcpy(&boolean, node->array, sizeof(boolean));
return boolean;
}
+
+INLINE_DEVICE\
+(void)
+device_add_ihandle_runtime_property(device *me,
+ const char *property,
+ const ihandle_runtime_property_spec *ihandle)
+{
+ /* enter the full path as the init array */
+ device_add_property(me, property, ihandle_property,
+ ihandle->full_path, strlen(ihandle->full_path) + 1,
+ NULL, 0,
+ NULL, permenant_object);
+}
+
+INLINE_DEVICE\
+(void)
+device_find_ihandle_runtime_property(device *me,
+ const char *property,
+ ihandle_runtime_property_spec *ihandle)
+{
+ device_property_entry *entry = find_property_entry(me, property);
+ TRACE(trace_devices,
+ ("device_find_ihandle_runtime_property(me=0x%lx, property=%s)\n",
+ (long)me, property));
+ if (entry == NULL
+ || entry->value->type != ihandle_property
+ || entry->value->disposition != permenant_object)
+ device_error(me, "property %s not found or of wrong type", property);
+ ASSERT(entry->init_array != NULL);
+ /* the full path */
+ ihandle->full_path = entry->init_array;
+}
+
+
+
+INLINE_DEVICE\
+(void)
+device_set_ihandle_property(device *me,
+ const char *property,
+ device_instance *ihandle)
+{
+ unsigned_cell cells;
+ cells = H2BE_cell(device_instance_to_external(ihandle));
+ device_set_property(me, property, ihandle_property,
+ &cells, sizeof(cells));
+
+}
+
INLINE_DEVICE\
(device_instance *)
device_find_ihandle_property(device *me,
const char *property)
{
const device_property *node;
- unsigned32 ihandle;
+ unsigned_cell ihandle;
device_instance *instance;
- TRACE(trace_devices,
- ("device_find_ihandle_property(me=0x%lx, property=%s)\n",
- (long)me, property));
+
node = device_find_property(me, property);
- if (node == (device_property*)0
- || node->type != ihandle_property)
- error("%s property %s not found or of wrong type\n",
- me->name, property);
+ if (node == NULL || node->type != ihandle_property)
+ device_error(me, "property %s not found or of wrong type", property);
+ if (node->array == NULL)
+ device_error(me, "runtime property %s not yet initialized", property);
+
ASSERT(sizeof(ihandle) == node->sizeof_array);
memcpy(&ihandle, node->array, sizeof(ihandle));
- BE2H(ihandle);
- instance = external_to_device_instance(me, ihandle);
+ instance = external_to_device_instance(me, BE2H_cell(ihandle));
ASSERT(instance != NULL);
return instance;
}
+
INLINE_DEVICE\
-(signed_word)
+(void)
+device_add_integer_property(device *me,
+ const char *property,
+ signed_cell integer)
+{
+ H2BE(integer);
+ device_add_property(me, property, integer_property,
+ &integer, sizeof(integer),
+ &integer, sizeof(integer),
+ NULL, permenant_object);
+}
+
+INLINE_DEVICE\
+(signed_cell)
device_find_integer_property(device *me,
const char *property)
{
const device_property *node;
- signed32 integer;
+ signed_cell integer;
TRACE(trace_devices,
("device_find_integer(me=0x%lx, property=%s)\n",
(long)me, property));
node = device_find_property(me, property);
if (node == (device_property*)0
|| node->type != integer_property)
- error("%s property %s not found or of wrong type\n",
- me->name, property);
+ device_error(me, "property %s not found or of wrong type", property);
ASSERT(sizeof(integer) == node->sizeof_array);
memcpy(&integer, node->array, sizeof(integer));
- BE2H(integer);
- return integer;
+ return BE2H_cell(integer);
}
INLINE_DEVICE\
-(device *)
-device_find_phandle_property(device *me,
- const char *property)
+(int)
+device_find_integer_array_property(device *me,
+ const char *property,
+ unsigned index,
+ signed_cell *integer)
{
- error("device_find_ihandle_property unimplemented\n");
- return 0;
+ const device_property *node;
+ int sizeof_integer = sizeof(*integer);
+ signed_cell *cell;
+ TRACE(trace_devices,
+ ("device_find_integer(me=0x%lx, property=%s)\n",
+ (long)me, property));
+
+ /* check things sane */
+ node = device_find_property(me, property);
+ if (node == (device_property*)0
+ || (node->type != integer_property
+ && node->type != array_property))
+ device_error(me, "property %s not found or of wrong type", property);
+ if ((node->sizeof_array % sizeof_integer) != 0)
+ device_error(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_INLINE_DEVICE\
+(unsigned_cell *)
+unit_address_to_cells(const device_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_INLINE_DEVICE\
+(const unsigned_cell *)
+cells_to_unit_address(const unsigned_cell *cell,
+ device_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_INLINE_DEVICE\
+(unsigned)
+nr_range_property_cells(device *me,
+ int nr_ranges)
+{
+ return ((device_nr_address_cells(me)
+ + device_nr_address_cells(device_parent(me))
+ + device_nr_size_cells(me))
+ ) * nr_ranges;
}
INLINE_DEVICE\
-(const char *)
-device_find_string_property(device *me,
- const char *property)
+(void)
+device_add_range_array_property(device *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 = zalloc(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,
+ device_nr_address_cells(me));
+ /* copy the parent address */
+ cell = unit_address_to_cells(&range->parent_address, cell,
+ device_nr_address_cells(device_parent(me)));
+ /* copy the size */
+ cell = unit_address_to_cells(&range->size, cell,
+ device_nr_size_cells(me));
+ }
+ ASSERT(cell == &cells[nr_range_property_cells(me, nr_ranges)]);
+
+ /* add it */
+ device_add_property(me, property, range_array_property,
+ cells, sizeof_cells,
+ cells, sizeof_cells,
+ NULL, permenant_object);
+
+ zfree(cells);
+}
+
+INLINE_DEVICE\
+(int)
+device_find_range_array_property(device *me,
+ const char *property,
+ unsigned index,
+ range_property_spec *range)
{
const device_property *node;
- const char *string;
- TRACE(trace_devices,
- ("device_find_string(me=0x%lx, property=%s)\n",
- (long)me, property));
+ unsigned sizeof_entry = (nr_range_property_cells(me, 1)
+ * sizeof(unsigned_cell));
+ const unsigned_cell *cells;
+
+ /* locate the property */
node = device_find_property(me, property);
if (node == (device_property*)0
- || node->type != string_property)
- error("%s property %s not found or of wrong type\n",
- me->name, property);
- string = node->array;
- ASSERT(strlen(string) + 1 == node->sizeof_array);
- return string;
+ || node->type != range_array_property)
+ device_error(me, "property %s not found or of wrong type", property);
+
+ /* aligned ? */
+ if ((node->sizeof_array % sizeof_entry) != 0)
+ device_error(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,
+ device_nr_address_cells(me));
+
+ /* copy the parent address out - converting as we go */
+ cells = cells_to_unit_address(cells, &range->parent_address,
+ device_nr_address_cells(device_parent(me)));
+
+ /* copy the size - converting as we go */
+ cells = cells_to_unit_address(cells, &range->size,
+ device_nr_size_cells(me));
+
+ return node->sizeof_array / sizeof_entry;
}
-/* local - not available externally */
+
STATIC_INLINE_DEVICE\
-(device_property *)
-device_add_property(device *me,
- const char *property,
- device_property_type type,
- const void *array,
- int sizeof_array,
- const device_property *original)
+(unsigned)
+nr_reg_property_cells(device *me,
+ int nr_regs)
{
- device_property_entry *new_entry = 0;
- device_property *new_value = 0;
- void *new_array = 0;
- /* find the list end */
- device_property_entry **insertion_point = &me->properties;
- while (*insertion_point != NULL) {
- if (strcmp((*insertion_point)->value->name, property) == 0)
- return (*insertion_point)->value;
- insertion_point = &(*insertion_point)->next;
- }
- /* alloc data for the new property */
- new_entry = ZALLOC(device_property_entry);
- new_value = ZALLOC(device_property);
- new_array = (sizeof_array > 0
- ? zalloc(sizeof_array)
- : (void*)0);
- /* insert the new property into the list */
- *insertion_point = new_entry;
- new_entry->value = new_value;
- new_value->name = strdup(property);
- new_value->type = type;
- new_value->sizeof_array = sizeof_array;
- new_value->array = new_array;
- new_value->owner = me;
- new_value->original = original;
- if (sizeof_array > 0)
- memcpy(new_array, array, sizeof_array);
- return new_value;
+ return (device_nr_address_cells(device_parent(me))
+ + device_nr_size_cells(device_parent(me))
+ ) * nr_regs;
}
INLINE_DEVICE\
(void)
-device_add_duplicate_property(device *me,
+device_add_reg_array_property(device *me,
const char *property,
- const device_property *original)
-{
- TRACE(trace_devices,
- ("device_add_duplicate_property(me=0x%lx, property=%s, ...)\n",
- (long)me, property));
- device_add_property(me, property,
- original->type,
- original->array,
- original->sizeof_array,
- original);
+ const reg_property_spec *regs,
+ unsigned nr_regs)
+{
+ unsigned sizeof_cells = (nr_reg_property_cells(me, nr_regs)
+ * sizeof(unsigned_cell));
+ unsigned_cell *cells = zalloc(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,
+ device_nr_address_cells(device_parent(me)));
+ /* copy the size */
+ cell = unit_address_to_cells(&reg->size, cell,
+ device_nr_size_cells(device_parent(me)));
+ }
+ ASSERT(cell == &cells[nr_reg_property_cells(me, nr_regs)]);
+
+ /* add it */
+ device_add_property(me, property, reg_array_property,
+ cells, sizeof_cells,
+ cells, sizeof_cells,
+ NULL, permenant_object);
+
+ zfree(cells);
}
INLINE_DEVICE\
-(void)
-device_add_array_property(device *me,
- const char *property,
- const void *array,
- int sizeof_array)
+(int)
+device_find_reg_array_property(device *me,
+ const char *property,
+ unsigned index,
+ reg_property_spec *reg)
{
- TRACE(trace_devices,
- ("device_add_array_property(me=0x%lx, property=%s, ...)\n",
- (long)me, property));
- device_add_property(me, property,
- array_property, array, sizeof_array, NULL);
+ const device_property *node;
+ unsigned sizeof_entry = (nr_reg_property_cells(me, 1)
+ * sizeof(unsigned_cell));
+ const unsigned_cell *cells;
+
+ /* locate the property */
+ node = device_find_property(me, property);
+ if (node == (device_property*)0
+ || node->type != reg_array_property)
+ device_error(me, "property %s not found or of wrong type", property);
+
+ /* aligned ? */
+ if ((node->sizeof_array % sizeof_entry) != 0)
+ device_error(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,
+ device_nr_address_cells(device_parent(me)));
+
+ /* copy the size out - converting as we go */
+ cells = cells_to_unit_address(cells, &reg->size,
+ device_nr_size_cells(device_parent(me)));
+
+ return node->sizeof_array / sizeof_entry;
}
+
INLINE_DEVICE\
(void)
-device_add_boolean_property(device *me,
- const char *property,
- int boolean)
+device_add_string_property(device *me,
+ const char *property,
+ const char *string)
{
- signed32 new_boolean = (boolean ? -1 : 0);
- TRACE(trace_devices,
- ("device_add_boolean(me=0x%lx, property=%s, boolean=%d)\n",
- (long)me, property, boolean));
- device_add_property(me, property, boolean_property,
- &new_boolean, sizeof(new_boolean), NULL);
+ device_add_property(me, property, string_property,
+ string, strlen(string) + 1,
+ string, strlen(string) + 1,
+ NULL, permenant_object);
}
INLINE_DEVICE\
-(void)
-device_add_ihandle_property(device *me,
- const char *property,
- device_instance *instance)
+(const char *)
+device_find_string_property(device *me,
+ const char *property)
{
- unsigned32 ihandle = H2BE_4(device_instance_to_external(instance));
- TRACE(trace_devices,
- ("device_add_ihandle_property(me=0x%lx, property=%s, instance=0x%lx)\n",
- (long)me, property, (unsigned long)instance));
- device_add_property(me, property, ihandle_property,
- &ihandle, sizeof(ihandle), NULL);
+ const device_property *node;
+ const char *string;
+ node = device_find_property(me, property);
+ if (node == (device_property*)0
+ || node->type != string_property)
+ device_error(me, "property %s not found or of wrong type", property);
+ string = node->array;
+ ASSERT(strlen(string) + 1 == node->sizeof_array);
+ return string;
}
INLINE_DEVICE\
(void)
-device_add_integer_property(device *me,
- const char *property,
- signed32 integer)
-{
- TRACE(trace_devices,
- ("device_add_integer_property(me=0x%lx, property=%s, integer=%ld)\n",
- (long)me, property, (long)integer));
- H2BE(integer);
- device_add_property(me, property, integer_property,
- &integer, sizeof(integer), NULL);
+device_add_string_array_property(device *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)
+ device_error(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*)zalloc(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 */
+ device_add_property(me, property, string_array_property,
+ array, sizeof_array,
+ array, sizeof_array,
+ NULL, permenant_object);
}
INLINE_DEVICE\
-(void)
-device_add_phandle_property(device *me,
- const char *property,
- device *phandle)
+(int)
+device_find_string_array_property(device *me,
+ const char *property,
+ unsigned index,
+ string_property_spec *string)
{
- error("device_add_phandle_property unimplemented\n");
+ const device_property *node;
+ node = device_find_property(me, property);
+ if (node == (device_property*)0)
+ device_error(me, "property %s not found", property);
+ switch (node->type) {
+ default:
+ device_error(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')
+ device_error(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;
}
INLINE_DEVICE\
(void)
-device_add_string_property(device *me,
- const char *property,
- const char *string)
+device_add_duplicate_property(device *me,
+ const char *property,
+ const device_property *original)
{
-
+ device_property_entry *master;
TRACE(trace_devices,
- ("device_add_property(me=0x%lx, property=%s, string=%s)\n",
- (long)me, property, string));
- device_add_property(me, property, string_property,
- string, strlen(string) + 1, NULL);
+ ("device_add_duplicate_property(me=0x%lx, property=%s, ...)\n",
+ (long)me, property));
+ if (original->disposition != permenant_object)
+ device_error(me, "Can only duplicate permenant objects");
+ /* find the original's master */
+ master = original->owner->properties;
+ while (master->value != original) {
+ master = master->next;
+ ASSERT(master != NULL);
+ }
+ /* now duplicate it */
+ device_add_property(me, property,
+ original->type,
+ master->init_array, master->sizeof_init_array,
+ original->array, original->sizeof_array,
+ original, permenant_object);
}
@@ -1077,9 +1539,11 @@ device_io_read_buffer(device *me,
cpu *processor,
unsigned_word cia)
{
- return me->callback->io_read_buffer(me, dest, space,
- addr, nr_bytes,
- processor, cia);
+ if (me->callback->io.read_buffer == NULL)
+ device_error(me, "no io.read_buffer method");
+ return me->callback->io.read_buffer(me, dest, space,
+ addr, nr_bytes,
+ processor, cia);
}
INLINE_DEVICE\
@@ -1092,7 +1556,9 @@ device_io_write_buffer(device *me,
cpu *processor,
unsigned_word cia)
{
- return me->callback->io_write_buffer(me, source, space,
+ if (me->callback->io.write_buffer == NULL)
+ device_error(me, "no io.write_buffer method");
+ return me->callback->io.write_buffer(me, source, space,
addr, nr_bytes,
processor, cia);
}
@@ -1105,7 +1571,9 @@ device_dma_read_buffer(device *me,
unsigned_word addr,
unsigned nr_bytes)
{
- return me->callback->dma_read_buffer(me, dest, space,
+ if (me->callback->dma.read_buffer == NULL)
+ device_error(me, "no dma.read_buffer method");
+ return me->callback->dma.read_buffer(me, dest, space,
addr, nr_bytes);
}
@@ -1118,7 +1586,9 @@ device_dma_write_buffer(device *me,
unsigned nr_bytes,
int violate_read_only_section)
{
- return me->callback->dma_write_buffer(me, source, space,
+ if (me->callback->dma.write_buffer == NULL)
+ device_error(me, "no dma.write_buffer method");
+ return me->callback->dma.write_buffer(me, source, space,
addr, nr_bytes,
violate_read_only_section);
}
@@ -1126,31 +1596,33 @@ device_dma_write_buffer(device *me,
INLINE_DEVICE\
(void)
device_attach_address(device *me,
- const char *name,
attach_type attach,
int space,
unsigned_word addr,
unsigned nr_bytes,
access_type access,
- device *who) /*callback/default*/
+ device *client) /*callback/default*/
{
- me->callback->attach_address(me, name, attach, space,
- addr, nr_bytes, access, who);
+ if (me->callback->address.attach == NULL)
+ device_error(me, "no address.attach method");
+ me->callback->address.attach(me, attach, space,
+ addr, nr_bytes, access, client);
}
INLINE_DEVICE\
(void)
device_detach_address(device *me,
- const char *name,
attach_type attach,
int space,
unsigned_word addr,
unsigned nr_bytes,
access_type access,
- device *who) /*callback/default*/
+ device *client) /*callback/default*/
{
- me->callback->detach_address(me, name, attach, space,
- addr, nr_bytes, access, who);
+ if (me->callback->address.detach == NULL)
+ device_error(me, "no address.detach method");
+ me->callback->address.detach(me, attach, space,
+ addr, nr_bytes, access, client);
}
@@ -1164,45 +1636,26 @@ device_interrupt_event(device *me,
cpu *processor,
unsigned_word cia)
{
- int found_a_handler = 0;
+ int found_an_edge = 0;
device_interrupt_edge *edge;
/* device's interrupt lines directly connected */
for (edge = me->interrupt_destinations;
edge != NULL;
edge = edge->next) {
if (edge->my_port == my_port) {
- if (edge->dest->callback->interrupt_event == NULL)
- error("device_interrupt_event: interrupt callback null\n");
- edge->dest->callback->interrupt_event(edge->dest,
+ if (edge->dest->callback->interrupt.event == NULL)
+ device_error(me, "no interrupt method");
+ edge->dest->callback->interrupt.event(edge->dest,
edge->dest_port,
me,
my_port,
level,
processor, cia);
- found_a_handler = 1;
+ found_an_edge = 1;
}
}
- if (!found_a_handler) {
- /* device's interrupt lines hopefully on a parents bus */
- device *parent;
- for (parent = me->parent;
- parent != NULL;
- parent = parent->parent) {
- for (edge = parent->child_interrupt_destinations;
- edge != NULL;
- edge = edge->next) {
- if (edge->dest->callback->child_interrupt_event == NULL)
- error("device_interrupt_event: child_interrupt callback null\n");
- edge->dest->callback->child_interrupt_event(edge->dest,
- parent,
- me,
- my_port,
- level,
- processor, cia);
- return;
- }
- }
- error("device_interrupt_event: fell out of tree\n");
+ if (!found_an_edge) {
+ device_error(me, "No interrupt edge for port %d", my_port);
}
}
@@ -1212,13 +1665,13 @@ device_interrupt_attach(device *me,
int my_port,
device *dest,
int dest_port,
- int permenant)
+ object_disposition disposition)
{
attach_device_interrupt_edge(&me->interrupt_destinations,
my_port,
dest,
dest_port,
- permenant);
+ disposition);
}
INLINE_DEVICE\
@@ -1228,7 +1681,8 @@ device_interrupt_detach(device *me,
device *dest,
int dest_port)
{
- detach_device_interrupt_edge(&me->interrupt_destinations,
+ detach_device_interrupt_edge(me,
+ &me->interrupt_destinations,
my_port,
dest,
dest_port);
@@ -1236,26 +1690,103 @@ device_interrupt_detach(device *me,
INLINE_DEVICE\
(void)
-device_child_interrupt_attach(device *me,
- device *dest,
- int permenant)
+device_interrupt_traverse(device *me,
+ device_interrupt_traverse_function *handler,
+ void *data)
{
- attach_device_interrupt_edge(&me->interrupt_destinations,
- 0, /*my_port*/
- dest,
- 0, /*dest_port*/
- permenant);
+ device_interrupt_edge *interrupt_edge;
+ for (interrupt_edge = me->interrupt_destinations;
+ interrupt_edge != NULL;
+ interrupt_edge = interrupt_edge->next) {
+ handler(me, interrupt_edge->my_port,
+ interrupt_edge->dest, interrupt_edge->dest_port,
+ data);
+ }
}
INLINE_DEVICE\
-(void)
-device_child_interrupt_detach(device *me,
- device *dest)
+(int)
+device_interrupt_decode(device *me,
+ const char *port_name,
+ port_direction direction)
{
- detach_device_interrupt_edge(&me->interrupt_destinations,
- 0, /*my_port*/
- dest,
- 0); /*dest_port*/
+ if (port_name == NULL || port_name[0] == '\0')
+ return 0;
+ if (isdigit(port_name[0])) {
+ return strtoul(port_name, NULL, 0);
+ }
+ else {
+ const device_interrupt_port_descriptor *ports =
+ me->callback->interrupt.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)
+ device_error(me, "Interrupt port %s out of range",
+ port_name);
+ return port;
+ }
+ }
+ }
+ else if (strcmp(port_name, ports->name) == 0)
+ return ports->number;
+ }
+ ports++;
+ }
+ }
+ }
+ device_error(me, "Unreconized interrupt port %s", port_name);
+ return 0;
+}
+
+INLINE_DEVICE\
+(int)
+device_interrupt_encode(device *me,
+ int port_number,
+ char *buf,
+ int sizeof_buf,
+ port_direction direction)
+{
+ const device_interrupt_port_descriptor *ports = NULL;
+ ports = me->callback->interrupt.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)
+ error("device_interrupt_encode: buffer overflow");
+ return strlen(buf);
+ }
+ }
+ else {
+ if (ports->number == port_number) {
+ if (strlen(ports->name) >= sizeof_buf)
+ error("device_interrupt_encode: buffer overflow");
+ strcpy(buf, ports->name);
+ return strlen(buf);
+ }
+ }
+ }
+ ports++;
+ }
+ }
+ sprintf(buf, "%d", port_number);
+ if (strlen(buf) >= sizeof_buf)
+ error("device_interrupt_encode: buffer overflow");
+ return strlen(buf);
}
@@ -1263,407 +1794,205 @@ device_child_interrupt_detach(device *me,
/* IOCTL: */
EXTERN_DEVICE\
-(void)
+(int)
device_ioctl(device *me,
- psim *system,
cpu *processor,
unsigned_word cia,
+ device_ioctl_request request,
...)
{
+ int status;
va_list ap;
- va_start(ap, cia);
- me->callback->ioctl(me, system, processor, cia, ap);
+ va_start(ap, request);
+ if (me->callback->ioctl == NULL)
+ device_error(me, "no ioctl method");
+ status = me->callback->ioctl(me, processor, cia, request, ap);
va_end(ap);
+ return status;
}
-/* Tree utilities: */
+/* I/O */
EXTERN_DEVICE\
-(device *)
-device_tree_add_parsed(device *current,
- const char *fmt,
- ...)
-{
- char device_specifier[1024];
- name_specifier spec;
-
- /* format the path */
- {
- va_list ap;
- va_start(ap, fmt);
- vsprintf(device_specifier, fmt, ap);
- va_end(ap);
- if (strlen(device_specifier) >= sizeof(device_specifier))
- error("error in device_tree_add_parsed - buffer overflow\n");
- }
-
- /* break it up */
- if (!split_device_specifier(device_specifier, &spec))
- error("error parsing device %s\n", device_path);
-
- /* fill our tree with its contents */
- current = split_find_device(current, &spec);
+(void volatile)
+device_error(device *me,
+ const char *fmt,
+ ...)
+{
+ char message[1024];
+ va_list ap;
+ /* format the message */
+ va_start(ap, fmt);
+ vsprintf(message, fmt, ap);
+ va_end(ap);
+ /* sanity check */
+ if (strlen(message) >= sizeof(message))
+ error("device_error: buffer overflow");
+ if (me == NULL)
+ error("device: %s", message);
+ else if (me->path != NULL && me->path[0] != '\0')
+ error("%s: %s", me->path, message);
+ else if (me->name != NULL && me->name[0] != '\0')
+ error("%s: %s", me->name, message);
+ else
+ error("device: %s", message);
+ while(1);
+}
- /* add any additional devices as needed */
- if (spec.name != NULL) {
- do {
- current =
- device_template_create_device(current, spec.name, spec.unit, spec.args);
- } while (split_device_name(&spec));
- }
+INLINE_DEVICE\
+(int)
+device_trace(device *me)
+{
+ return me->trace;
+}
- /* is there an interrupt spec */
- if (spec.property == NULL
- && spec.value != NULL) {
- switch (spec.value[0]) {
- case '>':
- {
- int my_port = strtoul(spec.value+1, &spec.value, 0);
- int dest_port = strtoul(spec.value+1, &spec.value, 0);
- device *dest = device_tree_find_device(current, spec.value);
- device_interrupt_attach(current,
- my_port,
- dest,
- dest_port,
- 1);/*permenant*/
- }
- break;
- case '<':
- spec.value++;
- device_child_interrupt_attach(current,
- device_tree_find_device(current,
- spec.value),
- 1);/*permenant*/
- break;
- default:
- error("unreconised interrupt spec %s\n", spec.value);
- break;
- }
- }
+
+/* External representation */
- /* is there a property */
- if (spec.property != NULL) {
- if (strcmp(spec.value, "true") == 0)
- device_add_boolean_property(current, spec.property, 1);
- else if (strcmp(spec.value, "false") == 0)
- device_add_boolean_property(current, spec.property, 0);
- else {
- const device_property *property;
- switch (spec.value[0]) {
- case '*':
- spec.value++;
- device_add_ihandle_property(current, spec.property,
- device_instance_create(current,
- spec.value,
- 1/*permenant*/));
- break;
- case '-': case '+':
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- device_add_integer_property(current, spec.property,
- strtoul(spec.value, &spec.value, 0));
- break;
- 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;
- }
- device_add_array_property(current, spec.property,
- words, sizeof(words[0]) * nr_words);
- }
- break;
- case '{':
- {
- unsigned32 words[1024];
- char *curr = spec.value + 1;
- int nr_words = 0;
- while (1) {
- char *next;
- words[nr_words] = H2BE_4(strtoul(curr, &next, 0));
- if (curr == next)
- break;
- curr = next;
- nr_words += 1;
- }
- device_add_array_property(current, spec.property,
- words, sizeof(words[0]) * nr_words);
- }
- break;
- case '&':
- spec.value++;
- device_add_phandle_property(current, spec.property,
- device_tree_find_device(current,
- spec.value));
- break;
- case '"':
- spec.value++;
- default:
- device_add_string_property(current, spec.property, spec.value);
- break;
- case '!':
- spec.value++;
- property = device_find_property(current, spec.value);
- if (property == NULL)
- error("Can not duplicate property, original %s not found\n",
- spec.value);
- device_add_duplicate_property(current,
- spec.property,
- property);
- break;
- }
- }
- }
- return current;
+INLINE_DEVICE\
+(device *)
+external_to_device(device *tree_member,
+ unsigned_cell phandle)
+{
+ device *me = cap_internal(tree_member->phandles, phandle);
+ return me;
}
INLINE_DEVICE\
-(void)
-device_tree_traverse(device *root,
- device_tree_traverse_function *prefix,
- device_tree_traverse_function *postfix,
- void *data)
-{
- device *child;
- if (prefix != NULL)
- prefix(root, data);
- for (child = root->children; child != NULL; child = child->sibling) {
- device_tree_traverse(child, prefix, postfix, data);
- }
- if (postfix != NULL)
- postfix(root, data);
+(unsigned_cell)
+device_to_external(device *me)
+{
+ unsigned_cell phandle = cap_external(me->phandles, me);
+ return phandle;
}
INLINE_DEVICE\
-(void)
-device_tree_print_device(device *me,
- void *ignore_or_null)
+(device_instance *)
+external_to_device_instance(device *tree_member,
+ unsigned_cell ihandle)
{
- const device_property *property;
- device_interrupt_edge *interrupt_edge;
- /* output my name */
- printf_filtered("%s\n", me->path);
- /* properties */
- for (property = device_find_property(me, NULL);
- property != NULL;
- property = device_next_property(property)) {
- printf_filtered("%s/%s", me->path, property->name);
- if (property->original != NULL) {
- printf_filtered(" !");
- printf_filtered("%s/%s\n", property->original->owner->path,
- property->original->name);
- }
- else {
- switch (property->type) {
- case array_property:
- {
- if ((property->sizeof_array % sizeof(unsigned32)) == 0) {
- unsigned32 *w = (unsigned32*)property->array;
- printf_filtered(" {");
- while ((char*)w - (char*)property->array < property->sizeof_array) {
- printf_filtered(" 0x%lx", BE2H_4(*w));
- w++;
- }
- }
- else {
- unsigned8 *w = (unsigned8*)property->array;
- printf_filtered(" [");
- while ((char*)w - (char*)property->array < property->sizeof_array) {
- printf_filtered(" 0x%2x", BE2H_1(*w));
- w++;
- }
- }
- printf_filtered("\n");
- }
- break;
- case boolean_property:
- {
- int b = device_find_boolean_property(me, property->name);
- printf_filtered(" %s\n", b ? "true" : "false");
- }
- break;
- case ihandle_property:
- {
- device_instance *i = device_find_ihandle_property(me, property-> name);
- printf_filtered(" *%s\n", i->path);
- }
- break;
- case integer_property:
- {
- unsigned_word w = device_find_integer_property(me, property->name);
- printf_filtered(" 0x%lx\n", (unsigned long)w);
- }
- break;
- case phandle_property:
- {
- device *d = device_find_phandle_property(me, property->name);
- printf_filtered(" *%s\n", d->path);
- }
- break;
- case string_property:
- {
- const char *s = device_find_string_property(me, property->name);
- printf_filtered(" \"%s\n", s);
- }
- break;
- }
- }
- }
- /* interrupts */
- for (interrupt_edge = me->interrupt_destinations;
- interrupt_edge != NULL;
- interrupt_edge = interrupt_edge->next) {
- printf_filtered("%s >%d %d %s\n",
- me->path,
- interrupt_edge->my_port,
- interrupt_edge->dest_port,
- interrupt_edge->dest->path);
- }
- /* child interrupts */
- for (interrupt_edge = me->child_interrupt_destinations;
- interrupt_edge != NULL;
- interrupt_edge = interrupt_edge->next) {
- printf_filtered("%s <%s\n", me->path, interrupt_edge->dest->path);
- }
+ device_instance *instance = cap_internal(tree_member->ihandles, ihandle);
+ return instance;
}
INLINE_DEVICE\
-(device *)
-device_tree_find_device(device *root,
- const char *path)
-{
- device *node;
- name_specifier spec;
- TRACE(trace_device_tree,
- ("device_tree_find_device_tree(root=0x%lx, path=%s)\n",
- (long)root, path));
- /* parse the path */
- split_device_specifier(path, &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 */
+(unsigned_cell)
+device_instance_to_external(device_instance *instance)
+{
+ unsigned_cell ihandle = cap_external(instance->owner->ihandles, instance);
+ return ihandle;
+}
- return node;
+
+/* Map onto the event functions */
+
+INLINE_DEVICE\
+(event_entry_tag)
+device_event_queue_schedule(device *me,
+ signed64 delta_time,
+ device_event_handler *handler,
+ void *data)
+{
+ return event_queue_schedule(psim_event_queue(me->system),
+ delta_time,
+ handler,
+ data);
}
INLINE_DEVICE\
(void)
-device_usage(int verbose)
+device_event_queue_deschedule(device *me,
+ event_entry_tag event_to_remove)
{
- if (verbose == 1) {
- device_descriptor *descr;
- int pos;
- printf_filtered("\n");
- printf_filtered("A device/property specifier has the form:\n");
- printf_filtered("\n");
- printf_filtered(" /path/to/a/device [ property-value ]\n");
- printf_filtered("\n");
- printf_filtered("and a possible device is\n");
- printf_filtered("\n");
- pos = 0;
- for (descr = device_table; descr->name != NULL; descr++) {
- pos += strlen(descr->name) + 2;
- if (pos > 75) {
- pos = strlen(descr->name) + 2;
- printf_filtered("\n");
- }
- printf_filtered(" %s", descr->name);
- }
- printf_filtered("\n");
- }
- if (verbose > 1) {
- device_descriptor *descr;
- printf_filtered("\n");
- printf_filtered("A device/property specifier (<spec>) has the format:\n");
- printf_filtered("\n");
- printf_filtered(" <spec> ::= <path> [ <value> ] ;\n");
- printf_filtered(" <path> ::= { <prefix> } { <node> \"/\" } <node> ;\n");
- printf_filtered(" <prefix> ::= ( | \"/\" | \"../\" | \"./\" ) ;\n");
- printf_filtered(" <node> ::= <name> [ \"@\" <unit> ] [ \":\" <args> ] ;\n");
- printf_filtered(" <unit> ::= <number> { \",\" <number> } ;\n");
- printf_filtered("\n");
- printf_filtered("Where:\n");
- printf_filtered("\n");
- printf_filtered(" <name> is the name of a device (list below)\n");
- printf_filtered(" <unit> is the unit-address relative to the parent bus\n");
- printf_filtered(" <args> additional arguments used when creating the device\n");
- printf_filtered(" <value> ::= ( <number> # integer property\n");
- printf_filtered(" | \"[\" { <number> } # array property (byte)\n");
- printf_filtered(" | \"{\" { <number> } # array property (cell)\n");
- printf_filtered(" | [ \"true\" | \"false\" ] # boolean property\n");
- printf_filtered(" | \"*\" <path> # ihandle property\n");
- printf_filtered(" | \"*\" <path> # ihandle property\n");
- printf_filtered(" | \"!\" <path> # copy property\n");
- printf_filtered(" | \">\" [ <number> ] <path> # attach interrupt\n");
- printf_filtered(" | \"<\" <path> # attach child interrupt\n");
- printf_filtered(" | \"\\\"\" <text> # string property\n");
- printf_filtered(" | <text> # string property\n");
- printf_filtered(" ) ;\n");
- printf_filtered("\n");
- printf_filtered("And the following are valid device names:\n");
- printf_filtered("\n");
- for (descr = device_table; descr->name != NULL; descr++) {
- if (descr->callbacks->usage != NULL)
- descr->callbacks->usage(verbose);
- else
- printf_filtered(" %s\n", descr->name);
- }
- }
+ event_queue_deschedule(psim_event_queue(me->system),
+ event_to_remove);
}
-
-
-/* External representation */
-
INLINE_DEVICE\
-(device *)
-external_to_device(device *tree_member,
- unsigned32 phandle)
+(signed64)
+device_event_queue_time(device *me)
{
- device *root = device_tree_find_device(tree_member, "/");
- device *me = cap_internal(root->phandles, phandle);
- return me;
+ return event_queue_time(psim_event_queue(me->system));
}
+
+/* Initialization: */
+
+
INLINE_DEVICE\
-(unsigned32)
-device_to_external(device *me)
+(void)
+device_clean(device *me,
+ void *data)
{
- device *root = device_tree_find_device(me, "/");
- unsigned32 phandle = cap_external(root->phandles, me);
- return phandle;
+ psim *system;
+ system = (psim*)data;
+ TRACE(trace_device_init, ("device_clean - initializing %s", me->path));
+ clean_device_interrupt_edges(&me->interrupt_destinations);
+ clean_device_instances(me);
+ clean_device_properties(me);
}
+/* Device initialization: */
+
INLINE_DEVICE\
-(device_instance *)
-external_to_device_instance(device *tree_member,
- unsigned32 ihandle)
+(void)
+device_init_address(device *me,
+ void *data)
{
- device *root = device_tree_find_device(tree_member, "/");
- device_instance *instance = cap_internal(root->ihandles, ihandle);
- return instance;
+ psim *system = (psim*)data;
+ int nr_address_cells;
+ int nr_size_cells;
+ TRACE(trace_device_init, ("device_init_address - initializing %s", me->path));
+
+ /* ensure the cap database is valid */
+ if (me->parent == NULL) {
+ cap_init(me->ihandles);
+ cap_init(me->phandles);
+ }
+
+ /* some basics */
+ me->system = system; /* misc things not known until now */
+ me->trace = (device_find_property(me, "trace")
+ ? device_find_integer_property(me, "trace")
+ : 0);
+
+ /* Ensure that the first address found in the reg property matches
+ anything that was specified as part of the devices name */
+ if (device_find_property(me, "reg") != NULL) {
+ reg_property_spec unit;
+ device_find_reg_array_property(me, "reg", 0, &unit);
+ if (memcmp(device_unit_address(me), &unit.address, sizeof(unit.address))
+ != 0)
+ device_error(me, "Unit address as specified by the reg property in conflict with the value previously specified in the devices path");
+ }
+
+ /* ensure that the devices #address/size-cells is consistent */
+ nr_address_cells = device_nr_address_cells(me);
+ if (device_find_property(me, "#address-cells") != NULL
+ && (nr_address_cells
+ != device_find_integer_property(me, "#address-cells")))
+ device_error(me, "#address-cells property used before defined");
+ nr_size_cells = device_nr_size_cells(me);
+ if (device_find_property(me, "#size-cells") != NULL
+ && (nr_size_cells
+ != device_find_integer_property(me, "#size-cells")))
+ device_error(me, "#size-cells property used before defined");
+
+ /* now init it */
+ if (me->callback->init.address != NULL)
+ me->callback->init.address(me);
}
INLINE_DEVICE\
-(unsigned32)
-device_instance_to_external(device_instance *instance)
+(void)
+device_init_data(device *me,
+ void *data)
{
- device *root = device_tree_find_device(instance->owner, "/");
- unsigned32 ihandle = cap_external(root->ihandles, instance);
- return ihandle;
+ TRACE(trace_device_init, ("device_init_data - initializing %s", me->path));
+ if (me->callback->init.data != NULL)
+ me->callback->init.data(me);
}
#endif /* _DEVICE_C_ */
diff --git a/gnu/dist/sim/ppc/device.h b/gnu/dist/sim/ppc/device.h
index 7c74aefdd1c..6fc647145c0 100644
--- a/gnu/dist/sim/ppc/device.h
+++ b/gnu/dist/sim/ppc/device.h
@@ -30,189 +30,185 @@
/* typedef struct _device device; */
-/* Devices:
+/* Introduction:
- OpenBoot documentation refers to devices, device nodes, packages,
- package instances, methods, static methods and properties. This
- device implementation uses its own termonology. Where ever it
- exists, the notes will indicate a correspondance between PSIM terms
- and those found in OpenBoot.
+ As explained in earlier sections, the device, device instance,
+ property and interrupts lie at the heart of PSIM's device model.
- device:
+ In the below a synopsis of the device object and the operations it
+ supports are given. Details of this object can be found in the
+ files <<device.h>> and <<device.c>>.
- A device is the basic building block in this model. A device can
- be further categorized into one of three classes - template, node
- and instance.
-
- device-node (aka device):
-
- The device tree is constructed from device-nodes. Each node has
- both local state (data), a relationship with the device nodes
- around it and an address (unit-address) on the parents bus `bus' */
-
-INLINE_DEVICE(device *) device_parent
-(device *me);
-
-INLINE_DEVICE(device *) device_sibling
-(device *me);
+ */
-INLINE_DEVICE(device *) device_child
-(device *me);
-INLINE_DEVICE(const char *) device_name
-(device *me);
+/* Device creation: */
-INLINE_DEVICE(const char *) device_path
-(device *me);
+INLINE_DEVICE\
+(device *) device_create
+(device *parent,
+ const char *base,
+ const char *name,
+ const char *unit_address,
+ const char *args);
-INLINE_DEVICE(void *) device_data
-(device *me);
+INLINE_DEVICE\
+(void) device_usage
+(int verbose);
-typedef struct _device_unit {
- int nr_cells;
- unsigned32 cells[4]; /* unused cells are zero */
-} device_unit;
-INLINE_DEVICE(const device_unit *) device_unit_address
-(device *me);
+/* Device initialization: */
-/* Each device-node normally corresponds to a hardware component of
- the system being modeled. Leaf nodes matching external devices and
- intermediate nodes matching bridges and controllers.
-
- Device nodes also support methods that are an abstraction of the
- transactions that occure in real hardware. These operations
- (io/dma read/writes and interrupts) are discussed separatly later.
+INLINE_DEVICE\
+(void) device_clean
+(device *root,
+ void *data);
- OpenBoot refers to device nodes by many names. The most common are
- device, device node and package.
+INLINE_DEVICE\
+(void) device_init_static_properties
+(device *me,
+ void *data);
+INLINE_DEVICE\
+(void) device_init_address
+(device *me,
+ void *data);
- device-template:
+INLINE_DEVICE\
+(void) device_init_runtime_properties
+(device *me,
+ void *data);
- A device node is created from its template. The only valid
- operation on a template is to create a device node from it: */
+INLINE_DEVICE\
+(void) device_init_data
+(device *me,
+ void *data);
-INLINE_DEVICE(device *) device_template_create_device
-(device *parent,
- const char *name,
- const char *unit_address,
- const char *args);
-/* The create is paramaterized by both the devices unit address (a
- string that is converted into numeric form by the devices parent)
- and optionally extra argument information.
+/* Relationships:
- The actual device node is constructed by a number of pieces provided
- by the template function: */
+ 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).
-typedef struct _device_callbacks device_callbacks;
+ */
-INLINE_DEVICE(device *) device_create_from
-(const char *name,
- const device_unit *unit_address,
- void *data,
- const device_callbacks *callbacks,
- device *parent);
+INLINE_DEVICE\
+(device *) device_parent
+(device *me);
-/* OpenBoot discusses the creation of packages (devices).
+INLINE_DEVICE\
+(device *) device_root
+(device *me);
+INLINE_DEVICE\
+(device *) device_sibling
+(device *me);
+INLINE_DEVICE\
+(device *) device_child
+(device *me);
+INLINE_DEVICE\
+(const char *) device_name
+(device *me);
- device-instance:
+INLINE_DEVICE\
+(const char *) device_base
+(device *me);
- Devices support an abstract I/O model. A unique I/O instance can be
- created from a device node and then this instance used to perform
- I/O that is independant of other instances. */
+INLINE_DEVICE\
+(const char *) device_path
+(device *me);
-INLINE_DEVICE(device_instance *)device_instance_create
-(device *me,
- const char *device_specifier,
- int permanant);
+INLINE_DEVICE\
+(void *) device_data
+(device *me);
-INLINE_DEVICE(void) device_instance_delete
-(device_instance *instance);
+INLINE_DEVICE\
+(psim *) device_system
+(device *me);
-INLINE_DEVICE(int) device_instance_read
-(device_instance *instance,
- void *addr,
- unsigned_word len);
+typedef struct _device_unit {
+ int nr_cells;
+ unsigned_cell cells[4]; /* unused cells are zero */
+} device_unit;
-INLINE_DEVICE(int) device_instance_write
-(device_instance *instance,
- const void *addr,
- unsigned_word len);
+INLINE_DEVICE\
+(const device_unit *) device_unit_address
+(device *me);
-INLINE_DEVICE(int) device_instance_seek
-(device_instance *instance,
- unsigned_word pos_hi,
- unsigned_word pos_lo);
+INLINE_DEVICE\
+(int) device_decode_unit
+(device *bus,
+ const char *unit,
+ device_unit *address);
-INLINE_DEVICE(device *) device_instance_device
-(device_instance *instance);
+INLINE_DEVICE\
+(int) device_encode_unit
+(device *bus,
+ const device_unit *unit_address,
+ char *buf,
+ int sizeof_buf);
-INLINE_DEVICE(const char *) device_instance_name
-(device_instance *instance);
-INLINE_DEVICE(const char *) device_instance_path
-(device_instance *instance);
+/* Convert an Open Firmware size into a form suitable for attach
+ address calls.
-INLINE_DEVICE(void *) device_instance_data
-(device_instance *instance);
+ Return a zero result if the address should be ignored when looking
+ for attach addresses */
-/* A device instance can be marked (when created) as being permenant.
- Such instances are assigned a reserved address and are *not*
- deleted between simulation runs.
+INLINE_DEVICE\
+(int) device_address_to_attach_address
+(device *me,
+ const device_unit *address,
+ int *attach_space,
+ unsigned_word *attach_address,
+ device *client);
- OpenBoot refers to a device instace as a package instance */
-
-/* Device initialization:
+/* Convert an Open Firmware size into a form suitable for attach
+ address calls
- A device is created once (from its template) but initialized at the
- start of every simulation run. This initialization is performed in
- stages:
+ Return a zero result if the address should be ignored */
- o All attached addresses are detached
- Any non-permenant interrupts are detached
- Any non-permemant device instances are deleted
+INLINE_DEVICE\
+(int) device_size_to_attach_size
+(device *me,
+ const device_unit *size,
+ unsigned *nr_bytes,
+ device *client);
- o the devices all initialize their address spaces
-
- o the devices all initialize their data areas
- */
+INLINE_DEVICE\
+(unsigned) device_nr_address_cells
+(device *me);
-INLINE_DEVICE(void) device_init_address
-(device *me,
- psim *system);
+INLINE_DEVICE\
+(unsigned) device_nr_size_cells
+(device *me);
-INLINE_DEVICE(void) device_init_data
-(device *me,
- psim *system);
-INLINE_DEVICE(void) device_tree_init
-(device *root,
- psim *system);
+/* Properties:
+ Attached to a device are a number of properties. Each property has
+ a size and type (both of which can be queried). A device is able
+ to iterate over or query and set a properties value.
-
-/* Device Properties:
+ */
- Attached to a device node are its properties. Properties describe
- the devices characteristics, for instance the address of its
- configuration and contrll registers. Unlike OpenBoot PSIM strictly
- types all properties.properties that profile the devices features.
- The below allow the manipulation of device properties */
+/* The following are valid property types. The property `array' is
+ for generic untyped data. */
typedef enum {
array_property,
boolean_property,
- ihandle_property,
+ ihandle_property, /*runtime*/
integer_property,
- phandle_property,
+ range_array_property,
+ reg_array_property,
string_property,
+ string_array_property,
} device_property_type;
typedef struct _device_property device_property;
@@ -223,251 +219,296 @@ struct _device_property {
unsigned sizeof_array;
const void *array;
const device_property *original;
+ object_disposition disposition;
};
-/* Locate a devices properties */
+/* iterate through the properties attached to a device */
-INLINE_DEVICE(const device_property *) device_next_property
+INLINE_DEVICE\
+(const device_property *) device_next_property
(const device_property *previous);
-INLINE_DEVICE(const device_property *) device_find_property
+INLINE_DEVICE\
+(const device_property *) device_find_property
(device *me,
const char *property); /* NULL for first property */
-/* Similar to above except that the property *must* be in the device
- tree and *must* be of the specified type.
+/* Manipulate the properties belonging to a given device.
- If this isn't the case each function indicates is fail action */
+ SET on the other hand will force the properties value. The
+ simulation is aborted if the property was present but of a
+ conflicting type.
-INLINE_DEVICE(const device_property *) device_find_array_property
-(device *me,
- const char *property);
+ FIND returns the specified properties value, aborting the
+ simulation if the property is missing. Code locating a property
+ should first check its type (using device_find_property above) and
+ then obtain its value using the below.
+
+ void device_add_<type>_property(device *, const char *, <type>)
+ void device_add_*_array_property(device *, const char *, const <type>*, int)
+ void device_set_*_property(device *, const char *, <type>)
+ void device_set_*_array_property(device *, const char *, const <type>*, int)
+ <type> device_find_*_property(device *, const char *)
+ int device_find_*_array_property(device *, const char *, int, <type>*)
+
+ */
-INLINE_DEVICE(int) device_find_boolean_property
+
+INLINE_DEVICE\
+(void) device_add_array_property
(device *me,
- const char *property);
+ const char *property,
+ const void *array,
+ int sizeof_array);
-INLINE_DEVICE(device_instance *) device_find_ihandle_property
+INLINE_DEVICE\
+(void) device_set_array_property
(device *me,
- const char *property);
+ const char *property,
+ const void *array,
+ int sizeof_array);
-INLINE_DEVICE(signed_word) device_find_integer_property
+INLINE_DEVICE\
+(const device_property *) device_find_array_property
(device *me,
const char *property);
-INLINE_DEVICE(device *) device_find_phandle_property
+
+
+INLINE_DEVICE\
+(void) device_add_boolean_property
(device *me,
- const char *property);
+ const char *property,
+ int bool);
-INLINE_DEVICE(const char *) device_find_string_property
+INLINE_DEVICE\
+(int) device_find_boolean_property
(device *me,
const char *property);
-/* INLINE_DEVICE void device_add_property
- No such external function, all properties, when added are explictly
- typed */
-INLINE_DEVICE(void) device_add_duplicate_property
-(device *me,
- const char *property,
- const device_property *original);
+typedef struct _ihandle_runtime_property_spec {
+ const char *full_path;
+} ihandle_runtime_property_spec;
-INLINE_DEVICE(void) device_add_array_property
+INLINE_DEVICE\
+(void) device_add_ihandle_runtime_property
(device *me,
const char *property,
- const void *array,
- int sizeof_array);
+ const ihandle_runtime_property_spec *ihandle);
-INLINE_DEVICE(void) device_add_boolean_property
+INLINE_DEVICE\
+(void) device_find_ihandle_runtime_property
(device *me,
const char *property,
- int bool);
+ ihandle_runtime_property_spec *ihandle);
-INLINE_DEVICE(void) device_add_ihandle_property
+INLINE_DEVICE\
+(void) device_set_ihandle_property
(device *me,
const char *property,
device_instance *ihandle);
-INLINE_DEVICE(void) device_add_integer_property
+INLINE_DEVICE\
+(device_instance *) device_find_ihandle_property
(device *me,
- const char *property,
- signed_word integer);
+ const char *property);
-INLINE_DEVICE(void) device_add_phandle_property
+
+
+INLINE_DEVICE\
+(void) device_add_integer_property
(device *me,
const char *property,
- device *phandle);
+ signed_cell integer);
+
+INLINE_DEVICE\
+(signed_cell) device_find_integer_property
+(device *me,
+ const char *property);
-INLINE_DEVICE(void) device_add_string_property
+INLINE_DEVICE\
+(int) device_find_integer_array_property
(device *me,
const char *property,
- const char *string);
+ unsigned index,
+ signed_word *integer);
+
-
-/* Device Hardware:
+typedef struct _range_property_spec {
+ device_unit child_address;
+ device_unit parent_address;
+ device_unit size;
+} range_property_spec;
- This model assumes that the data paths of the system being modeled
- have a tree topology. That is, one or more processors sit at the
- top of a tree. That tree containing leaf nodes (real devices) and
- branch nodes (bridges).
+INLINE_DEVICE\
+(void) device_add_range_array_property
+(device *me,
+ const char *property,
+ const range_property_spec *ranges,
+ unsigned nr_ranges);
- For instance, consider the tree:
+INLINE_DEVICE\
+(int) device_find_range_array_property
+(device *me,
+ const char *property,
+ unsigned index,
+ range_property_spec *range);
- /pci # PCI-HOST bridge
- /pci/pci1000,1@1 # A pci controller
- /pci/isa8086 # PCI-ISA bridge
- /pci/isa8086/fdc@300 # floppy disk controller on ISA bus
- A processor needing to access the device fdc@300 on the ISA bus
- would do so using a data path that goes through the pci-host bridge
- (pci)and the isa-pci bridge (isa8086) to finally reach the device
- fdc@300. As the data transfer passes through each intermediate
- bridging node that bridge device is able to (just like with real
- hardware) manipulate either the address or data involved in the
- transfer. */
-INLINE_DEVICE(unsigned) device_io_read_buffer
+typedef struct _reg_property_spec {
+ device_unit address;
+ device_unit size;
+} reg_property_spec;
+
+INLINE_DEVICE\
+(void) device_add_reg_array_property
(device *me,
- void *dest,
- int space,
- unsigned_word addr,
- unsigned nr_bytes,
- cpu *processor,
- unsigned_word cia);
+ const char *property,
+ const reg_property_spec *reg,
+ unsigned nr_regs);
-INLINE_DEVICE(unsigned) device_io_write_buffer
+INLINE_DEVICE\
+(int) device_find_reg_array_property
(device *me,
- const void *source,
- int space,
- unsigned_word addr,
- unsigned nr_bytes,
- cpu *processor,
- unsigned_word cia);
+ const char *property,
+ unsigned index,
+ reg_property_spec *reg);
-/* Conversly, the device pci1000,1@1 my 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 */
-INLINE_DEVICE(unsigned) device_dma_read_buffer
+INLINE_DEVICE\
+(void) device_add_string_property
(device *me,
- void *dest,
- int space,
- unsigned_word addr,
- unsigned nr_bytes);
+ const char *property,
+ const char *string);
-INLINE_DEVICE(unsigned) device_dma_write_buffer
+INLINE_DEVICE\
+(const char *) device_find_string_property
(device *me,
- const void *source,
- int space,
- unsigned_word addr,
- unsigned nr_bytes,
- int violate_read_only_section);
+ const char *property);
-/* To avoid the need for an intermediate (bridging) node to ask each
- of its child devices in turn if an IO access is intended for them,
- parent nodes maintain a table mapping addresses directly to
- specific devices. When a device is `connected' to its bus it
- attaches its self to its parent. */
-/* Address access attributes */
-typedef enum _access_type {
- access_invalid = 0,
- access_read = 1,
- access_write = 2,
- access_read_write = 3,
- access_exec = 4,
- access_read_exec = 5,
- access_write_exec = 6,
- access_read_write_exec = 7,
-} access_type;
-/* Address attachement types */
-typedef enum _attach_type {
- attach_invalid,
- attach_callback,
- attach_default,
- attach_raw_memory,
-} attach_type;
+typedef const char *string_property_spec;
-INLINE_DEVICE(void) device_attach_address
+INLINE_DEVICE\
+(void) device_add_string_array_property
(device *me,
- const char *name,
- attach_type attach,
- int space,
- unsigned_word addr,
- unsigned nr_bytes,
- access_type access,
- device *who); /*callback/default*/
+ const char *property,
+ const string_property_spec *strings,
+ unsigned nr_strings);
-INLINE_DEVICE(void) device_detach_address
+INLINE_DEVICE\
+(int) device_find_string_array_property
(device *me,
- const char *name,
- attach_type attach,
- int space,
- unsigned_word addr,
- unsigned nr_bytes,
- access_type access,
- device *who); /*callback/default*/
+ const char *property,
+ unsigned index,
+ string_property_spec *string);
-/* where the attached address space can be any of:
- callback - all accesses to that range of addresses are past on to
- the attached child device.
- default - if no other device claims the access, it is passed on to
- this child device (giving subtractive decoding).
+INLINE_DEVICE\
+(void) device_add_duplicate_property
+(device *me,
+ const char *property,
+ const device_property *original);
- memory - the specified address space contains RAM, the node that is
- having the ram attached is responsible for allocating space for and
- maintaining that space. The device initiating the attach will not
- be notified of accesses to such an attachement.
- The last type of attachement is very important. By giving the
- parent node the responsability (and freedom) of managing RAM, that
- node is able to implement memory spaces more efficiently. For
- instance it could `cache' accesses or merge adjacent memory areas.
+/* Instances:
- In addition to I/O and DMA, devices interact with the rest of the
- system via interrupts. Interrupts are discussed in the next
- section. */
+ 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.
-
-/* Interrupts
+ This model includes methods that faciliate the creation of device
+ instance and (should a given device support it) standard operations
+ on those instances.
- PSIM models interrupts and their wiring as a directed graph of
- connections between interrupt sources and destinations. The source
- and destination are both a tupple consisting of a port number and
- device. Both multiple destinations attached to a single source and
- multiple sources attached to a single destination are allowed.
+ */
- When a device drives an interrupt port with multiple destinations a
- broadcast of that interrupt event (message to all destinations)
- occures. Each of those destination (device/port) are able to
- further propogate the interrupt until it reaches its ultimate
- destination.
+typedef struct _device_instance_callbacks device_instance_callbacks;
- Normally an interrupt source would be a model of a real device
- (such as a keyboard) while an interrupt destination would be an
- interrupt controller. The facility that allows an interrupt to be
- delivered to multiple devices and to be propogated from device to
- device was designed so that requirements specified by OpenPIC (ISA
- interrupts go to both OpenPIC and 8259), CHRP (8259 connected to
- OpenPIC) and hardware designs such as PCI-PCI bridges.
+INLINE_DEVICE\
+(device_instance *) device_create_instance_from
+(device *me, /*OR*/ device_instance *parent,
+ void *data,
+ const char *path,
+ const char *args,
+ const device_instance_callbacks *callbacks);
+INLINE_DEVICE\
+(device_instance *) device_create_instance
+(device *me,
+ const char *full_path,
+ const char *args);
+
+INLINE_DEVICE\
+(void) device_instance_delete
+(device_instance *instance);
+
+INLINE_DEVICE\
+(int) device_instance_read
+(device_instance *instance,
+ void *addr,
+ unsigned_word len);
+
+INLINE_DEVICE\
+(int) device_instance_write
+(device_instance *instance,
+ const void *addr,
+ unsigned_word len);
+
+INLINE_DEVICE\
+(int) device_instance_seek
+(device_instance *instance,
+ unsigned_word pos_hi,
+ unsigned_word pos_lo);
+
+INLINE_DEVICE\
+(int) device_instance_call_method
+(device_instance *instance,
+ const char *method,
+ int n_stack_args,
+ unsigned_cell stack_args[/*n_stack_args*/],
+ int n_stack_returns,
+ unsigned_cell stack_returns[/*n_stack_returns*/]);
+
+INLINE_DEVICE\
+(device *) device_instance_device
+(device_instance *instance);
+
+INLINE_DEVICE\
+(const char *) device_instance_path
+(device_instance *instance);
+
+INLINE_DEVICE\
+(void *) device_instance_data
+(device_instance *instance);
+
+
+/* Interrupts:
+
+ */
- Interrupt Source
+/* Interrupt Source
- A device drives its interrupt line using the call: */
+ A device drives its interrupt line using the call
-INLINE_DEVICE(void) device_interrupt_event
+ */
+
+INLINE_DEVICE\
+(void) device_interrupt_event
(device *me,
int my_port,
int value,
@@ -492,193 +533,212 @@ INLINE_DEVICE(void) device_interrupt_event
A destination is attached/detached to a device line using the
attach and detach calls. */
-INLINE_DEVICE(void) device_interrupt_attach
+INLINE_DEVICE\
+(void) device_interrupt_attach
(device *me,
int my_port,
device *dest,
int dest_port,
- int permenant);
+ object_disposition disposition);
-INLINE_DEVICE(void) device_interrupt_detach
+INLINE_DEVICE\
+(void) device_interrupt_detach
(device *me,
int my_port,
device *dest,
int dest_port);
-/* DESTINATION is attached (detached) to LINE of the device ME
-
- Should no destination be attached to a given devices interrupt line
- then that interrupt is propogated up the device tree (through
- parent nodes) until a parent that has an interrupt destination
- attached to its special child-interrupt line. These are attached
- with: */
-
-INLINE_DEVICE(void) device_child_interrupt_attach
-(device *me,
- device *destination,
- int permenant);
+typedef void (device_interrupt_traverse_function)
+ (device *me,
+ int my_port,
+ device *dest,
+ int my_dest,
+ void *data);
-INLINE_DEVICE(void) device_child_interrupt_detach
+INLINE_DEVICE\
+(void) device_interrupt_traverse
(device *me,
- device *destination);
-
-/* It is an error for an interrupt to be propogated past the root node
+ device_interrupt_traverse_function *handler,
+ void *data);
+
+/* DESTINATION is attached (detached) to LINE of the device ME
- Interrupting a processor
- While it is possible for an interrupt destination device to
- directly interrupt a processor (using interrupt.h calls) it is not
- the norm. Interrupting a processor midway through the cpu cycle
- would result in a simulation restart. This restart may result in
- the interrupt not being delivered to all the intended destinations.
+ Interrupt conversion
- Instead, an interrupt controller, when it has been determined that
- a processor should be interrupted should:
+ Users refer to interrupt port numbers symbolically. For instance a
+ device may refer to its `INT' signal which is internally
+ represented by port 3.
- o Schedule an immediate timer event (using events.h)
- These events occure at the end of the cpu cycle.
+ To convert to/from the symbolic and internal representation of a
+ port name/number. The following functions are available. */
- o When this timer event is delivered (at the end of the
- cpu cycle) the interrupt controller can then deliver
- its interrupt.
+INLINE_DEVICE\
+(int) device_interrupt_decode
+(device *me,
+ const char *symbolic_name,
+ port_direction direction);
- It should be noted that interrupts can be delivered to an interrupt
- controller either during the middle of the cpu cycle or at the end.
- Further an interrupt could be delivered at the end of a cycle
- before and after an interrupt controller receives its own timer
- events. An interrupt controller must be able to handle these cases
- gracefully. */
+INLINE_DEVICE\
+(int) device_interrupt_encode
+(device *me,
+ int port_number,
+ char *buf,
+ int sizeof_buf,
+ port_direction direction);
+
-
-/* IOCTL:
+/* Hardware operations:
- Very simply, a catch all for any thing that turns up that until now
- either hasn't been thought of or doesn't justify an extra function. */
+ */
-EXTERN_DEVICE\
-(void) device_ioctl
+INLINE_DEVICE\
+(unsigned) device_io_read_buffer
(device *me,
- psim *system,
+ void *dest,
+ int space,
+ unsigned_word addr,
+ unsigned nr_bytes,
cpu *processor,
- unsigned_word cia,
- ...);
-
-
-/* Tree utilities:
-
- In addition to the standard method of creating a device from a
- device template, the following sortcuts can be used.
-
- Create a device or property from a textual representation */
-
-EXTERN_DEVICE(device *) device_tree_add_parsed
-(device *current,
- const char *fmt,
- ...) __attribute__ ((format (printf, 2, 3)));
-
-/* where FMT,... once formatted (using vsprintf) is used to locate and
- create either a device or property. Its syntax is almost identical
- to that used in OpenBoot documentation - the only extension is in
- allowing properties and their values to be specified vis:
-
- "/pci/pci1000,1@1/disk@0,0"
-
- Path:
-
- The path to a device or property can either be absolute (leading
- `/') or relative (leading `.' or `..'). Relative paths start from
- the CURRENT node. The new current node is returned as the result.
- In addition, a path may start with a leading alias (resolved by
- looking in /aliases).
-
- Device name:
-
- <name> "@" <unit> [ ":" <args> ]
-
- Where <name> is the name of the template device, <unit> is a
- textual specification of the devices unit address (that is
- converted into a numeric form by the devices parent) and <args> are
- optional additional information to be passed to the device-template
- when it creates the device.
-
- Properties:
-
- Properties are specified in a similar way to devices except that
- the last element on the path (which would have been the device) is
- the property name. This path is then followed by the property
- value. Unlike OpenBoot, the property values in the device tree are
- strongly typed.
+ unsigned_word cia);
- String property:
+INLINE_DEVICE\
+(unsigned) device_io_write_buffer
+(device *me,
+ const void *source,
+ int space,
+ unsigned_word addr,
+ unsigned nr_bytes,
+ cpu *processor,
+ unsigned_word cia);
- <property-name> " " <text>
- <property-name> " " "\"" <text>
-
- Boolean property:
- <property-name> " " [ "true" | "false" ]
- Integer property or integer array property:
+/* Conversly, the device pci1000,1@1 my 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 */
- <property-name> " " <number> { <number> }
+INLINE_DEVICE\
+(unsigned) device_dma_read_buffer
+(device *me,
+ void *dest,
+ int space,
+ unsigned_word addr,
+ unsigned nr_bytes);
- Phandle property:
+INLINE_DEVICE\
+(unsigned) device_dma_write_buffer
+(device *me,
+ const void *source,
+ int space,
+ unsigned_word addr,
+ unsigned nr_bytes,
+ int violate_read_only_section);
- <property-name> " " "&" <path-to-device>
+/* To avoid the need for an intermediate (bridging) node to ask each
+ of its child devices in turn if an IO access is intended for them,
+ parent nodes maintain a table mapping addresses directly to
+ specific devices. When a device is `connected' to its bus it
+ attaches its self to its parent. */
- Ihandle property:
+/* Address access attributes */
+typedef enum _access_type {
+ access_invalid = 0,
+ access_read = 1,
+ access_write = 2,
+ access_read_write = 3,
+ access_exec = 4,
+ access_read_exec = 5,
+ access_write_exec = 6,
+ access_read_write_exec = 7,
+} access_type;
- <property-name> " " "*" <path-to-device-to-open>
+/* Address attachement types */
+typedef enum _attach_type {
+ attach_invalid,
+ attach_raw_memory,
+ attach_callback,
+ /* ... */
+} attach_type;
- Duplicate existing property:
+INLINE_DEVICE\
+(void) device_attach_address
+(device *me,
+ attach_type attach,
+ int space,
+ unsigned_word addr,
+ unsigned nr_bytes,
+ access_type access,
+ device *client); /*callback/default*/
- <property-name> " " "!" <path-to-original-property>
+INLINE_DEVICE\
+(void) device_detach_address
+(device *me,
+ attach_type attach,
+ int space,
+ unsigned_word addr,
+ unsigned nr_bytes,
+ access_type access,
+ device *client); /*callback/default*/
+/* Utilities:
- In addition to properties, the wiring of interrupts can be
- specified:
+ */
- Attach interrupt <line> of <device> to <controller>:
+/* IOCTL::
- <device> " " ">" <my-port> <dest-port> <dest-device>
+ 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 <<device_ioctl()>>.
- Attach child interrupt of <device> to <controller>:
+ */
- <device> " " "<" <controller>
+typedef enum {
+ device_ioctl_break, /* unsigned_word requested_break */
+ device_ioctl_set_trace, /* void */
+ device_ioctl_create_stack, /* unsigned_word *sp, char **argv, char **envp */
+ device_ioctl_change_media, /* const char *new_image (possibly NULL) */
+ nr_device_ioctl_requests,
+} device_ioctl_request;
+EXTERN_DEVICE\
+(int) device_ioctl
+(device *me,
+ cpu *processor,
+ unsigned_word cia,
+ device_ioctl_request request,
+ ...);
- Once created, a device tree can be traversed in various orders: */
-typedef void (device_tree_traverse_function)
- (device *device,
- void *data);
+/* Error reporting::
-INLINE_DEVICE(void) device_tree_traverse
-(device *root,
- device_tree_traverse_function *prefix,
- device_tree_traverse_function *postfix,
- void *data);
+ So that errors originating from devices appear in a consistent
+ format, the <<device_error()>> function can be used. Formats and
+ outputs the error message before aborting the simulation
-/* Or dumped out in a format that can be read back in using
- device_add_parsed() */
+ 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).
-INLINE_DEVICE(void) device_tree_print_device
-(device *device,
- void *ignore_data_argument);
+ */
-/* Individual nodes can be located using */
+EXTERN_DEVICE\
+(void volatile) device_error
+(device *me,
+ const char *fmt,
+ ...) __attribute__ ((format (printf, 2, 3)));
-INLINE_DEVICE(device *) device_tree_find_device
-(device *root,
- const char *path);
+INLINE_DEVICE\
+(int) device_trace
+(device *me);
-/* And the current list of devices can be listed */
-INLINE_DEVICE(void) device_usage
-(int verbose);
-
-/* External representation
+/* External representation:
Both device nodes and device instances, in OpenBoot firmware have
an external representation (phandles and ihandles) and these values
@@ -688,20 +748,50 @@ INLINE_DEVICE(void) device_usage
To limit the potential risk associated with trusing `data' from the
client program, the following mapping operators `safely' convert
- between the two representations: */
+ between the two representations
-INLINE_DEVICE(device *) external_to_device
+ */
+
+INLINE_DEVICE\
+(device *) external_to_device
(device *tree_member,
- unsigned32 phandle);
+ unsigned_cell phandle);
-INLINE_DEVICE(unsigned32) device_to_external
+INLINE_DEVICE\
+(unsigned_cell) device_to_external
(device *me);
-INLINE_DEVICE(device_instance *) external_to_device_instance
+INLINE_DEVICE\
+(device_instance *) external_to_device_instance
(device *tree_member,
- unsigned32 ihandle);
+ unsigned_cell ihandle);
-INLINE_DEVICE(unsigned32) device_instance_to_external
+INLINE_DEVICE\
+(unsigned_cell) device_instance_to_external
(device_instance *me);
+
+/* Event queue:
+
+ The device inherets certain event queue operations from the main
+ simulation. */
+
+typedef void device_event_handler(void *data);
+
+INLINE_DEVICE\
+(event_entry_tag) device_event_queue_schedule
+(device *me,
+ signed64 delta_time,
+ device_event_handler *handler,
+ void *data);
+
+INLINE_EVENTS\
+(void) device_event_queue_deschedule
+(device *me,
+ event_entry_tag event_to_remove);
+
+INLINE_EVENTS\
+(signed64) device_event_queue_time
+(device *me);
+
#endif /* _DEVICE_H_ */
diff --git a/gnu/dist/sim/ppc/device_table.c b/gnu/dist/sim/ppc/device_table.c
index 8bc225190d9..09772aba6b4 100644
--- a/gnu/dist/sim/ppc/device_table.c
+++ b/gnu/dist/sim/ppc/device_table.c
@@ -22,78 +22,72 @@
#ifndef _DEVICE_TABLE_C_
#define _DEVICE_TABLE_C_
-#ifndef STATIC_INLINE_DEVICE_TABLE
-#define STATIC_INLINE_DEVICE_TABLE STATIC_INLINE
-#endif
-
-#include <stdio.h>
-#include <fcntl.h>
-#include <signal.h>
-#include <stdarg.h>
-#include <ctype.h>
-
#include "device_table.h"
-#include "events.h"
-
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#ifdef HAVE_STDLIB_H
+#if 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 "cpu.h"
+#include <ctype.h>
-#include "bfd.h"
/* Helper functions */
-/* Generic device init: Attaches the device of size <nr_bytes> (taken
- from <name>@<int>,<nr_bytes>) to its parent at address zero and
- with read/write access. */
-typedef struct _reg_spec {
- unsigned32 base;
- unsigned32 size;
-} reg_spec;
+/* Go through the devices various reg properties for those that
+ specify attach addresses */
-void
-generic_device_init_address(device *me,
- psim *system)
-{
- const device_property *reg = device_find_array_property(me, "reg");
- const reg_spec *spec = reg->array;
- int nr_entries = reg->sizeof_array / sizeof(reg_spec);
- if ((reg->sizeof_array % sizeof(reg_spec)) != 0)
- error("devices/%s reg property is of wrong size\n", device_name(me));
-
- while (nr_entries > 0) {
- device_attach_address(device_parent(me),
- device_name(me),
- attach_callback,
- 0 /*space*/,
- BE2H_4(spec->base),
- BE2H_4(spec->size),
- access_read_write_exec,
- me);
- spec++;
- nr_entries--;
+void
+generic_device_init_address(device *me)
+{
+ 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 (device_find_property(me, *reg_property_name) != NULL) {
+ reg_property_spec reg;
+ int reg_entry;
+ for (reg_entry = 0;
+ device_find_reg_array_property(me, *reg_property_name, reg_entry,
+ &reg);
+ reg_entry++) {
+ unsigned_word attach_address;
+ int attach_space;
+ unsigned attach_size;
+ if (!device_address_to_attach_address(device_parent(me),
+ &reg.address,
+ &attach_space, &attach_address,
+ me))
+ continue;
+ if (!device_size_to_attach_size(device_parent(me),
+ &reg.size,
+ &attach_size, me))
+ continue;
+ device_attach_address(device_parent(me),
+ attach_callback,
+ attach_space, attach_address, attach_size,
+ access_read_write_exec,
+ me);
+ nr_valid_reg_properties++;
+ }
+ /* if first option matches don't try for any others */
+ if (reg_property_name == reg_property_names)
+ break;
+ }
}
}
int
-generic_device_unit_decode(device *me,
+generic_device_unit_decode(device *bus,
const char *unit,
device_unit *phys)
{
@@ -101,315 +95,150 @@ generic_device_unit_decode(device *me,
if (unit == NULL)
return 0;
else {
- char *pos = (char*)unit; /* force for strtoul() */
+ int nr_cells = 0;
+ const int max_nr_cells = device_nr_address_cells(bus);
while (1) {
- char *old_pos = pos;
- long int val = strtoul(pos, &pos, 0);
- if (old_pos == pos && *pos == '\0')
- return phys->nr_cells;
- if (old_pos == pos && *pos != '\0')
+ 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;
- if (phys->nr_cells == 4)
+ /* save it */
+ phys->cells[nr_cells] = val;
+ nr_cells++;
+ unit = end;
+ /* more to follow? */
+ if (isspace(*unit) || *unit == '\0')
+ break;
+ if (*unit != ',')
return -1;
- phys->cells[phys->nr_cells] = val;
- phys->nr_cells++;
+ 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;
}
}
int
-generic_device_unit_encode(device *me,
+generic_device_unit_encode(device *bus,
const device_unit *phys,
char *buf,
int sizeof_buf)
{
int i;
int len;
- char *pos = buf; /* force for strtoul() */
+ char *pos = buf;
+ /* skip leading zero's */
for (i = 0; i < phys->nr_cells; i++) {
- if (pos != buf) {
- strcat(pos, ",");
+ 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');
}
- sprintf(pos, "0x%lx", (unsigned long)phys->cells[i]);
- pos = strchr(pos, '\0');
+ len = pos - buf;
}
- len = pos - buf;
if (len >= sizeof_buf)
error("generic_unit_encode - buffer overflow\n");
return len;
}
-/* DMA a file into memory */
-STATIC_INLINE_DEVICE_TABLE int
-dma_file(device *me,
- const char *file_name,
- unsigned_word addr)
-{
- int count;
- int inc;
- FILE *image;
- char buf[1024];
-
- /* get it open */
- image = fopen(file_name, "r");
- if (image == NULL)
- return -1;
-
- /* read it in slowly */
- count = 0;
- while (1) {
- inc = fread(buf, 1, sizeof(buf), image);
- if (feof(image) || ferror(image))
- break;
- if (device_dma_write_buffer(device_parent(me),
- buf,
- 0 /*address-space*/,
- addr+count,
- inc /*nr-bytes*/,
- 1 /*violate ro*/) != inc) {
- fclose(image);
- return -1;
- }
- count += inc;
- }
-
- /* close down again */
- fclose(image);
-
- return count;
-}
-
-
-
-/* inimplemented versions of each function */
-
-void
-unimp_device_init(device *me,
- psim *system)
-{
- error("device_init_callback for %s not implemented\n", device_name(me));
-}
-
-void
-unimp_device_attach_address(device *me,
- const char *name,
- attach_type type,
- int space,
- unsigned_word addr,
- unsigned nr_bytes,
- access_type access,
- device *who) /*callback/default*/
-{
- error("device_attach_address_callback for %s not implemented\n", device_name(me));
-}
-
-void
-unimp_device_detach_address(device *me,
- const char *name,
- attach_type type,
- int space,
- unsigned_word addr,
- unsigned nr_bytes,
- access_type access,
- device *who) /*callback/default*/
-{
- error("device_detach_address_callback for %s not implemented\n", device_name(me));
-}
-
-unsigned
-unimp_device_io_read_buffer(device *me,
- void *dest,
- int space,
- unsigned_word addr,
- unsigned nr_bytes,
- cpu *processor,
- unsigned_word cia)
-{
- error("device_io_read_buffer_callback for %s not implemented\n", device_name(me));
- return 0;
-}
-
-unsigned
-unimp_device_io_write_buffer(device *me,
- const void *source,
- int space,
- unsigned_word addr,
- unsigned nr_bytes,
- cpu *processor,
- unsigned_word cia)
-{
- error("device_io_write_buffer_callback for %s not implemented\n", device_name(me));
- return 0;
-}
-
-unsigned
-unimp_device_dma_read_buffer(device *me,
- void *target,
- int space,
- unsigned_word addr,
- unsigned nr_bytes)
-{
- error("device_dma_read_buffer_callback for %s not implemented\n", device_name(me));
- return 0;
-}
-
-unsigned
-unimp_device_dma_write_buffer(device *me,
- const void *source,
- int space,
- unsigned_word addr,
- unsigned nr_bytes,
- int violate_read_only_section)
-{
- error("device_dma_write_buffer_callback for %s not implemented\n", device_name(me));
- return 0;
-}
-
-void
-unimp_device_interrupt_event(device *me,
- int my_port,
- device *source,
- int source_port,
- int level,
- cpu *processor,
- unsigned_word cia)
-{
- error("unimp_device_interrupt_event for %s unimplemented\n",
- device_name(me));
-}
-
-void
-unimp_device_child_interrupt_event(device *me,
- device *parent,
- device *source,
- int source_port,
- int level,
- cpu *processor,
- unsigned_word cia)
-{
- error("unimp_device_child_interrupt_event_callback for %s unimplemented\n",
- device_name(me));
-}
-
-int
-unimp_device_unit_decode(device *me,
- const char *unit,
- device_unit *address)
-{
- error("unimp_device_unit_decode_callback for %s unimplemented\n",
- device_name(me));
- return 0;
-}
-
int
-unimp_device_unit_encode(device *me,
- const device_unit *unit_address,
- char *buf,
- int sizeof_buf)
-{
- error("unimp_device_unit_encode_callback for %s unimplemented\n",
- device_name(me));
- return 0;
-}
-
-void *
-unimp_device_instance_create(device *me,
- const char *args)
-{
- error("unimp_device_instance_create_callback for %s unimplemented\n",
- device_name(me));
- return 0;
-}
-
-void
-unimp_device_instance_delete(device_instance *instance)
+generic_device_address_to_attach_address(device *me,
+ const device_unit *address,
+ int *attach_space,
+ unsigned_word *attach_address,
+ device *client)
{
- error("unimp_device_instance_delete_callback for %s unimplemented\n",
- device_instance_name(instance));
-}
-
-int
-unimp_device_instance_read(device_instance *instance,
- void *buf,
- unsigned_word len)
-{
- error("unimp_device_instance_read_callback for %s unimplemented\n",
- device_instance_name(instance));
- return 0;
-}
-
-int
-unimp_device_instance_write(device_instance *instance,
- const void *buf,
- unsigned_word len)
-{
- error("unimp_device_instance_write_callback for %s unimplemented\n",
- device_instance_name(instance));
- return 0;
+ int i;
+ for (i = 0; i < address->nr_cells - 2; i++) {
+ if (address->cells[i] != 0)
+ device_error(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;
}
int
-unimp_device_instance_seek(device_instance *instance,
- unsigned_word pos_hi,
- unsigned_word pos_lo)
+generic_device_size_to_attach_size(device *me,
+ const device_unit *size,
+ unsigned *nr_bytes,
+ device *client)
{
- error("unimp_device_instance_seek_callback for %s unimplemented\n",
- device_instance_name(instance));
- return 0;
-}
-
-
-void
-unimp_device_ioctl(device *me,
- psim *system,
- cpu *processor,
- unsigned_word cia,
- va_list ap)
-{
- error("device_ioctl_callback for %s not implemented\n", device_name(me));
+ int i;
+ for (i = 0; i < size->nr_cells - 1; i++) {
+ if (size->cells[i] != 0)
+ device_error(me, "Only 32bit sizes supported");
+ }
+ *nr_bytes = size->cells[0];
+ return *nr_bytes;
}
-
/* ignore/passthrough versions of each function */
void
-ignore_device_init(device *me,
- psim *system)
-{
- /*null*/
-}
-
-void
-passthrough_device_attach_address(device *me,
- const char *name,
+passthrough_device_address_attach(device *me,
attach_type attach,
int space,
unsigned_word addr,
unsigned nr_bytes,
access_type access,
- device *who) /*callback/default*/
+ device *client) /*callback/default*/
{
- device_attach_address(device_parent(me), name, attach,
+ device_attach_address(device_parent(me), attach,
space, addr, nr_bytes,
access,
- who);
+ client);
}
void
-passthrough_device_detach_address(device *me,
- const char *name,
+passthrough_device_address_detach(device *me,
attach_type attach,
int space,
unsigned_word addr,
unsigned nr_bytes,
access_type access,
- device *who) /*callback/default*/
+ device *client) /*callback/default*/
{
- device_detach_address(device_parent(me), name, attach,
+ device_detach_address(device_parent(me), attach,
space, addr, nr_bytes, access,
- who);
+ client);
}
unsigned
@@ -448,1786 +277,18 @@ ignore_device_unit_decode(device *me,
static const device_callbacks passthrough_callbacks = {
- ignore_device_init,
- ignore_device_init,
- passthrough_device_attach_address,
- passthrough_device_detach_address,
- unimp_device_io_read_buffer,
- unimp_device_io_write_buffer,
- passthrough_device_dma_read_buffer,
- passthrough_device_dma_write_buffer,
- unimp_device_interrupt_event,
- unimp_device_child_interrupt_event,
- generic_device_unit_decode,
- generic_device_unit_encode,
- unimp_device_instance_create,
- unimp_device_instance_delete,
- unimp_device_instance_read,
- unimp_device_instance_write,
- unimp_device_instance_seek,
- unimp_device_ioctl,
-};
-
-
-
-/* Simple console device: console@<address>,16
-
- Input characters are taken from the keyboard, output characters
- sent to the terminal. Echoing of characters is not disabled.
-
- The device has four registers:
-
- 0x0: read
- 0x4: read-status
- 0x8: write
- 0xC: write-status
-
- Where a nonzero status register indicates that the device is ready
- (input fifo contains a character or output fifo has space). */
-
-typedef struct _console_buffer {
- char buffer;
- int status;
- event_entry_tag event_tag;
-} console_buffer;
-
-typedef struct _console_device {
- console_buffer input;
- console_buffer output;
-} console_device;
-
-typedef enum {
- console_read_buffer = 0,
- console_read_status = 4,
- console_write_buffer = 8,
- console_write_status = 12,
- console_offset_mask = 0xc,
- console_size = 16,
-} console_offsets;
-
-/* check the console for an available character */
-static void
-scan_console(console_device *console)
-{ /* check for input */
- int flags;
- int status;
- /* get the old status */
- flags = fcntl(0, F_GETFL, 0);
- if (flags == -1) {
- perror("console");
- return;
- }
- /* temp, disable blocking IO */
- status = fcntl(0, F_SETFL, flags | O_NDELAY);
- if (status == -1) {
- perror("console");
- return;
- }
- /* try for input */
- status = read(0, &console->input.buffer, 1);
- if (status == 1) {
- console->input.status = 1;
- }
- else {
- console->input.status = 0;
- }
- /* return to regular vewing */
- flags = fcntl(0, F_SETFL, flags);
- if (flags == -1) {
- perror("console");
- return;
- }
-}
-
-/* write the character to the console */
-static void
-write_console(console_device *console,
- char val)
-{
- DTRACE(console, ("<%c:%d>", val, val));
- printf_filtered("%c", val) ;
- console->output.buffer = val;
- console->output.status = 1;
-}
-
-static unsigned
-console_io_read_buffer_callback(device *me,
- void *dest,
- int space,
- unsigned_word addr,
- unsigned nr_bytes,
- cpu *processor,
- unsigned_word cia)
-{
- console_device *console = (console_device*)device_data(me);
- unsigned_1 val;
-
- /* determine what was read */
-
- switch ((int)addr & console_offset_mask) {
-
- case console_read_buffer:
- val = console->input.buffer;
- break;
-
- case console_read_status:
- scan_console(console);
- val = console->input.status;
- break;
-
- case console_write_buffer:
- val = console->output.buffer;
- break;
-
- case console_write_status:
- val = console->output.status;
- break;
-
- default:
- error("console_read_callback() internal error\n");
- val = 0;
- break;
-
- }
-
- memset(dest, 0, nr_bytes);
- *(unsigned_1*)dest = val;
- return nr_bytes;
-}
-
-static unsigned
-console_io_write_buffer_callback(device *me,
- const void *source,
- int space,
- unsigned_word addr,
- unsigned nr_bytes,
- cpu *processor,
- unsigned_word cia)
-{
- console_device *console = (console_device*)device_data(me);
- unsigned_1 val = *(unsigned_1*)source;
-
- switch ((int)addr & console_offset_mask) {
-
- case console_read_buffer:
- console->input.buffer = val;
- break;
-
- case console_read_status:
- console->input.status = val;
- break;
-
- case console_write_buffer:
- write_console(console, val);
- break;
-
- case console_write_status:
- console->output.status = val;
- break;
-
- default:
- error("console_write_callback() internal error\n");
-
- }
-
- return nr_bytes;
-}
-
-/* instances of the console device */
-static void *
-console_instance_create_callback(device *me,
- const char *args)
-{
- /* make life easier, attach the console data to the instance */
- return device_data(me);
-}
-
-static void
-console_instance_delete_callback(device_instance *instance)
-{
- /* nothing to delete, the console is attached to the device */
- return;
-}
-
-static int
-console_instance_read_callback(device_instance *instance,
- void *buf,
- unsigned_word len)
-{
- console_device *console = device_instance_data(instance);
- if (!console->input.status)
- scan_console(console);
- if (console->input.status) {
- *(char*)buf = console->input.buffer;
- console->input.status = 0;
- return 1;
- }
- else {
- return -2; /* not ready */
- }
-}
-
-static int
-console_instance_write_callback(device_instance *instance,
- const void *buf,
- unsigned_word len)
-{
- int i;
- const char *chp = buf;
- console_device *console = device_instance_data(instance);
- for (i = 0; i < len; i++)
- write_console(console, chp[i]);
- return i;
-}
-
-static device_callbacks const console_callbacks = {
- generic_device_init_address,
- ignore_device_init,
- unimp_device_attach_address,
- unimp_device_detach_address,
- console_io_read_buffer_callback,
- console_io_write_buffer_callback,
- unimp_device_dma_read_buffer,
- unimp_device_dma_write_buffer,
- unimp_device_interrupt_event,
- unimp_device_child_interrupt_event,
- unimp_device_unit_decode,
- unimp_device_unit_encode,
- console_instance_create_callback,
- console_instance_delete_callback,
- console_instance_read_callback,
- console_instance_write_callback,
- unimp_device_instance_seek,
- unimp_device_ioctl,
-};
-
-
-static void *
-console_create(const char *name,
- const device_unit *unit_address,
- const char *args,
- device *parent)
-{
- /* create the descriptor */
- console_device *console = ZALLOC(console_device);
- console->output.status = 1;
- console->output.buffer = '\0';
- console->input.status = 0;
- console->input.buffer = '\0';
- return console;
-}
-
-
-
-/* ICU device: icu@<address>
-
- <address> : read - processor nr
- <address> : write - interrupt processor nr
- <address> + 4 : read - nr processors
-
- Single byte registers that control a simple ICU.
-
- Illustrates passing of events to parent device. Passing of
- interrupts to an interrupt destination. */
-
-
-static unsigned
-icu_io_read_buffer_callback(device *me,
- void *dest,
- int space,
- unsigned_word addr,
- unsigned nr_bytes,
- cpu *processor,
- unsigned_word cia)
-{
- memset(dest, 0, nr_bytes);
- switch (addr & 4) {
- case 0:
- *(unsigned_1*)dest = cpu_nr(processor);
- break;
- case 4:
- *(unsigned_1*)dest =
- device_find_integer_property(me, "/openprom/options/smp");
- break;
- }
- return nr_bytes;
-}
-
-
-static unsigned
-icu_io_write_buffer_callback(device *me,
- const void *source,
- int space,
- unsigned_word addr,
- unsigned nr_bytes,
- cpu *processor,
- unsigned_word cia)
-{
- unsigned_1 val = H2T_1(*(unsigned_1*)source);
- /* tell the parent device that the interrupt lines have changed.
- For this fake ICU. The interrupt lines just indicate the cpu to
- interrupt next */
- device_interrupt_event(me,
- val, /*my_port*/
- val, /*val*/
- processor, cia);
- return nr_bytes;
-}
-
-static void
-icu_do_interrupt(event_queue *queue,
- void *data)
-{
- cpu *target = (cpu*)data;
- /* try to interrupt the processor. If the attempt fails, try again
- on the next tick */
- if (!external_interrupt(target))
- event_queue_schedule(queue, 1, icu_do_interrupt, target);
-}
-
-
-static void
-icu_interrupt_event_callback(device *me,
- int my_port,
- device *source,
- int source_port,
- int level,
- cpu *processor,
- unsigned_word cia)
-{
- /* the interrupt controller can't interrupt a cpu at any time.
- Rather it must synchronize with the system clock before
- performing an interrupt on the given processor */
- psim *system = cpu_system(processor);
- cpu *target = psim_cpu(system, my_port);
- if (target != NULL) {
- event_queue *events = cpu_event_queue(target);
- event_queue_schedule(events, 1, icu_do_interrupt, target);
- }
-}
-
-static device_callbacks const icu_callbacks = {
- generic_device_init_address,
- ignore_device_init,
- unimp_device_attach_address,
- unimp_device_detach_address,
- icu_io_read_buffer_callback,
- icu_io_write_buffer_callback,
- unimp_device_dma_read_buffer,
- unimp_device_dma_write_buffer,
- icu_interrupt_event_callback,
- unimp_device_child_interrupt_event,
- unimp_device_unit_decode,
- unimp_device_unit_encode,
- unimp_device_instance_create,
- unimp_device_instance_delete,
- unimp_device_instance_read,
- unimp_device_instance_write,
- unimp_device_instance_seek,
- unimp_device_ioctl,
-};
-
-
-
-/* HALT device: halt@0x<address>,4
-
- With real hardware, the processor operation is normally terminated
- through a reset. This device illustrates how a reset device could
- be attached to an address */
-
-
-static unsigned
-halt_io_read_buffer_callback(device *me,
- void *dest,
- int space,
- unsigned_word addr,
- unsigned nr_bytes,
- cpu *processor,
- unsigned_word cia)
-{
- cpu_halt(processor, cia, was_exited, 0);
- return 0;
-}
-
-
-static unsigned
-halt_io_write_buffer_callback(device *me,
- const void *source,
- int space,
- unsigned_word addr,
- unsigned nr_bytes,
- cpu *processor,
- unsigned_word cia)
-{
- cpu_halt(processor, cia, was_exited, *(unsigned_1*)source);
- return 0;
-}
-
-
-static device_callbacks const halt_callbacks = {
- generic_device_init_address,
- ignore_device_init,
- unimp_device_attach_address,
- unimp_device_detach_address,
- halt_io_read_buffer_callback,
- halt_io_write_buffer_callback,
- unimp_device_dma_read_buffer,
- unimp_device_dma_write_buffer,
- unimp_device_interrupt_event,
- unimp_device_child_interrupt_event,
- unimp_device_unit_decode,
- unimp_device_unit_encode,
- unimp_device_instance_create,
- unimp_device_instance_delete,
- unimp_device_instance_read,
- unimp_device_instance_write,
- unimp_device_instance_seek,
- unimp_device_ioctl,
-};
-
-
-
-/* Register init device: register@<nothing>
-
- Properties attached to the register device specify the name/value
- initialization pair for cpu registers.
-
- A specific processor can be initialized by creating a property with
- a name like `0.pc'.
-
- Properties are normally processed old-to-new and this function
- needs to allow older (first in) properties to override new (last
- in) ones. The suport function do_register_init() manages this. */
-
-static void
-do_register_init(device *me,
- psim *system,
- const device_property *prop)
-{
- if (prop != NULL) {
- const char *name = prop->name;
- unsigned32 value = device_find_integer_property(me, name);
- int processor;
-
- do_register_init(me, system, device_next_property(prop));
-
- if (strchr(name, '.') == NULL) {
- processor = -1;
- DTRACE(register, ("%s=0x%lx\n", name, (unsigned long)value));
- }
- else {
- char *end;
- processor = strtoul(name, &end, 0);
- ASSERT(end[0] == '.');
- name = end+1;
- DTRACE(register, ("%d.%s=0x%lx\n", processor, name,
- (unsigned long)value));
- }
- psim_write_register(system, processor, /* all processors */
- &value,
- name,
- cooked_transfer);
- }
-}
-
-
-static void
-register_init_data_callback(device *me,
- psim *system)
-{
- const device_property *prop = device_find_property(me, NULL);
- do_register_init(me, system, prop);
-}
-
-
-static device_callbacks const register_callbacks = {
- ignore_device_init,
- register_init_data_callback,
- unimp_device_attach_address,
- unimp_device_detach_address,
- unimp_device_io_read_buffer,
- unimp_device_io_write_buffer,
- unimp_device_dma_read_buffer,
- unimp_device_dma_write_buffer,
- unimp_device_interrupt_event,
- unimp_device_child_interrupt_event,
- unimp_device_unit_decode,
- unimp_device_unit_encode,
- unimp_device_instance_create,
- unimp_device_instance_delete,
- unimp_device_instance_read,
- unimp_device_instance_write,
- unimp_device_instance_seek,
- unimp_device_ioctl,
-};
-
-
-
-/* Trace device:
-
- Properties attached to the trace device are names and values for
- the various trace variables. When initialized trace goes through
- the propertie and sets the global trace variables so that they
- match what was specified in the device tree. */
-
-static void
-trace_init_data_callback(device *me,
- psim *system)
-{
- const device_property *prop = device_find_property(me, NULL);
- while (prop != NULL) {
- const char *name = prop->name;
- unsigned32 value = device_find_integer_property(me, name);
- trace_option(name, value);
- prop = device_next_property(prop);
- }
-}
-
-
-static device_callbacks const trace_callbacks = {
- ignore_device_init,
- trace_init_data_callback,
- unimp_device_attach_address,
- unimp_device_detach_address,
- unimp_device_io_read_buffer,
- unimp_device_io_write_buffer,
- unimp_device_dma_read_buffer,
- unimp_device_dma_write_buffer,
- unimp_device_interrupt_event,
- unimp_device_child_interrupt_event,
- unimp_device_unit_decode,
- unimp_device_unit_encode,
- unimp_device_instance_create,
- unimp_device_instance_delete,
- unimp_device_instance_read,
- unimp_device_instance_write,
- unimp_device_instance_seek,
- unimp_device_ioctl,
-};
-
-
-
-/* VEA VM:
-
- vm@<stack-base>
- stack-base =
- nr-bytes =
-
- A VEA mode device. This sets its self up as the default memory
- device capturing all accesses (reads/writes) to currently unmapped
- addresses. If the unmaped access falls within unallocated stack or
- heap address ranges then memory is allocated and the access is
- allowed to continue.
-
- During init phase, this device expects to receive `attach' requests
- from its children for the text/data/bss memory areas. Typically,
- this would be done by the binary device.
-
- STACK: The location of the stack in memory is specified as part of
- the devices name. Unmaped accesses that fall within the stack
- space result in the allocated stack being grown downwards so that
- it includes the page of the culprit access.
-
- HEAP: During initialization, the vm device monitors all `attach'
- operations from its children using this to determine the initial
- location of the heap. The heap is then extended by system calls
- that frob the heap upper bound variable (see system.c). */
-
-
-typedef struct _vm_device {
- /* area of memory valid for stack addresses */
- unsigned_word stack_base; /* min possible stack value */
- unsigned_word stack_bound;
- unsigned_word stack_lower_limit;
- /* area of memory valid for heap addresses */
- unsigned_word heap_base;
- unsigned_word heap_bound;
- unsigned_word heap_upper_limit;
-} vm_device;
-
-
-static void
-vm_init_address_callback(device *me,
- psim *system)
-{
- vm_device *vm = (vm_device*)device_data(me);
-
- /* revert the stack/heap variables to their defaults */
- vm->stack_base = device_find_integer_property(me, "stack-base");
- vm->stack_bound = (vm->stack_base
- + device_find_integer_property(me, "nr-bytes"));
- vm->stack_lower_limit = vm->stack_bound;
- vm->heap_base = 0;
- vm->heap_bound = 0;
- vm->heap_upper_limit = 0;
-
- /* establish this device as the default memory handler */
- device_attach_address(device_parent(me),
- device_name(me),
- attach_default,
- 0 /*address space - ignore*/,
- 0 /*addr - ignore*/,
- 0 /*nr_bytes - ignore*/,
- access_read_write /*access*/,
- me);
-}
-
-
-static void
-vm_attach_address(device *me,
- const char *name,
- attach_type attach,
- int space,
- unsigned_word addr,
- unsigned nr_bytes,
- access_type access,
- device *who) /*callback/default*/
-{
- vm_device *vm = (vm_device*)device_data(me);
- /* update end of bss if necessary */
- if (vm->heap_base < addr + nr_bytes) {
- vm->heap_base = addr + nr_bytes;
- vm->heap_bound = addr + nr_bytes;
- vm->heap_upper_limit = addr + nr_bytes;
- }
- device_attach_address(device_parent(me),
- "vm@0x0,0", /* stop remap */
- attach_raw_memory,
- 0 /*address space*/,
- addr,
- nr_bytes,
- access,
- me);
-}
-
-
-STATIC_INLINE_DEVICE_TABLE unsigned
-add_vm_space(device *me,
- unsigned_word addr,
- unsigned nr_bytes,
- cpu *processor,
- unsigned_word cia)
-{
- vm_device *vm = (vm_device*)device_data(me);
- unsigned_word block_addr;
- unsigned block_nr_bytes;
-
- /* an address in the stack area, allocate just down to the addressed
- page */
- if (addr >= vm->stack_base && addr < vm->stack_lower_limit) {
- block_addr = FLOOR_PAGE(addr);
- block_nr_bytes = vm->stack_lower_limit - block_addr;
- vm->stack_lower_limit = block_addr;
- }
- /* an address in the heap area, allocate all of the required heap */
- else if (addr >= vm->heap_upper_limit && addr < vm->heap_bound) {
- block_addr = vm->heap_upper_limit;
- block_nr_bytes = vm->heap_bound - vm->heap_upper_limit;
- vm->heap_upper_limit = vm->heap_bound;
- }
- /* oops - an invalid address - abort the cpu */
- else if (processor != NULL) {
- cpu_halt(processor, cia, was_signalled, SIGSEGV);
- return 0;
- }
- /* 2*oops - an invalid address and no processor */
- else {
- return 0;
- }
-
- /* got the parameters, allocate the space */
- device_attach_address(device_parent(me),
- "vm@0x0,0", /* stop remap */
- attach_raw_memory,
- 0 /*address space*/,
- block_addr,
- block_nr_bytes,
- access_read_write,
- me);
- return block_nr_bytes;
-}
-
-
-static unsigned
-vm_io_read_buffer_callback(device *me,
- void *dest,
- int space,
- unsigned_word addr,
- unsigned nr_bytes,
- cpu *processor,
- unsigned_word cia)
-{
- if (add_vm_space(me, addr, nr_bytes, processor, cia) >= nr_bytes) {
- memset(dest, 0, nr_bytes); /* always initialized to zero */
- return nr_bytes;
- }
- else
- return 0;
-}
-
-
-static unsigned
-vm_io_write_buffer_callback(device *me,
- const void *source,
- int space,
- unsigned_word addr,
- unsigned nr_bytes,
- cpu *processor,
- unsigned_word cia)
-{
- if (add_vm_space(me, addr, nr_bytes, processor, cia) >= nr_bytes) {
- return device_dma_write_buffer(device_parent(me), source,
- space, addr,
- nr_bytes,
- 0/*violate_read_only*/);
- }
- else
- return 0;
-}
-
-
-static void
-vm_ioctl_callback(device *me,
- psim *system,
- cpu *processor,
- unsigned_word cia,
- va_list ap)
-{
- /* While the caller is notified that the heap has grown by the
- requested amount, the heap is infact extended out to a page
- boundary. */
- vm_device *vm = (vm_device*)device_data(me);
- unsigned_word new_break = ALIGN_8(cpu_registers(processor)->gpr[3]);
- unsigned_word old_break = vm->heap_bound;
- signed_word delta = new_break - old_break;
- if (delta > 0)
- vm->heap_bound = ALIGN_PAGE(new_break);
- cpu_registers(processor)->gpr[0] = 0;
- cpu_registers(processor)->gpr[3] = new_break;
-}
-
-
-static device_callbacks const vm_callbacks = {
- vm_init_address_callback,
- ignore_device_init,
- vm_attach_address,
- passthrough_device_detach_address,
- vm_io_read_buffer_callback,
- vm_io_write_buffer_callback,
- unimp_device_dma_read_buffer,
- passthrough_device_dma_write_buffer,
- unimp_device_interrupt_event,
- unimp_device_child_interrupt_event,
- generic_device_unit_decode,
- generic_device_unit_encode,
- unimp_device_instance_create,
- unimp_device_instance_delete,
- unimp_device_instance_read,
- unimp_device_instance_write,
- unimp_device_instance_seek,
- vm_ioctl_callback,
-};
-
-
-static void *
-vea_vm_create(const char *name,
- const device_unit *address,
- const char *args,
- device *parent)
-{
- vm_device *vm = ZALLOC(vm_device);
- return vm;
-}
-
-
-
-/* Memory init device: memory@0x<addr>
-
- This strange device is used create sections of memory */
-
-static void
-memory_init_address_callback(device *me,
- psim *system)
-{
- const device_property *reg = device_find_array_property(me, "reg");
- const reg_spec *spec = reg->array;
- int nr_entries = reg->sizeof_array / sizeof(*spec);
-
- if ((reg->sizeof_array % sizeof(*spec)) != 0)
- error("devices/%s reg property of incorrect size\n", device_name(me));
- while (nr_entries > 0) {
- device_attach_address(device_parent(me),
- device_name(me),
- attach_raw_memory,
- 0 /*address space*/,
- BE2H_4(spec->base),
- BE2H_4(spec->size),
- access_read_write_exec,
- me);
- spec++;
- nr_entries--;
- }
-}
-
-static void *
-memory_instance_create_callback(device *me,
- const char *args)
-{
- return me; /* for want of any thing better */
-}
-
-static void
-memory_instance_delete_callback(device_instance *instance)
-{
- return;
-}
-
-static device_callbacks const memory_callbacks = {
- memory_init_address_callback,
- ignore_device_init,
- unimp_device_attach_address,
- unimp_device_detach_address,
- unimp_device_io_read_buffer,
- unimp_device_io_write_buffer,
- unimp_device_dma_read_buffer,
- unimp_device_dma_write_buffer,
- unimp_device_interrupt_event,
- unimp_device_child_interrupt_event,
- unimp_device_unit_decode,
- unimp_device_unit_encode,
- memory_instance_create_callback,
- memory_instance_delete_callback,
- unimp_device_instance_read,
- unimp_device_instance_write,
- unimp_device_instance_seek,
- unimp_device_ioctl,
-};
-
-
-
-/* IOBUS device: iobus@<address>
-
- Simple bus on which some IO devices live */
-
-static void
-iobus_attach_address_callback(device *me,
- const char *name,
- attach_type type,
- int space,
- unsigned_word addr,
- unsigned nr_bytes,
- access_type access,
- device *who) /*callback/default*/
-{
- unsigned_word iobus_addr;
- /* sanity check */
- if (type == attach_default)
- error("iobus_attach_address_callback() no default for %s/%s\n",
- device_name(me), name);
- if (space != 0)
- error("iobus_attach_address_callback() no space for %s/%s\n",
- device_name(me), name);
- /* get the bus address */
- if (device_unit_address(me)->nr_cells != 1)
- error("iobus_attach_address_callback() invalid address for %s\n",
- device_name(me));
- iobus_addr = device_unit_address(me)->cells[0];
- device_attach_address(device_parent(me),
- device_name(me),
- type,
- 0 /*space*/,
- iobus_addr + addr,
- nr_bytes,
- access,
- who);
-}
-
-
-static device_callbacks const iobus_callbacks = {
- ignore_device_init,
- ignore_device_init,
- iobus_attach_address_callback,
- unimp_device_detach_address,
- unimp_device_io_read_buffer,
- unimp_device_io_write_buffer,
- unimp_device_dma_read_buffer,
- unimp_device_dma_write_buffer,
- unimp_device_interrupt_event,
- unimp_device_child_interrupt_event,
- generic_device_unit_decode,
- generic_device_unit_encode,
- unimp_device_instance_create,
- unimp_device_instance_delete,
- unimp_device_instance_read,
- unimp_device_instance_write,
- unimp_device_instance_seek,
- unimp_device_ioctl,
-};
-
-
-
-/* FILE device: file@0x<address>,<file-name>
- (later - file@0x<address>,<size>,<file-offset>,<file-name>)
-
- Specifies a file to read directly into memory starting at <address> */
-
-
-static void
-file_init_data_callback(device *me,
- psim *system)
-{
- int count;
- const char *file_name = device_find_string_property(me, "file-name");
- unsigned_word addr = device_find_integer_property(me, "real-address");
- /* load the file */
- count = dma_file(me, file_name, addr);
- if (count < 0)
- error("device_table/%s - Problem loading file %s\n",
- device_name(me), file_name);
-}
-
-
-static device_callbacks const file_callbacks = {
- ignore_device_init,
- file_init_data_callback,
- unimp_device_attach_address,
- unimp_device_detach_address,
- unimp_device_io_read_buffer,
- unimp_device_io_write_buffer,
- unimp_device_dma_read_buffer,
- unimp_device_dma_write_buffer,
- unimp_device_interrupt_event,
- unimp_device_child_interrupt_event,
- unimp_device_unit_decode,
- unimp_device_unit_encode,
- unimp_device_instance_create,
- unimp_device_instance_delete,
- unimp_device_instance_read,
- unimp_device_instance_write,
- unimp_device_instance_seek,
- unimp_device_ioctl,
-};
-
-
-
-/* DATA device: data@<address>
-
- <data> - property containing the value to store
- <real-address> - address to store data at
-
- Store <data> at <address> using approperiate byte order */
-
-static void
-data_init_data_callback(device *me,
- psim *system)
-{
- unsigned_word addr = device_find_integer_property(me, "real-address");
- const device_property *data = device_find_property(me, "data");
- if (data == NULL)
- error("devices/data - missing data property\n");
- switch (data->type) {
- case integer_property:
- {
- unsigned32 buf = device_find_integer_property(me, "data");
- H2T(buf);
- if (device_dma_write_buffer(device_parent(me),
- &buf,
- 0 /*address-space*/,
- addr,
- sizeof(buf), /*nr-bytes*/
- 1 /*violate ro*/) != sizeof(buf))
- error("devices/%s - Problem storing integer 0x%x at 0x%lx\n",
- device_name(me), (long)buf, (unsigned long)addr);
- }
- break;
- default:
- error("devices/%s - write of this data is not yet implemented\n", device_name(me));
- break;
- }
-}
-
-
-static device_callbacks const data_callbacks = {
- ignore_device_init,
- data_init_data_callback,
- unimp_device_attach_address,
- unimp_device_detach_address,
- unimp_device_io_read_buffer,
- unimp_device_io_write_buffer,
- unimp_device_dma_read_buffer,
- unimp_device_dma_write_buffer,
- unimp_device_interrupt_event,
- unimp_device_child_interrupt_event,
- unimp_device_unit_decode,
- unimp_device_unit_encode,
- unimp_device_instance_create,
- unimp_device_instance_delete,
- unimp_device_instance_read,
- unimp_device_instance_write,
- unimp_device_instance_seek,
- unimp_device_ioctl,
-};
-
-
-
-/* HTAB:
-
- htab@<real-address>
- real-address =
- nr-bytes =
-
- pte@<real-address>
- real-address =
- virtual-address =
- nr-bytes =
- wimg =
- pp =
-
- pte@<real-address>
- real-address =
- file-name =
- wimg =
- pp =
-
- HTAB defines the location (in physical memory) of a HASH table.
- PTE (as a child of HTAB) defines a mapping that is to be entered
- into that table.
-
- NB: All the work in this device is done during init by the PTE.
- The pte, looks up its parent to determine the address of the HTAB
- and then uses DMA calls to establish the required mapping. */
-
-STATIC_INLINE_DEVICE_TABLE void
-htab_decode_hash_table(device *parent,
- unsigned32 *htaborg,
- unsigned32 *htabmask)
-{
- unsigned_word htab_ra;
- unsigned htab_nr_bytes;
- unsigned n;
- /* determine the location/size of the hash table */
- if (parent == NULL
- || strcmp(device_name(parent), "htab") != 0)
- error("devices/htab - missing htab parent device\n");
- htab_ra = device_find_integer_property(parent, "real-address");
- htab_nr_bytes = device_find_integer_property(parent, "nr-bytes");
- for (n = htab_nr_bytes; n > 1; n = n / 2) {
- if (n % 2 != 0)
- error("devices/%s - htab size 0x%x not a power of two\n",
- device_name(parent), htab_nr_bytes);
- }
- *htaborg = htab_ra;
- *htabmask = MASKED32(htab_nr_bytes - 1, 7, 31-6);
- if ((htab_ra & INSERTED32(*htabmask, 7, 15)) != 0) {
- error("devices/%s - htaborg 0x%x not aligned to htabmask 0x%x\n",
- device_name(parent), *htaborg, *htabmask);
- }
- DTRACE(htab, ("htab - htaborg=0x%lx htabmask=0x%lx\n",
- (unsigned long)*htaborg, (unsigned long)*htabmask));
-}
-
-STATIC_INLINE void
-htab_map_page(device *me,
- unsigned_word ra,
- unsigned64 va,
- unsigned wimg,
- unsigned pp,
- unsigned32 htaborg,
- unsigned32 htabmask)
-{
- unsigned64 vpn = va << 12;
- unsigned32 vsid = INSERTED32(EXTRACTED64(vpn, 0, 23), 0, 23);
- unsigned32 page = INSERTED32(EXTRACTED64(vpn, 24, 39), 0, 15);
- unsigned32 hash = INSERTED32(EXTRACTED32(vsid, 5, 23)
- ^ EXTRACTED32(page, 0, 15),
- 7, 31-6);
- int h;
- for (h = 0; h < 2; h++) {
- unsigned32 pteg = (htaborg | (hash & htabmask));
- int pti;
- for (pti = 0; pti < 8; pti++, pteg += 8) {
- unsigned32 current_target_pte0;
- unsigned32 current_pte0;
- if (device_dma_read_buffer(device_parent(me),
- &current_target_pte0,
- 0, /*space*/
- pteg,
- sizeof(current_target_pte0)) != 4)
- error("htab_init_callback() failed to read a pte at 0x%x\n",
- pteg);
- current_pte0 = T2H_4(current_target_pte0);
- if (!MASKED32(current_pte0, 0, 0)) {
- /* empty pte fill it */
- unsigned32 pte0 = (MASK32(0, 0)
- | INSERTED32(EXTRACTED32(vsid, 0, 23), 1, 24)
- | INSERTED32(h, 25, 25)
- | INSERTED32(EXTRACTED32(page, 0, 5), 26, 31));
- unsigned32 target_pte0 = H2T_4(pte0);
- unsigned32 pte1 = (INSERTED32(EXTRACTED32(ra, 0, 19), 0, 19)
- | INSERTED32(wimg, 25, 28)
- | INSERTED32(pp, 30, 31));
- unsigned32 target_pte1 = H2T_4(pte1);
- if (device_dma_write_buffer(device_parent(me),
- &target_pte0,
- 0, /*space*/
- pteg,
- sizeof(target_pte0),
- 1/*ro?*/) != 4
- || device_dma_write_buffer(device_parent(me),
- &target_pte1,
- 0, /*space*/
- pteg + 4,
- sizeof(target_pte1),
- 1/*ro?*/) != 4)
- error("htab_init_callback() failed to write a pte a 0x%x\n",
- pteg);
- DTRACE(htab, ("map - va=0x%lx ra=0x%lx &pte0=0x%lx pte0=0x%lx pte1=0x%lx\n",
- (unsigned long)va, (unsigned long)ra,
- (unsigned long)pteg,
- (unsigned long)pte0, (unsigned long)pte1));
- return;
- }
- }
- /* re-hash */
- hash = MASKED32(~hash, 0, 18);
- }
-}
-
-STATIC_INLINE_DEVICE_TABLE void
-htab_map_region(device *me,
- unsigned_word pte_ra,
- unsigned_word pte_va,
- unsigned nr_bytes,
- unsigned wimg,
- unsigned pp,
- unsigned32 htaborg,
- unsigned32 htabmask)
-{
- unsigned_word ra;
- unsigned64 va;
- /* go through all pages and create a pte for each */
- for (ra = pte_ra, va = (signed_word)pte_va;
- ra < pte_ra + nr_bytes;
- ra += 0x1000, va += 0x1000) {
- htab_map_page(me, ra, va, wimg, pp, htaborg, htabmask);
- }
-}
-
-typedef struct _htab_binary_sizes {
- unsigned_word text_ra;
- unsigned_word text_base;
- unsigned_word text_bound;
- unsigned_word data_ra;
- unsigned_word data_base;
- unsigned data_bound;
- device *me;
-} htab_binary_sizes;
-
-STATIC_INLINE_DEVICE_TABLE void
-htab_sum_binary(bfd *abfd,
- sec_ptr sec,
- PTR data)
-{
- htab_binary_sizes *sizes = (htab_binary_sizes*)data;
- unsigned_word size = bfd_get_section_size_before_reloc (sec);
- unsigned_word vma = bfd_get_section_vma (abfd, sec);
-
- /* skip the section if no memory to allocate */
- if (! (bfd_get_section_flags(abfd, sec) & SEC_ALLOC))
- return;
-
- if ((bfd_get_section_flags (abfd, sec) & SEC_CODE)
- || (bfd_get_section_flags (abfd, sec) & SEC_READONLY)) {
- if (sizes->text_bound < vma + size)
- sizes->text_bound = ALIGN_PAGE(vma + size);
- if (sizes->text_base > vma)
- sizes->text_base = FLOOR_PAGE(vma);
- }
- else if ((bfd_get_section_flags (abfd, sec) & SEC_DATA)
- || (bfd_get_section_flags (abfd, sec) & SEC_ALLOC)) {
- if (sizes->data_bound < vma + size)
- sizes->data_bound = ALIGN_PAGE(vma + size);
- if (sizes->data_base > vma)
- sizes->data_base = FLOOR_PAGE(vma);
- }
-}
-
-STATIC_INLINE_DEVICE_TABLE void
-htab_dma_binary(bfd *abfd,
- sec_ptr sec,
- PTR data)
-{
- htab_binary_sizes *sizes = (htab_binary_sizes*)data;
- void *section_init;
- unsigned_word section_vma;
- unsigned_word section_size;
- unsigned_word section_ra;
- device *me = sizes->me;
-
- /* skip the section if no memory to allocate */
- if (! (bfd_get_section_flags(abfd, sec) & SEC_ALLOC))
- return;
-
- /* check/ignore any sections of size zero */
- section_size = bfd_get_section_size_before_reloc(sec);
- if (section_size == 0)
- return;
-
- /* if nothing to load, ignore this one */
- if (! (bfd_get_section_flags(abfd, sec) & SEC_LOAD))
- return;
-
- /* find where it is to go */
- section_vma = bfd_get_section_vma(abfd, sec);
- section_ra = 0;
- if ((bfd_get_section_flags (abfd, sec) & SEC_CODE)
- || (bfd_get_section_flags (abfd, sec) & SEC_READONLY))
- section_ra = (section_vma - sizes->text_base + sizes->text_ra);
- else if ((bfd_get_section_flags (abfd, sec) & SEC_DATA))
- section_ra = (section_vma - sizes->data_base + sizes->data_ra);
- else
- return; /* just ignore it */
-
- DTRACE(htab,
- ("load - name=%-7s vma=0x%.8lx size=%6ld ra=0x%.8lx flags=%3lx(%s%s%s%s%s )\n",
- bfd_get_section_name(abfd, sec),
- (long)section_vma,
- (long)section_size,
- (long)section_ra,
- (long)bfd_get_section_flags(abfd, sec),
- bfd_get_section_flags(abfd, sec) & SEC_LOAD ? " LOAD" : "",
- bfd_get_section_flags(abfd, sec) & SEC_CODE ? " CODE" : "",
- bfd_get_section_flags(abfd, sec) & SEC_DATA ? " DATA" : "",
- bfd_get_section_flags(abfd, sec) & SEC_ALLOC ? " ALLOC" : "",
- bfd_get_section_flags(abfd, sec) & SEC_READONLY ? " READONLY" : ""
- ));
-
- /* dma in the sections data */
- section_init = zalloc(section_size);
- if (!bfd_get_section_contents(abfd,
- sec,
- section_init, 0,
- section_size)) {
- bfd_perror("devices/pte");
- error("devices/%s - no data loaded\n", device_name(me));
- }
- if (device_dma_write_buffer(device_parent(me),
- section_init,
- 0 /*space*/,
- section_ra,
- section_size,
- 1 /*violate_read_only*/)
- != section_size)
- error("devices/%s - broken dma transfer\n", device_name(me));
- zfree(section_init); /* only free if load */
-}
-
-STATIC_INLINE_DEVICE_TABLE void
-htab_map_binary(device *me,
- unsigned_word ra,
- unsigned wimg,
- unsigned pp,
- const char *file_name,
- unsigned32 htaborg,
- unsigned32 htabmask)
-{
- htab_binary_sizes sizes;
- bfd *image;
- sizes.text_base = -1;
- sizes.data_base = -1;
- sizes.text_bound = 0;
- sizes.data_bound = 0;
- sizes.me = me;
-
- /* open the file */
- image = bfd_openr(file_name, NULL);
- if (image == NULL) {
- bfd_perror("devices/pte");
- error("devices/%s - the file %s not loaded\n", device_name(me), file_name);
- }
-
- /* check it is valid */
- if (!bfd_check_format(image, bfd_object)) {
- bfd_close(image);
- error("devices/%s - the file %s has an invalid binary format\n",
- device_name(me), file_name);
- }
-
- /* determine the size of each of the files regions */
- bfd_map_over_sections (image, htab_sum_binary, (PTR) &sizes);
-
- /* determine the real addresses of the sections */
- sizes.text_ra = ra;
- sizes.data_ra = ALIGN_PAGE(sizes.text_ra +
- (sizes.text_bound - sizes.text_base));
-
- DTRACE(htab, ("text map - base=0x%lx bound=0x%lx ra=0x%lx\n",
- (unsigned long)sizes.text_base,
- (unsigned long)sizes.text_bound,
- (unsigned long)sizes.text_ra));
- DTRACE(htab, ("data map - base=0x%lx bound=0x%lx ra=0x%lx\n",
- (unsigned long)sizes.data_base,
- (unsigned long)sizes.data_bound,
- (unsigned long)sizes.data_ra));
-
- /* set up virtual memory maps for each of the regions */
- htab_map_region(me, sizes.text_ra, sizes.text_base,
- sizes.text_bound - sizes.text_base,
- wimg, pp,
- htaborg, htabmask);
- htab_map_region(me, sizes.data_ra, sizes.data_base,
- sizes.data_bound - sizes.data_base,
- wimg, pp,
- htaborg, htabmask);
-
- /* dma the sections into physical memory */
- bfd_map_over_sections (image, htab_dma_binary, (PTR) &sizes);
-}
-
-static void
-htab_init_data_callback(device *me,
- psim *system)
-{
- if (WITH_TARGET_WORD_BITSIZE != 32)
- error("devices/htab: only 32bit targets currently suported\n");
-
- /* only the pte does work */
- if (strcmp(device_name(me), "pte") == 0) {
- unsigned32 htaborg;
- unsigned32 htabmask;
-
- htab_decode_hash_table(device_parent(me), &htaborg, &htabmask);
-
- if (device_find_property(me, "file-name") != NULL) {
- /* map in a binary */
- unsigned32 pte_ra = device_find_integer_property(me, "real-address");
- unsigned pte_wimg = device_find_integer_property(me, "wimg");
- unsigned pte_pp = device_find_integer_property(me, "pp");
- const char *file_name = device_find_string_property(me, "file-name");
- DTRACE(htab, ("pte - ra=0x%lx, wimg=%ld, pp=%ld, file-name=%s\n",
- (unsigned long)pte_ra,
- (unsigned long)pte_wimg,
- (long)pte_pp,
- file_name));
- htab_map_binary(me, pte_ra, pte_wimg, pte_pp, file_name,
- htaborg, htabmask);
- }
- else {
- /* handle a normal mapping definition */
- /* so that 0xff...0 is make 0xffffff00 */
- signed32 pte_va = device_find_integer_property(me, "virtual-address");
- unsigned32 pte_ra = device_find_integer_property(me, "real-address");
- unsigned pte_nr_bytes = device_find_integer_property(me, "nr-bytes");
- unsigned pte_wimg = device_find_integer_property(me, "wimg");
- unsigned pte_pp = device_find_integer_property(me, "pp");
- DTRACE(htab, ("pte - ra=0x%lx, wimg=%ld, pp=%ld, va=0x%lx, nr_bytes=%ld\n",
- (unsigned long)pte_ra,
- (long)pte_wimg,
- (long)pte_pp,
- (unsigned long)pte_va,
- (long)pte_nr_bytes));
- htab_map_region(me, pte_ra, pte_va, pte_nr_bytes, pte_wimg, pte_pp,
- htaborg, htabmask);
- }
- }
-}
-
-
-static device_callbacks const htab_callbacks = {
- ignore_device_init,
- htab_init_data_callback,
- unimp_device_attach_address,
- unimp_device_detach_address,
- unimp_device_io_read_buffer,
- unimp_device_io_write_buffer,
- passthrough_device_dma_read_buffer,
- passthrough_device_dma_write_buffer,
- unimp_device_interrupt_event,
- unimp_device_child_interrupt_event,
- generic_device_unit_decode,
- generic_device_unit_encode,
- unimp_device_instance_create,
- unimp_device_instance_delete,
- unimp_device_instance_read,
- unimp_device_instance_write,
- unimp_device_instance_seek,
- unimp_device_ioctl,
+ { NULL, }, /* init */
+ { passthrough_device_address_attach,
+ passthrough_device_address_detach, },
+ { NULL, }, /* IO */
+ { passthrough_device_dma_read_buffer, passthrough_device_dma_write_buffer, },
+ { NULL, }, /* interrupt */
+ { generic_device_unit_decode,
+ generic_device_unit_encode, },
};
-
-/* Load device: binary
-
- Single property the name of which specifies the file (understood by
- BFD) that is to be DMAed into memory as part of init */
-
-STATIC_INLINE_DEVICE_TABLE void
-update_for_binary_section(bfd *abfd,
- asection *the_section,
- PTR obj)
-{
- unsigned_word section_vma;
- unsigned_word section_size;
- access_type access;
- device *me = (device*)obj;
-
- /* skip the section if no memory to allocate */
- if (! (bfd_get_section_flags(abfd, the_section) & SEC_ALLOC))
- return;
-
- /* check/ignore any sections of size zero */
- section_size = bfd_get_section_size_before_reloc(the_section);
- if (section_size == 0)
- return;
-
- /* find where it is to go */
- section_vma = bfd_get_section_vma(abfd, the_section);
-
- DTRACE(binary,
- ("name=%-7s, vma=0x%.8lx, size=%6ld, flags=%3lx(%s%s%s%s%s )\n",
- bfd_get_section_name(abfd, the_section),
- (long)section_vma,
- (long)section_size,
- (long)bfd_get_section_flags(abfd, the_section),
- bfd_get_section_flags(abfd, the_section) & SEC_LOAD ? " LOAD" : "",
- bfd_get_section_flags(abfd, the_section) & SEC_CODE ? " CODE" : "",
- bfd_get_section_flags(abfd, the_section) & SEC_DATA ? " DATA" : "",
- bfd_get_section_flags(abfd, the_section) & SEC_ALLOC ? " ALLOC" : "",
- bfd_get_section_flags(abfd, the_section) & SEC_READONLY ? " READONLY" : ""
- ));
-
- /* determine the devices access */
- access = access_read;
- if (bfd_get_section_flags(abfd, the_section) & SEC_CODE)
- access |= access_exec;
- if (!(bfd_get_section_flags(abfd, the_section) & SEC_READONLY))
- access |= access_write;
-
- /* if a map, pass up a request to create the memory in core */
- if (strncmp(device_name(me), "map-binary", strlen("map-binary")) == 0)
- device_attach_address(device_parent(me),
- device_name(me),
- attach_raw_memory,
- 0 /*address space*/,
- section_vma,
- section_size,
- access,
- me);
-
- /* if a load dma in the required data */
- if (bfd_get_section_flags(abfd, the_section) & SEC_LOAD) {
- void *section_init = zalloc(section_size);
- if (!bfd_get_section_contents(abfd,
- the_section,
- section_init, 0,
- section_size)) {
- bfd_perror("core:load_section()");
- error("load of data failed");
- return;
- }
- if (device_dma_write_buffer(device_parent(me),
- section_init,
- 0 /*space*/,
- section_vma,
- section_size,
- 1 /*violate_read_only*/)
- != section_size)
- error("data_init_callback() broken transfer for %s\n", device_name(me));
- zfree(section_init); /* only free if load */
- }
-}
-
-
-static void
-binary_init_data_callback(device *me,
- psim *system)
-{
- /* get the file name */
- const char *file_name = device_find_string_property(me, "file-name");
- bfd *image;
-
- /* open the file */
- image = bfd_openr(file_name, NULL);
- if (image == NULL) {
- bfd_perror("devices/binary");
- error("devices/%s - the file %s not loaded\n", device_name(me), file_name);
- }
-
- /* check it is valid */
- if (!bfd_check_format(image, bfd_object)) {
- bfd_close(image);
- error("devices/%s - the file %s has an invalid binary format\n",
- device_name(me), file_name);
- }
-
- /* and the data sections */
- bfd_map_over_sections(image,
- update_for_binary_section,
- (PTR)me);
-
- bfd_close(image);
-}
-
-
-static device_callbacks const binary_callbacks = {
- ignore_device_init,
- binary_init_data_callback,
- unimp_device_attach_address,
- unimp_device_detach_address,
- unimp_device_io_read_buffer,
- unimp_device_io_write_buffer,
- unimp_device_dma_read_buffer,
- unimp_device_dma_write_buffer,
- unimp_device_interrupt_event,
- unimp_device_child_interrupt_event,
- unimp_device_unit_decode,
- unimp_device_unit_encode,
- unimp_device_instance_create,
- unimp_device_instance_delete,
- unimp_device_instance_read,
- unimp_device_instance_write,
- unimp_device_instance_seek,
- unimp_device_ioctl,
-};
-
-
-
-/* Stack device: stack@<type>
-
- Has a single IOCTL to create a stack frame of the specified type.
- If <type> is elf or xcoff then a corresponding stack is created.
- Any other value of type is ignored.
-
- The IOCTL takes the additional arguments:
-
- unsigned_word stack_end -- where the stack should come down from
- char **argv -- ...
- char **envp -- ...
-
- */
-
-STATIC_INLINE_DEVICE_TABLE int
-sizeof_argument_strings(char **arg)
-{
- int sizeof_strings = 0;
-
- /* robust */
- if (arg == NULL)
- return 0;
-
- /* add up all the string sizes (padding as we go) */
- for (; *arg != NULL; arg++) {
- int len = strlen(*arg) + 1;
- sizeof_strings += ALIGN_8(len);
- }
-
- return sizeof_strings;
-}
-
-STATIC_INLINE_DEVICE_TABLE int
-number_of_arguments(char **arg)
-{
- int nr;
- if (arg == NULL)
- return 0;
- for (nr = 0; *arg != NULL; arg++, nr++);
- return nr;
-}
-
-STATIC_INLINE_DEVICE_TABLE int
-sizeof_arguments(char **arg)
-{
- return ALIGN_8((number_of_arguments(arg) + 1) * sizeof(unsigned_word));
-}
-
-STATIC_INLINE_DEVICE_TABLE void
-write_stack_arguments(psim *system,
- char **arg,
- unsigned_word start_block,
- unsigned_word end_block,
- unsigned_word start_arg,
- unsigned_word end_arg)
-{
- DTRACE(stack,
- ("write_stack_arguments(system=0x%lx, arg=0x%lx, start_block=0x%lx, end_block=0x%lx, start_arg=0x%lx, end_arg=0x%lx)\n",
- (long)system, (long)arg, (long)start_block, (long)end_block, (long)start_arg, (long)end_arg));
- if (arg == NULL)
- error("write_arguments: character array NULL\n");
- /* only copy in arguments, memory is already zero */
- for (; *arg != NULL; arg++) {
- int len = strlen(*arg)+1;
- unsigned_word target_start_block;
- DTRACE(stack,
- ("write_stack_arguments() write %s=%s at %s=0x%lx %s=0x%lx %s=0x%lx\n",
- "**arg", *arg, "start_block", (long)start_block,
- "len", (long)len, "start_arg", (long)start_arg));
- if (psim_write_memory(system, 0, *arg,
- start_block, len,
- 0/*violate_readonly*/) != len)
- error("write_stack_arguments() - write of **arg (%s) at 0x%x failed\n",
- *arg, start_block);
- target_start_block = H2T_word(start_block);
- if (psim_write_memory(system, 0, &target_start_block,
- start_arg, sizeof(target_start_block),
- 0) != sizeof(target_start_block))
- error("write_stack_arguments() - write of *arg failed\n");
- start_block += ALIGN_8(len);
- start_arg += sizeof(start_block);
- }
- start_arg += sizeof(start_block); /*the null at the end*/
- if (start_block != end_block
- || ALIGN_8(start_arg) != end_arg)
- error("write_stack_arguments - possible corruption\n");
- DTRACE(stack,
- ("write_stack_arguments() = void\n"));
-}
-
-STATIC_INLINE_DEVICE_TABLE void
-create_elf_stack_frame(psim *system,
- unsigned_word bottom_of_stack,
- char **argv,
- char **envp)
-{
- /* fixme - this is over aligned */
-
- /* information block */
- const unsigned sizeof_envp_block = sizeof_argument_strings(envp);
- const unsigned_word start_envp_block = bottom_of_stack - sizeof_envp_block;
- const unsigned sizeof_argv_block = sizeof_argument_strings(argv);
- const unsigned_word start_argv_block = start_envp_block - sizeof_argv_block;
-
- /* auxiliary vector - contains only one entry */
- const unsigned sizeof_aux_entry = 2*sizeof(unsigned_word); /* magic */
- const unsigned_word start_aux = start_argv_block - ALIGN_8(sizeof_aux_entry);
-
- /* environment points (including null sentinal) */
- const unsigned sizeof_envp = sizeof_arguments(envp);
- const unsigned_word start_envp = start_aux - sizeof_envp;
-
- /* argument pointers (including null sentinal) */
- const int argc = number_of_arguments(argv);
- const unsigned sizeof_argv = sizeof_arguments(argv);
- const unsigned_word start_argv = start_envp - sizeof_argv;
-
- /* link register save address - alligned to a 16byte boundary */
- const unsigned_word top_of_stack = ((start_argv
- - 2 * sizeof(unsigned_word))
- & ~0xf);
-
- /* install arguments on stack */
- write_stack_arguments(system, envp,
- start_envp_block, bottom_of_stack,
- start_envp, start_aux);
- write_stack_arguments(system, argv,
- start_argv_block, start_envp_block,
- start_argv, start_envp);
-
- /* set up the registers */
- psim_write_register(system, -1,
- &top_of_stack, "sp", cooked_transfer);
- psim_write_register(system, -1,
- &argc, "r3", cooked_transfer);
- psim_write_register(system, -1,
- &start_argv, "r4", cooked_transfer);
- psim_write_register(system, -1,
- &start_envp, "r5", cooked_transfer);
- psim_write_register(system, -1,
- &start_aux, "r6", cooked_transfer);
-}
-
-STATIC_INLINE_DEVICE_TABLE void
-create_aix_stack_frame(psim *system,
- unsigned_word bottom_of_stack,
- char **argv,
- char **envp)
-{
- unsigned_word core_envp;
- unsigned_word core_argv;
- unsigned_word core_argc;
- unsigned_word core_aux;
- unsigned_word top_of_stack;
-
- /* cheat - create an elf stack frame */
- create_elf_stack_frame(system, bottom_of_stack, argv, envp);
-
- /* extract argument addresses from registers */
- psim_read_register(system, 0, &top_of_stack, "r1", cooked_transfer);
- psim_read_register(system, 0, &core_argc, "r3", cooked_transfer);
- psim_read_register(system, 0, &core_argv, "r4", cooked_transfer);
- psim_read_register(system, 0, &core_envp, "r5", cooked_transfer);
- psim_read_register(system, 0, &core_aux, "r6", cooked_transfer);
-
- /* extract arguments from registers */
- error("create_aix_stack_frame() - what happens next?\n");
-}
-
-
-
-static void
-stack_ioctl_callback(device *me,
- psim *system,
- cpu *processor,
- unsigned_word cia,
- va_list ap)
-{
- unsigned_word stack_pointer;
- const char *stack_type;
- char **argv;
- char **envp;
- stack_pointer = va_arg(ap, unsigned_word);
- argv = va_arg(ap, char **);
- envp = va_arg(ap, char **);
- DTRACE(stack,
- ("stack_ioctl_callback(me=0x%lx:%s, system=0x%lx, processor=0x%lx, cia=0x%lx, argv=0x%lx, envp=0x%lx)\n",
- (long)me, device_name(me), (long)system, (long)processor, (long)cia, (long)argv, (long)envp));
- stack_type = device_find_string_property(me, "stack-type");
- if (strcmp(stack_type, "elf") == 0)
- create_elf_stack_frame(system, stack_pointer, argv, envp);
- else if (strcmp(stack_type, "xcoff") == 0)
- create_aix_stack_frame(system, stack_pointer, argv, envp);
- DTRACE(stack,
- ("stack_ioctl_callback() = void\n"));
-}
-
-static device_callbacks const stack_callbacks = {
- ignore_device_init,
- ignore_device_init,
- unimp_device_attach_address,
- unimp_device_detach_address,
- unimp_device_io_read_buffer,
- unimp_device_io_write_buffer,
- unimp_device_dma_read_buffer,
- unimp_device_dma_write_buffer,
- unimp_device_interrupt_event,
- unimp_device_child_interrupt_event,
- unimp_device_unit_decode,
- unimp_device_unit_encode,
- unimp_device_instance_create,
- unimp_device_instance_delete,
- unimp_device_instance_read,
- unimp_device_instance_write,
- unimp_device_instance_seek,
- stack_ioctl_callback,
-};
-
-
-
-device_descriptor device_table[] = {
- { "console", console_create, &console_callbacks },
- { "memory", NULL, &memory_callbacks },
- { "eeprom", NULL, &memory_callbacks },
- { "vm", vea_vm_create, &vm_callbacks },
- { "halt", NULL, &halt_callbacks },
- { "icu", NULL, &icu_callbacks },
- { "register", NULL, &register_callbacks },
- { "iobus", NULL, &iobus_callbacks },
- { "file", NULL, &file_callbacks },
- { "data", NULL, &data_callbacks },
- { "htab", NULL, &htab_callbacks },
- { "pte", NULL, &htab_callbacks }, /* yep - uses htab's table */
- { "stack", NULL, &stack_callbacks },
- { "load-binary", NULL, &binary_callbacks },
- { "map-binary", NULL, &binary_callbacks },
+static const device_descriptor ob_device_table[] = {
/* standard OpenBoot devices */
{ "aliases", NULL, &passthrough_callbacks },
{ "options", NULL, &passthrough_callbacks },
@@ -2236,8 +297,14 @@ device_descriptor device_table[] = {
{ "cpus", NULL, &passthrough_callbacks },
{ "openprom", NULL, &passthrough_callbacks },
{ "init", NULL, &passthrough_callbacks },
- { "trace", NULL, &trace_callbacks },
{ NULL },
};
+const device_descriptor *const device_table[] = {
+ ob_device_table,
+#include "hw.c"
+ NULL,
+};
+
+
#endif /* _DEVICE_TABLE_C_ */
diff --git a/gnu/dist/sim/ppc/device_table.h b/gnu/dist/sim/ppc/device_table.h
index 180c13bbbc4..af6c28d697d 100644
--- a/gnu/dist/sim/ppc/device_table.h
+++ b/gnu/dist/sim/ppc/device_table.h
@@ -22,24 +22,60 @@
#ifndef _DEVICE_TABLE_H_
#define _DEVICE_TABLE_H_
-#include <stdarg.h>
-
#include "basics.h"
#include "device.h"
+#include "tree.h"
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#endif
+
+
+typedef struct _device_callbacks device_callbacks;
+
+
+/* The creator, returns a pointer to any data that should be allocated
+ once during (multiple) simulation runs */
+
+typedef void *(device_creator)
+ (const char *name,
+ const device_unit *unit_address,
+ const char *args);
+
+
+/* two stages of initialization */
typedef void (device_init_callback)
- (device *me,
- psim *system);
+ (device *me);
-typedef void (device_config_address_callback)
+typedef struct _device_init_callbacks {
+ device_init_callback *address; /* NULL - ignore */
+ device_init_callback *data; /* NULL - ignore */
+} device_init_callbacks;
+
+
+/* attaching/detaching a devices address space to its parent */
+
+typedef void (device_address_callback)
(device *me,
- const char *name,
attach_type attach,
int space,
unsigned_word addr,
unsigned nr_bytes,
access_type access,
- device *who); /*callback/default*/
+ device *client); /*callback/default*/
+
+typedef struct _device_address_callbacks {
+ device_address_callback *attach;
+ device_address_callback *detach;
+} device_address_callbacks;
+
+
+/* I/O operations - from parent */
typedef unsigned (device_io_read_buffer_callback)
(device *me,
@@ -59,6 +95,14 @@ typedef unsigned (device_io_write_buffer_callback)
cpu *processor,
unsigned_word cia);
+typedef struct _device_io_callbacks { /* NULL - error */
+ device_io_read_buffer_callback *read_buffer;
+ device_io_write_buffer_callback *write_buffer;
+} device_io_callbacks;
+
+
+/* DMA transfers by a device via its parent */
+
typedef unsigned (device_dma_read_buffer_callback)
(device *me,
void *dest,
@@ -74,6 +118,11 @@ typedef unsigned (device_dma_write_buffer_callback)
unsigned nr_bytes,
int violate_read_only_section);
+typedef struct _device_dma_callbacks { /* NULL - error */
+ device_dma_read_buffer_callback *read_buffer;
+ device_dma_write_buffer_callback *write_buffer;
+} device_dma_callbacks;
+
/* Interrupts */
@@ -95,26 +144,55 @@ typedef void (device_child_interrupt_event_callback)
cpu *processor,
unsigned_word cia);
+typedef struct _device_interrupt_port_descriptor {
+ const char *name;
+ int number;
+ int nr_ports;
+ port_direction direction;
+} device_interrupt_port_descriptor;
+
+typedef struct _device_interrupt_callbacks {
+ device_interrupt_event_callback *event;
+ device_child_interrupt_event_callback *child_event;
+ const device_interrupt_port_descriptor *ports;
+} device_interrupt_callbacks;
-/* bus address decoding */
+
+/* symbolic value decoding */
typedef int (device_unit_decode_callback)
- (device *me,
+ (device *bus,
const char *unit,
device_unit *address);
typedef int (device_unit_encode_callback)
- (device *me,
+ (device *bus,
const device_unit *unit_address,
char *buf,
int sizeof_buf);
+typedef int (device_address_to_attach_address_callback)
+ (device *bus,
+ const device_unit *address,
+ int *attach_space,
+ unsigned_word *attach_address,
+ device *client);
-/* instances */
+typedef int (device_size_to_attach_size_callback)
+ (device *bus,
+ const device_unit *size,
+ unsigned *nr_bytes,
+ device *client);
-typedef void *(device_instance_create_callback)
- (device *me,
- const char *args);
+typedef struct _device_convert_callbacks {
+ device_unit_decode_callback *decode_unit;
+ device_unit_encode_callback *encode_unit;
+ device_address_to_attach_address_callback *address_to_attach_address;
+ device_size_to_attach_size_callback *size_to_attach_size;
+} device_convert_callbacks;
+
+
+/* instances */
typedef void (device_instance_delete_callback)
(device_instance *instance);
@@ -134,14 +212,43 @@ typedef int (device_instance_seek_callback)
unsigned_word pos_hi,
unsigned_word pos_lo);
+typedef int (device_instance_method)
+ (device_instance *instance,
+ int n_stack_args,
+ unsigned_cell stack_args[/*n_stack_args*/],
+ int n_stack_returns,
+ unsigned_cell stack_returns[/*n_stack_returns*/]);
+
+typedef struct _device_instance_methods {
+ const char *name;
+ device_instance_method *method;
+} device_instance_methods;
+
+struct _device_instance_callbacks { /* NULL - error */
+ device_instance_delete_callback *delete;
+ device_instance_read_callback *read;
+ device_instance_write_callback *write;
+ device_instance_seek_callback *seek;
+ const device_instance_methods *methods;
+};
+
+typedef device_instance *(device_create_instance_callback)
+ (device *me,
+ const char *full_path,
+ const char *args);
+
+typedef device_instance *(package_create_instance_callback)
+ (device_instance *parent,
+ const char *args);
+
/* all else fails */
-typedef void (device_ioctl_callback)
+typedef int (device_ioctl_callback)
(device *me,
- psim *system,
cpu *processor,
unsigned_word cia,
+ device_ioctl_request request,
va_list ap);
typedef void (device_usage_callback)
@@ -153,35 +260,25 @@ typedef void (device_usage_callback)
struct _device_callbacks {
/* initialization */
- device_init_callback *init_address;
- device_init_callback *init_data;
+ device_init_callbacks init;
/* address/data config - from child */
- device_config_address_callback *attach_address;
- device_config_address_callback *detach_address;
+ device_address_callbacks address;
- /* address/data transfer - to child */
- device_io_read_buffer_callback *io_read_buffer;
- device_io_write_buffer_callback *io_write_buffer;
+ /* address/data transfer - from parent */
+ device_io_callbacks io;
/* address/data transfer - from child */
- device_dma_read_buffer_callback *dma_read_buffer;
- device_dma_write_buffer_callback *dma_write_buffer;
+ device_dma_callbacks dma;
/* interrupt signalling */
- device_interrupt_event_callback *interrupt_event;
- device_child_interrupt_event_callback *child_interrupt_event;
+ device_interrupt_callbacks interrupt;
/* bus address decoding */
- device_unit_decode_callback *decode_unit;
- device_unit_encode_callback *encode_unit;
+ device_convert_callbacks convert;
/* instances */
- device_instance_create_callback *instance_create;
- device_instance_delete_callback *instance_delete;
- device_instance_read_callback *instance_read;
- device_instance_write_callback *instance_write;
- device_instance_seek_callback *instance_seek;
+ device_create_instance_callback *instance_create;
/* back door to anything we've forgot */
device_ioctl_callback *ioctl;
@@ -192,12 +289,6 @@ struct _device_callbacks {
/* Table of all the devices and a function to lookup/create a device
from its name */
-typedef void *(device_creator)
- (const char *name,
- const device_unit *unit_address,
- const char *args,
- device *parent);
-
typedef struct _device_descriptor device_descriptor;
struct _device_descriptor {
const char *name;
@@ -205,48 +296,28 @@ struct _device_descriptor {
const device_callbacks *callbacks;
};
-extern device_descriptor device_table[];
-
-
-/* Unimplemented call back functions. These abort the simulation */
-
-extern device_init_callback unimp_device_init;
-extern device_config_address_callback unimp_device_attach_address;
-extern device_config_address_callback unimp_device_detach_address;
-extern device_io_read_buffer_callback unimp_device_io_read_buffer;
-extern device_io_write_buffer_callback unimp_device_io_write_buffer;
-extern device_dma_read_buffer_callback unimp_device_dma_read_buffer;
-extern device_dma_write_buffer_callback unimp_device_dma_write_buffer;
-extern device_interrupt_event_callback unimp_device_interrupt_event;
-extern device_child_interrupt_event_callback unimp_device_child_interrupt_event;
-extern device_unit_decode_callback unimp_device_unit_decode;
-extern device_unit_encode_callback unimp_device_unit_encode;
-extern device_instance_create_callback unimp_device_instance_create;
-extern device_instance_delete_callback unimp_device_instance_delete;
-extern device_instance_read_callback unimp_device_instance_read;
-extern device_instance_write_callback unimp_device_instance_write;
-extern device_instance_seek_callback unimp_device_instance_seek;
-extern device_ioctl_callback unimp_device_ioctl;
+extern const device_descriptor *const device_table[];
+#include "hw.h"
/* Pass through, ignore and generic callback functions. A call going
towards the root device are passed on up, local calls are ignored
and call downs abort */
-extern device_config_address_callback passthrough_device_attach_address;
-extern device_config_address_callback passthrough_device_detach_address;
+extern device_address_callback passthrough_device_address_attach;
+extern device_address_callback passthrough_device_address_detach;
extern device_dma_read_buffer_callback passthrough_device_dma_read_buffer;
extern device_dma_write_buffer_callback passthrough_device_dma_write_buffer;
-extern device_init_callback ignore_device_init;
extern device_unit_decode_callback ignore_device_unit_decode;
extern device_init_callback generic_device_init_address;
extern device_unit_decode_callback generic_device_unit_decode;
extern device_unit_encode_callback generic_device_unit_encode;
+extern device_address_to_attach_address_callback generic_device_address_to_attach_address;
+extern device_size_to_attach_size_callback generic_device_size_to_attach_size;
extern const device_callbacks passthrough_device_callbacks;
-
#endif /* _DEVICE_TABLE_H_ */
diff --git a/gnu/dist/sim/ppc/dgen.c b/gnu/dist/sim/ppc/dgen.c
index 23994127835..54e0e2657c9 100644
--- a/gnu/dist/sim/ppc/dgen.c
+++ b/gnu/dist/sim/ppc/dgen.c
@@ -51,7 +51,6 @@
/****************************************************************/
int spreg_lookup_table = 1;
-int number_lines = 1;
enum {
nr_of_sprs = 1024,
};
@@ -156,7 +155,7 @@ gen_spreg_h(spreg_table *table, lf *file)
spreg_table_entry *entry;
char **attribute;
- lf_print_copyleft(file);
+ lf_print__gnu_copyleft(file);
lf_printf(file, "\n");
lf_printf(file, "#ifndef _SPREG_H_\n");
lf_printf(file, "#define _SPREG_H_\n");
@@ -198,7 +197,7 @@ gen_spreg_c(spreg_table *table, lf *file)
char **attribute;
int spreg_nr;
- lf_print_copyleft(file);
+ lf_print__gnu_copyleft(file);
lf_printf(file, "\n");
lf_printf(file, "#ifndef _SPREG_C_\n");
lf_printf(file, "#define _SPREG_C_\n");
@@ -281,25 +280,25 @@ main(int argc,
char **argv,
char **envp)
{
+ lf_file_references file_references = lf_include_references;
spreg_table *sprs = NULL;
char *real_file_name = NULL;
+ int is_header = 0;
int ch;
if (argc <= 1) {
printf("Usage: dgen ...\n");
printf("-s Use switch instead of table\n");
- printf("-n Use this as cpp line numbering name\n");
- printf("-[Pp] <spreg> Output spreg.h(P) or spreg.c(p)\n");
- printf("-l Suppress cpp line numbering in output files\n");
+ printf("-n <file-name> Use this as cpp line numbering name\n");
+ printf("-h Output header file\n");
+ printf("-p <spreg-file> Output spreg.h(P) or spreg.c(p)\n");
+ printf("-L Suppress cpp line numbering in output files\n");
}
- while ((ch = getopt(argc, argv, "lsn:r:P:p:")) != -1) {
+ while ((ch = getopt(argc, argv, "hLsn:r:p:")) != -1) {
fprintf(stderr, "\t-%c %s\n", ch, ( optarg ? optarg : ""));
switch(ch) {
- case 'l':
- number_lines = 0;
- break;
case 's':
spreg_lookup_table = 0;
break;
@@ -309,19 +308,23 @@ main(int argc,
case 'n':
real_file_name = strdup(optarg);
break;
- case 'P':
+ case 'L':
+ file_references = lf_omit_references;
+ break;
+ case 'h':
+ is_header = 1;
+ break;
case 'p':
{
- lf *file = lf_open(optarg, real_file_name, number_lines);
- switch (ch) {
- case 'P':
+ lf *file = lf_open(optarg, real_file_name, file_references,
+ (is_header ? lf_is_h : lf_is_c),
+ argv[0]);
+ if (is_header)
gen_spreg_h(sprs, file);
- break;
- case 'p':
+ else
gen_spreg_c(sprs, file);
- break;
- }
lf_close(file);
+ is_header = 0;
}
real_file_name = NULL;
break;
diff --git a/gnu/dist/sim/ppc/emul_bugapi.c b/gnu/dist/sim/ppc/emul_bugapi.c
index 1c335854c7e..97028bf9de9 100644
--- a/gnu/dist/sim/ppc/emul_bugapi.c
+++ b/gnu/dist/sim/ppc/emul_bugapi.c
@@ -1,6 +1,6 @@
/* This file is part of the program psim.
- Copyright (C) 1994-1996, Andrew Cagney <cagney@highland.com.au>
+ 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
@@ -11,11 +11,11 @@
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.
-
+
*/
@@ -36,6 +36,25 @@
#include <stdlib.h>
#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#endif
+
+
+/* EMULATION
+
+ BUG - Motorola's embeded firmware BUG interface
+
+ DESCRIPTION
+
+
+
+ */
+
/* from PowerPCBug Debugging Package User's Manual, part 2 of 2 and also bug.S - Dale Rahn */
#define _INCHR 0x000 /* Input character */
@@ -45,7 +64,7 @@
#define _READLN 0x004 /* Input line (pointer / count format) */
#define _CHKBRK 0x005 /* Check for break */
#define _DSKRD 0x010 /* Disk read */
-#define _DKSWR 0x011 /* Disk write */
+#define _DSKWR 0x011 /* Disk write */
#define _DSKCFIG 0x012 /* Disk configure */
#define _DSKFMT 0x014 /* Disk format */
#define _DSKCTRL 0x015 /* Disk control */
@@ -104,7 +123,7 @@ static const struct bug_map bug_mapping[] = {
{ _READLN, ".READLN -- Input line (pointer / count format)" },
{ _CHKBRK, ".CHKBRK -- Check for break" },
{ _DSKRD, ".DSKRD -- Disk read" },
- { _DKSWR, ".DKSWR -- Disk write" },
+ { _DSKWR, ".DSKWR -- Disk write" },
{ _DSKCFIG, ".DSKCFIG -- Disk configure" },
{ _DSKFMT, ".DSKFMT -- Disk format" },
{ _DSKCTRL, ".DSKCTRL -- Disk control" },
@@ -151,13 +170,17 @@ static const struct bug_map bug_mapping[] = {
{ _SYMBOLDA, ".SYMBOLDA -- Detach symbol table" },
};
-#ifndef OEA_START_ADDRESS
-#define OEA_START_ADDRESS 0x100000
+#ifndef BUGAPI_END_ADDRESS
+#define BUGAPI_END_ADDRESS 0x100000
#endif
+enum {
+ nr_bugapi_disks = 2,
+};
struct _os_emul_data {
+ device *root;
unsigned_word memory_size;
unsigned_word top_of_stack;
int interrupt_prefix;
@@ -166,6 +189,10 @@ struct _os_emul_data {
unsigned_word stall_cpu_loop_address;
int little_endian;
int floating_point_available;
+ /* I/O devices */
+ device_instance *output;
+ device_instance *input;
+ device_instance *(disk[nr_bugapi_disks]);
};
@@ -174,7 +201,6 @@ emul_bugapi_create(device *root,
bfd *image,
const char *name)
{
- int elf_binary;
device *node;
os_emul_data *bugapi;
@@ -185,25 +211,28 @@ emul_bugapi_create(device *root,
return NULL;
if (image != NULL
&& name == NULL
- && bfd_get_start_address(image) > OEA_START_ADDRESS)
+ && bfd_get_start_address(image) >= BUGAPI_END_ADDRESS)
return NULL;
bugapi = ZALLOC(os_emul_data);
- /* some defaults */
- elf_binary = image->xvec->flavour == bfd_target_elf_flavour;
-
/* options */
emul_add_tree_options(root, image, "bug", "oea",
1 /*oea-interrupt-prefix*/);
-
- /* add some real hardware */
+
+ /* add some real hardware, include eeprom memory for the eeprom trap
+ addresses */
emul_add_tree_hardware(root);
+ node = tree_parse(root, "/openprom/memory@0xfff00000");
+ tree_parse(node, "./psim,description \"eeprom trap addresses");
+ tree_parse(node, "./reg 0xfff00000 0x3000");
+
+ bugapi->root = root;
bugapi->memory_size
- = device_find_integer_property(root, "/openprom/options/oea-memory-size");
+ = tree_find_integer_property(root, "/openprom/options/oea-memory-size");
bugapi->interrupt_prefix =
- device_find_integer_property(root, "/openprom/options/oea-interrupt-prefix");
+ tree_find_integer_property(root, "/openprom/options/oea-interrupt-prefix");
bugapi->interrupt_vector_address = (bugapi->interrupt_prefix
? MASK(0, 43)
: 0);
@@ -211,69 +240,93 @@ emul_bugapi_create(device *root,
bugapi->stall_cpu_loop_address = (bugapi->system_call_address + 0x000f0);
bugapi->top_of_stack = bugapi->memory_size - 0x1000;
bugapi->little_endian
- = device_find_boolean_property(root, "/options/little-endian?");
+ = tree_find_boolean_property(root, "/options/little-endian?");
bugapi->floating_point_available
- = device_find_boolean_property(root, "/openprom/options/floating-point?");
+ = tree_find_boolean_property(root, "/openprom/options/floating-point?");
+ bugapi->input = NULL;
+ bugapi->output = NULL;
/* initialization */
- device_tree_add_parsed(root, "/openprom/init/register/0.pc 0x%lx",
- (unsigned long)bfd_get_start_address(image));
- device_tree_add_parsed(root, "/openprom/init/register/pc 0x%lx",
- (unsigned long)bugapi->stall_cpu_loop_address);
- device_tree_add_parsed(root, "/openprom/init/register/sp 0x%lx",
- (unsigned long)(bugapi->top_of_stack - 16));
- device_tree_add_parsed(root, "/openprom/init/register/msr 0x%x",
- (msr_recoverable_interrupt
- | (bugapi->little_endian
- ? (msr_little_endian_mode
- | msr_interrupt_little_endian_mode)
- : 0)
- | (bugapi->floating_point_available
- ? msr_floating_point_available
- : 0)
- | (bugapi->interrupt_prefix
- ? msr_interrupt_prefix
- : 0)
- ));
-
+ if (image != NULL)
+ tree_parse(root, "/openprom/init/register/0.pc 0x%lx",
+ (unsigned long)bfd_get_start_address(image));
+ tree_parse(root, "/openprom/init/register/pc 0x%lx",
+ (unsigned long)bugapi->stall_cpu_loop_address);
+ tree_parse(root, "/openprom/init/register/sp 0x%lx",
+ (unsigned long)(bugapi->top_of_stack - 16));
+ tree_parse(root, "/openprom/init/register/msr 0x%x",
+ (msr_recoverable_interrupt
+ | (bugapi->little_endian
+ ? (msr_little_endian_mode
+ | msr_interrupt_little_endian_mode)
+ : 0)
+ | (bugapi->floating_point_available
+ ? msr_floating_point_available
+ : 0)
+ | (bugapi->interrupt_prefix
+ ? msr_interrupt_prefix
+ : 0)
+ ));
+
/* patch the system call instruction to call this emulation and then
do an rfi */
- node = device_tree_add_parsed(root, "/openprom/init/data@0x%lx",
- (unsigned long)bugapi->system_call_address);
- device_tree_add_parsed(node, "./real-address 0x%lx",
- (unsigned long)bugapi->system_call_address);
- device_tree_add_parsed(node, "./data 0x%x",
- emul_call_instruction);
- node = device_tree_add_parsed(root, "/openprom/init/data@0x%lx",
- (unsigned long)bugapi->system_call_address + 4);
- device_tree_add_parsed(node, "./real-address 0x%lx",
- (unsigned long)bugapi->system_call_address + 4);
- device_tree_add_parsed(node, "./data 0x%x",
- emul_rfi_instruction);
+ node = tree_parse(root, "/openprom/init/data@0x%lx",
+ (unsigned long)bugapi->system_call_address);
+ tree_parse(node, "./psim,description \"system-call trap instruction");
+ tree_parse(node, "./real-address 0x%lx",
+ (unsigned long)bugapi->system_call_address);
+ tree_parse(node, "./data 0x%x", emul_call_instruction);
+ node = tree_parse(root, "/openprom/init/data@0x%lx",
+ (unsigned long)bugapi->system_call_address + 4);
+ tree_parse(node, "./psim,description \"return from interrupt instruction");
+ tree_parse(node, "./real-address 0x%lx",
+ (unsigned long)bugapi->system_call_address + 4);
+ tree_parse(node, "./data 0x%x",
+ emul_rfi_instruction);
/* patch the end of the system call instruction so that it contains
a loop to self instruction and point all the cpu's at this */
- node = device_tree_add_parsed(root, "/openprom/init/data@0x%lx",
- (unsigned long)bugapi->stall_cpu_loop_address);
- device_tree_add_parsed(node, "./real-address 0x%lx",
- (unsigned long)bugapi->stall_cpu_loop_address);
- device_tree_add_parsed(node, "./data 0x%lx",
- (unsigned long)emul_loop_instruction);
-
- device_tree_add_parsed(root, "/openprom/init/stack/stack-type %s",
- elf_binary ? "elf" : "aix");
-
- device_tree_add_parsed(root, "/openprom/init/load-binary/file-name \"%s",
- bfd_get_filename(image));
+ node = tree_parse(root, "/openprom/init/data@0x%lx",
+ (unsigned long)bugapi->stall_cpu_loop_address);
+ tree_parse(node, "./psim,description \"cpu-loop instruction");
+ tree_parse(node, "./real-address 0x%lx",
+ (unsigned long)bugapi->stall_cpu_loop_address);
+ tree_parse(node, "./data 0x%lx",
+ (unsigned long)emul_loop_instruction);
+
+ if (image != NULL)
+ tree_parse(root, "/openprom/init/stack/stack-type %s",
+ (image->xvec->flavour == bfd_target_elf_flavour
+ ? "ppc-elf"
+ : "ppc-xcoff"));
+
+ if (image != NULL)
+ tree_parse(root, "/openprom/init/load-binary/file-name \"%s",
+ bfd_get_filename(image));
return bugapi;
}
static void
-emul_bugapi_init(os_emul_data *emul_data,
+emul_bugapi_init(os_emul_data *bugapi,
int nr_cpus)
{
- /* nothing happens here */
+ int i;
+ /* get the current input/output devices that were created during
+ device tree initialization */
+ bugapi->input = tree_find_ihandle_property(bugapi->root, "/chosen/stdin");
+ bugapi->output = tree_find_ihandle_property(bugapi->root, "/chosen/stdout");
+ /* if present, extract the selected disk devices */
+ for (i = 0; i < nr_bugapi_disks; i++) {
+ char disk[32];
+ char *chp;
+ strcpy(disk, "/chosen/disk0");
+ ASSERT(sizeof(disk) > strlen(disk));
+ chp = strchr(disk, '0');
+ *chp = *chp + i;
+ if (tree_find_property(bugapi->root, disk) != NULL)
+ bugapi->disk[i] = tree_find_ihandle_property(bugapi->root, disk);
+ }
}
static const char *
@@ -293,7 +346,8 @@ emul_bugapi_instruction_name(int call_id)
}
static int
-emul_bugapi_do_read(cpu *processor,
+emul_bugapi_do_read(os_emul_data *bugapi,
+ cpu *processor,
unsigned_word cia,
unsigned_word buf,
int nbytes)
@@ -303,20 +357,22 @@ emul_bugapi_do_read(cpu *processor,
/* get a tempoary bufer */
scratch_buffer = (unsigned char *) zalloc(nbytes);
-
+
/* check if buffer exists by reading it */
emul_read_buffer((void *)scratch_buffer, buf, nbytes, processor, cia);
-
+
/* read */
- status = read (0, (void *)scratch_buffer, nbytes);
+ status = device_instance_read(bugapi->input,
+ (void *)scratch_buffer, nbytes);
- if (status == -1) {
+ /* -1 = error, -2 = nothing available - see "serial" [IEEE1275] */
+ if (status < 0) {
status = 0;
}
if (status > 0) {
emul_write_buffer((void *)scratch_buffer, buf, status, processor, cia);
-
+
/* Bugapi chops off the trailing n, but leaves it in the buffer */
if (scratch_buffer[status-1] == '\n' || scratch_buffer[status-1] == '\r')
status--;
@@ -327,15 +383,77 @@ emul_bugapi_do_read(cpu *processor,
}
static void
-emul_bugapi_do_write(cpu *processor,
+emul_bugapi_do_diskio(os_emul_data *bugapi,
+ cpu *processor,
+ unsigned_word cia,
+ unsigned_word descriptor_addr,
+ int call_id)
+{
+ struct dskio_descriptor {
+ unsigned_1 ctrl_lun;
+ unsigned_1 dev_lun;
+ unsigned_2 status;
+ unsigned_word pbuffer;
+ unsigned_4 blk_num;
+ unsigned_2 blk_cnt;
+ unsigned_1 flag;
+#define BUG_FILE_MARK 0x80
+#define IGNORE_FILENUM 0x02
+#define END_OF_FILE 0x01
+ unsigned_1 addr_mod;
+ } descriptor;
+ int block;
+ emul_read_buffer(&descriptor, descriptor_addr, sizeof(descriptor),
+ processor, cia);
+ T2H(descriptor.ctrl_lun);
+ T2H(descriptor.dev_lun);
+ T2H(descriptor.status);
+ T2H(descriptor.pbuffer);
+ T2H(descriptor.blk_num);
+ T2H(descriptor.blk_cnt);
+ T2H(descriptor.flag);
+ T2H(descriptor.addr_mod);
+ if (descriptor.dev_lun >= nr_bugapi_disks
+ || bugapi->disk[descriptor.dev_lun] == NULL) {
+ error("emul_bugapi_do_diskio: attempt to access unconfigured disk /chosen/disk%d",
+ descriptor.dev_lun);
+ }
+ else {
+ for (block = 0; block < descriptor.blk_cnt; block++) {
+ device_instance *disk = bugapi->disk[descriptor.dev_lun];
+ unsigned_1 buf[512]; /*????*/
+ unsigned_word block_nr = descriptor.blk_num + block;
+ unsigned_word byte_nr = block_nr * sizeof(buf);
+ unsigned_word block_addr = descriptor.pbuffer + block*sizeof(buf);
+ if (device_instance_seek(disk, 0, byte_nr) < 0)
+ error("emul_bugapi_do_diskio: bad seek\n");
+ switch (call_id) {
+ case _DSKRD:
+ if (device_instance_read(disk, buf, sizeof(buf)) != sizeof(buf))
+ error("emul_`bugapi_do_diskio: bad read\n");
+ emul_write_buffer(buf, block_addr, sizeof(buf), processor, cia);
+ break;
+ case _DSKWR:
+ emul_read_buffer(buf, block_addr, sizeof(buf), processor, cia);
+ if (device_instance_write(disk, buf, sizeof(buf)) != sizeof(buf))
+ error("emul_bugapi_do_diskio: bad write\n");
+ break;
+ default:
+ error("emul_bugapi_do_diskio: bad switch\n");
+ }
+ }
+ }
+}
+
+static void
+emul_bugapi_do_write(os_emul_data *bugapi,
+ cpu *processor,
unsigned_word cia,
unsigned_word buf,
int nbytes,
const char *suffix)
{
void *scratch_buffer = NULL;
- char *p;
- int nr_moved;
/* get a tempoary bufer */
if (nbytes > 0)
@@ -343,25 +461,17 @@ emul_bugapi_do_write(cpu *processor,
scratch_buffer = zalloc(nbytes);
/* copy in */
- nr_moved = vm_data_map_read_buffer(cpu_data_map(processor),
- scratch_buffer,
- buf,
- nbytes);
- if (nr_moved != nbytes) {
- /* FIXME - should handle better */
- error("system_call()write copy failed (nr_moved=%d != nbytes=%d)\n",
- nr_moved, nbytes);
- }
-
+ emul_read_buffer(scratch_buffer, buf, nbytes,
+ processor, cia);
+
/* write */
- for (p = (char *)scratch_buffer; nbytes-- > 0; p++)
- printf_filtered("%c", *p);
+ device_instance_write(bugapi->output, scratch_buffer, nbytes);
zfree(scratch_buffer);
}
if (suffix)
- printf_filtered("%s", suffix);
+ device_instance_write(bugapi->output, suffix, strlen(suffix));
flush_stdoutput ();
}
@@ -370,64 +480,88 @@ static int
emul_bugapi_instruction_call(cpu *processor,
unsigned_word cia,
unsigned_word ra,
- os_emul_data *emul_data)
+ os_emul_data *bugapi)
{
const int call_id = cpu_registers(processor)->gpr[10];
- const char *my_prefix UNUSED = "bugapi";
unsigned char uc;
- ITRACE (trace_os_emul,(" 0x%x %s, r3 = 0x%lx, r4 = 0x%lx\n",
- call_id, emul_bugapi_instruction_name (call_id),
- (long)cpu_registers(processor)->gpr[3],
- (long)cpu_registers(processor)->gpr[4]));;
+#define MY_INDEX itable_instruction_call
+ ITRACE (trace_os_emul,
+ (" 0x%x %s, r3 = 0x%lx, r4 = 0x%lx\n",
+ call_id, emul_bugapi_instruction_name (call_id),
+ (long)cpu_registers(processor)->gpr[3],
+ (long)cpu_registers(processor)->gpr[4]));;
/* check that this isn't an invalid instruction */
- if (cia != emul_data->system_call_address)
+ if (cia != bugapi->system_call_address)
return 0;
+
switch (call_id) {
default:
error("emul-bugapi: unimplemented bugapi %s from address 0x%lx\n",
emul_bugapi_instruction_name (call_id), SRR0);
break;
+
/* read a single character, output r3 = byte */
/* FIXME: Add support to unbuffer input */
case _INCHR:
- if (read (0, &uc, 1) < 0)
+ if (device_instance_read(bugapi->input, (void *)&uc, 1) <= 0)
uc = 0;
cpu_registers(processor)->gpr[3] = uc;
break;
+
/* read a line of at most 256 bytes, r3 = ptr to 1st byte, output r3 = ptr to last byte+1 */
case _INLN:
- cpu_registers(processor)->gpr[3] += emul_bugapi_do_read(processor, cia,
+ cpu_registers(processor)->gpr[3] += emul_bugapi_do_read(bugapi,
+ processor, cia,
cpu_registers(processor)->gpr[3],
256);
break;
+
/* output a character, r3 = character */
case _OUTCHR:
- printf_filtered("%c", (char)cpu_registers(processor)->gpr[3]);
- break;
+ {
+ char out = (char)cpu_registers(processor)->gpr[3];
+ device_instance_write(bugapi->output, &out, 1);
+ break;
+ }
+
/* output a string, r3 = ptr to 1st byte, r4 = ptr to last byte+1 */
case _OUTSTR:
- emul_bugapi_do_write(processor, cia,
+ emul_bugapi_do_write(bugapi,
+ processor, cia,
cpu_registers(processor)->gpr[3],
cpu_registers(processor)->gpr[4] - cpu_registers(processor)->gpr[3],
(const char *)0);
break;
+
/* output a string followed by \r\n, r3 = ptr to 1st byte, r4 = ptr to last byte+1 */
case _OUTLN:
-
- emul_bugapi_do_write(processor, cia,
+
+ emul_bugapi_do_write(bugapi,
+ processor, cia,
cpu_registers(processor)->gpr[3],
cpu_registers(processor)->gpr[4] - cpu_registers(processor)->gpr[3],
"\n");
break;
+
/* output a \r\n */
case _PCRLF:
- printf_filtered("\n");
+ device_instance_write(bugapi->output, "\n", 1);
break;
- /* return to ppcbug monitor */
+
+ /* read/write blocks of data to/from the disk */
+ case _DSKWR:
+ case _DSKRD:
+ emul_bugapi_do_diskio(bugapi, processor, cia,
+ cpu_registers(processor)->gpr[3],
+ call_id);
+ break;
+
+ /* return to ppcbug monitor (exiting with gpr[3] as status is not
+ part of the bug monitor) */
case _RETURN:
- cpu_halt(processor, cia, was_exited, 0); /* always succeeds */
+ cpu_halt(processor, cia, was_exited, cpu_registers(processor)->gpr[3]);
break;
}
return 1;
diff --git a/gnu/dist/sim/ppc/emul_chirp.c b/gnu/dist/sim/ppc/emul_chirp.c
index e1c97e3b885..52efefc048c 100644
--- a/gnu/dist/sim/ppc/emul_chirp.c
+++ b/gnu/dist/sim/ppc/emul_chirp.c
@@ -1,6 +1,6 @@
/* This file is part of the program psim.
- Copyright (C) 1994-1996, Andrew Cagney <cagney@highland.com.au>
+ 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
@@ -11,11 +11,11 @@
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.
-
+
*/
@@ -43,12 +43,35 @@
#endif
+/* EMULATION
+
+
+ OpenFirmware - IEEE Standard for Boot (Initialization
+ Configuration) Firmware.
+
+
+ DESCRIPTION
+
+
+ BUGS
+
+
+ This code assumes that the memory node has #address-cells and
+ #size-cells set to one. For future implementations, this may not
+ be the case.
+
+ */
+
+
+
+
/* Descriptor of the open boot services being emulated */
typedef int (chirp_handler)
(os_emul_data *data,
cpu *processor,
unsigned_word cia);
+
typedef struct _chirp_services {
const char *name;
chirp_handler *handler;
@@ -74,21 +97,28 @@ struct _os_emul_data {
chirp_services *services;
/* configuration */
unsigned_word memory_size;
+ unsigned_word real_base;
+ unsigned_word real_size;
unsigned_word virt_base;
- int little_endian;
+ unsigned_word virt_size;
int real_mode;
+ int little_endian;
int floating_point_available;
int interrupt_prefix;
+ unsigned_word load_base;
/* hash table */
unsigned_word nr_page_table_entry_groups;
+ unsigned_word htab_offset;
unsigned_word htab_ra;
unsigned_word htab_va;
unsigned_word sizeof_htab;
/* virtual address of htab */
+ unsigned_word stack_offset;
unsigned_word stack_ra;
unsigned_word stack_va;
unsigned_word sizeof_stack;
/* addresses of emulation instructions virtual/real */
+ unsigned_word code_offset;
unsigned_word code_va;
unsigned_word code_ra;
unsigned_word sizeof_code;
@@ -101,6 +131,18 @@ struct _os_emul_data {
};
+/* returns the name of the corresponding Ihandle */
+static const char *
+ihandle_name(device_instance *ihandle)
+{
+ if (ihandle == NULL)
+ return "";
+ else
+ return device_name(device_instance_device(ihandle));
+}
+
+
+
/* Read/write the argument list making certain that all values are
converted to/from host byte order.
@@ -115,9 +157,10 @@ chirp_read_t2h_args(void *args,
cpu *processor,
unsigned_word cia)
{
- unsigned32 *words;
+ unsigned_cell *words;
int i;
- /* check the number of arguments */
+ /* check against the number of arguments specified by the client
+ program */
if ((n_args >= 0 && data->n_args != n_args)
|| (n_returns >= 0 && data->n_returns != n_returns)) {
TRACE(trace_os_emul, ("%s - invalid nr of args - n_args=%ld, n_returns=%ld\n",
@@ -127,16 +170,17 @@ chirp_read_t2h_args(void *args,
return -1;
}
/* check that there is enough space */
- if (sizeof(unsigned32) * (data->n_args + data->n_returns) > sizeof_args)
+ if (sizeof(unsigned_cell) * (data->n_args + data->n_returns) > sizeof_args)
return -1;
/* bring in the data */
- emul_read_buffer(args, data->arguments + 3 * sizeof(unsigned32),
- sizeof(unsigned32) * (data->n_args + data->n_returns),
+ memset(args, 0, sizeof_args);
+ emul_read_buffer(args, data->arguments + 3 * sizeof(unsigned_cell),
+ sizeof(unsigned_cell) * (data->n_args + data->n_returns),
processor, cia);
/* convert all words to host format */
words = args;
- for (i = 0; i < (sizeof_args / sizeof(unsigned32)); i++)
- words[i] = T2H_4(words[i]);
+ for (i = 0; i < (sizeof_args / sizeof(unsigned_cell)); i++)
+ words[i] = T2H_cell(words[i]);
return 0;
}
@@ -148,14 +192,14 @@ chirp_write_h2t_args(void *args,
unsigned_word cia)
{
int i;
- unsigned32 *words;
+ unsigned_cell *words;
/* convert to target everything */
words = args;
- for (i = 0; i < (sizeof_args / sizeof(unsigned32)); i++)
- words[i] = H2T_4(words[i]);
+ for (i = 0; i < (sizeof_args / sizeof(unsigned_cell)); i++)
+ words[i] = H2T_cell(words[i]);
/* bring in the data */
- emul_write_buffer(args, data->arguments + 3 * sizeof(unsigned32),
- sizeof(unsigned32) * (data->n_args + data->n_returns),
+ emul_write_buffer(args, data->arguments + 3 * sizeof(unsigned_cell),
+ sizeof(unsigned_cell) * (data->n_args + data->n_returns),
processor, cia);
}
@@ -171,9 +215,9 @@ chirp_emul_test(os_emul_data *data,
{
struct test_args {
/*in*/
- unsigned32 name; /*string*/
+ unsigned_cell name; /*string*/
/*out*/
- unsigned32 missing;
+ unsigned_cell missing;
} args;
char name[32];
chirp_services *service = NULL;
@@ -212,9 +256,9 @@ chirp_emul_peer(os_emul_data *data,
{
struct peer_args {
/*in*/
- unsigned32 phandle;
+ unsigned_cell phandle;
/*out*/
- unsigned32 sibling_phandle;
+ unsigned_cell sibling_phandle;
} args;
device *phandle;
device *sibling_phandle = NULL;
@@ -237,7 +281,10 @@ chirp_emul_peer(os_emul_data *data,
}
else {
sibling_phandle = device_sibling(phandle);
- args.sibling_phandle = device_to_external(sibling_phandle);
+ if (sibling_phandle == NULL)
+ args.sibling_phandle = 0;
+ else
+ args.sibling_phandle = device_to_external(sibling_phandle);
}
/* write the arguments back out */
TRACE(trace_os_emul, ("peer - out - sibling_phandle=0x%lx(0x%lx`%s')\n",
@@ -258,9 +305,9 @@ chirp_emul_child(os_emul_data *data,
{
struct child_args {
/*in*/
- unsigned32 phandle;
+ unsigned_cell phandle;
/*out*/
- unsigned32 child_phandle;
+ unsigned_cell child_phandle;
} args;
device *phandle;
device *child_phandle;
@@ -280,7 +327,10 @@ chirp_emul_child(os_emul_data *data,
}
else {
child_phandle = device_child(phandle);
- args.child_phandle = device_to_external(child_phandle);
+ if (child_phandle == NULL)
+ args.child_phandle = 0;
+ else
+ args.child_phandle = device_to_external(child_phandle);
}
/* write the result out */
TRACE(trace_os_emul, ("child - out - child_phandle=0x%lx(0x%lx`%s')\n",
@@ -301,9 +351,9 @@ chirp_emul_parent(os_emul_data *data,
{
struct parent_args {
/*in*/
- unsigned32 phandle;
+ unsigned_cell phandle;
/*out*/
- unsigned32 parent_phandle;
+ unsigned_cell parent_phandle;
} args;
device *phandle;
device *parent_phandle;
@@ -323,7 +373,10 @@ chirp_emul_parent(os_emul_data *data,
}
else {
parent_phandle = device_parent(phandle);
- args.parent_phandle = device_to_external(parent_phandle);
+ if (parent_phandle == NULL)
+ args.parent_phandle = 0;
+ else
+ args.parent_phandle = device_to_external(parent_phandle);
}
/* return the result */
TRACE(trace_os_emul, ("parent - out - parent_phandle=0x%lx(0x%lx`%s')\n",
@@ -344,9 +397,9 @@ chirp_emul_instance_to_package(os_emul_data *data,
{
struct instance_to_package_args {
/*in*/
- unsigned32 ihandle;
+ unsigned_cell ihandle;
/*out*/
- unsigned32 phandle;
+ unsigned_cell phandle;
} args;
device_instance *ihandle;
device *phandle = NULL;
@@ -357,10 +410,9 @@ chirp_emul_instance_to_package(os_emul_data *data,
TRACE(trace_os_emul, ("instance-to-package - in - ihandle=0x%lx(0x%lx`%s')\n",
(unsigned long)args.ihandle,
(unsigned long)ihandle,
- (ihandle == NULL ? "" : device_instance_name(ihandle))));
+ ihandle_name(ihandle)));
/* find the corresponding phandle */
- if (args.ihandle == 0
- || ihandle == NULL) {
+ if (ihandle == NULL) {
phandle = NULL;
args.phandle = -1;
}
@@ -387,10 +439,10 @@ chirp_emul_getproplen(os_emul_data *data,
{
struct getproplen_args {
/*in*/
- unsigned32 phandle;
- unsigned32 name;
+ unsigned_cell phandle;
+ unsigned_cell name;
/*out*/
- unsigned32 proplen;
+ unsigned_cell proplen;
} args;
char name[32];
device *phandle;
@@ -438,12 +490,12 @@ chirp_emul_getprop(os_emul_data *data,
{
struct getprop_args {
/*in*/
- unsigned32 phandle;
- unsigned32 name;
- unsigned32 buf;
- unsigned32 buflen;
+ unsigned_cell phandle;
+ unsigned_cell name;
+ unsigned_cell buf;
+ unsigned_cell buflen;
/*out*/
- unsigned32 size;
+ unsigned_cell size;
} args;
char name[32];
device *phandle;
@@ -486,8 +538,10 @@ chirp_emul_getprop(os_emul_data *data,
device_find_string_property(phandle, name)));
break;
case ihandle_property:
- TRACE(trace_os_emul, ("getprop - ihandle 0x%lx\n",
- (unsigned long)device_find_ihandle_property(phandle, name)));
+ TRACE(trace_os_emul, ("getprop - ihandle=0x%lx(0x%lx`%s')\n",
+ BE2H_cell(*(unsigned_cell*)prop->array),
+ (unsigned long)device_find_ihandle_property(phandle, name),
+ ihandle_name(device_find_ihandle_property(phandle, name))));
break;
default:
break;
@@ -516,11 +570,11 @@ chirp_emul_nextprop(os_emul_data *data,
{
struct nextprop_args {
/*in*/
- unsigned32 phandle;
- unsigned32 previous;
- unsigned32 buf;
+ unsigned_cell phandle;
+ unsigned_cell previous;
+ unsigned_cell buf;
/*out*/
- unsigned32 flag;
+ unsigned_cell flag;
} args;
char previous[32];
device *phandle;
@@ -578,7 +632,7 @@ chirp_emul_setprop(os_emul_data *data,
cpu *processor,
unsigned_word cia)
{
- error("chirp: setprop not implemented\n");
+ error("chirp: setprop method not implemented\n");
return 0;
}
#endif
@@ -590,11 +644,11 @@ chirp_emul_canon(os_emul_data *data,
{
struct canon_args {
/*in*/
- unsigned32 device_specifier;
- unsigned32 buf;
- unsigned32 buflen;
+ unsigned_cell device_specifier;
+ unsigned_cell buf;
+ unsigned_cell buflen;
/*out*/
- unsigned32 length;
+ unsigned_cell length;
} args;
char device_specifier[1024];
device *phandle;
@@ -612,7 +666,7 @@ chirp_emul_canon(os_emul_data *data,
(unsigned long)args.buf,
(unsigned long)args.buflen));
/* canon the name */
- phandle = device_tree_find_device(data->root, device_specifier);
+ phandle = tree_find_device(data->root, device_specifier);
if (phandle == NULL) {
length = -1;
path = "";
@@ -645,9 +699,9 @@ chirp_emul_finddevice(os_emul_data *data,
{
struct finddevice_args {
/*in*/
- unsigned32 device_specifier;
+ unsigned_cell device_specifier;
/*out*/
- unsigned32 phandle;
+ unsigned_cell phandle;
} args;
char device_specifier[1024];
device *phandle;
@@ -661,8 +715,7 @@ chirp_emul_finddevice(os_emul_data *data,
TRACE(trace_os_emul, ("finddevice - in - device_specifier=`%s'\n",
device_specifier));
/* find the device */
- phandle = device_tree_find_device(data->root,
- device_specifier);
+ phandle = tree_find_device(data->root, device_specifier);
if (phandle == NULL)
args.phandle = -1;
else
@@ -686,11 +739,11 @@ chirp_emul_instance_to_path(os_emul_data *data,
{
struct instance_to_path_args {
/*in*/
- unsigned32 ihandle;
- unsigned32 buf;
- unsigned32 buflen;
+ unsigned_cell ihandle;
+ unsigned_cell buf;
+ unsigned_cell buflen;
/*out*/
- unsigned32 length;
+ unsigned_cell length;
} args;
device_instance *ihandle;
const char *path;
@@ -702,18 +755,23 @@ chirp_emul_instance_to_path(os_emul_data *data,
TRACE(trace_os_emul, ("instance-to-path - in - ihandle=0x%lx(0x%lx`%s') buf=0x%lx buflen=%ld\n",
(unsigned long)args.ihandle,
(unsigned long)ihandle,
- (ihandle == NULL ? "" : device_instance_name(ihandle)),
+ ihandle_name(ihandle),
(unsigned long)args.buf,
(unsigned long)args.buflen));
/* get the devices name */
- if (ihandle == NULL)
- return -1;
- path = device_instance_path(ihandle);
- length = strlen(path);
- if (length >= args.buflen)
- length = args.buflen - 1;
- emul_write_buffer(path, args.buf, length,
- processor, cia);
+ if (ihandle == NULL) {
+ args.length = -1;
+ path = "(null)";
+ }
+ else {
+ path = device_instance_path(ihandle);
+ length = strlen(path);
+ if (length >= args.buflen)
+ length = args.buflen - 1;
+ emul_write_buffer(path, args.buf, length,
+ processor, cia);
+ args.length = length;
+ }
/* return its phandle */
TRACE(trace_os_emul, ("instance-to-path - out - length=%ld buf=`%s')\n",
(unsigned long)args.length,
@@ -727,20 +785,19 @@ chirp_emul_instance_to_path(os_emul_data *data,
static int
chirp_emul_package_to_path(os_emul_data *data,
- cpu *processor,
- unsigned_word cia)
+ cpu *processor,
+ unsigned_word cia)
{
struct package_to_path_args {
/*in*/
- unsigned32 phandle;
- unsigned32 buf;
- unsigned32 buflen;
+ unsigned_cell phandle;
+ unsigned_cell buf;
+ unsigned_cell buflen;
/*out*/
- unsigned32 length;
+ unsigned_cell length;
} args;
device *phandle;
const char *path;
- int length;
/* get the args */
if (chirp_read_t2h_args(&args, sizeof(args), 3, 1, data, processor, cia))
return -1;
@@ -752,14 +809,20 @@ chirp_emul_package_to_path(os_emul_data *data,
(unsigned long)args.buf,
(unsigned long)args.buflen));
/* get the devices name */
- if (phandle == NULL)
- return -1;
- path = device_path(phandle);
- length = strlen(path);
- if (length >= args.buflen)
- length = args.buflen - 1;
- emul_write_buffer(path, args.buf, length,
- processor, cia);
+ if (phandle == NULL) {
+ args.length = -1;
+ path = "(null)";
+ }
+ else {
+ int length;
+ path = device_path(phandle);
+ length = strlen(path);
+ if (length >= args.buflen)
+ length = args.buflen - 1;
+ emul_write_buffer(path, args.buf, length,
+ processor, cia);
+ args.length = length;
+ }
/* return its phandle */
TRACE(trace_os_emul, ("package-to-path - out - length=%ld buf=`%s')\n",
(unsigned long)args.length,
@@ -778,13 +841,18 @@ chirp_emul_call_method(os_emul_data *data,
{
struct call_method_args {
/*in*/
- unsigned32 method;
- unsigned32 ihandle;
+ unsigned_cell method;
+ unsigned_cell ihandle;
/*in/out*/
- unsigned32 stack[13]; /*6in + 6out + catch */
+ unsigned_cell stack[13]; /*6in + 6out + catch */
} args;
char method[32];
device_instance *ihandle;
+ /* some useful info about our mini stack */
+ int n_stack_args;
+ int n_stack_returns;
+ int stack_catch_result;
+ int stack_returns;
/* read the args */
if (chirp_read_t2h_args(&args, sizeof(args), -1, -1, data, processor, cia))
return -1;
@@ -793,15 +861,34 @@ chirp_emul_call_method(os_emul_data *data,
sizeof(method),
processor, cia);
ihandle = external_to_device_instance(data->root, args.ihandle);
+ n_stack_args = data->n_args - 2;
+ n_stack_returns = data->n_returns - 1;
+ stack_catch_result = n_stack_args;
+ stack_returns = stack_catch_result + 1;
TRACE(trace_os_emul, ("call-method - in - n_args=%ld n_returns=%ld method=`%s' ihandle=0x%lx(0x%lx`%s')\n",
(unsigned long)data->n_args,
(unsigned long)data->n_returns,
method,
(unsigned long)args.ihandle,
(unsigned long)ihandle,
- (ihandle == NULL ? "" : device_instance_name(ihandle))));
- printf_filtered("warning chirp: call-method %s not implemented\n", method);
- args.stack[data->n_args-2+1] = 0;
+ ihandle_name(ihandle)));
+ /* see if we can emulate this method */
+ if (ihandle == NULL) {
+ /* OpenFirmware doesn't define this error */
+ error("chirp: invalid ihandle passed to call-method method");
+ }
+ else {
+ args.stack[stack_catch_result] =
+ device_instance_call_method(ihandle,
+ method,
+ n_stack_args,
+ &args.stack[0],
+ n_stack_returns,
+ &args.stack[stack_returns]);
+ }
+ /* finished */
+ TRACE(trace_os_emul, ("call-method - out - catch-result=%ld\n",
+ (unsigned long)args.stack[stack_catch_result]));
chirp_write_h2t_args(&args,
sizeof(args),
data,
@@ -819,9 +906,9 @@ chirp_emul_open(os_emul_data *data,
{
struct open_args {
/*in*/
- unsigned32 device_specifier;
+ unsigned_cell device_specifier;
/*out*/
- unsigned32 ihandle;
+ unsigned_cell ihandle;
} args;
char device_specifier[1024];
device_instance *ihandle;
@@ -835,7 +922,7 @@ chirp_emul_open(os_emul_data *data,
TRACE(trace_os_emul, ("open - in - device_specifier=`%s'\n",
device_specifier));
/* open the device */
- ihandle = device_instance_create(data->root, device_specifier, 0);
+ ihandle = tree_instance(data->root, device_specifier);
if (ihandle == NULL)
args.ihandle = -1;
else
@@ -844,7 +931,7 @@ chirp_emul_open(os_emul_data *data,
TRACE(trace_os_emul, ("open - out - ihandle=0x%lx(0x%lx`%s')\n",
(unsigned long)args.ihandle,
(unsigned long)ihandle,
- (ihandle == NULL ? "" : device_instance_name(ihandle))));
+ ihandle_name(ihandle)));
chirp_write_h2t_args(&args,
sizeof(args),
data,
@@ -859,7 +946,7 @@ chirp_emul_close(os_emul_data *data,
{
struct close_args {
/*in*/
- unsigned32 ihandle;
+ unsigned_cell ihandle;
/*out*/
} args;
device_instance *ihandle;
@@ -870,10 +957,15 @@ chirp_emul_close(os_emul_data *data,
TRACE(trace_os_emul, ("close - in - ihandle=0x%lx(0x%lx`%s')\n",
(unsigned long)args.ihandle,
(unsigned long)ihandle,
- (ihandle == NULL ? "" : device_instance_name(ihandle))));
+ ihandle_name(ihandle)));
/* close the device */
- if (ihandle != NULL)
+ if (ihandle == NULL) {
+ /* OpenFirmware doesn't define this error */
+ error("chirp: invalid ihandle passed to close method");
+ }
+ else {
device_instance_delete(ihandle);
+ }
/* return the ihandle result */
TRACE(trace_os_emul, ("close - out\n"));
chirp_write_h2t_args(&args,
@@ -890,14 +982,13 @@ chirp_emul_read(os_emul_data *data,
{
struct read_args {
/*in*/
- unsigned32 ihandle;
- unsigned32 addr;
- unsigned32 len;
+ unsigned_cell ihandle;
+ unsigned_cell addr;
+ unsigned_cell len;
/*out*/
- unsigned32 actual;
+ unsigned_cell actual;
} args;
char buf[1024];
- int actual;
device_instance *ihandle;
/* read the args */
if (chirp_read_t2h_args(&args, sizeof(args), 3, 1, data, processor, cia))
@@ -906,31 +997,60 @@ chirp_emul_read(os_emul_data *data,
TRACE(trace_os_emul, ("read - in - ihandle=0x%lx(0x%lx`%s') addr=0x%lx len=%ld\n",
(unsigned long)args.ihandle,
(unsigned long)ihandle,
- (ihandle == NULL ? "" : device_instance_name(ihandle)),
+ ihandle_name(ihandle),
(unsigned long)args.addr,
(unsigned long)args.len));
- if (ihandle == NULL)
- return -1;
- /* do the read */
- actual = args.len;
- if (actual >= sizeof(buf))
- actual = sizeof(buf) - 1;
- actual = device_instance_read(ihandle, buf, actual);
- if (actual >= 0) {
- emul_write_buffer(buf,
- args.addr,
- actual,
- processor, cia);
- args.actual = actual;
- buf[actual] = '\0';
+ if (ihandle == NULL) {
+ /* OpenFirmware doesn't define this error */
+ error("chirp: invalid ihandle passed to read method");
}
else {
- args.actual = 0;
+ /* do the reads */
+ int actual = 0;
+ while (actual < args.len) {
+ int remaining = args.len - actual;
+ int to_read = (remaining <= sizeof(buf) ? remaining : sizeof(buf));
+ int nr_read = device_instance_read(ihandle, buf, to_read);
+ if (nr_read < 0) {
+ actual = nr_read; /* the error */
+ break;
+ }
+ else if (nr_read == 0) {
+ break;
+ }
+ emul_write_buffer(buf,
+ args.addr + actual,
+ nr_read,
+ processor, cia);
+ actual += nr_read;
+ }
+ if (actual >= 0) {
+ args.actual = actual;
+ if (actual < sizeof(buf))
+ buf[actual] = '\0';
+ else
+ buf[sizeof(buf) - 1] = '\0';
+ }
+ else {
+ switch (actual) {
+ case sim_io_eof:
+ args.actual = 0;
+ break;
+ case sim_io_not_ready:
+ ASSERT(sim_io_not_ready == -2);
+ args.actual = sim_io_not_ready;
+ break;
+ default:
+ error("Bad error value %ld", (long)actual);
+ break;
+ }
+ }
}
/* return the result */
TRACE(trace_os_emul, ("read - out - actual=%ld `%s'\n",
(long)args.actual,
- (actual >= 0 ? buf : "")));
+ ((args.actual > 0 && args.actual < sizeof(buf)) ? buf : "")
+ ));
chirp_write_h2t_args(&args,
sizeof(args),
data,
@@ -940,16 +1060,16 @@ chirp_emul_read(os_emul_data *data,
static int
chirp_emul_write(os_emul_data *data,
- cpu *processor,
- unsigned_word cia)
+ cpu *processor,
+ unsigned_word cia)
{
struct write_args {
/*in*/
- unsigned32 ihandle;
- unsigned32 addr;
- unsigned32 len;
+ unsigned_cell ihandle;
+ unsigned_cell addr;
+ unsigned_cell len;
/*out*/
- unsigned32 actual;
+ unsigned_cell actual;
} args;
char buf[1024];
device_instance *ihandle;
@@ -969,16 +1089,20 @@ chirp_emul_write(os_emul_data *data,
TRACE(trace_os_emul, ("write - in - ihandle=0x%lx(0x%lx`%s') `%s' (%ld)\n",
(unsigned long)args.ihandle,
(unsigned long)ihandle,
- (ihandle == NULL ? "" : device_instance_name(ihandle)),
+ ihandle_name(ihandle),
buf, (long)actual));
- if (ihandle == NULL)
- return -1;
- /* write it out */
- actual = device_instance_write(ihandle, buf, actual);
- if (actual < 0)
- args.actual = 0;
- else
- args.actual = actual;
+ if (ihandle == NULL) {
+ /* OpenFirmware doesn't define this error */
+ error("chirp: invalid ihandle passed to write method");
+ }
+ else {
+ /* write it out */
+ actual = device_instance_write(ihandle, buf, actual);
+ if (actual < 0)
+ args.actual = 0;
+ else
+ args.actual = actual;
+ }
/* return the result */
TRACE(trace_os_emul, ("write - out - actual=%ld\n",
(long)args.actual));
@@ -996,11 +1120,11 @@ chirp_emul_seek(os_emul_data *data,
{
struct seek_args {
/*in*/
- unsigned32 ihandle;
- unsigned32 pos_hi;
- unsigned32 pos_lo;
+ unsigned_cell ihandle;
+ unsigned_cell pos_hi;
+ unsigned_cell pos_lo;
/*out*/
- unsigned32 status;
+ unsigned_cell status;
} args;
int status;
device_instance *ihandle;
@@ -1011,15 +1135,17 @@ chirp_emul_seek(os_emul_data *data,
TRACE(trace_os_emul, ("seek - in - ihandle=0x%lx(0x%lx`%s') pos.hi=0x%lx pos.lo=0x%lx\n",
(unsigned long)args.ihandle,
(unsigned long)ihandle,
- (ihandle == NULL ? "" : device_instance_name(ihandle)),
+ ihandle_name(ihandle),
args.pos_hi, args.pos_lo));
- if (ihandle == NULL)
- return -1;
- /* seek it out */
- if (ihandle == NULL)
- return -1;
- status = device_instance_seek(ihandle, args.pos_hi, args.pos_lo);
- args.status = status;
+ if (ihandle == NULL) {
+ /* OpenFirmware doesn't define this error */
+ error("chirp: invalid ihandle passed to seek method");
+ }
+ else {
+ /* seek it out */
+ status = device_instance_seek(ihandle, args.pos_hi, args.pos_lo);
+ args.status = status;
+ }
/* return the result */
TRACE(trace_os_emul, ("seek - out - status=%ld\n",
(long)args.status));
@@ -1038,7 +1164,55 @@ chirp_emul_claim(os_emul_data *data,
cpu *processor,
unsigned_word cia)
{
- error("chirp: claim not implemented\n");
+ /* NOTE: the client interface claim routine is *very* different to
+ the "claim" method described in IEEE-1275 appendix A. The latter
+ uses real addresses while this uses virtual (effective)
+ addresses. */
+ struct claim_args {
+ /* in */
+ unsigned_cell virt;
+ unsigned_cell size;
+ unsigned_cell align;
+ /* out */
+ unsigned_cell baseaddr;
+ } args;
+ /* read the args */
+ if (chirp_read_t2h_args(&args, sizeof(args),
+ 3 /*n_args*/, 1 /*n_returns*/,
+ data, processor, cia))
+ return -1;
+ TRACE(trace_os_emul, ("claim - in - virt=0x%lx size=%ld align=%d\n",
+ (unsigned long)args.virt,
+ (long int)args.size,
+ (int)args.align));
+ /* use the memory device to allocate (real) memory at the requested
+ address */
+ {
+ device_instance *memory = tree_find_ihandle_property(data->root, "/chosen/memory");
+ unsigned_cell mem_in[3];
+ unsigned_cell mem_out[1];
+ mem_in[0] = args.align; /*top-of-stack*/
+ mem_in[1] = args.size;
+ mem_in[2] = args.virt;
+ if (device_instance_call_method(memory, "claim",
+ 3, mem_in, 1, mem_out) < 0)
+ error("chirp: claim failed to allocate memory virt=0x%lx size=%ld align=%d",
+ (unsigned long)args.virt,
+ (long int)args.size,
+ (int)args.align);
+ args.baseaddr = mem_out[0];
+ }
+ /* if using virtual addresses, create a 1-1 map of this address space */
+ if (!data->real_mode) {
+ error("chirp: claim method does not support virtual mode");
+ }
+ /* return the base address */
+ TRACE(trace_os_emul, ("claim - out - baseaddr=0x%lx\n",
+ (unsigned long)args.baseaddr));
+ chirp_write_h2t_args(&args,
+ sizeof(args),
+ data,
+ processor, cia);
return 0;
}
@@ -1047,7 +1221,47 @@ chirp_emul_release(os_emul_data *data,
cpu *processor,
unsigned_word cia)
{
- error("chirp: release not implemented\n");
+ /* NOTE: the client interface release routine is *very* different to
+ the "claim" method described in IEEE-1275 appendix A. The latter
+ uses real addresses while this uses virtual (effective)
+ addresses. */
+ struct claim_args {
+ /* in */
+ unsigned_cell virt;
+ unsigned_cell size;
+ /* out */
+ } args;
+ /* read the args */
+ if (chirp_read_t2h_args(&args, sizeof(args),
+ 2 /*n_args*/, 0 /*n_returns*/,
+ data, processor, cia))
+ return -1;
+ TRACE(trace_os_emul, ("release - in - virt=0x%lx size=%ld\n",
+ (unsigned long)args.virt,
+ (long int)args.size));
+ /* use the memory device to release (real) memory at the requested
+ address */
+ {
+ device_instance *memory = tree_find_ihandle_property(data->root, "/chosen/memory");
+ unsigned_cell mem_in[2];
+ mem_in[0] = args.size;
+ mem_in[1] = args.virt;
+ if (device_instance_call_method(memory, "release",
+ 2, mem_in, 0, NULL) < 0)
+ error("chirp: claim failed to release memory virt=0x%lx size=%ld",
+ (unsigned long)args.virt,
+ (long int)args.size);
+ }
+ /* if using virtual addresses, remove the 1-1 map of this address space */
+ if (!data->real_mode) {
+ error("chirp: release method does not support virtual mode");
+ }
+ /* return the base address */
+ TRACE(trace_os_emul, ("release - out\n"));
+ chirp_write_h2t_args(&args,
+ sizeof(args),
+ data,
+ processor, cia);
return 0;
}
@@ -1059,7 +1273,25 @@ chirp_emul_boot(os_emul_data *data,
cpu *processor,
unsigned_word cia)
{
- error("chirp: boot not implemented\n");
+ /* unlike OpenFirmware this one can take an argument */
+ struct boot_args {
+ /*in*/
+ unsigned_cell bootspec;
+ /*out*/
+ } args;
+ char bootspec[1024];
+ /* read in the arguments */
+ if (chirp_read_t2h_args(&args, sizeof(args), -1, 0, data, processor, cia))
+ cpu_halt(processor, cia, was_exited, -1);
+ if (args.bootspec != 0)
+ emul_read_string(bootspec, args.bootspec, sizeof(bootspec),
+ processor, cia);
+ else
+ strcpy(bootspec, "(null)");
+ TRACE(trace_os_emul, ("boot - in bootspec=`%s'\n", bootspec));
+ /* just report this and exit */
+ printf_filtered("chrp: boot %s called, exiting.\n", bootspec);
+ cpu_halt(processor, cia, was_exited, 0);
return 0;
}
@@ -1068,7 +1300,7 @@ chirp_emul_enter(os_emul_data *data,
cpu *processor,
unsigned_word cia)
{
- error("chirp: enter not implemented\n");
+ error("chirp: enter method not implemented\n");
return 0;
}
@@ -1077,7 +1309,15 @@ chirp_emul_exit(os_emul_data *data,
cpu *processor,
unsigned_word cia)
{
- cpu_halt(processor, cia, was_exited, 0); /* always succeeds */
+ /* unlike OpenBoot this one can take an argument */
+ struct exit_args {
+ /*in*/
+ signed_cell status;
+ /*out*/
+ } args;
+ if (chirp_read_t2h_args(&args, sizeof(args), -1, 0, data, processor, cia))
+ cpu_halt(processor, cia, was_exited, -1);
+ cpu_halt(processor, cia, was_exited, args.status);
return 0;
}
@@ -1086,7 +1326,7 @@ chirp_emul_chain(os_emul_data *data,
cpu *processor,
unsigned_word cia)
{
- error("chirp: chain not implemented\n");
+ error("chirp: chain method not implemented\n");
return 0;
}
@@ -1098,7 +1338,7 @@ chirp_emul_interpret(os_emul_data *data,
cpu *processor,
unsigned_word cia)
{
- error("chirp: interpret not implemented\n");
+ error("chirp: interpret method not implemented\n");
return 0;
}
@@ -1107,7 +1347,7 @@ chirp_emul_set_callback(os_emul_data *data,
cpu *processor,
unsigned_word cia)
{
- error("chirp: set_callback not implemented\n");
+ error("chirp: set_callback method not implemented\n");
return 0;
}
@@ -1116,7 +1356,7 @@ chirp_emul_set_symbol_lookup(os_emul_data *data,
cpu *processor,
unsigned_word cia)
{
- error("chirp: set_symbol_lookup not implemented\n");
+ error("chirp: set_symbol_lookup method not implemented\n");
return 0;
}
@@ -1131,14 +1371,14 @@ chirp_emul_milliseconds(os_emul_data *data,
struct test_args {
/*in*/
/*out*/
- unsigned32 ms;
+ unsigned_cell ms;
} args;
unsigned64 time;
/* read in the arguments */
if (chirp_read_t2h_args(&args, sizeof(args), 1, 1, data, processor, cia))
return -1;
/* make up a number */
- time = event_queue_time(cpu_event_queue(processor)) / 1000000;
+ time = event_queue_time(psim_event_queue(cpu_system(processor))) / 1000000;
args.ms = time;
/* write the arguments back out */
TRACE(trace_os_emul, ("milliseconds - out - ms=%ld\n",
@@ -1211,6 +1451,10 @@ static chirp_services services[] = {
#ifndef CHIRP_START_ADDRESS
#define CHIRP_START_ADDRESS 0x80000000
#endif
+#ifndef CHIRP_LOAD_BASE
+#define CHIRP_LOAD_BASE -1
+#endif
+
typedef struct _chirp_note_desc {
signed32 real_mode;
@@ -1218,11 +1462,17 @@ typedef struct _chirp_note_desc {
signed32 real_size;
signed32 virt_base;
signed32 virt_size;
+ signed32 load_base;
} chirp_note_desc;
+typedef enum {
+ note_missing,
+ note_found,
+ note_correct,
+} note_found_status;
typedef struct _chirp_note {
chirp_note_desc desc;
- int found;
+ note_found_status found;
} chirp_note;
typedef struct _chirp_note_head {
@@ -1249,41 +1499,43 @@ map_over_chirp_note(bfd *image,
head.type = bfd_get_32(image, (void*)&head.type);
if (head.type != 0x1275)
return;
- note->found = 1;
/* check the name field */
if (head.namesz > sizeof(name)) {
- printf_filtered("open-boot warning: note name too long (%ld)\n",
- (long)head.namesz);
- return;
+ error("chirp: note name too long (%d > %d)\n", (int)head.namesz, sizeof(name));
}
if (!bfd_get_section_contents(image, sect,
name, sizeof(head), head.namesz)) {
- printf_filtered("open-boot warning: note name unreadable\n");
- return;
+ error("chirp: note name unreadable\n");
}
if (strcmp(name, "PowerPC") != 0) {
- printf_filtered("open-boot warning: note name (%s) not `PowerPC'\n",
- name);
- return;
+ printf_filtered("chirp: note name (%s) not `PowerPC'\n", name);
}
- /* get the contents */
- if (head.descsz != sizeof(note->desc)) {
- printf_filtered("open-boot warning: note descriptor of wrong size\n");
+ /* check the size */
+ if (head.descsz == sizeof(note->desc) - sizeof(signed32)) {
+ sim_io_printf_filtered("chirp: note descriptor missing load-base\n");
+ }
+ else if (head.descsz != sizeof(note->desc)) {
+ sim_io_printf_filtered("chirp: note descriptor of wrong size\n");
+ note->found = note_found;
return;
}
+ note->found = note_correct;
+ /* get the contents */
if (!bfd_get_section_contents(image, sect,
&note->desc, /* page align start */
((sizeof(head) + head.namesz) + 3) & ~3,
head.descsz)) {
- printf_filtered("open-boot warning: note descriptor unreadable\n");
- return;
+ error("chirp: note descriptor unreadable\n");
}
note->desc.real_mode = bfd_get_32(image, (void*)&note->desc.real_mode);
note->desc.real_base = bfd_get_32(image, (void*)&note->desc.real_base);
note->desc.real_size = bfd_get_32(image, (void*)&note->desc.real_size);
note->desc.virt_base = bfd_get_32(image, (void*)&note->desc.virt_base);
note->desc.virt_size = bfd_get_32(image, (void*)&note->desc.virt_size);
- note->found = 2;
+ if (head.descsz == sizeof(note->desc))
+ note->desc.load_base = bfd_get_32(image, (void*)&note->desc.load_base);
+ else
+ note->desc.load_base = CHIRP_LOAD_BASE;
}
}
@@ -1296,6 +1548,7 @@ emul_chirp_create(device *root,
os_emul_data *chirp;
device *node;
chirp_note note;
+ int i;
/* Sanity check that this really is the chosen emulation */
if (name == NULL && image == NULL)
@@ -1308,65 +1561,173 @@ emul_chirp_create(device *root,
&& strcmp(name, "openboot") != 0)
return NULL;
- /* look for an elf note section */
+ /* look for an elf note section, enter its values into the device tree */
memset(&note, 0, sizeof(note));
if (image != NULL)
bfd_map_over_sections(image, map_over_chirp_note, &note);
- if (name == NULL && image != NULL && !note.found)
+ if (name == NULL && image != NULL && note.found == note_missing)
return NULL;
+ /* Assume that it is a chirp emulation */
+
+ chirp = ZALLOC(os_emul_data);
+ chirp->root = root;
+ chirp->services = services;
+
/* the root node */
- device_add_string_property(root,
- "name",
- "gpl,clayton");
+ tree_parse(root, "/name \"gpl,clayton");
/* default options */
emul_add_tree_options(root, image, "chirp", "oea",
0 /*oea-interrupt-prefix*/);
-
+
/* hardware */
emul_add_tree_hardware(root);
-
+
/* basic information */
- chirp = ZALLOC(os_emul_data);
chirp->memory_size
- = device_find_integer_property(root, "/openprom/options/oea-memory-size");
+ = tree_find_integer_property(root, "/openprom/options/oea-memory-size");
chirp->little_endian
- = device_find_boolean_property(root, "/options/little-endian?");
+ = tree_find_boolean_property(root, "/options/little-endian?");
chirp->floating_point_available
- = device_find_boolean_property(root, "/openprom/options/floating-point?");
+ = tree_find_boolean_property(root, "/openprom/options/floating-point?");
chirp->interrupt_prefix =
- device_find_integer_property(root, "/openprom/options/oea-interrupt-prefix");
+ tree_find_integer_property(root, "/openprom/options/oea-interrupt-prefix");
+
+
+ /* Perform an interum layout of the openboot firmware in memory */
- chirp->root = root;
- chirp->services = services;
- /* the hash table */
- chirp->nr_page_table_entry_groups = (chirp->memory_size < 0x800000
- ? 1024 /* min allowed */
- : (chirp->memory_size / 4096 / 2));
- chirp->sizeof_htab = chirp->nr_page_table_entry_groups * 64;
- chirp->htab_ra = chirp->memory_size - chirp->sizeof_htab;
-
/* a page for firmware calls */
chirp->sizeof_code = 4096;
- chirp->code_ra = chirp->htab_ra - chirp->sizeof_code;
-
+ chirp->code_offset = 0x4000; /* possible space for interrupt table */
+
/* the stack */
chirp->sizeof_stack = 32 * 1024;
- chirp->stack_ra = chirp->code_ra - chirp->sizeof_stack;
-
- /* the firmware's home */
- chirp->real_mode = 0;
- /* const unsigned_word real_base = stack_ra; */
- /* const unsigned real_size = memory_size - real_base; */
- chirp->virt_base = CHIRP_START_ADDRESS;
- /* const unsigned virt_size = real_size;*/
-
- /* the virtual addresses */
- chirp->htab_va = chirp->code_va + chirp->sizeof_code;
- chirp->stack_va = chirp->virt_base;
- chirp->code_va = chirp->stack_va + chirp->sizeof_stack;
+ chirp->stack_offset = chirp->code_offset + chirp->sizeof_code;
+
+ /* the hash table */
+ if (!note.desc.real_mode) {
+ chirp->nr_page_table_entry_groups = (chirp->memory_size < 0x800000
+ ? 1024 /* min allowed */
+ : (chirp->memory_size / 4096 / 2));
+ chirp->sizeof_htab = chirp->nr_page_table_entry_groups * 64;
+ }
+ chirp->htab_offset = chirp->stack_offset + chirp->sizeof_stack;
+
+ /* the actual amount of space needed */
+ chirp->real_size = chirp->htab_offset + chirp->sizeof_htab;
+
+
+ /* now go through and see if it fits in what is available */
+
+
+ /* resolve real-mode? */
+ if (note.found == note_correct)
+ chirp->real_mode = note.desc.real_mode;
+ else if (tree_find_property(root, "/options/real-mode?") != NULL)
+ chirp->real_mode = tree_find_boolean_property(root, "/options/real-mode?");
+ else
+ chirp->real_mode = 0;
+ if (tree_find_property(root, "/options/real-mode?") != NULL) {
+ if (!chirp->real_mode
+ != !tree_find_boolean_property(root, "/options/real-mode?"))
+ error("chirp: /options/real-mode? conflicts with note section\n");
+ }
+ else
+ tree_parse(root, "/options/real-mode? %s",
+ chirp->real_mode ? "true" : "false");
+
+ /* resolve real-base */
+ if (note.found == note_correct
+ && note.desc.real_base != (signed32)-1)
+ chirp->real_base = note.desc.real_base;
+ else if (tree_find_property(root, "/options/real-base") != NULL)
+ chirp->real_base = tree_find_integer_property(root, "/options/real-base");
+ else
+ chirp->real_base = chirp->memory_size - chirp->real_size;
+ if (tree_find_property(root, "/options/real-base") != NULL) {
+ if (chirp->real_base != tree_find_integer_property(root, "/options/real-base"))
+ error("chirp: /options/real-base conflicts with note section\n");
+ }
+ else
+ tree_parse(root, "/options/real-base 0x%lx",
+ (unsigned long)chirp->real_base);
+
+ /* resolve real-size */
+ if (note.found == note_correct
+ && note.desc.real_size != (signed32)-1
+ && note.desc.real_size != 0
+ && chirp->real_size > note.desc.real_size)
+ error("chirp: insufficient physical memory for firmware\n");
+ if (tree_find_property(root, "/options/real-size") != NULL) {
+ if (chirp->real_size > tree_find_integer_property(root, "/options/real-size"))
+ error("chirp: /options/real-size conflicts with note section\n");
+ }
+ else
+ tree_parse(root, "/options/real-size 0x%lx",
+ (unsigned long)chirp->real_size);
+
+ /* resolve virt-base */
+ if (chirp->real_mode)
+ chirp->virt_base = chirp->real_base;
+ else if (note.found == note_correct && note.desc.virt_base != -1)
+ chirp->virt_base = note.desc.virt_base;
+ else if (tree_find_property(root, "/options/virt-base") != NULL)
+ chirp->virt_base = tree_find_integer_property(root, "/options/virt-base");
+ else
+ chirp->virt_base = CHIRP_START_ADDRESS;
+ if (tree_find_property(root, "/options/virt-base") != NULL) {
+ unsigned_word virt_base = tree_find_integer_property(root, "/options/virt-base");
+ if (virt_base != -1 && chirp->virt_base != virt_base)
+ error("chirp: /options/virt-base conflicts with note section\n");
+ }
+ else
+ tree_parse(root, "/options/virt-base 0x%lx",
+ chirp->real_mode ? -1 : (unsigned long)chirp->virt_base);
+
+ /* resolve virt-size */
+ chirp->virt_size = chirp->real_size;
+ if (note.found == note_correct
+ && note.desc.virt_size != (signed32)-1
+ && note.desc.virt_size != 0
+ && !chirp->real_mode
+ && chirp->virt_size > note.desc.virt_size)
+ error("chirp: insufficent virtual memory for firmware\n");
+ if (tree_find_property(root, "/options/virt-size") != NULL) {
+ if (chirp->virt_size > tree_find_integer_property(root, "/options/virt-size"))
+ error("chirp: /options/virt-size conflicts with note section\n");
+ }
+ else
+ tree_parse(root, "/options/virt-size 0x%lx",
+ chirp->real_mode ? -1 : (unsigned long)chirp->virt_size);
+
+ /* resolve load-base */
+ if (note.found == note_correct
+ && note.desc.load_base != (signed32)-1)
+ chirp->load_base = note.desc.load_base;
+ else if (tree_find_property(root, "/options/load-base") != NULL)
+ chirp->load_base = tree_find_integer_property(root, "/options/load-base");
+ else
+ chirp->load_base = CHIRP_LOAD_BASE;
+ if (tree_find_property(root, "/options/load-base") != NULL) {
+ if (chirp->load_base != tree_find_integer_property(root, "/options/load-base"))
+ error("chirp: /options/load-base conflicts with note section\n");
+ }
+ else
+ tree_parse(root, "/options/load-base 0x%lx",
+ (unsigned long)chirp->load_base);
+
+ /* now adjust the preliminary firmware addresses to final values */
+ chirp->code_ra = chirp->code_offset + chirp->real_base;
+ chirp->stack_ra = chirp->stack_offset + chirp->real_base;
+ chirp->htab_ra = chirp->htab_offset + chirp->real_base;
+
+ /* the virtual addresses. In real mode these are real addresses. */
+
+ chirp->code_va = chirp->code_offset + chirp->virt_base;
+ chirp->stack_va = chirp->stack_offset + chirp->virt_base;
+ chirp->htab_va = chirp->htab_offset + chirp->virt_base;
chirp->code_client_va = chirp->code_va;
chirp->code_client_ra = chirp->code_ra;
@@ -1376,131 +1737,171 @@ emul_chirp_create(device *root,
chirp->code_loop_va = chirp->code_callback_va + 16;
chirp->code_loop_ra = chirp->code_callback_ra + 16;
-
+
/* initialization */
- device_tree_add_parsed(root, "/openprom/init");
- device_tree_add_parsed(root, "/openprom/init/register");
- device_tree_add_parsed(root, "/openprom/init/register/0.pc 0x%lx",
- (unsigned long)bfd_get_start_address(image));
- device_tree_add_parsed(root, "/openprom/init/register/pc 0x%lx",
- (unsigned long)chirp->code_loop_va);
- device_tree_add_parsed(root, "/openprom/init/register/sp 0x%lx",
- (unsigned long)(chirp->stack_va + chirp->sizeof_stack - 16));
- device_tree_add_parsed(root, "/openprom/init/register/msr 0x%x",
- (msr_machine_check_enable
- | (chirp->real_mode
- ? 0
- : (msr_instruction_relocate
- | msr_data_relocate))
- | (chirp->little_endian
- ? (msr_little_endian_mode
- | msr_interrupt_little_endian_mode)
- : 0)
- | (chirp->floating_point_available
- ? msr_floating_point_available
- : 0)
- | (chirp->interrupt_prefix
- ? msr_interrupt_prefix
- : 0)
- ));
- device_tree_add_parsed(root, "/openprom/init/register/sdr1 0x%lx",
- (unsigned long)(chirp->htab_ra
- | MASK32(16, 22)
- | ((chirp->sizeof_htab - 1) >> 16)));
- /* FIXME */
- device_tree_add_parsed(root, "/openprom/init/register/sr8 0x%x",
- 0x00fffff8);
- device_tree_add_parsed(root, "/openprom/init/register/sr9 0x%x",
- 0x00fffff9);
-
-
- /* init the code callback along with a loop for the unused cpu's */
- device_tree_add_parsed(root, "/openprom/init/register/r5 0x%lx",
- (unsigned long)chirp->code_client_va);
-
+
+ tree_parse(root, "/openprom/init");
+ tree_parse(root, "/openprom/init/register");
+ tree_parse(root, "/openprom/init/register/0.pc 0x%lx",
+ (unsigned long)bfd_get_start_address(image));
+ tree_parse(root, "/openprom/init/register/pc 0x%lx",
+ (unsigned long)chirp->code_loop_va);
+ tree_parse(root, "/openprom/init/register/msr 0x%x",
+ (msr_machine_check_enable
+ | (chirp->real_mode
+ ? 0
+ : (msr_instruction_relocate
+ | msr_data_relocate))
+ | (chirp->little_endian
+ ? (msr_little_endian_mode
+ | msr_interrupt_little_endian_mode)
+ : 0)
+ | (chirp->floating_point_available
+ ? msr_floating_point_available
+ : 0)
+ | (chirp->interrupt_prefix
+ ? msr_interrupt_prefix
+ : 0)
+ ));
+ tree_parse(root, "/openprom/init/register/sdr1 0x%lx",
+ (unsigned long)(chirp->htab_ra
+ | MASK32(16, 22)
+ | ((chirp->sizeof_htab - 1) >> 16)));
+ /* make certain that the segment registers map straight through */
+ for (i = 0; i < 16; i++) {
+ tree_parse(root, "/openprom/init/register/sr%d 0x%lx",
+ i, (unsigned long)i);
+ }
+
+ /* establish an initial state for all processors */
+
+
+ /* the client interface address */
+ tree_parse(root, "/openprom/init/register/r5 0x%lx",
+ (unsigned long)chirp->code_client_va);
+ /* a stack */
+ tree_parse(root, "/openprom/init/register/sp 0x%lx",
+ (unsigned long)(chirp->stack_va + chirp->sizeof_stack - 16));
+ /* in chrp mode any arguments end up being concatinated */
+ tree_parse(root, "/openprom/init/stack/stack-type chirp");
+
+
/* client interface - emul-call followed by return instruction */
-
- node = device_tree_add_parsed(root, "/openprom/init/data@0x%lx",
- (unsigned long)chirp->code_client_ra);
- device_tree_add_parsed(node, "./real-address 0x%lx",
- (unsigned long)chirp->code_client_ra);
- device_tree_add_parsed(node, "./data 0x%lx",
- (unsigned long)emul_call_instruction);
-
- node = device_tree_add_parsed(root, "/openprom/init/data@0x%lx",
- (unsigned long)(chirp->code_client_ra + 4));
- device_tree_add_parsed(node, "./real-address 0x%lx",
- (unsigned long)(chirp->code_client_ra + 4));
- device_tree_add_parsed(node, "./data 0x%lx",
- (unsigned long)emul_blr_instruction);
-
- /* return address for client callbacks - an emul-call instruction */
-
- node = device_tree_add_parsed(root, "/openprom/init/data@0x%lx",
- (unsigned long)chirp->code_callback_ra);
- device_tree_add_parsed(node, "./real-address 0x%lx",
- (unsigned long)chirp->code_callback_ra);
- device_tree_add_parsed(node, "./data 0x%lx",
- (unsigned long)emul_call_instruction);
-
+
+
+ node = tree_parse(root, "/openprom/init/data@0x%lx",
+ (unsigned long)chirp->code_client_ra);
+ tree_parse(node, "./psim,description \"client-interface instruction");
+ tree_parse(node, "./real-address 0x%lx",
+ (unsigned long)chirp->code_client_ra);
+ tree_parse(node, "./data 0x%lx",
+ (unsigned long)emul_call_instruction);
+
+ node = tree_parse(root, "/openprom/init/data@0x%lx",
+ (unsigned long)(chirp->code_client_ra + 4));
+ tree_parse(node, "./psim,description \"client-interface return instruction");
+ tree_parse(node, "./real-address 0x%lx",
+ (unsigned long)(chirp->code_client_ra + 4));
+ tree_parse(node, "./data 0x%lx",
+ (unsigned long)emul_blr_instruction);
+
+
+ /* return address for client callbacks - an emul-call instruction
+ that is again followed by a return instruction */
+
+
+ node = tree_parse(root, "/openprom/init/data@0x%lx",
+ (unsigned long)chirp->code_callback_ra);
+ tree_parse(node, "./psim,description \"client-callback instruction");
+ tree_parse(node, "./real-address 0x%lx",
+ (unsigned long)chirp->code_callback_ra);
+ tree_parse(node, "./data 0x%lx",
+ (unsigned long)emul_call_instruction);
+
+ node = tree_parse(root, "/openprom/init/data@0x%lx",
+ (unsigned long)(chirp->code_callback_ra + 4));
+ tree_parse(node, "./psim,description \"client-callback return instruction");
+ tree_parse(node, "./real-address 0x%lx",
+ (unsigned long)(chirp->code_callback_ra + 4));
+ tree_parse(node, "./data 0x%lx",
+ (unsigned long)emul_blr_instruction);
+
/* loop to keep other processors busy */
-
- node = device_tree_add_parsed(root, "/openprom/init/data@0x%lx",
- (unsigned long)chirp->code_loop_ra);
- device_tree_add_parsed(node, "./real-address 0x%lx",
- (unsigned long)chirp->code_loop_ra);
- device_tree_add_parsed(node, "./data 0x%lx",
- (unsigned long)emul_loop_instruction);
-
- /* hash table and vm */
- node = device_tree_add_parsed(root, "/openprom/init/htab@0x%lx",
- (unsigned long)chirp->htab_ra);
- device_tree_add_parsed(node, "./real-address 0x%lx",
- (unsigned long)chirp->htab_ra);
- device_tree_add_parsed(node, "./nr-bytes 0x%lx",
- (unsigned long)chirp->sizeof_htab);
-
- node = device_tree_add_parsed(root, "/openprom/init/htab/pte@0x%lx",
- (unsigned long)chirp->stack_ra);
- device_tree_add_parsed(node, "./virtual-address 0x%lx",
- (unsigned long)chirp->stack_va);
- device_tree_add_parsed(node, "./real-address 0x%lx",
- (unsigned long)chirp->stack_ra);
- device_tree_add_parsed(node, "./nr-bytes 0x%lx",
- (unsigned long)chirp->sizeof_stack);
- device_tree_add_parsed(node, "./wimg %d", 0x7);
- device_tree_add_parsed(node, "./pp %d", 0x2);
-
- node = device_tree_add_parsed(root, "/openprom/init/htab/pte@0x%lx",
- (unsigned long)chirp->code_ra);
- device_tree_add_parsed(node, "./virtual-address 0x%lx",
- (unsigned long)chirp->code_va);
- device_tree_add_parsed(node, "./real-address 0x%lx",
- (unsigned long)chirp->code_ra);
- device_tree_add_parsed(node, "./nr-bytes 0x%lx",
- (unsigned long)chirp->sizeof_code);
- device_tree_add_parsed(node, "./wimg %d", 0x7);
- device_tree_add_parsed(node, "./pp %d", 0x2);
-
- node = device_tree_add_parsed(root, "/openprom/init/htab/pte@0x%lx",
- (unsigned long)chirp->htab_ra);
- device_tree_add_parsed(node, "./virtual-address 0x%lx",
- (unsigned long)chirp->htab_va);
- device_tree_add_parsed(node, "./real-address 0x%lx",
- (unsigned long)chirp->htab_ra);
- device_tree_add_parsed(node, "./nr-bytes 0x%lx",
- (unsigned long)chirp->sizeof_stack);
- device_tree_add_parsed(node, "./wimg %d", 0x7);
- device_tree_add_parsed(node, "./pp %d", 0x2);
-
- node = device_tree_add_parsed(root, "/openprom/init/htab/pte@0x%lx",
- (unsigned long)0x4000 /*magic*/);
- device_tree_add_parsed(node, "./real-address 0x%lx",
- (unsigned long)0x4000);
- device_tree_add_parsed(node, "./file-name \"%s", bfd_get_filename(image));
- device_tree_add_parsed(node, "./wimg %d", 0x7);
- device_tree_add_parsed(node, "./pp %d", 0x2);
-
+
+ node = tree_parse(root, "/openprom/init/data@0x%lx",
+ (unsigned long)chirp->code_loop_ra);
+ tree_parse(node, "./psim,description \"processor busy loop");
+ tree_parse(node, "./real-address 0x%lx",
+ (unsigned long)chirp->code_loop_ra);
+ tree_parse(node, "./data 0x%lx",
+ (unsigned long)emul_loop_instruction);
+
+ /* hash table */
+
+ /* create a hash table */
+
+ if (!chirp->real_mode) {
+ node = tree_parse(root, "/openprom/init/htab@0x%lx",
+ (unsigned long)chirp->htab_ra);
+ tree_parse(node, "./claim 0");
+ tree_parse(node, "./real-address 0x%lx",
+ (unsigned long)chirp->htab_ra);
+ tree_parse(node, "./nr-bytes 0x%lx",
+ (unsigned long)chirp->sizeof_htab);
+ }
+
+ /* map in the stack */
+
+ if (!chirp->real_mode) {
+ node = tree_parse(root, "/openprom/init/htab/pte@0x%lx",
+ (unsigned long)chirp->stack_ra);
+ tree_parse(node, "./psim,description \"map in the stack");
+ tree_parse(node, "./claim 1");
+ tree_parse(node, "./virtual-address 0x%lx",
+ (unsigned long)chirp->stack_va);
+ tree_parse(node, "./real-address 0x%lx",
+ (unsigned long)chirp->stack_ra);
+ tree_parse(node, "./nr-bytes 0x%lx",
+ (unsigned long)chirp->sizeof_stack);
+ tree_parse(node, "./wimg %d", 0x7);
+ tree_parse(node, "./pp %d", 0x2);
+ }
+
+ /* map in the chrp openboot callback code */
+
+ if (!chirp->real_mode) {
+ node = tree_parse(root, "/openprom/init/htab/pte@0x%lx",
+ (unsigned long)chirp->code_ra);
+ tree_parse(node, "./psim,description \"map in chrp openboot callback code");
+ tree_parse(node, "./claim 1");
+ tree_parse(node, "./virtual-address 0x%lx",
+ (unsigned long)chirp->code_va);
+ tree_parse(node, "./real-address 0x%lx",
+ (unsigned long)chirp->code_ra);
+ tree_parse(node, "./nr-bytes 0x%lx",
+ (unsigned long)chirp->sizeof_code);
+ tree_parse(node, "./wimg %d", 0x7);
+ tree_parse(node, "./pp %d", 0x2);
+ }
+
+ /* map in the program to run */
+
+ if (chirp->real_mode) {
+ node = tree_parse(node, "/openprom/init/load-binary");
+ tree_parse(node, "./psim,description \"load the binary");
+ tree_parse(node, "./file-name %s", bfd_get_filename(image));
+ tree_parse(node, "./claim 1");
+ }
+ else {
+ node = tree_parse(root, "/openprom/init/htab/pte@0x%lx",
+ (unsigned long)chirp->load_base);
+ tree_parse(node, "./psim,description \"load & map the binary");
+ tree_parse(node, "./claim 1");
+ tree_parse(node, "./file-name \"%s", bfd_get_filename(image));
+ tree_parse(node, "./wimg %d", 0x7);
+ tree_parse(node, "./pp %d", 0x2);
+ }
+
return chirp;
}
@@ -1522,9 +1923,9 @@ emul_chirp_instruction_call(cpu *processor,
char service_buf[32];
char *service_name;
chirp_services *service;
-
+
switch (emul_data->state) {
-
+
case serving:
/* we are waiting on an OpenBoot request from the client program
via the client interface */
@@ -1537,27 +1938,51 @@ emul_chirp_instruction_call(cpu *processor,
processor, cia);
service_name = emul_read_string(service_buf, service_name_addr,
sizeof(service_buf), processor, cia);
- emul_data->n_args = emul_read_word(emul_data->arguments + sizeof(unsigned32),
+ emul_data->n_args = emul_read_word(emul_data->arguments + sizeof(unsigned_cell),
processor, cia);
- emul_data->n_returns = emul_read_word(emul_data->arguments + 2 * sizeof(unsigned32),
+ emul_data->n_returns = emul_read_word(emul_data->arguments + 2 * sizeof(unsigned_cell),
processor, cia);
+ /* verify what was passed */
+ if (service_name_addr == 0
+ || service_name == NULL) {
+ error("OpenFirmware called with invalid (NULL) service name from 0x%lx with args 0x%lx\n",
+ (unsigned long)emul_data->return_address,
+ (unsigned long)emul_data->arguments);
+ }
+ if (emul_data->n_args > 6) { /* See iee1275 requirements on nr returns */
+ error("OpenFirmware service %s called from 0x%lx with args 0x%lx, too many args (%d)\n",
+ (unsigned long)emul_data->return_address,
+ (unsigned long)emul_data->arguments,
+ emul_data->n_returns);
+ }
+ if (emul_data->n_returns > 6) {
+ error("OpenFirmware service %s called from 0x%lx with args 0x%lx, with too many returns (%d)\n",
+ (unsigned long)emul_data->return_address,
+ (unsigned long)emul_data->arguments,
+ emul_data->n_args);
+ }
+ /* look it up */
TRACE(trace_os_emul, ("%s called from 0x%lx with args 0x%lx\n",
service_name,
(unsigned long)emul_data->return_address,
(unsigned long)emul_data->arguments));
- /* look it up */
service = services;
while (service->name != NULL && strcmp(service->name, service_name) != 0)
service++;
+ /* found or not? */
if (service->name == NULL) {
error("OpenBoot service `%s' not found\n", service_name);
TRACE(trace_os_emul, ("%s not found\n", service_name));
- cpu_registers(processor)->gpr[3] = 0;
- cpu_restart(processor, emul_data->return_address);
+ cpu_registers(processor)->gpr[3] = -1;
+ }
+ else {
+ emul_data->service = service;
+ /* call upon it */
+ result = service->handler(emul_data, processor, cia);
+ if (result != 0)
+ TRACE(trace_os_emul, ("%s aborted with %ld\n", service_name, (long)result));
+ cpu_registers(processor)->gpr[3] = result;
}
- emul_data->service = service;
- /* call upon it */
- result = service->handler(emul_data, processor, cia);
break;
default:
diff --git a/gnu/dist/sim/ppc/emul_chirp.h b/gnu/dist/sim/ppc/emul_chirp.h
index 8695641a7a4..2265f5c3ee4 100644
--- a/gnu/dist/sim/ppc/emul_chirp.h
+++ b/gnu/dist/sim/ppc/emul_chirp.h
@@ -1,6 +1,6 @@
/* This file is part of the program psim.
- Copyright (C) 1994-1996, Andrew Cagney <cagney@highland.com.au>
+ 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
diff --git a/gnu/dist/sim/ppc/emul_generic.c b/gnu/dist/sim/ppc/emul_generic.c
index 5a9a3a22bd4..a417034f933 100644
--- a/gnu/dist/sim/ppc/emul_generic.c
+++ b/gnu/dist/sim/ppc/emul_generic.c
@@ -1,6 +1,6 @@
/* This file is part of the program psim.
- Copyright (C) 1994-1996, Andrew Cagney <cagney@highland.com.au>
+ 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
@@ -11,11 +11,11 @@
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.
-
+
*/
@@ -38,7 +38,7 @@ emul_syscall_enter(emul_syscall *emul,
{
printf_filtered("%d:0x%lx:%s(",
cpu_nr(processor) + 1,
- (long)cia,
+ (long)cia,
emul->syscall_descriptor[call].name);
}
@@ -123,11 +123,32 @@ emul_write_status(cpu *processor,
int status,
int errno)
{
- cpu_registers(processor)->gpr[3] = status;
- if (status < 0)
- cpu_registers(processor)->gpr[0] = errno;
- else
- cpu_registers(processor)->gpr[0] = 0;
+ if (status == -1 && errno != 0) {
+ cpu_registers(processor)->gpr[3] = errno;
+ CR_SET(0, cr_i_summary_overflow);
+ }
+ else {
+ cpu_registers(processor)->gpr[3] = status;
+ CR_SET(0, 0);
+ }
+}
+
+
+INLINE_EMUL_GENERIC void
+emul_write2_status(cpu *processor,
+ int status1,
+ int status2,
+ int errno)
+{
+ if (status1 == -1 && errno != 0) {
+ cpu_registers(processor)->gpr[3] = errno;
+ CR_SET(0, cr_i_summary_overflow);
+ }
+ else {
+ cpu_registers(processor)->gpr[3] = status1;
+ cpu_registers(processor)->gpr[4] = status2;
+ CR_SET(0, 0);
+ }
}
@@ -201,8 +222,13 @@ emul_do_system_call(os_emul_data *emul_data,
error("do_call() os_emul call %d out-of-range\n", call);
handler = emul->syscall_descriptor[call].handler;
- if (handler == NULL)
- error("do_call() unimplemented call %d\n", call);
+ if (handler == NULL) {
+ if (emul->syscall_descriptor[call].name) {
+ error("do_call() unimplemented call %s\n", emul->syscall_descriptor[call].name);
+ } else {
+ error("do_call() unimplemented call %d\n", call);
+ }
+ }
if (WITH_TRACE && ppc_trace[trace_os_emul])
emul_syscall_enter(emul, call, arg0, processor, cia);
@@ -234,8 +260,8 @@ emul_add_tree_options(device *tree,
int little_endian = 0;
/* sort out little endian */
- if (device_find_property(tree, "/options/little-endian?"))
- little_endian = device_find_boolean_property(tree, "/options/little-endian?");
+ if (tree_find_property(tree, "/options/little-endian?"))
+ little_endian = tree_find_boolean_property(tree, "/options/little-endian?");
else {
#ifdef bfd_little_endian /* new bfd */
little_endian = (image != NULL && bfd_little_endian(image));
@@ -243,53 +269,76 @@ emul_add_tree_options(device *tree,
little_endian = (image != NULL &&
!image->xvec->byteorder_big_p);
#endif
- device_tree_add_parsed(tree, "/options/little-endian? %s",
- little_endian ? "true" : "false");
+ tree_parse(tree, "/options/little-endian? %s",
+ little_endian ? "true" : "false");
}
/* misc other stuff */
- device_tree_add_parsed(tree, "/openprom/options/oea-memory-size 0x%x",
- OEA_MEMORY_SIZE);
- device_tree_add_parsed(tree, "/openprom/options/oea-interrupt-prefix %d",
- oea_interrupt_prefix);
- device_tree_add_parsed(tree, "/openprom/options/smp 1");
- device_tree_add_parsed(tree, "/openprom/options/env %s", env);
- device_tree_add_parsed(tree, "/openprom/options/os-emul %s", emul);
- device_tree_add_parsed(tree, "/openprom/options/strict-alignment? %s",
- (WITH_ALIGNMENT == STRICT_ALIGNMENT || little_endian)
- ? "true" : "false");
- device_tree_add_parsed(tree, "/openprom/options/floating-point? %s",
- WITH_FLOATING_POINT ? "true" : "false");
- device_tree_add_parsed(tree, "/openprom/options/model \"%s",
- model_name[WITH_DEFAULT_MODEL]);
- device_tree_add_parsed(tree, "/openprom/options/model-issue %d",
- MODEL_ISSUE_IGNORE);
+ tree_parse(tree, "/openprom/options/oea-memory-size 0x%x",
+ OEA_MEMORY_SIZE);
+ tree_parse(tree, "/openprom/options/oea-interrupt-prefix %d",
+ oea_interrupt_prefix);
+ tree_parse(tree, "/openprom/options/smp 1");
+ tree_parse(tree, "/openprom/options/env %s", env);
+ tree_parse(tree, "/openprom/options/os-emul %s", emul);
+ tree_parse(tree, "/openprom/options/strict-alignment? %s",
+ ((WITH_ALIGNMENT == 0 && little_endian)
+ || (WITH_ALIGNMENT == STRICT_ALIGNMENT))
+ ? "true" : "false");
+ tree_parse(tree, "/openprom/options/floating-point? %s",
+ WITH_FLOATING_POINT ? "true" : "false");
+ tree_parse(tree, "/openprom/options/use-stdio? %s",
+ ((WITH_STDIO == DO_USE_STDIO
+ || WITH_STDIO == 0)
+ ? "true" : "false"));
+ tree_parse(tree, "/openprom/options/model \"%s",
+ model_name[WITH_DEFAULT_MODEL]);
+ tree_parse(tree, "/openprom/options/model-issue %d",
+ MODEL_ISSUE_IGNORE);
+
+ /* useful options */
}
INLINE_EMUL_GENERIC void
emul_add_tree_hardware(device *root)
{
+ int i;
+ int nr_cpus = tree_find_integer_property(root, "/openprom/options/smp");
+
+ /* sanity check the number of processors */
+ if (nr_cpus > MAX_NR_PROCESSORS)
+ error("Specified number of processors (%d) exceeds the number configured (%d).\n",
+ nr_cpus, MAX_NR_PROCESSORS);
+
+ /* set the number of address cells (1 or 2) */
+ tree_parse(root, "#address-cells %d", WITH_TARGET_WORD_BITSIZE / 32);
+
/* add some memory */
- if (device_tree_find_device(root, "/memory") == NULL) {
+ if (tree_find_device(root, "/memory") == NULL) {
unsigned_word memory_size =
- device_find_integer_property(root, "/openprom/options/oea-memory-size");
- device_tree_add_parsed(root, "/memory@0/reg { 0x0 0x%lx",
- (unsigned long)memory_size);
- /* what about allocated? */
+ tree_find_integer_property(root, "/openprom/options/oea-memory-size");
+ const unsigned_word avail_start = 0x3000;
+ tree_parse(root, "/memory@0/reg 0x0 0x%lx",
+ (unsigned long)memory_size);
+ /* reserve the first 0x3000 for the PowerPC interrupt table */
+ tree_parse(root, "/memory@0/available 0x%lx 0x%lx",
+ (unsigned long)avail_start,
+ (unsigned long)memory_size - avail_start);
+ }
+
+ /* our processors */
+ for (i = 0; i < nr_cpus; i++) {
+ tree_parse(root, "/cpus/cpu@%d/cpu-nr %d", i, i);
}
- /* an eeprom */
- device_tree_add_parsed(root, "/openprom/eeprom@0xfff00000/reg { 0xfff00000 0x3000");
- /* the IO bus */
- device_tree_add_parsed(root, "/iobus@0x80000000/reg { 0x80000000 0x400000");
- device_tree_add_parsed(root, "/iobus/console@0x000000/reg { 0x000000 16");
- device_tree_add_parsed(root, "/iobus/halt@0x100000/reg { 0x100000 4");
- device_tree_add_parsed(root, "/iobus/icu@0x200000/reg { 0x200000 8");
- device_tree_add_parsed(root, "/iobus/icu > 0 0 /iobus/icu");
- device_tree_add_parsed(root, "/iobus/icu > 1 1 /iobus/icu");
+
+ /* the debugging pal - hide it in the openprom and don't attach it
+ to any bus */
+ tree_parse(root, "/openprom/pal");
+
/* chosen etc */
- device_tree_add_parsed(root, "/chosen/stdin */iobus/console");
- device_tree_add_parsed(root, "/chosen/stdout !/chosen/stdin");
- device_tree_add_parsed(root, "/chosen/memory */memory");
+ tree_parse(root, "/chosen/stdin */openprom/pal");
+ tree_parse(root, "/chosen/stdout !/chosen/stdin");
+ tree_parse(root, "/chosen/memory */memory");
}
-#endif /* _SYSTEM_C_ */
+#endif /* _EMUL_GENERIC_C_ */
diff --git a/gnu/dist/sim/ppc/emul_generic.h b/gnu/dist/sim/ppc/emul_generic.h
index ae0c8274abd..a86026e9b9d 100644
--- a/gnu/dist/sim/ppc/emul_generic.h
+++ b/gnu/dist/sim/ppc/emul_generic.h
@@ -26,6 +26,8 @@
#include "idecode.h"
#include "os_emul.h"
+#include "tree.h"
+
#include "bfd.h"
#ifndef INLINE_EMUL_GENERIC
@@ -123,6 +125,12 @@ INLINE_EMUL_GENERIC void emul_write_status
int status,
int errno);
+INLINE_EMUL_GENERIC void emul_write2_status
+(cpu *processor,
+ int status1,
+ int status2,
+ int errno);
+
INLINE_EMUL_GENERIC char *emul_read_string
(char *dest,
unsigned_word addr,
diff --git a/gnu/dist/sim/ppc/emul_netbsd.c b/gnu/dist/sim/ppc/emul_netbsd.c
index 3db42ffe54d..7a48292382f 100644
--- a/gnu/dist/sim/ppc/emul_netbsd.c
+++ b/gnu/dist/sim/ppc/emul_netbsd.c
@@ -1,6 +1,6 @@
/* This file is part of the program psim.
- Copyright (C) 1994-1996, Andrew Cagney <cagney@highland.com.au>
+ 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
@@ -11,11 +11,11 @@
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.
-
+
*/
@@ -57,7 +57,9 @@
int getrusage();
#endif
+#if HAVE_SYS_IOCTL_H
#include <sys/ioctl.h>
+#endif
#if HAVE_SYS_MOUNT_H
#include <sys/mount.h>
@@ -81,6 +83,7 @@ int getrusage();
#endif
#ifdef HAVE_UNISTD_H
+#undef MAXPATHLEN /* sys/param.h might define this also */
#include <unistd.h>
#endif
@@ -93,6 +96,11 @@ int getrusage();
#include <sys/syscall.h> /* FIXME - should not be including this one */
#include <sys/sysctl.h>
extern int getdirentries(int fd, char *buf, int nbytes, long *basep);
+#else
+
+/* If this is not netbsd, don't allow fstatfs or getdirentries at this time */
+#undef HAVE_FSTATFS
+#undef HAVE_GETDIRENTRIES
#endif
#if (BSD < 199306) /* here BSD as just a bug */
@@ -117,6 +125,15 @@ extern int errno;
#endif
+/* EMULATION
+
+ NetBSD - Emulation of user programs for NetBSD/PPC
+
+ DESCRIPTION
+
+ */
+
+
/* NetBSD's idea of what is needed to implement emulations */
struct _os_emul_data {
@@ -138,7 +155,6 @@ write_stat(unsigned_word addr,
H2T(buf.st_nlink);
H2T(buf.st_uid);
H2T(buf.st_gid);
- H2T(buf.st_rdev);
H2T(buf.st_size);
H2T(buf.st_atime);
/* H2T(buf.st_spare1); */
@@ -146,8 +162,15 @@ write_stat(unsigned_word addr,
/* H2T(buf.st_spare2); */
H2T(buf.st_ctime);
/* H2T(buf.st_spare3); */
+#ifdef AC_STRUCT_ST_RDEV
+ H2T(buf.st_rdev);
+#endif
+#ifdef AC_STRUCT_ST_BLKSIZE
H2T(buf.st_blksize);
+#endif
+#ifdef AC_STRUCT_ST_BLOCKS
H2T(buf.st_blocks);
+#endif
#if WITH_NetBSD_HOST
H2T(buf.st_flags);
H2T(buf.st_gen);
@@ -155,8 +178,8 @@ write_stat(unsigned_word addr,
emul_write_buffer(&buf, addr, sizeof(buf), processor, cia);
}
-
-#if NetBSD
+
+#ifdef HAVE_FSTATFS
STATIC_INLINE_EMUL_NETBSD void
write_statfs(unsigned_word addr,
struct statfs buf,
@@ -183,7 +206,7 @@ write_statfs(unsigned_word addr,
}
#endif
-
+
STATIC_INLINE_EMUL_NETBSD void
write_timeval(unsigned_word addr,
struct timeval t,
@@ -195,7 +218,7 @@ write_timeval(unsigned_word addr,
emul_write_buffer(&t, addr, sizeof(t), processor, cia);
}
-
+
STATIC_INLINE_EMUL_NETBSD void
write_timezone(unsigned_word addr,
struct timezone tz,
@@ -207,8 +230,8 @@ write_timezone(unsigned_word addr,
emul_write_buffer(&tz, addr, sizeof(tz), processor, cia);
}
-
-#if WITH_NetBSD_HOST
+
+#ifdef HAVE_GETDIRENTRIES
STATIC_INLINE_EMUL_NETBSD void
write_direntries(unsigned_word addr,
char *buf,
@@ -264,7 +287,7 @@ write_rusage(unsigned_word addr,
emul_write_buffer(&rusage, addr, sizeof(rusage), processor, cia);
}
#endif
-
+
static void
do_exit(os_emul_data *emul,
unsigned call,
@@ -294,16 +317,16 @@ do_read(os_emul_data *emul,
int nbytes = cpu_registers(processor)->gpr[arg0+2];
int status;
SYS(read);
-
+
if (WITH_TRACE && ppc_trace[trace_os_emul])
printf_filtered ("%d, 0x%lx, %d", d, (long)buf, nbytes);
/* get a tempoary bufer */
scratch_buffer = zalloc(nbytes);
-
+
/* check if buffer exists by reading it */
emul_read_buffer(scratch_buffer, buf, nbytes, processor, cia);
-
+
/* read */
#if 0
if (d == 0) {
@@ -313,16 +336,11 @@ do_read(os_emul_data *emul,
}
#endif
status = read (d, scratch_buffer, nbytes);
-
- if (status == -1) {
- cpu_registers(processor)->gpr[0] = errno;
- } else {
- cpu_registers(processor)->gpr[3] = status;
-
- if (status > 0)
- emul_write_buffer(scratch_buffer, buf, status, processor, cia);
- }
-
+
+ emul_write_status(processor, status, errno);
+ if (status > 0)
+ emul_write_buffer(scratch_buffer, buf, status, processor, cia);
+
zfree(scratch_buffer);
}
@@ -335,30 +353,22 @@ do_write(os_emul_data *emul,
unsigned_word cia)
{
void *scratch_buffer = NULL;
- int nr_moved;
int d = (int)cpu_registers(processor)->gpr[arg0];
unsigned_word buf = cpu_registers(processor)->gpr[arg0+1];
int nbytes = cpu_registers(processor)->gpr[arg0+2];
int status;
SYS(write);
-
+
if (WITH_TRACE && ppc_trace[trace_os_emul])
printf_filtered ("%d, 0x%lx, %d", d, (long)buf, nbytes);
/* get a tempoary bufer */
scratch_buffer = zalloc(nbytes); /* FIXME - nbytes == 0 */
-
+
/* copy in */
- nr_moved = vm_data_map_read_buffer(cpu_data_map(processor),
- scratch_buffer,
- buf,
- nbytes);
- if (nr_moved != nbytes) {
- /* FIXME - should handle better */
- error("system_call()write copy failed (nr_moved=%d != nbytes=%d)\n",
- nr_moved, nbytes);
- }
-
+ emul_read_buffer(scratch_buffer, buf, nbytes,
+ processor, cia);
+
/* write */
status = write(d, scratch_buffer, nbytes);
emul_write_status(processor, status, errno);
@@ -414,21 +424,25 @@ do_break(os_emul_data *emul,
unsigned_word cia)
{
/* just pass this onto the `vm' device */
- psim *system = cpu_system(processor);
+ unsigned_word new_break = cpu_registers(processor)->gpr[arg0];
+ int status;
if (WITH_TRACE && ppc_trace[trace_os_emul])
printf_filtered ("0x%lx", (long)cpu_registers(processor)->gpr[arg0]);
SYS(break);
- device_ioctl(emul->vm,
- system,
- processor,
- cia,
- 0, /*ioctl*/
- NULL); /*ioctl-data*/
+ status = device_ioctl(emul->vm,
+ processor,
+ cia,
+ device_ioctl_break,
+ new_break); /*ioctl-data*/
+ emul_write_status(processor, 0, status);
}
+#ifndef HAVE_GETPID
+#define do_getpid 0
+#else
static void
do_getpid(os_emul_data *emul,
unsigned call,
@@ -437,10 +451,13 @@ do_getpid(os_emul_data *emul,
unsigned_word cia)
{
SYS(getpid);
- cpu_registers(processor)->gpr[3] = (int)getpid();
+ emul_write_status(processor, (int)getpid(), 0);
}
+#endif
-
+#ifndef HAVE_GETUID
+#define do_getuid 0
+#else
static void
do_getuid(os_emul_data *emul,
unsigned call,
@@ -449,10 +466,13 @@ do_getuid(os_emul_data *emul,
unsigned_word cia)
{
SYS(getuid);
- cpu_registers(processor)->gpr[3] = (int)getuid();
+ emul_write_status(processor, (int)getuid(), 0);
}
+#endif
-
+#ifndef HAVE_GETEUID
+#define do_geteuid 0
+#else
static void
do_geteuid(os_emul_data *emul,
unsigned call,
@@ -461,10 +481,13 @@ do_geteuid(os_emul_data *emul,
unsigned_word cia)
{
SYS(geteuid);
- cpu_registers(processor)->gpr[3] = (int)geteuid();
+ emul_write_status(processor, (int)geteuid(), 0);
}
+#endif
-
+#ifndef HAVE_KILL
+#define do_kill 0
+#else
static void
do_kill(os_emul_data *emul,
unsigned call,
@@ -483,8 +506,11 @@ do_kill(os_emul_data *emul,
(long)cia);
cpu_halt(processor, cia, was_signalled, sig);
}
+#endif
-
+#ifndef HAVE_DUP
+#define do_dup 0
+#else
static void
do_dup(os_emul_data *emul,
unsigned call,
@@ -494,15 +520,19 @@ do_dup(os_emul_data *emul,
{
int oldd = cpu_registers(processor)->gpr[arg0];
int status = dup(oldd);
+ int err = errno;
if (WITH_TRACE && ppc_trace[trace_os_emul])
printf_filtered ("%d", oldd);
SYS(dup);
- emul_write_status(processor, status, errno);
+ emul_write_status(processor, status, err);
}
+#endif
-
+#ifndef HAVE_GETEGID
+#define do_getegid 0
+#else
static void
do_getegid(os_emul_data *emul,
unsigned call,
@@ -511,10 +541,13 @@ do_getegid(os_emul_data *emul,
unsigned_word cia)
{
SYS(getegid);
- cpu_registers(processor)->gpr[3] = (int)getegid();
+ emul_write_status(processor, (int)getegid(), 0);
}
+#endif
-
+#ifndef HAVE_GETGID
+#define do_getgid 0
+#else
static void
do_getgid(os_emul_data *emul,
unsigned call,
@@ -523,10 +556,13 @@ do_getgid(os_emul_data *emul,
unsigned_word cia)
{
SYS(getgid);
- cpu_registers(processor)->gpr[3] = (int)getgid();
+ emul_write_status(processor, (int)getgid(), 0);
}
+#endif
-
+#ifndef HAVE_SIGPROCMASK
+#define do_sigprocmask 0
+#else
static void
do_sigprocmask(os_emul_data *emul,
unsigned call,
@@ -542,11 +578,14 @@ do_sigprocmask(os_emul_data *emul,
if (WITH_TRACE && ppc_trace[trace_os_emul])
printf_filtered ("%ld, 0x%ld, 0x%ld", (long)how, (long)set, (long)oset);
- cpu_registers(processor)->gpr[3] = 0;
+ emul_write_status(processor, 0, 0);
cpu_registers(processor)->gpr[4] = set;
}
+#endif
-
+#ifndef HAVE_IOCTL
+#define do_ioctl 0
+#else
static void
do_ioctl(os_emul_data *emul,
unsigned call,
@@ -576,8 +615,11 @@ do_ioctl(os_emul_data *emul,
if (WITH_TRACE && ppc_trace[trace_os_emul])
printf_filtered ("%d, 0x%x, 0x%lx", d, request, (long)argp_addr);
}
+#endif
-
+#ifndef HAVE_UMASK
+#define do_umask 0
+#else
static void
do_umask(os_emul_data *emul,
unsigned call,
@@ -591,10 +633,13 @@ do_umask(os_emul_data *emul,
printf_filtered ("0%o", mask);
SYS(umask);
- cpu_registers(processor)->gpr[3] = umask(mask);
+ emul_write_status(processor, umask(mask), 0);
}
+#endif
-
+#ifndef HAVE_DUP2
+#define do_dup2 0
+#else
static void
do_dup2(os_emul_data *emul,
unsigned call,
@@ -605,15 +650,19 @@ do_dup2(os_emul_data *emul,
int oldd = cpu_registers(processor)->gpr[arg0];
int newd = cpu_registers(processor)->gpr[arg0+1];
int status = dup2(oldd, newd);
+ int err = errno;
if (WITH_TRACE && ppc_trace[trace_os_emul])
printf_filtered ("%d, %d", oldd, newd);
SYS(dup2);
- emul_write_status(processor, status, errno);
+ emul_write_status(processor, status, err);
}
+#endif
-
+#ifndef HAVE_FCNTL
+#define do_fcntl 0
+#else
static void
do_fcntl(os_emul_data *emul,
unsigned call,
@@ -633,8 +682,11 @@ do_fcntl(os_emul_data *emul,
status = fcntl(fd, cmd, arg);
emul_write_status(processor, status, errno);
}
+#endif
-
+#ifndef HAVE_GETTIMEOFDAY
+#define do_gettimeofday 0
+#else
static void
do_gettimeofday(os_emul_data *emul,
unsigned call,
@@ -648,12 +700,13 @@ do_gettimeofday(os_emul_data *emul,
struct timezone tz;
int status = gettimeofday((t_addr != 0 ? &t : NULL),
(tz_addr != 0 ? &tz : NULL));
+ int err = errno;
if (WITH_TRACE && ppc_trace[trace_os_emul])
printf_filtered ("0x%lx, 0x%lx", (long)t_addr, (long)tz_addr);
SYS(gettimeofday);
- emul_write_status(processor, status, errno);
+ emul_write_status(processor, status, err);
if (status == 0) {
if (t_addr != 0)
write_timeval(t_addr, t, processor, cia);
@@ -661,7 +714,7 @@ do_gettimeofday(os_emul_data *emul,
write_timezone(tz_addr, tz, processor, cia);
}
}
-
+#endif
#ifndef HAVE_GETRUSAGE
#define do_getrusage 0
@@ -677,12 +730,13 @@ do_getrusage(os_emul_data *emul,
unsigned_word rusage_addr = cpu_registers(processor)->gpr[arg0+1];
struct rusage rusage;
int status = getrusage(who, (rusage_addr != 0 ? &rusage : NULL));
+ int err = errno;
if (WITH_TRACE && ppc_trace[trace_os_emul])
printf_filtered ("%d, 0x%lx", who, (long)rusage_addr);
SYS(getrusage);
- emul_write_status(processor, status, errno);
+ emul_write_status(processor, status, err);
if (status == 0) {
if (rusage_addr != 0)
write_rusage(rusage_addr, rusage, processor, cia);
@@ -691,7 +745,7 @@ do_getrusage(os_emul_data *emul,
#endif
-#if !WITH_NetBSD_HOST
+#ifndef HAVE_FSTATFS
#define do_fstatfs 0
#else
static void
@@ -719,7 +773,9 @@ do_fstatfs(os_emul_data *emul,
}
#endif
-
+#ifndef HAVE_STAT
+#define do_stat 0
+#else
static void
do_stat(os_emul_data *emul,
unsigned call,
@@ -739,8 +795,11 @@ do_stat(os_emul_data *emul,
if (status == 0)
write_stat(stat_buf_addr, buf, processor, cia);
}
+#endif
-
+#ifndef HAVE_FSTAT
+#define do_fstat 0
+#else
static void
do_fstat(os_emul_data *emul,
unsigned call,
@@ -755,8 +814,11 @@ do_fstat(os_emul_data *emul,
emul_write_status(processor, fstat(fd, &buf), errno);
write_stat(stat_buf_addr, buf, processor, cia);
}
+#endif
-
+#ifndef HAVE_LSTAT
+#define do_lstat 0
+#else
static void
do_lstat(os_emul_data *emul,
unsigned call,
@@ -773,9 +835,9 @@ do_lstat(os_emul_data *emul,
emul_write_status(processor, stat(path, &buf), errno);
write_stat(stat_buf_addr, buf, processor, cia);
}
+#endif
-
-#if !WITH_NetBSD_HOST
+#ifndef HAVE_GETDIRENTRIES
#define do_getdirentries 0
#else
static void
@@ -828,7 +890,9 @@ do___syscall(os_emul_data *emul,
cia);
}
-
+#ifndef HAVE_LSEEK
+#define do_lseek 0
+#else
static void
do_lseek(os_emul_data *emul,
unsigned call,
@@ -845,10 +909,11 @@ do_lseek(os_emul_data *emul,
if (status == -1)
emul_write_status(processor, -1, errno);
else {
+ emul_write_status(processor, 0, 0); /* success */
emul_write_gpr64(processor, 3, status);
}
}
-
+#endif
static void
do___sysctl(os_emul_data *emul,
@@ -875,7 +940,7 @@ do___sysctl(os_emul_data *emul,
processor,
cia);
name += sizeof(mib);
-
+
/* see what to do with it ... */
switch ((int)mib) {
case 6/*CTL_HW*/:
@@ -914,7 +979,7 @@ do___sysctl(os_emul_data *emul,
error("sysctl() name[0]=%d unknown\n", (int)mib);
break;
}
- cpu_registers(processor)->gpr[3] = 0;
+ emul_write_status(processor, 0, 0); /* always succeed */
}
@@ -922,7 +987,7 @@ do___sysctl(os_emul_data *emul,
static emul_syscall_descriptor netbsd_descriptors[] = {
/* 0 */ { 0, "syscall" },
/* 1 */ { do_exit, "exit" },
- /* 2 */ { 0, "fork" },
+ /* 2 */ { 0, "fork" },
/* 3 */ { do_read, "read" },
/* 4 */ { do_write, "write" },
/* 5 */ { do_open, "open" },
@@ -1126,7 +1191,7 @@ static emul_syscall_descriptor netbsd_descriptors[] = {
/* 203 */ { 0, "mlock" },
/* 204 */ { 0, "munlock" },
};
-
+
static char *(netbsd_error_names[]) = {
/* 0 */ "ESUCCESS",
/* 1 */ "EPERM",
@@ -1300,26 +1365,25 @@ emul_netbsd_create(device *root,
0 /*oea-interrupt-prefix*/);
/* virtual memory - handles growth of stack/heap */
- vm = device_tree_add_parsed(root, "/openprom/vm@0x%lx",
- (unsigned long)(top_of_stack - stack_size));
- device_tree_add_parsed(vm, "./stack-base 0x%lx",
- (unsigned long)(top_of_stack - stack_size));
- device_tree_add_parsed(vm, "./nr-bytes 0x%x", stack_size);
+ vm = tree_parse(root, "/openprom/vm");
+ tree_parse(vm, "./stack-base 0x%lx",
+ (unsigned long)(top_of_stack - stack_size));
+ tree_parse(vm, "./nr-bytes 0x%x", stack_size);
- device_tree_add_parsed(root, "/openprom/vm/map-binary/file-name %s",
- bfd_get_filename(image));
+ tree_parse(root, "/openprom/vm/map-binary/file-name %s",
+ bfd_get_filename(image));
/* finish the init */
- device_tree_add_parsed(root, "/openprom/init/register/pc 0x%lx",
- (unsigned long)bfd_get_start_address(image));
- device_tree_add_parsed(root, "/openprom/init/register/sp 0x%lx",
- (unsigned long)top_of_stack);
- device_tree_add_parsed(root, "/openprom/init/register/msr 0x%x",
- (device_find_boolean_property(root, "/options/little-endian?")
- ? msr_little_endian_mode
- : 0));
- device_tree_add_parsed(root, "/openprom/init/stack/stack-type %s",
- (elf_binary ? "elf" : "xcoff"));
+ tree_parse(root, "/openprom/init/register/pc 0x%lx",
+ (unsigned long)bfd_get_start_address(image));
+ tree_parse(root, "/openprom/init/register/sp 0x%lx",
+ (unsigned long)top_of_stack);
+ tree_parse(root, "/openprom/init/register/msr 0x%x",
+ (tree_find_boolean_property(root, "/options/little-endian?")
+ ? msr_little_endian_mode
+ : 0));
+ tree_parse(root, "/openprom/init/stack/stack-type %s",
+ (elf_binary ? "ppc-elf" : "ppc-xcoff"));
/* finally our emulation data */
bsd_data = ZALLOC(os_emul_data);
diff --git a/gnu/dist/sim/ppc/emul_unix.c b/gnu/dist/sim/ppc/emul_unix.c
new file mode 100644
index 00000000000..5221fa0d609
--- /dev/null
+++ b/gnu/dist/sim/ppc/emul_unix.c
@@ -0,0 +1,2809 @@
+/* This file is part of the program psim.
+
+ Copyright (C) 1996-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 _EMUL_UNIX_C_
+#define _EMUL_UNIX_C_
+
+
+/* Note: this module is called via a table. There is no benefit in
+ making it inline */
+
+#include "emul_generic.h"
+#include "emul_unix.h"
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/stat.h>
+#else
+#undef HAVE_STAT
+#undef HAVE_LSTAT
+#undef HAVE_FSTAT
+#endif
+
+#include <stdio.h>
+#include <signal.h>
+#include <errno.h>
+
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+
+#ifndef HAVE_TERMIOS_STRUCTURE
+#undef HAVE_SYS_TERMIOS_H
+#undef HAVE_TCGETATTR
+#else
+#ifndef HAVE_SYS_TERMIOS_H
+#undef HAVE_TERMIOS_STRUCTURE
+#endif
+#endif
+
+#ifdef HAVE_TERMIOS_STRUCTURE
+#include <sys/termios.h>
+
+/* If we have TERMIOS, use that for the termio structure, since some systems
+ don't like including both sys/termios.h and sys/termio.h at the same
+ time. */
+#undef HAVE_TERMIO_STRUCTURE
+#undef TCGETA
+#undef termio
+#define termio termios
+#endif
+
+#ifndef HAVE_TERMIO_STRUCTURE
+#undef HAVE_SYS_TERMIO_H
+#else
+#ifndef HAVE_SYS_TERMIO_H
+#undef HAVE_TERMIO_STRUCTURE
+#endif
+#endif
+
+#ifdef HAVE_TERMIO_STRUCTURE
+#include <sys/termio.h>
+#endif
+
+#ifdef HAVE_GETRUSAGE
+#ifndef HAVE_SYS_RESOURCE_H
+#undef HAVE_GETRUSAGE
+#endif
+#endif
+
+#ifdef HAVE_GETRUSAGE
+#include <sys/resource.h>
+int getrusage();
+#endif
+
+#if HAVE_SYS_MOUNT_H
+#include <sys/mount.h>
+#endif
+
+#if HAVE_DIRENT_H
+# include <dirent.h>
+# define NAMLEN(dirent) strlen((dirent)->d_name)
+#else
+# define dirent direct
+# define NAMLEN(dirent) (dirent)->d_namlen
+# if HAVE_SYS_NDIR_H
+# include <sys/ndir.h>
+# endif
+# if HAVE_SYS_DIR_H
+# include <sys/dir.h>
+# endif
+# if HAVE_NDIR_H
+# include <ndir.h>
+# endif
+#endif
+
+#ifdef HAVE_UNISTD_H
+#undef MAXPATHLEN /* sys/param.h might define this also */
+#include <unistd.h>
+#endif
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#if defined(BSD) && !defined(errno) && (BSD < 199306) /* here BSD as just a bug */
+extern int errno;
+#endif
+
+#ifndef STATIC_INLINE_EMUL_UNIX
+#define STATIC_INLINE_EMUL_UNIX STATIC_INLINE
+#endif
+
+#ifndef PATH_MAX
+#define PATH_MAX 1024
+#endif
+
+#ifndef EINVAL
+#define EINVAL -1
+#endif
+
+/* UNIX's idea of what is needed to implement emulations */
+
+struct _os_emul_data {
+ device *vm;
+ emul_syscall *syscalls;
+};
+
+
+/* Emulation of simple UNIX system calls that are common on all systems. */
+
+/* Structures that are common agmonst the UNIX varients */
+struct unix_timeval {
+ signed32 tv_sec; /* seconds */
+ signed32 tv_usec; /* microseconds */
+};
+
+struct unix_timezone {
+ signed32 tz_minuteswest; /* minutes west of Greenwich */
+ signed32 tz_dsttime; /* type of dst correction */
+};
+
+#define UNIX_RUSAGE_SELF 0
+#define UNIX_RUSAGE_CHILDREN (-1)
+#define UNIX_RUSAGE_BOTH (-2) /* sys_wait4() uses this */
+
+struct unix_rusage {
+ struct unix_timeval ru_utime; /* user time used */
+ struct unix_timeval ru_stime; /* system time used */
+ signed32 ru_maxrss; /* maximum resident set size */
+ signed32 ru_ixrss; /* integral shared memory size */
+ signed32 ru_idrss; /* integral unshared data size */
+ signed32 ru_isrss; /* integral unshared stack size */
+ signed32 ru_minflt; /* any page faults not requiring I/O */
+ signed32 ru_majflt; /* any page faults requiring I/O */
+ signed32 ru_nswap; /* swaps */
+ signed32 ru_inblock; /* block input operations */
+ signed32 ru_oublock; /* block output operations */
+ signed32 ru_msgsnd; /* messages sent */
+ signed32 ru_msgrcv; /* messages received */
+ signed32 ru_nsignals; /* signals received */
+ signed32 ru_nvcsw; /* voluntary context switches */
+ signed32 ru_nivcsw; /* involuntary " */
+};
+
+
+static void
+do_unix_exit(os_emul_data *emul,
+ unsigned call,
+ const int arg0,
+ cpu *processor,
+ unsigned_word cia)
+{
+ int status = (int)cpu_registers(processor)->gpr[arg0];
+ if (WITH_TRACE && ppc_trace[trace_os_emul])
+ printf_filtered ("%d)\n", status);
+
+ cpu_halt(processor, cia, was_exited, status);
+}
+
+
+static void
+do_unix_read(os_emul_data *emul,
+ unsigned call,
+ const int arg0,
+ cpu *processor,
+ unsigned_word cia)
+{
+ void *scratch_buffer;
+ int d = (int)cpu_registers(processor)->gpr[arg0];
+ unsigned_word buf = cpu_registers(processor)->gpr[arg0+1];
+ int nbytes = cpu_registers(processor)->gpr[arg0+2];
+ int status;
+
+ if (WITH_TRACE && ppc_trace[trace_os_emul])
+ printf_filtered ("%d, 0x%lx, %d", d, (long)buf, nbytes);
+
+ /* get a tempoary bufer */
+ scratch_buffer = zalloc(nbytes);
+
+ /* check if buffer exists by reading it */
+ emul_read_buffer(scratch_buffer, buf, nbytes, processor, cia);
+
+ /* read */
+ status = read (d, scratch_buffer, nbytes);
+
+ emul_write_status(processor, status, errno);
+ if (status > 0)
+ emul_write_buffer(scratch_buffer, buf, status, processor, cia);
+
+ zfree(scratch_buffer);
+}
+
+
+static void
+do_unix_write(os_emul_data *emul,
+ unsigned call,
+ const int arg0,
+ cpu *processor,
+ unsigned_word cia)
+{
+ void *scratch_buffer = NULL;
+ int d = (int)cpu_registers(processor)->gpr[arg0];
+ unsigned_word buf = cpu_registers(processor)->gpr[arg0+1];
+ int nbytes = cpu_registers(processor)->gpr[arg0+2];
+ int status;
+
+ if (WITH_TRACE && ppc_trace[trace_os_emul])
+ printf_filtered ("%d, 0x%lx, %d", d, (long)buf, nbytes);
+
+ /* get a tempoary bufer */
+ scratch_buffer = zalloc(nbytes); /* FIXME - nbytes == 0 */
+
+ /* copy in */
+ emul_read_buffer(scratch_buffer, buf, nbytes,
+ processor, cia);
+
+ /* write */
+ status = write(d, scratch_buffer, nbytes);
+ emul_write_status(processor, status, errno);
+ zfree(scratch_buffer);
+
+ flush_stdoutput();
+}
+
+
+static void
+do_unix_open(os_emul_data *emul,
+ unsigned call,
+ const int arg0,
+ cpu *processor,
+ unsigned_word cia)
+{
+ unsigned_word path_addr = cpu_registers(processor)->gpr[arg0];
+ char path_buf[PATH_MAX];
+ char *path = emul_read_string(path_buf, path_addr, PATH_MAX, processor, cia);
+ int flags = (int)cpu_registers(processor)->gpr[arg0+1];
+ int mode = (int)cpu_registers(processor)->gpr[arg0+2];
+ int status;
+
+ if (WITH_TRACE && ppc_trace[trace_os_emul])
+ printf_filtered ("0x%lx [%s], 0x%x, 0x%x", (long)path_addr, path, flags, mode);
+
+ status = open(path, flags, mode);
+ emul_write_status(processor, status, errno);
+}
+
+
+static void
+do_unix_close(os_emul_data *emul,
+ unsigned call,
+ const int arg0,
+ cpu *processor,
+ unsigned_word cia)
+{
+ int d = (int)cpu_registers(processor)->gpr[arg0];
+ int status;
+
+ if (WITH_TRACE && ppc_trace[trace_os_emul])
+ printf_filtered ("%d", d);
+
+ status = close(d);
+ emul_write_status(processor, status, errno);
+}
+
+
+static void
+do_unix_break(os_emul_data *emul,
+ unsigned call,
+ const int arg0,
+ cpu *processor,
+ unsigned_word cia)
+{
+ /* just pass this onto the `vm' device */
+ unsigned_word new_break = cpu_registers(processor)->gpr[arg0];
+ int status;
+
+ if (WITH_TRACE && ppc_trace[trace_os_emul])
+ printf_filtered ("0x%lx", (long)cpu_registers(processor)->gpr[arg0]);
+
+ status = device_ioctl(emul->vm,
+ processor,
+ cia,
+ device_ioctl_break,
+ new_break); /*ioctl-data*/
+
+ emul_write_status(processor, 0, status);
+}
+
+#ifndef HAVE_ACCESS
+#define do_unix_access 0
+#else
+static void
+do_unix_access(os_emul_data *emul,
+ unsigned call,
+ const int arg0,
+ cpu *processor,
+ unsigned_word cia)
+{
+ unsigned_word path_addr = cpu_registers(processor)->gpr[arg0];
+ char path_buf[PATH_MAX];
+ char *path = emul_read_string(path_buf, path_addr, PATH_MAX, processor, cia);
+ int mode = (int)cpu_registers(processor)->gpr[arg0+1];
+ int status;
+
+ if (WITH_TRACE && ppc_trace[trace_os_emul])
+ printf_filtered ("0x%lx [%s], 0x%x [0%o]", (long)path_addr, path, mode, mode);
+
+ status = access(path, mode);
+ emul_write_status(processor, status, errno);
+}
+#endif
+
+#ifndef HAVE_GETPID
+#define do_unix_getpid 0
+#else
+static void
+do_unix_getpid(os_emul_data *emul,
+ unsigned call,
+ const int arg0,
+ cpu *processor,
+ unsigned_word cia)
+{
+ pid_t status = getpid();
+ emul_write_status(processor, (int)status, errno);
+}
+#endif
+
+#ifndef HAVE_GETPPID
+#define do_unix_getppid 0
+#else
+static void
+do_unix_getppid(os_emul_data *emul,
+ unsigned call,
+ const int arg0,
+ cpu *processor,
+ unsigned_word cia)
+{
+ pid_t status = getppid();
+ emul_write_status(processor, (int)status, errno);
+}
+#endif
+
+#if !defined(HAVE_GETPID) || !defined(HAVE_GETPPID)
+#define do_unix_getpid2 0
+#else
+static void
+do_unix_getpid2(os_emul_data *emul,
+ unsigned call,
+ const int arg0,
+ cpu *processor,
+ unsigned_word cia)
+{
+ int pid = (int)getpid();
+ int ppid = (int)getppid();
+ emul_write2_status(processor, pid, ppid, errno);
+}
+#endif
+
+#if !defined(HAVE_GETUID) || !defined(HAVE_GETEUID)
+#define do_unix_getuid2 0
+#else
+static void
+do_unix_getuid2(os_emul_data *emul,
+ unsigned call,
+ const int arg0,
+ cpu *processor,
+ unsigned_word cia)
+{
+ uid_t uid = getuid();
+ uid_t euid = geteuid();
+ emul_write2_status(processor, (int)uid, (int)euid, errno);
+}
+#endif
+
+#ifndef HAVE_GETUID
+#define do_unix_getuid 0
+#else
+static void
+do_unix_getuid(os_emul_data *emul,
+ unsigned call,
+ const int arg0,
+ cpu *processor,
+ unsigned_word cia)
+{
+ uid_t status = getuid();
+ emul_write_status(processor, (int)status, errno);
+}
+#endif
+
+#ifndef HAVE_GETEUID
+#define do_unix_geteuid 0
+#else
+static void
+do_unix_geteuid(os_emul_data *emul,
+ unsigned call,
+ const int arg0,
+ cpu *processor,
+ unsigned_word cia)
+{
+ uid_t status = geteuid();
+ emul_write_status(processor, (int)status, errno);
+}
+#endif
+
+#if 0
+#ifndef HAVE_KILL
+#define do_unix_kill 0
+#else
+static void
+do_unix_kill(os_emul_data *emul,
+ unsigned call,
+ const int arg0,
+ cpu *processor,
+ unsigned_word cia)
+{
+ pid_t pid = cpu_registers(processor)->gpr[arg0];
+ int sig = cpu_registers(processor)->gpr[arg0+1];
+
+ if (WITH_TRACE && ppc_trace[trace_os_emul])
+ printf_filtered ("%d, %d", (int)pid, sig);
+
+ printf_filtered("SYS_kill at 0x%lx - more to this than just being killed\n",
+ (long)cia);
+
+ cpu_halt(processor, cia, was_signalled, sig);
+}
+#endif
+#endif
+
+#ifndef HAVE_DUP
+#define do_unix_dup 0
+#else
+static void
+do_unix_dup(os_emul_data *emul,
+ unsigned call,
+ const int arg0,
+ cpu *processor,
+ unsigned_word cia)
+{
+ int oldd = cpu_registers(processor)->gpr[arg0];
+ int status = dup(oldd);
+ int err = errno;
+
+ if (WITH_TRACE && ppc_trace[trace_os_emul])
+ printf_filtered ("%d", oldd);
+
+ emul_write_status(processor, status, err);
+}
+#endif
+
+#ifndef HAVE_DUP2
+#define do_unix_dup2 0
+#else
+static void
+do_unix_dup2(os_emul_data *emul,
+ unsigned call,
+ const int arg0,
+ cpu *processor,
+ unsigned_word cia)
+{
+ int oldd = cpu_registers(processor)->gpr[arg0];
+ int newd = cpu_registers(processor)->gpr[arg0+1];
+ int status = dup2(oldd, newd);
+ int err = errno;
+
+ if (WITH_TRACE && ppc_trace[trace_os_emul])
+ printf_filtered ("%d, %d", oldd, newd);
+
+ emul_write_status(processor, status, err);
+}
+#endif
+
+#ifndef HAVE_LSEEK
+#define do_unix_lseek 0
+#else
+static void
+do_unix_lseek(os_emul_data *emul,
+ unsigned call,
+ const int arg0,
+ cpu *processor,
+ unsigned_word cia)
+{
+ int fildes = (int)cpu_registers(processor)->gpr[arg0];
+ off_t offset = (off_t)cpu_registers(processor)->gpr[arg0+1];
+ int whence = (int)cpu_registers(processor)->gpr[arg0+2];
+ off_t status;
+
+ if (WITH_TRACE && ppc_trace[trace_os_emul])
+ printf_filtered ("%d %ld %d", fildes, (long)offset, whence);
+
+ status = lseek(fildes, offset, whence);
+ emul_write_status(processor, (int)status, errno);
+}
+#endif
+
+
+#if !defined(HAVE_GETGID) || !defined(HAVE_GETEGID)
+#define do_unix_getgid2 0
+#else
+static void
+do_unix_getgid2(os_emul_data *emul,
+ unsigned call,
+ const int arg0,
+ cpu *processor,
+ unsigned_word cia)
+{
+ gid_t gid = getgid();
+ gid_t egid = getegid();
+ emul_write2_status(processor, (int)gid, (int)egid, errno);
+}
+#endif
+
+#ifndef HAVE_GETGID
+#define do_unix_getgid 0
+#else
+static void
+do_unix_getgid(os_emul_data *emul,
+ unsigned call,
+ const int arg0,
+ cpu *processor,
+ unsigned_word cia)
+{
+ gid_t status = getgid();
+ emul_write_status(processor, (int)status, errno);
+}
+#endif
+
+#ifndef HAVE_GETEGID
+#define do_unix_getegid 0
+#else
+static void
+do_unix_getegid(os_emul_data *emul,
+ unsigned call,
+ const int arg0,
+ cpu *processor,
+ unsigned_word cia)
+{
+ gid_t status = getegid();
+ emul_write_status(processor, (int)status, errno);
+}
+#endif
+
+#ifndef HAVE_UMASK
+#define do_unix_umask 0
+#else
+static void
+do_unix_umask(os_emul_data *emul,
+ unsigned call,
+ const int arg0,
+ cpu *processor,
+ unsigned_word cia)
+{
+ mode_t mask = (mode_t)cpu_registers(processor)->gpr[arg0];
+ int status = umask(mask);
+
+ if (WITH_TRACE && ppc_trace[trace_os_emul])
+ printf_filtered ("0%o", (unsigned int)mask);
+
+ emul_write_status(processor, status, errno);
+}
+#endif
+
+#ifndef HAVE_CHDIR
+#define do_unix_chdir 0
+#else
+static void
+do_unix_chdir(os_emul_data *emul,
+ unsigned call,
+ const int arg0,
+ cpu *processor,
+ unsigned_word cia)
+{
+ unsigned_word path_addr = cpu_registers(processor)->gpr[arg0];
+ char path_buf[PATH_MAX];
+ char *path = emul_read_string(path_buf, path_addr, PATH_MAX, processor, cia);
+ int status;
+
+ if (WITH_TRACE && ppc_trace[trace_os_emul])
+ printf_filtered ("0x%lx [%s]", (long)path_addr, path);
+
+ status = chdir(path);
+ emul_write_status(processor, status, errno);
+}
+#endif
+
+#ifndef HAVE_LINK
+#define do_unix_link 0
+#else
+static void
+do_unix_link(os_emul_data *emul,
+ unsigned call,
+ const int arg0,
+ cpu *processor,
+ unsigned_word cia)
+{
+ unsigned_word path1_addr = cpu_registers(processor)->gpr[arg0];
+ char path1_buf[PATH_MAX];
+ char *path1 = emul_read_string(path1_buf, path1_addr, PATH_MAX, processor, cia);
+ unsigned_word path2_addr = cpu_registers(processor)->gpr[arg0+1];
+ char path2_buf[PATH_MAX];
+ char *path2 = emul_read_string(path2_buf, path2_addr, PATH_MAX, processor, cia);
+ int status;
+
+ if (WITH_TRACE && ppc_trace[trace_os_emul])
+ printf_filtered ("0x%lx [%s], 0x%lx [%s]", (long)path1_addr, path1, (long)path2_addr, path2);
+
+ status = link(path1, path2);
+ emul_write_status(processor, status, errno);
+}
+#endif
+
+#ifndef HAVE_SYMLINK
+#define do_unix_symlink 0
+#else
+static void
+do_unix_symlink(os_emul_data *emul,
+ unsigned call,
+ const int arg0,
+ cpu *processor,
+ unsigned_word cia)
+{
+ unsigned_word path1_addr = cpu_registers(processor)->gpr[arg0];
+ char path1_buf[PATH_MAX];
+ char *path1 = emul_read_string(path1_buf, path1_addr, PATH_MAX, processor, cia);
+ unsigned_word path2_addr = cpu_registers(processor)->gpr[arg0+1];
+ char path2_buf[PATH_MAX];
+ char *path2 = emul_read_string(path2_buf, path2_addr, PATH_MAX, processor, cia);
+ int status;
+
+ if (WITH_TRACE && ppc_trace[trace_os_emul])
+ printf_filtered ("0x%lx [%s], 0x%lx [%s]", (long)path1_addr, path1, (long)path2_addr, path2);
+
+ status = symlink(path1, path2);
+ emul_write_status(processor, status, errno);
+}
+#endif
+
+#ifndef HAVE_UNLINK
+#define do_unix_unlink 0
+#else
+static void
+do_unix_unlink(os_emul_data *emul,
+ unsigned call,
+ const int arg0,
+ cpu *processor,
+ unsigned_word cia)
+{
+ unsigned_word path_addr = cpu_registers(processor)->gpr[arg0];
+ char path_buf[PATH_MAX];
+ char *path = emul_read_string(path_buf, path_addr, PATH_MAX, processor, cia);
+ int status;
+
+ if (WITH_TRACE && ppc_trace[trace_os_emul])
+ printf_filtered ("0x%lx [%s]", (long)path_addr, path);
+
+ status = unlink(path);
+ emul_write_status(processor, status, errno);
+}
+#endif
+
+#ifndef HAVE_MKDIR
+#define do_unix_mkdir 0
+#else
+static void
+do_unix_mkdir(os_emul_data *emul,
+ unsigned call,
+ const int arg0,
+ cpu *processor,
+ unsigned_word cia)
+{
+ unsigned_word path_addr = cpu_registers(processor)->gpr[arg0];
+ char path_buf[PATH_MAX];
+ char *path = emul_read_string(path_buf, path_addr, PATH_MAX, processor, cia);
+ int mode = (int)cpu_registers(processor)->gpr[arg0+1];
+ int status;
+
+ if (WITH_TRACE && ppc_trace[trace_os_emul])
+ printf_filtered ("0x%lx [%s], 0%3o", (long)path_addr, path, mode);
+
+ status = mkdir(path, mode);
+ emul_write_status(processor, status, errno);
+}
+#endif
+
+#ifndef HAVE_RMDIR
+#define do_unix_rmdir 0
+#else
+static void
+do_unix_rmdir(os_emul_data *emul,
+ unsigned call,
+ const int arg0,
+ cpu *processor,
+ unsigned_word cia)
+{
+ unsigned_word path_addr = cpu_registers(processor)->gpr[arg0];
+ char path_buf[PATH_MAX];
+ char *path = emul_read_string(path_buf, path_addr, PATH_MAX, processor, cia);
+ int status;
+
+ if (WITH_TRACE && ppc_trace[trace_os_emul])
+ printf_filtered ("0x%lx [%s]", (long)path_addr, path);
+
+ status = rmdir(path);
+ emul_write_status(processor, status, errno);
+}
+#endif
+
+#ifndef HAVE_TIME
+#define do_unix_time 0
+#else
+static void
+do_unix_time(os_emul_data *emul,
+ unsigned call,
+ const int arg0,
+ cpu *processor,
+ unsigned_word cia)
+{
+ unsigned_word tp = cpu_registers(processor)->gpr[arg0];
+ time_t now = time ((time_t *)0);
+ unsigned_word status = H2T_4(now);
+
+ if (WITH_TRACE && ppc_trace[trace_os_emul])
+ printf_filtered ("0x%lx", (long)tp);
+
+ emul_write_status(processor, (int)status, errno);
+
+ if (tp)
+ emul_write_buffer(&status, tp, sizeof(status), processor, cia);
+}
+#endif
+
+#if !defined(HAVE_GETTIMEOFDAY) || !defined(HAVE_SYS_TIME_H)
+#define do_unix_gettimeofday 0
+#else
+static void
+do_unix_gettimeofday(os_emul_data *emul,
+ unsigned call,
+ const int arg0,
+ cpu *processor,
+ unsigned_word cia)
+{
+ unsigned_word tv = cpu_registers(processor)->gpr[arg0];
+ unsigned_word tz = cpu_registers(processor)->gpr[arg0+1];
+ struct unix_timeval target_timeval;
+ struct timeval host_timeval;
+ struct unix_timezone target_timezone;
+ struct timezone host_timezone;
+ int status;
+
+ if (WITH_TRACE && ppc_trace[trace_os_emul])
+ printf_filtered ("0x%lx, 0x%lx", (long)tv, (long)tz);
+
+ /* Just in case the system doesn't set the timezone structure */
+ host_timezone.tz_minuteswest = 0;
+ host_timezone.tz_dsttime = 0;
+
+ status = gettimeofday(&host_timeval, &host_timezone);
+ if (status >= 0) {
+ if (tv) {
+ target_timeval.tv_sec = H2T_4(host_timeval.tv_sec);
+ target_timeval.tv_usec = H2T_4(host_timeval.tv_usec);
+ emul_write_buffer((void *) &target_timeval, tv, sizeof(target_timeval), processor, cia);
+ }
+
+ if (tz) {
+ target_timezone.tz_minuteswest = H2T_4(host_timezone.tz_minuteswest);
+ target_timezone.tz_dsttime = H2T_4(host_timezone.tz_dsttime);
+ emul_write_buffer((void *) &target_timezone, tv, sizeof(target_timezone), processor, cia);
+ }
+ }
+
+ emul_write_status(processor, (int)status, errno);
+}
+#endif
+
+
+#ifndef HAVE_GETRUSAGE
+#define do_unix_getrusage 0
+#else
+static void
+do_unix_getrusage(os_emul_data *emul,
+ unsigned call,
+ const int arg0,
+ cpu *processor,
+ unsigned_word cia)
+{
+ signed_word who = (signed_word)cpu_registers(processor)->gpr[arg0];
+ unsigned_word usage = cpu_registers(processor)->gpr[arg0+1];
+ struct rusage host_rusage, host_rusage2;
+ struct unix_rusage target_rusage;
+ int status;
+
+ if (WITH_TRACE && ppc_trace[trace_os_emul])
+ printf_filtered ("%ld, 0x%lx", (long)who, (long)usage);
+
+ switch (who) {
+ default:
+ status = -1;
+ errno = EINVAL;
+ break;
+
+ case UNIX_RUSAGE_SELF:
+ status = getrusage(RUSAGE_SELF, &host_rusage);
+ break;
+
+ case UNIX_RUSAGE_CHILDREN:
+ status = getrusage(RUSAGE_CHILDREN, &host_rusage);
+ break;
+
+ case UNIX_RUSAGE_BOTH:
+ status = getrusage(RUSAGE_SELF, &host_rusage);
+ if (status >= 0) {
+ status = getrusage(RUSAGE_CHILDREN, &host_rusage2);
+ if (status >= 0) {
+ host_rusage.ru_utime.tv_sec += host_rusage2.ru_utime.tv_sec;
+ host_rusage.ru_utime.tv_usec += host_rusage2.ru_utime.tv_usec;
+ host_rusage.ru_stime.tv_sec += host_rusage2.ru_stime.tv_sec;
+ host_rusage.ru_stime.tv_usec += host_rusage2.ru_stime.tv_usec;
+ host_rusage.ru_maxrss += host_rusage2.ru_maxrss;
+ host_rusage.ru_ixrss += host_rusage2.ru_ixrss;
+ host_rusage.ru_idrss += host_rusage2.ru_idrss;
+ host_rusage.ru_isrss += host_rusage2.ru_isrss;
+ host_rusage.ru_minflt += host_rusage2.ru_minflt;
+ host_rusage.ru_majflt += host_rusage2.ru_majflt;
+ host_rusage.ru_nswap += host_rusage2.ru_nswap;
+ host_rusage.ru_inblock += host_rusage2.ru_inblock;
+ host_rusage.ru_oublock += host_rusage2.ru_oublock;
+ host_rusage.ru_msgsnd += host_rusage2.ru_msgsnd;
+ host_rusage.ru_msgrcv += host_rusage2.ru_msgrcv;
+ host_rusage.ru_nsignals += host_rusage2.ru_nsignals;
+ host_rusage.ru_nvcsw += host_rusage2.ru_nvcsw;
+ host_rusage.ru_nivcsw += host_rusage2.ru_nivcsw;
+ }
+ }
+ }
+
+ if (status >= 0) {
+ target_rusage.ru_utime.tv_sec = H2T_4(host_rusage2.ru_utime.tv_sec);
+ target_rusage.ru_utime.tv_usec = H2T_4(host_rusage2.ru_utime.tv_usec);
+ target_rusage.ru_stime.tv_sec = H2T_4(host_rusage2.ru_stime.tv_sec);
+ target_rusage.ru_stime.tv_usec = H2T_4(host_rusage2.ru_stime.tv_usec);
+ target_rusage.ru_maxrss = H2T_4(host_rusage2.ru_maxrss);
+ target_rusage.ru_ixrss = H2T_4(host_rusage2.ru_ixrss);
+ target_rusage.ru_idrss = H2T_4(host_rusage2.ru_idrss);
+ target_rusage.ru_isrss = H2T_4(host_rusage2.ru_isrss);
+ target_rusage.ru_minflt = H2T_4(host_rusage2.ru_minflt);
+ target_rusage.ru_majflt = H2T_4(host_rusage2.ru_majflt);
+ target_rusage.ru_nswap = H2T_4(host_rusage2.ru_nswap);
+ target_rusage.ru_inblock = H2T_4(host_rusage2.ru_inblock);
+ target_rusage.ru_oublock = H2T_4(host_rusage2.ru_oublock);
+ target_rusage.ru_msgsnd = H2T_4(host_rusage2.ru_msgsnd);
+ target_rusage.ru_msgrcv = H2T_4(host_rusage2.ru_msgrcv);
+ target_rusage.ru_nsignals = H2T_4(host_rusage2.ru_nsignals);
+ target_rusage.ru_nvcsw = H2T_4(host_rusage2.ru_nvcsw);
+ target_rusage.ru_nivcsw = H2T_4(host_rusage2.ru_nivcsw);
+ emul_write_buffer((void *) &target_rusage, usage, sizeof(target_rusage), processor, cia);
+ }
+
+ emul_write_status(processor, status, errno);
+}
+#endif
+
+
+static void
+do_unix_nop(os_emul_data *emul,
+ unsigned call,
+ const int arg0,
+ cpu *processor,
+ unsigned_word cia)
+{
+ if (WITH_TRACE && ppc_trace[trace_os_emul])
+ printf_filtered ("0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx",
+ (long)cpu_registers(processor)->gpr[arg0],
+ (long)cpu_registers(processor)->gpr[arg0+1],
+ (long)cpu_registers(processor)->gpr[arg0+2],
+ (long)cpu_registers(processor)->gpr[arg0+3],
+ (long)cpu_registers(processor)->gpr[arg0+4],
+ (long)cpu_registers(processor)->gpr[arg0+5]);
+
+ emul_write_status(processor, 0, errno);
+}
+
+
+/* Common code for initializing the system call stuff */
+
+static os_emul_data *
+emul_unix_create(device *root,
+ bfd *image,
+ const char *name,
+ emul_syscall *syscall)
+{
+ unsigned_word top_of_stack;
+ unsigned stack_size;
+ int elf_binary;
+ os_emul_data *data;
+ device *vm;
+
+ /* merge any emulation specific entries into the device tree */
+
+ /* establish a few defaults */
+ if (image->xvec->flavour == bfd_target_elf_flavour) {
+ elf_binary = 1;
+ top_of_stack = 0xe0000000;
+ stack_size = 0x00100000;
+ }
+ else {
+ elf_binary = 0;
+ top_of_stack = 0x20000000;
+ stack_size = 0x00100000;
+ }
+
+ /* options */
+ emul_add_tree_options(root, image, name,
+ (WITH_ENVIRONMENT == USER_ENVIRONMENT
+ ? "user" : "virtual"),
+ 0 /*oea-interrupt-prefix*/);
+
+ /* virtual memory - handles growth of stack/heap */
+ vm = tree_parse(root, "/openprom/vm@0x%lx",
+ (unsigned long)(top_of_stack - stack_size));
+ tree_parse(vm, "./stack-base 0x%lx",
+ (unsigned long)(top_of_stack - stack_size));
+ tree_parse(vm, "./nr-bytes 0x%x", stack_size);
+
+ tree_parse(root, "/openprom/vm/map-binary/file-name %s",
+ bfd_get_filename(image));
+
+ /* finish the init */
+ tree_parse(root, "/openprom/init/register/pc 0x%lx",
+ (unsigned long)bfd_get_start_address(image));
+ tree_parse(root, "/openprom/init/register/sp 0x%lx",
+ (unsigned long)top_of_stack);
+ tree_parse(root, "/openprom/init/register/msr 0x%x",
+ msr_little_endian_mode);
+ tree_parse(root, "/openprom/init/stack/stack-type %s",
+ (elf_binary ? "ppc-elf" : "ppc-xcoff"));
+
+ /* finally our emulation data */
+ data = ZALLOC(os_emul_data);
+ data->vm = vm;
+ data->syscalls = syscall;
+ return data;
+}
+
+
+/* EMULATION
+
+ Solaris - Emulation of user programs for Solaris/PPC
+
+ DESCRIPTION
+
+ */
+
+
+/* Solaris specific implementation */
+
+typedef signed32 solaris_uid_t;
+typedef signed32 solaris_gid_t;
+typedef signed32 solaris_off_t;
+typedef signed32 solaris_pid_t;
+typedef signed32 solaris_time_t;
+typedef unsigned32 solaris_dev_t;
+typedef unsigned32 solaris_ino_t;
+typedef unsigned32 solaris_mode_t;
+typedef unsigned32 solaris_nlink_t;
+
+#ifdef HAVE_SYS_STAT_H
+#define SOLARIS_ST_FSTYPSZ 16 /* array size for file system type name */
+
+struct solaris_stat {
+ solaris_dev_t st_dev;
+ signed32 st_pad1[3]; /* reserved for network id */
+ solaris_ino_t st_ino;
+ solaris_mode_t st_mode;
+ solaris_nlink_t st_nlink;
+ solaris_uid_t st_uid;
+ solaris_gid_t st_gid;
+ solaris_dev_t st_rdev;
+ signed32 st_pad2[2];
+ solaris_off_t st_size;
+ signed32 st_pad3; /* future off_t expansion */
+ struct unix_timeval st_atim;
+ struct unix_timeval st_mtim;
+ struct unix_timeval st_ctim;
+ signed32 st_blksize;
+ signed32 st_blocks;
+ char st_fstype[SOLARIS_ST_FSTYPSZ];
+ signed32 st_pad4[8]; /* expansion area */
+};
+
+/* Convert from host stat structure to solaris stat structure */
+STATIC_INLINE_EMUL_UNIX void
+convert_to_solaris_stat(unsigned_word addr,
+ struct stat *host,
+ cpu *processor,
+ unsigned_word cia)
+{
+ struct solaris_stat target;
+ int i;
+
+ target.st_dev = H2T_4(host->st_dev);
+ target.st_ino = H2T_4(host->st_ino);
+ target.st_mode = H2T_4(host->st_mode);
+ target.st_nlink = H2T_4(host->st_nlink);
+ target.st_uid = H2T_4(host->st_uid);
+ target.st_gid = H2T_4(host->st_gid);
+ target.st_size = H2T_4(host->st_size);
+
+#ifdef HAVE_ST_RDEV
+ target.st_rdev = H2T_4(host->st_rdev);
+#else
+ target.st_rdev = 0;
+#endif
+
+#ifdef HAVE_ST_BLKSIZE
+ target.st_blksize = H2T_4(host->st_blksize);
+#else
+ target.st_blksize = 0;
+#endif
+
+#ifdef HAVE_ST_BLOCKS
+ target.st_blocks = H2T_4(host->st_blocks);
+#else
+ target.st_blocks = 0;
+#endif
+
+ target.st_atim.tv_sec = H2T_4(host->st_atime);
+ target.st_atim.tv_usec = 0;
+
+ target.st_ctim.tv_sec = H2T_4(host->st_ctime);
+ target.st_ctim.tv_usec = 0;
+
+ target.st_mtim.tv_sec = H2T_4(host->st_mtime);
+ target.st_mtim.tv_usec = 0;
+
+ for (i = 0; i < sizeof (target.st_pad1) / sizeof (target.st_pad1[0]); i++)
+ target.st_pad1[i] = 0;
+
+ for (i = 0; i < sizeof (target.st_pad2) / sizeof (target.st_pad2[0]); i++)
+ target.st_pad2[i] = 0;
+
+ target.st_pad3 = 0;
+
+ for (i = 0; i < sizeof (target.st_pad4) / sizeof (target.st_pad4[0]); i++)
+ target.st_pad4[i] = 0;
+
+ /* For now, just punt and always say it is a ufs file */
+ strcpy (target.st_fstype, "ufs");
+
+ emul_write_buffer(&target, addr, sizeof(target), processor, cia);
+}
+#endif /* HAVE_SYS_STAT_H */
+
+#ifndef HAVE_STAT
+#define do_solaris_stat 0
+#else
+static void
+do_solaris_stat(os_emul_data *emul,
+ unsigned call,
+ const int arg0,
+ cpu *processor,
+ unsigned_word cia)
+{
+ unsigned_word path_addr = cpu_registers(processor)->gpr[arg0];
+ unsigned_word stat_pkt = cpu_registers(processor)->gpr[arg0+1];
+ char path_buf[PATH_MAX];
+ struct stat buf;
+ char *path = emul_read_string(path_buf, path_addr, PATH_MAX, processor, cia);
+ int status;
+
+ if (WITH_TRACE && ppc_trace[trace_os_emul])
+ printf_filtered ("0x%lx [%s], 0x%lx", (long)path_addr, path, (long)stat_pkt);
+
+ status = stat (path, &buf);
+ if (status == 0)
+ convert_to_solaris_stat (stat_pkt, &buf, processor, cia);
+
+ emul_write_status(processor, status, errno);
+}
+#endif
+
+#ifndef HAVE_LSTAT
+#define do_solaris_lstat 0
+#else
+static void
+do_solaris_lstat(os_emul_data *emul,
+ unsigned call,
+ const int arg0,
+ cpu *processor,
+ unsigned_word cia)
+{
+ unsigned_word path_addr = cpu_registers(processor)->gpr[arg0];
+ unsigned_word stat_pkt = cpu_registers(processor)->gpr[arg0+1];
+ char path_buf[PATH_MAX];
+ struct stat buf;
+ char *path = emul_read_string(path_buf, path_addr, PATH_MAX, processor, cia);
+ int status;
+
+ if (WITH_TRACE && ppc_trace[trace_os_emul])
+ printf_filtered ("0x%lx [%s], 0x%lx", (long)path_addr, path, (long)stat_pkt);
+
+ status = lstat (path, &buf);
+ if (status == 0)
+ convert_to_solaris_stat (stat_pkt, &buf, processor, cia);
+
+ emul_write_status(processor, status, errno);
+}
+#endif
+
+#ifndef HAVE_FSTAT
+#define do_solaris_fstat 0
+#else
+static void
+do_solaris_fstat(os_emul_data *emul,
+ unsigned call,
+ const int arg0,
+ cpu *processor,
+ unsigned_word cia)
+{
+ int fildes = (int)cpu_registers(processor)->gpr[arg0];
+ unsigned_word stat_pkt = cpu_registers(processor)->gpr[arg0+1];
+ struct stat buf;
+ int status;
+
+ if (WITH_TRACE && ppc_trace[trace_os_emul])
+ printf_filtered ("%d, 0x%lx", fildes, (long)stat_pkt);
+
+ status = fstat (fildes, &buf);
+ if (status == 0)
+ convert_to_solaris_stat (stat_pkt, &buf, processor, cia);
+
+ emul_write_status(processor, status, errno);
+}
+#endif
+
+#if defined(HAVE_TERMIO_STRUCTURE) || defined(HAVE_TERMIOS_STRUCTURE)
+#define SOLARIS_TIOC ('T'<<8)
+#define SOLARIS_NCC 8
+#define SOLARIS_NCCS 19
+
+#define SOLARIS_VINTR 0
+#define SOLARIS_VQUIT 1
+#define SOLARIS_VERASE 2
+#define SOLARIS_VKILL 3
+#define SOLARIS_VEOF 4
+#define SOLARIS_VEOL 5
+#define SOLARIS_VEOL2 6
+#define SOLARIS_VSWTCH 7
+#define SOLARIS_VSTART 8
+#define SOLARIS_VSTOP 9
+#define SOLARIS_VSUSP 10
+#define SOLARIS_VDSUSP 11
+#define SOLARIS_VREPRINT 12
+#define SOLARIS_VDISCARD 13
+#define SOLARIS_VWERASE 14
+#define SOLARIS_VLNEXT 15
+#endif
+
+#if defined(HAVE_TERMIO_STRUCTURE) || defined(HAVE_TERMIOS_STRUCTURE)
+/* Convert to/from host termio structure */
+
+struct solaris_termio {
+ unsigned16 c_iflag; /* input modes */
+ unsigned16 c_oflag; /* output modes */
+ unsigned16 c_cflag; /* control modes */
+ unsigned16 c_lflag; /* line discipline modes */
+ unsigned8 c_line; /* line discipline */
+ unsigned8 c_cc[SOLARIS_NCC]; /* control chars */
+};
+
+STATIC_INLINE_EMUL_UNIX void
+convert_to_solaris_termio(unsigned_word addr,
+ struct termio *host,
+ cpu *processor,
+ unsigned_word cia)
+{
+ struct solaris_termio target;
+ int i;
+
+ target.c_iflag = H2T_2 (host->c_iflag);
+ target.c_oflag = H2T_2 (host->c_oflag);
+ target.c_cflag = H2T_2 (host->c_cflag);
+ target.c_lflag = H2T_2 (host->c_lflag);
+
+#if defined(HAVE_TERMIO_CLINE) || defined(HAVE_TERMIOS_CLINE)
+ target.c_line = host->c_line;
+#else
+ target.c_line = 0;
+#endif
+
+ for (i = 0; i < SOLARIS_NCC; i++)
+ target.c_cc[i] = 0;
+
+#ifdef VINTR
+ target.c_cc[SOLARIS_VINTR] = host->c_cc[VINTR];
+#endif
+
+#ifdef VQUIT
+ target.c_cc[SOLARIS_VQUIT] = host->c_cc[VQUIT];
+#endif
+
+#ifdef VERASE
+ target.c_cc[SOLARIS_VERASE] = host->c_cc[VERASE];
+#endif
+
+#ifdef VKILL
+ target.c_cc[SOLARIS_VKILL] = host->c_cc[VKILL];
+#endif
+
+#ifdef VEOF
+ target.c_cc[SOLARIS_VEOF] = host->c_cc[VEOF];
+#endif
+
+#ifdef VEOL
+ target.c_cc[SOLARIS_VEOL] = host->c_cc[VEOL];
+#endif
+
+#ifdef VEOL2
+ target.c_cc[SOLARIS_VEOL2] = host->c_cc[VEOL2];
+#endif
+
+#ifdef VSWTCH
+ target.c_cc[SOLARIS_VSWTCH] = host->c_cc[VSWTCH];
+
+#else
+#ifdef VSWTC
+ target.c_cc[SOLARIS_VSWTCH] = host->c_cc[VSWTC];
+#endif
+#endif
+
+ emul_write_buffer(&target, addr, sizeof(target), processor, cia);
+}
+#endif /* HAVE_TERMIO_STRUCTURE || HAVE_TERMIOS_STRUCTURE */
+
+#ifdef HAVE_TERMIOS_STRUCTURE
+/* Convert to/from host termios structure */
+
+typedef unsigned32 solaris_tcflag_t;
+typedef unsigned8 solaris_cc_t;
+typedef unsigned32 solaris_speed_t;
+
+struct solaris_termios {
+ solaris_tcflag_t c_iflag;
+ solaris_tcflag_t c_oflag;
+ solaris_tcflag_t c_cflag;
+ solaris_tcflag_t c_lflag;
+ solaris_cc_t c_cc[SOLARIS_NCCS];
+};
+
+STATIC_INLINE_EMUL_UNIX void
+convert_to_solaris_termios(unsigned_word addr,
+ struct termios *host,
+ cpu *processor,
+ unsigned_word cia)
+{
+ struct solaris_termios target;
+ int i;
+
+ target.c_iflag = H2T_4 (host->c_iflag);
+ target.c_oflag = H2T_4 (host->c_oflag);
+ target.c_cflag = H2T_4 (host->c_cflag);
+ target.c_lflag = H2T_4 (host->c_lflag);
+
+ for (i = 0; i < SOLARIS_NCCS; i++)
+ target.c_cc[i] = 0;
+
+#ifdef VINTR
+ target.c_cc[SOLARIS_VINTR] = host->c_cc[VINTR];
+#endif
+
+#ifdef VQUIT
+ target.c_cc[SOLARIS_VQUIT] = host->c_cc[VQUIT];
+#endif
+
+#ifdef VERASE
+ target.c_cc[SOLARIS_VERASE] = host->c_cc[VERASE];
+#endif
+
+#ifdef VKILL
+ target.c_cc[SOLARIS_VKILL] = host->c_cc[VKILL];
+#endif
+
+#ifdef VEOF
+ target.c_cc[SOLARIS_VEOF] = host->c_cc[VEOF];
+#endif
+
+#ifdef VEOL
+ target.c_cc[SOLARIS_VEOL] = host->c_cc[VEOL];
+#endif
+
+#ifdef VEOL2
+ target.c_cc[SOLARIS_VEOL2] = host->c_cc[VEOL2];
+#endif
+
+#ifdef VSWTCH
+ target.c_cc[SOLARIS_VSWTCH] = host->c_cc[VSWTCH];
+
+#else
+#ifdef VSWTC
+ target.c_cc[SOLARIS_VSWTCH] = host->c_cc[VSWTC];
+#endif
+#endif
+
+#ifdef VSTART
+ target.c_cc[SOLARIS_VSTART] = host->c_cc[VSTART];
+#endif
+
+#ifdef VSTOP
+ target.c_cc[SOLARIS_VSTOP] = host->c_cc[VSTOP];
+#endif
+
+#ifdef VSUSP
+ target.c_cc[SOLARIS_VSUSP] = host->c_cc[VSUSP];
+#endif
+
+#ifdef VDSUSP
+ target.c_cc[SOLARIS_VDSUSP] = host->c_cc[VDSUSP];
+#endif
+
+#ifdef VREPRINT
+ target.c_cc[SOLARIS_VREPRINT] = host->c_cc[VREPRINT];
+#endif
+
+#ifdef VDISCARD
+ target.c_cc[SOLARIS_VDISCARD] = host->c_cc[VDISCARD];
+#endif
+
+#ifdef VWERASE
+ target.c_cc[SOLARIS_VWERASE] = host->c_cc[VWERASE];
+#endif
+
+#ifdef VLNEXT
+ target.c_cc[SOLARIS_VLNEXT] = host->c_cc[VLNEXT];
+#endif
+
+ emul_write_buffer(&target, addr, sizeof(target), processor, cia);
+}
+#endif /* HAVE_TERMIOS_STRUCTURE */
+
+#ifndef HAVE_IOCTL
+#define do_solaris_ioctl 0
+#else
+static void
+do_solaris_ioctl(os_emul_data *emul,
+ unsigned call,
+ const int arg0,
+ cpu *processor,
+ unsigned_word cia)
+{
+ int fildes = cpu_registers(processor)->gpr[arg0];
+ unsigned request = cpu_registers(processor)->gpr[arg0+1];
+ unsigned_word argp_addr = cpu_registers(processor)->gpr[arg0+2];
+ int status = 0;
+ const char *name = "<unknown>";
+
+#ifdef HAVE_TERMIOS_STRUCTURE
+ struct termios host_termio;
+
+#else
+#ifdef HAVE_TERMIO_STRUCTURE
+ struct termio host_termio;
+#endif
+#endif
+
+ switch (request)
+ {
+ case 0: /* make sure we have at least one case */
+ default:
+ status = -1;
+ errno = EINVAL;
+ break;
+
+#if defined(HAVE_TERMIO_STRUCTURE) || defined(HAVE_TERMIOS_STRUCTURE)
+#if defined(TCGETA) || defined(TCGETS) || defined(HAVE_TCGETATTR)
+ case SOLARIS_TIOC | 1: /* TCGETA */
+ name = "TCGETA";
+#ifdef HAVE_TCGETATTR
+ status = tcgetattr(fildes, &host_termio);
+#elif defined(TCGETS)
+ status = ioctl (fildes, TCGETS, &host_termio);
+#else
+ status = ioctl (fildes, TCGETA, &host_termio);
+#endif
+ if (status == 0)
+ convert_to_solaris_termio (argp_addr, &host_termio, processor, cia);
+ break;
+#endif /* TCGETA */
+#endif /* HAVE_TERMIO_STRUCTURE */
+
+#ifdef HAVE_TERMIOS_STRUCTURE
+#if defined(TCGETS) || defined(HAVE_TCGETATTR)
+ case SOLARIS_TIOC | 13: /* TCGETS */
+ name = "TCGETS";
+#ifdef HAVE_TCGETATTR
+ status = tcgetattr(fildes, &host_termio);
+#else
+ status = ioctl (fildes, TCGETS, &host_termio);
+#endif
+ if (status == 0)
+ convert_to_solaris_termios (argp_addr, &host_termio, processor, cia);
+ break;
+#endif /* TCGETS */
+#endif /* HAVE_TERMIOS_STRUCTURE */
+ }
+
+ emul_write_status(processor, status, errno);
+
+ if (WITH_TRACE && ppc_trace[trace_os_emul])
+ printf_filtered ("%d, 0x%x [%s], 0x%lx", fildes, request, name, (long)argp_addr);
+}
+#endif /* HAVE_IOCTL */
+
+static emul_syscall_descriptor solaris_descriptors[] = {
+ /* 0 */ { 0, "syscall" },
+ /* 1 */ { do_unix_exit, "exit" },
+ /* 2 */ { 0, "fork" },
+ /* 3 */ { do_unix_read, "read" },
+ /* 4 */ { do_unix_write, "write" },
+ /* 5 */ { do_unix_open, "open" },
+ /* 6 */ { do_unix_close, "close" },
+ /* 7 */ { 0, "wait" },
+ /* 8 */ { 0, "creat" },
+ /* 9 */ { do_unix_link, "link" },
+ /* 10 */ { do_unix_unlink, "unlink" },
+ /* 11 */ { 0, "exec" },
+ /* 12 */ { do_unix_chdir, "chdir" },
+ /* 13 */ { do_unix_time, "time" },
+ /* 14 */ { 0, "mknod" },
+ /* 15 */ { 0, "chmod" },
+ /* 16 */ { 0, "chown" },
+ /* 17 */ { do_unix_break, "brk" },
+ /* 18 */ { do_solaris_stat, "stat" },
+ /* 19 */ { do_unix_lseek, "lseek" },
+ /* 20 */ { do_unix_getpid2, "getpid" },
+ /* 21 */ { 0, "mount" },
+ /* 22 */ { 0, "umount" },
+ /* 23 */ { 0, "setuid" },
+ /* 24 */ { do_unix_getuid2, "getuid" },
+ /* 25 */ { 0, "stime" },
+ /* 26 */ { 0, "ptrace" },
+ /* 27 */ { 0, "alarm" },
+ /* 28 */ { do_solaris_fstat, "fstat" },
+ /* 29 */ { 0, "pause" },
+ /* 30 */ { 0, "utime" },
+ /* 31 */ { 0, "stty" },
+ /* 32 */ { 0, "gtty" },
+ /* 33 */ { do_unix_access, "access" },
+ /* 34 */ { 0, "nice" },
+ /* 35 */ { 0, "statfs" },
+ /* 36 */ { 0, "sync" },
+ /* 37 */ { 0, "kill" },
+ /* 38 */ { 0, "fstatfs" },
+ /* 39 */ { 0, "pgrpsys" },
+ /* 40 */ { 0, "xenix" },
+ /* 41 */ { do_unix_dup, "dup" },
+ /* 42 */ { 0, "pipe" },
+ /* 43 */ { 0, "times" },
+ /* 44 */ { 0, "profil" },
+ /* 45 */ { 0, "plock" },
+ /* 46 */ { 0, "setgid" },
+ /* 47 */ { do_unix_getgid2, "getgid" },
+ /* 48 */ { 0, "signal" },
+ /* 49 */ { 0, "msgsys" },
+ /* 50 */ { 0, "syssun" },
+ /* 51 */ { 0, "acct" },
+ /* 52 */ { 0, "shmsys" },
+ /* 53 */ { 0, "semsys" },
+ /* 54 */ { do_solaris_ioctl, "ioctl" },
+ /* 55 */ { 0, "uadmin" },
+ /* 56 */ { 0, 0 /* reserved for exch */ },
+ /* 57 */ { 0, "utssys" },
+ /* 58 */ { 0, "fdsync" },
+ /* 59 */ { 0, "execve" },
+ /* 60 */ { do_unix_umask, "umask" },
+ /* 61 */ { 0, "chroot" },
+ /* 62 */ { 0, "fcntl" },
+ /* 63 */ { 0, "ulimit" },
+ /* 64 */ { 0, 0 /* reserved for UNIX PC */ },
+ /* 64 */ { 0, 0 /* reserved for UNIX PC */ },
+ /* 65 */ { 0, 0 /* reserved for UNIX PC */ },
+ /* 66 */ { 0, 0 /* reserved for UNIX PC */ },
+ /* 67 */ { 0, 0 /* reserved for UNIX PC */ },
+ /* 68 */ { 0, 0 /* reserved for UNIX PC */ },
+ /* 69 */ { 0, 0 /* reserved for UNIX PC */ },
+ /* 70 */ { 0, 0 /* was advfs */ },
+ /* 71 */ { 0, 0 /* was unadvfs */ },
+ /* 72 */ { 0, 0 /* was rmount */ },
+ /* 73 */ { 0, 0 /* was rumount */ },
+ /* 74 */ { 0, 0 /* was rfstart */ },
+ /* 75 */ { 0, 0 /* was sigret */ },
+ /* 76 */ { 0, 0 /* was rdebug */ },
+ /* 77 */ { 0, 0 /* was rfstop */ },
+ /* 78 */ { 0, 0 /* was rfsys */ },
+ /* 79 */ { do_unix_rmdir, "rmdir" },
+ /* 80 */ { do_unix_mkdir, "mkdir" },
+ /* 81 */ { 0, "getdents" },
+ /* 82 */ { 0, 0 /* was libattach */ },
+ /* 83 */ { 0, 0 /* was libdetach */ },
+ /* 84 */ { 0, "sysfs" },
+ /* 85 */ { 0, "getmsg" },
+ /* 86 */ { 0, "putmsg" },
+ /* 87 */ { 0, "poll" },
+ /* 88 */ { do_solaris_lstat, "lstat" },
+ /* 89 */ { do_unix_symlink, "symlink" },
+ /* 90 */ { 0, "readlink" },
+ /* 91 */ { 0, "setgroups" },
+ /* 92 */ { 0, "getgroups" },
+ /* 93 */ { 0, "fchmod" },
+ /* 94 */ { 0, "fchown" },
+ /* 95 */ { 0, "sigprocmask" },
+ /* 96 */ { 0, "sigsuspend" },
+ /* 97 */ { do_unix_nop, "sigaltstack" },
+ /* 98 */ { do_unix_nop, "sigaction" },
+ /* 99 */ { 0, "sigpending" },
+ /* 100 */ { 0, "context" },
+ /* 101 */ { 0, "evsys" },
+ /* 102 */ { 0, "evtrapret" },
+ /* 103 */ { 0, "statvfs" },
+ /* 104 */ { 0, "fstatvfs" },
+ /* 105 */ { 0, 0 /* reserved */ },
+ /* 106 */ { 0, "nfssys" },
+ /* 107 */ { 0, "waitsys" },
+ /* 108 */ { 0, "sigsendsys" },
+ /* 109 */ { 0, "hrtsys" },
+ /* 110 */ { 0, "acancel" },
+ /* 111 */ { 0, "async" },
+ /* 112 */ { 0, "priocntlsys" },
+ /* 113 */ { 0, "pathconf" },
+ /* 114 */ { 0, "mincore" },
+ /* 115 */ { 0, "mmap" },
+ /* 116 */ { 0, "mprotect" },
+ /* 117 */ { 0, "munmap" },
+ /* 118 */ { 0, "fpathconf" },
+ /* 119 */ { 0, "vfork" },
+ /* 120 */ { 0, "fchdir" },
+ /* 121 */ { 0, "readv" },
+ /* 122 */ { 0, "writev" },
+ /* 123 */ { 0, "xstat" },
+ /* 124 */ { 0, "lxstat" },
+ /* 125 */ { 0, "fxstat" },
+ /* 126 */ { 0, "xmknod" },
+ /* 127 */ { 0, "clocal" },
+ /* 128 */ { 0, "setrlimit" },
+ /* 129 */ { 0, "getrlimit" },
+ /* 130 */ { 0, "lchown" },
+ /* 131 */ { 0, "memcntl" },
+ /* 132 */ { 0, "getpmsg" },
+ /* 133 */ { 0, "putpmsg" },
+ /* 134 */ { 0, "rename" },
+ /* 135 */ { 0, "uname" },
+ /* 136 */ { 0, "setegid" },
+ /* 137 */ { 0, "sysconfig" },
+ /* 138 */ { 0, "adjtime" },
+ /* 139 */ { 0, "systeminfo" },
+ /* 140 */ { 0, 0 /* reserved */ },
+ /* 141 */ { 0, "seteuid" },
+ /* 142 */ { 0, "vtrace" },
+ /* 143 */ { 0, "fork1" },
+ /* 144 */ { 0, "sigtimedwait" },
+ /* 145 */ { 0, "lwp_info" },
+ /* 146 */ { 0, "yield" },
+ /* 147 */ { 0, "lwp_sema_wait" },
+ /* 148 */ { 0, "lwp_sema_post" },
+ /* 149 */ { 0, 0 /* reserved */ },
+ /* 150 */ { 0, 0 /* reserved */ },
+ /* 151 */ { 0, 0 /* reserved */ },
+ /* 152 */ { 0, "modctl" },
+ /* 153 */ { 0, "fchroot" },
+ /* 154 */ { 0, "utimes" },
+ /* 155 */ { 0, "vhangup" },
+ /* 156 */ { do_unix_gettimeofday, "gettimeofday" },
+ /* 157 */ { 0, "getitimer" },
+ /* 158 */ { 0, "setitimer" },
+ /* 159 */ { 0, "lwp_create" },
+ /* 160 */ { 0, "lwp_exit" },
+ /* 161 */ { 0, "lwp_suspend" },
+ /* 162 */ { 0, "lwp_continue" },
+ /* 163 */ { 0, "lwp_kill" },
+ /* 164 */ { 0, "lwp_self" },
+ /* 165 */ { 0, "lwp_setprivate" },
+ /* 166 */ { 0, "lwp_getprivate" },
+ /* 167 */ { 0, "lwp_wait" },
+ /* 168 */ { 0, "lwp_mutex_unlock" },
+ /* 169 */ { 0, "lwp_mutex_lock" },
+ /* 170 */ { 0, "lwp_cond_wait" },
+ /* 171 */ { 0, "lwp_cond_signal" },
+ /* 172 */ { 0, "lwp_cond_broadcast" },
+ /* 173 */ { 0, "pread" },
+ /* 174 */ { 0, "pwrite" },
+ /* 175 */ { 0, "llseek" },
+ /* 176 */ { 0, "inst_sync" },
+ /* 177 */ { 0, 0 /* reserved */ },
+ /* 178 */ { 0, "kaio" },
+ /* 179 */ { 0, 0 /* reserved */ },
+ /* 180 */ { 0, 0 /* reserved */ },
+ /* 181 */ { 0, 0 /* reserved */ },
+ /* 182 */ { 0, 0 /* reserved */ },
+ /* 183 */ { 0, 0 /* reserved */ },
+ /* 184 */ { 0, "tsolsys" },
+ /* 185 */ { 0, "acl" },
+ /* 186 */ { 0, "auditsys" },
+ /* 187 */ { 0, "processor_bind" },
+ /* 188 */ { 0, "processor_info" },
+ /* 189 */ { 0, "p_online" },
+ /* 190 */ { 0, "sigqueue" },
+ /* 191 */ { 0, "clock_gettime" },
+ /* 192 */ { 0, "clock_settime" },
+ /* 193 */ { 0, "clock_getres" },
+ /* 194 */ { 0, "timer_create" },
+ /* 195 */ { 0, "timer_delete" },
+ /* 196 */ { 0, "timer_settime" },
+ /* 197 */ { 0, "timer_gettime" },
+ /* 198 */ { 0, "timer_getoverrun" },
+ /* 199 */ { 0, "nanosleep" },
+ /* 200 */ { 0, "facl" },
+ /* 201 */ { 0, "door" },
+ /* 202 */ { 0, "setreuid" },
+ /* 203 */ { 0, "setregid" },
+ /* 204 */ { 0, "install_utrap" },
+ /* 205 */ { 0, 0 /* reserved */ },
+ /* 206 */ { 0, 0 /* reserved */ },
+ /* 207 */ { 0, 0 /* reserved */ },
+ /* 208 */ { 0, 0 /* reserved */ },
+ /* 209 */ { 0, 0 /* reserved */ },
+ /* 210 */ { 0, "signotifywait" },
+ /* 211 */ { 0, "lwp_sigredirect" },
+ /* 212 */ { 0, "lwp_alarm" },
+};
+
+static char *(solaris_error_names[]) = {
+ /* 0 */ "ESUCCESS",
+ /* 1 */ "EPERM",
+ /* 2 */ "ENOENT",
+ /* 3 */ "ESRCH",
+ /* 4 */ "EINTR",
+ /* 5 */ "EIO",
+ /* 6 */ "ENXIO",
+ /* 7 */ "E2BIG",
+ /* 8 */ "ENOEXEC",
+ /* 9 */ "EBADF",
+ /* 10 */ "ECHILD",
+ /* 11 */ "EAGAIN",
+ /* 12 */ "ENOMEM",
+ /* 13 */ "EACCES",
+ /* 14 */ "EFAULT",
+ /* 15 */ "ENOTBLK",
+ /* 16 */ "EBUSY",
+ /* 17 */ "EEXIST",
+ /* 18 */ "EXDEV",
+ /* 19 */ "ENODEV",
+ /* 20 */ "ENOTDIR",
+ /* 21 */ "EISDIR",
+ /* 22 */ "EINVAL",
+ /* 23 */ "ENFILE",
+ /* 24 */ "EMFILE",
+ /* 25 */ "ENOTTY",
+ /* 26 */ "ETXTBSY",
+ /* 27 */ "EFBIG",
+ /* 28 */ "ENOSPC",
+ /* 29 */ "ESPIPE",
+ /* 30 */ "EROFS",
+ /* 31 */ "EMLINK",
+ /* 32 */ "EPIPE",
+ /* 33 */ "EDOM",
+ /* 34 */ "ERANGE",
+ /* 35 */ "ENOMSG",
+ /* 36 */ "EIDRM",
+ /* 37 */ "ECHRNG",
+ /* 38 */ "EL2NSYNC",
+ /* 39 */ "EL3HLT",
+ /* 40 */ "EL3RST",
+ /* 41 */ "ELNRNG",
+ /* 42 */ "EUNATCH",
+ /* 43 */ "ENOCSI",
+ /* 44 */ "EL2HLT",
+ /* 45 */ "EDEADLK",
+ /* 46 */ "ENOLCK",
+ /* 47 */ "ECANCELED",
+ /* 48 */ "ENOTSUP",
+ /* 49 */ "EDQUOT",
+ /* 50 */ "EBADE",
+ /* 51 */ "EBADR",
+ /* 52 */ "EXFULL",
+ /* 53 */ "ENOANO",
+ /* 54 */ "EBADRQC",
+ /* 55 */ "EBADSLT",
+ /* 56 */ "EDEADLOCK",
+ /* 57 */ "EBFONT",
+ /* 58 */ "Error code 58",
+ /* 59 */ "Error code 59",
+ /* 60 */ "ENOSTR",
+ /* 61 */ "ENODATA",
+ /* 62 */ "ETIME",
+ /* 63 */ "ENOSR",
+ /* 64 */ "ENONET",
+ /* 65 */ "ENOPKG",
+ /* 66 */ "EREMOTE",
+ /* 67 */ "ENOLINK",
+ /* 68 */ "EADV",
+ /* 69 */ "ESRMNT",
+ /* 70 */ "ECOMM",
+ /* 71 */ "EPROTO",
+ /* 72 */ "Error code 72",
+ /* 73 */ "Error code 73",
+ /* 74 */ "EMULTIHOP",
+ /* 75 */ "Error code 75",
+ /* 76 */ "Error code 76",
+ /* 77 */ "EBADMSG",
+ /* 78 */ "ENAMETOOLONG",
+ /* 79 */ "EOVERFLOW",
+ /* 80 */ "ENOTUNIQ",
+ /* 81 */ "EBADFD",
+ /* 82 */ "EREMCHG",
+ /* 83 */ "ELIBACC",
+ /* 84 */ "ELIBBAD",
+ /* 85 */ "ELIBSCN",
+ /* 86 */ "ELIBMAX",
+ /* 87 */ "ELIBEXEC",
+ /* 88 */ "EILSEQ",
+ /* 89 */ "ENOSYS",
+ /* 90 */ "ELOOP",
+ /* 91 */ "ERESTART",
+ /* 92 */ "ESTRPIPE",
+ /* 93 */ "ENOTEMPTY",
+ /* 94 */ "EUSERS",
+ /* 95 */ "ENOTSOCK",
+ /* 96 */ "EDESTADDRREQ",
+ /* 97 */ "EMSGSIZE",
+ /* 98 */ "EPROTOTYPE",
+ /* 99 */ "ENOPROTOOPT",
+ /* 100 */ "Error code 100",
+ /* 101 */ "Error code 101",
+ /* 102 */ "Error code 102",
+ /* 103 */ "Error code 103",
+ /* 104 */ "Error code 104",
+ /* 105 */ "Error code 105",
+ /* 106 */ "Error code 106",
+ /* 107 */ "Error code 107",
+ /* 108 */ "Error code 108",
+ /* 109 */ "Error code 109",
+ /* 110 */ "Error code 110",
+ /* 111 */ "Error code 111",
+ /* 112 */ "Error code 112",
+ /* 113 */ "Error code 113",
+ /* 114 */ "Error code 114",
+ /* 115 */ "Error code 115",
+ /* 116 */ "Error code 116",
+ /* 117 */ "Error code 117",
+ /* 118 */ "Error code 118",
+ /* 119 */ "Error code 119",
+ /* 120 */ "EPROTONOSUPPORT",
+ /* 121 */ "ESOCKTNOSUPPORT",
+ /* 122 */ "EOPNOTSUPP",
+ /* 123 */ "EPFNOSUPPORT",
+ /* 124 */ "EAFNOSUPPORT",
+ /* 125 */ "EADDRINUSE",
+ /* 126 */ "EADDRNOTAVAIL",
+ /* 127 */ "ENETDOWN",
+ /* 128 */ "ENETUNREACH",
+ /* 129 */ "ENETRESET",
+ /* 130 */ "ECONNABORTED",
+ /* 131 */ "ECONNRESET",
+ /* 132 */ "ENOBUFS",
+ /* 133 */ "EISCONN",
+ /* 134 */ "ENOTCONN",
+ /* 135 */ "Error code 135", /* XENIX has 135 - 142 */
+ /* 136 */ "Error code 136",
+ /* 137 */ "Error code 137",
+ /* 138 */ "Error code 138",
+ /* 139 */ "Error code 139",
+ /* 140 */ "Error code 140",
+ /* 141 */ "Error code 141",
+ /* 142 */ "Error code 142",
+ /* 143 */ "ESHUTDOWN",
+ /* 144 */ "ETOOMANYREFS",
+ /* 145 */ "ETIMEDOUT",
+ /* 146 */ "ECONNREFUSED",
+ /* 147 */ "EHOSTDOWN",
+ /* 148 */ "EHOSTUNREACH",
+ /* 149 */ "EALREADY",
+ /* 150 */ "EINPROGRESS",
+ /* 151 */ "ESTALE",
+};
+
+static char *(solaris_signal_names[]) = {
+ /* 0 */ 0,
+ /* 1 */ "SIGHUP",
+ /* 2 */ "SIGINT",
+ /* 3 */ "SIGQUIT",
+ /* 4 */ "SIGILL",
+ /* 5 */ "SIGTRAP",
+ /* 6 */ "SIGABRT",
+ /* 7 */ "SIGEMT",
+ /* 8 */ "SIGFPE",
+ /* 9 */ "SIGKILL",
+ /* 10 */ "SIGBUS",
+ /* 11 */ "SIGSEGV",
+ /* 12 */ "SIGSYS",
+ /* 13 */ "SIGPIPE",
+ /* 14 */ "SIGALRM",
+ /* 15 */ "SIGTERM",
+ /* 16 */ "SIGUSR1",
+ /* 17 */ "SIGUSR2",
+ /* 18 */ "SIGCHLD",
+ /* 19 */ "SIGPWR",
+ /* 20 */ "SIGWINCH",
+ /* 21 */ "SIGURG",
+ /* 22 */ "SIGPOLL",
+ /* 23 */ "SIGSTOP",
+ /* 24 */ "SIGTSTP",
+ /* 25 */ "SIGCONT",
+ /* 26 */ "SIGTTIN",
+ /* 27 */ "SIGTTOU",
+ /* 28 */ "SIGVTALRM",
+ /* 29 */ "SIGPROF",
+ /* 30 */ "SIGXCPU",
+ /* 31 */ "SIGXFSZ",
+ /* 32 */ "SIGWAITING",
+ /* 33 */ "SIGLWP",
+ /* 34 */ "SIGFREEZE",
+ /* 35 */ "SIGTHAW",
+ /* 36 */ "SIGCANCEL",
+};
+
+static emul_syscall emul_solaris_syscalls = {
+ solaris_descriptors,
+ sizeof(solaris_descriptors) / sizeof(solaris_descriptors[0]),
+ solaris_error_names,
+ sizeof(solaris_error_names) / sizeof(solaris_error_names[0]),
+ solaris_signal_names,
+ sizeof(solaris_signal_names) / sizeof(solaris_signal_names[0]),
+};
+
+
+/* Solaris's os_emul interface, most are just passed on to the generic
+ syscall stuff */
+
+static os_emul_data *
+emul_solaris_create(device *root,
+ bfd *image,
+ const char *name)
+{
+ /* check that this emulation is really for us */
+ if (name != NULL && strcmp(name, "solaris") != 0)
+ return NULL;
+
+ if (image == NULL)
+ return NULL;
+
+ return emul_unix_create(root, image, "solaris", &emul_solaris_syscalls);
+}
+
+static void
+emul_solaris_init(os_emul_data *emul_data,
+ int nr_cpus)
+{
+ /* nothing yet */
+}
+
+static void
+emul_solaris_system_call(cpu *processor,
+ unsigned_word cia,
+ os_emul_data *emul_data)
+{
+ emul_do_system_call(emul_data,
+ emul_data->syscalls,
+ cpu_registers(processor)->gpr[0],
+ 3, /*r3 contains arg0*/
+ processor,
+ cia);
+}
+
+const os_emul emul_solaris = {
+ "solaris",
+ emul_solaris_create,
+ emul_solaris_init,
+ emul_solaris_system_call,
+ 0, /*instruction_call*/
+ 0 /*data*/
+};
+
+
+/* EMULATION
+
+ Linux - Emulation of user programs for Linux/PPC
+
+ DESCRIPTION
+
+ */
+
+
+/* Linux specific implementation */
+
+typedef unsigned32 linux_dev_t;
+typedef unsigned32 linux_ino_t;
+typedef unsigned32 linux_mode_t;
+typedef unsigned16 linux_nlink_t;
+typedef signed32 linux_off_t;
+typedef signed32 linux_pid_t;
+typedef unsigned32 linux_uid_t;
+typedef unsigned32 linux_gid_t;
+typedef unsigned32 linux_size_t;
+typedef signed32 linux_ssize_t;
+typedef signed32 linux_ptrdiff_t;
+typedef signed32 linux_time_t;
+typedef signed32 linux_clock_t;
+typedef signed32 linux_daddr_t;
+
+#ifdef HAVE_SYS_STAT_H
+/* For the PowerPC, don't both with the 'old' stat structure, since there
+ should be no extant binaries with that structure. */
+
+struct linux_stat {
+ linux_dev_t st_dev;
+ linux_ino_t st_ino;
+ linux_mode_t st_mode;
+ linux_nlink_t st_nlink;
+ linux_uid_t st_uid;
+ linux_gid_t st_gid;
+ linux_dev_t st_rdev;
+ linux_off_t st_size;
+ unsigned32 st_blksize;
+ unsigned32 st_blocks;
+ unsigned32 st_atimx; /* don't use st_{a,c,m}time, that might a macro */
+ unsigned32 __unused1; /* defined by the host's stat.h */
+ unsigned32 st_mtimx;
+ unsigned32 __unused2;
+ unsigned32 st_ctimx;
+ unsigned32 __unused3;
+ unsigned32 __unused4;
+ unsigned32 __unused5;
+};
+
+/* Convert from host stat structure to solaris stat structure */
+STATIC_INLINE_EMUL_UNIX void
+convert_to_linux_stat(unsigned_word addr,
+ struct stat *host,
+ cpu *processor,
+ unsigned_word cia)
+{
+ struct linux_stat target;
+
+ target.st_dev = H2T_4(host->st_dev);
+ target.st_ino = H2T_4(host->st_ino);
+ target.st_mode = H2T_4(host->st_mode);
+ target.st_nlink = H2T_2(host->st_nlink);
+ target.st_uid = H2T_4(host->st_uid);
+ target.st_gid = H2T_4(host->st_gid);
+ target.st_size = H2T_4(host->st_size);
+
+#ifdef HAVE_ST_RDEV
+ target.st_rdev = H2T_4(host->st_rdev);
+#else
+ target.st_rdev = 0;
+#endif
+
+#ifdef HAVE_ST_BLKSIZE
+ target.st_blksize = H2T_4(host->st_blksize);
+#else
+ target.st_blksize = 0;
+#endif
+
+#ifdef HAVE_ST_BLOCKS
+ target.st_blocks = H2T_4(host->st_blocks);
+#else
+ target.st_blocks = 0;
+#endif
+
+ target.st_atimx = H2T_4(host->st_atime);
+ target.st_ctimx = H2T_4(host->st_ctime);
+ target.st_mtimx = H2T_4(host->st_mtime);
+ target.__unused1 = 0;
+ target.__unused2 = 0;
+ target.__unused3 = 0;
+ target.__unused4 = 0;
+ target.__unused5 = 0;
+
+ emul_write_buffer(&target, addr, sizeof(target), processor, cia);
+}
+#endif /* HAVE_SYS_STAT_H */
+
+#ifndef HAVE_STAT
+#define do_linux_stat 0
+#else
+static void
+do_linux_stat(os_emul_data *emul,
+ unsigned call,
+ const int arg0,
+ cpu *processor,
+ unsigned_word cia)
+{
+ unsigned_word path_addr = cpu_registers(processor)->gpr[arg0];
+ unsigned_word stat_pkt = cpu_registers(processor)->gpr[arg0+1];
+ char path_buf[PATH_MAX];
+ struct stat buf;
+ char *path = emul_read_string(path_buf, path_addr, PATH_MAX, processor, cia);
+ int status;
+
+ if (WITH_TRACE && ppc_trace[trace_os_emul])
+ printf_filtered ("0x%lx [%s], 0x%lx", (long)path_addr, path, (long)stat_pkt);
+
+ status = stat (path, &buf);
+ if (status == 0)
+ convert_to_linux_stat (stat_pkt, &buf, processor, cia);
+
+ emul_write_status(processor, status, errno);
+}
+#endif
+
+#ifndef HAVE_LSTAT
+#define do_linux_lstat 0
+#else
+static void
+do_linux_lstat(os_emul_data *emul,
+ unsigned call,
+ const int arg0,
+ cpu *processor,
+ unsigned_word cia)
+{
+ unsigned_word path_addr = cpu_registers(processor)->gpr[arg0];
+ unsigned_word stat_pkt = cpu_registers(processor)->gpr[arg0+1];
+ char path_buf[PATH_MAX];
+ struct stat buf;
+ char *path = emul_read_string(path_buf, path_addr, PATH_MAX, processor, cia);
+ int status;
+
+ if (WITH_TRACE && ppc_trace[trace_os_emul])
+ printf_filtered ("0x%lx [%s], 0x%lx", (long)path_addr, path, (long)stat_pkt);
+
+ status = lstat (path, &buf);
+ if (status == 0)
+ convert_to_linux_stat (stat_pkt, &buf, processor, cia);
+
+ emul_write_status(processor, status, errno);
+}
+#endif
+
+#ifndef HAVE_FSTAT
+#define do_linux_fstat 0
+#else
+static void
+do_linux_fstat(os_emul_data *emul,
+ unsigned call,
+ const int arg0,
+ cpu *processor,
+ unsigned_word cia)
+{
+ int fildes = (int)cpu_registers(processor)->gpr[arg0];
+ unsigned_word stat_pkt = cpu_registers(processor)->gpr[arg0+1];
+ struct stat buf;
+ int status;
+
+ if (WITH_TRACE && ppc_trace[trace_os_emul])
+ printf_filtered ("%d, 0x%lx", fildes, (long)stat_pkt);
+
+ status = fstat (fildes, &buf);
+ if (status == 0)
+ convert_to_linux_stat (stat_pkt, &buf, processor, cia);
+
+ emul_write_status(processor, status, errno);
+}
+#endif
+
+#if defined(HAVE_TERMIO_STRUCTURE) || defined(HAVE_TERMIOS_STRUCTURE)
+#define LINUX_NCC 10
+#define LINUX_NCCS 19
+
+#define LINUX_VINTR 0
+#define LINUX_VQUIT 1
+#define LINUX_VERASE 2
+#define LINUX_VKILL 3
+#define LINUX_VEOF 4
+#define LINUX_VMIN 5
+#define LINUX_VEOL 6
+#define LINUX_VTIME 7
+#define LINUX_VEOL2 8
+#define LINUX_VSWTC 9
+#define LINUX_VWERASE 10
+#define LINUX_VREPRINT 11
+#define LINUX_VSUSP 12
+#define LINUX_VSTART 13
+#define LINUX_VSTOP 14
+#define LINUX_VLNEXT 15
+#define LINUX_VDISCARD 16
+
+#define LINUX_IOC_NRBITS 8
+#define LINUX_IOC_TYPEBITS 8
+#define LINUX_IOC_SIZEBITS 13
+#define LINUX_IOC_DIRBITS 3
+
+#define LINUX_IOC_NRMASK ((1 << LINUX_IOC_NRBITS)-1)
+#define LINUX_IOC_TYPEMASK ((1 << LINUX_IOC_TYPEBITS)-1)
+#define LINUX_IOC_SIZEMASK ((1 << LINUX_IOC_SIZEBITS)-1)
+#define LINUX_IOC_DIRMASK ((1 << LINUX_IOC_DIRBITS)-1)
+
+#define LINUX_IOC_NRSHIFT 0
+#define LINUX_IOC_TYPESHIFT (LINUX_IOC_NRSHIFT+LINUX_IOC_NRBITS)
+#define LINUX_IOC_SIZESHIFT (LINUX_IOC_TYPESHIFT+LINUX_IOC_TYPEBITS)
+#define LINUX_IOC_DIRSHIFT (LINUX_IOC_SIZESHIFT+LINUX_IOC_SIZEBITS)
+
+/*
+ * Direction bits _IOC_NONE could be 0, but OSF/1 gives it a bit.
+ * And this turns out useful to catch old ioctl numbers in header
+ * files for us.
+ */
+#define LINUX_IOC_NONE 1U
+#define LINUX_IOC_READ 2U
+#define LINUX_IOC_WRITE 4U
+
+#define LINUX_IOC(dir,type,nr,size) \
+ (((dir) << LINUX_IOC_DIRSHIFT) | \
+ ((type) << LINUX_IOC_TYPESHIFT) | \
+ ((nr) << LINUX_IOC_NRSHIFT) | \
+ ((size) << LINUX_IOC_SIZESHIFT))
+
+/* used to create numbers */
+#define LINUX_IO(type,nr) LINUX_IOC(LINUX_IOC_NONE,(type),(nr),0)
+#define LINUX_IOR(type,nr,size) LINUX_IOC(LINUX_IOC_READ,(type),(nr),sizeof(size))
+#define LINUX_IOW(type,nr,size) LINUX_IOC(LINUX_IOC_WRITE,(type),(nr),sizeof(size))
+#define LINUX_IOWR(type,nr,size) LINUX_IOC(LINUX_IOC_READ|LINUX_IOC_WRITE,(type),(nr),sizeof(size))
+#endif
+
+#if defined(HAVE_TERMIO_STRUCTURE) || defined(HAVE_TERMIOS_STRUCTURE)
+/* Convert to/from host termio structure */
+
+struct linux_termio {
+ unsigned16 c_iflag; /* input modes */
+ unsigned16 c_oflag; /* output modes */
+ unsigned16 c_cflag; /* control modes */
+ unsigned16 c_lflag; /* line discipline modes */
+ unsigned8 c_line; /* line discipline */
+ unsigned8 c_cc[LINUX_NCC]; /* control chars */
+};
+
+STATIC_INLINE_EMUL_UNIX void
+convert_to_linux_termio(unsigned_word addr,
+ struct termio *host,
+ cpu *processor,
+ unsigned_word cia)
+{
+ struct linux_termio target;
+ int i;
+
+ target.c_iflag = H2T_2 (host->c_iflag);
+ target.c_oflag = H2T_2 (host->c_oflag);
+ target.c_cflag = H2T_2 (host->c_cflag);
+ target.c_lflag = H2T_2 (host->c_lflag);
+
+#if defined(HAVE_TERMIO_CLINE) || defined(HAVE_TERMIOS_CLINE)
+ target.c_line = host->c_line;
+#else
+ target.c_line = 0;
+#endif
+
+ for (i = 0; i < LINUX_NCC; i++)
+ target.c_cc[i] = 0;
+
+#ifdef VINTR
+ target.c_cc[LINUX_VINTR] = host->c_cc[VINTR];
+#endif
+
+#ifdef VQUIT
+ target.c_cc[LINUX_VQUIT] = host->c_cc[VQUIT];
+#endif
+
+#ifdef VERASE
+ target.c_cc[LINUX_VERASE] = host->c_cc[VERASE];
+#endif
+
+#ifdef VKILL
+ target.c_cc[LINUX_VKILL] = host->c_cc[VKILL];
+#endif
+
+#ifdef VEOF
+ target.c_cc[LINUX_VEOF] = host->c_cc[VEOF];
+#endif
+
+#ifdef VMIN
+ target.c_cc[LINUX_VMIN] = host->c_cc[VMIN];
+#endif
+
+#ifdef VEOL
+ target.c_cc[LINUX_VEOL] = host->c_cc[VEOL];
+#endif
+
+#ifdef VTIME
+ target.c_cc[LINUX_VTIME] = host->c_cc[VTIME];
+#endif
+
+#ifdef VEOL2
+ target.c_cc[LINUX_VEOL2] = host->c_cc[VEOL2];
+#endif
+
+#ifdef VSWTC
+ target.c_cc[LINUX_VSWTC] = host->c_cc[VSWTC];
+#endif
+
+#ifdef VSWTCH
+ target.c_cc[LINUX_VSWTC] = host->c_cc[VSWTCH];
+#endif
+
+ emul_write_buffer(&target, addr, sizeof(target), processor, cia);
+}
+#endif /* HAVE_TERMIO_STRUCTURE */
+
+#ifdef HAVE_TERMIOS_STRUCTURE
+/* Convert to/from host termios structure */
+
+typedef unsigned32 linux_tcflag_t;
+typedef unsigned8 linux_cc_t;
+typedef unsigned32 linux_speed_t;
+
+struct linux_termios {
+ linux_tcflag_t c_iflag;
+ linux_tcflag_t c_oflag;
+ linux_tcflag_t c_cflag;
+ linux_tcflag_t c_lflag;
+ linux_cc_t c_cc[LINUX_NCCS];
+ linux_cc_t c_line;
+ signed32 c_ispeed;
+ signed32 c_ospeed;
+};
+
+STATIC_INLINE_EMUL_UNIX void
+convert_to_linux_termios(unsigned_word addr,
+ struct termios *host,
+ cpu *processor,
+ unsigned_word cia)
+{
+ struct linux_termios target;
+ int i;
+
+ target.c_iflag = H2T_4 (host->c_iflag);
+ target.c_oflag = H2T_4 (host->c_oflag);
+ target.c_cflag = H2T_4 (host->c_cflag);
+ target.c_lflag = H2T_4 (host->c_lflag);
+
+ for (i = 0; i < LINUX_NCCS; i++)
+ target.c_cc[i] = 0;
+
+#ifdef VINTR
+ target.c_cc[LINUX_VINTR] = host->c_cc[VINTR];
+#endif
+
+#ifdef VQUIT
+ target.c_cc[LINUX_VQUIT] = host->c_cc[VQUIT];
+#endif
+
+#ifdef VERASE
+ target.c_cc[LINUX_VERASE] = host->c_cc[VERASE];
+#endif
+
+#ifdef VKILL
+ target.c_cc[LINUX_VKILL] = host->c_cc[VKILL];
+#endif
+
+#ifdef VEOF
+ target.c_cc[LINUX_VEOF] = host->c_cc[VEOF];
+#endif
+
+#ifdef VEOL
+ target.c_cc[LINUX_VEOL] = host->c_cc[VEOL];
+#endif
+
+#ifdef VEOL2
+ target.c_cc[LINUX_VEOL2] = host->c_cc[VEOL2];
+#endif
+
+#ifdef VSWTCH
+ target.c_cc[LINUX_VSWTC] = host->c_cc[VSWTCH];
+#endif
+
+#ifdef HAVE_TERMIOS_CLINE
+ target.c_line = host->c_line;
+#else
+ target.c_line = 0;
+#endif
+
+#ifdef HAVE_CFGETISPEED
+ target.c_ispeed = cfgetispeed (host);
+#else
+ target.c_ispeed = 0;
+#endif
+
+#ifdef HAVE_CFGETOSPEED
+ target.c_ospeed = cfgetospeed (host);
+#else
+ target.c_ospeed = 0;
+#endif
+
+ emul_write_buffer(&target, addr, sizeof(target), processor, cia);
+}
+#endif /* HAVE_TERMIOS_STRUCTURE */
+
+#ifndef HAVE_IOCTL
+#define do_linux_ioctl 0
+#else
+static void
+do_linux_ioctl(os_emul_data *emul,
+ unsigned call,
+ const int arg0,
+ cpu *processor,
+ unsigned_word cia)
+{
+ int fildes = cpu_registers(processor)->gpr[arg0];
+ unsigned request = cpu_registers(processor)->gpr[arg0+1];
+ unsigned_word argp_addr = cpu_registers(processor)->gpr[arg0+2];
+ int status = 0;
+ const char *name = "<unknown>";
+
+#ifdef HAVE_TERMIOS_STRUCTURE
+ struct termios host_termio;
+
+#else
+#ifdef HAVE_TERMIO_STRUCTURE
+ struct termio host_termio;
+#endif
+#endif
+
+ switch (request)
+ {
+ case 0: /* make sure we have at least one case */
+ default:
+ status = -1;
+ errno = EINVAL;
+ break;
+
+#if defined(HAVE_TERMIO_STRUCTURE) || defined(HAVE_TERMIOS_STRUCTURE)
+#if defined(TCGETA) || defined(TCGETS) || defined(HAVE_TCGETATTR)
+ case LINUX_IOR('t', 23, struct linux_termio): /* TCGETA */
+ name = "TCGETA";
+#ifdef HAVE_TCGETATTR
+ status = tcgetattr(fildes, &host_termio);
+#elif defined(TCGETS)
+ status = ioctl (fildes, TCGETS, &host_termio);
+#else
+ status = ioctl (fildes, TCGETA, &host_termio);
+#endif
+ if (status == 0)
+ convert_to_linux_termio (argp_addr, &host_termio, processor, cia);
+ break;
+#endif /* TCGETA */
+#endif /* HAVE_TERMIO_STRUCTURE */
+
+#ifdef HAVE_TERMIOS_STRUCTURE
+#if defined(TCGETS) || defined(HAVE_TCGETATTR)
+ case LINUX_IOR('t', 19, struct linux_termios): /* TCGETS */
+ name = "TCGETS";
+#ifdef HAVE_TCGETATTR
+ status = tcgetattr(fildes, &host_termio);
+#else
+ status = ioctl (fildes, TCGETS, &host_termio);
+#endif
+ if (status == 0)
+ convert_to_linux_termios (argp_addr, &host_termio, processor, cia);
+ break;
+#endif /* TCGETS */
+#endif /* HAVE_TERMIOS_STRUCTURE */
+ }
+
+ emul_write_status(processor, status, errno);
+
+ if (WITH_TRACE && ppc_trace[trace_os_emul])
+ printf_filtered ("%d, 0x%x [%s], 0x%lx", fildes, request, name, (long)argp_addr);
+}
+#endif /* HAVE_IOCTL */
+
+static emul_syscall_descriptor linux_descriptors[] = {
+ /* 0 */ { 0, "setup" },
+ /* 1 */ { do_unix_exit, "exit" },
+ /* 2 */ { 0, "fork" },
+ /* 3 */ { do_unix_read, "read" },
+ /* 4 */ { do_unix_write, "write" },
+ /* 5 */ { do_unix_open, "open" },
+ /* 6 */ { do_unix_close, "close" },
+ /* 7 */ { 0, "waitpid" },
+ /* 8 */ { 0, "creat" },
+ /* 9 */ { do_unix_link, "link" },
+ /* 10 */ { do_unix_unlink, "unlink" },
+ /* 11 */ { 0, "execve" },
+ /* 12 */ { do_unix_chdir, "chdir" },
+ /* 13 */ { do_unix_time, "time" },
+ /* 14 */ { 0, "mknod" },
+ /* 15 */ { 0, "chmod" },
+ /* 16 */ { 0, "chown" },
+ /* 17 */ { 0, "break" },
+ /* 18 */ { 0, "stat" },
+ /* 19 */ { do_unix_lseek, "lseek" },
+ /* 20 */ { do_unix_getpid, "getpid" },
+ /* 21 */ { 0, "mount" },
+ /* 22 */ { 0, "umount" },
+ /* 23 */ { 0, "setuid" },
+ /* 24 */ { do_unix_getuid, "getuid" },
+ /* 25 */ { 0, "stime" },
+ /* 26 */ { 0, "ptrace" },
+ /* 27 */ { 0, "alarm" },
+ /* 28 */ { 0, "fstat" },
+ /* 29 */ { 0, "pause" },
+ /* 30 */ { 0, "utime" },
+ /* 31 */ { 0, "stty" },
+ /* 32 */ { 0, "gtty" },
+ /* 33 */ { do_unix_access, "access" },
+ /* 34 */ { 0, "nice" },
+ /* 35 */ { 0, "ftime" },
+ /* 36 */ { 0, "sync" },
+ /* 37 */ { 0, "kill" },
+ /* 38 */ { 0, "rename" },
+ /* 39 */ { do_unix_mkdir, "mkdir" },
+ /* 40 */ { do_unix_rmdir, "rmdir" },
+ /* 41 */ { do_unix_dup, "dup" },
+ /* 42 */ { 0, "pipe" },
+ /* 43 */ { 0, "times" },
+ /* 44 */ { 0, "prof" },
+ /* 45 */ { do_unix_break, "brk" },
+ /* 46 */ { 0, "setgid" },
+ /* 47 */ { do_unix_getgid, "getgid" },
+ /* 48 */ { 0, "signal" },
+ /* 49 */ { do_unix_geteuid, "geteuid" },
+ /* 50 */ { do_unix_getegid, "getegid" },
+ /* 51 */ { 0, "acct" },
+ /* 52 */ { 0, "phys" },
+ /* 53 */ { 0, "lock" },
+ /* 54 */ { do_linux_ioctl, "ioctl" },
+ /* 55 */ { 0, "fcntl" },
+ /* 56 */ { 0, "mpx" },
+ /* 57 */ { 0, "setpgid" },
+ /* 58 */ { 0, "ulimit" },
+ /* 59 */ { 0, "olduname" },
+ /* 60 */ { do_unix_umask, "umask" },
+ /* 61 */ { 0, "chroot" },
+ /* 62 */ { 0, "ustat" },
+ /* 63 */ { do_unix_dup2, "dup2" },
+ /* 64 */ { do_unix_getppid, "getppid" },
+ /* 65 */ { 0, "getpgrp" },
+ /* 66 */ { 0, "setsid" },
+ /* 67 */ { 0, "sigaction" },
+ /* 68 */ { 0, "sgetmask" },
+ /* 69 */ { 0, "ssetmask" },
+ /* 70 */ { 0, "setreuid" },
+ /* 71 */ { 0, "setregid" },
+ /* 72 */ { 0, "sigsuspend" },
+ /* 73 */ { 0, "sigpending" },
+ /* 74 */ { 0, "sethostname" },
+ /* 75 */ { 0, "setrlimit" },
+ /* 76 */ { 0, "getrlimit" },
+ /* 77 */ { do_unix_getrusage, "getrusage" },
+ /* 78 */ { do_unix_gettimeofday, "gettimeofday" },
+ /* 79 */ { 0, "settimeofday" },
+ /* 80 */ { 0, "getgroups" },
+ /* 81 */ { 0, "setgroups" },
+ /* 82 */ { 0, "select" },
+ /* 83 */ { do_unix_symlink, "symlink" },
+ /* 84 */ { 0, "lstat" },
+ /* 85 */ { 0, "readlink" },
+ /* 86 */ { 0, "uselib" },
+ /* 87 */ { 0, "swapon" },
+ /* 88 */ { 0, "reboot" },
+ /* 89 */ { 0, "readdir" },
+ /* 90 */ { 0, "mmap" },
+ /* 91 */ { 0, "munmap" },
+ /* 92 */ { 0, "truncate" },
+ /* 93 */ { 0, "ftruncate" },
+ /* 94 */ { 0, "fchmod" },
+ /* 95 */ { 0, "fchown" },
+ /* 96 */ { 0, "getpriority" },
+ /* 97 */ { 0, "setpriority" },
+ /* 98 */ { 0, "profil" },
+ /* 99 */ { 0, "statfs" },
+ /* 100 */ { 0, "fstatfs" },
+ /* 101 */ { 0, "ioperm" },
+ /* 102 */ { 0, "socketcall" },
+ /* 103 */ { 0, "syslog" },
+ /* 104 */ { 0, "setitimer" },
+ /* 105 */ { 0, "getitimer" },
+ /* 106 */ { do_linux_stat, "newstat" },
+ /* 107 */ { do_linux_lstat, "newlstat" },
+ /* 108 */ { do_linux_fstat, "newfstat" },
+ /* 109 */ { 0, "uname" },
+ /* 110 */ { 0, "iopl" },
+ /* 111 */ { 0, "vhangup" },
+ /* 112 */ { 0, "idle" },
+ /* 113 */ { 0, "vm86" },
+ /* 114 */ { 0, "wait4" },
+ /* 115 */ { 0, "swapoff" },
+ /* 116 */ { 0, "sysinfo" },
+ /* 117 */ { 0, "ipc" },
+ /* 118 */ { 0, "fsync" },
+ /* 119 */ { 0, "sigreturn" },
+ /* 120 */ { 0, "clone" },
+ /* 121 */ { 0, "setdomainname" },
+ /* 122 */ { 0, "newuname" },
+ /* 123 */ { 0, "modify_ldt" },
+ /* 124 */ { 0, "adjtimex" },
+ /* 125 */ { 0, "mprotect" },
+ /* 126 */ { 0, "sigprocmask" },
+ /* 127 */ { 0, "create_module" },
+ /* 128 */ { 0, "init_module" },
+ /* 129 */ { 0, "delete_module" },
+ /* 130 */ { 0, "get_kernel_syms" },
+ /* 131 */ { 0, "quotactl" },
+ /* 132 */ { 0, "getpgid" },
+ /* 133 */ { 0, "fchdir" },
+ /* 134 */ { 0, "bdflush" },
+ /* 135 */ { 0, "sysfs" },
+ /* 136 */ { 0, "personality" },
+ /* 137 */ { 0, "afs_syscall" },
+ /* 138 */ { 0, "setfsuid" },
+ /* 139 */ { 0, "setfsgid" },
+ /* 140 */ { 0, "llseek" },
+ /* 141 */ { 0, "getdents" },
+ /* 142 */ { 0, "newselect" },
+ /* 143 */ { 0, "flock" },
+ /* 144 */ { 0, "msync" },
+ /* 145 */ { 0, "readv" },
+ /* 146 */ { 0, "writev" },
+ /* 147 */ { 0, "getsid" },
+ /* 148 */ { 0, "fdatasync" },
+ /* 149 */ { 0, "sysctl" },
+ /* 150 */ { 0, "mlock" },
+ /* 151 */ { 0, "munlock" },
+ /* 152 */ { 0, "mlockall" },
+ /* 153 */ { 0, "munlockall" },
+ /* 154 */ { 0, "sched_setparam" },
+ /* 155 */ { 0, "sched_getparam" },
+ /* 156 */ { 0, "sched_setscheduler" },
+ /* 157 */ { 0, "sched_getscheduler" },
+ /* 158 */ { 0, "sched_yield" },
+ /* 159 */ { 0, "sched_get_priority_max" },
+ /* 160 */ { 0, "sched_get_priority_min" },
+ /* 161 */ { 0, "sched_rr_get_interval" },
+};
+
+static char *(linux_error_names[]) = {
+ /* 0 */ "ESUCCESS",
+ /* 1 */ "EPERM",
+ /* 2 */ "ENOENT",
+ /* 3 */ "ESRCH",
+ /* 4 */ "EINTR",
+ /* 5 */ "EIO",
+ /* 6 */ "ENXIO",
+ /* 7 */ "E2BIG",
+ /* 8 */ "ENOEXEC",
+ /* 9 */ "EBADF",
+ /* 10 */ "ECHILD",
+ /* 11 */ "EAGAIN",
+ /* 12 */ "ENOMEM",
+ /* 13 */ "EACCES",
+ /* 14 */ "EFAULT",
+ /* 15 */ "ENOTBLK",
+ /* 16 */ "EBUSY",
+ /* 17 */ "EEXIST",
+ /* 18 */ "EXDEV",
+ /* 19 */ "ENODEV",
+ /* 20 */ "ENOTDIR",
+ /* 21 */ "EISDIR",
+ /* 22 */ "EINVAL",
+ /* 23 */ "ENFILE",
+ /* 24 */ "EMFILE",
+ /* 25 */ "ENOTTY",
+ /* 26 */ "ETXTBSY",
+ /* 27 */ "EFBIG",
+ /* 28 */ "ENOSPC",
+ /* 29 */ "ESPIPE",
+ /* 30 */ "EROFS",
+ /* 31 */ "EMLINK",
+ /* 32 */ "EPIPE",
+ /* 33 */ "EDOM",
+ /* 34 */ "ERANGE",
+ /* 35 */ "EDEADLK",
+ /* 36 */ "ENAMETOOLONG",
+ /* 37 */ "ENOLCK",
+ /* 38 */ "ENOSYS",
+ /* 39 */ "ENOTEMPTY",
+ /* 40 */ "ELOOP",
+ /* 41 */ 0,
+ /* 42 */ "ENOMSG",
+ /* 43 */ "EIDRM",
+ /* 44 */ "ECHRNG",
+ /* 45 */ "EL2NSYNC",
+ /* 46 */ "EL3HLT",
+ /* 47 */ "EL3RST",
+ /* 48 */ "ELNRNG",
+ /* 49 */ "EUNATCH",
+ /* 50 */ "ENOCSI",
+ /* 51 */ "EL2HLT",
+ /* 52 */ "EBADE",
+ /* 53 */ "EBADR",
+ /* 54 */ "EXFULL",
+ /* 55 */ "ENOANO",
+ /* 56 */ "EBADRQC",
+ /* 57 */ "EBADSLT",
+ /* 58 */ "EDEADLOCK",
+ /* 59 */ "EBFONT",
+ /* 60 */ "ENOSTR",
+ /* 61 */ "ENODATA",
+ /* 62 */ "ETIME",
+ /* 63 */ "ENOSR",
+ /* 64 */ "ENONET",
+ /* 65 */ "ENOPKG",
+ /* 66 */ "EREMOTE",
+ /* 67 */ "ENOLINK",
+ /* 68 */ "EADV",
+ /* 69 */ "ESRMNT",
+ /* 70 */ "ECOMM",
+ /* 71 */ "EPROTO",
+ /* 72 */ "EMULTIHOP",
+ /* 73 */ "EDOTDOT",
+ /* 74 */ "EBADMSG",
+ /* 75 */ "EOVERFLOW",
+ /* 76 */ "ENOTUNIQ",
+ /* 77 */ "EBADFD",
+ /* 78 */ "EREMCHG",
+ /* 79 */ "ELIBACC",
+ /* 80 */ "ELIBBAD",
+ /* 81 */ "ELIBSCN",
+ /* 82 */ "ELIBMAX",
+ /* 83 */ "ELIBEXEC",
+ /* 84 */ "EILSEQ",
+ /* 85 */ "ERESTART",
+ /* 86 */ "ESTRPIPE",
+ /* 87 */ "EUSERS",
+ /* 88 */ "ENOTSOCK",
+ /* 89 */ "EDESTADDRREQ",
+ /* 90 */ "EMSGSIZE",
+ /* 91 */ "EPROTOTYPE",
+ /* 92 */ "ENOPROTOOPT",
+ /* 93 */ "EPROTONOSUPPORT",
+ /* 94 */ "ESOCKTNOSUPPORT",
+ /* 95 */ "EOPNOTSUPP",
+ /* 96 */ "EPFNOSUPPORT",
+ /* 97 */ "EAFNOSUPPORT",
+ /* 98 */ "EADDRINUSE",
+ /* 99 */ "EADDRNOTAVAIL",
+ /* 100 */ "ENETDOWN",
+ /* 101 */ "ENETUNREACH",
+ /* 102 */ "ENETRESET",
+ /* 103 */ "ECONNABORTED",
+ /* 104 */ "ECONNRESET",
+ /* 105 */ "ENOBUFS",
+ /* 106 */ "EISCONN",
+ /* 107 */ "ENOTCONN",
+ /* 108 */ "ESHUTDOWN",
+ /* 109 */ "ETOOMANYREFS",
+ /* 110 */ "ETIMEDOUT",
+ /* 111 */ "ECONNREFUSED",
+ /* 112 */ "EHOSTDOWN",
+ /* 113 */ "EHOSTUNREACH",
+ /* 114 */ "EALREADY",
+ /* 115 */ "EINPROGRESS",
+ /* 116 */ "ESTALE",
+ /* 117 */ "EUCLEAN",
+ /* 118 */ "ENOTNAM",
+ /* 119 */ "ENAVAIL",
+ /* 120 */ "EISNAM",
+ /* 121 */ "EREMOTEIO",
+ /* 122 */ "EDQUOT",
+};
+
+static char *(linux_signal_names[]) = {
+ /* 0 */ 0,
+ /* 1 */ "SIGHUP",
+ /* 2 */ "SIGINT",
+ /* 3 */ "SIGQUIT",
+ /* 4 */ "SIGILL",
+ /* 5 */ "SIGTRAP",
+ /* 6 */ "SIGABRT",
+ /* 6 */ "SIGIOT",
+ /* 7 */ "SIGBUS",
+ /* 8 */ "SIGFPE",
+ /* 9 */ "SIGKILL",
+ /* 10 */ "SIGUSR1",
+ /* 11 */ "SIGSEGV",
+ /* 12 */ "SIGUSR2",
+ /* 13 */ "SIGPIPE",
+ /* 14 */ "SIGALRM",
+ /* 15 */ "SIGTERM",
+ /* 16 */ "SIGSTKFLT",
+ /* 17 */ "SIGCHLD",
+ /* 18 */ "SIGCONT",
+ /* 19 */ "SIGSTOP",
+ /* 20 */ "SIGTSTP",
+ /* 21 */ "SIGTTIN",
+ /* 22 */ "SIGTTOU",
+ /* 23 */ "SIGURG",
+ /* 24 */ "SIGXCPU",
+ /* 25 */ "SIGXFSZ",
+ /* 26 */ "SIGVTALRM",
+ /* 27 */ "SIGPROF",
+ /* 28 */ "SIGWINCH",
+ /* 29 */ "SIGIO",
+ /* 30 */ "SIGPWR",
+ /* 31 */ "SIGUNUSED",
+};
+
+static emul_syscall emul_linux_syscalls = {
+ linux_descriptors,
+ sizeof(linux_descriptors) / sizeof(linux_descriptors[0]),
+ linux_error_names,
+ sizeof(linux_error_names) / sizeof(linux_error_names[0]),
+ linux_signal_names,
+ sizeof(linux_signal_names) / sizeof(linux_signal_names[0]),
+};
+
+
+/* Linux's os_emul interface, most are just passed on to the generic
+ syscall stuff */
+
+static os_emul_data *
+emul_linux_create(device *root,
+ bfd *image,
+ const char *name)
+{
+ /* check that this emulation is really for us */
+ if (name != NULL && strcmp(name, "linux") != 0)
+ return NULL;
+
+ if (image == NULL)
+ return NULL;
+
+ return emul_unix_create(root, image, "linux", &emul_linux_syscalls);
+}
+
+static void
+emul_linux_init(os_emul_data *emul_data,
+ int nr_cpus)
+{
+ /* nothing yet */
+}
+
+static void
+emul_linux_system_call(cpu *processor,
+ unsigned_word cia,
+ os_emul_data *emul_data)
+{
+ emul_do_system_call(emul_data,
+ emul_data->syscalls,
+ cpu_registers(processor)->gpr[0],
+ 3, /*r3 contains arg0*/
+ processor,
+ cia);
+}
+
+const os_emul emul_linux = {
+ "linux",
+ emul_linux_create,
+ emul_linux_init,
+ emul_linux_system_call,
+ 0, /*instruction_call*/
+ 0 /*data*/
+};
+
+#endif /* _EMUL_UNIX_C_ */
diff --git a/gnu/dist/sim/ppc/emul_unix.h b/gnu/dist/sim/ppc/emul_unix.h
new file mode 100644
index 00000000000..6695cc7aa81
--- /dev/null
+++ b/gnu/dist/sim/ppc/emul_unix.h
@@ -0,0 +1,28 @@
+/* This file is part of the program psim.
+
+ Copyright (C) 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.
+
+ */
+
+
+#ifndef _EMUL_UNIX_H_
+#define _EMUL_UNIX_H_
+
+extern const os_emul emul_solaris;
+extern const os_emul emul_linux;
+
+#endif
diff --git a/gnu/dist/sim/ppc/events.c b/gnu/dist/sim/ppc/events.c
index 0212aa711a8..0b27971931b 100644
--- a/gnu/dist/sim/ppc/events.c
+++ b/gnu/dist/sim/ppc/events.c
@@ -1,6 +1,6 @@
/* This file is part of the program psim.
- Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
+ 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
@@ -25,19 +25,25 @@
#include "basics.h"
#include "events.h"
+#include <signal.h>
+
+
/* 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. The first event occures at time 0 - system start.
+ event.
TIME_FROM_EVENT: The current distance from TIME_OF_EVENT. If an
event is pending, this will be positive. If no future event is
pending this will be negative. This variable is decremented once
for each iteration of a clock cycle.
+ Initially, the clock is started at time one (1) with TIME_OF_EVENT
+ == 0 and TIME_FROM_EVENT == -1.
+
Clearly there is a bug in that this code assumes that the absolute
time counter will never become greater than 2^62. */
@@ -50,6 +56,7 @@ struct _event_entry {
};
struct _event_queue {
+ int processing;
event_entry *queue;
event_entry *volatile held;
event_entry *volatile *volatile held_end;
@@ -64,9 +71,11 @@ event_queue_create(void)
{
event_queue *new_event_queue = ZALLOC(event_queue);
+ new_event_queue->processing = 0;
new_event_queue->queue = NULL;
new_event_queue->held = NULL;
new_event_queue->held_end = &new_event_queue->held;
+
/* both times are already zero */
return new_event_queue;
}
@@ -79,16 +88,25 @@ event_queue_init(event_queue *queue)
event_entry *event;
/* drain the interrupt queue */
- /*-LOCK-*/
- event = queue->held;
- while (event != NULL) {
- event_entry *dead = event;
- event = event->next;
- zfree(dead);
+ {
+#if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK)
+ sigset_t old_mask;
+ sigset_t new_mask;
+ sigfillset(&new_mask);
+ /*-LOCK-*/ sigprocmask(SIG_SETMASK, &new_mask, &old_mask);
+#endif
+ event = queue->held;
+ while (event != NULL) {
+ event_entry *dead = event;
+ event = event->next;
+ zfree(dead);
+ }
+ queue->held = NULL;
+ queue->held_end = &queue->held;
+#if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK)
+ /*-UNLOCK-*/ sigprocmask(SIG_SETMASK, &old_mask, NULL);
+#endif
}
- queue->held = NULL;
- queue->held_end = &queue->held;
- /*-UNLOCK-*/
/* drain the normal queue */
event = queue->queue;
@@ -99,12 +117,35 @@ event_queue_init(event_queue *queue)
}
queue->queue = NULL;
- /* wind time back to zero */
+ /* wind time back to one */
+ queue->processing = 0;
queue->time_of_event = 0;
- queue->time_from_event = 0;
+ queue->time_from_event = -1;
}
+INLINE_EVENTS\
+(signed64)
+event_queue_time(event_queue *queue)
+{
+ return queue->time_of_event - queue->time_from_event;
+}
+STATIC_INLINE_EVENTS\
+(void)
+update_time_from_event(event_queue *events)
+{
+ signed64 current_time = event_queue_time(events);
+ if (events->queue != NULL) {
+ events->time_from_event = (events->queue->time_of_event - current_time);
+ events->time_of_event = events->queue->time_of_event;
+ }
+ else {
+ events->time_of_event = current_time - 1;
+ events->time_from_event = -1;
+ }
+ ASSERT(current_time == event_queue_time(events));
+ ASSERT((events->time_from_event >= 0) == (events->queue != NULL));
+}
STATIC_INLINE_EVENTS\
(void)
@@ -113,35 +154,33 @@ insert_event_entry(event_queue *events,
signed64 delta)
{
event_entry *curr;
- event_entry **last;
+ event_entry **prev;
signed64 time_of_event;
- if (delta <= 0)
- error("can not schedule event for current time\n");
+ if (delta < 0)
+ error("what is past is past!\n");
/* compute when the event should occure */
- time_of_event = (events->time_of_event
- - events->time_from_event
- + delta);
+ time_of_event = event_queue_time(events) + delta;
/* find the queue insertion point - things are time ordered */
- last = &events->queue;
+ prev = &events->queue;
curr = events->queue;
while (curr != NULL && time_of_event >= curr->time_of_event) {
- last = &curr->next;
+ ASSERT(curr->next == NULL
+ || curr->time_of_event <= curr->next->time_of_event);
+ prev = &curr->next;
curr = curr->next;
}
+ ASSERT(curr == NULL || time_of_event < curr->time_of_event);
/* insert it */
new_event->next = curr;
- *last = new_event;
+ *prev = new_event;
new_event->time_of_event = time_of_event;
/* adjust the time until the first event */
- events->time_from_event = (events->queue->time_of_event
- - (events->time_of_event
- - events->time_from_event));
- events->time_of_event = events->queue->time_of_event;
+ update_time_from_event(events);
}
INLINE_EVENTS\
@@ -155,7 +194,13 @@ event_queue_schedule(event_queue *events,
new_event->data = data;
new_event->handler = handler;
insert_event_entry(events, new_event, delta_time);
- return new_event;
+ TRACE(trace_events, ("event scheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx\n",
+ (long)event_queue_time(events),
+ (long)new_event,
+ (long)new_event->time_of_event,
+ (long)new_event->handler,
+ (long)new_event->data));
+ return (event_entry_tag)new_event;
}
@@ -173,17 +218,33 @@ event_queue_schedule_after_signal(event_queue *events,
new_event->time_of_event = delta_time; /* work it out later */
new_event->next = NULL;
- /*-LOCK-*/
- if (events->held == NULL) {
- events->held = new_event;
- }
- else {
- *events->held_end = new_event;
+ {
+#if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK)
+ sigset_t old_mask;
+ sigset_t new_mask;
+ sigfillset(&new_mask);
+ /*-LOCK-*/ sigprocmask(SIG_SETMASK, &new_mask, &old_mask);
+#endif
+ if (events->held == NULL) {
+ events->held = new_event;
+ }
+ else {
+ *events->held_end = new_event;
+ }
+ events->held_end = &new_event->next;
+#if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK)
+ /*-UNLOCK-*/ sigprocmask(SIG_SETMASK, &old_mask, NULL);
+#endif
}
- events->held_end = &new_event->next;
- /*-UNLOCK-*/
- return new_event;
+ TRACE(trace_events, ("event scheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx\n",
+ (long)event_queue_time(events),
+ (long)new_event,
+ (long)new_event->time_of_event,
+ (long)new_event->handler,
+ (long)new_event->data));
+
+ return (event_entry_tag)new_event;
}
@@ -192,18 +253,32 @@ INLINE_EVENTS\
event_queue_deschedule(event_queue *events,
event_entry_tag event_to_remove)
{
+ event_entry *to_remove = (event_entry*)event_to_remove;
+ ASSERT((events->time_from_event >= 0) == (events->queue != NULL));
if (event_to_remove != NULL) {
event_entry *current;
event_entry **ptr_to_current;
for (ptr_to_current = &events->queue, current = *ptr_to_current;
- current != NULL && current != event_to_remove;
+ current != NULL && current != to_remove;
ptr_to_current = &current->next, current = *ptr_to_current);
- if (current == event_to_remove) {
+ if (current == to_remove) {
*ptr_to_current = current->next;
+ TRACE(trace_events, ("event descheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx\n",
+ (long)event_queue_time(events),
+ (long)event_to_remove,
+ (long)current->time_of_event,
+ (long)current->handler,
+ (long)current->data));
zfree(current);
- /* Just forget to recompute the delay to the next event */
+ update_time_from_event(events);
+ }
+ else {
+ TRACE(trace_events, ("event descheduled at %ld - tag 0x%lx - not found\n",
+ (long)event_queue_time(events),
+ (long)event_to_remove));
}
}
+ ASSERT((events->time_from_event >= 0) == (events->queue != NULL));
}
@@ -213,16 +288,34 @@ INLINE_EVENTS\
(int)
event_queue_tick(event_queue *events)
{
- /* remove things from the asynchronous event queue onto the real one */
+ signed64 time_from_event;
+
+ /* we should only be here when the previous tick has been fully processed */
+ ASSERT(!events->processing);
+
+ /* move any events that were queued by any signal handlers onto the
+ real event queue. BTW: When inlining, having this code here,
+ instead of in event_queue_process() causes GCC to put greater
+ weight on keeping the pointer EVENTS in a register. This, in
+ turn results in better code being output. */
if (events->held != NULL) {
event_entry *held_events;
event_entry *curr_event;
- /*-LOCK-*/
- held_events = events->held;
- events->held = NULL;
- events->held_end = &events->held;
- /*-UNLOCK-*/
+ {
+#if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK)
+ sigset_t old_mask;
+ sigset_t new_mask;
+ sigfillset(&new_mask);
+ /*-LOCK-*/ sigprocmask(SIG_SETMASK, &new_mask, &old_mask);
+#endif
+ held_events = events->held;
+ events->held = NULL;
+ events->held_end = &events->held;
+#if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK)
+ /*-UNLOCK-*/ sigprocmask(SIG_SETMASK, &old_mask, NULL);
+#endif
+ }
do {
curr_event = held_events;
@@ -233,41 +326,43 @@ event_queue_tick(event_queue *events)
/* advance time, checking to see if we've reached time zero which
would indicate the time for the next event has arrived */
- events->time_from_event -= 1;
- return events->time_from_event == 0;
+ time_from_event = events->time_from_event;
+ events->time_from_event = time_from_event - 1;
+ return time_from_event == 0;
}
+
+
INLINE_EVENTS\
(void)
event_queue_process(event_queue *events)
{
- if (events->time_from_event == 0) {
- /* consume all events for this or earlier times */
- do {
- event_entry *to_do = events->queue;
- events->queue = to_do->next;
- to_do->handler(events,
- to_do->data);
- zfree(to_do);
- } while (events->queue != NULL
- && events->queue->time_of_event <= events->time_of_event);
- /* re-caculate time for new events */
- if (events->queue != NULL) {
- events->time_from_event = (events->queue->time_of_event
- - events->time_of_event);
- events->time_of_event = events->queue->time_of_event;
- }
- else {
- /* nothing to do, time_from_event will go negative */
- }
+ signed64 event_time = event_queue_time(events);
+
+ ASSERT((events->time_from_event == -1 && events->queue != NULL)
+ || events->processing); /* something to do */
+
+ /* consume all events for this or earlier times. Be careful to
+ allow a new event to appear under our feet */
+ events->processing = 1;
+ while (events->queue != NULL
+ && events->queue->time_of_event <= event_time) {
+ event_entry *to_do = events->queue;
+ event_handler *handler = to_do->handler;
+ void *data = to_do->data;
+ events->queue = to_do->next;
+ TRACE(trace_events, ("event issued at %ld - tag 0x%lx - handler 0x%lx, data 0x%lx\n",
+ (long)event_time,
+ (long)to_do,
+ (long)handler,
+ (long)data));
+ zfree(to_do);
+ handler(data);
}
-}
+ events->processing = 0;
-INLINE_EVENTS\
-(signed64)
-event_queue_time(event_queue *queue)
-{
- return queue->time_of_event - queue->time_from_event;
+ /* re-caculate time for new events */
+ update_time_from_event(events);
}
diff --git a/gnu/dist/sim/ppc/events.h b/gnu/dist/sim/ppc/events.h
index 9aa41700e30..be7be50cfcb 100644
--- a/gnu/dist/sim/ppc/events.h
+++ b/gnu/dist/sim/ppc/events.h
@@ -22,12 +22,10 @@
#ifndef _EVENTS_H_
#define _EVENTS_H_
-typedef struct _event_queue event_queue;
-typedef void *event_entry_tag;
+/* typedef struct _event_queue event_queue; */
+/* typedef struct _event_entry_tag *event_entry_tag; */
-typedef void event_handler
-(event_queue *queue,
- void *data);
+typedef void event_handler(void *data);
INLINE_EVENTS\
(event_queue *) event_queue_create
diff --git a/gnu/dist/sim/ppc/filter.c b/gnu/dist/sim/ppc/filter.c
new file mode 100644
index 00000000000..c901a1777f1
--- /dev/null
+++ b/gnu/dist/sim/ppc/filter.c
@@ -0,0 +1,150 @@
+/* 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.
+
+ */
+
+
+#include <stdio.h>
+
+#include "config.h"
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#endif
+
+#include "misc.h"
+#include "filter.h"
+
+struct _filter {
+ char *flag;
+ filter *next;
+};
+
+
+filter *
+new_filter(const char *filt,
+ filter *filters)
+{
+ while (strlen(filt) > 0) {
+ filter *new_filter;
+ /* break up the filt list */
+ char *end = strchr(filt, ',');
+ char *next;
+ int len;
+ if (end == NULL) {
+ end = strchr(filt, '\0');
+ next = end;
+ }
+ else {
+ next = end + 1;
+ }
+ len = end - filt;
+ /* add to filter list */
+ new_filter = ZALLOC(filter);
+ new_filter->flag = (char*)zalloc(len + 1);
+ strncpy(new_filter->flag, filt, len);
+ new_filter->next = filters;
+ filters = new_filter;
+ filt = next;
+ }
+ return filters;
+}
+
+
+int
+is_filtered_out(const char *flags,
+ filter *filters)
+{
+ while (strlen(flags) > 0) {
+ int present;
+ filter *filt = filters;
+ /* break the string up */
+ char *end = strchr(flags, ',');
+ char *next;
+ int len;
+ if (end == NULL) {
+ end = strchr(flags, '\0');
+ next = end;
+ }
+ else {
+ next = end + 1;
+ }
+ len = end - flags;
+ /* check that it is present */
+ present = 0;
+ filt = filters;
+ while (filt != NULL) {
+ if (strncmp(flags, filt->flag, len) == 0
+ && strlen(filt->flag) == len) {
+ present = 1;
+ break;
+ }
+ filt = filt->next;
+ }
+ if (!present)
+ return 1;
+ flags = next;
+ }
+ return 0;
+}
+
+
+int
+it_is(const char *flag,
+ const char *flags)
+{
+ int flag_len = strlen(flag);
+ while (*flags != '\0') {
+ if (!strncmp(flags, flag, flag_len)
+ && (flags[flag_len] == ',' || flags[flag_len] == '\0'))
+ return 1;
+ while (*flags != ',') {
+ if (*flags == '\0')
+ return 0;
+ flags++;
+ }
+ flags++;
+ }
+ return 0;
+}
+
+
+#ifdef MAIN
+int
+main(int argc, char **argv)
+{
+ filter *filters = NULL;
+ int i;
+ if (argc < 2) {
+ printf("Usage: filter <flags> <filter> ...\n");
+ exit (1);
+ }
+ /* load the filter up */
+ for (i = 2; i < argc; i++)
+ filters = new_filter(argv[i], filters);
+ if (is_filtered_out(argv[1], filters))
+ printf("fail\n");
+ else
+ printf("pass\n");
+ return 0;
+}
+#endif
diff --git a/gnu/dist/sim/ppc/filter.h b/gnu/dist/sim/ppc/filter.h
new file mode 100644
index 00000000000..814f704f8d2
--- /dev/null
+++ b/gnu/dist/sim/ppc/filter.h
@@ -0,0 +1,43 @@
+/* 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.
+
+ */
+
+
+typedef struct _filter filter;
+
+
+/* append the filter onto the end of the list */
+
+extern filter *new_filter
+(const char *filt,
+ filter *filters);
+
+
+/* returns true if the flags are non empty and some are missing from the filter list */
+
+extern int is_filtered_out
+(const char *flags,
+ filter *filters);
+
+/* true if the flag is in the list */
+
+extern int it_is
+(const char *flag,
+ const char *flags);
+
diff --git a/gnu/dist/sim/ppc/filter_filename.c b/gnu/dist/sim/ppc/filter_filename.c
index 0a2fea06e29..6d62d7a35ae 100644
--- a/gnu/dist/sim/ppc/filter_filename.c
+++ b/gnu/dist/sim/ppc/filter_filename.c
@@ -23,11 +23,11 @@
#include "filter_filename.h"
/* Shorten traces by eliminating the directory component to filenames. */
-extern char *
-filter_filename (char *filename)
+extern const char *
+filter_filename (const char *filename)
{
- char *p = filename;
- char *last = filename;
+ const char *p = filename;
+ const char *last = filename;
int ch;
while ((ch = *p++) != '\0' && ch != ':')
diff --git a/gnu/dist/sim/ppc/filter_filename.h b/gnu/dist/sim/ppc/filter_filename.h
index 60cc614f09e..a60b4f2d7dc 100644
--- a/gnu/dist/sim/ppc/filter_filename.h
+++ b/gnu/dist/sim/ppc/filter_filename.h
@@ -22,6 +22,6 @@
#define _FILTER_FILENAME_H
/* Remove directory part from filename */
-extern char *
-filter_filename(char *filename);
+extern const char *
+filter_filename(const char *filename);
#endif
diff --git a/gnu/dist/sim/ppc/gen-icache.c b/gnu/dist/sim/ppc/gen-icache.c
new file mode 100644
index 00000000000..0d58ab1873a
--- /dev/null
+++ b/gnu/dist/sim/ppc/gen-icache.c
@@ -0,0 +1,675 @@
+/* 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.
+
+ */
+
+
+#include "misc.h"
+#include "lf.h"
+#include "table.h"
+
+#include "filter.h"
+
+#include "ld-decode.h"
+#include "ld-cache.h"
+#include "ld-insn.h"
+
+#include "igen.h"
+
+#include "gen-semantics.h"
+#include "gen-idecode.h"
+#include "gen-icache.h"
+
+
+
+static void
+print_icache_function_header(lf *file,
+ const char *basename,
+ insn_bits *expanded_bits,
+ int is_function_definition)
+{
+ lf_printf(file, "\n");
+ lf_print_function_type(file, ICACHE_FUNCTION_TYPE, "EXTERN_ICACHE", " ");
+ print_function_name(file,
+ basename,
+ expanded_bits,
+ function_name_prefix_icache);
+ lf_printf(file, "\n(%s)", ICACHE_FUNCTION_FORMAL);
+ if (!is_function_definition)
+ lf_printf(file, ";");
+ lf_printf(file, "\n");
+}
+
+
+void
+print_icache_declaration(insn_table *entry,
+ lf *file,
+ void *data,
+ insn *instruction,
+ int depth)
+{
+ if (generate_expanded_instructions) {
+ ASSERT(entry->nr_insn == 1);
+ print_icache_function_header(file,
+ entry->insns->file_entry->fields[insn_name],
+ entry->expanded_bits,
+ 0/* is not function definition */);
+ }
+ else {
+ print_icache_function_header(file,
+ instruction->file_entry->fields[insn_name],
+ NULL,
+ 0/* is not function definition */);
+ }
+}
+
+
+
+static void
+print_icache_extraction(lf *file,
+ insn *instruction,
+ const char *entry_name,
+ const char *entry_type,
+ const char *entry_expression,
+ const char *original_name,
+ const char *file_name,
+ int line_nr,
+ insn_field *cur_field,
+ insn_bits *bits,
+ icache_decl_type what_to_declare,
+ icache_body_type what_to_do,
+ const char *reason)
+{
+ const char *expression;
+ ASSERT(entry_name != NULL);
+
+ /* Define a storage area for the cache element */
+ if (what_to_declare == undef_variables) {
+ /* We've finished with the value - destory it */
+ lf_indent_suppress(file);
+ lf_printf(file, "#undef %s\n", entry_name);
+ return;
+ }
+ else if (what_to_declare == define_variables) {
+ lf_indent_suppress(file);
+ lf_printf(file, "#define %s ", entry_name);
+ }
+ else {
+ if (file_name != NULL)
+ lf_print__external_reference(file, line_nr, file_name);
+ lf_printf(file, "%s const %s UNUSED = ",
+ entry_type == NULL ? "unsigned" : entry_type,
+ entry_name);
+ }
+
+ /* define a value for that storage area as determined by what is in
+ the cache */
+ if (bits != NULL
+ && strcmp(entry_name, cur_field->val_string) == 0
+ && ((bits->opcode->is_boolean && bits->value == 0)
+ || (!bits->opcode->is_boolean))) {
+ /* The simple field has been made constant (as a result of
+ expanding instructions or similar). Remember that for a
+ boolean field, value is either 0 (implying the required
+ boolean_constant) or nonzero (implying some other value and
+ handled later below) - Define the variable accordingly */
+ expression = "constant field";
+ ASSERT(bits->field == cur_field);
+ ASSERT(entry_type == NULL);
+ if (bits->opcode->is_boolean)
+ lf_printf(file, "%d", bits->opcode->boolean_constant);
+ else if (bits->opcode->last < bits->field->last)
+ lf_printf(file, "%d",
+ bits->value << (bits->field->last - bits->opcode->last));
+ else
+ lf_printf(file, "%d", bits->value);
+ }
+ else if (bits != NULL
+ && original_name != NULL
+ && strncmp(entry_name,
+ original_name, strlen(original_name)) == 0
+ && strncmp(entry_name + strlen(original_name),
+ "_is_", strlen("_is_")) == 0
+ && ((bits->opcode->is_boolean
+ && (atol(entry_name + strlen(original_name) + strlen("_is_"))
+ == bits->opcode->boolean_constant))
+ || (!bits->opcode->is_boolean))) {
+ expression = "constant compare";
+ /* An entry, derived from ORIGINAL_NAME, is testing to see of the
+ ORIGINAL_NAME has a specific constant value. That value
+ matching a boolean or constant field */
+ if (bits->opcode->is_boolean)
+ lf_printf(file, "%d /* %s == %d */",
+ bits->value == 0,
+ original_name,
+ bits->opcode->boolean_constant);
+ else if (bits->opcode->last < bits->field->last)
+ lf_printf(file, "%d /* %s == %d */",
+ (atol(entry_name + strlen(original_name) + strlen("_is_"))
+ == (bits->value << (bits->field->last - bits->opcode->last))),
+ original_name,
+ (bits->value << (bits->field->last - bits->opcode->last)));
+ else
+ lf_printf(file, "%d /* %s == %d */",
+ (atol(entry_name + strlen(original_name) + strlen("_is_"))
+ == bits->value),
+ original_name,
+ bits->value);
+ }
+ else {
+ /* put the field in the local variable, possibly also enter it
+ into the cache */
+ expression = "extraction";
+ /* handle the cache */
+ if ((what_to_do & get_values_from_icache)
+ || (what_to_do & put_values_in_icache)) {
+ lf_printf(file, "cache_entry->crack.%s.%s",
+ instruction->file_entry->fields[insn_form],
+ entry_name);
+ if (what_to_do & put_values_in_icache) /* also put it in the cache? */
+ lf_printf(file, " = ");
+ }
+ if ((what_to_do & put_values_in_icache)
+ || what_to_do == do_not_use_icache) {
+ if (cur_field != NULL && strcmp(entry_name, cur_field->val_string) == 0)
+ lf_printf(file, "EXTRACTED32(instruction, %d, %d)",
+ i2target(hi_bit_nr, cur_field->first),
+ i2target(hi_bit_nr, cur_field->last));
+ else if (entry_expression != NULL)
+ lf_printf(file, "%s", entry_expression);
+ else
+ lf_printf(file, "eval_%s", entry_name);
+ }
+ }
+
+ if (!((what_to_declare == define_variables)
+ || (what_to_declare == undef_variables)))
+ lf_printf(file, ";");
+ if (reason != NULL)
+ lf_printf(file, " /* %s - %s */", reason, expression);
+ lf_printf(file, "\n");
+}
+
+
+void
+print_icache_body(lf *file,
+ insn *instruction,
+ insn_bits *expanded_bits,
+ cache_table *cache_rules,
+ icache_decl_type what_to_declare,
+ icache_body_type what_to_do)
+{
+ insn_field *cur_field;
+
+ /* extract instruction fields */
+ lf_printf(file, "/* extraction: %s ",
+ instruction->file_entry->fields[insn_format]);
+ switch (what_to_declare) {
+ case define_variables:
+ lf_printf(file, "#define");
+ break;
+ case declare_variables:
+ lf_printf(file, "declare");
+ break;
+ case undef_variables:
+ lf_printf(file, "#undef");
+ break;
+ }
+ lf_printf(file, " ");
+ switch (what_to_do) {
+ case get_values_from_icache:
+ lf_printf(file, "get-values-from-icache");
+ break;
+ case put_values_in_icache:
+ lf_printf(file, "put-values-in-icache");
+ break;
+ case both_values_and_icache:
+ lf_printf(file, "get-values-from-icache|put-values-in-icache");
+ break;
+ case do_not_use_icache:
+ lf_printf(file, "do-not-use-icache");
+ break;
+ }
+ lf_printf(file, " */\n");
+
+ for (cur_field = instruction->fields->first;
+ cur_field->first < insn_bit_size;
+ cur_field = cur_field->next) {
+ if (cur_field->is_string) {
+ insn_bits *bits;
+ int found_rule = 0;
+ /* find any corresponding value */
+ for (bits = expanded_bits;
+ bits != NULL;
+ bits = bits->last) {
+ if (bits->field == cur_field)
+ break;
+ }
+ /* try the cache rule table for what to do */
+ {
+ cache_table *cache_rule;
+ for (cache_rule = cache_rules;
+ cache_rule != NULL;
+ cache_rule = cache_rule->next) {
+ if (strcmp(cur_field->val_string, cache_rule->field_name) == 0) {
+ found_rule = 1;
+ if (cache_rule->type == scratch_value
+ && ((what_to_do & put_values_in_icache)
+ || what_to_do == do_not_use_icache))
+ print_icache_extraction(file,
+ instruction,
+ cache_rule->derived_name,
+ cache_rule->type_def,
+ cache_rule->expression,
+ cache_rule->field_name,
+ cache_rule->file_entry->file_name,
+ cache_rule->file_entry->line_nr,
+ cur_field,
+ bits,
+ what_to_declare,
+ do_not_use_icache,
+ "icache scratch");
+ else if (cache_rule->type == compute_value
+ && ((what_to_do & get_values_from_icache)
+ || what_to_do == do_not_use_icache))
+ print_icache_extraction(file,
+ instruction,
+ cache_rule->derived_name,
+ cache_rule->type_def,
+ cache_rule->expression,
+ cache_rule->field_name,
+ cache_rule->file_entry->file_name,
+ cache_rule->file_entry->line_nr,
+ cur_field,
+ bits,
+ what_to_declare,
+ do_not_use_icache,
+ "semantic compute");
+ else if (cache_rule->type == cache_value
+ && ((what_to_declare != undef_variables)
+ || !(what_to_do & put_values_in_icache)))
+ print_icache_extraction(file,
+ instruction,
+ cache_rule->derived_name,
+ cache_rule->type_def,
+ cache_rule->expression,
+ cache_rule->field_name,
+ cache_rule->file_entry->file_name,
+ cache_rule->file_entry->line_nr,
+ cur_field,
+ bits,
+ ((what_to_do & put_values_in_icache)
+ ? declare_variables
+ : what_to_declare),
+ what_to_do,
+ "in icache");
+ }
+ }
+ }
+ /* No rule at all, assume that this is needed in the semantic
+ function (when values are extracted from the icache) and
+ hence must be put into the cache */
+ if (found_rule == 0
+ && ((what_to_declare != undef_variables)
+ || !(what_to_do & put_values_in_icache)))
+ print_icache_extraction(file,
+ instruction,
+ cur_field->val_string,
+ NULL, NULL, NULL, /* type, exp, orig */
+ instruction->file_entry->file_name,
+ instruction->file_entry->line_nr,
+ cur_field,
+ bits,
+ ((what_to_do & put_values_in_icache)
+ ? declare_variables
+ : what_to_declare),
+ what_to_do,
+ "default in icache");
+ /* any thing else ... */
+ }
+ }
+
+ lf_print__internal_reference(file);
+
+ if ((code & generate_with_insn_in_icache)) {
+ lf_printf(file, "\n");
+ print_icache_extraction(file,
+ instruction,
+ "insn",
+ "instruction_word",
+ "instruction",
+ NULL, /* origin */
+ NULL, 0, /* file_name & line_nr */
+ NULL, NULL,
+ what_to_declare,
+ what_to_do,
+ NULL);
+ }
+}
+
+
+
+typedef struct _icache_tree icache_tree;
+struct _icache_tree {
+ char *name;
+ icache_tree *next;
+ icache_tree *children;
+};
+
+static icache_tree *
+icache_tree_insert(icache_tree *tree,
+ char *name)
+{
+ icache_tree *new_tree;
+ /* find it */
+ icache_tree **ptr_to_cur_tree = &tree->children;
+ icache_tree *cur_tree = *ptr_to_cur_tree;
+ while (cur_tree != NULL
+ && strcmp(cur_tree->name, name) < 0) {
+ ptr_to_cur_tree = &cur_tree->next;
+ cur_tree = *ptr_to_cur_tree;
+ }
+ ASSERT(cur_tree == NULL
+ || strcmp(cur_tree->name, name) >= 0);
+ /* already in the tree */
+ if (cur_tree != NULL
+ && strcmp(cur_tree->name, name) == 0)
+ return cur_tree;
+ /* missing, insert it */
+ ASSERT(cur_tree == NULL
+ || strcmp(cur_tree->name, name) > 0);
+ new_tree = ZALLOC(icache_tree);
+ new_tree->name = name;
+ new_tree->next = cur_tree;
+ *ptr_to_cur_tree = new_tree;
+ return new_tree;
+}
+
+
+static icache_tree *
+insn_table_cache_fields(insn_table *table)
+{
+ icache_tree *tree = ZALLOC(icache_tree);
+ insn *instruction;
+ for (instruction = table->insns;
+ instruction != NULL;
+ instruction = instruction->next) {
+ insn_field *field;
+ icache_tree *form =
+ icache_tree_insert(tree,
+ instruction->file_entry->fields[insn_form]);
+ for (field = instruction->fields->first;
+ field != NULL;
+ field = field->next) {
+ if (field->is_string)
+ icache_tree_insert(form, field->val_string);
+ }
+ }
+ return tree;
+}
+
+
+
+extern void
+print_icache_struct(insn_table *instructions,
+ cache_table *cache_rules,
+ lf *file)
+{
+ icache_tree *tree = insn_table_cache_fields(instructions);
+
+ lf_printf(file, "\n");
+ lf_printf(file, "#define WITH_IDECODE_CACHE_SIZE %d\n",
+ (code & generate_with_icache) ? icache_size : 0);
+ lf_printf(file, "\n");
+
+ /* create an instruction cache if being used */
+ if ((code & generate_with_icache)) {
+ icache_tree *form;
+ lf_printf(file, "typedef struct _idecode_cache {\n");
+ lf_printf(file, " unsigned_word address;\n");
+ lf_printf(file, " void *semantic;\n");
+ lf_printf(file, " union {\n");
+ for (form = tree->children;
+ form != NULL;
+ form = form->next) {
+ icache_tree *field;
+ lf_printf(file, " struct {\n");
+ if (code & generate_with_insn_in_icache)
+ lf_printf(file, " instruction_word insn;\n");
+ for (field = form->children;
+ field != NULL;
+ field = field->next) {
+ cache_table *cache_rule;
+ int found_rule = 0;
+ for (cache_rule = cache_rules;
+ cache_rule != NULL;
+ cache_rule = cache_rule->next) {
+ if (strcmp(field->name, cache_rule->field_name) == 0) {
+ found_rule = 1;
+ if (cache_rule->derived_name != NULL)
+ lf_printf(file, " %s %s; /* %s */\n",
+ (cache_rule->type_def == NULL
+ ? "unsigned"
+ : cache_rule->type_def),
+ cache_rule->derived_name,
+ cache_rule->field_name);
+ }
+ }
+ if (!found_rule)
+ lf_printf(file, " unsigned %s;\n", field->name);
+ }
+ lf_printf(file, " } %s;\n", form->name);
+ }
+ lf_printf(file, " } crack;\n");
+ lf_printf(file, "} idecode_cache;\n");
+ }
+ else {
+ /* alernativly, since no cache, emit a dummy definition for
+ idecode_cache so that code refering to the type can still compile */
+ lf_printf(file, "typedef void idecode_cache;\n");
+ }
+ lf_printf(file, "\n");
+}
+
+
+
+static void
+print_icache_function(lf *file,
+ insn *instruction,
+ insn_bits *expanded_bits,
+ opcode_field *opcodes,
+ cache_table *cache_rules)
+{
+ int indent;
+
+ /* generate code to enter decoded instruction into the icache */
+ lf_printf(file, "\n");
+ lf_print_function_type(file, ICACHE_FUNCTION_TYPE, "EXTERN_ICACHE", "\n");
+ indent = print_function_name(file,
+ instruction->file_entry->fields[insn_name],
+ expanded_bits,
+ function_name_prefix_icache);
+ lf_indent(file, +indent);
+ lf_printf(file, "(%s)\n", ICACHE_FUNCTION_FORMAL);
+ lf_indent(file, -indent);
+
+ /* function header */
+ lf_printf(file, "{\n");
+ lf_indent(file, +2);
+
+ print_my_defines(file, expanded_bits, instruction->file_entry);
+ print_itrace(file, instruction->file_entry, 1/*putting-value-in-cache*/);
+
+ print_idecode_validate(file, instruction, opcodes);
+
+ lf_printf(file, "\n");
+ lf_printf(file, "{\n");
+ lf_indent(file, +2);
+ if ((code & generate_with_semantic_icache))
+ lf_printf(file, "unsigned_word nia;\n");
+ print_icache_body(file,
+ instruction,
+ expanded_bits,
+ cache_rules,
+ ((code & generate_with_direct_access)
+ ? define_variables
+ : declare_variables),
+ ((code & generate_with_semantic_icache)
+ ? both_values_and_icache
+ : put_values_in_icache));
+
+ lf_printf(file, "\n");
+ lf_printf(file, "cache_entry->address = cia;\n");
+ lf_printf(file, "cache_entry->semantic = ");
+ print_function_name(file,
+ instruction->file_entry->fields[insn_name],
+ expanded_bits,
+ function_name_prefix_semantics);
+ lf_printf(file, ";\n");
+ lf_printf(file, "\n");
+
+ if ((code & generate_with_semantic_icache)) {
+ lf_printf(file, "/* semantic routine */\n");
+ print_semantic_body(file,
+ instruction,
+ expanded_bits,
+ opcodes);
+ lf_printf(file, "return nia;\n");
+ }
+
+ if (!(code & generate_with_semantic_icache)) {
+ lf_printf(file, "/* return the function proper */\n");
+ lf_printf(file, "return ");
+ print_function_name(file,
+ instruction->file_entry->fields[insn_name],
+ expanded_bits,
+ function_name_prefix_semantics);
+ lf_printf(file, ";\n");
+ }
+
+ if ((code & generate_with_direct_access))
+ print_icache_body(file,
+ instruction,
+ expanded_bits,
+ cache_rules,
+ undef_variables,
+ ((code & generate_with_semantic_icache)
+ ? both_values_and_icache
+ : put_values_in_icache));
+
+ lf_indent(file, -2);
+ lf_printf(file, "}\n");
+ lf_indent(file, -2);
+ lf_printf(file, "}\n");
+}
+
+
+void
+print_icache_definition(insn_table *entry,
+ lf *file,
+ void *data,
+ insn *instruction,
+ int depth)
+{
+ cache_table *cache_rules = (cache_table*)data;
+ if (generate_expanded_instructions) {
+ ASSERT(entry->nr_insn == 1
+ && entry->opcode == NULL
+ && entry->parent != NULL
+ && entry->parent->opcode != NULL);
+ ASSERT(entry->nr_insn == 1
+ && entry->opcode == NULL
+ && entry->parent != NULL
+ && entry->parent->opcode != NULL
+ && entry->parent->opcode_rule != NULL);
+ print_icache_function(file,
+ entry->insns,
+ entry->expanded_bits,
+ entry->opcode,
+ cache_rules);
+ }
+ else {
+ print_icache_function(file,
+ instruction,
+ NULL,
+ NULL,
+ cache_rules);
+ }
+}
+
+
+
+void
+print_icache_internal_function_declaration(insn_table *table,
+ lf *file,
+ void *data,
+ table_entry *function)
+{
+ ASSERT((code & generate_with_icache) != 0);
+ if (it_is("internal", function->fields[insn_flags])) {
+ lf_printf(file, "\n");
+ lf_print_function_type(file, ICACHE_FUNCTION_TYPE, "INLINE_ICACHE",
+ "\n");
+ print_function_name(file,
+ function->fields[insn_name],
+ NULL,
+ function_name_prefix_icache);
+ lf_printf(file, "\n(%s);\n", ICACHE_FUNCTION_FORMAL);
+ }
+}
+
+
+void
+print_icache_internal_function_definition(insn_table *table,
+ lf *file,
+ void *data,
+ table_entry *function)
+{
+ ASSERT((code & generate_with_icache) != 0);
+ if (it_is("internal", function->fields[insn_flags])) {
+ lf_printf(file, "\n");
+ lf_print_function_type(file, ICACHE_FUNCTION_TYPE, "INLINE_ICACHE",
+ "\n");
+ print_function_name(file,
+ function->fields[insn_name],
+ NULL,
+ function_name_prefix_icache);
+ lf_printf(file, "\n(%s)\n", ICACHE_FUNCTION_FORMAL);
+ lf_printf(file, "{\n");
+ lf_indent(file, +2);
+ lf_printf(file, "/* semantic routine */\n");
+ table_entry_print_cpp_line_nr(file, function);
+ if ((code & generate_with_semantic_icache)) {
+ lf_print__c_code(file, function->annex);
+ lf_printf(file, "error(\"Internal function must longjump\\n\");\n");
+ lf_printf(file, "return 0;\n");
+ }
+ else {
+ lf_printf(file, "return ");
+ print_function_name(file,
+ function->fields[insn_name],
+ NULL,
+ function_name_prefix_semantics);
+ lf_printf(file, ";\n");
+ }
+
+ lf_print__internal_reference(file);
+ lf_indent(file, -2);
+ lf_printf(file, "}\n");
+ }
+}
diff --git a/gnu/dist/sim/ppc/gen-icache.h b/gnu/dist/sim/ppc/gen-icache.h
new file mode 100644
index 00000000000..7d9e0e16c01
--- /dev/null
+++ b/gnu/dist/sim/ppc/gen-icache.h
@@ -0,0 +1,68 @@
+/* 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.
+
+ */
+
+
+
+/* Output code to manipulate the instruction cache: either create it
+ or reference it */
+
+typedef enum {
+ declare_variables,
+ define_variables,
+ undef_variables,
+} icache_decl_type;
+
+typedef enum {
+ do_not_use_icache = 0,
+ get_values_from_icache = 0x1,
+ put_values_in_icache = 0x2,
+ both_values_and_icache = 0x3,
+} icache_body_type;
+
+extern void print_icache_body
+(lf *file,
+ insn *instruction,
+ insn_bits *expanded_bits,
+ cache_table *cache_rules,
+ icache_decl_type what_to_declare,
+ icache_body_type what_to_do);
+
+
+/* Output an instruction cache decode function */
+
+extern insn_handler print_icache_declaration;
+extern insn_handler print_icache_definition;
+
+
+/* Output an instruction cache support function */
+
+extern function_handler print_icache_internal_function_declaration;
+extern function_handler print_icache_internal_function_definition;
+
+
+/* Output the instruction cache table data structure */
+
+extern void print_icache_struct
+(insn_table *instructions,
+ cache_table *cache_rules,
+ lf *file);
+
+
+/* Output a single instructions decoder */
diff --git a/gnu/dist/sim/ppc/gen-idecode.c b/gnu/dist/sim/ppc/gen-idecode.c
new file mode 100644
index 00000000000..397dcde1816
--- /dev/null
+++ b/gnu/dist/sim/ppc/gen-idecode.c
@@ -0,0 +1,1545 @@
+/* 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.
+
+ */
+
+#include "misc.h"
+#include "lf.h"
+#include "table.h"
+
+#include "filter.h"
+
+#include "ld-decode.h"
+#include "ld-cache.h"
+#include "ld-insn.h"
+
+#include "igen.h"
+
+#include "gen-idecode.h"
+#include "gen-icache.h"
+#include "gen-semantics.h"
+
+
+
+static void
+lf_print_opcodes(lf *file,
+ insn_table *table)
+{
+ if (table != NULL) {
+ while (1) {
+ ASSERT(table->opcode != NULL);
+ lf_printf(file, "_%d_%d",
+ table->opcode->first,
+ table->opcode->last);
+ if (table->parent == NULL) break;
+ lf_printf(file, "__%d", table->opcode_nr);
+ table = table->parent;
+ }
+ }
+}
+
+/****************************************************************/
+
+
+static void
+lf_print_table_name(lf *file,
+ insn_table *table)
+{
+ lf_printf(file, "idecode_table");
+ lf_print_opcodes(file, table);
+}
+
+
+
+static void
+print_idecode_table(lf *file,
+ insn_table *entry,
+ const char *result)
+{
+ lf_printf(file, "/* prime the search */\n");
+ lf_printf(file, "idecode_table_entry *table = ");
+ lf_print_table_name(file, entry);
+ lf_printf(file, ";\n");
+ lf_printf(file, "int opcode = EXTRACTED32(instruction, %d, %d);\n",
+ i2target(hi_bit_nr, entry->opcode->first),
+ i2target(hi_bit_nr, entry->opcode->last));
+ lf_printf(file, "idecode_table_entry *table_entry = table + opcode;\n");
+
+ lf_printf(file, "\n");
+ lf_printf(file, "/* iterate until a leaf */\n");
+ lf_printf(file, "while (1) {\n");
+ lf_printf(file, " signed shift = table_entry->shift;\n");
+ lf_printf(file, "if (shift == function_entry) break;\n");
+ lf_printf(file, " if (shift >= 0) {\n");
+ lf_printf(file, " table = ((idecode_table_entry*)\n");
+ lf_printf(file, " table_entry->function_or_table);\n");
+ lf_printf(file, " opcode = ((instruction & table_entry->mask)\n");
+ lf_printf(file, " >> shift);\n");
+ lf_printf(file, " table_entry = table + opcode;\n");
+ lf_printf(file, " }\n");
+ lf_printf(file, " else {\n");
+ lf_printf(file, " /* must be a boolean */\n");
+ lf_printf(file, " ASSERT(table_entry->shift == boolean_entry);\n");
+ lf_printf(file, " opcode = ((instruction & table_entry->mask)\n");
+ lf_printf(file, " != table_entry->value);\n");
+ lf_printf(file, " table = ((idecode_table_entry*)\n");
+ lf_printf(file, " table_entry->function_or_table);\n");
+ lf_printf(file, " table_entry = table + opcode;\n");
+ lf_printf(file, " }\n");
+ lf_printf(file, "}\n");
+
+ lf_printf(file, "\n");
+ lf_printf(file, "/* call the leaf code */\n");
+ if ((code & generate_jumps)) {
+ lf_printf(file, "goto *table_entry->function_or_table;\n");
+ }
+ else {
+ lf_printf(file, "%s ", result);
+ if ((code & generate_with_icache)) {
+ lf_printf(file, "(((idecode_icache*)table_entry->function_or_table)\n");
+ lf_printf(file, " (%s));\n", ICACHE_FUNCTION_ACTUAL);
+ }
+ else {
+ lf_printf(file, "((idecode_semantic*)table_entry->function_or_table)\n");
+ lf_printf(file, " (%s);\n", SEMANTIC_FUNCTION_ACTUAL);
+ }
+ }
+}
+
+
+static void
+print_idecode_table_start(insn_table *table,
+ lf *file,
+ void *data,
+ int depth)
+{
+ ASSERT(depth == 0);
+ /* start of the table */
+ if (table->opcode_rule->gen == array_gen) {
+ lf_printf(file, "\n");
+ lf_printf(file, "static idecode_table_entry ");
+ lf_print_table_name(file, table);
+ lf_printf(file, "[] = {\n");
+ }
+}
+
+static void
+print_idecode_table_leaf(insn_table *entry,
+ lf *file,
+ void *data,
+ insn *instruction,
+ int depth)
+{
+ ASSERT(entry->parent != NULL);
+ ASSERT(depth == 0);
+
+ /* add an entry to the table */
+ if (entry->parent->opcode_rule->gen == array_gen) {
+ lf_printf(file, " /*%d*/ { ", entry->opcode_nr);
+ if (entry->opcode == NULL) {
+ /* table leaf entry */
+ lf_printf(file, "function_entry, 0, 0, ");
+ if ((code & generate_jumps))
+ lf_printf(file, "&&");
+ print_function_name(file,
+ entry->insns->file_entry->fields[insn_name],
+ entry->expanded_bits,
+ ((code & generate_with_icache)
+ ? function_name_prefix_icache
+ : function_name_prefix_semantics));
+ }
+ else if (entry->opcode_rule->gen == switch_gen
+ || entry->opcode_rule->gen == goto_switch_gen
+ || entry->opcode_rule->gen == padded_switch_gen) {
+ /* table calling switch statement */
+ lf_printf(file, "function_entry, 0, 0, ");
+ if ((code & generate_jumps))
+ lf_printf(file, "&&");
+ lf_print_table_name(file, entry);
+ }
+ else if (entry->opcode->is_boolean) {
+ /* table `calling' boolean table */
+ lf_printf(file, "boolean_entry, ");
+ lf_printf(file, "MASK32(%d, %d), ",
+ i2target(hi_bit_nr, entry->opcode->first),
+ i2target(hi_bit_nr, entry->opcode->last));
+ lf_printf(file, "INSERTED32(%d, %d, %d), ",
+ entry->opcode->boolean_constant,
+ i2target(hi_bit_nr, entry->opcode->first),
+ i2target(hi_bit_nr, entry->opcode->last));
+ lf_print_table_name(file, entry);
+ }
+ else {
+ /* table `calling' another table */
+ lf_printf(file, "%d, ", insn_bit_size - entry->opcode->last - 1);
+ lf_printf(file, "MASK32(%d,%d), ",
+ i2target(hi_bit_nr, entry->opcode->first),
+ i2target(hi_bit_nr, entry->opcode->last));
+ lf_printf(file, "0, ");
+ lf_print_table_name(file, entry);
+ }
+ lf_printf(file, " },\n");
+ }
+}
+
+static void
+print_idecode_table_end(insn_table *table,
+ lf *file,
+ void *data,
+ int depth)
+{
+ ASSERT(depth == 0);
+ if (table->opcode_rule->gen == array_gen) {
+ lf_printf(file, "};\n");
+ }
+}
+
+static void
+print_idecode_table_padding(insn_table *table,
+ lf *file,
+ void *data,
+ int depth,
+ int opcode_nr)
+{
+ ASSERT(depth == 0);
+ if (table->opcode_rule->gen == array_gen) {
+ lf_printf(file, " /*%d*/ { function_entry, 0, 0, ", opcode_nr);
+ if ((code & generate_jumps))
+ lf_printf(file, "&&");
+ lf_printf(file, "%s_illegal },\n",
+ ((code & generate_with_icache) ? "icache" : "semantic"));
+ }
+}
+
+
+/****************************************************************/
+
+
+static void
+print_goto_switch_name(lf *file,
+ insn_table *entry)
+{
+ lf_printf(file, "case_");
+ if (entry->opcode == NULL)
+ print_function_name(file,
+ entry->insns->file_entry->fields[insn_name],
+ entry->expanded_bits,
+ ((code & generate_with_icache)
+ ? function_name_prefix_icache
+ : function_name_prefix_semantics));
+ else
+ lf_print_table_name(file, entry);
+}
+
+static void
+print_goto_switch_table_leaf(insn_table *entry,
+ lf *file,
+ void *data,
+ insn *instruction,
+ int depth)
+{
+ ASSERT(entry->parent != NULL);
+ ASSERT(depth == 0);
+ ASSERT(entry->parent->opcode_rule->gen == goto_switch_gen);
+ ASSERT(entry->parent->opcode);
+
+ lf_printf(file, "&&");
+ print_goto_switch_name(file, entry);
+ lf_printf(file, ",\n");
+}
+
+static void
+print_goto_switch_table_padding(insn_table *table,
+ lf *file,
+ void *data,
+ int depth,
+ int opcode_nr)
+{
+ ASSERT(depth == 0);
+ ASSERT(table->opcode_rule->gen == goto_switch_gen);
+
+ lf_printf(file, "&&illegal_");
+ lf_print_table_name(file, table);
+ lf_printf(file, ",\n");
+}
+
+static void
+print_goto_switch_break(lf *file,
+ insn_table *entry)
+{
+ lf_printf(file, "goto break_");
+ lf_print_table_name(file, entry->parent);
+ lf_printf(file, ";\n");
+}
+
+
+static void
+print_goto_switch_table(lf *file,
+ insn_table *table)
+{
+ lf_printf(file, "const static void *");
+ lf_print_table_name(file, table);
+ lf_printf(file, "[] = {\n");
+ lf_indent(file, +2);
+ insn_table_traverse_tree(table,
+ file, NULL/*data*/,
+ 0,
+ NULL/*start*/,
+ print_goto_switch_table_leaf,
+ NULL/*end*/,
+ print_goto_switch_table_padding);
+ lf_indent(file, -2);
+ lf_printf(file, "};\n");
+}
+
+
+void print_idecode_switch
+(lf *file,
+ insn_table *table,
+ const char *result);
+
+static void
+idecode_switch_start(insn_table *table,
+ lf *file,
+ void *data,
+ int depth)
+{
+ /* const char *result = data; */
+ ASSERT(depth == 0);
+ ASSERT(table->opcode_rule->gen == switch_gen
+ || table->opcode_rule->gen == goto_switch_gen
+ || table->opcode_rule->gen == padded_switch_gen);
+
+ if (table->opcode->is_boolean
+ || table->opcode_rule->gen == switch_gen
+ || table->opcode_rule->gen == padded_switch_gen) {
+ lf_printf(file, "switch (EXTRACTED32(instruction, %d, %d)) {\n",
+ i2target(hi_bit_nr, table->opcode->first),
+ i2target(hi_bit_nr, table->opcode->last));
+ }
+ else if (table->opcode_rule->gen == goto_switch_gen) {
+ if (table->parent != NULL
+ && (table->parent->opcode_rule->gen == switch_gen
+ || table->parent->opcode_rule->gen == goto_switch_gen
+ || table->parent->opcode_rule->gen == padded_switch_gen)) {
+ lf_printf(file, "{\n");
+ lf_indent(file, +2);
+ }
+ print_goto_switch_table(file, table);
+ lf_printf(file, "ASSERT(EXTRACTED32(instruction, %d, %d)\n",
+ i2target(hi_bit_nr, table->opcode->first),
+ i2target(hi_bit_nr, table->opcode->last));
+ lf_printf(file, " < (sizeof(");
+ lf_print_table_name(file, table);
+ lf_printf(file, ") / sizeof(void*)));\n");
+ lf_printf(file, "goto *");
+ lf_print_table_name(file, table);
+ lf_printf(file, "[EXTRACTED32(instruction, %d, %d)];\n",
+ i2target(hi_bit_nr, table->opcode->first),
+ i2target(hi_bit_nr, table->opcode->last));
+ }
+ else {
+ ASSERT("bad switch" == NULL);
+ }
+}
+
+
+static void
+idecode_switch_leaf(insn_table *entry,
+ lf *file,
+ void *data,
+ insn *instruction,
+ int depth)
+{
+ const char *result = data;
+ ASSERT(entry->parent != NULL);
+ ASSERT(depth == 0);
+ ASSERT(entry->parent->opcode_rule->gen == switch_gen
+ || entry->parent->opcode_rule->gen == goto_switch_gen
+ || entry->parent->opcode_rule->gen == padded_switch_gen);
+ ASSERT(entry->parent->opcode);
+
+ if (entry->parent->opcode->is_boolean
+ && entry->opcode_nr == 0) {
+ /* boolean false target */
+ lf_printf(file, "case %d:\n", entry->parent->opcode->boolean_constant);
+ }
+ else if (entry->parent->opcode->is_boolean
+ && entry->opcode_nr != 0) {
+ /* boolean true case */
+ lf_printf(file, "default:\n");
+ }
+ else if (entry->parent->opcode_rule->gen == switch_gen
+ || entry->parent->opcode_rule->gen == padded_switch_gen) {
+ /* normal goto */
+ lf_printf(file, "case %d:\n", entry->opcode_nr);
+ }
+ else if (entry->parent->opcode_rule->gen == goto_switch_gen) {
+ /* lf_indent(file, -1); */
+ print_goto_switch_name(file, entry);
+ lf_printf(file, ":\n");
+ /* lf_indent(file, +1); */
+ }
+ else {
+ ASSERT("bad switch" == NULL);
+ }
+ lf_indent(file, +2);
+ {
+ if (entry->opcode == NULL) {
+ /* switch calling leaf */
+ if ((code & generate_jumps))
+ lf_printf(file, "goto ");
+ if ((code & generate_calls))
+ lf_printf(file, "%s ", result);
+ print_function_name(file,
+ entry->insns->file_entry->fields[insn_name],
+ entry->expanded_bits,
+ ((code & generate_with_icache)
+ ? function_name_prefix_icache
+ : function_name_prefix_semantics));
+ if ((code & generate_calls))
+ lf_printf(file, "(%s)", SEMANTIC_FUNCTION_ACTUAL);
+ lf_printf(file, ";\n");
+ }
+ else if (entry->opcode_rule->gen == switch_gen
+ || entry->opcode_rule->gen == goto_switch_gen
+ || entry->opcode_rule->gen == padded_switch_gen) {
+ /* switch calling switch */
+ print_idecode_switch(file, entry, result);
+ }
+ else {
+ /* switch looking up a table */
+ lf_printf(file, "{\n");
+ lf_indent(file, -2);
+ print_idecode_table(file, entry, result);
+ lf_indent(file, -2);
+ lf_printf(file, "}\n");
+ }
+ if (entry->parent->opcode->is_boolean
+ || entry->parent->opcode_rule->gen == switch_gen
+ || entry->parent->opcode_rule->gen == padded_switch_gen) {
+ lf_printf(file, "break;\n");
+ }
+ else if (entry->parent->opcode_rule->gen == goto_switch_gen) {
+ print_goto_switch_break(file, entry);
+ }
+ else {
+ ASSERT("bad switch" == NULL);
+ }
+ }
+ lf_indent(file, -2);
+}
+
+
+static void
+print_idecode_switch_illegal(lf *file,
+ const char *result)
+{
+ lf_indent(file, +2);
+ print_idecode_illegal(file, result);
+ lf_printf(file, "break;\n");
+ lf_indent(file, -2);
+}
+
+static void
+idecode_switch_end(insn_table *table,
+ lf *file,
+ void *data,
+ int depth)
+{
+ const char *result = data;
+ ASSERT(depth == 0);
+ ASSERT(table->opcode_rule->gen == switch_gen
+ || table->opcode_rule->gen == goto_switch_gen
+ || table->opcode_rule->gen == padded_switch_gen);
+ ASSERT(table->opcode);
+
+ if (table->opcode->is_boolean) {
+ lf_printf(file, "}\n");
+ }
+ else if (table->opcode_rule->gen == switch_gen
+ || table->opcode_rule->gen == padded_switch_gen) {
+ lf_printf(file, "default:\n");
+ switch (table->opcode_rule->gen) {
+ case switch_gen:
+ print_idecode_switch_illegal(file, result);
+ break;
+ case padded_switch_gen:
+ lf_printf(file, " error(\"Internal error - bad switch generated\\n\");\n");
+ lf_printf(file, " break;\n");
+ break;
+ default:
+ ASSERT("bad switch" == NULL);
+ }
+ lf_printf(file, "}\n");
+ }
+ else if (table->opcode_rule->gen == goto_switch_gen) {
+ lf_printf(file, "illegal_");
+ lf_print_table_name(file, table);
+ lf_printf(file, ":\n");
+ print_idecode_illegal(file, result);
+ lf_printf(file, "break_");
+ lf_print_table_name(file, table);
+ lf_printf(file, ":;\n");
+ if (table->parent != NULL
+ && (table->parent->opcode_rule->gen == switch_gen
+ || table->parent->opcode_rule->gen == goto_switch_gen
+ || table->parent->opcode_rule->gen == padded_switch_gen)) {
+ lf_indent(file, -2);
+ lf_printf(file, "}\n");
+ }
+ }
+ else {
+ ASSERT("bad switch" == NULL);
+ }
+}
+
+static void
+idecode_switch_padding(insn_table *table,
+ lf *file,
+ void *data,
+ int depth,
+ int opcode_nr)
+{
+ const char *result = data;
+ ASSERT(depth == 0);
+ ASSERT(table->opcode_rule->gen == switch_gen
+ || table->opcode_rule->gen == goto_switch_gen
+ || table->opcode_rule->gen == padded_switch_gen);
+
+ switch (table->opcode_rule->gen) {
+ case switch_gen:
+ break;
+ case padded_switch_gen:
+ lf_printf(file, "case %d:\n", opcode_nr);
+ print_idecode_switch_illegal(file, result);
+ break;
+ case goto_switch_gen:
+ /* no padding needed */
+ break;
+ default:
+ ASSERT("bad switch" != NULL);
+ }
+}
+
+
+void
+print_idecode_switch(lf *file,
+ insn_table *table,
+ const char *result)
+{
+ insn_table_traverse_tree(table,
+ file, (void*)result,
+ 0,
+ idecode_switch_start,
+ idecode_switch_leaf,
+ idecode_switch_end,
+ idecode_switch_padding);
+}
+
+
+static void
+print_idecode_switch_function_header(lf *file,
+ insn_table *table,
+ int is_function_definition)
+{
+ lf_printf(file, "\n");
+ if ((code & generate_calls)) {
+ lf_printf(file, "static ");
+ if ((code & generate_with_icache))
+ lf_printf(file, "idecode_semantic *");
+ else
+ lf_printf(file, "unsigned_word");
+ if (is_function_definition)
+ lf_printf(file, "\n");
+ else
+ lf_printf(file, " ");
+ lf_print_table_name(file, table);
+ lf_printf(file, "\n(%s)", ICACHE_FUNCTION_FORMAL);
+ if (!is_function_definition)
+ lf_printf(file, ";");
+ lf_printf(file, "\n");
+ }
+ if ((code & generate_jumps) && is_function_definition) {
+ lf_indent(file, -1);
+ lf_print_table_name(file, table);
+ lf_printf(file, ":\n");
+ lf_indent(file, +1);
+ }
+}
+
+
+static void
+idecode_declare_if_switch(insn_table *table,
+ lf *file,
+ void *data,
+ int depth)
+{
+ if ((table->opcode_rule->gen == switch_gen
+ || table->opcode_rule->gen == goto_switch_gen
+ || table->opcode_rule->gen == padded_switch_gen)
+ && table->parent != NULL /* don't declare the top one yet */
+ && table->parent->opcode_rule->gen == array_gen) {
+ print_idecode_switch_function_header(file,
+ table,
+ 0/*isnt function definition*/);
+ }
+}
+
+
+static void
+idecode_expand_if_switch(insn_table *table,
+ lf *file,
+ void *data,
+ int depth)
+{
+ if ((table->opcode_rule->gen == switch_gen
+ || table->opcode_rule->gen == goto_switch_gen
+ || table->opcode_rule->gen == padded_switch_gen)
+ && table->parent != NULL /* don't expand the top one yet */
+ && table->parent->opcode_rule->gen == array_gen) {
+ print_idecode_switch_function_header(file,
+ table,
+ 1/*is function definition*/);
+ if ((code & generate_calls)) {
+ lf_printf(file, "{\n");
+ lf_indent(file, +2);
+ }
+ print_idecode_switch(file, table, "return");
+ if ((code & generate_calls)) {
+ lf_indent(file, -2);
+ lf_printf(file, "}\n");
+ }
+ }
+}
+
+
+/****************************************************************/
+
+
+static void
+print_idecode_lookups(lf *file,
+ insn_table *table,
+ cache_table *cache_rules)
+{
+ int depth;
+
+ /* output switch function declarations where needed by tables */
+ insn_table_traverse_tree(table,
+ file, NULL,
+ 1,
+ idecode_declare_if_switch, /* START */
+ NULL, NULL, NULL);
+
+ /* output tables where needed */
+ for (depth = insn_table_depth(table);
+ depth > 0;
+ depth--) {
+ insn_table_traverse_tree(table,
+ file, NULL,
+ 1-depth,
+ print_idecode_table_start,
+ print_idecode_table_leaf,
+ print_idecode_table_end,
+ print_idecode_table_padding);
+ }
+
+ /* output switch functions where needed */
+ insn_table_traverse_tree(table,
+ file, NULL,
+ 1,
+ idecode_expand_if_switch, /* START */
+ NULL, NULL, NULL);
+}
+
+
+static void
+print_idecode_body(lf *file,
+ insn_table *table,
+ const char *result)
+{
+ if (table->opcode_rule->gen == switch_gen
+ || table->opcode_rule->gen == goto_switch_gen
+ || table->opcode_rule->gen == padded_switch_gen)
+ print_idecode_switch(file, table, result);
+ else
+ print_idecode_table(file, table, result);
+}
+
+
+/****************************************************************/
+
+
+static void
+print_run_until_stop_body(lf *file,
+ insn_table *table,
+ int can_stop)
+{
+ /* Output the function to execute real code:
+
+ Unfortunatly, there are multiple cases to consider vis:
+
+ <icache> X <smp> X <events> X <keep-running-flag> X ...
+
+ Consequently this function is written in multiple different ways */
+
+ lf_putstr(file, "{\n");
+ lf_indent(file, +2);
+ lf_putstr(file, "jmp_buf halt;\n");
+ lf_putstr(file, "jmp_buf restart;\n");
+ if (!generate_smp) {
+ lf_putstr(file, "cpu *processor = NULL;\n");
+ lf_putstr(file, "unsigned_word cia = -1;\n");
+ }
+ lf_putstr(file, "int last_cpu;\n");
+ if (generate_smp) {
+ lf_putstr(file, "int current_cpu;\n");
+ }
+
+ if ((code & generate_with_icache)) {
+ lf_putstr(file, "int cpu_nr;\n");
+ lf_putstr(file, "\n");
+ lf_putstr(file, "/* flush the icache of a possible break insn */\n");
+ lf_putstr(file, "for (cpu_nr = 0; cpu_nr < nr_cpus; cpu_nr++)\n");
+ lf_putstr(file, " cpu_flush_icache(processors[cpu_nr]);\n");
+ }
+
+ lf_putstr(file, "\n");
+ lf_putstr(file, "/* set the halt target initially */\n");
+ lf_putstr(file, "psim_set_halt_and_restart(system, &halt, NULL);\n");
+ lf_putstr(file, "if (setjmp(halt))\n");
+ lf_putstr(file, " return;\n");
+
+ lf_putstr(file, "\n");
+ lf_putstr(file, "/* where were we before the halt? */\n");
+ lf_putstr(file, "last_cpu = psim_last_cpu(system);\n");
+
+ lf_putstr(file, "\n");
+ lf_putstr(file, "/* check for need to force event processing first */\n");
+ lf_putstr(file, "if (WITH_EVENTS) {\n");
+ lf_putstr(file, " if (last_cpu == nr_cpus) {\n");
+ lf_putstr(file, " /* halted during event processing */\n");
+ lf_putstr(file, " event_queue_process(events);\n");
+ lf_putstr(file, " last_cpu = -1;\n");
+ lf_putstr(file, " }\n");
+ lf_putstr(file, " else if (last_cpu == nr_cpus - 1) {\n");
+ lf_putstr(file, " /* last cpu did halt */\n");
+ lf_putstr(file, " if (event_queue_tick(events)) {\n");
+ lf_putstr(file, " event_queue_process(events);\n");
+ lf_putstr(file, " }\n");
+ lf_putstr(file, " last_cpu = -1;\n");
+ lf_putstr(file, " }\n");
+ lf_putstr(file, "}\n");
+ lf_putstr(file, "else {\n");
+ lf_putstr(file, " if (last_cpu == nr_cpus - 1)\n");
+ lf_putstr(file, " /* cpu zero is next */\n");
+ lf_putstr(file, " last_cpu = -1;\n");
+ lf_putstr(file, "}\n");
+
+ lf_putstr(file, "\n");
+ lf_putstr(file, "/* have ensured that the event queue can not be first */\n");
+ lf_putstr(file, "ASSERT(last_cpu >= -1 && last_cpu < nr_cpus - 1);\n");
+
+ if (!generate_smp) {
+
+ lf_putstr(file, "
+/* CASE 1: NO SMP (with or with out instruction cache).
+
+ In this case, we can take advantage of the fact that the current
+ instruction address does not need to be returned to the cpu object
+ after every execution of an instruction. Instead it only needs to
+ be saved when either A. the main loop exits or B. A cpu-halt or
+ cpu-restart call forces the loop to be re-enered. The later
+ functions always save the current cpu instruction address.
+
+ Two subcases also exist that with and that without an instruction
+ cache.
+
+ An additional complexity is the need to ensure that a 1:1 ratio
+ is maintained between the execution of an instruction and the
+ incrementing of the simulation clock */");
+
+ lf_putstr(file, "\n");
+
+ lf_putstr(file, "\n");
+ lf_putstr(file, "/* now add restart target as ready to run */\n");
+ lf_putstr(file, "psim_set_halt_and_restart(system, &halt, &restart);\n");
+ lf_putstr(file, "if (setjmp(restart)) {\n");
+ lf_putstr(file, " if (WITH_EVENTS) {\n");
+ lf_putstr(file, " /* when restart, cpu must have been last, clock next */\n");
+ lf_putstr(file, " if (event_queue_tick(events)) {\n");
+ lf_putstr(file, " event_queue_process(events);\n");
+ lf_putstr(file, " }\n");
+ lf_putstr(file, " }\n");
+ lf_putstr(file, "}\n");
+
+ lf_putstr(file, "\n");
+ lf_putstr(file, "/* prime the main loop */\n");
+ lf_putstr(file, "processor = processors[0];\n");
+ lf_putstr(file, "cia = cpu_get_program_counter(processor);\n");
+
+ lf_putstr(file, "\n");
+ lf_putstr(file, "while (1) {\n");
+ lf_indent(file, +2);
+
+ if (!(code & generate_with_icache)) {
+ lf_putstr(file, "instruction_word instruction =\n");
+ lf_putstr(file, " vm_instruction_map_read(cpu_instruction_map(processor), processor, cia);\n");
+ lf_putstr(file, "\n");
+ print_idecode_body(file, table, "cia =");;
+ }
+
+ if ((code & generate_with_icache)) {
+ lf_putstr(file, "idecode_cache *cache_entry =\n");
+ lf_putstr(file, " cpu_icache_entry(processor, cia);\n");
+ lf_putstr(file, "if (cache_entry->address == cia) {\n");
+ lf_putstr(file, " /* cache hit */\n");
+ lf_putstr(file, " idecode_semantic *const semantic = cache_entry->semantic;\n");
+ lf_putstr(file, " cia = semantic(processor, cache_entry, cia);\n");
+ /* tail */
+ if (can_stop) {
+ lf_putstr(file, "if (keep_running != NULL && !*keep_running)\n");
+ lf_putstr(file, " cpu_halt(processor, cia, was_continuing, 0/*ignore*/);\n");
+ }
+ lf_putstr(file, "}\n");
+ lf_putstr(file, "else {\n");
+ lf_putstr(file, " /* cache miss */\n");
+ if (!(code & generate_with_semantic_icache)) {
+ lf_indent(file, +2);
+ lf_putstr(file, "idecode_semantic *semantic;\n");
+ lf_indent(file, -2);
+ }
+ lf_putstr(file, " instruction_word instruction =\n");
+ lf_putstr(file, " vm_instruction_map_read(cpu_instruction_map(processor), processor, cia);\n");
+ lf_putstr(file, " if (WITH_MON != 0)\n");
+ lf_putstr(file, " mon_event(mon_event_icache_miss, processor, cia);\n");
+ if ((code & generate_with_semantic_icache)) {
+ lf_putstr(file, "{\n");
+ lf_indent(file, +2);
+ print_idecode_body(file, table, "cia =");
+ lf_indent(file, -2);
+ lf_putstr(file, "}\n");
+ }
+ else {
+ print_idecode_body(file, table, "semantic =");
+ lf_putstr(file, " cia = semantic(processor, cache_entry, cia);\n");
+ }
+ lf_putstr(file, "}\n");
+ }
+
+ /* events */
+ lf_putstr(file, "\n");
+ lf_putstr(file, "/* process any events */\n");
+ lf_putstr(file, "if (WITH_EVENTS) {\n");
+ lf_putstr(file, " if (event_queue_tick(events)) {\n");
+ lf_putstr(file, " cpu_set_program_counter(processor, cia);\n");
+ lf_putstr(file, " event_queue_process(events);\n");
+ lf_putstr(file, " cia = cpu_get_program_counter(processor);\n");
+ lf_putstr(file, " }\n");
+ lf_putstr(file, "}\n");
+
+ /* tail */
+ if (can_stop) {
+ lf_putstr(file, "\n");
+ lf_putstr(file, "/* abort if necessary */\n");
+ lf_putstr(file, "if (keep_running != NULL && !*keep_running)\n");
+ lf_putstr(file, " cpu_halt(processor, cia, was_continuing, 0/*not important*/);\n");
+ }
+
+ lf_indent(file, -2);
+ lf_putstr(file, "}\n");
+ }
+
+ if (generate_smp) {
+
+ lf_putstr(file, "
+/* CASE 2: SMP (With or without ICACHE)
+
+ The complexity here comes from needing to correctly restart the
+ system when it is aborted. In particular if cpu0 requests a
+ restart, the next cpu is still cpu1. Cpu0 being restarted after
+ all the other CPU's and the event queue have been processed */");
+
+ lf_putstr(file, "\n");
+
+ lf_putstr(file, "\n");
+ lf_putstr(file, "/* now establish the restart target */\n");
+ lf_putstr(file, "psim_set_halt_and_restart(system, &halt, &restart);\n");
+ lf_putstr(file, "if (setjmp(restart)) {\n");
+ lf_putstr(file, " current_cpu = psim_last_cpu(system);\n");
+ lf_putstr(file, " ASSERT(current_cpu >= 0 && current_cpu < nr_cpus);\n");
+ lf_putstr(file, "}\n");
+ lf_putstr(file, "else {\n");
+ lf_putstr(file, " current_cpu = last_cpu;\n");
+ lf_putstr(file, " ASSERT(current_cpu >= -1 && current_cpu < nr_cpus);\n");
+ lf_putstr(file, "}\n");
+
+
+ lf_putstr(file, "\n");
+ lf_putstr(file, "while (1) {\n");
+ lf_indent(file, +2);
+
+ lf_putstr(file, "\n");
+ lf_putstr(file, "if (WITH_EVENTS) {\n");
+ lf_putstr(file, " current_cpu += 1;\n");
+ lf_putstr(file, " if (current_cpu == nr_cpus) {\n");
+ lf_putstr(file, " if (event_queue_tick(events)) {\n");
+ lf_putstr(file, " event_queue_process(events);\n");
+ lf_putstr(file, " }\n");
+ lf_putstr(file, " current_cpu = 0;\n");
+ lf_putstr(file, " }\n");
+ lf_putstr(file, "}\n");
+ lf_putstr(file, "else {\n");
+ lf_putstr(file, " current_cpu = (current_cpu + 1) % nr_cpus;\n");
+ lf_putstr(file, "}\n");
+
+ lf_putstr(file, "\n");
+ lf_putstr(file, "{\n");
+ lf_indent(file, +2);
+ lf_putstr(file, "cpu *processor = processors[current_cpu];\n");
+ lf_putstr(file, "unsigned_word cia =\n");
+ lf_putstr(file, " cpu_get_program_counter(processor);\n");
+
+ if (!(code & generate_with_icache)) {
+ lf_putstr(file, "instruction_word instruction =\n");
+ lf_putstr(file, " vm_instruction_map_read(cpu_instruction_map(processor), processor, cia);\n");
+ print_idecode_body(file, table, "cia =");
+ if (can_stop) {
+ lf_putstr(file, "if (keep_running != NULL && !*keep_running)\n");
+ lf_putstr(file, " cpu_halt(processor, cia, was_continuing, 0/*ignore*/);\n");
+ }
+ lf_putstr(file, "cpu_set_program_counter(processor, cia);\n");
+ }
+
+ if ((code & generate_with_icache)) {
+ lf_putstr(file, "idecode_cache *cache_entry =\n");
+ lf_putstr(file, " cpu_icache_entry(processor, cia);\n");
+ lf_putstr(file, "\n");
+ lf_putstr(file, "if (cache_entry->address == cia) {\n");
+ {
+ lf_indent(file, +2);
+ lf_putstr(file, "\n");
+ lf_putstr(file, "/* cache hit */\n");
+ lf_putstr(file, "idecode_semantic *semantic = cache_entry->semantic;\n");
+ lf_putstr(file, "cia = semantic(processor, cache_entry, cia);\n");
+ /* tail */
+ if (can_stop) {
+ lf_putstr(file, "if (keep_running != NULL && !*keep_running)\n");
+ lf_putstr(file, " cpu_halt(processor, cia, was_continuing, 0/*ignore-signal*/);\n");
+ }
+ lf_putstr(file, "cpu_set_program_counter(processor, cia);\n");
+ lf_putstr(file, "\n");
+ lf_indent(file, -2);
+ }
+ lf_putstr(file, "}\n");
+ lf_putstr(file, "else {\n");
+ {
+ lf_indent(file, +2);
+ lf_putstr(file, "\n");
+ lf_putstr(file, "/* cache miss */\n");
+ if (!(code & generate_with_semantic_icache)) {
+ lf_putstr(file, "idecode_semantic *semantic;\n");
+ }
+ lf_putstr(file, "instruction_word instruction =\n");
+ lf_putstr(file, " vm_instruction_map_read(cpu_instruction_map(processor), processor, cia);\n");
+ lf_putstr(file, "if (WITH_MON != 0)\n");
+ lf_putstr(file, " mon_event(mon_event_icache_miss, processors[current_cpu], cia);\n");
+ if ((code & generate_with_semantic_icache)) {
+ lf_putstr(file, "{\n");
+ lf_indent(file, +2);
+ print_idecode_body(file, table, "cia =");
+ lf_indent(file, -2);
+ lf_putstr(file, "}\n");
+ }
+ else {
+ print_idecode_body(file, table, "semantic = ");
+ lf_putstr(file, "cia = semantic(processor, cache_entry, cia);\n");
+ }
+ /* tail */
+ if (can_stop) {
+ lf_putstr(file, "if (keep_running != NULL && !*keep_running)\n");
+ lf_putstr(file, " cpu_halt(processor, cia, was_continuing, 0/*ignore-signal*/);\n");
+ }
+ lf_putstr(file, "cpu_set_program_counter(processor, cia);\n");
+ lf_putstr(file, "\n");
+ lf_indent(file, -2);
+ }
+ lf_putstr(file, "}\n");
+ }
+
+ /* close */
+ lf_indent(file, -2);
+ lf_putstr(file, "}\n");
+
+ /* tail */
+ lf_indent(file, -2);
+ lf_putstr(file, "}\n");
+ }
+
+
+ lf_indent(file, -2);
+ lf_putstr(file, "}\n");
+}
+
+
+/****************************************************************/
+
+static void
+print_jump(lf *file,
+ int is_tail)
+{
+ if (is_tail) {
+ lf_putstr(file, "if (keep_running != NULL && !*keep_running)\n");
+ lf_putstr(file, " cpu_halt(processor, nia, was_continuing, 0/*na*/);\n");
+ }
+
+ if (!generate_smp) {
+ lf_putstr(file, "if (WITH_EVENTS) {\n");
+ lf_putstr(file, " if (event_queue_tick(events)) {\n");
+ lf_putstr(file, " cpu_set_program_counter(processor, nia);\n");
+ lf_putstr(file, " event_queue_process(events);\n");
+ lf_putstr(file, " nia = cpu_get_program_counter(processor);\n");
+ lf_putstr(file, " }\n");
+ lf_putstr(file, "}\n");
+ }
+
+ if (generate_smp) {
+ if (is_tail)
+ lf_putstr(file, "cpu_set_program_counter(processor, nia);\n");
+ lf_putstr(file, "if (WITH_EVENTS) {\n");
+ lf_putstr(file, " current_cpu += 1;\n");
+ lf_putstr(file, " if (current_cpu >= nr_cpus) {\n");
+ lf_putstr(file, " if (event_queue_tick(events)) {\n");
+ lf_putstr(file, " event_queue_process(events);\n");
+ lf_putstr(file, " }\n");
+ lf_putstr(file, " current_cpu = 0;\n");
+ lf_putstr(file, " }\n");
+ lf_putstr(file, "}\n");
+ lf_putstr(file, "else {\n");
+ lf_putstr(file, " current_cpu = (current_cpu + 1) % nr_cpus;\n");
+ lf_putstr(file, "}\n");
+ lf_putstr(file, "processor = processors[current_cpu];\n");
+ lf_putstr(file, "nia = cpu_get_program_counter(processor);\n");
+ }
+
+ if ((code & generate_with_icache)) {
+ lf_putstr(file, "cache_entry = cpu_icache_entry(processor, nia);\n");
+ lf_putstr(file, "if (cache_entry->address == nia) {\n");
+ lf_putstr(file, " /* cache hit */\n");
+ lf_putstr(file, " goto *cache_entry->semantic;\n");
+ lf_putstr(file, "}\n");
+ if (is_tail) {
+ lf_putstr(file, "goto cache_miss;\n");
+ }
+ }
+
+ if (!(code & generate_with_icache) && is_tail) {
+ lf_printf(file, "goto idecode;\n");
+ }
+
+}
+
+
+
+
+
+static void
+print_jump_insn(lf *file,
+ insn *instruction,
+ insn_bits *expanded_bits,
+ opcode_field *opcodes,
+ cache_table *cache_rules)
+{
+
+ /* what we are for the moment */
+ lf_printf(file, "\n");
+ print_my_defines(file, expanded_bits, instruction->file_entry);
+
+ /* output the icache entry */
+ if ((code & generate_with_icache)) {
+ lf_printf(file, "\n");
+ lf_indent(file, -1);
+ print_function_name(file,
+ instruction->file_entry->fields[insn_name],
+ expanded_bits,
+ function_name_prefix_icache);
+ lf_printf(file, ":\n");
+ lf_indent(file, +1);
+ lf_printf(file, "{\n");
+ lf_indent(file, +2);
+ lf_putstr(file, "const unsigned_word cia = nia;\n");
+ print_itrace(file, instruction->file_entry, 1/*putting-value-in-cache*/);
+ print_idecode_validate(file, instruction, opcodes);
+ lf_printf(file, "\n");
+ lf_printf(file, "{\n");
+ lf_indent(file, +2);
+ print_icache_body(file,
+ instruction,
+ expanded_bits,
+ cache_rules,
+ 0, /*use_defines*/
+ put_values_in_icache);
+ lf_printf(file, "cache_entry->address = nia;\n");
+ lf_printf(file, "cache_entry->semantic = &&");
+ print_function_name(file,
+ instruction->file_entry->fields[insn_name],
+ expanded_bits,
+ function_name_prefix_semantics);
+ lf_printf(file, ";\n");
+ if ((code & generate_with_semantic_icache)) {
+ print_semantic_body(file,
+ instruction,
+ expanded_bits,
+ opcodes);
+ print_jump(file, 1/*is-tail*/);
+ }
+ else {
+ lf_printf(file, "/* goto ");
+ print_function_name(file,
+ instruction->file_entry->fields[insn_name],
+ expanded_bits,
+ function_name_prefix_semantics);
+ lf_printf(file, "; */\n");
+ }
+ lf_indent(file, -2);
+ lf_putstr(file, "}\n");
+ lf_indent(file, -2);
+ lf_printf(file, "}\n");
+ }
+
+ /* print the semantics */
+ lf_printf(file, "\n");
+ lf_indent(file, -1);
+ print_function_name(file,
+ instruction->file_entry->fields[insn_name],
+ expanded_bits,
+ function_name_prefix_semantics);
+ lf_printf(file, ":\n");
+ lf_indent(file, +1);
+ lf_printf(file, "{\n");
+ lf_indent(file, +2);
+ lf_putstr(file, "const unsigned_word cia = nia;\n");
+ print_icache_body(file,
+ instruction,
+ expanded_bits,
+ cache_rules,
+ ((code & generate_with_direct_access)
+ ? define_variables
+ : declare_variables),
+ ((code & generate_with_icache)
+ ? get_values_from_icache
+ : do_not_use_icache));
+ print_semantic_body(file,
+ instruction,
+ expanded_bits,
+ opcodes);
+ if (code & generate_with_direct_access)
+ print_icache_body(file,
+ instruction,
+ expanded_bits,
+ cache_rules,
+ undef_variables,
+ ((code & generate_with_icache)
+ ? get_values_from_icache
+ : do_not_use_icache));
+ print_jump(file, 1/*is tail*/);
+ lf_indent(file, -2);
+ lf_printf(file, "}\n");
+}
+
+static void
+print_jump_definition(insn_table *entry,
+ lf *file,
+ void *data,
+ insn *instruction,
+ int depth)
+{
+ cache_table *cache_rules = (cache_table*)data;
+ if (generate_expanded_instructions) {
+ ASSERT(entry->nr_insn == 1
+ && entry->opcode == NULL
+ && entry->parent != NULL
+ && entry->parent->opcode != NULL);
+ ASSERT(entry->nr_insn == 1
+ && entry->opcode == NULL
+ && entry->parent != NULL
+ && entry->parent->opcode != NULL
+ && entry->parent->opcode_rule != NULL);
+ print_jump_insn(file,
+ entry->insns,
+ entry->expanded_bits,
+ entry->opcode,
+ cache_rules);
+ }
+ else {
+ print_jump_insn(file,
+ instruction,
+ NULL,
+ NULL,
+ cache_rules);
+ }
+}
+
+
+static void
+print_jump_internal_function(insn_table *table,
+ lf *file,
+ void *data,
+ table_entry *function)
+{
+ if (it_is("internal", function->fields[insn_flags])) {
+ lf_printf(file, "\n");
+ table_entry_print_cpp_line_nr(file, function);
+ lf_indent(file, -1);
+ print_function_name(file,
+ function->fields[insn_name],
+ NULL,
+ ((code & generate_with_icache)
+ ? function_name_prefix_icache
+ : function_name_prefix_semantics));
+ lf_printf(file, ":\n");
+ lf_indent(file, +1);
+ lf_printf(file, "{\n");
+ lf_indent(file, +2);
+ lf_printf(file, "const unsigned_word cia = nia;\n");
+ lf_print__c_code(file, function->annex);
+ lf_print__internal_reference(file);
+ lf_printf(file, "error(\"Internal function must longjump\\n\");\n");
+ lf_indent(file, -2);
+ lf_printf(file, "}\n");
+ }
+}
+
+static void
+print_jump_until_stop_body(lf *file,
+ insn_table *table,
+ cache_table *cache_rules,
+ int can_stop)
+{
+ lf_printf(file, "{\n");
+ lf_indent(file, +2);
+ if (!can_stop)
+ lf_printf(file, "int *keep_running = NULL;\n");
+ lf_putstr(file, "jmp_buf halt;\n");
+ lf_putstr(file, "jmp_buf restart;\n");
+ lf_putstr(file, "cpu *processor = NULL;\n");
+ lf_putstr(file, "unsigned_word nia = -1;\n");
+ lf_putstr(file, "instruction_word instruction = 0;\n");
+ if ((code & generate_with_icache)) {
+ lf_putstr(file, "idecode_cache *cache_entry = NULL;\n");
+ }
+ if (generate_smp) {
+ lf_putstr(file, "int current_cpu = -1;\n");
+ }
+
+ /* all the switches and tables - they know about jumping */
+ print_idecode_lookups(file, table, cache_rules);
+
+ /* start the simulation up */
+ if ((code & generate_with_icache)) {
+ lf_putstr(file, "\n");
+ lf_putstr(file, "{\n");
+ lf_putstr(file, " int cpu_nr;\n");
+ lf_putstr(file, " for (cpu_nr = 0; cpu_nr < nr_cpus; cpu_nr++)\n");
+ lf_putstr(file, " cpu_flush_icache(processors[cpu_nr]);\n");
+ lf_putstr(file, "}\n");
+ }
+
+ lf_putstr(file, "\n");
+ lf_putstr(file, "psim_set_halt_and_restart(system, &halt, &restart);\n");
+
+ lf_putstr(file, "\n");
+ lf_putstr(file, "if (setjmp(halt))\n");
+ lf_putstr(file, " return;\n");
+
+ lf_putstr(file, "\n");
+ lf_putstr(file, "setjmp(restart);\n");
+
+ lf_putstr(file, "\n");
+ if (!generate_smp) {
+ lf_putstr(file, "processor = processors[0];\n");
+ lf_putstr(file, "nia = cpu_get_program_counter(processor);\n");
+ }
+ else {
+ lf_putstr(file, "current_cpu = psim_last_cpu(system);\n");
+ }
+
+ if (!(code & generate_with_icache)) {
+ lf_printf(file, "\n");
+ lf_indent(file, -1);
+ lf_printf(file, "idecode:\n");
+ lf_indent(file, +1);
+ }
+
+ print_jump(file, 0/*is_tail*/);
+
+ if ((code & generate_with_icache)) {
+ lf_indent(file, -1);
+ lf_printf(file, "cache_miss:\n");
+ lf_indent(file, +1);
+ }
+
+ lf_putstr(file, "instruction\n");
+ lf_putstr(file, " = vm_instruction_map_read(cpu_instruction_map(processor),\n");
+ lf_putstr(file, " processor, nia);\n");
+ print_idecode_body(file, table, "/*IGORE*/");
+
+ /* print out a table of all the internals functions */
+ insn_table_traverse_function(table,
+ file, NULL,
+ print_jump_internal_function);
+
+ /* print out a table of all the instructions */
+ if (generate_expanded_instructions)
+ insn_table_traverse_tree(table,
+ file, cache_rules,
+ 1,
+ NULL, /* start */
+ print_jump_definition, /* leaf */
+ NULL, /* end */
+ NULL); /* padding */
+ else
+ insn_table_traverse_insn(table,
+ file, cache_rules,
+ print_jump_definition);
+ lf_indent(file, -2);
+ lf_printf(file, "}\n");
+}
+
+
+/****************************************************************/
+
+
+
+static void
+print_idecode_floating_point_unavailable(lf *file)
+{
+ if ((code & generate_jumps))
+ lf_printf(file, "goto %s_floating_point_unavailable;\n", (code & generate_with_icache) ? "icache" : "semantic");
+ else if ((code & generate_with_icache))
+ lf_printf(file, "return icache_floating_point_unavailable(%s);\n",
+ ICACHE_FUNCTION_ACTUAL);
+ else
+ lf_printf(file, "return semantic_floating_point_unavailable(%s);\n",
+ SEMANTIC_FUNCTION_ACTUAL);
+}
+
+
+/* Output code to do any final checks on the decoded instruction.
+ This includes things like verifying any on decoded fields have the
+ correct value and checking that (for floating point) floating point
+ hardware isn't disabled */
+
+void
+print_idecode_validate(lf *file,
+ insn *instruction,
+ opcode_field *opcodes)
+{
+ /* Validate: unchecked instruction fields
+
+ If any constant fields in the instruction were not checked by the
+ idecode tables, output code to check that they have the correct
+ value here */
+ {
+ unsigned check_mask = 0;
+ unsigned check_val = 0;
+ insn_field *field;
+ opcode_field *opcode;
+
+ /* form check_mask/check_val containing what needs to be checked
+ in the instruction */
+ for (field = instruction->fields->first;
+ field->first < insn_bit_size;
+ field = field->next) {
+
+ check_mask <<= field->width;
+ check_val <<= field->width;
+
+ /* is it a constant that could need validating? */
+ if (!field->is_int && !field->is_slash)
+ continue;
+
+ /* has it been checked by a table? */
+ for (opcode = opcodes; opcode != NULL; opcode = opcode->parent) {
+ if (field->first >= opcode->first
+ && field->last <= opcode->last)
+ break;
+ }
+ if (opcode != NULL)
+ continue;
+
+ check_mask |= (1 << field->width)-1;
+ check_val |= field->val_int;
+ }
+
+ /* if any bits not checked by opcode tables, output code to check them */
+ if (check_mask) {
+ lf_printf(file, "\n");
+ lf_printf(file, "/* validate: %s */\n",
+ instruction->file_entry->fields[insn_format]);
+ lf_printf(file, "if (WITH_RESERVED_BITS && (instruction & 0x%x) != 0x%x)\n",
+ check_mask, check_val);
+ lf_indent(file, +2);
+ print_idecode_illegal(file, "return");
+ lf_indent(file, -2);
+ }
+ }
+
+ /* Validate floating point hardware
+
+ If the simulator is being built with out floating point hardware
+ (different to it being disabled in the MSR) then floating point
+ instructions are invalid */
+ {
+ if (it_is("f", instruction->file_entry->fields[insn_flags])) {
+ lf_printf(file, "\n");
+ lf_printf(file, "/* Validate: FP hardware exists */\n");
+ lf_printf(file, "if (CURRENT_FLOATING_POINT != HARD_FLOATING_POINT)\n");
+ lf_indent(file, +2);
+ print_idecode_illegal(file, "return");
+ lf_indent(file, -2);
+ }
+ }
+
+ /* Validate: Floating Point available
+
+ If floating point is not available, we enter a floating point
+ unavailable interrupt into the cache instead of the instruction
+ proper.
+
+ The PowerPC spec requires a CSI after MSR[FP] is changed and when
+ ever a CSI occures we flush the instruction cache. */
+
+ {
+ if (it_is("f", instruction->file_entry->fields[insn_flags])) {
+ lf_printf(file, "\n");
+ lf_printf(file, "/* Validate: FP available according to MSR[FP] */\n");
+ lf_printf(file, "if (!IS_FP_AVAILABLE(processor))\n");
+ lf_indent(file, +2);
+ print_idecode_floating_point_unavailable(file);
+ lf_indent(file, -2);
+ }
+ }
+}
+
+
+/****************************************************************/
+
+
+static void
+print_idecode_run_function_header(lf *file,
+ int can_stop,
+ int is_definition)
+{
+ int indent;
+ lf_printf(file, "\n");
+ lf_print_function_type(file, "void", "INLINE_IDECODE", (is_definition ? " " : "\n"));
+ indent = lf_putstr(file, (can_stop ? "idecode_run_until_stop" : "idecode_run"));
+ if (is_definition)
+ lf_putstr(file, "\n");
+ else
+ lf_indent(file, +indent);
+ lf_putstr(file, "(psim *system,\n");
+ if (can_stop)
+ lf_putstr(file, " volatile int *keep_running,\n");
+ lf_printf(file, " event_queue *events,\n");
+ lf_putstr(file, " cpu *const processors[],\n");
+ lf_putstr(file, " const int nr_cpus)");
+ if (is_definition)
+ lf_putstr(file, ";");
+ else
+ lf_indent(file, -indent);
+ lf_putstr(file, "\n");
+}
+
+
+void
+gen_idecode_h(lf *file,
+ insn_table *table,
+ cache_table *cache_rules)
+{
+ lf_printf(file, "/* The idecode_*.h functions shall move to support */\n");
+ lf_printf(file, "#include \"idecode_expression.h\"\n");
+ lf_printf(file, "#include \"idecode_fields.h\"\n");
+ lf_printf(file, "#include \"idecode_branch.h\"\n");
+ lf_printf(file, "\n");
+ print_icache_struct(table, cache_rules, file);
+ lf_printf(file, "\n");
+ lf_printf(file, "#define WITH_IDECODE_SMP %d\n", generate_smp);
+ lf_printf(file, "\n");
+ print_idecode_run_function_header(file, 0/*can stop*/, 1/*is definition*/);
+ print_idecode_run_function_header(file, 1/*can stop*/, 1/*is definition*/);
+}
+
+
+void
+gen_idecode_c(lf *file,
+ insn_table *table,
+ cache_table *cache_rules)
+{
+ /* the intro */
+ lf_printf(file, "#include \"inline.c\"\n");
+ lf_printf(file, "\n");
+ lf_printf(file, "#include \"cpu.h\"\n");
+ lf_printf(file, "#include \"idecode.h\"\n");
+ lf_printf(file, "#include \"semantics.h\"\n");
+ lf_printf(file, "#include \"icache.h\"\n");
+ lf_printf(file, "#include \"support.h\"\n");
+ lf_printf(file, "\n");
+ lf_printf(file, "#include <setjmp.h>\n");
+ lf_printf(file, "\n");
+ lf_printf(file, "enum {\n");
+ lf_printf(file, " /* greater or equal to zero => table */\n");
+ lf_printf(file, " function_entry = -1,\n");
+ lf_printf(file, " boolean_entry = -2,\n");
+ lf_printf(file, "};\n");
+ lf_printf(file, "\n");
+ lf_printf(file, "typedef struct _idecode_table_entry {\n");
+ lf_printf(file, " int shift;\n");
+ lf_printf(file, " instruction_word mask;\n");
+ lf_printf(file, " instruction_word value;");
+ lf_printf(file, " void *function_or_table;\n");
+ lf_printf(file, "} idecode_table_entry;\n");
+ lf_printf(file, "\n");
+ lf_printf(file, "\n");
+
+ if ((code & generate_calls)) {
+
+ print_idecode_lookups(file, table, cache_rules);
+
+ /* output the main idecode routine */
+ print_idecode_run_function_header(file, 0/*can stop*/, 0/*is definition*/);
+ print_run_until_stop_body(file, table, 0/* have stop argument */);
+
+ print_idecode_run_function_header(file, 1/*can stop*/, 0/*is definition*/);
+ print_run_until_stop_body(file, table, 1/* no stop argument */);
+
+ }
+ else if ((code & generate_jumps)) {
+
+ print_idecode_run_function_header(file, 0/*can stop*/, 0/*is definition*/);
+ print_jump_until_stop_body(file, table, cache_rules, 0 /* have stop argument */);
+
+ print_idecode_run_function_header(file, 1/*can stop*/, 0/*is definition*/);
+ print_jump_until_stop_body(file, table, cache_rules, 1/* have stop argument */);
+
+ }
+ else {
+ error("Something is wrong!\n");
+ }
+}
diff --git a/gnu/dist/sim/ppc/gen-idecode.h b/gnu/dist/sim/ppc/gen-idecode.h
new file mode 100644
index 00000000000..f46376bf9ed
--- /dev/null
+++ b/gnu/dist/sim/ppc/gen-idecode.h
@@ -0,0 +1,40 @@
+/* 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.
+
+ */
+
+extern void gen_idecode_h
+(lf *file,
+ insn_table *table,
+ cache_table *cache_rules);
+
+extern void gen_idecode_c
+(lf *file,
+ insn_table *table,
+ cache_table *cache_rules);
+
+
+/* Output code to do any final checks on the decoded instruction.
+ This includes things like verifying any on decoded fields have the
+ correct value and checking that (for floating point) floating point
+ hardware isn't disabled */
+
+extern void print_idecode_validate
+(lf *file,
+ insn *instruction,
+ opcode_field *opcodes);
diff --git a/gnu/dist/sim/ppc/gen-itable.c b/gnu/dist/sim/ppc/gen-itable.c
new file mode 100644
index 00000000000..132aa291e08
--- /dev/null
+++ b/gnu/dist/sim/ppc/gen-itable.c
@@ -0,0 +1,122 @@
+/* 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.
+
+ */
+
+
+
+#include "misc.h"
+#include "lf.h"
+#include "table.h"
+
+#include "filter.h"
+
+#include "ld-decode.h"
+#include "ld-insn.h"
+
+#include "igen.h"
+#include "gen-itable.h"
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+
+
+static void
+itable_h_insn(insn_table *entry,
+ lf *file,
+ void *data,
+ insn *instruction,
+ int depth)
+{
+ lf_printf(file, " ");
+ print_function_name(file,
+ instruction->file_entry->fields[insn_name],
+ NULL,
+ function_name_prefix_itable);
+ lf_printf(file, ",\n");
+}
+
+
+extern void
+gen_itable_h(insn_table *table, lf *file)
+{
+ /* output an enumerated type for each instruction */
+ lf_printf(file, "typedef enum {\n");
+ insn_table_traverse_insn(table,
+ file, NULL,
+ itable_h_insn);
+ lf_printf(file, " nr_itable_entries,\n");
+ lf_printf(file, "} itable_index;\n");
+ lf_printf(file, "\n");
+
+ /* output the table that contains the actual instruction info */
+ lf_printf(file, "typedef struct _itable_instruction_info {\n");
+ lf_printf(file, " itable_index nr;\n");
+ lf_printf(file, " char *format;\n");
+ lf_printf(file, " char *form;\n");
+ lf_printf(file, " char *flags;\n");
+ lf_printf(file, " char *mnemonic;\n");
+ lf_printf(file, " char *name;\n");
+ lf_printf(file, " char *file;\n");
+ lf_printf(file, " int line_nr;\n");
+ lf_printf(file, "} itable_info;\n");
+ lf_printf(file, "\n");
+ lf_printf(file, "extern itable_info itable[nr_itable_entries];\n");
+}
+
+/****************************************************************/
+
+static void
+itable_c_insn(insn_table *entry,
+ lf *file,
+ void *data,
+ insn *instruction,
+ int depth)
+{
+ char **fields = instruction->file_entry->fields;
+ lf_printf(file, " { ");
+ print_function_name(file,
+ instruction->file_entry->fields[insn_name],
+ NULL,
+ function_name_prefix_itable);
+ lf_printf(file, ",\n");
+ lf_printf(file, " \"%s\",\n", fields[insn_format]);
+ lf_printf(file, " \"%s\",\n", fields[insn_form]);
+ lf_printf(file, " \"%s\",\n", fields[insn_flags]);
+ lf_printf(file, " \"%s\",\n", fields[insn_mnemonic]);
+ lf_printf(file, " \"%s\",\n", fields[insn_name]);
+ lf_printf(file, " \"%s\",\n", filter_filename (instruction->file_entry->file_name));
+ lf_printf(file, " %d,\n", instruction->file_entry->line_nr);
+ lf_printf(file, " },\n");
+}
+
+
+extern void
+gen_itable_c(insn_table *table, lf *file)
+{
+ /* output the table that contains the actual instruction info */
+ lf_printf(file, "#include \"itable.h\"\n");
+ lf_printf(file, "\n");
+ lf_printf(file, "itable_info itable[nr_itable_entries] = {\n");
+ insn_table_traverse_insn(table,
+ file, NULL,
+ itable_c_insn);
+ lf_printf(file, "};\n");
+}
diff --git a/gnu/dist/sim/ppc/gen-itable.h b/gnu/dist/sim/ppc/gen-itable.h
new file mode 100644
index 00000000000..341dc678547
--- /dev/null
+++ b/gnu/dist/sim/ppc/gen-itable.h
@@ -0,0 +1,28 @@
+/* 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.
+
+ */
+
+
+extern void gen_itable_h
+(insn_table *table,
+ lf *file);
+
+extern void gen_itable_c
+(insn_table *table,
+ lf *file);
diff --git a/gnu/dist/sim/ppc/gen-model.c b/gnu/dist/sim/ppc/gen-model.c
new file mode 100644
index 00000000000..4ec167717c0
--- /dev/null
+++ b/gnu/dist/sim/ppc/gen-model.c
@@ -0,0 +1,393 @@
+/* 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.
+
+ */
+
+
+#include "misc.h"
+#include "lf.h"
+#include "table.h"
+
+#include "filter.h"
+
+#include "ld-decode.h"
+#include "ld-insn.h"
+
+#include "gen-model.h"
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+
+static void
+model_c_or_h_data(insn_table *table,
+ lf *file,
+ table_entry *data)
+{
+ if (data->annex) {
+ table_entry_print_cpp_line_nr(file, data);
+ lf_print__c_code(file, data->annex);
+ lf_print__internal_reference(file);
+ lf_printf(file, "\n");
+ }
+}
+
+static void
+model_c_or_h_function(insn_table *entry,
+ lf *file,
+ table_entry *function,
+ char *prefix)
+{
+ if (function->fields[function_type] == NULL
+ || function->fields[function_type][0] == '\0') {
+ error("Model function type not specified for %s", function->fields[function_name]);
+ }
+ lf_printf(file, "\n");
+ lf_print_function_type(file, function->fields[function_type], prefix, " ");
+ lf_printf(file, "%s\n(%s);\n",
+ function->fields[function_name],
+ function->fields[function_param]);
+ lf_printf(file, "\n");
+}
+
+void
+gen_model_h(insn_table *table, lf *file)
+{
+ insn *insn_ptr;
+ model *model_ptr;
+ insn *macro;
+ char *name;
+ int model_create_p = 0;
+ int model_init_p = 0;
+ int model_halt_p = 0;
+ int model_mon_info_p = 0;
+ int model_mon_info_free_p = 0;
+
+ for(macro = model_macros; macro; macro = macro->next) {
+ model_c_or_h_data(table, file, macro->file_entry);
+ }
+
+ lf_printf(file, "typedef enum _model_enum {\n");
+ lf_printf(file, " MODEL_NONE,\n");
+ for (model_ptr = models; model_ptr; model_ptr = model_ptr->next) {
+ lf_printf(file, " MODEL_%s,\n", model_ptr->name);
+ }
+ lf_printf(file, " nr_models\n");
+ lf_printf(file, "} model_enum;\n");
+ lf_printf(file, "\n");
+
+ lf_printf(file, "#define DEFAULT_MODEL MODEL_%s\n", (models) ? models->name : "NONE");
+ lf_printf(file, "\n");
+
+ lf_printf(file, "typedef struct _model_data model_data;\n");
+ lf_printf(file, "typedef struct _model_time model_time;\n");
+ lf_printf(file, "\n");
+
+ lf_printf(file, "extern model_enum current_model;\n");
+ lf_printf(file, "extern const char *model_name[ (int)nr_models ];\n");
+ lf_printf(file, "extern const char *const *const model_func_unit_name[ (int)nr_models ];\n");
+ lf_printf(file, "extern const model_time *const model_time_mapping[ (int)nr_models ];\n");
+ lf_printf(file, "\n");
+
+ for(insn_ptr = model_functions; insn_ptr; insn_ptr = insn_ptr->next) {
+ model_c_or_h_function(table, file, insn_ptr->file_entry, "INLINE_MODEL");
+ name = insn_ptr->file_entry->fields[function_name];
+ if (strcmp (name, "model_create") == 0)
+ model_create_p = 1;
+ else if (strcmp (name, "model_init") == 0)
+ model_init_p = 1;
+ else if (strcmp (name, "model_halt") == 0)
+ model_halt_p = 1;
+ else if (strcmp (name, "model_mon_info") == 0)
+ model_mon_info_p = 1;
+ else if (strcmp (name, "model_mon_info_free") == 0)
+ model_mon_info_free_p = 1;
+ }
+
+ if (!model_create_p) {
+ lf_print_function_type(file, "model_data *", "INLINE_MODEL", " ");
+ lf_printf(file, "model_create\n");
+ lf_printf(file, "(cpu *processor);\n");
+ lf_printf(file, "\n");
+ }
+
+ if (!model_init_p) {
+ lf_print_function_type(file, "void", "INLINE_MODEL", " ");
+ lf_printf(file, "model_init\n");
+ lf_printf(file, "(model_data *model_ptr);\n");
+ lf_printf(file, "\n");
+ }
+
+ if (!model_halt_p) {
+ lf_print_function_type(file, "void", "INLINE_MODEL", " ");
+ lf_printf(file, "model_halt\n");
+ lf_printf(file, "(model_data *model_ptr);\n");
+ lf_printf(file, "\n");
+ }
+
+ if (!model_mon_info_p) {
+ lf_print_function_type(file, "model_print *", "INLINE_MODEL", " ");
+ lf_printf(file, "model_mon_info\n");
+ lf_printf(file, "(model_data *model_ptr);\n");
+ lf_printf(file, "\n");
+ }
+
+ if (!model_mon_info_free_p) {
+ lf_print_function_type(file, "void", "INLINE_MODEL", " ");
+ lf_printf(file, "model_mon_info_free\n");
+ lf_printf(file, "(model_data *model_ptr,\n");
+ lf_printf(file, " model_print *info_ptr);\n");
+ lf_printf(file, "\n");
+ }
+
+ lf_print_function_type(file, "void", "INLINE_MODEL", " ");
+ lf_printf(file, "model_set\n");
+ lf_printf(file, "(const char *name);\n");
+}
+
+/****************************************************************/
+
+typedef struct _model_c_passed_data model_c_passed_data;
+struct _model_c_passed_data {
+ lf *file;
+ model *model_ptr;
+};
+
+static void
+model_c_insn(insn_table *entry,
+ lf *phony_file,
+ void *data,
+ insn *instruction,
+ int depth)
+{
+ model_c_passed_data *data_ptr = (model_c_passed_data *)data;
+ lf *file = data_ptr->file;
+ char *current_name = data_ptr->model_ptr->printable_name;
+ table_model_entry *model_ptr = instruction->file_entry->model_first;
+
+ while (model_ptr) {
+ if (model_ptr->fields[insn_model_name] == current_name) {
+ lf_printf(file, " { %-*s }, /* %s */\n",
+ max_model_fields_len,
+ model_ptr->fields[insn_model_fields],
+ instruction->file_entry->fields[insn_name]);
+ return;
+ }
+
+ model_ptr = model_ptr->next;
+ }
+
+ lf_printf(file, " { %-*s }, /* %s */\n",
+ max_model_fields_len,
+ data_ptr->model_ptr->insn_default,
+ instruction->file_entry->fields[insn_name]);
+}
+
+static void
+model_c_function(insn_table *table,
+ lf *file,
+ table_entry *function,
+ const char *prefix)
+{
+ if (function->fields[function_type] == NULL
+ || function->fields[function_type][0] == '\0') {
+ error("Model function return type not specified for %s", function->fields[function_name]);
+ }
+ else {
+ lf_printf(file, "\n");
+ lf_print_function_type(file, function->fields[function_type], prefix, "\n");
+ lf_printf(file, "%s(%s)\n",
+ function->fields[function_name],
+ function->fields[function_param]);
+ }
+ table_entry_print_cpp_line_nr(file, function);
+ lf_printf(file, "{\n");
+ if (function->annex) {
+ lf_indent(file, +2);
+ lf_print__c_code(file, function->annex);
+ lf_indent(file, -2);
+ }
+ lf_printf(file, "}\n");
+ lf_print__internal_reference(file);
+ lf_printf(file, "\n");
+}
+
+void
+gen_model_c(insn_table *table, lf *file)
+{
+ insn *insn_ptr;
+ model *model_ptr;
+ char *name;
+ int model_create_p = 0;
+ int model_init_p = 0;
+ int model_halt_p = 0;
+ int model_mon_info_p = 0;
+ int model_mon_info_free_p = 0;
+
+ lf_printf(file, "\n");
+ lf_printf(file, "#include \"cpu.h\"\n");
+ lf_printf(file, "#include \"mon.h\"\n");
+ lf_printf(file, "\n");
+ lf_printf(file, "#ifdef HAVE_STDLIB_H\n");
+ lf_printf(file, "#include <stdlib.h>\n");
+ lf_printf(file, "#endif\n");
+ lf_printf(file, "\n");
+
+ for(insn_ptr = model_data; insn_ptr; insn_ptr = insn_ptr->next) {
+ model_c_or_h_data(table, file, insn_ptr->file_entry);
+ }
+
+ for(insn_ptr = model_static; insn_ptr; insn_ptr = insn_ptr->next) {
+ model_c_or_h_function(table, file, insn_ptr->file_entry, "/*h*/STATIC");
+ }
+
+ for(insn_ptr = model_internal; insn_ptr; insn_ptr = insn_ptr->next) {
+ model_c_or_h_function(table, file, insn_ptr->file_entry, "STATIC_INLINE_MODEL");
+ }
+
+ for(insn_ptr = model_static; insn_ptr; insn_ptr = insn_ptr->next) {
+ model_c_function(table, file, insn_ptr->file_entry, "/*c*/STATIC");
+ }
+
+ for(insn_ptr = model_internal; insn_ptr; insn_ptr = insn_ptr->next) {
+ model_c_function(table, file, insn_ptr->file_entry, "STATIC_INLINE_MODEL");
+ }
+
+ for(insn_ptr = model_functions; insn_ptr; insn_ptr = insn_ptr->next) {
+ model_c_function(table, file, insn_ptr->file_entry, "INLINE_MODEL");
+ name = insn_ptr->file_entry->fields[function_name];
+ if (strcmp (name, "model_create") == 0)
+ model_create_p = 1;
+ else if (strcmp (name, "model_init") == 0)
+ model_init_p = 1;
+ else if (strcmp (name, "model_halt") == 0)
+ model_halt_p = 1;
+ else if (strcmp (name, "model_mon_info") == 0)
+ model_mon_info_p = 1;
+ else if (strcmp (name, "model_mon_info_free") == 0)
+ model_mon_info_free_p = 1;
+ }
+
+ if (!model_create_p) {
+ lf_print_function_type(file, "model_data *", "INLINE_MODEL", "\n");
+ lf_printf(file, "model_create(cpu *processor)\n");
+ lf_printf(file, "{\n");
+ lf_printf(file, " return (model_data *)0;\n");
+ lf_printf(file, "}\n");
+ lf_printf(file, "\n");
+ }
+
+ if (!model_init_p) {
+ lf_print_function_type(file, "void", "INLINE_MODEL", "\n");
+ lf_printf(file, "model_init(model_data *model_ptr)\n");
+ lf_printf(file, "{\n");
+ lf_printf(file, "}\n");
+ lf_printf(file, "\n");
+ }
+
+ if (!model_halt_p) {
+ lf_print_function_type(file, "void", "INLINE_MODEL", "\n");
+ lf_printf(file, "model_halt(model_data *model_ptr)\n");
+ lf_printf(file, "{\n");
+ lf_printf(file, "}\n");
+ lf_printf(file, "\n");
+ }
+
+ if (!model_mon_info_p) {
+ lf_print_function_type(file, "model_print *", "INLINE_MODEL", "\n");
+ lf_printf(file, "model_mon_info(model_data *model_ptr)\n");
+ lf_printf(file, "{\n");
+ lf_printf(file, " return (model_print *)0;\n");
+ lf_printf(file, "}\n");
+ lf_printf(file, "\n");
+ }
+
+ if (!model_mon_info_free_p) {
+ lf_print_function_type(file, "void", "INLINE_MODEL", "\n");
+ lf_printf(file, "model_mon_info_free(model_data *model_ptr,\n");
+ lf_printf(file, " model_print *info_ptr)\n");
+ lf_printf(file, "{\n");
+ lf_printf(file, "}\n");
+ lf_printf(file, "\n");
+ }
+
+ lf_printf(file, "/* Insn functional unit info */\n");
+ for(model_ptr = models; model_ptr; model_ptr = model_ptr->next) {
+ model_c_passed_data data;
+
+ lf_printf(file, "static const model_time model_time_%s[] = {\n", model_ptr->name);
+ data.file = file;
+ data.model_ptr = model_ptr;
+ insn_table_traverse_insn(table,
+ NULL, (void *)&data,
+ model_c_insn);
+
+ lf_printf(file, "};\n");
+ lf_printf(file, "\n");
+ lf_printf(file, "\f\n");
+ }
+
+ lf_printf(file, "#ifndef _INLINE_C_\n");
+ lf_printf(file, "const model_time *const model_time_mapping[ (int)nr_models ] = {\n");
+ lf_printf(file, " (const model_time *const)0,\n");
+ for(model_ptr = models; model_ptr; model_ptr = model_ptr->next) {
+ lf_printf(file, " model_time_%s,\n", model_ptr->name);
+ }
+ lf_printf(file, "};\n");
+ lf_printf(file, "#endif\n");
+ lf_printf(file, "\n");
+
+ lf_printf(file, "\f\n");
+ lf_printf(file, "/* map model enumeration into printable string */\n");
+ lf_printf(file, "#ifndef _INLINE_C_\n");
+ lf_printf(file, "const char *model_name[ (int)nr_models ] = {\n");
+ lf_printf(file, " \"NONE\",\n");
+ for (model_ptr = models; model_ptr; model_ptr = model_ptr->next) {
+ lf_printf(file, " \"%s\",\n", model_ptr->printable_name);
+ }
+ lf_printf(file, "};\n");
+ lf_printf(file, "#endif\n");
+ lf_printf(file, "\n");
+
+ lf_print_function_type(file, "void", "INLINE_MODEL", "\n");
+ lf_printf(file, "model_set(const char *name)\n");
+ lf_printf(file, "{\n");
+ if (models) {
+ lf_printf(file, " model_enum model;\n");
+ lf_printf(file, " for(model = MODEL_%s; model < nr_models; model++) {\n", models->name);
+ lf_printf(file, " if(strcmp(name, model_name[model]) == 0) {\n");
+ lf_printf(file, " current_model = model;\n");
+ lf_printf(file, " return;\n");
+ lf_printf(file, " }\n");
+ lf_printf(file, " }\n");
+ lf_printf(file, "\n");
+ lf_printf(file, " error(\"Unknown model '%%s', Models which are known are:%%s\n\",\n");
+ lf_printf(file, " name,\n");
+ lf_printf(file, " \"");
+ for(model_ptr = models; model_ptr; model_ptr = model_ptr->next) {
+ lf_printf(file, "\\n\\t%s", model_ptr->printable_name);
+ }
+ lf_printf(file, "\");\n");
+ } else {
+ lf_printf(file, " error(\"No models are currently known about\");\n");
+ }
+
+ lf_printf(file, "}\n");
+}
+
diff --git a/gnu/dist/sim/ppc/gen-model.h b/gnu/dist/sim/ppc/gen-model.h
new file mode 100644
index 00000000000..b465a75abf8
--- /dev/null
+++ b/gnu/dist/sim/ppc/gen-model.h
@@ -0,0 +1,30 @@
+/* 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.
+
+ */
+
+
+
+extern void gen_model_h
+(insn_table *table,
+ lf *file);
+
+
+extern void gen_model_c
+(insn_table *table,
+ lf *file);
diff --git a/gnu/dist/sim/ppc/gen-semantics.c b/gnu/dist/sim/ppc/gen-semantics.c
new file mode 100644
index 00000000000..b4c0613fe50
--- /dev/null
+++ b/gnu/dist/sim/ppc/gen-semantics.c
@@ -0,0 +1,250 @@
+/* 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.
+
+ */
+
+
+
+#include "misc.h"
+#include "lf.h"
+#include "table.h"
+#include "filter.h"
+
+#include "ld-decode.h"
+#include "ld-cache.h"
+#include "ld-insn.h"
+
+#include "igen.h"
+
+#include "gen-semantics.h"
+#include "gen-icache.h"
+#include "gen-idecode.h"
+
+
+static void
+print_semantic_function_header(lf *file,
+ const char *basename,
+ insn_bits *expanded_bits,
+ int is_function_definition)
+{
+ int indent;
+ lf_printf(file, "\n");
+ lf_print_function_type(file, SEMANTIC_FUNCTION_TYPE, "EXTERN_SEMANTICS",
+ (is_function_definition ? "\n" : " "));
+ indent = print_function_name(file,
+ basename,
+ expanded_bits,
+ function_name_prefix_semantics);
+ if (is_function_definition)
+ lf_indent(file, +indent);
+ else
+ lf_printf(file, "\n");
+ lf_printf(file, "(%s)", SEMANTIC_FUNCTION_FORMAL);
+ if (is_function_definition)
+ lf_indent(file, -indent);
+ else
+ lf_printf(file, ";");
+ lf_printf(file, "\n");
+}
+
+void
+print_semantic_declaration(insn_table *entry,
+ lf *file,
+ void *data,
+ insn *instruction,
+ int depth)
+{
+ if (generate_expanded_instructions) {
+ ASSERT(entry->nr_insn == 1);
+ print_semantic_function_header(file,
+ instruction->file_entry->fields[insn_name],
+ entry->expanded_bits,
+ 0/* is not function definition*/);
+ }
+ else {
+ print_semantic_function_header(file,
+ instruction->file_entry->fields[insn_name],
+ NULL,
+ 0/* is not function definition*/);
+ }
+}
+
+
+
+/* generate the semantics.c file */
+
+
+void
+print_idecode_illegal(lf *file,
+ const char *result)
+{
+ if ((code & generate_jumps))
+ lf_printf(file, "goto %s_illegal;\n", (code & generate_with_icache) ? "icache" : "semantic");
+ else if ((code & generate_with_icache))
+ lf_printf(file, "%s icache_illegal(%s);\n", result, ICACHE_FUNCTION_ACTUAL);
+ else
+ lf_printf(file, "%s semantic_illegal(%s);\n", result, SEMANTIC_FUNCTION_ACTUAL);
+}
+
+
+void
+print_semantic_body(lf *file,
+ insn *instruction,
+ insn_bits *expanded_bits,
+ opcode_field *opcodes)
+{
+ print_itrace(file, instruction->file_entry, 0/*put_value_in_cache*/);
+
+ /* validate the instruction, if a cache this has already been done */
+ if (!(code & generate_with_icache))
+ print_idecode_validate(file, instruction, opcodes);
+
+ /* generate the profiling call - this is delayed until after the
+ instruction has been verified */
+ lf_printf(file, "\n");
+ lf_printf(file, "/* monitoring: */\n");
+ lf_printf(file, "if (WITH_MON & MONITOR_INSTRUCTION_ISSUE) {\n");
+ lf_printf(file, " mon_issue(");
+ print_function_name(file,
+ instruction->file_entry->fields[insn_name],
+ NULL,
+ function_name_prefix_itable);
+ lf_printf(file, ", processor, cia);\n");
+ lf_printf(file, "}\n");
+
+ /* generate the code (or at least something */
+ lf_printf(file, "\n");
+ lf_printf(file, "/* semantics: */\n");
+ lf_printf(file, "nia = cia + %d;\n", insn_bit_size / 8);
+ if (instruction->file_entry->annex != NULL) {
+ /* true code */
+ table_entry_print_cpp_line_nr(file, instruction->file_entry);
+ lf_printf(file, "{\n");
+ lf_indent(file, +2);
+ lf_print__c_code(file, instruction->file_entry->annex);
+ lf_indent(file, -2);
+ lf_printf(file, "}\n");
+ lf_print__internal_reference(file);
+ }
+ else if (it_is("nop", instruction->file_entry->fields[insn_flags])) {
+ lf_print__internal_reference(file);
+ }
+ else {
+ /* abort so it is implemented now */
+ table_entry_print_cpp_line_nr(file, instruction->file_entry);
+ lf_putstr(file, "error(\"%s:%d:0x%08lx:%s unimplemented\\n\",\n");
+ lf_printf(file, " itable[MY_INDEX].file, itable[MY_INDEX].line_nr, (long)cia, itable[MY_INDEX].name);\n");
+ lf_print__internal_reference(file);
+ }
+}
+
+static void
+print_c_semantic(lf *file,
+ insn *instruction,
+ insn_bits *expanded_bits,
+ opcode_field *opcodes,
+ cache_table *cache_rules)
+{
+
+ lf_printf(file, "{\n");
+ lf_indent(file, +2);
+
+ print_my_defines(file, expanded_bits, instruction->file_entry);
+ lf_printf(file, "\n");
+ print_icache_body(file,
+ instruction,
+ expanded_bits,
+ cache_rules,
+ ((code & generate_with_direct_access)
+ ? define_variables
+ : declare_variables),
+ ((code & generate_with_icache)
+ ? get_values_from_icache
+ : do_not_use_icache));
+
+ lf_printf(file, "unsigned_word nia;\n");
+ print_semantic_body(file,
+ instruction,
+ expanded_bits,
+ opcodes);
+ lf_printf(file, "return nia;\n");
+
+ /* generate something to clean up any #defines created for the cache */
+ if (code & generate_with_direct_access)
+ print_icache_body(file,
+ instruction,
+ expanded_bits,
+ cache_rules,
+ undef_variables,
+ ((code & generate_with_icache)
+ ? get_values_from_icache
+ : do_not_use_icache));
+
+ lf_indent(file, -2);
+ lf_printf(file, "}\n");
+}
+
+static void
+print_c_semantic_function(lf *file,
+ insn *instruction,
+ insn_bits *expanded_bits,
+ opcode_field *opcodes,
+ cache_table *cache_rules)
+{
+ /* build the semantic routine to execute the instruction */
+ print_semantic_function_header(file,
+ instruction->file_entry->fields[insn_name],
+ expanded_bits,
+ 1/*is-function-definition*/);
+ print_c_semantic(file,
+ instruction,
+ expanded_bits,
+ opcodes,
+ cache_rules);
+}
+
+void
+print_semantic_definition(insn_table *entry,
+ lf *file,
+ void *data,
+ insn *instruction,
+ int depth)
+{
+ cache_table *cache_rules = (cache_table*)data;
+ if (generate_expanded_instructions) {
+ ASSERT(entry->nr_insn == 1
+ && entry->opcode == NULL
+ && entry->parent != NULL
+ && entry->parent->opcode != NULL);
+ ASSERT(entry->nr_insn == 1
+ && entry->opcode == NULL
+ && entry->parent != NULL
+ && entry->parent->opcode != NULL
+ && entry->parent->opcode_rule != NULL);
+ print_c_semantic_function(file,
+ entry->insns,
+ entry->expanded_bits,
+ entry->parent->opcode,
+ cache_rules);
+ }
+ else {
+ print_c_semantic_function(file, instruction,
+ NULL, NULL,
+ cache_rules);
+ }
+}
diff --git a/gnu/dist/sim/ppc/gen-semantics.h b/gnu/dist/sim/ppc/gen-semantics.h
new file mode 100644
index 00000000000..2c25715f7c7
--- /dev/null
+++ b/gnu/dist/sim/ppc/gen-semantics.h
@@ -0,0 +1,81 @@
+/* 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.
+
+ */
+
+
+/* Creates the files semantics.[hc].
+
+ The generated file semantics contains functions that implement the
+ operations required to model a single target processor instruction.
+
+ Several different variations on the semantics file can be created:
+
+ o uncached
+
+ No instruction cache exists. The semantic function
+ needs to generate any required values locally.
+
+ o cached - separate cracker and semantic
+
+ Two independant functions are created. Firstly the
+ function that cracks an instruction entering it into a
+ cache and secondly the semantic function propper that
+ uses the cache.
+
+ o cached - semantic + cracking semantic
+
+ The function that cracks the instruction and enters
+ all values into the cache also contains a copy of the
+ semantic code (avoiding the need to call both the
+ cracker and the semantic function when there is a
+ cache miss).
+
+ For each of these general forms, several refinements can occure:
+
+ o do/don't duplicate/expand semantic functions
+
+ As a consequence of decoding an instruction, the
+ decoder, as part of its table may have effectivly made
+ certain of the variable fields in an instruction
+ constant. Separate functions for each of the
+ alternative values for what would have been treated as
+ a variable part can be created.
+
+ o use cache struct directly.
+
+ When a cracking cache is present, the semantic
+ functions can be generated to either hold intermediate
+ cache values in local variables or always refer to the
+ contents of the cache directly. */
+
+
+
+extern insn_handler print_semantic_declaration;
+extern insn_handler print_semantic_definition;
+
+extern void print_idecode_illegal
+(lf *file,
+ const char *result);
+
+extern void print_semantic_body
+(lf *file,
+ insn *instruction,
+ insn_bits *expanded_bits,
+ opcode_field *opcodes);
+
diff --git a/gnu/dist/sim/ppc/gen-support.c b/gnu/dist/sim/ppc/gen-support.c
new file mode 100644
index 00000000000..56edec38e5f
--- /dev/null
+++ b/gnu/dist/sim/ppc/gen-support.c
@@ -0,0 +1,132 @@
+/* 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.
+
+ */
+
+#include "misc.h"
+#include "lf.h"
+#include "table.h"
+#include "filter.h"
+
+#include "ld-decode.h"
+#include "ld-cache.h"
+#include "ld-insn.h"
+
+#include "igen.h"
+
+#include "gen-semantics.h"
+#include "gen-support.h"
+
+static void
+print_support_function_name(lf *file,
+ table_entry *function,
+ int is_function_definition)
+{
+ if (it_is("internal", function->fields[insn_flags])) {
+ lf_print_function_type(file, SEMANTIC_FUNCTION_TYPE, "INLINE_SUPPORT",
+ (is_function_definition ? "\n" : " "));
+ print_function_name(file,
+ function->fields[function_name],
+ NULL,
+ function_name_prefix_semantics);
+ lf_printf(file, "\n(%s)", SEMANTIC_FUNCTION_FORMAL);
+ if (!is_function_definition)
+ lf_printf(file, ";");
+ lf_printf(file, "\n");
+ }
+ else {
+ lf_print_function_type(file,
+ function->fields[function_type],
+ "INLINE_SUPPORT",
+ (is_function_definition ? "\n" : " "));
+ lf_printf(file, "%s\n(%s)%s",
+ function->fields[function_name],
+ function->fields[function_param],
+ (is_function_definition ? "\n" : ";\n"));
+ }
+}
+
+
+static void
+support_h_function(insn_table *entry,
+ lf *file,
+ void *data,
+ table_entry *function)
+{
+ ASSERT(function->fields[function_type] != NULL);
+ ASSERT(function->fields[function_param] != NULL);
+ print_support_function_name(file,
+ function,
+ 0/*!is_definition*/);
+ lf_printf(file, "\n");
+}
+
+
+extern void
+gen_support_h(insn_table *table,
+ lf *file)
+{
+ /* output a declaration for all functions */
+ insn_table_traverse_function(table,
+ file, NULL,
+ support_h_function);
+ lf_printf(file, "\n");
+ lf_printf(file, "#if (SUPPORT_INLINE & INCLUDE_MODULE)\n");
+ lf_printf(file, "# include \"support.c\"\n");
+ lf_printf(file, "#endif\n");
+}
+
+static void
+support_c_function(insn_table *table,
+ lf *file,
+ void *data,
+ table_entry *function)
+{
+ ASSERT(function->fields[function_type] != NULL);
+ print_support_function_name(file,
+ function,
+ 1/*!is_definition*/);
+ table_entry_print_cpp_line_nr(file, function);
+ lf_printf(file, "{\n");
+ lf_indent(file, +2);
+ lf_print__c_code(file, function->annex);
+ if (it_is("internal", function->fields[insn_flags])) {
+ lf_printf(file, "error(\"Internal function must longjump\\n\");\n");
+ lf_printf(file, "return 0;\n");
+ }
+ lf_indent(file, -2);
+ lf_printf(file, "}\n");
+ lf_print__internal_reference(file);
+ lf_printf(file, "\n");
+}
+
+
+void
+gen_support_c(insn_table *table,
+ lf *file)
+{
+ lf_printf(file, "#include \"cpu.h\"\n");
+ lf_printf(file, "#include \"idecode.h\"\n");
+ lf_printf(file, "#include \"support.h\"\n");
+ lf_printf(file, "\n");
+
+ /* output a definition (c-code) for all functions */
+ insn_table_traverse_function(table,
+ file, NULL,
+ support_c_function);
+}
diff --git a/gnu/dist/sim/ppc/gen-support.h b/gnu/dist/sim/ppc/gen-support.h
new file mode 100644
index 00000000000..70862d76881
--- /dev/null
+++ b/gnu/dist/sim/ppc/gen-support.h
@@ -0,0 +1,29 @@
+/* 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.
+
+ */
+
+
+extern void gen_support_h
+(insn_table *table,
+ lf *file);
+
+extern void gen_support_c
+(insn_table *table,
+ lf *file);
+
diff --git a/gnu/dist/sim/ppc/hw_com.c b/gnu/dist/sim/ppc/hw_com.c
new file mode 100644
index 00000000000..436232289d2
--- /dev/null
+++ b/gnu/dist/sim/ppc/hw_com.c
@@ -0,0 +1,559 @@
+/* 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.
+
+ */
+
+
+#ifndef _HW_COM_C_
+#define _HW_COM_C_
+
+#ifndef STATIC_INLINE_HW_COM
+#define STATIC_INLINE_HW_COM STATIC_INLINE
+#endif
+
+#include "device_table.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
+
+
+ com - '550 compatible serial device
+
+
+ DESCRIPTION
+
+
+ Models the basics of the 8 register '550 serial device. The model
+ includes an interrupt line, input and output fifos, and status
+ information.
+
+ Independent configuration of the devices input and output streams is
+ allowed: use either the console or a file (buffered or unbuffered) as
+ the data source/sink; specify the real-time delay between each character
+ transfer.
+
+ When the devices input stream is being taken from a file, the end of
+ file is signaled by a loss of carrier (the loss of carrier may be
+ incorrectly proceeded by a single null character).
+
+
+ PROPERTIES
+
+
+ reg = <address> <size> ... (optional - note 1)
+
+ List of <address> <size> pairs. Each pair specifies an address for
+ the devices 8 registers. The address should be 8 byte aligned.
+
+
+ alternate-reg = <address> <size> ... (optional - note 1)
+
+ Alternative addreses for the registers.
+
+
+ assigned-addresses = <address> <size> ... (optional - note 1)
+
+ On a PCI bus, this property specifies the addresses assigned to the
+ device. The values reflect the devices configuration base registers.
+
+ Note 1: At least one of "assigned-addresses", "reg" or "alternative-reg"
+ must be specified. If "assigned-addresses" is specified the other
+ address specifications are ignored.
+
+
+ input-file = <file-name> (optional)
+
+ File to take all serial port input from (instead of the simulation
+ console).
+
+
+ output-file = <file-name> (optional)
+
+ File to send all output to (instead of the simulation console).
+
+
+ input-buffering = "unbuffered" (optional)
+
+ Specifying "unbuffered" buffering disables buffering on the serial
+ devices input stream (all data is immediatly read). In the future,
+ this option may be used to provide input buffering alternatives.
+
+
+ output-buffering = "unbuffered" (optional)
+
+ Specifying "unbuffered" buffering disables buffering on the serial
+ devices output stream (all data is immediatly written). In the future,
+ this option may be extended to include other buffering alternatives.
+
+
+ input-delay = <integer-delay> (optional)
+
+ Specify the number of ticks after the current character has been
+ read from the serial port that the next character becomes
+ available.
+
+
+ output-delay = <integer-delay> (optional)
+
+ Specify the number of ticks after a character has been written to
+ the empty output fifo that the fifo finishes draining. Any
+ characters written to the output fifo before it has drained will
+ not be lost and will still be displayed.
+
+
+ EXAMPLES
+
+
+ | /iobus@0xf0000000/com@0x3000/reg 0x3000 8
+
+ Create a simple console device at address <<0x3000>> within
+ <<iobus>>. Since iobus starts at address <<0xf0000000>> the
+ absolute address of the serial port will be <<0xf0003000>>.
+
+ The device will always be ready for I/O (no delay properties specified)
+ and both the input and output streams will use the simulation console
+ (no file properties).
+
+
+ | $ psim \
+ | -o '/cpus/cpu@0' \
+ | -o '/iobus@0xf0000000/com@0x4000/reg 0x4000 8' \
+ | -o '/iobus@0xf0000000/com@0x4000/input-file /etc/passwd' \
+ | -o '/iobus@0xf0000000/com@0x4000/input-delay 1000' \
+ | -o '/iobus@0xf0000000/com@0x4000 > 0 int /cpus/cpu@0x0' \
+ | psim-test/hw-com/cat.be 0xf0004000
+
+ The serial port (at address <<0xf0004000>> is configured so that it
+ takes its input from the file <</etc/passwd>> while its output is
+ allowed to appear on the simulation console.
+
+ The node <</cpus/cpu@0>> was explicitly specified to ensure that it had
+ been created before any interrupts were attached to it.
+
+ The program <<psim-test/hw-com/cat>> copies any characters on the serial
+ port's input (<</etc/passwd>>) to its output (the console).
+ Consequently, the aove program will display the contents of the file
+ <</etc/passwd>> on the screen.
+
+
+ BUGS
+
+
+ IEEE 1275 requires that a device on a PCI bus have, as its first reg
+ entry, the address of its configuration space registers. Currently,
+ this device does not even implement configuration registers.
+
+ This model does not attempt to model the '550's input and output fifos.
+ Instead, the input fifo is limited to a single character at a time,
+ while the output fifo is effectivly infinite. Consequently, unlike the
+ '550, this device will not discard output characters once a stream of 16
+ have been written to the data output register.
+
+ The input and output can only be taken from a file (or the current
+ terminal device). In the future, the <<com>> device should allow the
+ specification of other data streams (such as an xterm or TK window).
+
+ The input blocks if no data is available.
+
+ Interrupts have not been tested.
+
+ */
+
+enum {
+ max_hw_com_registers = 8,
+};
+
+typedef struct _com_port {
+ int ready;
+ int delay;
+ int interrupting;
+ FILE *file;
+} com_port;
+
+typedef struct _com_modem {
+ int carrier;
+ int carrier_changed;
+ int interrupting;
+} com_modem;
+
+typedef struct _hw_com_device {
+ com_port input;
+ com_port output;
+ com_modem modem;
+ char dlab[2];
+ char reg[max_hw_com_registers];
+ int interrupting;
+} hw_com_device;
+
+
+static void
+hw_com_device_init_data(device *me)
+{
+ hw_com_device *com = (hw_com_device*)device_data(me);
+ /* clean up */
+ if (com->output.file != NULL)
+ fclose(com->output.file);
+ if (com->input.file != NULL)
+ fclose(com->input.file);
+ memset(com, 0, sizeof(hw_com_device));
+
+ /* the fifo speed */
+ com->output.delay = (device_find_property(me, "output-delay") != NULL
+ ? device_find_integer_property(me, "output-delay")
+ : 0);
+ com->input.delay = (device_find_property(me, "input-delay") != NULL
+ ? device_find_integer_property(me, "input-delay")
+ : 0);
+
+ /* the data source/sink */
+ if (device_find_property(me, "input-file") != NULL) {
+ const char *input_file = device_find_string_property(me, "input-file");
+ com->input.file = fopen(input_file, "r");
+ if (com->input.file == NULL)
+ device_error(me, "Problem opening input file %s\n", input_file);
+ if (device_find_property(me, "input-buffering") != NULL) {
+ const char *buffering = device_find_string_property(me, "input-buffering");
+ if (strcmp(buffering, "unbuffered") == 0)
+ setbuf(com->input.file, NULL);
+ }
+ }
+ if (device_find_property(me, "output-file") != NULL) {
+ const char *output_file = device_find_string_property(me, "output-file");
+ com->output.file = fopen(output_file, "w");
+ if (com->input.file == NULL)
+ device_error(me, "Problem opening output file %s\n", output_file);
+ if (device_find_property(me, "output-buffering") != NULL) {
+ const char *buffering = device_find_string_property(me, "output-buffering");
+ if (strcmp(buffering, "unbuffered") == 0)
+ setbuf(com->output.file, NULL);
+ }
+ }
+
+ /* ready from the start */
+ com->input.ready = 1;
+ com->modem.carrier = 1;
+ com->output.ready = 1;
+}
+
+
+static void
+update_com_interrupts(device *me,
+ hw_com_device *com)
+{
+ int interrupting;
+ com->modem.interrupting = (com->modem.carrier_changed && (com->reg[1] & 0x80));
+ com->input.interrupting = (com->input.ready && (com->reg[1] & 0x1));
+ com->output.interrupting = (com->output.ready && (com->reg[1] & 0x2));
+ interrupting = (com->input.interrupting
+ || com->output.interrupting
+ || com->modem.interrupting);
+
+ if (interrupting) {
+ if (!com->interrupting) {
+ device_interrupt_event(me, 0 /*port*/, 1 /*value*/, NULL, 0);
+ }
+ }
+ else /*!interrupting*/ {
+ if (com->interrupting)
+ device_interrupt_event(me, 0 /*port*/, 0 /*value*/, NULL, 0);
+ }
+ com->interrupting = interrupting;
+}
+
+
+static void
+make_read_ready(void *data)
+{
+ device *me = (device*)data;
+ hw_com_device *com = (hw_com_device*)device_data(me);
+ com->input.ready = 1;
+ update_com_interrupts(me, com);
+}
+
+static void
+read_com(device *me,
+ hw_com_device *com,
+ unsigned_word a,
+ char val[1])
+{
+ unsigned_word addr = a % 8;
+
+ /* the divisor latch is special */
+ if (com->reg[3] & 0x8 && addr < 2) {
+ *val = com->dlab[addr];
+ return;
+ }
+
+ switch (addr) {
+
+ case 0:
+ /* fifo */
+ if (!com->modem.carrier)
+ *val = '\0';
+ if (com->input.ready) {
+ /* read the char in */
+ if (com->input.file == NULL) {
+ if (sim_io_read_stdin(val, 1) < 0)
+ com->modem.carrier_changed = 1;
+ }
+ else {
+ if (fread(val, 1, 1, com->input.file) == 0)
+ com->modem.carrier_changed = 1;
+ }
+ /* setup for next read */
+ if (com->modem.carrier_changed) {
+ /* once lost carrier, never ready */
+ com->modem.carrier = 0;
+ com->input.ready = 0;
+ *val = '\0';
+ }
+ else if (com->input.delay > 0) {
+ com->input.ready = 0;
+ device_event_queue_schedule(me, com->input.delay, make_read_ready, me);
+ }
+ }
+ else {
+ /* discard it? */
+ /* overflow input fifo? */
+ *val = '\0';
+ }
+ break;
+
+ case 2:
+ /* interrupt ident */
+ if (com->interrupting) {
+ if (com->input.interrupting)
+ *val = 0x4;
+ else if (com->output.interrupting)
+ *val = 0x2;
+ else if (com->modem.interrupting == 0)
+ *val = 0;
+ else
+ device_error(me, "bad elif for interrupts\n");
+ }
+ else
+ *val = 0x1;
+ break;
+
+ case 5:
+ /* line status */
+ *val = ((com->input.ready ? 0x1 : 0)
+ | (com->output.ready ? 0x60 : 0)
+ );
+ break;
+
+ case 6:
+ /* modem status */
+ *val = ((com->modem.carrier_changed ? 0x08 : 0)
+ | (com->modem.carrier ? 0x80 : 0)
+ );
+ com->modem.carrier_changed = 0;
+ break;
+
+ default:
+ *val = com->reg[addr];
+ break;
+
+ }
+ update_com_interrupts(me, com);
+}
+
+static unsigned
+hw_com_io_read_buffer_callback(device *me,
+ void *dest,
+ int space,
+ unsigned_word addr,
+ unsigned nr_bytes,
+ cpu *processor,
+ unsigned_word cia)
+{
+ hw_com_device *com = device_data(me);
+ int i;
+ for (i = 0; i < nr_bytes; i++) {
+ read_com(me, com, addr + i, &((char*)dest)[i]);
+ }
+ return nr_bytes;
+}
+
+
+static void
+make_write_ready(void *data)
+{
+ device *me = (device*)data;
+ hw_com_device *com = (hw_com_device*)device_data(me);
+ com->output.ready = 1;
+ update_com_interrupts(me, com);
+}
+
+static void
+write_com(device *me,
+ hw_com_device *com,
+ unsigned_word a,
+ char val)
+{
+ unsigned_word addr = a % 8;
+
+ /* the divisor latch is special */
+ if (com->reg[3] & 0x8 && addr < 2) {
+ com->dlab[addr] = val;
+ return;
+ }
+
+ switch (addr) {
+
+ case 0:
+ /* fifo */
+ if (com->output.file == NULL) {
+ sim_io_write_stdout(&val, 1);
+ }
+ else {
+ fwrite(&val, 1, 1, com->output.file);
+ }
+ /* setup for next write */
+ if (com->output.ready && com->output.delay > 0) {
+ com->output.ready = 0;
+ device_event_queue_schedule(me, com->output.delay, make_write_ready, me);
+ }
+ break;
+
+ default:
+ com->reg[addr] = val;
+ break;
+
+ }
+ update_com_interrupts(me, com);
+}
+
+static unsigned
+hw_com_io_write_buffer_callback(device *me,
+ const void *source,
+ int space,
+ unsigned_word addr,
+ unsigned nr_bytes,
+ cpu *processor,
+ unsigned_word cia)
+{
+ hw_com_device *com = device_data(me);
+ int i;
+ for (i = 0; i < nr_bytes; i++) {
+ write_com(me, com, addr + i, ((char*)source)[i]);
+ }
+ return nr_bytes;
+}
+
+
+/* instances of the hw_com device */
+
+static void
+hw_com_instance_delete(device_instance *instance)
+{
+ /* nothing to delete, the hw_com is attached to the device */
+ return;
+}
+
+static int
+hw_com_instance_read(device_instance *instance,
+ void *buf,
+ unsigned_word len)
+{
+ device *me = device_instance_device(instance);
+ hw_com_device *com = device_data(me);
+ if (com->input.file == NULL)
+ return sim_io_read_stdin(buf, len);
+ else {
+ return fread(buf, 1, len, com->input.file);
+ }
+}
+
+static int
+hw_com_instance_write(device_instance *instance,
+ const void *buf,
+ unsigned_word len)
+{
+ device *me = device_instance_device(instance);
+ hw_com_device *com = device_data(me);
+ if (com->output.file == NULL)
+ return sim_io_write_stdout(buf, len);
+ else {
+ return fwrite(buf, 1, len, com->output.file);
+ }
+}
+
+static const device_instance_callbacks hw_com_instance_callbacks = {
+ hw_com_instance_delete,
+ hw_com_instance_read,
+ hw_com_instance_write,
+};
+
+static device_instance *
+hw_com_create_instance(device *me,
+ const char *path,
+ const char *args)
+{
+ /* point an instance directly at the device */
+ return device_create_instance_from(me, NULL,
+ device_data(me),
+ path, args,
+ &hw_com_instance_callbacks);
+}
+
+
+static device_callbacks const hw_com_callbacks = {
+ { generic_device_init_address,
+ hw_com_device_init_data },
+ { NULL, }, /* address */
+ { hw_com_io_read_buffer_callback,
+ hw_com_io_write_buffer_callback, },
+ { NULL, }, /* DMA */
+ { NULL, }, /* interrupt */
+ { NULL, }, /* unit */
+ hw_com_create_instance,
+};
+
+
+static void *
+hw_com_create(const char *name,
+ const device_unit *unit_address,
+ const char *args)
+{
+ /* create the descriptor */
+ hw_com_device *hw_com = ZALLOC(hw_com_device);
+ return hw_com;
+}
+
+
+const device_descriptor hw_com_device_descriptor[] = {
+ { "com", hw_com_create, &hw_com_callbacks },
+ { NULL },
+};
+
+#endif /* _HW_COM_C_ */
diff --git a/gnu/dist/sim/ppc/hw_core.c b/gnu/dist/sim/ppc/hw_core.c
new file mode 100644
index 00000000000..1a439576bd9
--- /dev/null
+++ b/gnu/dist/sim/ppc/hw_core.c
@@ -0,0 +1,143 @@
+/* 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.
+
+ */
+
+
+#ifndef _HW_CORE_C_
+#define _HW_CORE_C_
+
+#include "device_table.h"
+
+#include "corefile.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
+hw_core_init_address_callback(device *me)
+{
+ core *memory = (core*)device_data(me);
+ core_init(memory);
+}
+
+
+static void
+hw_core_attach_address_callback(device *me,
+ attach_type attach,
+ int space,
+ unsigned_word addr,
+ unsigned nr_bytes,
+ access_type access,
+ device *client) /*callback/default*/
+{
+ core *memory = (core*)device_data(me);
+ if (space != 0)
+ error("core_attach_address_callback() invalid address space\n");
+ core_attach(memory,
+ attach,
+ space,
+ access,
+ addr,
+ nr_bytes,
+ client);
+}
+
+
+static unsigned
+hw_core_dma_read_buffer_callback(device *me,
+ void *dest,
+ int space,
+ unsigned_word addr,
+ unsigned nr_bytes)
+{
+ core *memory = (core*)device_data(me);
+ return core_map_read_buffer(core_readable(memory),
+ dest,
+ addr,
+ nr_bytes);
+}
+
+
+static unsigned
+hw_core_dma_write_buffer_callback(device *me,
+ const void *source,
+ int space,
+ unsigned_word addr,
+ unsigned nr_bytes,
+ int violate_read_only_section)
+{
+ core *memory = (core*)device_data(me);
+ core_map *map = (violate_read_only_section
+ ? core_readable(memory)
+ : core_writeable(memory));
+ return core_map_write_buffer(map,
+ source,
+ addr,
+ nr_bytes);
+}
+
+static device_callbacks const hw_core_callbacks = {
+ { hw_core_init_address_callback, },
+ { hw_core_attach_address_callback, },
+ { NULL, }, /* IO */
+ { hw_core_dma_read_buffer_callback,
+ hw_core_dma_write_buffer_callback, },
+ { NULL, }, /* interrupt */
+ { generic_device_unit_decode,
+ generic_device_unit_encode,
+ generic_device_address_to_attach_address,
+ generic_device_size_to_attach_size, },
+};
+
+
+static void *
+hw_core_create(const char *name,
+ const device_unit *unit_address,
+ const char *args)
+{
+ core *memory = core_create();
+ return memory;
+}
+
+const device_descriptor hw_core_device_descriptor[] = {
+ { "core", hw_core_create, &hw_core_callbacks },
+ { NULL },
+};
+
+#endif /* _HW_CORE_C_ */
diff --git a/gnu/dist/sim/ppc/hw_cpu.c b/gnu/dist/sim/ppc/hw_cpu.c
new file mode 100644
index 00000000000..117a4c256f2
--- /dev/null
+++ b/gnu/dist/sim/ppc/hw_cpu.c
@@ -0,0 +1,167 @@
+/* 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.
+
+ */
+
+
+#ifndef _HW_CPU_C_
+#define _HW_CPU_C_
+
+#ifndef STATIC_INLINE_HW_CPU
+#define STATIC_INLINE_HW_CPU STATIC_INLINE
+#endif
+
+#include "device_table.h"
+#include "hw_cpu.h"
+
+#include "interrupts.h"
+#include "cpu.h"
+
+
+/* DEVICE
+
+
+ cpu - Interface to a Processor
+
+
+ DESCRIPTION
+
+
+ The CPU device provides the connection between the interrupt net
+ (linking the devices and the interrupt controller) and the
+ simulated model of each processor. This device contains interrupt
+ ports that correspond directly to the external interrupt stimulus
+ that can be sent to a given processor. Sending an interrupt to one
+ of the ports results in an interrupt being delivered to the
+ corresponding processor.
+
+ Typically, an interrupt controller would have its inputs connected
+ to device interrupt sources and its outputs (sreset, int, et.al.)
+ connected to this device.
+
+
+ PROPERTIES
+
+
+ cpu-nr = <integer> (required)
+
+
+ Specify the processor (1..N) that this cpu device node should
+ control.
+
+
+ EXAMPLES
+
+
+ Connect an OpenPIC interrupt controller interrupt ports to
+ processor zero.
+
+ | -o '/phb/opic@0 > irq0 int /cpus/cpu@0' \
+ | -o '/phb/opic@0 > init hreset /cpus/cpu@0' \
+
+
+ */
+
+typedef struct _hw_cpu_device {
+ int cpu_nr;
+ cpu *processor;
+} hw_cpu_device;
+
+static const device_interrupt_port_descriptor hw_cpu_interrupt_ports[] = {
+ { "hreset", hw_cpu_hard_reset },
+ { "sreset", hw_cpu_soft_reset },
+ { "int", hw_cpu_external_interrupt },
+ { "mci", hw_cpu_machine_check_interrupt },
+ { "smi", hw_cpu_system_management_interrupt },
+ { NULL }
+};
+
+
+static void *
+hw_cpu_create(const char *name,
+ const device_unit *unit_address,
+ const char *args)
+{
+ hw_cpu_device *hw_cpu = ZALLOC(hw_cpu_device);
+ return hw_cpu;
+}
+
+
+/* during address initialization ensure that any missing cpu
+ properties are added to this devices node */
+
+static void
+hw_cpu_init_address(device *me)
+{
+ hw_cpu_device *hw_cpu = (hw_cpu_device*)device_data(me);
+ /* populate the node with properties */
+ /* clear our data */
+ memset(hw_cpu, 0x0, sizeof(hw_cpu_device));
+ hw_cpu->cpu_nr = device_find_integer_property(me, "cpu-nr");
+ hw_cpu->processor = psim_cpu(device_system(me), hw_cpu->cpu_nr);
+}
+
+
+/* Take the interrupt and synchronize its delivery with the clock. If
+ we've not yet scheduled an interrupt for the next clock tick, take
+ the oportunity to do it now */
+
+static void
+hw_cpu_interrupt_event(device *me,
+ int my_port,
+ device *source,
+ int source_port,
+ int level,
+ cpu *processor,
+ unsigned_word cia)
+{
+ hw_cpu_device *hw_cpu = (hw_cpu_device*)device_data(me);
+ if (my_port < 0 || my_port >= hw_cpu_nr_interrupt_ports)
+ error("hw_cpu_interrupt_event_callback: interrupt port out of range %d\n",
+ my_port);
+ switch (my_port) {
+ /*case hw_cpu_hard_reset:*/
+ /*case hw_cpu_soft_reset:*/
+ case hw_cpu_external_interrupt:
+ external_interrupt(hw_cpu->processor, level);
+ break;
+ /*case hw_cpu_machine_check_interrupt:*/
+ default:
+ error("hw_cpu_deliver_interrupt: unimplemented interrupt port %d\n",
+ my_port);
+ break;
+ }
+}
+
+
+static device_callbacks const hw_cpu_callbacks = {
+ { hw_cpu_init_address, }, /* init */
+ { NULL, }, /* address */
+ { NULL, }, /* io */
+ { NULL, }, /* DMA */
+ { hw_cpu_interrupt_event, NULL, hw_cpu_interrupt_ports }, /* interrupts */
+ { NULL, NULL, },
+};
+
+const device_descriptor hw_cpu_device_descriptor[] = {
+ { "hw-cpu", hw_cpu_create, &hw_cpu_callbacks },
+ { "cpu", hw_cpu_create, &hw_cpu_callbacks },
+ { NULL, },
+};
+
+#endif /* _HW_CPU_C_ */
diff --git a/gnu/dist/sim/ppc/hw_cpu.h b/gnu/dist/sim/ppc/hw_cpu.h
new file mode 100644
index 00000000000..11d0298ee12
--- /dev/null
+++ b/gnu/dist/sim/ppc/hw_cpu.h
@@ -0,0 +1,34 @@
+/* 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.
+
+ */
+
+
+#ifndef _HW_CPU_H_
+#define _HW_CPU_H_
+
+enum {
+ hw_cpu_hard_reset,
+ hw_cpu_soft_reset,
+ hw_cpu_external_interrupt,
+ hw_cpu_machine_check_interrupt,
+ hw_cpu_system_management_interrupt,
+ hw_cpu_nr_interrupt_ports
+};
+
+#endif /* _HW_CPU_H_ */
diff --git a/gnu/dist/sim/ppc/hw_disk.c b/gnu/dist/sim/ppc/hw_disk.c
new file mode 100644
index 00000000000..5934fead1a1
--- /dev/null
+++ b/gnu/dist/sim/ppc/hw_disk.c
@@ -0,0 +1,557 @@
+/* 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_DISK_C_
+#define _HW_DISK_C_
+
+#include "device_table.h"
+
+#include "pk.h"
+
+#include <stdio.h>
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifndef SEEK_SET
+#define SEEK_SET 0
+#endif
+
+/* DEVICE
+
+
+ cdrom - read-only removable mass storage device
+
+ disk - mass storage device
+
+ floppy - removable mass storage device
+
+
+ DESCRIPTION
+
+
+ Mass storage devices such as a hard-disk or cdrom-drive are not
+ normally directly connected to the processor. Instead, these
+ devices are attached to a logical bus, such as SCSI or IDE, and
+ then a controller of that bus is made accessible to the processor.
+
+ Reflecting this, within a device tree, mass storage devices such as
+ a <<cdrom>>, <<disk>> or <<floppy>> are created as children of of a
+ logical bus controller node (such as a SCSI or IDE interface).
+ That controller, in turn, would be made the child of a physical bus
+ node that is directly accessible to the processor.
+
+ The above mass storage devices provide two interfaces - a logical
+ and a physical.
+
+ At the physical level the <<device_io_...>> functions can be used
+ perform reads and writes of the raw media. The address being
+ interpreted as an offset from the start of the disk.
+
+ At the logical level, it is possible to create an instance of the
+ disk that provides access to any of the physical media, a disk
+ partition, or even a file within a partition. The <<disk-label>>
+ package, which implements this functionality, is described
+ elsewhere. Both the Open Firmware and Moto BUG rom emulations
+ support this interface.
+
+ Block devices such as the <<floppy>> and <<cdrom>> have removable
+ media. At the programmer level, the media can be changed using the
+ <<change_media>> ioctl. From within GDB, a <<change-media>>
+ operation can be initated by using the command.
+
+ | (gdb) sim
+
+
+ PROPERTIES
+
+
+ file = <file-name> (required)
+
+ The name of the file that contains an image of the disk. For
+ <<disk>> and <<floppy>> devices, the image will be opened for both
+ reading and writing. Multiple image files may be specified, the
+ second and later files being opened when <<change-media>> (with a
+ NULL file name) being specified.
+
+
+ block-size = <nr-bytes> (optional)
+
+ The value is returned by the block-size method. The default value
+ is 512 bytes.
+
+
+ max-transfer = <nr-bytes> (optional)
+
+ The value is returned by the max-transfer method. The default value
+ is 512 bytes.
+
+
+ #blocks = <nr-blocks> (optional)
+
+ The value is returned by the #blocks method. If no value is
+ present then -1 is returned.
+
+
+ read-only = <anything> (optional)
+
+ If this property is present, the disk file image is always opened
+ read-only.
+
+ EXAMPLES
+
+
+ Enable tracing
+
+ | $ psim -t 'disk-device' \
+
+
+ Add a CDROM and disk to an IDE bus. Specify the host operating
+ system's cd drive as the CD-ROM image.
+
+ | -o '/pci/ide/disk@0/file "disk-image' \
+ | -o '/pci/ide/cdrom@1/file "/dev/cd0a' \
+
+
+ As part of the code implementing a logical bus device (for instance
+ the IDE controller), locate the CDROM device and then read block
+ 47.
+
+ | device *cdrom = device_tree_find_device(me, "cdrom");
+ | char block[512];
+ | device_io_read_buffer(cdrom, buf, 0,
+ 0, 47 * sizeof(block), // space, address
+ sizeof(block), NULL, 0);
+
+
+ Use the device instance interface to read block 47 of the file
+ called <<netbsd.elf>> on the disks default partition. Similar code
+ would be used in an operating systems pre-boot loader.
+
+ | device_instance *netbsd =
+ | device_create_instance(root, "/pci/ide/disk:,\netbsd.elf");
+ | char block[512];
+ | device_instance_seek(netbsd, 0, 47 * sizeof(block));
+ | device_instance_read(netbsd, block, sizeof(block));
+
+
+ BUGS
+
+
+ The block device specification includes mechanisms for determining
+ the physical device characteristics - such as the disks size.
+ Currently this mechanism is not implemented.
+
+ The functionality of this device (in particular the device instance
+ interface) depends on the implementation of <<disk-label>> package.
+ That package may not be fully implemented.
+
+ The disk does not know its size. Hence it relies on the failure of
+ fread(), fwrite() and fseek() calls to detect errors.
+
+ The disk size is limited by the addressable range covered by
+ unsigned_word (addr). An extension would be to instead use the
+ concatenated value space:addr.
+
+ The method #blocks should `stat' the disk to determine the number
+ of blocks if there is no #blocks property.
+
+ It would appear that OpenFirmware does not define a client call for
+ changing (ejecting) the media of a device.
+
+ */
+
+typedef struct _hw_disk_device {
+ int name_index;
+ int nr_names;
+ char *name;
+ int read_only;
+ /* unsigned_word size; */
+ FILE *image;
+} hw_disk_device;
+
+typedef struct _hw_disk_instance {
+ unsigned_word pos;
+ hw_disk_device *disk;
+} hw_disk_instance;
+
+
+static void
+open_disk_image(device *me,
+ hw_disk_device *disk,
+ const char *name)
+{
+ if (disk->image != NULL)
+ fclose(disk->image);
+ if (disk->name != NULL)
+ zfree(disk->name);
+ disk->name = strdup(name);
+ disk->image = fopen(disk->name, disk->read_only ? "r" : "r+");
+ if (disk->image == NULL) {
+ perror(device_name(me));
+ device_error(me, "open %s failed\n", disk->name);
+ }
+
+ DTRACE(disk, ("image %s (%s)\n",
+ disk->name,
+ (disk->read_only ? "read-only" : "read-write")));
+}
+
+static void
+hw_disk_init_address(device *me)
+{
+ hw_disk_device *disk = device_data(me);
+ unsigned_word address;
+ int space;
+ const char *name;
+
+ /* attach to the parent. Since the bus is logical, attach using just
+ the unit-address (size must be zero) */
+ device_address_to_attach_address(device_parent(me), device_unit_address(me),
+ &space, &address, me);
+ device_attach_address(device_parent(me), attach_callback,
+ space, address, 0/*size*/, access_read_write_exec,
+ me);
+
+ /* get the name of the file specifying the disk image */
+ disk->name_index = 0;
+ disk->nr_names = device_find_string_array_property(me, "file",
+ disk->name_index, &name);
+ if (!disk->nr_names)
+ device_error(me, "invalid file property");
+
+ /* is it a RO device? */
+ disk->read_only =
+ (strcmp(device_name(me), "disk") != 0
+ && strcmp(device_name(me), "floppy") != 0
+ && device_find_property(me, "read-only") == NULL);
+
+ /* now open it */
+ open_disk_image(me, disk, name);
+}
+
+static int
+hw_disk_ioctl(device *me,
+ cpu *processor,
+ unsigned_word cia,
+ device_ioctl_request request,
+ va_list ap)
+{
+ switch (request) {
+ case device_ioctl_change_media:
+ {
+ hw_disk_device *disk = device_data(me);
+ const char *name = va_arg(ap, const char *);
+ if (name != NULL) {
+ disk->name_index = -1;
+ }
+ else {
+ disk->name_index = (disk->name_index + 1) % disk->nr_names;
+ if (!device_find_string_array_property(me, "file",
+ disk->name_index, &name))
+ device_error(me, "invalid file property");
+ }
+ open_disk_image(me, disk, name);
+ }
+ break;
+ default:
+ device_error(me, "insupported ioctl request");
+ break;
+ }
+ return 0;
+}
+
+
+
+
+
+static unsigned
+hw_disk_io_read_buffer(device *me,
+ void *dest,
+ int space,
+ unsigned_word addr,
+ unsigned nr_bytes,
+ cpu *processor,
+ unsigned_word cia)
+{
+ hw_disk_device *disk = device_data(me);
+ unsigned nr_bytes_read;
+ if (space != 0)
+ device_error(me, "read - extended disk addressing unimplemented");
+ if (nr_bytes == 0)
+ nr_bytes_read = 0;
+ else if (fseek(disk->image, addr, SEEK_SET) < 0)
+ nr_bytes_read = 0;
+ else if (fread(dest, nr_bytes, 1, disk->image) != 1)
+ nr_bytes_read = 0;
+ else
+ nr_bytes_read = nr_bytes;
+ DTRACE(disk, ("io-read - address 0x%lx, nr-bytes-read %d, requested %d\n",
+ (unsigned long) addr, (int)nr_bytes_read, (int)nr_bytes));
+ return nr_bytes_read;
+}
+
+
+static unsigned
+hw_disk_io_write_buffer(device *me,
+ const void *source,
+ int space,
+ unsigned_word addr,
+ unsigned nr_bytes,
+ cpu *processor,
+ unsigned_word cia)
+{
+ hw_disk_device *disk = device_data(me);
+ unsigned nr_bytes_written;
+ if (space != 0)
+ device_error(me, "write - extended disk addressing unimplemented");
+ if (disk->read_only)
+ nr_bytes_written = 0;
+ else if (nr_bytes == 0)
+ nr_bytes_written = 0;
+ else if (fseek(disk->image, addr, SEEK_SET) < 0)
+ nr_bytes_written = 0;
+ else if (fwrite(source, nr_bytes, 1, disk->image) != 1)
+ nr_bytes_written = 0;
+ else
+ nr_bytes_written = nr_bytes;
+ DTRACE(disk, ("io-write - address 0x%lx, nr-bytes-written %d, requested %d\n",
+ (unsigned long) addr, (int)nr_bytes_written, (int)nr_bytes));
+ return nr_bytes_written;
+}
+
+
+/* instances of the hw_disk device */
+
+static void
+hw_disk_instance_delete(device_instance *instance)
+{
+ hw_disk_instance *data = device_instance_data(instance);
+ DITRACE(disk, ("delete - instance=%ld\n",
+ (unsigned long)device_instance_to_external(instance)));
+ zfree(data);
+}
+
+static int
+hw_disk_instance_read(device_instance *instance,
+ void *buf,
+ unsigned_word len)
+{
+ hw_disk_instance *data = device_instance_data(instance);
+ DITRACE(disk, ("read - instance=%ld len=%ld\n",
+ (unsigned long)device_instance_to_external(instance),
+ (long)len));
+ if ((data->pos + len) < data->pos)
+ return -1; /* overflow */
+ if (fseek(data->disk->image, data->pos, SEEK_SET) < 0)
+ return -1;
+ if (fread(buf, len, 1, data->disk->image) != 1)
+ return -1;
+ data->pos = ftell(data->disk->image);
+ return len;
+}
+
+static int
+hw_disk_instance_write(device_instance *instance,
+ const void *buf,
+ unsigned_word len)
+{
+ hw_disk_instance *data = device_instance_data(instance);
+ DITRACE(disk, ("write - instance=%ld len=%ld\n",
+ (unsigned long)device_instance_to_external(instance),
+ (long)len));
+ if ((data->pos + len) < data->pos)
+ return -1; /* overflow */
+ if (data->disk->read_only)
+ return -1;
+ if (fseek(data->disk->image, data->pos, SEEK_SET) < 0)
+ return -1;
+ if (fwrite(buf, len, 1, data->disk->image) != 1)
+ return -1;
+ data->pos = ftell(data->disk->image);
+ return len;
+}
+
+static int
+hw_disk_instance_seek(device_instance *instance,
+ unsigned_word pos_hi,
+ unsigned_word pos_lo)
+{
+ hw_disk_instance *data = device_instance_data(instance);
+ if (pos_hi != 0)
+ device_error(device_instance_device(instance),
+ "seek - extended addressing unimplemented");
+ DITRACE(disk, ("seek - instance=%ld pos_hi=%ld pos_lo=%ld\n",
+ (unsigned long)device_instance_to_external(instance),
+ (long)pos_hi, (long)pos_lo));
+ data->pos = pos_lo;
+ return 0;
+}
+
+static int
+hw_disk_max_transfer(device_instance *instance,
+ int n_stack_args,
+ unsigned32 stack_args[/*n_stack_args*/],
+ int n_stack_returns,
+ unsigned32 stack_returns[/*n_stack_returns*/])
+{
+ device *me = device_instance_device(instance);
+ if ((n_stack_args != 0)
+ || (n_stack_returns != 1)) {
+ device_error(me, "Incorrect number of arguments for max-transfer method\n");
+ return -1;
+ }
+ else {
+ unsigned_cell max_transfer;
+ if (device_find_property(me, "max-transfer"))
+ max_transfer = device_find_integer_property(me, "max-transfer");
+ else
+ max_transfer = 512;
+ DITRACE(disk, ("max-transfer - instance=%ld max-transfer=%ld\n",
+ (unsigned long)device_instance_to_external(instance),
+ (long int)max_transfer));
+ stack_returns[0] = max_transfer;
+ return 0;
+ }
+}
+
+static int
+hw_disk_block_size(device_instance *instance,
+ int n_stack_args,
+ unsigned32 stack_args[/*n_stack_args*/],
+ int n_stack_returns,
+ unsigned32 stack_returns[/*n_stack_returns*/])
+{
+ device *me = device_instance_device(instance);
+ if ((n_stack_args != 0)
+ || (n_stack_returns != 1)) {
+ device_error(me, "Incorrect number of arguments for block-size method\n");
+ return -1;
+ }
+ else {
+ unsigned_cell block_size;
+ if (device_find_property(me, "block-size"))
+ block_size = device_find_integer_property(me, "block-size");
+ else
+ block_size = 512;
+ DITRACE(disk, ("block-size - instance=%ld block-size=%ld\n",
+ (unsigned long)device_instance_to_external(instance),
+ (long int)block_size));
+ stack_returns[0] = block_size;
+ return 0;
+ }
+}
+
+static int
+hw_disk_nr_blocks(device_instance *instance,
+ int n_stack_args,
+ unsigned32 stack_args[/*n_stack_args*/],
+ int n_stack_returns,
+ unsigned32 stack_returns[/*n_stack_returns*/])
+{
+ device *me = device_instance_device(instance);
+ if ((n_stack_args != 0)
+ || (n_stack_returns != 1)) {
+ device_error(me, "Incorrect number of arguments for block-size method\n");
+ return -1;
+ }
+ else {
+ unsigned_word nr_blocks;
+ if (device_find_property(me, "#blocks"))
+ nr_blocks = device_find_integer_property(me, "#blocks");
+ else
+ nr_blocks = -1;
+ DITRACE(disk, ("#blocks - instance=%ld #blocks=%ld\n",
+ (unsigned long)device_instance_to_external(instance),
+ (long int)nr_blocks));
+ stack_returns[0] = nr_blocks;
+ return 0;
+ }
+}
+
+static device_instance_methods hw_disk_instance_methods[] = {
+ { "max-transfer", hw_disk_max_transfer },
+ { "block-size", hw_disk_block_size },
+ { "#blocks", hw_disk_nr_blocks },
+ { NULL, },
+};
+
+static const device_instance_callbacks hw_disk_instance_callbacks = {
+ hw_disk_instance_delete,
+ hw_disk_instance_read,
+ hw_disk_instance_write,
+ hw_disk_instance_seek,
+ hw_disk_instance_methods,
+};
+
+static device_instance *
+hw_disk_create_instance(device *me,
+ const char *path,
+ const char *args)
+{
+ device_instance *instance;
+ hw_disk_device *disk = device_data(me);
+ hw_disk_instance *data = ZALLOC(hw_disk_instance);
+ data->disk = disk;
+ data->pos = 0;
+ instance = device_create_instance_from(me, NULL,
+ data,
+ path, args,
+ &hw_disk_instance_callbacks);
+ DITRACE(disk, ("create - path=%s(%s) instance=%ld\n",
+ path, args,
+ (unsigned long)device_instance_to_external(instance)));
+ return pk_disklabel_create_instance(instance, args);
+}
+
+static device_callbacks const hw_disk_callbacks = {
+ { hw_disk_init_address, NULL },
+ { NULL, }, /* address */
+ { hw_disk_io_read_buffer,
+ hw_disk_io_write_buffer, },
+ { NULL, }, /* DMA */
+ { NULL, }, /* interrupt */
+ { NULL, }, /* unit */
+ hw_disk_create_instance,
+ hw_disk_ioctl,
+};
+
+
+static void *
+hw_disk_create(const char *name,
+ const device_unit *unit_address,
+ const char *args)
+{
+ /* create the descriptor */
+ hw_disk_device *hw_disk = ZALLOC(hw_disk_device);
+ return hw_disk;
+}
+
+
+const device_descriptor hw_disk_device_descriptor[] = {
+ { "disk", hw_disk_create, &hw_disk_callbacks },
+ { "cdrom", hw_disk_create, &hw_disk_callbacks },
+ { "floppy", hw_disk_create, &hw_disk_callbacks },
+ { NULL },
+};
+
+#endif /* _HW_DISK_C_ */
diff --git a/gnu/dist/sim/ppc/hw_eeprom.c b/gnu/dist/sim/ppc/hw_eeprom.c
new file mode 100644
index 00000000000..5092984369e
--- /dev/null
+++ b/gnu/dist/sim/ppc/hw_eeprom.c
@@ -0,0 +1,839 @@
+/* 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.
+
+ */
+
+
+#ifndef _HW_EEPROM_C_
+#define _HW_EEPROM_C_
+
+#include "device_table.h"
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#endif
+
+
+/* DEVICE
+
+
+ eeprom - JEDEC? compatible electricaly erasable programable device
+
+
+ DESCRIPTION
+
+
+ This device implements a small byte addressable EEPROM.
+ Programming is performed using the same write sequences as used by
+ standard modern EEPROM components. Writes occure in real time, the
+ device returning a progress value until the programing has been
+ completed.
+
+ It is based on the AMD 29F040 component.
+
+
+ PROPERTIES
+
+
+ reg = <address> <size> (required)
+
+ Determine where the device lives in the parents address space.
+
+
+ nr-sectors = <integer> (required)
+
+ When erasing an entire sector is cleared at a time. This specifies
+ the number of sectors in the EEPROM component.
+
+
+ sector-size = <integer> (required)
+
+ The number of bytes in a sector. When erasing, memory chunks of
+ this size are cleared.
+
+ NOTE: The product nr-sectors * sector-size does not need to map the
+ size specified in the reg property. If the specified size is
+ smaller part of the eeprom will not be accessible while if it is
+ larger the addresses will wrap.
+
+
+ byte-write-delay = <integer> (required)
+
+ Number of clock ticks before the programming of a single byte
+ completes.
+
+
+ sector-start-delay = <integer> (required)
+
+ When erasing sectors, the number of clock ticks after the sector
+ has been specified that the actual erase process commences.
+
+
+ erase-delay = <intger> (required)
+
+ Number of clock ticks before an erase program completes
+
+
+ manufacture-code = <integer> (required)
+
+ The one byte value returned when the auto-select manufacturer code
+ is read.
+
+
+ device-code = <integer> (required)
+
+ The one byte value returned when the auto-select device code is
+ read.
+
+
+ input-file = <file-name> (optional)
+
+ Initialize the eeprom using the specified binary file.
+
+
+ output-file = <file-name> (optional)
+
+ When ever the eeprom is updated, save the modified image into the
+ specified file.
+
+
+ EXAMPLES
+
+
+ Enable tracing of the eeprom:
+
+ | bash$ psim -t eeprom-device \
+
+
+ Configure something very like the Amd Am29F040 - 512byte EEPROM
+ (but a bit faster):
+
+ | -o '/eeprom@0xfff00000/reg 0xfff00000 0x80000' \
+ | -o '/eeprom@0xfff00000/nr-sectors 8' \
+ | -o '/eeprom@0xfff00000/sector-size 0x10000' \
+ | -o '/eeprom@0xfff00000/byte-write-delay 1000' \
+ | -o '/eeprom@0xfff00000/sector-start-delay 100' \
+ | -o '/eeprom@0xfff00000/erase-delay 1000' \
+ | -o '/eeprom@0xfff00000/manufacture-code 0x01' \
+ | -o '/eeprom@0xfff00000/device-code 0xa4' \
+
+
+ Initialize the eeprom from the file <</dev/zero>>:
+
+ | -o '/eeprom@0xfff00000/input-file /dev/zero'
+
+
+ BUGS
+
+
+ */
+
+typedef enum {
+ read_reset,
+ write_nr_2,
+ write_nr_3,
+ write_nr_4,
+ write_nr_5,
+ write_nr_6,
+ byte_program,
+ byte_programming,
+ chip_erase,
+ sector_erase,
+ sector_erase_suspend,
+ autoselect,
+} hw_eeprom_states;
+
+static const char *
+state2a(hw_eeprom_states state)
+{
+ switch (state) {
+ case read_reset: return "read_reset";
+ case write_nr_2: return "write_nr_2";
+ case write_nr_3: return "write_nr_3";
+ case write_nr_4: return "write_nr_4";
+ case write_nr_5: return "write_nr_5";
+ case write_nr_6: return "write_nr_6";
+ case byte_program: return "byte_program";
+ case byte_programming: return "byte_programming";
+ case chip_erase: return "chip_erase";
+ case sector_erase: return "sector_erase";
+ case sector_erase_suspend: return "sector_erase_suspend";
+ case autoselect: return "autoselect";
+ }
+ return NULL;
+}
+
+typedef struct _hw_eeprom_device {
+ /* general */
+ hw_eeprom_states state;
+ unsigned8 *memory;
+ unsigned sizeof_memory;
+ unsigned erase_delay;
+ signed64 program_start_time;
+ signed64 program_finish_time;
+ unsigned8 manufacture_code;
+ unsigned8 device_code;
+ unsigned8 toggle_bit;
+ /* initialization */
+ const char *input_file_name;
+ const char *output_file_name;
+ /* for sector and sector programming */
+ hw_eeprom_states sector_state;
+ unsigned8 *sectors;
+ unsigned nr_sectors;
+ unsigned sizeof_sector;
+ unsigned sector_start_delay;
+ unsigned sector_start_time;
+ /* byte and byte programming */
+ unsigned byte_write_delay;
+ unsigned_word byte_program_address;
+ unsigned8 byte_program_byte;
+} hw_eeprom_device;
+
+typedef struct _hw_eeprom_reg_spec {
+ unsigned32 base;
+ unsigned32 size;
+} hw_eeprom_reg_spec;
+
+static void
+hw_eeprom_init_data(device *me)
+{
+ hw_eeprom_device *eeprom = (hw_eeprom_device*)device_data(me);
+
+ /* have we any input or output files */
+ if (device_find_property(me, "input-file") != NULL)
+ eeprom->input_file_name = device_find_string_property(me, "input-file");
+ if (device_find_property(me, "output-file") != NULL)
+ eeprom->input_file_name = device_find_string_property(me, "output-file");
+
+ /* figure out the sectors in the eeprom */
+ if (eeprom->sectors == NULL) {
+ eeprom->nr_sectors = device_find_integer_property(me, "nr-sectors");
+ eeprom->sizeof_sector = device_find_integer_property(me, "sector-size");
+ eeprom->sectors = zalloc(eeprom->nr_sectors);
+ }
+ else
+ memset(eeprom->sectors, 0, eeprom->nr_sectors);
+
+ /* initialize the eeprom */
+ if (eeprom->memory == NULL) {
+ eeprom->sizeof_memory = eeprom->sizeof_sector * eeprom->nr_sectors;
+ eeprom->memory = zalloc(eeprom->sizeof_memory);
+ }
+ else
+ memset(eeprom->memory, 0, eeprom->sizeof_memory);
+ if (eeprom->input_file_name != NULL) {
+ int i;
+ FILE *input_file = fopen(eeprom->input_file_name, "r");
+ if (input_file == NULL) {
+ perror("eeprom");
+ device_error(me, "Failed to open input file %s\n", eeprom->input_file_name);
+ }
+ for (i = 0; i < eeprom->sizeof_memory; i++) {
+ if (fread(&eeprom->memory[i], 1, 1, input_file) != 1)
+ break;
+ }
+ fclose(input_file);
+ }
+
+ /* timing */
+ eeprom->byte_write_delay = device_find_integer_property(me, "byte-write-delay");
+ eeprom->sector_start_delay = device_find_integer_property(me, "sector-start-delay");
+ eeprom->erase_delay = device_find_integer_property(me, "erase-delay");
+
+ /* misc */
+ eeprom->manufacture_code = device_find_integer_property(me, "manufacture-code");
+ eeprom->device_code = device_find_integer_property(me, "device-code");
+}
+
+
+static void
+invalid_read(device *me,
+ hw_eeprom_states state,
+ unsigned_word address,
+ const char *reason)
+{
+ DTRACE(eeprom, ("Invalid read to 0x%lx while in state %s (%s)\n",
+ (unsigned long)address,
+ state2a(state),
+ reason));
+}
+
+static void
+invalid_write(device *me,
+ hw_eeprom_states state,
+ unsigned_word address,
+ unsigned8 data,
+ const char *reason)
+{
+ DTRACE(eeprom, ("Invalid write of 0x%lx to 0x%lx while in state %s (%s)\n",
+ (unsigned long)data,
+ (unsigned long)address,
+ state2a(state),
+ reason));
+}
+
+static void
+dump_eeprom(device *me,
+ hw_eeprom_device *eeprom)
+{
+ if (eeprom->output_file_name != NULL) {
+ int i;
+ FILE *output_file = fopen(eeprom->output_file_name, "w");
+ if (output_file == NULL) {
+ perror("eeprom");
+ device_error(me, "Failed to open output file %s\n",
+ eeprom->output_file_name);
+ }
+ for (i = 0; i < eeprom->sizeof_memory; i++) {
+ if (fwrite(&eeprom->memory[i], 1, 1, output_file) != 1)
+ break;
+ }
+ fclose(output_file);
+ }
+}
+
+
+/* program a single byte of eeprom */
+
+static void
+start_programming_byte(device *me,
+ hw_eeprom_device *eeprom,
+ unsigned_word address,
+ unsigned8 new_byte)
+{
+ unsigned8 old_byte = eeprom->memory[address];
+ DTRACE(eeprom, ("start-programing-byte - address 0x%lx, new 0x%lx, old 0x%lx\n",
+ (unsigned long)address,
+ (unsigned long)new_byte,
+ (unsigned long)old_byte));
+ eeprom->byte_program_address = address;
+ /* : old new : ~old : new&~old
+ : 0 0 : 1 : 0
+ : 0 1 : 1 : 1 -- can not set a bit
+ : 1 0 : 0 : 0
+ : 1 1 : 0 : 0 */
+ if (~old_byte & new_byte)
+ invalid_write(me, eeprom->state, address, new_byte, "setting cleared bit");
+ /* : old new : old&new
+ : 0 0 : 0
+ : 0 1 : 0
+ : 1 0 : 0
+ : 1 1 : 1 */
+ eeprom->byte_program_byte = new_byte & old_byte;
+ eeprom->memory[address] = ~new_byte & ~0x24; /* LE-bits 5:3 zero */
+ eeprom->program_start_time = device_event_queue_time(me);
+ eeprom->program_finish_time = (eeprom->program_start_time
+ + eeprom->byte_write_delay);
+}
+
+static void
+finish_programming_byte(device *me,
+ hw_eeprom_device *eeprom)
+{
+ DTRACE(eeprom, ("finish-programming-byte - address 0x%lx, byte 0x%lx\n",
+ (unsigned long)eeprom->byte_program_address,
+ (unsigned long)eeprom->byte_program_byte));
+ eeprom->memory[eeprom->byte_program_address] = eeprom->byte_program_byte;
+ dump_eeprom(me, eeprom);
+}
+
+
+/* erase the eeprom completly */
+
+static void
+start_erasing_chip(device *me,
+ hw_eeprom_device *eeprom)
+{
+ DTRACE(eeprom, ("start-erasing-chip\n"));
+ memset(eeprom->memory, 0, eeprom->sizeof_memory);
+ eeprom->program_start_time = device_event_queue_time(me);
+ eeprom->program_finish_time = (eeprom->program_start_time
+ + eeprom->erase_delay);
+}
+
+static void
+finish_erasing_chip(device *me,
+ hw_eeprom_device *eeprom)
+{
+ DTRACE(eeprom, ("finish-erasing-chip\n"));
+ memset(eeprom->memory, 0xff, eeprom->sizeof_memory);
+ dump_eeprom(me, eeprom);
+}
+
+
+/* erase a single sector of the eeprom */
+
+static void
+start_erasing_sector(device *me,
+ hw_eeprom_device *eeprom,
+ unsigned_word address)
+{
+ int sector = address / eeprom->sizeof_sector;
+ DTRACE(eeprom, ("start-erasing-sector - address 0x%lx, sector %d\n",
+ (unsigned long)address, sector));
+ ASSERT(sector < eeprom->nr_sectors);
+ eeprom->sectors[sector] = 1;
+ memset(eeprom->memory + sector * eeprom->sizeof_sector,
+ 0x4, eeprom->sizeof_sector);
+ eeprom->program_start_time = device_event_queue_time(me);
+ eeprom->sector_start_time = (eeprom->program_start_time
+ + eeprom->sector_start_delay);
+ eeprom->program_finish_time = (eeprom->sector_start_time
+ + eeprom->erase_delay);
+
+}
+
+static void
+finish_erasing_sector(device *me,
+ hw_eeprom_device *eeprom)
+{
+ int sector;
+ DTRACE(eeprom, ("finish-erasing-sector\n"));
+ for (sector = 0; sector < eeprom->nr_sectors; sector++) {
+ if (eeprom->sectors[sector]) {
+ eeprom->sectors[sector] = 0;
+ memset(eeprom->memory + sector * eeprom->sizeof_sector,
+ 0xff, eeprom->sizeof_sector);
+ }
+ }
+ dump_eeprom(me, eeprom);
+}
+
+
+/* eeprom reads */
+
+static unsigned8
+toggle(hw_eeprom_device *eeprom,
+ unsigned8 byte)
+{
+ eeprom->toggle_bit = eeprom->toggle_bit ^ 0x40; /* le-bit 6 */
+ return eeprom->toggle_bit ^ byte;
+}
+
+static unsigned8
+read_byte(device *me,
+ hw_eeprom_device *eeprom,
+ unsigned_word address)
+{
+ /* may need multiple iterations of this */
+ while (1) {
+ switch (eeprom->state) {
+
+ case read_reset:
+ return eeprom->memory[address];
+
+ case autoselect:
+ if ((address & 0xff) == 0x00)
+ return eeprom->manufacture_code;
+ else if ((address & 0xff) == 0x01)
+ return eeprom->device_code;
+ else
+ return 0; /* not certain about this */
+
+ case byte_programming:
+ if (device_event_queue_time(me) > eeprom->program_finish_time) {
+ finish_programming_byte(me, eeprom);
+ eeprom->state = read_reset;
+ continue;
+ }
+ else if (address == eeprom->byte_program_address) {
+ return toggle(eeprom, eeprom->memory[address]);
+ }
+ else {
+ /* trash that memory location */
+ invalid_read(me, eeprom->state, address, "not byte program address");
+ eeprom->memory[address] = (eeprom->memory[address]
+ & eeprom->byte_program_byte);
+ return toggle(eeprom, eeprom->memory[eeprom->byte_program_address]);
+ }
+
+ case chip_erase:
+ if (device_event_queue_time(me) > eeprom->program_finish_time) {
+ finish_erasing_chip(me, eeprom);
+ eeprom->state = read_reset;
+ continue;
+ }
+ else {
+ return toggle(eeprom, eeprom->memory[address]);
+ }
+
+ case sector_erase:
+ if (device_event_queue_time(me) > eeprom->program_finish_time) {
+ finish_erasing_sector(me, eeprom);
+ eeprom->state = read_reset;
+ continue;
+ }
+ else if (!eeprom->sectors[address / eeprom->sizeof_sector]) {
+ /* read to wrong sector */
+ invalid_read(me, eeprom->state, address, "sector not being erased");
+ return toggle(eeprom, eeprom->memory[address]) & ~0x8;
+ }
+ else if (device_event_queue_time(me) > eeprom->sector_start_time) {
+ return toggle(eeprom, eeprom->memory[address]) | 0x8;
+ }
+ else {
+ return toggle(eeprom, eeprom->memory[address]) & ~0x8;
+ }
+
+ case sector_erase_suspend:
+ if (!eeprom->sectors[address / eeprom->sizeof_sector]) {
+ return eeprom->memory[address];
+ }
+ else {
+ invalid_read(me, eeprom->state, address, "sector being erased");
+ return eeprom->memory[address];
+ }
+
+ default:
+ invalid_read(me, eeprom->state, address, "invalid state");
+ return eeprom->memory[address];
+
+ }
+ }
+ return 0;
+}
+
+static unsigned
+hw_eeprom_io_read_buffer(device *me,
+ void *dest,
+ int space,
+ unsigned_word addr,
+ unsigned nr_bytes,
+ cpu *processor,
+ unsigned_word cia)
+{
+ hw_eeprom_device *eeprom = (hw_eeprom_device*)device_data(me);
+ int i;
+ for (i = 0; i < nr_bytes; i++) {
+ unsigned_word address = (addr + i) % eeprom->sizeof_memory;
+ unsigned8 byte = read_byte(me, eeprom, address);
+ ((unsigned8*)dest)[i] = byte;
+ }
+ return nr_bytes;
+}
+
+
+/* eeprom writes */
+
+static void
+write_byte(device *me,
+ hw_eeprom_device *eeprom,
+ unsigned_word address,
+ unsigned8 data)
+{
+ /* may need multiple transitions to process a write */
+ while (1) {
+ switch (eeprom->state) {
+
+ case read_reset:
+ if (address == 0x5555 && data == 0xaa)
+ eeprom->state = write_nr_2;
+ else if (data == 0xf0)
+ eeprom->state = read_reset;
+ else {
+ invalid_write(me, eeprom->state, address, data, "unexpected");
+ eeprom->state = read_reset;
+ }
+ return;
+
+ case write_nr_2:
+ if (address == 0x2aaa && data == 0x55)
+ eeprom->state = write_nr_3;
+ else {
+ invalid_write(me, eeprom->state, address, data, "unexpected");
+ eeprom->state = read_reset;
+ }
+ return;
+
+ case write_nr_3:
+ if (address == 0x5555 && data == 0xf0)
+ eeprom->state = read_reset;
+ else if (address == 0x5555 && data == 0x90)
+ eeprom->state = autoselect;
+ else if (address == 0x5555 && data == 0xa0) {
+ eeprom->state = byte_program;
+ }
+ else if (address == 0x5555 && data == 0x80)
+ eeprom->state = write_nr_4;
+ else {
+ invalid_write(me, eeprom->state, address, data, "unexpected");
+ eeprom->state = read_reset;
+ }
+ return;
+
+ case write_nr_4:
+ if (address == 0x5555 && data == 0xaa)
+ eeprom->state = write_nr_5;
+ else {
+ invalid_write(me, eeprom->state, address, data, "unexpected");
+ eeprom->state = read_reset;
+ }
+ return;
+
+ case write_nr_5:
+ if (address == 0x2aaa && data == 0x55)
+ eeprom->state = write_nr_6;
+ else {
+ invalid_write(me, eeprom->state, address, data, "unexpected");
+ eeprom->state = read_reset;
+ }
+ return;
+
+ case write_nr_6:
+ if (address == 0x5555 && data == 0x10) {
+ start_erasing_chip(me, eeprom);
+ eeprom->state = chip_erase;
+ }
+ else {
+ start_erasing_sector(me, eeprom, address);
+ eeprom->sector_state = read_reset;
+ eeprom->state = sector_erase;
+ }
+ return;
+
+ case autoselect:
+ if (data == 0xf0)
+ eeprom->state = read_reset;
+ else if (address == 0x5555 && data == 0xaa)
+ eeprom->state = write_nr_2;
+ else {
+ invalid_write(me, eeprom->state, address, data, "unsupported address");
+ eeprom->state = read_reset;
+ }
+ return;
+
+ case byte_program:
+ start_programming_byte(me, eeprom, address, data);
+ eeprom->state = byte_programming;
+ return;
+
+ case byte_programming:
+ if (device_event_queue_time(me) > eeprom->program_finish_time) {
+ finish_programming_byte(me, eeprom);
+ eeprom->state = read_reset;
+ continue;
+ }
+ /* ignore it */
+ return;
+
+ case chip_erase:
+ if (device_event_queue_time(me) > eeprom->program_finish_time) {
+ finish_erasing_chip(me, eeprom);
+ eeprom->state = read_reset;
+ continue;
+ }
+ /* ignore it */
+ return;
+
+ case sector_erase:
+ if (device_event_queue_time(me) > eeprom->program_finish_time) {
+ finish_erasing_sector(me, eeprom);
+ eeprom->state = eeprom->sector_state;
+ continue;
+ }
+ else if (device_event_queue_time(me) > eeprom->sector_start_time
+ && data == 0xb0) {
+ eeprom->sector_state = read_reset;
+ eeprom->state = sector_erase_suspend;
+ }
+ else {
+ if (eeprom->sector_state == read_reset
+ && address == 0x5555 && data == 0xaa)
+ eeprom->sector_state = write_nr_2;
+ else if (eeprom->sector_state == write_nr_2
+ && address == 0x2aaa && data == 0x55)
+ eeprom->sector_state = write_nr_3;
+ else if (eeprom->sector_state == write_nr_3
+ && address == 0x5555 && data == 0x80)
+ eeprom->sector_state = write_nr_4;
+ else if (eeprom->sector_state == write_nr_4
+ && address == 0x5555 && data == 0xaa)
+ eeprom->sector_state = write_nr_5;
+ else if (eeprom->sector_state == write_nr_5
+ && address == 0x2aaa && data == 0x55)
+ eeprom->sector_state = write_nr_6;
+ else if (eeprom->sector_state == write_nr_6
+ && address != 0x5555 && data == 0x30) {
+ if (device_event_queue_time(me) > eeprom->sector_start_time) {
+ DTRACE(eeprom, ("sector erase command after window closed\n"));
+ eeprom->sector_state = read_reset;
+ }
+ else {
+ start_erasing_sector(me, eeprom, address);
+ eeprom->sector_state = read_reset;
+ }
+ }
+ else {
+ invalid_write(me, eeprom->state, address, data, state2a(eeprom->sector_state));
+ eeprom->state = read_reset;
+ }
+ }
+ return;
+
+ case sector_erase_suspend:
+ if (data == 0x30)
+ eeprom->state = sector_erase;
+ else {
+ invalid_write(me, eeprom->state, address, data, "not resume command");
+ eeprom->state = read_reset;
+ }
+ return;
+
+ }
+ }
+}
+
+static unsigned
+hw_eeprom_io_write_buffer(device *me,
+ const void *source,
+ int space,
+ unsigned_word addr,
+ unsigned nr_bytes,
+ cpu *processor,
+ unsigned_word cia)
+{
+ hw_eeprom_device *eeprom = (hw_eeprom_device*)device_data(me);
+ int i;
+ for (i = 0; i < nr_bytes; i++) {
+ unsigned_word address = (addr + i) % eeprom->sizeof_memory;
+ unsigned8 byte = ((unsigned8*)source)[i];
+ write_byte(me, eeprom, address, byte);
+ }
+ return nr_bytes;
+}
+
+
+/* An instance of the eeprom */
+
+typedef struct _hw_eeprom_instance {
+ unsigned_word pos;
+ hw_eeprom_device *eeprom;
+ device *me;
+} hw_eeprom_instance;
+
+static void
+hw_eeprom_instance_delete(device_instance *instance)
+{
+ hw_eeprom_instance *data = device_instance_data(instance);
+ zfree(data);
+}
+
+static int
+hw_eeprom_instance_read(device_instance *instance,
+ void *buf,
+ unsigned_word len)
+{
+ hw_eeprom_instance *data = device_instance_data(instance);
+ int i;
+ if (data->eeprom->state != read_reset)
+ DITRACE(eeprom, ("eeprom not idle during instance read\n"));
+ for (i = 0; i < len; i++) {
+ ((unsigned8*)buf)[i] = data->eeprom->memory[data->pos];
+ data->pos = (data->pos + 1) % data->eeprom->sizeof_memory;
+ }
+ return len;
+}
+
+static int
+hw_eeprom_instance_write(device_instance *instance,
+ const void *buf,
+ unsigned_word len)
+{
+ hw_eeprom_instance *data = device_instance_data(instance);
+ int i;
+ if (data->eeprom->state != read_reset)
+ DITRACE(eeprom, ("eeprom not idle during instance write\n"));
+ for (i = 0; i < len; i++) {
+ data->eeprom->memory[data->pos] = ((unsigned8*)buf)[i];
+ data->pos = (data->pos + 1) % data->eeprom->sizeof_memory;
+ }
+ dump_eeprom(data->me, data->eeprom);
+ return len;
+}
+
+static int
+hw_eeprom_instance_seek(device_instance *instance,
+ unsigned_word pos_hi,
+ unsigned_word pos_lo)
+{
+ hw_eeprom_instance *data = device_instance_data(instance);
+ if (pos_lo >= data->eeprom->sizeof_memory)
+ device_error(data->me, "seek value 0x%lx out of range\n",
+ (unsigned long)pos_lo);
+ data->pos = pos_lo;
+ return 0;
+}
+
+static const device_instance_callbacks hw_eeprom_instance_callbacks = {
+ hw_eeprom_instance_delete,
+ hw_eeprom_instance_read,
+ hw_eeprom_instance_write,
+ hw_eeprom_instance_seek,
+};
+
+static device_instance *
+hw_eeprom_create_instance(device *me,
+ const char *path,
+ const char *args)
+{
+ hw_eeprom_device *eeprom = device_data(me);
+ hw_eeprom_instance *data = ZALLOC(hw_eeprom_instance);
+ data->eeprom = eeprom;
+ data->me = me;
+ return device_create_instance_from(me, NULL,
+ data,
+ path, args,
+ &hw_eeprom_instance_callbacks);
+}
+
+
+
+static device_callbacks const hw_eeprom_callbacks = {
+ { generic_device_init_address,
+ hw_eeprom_init_data },
+ { NULL, }, /* address */
+ { hw_eeprom_io_read_buffer,
+ hw_eeprom_io_write_buffer }, /* IO */
+ { NULL, }, /* DMA */
+ { NULL, }, /* interrupt */
+ { NULL, }, /* unit */
+ hw_eeprom_create_instance,
+};
+
+static void *
+hw_eeprom_create(const char *name,
+ const device_unit *unit_address,
+ const char *args)
+{
+ hw_eeprom_device *eeprom = ZALLOC(hw_eeprom_device);
+ return eeprom;
+}
+
+
+
+const device_descriptor hw_eeprom_device_descriptor[] = {
+ { "eeprom", hw_eeprom_create, &hw_eeprom_callbacks },
+ { NULL },
+};
+
+#endif /* _HW_EEPROM_C_ */
diff --git a/gnu/dist/sim/ppc/hw_glue.c b/gnu/dist/sim/ppc/hw_glue.c
new file mode 100644
index 00000000000..d7ad9290361
--- /dev/null
+++ b/gnu/dist/sim/ppc/hw_glue.c
@@ -0,0 +1,371 @@
+/* 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.
+
+ */
+
+
+#ifndef _HW_GLUE_C_
+#define _HW_GLUE_C_
+
+#include "device_table.h"
+
+
+/* DEVICE
+
+
+ glue - glue to interconnect and test interrupts
+
+
+ DESCRIPTION
+
+
+ The glue device provides two functions. Firstly, it provides a
+ mechanism for inspecting and driving the interrupt net. Secondly,
+ it provides a set of boolean primitives that can be used add
+ combinatorial operations to the interrupt network.
+
+ Glue devices have a variable number of big endian <<output>>
+ registers. Each host-word size. The registers can be both read
+ and written.
+
+ Writing a value to an output register causes an interrupt (of the
+ specified level) to be driven on the devices corresponding output
+ interrupt 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 interrupt ariving (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.
+
+
+ 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 dff, an inverter or a latch may be
+ useful.
+
+ */
+
+
+enum {
+ max_nr_interrupts = 2048,
+};
+
+typedef enum _hw_glue_type {
+ glue_undefined = 0,
+ glue_io,
+ glue_and,
+ glue_nand,
+ glue_or,
+ glue_xor,
+ glue_nor,
+ glue_not,
+} hw_glue_type;
+
+typedef struct _hw_glue_device {
+ 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;
+} hw_glue_device;
+
+
+static void
+hw_glue_init_address(device *me)
+{
+ hw_glue_device *glue = (hw_glue_device*)device_data(me);
+
+ /* attach to my parent */
+ generic_device_init_address(me);
+
+ /* establish the output registers */
+ if (glue->output != NULL) {
+ memset(glue->output, 0, glue->sizeof_output);
+ }
+ else {
+ reg_property_spec unit;
+ int reg_nr;
+ /* find a relevant reg entry */
+ reg_nr = 0;
+ while (device_find_reg_array_property(me, "reg", reg_nr, &unit)
+ && !device_size_to_attach_size(device_parent(me), &unit.size,
+ &glue->sizeof_output, me))
+ reg_nr++;
+ /* check out the size */
+ if (glue->sizeof_output == 0)
+ device_error(me, "at least one reg property size must be nonzero");
+ if (glue->sizeof_output % sizeof(unsigned_word) != 0)
+ device_error(me, "reg property size must be %d aligned", sizeof(unsigned_word));
+ /* and the address */
+ device_address_to_attach_address(device_parent(me),
+ &unit.address, &glue->space, &glue->address,
+ me);
+ if (glue->address % (sizeof(unsigned_word) * max_nr_interrupts) != 0)
+ device_error(me, "reg property address must be %d aligned",
+ sizeof(unsigned_word) * max_nr_interrupts);
+ glue->nr_outputs = glue->sizeof_output / sizeof(unsigned_word);
+ glue->output = zalloc(glue->sizeof_output);
+ }
+
+ /* establish the input interrupt ports */
+ if (glue->input != NULL) {
+ memset(glue->input, 0, glue->sizeof_input);
+ }
+ else {
+ const device_property *ranges = device_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) {
+ device_error(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 = zalloc(glue->sizeof_input);
+ }
+
+ /* determine our type */
+ if (glue->type == glue_undefined) {
+ const char *name = device_name(me);
+ if (strcmp(name, "glue") == 0)
+ glue->type = glue_io;
+ else if (strcmp(name, "glue-and") == 0)
+ glue->type = glue_and;
+ else
+ device_error(me, "unimplemented glue type");
+ }
+
+ DTRACE(glue, ("int-number %d, nr_inputs %d, nr_outputs %d\n",
+ glue->int_number, glue->nr_inputs, glue->nr_outputs));
+}
+
+static unsigned
+hw_glue_io_read_buffer_callback(device *me,
+ void *dest,
+ int space,
+ unsigned_word addr,
+ unsigned nr_bytes,
+ cpu *processor,
+ unsigned_word cia)
+{
+ hw_glue_device *glue = (hw_glue_device*)device_data(me);
+ int reg = ((addr - glue->address) / sizeof(unsigned_word)) % glue->nr_outputs;
+ if (nr_bytes != sizeof(unsigned_word)
+ || (addr % sizeof(unsigned_word)) != 0)
+ device_error(me, "missaligned read access (%d:0x%lx:%d) not supported",
+ space, (unsigned long)addr, nr_bytes);
+ *(unsigned_word*)dest = H2BE_4(glue->output[reg]);
+ DTRACE(glue, ("read - interrupt %d (0x%lx), level %d\n",
+ reg, (unsigned long) addr, glue->output[reg]));
+ return nr_bytes;
+}
+
+
+static unsigned
+hw_glue_io_write_buffer_callback(device *me,
+ const void *source,
+ int space,
+ unsigned_word addr,
+ unsigned nr_bytes,
+ cpu *processor,
+ unsigned_word cia)
+{
+ hw_glue_device *glue = (hw_glue_device*)device_data(me);
+ int reg = ((addr - glue->address) / sizeof(unsigned_word)) % max_nr_interrupts;
+ if (nr_bytes != sizeof(unsigned_word)
+ || (addr % sizeof(unsigned_word)) != 0)
+ device_error(me, "missaligned write access (%d:0x%lx:%d) not supported",
+ space, (unsigned long)addr, nr_bytes);
+ glue->output[reg] = H2BE_4(*(unsigned_word*)source);
+ DTRACE(glue, ("write - interrupt %d (0x%lx), level %d\n",
+ reg, (unsigned long) addr, glue->output[reg]));
+ device_interrupt_event(me, reg, glue->output[reg], processor, cia);
+ return nr_bytes;
+}
+
+static void
+hw_glue_interrupt_event(device *me,
+ int my_port,
+ device *source,
+ int source_port,
+ int level,
+ cpu *processor,
+ unsigned_word cia)
+{
+ hw_glue_device *glue = (hw_glue_device*)device_data(me);
+ int i;
+ if (my_port < glue->int_number
+ || my_port >= glue->int_number + glue->nr_inputs)
+ device_error(me, "interrupt %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;
+ DTRACE(glue, ("input - interrupt %d (0x%lx), level %d\n",
+ 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];
+ DTRACE(glue, ("and - interrupt %d, level %d arrived - output %d\n",
+ my_port, level, glue->output[0]));
+ device_interrupt_event(me, 0, glue->output[0], processor, cia);
+ break;
+ default:
+ device_error(me, "operator not implemented");
+ break;
+ }
+}
+
+
+static const device_interrupt_port_descriptor hw_glue_interrupt_ports[] = {
+ { "int", 0, max_nr_interrupts },
+ { NULL }
+};
+
+
+static device_callbacks const hw_glue_callbacks = {
+ { hw_glue_init_address, NULL },
+ { NULL, }, /* address */
+ { hw_glue_io_read_buffer_callback,
+ hw_glue_io_write_buffer_callback, },
+ { NULL, }, /* DMA */
+ { hw_glue_interrupt_event, NULL, hw_glue_interrupt_ports }, /* interrupt */
+ { NULL, }, /* unit */
+ NULL, /* instance */
+};
+
+
+static void *
+hw_glue_create(const char *name,
+ const device_unit *unit_address,
+ const char *args)
+{
+ /* create the descriptor */
+ hw_glue_device *glue = ZALLOC(hw_glue_device);
+ return glue;
+}
+
+
+const device_descriptor hw_glue_device_descriptor[] = {
+ { "glue", hw_glue_create, &hw_glue_callbacks },
+ { "glue-and", hw_glue_create, &hw_glue_callbacks },
+ { "glue-nand", hw_glue_create, &hw_glue_callbacks },
+ { "glue-or", hw_glue_create, &hw_glue_callbacks },
+ { "glue-xor", hw_glue_create, &hw_glue_callbacks },
+ { "glue-nor", hw_glue_create, &hw_glue_callbacks },
+ { "glue-not", hw_glue_create, &hw_glue_callbacks },
+ { NULL },
+};
+
+#endif /* _HW_GLUE_C_ */
diff --git a/gnu/dist/sim/ppc/hw_htab.c b/gnu/dist/sim/ppc/hw_htab.c
new file mode 100644
index 00000000000..35aa5711371
--- /dev/null
+++ b/gnu/dist/sim/ppc/hw_htab.c
@@ -0,0 +1,683 @@
+/* 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.
+
+ */
+
+
+#ifndef _HW_HTAB_C_
+#define _HW_HTAB_C_
+
+#include "device_table.h"
+
+#include "bfd.h"
+
+
+/* DEVICE
+
+
+ htab - pseudo-device describing a PowerPC hash table
+
+
+ DESCRIPTION
+
+
+ During the initialization of the device tree, the pseudo-device
+ <<htab>>, in conjunction with any child <<pte>> pseudo-devices,
+ will create a PowerPC hash table in memory. The hash table values
+ are written using dma transfers.
+
+ The size and address of the hash table are determined by properties
+ of the htab node.
+
+ By convention, the htab device is made a child of the
+ <</openprom/init>> node.
+
+ By convention, the real address of the htab is used as the htab
+ nodes unit address.
+
+
+ PROPERTIES
+
+
+ real-address = <address> (required)
+
+ The physical address of the hash table. The PowerPC architecture
+ places limitations on what is a valid hash table real-address.
+
+
+ nr-bytes = <size> (required)
+
+ The size of the hash table (in bytes) that is to be created at
+ <<real-address>>. The PowerPC architecture places limitations on
+ what is a valid hash table size.
+
+
+ claim = <anything> (optional)
+
+ If this property is present, the memory used to construct the hash
+ table will be claimed from the memory device. The memory device
+ being specified by the <</chosen/memory>> ihandle property.
+
+
+ EXAMPLES
+
+ Enable tracing.
+
+ | $ psim -t htab-device \
+
+
+ Create a htab specifying the base address and minimum size.
+
+ | -o '/openprom/init/htab@0x10000/real-address 0x10000' \
+ | -o '/openprom/init/htab@0x10000/claim 0' \
+ | -o '/openprom/init/htab@0x10000/nr-bytes 65536' \
+
+
+ BUGS
+
+
+ See the <<pte>> device.
+
+
+ */
+
+
+/* DEVICE
+
+
+ pte - pseudo-device describing a htab entry
+
+
+ DESCRIPTION
+
+
+ The <<pte>> pseudo-device, which must be a child of a <<htabl>>
+ node, describes a virtual to physical mapping that is to be entered
+ into the parents hash table.
+
+ Two alternative specifications of the mapping are allowed. Either
+ a section of physical memory can be mapped to a virtual address, or
+ the header of an executible image can be used to define the
+ mapping.
+
+ By convention, the real address of the map is specified as the pte
+ devices unit address.
+
+
+ PROPERTIES
+
+
+ real-address = <address> (required)
+
+ The starting physical address that is to be mapped by the hash
+ table.
+
+
+ wimg = <int> (required)
+ pp = <int> (required)
+
+ The value of hash table protection bits that are to be used when
+ creating the virtual to physical address map.
+
+
+ claim = <anything> (optional)
+
+ If this property is present, the real memory that is being mapped by the
+ hash table will be claimed from the memory node (specified by the
+ ihandle <</chosen/memory>>).
+
+
+ virtual-address = <integer> [ <integer> ] (option A)
+ nr-bytes = <size> (option A)
+
+ Option A - Virtual virtual address (and size) at which the physical
+ address is to be mapped. If multiple values are specified for the
+ virtual address then they are concatenated to gether to form a
+ longer virtual address.
+
+
+ file-name = <string> (option B)
+
+ Option B - An executable image that is to be loaded (starting at
+ the physical address specified above) and then mapped in using
+ informatioin taken from the executables header. information found
+ in the files header.
+
+
+ EXAMPLES
+
+
+ Enable tracing (note that both the <<htab>> and <<pte>> device use the
+ same trace option).
+
+ | -t htab-device \
+
+
+ Map a block of physical memory into a specified virtual address:
+
+ | -o '/openprom/init/htab/pte@0x0/real-address 0' \
+ | -o '/openprom/init/htab/pte@0x0/nr-bytes 4096' \
+ | -o '/openprom/init/htab/pte@0x0/virtual-address 0x1000000' \
+ | -o '/openprom/init/htab/pte@0x0/claim 0' \
+ | -o '/openprom/init/htab/pte@0x0/wimg 0x7' \
+ | -o '/openprom/init/htab/pte@0x0/pp 0x2' \
+
+
+ Map a file into memory.
+
+ | -o '/openprom/init/htab/pte@0x10000/real-address 0x10000' \
+ | -o '/openprom/init/htab/pte@0x10000/file-name "netbsd.elf' \
+ | -o '/openprom/init/htab/pte@0x10000/wimg 0x7' \
+ | -o '/openprom/init/htab/pte@0x10000/pp 0x2' \
+
+
+ BUGS
+
+
+ For an ELF executable, the header defines both the virtual and real
+ address at which each file section should be loaded. At present, the
+ real addresses that are specified in the header are ignored, the file
+ instead being loaded in to physical memory in a linear fashion.
+
+ When claiming memory, this device assumes that the #address-cells
+ and #size-cells is one. For future implementations, this may not
+ be the case.
+
+ */
+
+
+
+static void
+htab_decode_hash_table(device *me,
+ unsigned32 *htaborg,
+ unsigned32 *htabmask)
+{
+ unsigned_word htab_ra;
+ unsigned htab_nr_bytes;
+ unsigned n;
+ device *parent = device_parent(me);
+ /* determine the location/size of the hash table */
+ if (parent == NULL
+ || strcmp(device_name(parent), "htab") != 0)
+ device_error(parent, "must be a htab device");
+ htab_ra = device_find_integer_property(parent, "real-address");
+ htab_nr_bytes = device_find_integer_property(parent, "nr-bytes");
+ for (n = htab_nr_bytes; n > 1; n = n / 2) {
+ if (n % 2 != 0)
+ device_error(parent, "htab size 0x%x not a power of two",
+ htab_nr_bytes);
+ }
+ *htaborg = htab_ra;
+ *htabmask = MASKED32(htab_nr_bytes - 1, 7, 31-6);
+ if ((htab_ra & INSERTED32(*htabmask, 7, 15)) != 0) {
+ device_error(parent, "htaborg 0x%lx not aligned to htabmask 0x%lx",
+ (unsigned long)*htaborg, (unsigned long)*htabmask);
+ }
+ DTRACE(htab, ("htab - htaborg=0x%lx htabmask=0x%lx\n",
+ (unsigned long)*htaborg, (unsigned long)*htabmask));
+}
+
+static void
+htab_map_page(device *me,
+ unsigned_word ra,
+ unsigned64 va,
+ unsigned wimg,
+ unsigned pp,
+ unsigned32 htaborg,
+ unsigned32 htabmask)
+{
+ /* keep everything left shifted so that the numbering is easier */
+ unsigned64 vpn = va << 12;
+ unsigned32 vsid = INSERTED32(EXTRACTED64(vpn, 0, 23), 0, 23);
+ unsigned32 vpage = INSERTED32(EXTRACTED64(vpn, 24, 39), 0, 15);
+ unsigned32 hash = INSERTED32(EXTRACTED32(vsid, 5, 23)
+ ^ EXTRACTED32(vpage, 0, 15),
+ 7, 31-6);
+ int h;
+ for (h = 0; h < 2; h++) {
+ unsigned32 pteg = (htaborg | (hash & htabmask));
+ int pti;
+ for (pti = 0; pti < 8; pti++) {
+ unsigned32 pte = pteg + 8 * pti;
+ unsigned32 current_target_pte0;
+ unsigned32 current_pte0;
+ if (device_dma_read_buffer(device_parent(me),
+ &current_target_pte0,
+ 0, /*space*/
+ pte,
+ sizeof(current_target_pte0)) != 4)
+ device_error(me, "failed to read a pte at 0x%lx", (unsigned long)pte);
+ current_pte0 = T2H_4(current_target_pte0);
+ if (MASKED32(current_pte0, 0, 0)) {
+ /* full pte, check it isn't already mapping the same virtual
+ address */
+ unsigned32 curr_vsid = INSERTED32(EXTRACTED32(current_pte0, 1, 24), 0, 23);
+ unsigned32 curr_api = INSERTED32(EXTRACTED32(current_pte0, 26, 31), 0, 5);
+ unsigned32 curr_h = EXTRACTED32(current_pte0, 25, 25);
+ if (curr_h == h
+ && curr_vsid == vsid
+ && curr_api == MASKED32(vpage, 0, 5))
+ device_error(me, "duplicate map - va=0x%08lx ra=0x%lx vsid=0x%lx h=%d vpage=0x%lx hash=0x%lx pteg=0x%lx+%2d pte0=0x%lx",
+ (unsigned long)va,
+ (unsigned long)ra,
+ (unsigned long)vsid,
+ h,
+ (unsigned long)vpage,
+ (unsigned long)hash,
+ (unsigned long)pteg,
+ pti * 8,
+ (unsigned long)current_pte0);
+ }
+ else {
+ /* empty pte fill it */
+ unsigned32 pte0 = (MASK32(0, 0)
+ | INSERTED32(EXTRACTED32(vsid, 0, 23), 1, 24)
+ | INSERTED32(h, 25, 25)
+ | INSERTED32(EXTRACTED32(vpage, 0, 5), 26, 31));
+ unsigned32 target_pte0 = H2T_4(pte0);
+ unsigned32 pte1 = (INSERTED32(EXTRACTED32(ra, 0, 19), 0, 19)
+ | INSERTED32(wimg, 25, 28)
+ | INSERTED32(pp, 30, 31));
+ unsigned32 target_pte1 = H2T_4(pte1);
+ if (device_dma_write_buffer(device_parent(me),
+ &target_pte0,
+ 0, /*space*/
+ pte,
+ sizeof(target_pte0),
+ 1/*ro?*/) != 4
+ || device_dma_write_buffer(device_parent(me),
+ &target_pte1,
+ 0, /*space*/
+ pte + 4,
+ sizeof(target_pte1),
+ 1/*ro?*/) != 4)
+ device_error(me, "failed to write a pte a 0x%lx", (unsigned long)pte);
+ DTRACE(htab, ("map - va=0x%08lx ra=0x%lx vsid=0x%lx h=%d vpage=0x%lx hash=0x%lx pteg=0x%lx+%2d pte0=0x%lx pte1=0x%lx\n",
+ (unsigned long)va,
+ (unsigned long)ra,
+ (unsigned long)vsid,
+ h,
+ (unsigned long)vpage,
+ (unsigned long)hash,
+ (unsigned long)pteg,
+ pti * 8,
+ (unsigned long)pte0,
+ (unsigned long)pte1));
+ return;
+ }
+ }
+ /* re-hash */
+ hash = MASKED32(~hash, 0, 18);
+ }
+}
+
+static unsigned_word
+claim_memory(device *me,
+ device_instance *memory,
+ unsigned_word ra,
+ unsigned_word size)
+{
+ unsigned32 args[3];
+ unsigned32 results[1];
+ int status;
+ args[0] = 0; /* alignment */
+ args[1] = size;
+ args[2] = ra;
+ status = device_instance_call_method(memory, "claim", 3, args, 1, results);
+ if (status != 0)
+ device_error(me, "failed to claim memory");
+ return results[0];
+}
+
+static void
+htab_map_region(device *me,
+ device_instance *memory,
+ unsigned_word pte_ra,
+ unsigned64 pte_va,
+ unsigned nr_bytes,
+ unsigned wimg,
+ unsigned pp,
+ unsigned32 htaborg,
+ unsigned32 htabmask)
+{
+ unsigned_word ra;
+ unsigned64 va;
+ /* claim the memory */
+ if (memory != NULL)
+ claim_memory(me, memory, pte_ra, nr_bytes);
+ /* go through all pages and create a pte for each */
+ for (ra = pte_ra, va = pte_va;
+ ra < pte_ra + nr_bytes;
+ ra += 0x1000, va += 0x1000) {
+ htab_map_page(me, ra, va, wimg, pp, htaborg, htabmask);
+ }
+}
+
+typedef struct _htab_binary_sizes {
+ unsigned_word text_ra;
+ unsigned_word text_base;
+ unsigned_word text_bound;
+ unsigned_word data_ra;
+ unsigned_word data_base;
+ unsigned data_bound;
+ device *me;
+} htab_binary_sizes;
+
+static void
+htab_sum_binary(bfd *abfd,
+ sec_ptr sec,
+ PTR data)
+{
+ htab_binary_sizes *sizes = (htab_binary_sizes*)data;
+ unsigned_word size = bfd_get_section_size_before_reloc (sec);
+ unsigned_word vma = bfd_get_section_vma (abfd, sec);
+#define bfd_get_section_lma(abfd, sec) ((sec)->lma + 0)
+ unsigned_word ra = bfd_get_section_lma (abfd, sec);
+
+ /* skip the section if no memory to allocate */
+ if (! (bfd_get_section_flags(abfd, sec) & SEC_ALLOC))
+ return;
+
+ if ((bfd_get_section_flags (abfd, sec) & SEC_CODE)
+ || (bfd_get_section_flags (abfd, sec) & SEC_READONLY)) {
+ if (sizes->text_bound < vma + size)
+ sizes->text_bound = ALIGN_PAGE(vma + size);
+ if (sizes->text_base > vma)
+ sizes->text_base = FLOOR_PAGE(vma);
+ if (sizes->text_ra > ra)
+ sizes->text_ra = FLOOR_PAGE(ra);
+ }
+ else if ((bfd_get_section_flags (abfd, sec) & SEC_DATA)
+ || (bfd_get_section_flags (abfd, sec) & SEC_ALLOC)) {
+ if (sizes->data_bound < vma + size)
+ sizes->data_bound = ALIGN_PAGE(vma + size);
+ if (sizes->data_base > vma)
+ sizes->data_base = FLOOR_PAGE(vma);
+ if (sizes->data_ra > ra)
+ sizes->data_ra = FLOOR_PAGE(ra);
+ }
+}
+
+static void
+htab_dma_binary(bfd *abfd,
+ sec_ptr sec,
+ PTR data)
+{
+ htab_binary_sizes *sizes = (htab_binary_sizes*)data;
+ void *section_init;
+ unsigned_word section_vma;
+ unsigned_word section_size;
+ unsigned_word section_ra;
+ device *me = sizes->me;
+
+ /* skip the section if no memory to allocate */
+ if (! (bfd_get_section_flags(abfd, sec) & SEC_ALLOC))
+ return;
+
+ /* check/ignore any sections of size zero */
+ section_size = bfd_get_section_size_before_reloc(sec);
+ if (section_size == 0)
+ return;
+
+ /* if nothing to load, ignore this one */
+ if (! (bfd_get_section_flags(abfd, sec) & SEC_LOAD))
+ return;
+
+ /* find where it is to go */
+ section_vma = bfd_get_section_vma(abfd, sec);
+ section_ra = 0;
+ if ((bfd_get_section_flags (abfd, sec) & SEC_CODE)
+ || (bfd_get_section_flags (abfd, sec) & SEC_READONLY))
+ section_ra = (section_vma - sizes->text_base + sizes->text_ra);
+ else if ((bfd_get_section_flags (abfd, sec) & SEC_DATA))
+ section_ra = (section_vma - sizes->data_base + sizes->data_ra);
+ else
+ return; /* just ignore it */
+
+ DTRACE(htab,
+ ("load - name=%-7s vma=0x%.8lx size=%6ld ra=0x%.8lx flags=%3lx(%s%s%s%s%s )\n",
+ bfd_get_section_name(abfd, sec),
+ (long)section_vma,
+ (long)section_size,
+ (long)section_ra,
+ (long)bfd_get_section_flags(abfd, sec),
+ bfd_get_section_flags(abfd, sec) & SEC_LOAD ? " LOAD" : "",
+ bfd_get_section_flags(abfd, sec) & SEC_CODE ? " CODE" : "",
+ bfd_get_section_flags(abfd, sec) & SEC_DATA ? " DATA" : "",
+ bfd_get_section_flags(abfd, sec) & SEC_ALLOC ? " ALLOC" : "",
+ bfd_get_section_flags(abfd, sec) & SEC_READONLY ? " READONLY" : ""
+ ));
+
+ /* dma in the sections data */
+ section_init = zalloc(section_size);
+ if (!bfd_get_section_contents(abfd,
+ sec,
+ section_init, 0,
+ section_size)) {
+ bfd_perror("devices/pte");
+ device_error(me, "no data loaded");
+ }
+ if (device_dma_write_buffer(device_parent(me),
+ section_init,
+ 0 /*space*/,
+ section_ra,
+ section_size,
+ 1 /*violate_read_only*/)
+ != section_size)
+ device_error(me, "broken dma transfer");
+ zfree(section_init); /* only free if load */
+}
+
+/* create a memory map from a binaries virtual addresses to a copy of
+ the binary laid out linearly in memory */
+
+static void
+htab_map_binary(device *me,
+ device_instance *memory,
+ unsigned_word ra,
+ unsigned wimg,
+ unsigned pp,
+ const char *file_name,
+ unsigned32 htaborg,
+ unsigned32 htabmask)
+{
+ htab_binary_sizes sizes;
+ bfd *image;
+ sizes.text_ra = -1;
+ sizes.data_ra = -1;
+ sizes.text_base = -1;
+ sizes.data_base = -1;
+ sizes.text_bound = 0;
+ sizes.data_bound = 0;
+ sizes.me = me;
+
+ /* open the file */
+ image = bfd_openr(file_name, NULL);
+ if (image == NULL) {
+ bfd_perror("devices/pte");
+ device_error(me, "the file %s not loaded", file_name);
+ }
+
+ /* check it is valid */
+ if (!bfd_check_format(image, bfd_object)) {
+ bfd_close(image);
+ device_error(me, "the file %s has an invalid binary format", file_name);
+ }
+
+ /* determine the size of each of the files regions */
+ bfd_map_over_sections (image, htab_sum_binary, (PTR) &sizes);
+
+ /* if needed, determine the real addresses of the sections */
+ if (ra != -1) {
+ sizes.text_ra = ra;
+ sizes.data_ra = ALIGN_PAGE(sizes.text_ra +
+ (sizes.text_bound - sizes.text_base));
+ }
+
+ DTRACE(htab, ("text map - base=0x%lx bound=0x%lx-1 ra=0x%lx\n",
+ (unsigned long)sizes.text_base,
+ (unsigned long)sizes.text_bound,
+ (unsigned long)sizes.text_ra));
+ DTRACE(htab, ("data map - base=0x%lx bound=0x%lx-1 ra=0x%lx\n",
+ (unsigned long)sizes.data_base,
+ (unsigned long)sizes.data_bound,
+ (unsigned long)sizes.data_ra));
+
+ /* check for and fix a botched image (text and data segments
+ overlap) */
+ if ((sizes.text_base <= sizes.data_base
+ && sizes.text_bound >= sizes.data_bound)
+ || (sizes.data_base <= sizes.text_base
+ && sizes.data_bound >= sizes.data_bound)
+ || (sizes.text_bound > sizes.data_base
+ && sizes.text_bound <= sizes.data_bound)
+ || (sizes.text_base >= sizes.data_base
+ && sizes.text_base < sizes.data_bound)) {
+ DTRACE(htab, ("text and data segment overlaped - using just data segment\n"));
+ /* check va->ra linear */
+ if ((sizes.text_base - sizes.text_ra)
+ != (sizes.data_base - sizes.data_ra))
+ device_error(me, "overlapping but missaligned text and data segments");
+ /* enlarge the data segment */
+ if (sizes.text_base < sizes.data_base)
+ sizes.data_base = sizes.text_base;
+ if (sizes.text_bound > sizes.data_bound)
+ sizes.data_bound = sizes.text_bound;
+ if (sizes.text_ra < sizes.data_ra)
+ sizes.data_ra = sizes.text_ra;
+ /* zap the text segment */
+ sizes.text_base = 0;
+ sizes.text_bound = 0;
+ sizes.text_ra = 0;
+ DTRACE(htab, ("common map - base=0x%lx bound=0x%lx-1 ra=0x%lx\n",
+ (unsigned long)sizes.data_base,
+ (unsigned long)sizes.data_bound,
+ (unsigned long)sizes.data_ra));
+ }
+
+ /* set up virtual memory maps for each of the regions */
+ htab_map_region(me, memory, sizes.text_ra, sizes.text_base,
+ sizes.text_bound - sizes.text_base,
+ wimg, pp,
+ htaborg, htabmask);
+
+ htab_map_region(me, memory, sizes.data_ra, sizes.data_base,
+ sizes.data_bound - sizes.data_base,
+ wimg, pp,
+ htaborg, htabmask);
+
+ /* dma the sections into physical memory */
+ bfd_map_over_sections (image, htab_dma_binary, (PTR) &sizes);
+}
+
+static void
+htab_init_data_callback(device *me)
+{
+ device_instance *memory = NULL;
+ if (WITH_TARGET_WORD_BITSIZE != 32)
+ device_error(me, "only 32bit targets currently suported");
+
+ /* find memory device */
+ if (device_find_property(me, "claim") != NULL)
+ memory = tree_find_ihandle_property(me, "/chosen/memory");
+
+ /* for the htab, just allocate space for it */
+ if (strcmp(device_name(me), "htab") == 0) {
+ unsigned_word address = device_find_integer_property(me, "real-address");
+ unsigned_word length = device_find_integer_property(me, "nr-bytes");
+ unsigned_word base = claim_memory(me, memory, address, length);
+ if (base == -1 || base != address)
+ device_error(me, "cannot allocate hash table");
+ }
+
+ /* for the pte, do all the real work */
+ if (strcmp(device_name(me), "pte") == 0) {
+ unsigned32 htaborg;
+ unsigned32 htabmask;
+
+ htab_decode_hash_table(me, &htaborg, &htabmask);
+
+ if (device_find_property(me, "file-name") != NULL) {
+ /* map in a binary */
+ unsigned pte_wimg = device_find_integer_property(me, "wimg");
+ unsigned pte_pp = device_find_integer_property(me, "pp");
+ const char *file_name = device_find_string_property(me, "file-name");
+ if (device_find_property(me, "real-address") != NULL) {
+ unsigned32 pte_ra = device_find_integer_property(me, "real-address");
+ DTRACE(htab, ("pte - ra=0x%lx, wimg=%ld, pp=%ld, file-name=%s\n",
+ (unsigned long)pte_ra,
+ (unsigned long)pte_wimg,
+ (long)pte_pp,
+ file_name));
+ htab_map_binary(me, memory, pte_ra, pte_wimg, pte_pp, file_name,
+ htaborg, htabmask);
+ }
+ else {
+ DTRACE(htab, ("pte - wimg=%ld, pp=%ld, file-name=%s\n",
+ (unsigned long)pte_wimg,
+ (long)pte_pp,
+ file_name));
+ htab_map_binary(me, memory, -1, pte_wimg, pte_pp, file_name,
+ htaborg, htabmask);
+ }
+ }
+ else {
+ /* handle a normal mapping definition */
+ unsigned64 pte_va = 0;
+ unsigned32 pte_ra = device_find_integer_property(me, "real-address");
+ unsigned pte_nr_bytes = device_find_integer_property(me, "nr-bytes");
+ unsigned pte_wimg = device_find_integer_property(me, "wimg");
+ unsigned pte_pp = device_find_integer_property(me, "pp");
+ signed_cell partial_va;
+ int i;
+ for (i = 0;
+ device_find_integer_array_property(me, "virtual-address", i, &partial_va);
+ i++) {
+ pte_va = (pte_va << WITH_TARGET_WORD_BITSIZE) | (unsigned_cell)partial_va;
+ }
+ DTRACE(htab, ("pte - ra=0x%lx, wimg=%ld, pp=%ld, va=0x%lx, nr_bytes=%ld\n",
+ (unsigned long)pte_ra,
+ (long)pte_wimg,
+ (long)pte_pp,
+ (unsigned long)pte_va,
+ (long)pte_nr_bytes));
+ htab_map_region(me, memory, pte_ra, pte_va, pte_nr_bytes, pte_wimg, pte_pp,
+ htaborg, htabmask);
+ }
+ }
+}
+
+
+static device_callbacks const htab_callbacks = {
+ { NULL, htab_init_data_callback, },
+ { NULL, }, /* address */
+ { NULL, }, /* IO */
+ { passthrough_device_dma_read_buffer,
+ passthrough_device_dma_write_buffer, },
+ { NULL, }, /* interrupt */
+ { generic_device_unit_decode,
+ generic_device_unit_encode, },
+};
+
+const device_descriptor hw_htab_device_descriptor[] = {
+ { "htab", NULL, &htab_callbacks },
+ { "pte", NULL, &htab_callbacks }, /* yep - uses htab's table */
+ { NULL },
+};
+
+#endif /* _HW_HTAB_C_ */
diff --git a/gnu/dist/sim/ppc/hw_ide.c b/gnu/dist/sim/ppc/hw_ide.c
new file mode 100644
index 00000000000..00d54b32e1e
--- /dev/null
+++ b/gnu/dist/sim/ppc/hw_ide.c
@@ -0,0 +1,869 @@
+/* This file is part of the program psim.
+
+ Copyright (C) 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.
+
+ */
+
+
+#ifndef _HW_IDE_C_
+#define _HW_IDE_C_
+
+#include "device_table.h"
+
+
+
+/* DEVICE
+
+
+ ide - Integrated Disk Electronics
+
+
+ DESCRIPTION
+
+
+ This device models the primary/secondary <<ide>> controller
+ described in the [CHRPIO] document.
+
+ The controller has separate independant interrupt outputs for each
+ <<ide>> bus.
+
+
+ PROPERTIES
+
+
+ reg = ... (required)
+
+ The <<reg>> property is described in the document [CHRPIO].
+
+
+ ready-delay = <integer> (optional)
+
+ If present, this specifies the time that the <<ide>> device takes
+ to complete an I/O operation.
+
+
+ disk@?/ide-byte-count = <integer> (optional)
+
+ disk@?/ide-sector-count = <integer> (optional)
+
+ disk@?/ide-head-count = <integer> (optional)
+
+ The <<ide>> device checks each child (disk device) node to see if
+ it has the above properties. If present, these values will be used
+ to compute the <<LBA>> address in <<CHS>> addressing mode.
+
+
+ EXAMPLES
+
+
+ Enable tracing:
+
+ | -t ide-device \
+
+
+ Attach the <<ide>> device to the <<pci>> bus at slot one. Specify
+ legacy I/O addresses:
+
+ | -o '/phb/ide@1/assigned-addresses \
+ | ni0,0,10,1f0 8 \
+ | ni0,0,14,3f8 8 \
+ | ni0,0,18,170 8 \
+ | ni0,0,1c,378 8 \
+ | ni0,0,20,200 8' \
+ | -o '/phb@0x80000000/ide@1/reg \
+ | 1 0 \
+ | i0,0,10,0 8 \
+ | i0,0,18,0 8 \
+ | i0,0,14,6 1 \
+ | i0,0,1c,6 1 \
+ | i0,0,20,0 8' \
+
+ Note: the fouth and fifth reg entries specify that the register is
+ at an offset into the address specified by the base register
+ (<<assigned-addresses>>); Apart from restrictions placed by the
+ <<pci>> specification, no restrictions are placed on the number of
+ base registers specified by the <<assigned-addresses>> property.
+
+ Attach a <<disk>> to the primary and a <<cdrom>> to the secondary
+ <<ide>> controller.
+
+ | -o '/phb@0x80000000/ide@1/disk@0/file "zero' \
+ | -o '/phb@0x80000000/ide@1/cdrom@2/file "/dev/cdrom"' \
+
+ Connect the two interrupt outputs (a and b) to a <<glue>> device to
+ allow testing of the interrupt port. In a real simulation they
+ would be wired to the interrupt controller.
+
+ | -o '/phb@0x80000000/glue@2/reg 2 0 ni0,0,0,0 8' \
+ | -o '/phb@0x80000000/ide@1 > a 0 /phb@0x80000000/glue@2' \
+ | -o '/phb@0x80000000/ide@1 > b 1 /phb@0x80000000/glue@2'
+
+
+ BUGS
+
+
+ While the DMA registers are present, DMA support has not yet been
+ implemented.
+
+ The number of supported commands is very limited.
+
+ The standards documents appear to be vague on how to specify the
+ <<unit-address>> of disk devices devices being attached to the
+ <<ide>> controller. I've chosen to use integers with devices zero
+ and one going to the primary controller while two and three are
+ connected to the secondary controller.
+
+
+ REFERENCES
+
+
+ [CHRPIO] PowerPC(tm) Microprocessor Common Hardware Reference
+ Platform: I/O Device Reference. http://chrp.apple.com/???.
+
+ [SCHMIDT] The SCSI Bus and IDE Interface - Protocols, Applications
+ and Programming. Friedhelm Schmidt (translated by Michael
+ Schultz). ISBN 0-201-42284-0. Addison-Wesley Publishing Company.
+
+
+ */
+
+
+
+typedef enum _io_direction {
+ is_read,
+ is_write,
+} io_direction;
+
+
+enum {
+ nr_ide_controllers = 2,
+ nr_ide_drives_per_controller = 2,
+ nr_fifo_entries = 8192,
+};
+
+enum {
+ /* command register block - read */
+ ide_data_reg,
+ ide_error_reg, /*ide_feature_reg*/
+ ide_sector_count_reg,
+ ide_sector_number_reg,
+ ide_cylinder_reg0,
+ ide_cylinder_reg1,
+ ide_drive_head_reg,
+ ide_status_reg, /*ide_command_reg*/
+ /* command register block - write */
+ ide_feature_reg, /*ide_error_reg*/
+ ide_command_reg, /*ide_status_reg*/
+ /* control register block - read */
+ ide_alternate_status_reg, /*ide_control_reg*/
+ ide_control_reg, /*ide_alternate_status_reg*/
+ /* dma register block */
+ ide_dma_command_reg,
+ ide_dma_unused_1_reg,
+ ide_dma_status_reg,
+ ide_dma_unused_3_reg,
+ ide_dma_prd_table_address_reg0,
+ ide_dma_prd_table_address_reg1,
+ ide_dma_prd_table_address_reg2,
+ ide_dma_prd_table_address_reg3,
+ nr_ide_registers,
+};
+
+
+typedef enum _ide_states {
+ idle_state,
+ busy_loaded_state,
+ busy_drained_state,
+ busy_dma_state,
+ busy_command_state,
+ loading_state,
+ draining_state,
+} ide_states;
+
+static const char *
+ide_state_name(ide_states state)
+{
+ switch (state) {
+ case idle_state: return "idle";
+ case busy_loaded_state: return "busy_loaded_state";
+ case busy_drained_state: return "busy_drained_state";
+ case busy_dma_state: return "busy_dma_state";
+ case busy_command_state: return "busy_command_state";
+ case loading_state: return "loading_state";
+ case draining_state: return "draining_state";
+ default: return "illegal-state";
+ }
+}
+
+typedef struct _ide_geometry {
+ int head;
+ int sector;
+ int byte;
+} ide_geometry;
+
+typedef struct _ide_drive {
+ int nr;
+ device *device;
+ ide_geometry geometry;
+ ide_geometry default_geometry;
+} ide_drive;
+
+typedef struct _ide_controller {
+ int nr;
+ ide_states state;
+ unsigned8 reg[nr_ide_registers];
+ unsigned8 fifo[nr_fifo_entries];
+ int fifo_pos;
+ int fifo_size;
+ ide_drive *current_drive;
+ int current_byte;
+ int current_transfer;
+ ide_drive drive[nr_ide_drives_per_controller];
+ device *me;
+ event_entry_tag event_tag;
+ int is_interrupting;
+ signed64 ready_delay;
+} ide_controller;
+
+
+
+static void
+set_interrupt(device *me,
+ ide_controller *controller)
+{
+ if ((controller->reg[ide_control_reg] & 0x2) == 0) {
+ DTRACE(ide, ("controller %d - interrupt set\n", controller->nr));
+ device_interrupt_event(me, controller->nr, 1, NULL, 0);
+ controller->is_interrupting = 1;
+ }
+}
+
+
+static void
+clear_interrupt(device *me,
+ ide_controller *controller)
+{
+ if (controller->is_interrupting) {
+ DTRACE(ide, ("controller %d - interrupt clear\n", controller->nr));
+ device_interrupt_event(me, controller->nr, 0, NULL, 0);
+ controller->is_interrupting = 0;
+ }
+}
+
+
+static void
+do_event(void *data)
+{
+ ide_controller *controller = data;
+ device *me = controller->me;
+ controller->event_tag = 0;
+ switch (controller->state) {
+ case busy_loaded_state:
+ case busy_drained_state:
+ if (controller->current_transfer > 0) {
+ controller->state = (controller->state == busy_loaded_state
+ ? loading_state : draining_state);
+ }
+ else {
+ controller->state = idle_state;
+ }
+ set_interrupt(me, controller);
+ break;
+ default:
+ device_error(me, "controller %d - unexpected event", controller->nr);
+ break;
+ }
+}
+
+
+static void
+schedule_ready_event(device *me,
+ ide_controller *controller)
+{
+ if (controller->event_tag != 0)
+ device_error(me, "controller %d - attempting to schedule multiple events",
+ controller->nr);
+ controller->event_tag =
+ device_event_queue_schedule(me, controller->ready_delay,
+ do_event, controller);
+}
+
+
+static void
+do_fifo_read(device *me,
+ ide_controller *controller,
+ void *dest,
+ int nr_bytes)
+{
+ if (controller->state != draining_state)
+ device_error(me, "controller %d - reading fifo when not ready (%s)",
+ controller->nr,
+ ide_state_name(controller->state));
+ if (controller->fifo_pos + nr_bytes > controller->fifo_size)
+ device_error(me, "controller %d - fifo underflow", controller->nr);
+ if (nr_bytes > 0) {
+ memcpy(dest, &controller->fifo[controller->fifo_pos], nr_bytes);
+ controller->fifo_pos += nr_bytes;
+ }
+ if (controller->fifo_pos == controller->fifo_size) {
+ controller->current_transfer -= 1;
+ if (controller->current_transfer > 0
+ && controller->current_drive != NULL) {
+ DTRACE(ide, ("controller %d:%d - reading %d byte block at 0x%x\n",
+ controller->nr,
+ controller->current_drive->nr,
+ controller->fifo_size,
+ controller->current_byte));
+ if (device_io_read_buffer(controller->current_drive->device,
+ controller->fifo,
+ 0, controller->current_byte,
+ controller->fifo_size,
+ NULL, 0)
+ != controller->fifo_size)
+ device_error(me, "controller %d - disk %s io read error",
+ controller->nr,
+ device_path(controller->current_drive->device));
+ }
+ controller->state = busy_drained_state;
+ controller->fifo_pos = 0;
+ controller->current_byte += controller->fifo_size;
+ schedule_ready_event(me, controller);
+ }
+}
+
+
+static void
+do_fifo_write(device *me,
+ ide_controller *controller,
+ const void *source,
+ int nr_bytes)
+{
+ if (controller->state != loading_state)
+ device_error(me, "controller %d - writing fifo when not ready (%s)",
+ controller->nr,
+ ide_state_name(controller->state));
+ if (controller->fifo_pos + nr_bytes > controller->fifo_size)
+ device_error(me, "controller %d - fifo overflow", controller->nr);
+ if (nr_bytes > 0) {
+ memcpy(&controller->fifo[controller->fifo_pos], source, nr_bytes);
+ controller->fifo_pos += nr_bytes;
+ }
+ if (controller->fifo_pos == controller->fifo_size) {
+ if (controller->current_transfer > 0
+ && controller->current_drive != NULL) {
+ DTRACE(ide, ("controller %d:%d - writing %d byte block at 0x%x\n",
+ controller->nr,
+ controller->current_drive->nr,
+ controller->fifo_size,
+ controller->current_byte));
+ if (device_io_write_buffer(controller->current_drive->device,
+ controller->fifo,
+ 0, controller->current_byte,
+ controller->fifo_size,
+ NULL, 0)
+ != controller->fifo_size)
+ device_error(me, "controller %d - disk %s io write error",
+ controller->nr,
+ device_path(controller->current_drive->device));
+ }
+ controller->current_transfer -= 1;
+ controller->fifo_pos = 0;
+ controller->current_byte += controller->fifo_size;
+ controller->state = busy_loaded_state;
+ schedule_ready_event(me, controller);
+ }
+}
+
+
+static void
+setup_fifo(device *me,
+ ide_controller *controller,
+ int is_simple,
+ int is_with_disk,
+ io_direction direction)
+{
+ /* find the disk */
+ if (is_with_disk) {
+ int drive_nr = (controller->reg[ide_drive_head_reg] & 0x10) != 0;
+ controller->current_drive = &controller->drive[drive_nr];
+ }
+ else {
+ controller->current_drive = NULL;
+ }
+
+ /* number of transfers */
+ if (is_simple)
+ controller->current_transfer = 1;
+ else {
+ int sector_count = controller->reg[ide_sector_count_reg];
+ if (sector_count == 0)
+ controller->current_transfer = 256;
+ else
+ controller->current_transfer = sector_count;
+ }
+
+ /* the transfer size */
+ if (controller->current_drive == NULL)
+ controller->fifo_size = 512;
+ else
+ controller->fifo_size = controller->current_drive->geometry.byte;
+
+ /* empty the fifo */
+ controller->fifo_pos = 0;
+
+ /* the starting address */
+ if (controller->current_drive == NULL)
+ controller->current_byte = 0;
+ else if (controller->reg[ide_drive_head_reg] & 0x40) {
+ /* LBA addressing mode */
+ controller->current_byte = controller->fifo_size
+ * (((controller->reg[ide_drive_head_reg] & 0xf) << 24)
+ | (controller->reg[ide_cylinder_reg1] << 16)
+ | (controller->reg[ide_cylinder_reg0] << 8)
+ | (controller->reg[ide_sector_number_reg]));
+ }
+ else if (controller->current_drive->geometry.head != 0
+ && controller->current_drive->geometry.sector != 0) {
+ /* CHS addressing mode */
+ int head_nr = controller->reg[ide_drive_head_reg] & 0xf;
+ int cylinder_nr = ((controller->reg[ide_cylinder_reg1] << 8)
+ | controller->reg[ide_cylinder_reg0]);
+ int sector_nr = controller->reg[ide_sector_number_reg];
+ controller->current_byte = controller->fifo_size
+ * ((cylinder_nr * controller->current_drive->geometry.head + head_nr)
+ * controller->current_drive->geometry.sector + sector_nr - 1);
+ }
+ else
+ device_error(me, "controller %d:%d - CHS addressing disabled",
+ controller->nr, controller->current_drive->nr);
+ DTRACE(ide, ("controller %ld:%ld - transfer (%s) %ld blocks of %ld bytes from 0x%lx\n",
+ (long)controller->nr,
+ controller->current_drive == NULL ? -1L : (long)controller->current_drive->nr,
+ direction == is_read ? "read" : "write",
+ (long)controller->current_transfer,
+ (long)controller->fifo_size,
+ (unsigned long)controller->current_byte));
+ switch (direction) {
+ case is_read:
+ /* force a primeing read */
+ controller->current_transfer += 1;
+ controller->state = draining_state;
+ controller->fifo_pos = controller->fifo_size;
+ do_fifo_read(me, controller, NULL, 0);
+ break;
+ case is_write:
+ controller->state = loading_state;
+ break;
+ }
+}
+
+
+static void
+do_command(device *me,
+ ide_controller *controller,
+ int command)
+{
+ if (controller->state != idle_state)
+ device_error(me, "controller %d - command when not idle", controller->nr);
+ switch (command) {
+ case 0x20: case 0x21: /* read-sectors */
+ setup_fifo(me, controller, 0/*is_simple*/, 1/*is_with_disk*/, is_read);
+ break;
+ case 0x30: case 0x31: /* write */
+ setup_fifo(me, controller, 0/*is_simple*/, 1/*is_with_disk*/, is_write);
+ break;
+ }
+}
+
+static unsigned8
+get_status(device *me,
+ ide_controller *controller)
+{
+ switch (controller->state) {
+ case loading_state:
+ case draining_state:
+ return 0x08; /* data req */
+ case busy_loaded_state:
+ case busy_drained_state:
+ return 0x80; /* busy */
+ case idle_state:
+ return 0x40; /* drive ready */
+ default:
+ device_error(me, "internal error");
+ return 0;
+ }
+}
+
+
+/* The address presented to the IDE controler is decoded and then
+ mapped onto a controller:reg pair */
+
+enum {
+ nr_address_blocks = 6,
+};
+
+typedef struct _address_block {
+ int space;
+ unsigned_word base_addr;
+ unsigned_word bound_addr;
+ int controller;
+ int base_reg;
+} address_block;
+
+typedef struct _address_decoder {
+ address_block block[nr_address_blocks];
+} address_decoder;
+
+static void
+decode_address(device *me,
+ address_decoder *decoder,
+ int space,
+ unsigned_word address,
+ int *controller,
+ int *reg,
+ io_direction direction)
+{
+ int i;
+ for (i = 0; i < nr_address_blocks; i++) {
+ if (space == decoder->block[i].space
+ && address >= decoder->block[i].base_addr
+ && address <= decoder->block[i].bound_addr) {
+ *controller = decoder->block[i].controller;
+ *reg = (address
+ - decoder->block[i].base_addr
+ + decoder->block[i].base_reg);
+ if (direction == is_write) {
+ switch (*reg) {
+ case ide_error_reg: *reg = ide_feature_reg; break;
+ case ide_status_reg: *reg = ide_command_reg; break;
+ case ide_alternate_status_reg: *reg = ide_control_reg; break;
+ default: break;
+ }
+ }
+ return;
+ }
+ }
+ device_error(me, "address %d:0x%lx invalid",
+ space, (unsigned long)address);
+}
+
+
+static void
+build_address_decoder(device *me,
+ address_decoder *decoder)
+{
+ int reg;
+ for (reg = 1; reg < 6; reg++) {
+ reg_property_spec unit;
+ int space;
+ unsigned_word address;
+ unsigned size;
+ /* find and decode the reg property */
+ if (!device_find_reg_array_property(me, "reg", reg, &unit))
+ device_error(me, "missing or invalid reg entry %d", reg);
+ device_address_to_attach_address(device_parent(me), &unit.address,
+ &space, &address, me);
+ device_size_to_attach_size(device_parent(me), &unit.size, &size, me);
+ /* insert it into the address decoder */
+ switch (reg) {
+ case 1:
+ case 2:
+ /* command register block */
+ if (size != 8)
+ device_error(me, "reg entry %d must have a size of 8", reg);
+ decoder->block[reg-1].space = space;
+ decoder->block[reg-1].base_addr = address;
+ decoder->block[reg-1].bound_addr = address + size - 1;
+ decoder->block[reg-1].controller = (reg + 1) % nr_ide_controllers;
+ decoder->block[reg-1].base_reg = ide_data_reg;
+ DTRACE(ide, ("controller %d command register block at %d:0x%lx..0x%lx\n",
+ decoder->block[reg-1].controller,
+ decoder->block[reg-1].space,
+ (unsigned long)decoder->block[reg-1].base_addr,
+ (unsigned long)decoder->block[reg-1].bound_addr));
+ break;
+ case 3:
+ case 4:
+ /* control register block */
+ if (size != 1)
+ device_error(me, "reg entry %d must have a size of 1", reg);
+ decoder->block[reg-1].space = space;
+ decoder->block[reg-1].base_addr = address;
+ decoder->block[reg-1].bound_addr = address + size - 1;
+ decoder->block[reg-1].controller = (reg + 1) % nr_ide_controllers;
+ decoder->block[reg-1].base_reg = ide_alternate_status_reg;
+ DTRACE(ide, ("controller %d control register block at %d:0x%lx..0x%lx\n",
+ decoder->block[reg-1].controller,
+ decoder->block[reg-1].space,
+ (unsigned long)decoder->block[reg-1].base_addr,
+ (unsigned long)decoder->block[reg-1].bound_addr));
+ break;
+ case 5:
+ /* dma register block */
+ if (size != 8)
+ device_error(me, "reg entry %d must have a size of 8", reg);
+ decoder->block[reg-1].space = space;
+ decoder->block[reg-1].base_addr = address;
+ decoder->block[reg-1].bound_addr = address + 4 - 1;
+ decoder->block[reg-1].base_reg = ide_dma_command_reg;
+ decoder->block[reg-1].controller = 0;
+ DTRACE(ide, ("controller %d dma register block at %d:0x%lx..0x%lx\n",
+ decoder->block[reg-1].controller,
+ decoder->block[reg-1].space,
+ (unsigned long)decoder->block[reg-1].base_addr,
+ (unsigned long)decoder->block[reg-1].bound_addr));
+ decoder->block[reg].space = space;
+ decoder->block[reg].base_addr = address + 4;
+ decoder->block[reg].bound_addr = address + 8 - 1;
+ decoder->block[reg].controller = 1;
+ decoder->block[reg].base_reg = ide_dma_command_reg;
+ DTRACE(ide, ("controller %d dma register block at %d:0x%lx..0x%lx\n",
+ decoder->block[reg].controller,
+ decoder->block[reg-1].space,
+ (unsigned long)decoder->block[reg].base_addr,
+ (unsigned long)decoder->block[reg].bound_addr));
+ break;
+ default:
+ device_error(me, "internal error - bad switch");
+ break;
+ }
+ }
+}
+
+
+
+typedef struct _hw_ide_device {
+ ide_controller controller[nr_ide_controllers];
+ address_decoder decoder;
+} hw_ide_device;
+
+
+static void
+hw_ide_init_address(device *me)
+{
+ hw_ide_device *ide = device_data(me);
+ int controller;
+ int drive;
+
+ /* zero some things */
+ for (controller = 0; controller < nr_ide_controllers; controller++) {
+ memset(&ide->controller[controller], 0, sizeof(ide_controller));
+ for (drive = 0; drive < nr_ide_drives_per_controller; drive++) {
+ ide->controller[controller].drive[drive].nr = drive;
+ }
+ ide->controller[controller].me = me;
+ if (device_find_property(me, "ready-delay") != NULL)
+ ide->controller[controller].ready_delay =
+ device_find_integer_property(me, "ready-delay");
+ }
+
+ /* attach this device to its parent */
+ generic_device_init_address(me);
+
+ /* determine our own address map */
+ build_address_decoder(me, &ide->decoder);
+
+}
+
+
+static void
+hw_ide_attach_address(device *me,
+ attach_type type,
+ int space,
+ unsigned_word addr,
+ unsigned nr_bytes,
+ access_type access,
+ device *client) /*callback/default*/
+{
+ hw_ide_device *ide = (hw_ide_device*)device_data(me);
+ int controller_nr = addr / nr_ide_drives_per_controller;
+ int drive_nr = addr % nr_ide_drives_per_controller;
+ ide_controller *controller;
+ ide_drive *drive;
+ if (controller_nr >= nr_ide_controllers)
+ device_error(me, "no controller for disk %s",
+ device_path(client));
+
+ controller = &ide->controller[controller_nr];
+ drive = &controller->drive[drive_nr];
+ drive->device = client;
+ if (device_find_property(client, "ide-byte-count") != NULL)
+ drive->geometry.byte = device_find_integer_property(client, "ide-byte-count");
+ else
+ drive->geometry.byte = 512;
+ if (device_find_property(client, "ide-sector-count") != NULL)
+ drive->geometry.sector = device_find_integer_property(client, "ide-sector-count");
+ if (device_find_property(client, "ide-head-count") != NULL)
+ drive->geometry.head = device_find_integer_property(client, "ide-head-count");
+ drive->default_geometry = drive->geometry;
+ DTRACE(ide, ("controller %d:%d %s byte-count %d, sector-count %d, head-count %d\n",
+ controller_nr,
+ drive->nr,
+ device_path(client),
+ drive->geometry.byte,
+ drive->geometry.sector,
+ drive->geometry.head));
+}
+
+
+static unsigned
+hw_ide_io_read_buffer(device *me,
+ void *dest,
+ int space,
+ unsigned_word addr,
+ unsigned nr_bytes,
+ cpu *processor,
+ unsigned_word cia)
+{
+ hw_ide_device *ide = (hw_ide_device *)device_data(me);
+ int control_nr;
+ int reg;
+ ide_controller *controller;
+
+ /* find the interface */
+ decode_address(me, &ide->decoder, space, addr, &control_nr, &reg, is_read);
+ controller = & ide->controller[control_nr];
+
+ /* process the transfer */
+ memset(dest, 0, nr_bytes);
+ switch (reg) {
+ case ide_data_reg:
+ do_fifo_read(me, controller, dest, nr_bytes);
+ break;
+ case ide_status_reg:
+ *(unsigned8*)dest = get_status(me, controller);
+ clear_interrupt(me, controller);
+ break;
+ case ide_alternate_status_reg:
+ *(unsigned8*)dest = get_status(me, controller);
+ break;
+ case ide_error_reg:
+ case ide_sector_count_reg:
+ case ide_sector_number_reg:
+ case ide_cylinder_reg0:
+ case ide_cylinder_reg1:
+ case ide_drive_head_reg:
+ case ide_control_reg:
+ case ide_dma_command_reg:
+ case ide_dma_status_reg:
+ case ide_dma_prd_table_address_reg0:
+ case ide_dma_prd_table_address_reg1:
+ case ide_dma_prd_table_address_reg2:
+ case ide_dma_prd_table_address_reg3:
+ *(unsigned8*)dest = controller->reg[reg];
+ break;
+ default:
+ device_error(me, "bus-error at address 0x%lx", addr);
+ break;
+ }
+ return nr_bytes;
+}
+
+
+static unsigned
+hw_ide_io_write_buffer(device *me,
+ const void *source,
+ int space,
+ unsigned_word addr,
+ unsigned nr_bytes,
+ cpu *processor,
+ unsigned_word cia)
+{
+ hw_ide_device *ide = (hw_ide_device *)device_data(me);
+ int control_nr;
+ int reg;
+ ide_controller *controller;
+
+ /* find the interface */
+ decode_address(me, &ide->decoder, space, addr, &control_nr, &reg, is_write);
+ controller = &ide->controller[control_nr];
+
+ /* process the access */
+ switch (reg) {
+ case ide_data_reg:
+ do_fifo_write(me, controller, source, nr_bytes);
+ break;
+ case ide_command_reg:
+ do_command(me, controller, *(unsigned8*)source);
+ break;
+ case ide_control_reg:
+ controller->reg[reg] = *(unsigned8*)source;
+ /* possibly cancel interrupts */
+ if ((controller->reg[reg] & 0x02) == 0x02)
+ clear_interrupt(me, controller);
+ break;
+ case ide_feature_reg:
+ case ide_sector_count_reg:
+ case ide_sector_number_reg:
+ case ide_cylinder_reg0:
+ case ide_cylinder_reg1:
+ case ide_drive_head_reg:
+ case ide_dma_command_reg:
+ case ide_dma_status_reg:
+ case ide_dma_prd_table_address_reg0:
+ case ide_dma_prd_table_address_reg1:
+ case ide_dma_prd_table_address_reg2:
+ case ide_dma_prd_table_address_reg3:
+ controller->reg[reg] = *(unsigned8*)source;
+ break;
+ default:
+ device_error(me, "bus-error at 0x%lx", addr);
+ break;
+ }
+ return nr_bytes;
+}
+
+
+static const device_interrupt_port_descriptor hw_ide_interrupt_ports[] = {
+ { "a", 0, 0 },
+ { "b", 1, 0 },
+ { "c", 2, 0 },
+ { "d", 3, 0 },
+ { NULL }
+};
+
+
+
+static device_callbacks const hw_ide_callbacks = {
+ { hw_ide_init_address, },
+ { hw_ide_attach_address, }, /* attach */
+ { hw_ide_io_read_buffer, hw_ide_io_write_buffer, },
+ { NULL, }, /* DMA */
+ { NULL, NULL, hw_ide_interrupt_ports }, /* interrupt */
+ { generic_device_unit_decode,
+ generic_device_unit_encode,
+ generic_device_address_to_attach_address,
+ generic_device_size_to_attach_size },
+};
+
+
+static void *
+hw_ide_create(const char *name,
+ const device_unit *unit_address,
+ const char *args)
+{
+ hw_ide_device *ide = ZALLOC(hw_ide_device);
+ return ide;
+}
+
+
+const device_descriptor hw_ide_device_descriptor[] = {
+ { "ide", hw_ide_create, &hw_ide_callbacks },
+ { NULL, },
+};
+
+#endif /* _HW_IDE_ */
diff --git a/gnu/dist/sim/ppc/hw_init.c b/gnu/dist/sim/ppc/hw_init.c
new file mode 100644
index 00000000000..b486f6f7860
--- /dev/null
+++ b/gnu/dist/sim/ppc/hw_init.c
@@ -0,0 +1,721 @@
+/* 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_INIT_C_
+#define _HW_INIT_C_
+
+#include "device_table.h"
+#include "bfd.h"
+#include "psim.h"
+
+
+/* DMA a file into memory */
+static int
+dma_file(device *me,
+ const char *file_name,
+ unsigned_word addr)
+{
+ int count;
+ int inc;
+ FILE *image;
+ char buf[1024];
+
+ /* get it open */
+ image = fopen(file_name, "r");
+ if (image == NULL)
+ return -1;
+
+ /* read it in slowly */
+ count = 0;
+ while (1) {
+ inc = fread(buf, 1, sizeof(buf), image);
+ if (feof(image) || ferror(image))
+ break;
+ if (device_dma_write_buffer(device_parent(me),
+ buf,
+ 0 /*address-space*/,
+ addr+count,
+ inc /*nr-bytes*/,
+ 1 /*violate ro*/) != inc) {
+ fclose(image);
+ return -1;
+ }
+ count += inc;
+ }
+
+ /* close down again */
+ fclose(image);
+
+ return count;
+}
+
+
+/* DEVICE
+
+ file - load a file into memory
+
+ DESCRIPTION
+
+ Loads the entire contents of <file-name> into memory at starting at
+ <<real-address>>. Assumes that memory exists for the load.
+
+ PROPERTIES
+
+ file-name = <string>
+
+ Name of the file to be loaded into memory
+
+ real-address = <integer>
+
+ Real address at which the file is to be loaded */
+
+static void
+hw_file_init_data_callback(device *me)
+{
+ int count;
+ const char *file_name = device_find_string_property(me, "file-name");
+ unsigned_word addr = device_find_integer_property(me, "real-address");
+ /* load the file */
+ count = dma_file(me, file_name, addr);
+ if (count < 0)
+ device_error(me, "Problem loading file %s\n", file_name);
+}
+
+
+static device_callbacks const hw_file_callbacks = {
+ { NULL, hw_file_init_data_callback, },
+ { NULL, }, /* address */
+ { NULL, }, /* IO */
+ { NULL, }, /* DMA */
+ { NULL, }, /* interrupt */
+ { NULL, }, /* unit */
+};
+
+
+/* DEVICE
+
+
+ data - initialize a memory location with specified data
+
+
+ DESCRIPTION
+
+
+ The pseudo device <<data>> provides a mechanism specifying the
+ initialization of a small section of memory.
+
+ Normally, the data would be written using a dma operation.
+ However, for some addresses this will not result in the desired
+ result. For instance, to initialize an address in an eeprom,
+ instead of a simple dma of the data, a sequence of writes (and then
+ real delays) that program the eeprom would be required.
+
+ For dma write initialization, the data device will write the
+ specified <<data>> to <<real-address>> using a normal dma.
+
+ For instance write initialization, the specified <<instance>> is
+ opened. Then a seek to the <<real-address>> is performed followed
+ by a write of the data.
+
+
+ Integer properties are stored using the target's endian mode.
+
+
+ PROPERTIES
+
+
+ data = <any-valid-property> (required)
+
+ Data to be loaded into memory. The property type determines how it
+ is loaded.
+
+
+ real-address = <integer> (required)
+
+ Start address at which the data is to be stored.
+
+
+ instance = <string> (optional)
+
+ Instance specification of the device that is to be opened so that
+ the specified data can be written to it.
+
+
+ EXAMPLES
+
+
+ The examples below illustrate the two alternative mechanisms that
+ can be used to store the value 0x12345678 at address 0xfff00c00,
+ which is normally part of the 512k system eeprom.
+
+
+ If the eeprom is being modeled by ram (<<memory>> device) then the
+ standard dma initialization can be used. By convention: the data
+ devices are uniquely identified by argumenting them with the
+ destinations real address; and all data devices are put under the
+ node <</openprom/init>>.
+
+ | /openprom/memory@0xfff00000/reg 0xfff00000 0x80000
+ | /openprom/init/data@0x1000/data 0x12345678
+ | /openprom/init/data@0x1000/real-address 0x1000
+
+
+ If instead a real eeprom was being used the instance write method
+ would instead need to be used (storing just a single byte in an
+ eeprom requires a complex sequence of accesses). The
+ <<real-address>> is specified as <<0x0c00>> which is the offset
+ into the eeprom. For brevity, most of the eeprom properties have
+ been omited.
+
+ | /iobus/eeprom@0xfff00000/reg 0xfff00000 0x80000
+ | /openprom/init/data@0xfff00c00/real-address 0x0c00
+ | /openprom/init/data@0xfff00c00/data 0x12345667
+ | /openprom/init/data@0xfff00c00/instance /iobus/eeprom@0xfff00000/reg
+
+
+ BUGS
+
+
+ At present, only <<integer>> properties can be specified for an
+ initial data value.
+
+ */
+
+
+static void
+hw_data_init_data_callback(device *me)
+{
+ unsigned_word addr = device_find_integer_property(me, "real-address");
+ const device_property *data = device_find_property(me, "data");
+ const char *instance_spec = (device_find_property(me, "instance") != NULL
+ ? device_find_string_property(me, "instance")
+ : NULL);
+ device_instance *instance = NULL;
+ if (data == NULL)
+ device_error(me, "missing property <data>\n");
+ if (instance_spec != NULL)
+ instance = tree_instance(me, instance_spec);
+ switch (data->type) {
+ case integer_property:
+ {
+ unsigned_cell buf = device_find_integer_property(me, "data");
+ H2T(buf);
+ if (instance == NULL) {
+ if (device_dma_write_buffer(device_parent(me),
+ &buf,
+ 0 /*address-space*/,
+ addr,
+ sizeof(buf), /*nr-bytes*/
+ 1 /*violate ro*/) != sizeof(buf))
+ device_error(me, "Problem storing integer 0x%x at 0x%lx\n",
+ (unsigned)buf, (unsigned long)addr);
+ }
+ else {
+ if (device_instance_seek(instance, 0, addr) < 0
+ || device_instance_write(instance, &buf, sizeof(buf)) != sizeof(buf))
+ device_error(me, "Problem storing integer 0x%x at 0x%lx of instance %s\n",
+ (unsigned)buf, (unsigned long)addr, instance_spec);
+ }
+ }
+ break;
+ default:
+ device_error(me, "Write of this data is not yet implemented\n");
+ break;
+ }
+ if (instance != NULL)
+ device_instance_delete(instance);
+}
+
+
+static device_callbacks const hw_data_callbacks = {
+ { NULL, hw_data_init_data_callback, },
+ { NULL, }, /* address */
+ { NULL, }, /* IO */
+ { NULL, }, /* DMA */
+ { NULL, }, /* interrupt */
+ { NULL, }, /* unit */
+};
+
+
+/* DEVICE
+
+
+ load-binary - load binary segments into memory
+
+
+ DESCRIPTION
+
+ Each loadable segment of the specified binary is loaded into memory
+ at its required address. It is assumed that the memory at those
+ addresses already exists.
+
+ This device is normally used to load an executable into memory as
+ part of real mode simulation.
+
+
+ PROPERTIES
+
+
+ file-name = <string>
+
+ Name of the binary to be loaded.
+
+
+ claim = <anything> (optional)
+
+ If this property is present, the real memory that is to be used by
+ the image being loaded will be claimed from the memory node
+ (specified by the ihandle <</chosen/memory>>).
+
+
+ BUGS
+
+
+ When loading the binary the bfd virtual-address is used. It should
+ be using the bfd load-address.
+
+ */
+
+/* DEVICE
+
+ map-binary - map the binary into the users address space
+
+ DESCRIPTION
+
+ Similar to load-binary except that memory for each segment is
+ created before the corresponding data for the segment is loaded.
+
+ This device is normally used to load an executable into a user mode
+ simulation.
+
+ PROPERTIES
+
+ file-name = <string>
+
+ Name of the binary to be loaded.
+
+ */
+
+static void
+update_for_binary_section(bfd *abfd,
+ asection *the_section,
+ PTR obj)
+{
+ unsigned_word section_vma;
+ unsigned_word section_size;
+ access_type access;
+ device *me = (device*)obj;
+
+ /* skip the section if no memory to allocate */
+ if (! (bfd_get_section_flags(abfd, the_section) & SEC_ALLOC))
+ return;
+
+ /* check/ignore any sections of size zero */
+ section_size = bfd_get_section_size_before_reloc(the_section);
+ if (section_size == 0)
+ return;
+
+ /* find where it is to go */
+ section_vma = bfd_get_section_vma(abfd, the_section);
+
+ DTRACE(binary,
+ ("name=%-7s, vma=0x%.8lx, size=%6ld, flags=%3lx(%s%s%s%s%s )\n",
+ bfd_get_section_name(abfd, the_section),
+ (long)section_vma,
+ (long)section_size,
+ (long)bfd_get_section_flags(abfd, the_section),
+ bfd_get_section_flags(abfd, the_section) & SEC_LOAD ? " LOAD" : "",
+ bfd_get_section_flags(abfd, the_section) & SEC_CODE ? " CODE" : "",
+ bfd_get_section_flags(abfd, the_section) & SEC_DATA ? " DATA" : "",
+ bfd_get_section_flags(abfd, the_section) & SEC_ALLOC ? " ALLOC" : "",
+ bfd_get_section_flags(abfd, the_section) & SEC_READONLY ? " READONLY" : ""
+ ));
+
+ /* If there is an .interp section, it means it needs a shared library interpreter. */
+ if (strcmp(".interp", bfd_get_section_name(abfd, the_section)) == 0)
+ error("Shared libraries are not yet supported.\n");
+
+ /* determine the devices access */
+ access = access_read;
+ if (bfd_get_section_flags(abfd, the_section) & SEC_CODE)
+ access |= access_exec;
+ if (!(bfd_get_section_flags(abfd, the_section) & SEC_READONLY))
+ access |= access_write;
+
+ /* if claim specified, allocate region from the memory device */
+ if (device_find_property(me, "claim") != NULL) {
+ device_instance *memory = tree_find_ihandle_property(me, "/chosen/memory");
+ unsigned_cell mem_in[3];
+ unsigned_cell mem_out[1];
+ mem_in[0] = 0; /*alignment - top-of-stack*/
+ mem_in[1] = section_size;
+ mem_in[2] = section_vma;
+ if (device_instance_call_method(memory, "claim", 3, mem_in, 1, mem_out) < 0)
+ device_error(me, "failed to claim memory for section at 0x%lx (0x%lx",
+ section_vma,
+ section_size);
+ if (mem_out[0] != section_vma)
+ device_error(me, "section address not as requested");
+ }
+
+ /* if a map, pass up a request to create the memory in core */
+ if (strncmp(device_name(me), "map-binary", strlen("map-binary")) == 0)
+ device_attach_address(device_parent(me),
+ attach_raw_memory,
+ 0 /*address space*/,
+ section_vma,
+ section_size,
+ access,
+ me);
+
+ /* if a load dma in the required data */
+ if (bfd_get_section_flags(abfd, the_section) & SEC_LOAD) {
+ void *section_init = zalloc(section_size);
+ if (!bfd_get_section_contents(abfd,
+ the_section,
+ section_init, 0,
+ section_size)) {
+ bfd_perror("binary");
+ device_error(me, "load of data failed");
+ return;
+ }
+ if (device_dma_write_buffer(device_parent(me),
+ section_init,
+ 0 /*space*/,
+ section_vma,
+ section_size,
+ 1 /*violate_read_only*/)
+ != section_size)
+ device_error(me, "broken transfer\n");
+ zfree(section_init); /* only free if load */
+ }
+}
+
+static void
+hw_binary_init_data_callback(device *me)
+{
+ /* get the file name */
+ const char *file_name = device_find_string_property(me, "file-name");
+ bfd *image;
+
+ /* open the file */
+ image = bfd_openr(file_name, NULL);
+ if (image == NULL) {
+ bfd_perror("binary");
+ device_error(me, "Failed to open file %s\n", file_name);
+ }
+
+ /* check it is valid */
+ if (!bfd_check_format(image, bfd_object)) {
+ bfd_close(image);
+ device_error(me, "The file %s has an invalid binary format\n", file_name);
+ }
+
+ /* and the data sections */
+ bfd_map_over_sections(image,
+ update_for_binary_section,
+ (PTR)me);
+
+ bfd_close(image);
+}
+
+
+static device_callbacks const hw_binary_callbacks = {
+ { NULL, hw_binary_init_data_callback, },
+ { NULL, }, /* address */
+ { NULL, }, /* IO */
+ { NULL, }, /* DMA */
+ { NULL, }, /* interrupt */
+ { NULL, }, /* unit */
+};
+
+
+/* DEVICE
+
+ stack - create an initial stack frame in memory
+
+ DESCRIPTION
+
+ Creates a stack frame of the specified type in memory.
+
+ Due to the startup sequence gdb uses when commencing a simulation,
+ it is not possible for the data to be placed on the stack to be
+ specified as part of the device tree. Instead the arguments to be
+ pushed onto the stack are specified using an IOCTL call.
+
+ The IOCTL takes the additional arguments:
+
+ | unsigned_word stack_end -- where the stack should come down from
+ | char **argv -- ...
+ | char **envp -- ...
+
+ PROPERTIES
+
+ stack-type = <string>
+
+ The form of the stack frame that is to be created.
+
+ */
+
+static int
+sizeof_argument_strings(char **arg)
+{
+ int sizeof_strings = 0;
+
+ /* robust */
+ if (arg == NULL)
+ return 0;
+
+ /* add up all the string sizes (padding as we go) */
+ for (; *arg != NULL; arg++) {
+ int len = strlen(*arg) + 1;
+ sizeof_strings += ALIGN_8(len);
+ }
+
+ return sizeof_strings;
+}
+
+static int
+number_of_arguments(char **arg)
+{
+ int nr;
+ if (arg == NULL)
+ return 0;
+ for (nr = 0; *arg != NULL; arg++, nr++);
+ return nr;
+}
+
+static int
+sizeof_arguments(char **arg)
+{
+ return ALIGN_8((number_of_arguments(arg) + 1) * sizeof(unsigned_word));
+}
+
+static void
+write_stack_arguments(device *me,
+ char **arg,
+ unsigned_word start_block,
+ unsigned_word end_block,
+ unsigned_word start_arg,
+ unsigned_word end_arg)
+{
+ DTRACE(stack,
+ ("write_stack_arguments(device=%s, arg=0x%lx, start_block=0x%lx, end_block=0x%lx, start_arg=0x%lx, end_arg=0x%lx)\n",
+ device_name(me), (long)arg, (long)start_block, (long)end_block, (long)start_arg, (long)end_arg));
+ if (arg == NULL)
+ device_error(me, "Attempt to write a null array onto the stack\n");
+ /* only copy in arguments, memory is already zero */
+ for (; *arg != NULL; arg++) {
+ int len = strlen(*arg)+1;
+ unsigned_word target_start_block;
+ DTRACE(stack,
+ ("write_stack_arguments() write %s=%s at %s=0x%lx %s=0x%lx %s=0x%lx\n",
+ "**arg", *arg, "start_block", (long)start_block,
+ "len", (long)len, "start_arg", (long)start_arg));
+ if (psim_write_memory(device_system(me), 0, *arg,
+ start_block, len,
+ 0/*violate_readonly*/) != len)
+ device_error(me, "Write of **arg (%s) at 0x%lx of stack failed\n",
+ *arg, (unsigned long)start_block);
+ target_start_block = H2T_word(start_block);
+ if (psim_write_memory(device_system(me), 0, &target_start_block,
+ start_arg, sizeof(target_start_block),
+ 0) != sizeof(target_start_block))
+ device_error(me, "Write of *arg onto stack failed\n");
+ start_block += ALIGN_8(len);
+ start_arg += sizeof(start_block);
+ }
+ start_arg += sizeof(start_block); /*the null at the end*/
+ if (start_block != end_block
+ || ALIGN_8(start_arg) != end_arg)
+ device_error(me, "Probable corrpution of stack arguments\n");
+ DTRACE(stack, ("write_stack_arguments() = void\n"));
+}
+
+static void
+create_ppc_elf_stack_frame(device *me,
+ unsigned_word bottom_of_stack,
+ char **argv,
+ char **envp)
+{
+ /* fixme - this is over aligned */
+
+ /* information block */
+ const unsigned sizeof_envp_block = sizeof_argument_strings(envp);
+ const unsigned_word start_envp_block = bottom_of_stack - sizeof_envp_block;
+ const unsigned sizeof_argv_block = sizeof_argument_strings(argv);
+ const unsigned_word start_argv_block = start_envp_block - sizeof_argv_block;
+
+ /* auxiliary vector - contains only one entry */
+ const unsigned sizeof_aux_entry = 2*sizeof(unsigned_word); /* magic */
+ const unsigned_word start_aux = start_argv_block - ALIGN_8(sizeof_aux_entry);
+
+ /* environment points (including null sentinal) */
+ const unsigned sizeof_envp = sizeof_arguments(envp);
+ const unsigned_word start_envp = start_aux - sizeof_envp;
+
+ /* argument pointers (including null sentinal) */
+ const int argc = number_of_arguments(argv);
+ const unsigned sizeof_argv = sizeof_arguments(argv);
+ const unsigned_word start_argv = start_envp - sizeof_argv;
+
+ /* link register save address - alligned to a 16byte boundary */
+ const unsigned_word top_of_stack = ((start_argv
+ - 2 * sizeof(unsigned_word))
+ & ~0xf);
+
+ /* install arguments on stack */
+ write_stack_arguments(me, envp,
+ start_envp_block, bottom_of_stack,
+ start_envp, start_aux);
+ write_stack_arguments(me, argv,
+ start_argv_block, start_envp_block,
+ start_argv, start_envp);
+
+ /* set up the registers */
+ psim_write_register(device_system(me), -1,
+ &top_of_stack, "sp", cooked_transfer);
+ psim_write_register(device_system(me), -1,
+ &argc, "r3", cooked_transfer);
+ psim_write_register(device_system(me), -1,
+ &start_argv, "r4", cooked_transfer);
+ psim_write_register(device_system(me), -1,
+ &start_envp, "r5", cooked_transfer);
+ psim_write_register(device_system(me), -1,
+ &start_aux, "r6", cooked_transfer);
+}
+
+static void
+create_ppc_aix_stack_frame(device *me,
+ unsigned_word bottom_of_stack,
+ char **argv,
+ char **envp)
+{
+ unsigned_word core_envp;
+ unsigned_word core_argv;
+ unsigned_word core_argc;
+ unsigned_word core_aux;
+ unsigned_word top_of_stack;
+
+ /* cheat - create an elf stack frame */
+ create_ppc_elf_stack_frame(me, bottom_of_stack, argv, envp);
+
+ /* extract argument addresses from registers */
+ psim_read_register(device_system(me), 0,
+ &top_of_stack, "r1", cooked_transfer);
+ psim_read_register(device_system(me), 0,
+ &core_argc, "r3", cooked_transfer);
+ psim_read_register(device_system(me), 0,
+ &core_argv, "r4", cooked_transfer);
+ psim_read_register(device_system(me), 0,
+ &core_envp, "r5", cooked_transfer);
+ psim_read_register(device_system(me), 0,
+ &core_aux, "r6", cooked_transfer);
+
+ /* extract arguments from registers */
+ device_error(me, "Unfinished procedure create_ppc_aix_stack_frame\n");
+}
+
+
+static void
+create_ppc_chirp_bootargs(device *me,
+ char **argv)
+{
+ /* concat the arguments */
+ char args[1024];
+ char **chp = argv + 1;
+ args[0] = '\0';
+ while (*chp != NULL) {
+ if (strlen(args) > 0)
+ strcat(args, " ");
+ if (strlen(args) + strlen(*chp) >= sizeof(args))
+ device_error(me, "buffer overflow");
+ strcat(args, *chp);
+ chp++;
+ }
+
+ /* set the arguments property */
+ tree_parse(me, "/chosen/bootargs \"%s", args);
+}
+
+
+static int
+hw_stack_ioctl(device *me,
+ cpu *processor,
+ unsigned_word cia,
+ device_ioctl_request request,
+ va_list ap)
+{
+ switch (request) {
+ case device_ioctl_create_stack:
+ {
+ unsigned_word stack_pointer = va_arg(ap, unsigned_word);
+ char **argv = va_arg(ap, char **);
+ char **envp = va_arg(ap, char **);
+ const char *stack_type;
+ DTRACE(stack,
+ ("stack_ioctl_callback(me=0x%lx:%s processor=0x%lx cia=0x%lx argv=0x%lx envp=0x%lx)\n",
+ (long)me, device_name(me),
+ (long)processor,
+ (long)cia,
+ (long)argv,
+ (long)envp));
+ stack_type = device_find_string_property(me, "stack-type");
+ if (strcmp(stack_type, "ppc-elf") == 0)
+ create_ppc_elf_stack_frame(me, stack_pointer, argv, envp);
+ else if (strcmp(stack_type, "ppc-xcoff") == 0)
+ create_ppc_aix_stack_frame(me, stack_pointer, argv, envp);
+ else if (strcmp(stack_type, "chirp") == 0)
+ create_ppc_chirp_bootargs(me, argv);
+ else if (strcmp(stack_type, "none") != 0)
+ device_error(me, "Unknown initial stack frame type %s", stack_type);
+ DTRACE(stack,
+ ("stack_ioctl_callback() = void\n"));
+ break;
+ }
+ default:
+ device_error(me, "Unsupported ioctl requested");
+ break;
+ }
+ return 0;
+}
+
+static device_callbacks const hw_stack_callbacks = {
+ { NULL, },
+ { NULL, }, /* address */
+ { NULL, }, /* IO */
+ { NULL, }, /* DMA */
+ { NULL, }, /* interrupt */
+ { NULL, }, /* unit */
+ NULL, /* instance */
+ hw_stack_ioctl,
+};
+
+const device_descriptor hw_init_device_descriptor[] = {
+ { "file", NULL, &hw_file_callbacks },
+ { "data", NULL, &hw_data_callbacks },
+ { "load-binary", NULL, &hw_binary_callbacks },
+ { "map-binary", NULL, &hw_binary_callbacks },
+ { "stack", NULL, &hw_stack_callbacks },
+ { NULL },
+};
+
+#endif _HW_INIT_C_
diff --git a/gnu/dist/sim/ppc/hw_iobus.c b/gnu/dist/sim/ppc/hw_iobus.c
new file mode 100644
index 00000000000..3cd138c1c80
--- /dev/null
+++ b/gnu/dist/sim/ppc/hw_iobus.c
@@ -0,0 +1,100 @@
+/* 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.
+
+ */
+
+
+#ifndef _HW_IOBUS_C_
+#define _HW_IOBUS_C_
+
+#ifndef STATIC_INLINE_HW_IOBUS
+#define STATIC_INLINE_HW_IOBUS STATIC_INLINE
+#endif
+
+#include "device_table.h"
+
+
+/* DEVICE
+
+ iobus - simple bus for attaching devices
+
+ DESCRIPTION
+
+ IOBUS provides a simple `local' bus for attaching (hanging)
+ programmed IO devices from. All child devices are directly mapped
+ into this devices parent address space (after checking that the
+ attach address lies within the <<iobus>> address range. address).
+
+ PROPERTIES
+
+ None.
+
+ */
+
+static void
+hw_iobus_attach_address_callback(device *me,
+ attach_type type,
+ int space,
+ unsigned_word addr,
+ unsigned nr_bytes,
+ access_type access,
+ device *client) /*callback/default*/
+{
+ int attach_space;
+ unsigned_word attach_address;
+ /* sanity check */
+ if (space != 0)
+ device_error(me, "invalid space (%d) specified by %s",
+ space, device_path(client));
+ /* get the bus address */
+ device_address_to_attach_address(device_parent(me),
+ device_unit_address(me),
+ &attach_space,
+ &attach_address,
+ me);
+ if (addr < attach_address)
+ device_error(me, "Invalid attach address 0x%lx", (unsigned long)addr);
+ device_attach_address(device_parent(me),
+ type,
+ attach_space,
+ addr,
+ nr_bytes,
+ access,
+ client);
+}
+
+
+static device_callbacks const hw_iobus_callbacks = {
+ { NULL, },
+ { hw_iobus_attach_address_callback, },
+ { NULL, }, /* IO */
+ { NULL, }, /* DMA */
+ { NULL, }, /* interrupt */
+ { generic_device_unit_decode,
+ generic_device_unit_encode,
+ generic_device_address_to_attach_address,
+ generic_device_size_to_attach_size }
+};
+
+
+const device_descriptor hw_iobus_device_descriptor[] = {
+ { "iobus", NULL, &hw_iobus_callbacks },
+ { NULL, },
+};
+
+#endif /* _HW_IOBUS_ */
diff --git a/gnu/dist/sim/ppc/hw_memory.c b/gnu/dist/sim/ppc/hw_memory.c
new file mode 100644
index 00000000000..117324b0edd
--- /dev/null
+++ b/gnu/dist/sim/ppc/hw_memory.c
@@ -0,0 +1,538 @@
+/* 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_MEMORY_C_
+#define _HW_MEMORY_C_
+
+#ifndef STATIC_INLINE_HW_MEMORY
+#define STATIC_INLINE_HW_MEMORY STATIC_INLINE
+#endif
+
+#include "device_table.h"
+
+/* DEVICE
+
+
+ memory - description of system memory
+
+
+ DESCRIPTION
+
+
+ This device describes the size and location of the banks of
+ physical memory within the simulation.
+
+ In addition, this device supports the "claim" and "release" methods
+ that can be used by OpenBoot client programs to manage the
+ allocation of physical memory.
+
+
+ PROPERTIES
+
+
+ reg = { <address> <size> } (required)
+
+ Each pair specify one bank of memory.
+
+ available = { <address> <size> } (automatic)
+
+ Each pair specifies a block of memory that is currently unallocated.
+
+
+ BUGS
+
+
+ OpenFirmware doesn't make it clear if, when releasing memory the
+ same address + size pair as was used during the claim should be
+ specified.
+
+ It is assumed that #size-cells and #address-cells for the parent
+ node of this device are both one i.e. an address or size can be
+ specified using a single memory cell (word).
+
+ Significant work will be required before the <<memory>> device can
+ support 64bit addresses (#address-cells equal two).
+
+ */
+
+typedef struct _memory_reg_spec {
+ unsigned_cell base;
+ unsigned_cell size;
+} memory_reg_spec;
+
+typedef struct _hw_memory_chunk hw_memory_chunk;
+struct _hw_memory_chunk {
+ unsigned_word address;
+ unsigned_word size;
+ int available;
+ hw_memory_chunk *next;
+};
+
+typedef struct _hw_memory_device {
+ hw_memory_chunk *heap;
+} hw_memory_device;
+
+
+static void *
+hw_memory_create(const char *name,
+ const device_unit *unit_address,
+ const char *args)
+{
+ hw_memory_device *hw_memory = ZALLOC(hw_memory_device);
+ return hw_memory;
+}
+
+
+static void
+hw_memory_set_available(device *me,
+ hw_memory_device *hw_memory)
+{
+ hw_memory_chunk *chunk = NULL;
+ memory_reg_spec *available = NULL;
+ int nr_available = 0;
+ int curr = 0;
+ int sizeof_available = 0;
+ /* determine the nr of available chunks */
+ chunk = hw_memory->heap;
+ nr_available = 0;
+ while (chunk != NULL) {
+ if (chunk->available)
+ nr_available += 1;
+ ASSERT(chunk->next == NULL
+ || chunk->address < chunk->next->address);
+ ASSERT(chunk->next == NULL
+ || chunk->address + chunk->size == chunk->next->address);
+ chunk = chunk->next;
+ }
+ /* now create the available struct */
+ ASSERT(nr_available > 0);
+ sizeof_available = sizeof(memory_reg_spec) * nr_available;
+ available = zalloc(sizeof_available);
+ chunk = hw_memory->heap;
+ curr = 0;
+ while (chunk != NULL) {
+ if (chunk->available) {
+ available[curr].base = H2BE_cell(chunk->address);
+ available[curr].size = H2BE_cell(chunk->size);
+ curr += 1;
+ }
+ chunk = chunk->next;
+ }
+ /* update */
+ device_set_array_property(me, "available", available, sizeof_available);
+ zfree(available);
+}
+
+
+static void
+hw_memory_init_address(device *me)
+{
+ hw_memory_device *hw_memory = (hw_memory_device*)device_data(me);
+
+ /* free up any previous structures */
+ {
+ hw_memory_chunk *curr_chunk = hw_memory->heap;
+ hw_memory->heap = NULL;
+ while (curr_chunk != NULL) {
+ hw_memory_chunk *dead_chunk = curr_chunk;
+ curr_chunk = dead_chunk->next;
+ dead_chunk->next = NULL;
+ zfree(dead_chunk);
+ }
+ }
+
+ /* attach memory regions according to the "reg" property */
+ {
+ int reg_nr;
+ reg_property_spec reg;
+ for (reg_nr = 0;
+ device_find_reg_array_property(me, "reg", reg_nr, &reg);
+ reg_nr++) {
+ int i;
+ /* check that the entry meets restrictions */
+ for (i = 0; i < reg.address.nr_cells - 1; i++)
+ if (reg.address.cells[i] != 0)
+ device_error(me, "Only single celled addresses supported");
+ for (i = 0; i < reg.size.nr_cells - 1; i++)
+ if (reg.size.cells[i] != 0)
+ device_error(me, "Only single celled sizes supported");
+ /* attach the range */
+ device_attach_address(device_parent(me),
+ attach_raw_memory,
+ 0 /*address space*/,
+ reg.address.cells[reg.address.nr_cells - 1],
+ reg.size.cells[reg.size.nr_cells - 1],
+ access_read_write_exec,
+ me);
+ }
+ }
+
+ /* create the initial `available memory' data structure */
+ if (device_find_property(me, "available") != NULL) {
+ hw_memory_chunk **curr_chunk = &hw_memory->heap;
+ int cell_nr;
+ unsigned_cell dummy;
+ int nr_cells = device_find_integer_array_property(me, "available", 0, &dummy);
+ if ((nr_cells % 2) != 0)
+ device_error(me, "property \"available\" invalid - contains an odd number of cells");
+ for (cell_nr = 0;
+ cell_nr < nr_cells;
+ cell_nr += 2) {
+ hw_memory_chunk *new_chunk = ZALLOC(hw_memory_chunk);
+ device_find_integer_array_property(me, "available", cell_nr,
+ &new_chunk->address);
+ device_find_integer_array_property(me, "available", cell_nr + 1,
+ &new_chunk->size);
+ new_chunk->available = 1;
+ *curr_chunk = new_chunk;
+ curr_chunk = &new_chunk->next;
+ }
+ }
+ else {
+ hw_memory_chunk **curr_chunk = &hw_memory->heap;
+ int reg_nr;
+ reg_property_spec reg;
+ for (reg_nr = 0;
+ device_find_reg_array_property(me, "reg", reg_nr, &reg);
+ reg_nr++) {
+ hw_memory_chunk *new_chunk;
+ new_chunk = ZALLOC(hw_memory_chunk);
+ new_chunk->address = reg.address.cells[reg.address.nr_cells - 1];
+ new_chunk->size = reg.size.cells[reg.size.nr_cells - 1];
+ new_chunk->available = 1;
+ *curr_chunk = new_chunk;
+ curr_chunk = &new_chunk->next;
+ }
+ }
+
+ /* initialize the alloc property for this device */
+ hw_memory_set_available(me, hw_memory);
+}
+
+static void
+hw_memory_instance_delete(device_instance *instance)
+{
+ return;
+}
+
+static int
+hw_memory_instance_claim(device_instance *instance,
+ int n_stack_args,
+ unsigned_cell stack_args[/*n_stack_args*/],
+ int n_stack_returns,
+ unsigned_cell stack_returns[/*n_stack_returns*/])
+{
+ hw_memory_device *hw_memory = device_instance_data(instance);
+ device *me = device_instance_device(instance);
+ int stackp = 0;
+ unsigned_word alignment;
+ unsigned_cell size;
+ unsigned_cell address;
+ hw_memory_chunk *chunk = NULL;
+
+ /* get the alignment from the stack */
+ if (n_stack_args < stackp + 1)
+ device_error(me, "claim - incorrect number of arguments (alignment missing)");
+ alignment = stack_args[stackp];
+ stackp++;
+
+ /* get the size from the stack */
+ {
+ int i;
+ int nr_cells = device_nr_size_cells(device_parent(me));
+ if (n_stack_args < stackp + nr_cells)
+ device_error(me, "claim - incorrect number of arguments (size missing)");
+ for (i = 0; i < nr_cells - 1; i++) {
+ if (stack_args[stackp] != 0)
+ device_error(me, "claim - multi-cell sizes not supported");
+ stackp++;
+ }
+ size = stack_args[stackp];
+ stackp++;
+ }
+
+ /* get the address from the stack */
+ {
+ int nr_cells = device_nr_address_cells(device_parent(me));
+ if (alignment != 0) {
+ if (n_stack_args != stackp) {
+ if (n_stack_args == stackp + nr_cells)
+ DTRACE(memory, ("claim - extra address argument ignored\n"));
+ else
+ device_error(me, "claim - incorrect number of arguments (optional addr)");
+ }
+ address = 0;
+ }
+ else {
+ int i;
+ if (n_stack_args != stackp + nr_cells)
+ device_error(me, "claim - incorrect number of arguments (addr missing)");
+ for (i = 0; i < nr_cells - 1; i++) {
+ if (stack_args[stackp] != 0)
+ device_error(me, "claim - multi-cell addresses not supported");
+ stackp++;
+ }
+ address = stack_args[stackp];
+ }
+ }
+
+ /* check that there is space for the result */
+ if (n_stack_returns != 0
+ && n_stack_returns != device_nr_address_cells(device_parent(me)))
+ device_error(me, "claim - invalid number of return arguments");
+
+ /* find a chunk candidate, either according to address or alignment */
+ if (alignment == 0) {
+ chunk = hw_memory->heap;
+ while (chunk != NULL) {
+ if ((address + size) <= (chunk->address + chunk->size))
+ break;
+ chunk = chunk->next;
+ }
+ if (chunk == NULL || address < chunk->address || !chunk->available)
+ device_error(me, "failed to allocate %ld bytes at 0x%lx",
+ (unsigned long)size, (unsigned long)address);
+ DTRACE(memory, ("claim - address=0x%lx size=0x%lx\n",
+ (unsigned long)address,
+ (unsigned long)size));
+ }
+ else {
+ /* adjust the alignment so that it is a power of two */
+ unsigned_word align_mask = 1;
+ while (align_mask < alignment && align_mask != 0)
+ align_mask <<= 1;
+ if (align_mask == 0)
+ device_error(me, "alignment 0x%lx is to large", (unsigned long)alignment);
+ align_mask -= 1;
+ /* now find an aligned chunk that fits */
+ chunk = hw_memory->heap;
+ while (chunk != NULL) {
+ address = ((chunk->address + align_mask) & ~align_mask);
+ if ((chunk->available)
+ && (chunk->address + chunk->size >= address + size))
+ break;
+ chunk = chunk->next;
+ }
+ if (chunk == NULL)
+ device_error(me, "failed to allocate %ld bytes with alignment %ld",
+ (unsigned long)size, (unsigned long)alignment);
+ DTRACE(memory, ("claim - size=0x%lx alignment=%ld (0x%lx), address=0x%lx\n",
+ (unsigned long)size,
+ (unsigned long)alignment,
+ (unsigned long)alignment,
+ (unsigned long)address));
+ }
+
+ /* break off a bit before this chunk if needed */
+ ASSERT(address >= chunk->address);
+ if (address > chunk->address) {
+ hw_memory_chunk *next_chunk = ZALLOC(hw_memory_chunk);
+ /* insert a new chunk */
+ next_chunk->next = chunk->next;
+ chunk->next = next_chunk;
+ /* adjust the address/size */
+ next_chunk->address = address;
+ next_chunk->size = chunk->address + chunk->size - next_chunk->address;
+ next_chunk->available = 1;
+ chunk->size = next_chunk->address - chunk->address;
+ /* make this new chunk the one to allocate */
+ chunk = next_chunk;
+ }
+ ASSERT(address == chunk->address);
+
+ /* break off a bit after this chunk if needed */
+ ASSERT(address + size <= chunk->address + chunk->size);
+ if (address + size < chunk->address + chunk->size) {
+ hw_memory_chunk *next_chunk = ZALLOC(hw_memory_chunk);
+ /* insert it in to the list */
+ next_chunk->next = chunk->next;
+ chunk->next = next_chunk;
+ /* adjust the address/size */
+ next_chunk->address = address + size;
+ next_chunk->size = chunk->address + chunk->size - next_chunk->address;
+ next_chunk->available = 1;
+ chunk->size = next_chunk->address - chunk->address;
+ }
+ ASSERT(address + size == chunk->address + chunk->size);
+
+ /* now allocate/return it */
+ chunk->available = 0;
+ hw_memory_set_available(device_instance_device(instance), hw_memory);
+ if (n_stack_returns > 0) {
+ int i;
+ for (i = 0; i < n_stack_returns - 1; i++)
+ stack_returns[i] = 0;
+ stack_returns[n_stack_returns - 1] = address;
+ }
+
+ return 0;
+}
+
+
+static int
+hw_memory_instance_release(device_instance *instance,
+ int n_stack_args,
+ unsigned_cell stack_args[/*n_stack_args*/],
+ int n_stack_returns,
+ unsigned_cell stack_returns[/*n_stack_returns*/])
+{
+ hw_memory_device *hw_memory = device_instance_data(instance);
+ device *me = device_instance_device(instance);
+ unsigned_word length;
+ unsigned_word address;
+ int stackp = 0;
+ hw_memory_chunk *chunk;
+
+ /* get the length from the stack */
+ {
+ int i;
+ int nr_cells = device_nr_size_cells(device_parent(me));
+ if (n_stack_args < stackp + nr_cells)
+ device_error(me, "release - incorrect number of arguments (length missing)");
+ for (i = 0; i < nr_cells - 1; i++) {
+ if (stack_args[stackp] != 0)
+ device_error(me, "release - multi-cell length not supported");
+ stackp++;
+ }
+ length = stack_args[stackp];
+ stackp++;
+ }
+
+ /* get the address from the stack */
+ {
+ int i;
+ int nr_cells = device_nr_address_cells(device_parent(me));
+ if (n_stack_args != stackp + nr_cells)
+ device_error(me, "release - incorrect number of arguments (addr missing)");
+ for (i = 0; i < nr_cells - 1; i++) {
+ if (stack_args[stackp] != 0)
+ device_error(me, "release - multi-cell addresses not supported");
+ stackp++;
+ }
+ address = stack_args[stackp];
+ }
+
+ /* returns ok */
+ if (n_stack_returns != 0)
+ device_error(me, "release - nonzero number of results");
+
+ /* try to free the corresponding memory chunk */
+ chunk = hw_memory->heap;
+ while (chunk != NULL) {
+ if (chunk->address == address
+ && chunk->size == length) {
+ /* an exact match */
+ if (chunk->available)
+ device_error(me, "memory chunk 0x%lx (size 0x%lx) already available",
+ (unsigned long)address,
+ (unsigned long)length);
+ else {
+ /* free this chunk */
+ DTRACE(memory, ("release - address=0x%lx, length=0x%lx\n",
+ (unsigned long) address,
+ (unsigned long) length));
+ chunk->available = 1;
+ break;
+ }
+ }
+ else if (chunk->address >= address
+ && chunk->address + chunk->size <= address + length) {
+ /* a sub region */
+ if (!chunk->available) {
+ DTRACE(memory, ("release - address=0x%lx, size=0x%lx within region 0x%lx length 0x%lx\n",
+ (unsigned long) chunk->address,
+ (unsigned long) chunk->size,
+ (unsigned long) address,
+ (unsigned long) length));
+ chunk->available = 1;
+ }
+ }
+ chunk = chunk->next;
+ }
+ if (chunk == NULL) {
+ printf_filtered("warning: released chunks within region 0x%lx..0x%lx\n",
+ (unsigned long)address,
+ (unsigned long)(address + length - 1));
+ }
+
+ /* check for the chance to merge two adjacent available memory chunks */
+ chunk = hw_memory->heap;
+ while (chunk != NULL) {
+ if (chunk->available
+ && chunk->next != NULL && chunk->next->available) {
+ /* adjacent */
+ hw_memory_chunk *delete = chunk->next;
+ ASSERT(chunk->address + chunk->size == delete->address);
+ chunk->size += delete->size;
+ chunk->next = delete->next;
+ zfree(delete);
+ }
+ else {
+ chunk = chunk->next;
+ }
+ }
+
+ /* update the corresponding property */
+ hw_memory_set_available(device_instance_device(instance), hw_memory);
+
+ return 0;
+}
+
+
+static device_instance_methods hw_memory_instance_methods[] = {
+ { "claim", hw_memory_instance_claim },
+ { "release", hw_memory_instance_release },
+ { NULL, },
+};
+
+static device_instance_callbacks const hw_memory_instance_callbacks = {
+ hw_memory_instance_delete,
+ NULL /*read*/, NULL /*write*/, NULL /*seek*/,
+ hw_memory_instance_methods
+};
+
+static device_instance *
+hw_memory_create_instance(device *me,
+ const char *path,
+ const char *args)
+{
+ return device_create_instance_from(me, NULL,
+ device_data(me), /* nothing better */
+ path, args,
+ &hw_memory_instance_callbacks);
+}
+
+static device_callbacks const hw_memory_callbacks = {
+ { hw_memory_init_address, },
+ { NULL, }, /* address */
+ { NULL, }, /* IO */
+ { NULL, }, /* DMA */
+ { NULL, }, /* interrupt */
+ { NULL, }, /* unit */
+ hw_memory_create_instance,
+};
+
+const device_descriptor hw_memory_device_descriptor[] = {
+ { "memory", hw_memory_create, &hw_memory_callbacks },
+ { NULL },
+};
+
+#endif /* _HW_MEMORY_C_ */
diff --git a/gnu/dist/sim/ppc/hw_nvram.c b/gnu/dist/sim/ppc/hw_nvram.c
new file mode 100644
index 00000000000..6d899a1c665
--- /dev/null
+++ b/gnu/dist/sim/ppc/hw_nvram.c
@@ -0,0 +1,261 @@
+/* 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.
+
+ */
+
+
+#ifndef _HW_NVRAM_C_
+#define _HW_NVRAM_C_
+
+#ifndef STATIC_INLINE_HW_NVRAM
+#define STATIC_INLINE_HW_NVRAM STATIC_INLINE
+#endif
+
+#include "device_table.h"
+
+#ifdef HAVE_TIME_H
+#include <time.h>
+#endif
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#endif
+
+/* DEVICE
+
+
+ nvram - non-volatile memory with clock
+
+
+ DESCRIPTION
+
+
+ This device implements a small byte addressable non-volatile
+ memory. The top 8 bytes of this memory include a real-time clock.
+
+
+ PROPERTIES
+
+
+ reg = <address> <size> (required)
+
+ Specify the address/size of this device within its parents address
+ space.
+
+
+ timezone = <integer> (optional)
+
+ Adjustment to the hosts current GMT (in seconds) that should be
+ applied when updating the NVRAM's clock. If no timezone is
+ specified, zero (GMT or UCT) is assumed.
+
+
+ */
+
+typedef struct _hw_nvram_device {
+ unsigned8 *memory;
+ unsigned sizeof_memory;
+#ifdef HAVE_TIME_H
+ time_t host_time;
+#else
+ long host_time;
+#endif
+ unsigned timezone;
+ /* useful */
+ unsigned addr_year;
+ unsigned addr_month;
+ unsigned addr_date;
+ unsigned addr_day;
+ unsigned addr_hour;
+ unsigned addr_minutes;
+ unsigned addr_seconds;
+ unsigned addr_control;
+} hw_nvram_device;
+
+static void *
+hw_nvram_create(const char *name,
+ const device_unit *unit_address,
+ const char *args)
+{
+ hw_nvram_device *nvram = ZALLOC(hw_nvram_device);
+ return nvram;
+}
+
+typedef struct _hw_nvram_reg_spec {
+ unsigned32 base;
+ unsigned32 size;
+} hw_nvram_reg_spec;
+
+static void
+hw_nvram_init_address(device *me)
+{
+ hw_nvram_device *nvram = (hw_nvram_device*)device_data(me);
+
+ /* use the generic init code to attach this device to its parent bus */
+ generic_device_init_address(me);
+
+ /* find the first non zero reg property and use that as the device
+ size */
+ if (nvram->sizeof_memory == 0) {
+ reg_property_spec reg;
+ int reg_nr;
+ for (reg_nr = 0;
+ device_find_reg_array_property(me, "reg", reg_nr, &reg);
+ reg_nr++) {
+ unsigned attach_size;
+ if (device_size_to_attach_size(device_parent(me),
+ &reg.size, &attach_size,
+ me)) {
+ nvram->sizeof_memory = attach_size;
+ break;
+ }
+ }
+ if (nvram->sizeof_memory == 0)
+ device_error(me, "reg property must contain a non-zero phys-addr:size tupple");
+ if (nvram->sizeof_memory < 8)
+ device_error(me, "NVRAM must be at least 8 bytes in size");
+ }
+
+ /* initialize the hw_nvram */
+ if (nvram->memory == NULL) {
+ nvram->memory = zalloc(nvram->sizeof_memory);
+ }
+ else
+ memset(nvram->memory, nvram->sizeof_memory, 0);
+
+ if (device_find_property(me, "timezone") == NULL)
+ nvram->timezone = 0;
+ else
+ nvram->timezone = device_find_integer_property(me, "timezone");
+
+ nvram->addr_year = nvram->sizeof_memory - 1;
+ nvram->addr_month = nvram->sizeof_memory - 2;
+ nvram->addr_date = nvram->sizeof_memory - 3;
+ nvram->addr_day = nvram->sizeof_memory - 4;
+ nvram->addr_hour = nvram->sizeof_memory - 5;
+ nvram->addr_minutes = nvram->sizeof_memory - 6;
+ nvram->addr_seconds = nvram->sizeof_memory - 7;
+ nvram->addr_control = nvram->sizeof_memory - 8;
+
+}
+
+static int
+hw_nvram_bcd(int val)
+{
+ return ((val / 10) << 4) + (val % 10);
+}
+
+
+/* If reached an update interval and allowed, update the clock within
+ the hw_nvram. While this function could be implemented using events
+ it isn't on the assumption that the HW_NVRAM will hardly ever be
+ referenced and hence there is little need in keeping the clock
+ continually up-to-date */
+
+static void
+hw_nvram_update_clock(hw_nvram_device *nvram,
+ cpu *processor)
+{
+#ifdef HAVE_TIME_H
+ if (!(nvram->memory[nvram->addr_control] & 0xc0)) {
+ time_t host_time = time(NULL);
+ if (nvram->host_time != host_time) {
+ time_t nvtime = host_time + nvram->timezone;
+ struct tm *clock = gmtime(&nvtime);
+ nvram->host_time = host_time;
+ nvram->memory[nvram->addr_year] = hw_nvram_bcd(clock->tm_year);
+ nvram->memory[nvram->addr_month] = hw_nvram_bcd(clock->tm_mon + 1);
+ nvram->memory[nvram->addr_date] = hw_nvram_bcd(clock->tm_mday);
+ nvram->memory[nvram->addr_day] = hw_nvram_bcd(clock->tm_wday + 1);
+ nvram->memory[nvram->addr_hour] = hw_nvram_bcd(clock->tm_hour);
+ nvram->memory[nvram->addr_minutes] = hw_nvram_bcd(clock->tm_min);
+ nvram->memory[nvram->addr_seconds] = hw_nvram_bcd(clock->tm_sec);
+ }
+ }
+#else
+ error("fixme - where do I find out GMT\n");
+#endif
+}
+
+static void
+hw_nvram_set_clock(hw_nvram_device *nvram, cpu *processor)
+{
+ error ("fixme - how do I set the localtime\n");
+}
+
+static unsigned
+hw_nvram_io_read_buffer(device *me,
+ void *dest,
+ int space,
+ unsigned_word addr,
+ unsigned nr_bytes,
+ cpu *processor,
+ unsigned_word cia)
+{
+ int i;
+ hw_nvram_device *nvram = (hw_nvram_device*)device_data(me);
+ for (i = 0; i < nr_bytes; i++) {
+ unsigned address = (addr + i) % nvram->sizeof_memory;
+ unsigned8 data = nvram->memory[address];
+ hw_nvram_update_clock(nvram, processor);
+ ((unsigned8*)dest)[i] = data;
+ }
+ return nr_bytes;
+}
+
+static unsigned
+hw_nvram_io_write_buffer(device *me,
+ const void *source,
+ int space,
+ unsigned_word addr,
+ unsigned nr_bytes,
+ cpu *processor,
+ unsigned_word cia)
+{
+ int i;
+ hw_nvram_device *nvram = (hw_nvram_device*)device_data(me);
+ for (i = 0; i < nr_bytes; i++) {
+ unsigned address = (addr + i) % nvram->sizeof_memory;
+ unsigned8 data = ((unsigned8*)source)[i];
+ if (address == nvram->addr_control
+ && (data & 0x80) == 0
+ && (nvram->memory[address] & 0x80) == 0x80)
+ hw_nvram_set_clock(nvram, processor);
+ else
+ hw_nvram_update_clock(nvram, processor);
+ nvram->memory[address] = data;
+ }
+ return nr_bytes;
+}
+
+static device_callbacks const hw_nvram_callbacks = {
+ { hw_nvram_init_address, },
+ { NULL, }, /* address */
+ { hw_nvram_io_read_buffer, hw_nvram_io_write_buffer }, /* IO */
+};
+
+const device_descriptor hw_nvram_device_descriptor[] = {
+ { "nvram", hw_nvram_create, &hw_nvram_callbacks },
+ { NULL },
+};
+
+#endif /* _HW_NVRAM_C_ */
diff --git a/gnu/dist/sim/ppc/hw_opic.c b/gnu/dist/sim/ppc/hw_opic.c
new file mode 100644
index 00000000000..c314347e5a5
--- /dev/null
+++ b/gnu/dist/sim/ppc/hw_opic.c
@@ -0,0 +1,1827 @@
+/* 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.
+
+ */
+
+
+#ifndef _HW_OPIC_C_
+#define _HW_OPIC_C_
+
+#include "device_table.h"
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#endif
+
+
+/* DEVICE
+
+
+ opic - Open Programmable Interrupt Controller (OpenPIC)
+
+
+ DESCRIPTION
+
+
+ This device implements the core of the OpenPIC interrupt controller
+ as described in the OpenPIC specification 1.2 and other related
+ documents.
+
+ The model includes:
+
+ o Up to 2048 external interrupt sources
+
+ o The four count down timers
+
+ o The four interprocessor multicast interrupts
+
+ o multiprocessor support
+
+ o Full tracing to assist help debugging
+
+ o Support for all variations of edge/level x high/low polarity.
+
+
+
+ PROPERTIES
+
+
+ reg = <address> <size> ... (required)
+
+ Determine where the device lives in the parents address space. The
+ first <<address>> <<size>> pair specifies the address of the
+ interrupt destination unit (which might contain an interrupt source
+ unit) while successive reg entries specify additional interrupt
+ source units.
+
+ Note that for an <<opic>> device attached to a <<pci>> bus, the
+ first <<reg>> entry may need to be ignored it will be the address
+ of the devices configuration registers.
+
+
+ interrupt-ranges = <int-number> <range> ... (required)
+
+ A list of pairs. Each pair corresponds to a block of interrupt
+ source units (the address of which being specified by the
+ corresponding reg tupple). <<int-number>> is the number of the
+ first interrupt in the block while <<range>> is the number of
+ interrupts in the block.
+
+
+ timer-frequency = <integer> (optional)
+
+ If present, specifies the default value of the timer frequency
+ reporting register. By default a value of 1 HZ is used. The value
+ is arbitrary, the timers are always updated once per machine cycle.
+
+
+ vendor-identification = <integer> (optional)
+
+ If present, specifies the value to be returned when the vendor
+ identification register is read.
+
+
+ EXAMPLES
+
+
+ See the test suite directory:
+
+ | psim-test/hw-opic
+
+
+ BUGS
+
+ For an OPIC controller attached to a PCI bus, it is not clear what
+ the value of the <<reg>> and <<interrupt-ranges>> properties should
+ be. In particular, the PCI firmware bindings require the first
+ value of the <<reg>> property to specify the devices configuration
+ address while the OpenPIC bindings require that same entry to
+ specify the address of the Interrupt Delivery Unit. This
+ implementation checks for and, if present, ignores any
+ configuration address (and its corresponding <<interrupt-ranges>>
+ entry).
+
+ The OpenPIC specification requires the controller to be fair when
+ distributing interrupts between processors. At present the
+ algorithm used isn't fair. It is biased towards processor zero.
+
+ The OpenPIC specification includes a 8259 pass through mode. This
+ is not supported.
+
+
+ REFERENCES
+
+
+ PowerPC Multiprocessor Interrupt Controller (MPIC), January 19,
+ 1996. Available from IBM.
+
+
+ The Open Programmable Interrupt Controller (PIC) Register Interface
+ Specification Revision 1.2. Issue Date: Opctober 1995. Available
+ somewhere on AMD's web page (http://www.amd.com/)
+
+
+ PowerPC Microprocessor Common Hardware Reference Platform (CHRP)
+ System bindings to: IEEE Std 1275-1994 Standard for Boot
+ (Initialization, Configuration) Firmware. Revision 1.2b (INTERIM
+ DRAFT). April 22, 1996. Available on the Open Firmware web site
+ http://playground.sun.com/p1275/.
+
+
+ */
+
+
+/* forward types */
+
+typedef struct _hw_opic_device hw_opic_device;
+
+
+/* bounds */
+
+enum {
+ max_nr_interrupt_sources = 2048,
+ max_nr_interrupt_destinations = 32,
+ max_nr_task_priorities = 16,
+};
+
+
+enum {
+ opic_alignment = 16,
+};
+
+
+/* global configuration register */
+
+enum {
+ gcr0_8259_bit = 0x20000000,
+ gcr0_reset_bit = 0x80000000,
+};
+
+
+/* offsets and sizes */
+
+enum {
+ idu_isu_base = 0x10000,
+ sizeof_isu_register_block = 32,
+ idu_per_processor_register_base = 0x20000,
+ sizeof_idu_per_processor_register_block = 0x1000,
+ idu_timer_base = 0x01100,
+ sizeof_timer_register_block = 0x00040,
+};
+
+
+/* Interrupt sources */
+
+enum {
+ isu_mask_bit = 0x80000000,
+ isu_active_bit = 0x40000000,
+ isu_multicast_bit = 0x20000000,
+ isu_positive_polarity_bit = 0x00800000,
+ isu_level_triggered_bit = 0x00400000,
+ isu_priority_shift = 16,
+ isu_vector_bits = 0x000000ff,
+};
+
+
+typedef struct _opic_interrupt_source {
+ unsigned is_masked; /* left in place */
+ unsigned is_multicast; /* left in place */
+ unsigned is_positive_polarity; /* left in place */
+ unsigned is_level_triggered; /* left in place */
+ unsigned priority;
+ unsigned vector;
+ /* misc */
+ int nr;
+ unsigned destination;
+ unsigned pending;
+ unsigned in_service;
+} opic_interrupt_source;
+
+
+/* interrupt destinations (normally processors) */
+
+typedef struct _opic_interrupt_destination {
+ int nr;
+ unsigned base_priority;
+ opic_interrupt_source *current_pending;
+ opic_interrupt_source *current_in_service;
+ unsigned bit;
+ int init_port;
+ int intr_port;
+} opic_interrupt_destination;
+
+
+/* address map descriptors */
+
+typedef struct _opic_isu_block { /* interrupt source unit block */
+ int space;
+ unsigned_word address;
+ unsigned size;
+ unsigned_cell int_number;
+ unsigned_cell range;
+ int reg;
+} opic_isu_block;
+
+
+typedef struct _opic_idu { /* interrupt delivery unit */
+ int reg;
+ int space;
+ unsigned_word address;
+ unsigned size;
+} opic_idu;
+
+typedef enum {
+ /* bad */
+ invalid_opic_register,
+ /* interrupt source */
+ interrupt_source_N_destination_register,
+ interrupt_source_N_vector_priority_register,
+ /* timers */
+ timer_N_destination_register,
+ timer_N_vector_priority_register,
+ timer_N_base_count_register,
+ timer_N_current_count_register,
+ timer_frequency_reporting_register,
+ /* inter-processor interrupts */
+ ipi_N_vector_priority_register,
+ ipi_N_dispatch_register,
+ /* global configuration */
+ spurious_vector_register,
+ processor_init_register,
+ vendor_identification_register,
+ global_configuration_register_N,
+ feature_reporting_register_N,
+ /* per processor */
+ end_of_interrupt_register_N,
+ interrupt_acknowledge_register_N,
+ current_task_priority_register_N,
+} opic_register;
+
+static const char *
+opic_register_name(opic_register type)
+{
+ switch (type) {
+ case invalid_opic_register: return "invalid_opic_register";
+ case interrupt_source_N_destination_register: return "interrupt_source_N_destination_register";
+ case interrupt_source_N_vector_priority_register: return "interrupt_source_N_vector_priority_register";
+ case timer_N_destination_register: return "timer_N_destination_register";
+ case timer_N_vector_priority_register: return "timer_N_vector_priority_register";
+ case timer_N_base_count_register: return "timer_N_base_count_register";
+ case timer_N_current_count_register: return "timer_N_current_count_register";
+ case timer_frequency_reporting_register: return "timer_frequency_reporting_register";
+ case ipi_N_vector_priority_register: return "ipi_N_vector_priority_register";
+ case ipi_N_dispatch_register: return "ipi_N_dispatch_register";
+ case spurious_vector_register: return "spurious_vector_register";
+ case processor_init_register: return "processor_init_register";
+ case vendor_identification_register: return "vendor_identification_register";
+ case global_configuration_register_N: return "global_configuration_register_N";
+ case feature_reporting_register_N: return "feature_reporting_register_N";
+ case end_of_interrupt_register_N: return "end_of_interrupt_register_N";
+ case interrupt_acknowledge_register_N: return "interrupt_acknowledge_register_N";
+ case current_task_priority_register_N: return "current_task_priority_register_N";
+ }
+ return NULL;
+}
+
+
+
+/* timers */
+
+typedef struct _opic_timer {
+ int nr;
+ device *me; /* find my way home */
+ hw_opic_device *opic; /* ditto */
+ unsigned base_count;
+ int inhibited;
+ signed64 count; /* *ONLY* if inhibited */
+ event_entry_tag timeout_event;
+ opic_interrupt_source *interrupt_source;
+} opic_timer;
+
+
+/* the OPIC */
+
+struct _hw_opic_device {
+
+ /* vendor id */
+ unsigned vendor_identification;
+
+ /* interrupt destinations - processors */
+ int nr_interrupt_destinations;
+ opic_interrupt_destination *interrupt_destination;
+ unsigned sizeof_interrupt_destination;
+
+ /* bogus interrupts */
+ int spurious_vector;
+
+ /* interrupt sources - external interrupt source units + extra internal ones */
+ int nr_interrupt_sources;
+ opic_interrupt_source *interrupt_source;
+ unsigned sizeof_interrupt_source;
+
+ /* external interrupts */
+ int nr_external_interrupts;
+ opic_interrupt_source *external_interrupt_source;
+
+ /* inter-processor-interrupts */
+ int nr_interprocessor_interrupts;
+ opic_interrupt_source *interprocessor_interrupt_source;
+
+ /* timers */
+ int nr_timer_interrupts;
+ opic_timer *timer;
+ unsigned sizeof_timer;
+ opic_interrupt_source *timer_interrupt_source;
+ unsigned timer_frequency;
+
+ /* init register */
+ unsigned32 init;
+
+ /* address maps */
+ opic_idu idu;
+ int nr_isu_blocks;
+ opic_isu_block *isu_block;
+};
+
+
+static void
+hw_opic_init_data(device *me)
+{
+ hw_opic_device *opic = (hw_opic_device*)device_data(me);
+ int isb;
+ int idu_reg;
+ int nr_isu_blocks;
+ int i;
+
+ /* determine the first valid reg property entry (there could be
+ leading reg entries with invalid (zero) size fields) and the
+ number of isu entries found in the reg property. */
+ idu_reg = 0;
+ nr_isu_blocks = 0;
+ while (1) {
+ reg_property_spec unit;
+ int attach_space;
+ unsigned_word attach_address;
+ unsigned attach_size;
+ if (!device_find_reg_array_property(me, "reg", idu_reg + nr_isu_blocks,
+ &unit))
+ break;
+ if (nr_isu_blocks > 0
+ || (device_address_to_attach_address(device_parent(me), &unit.address,
+ &attach_space, &attach_address,
+ me)
+ && device_size_to_attach_size(device_parent(me), &unit.size,
+ &attach_size,
+ me))) {
+ /* we count any thing once we've found one valid address/size pair */
+ nr_isu_blocks += 1;
+ }
+ else {
+ idu_reg += 1;
+ }
+ }
+
+ /* determine the number and location of the multiple interrupt
+ source units and the single interrupt delivery unit */
+ if (opic->isu_block == NULL) {
+ int reg_nr;
+ opic->nr_isu_blocks = nr_isu_blocks;
+ opic->isu_block = zalloc(sizeof(opic_isu_block) * opic->nr_isu_blocks);
+ isb = 0;
+ reg_nr = idu_reg;
+ while (isb < opic->nr_isu_blocks) {
+ reg_property_spec reg;
+ if (!device_find_reg_array_property(me, "reg", reg_nr, &reg))
+ device_error(me, "reg property missing entry number %d", reg_nr);
+ opic->isu_block[isb].reg = reg_nr;
+ if (!device_address_to_attach_address(device_parent(me), &reg.address,
+ &opic->isu_block[isb].space,
+ &opic->isu_block[isb].address,
+ me)
+ || !device_size_to_attach_size(device_parent(me), &reg.size,
+ &opic->isu_block[isb].size,
+ me)) {
+ device_error(me, "reg property entry %d invalid", reg_nr);
+ }
+ if (!device_find_integer_array_property(me, "interrupt-ranges",
+ reg_nr * 2,
+ &opic->isu_block[isb].int_number)
+ || !device_find_integer_array_property(me, "interrupt-ranges",
+ reg_nr * 2 + 1,
+ &opic->isu_block[isb].range))
+ device_error(me, "missing or invalid interrupt-ranges property entry %d", reg_nr);
+ /* first reg entry specifies the address of both the IDU and the
+ first set of ISU registers, adjust things accordingly */
+ if (reg_nr == idu_reg) {
+ opic->idu.reg = opic->isu_block[isb].reg;
+ opic->idu.space = opic->isu_block[isb].space;
+ opic->idu.address = opic->isu_block[isb].address;
+ opic->idu.size = opic->isu_block[isb].size;
+ opic->isu_block[isb].address += idu_isu_base;
+ opic->isu_block[isb].size = opic->isu_block[isb].range * (16 + 16);
+ }
+ /* was this a valid reg entry? */
+ if (opic->isu_block[isb].range == 0) {
+ opic->nr_isu_blocks -= 1;
+ }
+ else {
+ opic->nr_external_interrupts += opic->isu_block[isb].range;
+ isb++;
+ }
+ reg_nr++;
+ }
+ }
+ DTRACE(opic, ("interrupt source unit block - effective number of blocks %d\n",
+ (int)opic->nr_isu_blocks));
+
+
+ /* the number of other interrupts */
+ opic->nr_interprocessor_interrupts = 4;
+ opic->nr_timer_interrupts = 4;
+
+
+ /* create space for the interrupt source registers */
+ if (opic->interrupt_source != NULL) {
+ memset(opic->interrupt_source, 0, opic->sizeof_interrupt_source);
+ }
+ else {
+ opic->nr_interrupt_sources = (opic->nr_external_interrupts
+ + opic->nr_interprocessor_interrupts
+ + opic->nr_timer_interrupts);
+ if (opic->nr_interrupt_sources > max_nr_interrupt_sources)
+ device_error(me, "number of interrupt sources exceeded");
+ opic->sizeof_interrupt_source = (sizeof(opic_interrupt_source)
+ * opic->nr_interrupt_sources);
+ opic->interrupt_source = zalloc(opic->sizeof_interrupt_source);
+ opic->external_interrupt_source = opic->interrupt_source;
+ opic->interprocessor_interrupt_source = (opic->external_interrupt_source
+ + opic->nr_external_interrupts);
+ opic->timer_interrupt_source = (opic->interprocessor_interrupt_source
+ + opic->nr_interprocessor_interrupts);
+ }
+ for (i = 0; i < opic->nr_interrupt_sources; i++) {
+ opic_interrupt_source *source = &opic->interrupt_source[i];
+ source->nr = i;
+ source->is_masked = isu_mask_bit;
+ }
+ DTRACE(opic, ("interrupt sources - external %d, timer %d, ipi %d, total %d\n",
+ opic->nr_external_interrupts,
+ opic->nr_timer_interrupts,
+ opic->nr_interprocessor_interrupts,
+ opic->nr_interrupt_sources));
+
+
+ /* timers or interprocessor interrupts */
+ if (opic->timer != NULL)
+ memset(opic->timer, 0, opic->sizeof_timer);
+ else {
+ opic->nr_timer_interrupts = 4;
+ opic->sizeof_timer = sizeof(opic_timer) * opic->nr_timer_interrupts;
+ opic->timer = zalloc(opic->sizeof_timer);
+ }
+ for (i = 0; i < opic->nr_timer_interrupts; i++) {
+ opic_timer *timer = &opic->timer[i];
+ timer->nr = i;
+ timer->me = me;
+ timer->opic = opic;
+ timer->inhibited = 1;
+ timer->interrupt_source = &opic->timer_interrupt_source[i];
+ }
+ if (device_find_property(me, "timer-frequency"))
+ opic->timer_frequency = device_find_integer_property(me, "timer-frequency");
+ else
+ opic->timer_frequency = 1;
+
+
+ /* create space for the interrupt destination registers */
+ if (opic->interrupt_destination != NULL) {
+ memset(opic->interrupt_destination, 0, opic->sizeof_interrupt_destination);
+ }
+ else {
+ opic->nr_interrupt_destinations = tree_find_integer_property(me, "/openprom/options/smp");
+ opic->sizeof_interrupt_destination = (sizeof(opic_interrupt_destination)
+ * opic->nr_interrupt_destinations);
+ opic->interrupt_destination = zalloc(opic->sizeof_interrupt_destination);
+ if (opic->nr_interrupt_destinations > max_nr_interrupt_destinations)
+ device_error(me, "number of interrupt destinations exceeded");
+ }
+ for (i = 0; i < opic->nr_interrupt_destinations; i++) {
+ opic_interrupt_destination *dest = &opic->interrupt_destination[i];
+ dest->bit = (1 << i);
+ dest->nr = i;
+ dest->init_port = (device_interrupt_decode(me, "init0", output_port)
+ + i);
+ dest->intr_port = (device_interrupt_decode(me, "intr0", output_port)
+ + i);
+ dest->base_priority = max_nr_task_priorities - 1;
+ }
+ DTRACE(opic, ("interrupt destinations - total %d\n",
+ (int)opic->nr_interrupt_destinations));
+
+
+ /* verify and print out the ISU's */
+ for (isb = 0; isb < opic->nr_isu_blocks; isb++) {
+ unsigned correct_size;
+ if ((opic->isu_block[isb].address % opic_alignment) != 0)
+ device_error(me, "interrupt source unit %d address not aligned to %d byte boundary",
+ isb, opic_alignment);
+ correct_size = opic->isu_block[isb].range * sizeof_isu_register_block;
+ if (opic->isu_block[isb].size != correct_size)
+ device_error(me, "interrupt source unit %d (reg %d) has an incorrect size, should be 0x%x",
+ isb, opic->isu_block[isb].reg, correct_size);
+ DTRACE(opic, ("interrupt source unit block %ld - address %d:0x%lx, size 0x%lx, int-number %ld, range %ld\n",
+ (long)isb,
+ (int)opic->isu_block[isb].space,
+ (unsigned long)opic->isu_block[isb].address,
+ (unsigned long)opic->isu_block[isb].size,
+ (long)opic->isu_block[isb].int_number,
+ (long)opic->isu_block[isb].range));
+ }
+
+
+ /* verify and print out the IDU */
+ {
+ unsigned correct_size;
+ unsigned alternate_size;
+ if ((opic->idu.address % opic_alignment) != 0)
+ device_error(me, "interrupt delivery unit not aligned to %d byte boundary",
+ opic_alignment);
+ correct_size = (idu_per_processor_register_base
+ + (sizeof_idu_per_processor_register_block
+ * opic->nr_interrupt_destinations));
+ alternate_size = (idu_per_processor_register_base
+ + (sizeof_idu_per_processor_register_block
+ * max_nr_interrupt_destinations));
+ if (opic->idu.size != correct_size
+ && opic->idu.size != alternate_size)
+ device_error(me, "interrupt delivery unit has incorrect size, should be 0x%x or 0x%x",
+ correct_size, alternate_size);
+ DTRACE(opic, ("interrupt delivery unit - address %d:0x%lx, size 0x%lx\n",
+ (int)opic->idu.space,
+ (unsigned long)opic->idu.address,
+ (unsigned long)opic->idu.size));
+ }
+
+ /* initialize the init interrupts */
+ opic->init = 0;
+
+
+ /* vendor ident */
+ if (device_find_property(me, "vendor-identification") != NULL)
+ opic->vendor_identification = device_find_integer_property(me, "vendor-identification");
+ else
+ opic->vendor_identification = 0;
+
+ /* misc registers */
+ opic->spurious_vector = 0xff;
+
+}
+
+
+/* interrupt related actions */
+
+static void
+assert_interrupt(device *me,
+ hw_opic_device *opic,
+ opic_interrupt_destination *dest)
+{
+ ASSERT(dest >= opic->interrupt_destination);
+ ASSERT(dest < opic->interrupt_destination + opic->nr_interrupt_destinations);
+ DTRACE(opic, ("assert interrupt - intr port %d\n", dest->intr_port));
+ device_interrupt_event(me, dest->intr_port, 1, NULL, 0);
+}
+
+
+static void
+negate_interrupt(device *me,
+ hw_opic_device *opic,
+ opic_interrupt_destination *dest)
+{
+ ASSERT(dest >= opic->interrupt_destination);
+ ASSERT(dest < opic->interrupt_destination + opic->nr_interrupt_destinations);
+ DTRACE(opic, ("negate interrupt - intr port %d\n", dest->intr_port));
+ device_interrupt_event(me, dest->intr_port, 0, NULL, 0);
+}
+
+
+static int
+can_deliver(device *me,
+ opic_interrupt_source *source,
+ opic_interrupt_destination *dest)
+{
+ return (source != NULL && dest != NULL
+ && source->priority > dest->base_priority
+ && (dest->current_in_service == NULL
+ || source->priority > dest->current_in_service->priority));
+}
+
+
+static unsigned
+deliver_pending(device *me,
+ hw_opic_device *opic,
+ opic_interrupt_destination *dest)
+{
+ ASSERT(can_deliver(me, dest->current_pending, dest));
+ dest->current_in_service = dest->current_pending;
+ dest->current_in_service->in_service |= dest->bit;
+ if (!dest->current_pending->is_level_triggered) {
+ if (dest->current_pending->is_multicast)
+ dest->current_pending->pending &= ~dest->bit;
+ else
+ dest->current_pending->pending = 0;
+ }
+ dest->current_pending = NULL;
+ negate_interrupt(me, opic, dest);
+ return dest->current_in_service->vector;
+}
+
+
+typedef enum {
+ pending_interrupt,
+ in_service_interrupt,
+} interrupt_class;
+
+static opic_interrupt_source *
+find_interrupt_for_dest(device *me,
+ hw_opic_device *opic,
+ opic_interrupt_destination *dest,
+ interrupt_class class)
+{
+ int i;
+ opic_interrupt_source *pending = NULL;
+ for (i = 0; i < opic->nr_interrupt_sources; i++) {
+ opic_interrupt_source *src = &opic->interrupt_source[i];
+ /* is this a potential hit? */
+ switch (class) {
+ case in_service_interrupt:
+ if ((src->in_service & dest->bit) == 0)
+ continue;
+ break;
+ case pending_interrupt:
+ if ((src->pending & dest->bit) == 0)
+ continue;
+ break;
+ }
+ /* see if it is the highest priority */
+ if (pending == NULL)
+ pending = src;
+ else if (src->priority > pending->priority)
+ pending = src;
+ }
+ return pending;
+}
+
+
+static opic_interrupt_destination *
+find_lowest_dest(device *me,
+ hw_opic_device *opic,
+ opic_interrupt_source *src)
+{
+ int i;
+ opic_interrupt_destination *lowest = NULL;
+ for (i = 0; i < opic->nr_interrupt_destinations; i++) {
+ opic_interrupt_destination *dest = &opic->interrupt_destination[i];
+ if (src->destination & dest->bit) {
+ if (dest->base_priority < src->priority) {
+ if (lowest == NULL)
+ lowest = dest;
+ else if (lowest->base_priority > dest->base_priority)
+ lowest = dest;
+ else if (lowest->current_in_service != NULL
+ && dest->current_in_service == NULL)
+ lowest = dest; /* not doing anything */
+ else if (lowest->current_in_service != NULL
+ && dest->current_in_service != NULL
+ && (lowest->current_in_service->priority
+ > dest->current_in_service->priority))
+ lowest = dest; /* less urgent */
+ /* FIXME - need to be more fair */
+ }
+ }
+ }
+ return lowest;
+}
+
+
+static void
+handle_interrupt(device *me,
+ hw_opic_device *opic,
+ opic_interrupt_source *src,
+ int asserted)
+{
+ if (src->is_masked) {
+ DTRACE(opic, ("interrupt %d - ignore masked\n", src->nr));
+ }
+ else if (src->is_multicast) {
+ /* always try to deliver multicast interrupts - just easier */
+ int i;
+ ASSERT(!src->is_level_triggered);
+ ASSERT(src->is_positive_polarity);
+ ASSERT(asserted);
+ for (i = 0; i < opic->nr_interrupt_destinations; i++) {
+ opic_interrupt_destination *dest = &opic->interrupt_destination[i];
+ if (src->destination & dest->bit) {
+ if (src->pending & dest->bit) {
+ DTRACE(opic, ("interrupt %d - multicast still pending to %d\n",
+ src->nr, dest->nr));
+ }
+ else if (can_deliver(me, src, dest)) {
+ dest->current_pending = src;
+ src->pending |= dest->bit;
+ assert_interrupt(me, opic, dest);
+ DTRACE(opic, ("interrupt %d - multicast to %d\n",
+ src->nr, dest->nr));
+ }
+ else {
+ src->pending |= dest->bit;
+ DTRACE(opic, ("interrupt %d - multicast pending to %d\n",
+ src->nr, dest->nr));
+ }
+ }
+ }
+ }
+ else if (src->is_level_triggered
+ && src->is_positive_polarity
+ && !asserted) {
+ if (src->pending)
+ DTRACE(opic, ("interrupt %d - ignore withdrawn (active high)\n",
+ src->nr));
+ else
+ DTRACE(opic, ("interrupt %d - ignore low level (active high)\n",
+ src->nr));
+ ASSERT(!src->is_multicast);
+ src->pending = 0;
+ }
+ else if (src->is_level_triggered
+ && !src->is_positive_polarity
+ && asserted) {
+ if (src->pending)
+ DTRACE(opic, ("interrupt %d - ignore withdrawn (active low)\n",
+ src->nr));
+ else
+ DTRACE(opic, ("interrupt %d - ignore high level (active low)\n",
+ src->nr));
+
+ ASSERT(!src->is_multicast);
+ src->pending = 0;
+ }
+ else if (!src->is_level_triggered
+ && src->is_positive_polarity
+ && !asserted) {
+ DTRACE(opic, ("interrupt %d - ignore falling edge (positive edge trigered)\n",
+ src->nr));
+ }
+ else if (!src->is_level_triggered
+ && !src->is_positive_polarity
+ && asserted) {
+ DTRACE(opic, ("interrupt %d - ignore rising edge (negative edge trigered)\n",
+ src->nr));
+ }
+ else if (src->in_service != 0) {
+ /* leave the interrupt where it is */
+ ASSERT(!src->is_multicast);
+ ASSERT(src->pending == 0 || src->pending == src->in_service);
+ src->pending = src->in_service;
+ DTRACE(opic, ("interrupt %ld - ignore already in service to 0x%lx\n",
+ (long)src->nr, (long)src->in_service));
+ }
+ else if (src->pending != 0) {
+ DTRACE(opic, ("interrupt %ld - ignore still pending to 0x%lx\n",
+ (long)src->nr, (long)src->pending));
+ }
+ else {
+ /* delivery is needed */
+ opic_interrupt_destination *dest = find_lowest_dest(me, opic, src);
+ if (can_deliver(me, src, dest)) {
+ dest->current_pending = src;
+ src->pending = dest->bit;
+ DTRACE(opic, ("interrupt %d - delivered to %d\n", src->nr, dest->nr));
+ assert_interrupt(me, opic, dest);
+ }
+ else {
+ src->pending = src->destination; /* any can take this */
+ DTRACE(opic, ("interrupt %ld - pending to 0x%lx\n",
+ (long)src->nr, (long)src->pending));
+ }
+ }
+}
+
+static unsigned
+do_interrupt_acknowledge_register_N_read(device *me,
+ hw_opic_device *opic,
+ int dest_nr)
+{
+ opic_interrupt_destination *dest = &opic->interrupt_destination[dest_nr];
+ unsigned vector;
+
+ ASSERT(dest_nr >= 0 && dest_nr < opic->nr_interrupt_destinations);
+ ASSERT(dest_nr == dest->nr);
+
+ /* try the current pending */
+ if (can_deliver(me, dest->current_pending, dest)) {
+ ASSERT(dest->current_pending->pending & dest->bit);
+ vector = deliver_pending(me, opic, dest);
+ DTRACE(opic, ("interrupt ack %d - entering %d (pending) - vector %d (%d), priority %d\n",
+ dest->nr,
+ dest->current_in_service->nr,
+ dest->current_in_service->vector, vector,
+ dest->current_in_service->priority));
+ }
+ else {
+ /* try for something else */
+ dest->current_pending = find_interrupt_for_dest(me, opic, dest, pending_interrupt);
+ if (can_deliver(me, dest->current_pending, dest)) {
+ vector = deliver_pending(me, opic, dest);
+ DTRACE(opic, ("interrupt ack %d - entering %d (not pending) - vector %d (%d), priority %d\n",
+ dest->nr,
+ dest->current_in_service->nr,
+ dest->current_in_service->vector, vector,
+ dest->current_in_service->priority));
+ }
+ else {
+ dest->current_pending = NULL;
+ vector = opic->spurious_vector;
+ DTRACE(opic, ("interrupt ack %d - spurious interrupt %d\n",
+ dest->nr, vector));
+ }
+ }
+ return vector;
+}
+
+
+static void
+do_end_of_interrupt_register_N_write(device *me,
+ hw_opic_device *opic,
+ int dest_nr,
+ unsigned reg)
+{
+ opic_interrupt_destination *dest = &opic->interrupt_destination[dest_nr];
+
+ ASSERT(dest_nr >= 0 && dest_nr < opic->nr_interrupt_destinations);
+ ASSERT(dest_nr == dest->nr);
+
+ /* check the value written is zero */
+ if (reg != 0) {
+ DTRACE(opic, ("eoi %d - ignoring nonzero value\n", dest->nr));
+ }
+
+ /* user doing wierd things? */
+ if (dest->current_in_service == NULL) {
+ DTRACE(opic, ("eoi %d - strange, no current interrupt\n", dest->nr));
+ return;
+ }
+
+ /* an internal stuff up? */
+ if (!(dest->current_in_service->in_service & dest->bit)) {
+ device_error(me, "eoi %d - current interrupt not in service", dest->nr);
+ }
+
+ /* find what was probably the previous in service interrupt */
+ dest->current_in_service->in_service &= ~dest->bit;
+ DTRACE(opic, ("eoi %d - ending %d - priority %d, vector %d\n",
+ dest->nr,
+ dest->current_in_service->nr,
+ dest->current_in_service->priority,
+ dest->current_in_service->vector));
+ dest->current_in_service = find_interrupt_for_dest(me, opic, dest, in_service_interrupt);
+ if (dest->current_in_service != NULL)
+ DTRACE(opic, ("eoi %d - resuming %d - priority %d, vector %d\n",
+ dest->nr,
+ dest->current_in_service->nr,
+ dest->current_in_service->priority,
+ dest->current_in_service->vector));
+ else
+ DTRACE(opic, ("eoi %d - resuming none\n", dest->nr));
+
+ /* check to see if that shouldn't be interrupted */
+ dest->current_pending = find_interrupt_for_dest(me, opic, dest, pending_interrupt);
+ if (can_deliver(me, dest->current_pending, dest)) {
+ ASSERT(dest->current_pending->pending & dest->bit);
+ assert_interrupt(me, opic, dest);
+ }
+ else {
+ dest->current_pending = NULL;
+ }
+}
+
+
+static void
+decode_opic_address(device *me,
+ hw_opic_device *opic,
+ int space,
+ unsigned_word address,
+ unsigned nr_bytes,
+ opic_register *type,
+ int *index)
+{
+ int isb = 0;
+
+ /* is the size valid? */
+ if (nr_bytes != 4) {
+ *type = invalid_opic_register;
+ *index = -1;
+ return;
+ }
+
+ /* try for a per-processor register within the interrupt delivery
+ unit */
+ if (space == opic->idu.space
+ && address >= (opic->idu.address + idu_per_processor_register_base)
+ && address < (opic->idu.address + idu_per_processor_register_base
+ + (sizeof_idu_per_processor_register_block
+ * opic->nr_interrupt_destinations))) {
+ unsigned_word block_offset = (address
+ - opic->idu.address
+ - idu_per_processor_register_base);
+ unsigned_word offset = block_offset % sizeof_idu_per_processor_register_block;
+ *index = block_offset / sizeof_idu_per_processor_register_block;
+ switch (offset) {
+ case 0x040:
+ *type = ipi_N_dispatch_register;
+ *index = 0;
+ break;
+ case 0x050:
+ *type = ipi_N_dispatch_register;
+ *index = 1;
+ break;
+ case 0x060:
+ *type = ipi_N_dispatch_register;
+ *index = 2;
+ break;
+ case 0x070:
+ *type = ipi_N_dispatch_register;
+ *index = 3;
+ break;
+ case 0x080:
+ *type = current_task_priority_register_N;
+ break;
+ case 0x0a0:
+ *type = interrupt_acknowledge_register_N;
+ break;
+ case 0x0b0:
+ *type = end_of_interrupt_register_N;
+ break;
+ default:
+ *type = invalid_opic_register;
+ break;
+ }
+ DTRACE(opic, ("per-processor register %d:0x%lx - %s[%d]\n",
+ space, (unsigned long)address,
+ opic_register_name(*type),
+ *index));
+ return;
+ }
+
+ /* try for an interrupt source unit */
+ for (isb = 0; isb < opic->nr_isu_blocks; isb++) {
+ if (opic->isu_block[isb].space == space
+ && address >= opic->isu_block[isb].address
+ && address < (opic->isu_block[isb].address + opic->isu_block[isb].size)) {
+ unsigned_word block_offset = address - opic->isu_block[isb].address;
+ unsigned_word offset = block_offset % sizeof_isu_register_block;
+ *index = (opic->isu_block[isb].int_number
+ + (block_offset / sizeof_isu_register_block));
+ switch (offset) {
+ case 0x00:
+ *type = interrupt_source_N_vector_priority_register;
+ break;
+ case 0x10:
+ *type = interrupt_source_N_destination_register;
+ break;
+ default:
+ *type = invalid_opic_register;
+ break;
+ }
+ DTRACE(opic, ("isu register %d:0x%lx - %s[%d]\n",
+ space, (unsigned long)address,
+ opic_register_name(*type),
+ *index));
+ return;
+ }
+ }
+
+ /* try for a timer */
+ if (space == opic->idu.space
+ && address >= (opic->idu.address + idu_timer_base)
+ && address < (opic->idu.address + idu_timer_base
+ + opic->nr_timer_interrupts * sizeof_timer_register_block)) {
+ unsigned_word offset = address % sizeof_timer_register_block;
+ *index = ((address - opic->idu.address - idu_timer_base)
+ / sizeof_timer_register_block);
+ switch (offset) {
+ case 0x00:
+ *type = timer_N_current_count_register;
+ break;
+ case 0x10:
+ *type = timer_N_base_count_register;
+ break;
+ case 0x20:
+ *type = timer_N_vector_priority_register;
+ break;
+ case 0x30:
+ *type = timer_N_destination_register;
+ break;
+ default:
+ *type = invalid_opic_register;
+ break;
+ }
+ DTRACE(opic, ("timer register %d:0x%lx - %s[%d]\n",
+ space, (unsigned long)address,
+ opic_register_name(*type),
+ *index));
+ return;
+ }
+
+ /* finally some other misc global register */
+ if (space == opic->idu.space
+ && address >= opic->idu.address
+ && address < opic->idu.address + opic->idu.size) {
+ unsigned_word block_offset = address - opic->idu.address;
+ switch (block_offset) {
+ case 0x010f0:
+ *type = timer_frequency_reporting_register;
+ *index = -1;
+ break;
+ case 0x010e0:
+ *type = spurious_vector_register;
+ *index = -1;
+ break;
+ case 0x010d0:
+ case 0x010c0:
+ case 0x010b0:
+ case 0x010a0:
+ *type = ipi_N_vector_priority_register;
+ *index = (block_offset - 0x010a0) / 16;
+ break;
+ case 0x01090:
+ *type = processor_init_register;
+ *index = -1;
+ break;
+ case 0x01080:
+ *type = vendor_identification_register;
+ *index = -1;
+ break;
+ case 0x01020:
+ *type = global_configuration_register_N;
+ *index = 0;
+ break;
+ case 0x01000:
+ *type = feature_reporting_register_N;
+ *index = 0;
+ break;
+ default:
+ *type = invalid_opic_register;
+ *index = -1;
+ break;
+ }
+ DTRACE(opic, ("global register %d:0x%lx - %s[%d]\n",
+ space, (unsigned long)address,
+ opic_register_name(*type),
+ *index));
+ return;
+ }
+
+ /* nothing matched */
+ *type = invalid_opic_register;
+ DTRACE(opic, ("invalid register %d:0x%lx\n",
+ space, (unsigned long)address));
+ return;
+}
+
+
+/* Processor init register:
+
+ The bits in this register (one per processor) are directly wired to
+ output "init" interrupt ports. */
+
+static unsigned
+do_processor_init_register_read(device *me,
+ hw_opic_device *opic)
+{
+ unsigned reg = opic->init;
+ DTRACE(opic, ("processor init register - read 0x%lx\n",
+ (long)reg));
+ return reg;
+}
+
+static void
+do_processor_init_register_write(device *me,
+ hw_opic_device *opic,
+ unsigned reg)
+{
+ int i;
+ for (i = 0; i < opic->nr_interrupt_destinations; i++) {
+ opic_interrupt_destination *dest = &opic->interrupt_destination[i];
+ if ((reg & dest->bit) != (opic->init & dest->bit)) {
+ if (reg & dest->bit) {
+ DTRACE(opic, ("processor init register - write 0x%lx - asserting init%d\n",
+ (long)reg, i));
+ opic->init |= dest->bit;
+ device_interrupt_event(me, dest->init_port, 1, NULL, 0);
+ }
+ else {
+ DTRACE(opic, ("processor init register - write 0x%lx - negating init%d\n",
+ (long)reg, i));
+ opic->init &= ~dest->bit;
+ device_interrupt_event(me, dest->init_port, 0, NULL, 0);
+ }
+ }
+ }
+}
+
+
+
+/* Interrupt Source Vector/Priority Register: */
+
+static unsigned
+read_vector_priority_register(device *me,
+ hw_opic_device *opic,
+ opic_interrupt_source *interrupt,
+ const char *reg_name,
+ int reg_index)
+{
+ unsigned reg;
+ reg = 0;
+ reg |= interrupt->is_masked;
+ reg |= (interrupt->in_service || interrupt->pending
+ ? isu_active_bit : 0); /* active */
+ reg |= interrupt->is_multicast;
+ reg |= interrupt->is_positive_polarity;
+ reg |= interrupt->is_level_triggered; /* sense? */
+ reg |= interrupt->priority << isu_priority_shift;
+ reg |= interrupt->vector;
+ DTRACE(opic, ("%s %d vector/priority register - read 0x%lx\n",
+ reg_name, reg_index, (unsigned long)reg));
+ return reg;
+}
+
+static unsigned
+do_interrupt_source_N_vector_priority_register_read(device *me,
+ hw_opic_device *opic,
+ int index)
+{
+ unsigned reg;
+ ASSERT(index < opic->nr_external_interrupts);
+ reg = read_vector_priority_register(me, opic,
+ &opic->interrupt_source[index],
+ "interrupt source", index);
+ return reg;
+}
+
+static void
+write_vector_priority_register(device *me,
+ hw_opic_device *opic,
+ opic_interrupt_source *interrupt,
+ unsigned reg,
+ const char *reg_name,
+ int reg_index)
+{
+ interrupt->is_masked = (reg & isu_mask_bit);
+ interrupt->is_multicast = (reg & isu_multicast_bit);
+ interrupt->is_positive_polarity = (reg & isu_positive_polarity_bit);
+ interrupt->is_level_triggered = (reg & isu_level_triggered_bit);
+ interrupt->priority = ((reg >> isu_priority_shift)
+ % max_nr_task_priorities);
+ interrupt->vector = (reg & isu_vector_bits);
+ DTRACE(opic, ("%s %d vector/priority register - write 0x%lx - %s%s%s-polarity, %s-triggered, priority %ld vector %ld\n",
+ reg_name,
+ reg_index,
+ (unsigned long)reg,
+ interrupt->is_masked ? "masked, " : "",
+ interrupt->is_multicast ? "multicast, " : "",
+ interrupt->is_positive_polarity ? "positive" : "negative",
+ interrupt->is_level_triggered ? "level" : "edge",
+ (long)interrupt->priority,
+ (long)interrupt->vector));
+}
+
+static void
+do_interrupt_source_N_vector_priority_register_write(device *me,
+ hw_opic_device *opic,
+ int index,
+ unsigned reg)
+{
+ ASSERT(index < opic->nr_external_interrupts);
+ reg &= ~isu_multicast_bit; /* disable multicast */
+ write_vector_priority_register(me, opic,
+ &opic->interrupt_source[index],
+ reg, "interrupt source", index);
+}
+
+
+
+/* Interrupt Source Destination Register: */
+
+static unsigned
+read_destination_register(device *me,
+ hw_opic_device *opic,
+ opic_interrupt_source *interrupt,
+ const char *reg_name,
+ int reg_index)
+{
+ unsigned long reg;
+ reg = interrupt->destination;
+ DTRACE(opic, ("%s %d destination register - read 0x%lx\n",
+ reg_name, reg_index, reg));
+ return reg;
+}
+
+static unsigned
+do_interrupt_source_N_destination_register_read(device *me,
+ hw_opic_device *opic,
+ int index)
+{
+ unsigned reg;
+ ASSERT(index < opic->nr_external_interrupts);
+ reg = read_destination_register(me, opic, &opic->external_interrupt_source[index],
+ "interrupt source", index);
+ return reg;
+}
+
+static void
+write_destination_register(device *me,
+ hw_opic_device *opic,
+ opic_interrupt_source *interrupt,
+ unsigned reg,
+ const char *reg_name,
+ int reg_index)
+{
+ reg &= (1 << opic->nr_interrupt_destinations) - 1; /* mask out invalid */
+ DTRACE(opic, ("%s %d destination register - write 0x%x\n",
+ reg_name, reg_index, reg));
+ interrupt->destination = reg;
+}
+
+static void
+do_interrupt_source_N_destination_register_write(device *me,
+ hw_opic_device *opic,
+ int index,
+ unsigned reg)
+{
+ ASSERT(index < opic->nr_external_interrupts);
+ write_destination_register(me, opic, &opic->external_interrupt_source[index],
+ reg, "interrupt source", index);
+}
+
+
+
+/* Spurious vector register: */
+
+static unsigned
+do_spurious_vector_register_read(device *me,
+ hw_opic_device *opic)
+{
+ unsigned long reg = opic->spurious_vector;
+ DTRACE(opic, ("spurious vector register - read 0x%lx\n", reg));
+ return reg;
+}
+
+static void
+do_spurious_vector_register_write(device *me,
+ hw_opic_device *opic,
+ unsigned reg)
+{
+ reg &= 0xff; /* mask off invalid */
+ DTRACE(opic, ("spurious vector register - write 0x%x\n", reg));
+ opic->spurious_vector = reg;
+}
+
+
+
+/* current task priority register: */
+
+static unsigned
+do_current_task_priority_register_N_read(device *me,
+ hw_opic_device *opic,
+ int index)
+{
+ opic_interrupt_destination *interrupt_destination = &opic->interrupt_destination[index];
+ unsigned reg;
+ ASSERT(index >= 0 && index < opic->nr_interrupt_destinations);
+ reg = interrupt_destination->base_priority;
+ DTRACE(opic, ("current task priority register %d - read 0x%x\n", index, reg));
+ return reg;
+}
+
+static void
+do_current_task_priority_register_N_write(device *me,
+ hw_opic_device *opic,
+ int index,
+ unsigned reg)
+{
+ opic_interrupt_destination *interrupt_destination = &opic->interrupt_destination[index];
+ ASSERT(index >= 0 && index < opic->nr_interrupt_destinations);
+ reg %= max_nr_task_priorities;
+ DTRACE(opic, ("current task priority register %d - write 0x%x\n", index, reg));
+ interrupt_destination->base_priority = reg;
+}
+
+
+
+/* Timer Frequency Reporting Register: */
+
+static unsigned
+do_timer_frequency_reporting_register_read(device *me,
+ hw_opic_device *opic)
+{
+ unsigned reg;
+ reg = opic->timer_frequency;
+ DTRACE(opic, ("timer frequency reporting register - read 0x%x\n", reg));
+ return reg;
+}
+
+static void
+do_timer_frequency_reporting_register_write(device *me,
+ hw_opic_device *opic,
+ unsigned reg)
+{
+ DTRACE(opic, ("timer frequency reporting register - write 0x%x\n", reg));
+ opic->timer_frequency = reg;
+}
+
+
+/* timer registers: */
+
+static unsigned
+do_timer_N_current_count_register_read(device *me,
+ hw_opic_device *opic,
+ int index)
+{
+ opic_timer *timer = &opic->timer[index];
+ unsigned reg;
+ ASSERT(index >= 0 && index < opic->nr_timer_interrupts);
+ if (timer->inhibited)
+ reg = timer->count; /* stalled value */
+ else
+ reg = timer->count - device_event_queue_time(me); /* time remaining */
+ DTRACE(opic, ("timer %d current count register - read 0x%x\n", index, reg));
+ return reg;
+}
+
+
+static unsigned
+do_timer_N_base_count_register_read(device *me,
+ hw_opic_device *opic,
+ int index)
+{
+ opic_timer *timer = &opic->timer[index];
+ unsigned reg;
+ ASSERT(index >= 0 && index < opic->nr_timer_interrupts);
+ reg = timer->base_count;
+ DTRACE(opic, ("timer %d base count register - read 0x%x\n", index, reg));
+ return reg;
+}
+
+
+static void
+timer_event(void *data)
+{
+ opic_timer *timer = data;
+ device *me = timer->me;
+ if (timer->inhibited)
+ device_error(timer->me, "internal-error - timer event occured when timer %d inhibited",
+ timer->nr);
+ handle_interrupt(timer->me, timer->opic, timer->interrupt_source, 1);
+ timer->timeout_event = device_event_queue_schedule(me, timer->base_count,
+ timer_event, timer);
+ DTRACE(opic, ("timer %d - interrupt at %ld, next at %d\n",
+ timer->nr, (long)device_event_queue_time(me), timer->base_count));
+}
+
+
+static void
+do_timer_N_base_count_register_write(device *me,
+ hw_opic_device *opic,
+ int index,
+ unsigned reg)
+{
+ opic_timer *timer = &opic->timer[index];
+ int inhibit;
+ ASSERT(index >= 0 && index < opic->nr_timer_interrupts);
+ inhibit = reg & 0x80000000;
+ if (timer->inhibited && !inhibit) {
+ timer->inhibited = 0;
+ if (timer->timeout_event != NULL)
+ device_event_queue_deschedule(me, timer->timeout_event);
+ timer->count = device_event_queue_time(me) + reg;
+ timer->base_count = reg;
+ timer->timeout_event = device_event_queue_schedule(me, timer->base_count,
+ timer_event, (void*)timer);
+ DTRACE(opic, ("timer %d base count register - write 0x%x - timer started\n",
+ index, reg));
+ }
+ else if (!timer->inhibited && inhibit) {
+ if (timer->timeout_event != NULL)
+ device_event_queue_deschedule(me, timer->timeout_event);
+ timer->count = timer->count - device_event_queue_time(me);
+ timer->inhibited = 1;
+ timer->base_count = reg;
+ DTRACE(opic, ("timer %d base count register - write 0x%x - timer stopped\n",
+ index, reg));
+ }
+ else {
+ ASSERT((timer->inhibited && inhibit) || (!timer->inhibited && !inhibit));
+ DTRACE(opic, ("timer %d base count register - write 0x%x\n", index, reg));
+ timer->base_count = reg;
+ }
+}
+
+
+static unsigned
+do_timer_N_vector_priority_register_read(device *me,
+ hw_opic_device *opic,
+ int index)
+{
+ unsigned reg;
+ ASSERT(index >= 0 && index < opic->nr_timer_interrupts);
+ reg = read_vector_priority_register(me, opic,
+ &opic->timer_interrupt_source[index],
+ "timer", index);
+ return reg;
+}
+
+static void
+do_timer_N_vector_priority_register_write(device *me,
+ hw_opic_device *opic,
+ int index,
+ unsigned reg)
+{
+ ASSERT(index >= 0 && index < opic->nr_timer_interrupts);
+ reg &= ~isu_level_triggered_bit; /* force edge trigger */
+ reg |= isu_positive_polarity_bit; /* force rising (positive) edge */
+ reg |= isu_multicast_bit; /* force multicast */
+ write_vector_priority_register(me, opic,
+ &opic->timer_interrupt_source[index],
+ reg, "timer", index);
+}
+
+
+static unsigned
+do_timer_N_destination_register_read(device *me,
+ hw_opic_device *opic,
+ int index)
+{
+ unsigned reg;
+ ASSERT(index >= 0 && index < opic->nr_timer_interrupts);
+ reg = read_destination_register(me, opic, &opic->timer_interrupt_source[index],
+ "timer", index);
+ return reg;
+}
+
+static void
+do_timer_N_destination_register_write(device *me,
+ hw_opic_device *opic,
+ int index,
+ unsigned reg)
+{
+ ASSERT(index >= 0 && index < opic->nr_timer_interrupts);
+ write_destination_register(me, opic, &opic->timer_interrupt_source[index],
+ reg, "timer", index);
+}
+
+
+/* IPI registers */
+
+static unsigned
+do_ipi_N_vector_priority_register_read(device *me,
+ hw_opic_device *opic,
+ int index)
+{
+ unsigned reg;
+ ASSERT(index >= 0 && index < opic->nr_interprocessor_interrupts);
+ reg = read_vector_priority_register(me, opic,
+ &opic->interprocessor_interrupt_source[index],
+ "ipi", index);
+ return reg;
+}
+
+static void
+do_ipi_N_vector_priority_register_write(device *me,
+ hw_opic_device *opic,
+ int index,
+ unsigned reg)
+{
+ ASSERT(index >= 0 && index < opic->nr_interprocessor_interrupts);
+ reg &= ~isu_level_triggered_bit; /* force edge trigger */
+ reg |= isu_positive_polarity_bit; /* force rising (positive) edge */
+ reg |= isu_multicast_bit; /* force a multicast source */
+ write_vector_priority_register(me, opic,
+ &opic->interprocessor_interrupt_source[index],
+ reg, "ipi", index);
+}
+
+static void
+do_ipi_N_dispatch_register_write(device *me,
+ hw_opic_device *opic,
+ int index,
+ unsigned reg)
+{
+ opic_interrupt_source *source = &opic->interprocessor_interrupt_source[index];
+ ASSERT(index >= 0 && index < opic->nr_interprocessor_interrupts);
+ DTRACE(opic, ("ipi %d interrupt dispatch register - write 0x%x\n", index, reg));
+ source->destination = reg;
+ handle_interrupt(me, opic, source, 1);
+}
+
+
+/* vendor and other global registers */
+
+static unsigned
+do_vendor_identification_register_read(device *me,
+ hw_opic_device *opic)
+{
+ unsigned reg;
+ reg = opic->vendor_identification;
+ DTRACE(opic, ("vendor identification register - read 0x%x\n", reg));
+ return reg;
+}
+
+static unsigned
+do_feature_reporting_register_N_read(device *me,
+ hw_opic_device *opic,
+ int index)
+{
+ unsigned reg = 0;
+ ASSERT(index == 0);
+ switch (index) {
+ case 0:
+ reg |= (opic->nr_external_interrupts << 16);
+ reg |= (opic->nr_interrupt_destinations << 8);
+ reg |= (2/*version 1.2*/);
+ break;
+ }
+ DTRACE(opic, ("feature reporting register %d - read 0x%x\n", index, reg));
+ return reg;
+}
+
+static unsigned
+do_global_configuration_register_N_read(device *me,
+ hw_opic_device *opic,
+ int index)
+{
+ unsigned reg = 0;
+ ASSERT(index == 0);
+ switch (index) {
+ case 0:
+ reg |= gcr0_8259_bit; /* hardwire 8259 disabled */
+ break;
+ }
+ DTRACE(opic, ("global configuration register %d - read 0x%x\n", index, reg));
+ return reg;
+}
+
+static void
+do_global_configuration_register_N_write(device *me,
+ hw_opic_device *opic,
+ int index,
+ unsigned reg)
+{
+ ASSERT(index == 0);
+ if (reg & gcr0_reset_bit) {
+ DTRACE(opic, ("global configuration register %d - write 0x%x - reseting opic\n", index, reg));
+ hw_opic_init_data(me);
+ }
+ if (!(reg & gcr0_8259_bit)) {
+ DTRACE(opic, ("global configuration register %d - write 0x%x - ignoring 8259 enable\n", index, reg));
+ }
+}
+
+
+
+/* register read-write */
+
+static unsigned
+hw_opic_io_read_buffer(device *me,
+ void *dest,
+ int space,
+ unsigned_word addr,
+ unsigned nr_bytes,
+ cpu *processor,
+ unsigned_word cia)
+{
+ hw_opic_device *opic = (hw_opic_device*)device_data(me);
+ opic_register type;
+ int index;
+ decode_opic_address(me, opic, space, addr, nr_bytes, &type, &index);
+ if (type == invalid_opic_register) {
+ device_error(me, "invalid opic read access to %d:0x%lx (%d bytes)",
+ space, (unsigned long)addr, nr_bytes);
+ }
+ else {
+ unsigned reg;
+ switch (type) {
+ case processor_init_register:
+ reg = do_processor_init_register_read(me, opic);
+ break;
+ case interrupt_source_N_vector_priority_register:
+ reg = do_interrupt_source_N_vector_priority_register_read(me, opic, index);
+ break;
+ case interrupt_source_N_destination_register:
+ reg = do_interrupt_source_N_destination_register_read(me, opic, index);
+ break;
+ case interrupt_acknowledge_register_N:
+ reg = do_interrupt_acknowledge_register_N_read(me, opic, index);
+ break;
+ case spurious_vector_register:
+ reg = do_spurious_vector_register_read(me, opic);
+ break;
+ case current_task_priority_register_N:
+ reg = do_current_task_priority_register_N_read(me, opic, index);
+ break;
+ case timer_frequency_reporting_register:
+ reg = do_timer_frequency_reporting_register_read(me, opic);
+ break;
+ case timer_N_current_count_register:
+ reg = do_timer_N_current_count_register_read(me, opic, index);
+ break;
+ case timer_N_base_count_register:
+ reg = do_timer_N_base_count_register_read(me, opic, index);
+ break;
+ case timer_N_vector_priority_register:
+ reg = do_timer_N_vector_priority_register_read(me, opic, index);
+ break;
+ case timer_N_destination_register:
+ reg = do_timer_N_destination_register_read(me, opic, index);
+ break;
+ case ipi_N_vector_priority_register:
+ reg = do_ipi_N_vector_priority_register_read(me, opic, index);
+ break;
+ case feature_reporting_register_N:
+ reg = do_feature_reporting_register_N_read(me, opic, index);
+ break;
+ case global_configuration_register_N:
+ reg = do_global_configuration_register_N_read(me, opic, index);
+ break;
+ case vendor_identification_register:
+ reg = do_vendor_identification_register_read(me, opic);
+ break;
+ default:
+ reg = 0;
+ device_error(me, "unimplemented read of register %s[%d]",
+ opic_register_name(type), index);
+ }
+ *(unsigned_4*)dest = H2LE_4(reg);
+ }
+ return nr_bytes;
+}
+
+
+static unsigned
+hw_opic_io_write_buffer(device *me,
+ const void *source,
+ int space,
+ unsigned_word addr,
+ unsigned nr_bytes,
+ cpu *processor,
+ unsigned_word cia)
+{
+ hw_opic_device *opic = (hw_opic_device*)device_data(me);
+ opic_register type;
+ int index;
+ decode_opic_address(me, opic, space, addr, nr_bytes, &type, &index);
+ if (type == invalid_opic_register) {
+ device_error(me, "invalid opic write access to %d:0x%lx (%d bytes)",
+ space, (unsigned long)addr, nr_bytes);
+ }
+ else {
+ unsigned reg = LE2H_4(*(unsigned_4*)source);
+ switch (type) {
+ case processor_init_register:
+ do_processor_init_register_write(me, opic, reg);
+ break;
+ case interrupt_source_N_vector_priority_register:
+ do_interrupt_source_N_vector_priority_register_write(me, opic, index, reg);
+ break;
+ case interrupt_source_N_destination_register:
+ do_interrupt_source_N_destination_register_write(me, opic, index, reg);
+ break;
+ case end_of_interrupt_register_N:
+ do_end_of_interrupt_register_N_write(me, opic, index, reg);
+ break;
+ case spurious_vector_register:
+ do_spurious_vector_register_write(me, opic, reg);
+ break;
+ case current_task_priority_register_N:
+ do_current_task_priority_register_N_write(me, opic, index, reg);
+ break;
+ case timer_frequency_reporting_register:
+ do_timer_frequency_reporting_register_write(me, opic, reg);
+ break;
+ case timer_N_base_count_register:
+ do_timer_N_base_count_register_write(me, opic, index, reg);
+ break;
+ case timer_N_vector_priority_register:
+ do_timer_N_vector_priority_register_write(me, opic, index, reg);
+ break;
+ case timer_N_destination_register:
+ do_timer_N_destination_register_write(me, opic, index, reg);
+ break;
+ case ipi_N_dispatch_register:
+ do_ipi_N_dispatch_register_write(me, opic, index, reg);
+ break;
+ case ipi_N_vector_priority_register:
+ do_ipi_N_vector_priority_register_write(me, opic, index, reg);
+ break;
+ case global_configuration_register_N:
+ do_global_configuration_register_N_write(me, opic, index, reg);
+ break;
+ default:
+ device_error(me, "unimplemented write to register %s[%d]",
+ opic_register_name(type), index);
+ }
+ }
+ return nr_bytes;
+}
+
+
+static void
+hw_opic_interrupt_event(device *me,
+ int my_port,
+ device *source,
+ int source_port,
+ int level,
+ cpu *processor,
+ unsigned_word cia)
+{
+ hw_opic_device *opic = (hw_opic_device*)device_data(me);
+
+ int isb;
+ int src_nr = 0;
+
+ /* find the corresponding internal input port */
+ for (isb = 0; isb < opic->nr_isu_blocks; isb++) {
+ if (my_port >= opic->isu_block[isb].int_number
+ && my_port < opic->isu_block[isb].int_number + opic->isu_block[isb].range) {
+ src_nr += my_port - opic->isu_block[isb].int_number;
+ break;
+ }
+ else
+ src_nr += opic->isu_block[isb].range;
+ }
+ if (isb == opic->nr_isu_blocks)
+ device_error(me, "interrupt %d out of range", my_port);
+ DTRACE(opic, ("external-interrupt %d, internal %d, level %d\n",
+ my_port, src_nr, level));
+
+ /* pass it on */
+ ASSERT(src_nr >= 0 && src_nr < opic->nr_external_interrupts);
+ handle_interrupt(me, opic, &opic->external_interrupt_source[src_nr], level);
+}
+
+
+static const device_interrupt_port_descriptor hw_opic_interrupt_ports[] = {
+ { "irq", 0, max_nr_interrupt_sources, input_port, },
+ { "intr", 0, max_nr_interrupt_destinations, output_port, },
+ { "init", max_nr_interrupt_destinations, max_nr_interrupt_destinations, output_port, },
+ { NULL }
+};
+
+
+static device_callbacks const hw_opic_callbacks = {
+ { generic_device_init_address,
+ hw_opic_init_data },
+ { NULL, }, /* address */
+ { hw_opic_io_read_buffer,
+ hw_opic_io_write_buffer }, /* IO */
+ { NULL, }, /* DMA */
+ { hw_opic_interrupt_event, NULL, hw_opic_interrupt_ports }, /* interrupt */
+ { NULL, }, /* unit */
+ NULL, /* instance */
+};
+
+static void *
+hw_opic_create(const char *name,
+ const device_unit *unit_address,
+ const char *args)
+{
+ hw_opic_device *opic = ZALLOC(hw_opic_device);
+ return opic;
+}
+
+
+
+const device_descriptor hw_opic_device_descriptor[] = {
+ { "opic", hw_opic_create, &hw_opic_callbacks },
+ { NULL },
+};
+
+#endif /* _HW_OPIC_C_ */
diff --git a/gnu/dist/sim/ppc/hw_pal.c b/gnu/dist/sim/ppc/hw_pal.c
new file mode 100644
index 00000000000..a4256b94f3a
--- /dev/null
+++ b/gnu/dist/sim/ppc/hw_pal.c
@@ -0,0 +1,366 @@
+/* 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.
+
+ */
+
+
+#ifndef _HW_PAL_C_
+#define _HW_PAL_C_
+
+#ifndef STATIC_INLINE_HW_PAL
+#define STATIC_INLINE_HW_PAL STATIC_INLINE
+#endif
+
+#include "device_table.h"
+
+#include "cpu.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. Except for the interrupt
+ level register, each of the below is 8 bytes in size and must be
+ accessed using correct alignment. For 16 and 32 bit accesses the
+ bytes not directed to the register are ignored:
+
+ |0 reset register (write)
+ |4 processor id register (read)
+ |8 interrupt port (write)
+ |9 interrupt level (write)
+ |12 processor count register (read)
+ |16 tty input fifo register (read)
+ |20 tty input status register (read)
+ |24 tty output fifo register (write)
+ |28 tty output status register (read)
+
+ Reset register (write) halts the simulator exiting with the
+ value written.
+
+ Processor id register (read) returns the processor number (0
+ .. N-1) of the processor performing the read.
+
+ The interrupt registers should be accessed as a pair (using a 16 or
+ 32 bit store). The low byte specifies the interrupt port while the
+ high byte specifies the level to drive that port at. 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 to
+ be asserted.
+
+ Processor count register (read) returns the total number of
+ processors active in the current simulation.
+
+ TTY input fifo register (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.
+
+ Similarly, the TTY output fifo register (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.
+
+
+ PROPERTIES
+
+
+ reg = <address> <size> (required)
+
+ Specify the address (within the parent bus) that this device is to
+ live.
+
+
+ */
+
+
+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_address_mask = 0x1f,
+};
+
+
+typedef struct _hw_pal_console_buffer {
+ char buffer;
+ int status;
+} hw_pal_console_buffer;
+
+typedef struct _hw_pal_device {
+ hw_pal_console_buffer input;
+ hw_pal_console_buffer output;
+ device *disk;
+} hw_pal_device;
+
+
+/* check the console for an available character */
+static void
+scan_hw_pal(hw_pal_device *hw_pal)
+{
+ char c;
+ int count;
+ count = sim_io_read_stdin(&c, sizeof(c));
+ switch (count) {
+ case sim_io_not_ready:
+ case sim_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(hw_pal_device *hw_pal,
+ char val)
+{
+ sim_io_write_stdout(&val, 1);
+ hw_pal->output.buffer = val;
+ hw_pal->output.status = 1;
+}
+
+
+static unsigned
+hw_pal_io_read_buffer_callback(device *me,
+ void *dest,
+ int space,
+ unsigned_word addr,
+ unsigned nr_bytes,
+ cpu *processor,
+ unsigned_word cia)
+{
+ hw_pal_device *hw_pal = (hw_pal_device*)device_data(me);
+ unsigned_1 val;
+ switch (addr & hw_pal_address_mask) {
+ case hw_pal_cpu_nr_register:
+ val = cpu_nr(processor);
+ DTRACE(pal, ("read - cpu-nr %d\n", val));
+ break;
+ case hw_pal_nr_cpu_register:
+ val = tree_find_integer_property(me, "/openprom/options/smp");
+ DTRACE(pal, ("read - nr-cpu %d\n", val));
+ break;
+ case hw_pal_read_fifo:
+ val = hw_pal->input.buffer;
+ DTRACE(pal, ("read - input-fifo %d\n", val));
+ break;
+ case hw_pal_read_status:
+ scan_hw_pal(hw_pal);
+ val = hw_pal->input.status;
+ DTRACE(pal, ("read - input-status %d\n", val));
+ break;
+ case hw_pal_write_fifo:
+ val = hw_pal->output.buffer;
+ DTRACE(pal, ("read - output-fifo %d\n", val));
+ break;
+ case hw_pal_write_status:
+ val = hw_pal->output.status;
+ DTRACE(pal, ("read - output-status %d\n", val));
+ break;
+ default:
+ val = 0;
+ DTRACE(pal, ("read - ???\n"));
+ }
+ memset(dest, 0, nr_bytes);
+ *(unsigned_1*)dest = val;
+ return nr_bytes;
+}
+
+
+static unsigned
+hw_pal_io_write_buffer_callback(device *me,
+ const void *source,
+ int space,
+ unsigned_word addr,
+ unsigned nr_bytes,
+ cpu *processor,
+ unsigned_word cia)
+{
+ hw_pal_device *hw_pal = (hw_pal_device*)device_data(me);
+ unsigned_1 *byte = (unsigned_1*)source;
+
+ switch (addr & hw_pal_address_mask) {
+ case hw_pal_reset_register:
+ cpu_halt(processor, cia, was_exited, byte[0]);
+ break;
+ case hw_pal_int_register:
+ device_interrupt_event(me,
+ byte[0], /*port*/
+ (nr_bytes > 1 ? byte[1] : 0), /* val */
+ processor, cia);
+ break;
+ case hw_pal_read_fifo:
+ hw_pal->input.buffer = byte[0];
+ DTRACE(pal, ("write - input-fifo %d\n", byte[0]));
+ break;
+ case hw_pal_read_status:
+ hw_pal->input.status = byte[0];
+ DTRACE(pal, ("write - input-status %d\n", byte[0]));
+ break;
+ case hw_pal_write_fifo:
+ write_hw_pal(hw_pal, byte[0]);
+ DTRACE(pal, ("write - output-fifo %d\n", byte[0]));
+ break;
+ case hw_pal_write_status:
+ hw_pal->output.status = byte[0];
+ DTRACE(pal, ("write - output-status %d\n", byte[0]));
+ break;
+ }
+ return nr_bytes;
+}
+
+
+/* instances of the hw_pal device */
+
+static void
+hw_pal_instance_delete_callback(device_instance *instance)
+{
+ /* nothing to delete, the hw_pal is attached to the device */
+ return;
+}
+
+static int
+hw_pal_instance_read_callback(device_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);
+}
+
+static int
+hw_pal_instance_write_callback(device_instance *instance,
+ const void *buf,
+ unsigned_word len)
+{
+ int i;
+ const char *chp = buf;
+ hw_pal_device *hw_pal = device_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;
+}
+
+static const device_instance_callbacks hw_pal_instance_callbacks = {
+ hw_pal_instance_delete_callback,
+ hw_pal_instance_read_callback,
+ hw_pal_instance_write_callback,
+};
+
+static device_instance *
+hw_pal_create_instance(device *me,
+ const char *path,
+ const char *args)
+{
+ return device_create_instance_from(me, NULL,
+ device_data(me),
+ path, args,
+ &hw_pal_instance_callbacks);
+}
+
+static const device_interrupt_port_descriptor hw_pal_interrupt_ports[] = {
+ { "int", 0, MAX_NR_PROCESSORS },
+ { NULL }
+};
+
+
+static void
+hw_pal_attach_address(device *me,
+ attach_type attach,
+ int space,
+ unsigned_word addr,
+ unsigned nr_bytes,
+ access_type access,
+ device *client)
+{
+ hw_pal_device *pal = (hw_pal_device*)device_data(me);
+ pal->disk = client;
+}
+
+
+static device_callbacks const hw_pal_callbacks = {
+ { generic_device_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_device_unit_decode,
+ generic_device_unit_encode,
+ generic_device_address_to_attach_address,
+ generic_device_size_to_attach_size },
+ hw_pal_create_instance,
+};
+
+
+static void *
+hw_pal_create(const char *name,
+ const device_unit *unit_address,
+ const char *args)
+{
+ /* create the descriptor */
+ hw_pal_device *hw_pal = ZALLOC(hw_pal_device);
+ hw_pal->output.status = 1;
+ hw_pal->output.buffer = '\0';
+ hw_pal->input.status = 0;
+ hw_pal->input.buffer = '\0';
+ return hw_pal;
+}
+
+
+const device_descriptor hw_pal_device_descriptor[] = {
+ { "pal", hw_pal_create, &hw_pal_callbacks },
+ { NULL },
+};
+
+#endif /* _HW_PAL_C_ */
diff --git a/gnu/dist/sim/ppc/hw_phb.c b/gnu/dist/sim/ppc/hw_phb.c
new file mode 100644
index 00000000000..0071f59faf3
--- /dev/null
+++ b/gnu/dist/sim/ppc/hw_phb.c
@@ -0,0 +1,1068 @@
+/* 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.
+
+ */
+
+
+#ifndef _HW_PHB_C_
+#define _HW_PHB_C_
+
+#include "device_table.h"
+
+#include "hw_phb.h"
+
+#include "corefile.h"
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#include <ctype.h>
+
+
+/* DEVICE
+
+
+ phb - PCI Host Bridge
+
+
+ DESCRIPTION
+
+
+ PHB implements a model of the PCI-host bridge described in the PPCP
+ document.
+
+ For bridge devices, Open Firmware specifies that the <<ranges>>
+ property be used to specify the mapping of address spaces between a
+ bridges parent and child busses. This PHB model configures itsself
+ according to the information specified in its ranges property. The
+ <<ranges>> property is described in detail in the Open Firmware
+ documentation.
+
+ For DMA transfers, any access to a PCI address space which falls
+ outside of the mapped memory space is assumed to be a transfer
+ intended for the parent bus.
+
+
+ PROPERTIES
+
+
+ ranges = <my-phys-addr> <parent-phys-addr> <my-size> ... (required)
+
+ Define a number of mappings from the parent bus to one of this
+ devices PCI busses. The exact format of the <<parent-phys-addr>>
+ is parent bus dependant. The format of <<my-phys-addr>> is
+ described in the Open Firmware PCI bindings document (note that the
+ address must be non-relocatable).
+
+
+ #address-cells = 3 (required)
+
+ Number of cells used by an Open Firmware PCI address. This
+ property must be defined before specifying the <<ranges>> property.
+
+
+ #size-cells = 2 (required)
+
+ Number of cells used by an Open Firmware PCI size. This property
+ must be defined before specifying the <<ranges>> property.
+
+
+ EXAMPLES
+
+
+ Enable tracing:
+
+ | $ psim \
+ | -t phb-device \
+
+
+ Since device tree entries that are specified on the command line
+ are added before most of the device tree has been built it is often
+ necessary to explictly add certain device properties and thus
+ ensure they are already present in the device tree. For the
+ <<phb>> one such property is parent busses <<#address-cells>>.
+
+ | -o '/#address-cells 1' \
+
+
+ Create the PHB remembering to include the cell size properties:
+
+ | -o '/phb@0x80000000/#address-cells 3' \
+ | -o '/phb@0x80000000/#size-cells 2' \
+
+
+ Specify that the memory address range <<0x80000000>> to
+ <<0x8fffffff>> should map directly onto the PCI memory address
+ space while the processor address range <<0xc0000000>> to
+ <<0xc000ffff>> should map onto the PCI I/O address range starting
+ at location zero:
+
+ | -o '/phb@0x80000000/ranges \
+ | nm0,0,0,80000000 0x80000000 0x10000000 \
+ | ni0,0,0,0 0xc0000000 0x10000' \
+
+
+ Insert a 4k <<nvram>> into slot zero of the PCI bus. Have it
+ directly accessible in both the I/O (address <<0x100>>) and memory
+ (address 0x80001000) spaces:
+
+ | -o '/phb@0x80000000/nvram@0/assigned-addresses \
+ | nm0,0,10,80001000 4096 \
+ | ni0,0,14,100 4096'
+ | -o '/phb@0x80000000/nvram@0/reg \
+ | 0 0 \
+ | i0,0,14,0 4096'
+ | -o '/phb@0x80000000/nvram@0/alternate-reg \
+ | 0 0 \
+ | m0,0,10,0 4096'
+
+ The <<assigned-address>> property corresponding to what (if it were
+ implemented) be found in the config base registers while the
+ <<reg>> and <<alternative-reg>> properties indicating the location
+ of registers within each address space.
+
+ Of the possible addresses, only the non-relocatable versions are
+ used when attaching the device to the bus.
+
+
+ BUGS
+
+
+ The implementation of the PCI configuration space is left as an
+ exercise for the reader. Such a restriction should only impact on
+ systems wanting to dynamically configure devices on the PCI bus.
+
+ The <<CHRP>> document specfies additional (optional) functionality
+ of the primary PHB. The implementation of such functionality is
+ left as an exercise for the reader.
+
+ The Open Firmware PCI bus bindings document (rev 1.6 and 2.0) is
+ unclear on the value of the "ss" bits for a 64bit memory address.
+ The correct value, as used by this module, is 0b11.
+
+ The Open Firmware PCI bus bindings document (rev 1.6) suggests that
+ the register field of non-relocatable PCI address should be zero.
+ Unfortunatly, PCI addresses specified in the <<assigned-addresses>>
+ property must be both non-relocatable and have non-zero register
+ fields.
+
+ The unit-decode method is not inserting a bus number into any
+ address that it decodes. Instead the bus-number is left as zero.
+
+ Support for aliased memory and I/O addresses is left as an exercise
+ for the reader.
+
+ Support for interrupt-ack and special cycles are left as an
+ exercise for the reader. One issue to consider when attempting
+ this exercise is how to specify the address of the int-ack and
+ special cycle register. Hint: <</8259-interrupt-ackowledge>> is
+ the wrong answer.
+
+ Children of this node can only use the client callback interface
+ when attaching themselves to the <<phb>>.
+
+
+ REFERENCES
+
+
+ http://playground.sun.com/1275/home.html#OFDbusPCI
+
+
+ */
+
+
+typedef struct _phb_space {
+ core *map;
+ core_map *readable;
+ core_map *writeable;
+ unsigned_word parent_base;
+ int parent_space;
+ unsigned_word my_base;
+ int my_space;
+ unsigned size;
+ const char *name;
+} phb_space;
+
+typedef struct _hw_phb_device {
+ phb_space space[nr_hw_phb_spaces];
+} hw_phb_device;
+
+
+static const char *
+hw_phb_decode_name(hw_phb_decode level)
+{
+ switch (level) {
+ case hw_phb_normal_decode: return "normal";
+ case hw_phb_subtractive_decode: return "subtractive";
+ case hw_phb_master_abort_decode: return "master-abort";
+ default: return "invalid decode";
+ }
+}
+
+
+static void
+hw_phb_init_address(device *me)
+{
+ hw_phb_device *phb = device_data(me);
+
+ /* check some basic properties */
+ if (device_nr_address_cells(me) != 3)
+ device_error(me, "incorrect #address-cells");
+ if (device_nr_size_cells(me) != 2)
+ device_error(me, "incorrect #size-cells");
+
+ /* (re) initialize each PCI space */
+ {
+ hw_phb_spaces space_nr;
+ for (space_nr = 0; space_nr < nr_hw_phb_spaces; space_nr++) {
+ phb_space *pci_space = &phb->space[space_nr];
+ core_init(pci_space->map);
+ pci_space->size = 0;
+ }
+ }
+
+ /* decode each of the ranges properties entering the information
+ into the space table */
+ {
+ range_property_spec range;
+ int ranges_entry;
+
+ for (ranges_entry = 0;
+ device_find_range_array_property(me, "ranges", ranges_entry,
+ &range);
+ ranges_entry++) {
+ int my_attach_space;
+ unsigned_word my_attach_address;
+ int parent_attach_space;
+ unsigned_word parent_attach_address;
+ unsigned size;
+ phb_space *pci_space;
+ /* convert the addresses into something meaningful */
+ device_address_to_attach_address(me, &range.child_address,
+ &my_attach_space,
+ &my_attach_address,
+ me);
+ device_address_to_attach_address(device_parent(me),
+ &range.parent_address,
+ &parent_attach_space,
+ &parent_attach_address,
+ me);
+ device_size_to_attach_size(me, &range.size, &size, me);
+ if (my_attach_space < 0 || my_attach_space >= nr_hw_phb_spaces)
+ device_error(me, "ranges property contains an invalid address space");
+ pci_space = &phb->space[my_attach_space];
+ if (pci_space->size != 0)
+ device_error(me, "ranges property contains duplicate mappings for %s address space",
+ pci_space->name);
+ pci_space->parent_base = parent_attach_address;
+ pci_space->parent_space = parent_attach_space;
+ pci_space->my_base = my_attach_address;
+ pci_space->my_space = my_attach_space;
+ pci_space->size = size;
+ device_attach_address(device_parent(me),
+ attach_callback,
+ parent_attach_space, parent_attach_address, size,
+ access_read_write_exec,
+ me);
+ DTRACE(phb, ("map %d:0x%lx to %s:0x%lx (0x%lx bytes)\n",
+ (int)parent_attach_space,
+ (unsigned long)parent_attach_address,
+ pci_space->name,
+ (unsigned long)my_attach_address,
+ (unsigned long)size));
+ }
+
+ if (ranges_entry == 0) {
+ device_error(me, "Missing or empty ranges property");
+ }
+
+ }
+
+}
+
+static void
+hw_phb_attach_address(device *me,
+ attach_type type,
+ int space,
+ unsigned_word addr,
+ unsigned nr_bytes,
+ access_type access,
+ device *client) /*callback/default*/
+{
+ hw_phb_device *phb = device_data(me);
+ phb_space *pci_space;
+ /* sanity checks */
+ if (space < 0 || space >= nr_hw_phb_spaces)
+ device_error(me, "attach space (%d) specified by %s invalid",
+ space, device_path(client));
+ pci_space = &phb->space[space];
+ if (addr + nr_bytes > pci_space->my_base + pci_space->size
+ || addr < pci_space->my_base)
+ device_error(me, "attach addr (0x%lx) specified by %s outside of bus address range",
+ (unsigned long)addr, device_path(client));
+ if (type != hw_phb_normal_decode
+ && type != hw_phb_subtractive_decode)
+ device_error(me, "attach type (%d) specified by %s invalid",
+ type, device_path(client));
+ /* attach it to the relevent bus */
+ DTRACE(phb, ("attach %s - %s %s:0x%lx (0x%lx bytes)\n",
+ device_path(client),
+ hw_phb_decode_name(type),
+ pci_space->name,
+ (unsigned long)addr,
+ (unsigned long)nr_bytes));
+ core_attach(pci_space->map,
+ type,
+ space,
+ access,
+ addr,
+ nr_bytes,
+ client);
+}
+
+
+/* Extract/set various fields from a PCI unit address.
+
+ Note: only the least significant 32 bits of each cell is used.
+
+ Note: for PPC MSB is 0 while for PCI it is 31. */
+
+
+/* relocatable bit n */
+
+static unsigned
+extract_n(const device_unit *address)
+{
+ return EXTRACTED32(address->cells[0], 0, 0);
+}
+
+static void
+set_n(device_unit *address)
+{
+ BLIT32(address->cells[0], 0, 1);
+}
+
+
+/* prefetchable bit p */
+
+static unsigned
+extract_p(const device_unit *address)
+{
+ ASSERT(address->nr_cells == 3);
+ return EXTRACTED32(address->cells[0], 1, 1);
+}
+
+static void
+set_p(device_unit *address)
+{
+ BLIT32(address->cells[0], 1, 1);
+}
+
+
+/* aliased bit t */
+
+static unsigned
+extract_t(const device_unit *address)
+{
+ ASSERT(address->nr_cells == 3);
+ return EXTRACTED32(address->cells[0], 2, 2);
+}
+
+static void
+set_t(device_unit *address)
+{
+ BLIT32(address->cells[0], 2, 1);
+}
+
+
+/* space code ss */
+
+typedef enum {
+ ss_config_code = 0,
+ ss_io_code = 1,
+ ss_32bit_memory_code = 2,
+ ss_64bit_memory_code = 3,
+} ss_type;
+
+static ss_type
+extract_ss(const device_unit *address)
+{
+ ASSERT(address->nr_cells == 3);
+ return EXTRACTED32(address->cells[0], 6, 7);
+}
+
+static void
+set_ss(device_unit *address, ss_type val)
+{
+ MBLIT32(address->cells[0], 6, 7, val);
+}
+
+
+/* bus number bbbbbbbb */
+
+#if 0
+static unsigned
+extract_bbbbbbbb(const device_unit *address)
+{
+ ASSERT(address->nr_cells == 3);
+ return EXTRACTED32(address->cells[0], 8, 15);
+}
+#endif
+
+#if 0
+static void
+set_bbbbbbbb(device_unit *address, unsigned val)
+{
+ MBLIT32(address->cells[0], 8, 15, val);
+}
+#endif
+
+
+/* device number ddddd */
+
+static unsigned
+extract_ddddd(const device_unit *address)
+{
+ ASSERT(address->nr_cells == 3);
+ return EXTRACTED32(address->cells[0], 16, 20);
+}
+
+static void
+set_ddddd(device_unit *address, unsigned val)
+{
+ MBLIT32(address->cells[0], 16, 20, val);
+}
+
+
+/* function number fff */
+
+static unsigned
+extract_fff(const device_unit *address)
+{
+ ASSERT(address->nr_cells == 3);
+ return EXTRACTED32(address->cells[0], 21, 23);
+}
+
+static void
+set_fff(device_unit *address, unsigned val)
+{
+ MBLIT32(address->cells[0], 21, 23, val);
+}
+
+
+/* register number rrrrrrrr */
+
+static unsigned
+extract_rrrrrrrr(const device_unit *address)
+{
+ ASSERT(address->nr_cells == 3);
+ return EXTRACTED32(address->cells[0], 24, 31);
+}
+
+static void
+set_rrrrrrrr(device_unit *address, unsigned val)
+{
+ MBLIT32(address->cells[0], 24, 31, val);
+}
+
+
+/* MSW of 64bit address hh..hh */
+
+static unsigned
+extract_hh_hh(const device_unit *address)
+{
+ ASSERT(address->nr_cells == 3);
+ return address->cells[1];
+}
+
+static void
+set_hh_hh(device_unit *address, unsigned val)
+{
+ address->cells[2] = val;
+}
+
+
+/* LSW of 64bit address ll..ll */
+
+static unsigned
+extract_ll_ll(const device_unit *address)
+{
+ ASSERT(address->nr_cells == 3);
+ return address->cells[2];
+}
+
+static void
+set_ll_ll(device_unit *address, unsigned val)
+{
+ address->cells[2] = val;
+}
+
+
+/* Convert PCI textual bus address into a device unit */
+
+static int
+hw_phb_unit_decode(device *me,
+ const char *unit,
+ device_unit *address)
+{
+ char *end = NULL;
+ const char *chp = unit;
+ unsigned long val;
+
+ if (device_nr_address_cells(me) != 3)
+ device_error(me, "PCI bus should have #address-cells == 3");
+ memset(address, 0, sizeof(*address));
+
+ if (unit == NULL)
+ return 0;
+
+ address->nr_cells = 3;
+
+ if (isxdigit(*chp)) {
+ set_ss(address, ss_config_code);
+ }
+ else {
+
+ /* non-relocatable? */
+ if (*chp == 'n') {
+ set_n(address);
+ chp++;
+ }
+
+ /* address-space? */
+ if (*chp == 'i') {
+ set_ss(address, ss_io_code);
+ chp++;
+ }
+ else if (*chp == 'm') {
+ set_ss(address, ss_32bit_memory_code);
+ chp++;
+ }
+ else if (*chp == 'x') {
+ set_ss(address, ss_64bit_memory_code);
+ chp++;
+ }
+ else
+ device_error(me, "Problem parsing PCI address %s", unit);
+
+ /* possible alias */
+ if (*chp == 't') {
+ if (extract_ss(address) == ss_64bit_memory_code)
+ device_error(me, "Invalid alias bit in PCI address %s", unit);
+ set_t(address);
+ chp++;
+ }
+
+ /* possible p */
+ if (*chp == 'p') {
+ if (extract_ss(address) != ss_32bit_memory_code)
+ device_error(me, "Invalid prefetchable bit (p) in PCI address %s",
+ unit);
+ set_p(address);
+ chp++;
+ }
+
+ }
+
+ /* required DD */
+ if (!isxdigit(*chp))
+ device_error(me, "Missing device number in PCI address %s", unit);
+ val = strtoul(chp, &end, 16);
+ if (chp == end)
+ device_error(me, "Problem parsing device number in PCI address %s", unit);
+ if ((val & 0x1f) != val)
+ device_error(me, "Device number (0x%lx) out of range (0..0x1f) in PCI address %s",
+ val, unit);
+ set_ddddd(address, val);
+ chp = end;
+
+ /* For config space, the F is optional */
+ if (extract_ss(address) == ss_config_code
+ && (isspace(*chp) || *chp == '\0'))
+ return chp - unit;
+
+ /* function number F */
+ if (*chp != ',')
+ device_error(me, "Missing function number in PCI address %s", unit);
+ chp++;
+ val = strtoul(chp, &end, 10);
+ if (chp == end)
+ device_error(me, "Problem parsing function number in PCI address %s",
+ unit);
+ if ((val & 7) != val)
+ device_error(me, "Function number (%ld) out of range (0..7) in PCI address %s",
+ (long)val, unit);
+ set_fff(address, val);
+ chp = end;
+
+ /* for config space, must be end */
+ if (extract_ss(address) == ss_config_code) {
+ if (!isspace(*chp) && *chp != '\0')
+ device_error(me, "Problem parsing PCI config address %s",
+ unit);
+ return chp - unit;
+ }
+
+ /* register number RR */
+ if (*chp != ',')
+ device_error(me, "Missing register number in PCI address %s", unit);
+ chp++;
+ val = strtoul(chp, &end, 16);
+ if (chp == end)
+ device_error(me, "Problem parsing register number in PCI address %s",
+ unit);
+ switch (extract_ss(address)) {
+ case ss_io_code:
+#if 0
+ if (extract_n(address) && val != 0)
+ device_error(me, "non-relocatable I/O register must be zero in PCI address %s", unit);
+ else if (!extract_n(address)
+ && val != 0x10 && val != 0x14 && val != 0x18
+ && val != 0x1c && val != 0x20 && val != 0x24)
+ device_error(me, "I/O register invalid in PCI address %s", unit);
+#endif
+ break;
+ case ss_32bit_memory_code:
+#if 0
+ if (extract_n(address) && val != 0)
+ device_error(me, "non-relocatable memory register must be zero in PCI address %s", unit);
+ else if (!extract_n(address)
+ && val != 0x10 && val != 0x14 && val != 0x18
+ && val != 0x1c && val != 0x20 && val != 0x24 && val != 0x30)
+ device_error(me, "I/O register (0x%lx) invalid in PCI address %s",
+ val, unit);
+#endif
+ break;
+ case ss_64bit_memory_code:
+ if (extract_n(address) && val != 0)
+ device_error(me, "non-relocatable 32bit memory register must be zero in PCI address %s", unit);
+ else if (!extract_n(address)
+ && val != 0x10 && val != 0x18 && val != 0x20)
+ device_error(me, "Register number (0x%lx) invalid in 64bit PCI address %s",
+ val, unit);
+ case ss_config_code:
+ device_error(me, "internal error");
+ }
+ if ((val & 0xff) != val)
+ device_error(me, "Register number (0x%lx) out of range (0..0xff) in PCI address %s",
+ val, unit);
+ set_rrrrrrrr(address, val);
+ chp = end;
+
+ /* address */
+ if (*chp != ',')
+ device_error(me, "Missing address in PCI address %s", unit);
+ chp++;
+ switch (extract_ss(address)) {
+ case ss_io_code:
+ case ss_32bit_memory_code:
+ val = strtoul(chp, &end, 16);
+ if (chp == end)
+ device_error(me, "Problem parsing address in PCI address %s", unit);
+ switch (extract_ss(address)) {
+ case ss_io_code:
+ if (extract_n(address) && extract_t(address)
+ && (val & 1024) != val)
+ device_error(me, "10bit aliased non-relocatable address (0x%lx) out of range in PCI address %s",
+ val, unit);
+ if (!extract_n(address) && extract_t(address)
+ && (val & 0xffff) != val)
+ device_error(me, "64k relocatable address (0x%lx) out of range in PCI address %s",
+ val, unit);
+ break;
+ case ss_32bit_memory_code:
+ if (extract_t(address) && (val & 0xfffff) != val)
+ device_error(me, "1mb memory address (0x%lx) out of range in PCI address %s",
+ val, unit);
+ if (!extract_t(address) && (val & 0xffffffff) != val)
+ device_error(me, "32bit memory address (0x%lx) out of range in PCI address %s",
+ val, unit);
+ break;
+ case ss_64bit_memory_code:
+ case ss_config_code:
+ device_error(me, "internal error");
+ }
+ set_ll_ll(address, val);
+ chp = end;
+ break;
+ case ss_64bit_memory_code:
+ device_error(me, "64bit addresses unimplemented");
+ set_hh_hh(address, val);
+ set_ll_ll(address, val);
+ break;
+ case ss_config_code:
+ device_error(me, "internal error");
+ break;
+ }
+
+ /* finished? */
+ if (!isspace(*chp) && *chp != '\0')
+ device_error(me, "Problem parsing PCI address %s", unit);
+
+ return chp - unit;
+}
+
+
+/* Convert PCI device unit into its corresponding textual
+ representation */
+
+static int
+hw_phb_unit_encode(device *me,
+ const device_unit *unit_address,
+ char *buf,
+ int sizeof_buf)
+{
+ if (unit_address->nr_cells != 3)
+ device_error(me, "Incorrect number of cells in PCI unit address");
+ if (device_nr_address_cells(me) != 3)
+ device_error(me, "PCI bus should have #address-cells == 3");
+ if (extract_ss(unit_address) == ss_config_code
+ && extract_fff(unit_address) == 0
+ && extract_rrrrrrrr(unit_address) == 0
+ && extract_hh_hh(unit_address) == 0
+ && extract_ll_ll(unit_address) == 0) {
+ /* DD - Configuration Space address */
+ sprintf(buf, "%x",
+ extract_ddddd(unit_address));
+ }
+ else if (extract_ss(unit_address) == ss_config_code
+ && extract_fff(unit_address) != 0
+ && extract_rrrrrrrr(unit_address) == 0
+ && extract_hh_hh(unit_address) == 0
+ && extract_ll_ll(unit_address) == 0) {
+ /* DD,F - Configuration Space */
+ sprintf(buf, "%x,%d",
+ extract_ddddd(unit_address),
+ extract_fff(unit_address));
+ }
+ else if (extract_ss(unit_address) == ss_io_code
+ && extract_hh_hh(unit_address) == 0) {
+ /* [n]i[t]DD,F,RR,NNNNNNNN - 32bit I/O space */
+ sprintf(buf, "%si%s%x,%d,%x,%x",
+ extract_n(unit_address) ? "n" : "",
+ extract_t(unit_address) ? "t" : "",
+ extract_ddddd(unit_address),
+ extract_fff(unit_address),
+ extract_rrrrrrrr(unit_address),
+ extract_ll_ll(unit_address));
+ }
+ else if (extract_ss(unit_address) == ss_32bit_memory_code
+ && extract_hh_hh(unit_address) == 0) {
+ /* [n]m[t][p]DD,F,RR,NNNNNNNN - 32bit memory space */
+ sprintf(buf, "%sm%s%s%x,%d,%x,%x",
+ extract_n(unit_address) ? "n" : "",
+ extract_t(unit_address) ? "t" : "",
+ extract_p(unit_address) ? "p" : "",
+ extract_ddddd(unit_address),
+ extract_fff(unit_address),
+ extract_rrrrrrrr(unit_address),
+ extract_ll_ll(unit_address));
+ }
+ else if (extract_ss(unit_address) == ss_32bit_memory_code) {
+ /* [n]x[p]DD,F,RR,NNNNNNNNNNNNNNNN - 64bit memory space */
+ sprintf(buf, "%sx%s%x,%d,%x,%x%08x",
+ extract_n(unit_address) ? "n" : "",
+ extract_p(unit_address) ? "p" : "",
+ extract_ddddd(unit_address),
+ extract_fff(unit_address),
+ extract_rrrrrrrr(unit_address),
+ extract_hh_hh(unit_address),
+ extract_ll_ll(unit_address));
+ }
+ else {
+ device_error(me, "Invalid PCI unit address 0x%08lx 0x%08lx 0x%08lx",
+ (unsigned long)unit_address->cells[0],
+ (unsigned long)unit_address->cells[1],
+ (unsigned long)unit_address->cells[2]);
+ }
+ if (strlen(buf) > sizeof_buf)
+ error("buffer overflow");
+ return strlen(buf);
+}
+
+
+static int
+hw_phb_address_to_attach_address(device *me,
+ const device_unit *address,
+ int *attach_space,
+ unsigned_word *attach_address,
+ device *client)
+{
+ if (address->nr_cells != 3)
+ device_error(me, "attach address has incorrect number of cells");
+ if (address->cells[1] != 0)
+ device_error(me, "64bit attach address unsupported");
+
+ /* directly decode the address/space */
+ *attach_address = address->cells[2];
+ switch (extract_ss(address)) {
+ case ss_config_code:
+ *attach_space = hw_phb_config_space;
+ break;
+ case ss_io_code:
+ *attach_space = hw_phb_io_space;
+ break;
+ case ss_32bit_memory_code:
+ case ss_64bit_memory_code:
+ *attach_space = hw_phb_memory_space;
+ break;
+ }
+
+ /* if non-relocatable finished */
+ if (extract_n(address))
+ return 1;
+
+ /* make memory and I/O addresses absolute */
+ if (*attach_space == hw_phb_io_space
+ || *attach_space == hw_phb_memory_space) {
+ int reg_nr;
+ reg_property_spec assigned;
+ if (extract_ss(address) == ss_64bit_memory_code)
+ device_error(me, "64bit memory address not unsuported");
+ for (reg_nr = 0;
+ device_find_reg_array_property(client, "assigned-addresses", reg_nr,
+ &assigned);
+ reg_nr++) {
+ if (!extract_n(&assigned.address)
+ || extract_rrrrrrrr(&assigned.address) == 0)
+ device_error(me, "client %s has invalid assigned-address property",
+ device_path(client));
+ if (extract_rrrrrrrr(address) == extract_rrrrrrrr(&assigned.address)) {
+ /* corresponding base register */
+ if (extract_ss(address) != extract_ss(&assigned.address))
+ device_error(me, "client %s has conflicting types for base register 0x%lx",
+ device_path(client),
+ (unsigned long)extract_rrrrrrrr(address));
+ *attach_address += assigned.address.cells[2];
+ return 0;
+ }
+ }
+ device_error(me, "client %s missing base address register 0x%lx in assigned-addresses property",
+ device_path(client),
+ (unsigned long)extract_rrrrrrrr(address));
+ }
+
+ return 0;
+}
+
+
+static int
+hw_phb_size_to_attach_size(device *me,
+ const device_unit *size,
+ unsigned *nr_bytes,
+ device *client)
+{
+ if (size->nr_cells != 2)
+ device_error(me, "size has incorrect number of cells");
+ if (size->cells[0] != 0)
+ device_error(me, "64bit size unsupported");
+ *nr_bytes = size->cells[1];
+ return size->cells[1];
+}
+
+
+static const phb_space *
+find_phb_space(hw_phb_device *phb,
+ unsigned_word addr,
+ unsigned nr_bytes)
+{
+ hw_phb_spaces space;
+ /* find the space that matches the address */
+ for (space = 0; space < nr_hw_phb_spaces; space++) {
+ phb_space *pci_space = &phb->space[space];
+ if (addr >= pci_space->parent_base
+ && (addr + nr_bytes) <= (pci_space->parent_base + pci_space->size)) {
+ return pci_space;
+ }
+ }
+ return NULL;
+}
+
+
+static unsigned_word
+map_phb_addr(const phb_space *space,
+ unsigned_word addr)
+{
+ return addr - space->parent_base + space->my_base;
+}
+
+
+
+static unsigned
+hw_phb_io_read_buffer(device *me,
+ void *dest,
+ int space,
+ unsigned_word addr,
+ unsigned nr_bytes,
+ cpu *processor,
+ unsigned_word cia)
+{
+ hw_phb_device *phb = (hw_phb_device*)device_data(me);
+ const phb_space *pci_space = find_phb_space(phb, addr, nr_bytes);
+ unsigned_word bus_addr;
+ if (pci_space == NULL)
+ return 0;
+ bus_addr = map_phb_addr(pci_space, addr);
+ DTRACE(phb, ("io read - %d:0x%lx -> %s:0x%lx (%u bytes)\n",
+ space, (unsigned long)addr, pci_space->name, (unsigned long)bus_addr,
+ nr_bytes));
+ return core_map_read_buffer(pci_space->readable,
+ dest, bus_addr, nr_bytes);
+}
+
+
+static unsigned
+hw_phb_io_write_buffer(device *me,
+ const void *source,
+ int space,
+ unsigned_word addr,
+ unsigned nr_bytes,
+ cpu *processor,
+ unsigned_word cia)
+{
+ hw_phb_device *phb = (hw_phb_device*)device_data(me);
+ const phb_space *pci_space = find_phb_space(phb, addr, nr_bytes);
+ unsigned_word bus_addr;
+ if (pci_space == NULL)
+ return 0;
+ bus_addr = map_phb_addr(pci_space, addr);
+ DTRACE(phb, ("io write - %d:0x%lx -> %s:0x%lx (%u bytes)\n",
+ space, (unsigned long)addr, pci_space->name, (unsigned long)bus_addr,
+ nr_bytes));
+ return core_map_write_buffer(pci_space->writeable, source,
+ bus_addr, nr_bytes);
+}
+
+
+static unsigned
+hw_phb_dma_read_buffer(device *me,
+ void *dest,
+ int space,
+ unsigned_word addr,
+ unsigned nr_bytes)
+{
+ hw_phb_device *phb = (hw_phb_device*)device_data(me);
+ const phb_space *pci_space;
+ /* find the space */
+ if (space != hw_phb_memory_space)
+ device_error(me, "invalid dma address space %d", space);
+ pci_space = &phb->space[space];
+ /* check out the address */
+ if ((addr >= pci_space->my_base
+ && addr <= pci_space->my_base + pci_space->size)
+ || (addr + nr_bytes >= pci_space->my_base
+ && addr + nr_bytes <= pci_space->my_base + pci_space->size))
+ device_error(me, "Do not support DMA into own bus");
+ /* do it */
+ DTRACE(phb, ("dma read - %s:0x%lx (%d bytes)\n",
+ pci_space->name, addr, nr_bytes));
+ return device_dma_read_buffer(device_parent(me),
+ dest, pci_space->parent_space,
+ addr, nr_bytes);
+}
+
+
+static unsigned
+hw_phb_dma_write_buffer(device *me,
+ const void *source,
+ int space,
+ unsigned_word addr,
+ unsigned nr_bytes,
+ int violate_read_only_section)
+{
+ hw_phb_device *phb = (hw_phb_device*)device_data(me);
+ const phb_space *pci_space;
+ /* find the space */
+ if (space != hw_phb_memory_space)
+ device_error(me, "invalid dma address space %d", space);
+ pci_space = &phb->space[space];
+ /* check out the address */
+ if ((addr >= pci_space->my_base
+ && addr <= pci_space->my_base + pci_space->size)
+ || (addr + nr_bytes >= pci_space->my_base
+ && addr + nr_bytes <= pci_space->my_base + pci_space->size))
+ device_error(me, "Do not support DMA into own bus");
+ /* do it */
+ DTRACE(phb, ("dma write - %s:0x%lx (%d bytes)\n",
+ pci_space->name, addr, nr_bytes));
+ return device_dma_write_buffer(device_parent(me),
+ source, pci_space->parent_space,
+ addr, nr_bytes,
+ violate_read_only_section);
+}
+
+
+static device_callbacks const hw_phb_callbacks = {
+ { hw_phb_init_address, },
+ { hw_phb_attach_address, },
+ { hw_phb_io_read_buffer, hw_phb_io_write_buffer },
+ { hw_phb_dma_read_buffer, hw_phb_dma_write_buffer },
+ { NULL, }, /* interrupt */
+ { hw_phb_unit_decode,
+ hw_phb_unit_encode,
+ hw_phb_address_to_attach_address,
+ hw_phb_size_to_attach_size }
+};
+
+
+static void *
+hw_phb_create(const char *name,
+ const device_unit *unit_address,
+ const char *args)
+{
+ /* create the descriptor */
+ hw_phb_device *phb = ZALLOC(hw_phb_device);
+
+ /* create the core maps now */
+ hw_phb_spaces space_nr;
+ for (space_nr = 0; space_nr < nr_hw_phb_spaces; space_nr++) {
+ phb_space *pci_space = &phb->space[space_nr];
+ pci_space->map = core_create();
+ pci_space->readable = core_readable(pci_space->map);
+ pci_space->writeable = core_writeable(pci_space->map);
+ switch (space_nr) {
+ case hw_phb_memory_space:
+ pci_space->name = "memory";
+ break;
+ case hw_phb_io_space:
+ pci_space->name = "I/O";
+ break;
+ case hw_phb_config_space:
+ pci_space->name = "config";
+ break;
+ case hw_phb_special_space:
+ pci_space->name = "special";
+ break;
+ default:
+ error ("internal error");
+ break;
+ }
+ }
+
+ return phb;
+}
+
+
+const device_descriptor hw_phb_device_descriptor[] = {
+ { "phb", hw_phb_create, &hw_phb_callbacks },
+ { "pci", NULL, &hw_phb_callbacks },
+ { NULL, },
+};
+
+#endif /* _HW_PHB_ */
diff --git a/gnu/dist/sim/ppc/hw_phb.h b/gnu/dist/sim/ppc/hw_phb.h
new file mode 100644
index 00000000000..030fe0a8194
--- /dev/null
+++ b/gnu/dist/sim/ppc/hw_phb.h
@@ -0,0 +1,40 @@
+/* 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.
+
+ */
+
+
+#ifndef _HW_PHB_H_
+#define _HW_PHB_H_
+
+typedef enum {
+ hw_phb_memory_space,
+ hw_phb_io_space,
+ hw_phb_config_space,
+ hw_phb_special_space,
+ nr_hw_phb_spaces,
+} hw_phb_spaces;
+
+typedef enum {
+ hw_phb_normal_decode = attach_callback,
+ hw_phb_subtractive_decode,
+ hw_phb_master_abort_decode,
+} hw_phb_decode;
+
+
+#endif /* _HW_PHB_H_ */
diff --git a/gnu/dist/sim/ppc/hw_register.c b/gnu/dist/sim/ppc/hw_register.c
new file mode 100644
index 00000000000..f361e462527
--- /dev/null
+++ b/gnu/dist/sim/ppc/hw_register.c
@@ -0,0 +1,131 @@
+/* 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.
+
+ */
+
+
+#ifndef _HW_REGISTER_C_
+#define _HW_REGISTER_C_
+
+#include "device_table.h"
+#include <stdlib.h>
+#include "psim.h"
+
+/* DEVICE
+
+
+ register - dummy device to initialize processor registers
+
+
+ DESCRIPTION
+
+ The properties of this device are used, during initialization, to
+ specify the initial value of various processor registers. The
+ property name specifying the register to be initialized with the
+ special form <cpu-nr>.<register> being used to initialize a
+ specific processor's register (eg 0.pc).
+
+ Because, when the device tree is created, overriding properties are
+ entered into the tree before any default values, this device must
+ initialize registers in newest (default) to oldest (overriding)
+ property order.
+
+ The actual registers (for a given target) are defined in the file
+ registers.c.
+
+ This device is normally a child of the /openprom/init node.
+
+
+ EXAMPLES
+
+
+ Given a device tree containing the entry:
+
+ | /openprom/init/register/pc 0xfff00cf0
+
+ then specifying the command line option:
+
+ | -o '/openprom/init/register/pc 0x0'
+
+ would override the initial value of processor zero's program
+ counter. The resultant device tree tree containing:
+
+ | /openprom/init/register/0.pc 0x0
+ | /openprom/init/register/pc 0xfff00cf0
+
+ and would be processed last to first resulting in the sequence: set
+ all program counters to 0xfff00cf0; set processor zero's program
+ counter to zero.
+
+ */
+
+static void
+do_register_init(device *me,
+ const device_property *prop)
+{
+ psim *system = device_system(me);
+ if (prop != NULL) {
+ const char *name = prop->name;
+ unsigned32 value = device_find_integer_property(me, name);
+ int processor;
+
+ do_register_init(me, device_next_property(prop));
+
+ if (strchr(name, '.') == NULL) {
+ processor = -1;
+ DTRACE(register, ("%s=0x%lx\n", name, (unsigned long)value));
+ }
+ else {
+ char *end;
+ processor = strtoul(name, &end, 0);
+ ASSERT(end[0] == '.');
+ name = end+1;
+ DTRACE(register, ("%d.%s=0x%lx\n", processor, name,
+ (unsigned long)value));
+ }
+ psim_write_register(system, processor, /* all processors */
+ &value,
+ name,
+ cooked_transfer);
+ }
+}
+
+
+static void
+register_init_data_callback(device *me)
+{
+ const device_property *prop = device_find_property(me, NULL);
+ do_register_init(me, prop);
+}
+
+
+static device_callbacks const register_callbacks = {
+ { NULL, register_init_data_callback, },
+ { NULL, }, /* address */
+ { NULL, }, /* IO */
+ { NULL, }, /* DMA */
+ { NULL, }, /* interrupt */
+ { NULL, }, /* unit */
+};
+
+const device_descriptor hw_register_device_descriptor[] = {
+ { "register", NULL, &register_callbacks },
+ { NULL },
+};
+
+#endif _HW_REGISTER_C_
diff --git a/gnu/dist/sim/ppc/hw_trace.c b/gnu/dist/sim/ppc/hw_trace.c
new file mode 100644
index 00000000000..a46483a5191
--- /dev/null
+++ b/gnu/dist/sim/ppc/hw_trace.c
@@ -0,0 +1,103 @@
+/* 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.
+
+ */
+
+
+#ifndef _HW_TRACE_C_
+#define _HW_TRACE_C_
+
+#include "device_table.h"
+#include <stdarg.h>
+
+/* DEVICE
+
+ trace - the properties of this dummy device specify trace options
+
+ DESCRIPTION
+
+ The properties of this device are used, during initialization, to
+ specify the value various simulation trace options. The
+ initialization can occure implicitly (during device tree init) or
+ explicitly using this devices ioctl method.
+
+ The actual options and their default values (for a given target)
+ are defined in the file debug.
+
+ This device is normally a child of the /openprom node.
+
+ EXAMPLE
+
+ The trace option dump-device-tree can be enabled by specifying the
+ option:
+
+ | -o '/openprom/trace/dump-device-tree 0x1'
+
+ Alternativly the shorthand version:
+
+ | -t dump-device-tree
+
+ can be used. */
+
+
+/* Hook to allow the initialization of the trace options at any time */
+
+static int
+hw_trace_ioctl(device *me,
+ cpu *processor,
+ unsigned_word cia,
+ device_ioctl_request request,
+ va_list ap)
+{
+ switch (request) {
+ case device_ioctl_set_trace:
+ {
+ const device_property *prop = device_find_property(me, NULL);
+ while (prop != NULL) {
+ const char *name = prop->name;
+ unsigned32 value = device_find_integer_property(me, name);
+ trace_option(name, value);
+ prop = device_next_property(prop);
+ }
+ }
+ break;
+ default:
+ device_error(me, "insupported ioctl request");
+ break;
+ }
+ return 0;
+}
+
+
+static device_callbacks const hw_trace_callbacks = {
+ { NULL, }, /* init */
+ { NULL, }, /* address */
+ { NULL, }, /* IO */
+ { NULL, }, /* DMA */
+ { NULL, }, /* interrupt */
+ { NULL, }, /* unit */
+ NULL, /* instance-create */
+ hw_trace_ioctl,
+};
+
+const device_descriptor hw_trace_device_descriptor[] = {
+ { "trace", NULL, &hw_trace_callbacks },
+ { NULL },
+};
+
+#endif _HW_TRACE_C_
diff --git a/gnu/dist/sim/ppc/hw_vm.c b/gnu/dist/sim/ppc/hw_vm.c
new file mode 100644
index 00000000000..e42b8002347
--- /dev/null
+++ b/gnu/dist/sim/ppc/hw_vm.c
@@ -0,0 +1,275 @@
+/* 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.
+
+ */
+
+
+#ifndef _HW_VM_C_
+#define _HW_VM_C_
+
+#include "device_table.h"
+#include "cpu.h"
+
+#include <signal.h>
+
+/* DEVICE
+
+ vm - virtual memory device for user simulation modes
+
+ DESCRIPTION
+
+ In user mode, mapped text, data and stack addresses are managed by
+ the core. Unmapped addresses are passed onto this device (because
+ it establishes its self as the fallback device) for processing.
+
+ During initialization, children of this device will request the
+ mapping of the initial text and data segments. Those requests are
+ passed onto the core device so that that may establish the initial
+ memory regions.
+
+ Once the simulation has started (as noted above) any access to an
+ unmapped address range will be passed down to this device as an IO
+ access. This device will then either attach additional memory to
+ the core device or signal the access as being invalid.
+
+ The IOCTL function is used to notify this device of any changes to
+ the users `brk' point.
+
+ PROPERTIES
+
+ stack-base = <number>
+
+ Specifies the lower address of the stack segment in the users
+ virtual address space. The initial stack page is defined by
+ stack-base + nr-bytes.
+
+ nr-bytes = <number>
+
+ Specifies the maximum size of the stack segment in the users
+ address space.
+
+ */
+
+typedef struct _hw_vm_device {
+ /* area of memory valid for stack addresses */
+ unsigned_word stack_base; /* min possible stack value */
+ unsigned_word stack_bound;
+ unsigned_word stack_lower_limit;
+ /* area of memory valid for heap addresses */
+ unsigned_word heap_base;
+ unsigned_word heap_bound;
+ unsigned_word heap_upper_limit;
+} hw_vm_device;
+
+
+static void
+hw_vm_init_address_callback(device *me)
+{
+ hw_vm_device *vm = (hw_vm_device*)device_data(me);
+
+ /* revert the stack/heap variables to their defaults */
+ vm->stack_base = device_find_integer_property(me, "stack-base");
+ vm->stack_bound = (vm->stack_base
+ + device_find_integer_property(me, "nr-bytes"));
+ vm->stack_lower_limit = vm->stack_bound;
+ vm->heap_base = 0;
+ vm->heap_bound = 0;
+ vm->heap_upper_limit = 0;
+
+ /* establish this device as the default memory handler */
+ device_attach_address(device_parent(me),
+ attach_callback + 1,
+ 0 /*address space - ignore*/,
+ 0 /*addr - ignore*/,
+ (((unsigned)0)-1) /*nr_bytes - ignore*/,
+ access_read_write /*access*/,
+ me);
+}
+
+
+static void
+hw_vm_attach_address(device *me,
+ attach_type attach,
+ int space,
+ unsigned_word addr,
+ unsigned nr_bytes,
+ access_type access,
+ device *client) /*callback/default*/
+{
+ hw_vm_device *vm = (hw_vm_device*)device_data(me);
+ /* update end of bss if necessary */
+ if (vm->heap_base < addr + nr_bytes) {
+ vm->heap_base = addr + nr_bytes;
+ vm->heap_bound = addr + nr_bytes;
+ vm->heap_upper_limit = addr + nr_bytes;
+ }
+ device_attach_address(device_parent(me),
+ attach_raw_memory,
+ 0 /*address space*/,
+ addr,
+ nr_bytes,
+ access,
+ me);
+}
+
+
+static unsigned
+hw_vm_add_space(device *me,
+ unsigned_word addr,
+ unsigned nr_bytes,
+ cpu *processor,
+ unsigned_word cia)
+{
+ hw_vm_device *vm = (hw_vm_device*)device_data(me);
+ unsigned_word block_addr;
+ unsigned block_nr_bytes;
+
+ /* an address in the stack area, allocate just down to the addressed
+ page */
+ if (addr >= vm->stack_base && addr < vm->stack_lower_limit) {
+ block_addr = FLOOR_PAGE(addr);
+ block_nr_bytes = vm->stack_lower_limit - block_addr;
+ vm->stack_lower_limit = block_addr;
+ }
+ /* an address in the heap area, allocate all of the required heap */
+ else if (addr >= vm->heap_upper_limit && addr < vm->heap_bound) {
+ block_addr = vm->heap_upper_limit;
+ block_nr_bytes = vm->heap_bound - vm->heap_upper_limit;
+ vm->heap_upper_limit = vm->heap_bound;
+ }
+ /* oops - an invalid address - abort the cpu */
+ else if (processor != NULL) {
+ cpu_halt(processor, cia, was_signalled, SIGSEGV);
+ return 0;
+ }
+ /* 2*oops - an invalid address and no processor */
+ else {
+ return 0;
+ }
+
+ /* got the parameters, allocate the space */
+ device_attach_address(device_parent(me),
+ attach_raw_memory,
+ 0 /*address space*/,
+ block_addr,
+ block_nr_bytes,
+ access_read_write,
+ me);
+ return block_nr_bytes;
+}
+
+
+static unsigned
+hw_vm_io_read_buffer_callback(device *me,
+ void *dest,
+ int space,
+ unsigned_word addr,
+ unsigned nr_bytes,
+ cpu *processor,
+ unsigned_word cia)
+{
+ if (hw_vm_add_space(me, addr, nr_bytes, processor, cia) >= nr_bytes) {
+ memset(dest, 0, nr_bytes); /* always initialized to zero */
+ return nr_bytes;
+ }
+ else
+ return 0;
+}
+
+
+static unsigned
+hw_vm_io_write_buffer_callback(device *me,
+ const void *source,
+ int space,
+ unsigned_word addr,
+ unsigned nr_bytes,
+ cpu *processor,
+ unsigned_word cia)
+{
+ if (hw_vm_add_space(me, addr, nr_bytes, processor, cia) >= nr_bytes) {
+ return device_dma_write_buffer(device_parent(me), source,
+ space, addr,
+ nr_bytes,
+ 0/*violate_read_only*/);
+ }
+ else
+ return 0;
+}
+
+
+static int
+hw_vm_ioctl(device *me,
+ cpu *processor,
+ unsigned_word cia,
+ device_ioctl_request request,
+ va_list ap)
+{
+ /* While the caller is notified that the heap has grown by the
+ requested amount, the heap is actually extended out to a page
+ boundary. */
+ hw_vm_device *vm = (hw_vm_device*)device_data(me);
+ switch (request) {
+ case device_ioctl_break:
+ {
+ unsigned_word requested_break = va_arg(ap, unsigned_word);
+ unsigned_word new_break = ALIGN_8(requested_break);
+ unsigned_word old_break = vm->heap_bound;
+ signed_word delta = new_break - old_break;
+ if (delta > 0)
+ vm->heap_bound = ALIGN_PAGE(new_break);
+ break;
+ }
+ default:
+ device_error(me, "Unsupported ioctl request");
+ break;
+ }
+ return 0;
+
+}
+
+
+static device_callbacks const hw_vm_callbacks = {
+ { hw_vm_init_address_callback, },
+ { hw_vm_attach_address,
+ passthrough_device_address_detach, },
+ { hw_vm_io_read_buffer_callback,
+ hw_vm_io_write_buffer_callback, },
+ { NULL, passthrough_device_dma_write_buffer, },
+ { NULL, }, /* interrupt */
+ { generic_device_unit_decode,
+ generic_device_unit_encode, },
+ NULL, /* instance */
+ hw_vm_ioctl,
+};
+
+
+static void *
+hw_vm_create(const char *name,
+ const device_unit *address,
+ const char *args)
+{
+ hw_vm_device *vm = ZALLOC(hw_vm_device);
+ return vm;
+}
+
+const device_descriptor hw_vm_device_descriptor[] = {
+ { "vm", hw_vm_create, &hw_vm_callbacks },
+ { NULL },
+};
+
+#endif _HW_VM_C_
diff --git a/gnu/dist/sim/ppc/idecode_expression.h b/gnu/dist/sim/ppc/idecode_expression.h
index f3e4e4cd522..bf11ba6ccae 100644
--- a/gnu/dist/sim/ppc/idecode_expression.h
+++ b/gnu/dist/sim/ppc/idecode_expression.h
@@ -1,6 +1,6 @@
/* This file is part of the program psim.
- Copyright (C) 1994-1996, Andrew Cagney <cagney@highland.com.au>
+ 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
@@ -86,8 +86,8 @@
else \
XER &= (~xer_carry); */ \
} \
- ITRACE(trace_alu, (" Result = %ld (0x%lx), XER = %ld\n", \
- (long)alu_result, (long)alu_result, (long)XER)); \
+ TRACE(trace_alu, (" Result = %ld (0x%lx), XER = %ld\n", \
+ (long)alu_result, (long)alu_result, (long)XER)); \
/* Update the Result Conditions if needed */ \
CR0_COMPARE(alu_result, 0, Rc); \
/* assign targ same */ \
@@ -261,6 +261,7 @@ do { \
: cr_i_zero))
#define CR_SET(REG, VAL) MBLIT32(CR, REG*4, REG*4+3, VAL)
+#define CR_FIELD(REG) EXTRACTED32(CR, REG*4, REG*4+3)
#define CR_SET_XER_SO(REG, VAL) \
do { \
creg new_bits = ((XER & xer_summary_overflow) \
@@ -281,9 +282,9 @@ do { \
do { \
if (Rc) { \
CR_COMPARE(0, LHS, RHS); \
- ITRACE(trace_alu, \
- ("CR=0x%08lx, LHS=%ld, RHS=%ld\n", \
- (unsigned long)CR, (long)LHS, (long)RHS)); \
+ TRACE(trace_alu, \
+ ("CR=0x%08lx, LHS=%ld, RHS=%ld\n", \
+ (unsigned long)CR, (long)LHS, (long)RHS)); \
} \
} while (0)
@@ -302,33 +303,49 @@ do { \
} while (0)
-/* some FPSCR update macros */
+
+/* some FPSCR update macros. */
#define FPSCR_BEGIN \
-FPSCR &= ~fpscr_reserved_20; \
{ \
- fpscreg old_fpscr __attribute__((__unused__)) = FPSCR
+ fpscreg old_fpscr UNUSED = FPSCR
#define FPSCR_END(Rc) { \
+ /* always update VX */ \
+ if ((FPSCR & fpscr_vx_bits)) \
+ FPSCR |= fpscr_vx; \
+ else \
+ FPSCR &= ~fpscr_vx; \
+ /* always update FEX */ \
+ if (((FPSCR & fpscr_vx) && (FPSCR & fpscr_ve)) \
+ || ((FPSCR & fpscr_ox) && (FPSCR & fpscr_oe)) \
+ || ((FPSCR & fpscr_ux) && (FPSCR & fpscr_ue)) \
+ || ((FPSCR & fpscr_zx) && (FPSCR & fpscr_ze)) \
+ || ((FPSCR & fpscr_xx) && (FPSCR & fpscr_xe))) \
+ FPSCR |= fpscr_fex; \
+ else \
+ FPSCR &= ~fpscr_fex; \
CR1_UPDATE(Rc); \
- if (FPSCR & fpscr_reserved_20) { \
- FPSCR &= ~fpscr_reserved_20; \
+ /* interrupt enabled? */ \
+ if ((MSR & (msr_floating_point_exception_mode_0 \
+ | msr_floating_point_exception_mode_1)) \
+ && (FPSCR & fpscr_fex)) \
program_interrupt(processor, cia, \
floating_point_enabled_program_interrupt); \
- } \
}}
+#define FPSCR_SET(REG, VAL) MBLIT32(FPSCR, REG*4, REG*4+3, VAL)
+#define FPSCR_FIELD(REG) EXTRACTED32(FPSCR, REG*4, REG*4+3)
+
#define FPSCR_SET_FPCC(VAL) MBLIT32(FPSCR, fpscr_fpcc_bit, fpscr_fpcc_bit+3, VAL)
/* Handle various exceptions */
#define FPSCR_OR_VX(VAL) \
do { \
+ /* NOTE: VAL != 0 */ \
FPSCR |= (VAL); \
FPSCR |= fpscr_fx; \
- if (FPSCR & fpscr_ve) \
- FPSCR |= fpscr_fex | fpscr_reserved_20; \
- FPSCR |= fpscr_vx; \
} while (0)
#define FPSCR_SET_OX(COND) \
@@ -336,8 +353,6 @@ do { \
if (COND) { \
FPSCR |= fpscr_ox; \
FPSCR |= fpscr_fx; \
- if (FPSCR & fpscr_oe) \
- FPSCR |= fpscr_fex | fpscr_reserved_20; \
} \
else \
FPSCR &= ~fpscr_ox; \
@@ -348,8 +363,6 @@ do { \
if (COND) { \
FPSCR |= fpscr_ux; \
FPSCR |= fpscr_fx; \
- if (FPSCR & fpscr_ue) \
- FPSCR |= fpscr_fex | fpscr_reserved_20; \
} \
else \
FPSCR &= ~fpscr_ux; \
@@ -360,8 +373,6 @@ do { \
if (COND) { \
FPSCR |= fpscr_zx; \
FPSCR |= fpscr_fx; \
- if (FPSCR & fpscr_ze) \
- FPSCR |= fpscr_fex | fpscr_reserved_20; \
} \
else \
FPSCR &= ~fpscr_zx; \
@@ -372,13 +383,12 @@ do { \
if (COND) { \
FPSCR |= fpscr_xx; \
FPSCR |= fpscr_fx; \
- if (FPSCR & fpscr_xe) \
- FPSCR |= fpscr_fex | fpscr_reserved_20; \
} \
} while (0)
-#define FPSCR_SET_FR(COND) \
-do { \
+/* Note: code using SET_FI must also explicitly call SET_XX */
+
+#define FPSCR_SET_FR(COND) do { \
if (COND) \
FPSCR |= fpscr_fr; \
else \
@@ -387,8 +397,9 @@ do { \
#define FPSCR_SET_FI(COND) \
do { \
- if (COND) \
+ if (COND) { \
FPSCR |= fpscr_fi; \
+ } \
else \
FPSCR &= ~fpscr_fi; \
} while (0)
diff --git a/gnu/dist/sim/ppc/idecode_fields.h b/gnu/dist/sim/ppc/idecode_fields.h
index a248b48a35f..1c449bc9769 100644
--- a/gnu/dist/sim/ppc/idecode_fields.h
+++ b/gnu/dist/sim/ppc/idecode_fields.h
@@ -100,3 +100,6 @@
#define BO_2_ ((BO & BIT5(2)) != 0)
#define BO_3_ ((BO & BIT5(3)) != 0)
#define BO_4_ ((BO & BIT5(4)) != 0)
+
+#define GOTO(dest) goto XCONCAT4(label__,dest,__,MY_PREFIX)
+#define LABEL(dest) XCONCAT4(label__,dest,__,MY_PREFIX)
diff --git a/gnu/dist/sim/ppc/igen.c b/gnu/dist/sim/ppc/igen.c
index ad5f21a897d..7cb917fcac5 100644
--- a/gnu/dist/sim/ppc/igen.c
+++ b/gnu/dist/sim/ppc/igen.c
@@ -1,6 +1,6 @@
/* This file is part of the program psim.
- Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
+ 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
@@ -18,8 +18,8 @@
*/
-#include <stdio.h>
-#include <ctype.h>
+
+
#include <getopt.h>
#include "misc.h"
@@ -27,1194 +27,72 @@
#include "table.h"
#include "config.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 {
- max_insn_size = 32,
-};
-
-static int hi_bit_nr = 0;
-static int insn_size = max_insn_size;
-static int idecode_expand_semantics = 0;
-static int idecode_cache = 0;
-static int semantics_use_cache_struct = 0;
-static int number_lines = 1;
-
-
-/****************************************************************/
-
-
-static char *cache_idecode_formal =
-"cpu *processor,\n\
- instruction_word instruction,\n\
- unsigned_word cia,\n\
- idecode_cache *cache_entry";
-
-static char *cache_idecode_actual = "processor, instruction, cia, cache_entry";
-
-static char *cache_semantic_formal =
-"cpu *processor,\n\
- idecode_cache *cache_entry,\n\
- unsigned_word cia";
+#include "filter.h"
-static char *semantic_formal =
-"cpu *processor,\n\
- instruction_word instruction,\n\
- unsigned_word cia";
+#include "ld-decode.h"
+#include "ld-cache.h"
+#include "ld-insn.h"
-static char *semantic_actual = "processor, instruction, cia";
+#include "igen.h"
+#include "gen-model.h"
+#include "gen-icache.h"
+#include "gen-itable.h"
+#include "gen-idecode.h"
+#include "gen-semantics.h"
+#include "gen-support.h"
+int hi_bit_nr;
+int insn_bit_size = max_insn_bit_size;
-/****************************************************************/
-
-
-typedef struct _filter filter;
-struct _filter {
- char *flag;
- filter *next;
-};
-static filter *filters = NULL;
+igen_code code = generate_calls;
+int generate_expanded_instructions;
+int icache_size = 1024;
+int generate_smp;
/****************************************************************/
-
-typedef struct _cache_rules cache_rules;
-struct _cache_rules {
- int valid;
- char *old_name;
- char *new_name;
- char *type;
- char *expression;
- cache_rules *next;
-};
-static cache_rules *cache_table;
-
-
-enum {
- ca_valid,
- ca_old_name,
- ca_new_name,
- ca_type,
- ca_expression,
- nr_cache_rule_fields,
-};
-
-static cache_rules *
-load_cache_rules(char *file_name)
-{
- table *file = table_open(file_name, nr_cache_rule_fields, 0);
- table_entry *entry;
- cache_rules *table = NULL;
- cache_rules **curr_rule = &table;
- while ((entry = table_entry_read(file)) != NULL) {
- cache_rules *new_rule = ZALLOC(cache_rules);
- new_rule->valid = target_a2i(hi_bit_nr, entry->fields[ca_valid]);
- new_rule->old_name = entry->fields[ca_old_name];
- new_rule->new_name = entry->fields[ca_new_name];
- new_rule->type = (strlen(entry->fields[ca_type])
- ? entry->fields[ca_type]
- : NULL);
- new_rule->expression = (strlen(entry->fields[ca_expression]) > 0
- ? entry->fields[ca_expression]
- : NULL);
- *curr_rule = new_rule;
- curr_rule = &new_rule->next;
- }
- return table;
-}
-
-
-
-static void
-dump_cache_rule(cache_rules* rule,
- int indent)
-{
- dumpf(indent, "((cache_rules*)0x%x\n", rule);
- dumpf(indent, " (valid %d)\n", rule->valid);
- dumpf(indent, " (old_name \"%s\")\n", rule->old_name);
- dumpf(indent, " (new_name \"%s\")\n", rule->new_name);
- dumpf(indent, " (type \"%s\")\n", rule->type);
- dumpf(indent, " (expression \"%s\")\n", rule->expression);
- dumpf(indent, " (next 0x%x)\n", rule->next);
- dumpf(indent, " )\n");
-}
-
-
-static void
-dump_cache_rules(cache_rules* rule, int indent)
-{
- while (rule) {
- dump_cache_rule(rule, indent);
- rule = rule->next;
- }
-}
-
-
-/****************************************************************/
-
-
-typedef struct _opcode_rules opcode_rules;
-struct _opcode_rules {
- int first;
- int last;
- int force_first;
- int force_last;
- int force_slash;
- char *force_expansion;
- int use_switch;
- unsigned special_mask;
- unsigned special_value;
- unsigned special_rule;
- opcode_rules *next;
-};
-static opcode_rules *opcode_table;
-
-
-enum {
- op_first,
- op_last,
- op_force_first,
- op_force_last,
- op_force_slash,
- op_force_expansion,
- op_use_switch,
- op_special_mask,
- op_special_value,
- op_special_rule,
- nr_opcode_fields,
-};
-
-
-static opcode_rules *
-load_opcode_rules(char *file_name)
-{
- table *file = table_open(file_name, nr_opcode_fields, 0);
- table_entry *entry;
- opcode_rules *table = NULL;
- opcode_rules **curr_rule = &table;
- while ((entry = table_entry_read(file)) != NULL) {
- opcode_rules *new_rule = ZALLOC(opcode_rules);
- new_rule->first = target_a2i(hi_bit_nr, entry->fields[op_first]);
- new_rule->last = target_a2i(hi_bit_nr, entry->fields[op_last]);
- new_rule->force_first = target_a2i(hi_bit_nr, entry->fields[op_force_first]);
- new_rule->force_last = target_a2i(hi_bit_nr, entry->fields[op_force_last]);
- new_rule->force_slash = a2i(entry->fields[op_force_slash]);
- new_rule->force_expansion = entry->fields[op_force_expansion];
- new_rule->use_switch = a2i(entry->fields[op_use_switch]);
- new_rule->special_mask = a2i(entry->fields[op_special_mask]);
- new_rule->special_value = a2i(entry->fields[op_special_value]);
- new_rule->special_rule = a2i(entry->fields[op_special_rule]);
- *curr_rule = new_rule;
- curr_rule = &new_rule->next;
- }
- return table;
-}
-
-
-static void
-dump_opcode_rule(opcode_rules *rule,
- int indent)
-{
- dumpf(indent, "((opcode_rules*)%p\n", rule);
- if (rule) {
- dumpf(indent, " (first %d)\n", rule->first);
- dumpf(indent, " (last %d)\n", rule->last);
- dumpf(indent, " (force_first %d)\n", rule->force_first);
- dumpf(indent, " (force_last %d)\n", rule->force_last);
- dumpf(indent, " (force_slash %d)\n", rule->force_slash);
- dumpf(indent, " (force_expansion \"%s\")\n", rule->force_expansion);
- dumpf(indent, " (use_switch %d)\n", rule->use_switch);
- dumpf(indent, " (special_mask 0x%x)\n", rule->special_mask);
- dumpf(indent, " (special_value 0x%x)\n", rule->special_value);
- dumpf(indent, " (special_rule 0x%x)\n", rule->special_rule);
- dumpf(indent, " (next 0x%x)\n", rule->next);
- }
- dumpf(indent, " )\n");
-}
-
-
-static void
-dump_opcode_rules(opcode_rules *rule,
- int indent)
-{
- while (rule) {
- dump_opcode_rule(rule, indent);
- rule = rule->next;
- }
-}
-
-
-/****************************************************************/
-
-typedef struct _insn_field insn_field;
-struct _insn_field {
- int first;
- int last;
- int width;
- int is_int;
- int is_slash;
- int is_string;
- int val_int;
- char *pos_string;
- char *val_string;
- insn_field *next;
- insn_field *prev;
-};
-
-typedef struct _insn_fields insn_fields;
-struct _insn_fields {
- insn_field *bits[max_insn_size];
- insn_field *first;
- insn_field *last;
- unsigned value;
-};
-
-static insn_fields *
-parse_insn_format(table_entry *entry,
- char *format)
-{
- char *chp;
- insn_fields *fields = ZALLOC(insn_fields);
-
- /* create a leading sentinal */
- fields->first = ZALLOC(insn_field);
- fields->first->first = -1;
- fields->first->last = -1;
- fields->first->width = 0;
-
- /* and a trailing sentinal */
- fields->last = ZALLOC(insn_field);
- fields->last->first = insn_size;
- fields->last->last = insn_size;
- fields->last->width = 0;
-
- /* link them together */
- fields->first->next = fields->last;
- fields->last->prev = fields->first;
-
- /* now work through the formats */
- chp = format;
-
- while (*chp != '\0') {
- char *start_pos;
- char *start_val;
- int strlen_val;
- int strlen_pos;
- insn_field *new_field;
-
- /* sanity check */
- if (!isdigit(*chp)) {
- error("%s:%d: missing position field at `%s'\n",
- entry->file_name, entry->line_nr, chp);
- }
-
- /* break out the bit position */
- start_pos = chp;
- while (isdigit(*chp))
- chp++;
- strlen_pos = chp - start_pos;
- if (*chp == '.' && strlen_pos > 0)
- chp++;
- else {
- error("%s:%d: missing field value at %s\n",
- entry->file_name, entry->line_nr, chp);
- break;
- }
-
- /* break out the value */
- start_val = chp;
- while ((*start_val == '/' && *chp == '/')
- || (isdigit(*start_val) && isdigit(*chp))
- || (isalpha(*start_val) && (isalnum(*chp) || *chp == '_')))
- chp++;
- strlen_val = chp - start_val;
- if (*chp == ',')
- chp++;
- else if (*chp != '\0' || strlen_val == 0) {
- error("%s:%d: missing field terminator at %s\n",
- entry->file_name, entry->line_nr, chp);
- break;
- }
-
- /* create a new field and insert it */
- new_field = ZALLOC(insn_field);
- new_field->next = fields->last;
- new_field->prev = fields->last->prev;
- new_field->next->prev = new_field;
- new_field->prev->next = new_field;
-
- /* the value */
- new_field->val_string = (char*)zalloc(strlen_val+1);
- strncpy(new_field->val_string, start_val, strlen_val);
- if (isdigit(*new_field->val_string)) {
- new_field->val_int = a2i(new_field->val_string);
- new_field->is_int = 1;
- }
- else if (new_field->val_string[0] == '/') {
- new_field->is_slash = 1;
- }
- else {
- new_field->is_string = 1;
- }
-
- /* the pos */
- new_field->pos_string = (char*)zalloc(strlen_pos+1);
- strncpy(new_field->pos_string, start_pos, strlen_pos);
- new_field->first = target_a2i(hi_bit_nr, new_field->pos_string);
- new_field->last = new_field->next->first - 1; /* guess */
- new_field->width = new_field->last - new_field->first + 1; /* guess */
- new_field->prev->last = new_field->first-1; /*fix*/
- new_field->prev->width = new_field->first - new_field->prev->first; /*fix*/
- }
-
- /* fiddle first/last so that the sentinals `disapear' */
- ASSERT(fields->first->last < 0);
- ASSERT(fields->last->first >= insn_size);
- fields->first = fields->first->next;
- fields->last = fields->last->prev;
-
- /* now go over this again, pointing each bit position at a field
- record */
- {
- int i;
- insn_field *field;
- field = fields->first;
- for (i = 0; i < insn_size; i++) {
- while (field->last < i)
- field = field->next;
- fields->bits[i] = field;
- }
- }
-
- /* go over each of the fields, and compute a `value' for the insn */
- {
- insn_field *field;
- fields->value = 0;
- for (field = fields->first;
- field->last < insn_size;
- field = field->next) {
- fields->value <<= field->width;
- if (field->is_int)
- fields->value |= field->val_int;
- }
- }
- return fields;
-}
-
-
-typedef enum {
- field_constant_int = 1,
- field_constant_slash = 2,
- field_constant_string = 3
-} constant_field_types;
-
-
static int
-insn_field_is_constant(insn_field *field,
- opcode_rules *rule)
-{
- /* field is an integer */
- if (field->is_int)
- return field_constant_int;
- /* field is `/' and treating that as a constant */
- if (field->is_slash && rule->force_slash)
- return field_constant_slash;
- /* field, though variable is on the list */
- if (field->is_string && rule->force_expansion != NULL) {
- char *forced_fields = rule->force_expansion;
- while (*forced_fields != '\0') {
- int field_len;
- char *end = strchr(forced_fields, ',');
- if (end == NULL)
- field_len = strlen(forced_fields);
- else
- field_len = end-forced_fields;
- if (strncmp(forced_fields, field->val_string, field_len) == 0
- && field->val_string[field_len] == '\0')
- return field_constant_string;
- forced_fields += field_len;
- if (*forced_fields == ',')
- forced_fields++;
- }
- }
- return 0;
-}
-
-
-static void
-dump_insn_field(insn_field *field,
- int indent)
-{
-
- printf("(insn_field*)0x%x\n", (unsigned)field);
-
- dumpf(indent, "(first %d)\n", field->first);
-
- dumpf(indent, "(last %d)\n", field->last);
-
- dumpf(indent, "(width %d)\n", field->width);
-
- if (field->is_int)
- dumpf(indent, "(is_int %d)\n", field->val_int);
-
- if (field->is_slash)
- dumpf(indent, "(is_slash)\n");
-
- if (field->is_string)
- dumpf(indent, "(is_string `%s')\n", field->val_string);
-
- dumpf(indent, "(next 0x%x)\n", field->next);
-
- dumpf(indent, "(prev 0x%x)\n", field->prev);
-
-
-}
-
-static void
-dump_insn_fields(insn_fields *fields,
- int indent)
-{
- int i;
-
- printf("(insn_fields*)%p\n", fields);
-
- dumpf(indent, "(first 0x%x)\n", fields->first);
- dumpf(indent, "(last 0x%x)\n", fields->last);
-
- dumpf(indent, "(value 0x%x)\n", fields->value);
-
- for (i = 0; i < insn_size; i++) {
- dumpf(indent, "(bits[%d] ", i, fields->bits[i]);
- dump_insn_field(fields->bits[i], indent+1);
- dumpf(indent, " )\n");
- }
-
-}
-
-
-/****************************************************************/
-
-typedef struct _opcode_field opcode_field;
-struct _opcode_field {
- int first;
- int last;
- int is_boolean;
- opcode_field *parent;
-};
-
-static void
-dump_opcode_field(opcode_field *field, int indent, int levels)
-{
- printf("(opcode_field*)%p\n", field);
- if (levels && field != NULL) {
- dumpf(indent, "(first %d)\n", field->first);
- dumpf(indent, "(last %d)\n", field->last);
- dumpf(indent, "(is_boolean %d)\n", field->is_boolean);
- dumpf(indent, "(parent ");
- dump_opcode_field(field->parent, indent, levels-1);
- }
-}
-
-
-/****************************************************************/
-
-typedef struct _insn_bits insn_bits;
-struct _insn_bits {
- int is_expanded;
- int value;
- insn_field *field;
- opcode_field *opcode;
- insn_bits *last;
-};
-
-
-static void
-dump_insn_bits(insn_bits *bits, int indent, int levels)
-{
- printf("(insn_bits*)%p\n", bits);
-
- if (levels && bits != NULL) {
- dumpf(indent, "(value %d)\n", bits->value);
- dumpf(indent, "(opcode ");
- dump_opcode_field(bits->opcode, indent+1, 0);
- dumpf(indent, " )\n");
- dumpf(indent, "(field ");
- dump_insn_field(bits->field, indent+1);
- dumpf(indent, " )\n");
- dumpf(indent, "(last ");
- dump_insn_bits(bits->last, indent+1, levels-1);
- }
-}
-
-
-/****************************************************************/
-
-
-typedef enum {
- insn_format,
- insn_form,
- insn_flags,
- insn_mnemonic,
- insn_name,
- insn_comment,
- nr_insn_table_fields
-} insn_table_fields;
-
-typedef enum {
- function_type = insn_format,
- function_name = insn_name,
- function_param = insn_comment
-} function_table_fields;
-
-typedef enum {
- model_name = insn_mnemonic,
- model_identifer = insn_name,
- model_default = insn_comment,
-} model_table_fields;
-
-typedef struct _insn insn;
-struct _insn {
- table_entry *file_entry;
- insn_fields *fields;
- insn *next;
-};
-
-typedef struct _insn_undef insn_undef;
-struct _insn_undef {
- insn_undef *next;
- char *name;
-};
-
-static insn_undef *first_undef, *last_undef;
-
-typedef struct _model model;
-struct _model {
- model *next;
- char *name;
- char *printable_name;
- char *insn_default;
- table_model_entry *func_unit_start;
- table_model_entry *func_unit_end;
-};
-
-typedef struct _insn_table insn_table;
-struct _insn_table {
- int opcode_nr;
- insn_bits *expanded_bits;
- int nr_insn;
- insn *insns;
- insn *functions;
- insn *last_function;
- opcode_rules *opcode_rule;
- opcode_field *opcode;
- int nr_entries;
- insn_table *entries;
- insn_table *sibling;
- insn_table *parent;
-};
-
-typedef enum {
- insn_model_name,
- insn_model_fields,
- nr_insn_model_table_fields
-} insn_model_table_fields;
-
-static model *models;
-static model *last_model;
-
-static insn *model_macros;
-static insn *last_model_macro;
-
-static insn *model_functions;
-static insn *last_model_function;
-
-static insn *model_internal;
-static insn *last_model_internal;
-
-static insn *model_static;
-static insn *last_model_static;
-
-static insn *model_data;
-static insn *last_model_data;
-
-static int max_model_fields_len;
-
-static void
-insn_table_insert_function(insn_table *table,
- table_entry *file_entry)
-{
- /* create a new function */
- insn *new_function = ZALLOC(insn);
- new_function->file_entry = file_entry;
-
- /* append it to the end of the function list */
- if (table->last_function)
- table->last_function->next = new_function;
- else
- table->functions = new_function;
- table->last_function = new_function;
-}
-
-static void
-insn_table_insert_insn(insn_table *table,
- table_entry *file_entry,
- insn_fields *fields)
-{
- insn **ptr_to_cur_insn = &table->insns;
- insn *cur_insn = *ptr_to_cur_insn;
- table_model_entry *insn_model_ptr;
- model *model_ptr;
-
- /* create a new instruction */
- insn *new_insn = ZALLOC(insn);
- new_insn->file_entry = file_entry;
- new_insn->fields = fields;
-
- /* Check out any model information returned to make sure the model
- is correct. */
- for(insn_model_ptr = file_entry->model_first; insn_model_ptr; insn_model_ptr = insn_model_ptr->next) {
- char *name = insn_model_ptr->fields[insn_model_name];
- int len = strlen (insn_model_ptr->fields[insn_model_fields]);
-
- while (len > 0 && isspace(*insn_model_ptr->fields[insn_model_fields])) {
- len--;
- insn_model_ptr->fields[insn_model_fields]++;
- }
-
- if (max_model_fields_len < len)
- max_model_fields_len = len;
-
- for(model_ptr = models; model_ptr; model_ptr = model_ptr->next) {
- if (strcmp(name, model_ptr->printable_name) == 0) {
-
- /* Replace the name field with that of the global model, so that when we
- want to print it out, we can just compare pointers. */
- insn_model_ptr->fields[insn_model_name] = model_ptr->printable_name;
- break;
- }
- }
-
- if (!model_ptr)
- error("%s:%d: machine model `%s' was not known about\n",
- file_entry->file_name, file_entry->line_nr, name);
- }
-
- /* insert it according to the order of the fields */
- while (cur_insn != NULL
- && new_insn->fields->value >= cur_insn->fields->value) {
- ptr_to_cur_insn = &cur_insn->next;
- cur_insn = *ptr_to_cur_insn;
- }
-
- new_insn->next = cur_insn;
- *ptr_to_cur_insn = new_insn;
-
- table->nr_insn++;
-}
-
-
-static opcode_field *
-insn_table_find_opcode_field(insn *insns,
- opcode_rules *rule,
- int string_only)
-{
- opcode_field *curr_opcode = ZALLOC(opcode_field);
- insn *entry;
- ASSERT(rule);
-
- curr_opcode->first = insn_size;
- curr_opcode->last = -1;
- for (entry = insns; entry != NULL; entry = entry->next) {
- insn_fields *fields = entry->fields;
- opcode_field new_opcode;
-
- /* find a start point for the opcode field */
- new_opcode.first = rule->first;
- while (new_opcode.first <= rule->last
- && (!string_only
- || insn_field_is_constant(fields->bits[new_opcode.first],
- rule) != field_constant_string)
- && (string_only
- || !insn_field_is_constant(fields->bits[new_opcode.first],
- rule)))
- new_opcode.first = fields->bits[new_opcode.first]->last + 1;
- ASSERT(new_opcode.first > rule->last
- || (string_only
- && insn_field_is_constant(fields->bits[new_opcode.first],
- rule) == field_constant_string)
- || (!string_only
- && insn_field_is_constant(fields->bits[new_opcode.first],
- rule)));
-
- /* find the end point for the opcode field */
- new_opcode.last = rule->last;
- while (new_opcode.last >= rule->first
- && (!string_only
- || insn_field_is_constant(fields->bits[new_opcode.last],
- rule) != field_constant_string)
- && (string_only
- || !insn_field_is_constant(fields->bits[new_opcode.last],
- rule)))
- new_opcode.last = fields->bits[new_opcode.last]->first - 1;
- ASSERT(new_opcode.last < rule->first
- || (string_only
- && insn_field_is_constant(fields->bits[new_opcode.last],
- rule) == field_constant_string)
- || (!string_only
- && insn_field_is_constant(fields->bits[new_opcode.last],
- rule)));
-
- /* now see if our current opcode needs expanding */
- if (new_opcode.first <= rule->last
- && curr_opcode->first > new_opcode.first)
- curr_opcode->first = new_opcode.first;
- if (new_opcode.last >= rule->first
- && curr_opcode->last < new_opcode.last)
- curr_opcode->last = new_opcode.last;
-
- }
-
- /* was any thing interesting found? */
- if (curr_opcode->first > rule->last) {
- ASSERT(curr_opcode->last < rule->first);
- return NULL;
- }
- ASSERT(curr_opcode->last >= rule->first);
- ASSERT(curr_opcode->first <= rule->last);
-
- /* if something was found, check it includes the forced field range */
- if (!string_only
- && curr_opcode->first > rule->force_first) {
- curr_opcode->first = rule->force_first;
- }
- if (!string_only
- && curr_opcode->last < rule->force_last) {
- curr_opcode->last = rule->force_last;
- }
- /* handle special case elminating any need to do shift after mask */
- if (string_only
- && rule->force_last == insn_size-1) {
- curr_opcode->last = insn_size-1;
- }
-
- /* handle any special cases */
- switch (rule->special_rule) {
- case 0: /* let the above apply */
- break;
- case 1: /* expand a limited nr of bits, ignoring the rest */
- curr_opcode->first = rule->force_first;
- curr_opcode->last = rule->force_last;
- break;
- case 2: /* boolean field */
- curr_opcode->is_boolean = 1;
- break;
- }
-
- return curr_opcode;
-}
-
-
-static void
-insn_table_insert_expanded(insn_table *table,
- insn *old_insn,
- int new_opcode_nr,
- insn_bits *new_bits)
-{
- insn_table **ptr_to_cur_entry = &table->entries;
- insn_table *cur_entry = *ptr_to_cur_entry;
-
- /* find the new table for this entry */
- while (cur_entry != NULL
- && cur_entry->opcode_nr < new_opcode_nr) {
- ptr_to_cur_entry = &cur_entry->sibling;
- cur_entry = *ptr_to_cur_entry;
- }
-
- if (cur_entry == NULL || cur_entry->opcode_nr != new_opcode_nr) {
- insn_table *new_entry = ZALLOC(insn_table);
- new_entry->opcode_nr = new_opcode_nr;
- new_entry->expanded_bits = new_bits;
- new_entry->opcode_rule = table->opcode_rule->next;
- new_entry->sibling = cur_entry;
- new_entry->parent = table;
- *ptr_to_cur_entry = new_entry;
- cur_entry = new_entry;
- table->nr_entries++;
- }
- /* ASSERT new_bits == cur_entry bits */
- ASSERT(cur_entry != NULL && cur_entry->opcode_nr == new_opcode_nr);
- insn_table_insert_insn(cur_entry,
- old_insn->file_entry,
- old_insn->fields);
-}
-
-static void
-insn_table_expand_opcode(insn_table *table,
- insn *instruction,
- int field_nr,
- int opcode_nr,
- insn_bits *bits)
-{
-
- if (field_nr > table->opcode->last) {
- insn_table_insert_expanded(table, instruction, opcode_nr, bits);
- }
- else {
- insn_field *field = instruction->fields->bits[field_nr];
- if (field->is_int || field->is_slash) {
- ASSERT(field->first >= table->opcode->first
- && field->last <= table->opcode->last);
- insn_table_expand_opcode(table, instruction, field->last+1,
- ((opcode_nr << field->width) + field->val_int),
- bits);
- }
- else {
- int val;
- int last_pos = ((field->last < table->opcode->last)
- ? field->last : table->opcode->last);
- int first_pos = ((field->first > table->opcode->first)
- ? field->first : table->opcode->first);
- int width = last_pos - first_pos + 1;
- int last_val = (table->opcode->is_boolean
- ? 2 : (1 << width));
- for (val = 0; val < last_val; val++) {
- insn_bits *new_bits = ZALLOC(insn_bits);
- new_bits->field = field;
- new_bits->value = val;
- new_bits->last = bits;
- new_bits->opcode = table->opcode;
- insn_table_expand_opcode(table, instruction, last_pos+1,
- ((opcode_nr << width) | val),
- new_bits);
- }
- }
- }
-}
-
-static void
-insn_table_insert_expanding(insn_table *table,
- insn *entry)
-{
- insn_table_expand_opcode(table,
- entry,
- table->opcode->first,
- 0,
- table->expanded_bits);
-}
-
-
-static void
-insn_table_expand_insns(insn_table *table)
-{
-
- ASSERT(table->nr_insn >= 1);
-
- /* determine a valid opcode */
- while (table->opcode_rule) {
- /* specials only for single instructions */
- if ((table->nr_insn > 1
- && table->opcode_rule->special_mask == 0
- && table->opcode_rule->special_rule == 0)
- || (table->nr_insn == 1
- && table->opcode_rule->special_mask != 0
- && ((table->insns->fields->value
- & table->opcode_rule->special_mask)
- == table->opcode_rule->special_value))
- || (idecode_expand_semantics
- && table->opcode_rule->special_mask == 0
- && table->opcode_rule->special_rule == 0))
- table->opcode =
- insn_table_find_opcode_field(table->insns,
- table->opcode_rule,
- table->nr_insn == 1/*string*/
- );
- if (table->opcode != NULL)
- break;
- table->opcode_rule = table->opcode_rule->next;
- }
-
- /* did we find anything */
- if (table->opcode == NULL) {
- return;
- }
- ASSERT(table->opcode != NULL);
-
- /* back link what we found to its parent */
- if (table->parent != NULL) {
- ASSERT(table->parent->opcode != NULL);
- table->opcode->parent = table->parent->opcode;
- }
-
- /* expand the raw instructions according to the opcode */
- {
- insn *entry;
- for (entry = table->insns; entry != NULL; entry = entry->next) {
- insn_table_insert_expanding(table, entry);
- }
- }
-
- /* and do the same for the sub entries */
- {
- insn_table *entry;
- for (entry = table->entries; entry != NULL; entry = entry->sibling) {
- insn_table_expand_insns(entry);
- }
- }
-}
-
-
-static void
-model_table_insert(insn_table *table,
- table_entry *file_entry)
-{
- int len;
-
- /* create a new model */
- model *new_model = ZALLOC(model);
-
- new_model->name = file_entry->fields[model_identifer];
- new_model->printable_name = file_entry->fields[model_name];
- new_model->insn_default = file_entry->fields[model_default];
-
- while (*new_model->insn_default && isspace(*new_model->insn_default))
- new_model->insn_default++;
-
- len = strlen(new_model->insn_default);
- if (max_model_fields_len < len)
- max_model_fields_len = len;
-
- /* append it to the end of the model list */
- if (last_model)
- last_model->next = new_model;
- else
- models = new_model;
- last_model = new_model;
-}
-
-static void
-model_table_insert_specific(insn_table *table,
- table_entry *file_entry,
- insn **start_ptr,
- insn **end_ptr)
-{
- insn *ptr = ZALLOC(insn);
- ptr->file_entry = file_entry;
- if (*end_ptr)
- (*end_ptr)->next = ptr;
- else
- (*start_ptr) = ptr;
- (*end_ptr) = ptr;
-}
-
-
-
-static insn_table *
-insn_table_load_insns(char *file_name)
-{
- table *file = table_open(file_name, nr_insn_table_fields, nr_insn_model_table_fields);
- insn_table *table = ZALLOC(insn_table);
- table_entry *file_entry;
- table->opcode_rule = opcode_table;
-
- while ((file_entry = table_entry_read(file)) != NULL) {
- if (it_is("function", file_entry->fields[insn_flags])
- || it_is("internal", file_entry->fields[insn_flags])) {
- insn_table_insert_function(table, file_entry);
- }
- else if (it_is("model", file_entry->fields[insn_flags])) {
- model_table_insert(table, file_entry);
- }
- else if (it_is("model-macro", file_entry->fields[insn_flags])) {
- model_table_insert_specific(table, file_entry, &model_macros, &last_model_macro);
- }
- else if (it_is("model-function", file_entry->fields[insn_flags])) {
- model_table_insert_specific(table, file_entry, &model_functions, &last_model_function);
- }
- else if (it_is("model-internal", file_entry->fields[insn_flags])) {
- model_table_insert_specific(table, file_entry, &model_internal, &last_model_internal);
- }
- else if (it_is("model-static", file_entry->fields[insn_flags])) {
- model_table_insert_specific(table, file_entry, &model_static, &last_model_static);
- }
- else if (it_is("model-data", file_entry->fields[insn_flags])) {
- model_table_insert_specific(table, file_entry, &model_data, &last_model_data);
- }
- else {
- insn_fields *fields;
- /* skip instructions that aren't relevant to the mode */
- filter *filt = filters;
- while (filt != NULL) {
- if (it_is(filt->flag, file_entry->fields[insn_flags]))
- break;
- filt = filt->next;
- }
- if (filt == NULL) {
- /* create/insert the new instruction */
- fields = parse_insn_format(file_entry,
- file_entry->fields[insn_format]);
- insn_table_insert_insn(table, file_entry, fields);
- }
- }
- }
- return table;
-}
-
-
-static void
-dump_insn(insn *entry, int indent, int levels)
-{
- printf("(insn*)%p\n", entry);
-
- if (levels && entry != NULL) {
-
- dumpf(indent, "(file_entry ");
- dump_table_entry(entry->file_entry, indent+1);
- dumpf(indent, " )\n");
-
- dumpf(indent, "(fields ");
- dump_insn_fields(entry->fields, indent+1);
- dumpf(indent, " )\n");
-
- dumpf(indent, "(next ");
- dump_insn(entry->next, indent+1, levels-1);
- dumpf(indent, " )\n");
-
- }
-
-}
-
-
-static void
-dump_insn_table(insn_table *table,
- int indent, int levels)
-{
-
- printf("(insn_table*)%p\n", table);
-
- if (levels && table != NULL) {
-
- dumpf(indent, "(opcode_nr %d)\n", table->opcode_nr);
-
- dumpf(indent, "(expanded_bits ");
- dump_insn_bits(table->expanded_bits, indent+1, -1);
- dumpf(indent, " )\n");
-
- dumpf(indent, "(int nr_insn %d)\n", table->nr_insn);
-
- dumpf(indent, "(insns ");
- dump_insn(table->insns, indent+1, table->nr_insn);
- dumpf(indent, " )\n");
-
- dumpf(indent, "(opcode_rule ");
- dump_opcode_rule(table->opcode_rule, indent+1);
- dumpf(indent, " )\n");
-
- dumpf(indent, "(opcode ");
- dump_opcode_field(table->opcode, indent+1, 1);
- dumpf(indent, " )\n");
-
- dumpf(indent, "(nr_entries %d)\n", table->entries);
- dumpf(indent, "(entries ");
- dump_insn_table(table->entries, indent+1, table->nr_entries);
- dumpf(indent, " )\n");
-
- dumpf(indent, "(sibling ", table->sibling);
- dump_insn_table(table->sibling, indent+1, levels-1);
- dumpf(indent, " )\n");
-
- dumpf(indent, "(parent ", table->parent);
- dump_insn_table(table->parent, indent+1, 0);
- dumpf(indent, " )\n");
-
- }
-}
-
-
-/****************************************************************/
-
-
-static void
-lf_print_insn_bits(lf *file, insn_bits *bits)
+print_insn_bits(lf *file, insn_bits *bits)
{
+ int nr = 0;
if (bits == NULL)
- return;
- lf_print_insn_bits(file, bits->last);
- lf_putchr(file, '_');
- lf_putstr(file, bits->field->val_string);
- if (!bits->opcode->is_boolean || bits->value == 0) {
+ return nr;
+ nr += print_insn_bits(file, bits->last);
+ nr += lf_putchr(file, '_');
+ nr += lf_putstr(file, bits->field->val_string);
+ if (bits->opcode->is_boolean && bits->value == 0)
+ nr += lf_putint(file, bits->opcode->boolean_constant);
+ else if (!bits->opcode->is_boolean) {
if (bits->opcode->last < bits->field->last)
- lf_putint(file, bits->value << (bits->field->last - bits->opcode->last));
+ nr += lf_putint(file, bits->value << (bits->field->last - bits->opcode->last));
else
- lf_putint(file, bits->value);
- }
-}
-
-static void
-lf_print_opcodes(lf *file,
- insn_table *table)
-{
- if (table != NULL) {
- while (1) {
- lf_printf(file, "_%d_%d",
- table->opcode->first,
- table->opcode->last);
- if (table->parent == NULL) break;
- lf_printf(file, "__%d", table->opcode_nr);
- table = table->parent;
- }
+ nr += lf_putint(file, bits->value);
}
+ return nr;
}
-static void
-lf_print_table_name(lf *file,
- insn_table *table)
-{
- lf_printf(file, "idecode_table");
- lf_print_opcodes(file, table);
-}
-
-
-
-typedef enum {
- function_name_prefix_semantics,
- function_name_prefix_idecode,
- function_name_prefix_itable,
- function_name_prefix_none
-} lf_function_name_prefixes;
-
-static void
-lf_print_function_name(lf *file,
- char *basename,
- insn_bits *expanded_bits,
- lf_function_name_prefixes prefix)
+extern int
+print_function_name(lf *file,
+ const char *basename,
+ insn_bits *expanded_bits,
+ lf_function_name_prefixes prefix)
{
-
+ int nr = 0;
/* the prefix */
switch (prefix) {
case function_name_prefix_semantics:
- lf_putstr(file, "semantic_");
+ nr += lf_putstr(file, "semantic_");
break;
case function_name_prefix_idecode:
- lf_printf(file, "idecode_");
+ nr += lf_printf(file, "idecode_");
break;
case function_name_prefix_itable:
- lf_putstr(file, "itable_");
+ nr += lf_putstr(file, "itable_");
+ break;
+ case function_name_prefix_icache:
+ nr += lf_putstr(file, "icache_");
break;
default:
break;
@@ -1222,7 +100,7 @@ lf_print_function_name(lf *file,
/* the function name */
{
- char *pos;
+ const char *pos;
for (pos = basename;
*pos != '\0';
pos++) {
@@ -1231,1233 +109,127 @@ lf_print_function_name(lf *file,
case '-':
break;
case ' ':
- lf_putchr(file, '_');
+ nr += lf_putchr(file, '_');
break;
default:
- lf_putchr(file, *pos);
+ nr += lf_putchr(file, *pos);
break;
}
}
}
/* the suffix */
- if (idecode_expand_semantics)
- lf_print_insn_bits(file, expanded_bits);
-}
-
-
-static void
-lf_print_idecode_table(lf *file,
- insn_table *entry)
-{
- int can_assume_leaf;
- opcode_rules *opcode_rule;
-
- /* have a look at the rule table, if all table rules follow all
- switch rules, I can assume that all end points are leaves */
- opcode_rule = opcode_table;
- while (opcode_rule != NULL
- && opcode_rule->use_switch)
- opcode_rule = opcode_rule->next;
- while (opcode_rule != NULL
- && opcode_rule->use_switch
- && opcode_rule->special_rule)
- opcode_rule = opcode_rule->next;
- can_assume_leaf = opcode_rule == NULL;
-
- lf_printf(file, "{\n");
- lf_indent(file, +2);
- {
- lf_printf(file, "idecode_table_entry *table = ");
- lf_print_table_name(file, entry);
- lf_printf(file, ";\n");
- lf_printf(file, "int opcode = EXTRACTED32(instruction, %d, %d);\n",
- i2target(hi_bit_nr, entry->opcode->first),
- i2target(hi_bit_nr, entry->opcode->last));
- lf_printf(file, "idecode_table_entry *table_entry = table + opcode;\n");
- lf_printf(file, "while (1) {\n");
- lf_indent(file, +2);
- {
- lf_printf(file, "/* nonzero mask -> another table */\n");
- lf_printf(file, "while (table_entry->mask != 0) {\n");
- lf_indent(file, +2);
- {
- lf_printf(file, "table = ((idecode_table_entry*)\n");
- lf_printf(file, " table_entry->function_or_table);\n");
- lf_printf(file, "opcode = ((instruction & table_entry->mask)\n");
- lf_printf(file, " >> table_entry->shift);\n");
- lf_printf(file, "table_entry = table + opcode;\n");
- }
- lf_indent(file, -2);
- lf_printf(file, "}\n");
- lf_printf(file, "ASSERT(table_entry->mask == 0);\n");
- if (can_assume_leaf)
- lf_printf(file, "ASSERT(table_entry->shift == 0);\n");
- else {
- lf_printf(file, "if (table_entry->shift == 0)\n");
- lf_indent(file, +2);
- }
- if (idecode_cache) {
- lf_printf(file, "return (((idecode_crack*)\n");
- lf_printf(file, " table_entry->function_or_table)\n");
- lf_printf(file, " (%s));\n", cache_idecode_actual);
- }
- else {
- lf_printf(file, "return (((idecode_semantic*)\n");
- lf_printf(file, " table_entry->function_or_table)\n");
- lf_printf(file, " (%s));\n", semantic_actual);
- }
- if (!can_assume_leaf) {
- lf_indent(file, -2);
- lf_printf(file, "/* must be a boolean */\n");
- lf_printf(file, "opcode = (instruction & table_entry->shift) != 0;\n");
- lf_printf(file, "table = ((idecode_table_entry*)\n");
- lf_printf(file, " table_entry->function_or_table);\n");
- lf_printf(file, "table_entry = table + opcode;\n");
- }
- }
- lf_indent(file, -2);
- lf_printf(file, "}\n");
- }
- lf_indent(file, -2);
- lf_printf(file, "}\n");
-}
-
-
-static void
-lf_print_my_prefix(lf *file,
- table_entry *file_entry,
- int idecode)
-{
- lf_printf(file, "const char *const my_prefix __attribute__((__unused__)) = \n");
- lf_printf(file, " \"%s:%s:%s:%d\";\n",
- filter_filename (file_entry->file_name),
- (idecode ? "idecode" : "semantics"),
- file_entry->fields[insn_name],
- file_entry->line_nr);
- lf_printf(file, "const itable_index my_index __attribute__((__unused__)) = ");
- lf_print_function_name(file,
- file_entry->fields[insn_name],
- NULL,
- function_name_prefix_itable);
- lf_printf(file, ";\n");
-}
-
-
-static void
-lf_print_ptrace(lf *file,
- int idecode)
-{
- lf_printf(file, "\n");
- lf_printf(file, "ITRACE(trace_%s, (\"\\n\"));\n",
- (idecode ? "idecode" : "semantics"));
-}
-
-
-/****************************************************************/
-
-typedef void leaf_handler
-(insn_table *entry,
- void *data,
- int depth);
-typedef void padding_handler
-(insn_table *table,
- void *data,
- int depth,
- int opcode_nr);
-
-
-static void
-insn_table_traverse_tree(insn_table *table,
- void *data,
- int depth,
- leaf_handler *start,
- leaf_handler *leaf,
- leaf_handler *end,
- padding_handler *padding)
-{
- insn_table *entry;
- int entry_nr;
-
- ASSERT(table != NULL
- && table->opcode != NULL
- && table->nr_entries > 0
- && table->entries != 0);
-
- if (start != NULL && depth >= 0)
- start(table, data, depth);
-
- for (entry_nr = 0, entry = table->entries;
- entry_nr < (table->opcode->is_boolean
- ? 2
- : (1 << (table->opcode->last - table->opcode->first + 1)));
- entry_nr ++) {
- if (entry == NULL
- || (!table->opcode->is_boolean
- && entry_nr < entry->opcode_nr)) {
- if (padding != NULL && depth >= 0)
- padding(table, data, depth, entry_nr);
- }
- else {
- ASSERT(entry != NULL && (entry->opcode_nr == entry_nr
- || table->opcode->is_boolean));
- if (entry->opcode != NULL && depth != 0) {
- insn_table_traverse_tree(entry, data, depth+1,
- start, leaf, end, padding);
- }
- else if (depth >= 0) {
- if (leaf != NULL)
- leaf(entry, data, depth);
- }
- entry = entry->sibling;
- }
- }
- if (end != NULL && depth >= 0)
- end(table, data, depth);
-}
-
-
-typedef void function_handler
-(insn_table *table,
- void *data,
- table_entry *function);
-
-static void
-insn_table_traverse_function(insn_table *table,
- void *data,
- function_handler *leaf)
-{
- insn *function;
- for (function = table->functions;
- function != NULL;
- function = function->next) {
- leaf(table, data, function->file_entry);
- }
-}
-
-
-typedef void insn_handler
-(insn_table *table,
- void *data,
- insn *instruction);
-
-static void
-insn_table_traverse_insn(insn_table *table,
- void *data,
- insn_handler *leaf)
-{
- insn *instruction;
- for (instruction = table->insns;
- instruction != NULL;
- instruction = instruction->next) {
- leaf(table, data, instruction);
- }
-}
+ if (generate_expanded_instructions)
+ nr += print_insn_bits(file, expanded_bits);
-
-static void
-update_depth(insn_table *entry,
- void *data,
- int depth)
-{
- int *max_depth = (int*)data;
- if (*max_depth < depth)
- *max_depth = depth;
-}
-
-
-static int
-insn_table_depth(insn_table *table)
-{
- int depth = 0;
- insn_table_traverse_tree(table,
- &depth,
- 1,
- NULL, /*start*/
- update_depth,
- NULL, /*end*/
- NULL); /*padding*/
- return depth;
-}
-
-
-/****************************************************************/
-
-static void
-dump_traverse_start(insn_table *table,
- void *data,
- int depth)
-{
- dumpf(depth*2, "(%d\n", table->opcode_nr);
-}
-
-static void
-dump_traverse_leaf(insn_table *entry,
- void *data,
- int depth)
-{
- ASSERT(entry->nr_entries == 0
- && entry->nr_insn == 1
- && entry->opcode == NULL);
- dumpf(depth*2, ".%d %s\n", entry->opcode_nr,
- entry->insns->file_entry->fields[insn_format]);
-}
-
-static void
-dump_traverse_end(insn_table *table,
- void *data,
- int depth)
-{
- dumpf(depth*2, ")\n");
-}
-
-static void
-dump_traverse_padding(insn_table *table,
- void *data,
- int depth,
- int opcode_nr)
-{
- dumpf(depth*2, ".<%d>\n", opcode_nr);
-}
-
-
-static void
-dump_traverse(insn_table *table)
-{
- insn_table_traverse_tree(table, NULL, 1,
- dump_traverse_start,
- dump_traverse_leaf,
- dump_traverse_end,
- dump_traverse_padding);
+ return nr;
}
-/****************************************************************/
-
-
-static void
-lf_print_semantic_function_header(lf *file,
- char *basename,
- insn_bits *expanded_bits,
- int is_function_definition,
- int is_inline_function)
-{
- lf_printf(file, "\n");
- lf_print_function_type(file, "unsigned_word", "EXTERN_SEMANTICS",
- " ");
- lf_print_function_name(file,
- basename,
- expanded_bits,
- function_name_prefix_semantics);
- lf_printf(file, "\n(%s)",
- (idecode_cache ? cache_semantic_formal : semantic_formal));
- if (!is_function_definition)
- lf_printf(file, ";");
+void
+print_my_defines(lf *file,
+ insn_bits *expanded_bits,
+ table_entry *file_entry)
+{
+ /* #define MY_INDEX xxxxx */
+ lf_indent_suppress(file);
+ lf_printf(file, "#undef MY_INDEX\n");
+ lf_indent_suppress(file);
+ lf_printf(file, "#define MY_INDEX ");
+ print_function_name(file,
+ file_entry->fields[insn_name],
+ NULL,
+ function_name_prefix_itable);
+ lf_printf(file, "\n");
+ /* #define MY_PREFIX xxxxxx */
+ lf_indent_suppress(file);
+ lf_printf(file, "#undef MY_PREFIX\n");
+ lf_indent_suppress(file);
+ lf_printf(file, "#define MY_PREFIX ");
+ print_function_name(file,
+ file_entry->fields[insn_name],
+ expanded_bits,
+ function_name_prefix_none);
lf_printf(file, "\n");
}
-static void
-semantics_h_leaf(insn_table *entry,
- void *data,
- int depth)
-{
- lf *file = (lf*)data;
- ASSERT(entry->nr_insn == 1);
- lf_print_semantic_function_header(file,
- entry->insns->file_entry->fields[insn_name],
- entry->expanded_bits,
- 0/* isnt function definition*/,
- !idecode_cache && entry->parent->opcode_rule->use_switch);
-}
-
-static void
-semantics_h_insn(insn_table *entry,
- void *data,
- insn *instruction)
-{
- lf *file = (lf*)data;
- lf_print_semantic_function_header(file,
- instruction->file_entry->fields[insn_name],
- NULL,
- 0/*isnt function definition*/,
- 0/*isnt inline function*/);
-}
-
-static void
-semantics_h_function(insn_table *entry,
- void *data,
- table_entry *function)
+void
+print_itrace(lf *file,
+ table_entry *file_entry,
+ int idecode)
{
- lf *file = (lf*)data;
- if (function->fields[function_type] == NULL
- || function->fields[function_type][0] == '\0') {
- lf_print_semantic_function_header(file,
- function->fields[function_name],
- NULL,
- 0/*isnt function definition*/,
- 1/*is inline function*/);
- }
- else {
- lf_printf(file, "\n");
- lf_print_function_type(file, function->fields[function_type],
- "INLINE_SEMANTICS", " ");
- lf_printf(file, "%s\n(%s);\n",
- function->fields[function_name],
- function->fields[function_param]);
- }
+ lf_print__external_reference(file, file_entry->line_nr, file_entry->file_name);
+ lf_printf(file, "ITRACE(trace_%s, (\"%s %s\\n\"));\n",
+ (idecode ? "idecode" : "semantics"),
+ (idecode ? "idecode" : "semantics"),
+ file_entry->fields[insn_name]);
+ lf_print__internal_reference(file);
}
-static void
-gen_semantics_h(insn_table *table, lf *file)
-{
-
- lf_print_copyleft(file);
- lf_printf(file, "\n");
- lf_printf(file, "#ifndef _SEMANTICS_H_\n");
- lf_printf(file, "#define _SEMANTICS_H_\n");
- lf_printf(file, "\n");
-
- /* output a declaration for all functions */
- insn_table_traverse_function(table,
- file,
- semantics_h_function);
-
- /* output a declaration for all instructions */
- if (idecode_expand_semantics)
- insn_table_traverse_tree(table,
- file,
- 1,
- NULL, /* start */
- semantics_h_leaf, /* leaf */
- NULL, /* end */
- NULL); /* padding */
- else
- insn_table_traverse_insn(table,
- file,
- semantics_h_insn);
-
- lf_printf(file, "\n");
- lf_printf(file, "#endif /* _SEMANTICS_H_ */\n");
-
-}
-
/****************************************************************/
-typedef struct _icache_tree icache_tree;
-struct _icache_tree {
- char *name;
- icache_tree *next;
- icache_tree *children;
-};
-
-static icache_tree *
-icache_tree_insert(icache_tree *tree,
- char *name)
-{
- icache_tree *new_tree;
- /* find it */
- icache_tree **ptr_to_cur_tree = &tree->children;
- icache_tree *cur_tree = *ptr_to_cur_tree;
- while (cur_tree != NULL
- && strcmp(cur_tree->name, name) < 0) {
- ptr_to_cur_tree = &cur_tree->next;
- cur_tree = *ptr_to_cur_tree;
- }
- ASSERT(cur_tree == NULL
- || strcmp(cur_tree->name, name) >= 0);
- /* already in the tree */
- if (cur_tree != NULL
- && strcmp(cur_tree->name, name) == 0)
- return cur_tree;
- /* missing, insert it */
- ASSERT(cur_tree == NULL
- || strcmp(cur_tree->name, name) > 0);
- new_tree = ZALLOC(icache_tree);
- new_tree->name = name;
- new_tree->next = cur_tree;
- *ptr_to_cur_tree = new_tree;
- return new_tree;
-}
-
-
-static icache_tree *
-insn_table_cache_fields(insn_table *table)
-{
- icache_tree *tree = ZALLOC(icache_tree);
- insn *instruction;
- for (instruction = table->insns;
- instruction != NULL;
- instruction = instruction->next) {
- insn_field *field;
- icache_tree *form =
- icache_tree_insert(tree,
- instruction->file_entry->fields[insn_form]);
- for (field = instruction->fields->first;
- field != NULL;
- field = field->next) {
- if (field->is_string)
- icache_tree_insert(form, field->val_string);
- }
- }
- return tree;
-}
-
-
static void
-gen_icache_h(icache_tree *tree,
- lf *file)
+gen_semantics_h(insn_table *table,
+ lf *file,
+ igen_code generate)
{
- lf_print_copyleft(file);
- lf_printf(file, "\n");
- lf_printf(file, "#ifndef _ICACHE_H_\n");
- lf_printf(file, "#define _ICACHE_H_\n");
- lf_printf(file, "\n");
-
- lf_printf(file, "#define WITH_IDECODE_CACHE_SIZE %d\n",
- idecode_cache);
- lf_printf(file, "\n");
-
- /* create an instruction cache if being used */
- if (idecode_cache) {
- icache_tree *form;
- lf_printf(file, "typedef struct _idecode_cache {\n");
- lf_printf(file, " unsigned_word address;\n");
- lf_printf(file, " void *semantic;\n");
- lf_printf(file, " union {\n");
- for (form = tree->children;
- form != NULL;
- form = form->next) {
- icache_tree *field;
- lf_printf(file, " struct {\n");
- for (field = form->children;
- field != NULL;
- field = field->next) {
- cache_rules *cache_rule;
- int found_rule = 0;
- for (cache_rule = cache_table;
- cache_rule != NULL;
- cache_rule = cache_rule->next) {
- if (strcmp(field->name, cache_rule->old_name) == 0) {
- found_rule = 1;
- if (cache_rule->new_name != NULL)
- lf_printf(file, " %s %s; /* %s */\n",
- (cache_rule->type == NULL
- ? "unsigned"
- : cache_rule->type),
- cache_rule->new_name,
- cache_rule->old_name);
- }
- }
- if (!found_rule)
- lf_printf(file, " unsigned %s;\n", field->name);
- }
- lf_printf(file, " } %s;\n", form->name);
- }
- lf_printf(file, " } crack;\n");
- lf_printf(file, "} idecode_cache;\n");
- }
- else {
- /* alernativly, since no cache, #define the fields to be
- extractions from the instruction variable. Emit a dummy
- definition for idecode_cache to allow model_issue to not
- be #ifdefed at the call level */
- cache_rules *cache_rule;
- lf_printf(file, "\n");
- lf_printf(file, "typedef void idecode_cache;\n");
- lf_printf(file, "\n");
- for (cache_rule = cache_table;
- cache_rule != NULL;
- cache_rule = cache_rule->next) {
- if (cache_rule->expression != NULL
- && strlen(cache_rule->expression) > 0)
- lf_printf(file, "#define %s %s\n",
- cache_rule->new_name, cache_rule->expression);
- }
- }
-
+ lf_printf(file, "typedef %s idecode_semantic\n(%s);\n",
+ SEMANTIC_FUNCTION_TYPE,
+ SEMANTIC_FUNCTION_FORMAL);
lf_printf(file, "\n");
- lf_printf(file, "#endif /* _ICACHE_H_ */\n");
-}
-
-
-
-
-/****************************************************************/
-
-
-static void
-lf_print_c_extraction(lf *file,
- insn *instruction,
- char *field_name,
- char *field_type,
- char *field_expression,
- insn_field *cur_field,
- insn_bits *bits,
- int get_value_from_cache,
- int put_value_in_cache)
-{
- ASSERT(field_name != NULL);
- if (bits != NULL
- && (!bits->opcode->is_boolean || bits->value == 0)
- && strcmp(field_name, cur_field->val_string) == 0) {
- ASSERT(bits->field == cur_field);
- ASSERT(field_type == NULL);
- table_entry_lf_c_line_nr(file, instruction->file_entry);
- lf_printf(file, "const unsigned %s __attribute__((__unused__)) = ",
- field_name);
- if (bits->opcode->last < bits->field->last)
- lf_printf(file, "%d;\n",
- bits->value << (bits->field->last - bits->opcode->last));
- else
- lf_printf(file, "%d;\n", bits->value);
- }
- else if (get_value_from_cache && !put_value_in_cache
- && semantics_use_cache_struct) {
- insn_undef *undef = ZALLOC(insn_undef);
- /* Use #define to reference the cache struct directly, rather than putting
- them into local variables */
- lf_indent_suppress(file);
- lf_printf(file, "#define %s (cache_entry->crack.%s.%s)\n",
- field_name,
- instruction->file_entry->fields[insn_form],
- field_name);
-
- if (first_undef)
- last_undef->next = undef;
+ if ((code & generate_calls)) {
+ if (generate_expanded_instructions)
+ insn_table_traverse_tree(table,
+ file, NULL,
+ 1,
+ NULL, /* start */
+ print_semantic_declaration, /* leaf */
+ NULL, /* end */
+ NULL); /* padding */
else
- first_undef = undef;
- last_undef = undef;;
- undef->name = field_name;
+ insn_table_traverse_insn(table,
+ file, NULL,
+ print_semantic_declaration);
+
}
else {
- /* put the field in the local variable */
- table_entry_lf_c_line_nr(file, instruction->file_entry);
- lf_printf(file, "%s const %s __attribute__((__unused__)) = ",
- field_type == NULL ? "unsigned" : field_type,
- field_name);
- /* getting it from the cache */
- if (get_value_from_cache || put_value_in_cache) {
- lf_printf(file, "cache_entry->crack.%s.%s",
- instruction->file_entry->fields[insn_form],
- field_name);
- if (put_value_in_cache) /* also put it in the cache? */
- lf_printf(file, " = ");
- }
- if (!get_value_from_cache) {
- if (strcmp(field_name, cur_field->val_string) == 0)
- lf_printf(file, "EXTRACTED32(instruction, %d, %d)",
- i2target(hi_bit_nr, cur_field->first),
- i2target(hi_bit_nr, cur_field->last));
- else if (field_expression != NULL)
- lf_printf(file, "%s", field_expression);
- else
- lf_printf(file, "eval_%s", field_name);
- }
- lf_printf(file, ";\n");
+ lf_print__this_file_is_empty(file);
}
}
static void
-lf_print_c_extractions(lf *file,
- insn *instruction,
- insn_bits *expanded_bits,
- int get_value_from_cache,
- int put_value_in_cache)
+gen_semantics_c(insn_table *table,
+ cache_table *cache_rules,
+ lf *file,
+ igen_code generate)
{
- insn_field *cur_field;
-
- /* extract instruction fields */
- lf_printf(file, "/* extraction: %s */\n",
- instruction->file_entry->fields[insn_format]);
-
- for (cur_field = instruction->fields->first;
- cur_field->first < insn_size;
- cur_field = cur_field->next) {
- if (cur_field->is_string) {
- insn_bits *bits;
- int found_rule = 0;
- /* find any corresponding value */
- for (bits = expanded_bits;
- bits != NULL;
- bits = bits->last) {
- if (bits->field == cur_field)
- break;
- }
- /* try the cache rule table for what to do */
- if (get_value_from_cache || put_value_in_cache) {
- cache_rules *cache_rule;
- for (cache_rule = cache_table;
- cache_rule != NULL;
- cache_rule = cache_rule->next) {
- if (strcmp(cur_field->val_string, cache_rule->old_name) == 0) {
- found_rule = 1;
- if (cache_rule->valid > 1 && put_value_in_cache)
- lf_print_c_extraction(file,
- instruction,
- cache_rule->new_name,
- cache_rule->type,
- cache_rule->expression,
- cur_field,
- bits,
- 0,
- 0);
- else if (cache_rule->valid == 1)
- lf_print_c_extraction(file,
- instruction,
- cache_rule->new_name,
- cache_rule->type,
- cache_rule->expression,
- cur_field,
- bits,
- get_value_from_cache,
- put_value_in_cache);
- }
- }
- }
- if (found_rule == 0)
- lf_print_c_extraction(file,
- instruction,
- cur_field->val_string,
- 0,
- 0,
- cur_field,
- bits,
- get_value_from_cache,
- put_value_in_cache);
- /* if any (XXX == 0), output a corresponding test */
- if (instruction->file_entry->annex != NULL) {
- char *field_name = cur_field->val_string;
- char *is_0_ptr = instruction->file_entry->annex;
- int field_len = strlen(field_name);
- if (strlen(is_0_ptr) >= (strlen("_is_0") + field_len)) {
- is_0_ptr += field_len;
- while ((is_0_ptr = strstr(is_0_ptr, "_is_0")) != NULL) {
- if (strncmp(is_0_ptr - field_len, field_name, field_len) == 0
- && !isalpha(is_0_ptr[ - field_len - 1])) {
- table_entry_lf_c_line_nr(file, instruction->file_entry);
- lf_printf(file, "const unsigned %s_is_0 __attribute__((__unused__)) = (", field_name);
- if (bits != NULL)
- lf_printf(file, "%d", bits->value);
- else
- lf_printf(file, "%s", field_name);
- lf_printf(file, " == 0);\n");
- break;
- }
- is_0_ptr += strlen("_is_0");
- }
- }
- }
- /* any thing else ... */
- }
- }
- lf_print_lf_c_line_nr(file);
-}
-
-
-static void
-lf_print_idecode_illegal(lf *file)
-{
- if (idecode_cache)
- lf_printf(file, "return idecode_illegal(%s);\n", cache_idecode_actual);
- else
- lf_printf(file, "return semantic_illegal(%s);\n", semantic_actual);
-}
-
-
-static void
-lf_print_idecode_floating_point_unavailable(lf *file)
-{
- if (idecode_cache)
- lf_printf(file, "return idecode_floating_point_unavailable(%s);\n",
- cache_idecode_actual);
- else
- lf_printf(file, "return semantic_floating_point_unavailable(%s);\n",
- semantic_actual);
-}
-
-
-/* Output code to do any final checks on the decoded instruction.
- This includes things like verifying any on decoded fields have the
- correct value and checking that (for floating point) floating point
- hardware isn't disabled */
-
-static void
-lf_print_c_validate(lf *file,
- insn *instruction,
- opcode_field *opcodes)
-{
- /* Validate: unchecked instruction fields
-
- If any constant fields in the instruction were not checked by the
- idecode tables, output code to check that they have the correct
- value here */
- {
- unsigned check_mask = 0;
- unsigned check_val = 0;
- insn_field *field;
- opcode_field *opcode;
-
- /* form check_mask/check_val containing what needs to be checked
- in the instruction */
- for (field = instruction->fields->first;
- field->first < insn_size;
- field = field->next) {
-
- check_mask <<= field->width;
- check_val <<= field->width;
-
- /* is it a constant that could need validating? */
- if (!field->is_int && !field->is_slash)
- continue;
-
- /* has it been checked by a table? */
- for (opcode = opcodes; opcode != NULL; opcode = opcode->parent) {
- if (field->first >= opcode->first
- && field->last <= opcode->last)
- break;
- }
- if (opcode != NULL)
- continue;
-
- check_mask |= (1 << field->width)-1;
- check_val |= field->val_int;
- }
-
- /* if any bits not checked by opcode tables, output code to check them */
- if (check_mask) {
- lf_printf(file, "\n");
- lf_printf(file, "/* validate: %s */\n",
- instruction->file_entry->fields[insn_format]);
- lf_printf(file, "if (WITH_RESERVED_BITS && (instruction & 0x%x) != 0x%x)\n",
- check_mask, check_val);
- lf_indent(file, +2);
- lf_print_idecode_illegal(file);
- lf_indent(file, -2);
- }
- }
-
- /* Validate floating point hardware
-
- If the simulator is being built with out floating point hardware
- (different to it being disabled in the MSR) then floating point
- instructions are invalid */
- {
- if (it_is("f", instruction->file_entry->fields[insn_flags])) {
- lf_printf(file, "\n");
- lf_printf(file, "/* Validate: FP hardware exists */\n");
- lf_printf(file, "if (CURRENT_FLOATING_POINT != HARD_FLOATING_POINT)\n");
- lf_indent(file, +2);
- lf_print_idecode_illegal(file);
- lf_indent(file, -2);
- }
- }
-
- /* Validate: Floating Point available
-
- If floating point is not available, we enter a floating point
- unavailable interrupt into the cache instead of the instruction
- proper.
-
- The PowerPC spec requires a CSI after MSR[FP] is changed and when
- ever a CSI occures we flush the instruction cache. */
-
- {
- if (it_is("f", instruction->file_entry->fields[insn_flags])) {
- lf_printf(file, "\n");
- lf_printf(file, "/* Validate: FP available according to MSR[FP] */\n");
- lf_printf(file, "if (!IS_FP_AVAILABLE(processor))\n");
- lf_indent(file, +2);
- lf_print_idecode_floating_point_unavailable(file);
- lf_indent(file, -2);
- }
- }
-}
-
-
-static void
-lf_print_c_cracker(lf *file,
- insn *instruction,
- insn_bits *expanded_bits,
- opcode_field *opcodes)
-{
-
- /* function header */
- lf_printf(file, "{\n");
- lf_indent(file, +2);
-
- lf_print_my_prefix(file,
- instruction->file_entry,
- 1/*putting-value-in-cache*/);
-
- lf_print_ptrace(file,
- 1/*putting-value-in-cache*/);
-
- lf_print_c_validate(file, instruction, opcodes);
-
- lf_printf(file, "\n");
- lf_printf(file, "{\n");
- lf_indent(file, +2);
- lf_print_c_extractions(file,
- instruction,
- expanded_bits,
- 0/*get_value_from_cache*/,
- 1/*put_value_in_cache*/);
- lf_indent(file, -2);
- lf_printf(file, "}\n");
-
- /* return the function propper (main sorts this one out) */
- lf_printf(file, "\n");
- lf_printf(file, "/* semantic routine */\n");
- table_entry_lf_c_line_nr(file, instruction->file_entry);
- lf_printf(file, "return ");
- lf_print_function_name(file,
- instruction->file_entry->fields[insn_name],
- expanded_bits,
- function_name_prefix_semantics);
- lf_printf(file, ";\n");
-
- lf_print_lf_c_line_nr(file);
- lf_indent(file, -2);
- lf_printf(file, "}\n");
-}
-
-
-static void
-lf_print_c_semantic(lf *file,
- insn *instruction,
- insn_bits *expanded_bits,
- opcode_field *opcodes)
-{
-
- lf_printf(file, "{\n");
- lf_indent(file, +2);
-
- lf_print_my_prefix(file,
- instruction->file_entry,
- 0/*not putting value in cache*/);
- lf_printf(file, "unsigned_word nia = cia + %d;\n", insn_size / 8);
-
- lf_printf(file, "\n");
- lf_print_c_extractions(file,
- instruction,
- expanded_bits,
- idecode_cache/*get_value_from_cache*/,
- 0/*put_value_in_cache*/);
-
- lf_print_ptrace(file,
- 0/*put_value_in_cache*/);
-
- /* validate the instruction, if a cache this has already been done */
- if (!idecode_cache)
- lf_print_c_validate(file, instruction, opcodes);
-
- /* generate the profiling call - this is delayed until after the
- instruction has been verified */
- lf_printf(file, "\n");
- lf_printf(file, "if (WITH_MON & MONITOR_INSTRUCTION_ISSUE) {\n");
- lf_printf(file, " mon_issue(");
- lf_print_function_name(file,
- instruction->file_entry->fields[insn_name],
- NULL,
- function_name_prefix_itable);
- lf_printf(file, ", processor, cia);\n");
- lf_printf(file, "}\n");
- lf_printf(file, "\n");
-
- /* generate the code (or at least something */
- if (instruction->file_entry->annex != NULL) {
- /* true code */
- lf_printf(file, "\n");
- table_entry_lf_c_line_nr(file, instruction->file_entry);
- lf_printf(file, "{\n");
- lf_indent(file, +2);
- lf_print_c_code(file, instruction->file_entry->annex);
- lf_indent(file, -2);
- lf_printf(file, "}\n");
- lf_print_lf_c_line_nr(file);
- }
- else if (it_is("nop", instruction->file_entry->fields[insn_flags])) {
- lf_print_lf_c_line_nr(file);
- }
- else if (it_is("f", instruction->file_entry->fields[insn_flags])) {
- /* unimplemented floating point instruction - call for assistance */
+ if ((code & generate_calls)) {
lf_printf(file, "\n");
- lf_printf(file, "/* unimplemented floating point instruction - call for assistance */\n");
- table_entry_lf_c_line_nr(file, instruction->file_entry);
- lf_putstr(file, "floating_point_assist_interrupt(processor, cia);\n");
- lf_print_lf_c_line_nr(file);
- }
- else {
- /* abort so it is implemented now */
- table_entry_lf_c_line_nr(file, instruction->file_entry);
- lf_putstr(file, "error(\"%s: unimplemented, cia=0x%x\\n\", my_prefix, cia);\n");
- lf_print_lf_c_line_nr(file);
+ lf_printf(file, "#include \"cpu.h\"\n");
+ lf_printf(file, "#include \"idecode.h\"\n");
+ lf_printf(file, "#include \"semantics.h\"\n");
+ lf_printf(file, "#include \"support.h\"\n");
lf_printf(file, "\n");
- }
-
- lf_printf(file, "return nia;\n");
- lf_indent(file, -2);
- lf_printf(file, "}\n");
-}
-
-static void
-lf_print_c_semantic_function(lf *file,
- insn *instruction,
- insn_bits *expanded_bits,
- opcode_field *opcodes,
- int is_inline_function)
-{
- insn_undef *undef, *next;
-
- /* build the semantic routine to execute the instruction */
- lf_print_semantic_function_header(file,
- instruction->file_entry->fields[insn_name],
- expanded_bits,
- 1/*is-function-definition*/,
- is_inline_function);
- lf_print_c_semantic(file,
- instruction,
- expanded_bits,
- opcodes);
-
- /* If we are referencing the cache structure directly instead of putting the values
- in local variables, undef any defines we created */
- for(undef = first_undef; undef; undef = next) {
- next = undef->next;
- lf_indent_suppress(file);
- lf_printf(file, "#undef %s\n", undef->name);
- free((void *)undef);
- }
- first_undef = (insn_undef *)0;
- last_undef = (insn_undef *)0;
-}
-
-
-static void
-semantics_c_leaf(insn_table *entry,
- void *data,
- int depth)
-{
- lf *file = (lf*)data;
- ASSERT(entry->nr_insn == 1
- && entry->opcode == NULL
- && entry->parent != NULL
- && entry->parent->opcode != NULL);
- lf_print_c_semantic_function(file,
- entry->insns,
- entry->expanded_bits,
- entry->parent->opcode,
- !idecode_cache && entry->parent->opcode_rule->use_switch);
-}
-
-static void
-semantics_c_insn(insn_table *table,
- void *data,
- insn *instruction)
-{
- lf *file = (lf*)data;
- lf_print_c_semantic_function(file, instruction,
- NULL, NULL,
- 0/*isnt_inline_function*/);
-}
-
-static void
-semantics_c_function(insn_table *table,
- void *data,
- table_entry *function)
-{
- lf *file = (lf*)data;
- if (function->fields[function_type] == NULL
- || function->fields[function_type][0] == '\0') {
- lf_print_semantic_function_header(file,
- function->fields[function_name],
- NULL,
- 1/*is function definition*/,
- 1/*is inline function*/);
- }
- else {
- lf_printf(file, "\n");
- lf_print_function_type(file, function->fields[function_type],
- "INLINE_SEMANTICS", "\n");
- lf_printf(file, "%s(%s)\n",
- function->fields[function_name],
- function->fields[function_param]);
- }
- table_entry_lf_c_line_nr(file, function);
- lf_printf(file, "{\n");
- lf_indent(file, +2);
- lf_print_c_code(file, function->annex);
- lf_indent(file, -2);
- lf_printf(file, "}\n");
- lf_print_lf_c_line_nr(file);
-}
-
-
-
-static void
-gen_semantics_c(insn_table *table, lf *file)
-{
- lf_print_copyleft(file);
- lf_printf(file, "\n");
- lf_printf(file, "#ifndef _SEMANTICS_C_\n");
- lf_printf(file, "#define _SEMANTICS_C_\n");
- lf_printf(file, "\n");
- lf_printf(file, "#include \"cpu.h\"\n");
- lf_printf(file, "#include \"idecode.h\"\n");
- lf_printf(file, "#include \"semantics.h\"\n");
- lf_printf(file, "\n");
-
- /* output a definition (c-code) for all functions */
- insn_table_traverse_function(table,
- file,
- semantics_c_function);
-
- /* output a definition (c-code) for all instructions */
- if (idecode_expand_semantics)
- insn_table_traverse_tree(table,
- file,
- 1,
- NULL, /* start */
- semantics_c_leaf,
- NULL, /* end */
- NULL); /* padding */
- else
- insn_table_traverse_insn(table,
- file,
- semantics_c_insn);
-
- lf_printf(file, "\n");
- lf_printf(file, "#endif /* _SEMANTICS_C_ */\n");
-}
-
-
-/****************************************************************/
-
-static void
-gen_idecode_h(insn_table *table, lf *file)
-{
- lf_print_copyleft(file);
- lf_printf(file, "\n");
- lf_printf(file, "#ifndef _IDECODE_H_\n");
- lf_printf(file, "#define _IDECODE_H_\n");
- lf_printf(file, "\n");
- lf_printf(file, "#include \"idecode_expression.h\"\n");
- lf_printf(file, "#include \"idecode_fields.h\"\n");
- lf_printf(file, "#include \"idecode_branch.h\"\n");
- lf_printf(file, "\n");
- lf_printf(file, "#include \"icache.h\"\n");
- lf_printf(file, "\n");
- lf_printf(file, "typedef unsigned_word idecode_semantic\n(%s);\n",
- (idecode_cache ? cache_semantic_formal : semantic_formal));
- lf_printf(file, "\n");
- if (idecode_cache) {
- lf_print_function_type(file, "idecode_semantic *", "INLINE_IDECODE", " ");
- lf_printf(file, "idecode\n(%s);\n", cache_idecode_formal);
+ if (generate_expanded_instructions)
+ insn_table_traverse_tree(table,
+ file, cache_rules,
+ 1,
+ NULL, /* start */
+ print_semantic_definition, /* leaf */
+ NULL, /* end */
+ NULL); /* padding */
+ else
+ insn_table_traverse_insn(table,
+ file, cache_rules,
+ print_semantic_definition);
+
}
else {
- lf_print_function_type(file, "unsigned_word", "INLINE_IDECODE", " ");
- lf_printf(file, "idecode_issue\n(%s);\n", semantic_formal);
- }
- lf_printf(file, "\n");
- lf_printf(file, "#endif /* _IDECODE_H_ */\n");
-}
-
-
-/****************************************************************/
-
-
-static void
-idecode_table_start(insn_table *table,
- void *data,
- int depth)
-{
- lf *file = (lf*)data;
- ASSERT(depth == 0);
- /* start of the table */
- if (!table->opcode_rule->use_switch) {
- lf_printf(file, "\n");
- lf_printf(file, "static idecode_table_entry ");
- lf_print_table_name(file, table);
- lf_printf(file, "[] = {\n");
- }
-}
-
-static void
-idecode_table_leaf(insn_table *entry,
- void *data,
- int depth)
-{
- lf *file = (lf*)data;
- ASSERT(entry->parent != NULL);
- ASSERT(depth == 0);
-
- /* add an entry to the table */
- if (!entry->parent->opcode_rule->use_switch) {
- if (entry->opcode == NULL) {
- /* table leaf entry */
- lf_printf(file, " /*%d*/ { 0, 0, ", entry->opcode_nr);
- lf_print_function_name(file,
- entry->insns->file_entry->fields[insn_name],
- entry->expanded_bits,
- (idecode_cache
- ? function_name_prefix_idecode
- : function_name_prefix_semantics));
- lf_printf(file, " },\n");
- }
- else if (entry->opcode_rule->use_switch) {
- /* table calling switch statement */
- lf_printf(file, " /*%d*/ { 0, 0, ",
- entry->opcode_nr);
- lf_print_table_name(file, entry);
- lf_printf(file, " },\n");
- }
- else {
- /* table `calling' another table */
- lf_printf(file, " /*%d*/ { ", entry->opcode_nr);
- if (entry->opcode->is_boolean)
- lf_printf(file, "MASK32(%d,%d), 0, ",
- i2target(hi_bit_nr, entry->opcode->first),
- i2target(hi_bit_nr, entry->opcode->last));
- else
- lf_printf(file, "%d, MASK32(%d,%d), ",
- insn_size - entry->opcode->last - 1,
- i2target(hi_bit_nr, entry->opcode->first),
- i2target(hi_bit_nr, entry->opcode->last));
- lf_print_table_name(file, entry);
- lf_printf(file, " },\n");
- }
- }
-}
-
-static void
-idecode_table_end(insn_table *table,
- void *data,
- int depth)
-{
- lf *file = (lf*)data;
- ASSERT(depth == 0);
-
- if (!table->opcode_rule->use_switch) {
- lf_printf(file, "};\n");
- }
-}
-
-static void
-idecode_table_padding(insn_table *table,
- void *data,
- int depth,
- int opcode_nr)
-{
- lf *file = (lf*)data;
- ASSERT(depth == 0);
-
- if (!table->opcode_rule->use_switch) {
- lf_printf(file, " /*%d*/ { 0, 0, %s_illegal },\n",
- opcode_nr, (idecode_cache ? "idecode" : "semantic"));
+ lf_print__this_file_is_empty(file);
}
}
@@ -2465,859 +237,79 @@ idecode_table_padding(insn_table *table,
/****************************************************************/
-void lf_print_idecode_switch
-(lf *file,
- insn_table *table);
-
-
-static void
-idecode_switch_start(insn_table *table,
- void *data,
- int depth)
-{
- lf *file = (lf*)data;
- ASSERT(depth == 0);
- ASSERT(table->opcode_rule->use_switch);
-
- lf_printf(file, "switch (EXTRACTED32(instruction, %d, %d)) {\n",
- i2target(hi_bit_nr, table->opcode->first),
- i2target(hi_bit_nr, table->opcode->last));
-}
-
-
-static void
-idecode_switch_leaf(insn_table *entry,
- void *data,
- int depth)
-{
- lf *file = (lf*)data;
- ASSERT(entry->parent != NULL);
- ASSERT(depth == 0);
- ASSERT(entry->parent->opcode_rule->use_switch);
- ASSERT(entry->parent->opcode);
-
- if (!entry->parent->opcode->is_boolean
- || entry->opcode_nr == 0)
- lf_printf(file, "case %d:\n", entry->opcode_nr);
- else
- lf_printf(file, "default:\n");
- lf_indent(file, +2);
- {
- if (entry->opcode == NULL) {
- /* switch calling leaf */
- lf_printf(file, "return ");
- lf_print_function_name(file,
- entry->insns->file_entry->fields[insn_name],
- entry->expanded_bits,
- (idecode_cache
- ? function_name_prefix_idecode
- : function_name_prefix_semantics));
- if (idecode_cache)
- lf_printf(file, "(%s);\n", cache_idecode_actual);
- else
- lf_printf(file, "(%s);\n", semantic_actual);
- }
- else if (entry->opcode_rule->use_switch) {
- /* switch calling switch */
- lf_print_idecode_switch(file, entry);
- }
- else {
- /* switch looking up a table */
- lf_print_idecode_table(file, entry);
- }
- lf_printf(file, "break;\n");
- }
- lf_indent(file, -2);
-}
-
-
-static void
-lf_print_idecode_switch_illegal(lf *file)
-{
- lf_indent(file, +2);
- lf_print_idecode_illegal(file);
- lf_printf(file, "break;\n");
- lf_indent(file, -2);
-}
-
-static void
-idecode_switch_end(insn_table *table,
- void *data,
- int depth)
-{
- lf *file = (lf*)data;
- ASSERT(depth == 0);
- ASSERT(table->opcode_rule->use_switch);
- ASSERT(table->opcode);
-
- if (table->opcode_rule->use_switch == 1
- && !table->opcode->is_boolean) {
- lf_printf(file, "default:\n");
- lf_print_idecode_switch_illegal(file);
- }
- lf_printf(file, "}\n");
-}
-
static void
-idecode_switch_padding(insn_table *table,
- void *data,
- int depth,
- int opcode_nr)
-{
- lf *file = (lf*)data;
-
- ASSERT(depth == 0);
- ASSERT(table->opcode_rule->use_switch);
-
- if (table->opcode_rule->use_switch > 1) {
- lf_printf(file, "case %d:\n", opcode_nr);
- lf_print_idecode_switch_illegal(file);
- }
-}
-
-
-void
-lf_print_idecode_switch(lf *file,
- insn_table *table)
+gen_icache_h(insn_table *table,
+ lf *file,
+ igen_code generate)
{
- insn_table_traverse_tree(table,
- file,
- 0,
- idecode_switch_start,
- idecode_switch_leaf,
- idecode_switch_end,
- idecode_switch_padding);
-}
-
-
-static void
-lf_print_idecode_switch_function_header(lf *file,
- insn_table *table,
- int is_function_definition)
-{
- lf_printf(file, "\n");
- lf_printf(file, "static ");
- if (idecode_cache)
- lf_printf(file, "idecode_semantic *");
- else
- lf_printf(file, "unsigned_word");
- if (is_function_definition)
- lf_printf(file, "\n");
- else
- lf_printf(file, " ");
- lf_print_table_name(file, table);
- lf_printf(file, "\n(%s)",
- (idecode_cache ? cache_idecode_formal : semantic_formal));
- if (!is_function_definition)
- lf_printf(file, ";");
+ lf_printf(file, "typedef %s idecode_icache\n(%s);\n",
+ ICACHE_FUNCTION_TYPE,
+ ICACHE_FUNCTION_FORMAL);
lf_printf(file, "\n");
-}
-
-
-static void
-idecode_declare_if_switch(insn_table *table,
- void *data,
- int depth)
-{
- lf *file = (lf*)data;
-
- if (table->opcode_rule->use_switch
- && table->parent != NULL /* don't declare the top one yet */
- && !table->parent->opcode_rule->use_switch) {
- lf_print_idecode_switch_function_header(file,
- table,
- 0/*isnt function definition*/);
- }
-}
-
-
-static void
-idecode_expand_if_switch(insn_table *table,
- void *data,
- int depth)
-{
- lf *file = (lf*)data;
-
- if (table->opcode_rule->use_switch
- && table->parent != NULL /* don't expand the top one yet */
- && !table->parent->opcode_rule->use_switch) {
- lf_print_idecode_switch_function_header(file,
- table,
- 1/*is function definition*/);
- lf_printf(file, "{\n");
- {
- lf_indent(file, +2);
- lf_print_idecode_switch(file, table);
- lf_indent(file, -2);
- }
- lf_printf(file, "}\n");
- }
-}
-
-
-static void
-lf_print_c_cracker_function(lf *file,
- insn *instruction,
- insn_bits *expanded_bits,
- opcode_field *opcodes,
- int is_inline_function)
-{
- /* if needed, generate code to enter this routine into a cache */
- lf_printf(file, "\n");
- lf_printf(file, "static idecode_semantic *\n");
- lf_print_function_name(file,
- instruction->file_entry->fields[insn_name],
- expanded_bits,
- function_name_prefix_idecode);
- lf_printf(file, "\n(%s)\n", cache_idecode_formal);
-
- lf_print_c_cracker(file,
- instruction,
- expanded_bits,
- opcodes);
-}
-
-static void
-idecode_crack_leaf(insn_table *entry,
- void *data,
- int depth)
-{
- lf *file = (lf*)data;
- ASSERT(entry->nr_insn == 1
- && entry->opcode == NULL
- && entry->parent != NULL
- && entry->parent->opcode != NULL
- && entry->parent->opcode_rule != NULL);
- lf_print_c_cracker_function(file,
- entry->insns,
- entry->expanded_bits,
- entry->opcode,
- entry->parent->opcode_rule->use_switch);
-}
-
-static void
-idecode_crack_insn(insn_table *entry,
- void *data,
- insn *instruction)
-{
- lf *file = (lf*)data;
- lf_print_c_cracker_function(file,
- instruction,
- NULL,
- NULL,
- 0/*isnt inline function*/);
-}
-
-static void
-idecode_c_internal_function(insn_table *table,
- void *data,
- table_entry *function)
-{
- lf *file = (lf*)data;
- ASSERT(idecode_cache != 0);
- if (it_is("internal", function->fields[insn_flags])) {
- lf_printf(file, "\n");
- lf_print_function_type(file, "idecode_semantic *", "STATIC_INLINE_IDECODE",
- "\n");
- lf_print_function_name(file,
- function->fields[insn_name],
- NULL,
- function_name_prefix_idecode);
- lf_printf(file, "\n(%s)\n", cache_idecode_formal);
- lf_printf(file, "{\n");
- lf_indent(file, +2);
- lf_printf(file, "/* semantic routine */\n");
- table_entry_lf_c_line_nr(file, function);
- lf_printf(file, "return ");
- lf_print_function_name(file,
- function->fields[insn_name],
- NULL,
- function_name_prefix_semantics);
- lf_printf(file, ";\n");
-
- lf_print_lf_c_line_nr(file);
- lf_indent(file, -2);
- lf_printf(file, "}\n");
- }
-}
-
-
-/****************************************************************/
-
-static void
-gen_idecode_c(insn_table *table, lf *file)
-{
- int depth;
-
- /* the intro */
- lf_print_copyleft(file);
- lf_printf(file, "\n");
- lf_printf(file, "\n");
- lf_printf(file, "#ifndef _IDECODE_C_\n");
- lf_printf(file, "#define _IDECODE_C_\n");
- lf_printf(file, "\n");
- lf_printf(file, "#include \"cpu.h\"\n");
- lf_printf(file, "#include \"idecode.h\"\n");
- lf_printf(file, "#include \"semantics.h\"\n");
- lf_printf(file, "\n");
- lf_printf(file, "\n");
- lf_printf(file, "typedef idecode_semantic *idecode_crack\n(%s);\n",
- (idecode_cache ? cache_idecode_formal : semantic_formal));
- lf_printf(file, "\n");
- lf_printf(file, "typedef struct _idecode_table_entry {\n");
- lf_printf(file, " unsigned shift;\n");
- lf_printf(file, " unsigned mask;\n");
- lf_printf(file, " void *function_or_table;\n");
- lf_printf(file, "} idecode_table_entry;\n");
- lf_printf(file, "\n");
- lf_printf(file, "\n");
-
- /* output `internal' invalid/floating-point unavailable functions
- where needed */
- if (idecode_cache) {
+ if ((code & generate_calls)
+ && (code & generate_with_icache)) {
insn_table_traverse_function(table,
- file,
- idecode_c_internal_function);
- }
-
- /* output cracking functions where needed */
- if (idecode_cache) {
- if (idecode_expand_semantics)
+ file, NULL,
+ print_icache_internal_function_declaration);
+ if (generate_expanded_instructions)
insn_table_traverse_tree(table,
- file,
+ file, NULL,
1,
- NULL,
- idecode_crack_leaf,
- NULL,
- NULL);
+ NULL, /* start */
+ print_icache_declaration, /* leaf */
+ NULL, /* end */
+ NULL); /* padding */
else
insn_table_traverse_insn(table,
- file,
- idecode_crack_insn);
- }
-
- /* output switch function declarations where needed by tables */
- insn_table_traverse_tree(table,
- file,
- 1,
- idecode_declare_if_switch, /* START */
- NULL, NULL, NULL);
-
- /* output tables where needed */
- for (depth = insn_table_depth(table);
- depth > 0;
- depth--) {
- insn_table_traverse_tree(table,
- file,
- 1-depth,
- idecode_table_start,
- idecode_table_leaf,
- idecode_table_end,
- idecode_table_padding);
- }
-
- /* output switch functions where needed */
- insn_table_traverse_tree(table,
- file,
- 1,
- idecode_expand_if_switch, /* START */
- NULL, NULL, NULL);
-
- /* output the main idecode routine */
- lf_printf(file, "\n");
- if (idecode_cache) {
- lf_print_function_type(file, "idecode_semantic *", "INLINE_IDECODE", "\n");
- lf_printf(file, "idecode\n(%s)\n", cache_idecode_formal);
+ file, NULL,
+ print_icache_declaration);
+
}
else {
- lf_print_function_type(file, "unsigned_word", "INLINE_IDECODE", "\n");
- lf_printf(file, "idecode_issue\n(%s)\n", semantic_formal);
- }
- lf_printf(file, "{\n");
- lf_indent(file, +2);
- if (table->opcode_rule->use_switch)
- lf_print_idecode_switch(file, table);
- else
- lf_print_idecode_table(file, table);
- lf_indent(file, -2);
- lf_printf(file, "}\n");
- lf_printf(file, "\n");
- lf_printf(file, "#endif /* _IDECODE_C_ */\n");
-}
-
-
-/****************************************************************/
-
-static void
-itable_h_insn(insn_table *entry,
- void *data,
- insn *instruction)
-{
- lf *file = (lf*)data;
- lf_printf(file, " ");
- lf_print_function_name(file,
- instruction->file_entry->fields[insn_name],
- NULL,
- function_name_prefix_itable);
- lf_printf(file, ",\n");
-}
-
-
-static void
-gen_itable_h(insn_table *table, lf *file)
-{
-
- lf_print_copyleft(file);
- lf_printf(file, "\n");
- lf_printf(file, "#ifndef _ITABLE_H_\n");
- lf_printf(file, "#define _ITABLE_H_\n");
- lf_printf(file, "\n");
-
- /* output an enumerated type for each instruction */
- lf_printf(file, "typedef enum {\n");
- insn_table_traverse_insn(table,
- file,
- itable_h_insn);
- lf_printf(file, " nr_itable_entries,\n");
- lf_printf(file, "} itable_index;\n");
- lf_printf(file, "\n");
-
- /* output the table that contains the actual instruction info */
- lf_printf(file, "typedef struct _itable_instruction_info {\n");
- lf_printf(file, " itable_index nr;\n");
- lf_printf(file, " char *format;\n");
- lf_printf(file, " char *form;\n");
- lf_printf(file, " char *flags;\n");
- lf_printf(file, " char *mnemonic;\n");
- lf_printf(file, " char *name;\n");
- lf_printf(file, "} itable_info;\n");
- lf_printf(file, "\n");
- lf_printf(file, "extern itable_info itable[nr_itable_entries];\n");
-
- lf_printf(file, "\n");
- lf_printf(file, "#endif /* _ITABLE_C_ */\n");
-
-}
-
-/****************************************************************/
-
-static void
-itable_c_insn(insn_table *entry,
- void *data,
- insn *instruction)
-{
- lf *file = (lf*)data;
- char **fields = instruction->file_entry->fields;
- lf_printf(file, " { ");
- lf_print_function_name(file,
- instruction->file_entry->fields[insn_name],
- NULL,
- function_name_prefix_itable);
- lf_printf(file, ",\n");
- lf_printf(file, " \"%s\",\n", fields[insn_format]);
- lf_printf(file, " \"%s\",\n", fields[insn_form]);
- lf_printf(file, " \"%s\",\n", fields[insn_flags]);
- lf_printf(file, " \"%s\",\n", fields[insn_mnemonic]);
- lf_printf(file, " \"%s\",\n", fields[insn_name]);
- lf_printf(file, " },\n");
-}
-
-
-static void
-gen_itable_c(insn_table *table, lf *file)
-{
-
- lf_print_copyleft(file);
- lf_printf(file, "\n");
- lf_printf(file, "#ifndef _ITABLE_C_\n");
- lf_printf(file, "#define _ITABLE_C_\n");
- lf_printf(file, "\n");
- lf_printf(file, "#include \"itable.h\"\n");
- lf_printf(file, "\n");
-
- /* output the table that contains the actual instruction info */
- lf_printf(file, "itable_info itable[nr_itable_entries] = {\n");
- insn_table_traverse_insn(table,
- file,
- itable_c_insn);
- lf_printf(file, "};\n");
- lf_printf(file, "\n");
-
- lf_printf(file, "\n");
- lf_printf(file, "#endif /* _ITABLE_C_ */\n");
-}
-
-/****************************************************************/
-
-static void
-model_c_or_h_data(insn_table *table,
- lf *file,
- table_entry *data)
-{
- if (data->annex) {
- table_entry_lf_c_line_nr(file, data);
- lf_print_c_code(file, data->annex);
- lf_print_lf_c_line_nr(file);
- lf_printf(file, "\n");
+ lf_print__this_file_is_empty(file);
}
}
static void
-model_c_or_h_function(insn_table *entry,
- lf *file,
- table_entry *function,
- char *prefix)
-{
- if (function->fields[function_type] == NULL
- || function->fields[function_type][0] == '\0') {
- error("Model function type not specified for %s", function->fields[function_name]);
- }
- lf_printf(file, "\n");
- lf_print_function_type(file, function->fields[function_type], prefix, " ");
- lf_printf(file, "%s\n(%s);\n",
- function->fields[function_name],
- function->fields[function_param]);
- lf_printf(file, "\n");
-}
-
-static void
-gen_model_h(insn_table *table, lf *file)
+gen_icache_c(insn_table *table,
+ cache_table *cache_rules,
+ lf *file,
+ igen_code generate)
{
- insn *insn_ptr;
- model *model_ptr;
- insn *macro;
- char *name;
- int model_create_p = 0;
- int model_init_p = 0;
- int model_halt_p = 0;
- int model_mon_info_p = 0;
- int model_mon_info_free_p = 0;
-
- lf_print_copyleft(file);
- lf_printf(file, "\n");
- lf_printf(file, "#ifndef _MODEL_H_\n");
- lf_printf(file, "#define _MODEL_H_\n");
- lf_printf(file, "\n");
-
- for(macro = model_macros; macro; macro = macro->next) {
- model_c_or_h_data(table, file, macro->file_entry);
- }
-
- lf_printf(file, "typedef enum _model_enum {\n");
- lf_printf(file, " MODEL_NONE,\n");
- for (model_ptr = models; model_ptr; model_ptr = model_ptr->next) {
- lf_printf(file, " MODEL_%s,\n", model_ptr->name);
- }
- lf_printf(file, " nr_models\n");
- lf_printf(file, "} model_enum;\n");
- lf_printf(file, "\n");
-
- lf_printf(file, "#define DEFAULT_MODEL MODEL_%s\n", (models) ? models->name : "NONE");
- lf_printf(file, "\n");
-
- lf_printf(file, "typedef struct _model_data model_data;\n");
- lf_printf(file, "typedef struct _model_time model_time;\n");
- lf_printf(file, "\n");
-
- lf_printf(file, "extern model_enum current_model;\n");
- lf_printf(file, "extern const char *model_name[ (int)nr_models ];\n");
- lf_printf(file, "extern const char *const *const model_func_unit_name[ (int)nr_models ];\n");
- lf_printf(file, "extern const model_time *const model_time_mapping[ (int)nr_models ];\n");
- lf_printf(file, "\n");
-
- for(insn_ptr = model_functions; insn_ptr; insn_ptr = insn_ptr->next) {
- model_c_or_h_function(table, file, insn_ptr->file_entry, "INLINE_MODEL");
- name = insn_ptr->file_entry->fields[function_name];
- if (strcmp (name, "model_create") == 0)
- model_create_p = 1;
- else if (strcmp (name, "model_init") == 0)
- model_init_p = 1;
- else if (strcmp (name, "model_halt") == 0)
- model_halt_p = 1;
- else if (strcmp (name, "model_mon_info") == 0)
- model_mon_info_p = 1;
- else if (strcmp (name, "model_mon_info_free") == 0)
- model_mon_info_free_p = 1;
- }
-
- if (!model_create_p) {
- lf_print_function_type(file, "model_data *", "INLINE_MODEL", " ");
- lf_printf(file, "model_create\n");
- lf_printf(file, "(cpu *processor);\n");
- lf_printf(file, "\n");
- }
-
- if (!model_init_p) {
- lf_print_function_type(file, "void", "INLINE_MODEL", " ");
- lf_printf(file, "model_init\n");
- lf_printf(file, "(model_data *model_ptr);\n");
- lf_printf(file, "\n");
- }
-
- if (!model_halt_p) {
- lf_print_function_type(file, "void", "INLINE_MODEL", " ");
- lf_printf(file, "model_halt\n");
- lf_printf(file, "(model_data *model_ptr);\n");
+ /* output `internal' invalid/floating-point unavailable functions
+ where needed */
+ if ((code & generate_calls)
+ && (code & generate_with_icache)) {
lf_printf(file, "\n");
- }
-
- if (!model_mon_info_p) {
- lf_print_function_type(file, "model_print *", "INLINE_MODEL", " ");
- lf_printf(file, "model_mon_info\n");
- lf_printf(file, "(model_data *model_ptr);\n");
+ lf_printf(file, "#include \"cpu.h\"\n");
+ lf_printf(file, "#include \"idecode.h\"\n");
+ lf_printf(file, "#include \"semantics.h\"\n");
+ lf_printf(file, "#include \"icache.h\"\n");
+ lf_printf(file, "#include \"support.h\"\n");
lf_printf(file, "\n");
- }
-
- if (!model_mon_info_free_p) {
- lf_print_function_type(file, "void", "INLINE_MODEL", " ");
- lf_printf(file, "model_mon_info_free\n");
- lf_printf(file, "(model_data *model_ptr,\n");
- lf_printf(file, " model_print *info_ptr);\n");
+ insn_table_traverse_function(table,
+ file, NULL,
+ print_icache_internal_function_definition);
lf_printf(file, "\n");
- }
-
- lf_print_function_type(file, "void", "INLINE_MODEL", " ");
- lf_printf(file, "model_set\n");
- lf_printf(file, "(const char *name);\n");
- lf_printf(file, "\n");
- lf_printf(file, "#endif /* _MODEL_H_ */\n");
-}
-
-/****************************************************************/
-
-typedef struct _model_c_passed_data model_c_passed_data;
-struct _model_c_passed_data {
- lf *file;
- model *model_ptr;
-};
-
-static void
-model_c_insn(insn_table *entry,
- void *data,
- insn *instruction)
-{
- model_c_passed_data *data_ptr = (model_c_passed_data *)data;
- lf *file = data_ptr->file;
- char *current_name = data_ptr->model_ptr->printable_name;
- table_model_entry *model_ptr = instruction->file_entry->model_first;
-
- while (model_ptr) {
- if (model_ptr->fields[insn_model_name] == current_name) {
- lf_printf(file, " { %-*s }, /* %s */\n",
- max_model_fields_len,
- model_ptr->fields[insn_model_fields],
- instruction->file_entry->fields[insn_name]);
- return;
- }
-
- model_ptr = model_ptr->next;
- }
-
- lf_printf(file, " { %-*s }, /* %s */\n",
- max_model_fields_len,
- data_ptr->model_ptr->insn_default,
- instruction->file_entry->fields[insn_name]);
-}
-
-static void
-model_c_function(insn_table *table,
- lf *file,
- table_entry *function,
- const char *prefix)
-{
- if (function->fields[function_type] == NULL
- || function->fields[function_type][0] == '\0') {
- error("Model function return type not specified for %s", function->fields[function_name]);
+ if (generate_expanded_instructions)
+ insn_table_traverse_tree(table,
+ file, cache_rules,
+ 1,
+ NULL, /* start */
+ print_icache_definition, /* leaf */
+ NULL, /* end */
+ NULL); /* padding */
+ else
+ insn_table_traverse_insn(table,
+ file, cache_rules,
+ print_icache_definition);
+
}
else {
- lf_printf(file, "\n");
- lf_print_function_type(file, function->fields[function_type], prefix, "\n");
- lf_printf(file, "%s(%s)\n",
- function->fields[function_name],
- function->fields[function_param]);
- }
- table_entry_lf_c_line_nr(file, function);
- lf_printf(file, "{\n");
- if (function->annex) {
- lf_indent(file, +2);
- lf_print_c_code(file, function->annex);
- lf_indent(file, -2);
+ lf_print__this_file_is_empty(file);
}
- lf_printf(file, "}\n");
- lf_print_lf_c_line_nr(file);
- lf_printf(file, "\n");
}
-static void
-gen_model_c(insn_table *table, lf *file)
-{
- insn *insn_ptr;
- model *model_ptr;
- char *name;
- int model_create_p = 0;
- int model_init_p = 0;
- int model_halt_p = 0;
- int model_mon_info_p = 0;
- int model_mon_info_free_p = 0;
-
- lf_print_copyleft(file);
- lf_printf(file, "\n");
- lf_printf(file, "#ifndef _MODEL_C_\n");
- lf_printf(file, "#define _MODEL_C_\n");
- lf_printf(file, "\n");
- lf_printf(file, "#include \"cpu.h\"\n");
- lf_printf(file, "#include \"mon.h\"\n");
- lf_printf(file, "\n");
- lf_printf(file, "#ifdef HAVE_STDLIB_H\n");
- lf_printf(file, "#include <stdlib.h>\n");
- lf_printf(file, "#endif\n");
- lf_printf(file, "\n");
-
- for(insn_ptr = model_data; insn_ptr; insn_ptr = insn_ptr->next) {
- model_c_or_h_data(table, file, insn_ptr->file_entry);
- }
-
- for(insn_ptr = model_static; insn_ptr; insn_ptr = insn_ptr->next) {
- model_c_or_h_function(table, file, insn_ptr->file_entry, "/*h*/STATIC");
- }
-
- for(insn_ptr = model_internal; insn_ptr; insn_ptr = insn_ptr->next) {
- model_c_or_h_function(table, file, insn_ptr->file_entry, "STATIC_INLINE_MODEL");
- }
-
- for(insn_ptr = model_static; insn_ptr; insn_ptr = insn_ptr->next) {
- model_c_function(table, file, insn_ptr->file_entry, "/*c*/STATIC");
- }
-
- for(insn_ptr = model_internal; insn_ptr; insn_ptr = insn_ptr->next) {
- model_c_function(table, file, insn_ptr->file_entry, "STATIC_INLINE_MODEL");
- }
-
- for(insn_ptr = model_functions; insn_ptr; insn_ptr = insn_ptr->next) {
- model_c_function(table, file, insn_ptr->file_entry, "INLINE_MODEL");
- name = insn_ptr->file_entry->fields[function_name];
- if (strcmp (name, "model_create") == 0)
- model_create_p = 1;
- else if (strcmp (name, "model_init") == 0)
- model_init_p = 1;
- else if (strcmp (name, "model_halt") == 0)
- model_halt_p = 1;
- else if (strcmp (name, "model_mon_info") == 0)
- model_mon_info_p = 1;
- else if (strcmp (name, "model_mon_info_free") == 0)
- model_mon_info_free_p = 1;
- }
-
- if (!model_create_p) {
- lf_print_function_type(file, "model_data *", "INLINE_MODEL", "\n");
- lf_printf(file, "model_create(cpu *processor)\n");
- lf_printf(file, "{\n");
- lf_printf(file, " return (model_data *)0;\n");
- lf_printf(file, "}\n");
- lf_printf(file, "\n");
- }
-
- if (!model_init_p) {
- lf_print_function_type(file, "void", "INLINE_MODEL", "\n");
- lf_printf(file, "model_init(model_data *model_ptr)\n");
- lf_printf(file, "{\n");
- lf_printf(file, "}\n");
- lf_printf(file, "\n");
- }
-
- if (!model_halt_p) {
- lf_print_function_type(file, "void", "INLINE_MODEL", "\n");
- lf_printf(file, "model_halt(model_data *model_ptr)\n");
- lf_printf(file, "{\n");
- lf_printf(file, "}\n");
- lf_printf(file, "\n");
- }
-
- if (!model_mon_info_p) {
- lf_print_function_type(file, "model_print *", "INLINE_MODEL", "\n");
- lf_printf(file, "model_mon_info(model_data *model_ptr)\n");
- lf_printf(file, "{\n");
- lf_printf(file, " return (model_print *)0;\n");
- lf_printf(file, "}\n");
- lf_printf(file, "\n");
- }
-
- if (!model_mon_info_free_p) {
- lf_print_function_type(file, "void", "INLINE_MODEL", "\n");
- lf_printf(file, "model_mon_info_free(model_data *model_ptr,\n");
- lf_printf(file, " model_print *info_ptr)\n");
- lf_printf(file, "{\n");
- lf_printf(file, "}\n");
- lf_printf(file, "\n");
- }
-
- lf_printf(file, "/* Insn functional unit info */\n");
- for(model_ptr = models; model_ptr; model_ptr = model_ptr->next) {
- model_c_passed_data data;
-
- lf_printf(file, "static const model_time model_time_%s[] = {\n", model_ptr->name);
- data.file = file;
- data.model_ptr = model_ptr;
- insn_table_traverse_insn(table,
- (void *)&data,
- model_c_insn);
-
- lf_printf(file, "};\n");
- lf_printf(file, "\n");
- lf_printf(file, "\f\n");
- }
-
- lf_printf(file, "#ifndef _INLINE_C_\n");
- lf_printf(file, "const model_time *const model_time_mapping[ (int)nr_models ] = {\n");
- lf_printf(file, " (const model_time *const)0,\n");
- for(model_ptr = models; model_ptr; model_ptr = model_ptr->next) {
- lf_printf(file, " model_time_%s,\n", model_ptr->name);
- }
- lf_printf(file, "};\n");
- lf_printf(file, "#endif\n");
- lf_printf(file, "\n");
-
- lf_printf(file, "\f\n");
- lf_printf(file, "/* map model enumeration into printable string */\n");
- lf_printf(file, "#ifndef _INLINE_C_\n");
- lf_printf(file, "const char *model_name[ (int)nr_models ] = {\n");
- lf_printf(file, " \"NONE\",\n");
- for (model_ptr = models; model_ptr; model_ptr = model_ptr->next) {
- lf_printf(file, " \"%s\",\n", model_ptr->printable_name);
- }
- lf_printf(file, "};\n");
- lf_printf(file, "#endif\n");
- lf_printf(file, "\n");
-
- lf_print_function_type(file, "void", "INLINE_MODEL", "\n");
- lf_printf(file, "model_set(const char *name)\n");
- lf_printf(file, "{\n");
- if (models) {
- lf_printf(file, " model_enum model;\n");
- lf_printf(file, " for(model = MODEL_%s; model < nr_models; model++) {\n", models->name);
- lf_printf(file, " if(strcmp(name, model_name[model]) == 0) {\n");
- lf_printf(file, " current_model = model;\n");
- lf_printf(file, " return;\n");
- lf_printf(file, " }\n");
- lf_printf(file, " }\n");
- lf_printf(file, "\n");
- lf_printf(file, " error(\"Unknown model '%%s', Models which are known are:%%s\n\",\n");
- lf_printf(file, " name,\n");
- lf_printf(file, " \"");
- for(model_ptr = models; model_ptr; model_ptr = model_ptr->next) {
- lf_printf(file, "\\n\\t%s", model_ptr->printable_name);
- }
- lf_printf(file, "\");\n");
- } else {
- lf_printf(file, " error(\"No models are currently known about\");\n");
- }
-
- lf_printf(file, "}\n");
- lf_printf(file, "\n");
-
- lf_printf(file, "#endif /* _MODEL_C_ */\n");
-
-}
/****************************************************************/
@@ -3327,140 +319,172 @@ main(int argc,
char **argv,
char **envp)
{
+ cache_table *cache_rules = NULL;
+ lf_file_references file_references = lf_include_references;
+ decode_table *decode_rules = NULL;
+ filter *filters = NULL;
insn_table *instructions = NULL;
- icache_tree *cache_fields = NULL;
char *real_file_name = NULL;
+ int is_header = 0;
int ch;
if (argc == 1) {
printf("Usage:\n");
printf(" igen <config-opts> ... <input-opts>... <output-opts>...\n");
printf("Config options:\n");
- printf(" -f <filter-out-flag> eg -f 64 to skip 64bit instructions\n");
- printf(" -e Expand (duplicate) semantic functions\n");
- printf(" -r <icache-size> Generate cracking cache version\n");
+ printf(" -F <filter-out-flag> eg -F 64 to skip 64bit instructions\n");
+ printf(" -E Expand (duplicate) semantic functions\n");
+ printf(" -I <icache-size> Generate cracking cache version\n");
+ printf(" -C Include semantics in cache functions\n");
+ printf(" -S Include insn (instruction) in icache\n");
printf(" -R Use defines to reference cache vars\n");
- printf(" -l Supress line numbering in output files\n");
- printf(" -b <bit-size> Set the number of bits in an instruction\n");
- printf(" -h <high-bit> Set the nr of the high (msb bit)\n");
+ printf(" -L Supress line numbering in output files\n");
+ printf(" -B <bit-size> Set the number of bits in an instruction\n");
+ printf(" -H <high-bit> Set the nr of the high (msb bit)\n");
+ printf(" -N <nr-cpus> Specify the max number of cpus the simulation will support\n");
+ printf(" -J Use jumps instead of function calls\n");
+ printf(" -T <mechanism> Override the mechanism used to decode an instruction\n");
+ printf(" using <mechanism> instead of what was specified in the\n");
+ printf(" decode-rules input file\n");
printf("\n");
printf("Input options (ucase version also dumps loaded table):\n");
- printf(" -[Oo] <opcode-rules>\n");
- printf(" -[Kk] <cache-rules>\n");
- printf(" -[Ii] <instruction-table>\n");
+ printf(" -o <decode-rules>\n");
+ printf(" -k <cache-rules>\n");
+ printf(" -i <instruction-table>\n");
printf("\n");
printf("Output options:\n");
- printf(" -[Cc] <output-file> output icache.h(C) invalid(c)\n");
- printf(" -[Dd] <output-file> output idecode.h(D) idecode.c(d)\n");
- printf(" -[Mm] <output-file> output model.h(M) model.c(M)\n");
- printf(" -[Ss] <output-file> output schematic.h(S) schematic.c(s)\n");
- printf(" -[Tt] <table> output itable.h(T) itable.c(t)\n");
+ printf(" -n <real-name> Specify the real name of for the next output file\n");
+ printf(" -h Generate header file\n");
+ printf(" -c <output-file> output icache\n");
+ printf(" -d <output-file> output idecode\n");
+ printf(" -m <output-file> output model\n");
+ printf(" -s <output-file> output schematic\n");
+ printf(" -t <output-file> output itable\n");
+ printf(" -f <output-file> output support functions\n");
}
while ((ch = getopt(argc, argv,
- "leb:h:r:Rf:I:i:O:o:K:k:M:m:n:S:s:D:d:T:t:C:")) != -1) {
+ "F:EI:RSLJT:CB:H:N:o:k:i:n:hc:d:m:s:t:f:"))
+ != -1) {
fprintf(stderr, "\t-%c %s\n", ch, (optarg ? optarg : ""));
switch(ch) {
- case 'l':
- number_lines = 0;
+ case 'C':
+ code |= generate_with_icache;
+ code |= generate_with_semantic_icache;
+ break;
+ case 'S':
+ code |= generate_with_icache;
+ code |= generate_with_insn_in_icache;
+ break;
+ case 'L':
+ file_references = lf_omit_references;
break;
- case 'e':
- idecode_expand_semantics = 1;
+ case 'E':
+ generate_expanded_instructions = 1;
+ break;
+ case 'I':
+ icache_size = a2i(optarg);
+ code |= generate_with_icache;
break;
- case 'r':
- idecode_cache = a2i(optarg);
+ case 'N':
+ generate_smp = a2i(optarg);
break;
case 'R':
- semantics_use_cache_struct = 1;
+ code |= generate_with_direct_access;
break;
- case 'b':
- insn_size = a2i(optarg);
- ASSERT(insn_size > 0 && insn_size <= max_insn_size
- && (hi_bit_nr == insn_size-1 || hi_bit_nr == 0));
+ case 'B':
+ insn_bit_size = a2i(optarg);
+ ASSERT(insn_bit_size > 0 && insn_bit_size <= max_insn_bit_size
+ && (hi_bit_nr == insn_bit_size-1 || hi_bit_nr == 0));
break;
- case 'h':
+ case 'H':
hi_bit_nr = a2i(optarg);
- ASSERT(hi_bit_nr == insn_size-1 || hi_bit_nr == 0);
+ ASSERT(hi_bit_nr == insn_bit_size-1 || hi_bit_nr == 0);
+ break;
+ case 'F':
+ filters = new_filter(optarg, filters);
+ break;
+ case 'J':
+ code &= ~generate_calls;
+ code |= generate_jumps;
+ break;
+ case 'T':
+ force_decode_gen_type(optarg);
break;
- case 'f':
- {
- filter *new_filter = ZALLOC(filter);
- new_filter->flag = strdup(optarg);
- new_filter->next = filters;
- filters = new_filter;
- break;
- }
- case 'I':
case 'i':
- ASSERT(opcode_table != NULL);
- ASSERT(cache_table != NULL);
- instructions = insn_table_load_insns(optarg);
+ if (decode_rules == NULL || cache_rules == NULL) {
+ fprintf(stderr, "Must specify decode and cache tables\n");
+ exit (1);
+ }
+ instructions = load_insn_table(optarg, decode_rules, filters);
fprintf(stderr, "\texpanding ...\n");
insn_table_expand_insns(instructions);
- fprintf(stderr, "\tcache fields ...\n");
- cache_fields = insn_table_cache_fields(instructions);
- if (ch == 'I') {
- dump_traverse(instructions);
- dump_insn_table(instructions, 0, 1);
- }
break;
- case 'O':
case 'o':
- opcode_table = load_opcode_rules(optarg);
- if (ch == 'O')
- dump_opcode_rules(opcode_table, 0);
+ decode_rules = load_decode_table(optarg, hi_bit_nr);
break;
- case 'K':
case 'k':
- cache_table = load_cache_rules(optarg);
- if (ch == 'K')
- dump_cache_rules(cache_table, 0);
+ cache_rules = load_cache_table(optarg, hi_bit_nr);
break;
case 'n':
real_file_name = strdup(optarg);
break;
- case 'S':
+ case 'h':
+ is_header = 1;
+ break;
case 's':
- case 'D':
case 'd':
- case 'M':
case 'm':
- case 'T':
case 't':
- case 'C':
+ case 'f':
+ case 'c':
{
- lf *file = lf_open(optarg, real_file_name, number_lines);
+ lf *file = lf_open(optarg, real_file_name, file_references,
+ (is_header ? lf_is_h : lf_is_c),
+ argv[0]);
+ lf_print__file_start(file);
ASSERT(instructions != NULL);
switch (ch) {
- case 'S':
- gen_semantics_h(instructions, file);
- break;
case 's':
- gen_semantics_c(instructions, file);
- break;
- case 'D':
- gen_idecode_h(instructions, file);
+ if(is_header)
+ gen_semantics_h(instructions, file, code);
+ else
+ gen_semantics_c(instructions, cache_rules, file, code);
break;
case 'd':
- gen_idecode_c(instructions, file);
- break;
- case 'M':
- gen_model_h(instructions, file);
+ if (is_header)
+ gen_idecode_h(file, instructions, cache_rules);
+ else
+ gen_idecode_c(file, instructions, cache_rules);
break;
case 'm':
- gen_model_c(instructions, file);
- break;
- case 'T':
- gen_itable_h(instructions, file);
+ if (is_header)
+ gen_model_h(instructions, file);
+ else
+ gen_model_c(instructions, file);
break;
case 't':
- gen_itable_c(instructions, file);
+ if (is_header)
+ gen_itable_h(instructions, file);
+ else
+ gen_itable_c(instructions, file);
+ break;
+ case 'f':
+ if (is_header)
+ gen_support_h(instructions, file);
+ else
+ gen_support_c(instructions, file);
break;
- case 'C':
- gen_icache_h(cache_fields, file);
+ case 'c':
+ if (is_header)
+ gen_icache_h(instructions, file, code);
+ else
+ gen_icache_c(instructions, cache_rules, file, code);
break;
}
+ lf_print__file_finish(file);
lf_close(file);
+ is_header = 0;
}
real_file_name = NULL;
break;
diff --git a/gnu/dist/sim/ppc/igen.h b/gnu/dist/sim/ppc/igen.h
new file mode 100644
index 00000000000..d3462098905
--- /dev/null
+++ b/gnu/dist/sim/ppc/igen.h
@@ -0,0 +1,199 @@
+/* This file is part of the program psim.
+
+ Copyright (C) 1994,1995,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.
+
+ */
+
+
+/* What does the instruction look like - bit ordering and size */
+extern int hi_bit_nr;
+extern int insn_bit_size;
+
+
+/* generation options: */
+
+
+enum {
+ generate_with_direct_access = 0x1,
+ generate_with_icache = 0x2,
+ generate_with_semantic_icache = 0x4,
+ generate_with_insn_in_icache = 0x8,
+};
+
+
+typedef enum {
+
+ /* Transfer control to an instructions semantic code using the the
+ standard call/return mechanism */
+
+ generate_calls = 0x100,
+
+ /* In addition, when refering to fields access them directly instead
+ of via variables */
+
+ generate_calls_with_direct_access
+ = generate_calls | generate_with_direct_access,
+
+ /* In addition, pre-decode an instructions opcode fields (entering
+ them into an icache) so that semantic code can avoid the need to
+ re-decode fields each time it is executed */
+
+ generate_calls_with_icache
+ = generate_calls | generate_with_icache,
+
+ /* In addition, the instruction decode code includes a duplicated
+ copy of the instructions semantic code. This avoids the need to
+ perform two calls (one to decode an instructions opcode fields
+ and one to execute the instruction) when there is a miss of the
+ icache */
+
+ generate_calls_with_semantic_icache
+ = generate_calls_with_icache | generate_with_semantic_icache,
+
+ /* In addition, the semantic function refers to icache entries
+ directly instead of first moving them into local variables */
+
+ generate_calls_with_direct_access_icache
+ = generate_calls_with_icache | generate_with_direct_access,
+
+ generate_calls_with_direct_access_semantic_icache
+ = generate_calls_with_direct_access_icache | generate_with_semantic_icache,
+
+
+ /* Transfer control to an instructions semantic code using
+ (computed) goto's instead of the more conventional call/return
+ mechanism */
+
+ generate_jumps = 0x200,
+
+ /* As for generate jumps but with instruction fields accessed
+ directly */
+
+ generate_jumps_with_direct_access
+ = generate_jumps | generate_with_direct_access,
+
+ /* As for generate_calls_with_icache but applies to jumping code */
+
+ generate_jumps_with_icache
+ = generate_jumps | generate_with_icache,
+
+ /* As for generate_calls_with_semantic_icache but applies to jumping
+ code */
+
+ generate_jumps_with_semantic_icache
+ = generate_jumps_with_icache | generate_with_semantic_icache,
+
+ /* As for generate_calls_with_direct_access */
+
+ generate_jumps_with_direct_access_icache
+ = generate_jumps_with_icache | generate_with_direct_access,
+
+ generate_jumps_with_direct_access_semantic_icache
+ = generate_jumps_with_direct_access_icache | generate_with_semantic_icache,
+
+} igen_code;
+
+extern igen_code code;
+
+
+
+
+extern int icache_size;
+
+
+/* Instruction expansion?
+
+ Should the semantic code for each instruction, when the oportunity
+ arrises, be expanded according to the variable opcode files that
+ the instruction decode process renders constant */
+
+extern int generate_expanded_instructions;
+
+
+/* SMP?
+
+ Should the generated code include SMP support (>0) and if so, for
+ how many processors? */
+
+extern int generate_smp;
+
+
+
+
+/* Misc junk */
+
+
+
+/* Function header definitions */
+
+
+/* Cache functions: */
+
+#define ICACHE_FUNCTION_FORMAL \
+"cpu *processor,\n\
+ instruction_word instruction,\n\
+ unsigned_word cia,\n\
+ idecode_cache *cache_entry"
+
+#define ICACHE_FUNCTION_ACTUAL "processor, instruction, cia, cache_entry"
+
+#define ICACHE_FUNCTION_TYPE \
+((code & generate_with_semantic_icache) \
+ ? SEMANTIC_FUNCTION_TYPE \
+ : "idecode_semantic *")
+
+
+/* Semantic functions: */
+
+#define SEMANTIC_FUNCTION_FORMAL \
+((code & generate_with_icache) \
+ ? "cpu *processor,\n idecode_cache *cache_entry,\n unsigned_word cia" \
+ : "cpu *processor,\n instruction_word instruction,\n unsigned_word cia")
+
+#define SEMANTIC_FUNCTION_ACTUAL \
+((code & generate_with_icache) \
+ ? "processor, instruction, cia, cache_entry" \
+ : "processor, instruction, cia")
+
+#define SEMANTIC_FUNCTION_TYPE "unsigned_word"
+
+
+
+extern void print_my_defines
+(lf *file,
+ insn_bits *expanded_bits,
+ table_entry *file_entry);
+
+extern void print_itrace
+(lf *file,
+ table_entry *file_entry,
+ int idecode);
+
+
+typedef enum {
+ function_name_prefix_semantics,
+ function_name_prefix_idecode,
+ function_name_prefix_itable,
+ function_name_prefix_icache,
+ function_name_prefix_none
+} lf_function_name_prefixes;
+
+extern int print_function_name
+(lf *file,
+ const char *basename,
+ insn_bits *expanded_bits,
+ lf_function_name_prefixes prefix);
diff --git a/gnu/dist/sim/ppc/inline.c b/gnu/dist/sim/ppc/inline.c
index 579859e5315..43595a53424 100644
--- a/gnu/dist/sim/ppc/inline.c
+++ b/gnu/dist/sim/ppc/inline.c
@@ -75,6 +75,10 @@
#include "device.c"
#endif
+#if (TREE_INLINE & INCLUDE_MODULE)
+#include "tree.c"
+#endif
+
#if (SPREG_INLINE & INCLUDE_MODULE)
#include "spreg.c"
#endif
diff --git a/gnu/dist/sim/ppc/inline.h b/gnu/dist/sim/ppc/inline.h
index 8b3771a8f38..f88cd9e4904 100644
--- a/gnu/dist/sim/ppc/inline.h
+++ b/gnu/dist/sim/ppc/inline.h
@@ -70,28 +70,6 @@
#endif
-/* icache is inlined with inline.c */
-
-#if defined(_INLINE_C_) && !defined(_ICACHE_C_) && (ICACHE_INLINE & INCLUDE_MODULE)
-# if (ICACHE_INLINE & INLINE_MODULE)
-# define INLINE_ICACHE(TYPE) static INLINE TYPE UNUSED
-# define EXTERN_ICACHE(TYPE) static TYPE UNUSED
-#else
-# define INLINE_ICACHE(TYPE) static TYPE UNUSED
-# define EXTERN_ICACHE(TYPE) static TYPE UNUSED
-#endif
-#else
-# define INLINE_ICACHE(TYPE) TYPE
-# define EXTERN_ICACHE(TYPE) TYPE
-#endif
-
-#if (ICACHE_INLINE & INLINE_LOCALS)
-# define STATIC_INLINE_ICACHE(TYPE) static INLINE TYPE
-#else
-# define STATIC_INLINE_ICACHE(TYPE) static TYPE
-#endif
-
-
/* core is inlined with inline.c */
#if defined(_INLINE_C_) && !defined(_CORE_C_) && (CORE_INLINE & INCLUDE_MODULE)
@@ -290,6 +268,28 @@
#endif
+/* tree is inlined with inline.c */
+
+#if defined(_INLINE_C_) && !defined(_TREE_C_) && (TREE_INLINE & INCLUDE_MODULE)
+# if (TREE_INLINE & INLINE_MODULE)
+# define INLINE_TREE(TYPE) static INLINE TYPE UNUSED
+# define EXTERN_TREE(TYPE) static TYPE UNUSED
+#else
+# define INLINE_TREE(TYPE) static TYPE UNUSED
+# define EXTERN_TREE(TYPE) static TYPE UNUSED
+#endif
+#else
+# define INLINE_TREE(TYPE) TYPE
+# define EXTERN_TREE(TYPE) TYPE
+#endif
+
+#if (TREE_INLINE & INLINE_LOCALS)
+# define STATIC_INLINE_TREE(TYPE) static INLINE TYPE
+#else
+# define STATIC_INLINE_TREE(TYPE) static TYPE
+#endif
+
+
/* spreg is inlined with inline.c */
#if defined(_INLINE_C_) && !defined(_SPREG_C_) && (SPREG_INLINE & INCLUDE_MODULE)
@@ -334,7 +334,7 @@
#endif
-/* idecode is inlined with inline.c */
+/* idecode is actually not inlined */
#if defined(_INLINE_C_) && !defined(_IDECODE_C_) && (IDECODE_INLINE & INCLUDE_MODULE)
# if (IDECODE_INLINE & INLINE_MODULE)
@@ -356,6 +356,50 @@
#endif
+/* icache is inlined with inline.c */
+
+#if defined(_INLINE_C_) && !defined(_ICACHE_C_) && (ICACHE_INLINE & INCLUDE_MODULE)
+# if (ICACHE_INLINE & INLINE_MODULE)
+# define INLINE_ICACHE(TYPE) static INLINE TYPE UNUSED
+# define EXTERN_ICACHE(TYPE) static TYPE UNUSED REGPARM
+#else
+# define INLINE_ICACHE(TYPE) static TYPE UNUSED REGPARM
+# define EXTERN_ICACHE(TYPE) static TYPE UNUSED REGPARM
+#endif
+#else
+# define INLINE_ICACHE(TYPE) TYPE REGPARM
+# define EXTERN_ICACHE(TYPE) TYPE REGPARM
+#endif
+
+#if (ICACHE_INLINE & INLINE_LOCALS)
+# define STATIC_INLINE_ICACHE(TYPE) static INLINE TYPE
+#else
+# define STATIC_INLINE_ICACHE(TYPE) static TYPE REGPARM
+#endif
+
+
+/* support is always inlined */
+
+#if !defined(_SUPPORT_C_) && (SUPPORT_INLINE & INCLUDE_MODULE)
+# if (SUPPORT_INLINE & INLINE_MODULE)
+# define INLINE_SUPPORT(TYPE) static INLINE TYPE UNUSED
+# define EXTERN_SUPPORT(TYPE) static TYPE UNUSED
+#else
+# define INLINE_SUPPORT(TYPE) static TYPE UNUSED
+# define EXTERN_SUPPORT(TYPE) static TYPE UNUSED
+#endif
+#else
+# define INLINE_SUPPORT(TYPE) TYPE
+# define EXTERN_SUPPORT(TYPE) TYPE
+#endif
+
+#if (SUPPORT_INLINE & INLINE_LOCALS)
+# define STATIC_INLINE_SUPPORT(TYPE) static INLINE TYPE
+#else
+# define STATIC_INLINE_SUPPORT(TYPE) static TYPE
+#endif
+
+
/* options is inlined with inline.c */
#if defined(_INLINE_C_) && !defined(_OPTIONS_C_) && (OPTIONS_INLINE & INCLUDE_MODULE)
@@ -400,7 +444,7 @@
#endif
-/* psim is inlined with inline.c */
+/* psim is actually not inlined */
#if defined(_INLINE_C_) && !defined(_PSIM_C_) && (PSIM_INLINE & INCLUDE_MODULE)
# if (PSIM_INLINE & INLINE_MODULE)
diff --git a/gnu/dist/sim/ppc/interrupts.c b/gnu/dist/sim/ppc/interrupts.c
index 01dc9c91e02..3079d3c2b0f 100644
--- a/gnu/dist/sim/ppc/interrupts.c
+++ b/gnu/dist/sim/ppc/interrupts.c
@@ -1,6 +1,6 @@
/* This file is part of the program psim.
- Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
+ 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
@@ -71,8 +71,8 @@ interrupt_srr1(msreg old_msr,
msreg srr1_set)
{
spreg srr1_mask = (MASK(0,32)
- | MASK(37, 41)
- | MASK(48, 63));
+ | MASK(37, 41)
+ | MASK(48, 63));
spreg srr1 = (old_msr & srr1_mask & ~srr1_clear) | srr1_set;
return srr1;
}
@@ -105,14 +105,21 @@ perform_oea_interrupt(cpu *processor,
msreg old_msr = MSR;
msreg new_msr = interrupt_msr(old_msr, msr_clear, msr_set);
unsigned_word nia;
- if (!(old_msr & msr_recoverable_interrupt))
- error("perform_oea_interrupt() recoverable_interrupt bit clear, cia=0x%x, msr=0x%x\n",
- cia, old_msr);
+ if (!(old_msr & msr_recoverable_interrupt)) {
+ cpu_error(processor, cia,
+ "double interrupt - MSR[RI] bit clear when attempting to deliver interrupt, cia=0x%lx, msr=0x%lx; srr0=0x%lx(cia), srr1=0x%lx(msr); trap-vector=0x%lx, trap-msr=0x%lx",
+ (unsigned long)cia,
+ (unsigned long)old_msr,
+ (unsigned long)SRR0,
+ (unsigned long)SRR1,
+ (unsigned long)vector_offset,
+ (unsigned long)new_msr);
+ }
SRR0 = (spreg)(cia);
SRR1 = interrupt_srr1(old_msr, srr1_clear, srr1_set);
MSR = new_msr;
nia = interrupt_base_ea(new_msr) + vector_offset;
- cpu_synchronize_context(processor);
+ cpu_synchronize_context(processor, cia);
return nia;
}
@@ -126,15 +133,16 @@ machine_check_interrupt(cpu *processor,
case USER_ENVIRONMENT:
case VIRTUAL_ENVIRONMENT:
- error("%s - cia=0x%x\n",
- "machine_check_interrupt", cia);
+ cpu_error(processor, cia, "machine-check interrupt");
case OPERATING_ENVIRONMENT:
+ TRACE(trace_interrupts, ("machine-check interrupt - cia=0x%lx\n",
+ (unsigned long)cia));
cia = perform_oea_interrupt(processor, cia, 0x00200, 0, 0, 0, 0);
cpu_restart(processor, cia);
default:
- error("machine_check_interrupt() - internal error\n");
+ error("internal error - machine_check_interrupt - bad switch");
}
}
@@ -152,7 +160,8 @@ data_storage_interrupt(cpu *processor,
case USER_ENVIRONMENT:
case VIRTUAL_ENVIRONMENT:
- error("data_storage_interrupt() should not be called in VEA mode\n");
+ error("internal error - data_storage_interrupt - should not be called in VEA mode");
+ break;
case OPERATING_ENVIRONMENT:
{
@@ -177,16 +186,20 @@ data_storage_interrupt(cpu *processor,
DSISR = dsisr_earwax_disabled | direction;
break;
default:
- error("data_storage_interrupt: unknown reason %d\n", reason);
+ error("internal error - data_storage_interrupt - reason %d not implemented", reason);
break;
}
DAR = (spreg)ea;
+ TRACE(trace_interrupts, ("data storage interrupt - cia=0x%lx DAR=0x%lx DSISR=0x%lx\n",
+ (unsigned long)cia,
+ (unsigned long)DAR,
+ (unsigned long)DSISR));
cia = perform_oea_interrupt(processor, cia, 0x00300, 0, 0, 0, 0);
cpu_restart(processor, cia);
}
default:
- error("data_storage_interrupt() - internal error\n");
+ error("internal error - data_storage_interrupt - bad switch");
}
}
@@ -202,8 +215,7 @@ instruction_storage_interrupt(cpu *processor,
case USER_ENVIRONMENT:
case VIRTUAL_ENVIRONMENT:
- error("instruction_storage_interrupt - cia=0x%x - not implemented\n",
- cia);
+ error("internal error - instruction_storage_interrupt - should not be called in VEA mode");
case OPERATING_ENVIRONMENT:
{
@@ -223,15 +235,18 @@ instruction_storage_interrupt(cpu *processor,
break;
default:
srr1_set = 0;
- error("instruction_storage_interrupt: unknown reason %d\n", reason);
+ error("internal error - instruction_storage_interrupt - reason %d not implemented");
break;
}
+ TRACE(trace_interrupts, ("instruction storage interrupt - cia=0x%lx SRR1|=0x%lx\n",
+ (unsigned long)cia,
+ (unsigned long)srr1_set));
cia = perform_oea_interrupt(processor, cia, 0x00400, 0, 0, 0, srr1_set);
cpu_restart(processor, cia);
}
default:
- error("instruction_storage_interrupt() - internal error\n");
+ error("internal error - instruction_storage_interrupt - bad switch");
}
}
@@ -248,17 +263,20 @@ alignment_interrupt(cpu *processor,
case USER_ENVIRONMENT:
case VIRTUAL_ENVIRONMENT:
- error("%s - cia=0x%x, ra=0x%x\n",
- "alignment_interrupt", cia, ra);
+ cpu_error(processor, cia, "alignment interrupt - ra=0x%lx", ra);
case OPERATING_ENVIRONMENT:
DAR = (spreg)ra;
DSISR = 0; /* FIXME */
+ TRACE(trace_interrupts, ("alignment interrupt - cia=0x%lx DAR=0x%lx DSISR=0x%lx\n",
+ (unsigned long)cia,
+ (unsigned long)DAR,
+ (unsigned long)DSISR));
cia = perform_oea_interrupt(processor, cia, 0x00600, 0, 0, 0, 0);
cpu_restart(processor, cia);
default:
- error("alignment_interrupt() - internal error\n");
+ error("internal error - alignment_interrupt - bad switch");
}
}
@@ -277,15 +295,38 @@ program_interrupt(cpu *processor,
case USER_ENVIRONMENT:
case VIRTUAL_ENVIRONMENT:
switch (reason) {
+ case floating_point_enabled_program_interrupt:
+ cpu_error(processor, cia, "program interrupt - %s",
+ "floating point enabled");
+ break;
+ case illegal_instruction_program_interrupt:
+ cpu_error(processor, cia, "program interrupt - %s",
+ "illegal instruction");
+ break;
+ case privileged_instruction_program_interrupt:
+ cpu_error(processor, cia, "program interrupt - %s",
+ "privileged instruction");
+ break;
+ case trap_program_interrupt:
+ cpu_error(processor, cia, "program interrupt - %s",
+ "trap");
+ break;
+ case optional_instruction_program_interrupt:
+ cpu_error(processor, cia, "program interrupt - %s",
+ "illegal instruction (optional instruction not supported)");
+ break;
default:
- error("%s - cia=0x%x, reason=%d - not implemented\n",
- "program_interrupt", cia, reason);
+ error("internal error - program_interrupt - reason %d not implemented", reason);
}
case OPERATING_ENVIRONMENT:
{
msreg srr1_set;
switch (reason) {
+ case floating_point_enabled_program_interrupt:
+ srr1_set = srr1_floating_point_enabled;
+ break;
+ case optional_instruction_program_interrupt:
case illegal_instruction_program_interrupt:
srr1_set = srr1_illegal_instruction;
break;
@@ -297,15 +338,18 @@ program_interrupt(cpu *processor,
break;
default:
srr1_set = 0;
- error("program_interrupt - cia=0x%x, reason=%d(%s) - not implemented\n",
- cia, reason);
+ error("internal error - program_interrupt - reason %d not implemented", reason);
+ break;
}
+ TRACE(trace_interrupts, ("program interrupt - cia=0x%lx SRR1|=0x%lx\n",
+ (unsigned long)cia,
+ (unsigned long)srr1_set));
cia = perform_oea_interrupt(processor, cia, 0x00700, 0, 0, 0, srr1_set);
cpu_restart(processor, cia);
}
default:
- error("program_interrupt() - internal error\n");
+ error("internal error - program_interrupt - bad switch");
}
}
@@ -320,15 +364,16 @@ floating_point_unavailable_interrupt(cpu *processor,
case USER_ENVIRONMENT:
case VIRTUAL_ENVIRONMENT:
- error("%s - cia=0x%x - not implemented\n",
- "floating_point_unavailable_interrupt", cia);
+ cpu_error(processor, cia, "floating-point unavailable interrupt");
case OPERATING_ENVIRONMENT:
+ TRACE(trace_interrupts, ("floating-point unavailable interrupt - cia=0x%lx\n",
+ (unsigned long)cia));
cia = perform_oea_interrupt(processor, cia, 0x00800, 0, 0, 0, 0);
cpu_restart(processor, cia);
default:
- error("floating_point_unavailable_interrupt() - internal error\n");
+ error("internal error - floating_point_unavailable_interrupt - bad switch");
}
}
@@ -339,6 +384,8 @@ INLINE_INTERRUPTS\
system_call_interrupt(cpu *processor,
unsigned_word cia)
{
+ TRACE(trace_interrupts, ("system-call interrupt - cia=0x%lx\n", (unsigned long)cia));
+
switch (CURRENT_ENVIRONMENT) {
case USER_ENVIRONMENT:
@@ -351,7 +398,7 @@ system_call_interrupt(cpu *processor,
cpu_restart(processor, cia);
default:
- error("system_call_interrupt() - internal error\n");
+ error("internal error - system_call_interrupt - bad switch");
}
}
@@ -365,54 +412,121 @@ floating_point_assist_interrupt(cpu *processor,
case USER_ENVIRONMENT:
case VIRTUAL_ENVIRONMENT:
- error("%s - cia=0x%x - not implemented\n",
- "floating_point_assist_interrupt", cia);
+ cpu_error(processor, cia, "floating-point assist interrupt");
case OPERATING_ENVIRONMENT:
+ TRACE(trace_interrupts, ("floating-point assist interrupt - cia=0x%lx\n", (unsigned long)cia));
cia = perform_oea_interrupt(processor, cia, 0x00e00, 0, 0, 0, 0);
cpu_restart(processor, cia);
default:
- error("floating_point_assist_interrupt() - internal error\n");
+ error("internal error - floating_point_assist_interrupt - bad switch");
}
}
-/* handle an externally generated event */
+/* handle an externally generated event or an interrupt that has just
+ been enabled through changes to the MSR. */
-INLINE_INTERRUPTS\
-(int)
-decrementer_interrupt(cpu *processor)
+STATIC_INLINE_INTERRUPTS\
+(void)
+deliver_hardware_interrupt(void *data)
{
- if (cpu_registers(processor)->msr & msr_external_interrupt_enable) {
+ cpu *processor = (cpu*)data;
+ interrupts *ints = cpu_interrupts(processor);
+ ints->delivery_scheduled = NULL;
+ if ((cpu_registers(processor)->msr & (msr_floating_point_exception_mode_0
+ | msr_floating_point_exception_mode_1))
+ && cpu_registers(processor)->fpscr & fpscr_fex) {
+ msreg srr1_set = srr1_floating_point_enabled | srr1_subsequent_instruction;
unsigned_word cia = cpu_get_program_counter(processor);
unsigned_word nia = perform_oea_interrupt(processor,
- cia, 0x00900, 0, 0, 0, 0);
+ cia, 0x00700, 0, 0, 0, srr1_set);
cpu_set_program_counter(processor, nia);
- return 1;
}
- else {
- return 0;
+ else if (cpu_registers(processor)->msr & msr_external_interrupt_enable) {
+ /* external interrupts have a high priority and remain pending */
+ if (ints->pending_interrupts & external_interrupt_pending) {
+ unsigned_word cia = cpu_get_program_counter(processor);
+ unsigned_word nia = perform_oea_interrupt(processor,
+ cia, 0x00500, 0, 0, 0, 0);
+ TRACE(trace_interrupts, ("external interrupt - cia=0x%lx\n", (unsigned long)cia));
+ cpu_set_program_counter(processor, nia);
+ }
+ /* decrementer interrupts have a lower priority and are once only */
+ else if (ints->pending_interrupts & decrementer_interrupt_pending) {
+ unsigned_word cia = cpu_get_program_counter(processor);
+ unsigned_word nia = perform_oea_interrupt(processor,
+ cia, 0x00900, 0, 0, 0, 0);
+ TRACE(trace_interrupts, ("decrementer interrupt - cia=0x%lx time=0x%lx\n",
+ (unsigned long)cia,
+ (unsigned long)event_queue_time(psim_event_queue(cpu_system(processor)))
+ ));
+ cpu_set_program_counter(processor, nia);
+ ints->pending_interrupts &= ~decrementer_interrupt_pending;
+ }
+ }
+}
+
+STATIC_INLINE_INTERRUPTS\
+(void)
+schedule_hardware_interrupt_delivery(cpu *processor)
+{
+ interrupts *ints = cpu_interrupts(processor);
+ if (ints->delivery_scheduled == NULL) {
+ ints->delivery_scheduled =
+ event_queue_schedule(psim_event_queue(cpu_system(processor)),
+ 0, deliver_hardware_interrupt, processor);
}
}
+
INLINE_INTERRUPTS\
-(int)
-external_interrupt(cpu *processor)
+(void)
+check_masked_interrupts(cpu *processor)
+{
+ if (((cpu_registers(processor)->msr & (msr_floating_point_exception_mode_0
+ | msr_floating_point_exception_mode_1))
+ && cpu_registers(processor)->fpscr & fpscr_fex)
+ || ((cpu_registers(processor)->msr & msr_external_interrupt_enable)
+ && (cpu_interrupts(processor)->pending_interrupts)))
+ schedule_hardware_interrupt_delivery(processor);
+}
+
+INLINE_INTERRUPTS\
+(void)
+decrementer_interrupt(cpu *processor)
{
+ interrupts *ints = cpu_interrupts(processor);
+ ints->pending_interrupts |= decrementer_interrupt_pending;
if (cpu_registers(processor)->msr & msr_external_interrupt_enable) {
- unsigned_word cia = cpu_get_program_counter(processor);
- unsigned_word nia = perform_oea_interrupt(processor,
- cia, 0x00500, 0, 0, 0, 0);
- cpu_set_program_counter(processor, nia);
- return 1;
+ schedule_hardware_interrupt_delivery(processor);
+ }
+}
+
+INLINE_INTERRUPTS\
+(void)
+external_interrupt(cpu *processor,
+ int is_asserted)
+{
+ interrupts *ints = cpu_interrupts(processor);
+ if (is_asserted) {
+ if (!ints->pending_interrupts & external_interrupt_pending) {
+ ints->pending_interrupts |= external_interrupt_pending;
+ if (cpu_registers(processor)->msr & msr_external_interrupt_enable)
+ schedule_hardware_interrupt_delivery(processor);
+ }
+ else {
+ /* check that we haven't missed out on a chance to deliver an
+ interrupt */
+ ASSERT(!(cpu_registers(processor)->msr & msr_external_interrupt_enable));
+ }
}
else {
- return 0; /* not delivered */
+ ints->pending_interrupts &= ~external_interrupt_pending;
}
}
-
#endif /* _INTERRUPTS_C_ */
diff --git a/gnu/dist/sim/ppc/interrupts.h b/gnu/dist/sim/ppc/interrupts.h
index 7aa45e1d784..403f66b3d0e 100644
--- a/gnu/dist/sim/ppc/interrupts.h
+++ b/gnu/dist/sim/ppc/interrupts.h
@@ -93,6 +93,7 @@ typedef enum {
illegal_instruction_program_interrupt,
privileged_instruction_program_interrupt,
trap_program_interrupt,
+ optional_instruction_program_interrupt, /* subset of illegal instruction */
nr_program_interrupt_reasons
} program_interrupt_reasons;
@@ -122,23 +123,47 @@ INLINE_INTERRUPTS\
(cpu *processor,
unsigned_word cia);
-/* Hardware generated interrupts
+/* Hardware generated interrupts:
- These hardware generated interrupt routines are called outside of
- the instruction execution cycle and so return normally.
+ These asynchronous hardware generated interrupts may be called at
+ any time. It is the responsibility of this (the interrupts) module
+ to ensure that interrupts are delivered correctly (when possible).
+ The delivery of these interrupts is controlled by the MSR's
+ external interrupt enable bit. When ever the MSR's value is
+ changed, the processor must call the check_masked_interrupts()
+ function in case delivery has been made possible.
- More importantly, they assume that the current instruction address
- held within the processor is correct.
+ decrementer_interrupt is `edge' sensitive. Multiple edges arriving
+ before the first edge has been delivered result in only one
+ interrupt.
- Return a non zero value if the interrupt was not successfully
- delivered */
+ external_interrupt is `level' sensitive. An external interrupt
+ will only be delivered when the external interrupt port is
+ `asserted'. While interrupts are disabled, the external interrupt
+ can be asserted and then de-asserted without an interrupt
+ eventually being delivered. */
+
+enum {
+ external_interrupt_pending = 1,
+ decrementer_interrupt_pending = 2,
+};
+
+typedef struct _interrupts {
+ event_entry_tag delivery_scheduled;
+ int pending_interrupts;
+} interrupts;
INLINE_INTERRUPTS\
-(int) decrementer_interrupt
+(void) check_masked_interrupts
(cpu *processor);
INLINE_INTERRUPTS\
-(int) external_interrupt
+(void) decrementer_interrupt
(cpu *processor);
+INLINE_INTERRUPTS\
+(void) external_interrupt
+(cpu *processor,
+ int is_asserted);
+
#endif /* _INTERRUPTS_H_ */
diff --git a/gnu/dist/sim/ppc/ld-cache.c b/gnu/dist/sim/ppc/ld-cache.c
new file mode 100644
index 00000000000..135013e5f23
--- /dev/null
+++ b/gnu/dist/sim/ppc/ld-cache.c
@@ -0,0 +1,115 @@
+/* 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.
+
+ */
+
+
+#include "misc.h"
+#include "lf.h"
+#include "table.h"
+#include "ld-cache.h"
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+
+enum {
+ ca_type,
+ ca_field_name,
+ ca_derived_name,
+ ca_type_def,
+ ca_expression,
+ nr_cache_rule_fields,
+};
+
+static const name_map cache_type_map[] = {
+ { "cache", cache_value },
+ { "compute", compute_value },
+ { "scratch", scratch_value },
+ { NULL, 0 },
+};
+
+
+cache_table *
+load_cache_table(char *file_name,
+ int hi_bit_nr)
+{
+ table *file = table_open(file_name, nr_cache_rule_fields, 0);
+ table_entry *entry;
+ cache_table *table = NULL;
+ cache_table **curr_rule = &table;
+ while ((entry = table_entry_read(file)) != NULL) {
+ cache_table *new_rule = ZALLOC(cache_table);
+ new_rule->type = name2i(entry->fields[ca_type], cache_type_map);
+ new_rule->field_name = entry->fields[ca_field_name];
+ new_rule->derived_name = entry->fields[ca_derived_name];
+ new_rule->type_def = (strlen(entry->fields[ca_type_def])
+ ? entry->fields[ca_type_def]
+ : NULL);
+ new_rule->expression = (strlen(entry->fields[ca_expression]) > 0
+ ? entry->fields[ca_expression]
+ : NULL);
+ new_rule->file_entry = entry;
+ *curr_rule = new_rule;
+ curr_rule = &new_rule->next;
+ }
+ return table;
+}
+
+
+
+#ifdef MAIN
+
+static void
+dump_cache_rule(cache_table* rule,
+ int indent)
+{
+ dumpf(indent, "((cache_table*)0x%x\n", rule);
+ dumpf(indent, " (type %s)\n", i2name(rule->type, cache_type_map));
+ dumpf(indent, " (field_name \"%s\")\n", rule->field_name);
+ dumpf(indent, " (derived_name \"%s\")\n", rule->derived_name);
+ dumpf(indent, " (type-def \"%s\")\n", rule->type_def);
+ dumpf(indent, " (expression \"%s\")\n", rule->expression);
+ dumpf(indent, " (next 0x%x)\n", rule->next);
+ dumpf(indent, " )\n");
+}
+
+
+static void
+dump_cache_rules(cache_table* rule,
+ int indent)
+{
+ while (rule) {
+ dump_cache_rule(rule, indent);
+ rule = rule->next;
+ }
+}
+
+
+int
+main(int argc, char **argv)
+{
+ cache_table *rules;
+ if (argc != 3)
+ error("Usage: cache <cache-file> <hi-bit-nr>\n");
+ rules = load_cache_table(argv[1], a2i(argv[2]));
+ dump_cache_rules(rules, 0);
+ return 0;
+}
+#endif
diff --git a/gnu/dist/sim/ppc/ld-cache.h b/gnu/dist/sim/ppc/ld-cache.h
new file mode 100644
index 00000000000..72e39504380
--- /dev/null
+++ b/gnu/dist/sim/ppc/ld-cache.h
@@ -0,0 +1,81 @@
+/* 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.
+
+ */
+
+/* Instruction unpacking:
+
+ Once the instruction has been decoded, the register (and other)
+ fields within the instruction need to be extracted.
+
+ The table that follows determines how each field should be treated.
+ Importantly it considers the case where the extracted field is to
+ be used immediatly or stored in an instruction cache.
+
+ <type>
+
+ Indicates what to do with the cache entry. If a cache is to be
+ used. SCRATCH and CACHE values are defined when a cache entry is
+ being filled while CACHE and COMPUTE values are defined in the
+ semantic code.
+
+ Zero marks the end of the table. More importantly 1. indicates
+ that the entry is valid and can be cached. 2. indicates that that
+ the entry is valid but can not be cached.
+
+ <field_name>
+
+ The field name as given in the instruction spec.
+
+ <derived_name>
+
+ A new name for <field_name> once it has been extracted from the
+ instruction (and possibly stored in the instruction cache).
+
+ <type>
+
+ String specifying the storage type for <new_name> (the extracted
+ field>.
+
+ <expression>
+
+ Specifies how to get <new_name> from <old_name>. If null, old and
+ new name had better be the same. */
+
+
+typedef enum {
+ scratch_value,
+ cache_value,
+ compute_value,
+} cache_rule_type;
+
+typedef struct _cache_table cache_table;
+struct _cache_table {
+ cache_rule_type type;
+ char *field_name;
+ char *derived_name;
+ char *type_def;
+ char *expression;
+ table_entry *file_entry;
+ cache_table *next;
+};
+
+
+extern cache_table *load_cache_table
+(char *file_name,
+ int hi_bit_nr);
diff --git a/gnu/dist/sim/ppc/ld-decode.c b/gnu/dist/sim/ppc/ld-decode.c
new file mode 100644
index 00000000000..3964960af26
--- /dev/null
+++ b/gnu/dist/sim/ppc/ld-decode.c
@@ -0,0 +1,155 @@
+/* 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.
+
+ */
+
+/* load the opcode stat structure */
+
+#include "misc.h"
+#include "lf.h"
+#include "table.h"
+#include "ld-decode.h"
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+enum {
+ op_options,
+ op_first,
+ op_last,
+ op_force_first,
+ op_force_last,
+ op_force_expansion,
+ op_special_mask,
+ op_special_value,
+ op_special_constant,
+ nr_decode_fields,
+};
+
+static const name_map decode_type_map[] = {
+ { "normal", normal_decode_rule },
+ { "expand-forced", expand_forced_rule },
+ { "boolean", boolean_rule },
+ { NULL, normal_decode_rule },
+};
+
+static const name_map decode_gen_map[] = {
+ { "array", array_gen },
+ { "switch", switch_gen },
+ { "padded-switch", padded_switch_gen },
+ { "goto-switch", goto_switch_gen },
+ { NULL, -1 },
+};
+
+static const name_map decode_slash_map[] = {
+ { "variable-slash", 0 },
+ { "constant-slash", 1 },
+ { NULL },
+};
+
+
+static decode_gen_type overriding_gen_type = invalid_gen;
+
+void
+force_decode_gen_type(const char *type)
+{
+ overriding_gen_type = name2i(type, decode_gen_map);
+}
+
+
+decode_table *
+load_decode_table(char *file_name,
+ int hi_bit_nr)
+{
+ table *file = table_open(file_name, nr_decode_fields, 0);
+ table_entry *entry;
+ decode_table *table = NULL;
+ decode_table **curr_rule = &table;
+ while ((entry = table_entry_read(file)) != NULL) {
+ decode_table *new_rule = ZALLOC(decode_table);
+ new_rule->type = name2i(entry->fields[op_options], decode_type_map);
+ new_rule->gen = (overriding_gen_type != invalid_gen
+ ? overriding_gen_type
+ : name2i(entry->fields[op_options], decode_gen_map));
+ new_rule->force_slash = name2i(entry->fields[op_options], decode_slash_map);
+ new_rule->first = target_a2i(hi_bit_nr, entry->fields[op_first]);
+ new_rule->last = target_a2i(hi_bit_nr, entry->fields[op_last]);
+ new_rule->force_first = (strlen(entry->fields[op_force_first])
+ ? target_a2i(hi_bit_nr, entry->fields[op_force_first])
+ : new_rule->last + 1);
+ new_rule->force_last = (strlen(entry->fields[op_force_last])
+ ? target_a2i(hi_bit_nr, entry->fields[op_force_last])
+ : new_rule->first - 1);
+ new_rule->force_expansion = entry->fields[op_force_expansion];
+ new_rule->special_mask = a2i(entry->fields[op_special_mask]);
+ new_rule->special_value = a2i(entry->fields[op_special_value]);
+ new_rule->special_constant = a2i(entry->fields[op_special_constant]);
+ *curr_rule = new_rule;
+ curr_rule = &new_rule->next;
+ }
+ return table;
+}
+
+
+void
+dump_decode_rule(decode_table *rule,
+ int indent)
+{
+ dumpf(indent, "((decode_table*)%p\n", rule);
+ if (rule) {
+ dumpf(indent, " (type %s)\n", i2name(rule->type, decode_type_map));
+ dumpf(indent, " (gen %s)\n", i2name(rule->gen, decode_gen_map));
+ dumpf(indent, " (force_slash %d)\n", rule->force_slash);
+ dumpf(indent, " (first %d)\n", rule->first);
+ dumpf(indent, " (last %d)\n", rule->last);
+ dumpf(indent, " (force_first %d)\n", rule->force_first);
+ dumpf(indent, " (force_last %d)\n", rule->force_last);
+ dumpf(indent, " (force_expansion \"%s\")\n", rule->force_expansion);
+ dumpf(indent, " (special_mask 0x%x)\n", rule->special_mask);
+ dumpf(indent, " (special_value 0x%x)\n", rule->special_value);
+ dumpf(indent, " (special_constant 0x%x)\n", rule->special_constant);
+ dumpf(indent, " (next 0x%x)\n", rule->next);
+ }
+ dumpf(indent, " )\n");
+}
+
+
+#ifdef MAIN
+
+static void
+dump_decode_rules(decode_table *rule,
+ int indent)
+{
+ while (rule) {
+ dump_decode_rule(rule, indent);
+ rule = rule->next;
+ }
+}
+
+int
+main(int argc, char **argv)
+{
+ decode_table *rules;
+ if (argc != 3)
+ error("Usage: decode <decode-file> <hi-bit-nr>\n");
+ rules = load_decode_table(argv[1], a2i(argv[2]));
+ dump_decode_rules(rules, 0);
+ return 0;
+}
+#endif
diff --git a/gnu/dist/sim/ppc/ld-decode.h b/gnu/dist/sim/ppc/ld-decode.h
new file mode 100644
index 00000000000..de23181ba37
--- /dev/null
+++ b/gnu/dist/sim/ppc/ld-decode.h
@@ -0,0 +1,143 @@
+/* This file is part of the program psim.
+
+ Copyright (C) 1994,1995,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.
+
+ */
+
+/* Instruction decode table:
+
+ <options>:<first>:<last>:<force-first>:<force-last>:<force-expand>:<special>...
+
+
+
+ Ignore the below:
+
+
+ The instruction decode table contains rules that dictate how igen
+ is going to firstly break down the opcode table and secondly
+
+ The table that follows is used by gen to construct a decision tree
+ that can identify each possible instruction. Gen then outputs this
+ decision tree as (according to config) a table or switch statement
+ as the function idecode.
+
+ In parallel to this, as mentioned above, WITH_EXPANDED_SEMANTICS
+ determines of the semantic functions themselves should be expanded
+ in a similar way.
+
+ <first>
+ <last>
+
+ Range of bits (within the instruction) that should be searched for
+ an instruction field. Within such ranges, gen looks for opcodes
+ (constants), registers (strings) and reserved bits (slash) and
+ according to the rules that follows includes or excludes them from
+ a possible instruction field.
+
+ <force_first>
+ <force_last>
+
+ If an instruction field was found, enlarge the field size so that
+ it is forced to at least include bits starting from <force_first>
+ (<force_last>). To stop this occuring, use <force_first> = <last>
+ + 1 and <force_last> = <first> - 1.
+
+ <force_slash>
+
+ Treat `/' fields as a constant instead of variable when looking for
+ an instruction field.
+
+ <force_expansion>
+
+ Treat any contained register (string) fields as constant when
+ determining the instruction field. For the instruction decode (and
+ controled by IDECODE_EXPAND_SEMANTICS) this forces the expansion of
+ what would otherwize be non constant bits of an instruction.
+
+ <use_switch>
+
+ Should this table be expanded using a switch statement (val 1) and
+ if so, should it be padded with entries so as to force the compiler
+ to generate a jump table (val 2). Or a branch table (val 3).
+
+ <special_mask>
+ <special_value>
+ <special_rule>
+ <special_constant>
+
+ Special rule to fine tune how specific (or groups) of instructions
+ are expanded. The applicability of the rule is determined by
+
+ <special_mask> != 0 && (instruction> & <special_mask>) == <special_value>
+
+ Where <instruction> is obtained by looking only at constant fields
+ with in an instructions spec. When determining an expansion, the
+ rule is only considered when a node contains a single instruction.
+ <special_rule> can be any of:
+
+ 0: for this instruction, expand by earlier rules
+ 1: expand bits <force_low> .. <force_hi> only
+ 2: boolean expansion of only zero/non-zero cases
+ 3: boolean expansion of equality of special constant
+
+ */
+
+
+typedef enum {
+ normal_decode_rule,
+ expand_forced_rule,
+ boolean_rule,
+ nr_decode_rules
+} decode_special_type;
+
+typedef enum {
+ invalid_gen,
+ array_gen,
+ switch_gen,
+ padded_switch_gen,
+ goto_switch_gen,
+ nr_decode_gen_types,
+} decode_gen_type;
+
+
+typedef struct _decode_table decode_table;
+struct _decode_table {
+ decode_special_type type;
+ decode_gen_type gen;
+ int first;
+ int last;
+ int force_first;
+ int force_last;
+ int force_slash;
+ char *force_expansion;
+ unsigned special_mask;
+ unsigned special_value;
+ unsigned special_constant;
+ decode_table *next;
+};
+
+
+extern void force_decode_gen_type
+(const char *type);
+
+extern decode_table *load_decode_table
+(char *file_name,
+ int hi_bit_nr);
+
+extern void dump_decode_rule
+(decode_table *rule,
+ int indent);
diff --git a/gnu/dist/sim/ppc/ld-insn.c b/gnu/dist/sim/ppc/ld-insn.c
new file mode 100644
index 00000000000..a190d85a83f
--- /dev/null
+++ b/gnu/dist/sim/ppc/ld-insn.c
@@ -0,0 +1,925 @@
+/* This file is part of the program psim.
+
+ Copyright (C) 1994,1995,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 "misc.h"
+#include "lf.h"
+#include "table.h"
+#include "filter.h"
+#include "ld-decode.h"
+#include "ld-cache.h"
+#include "ld-insn.h"
+
+#include "igen.h"
+
+static void
+update_depth(insn_table *entry,
+ lf *file,
+ void *data,
+ insn *instruction,
+ int depth)
+{
+ int *max_depth = (int*)data;
+ if (*max_depth < depth)
+ *max_depth = depth;
+}
+
+
+int
+insn_table_depth(insn_table *table)
+{
+ int depth = 0;
+ insn_table_traverse_tree(table,
+ NULL,
+ &depth,
+ 1,
+ NULL, /*start*/
+ update_depth,
+ NULL, /*end*/
+ NULL); /*padding*/
+ return depth;
+}
+
+
+static insn_fields *
+parse_insn_format(table_entry *entry,
+ char *format)
+{
+ char *chp;
+ insn_fields *fields = ZALLOC(insn_fields);
+
+ /* create a leading sentinal */
+ fields->first = ZALLOC(insn_field);
+ fields->first->first = -1;
+ fields->first->last = -1;
+ fields->first->width = 0;
+
+ /* and a trailing sentinal */
+ fields->last = ZALLOC(insn_field);
+ fields->last->first = insn_bit_size;
+ fields->last->last = insn_bit_size;
+ fields->last->width = 0;
+
+ /* link them together */
+ fields->first->next = fields->last;
+ fields->last->prev = fields->first;
+
+ /* now work through the formats */
+ chp = format;
+
+ while (*chp != '\0') {
+ char *start_pos;
+ char *start_val;
+ int strlen_val;
+ int strlen_pos;
+ insn_field *new_field;
+
+ /* sanity check */
+ if (!isdigit(*chp)) {
+ error("%s:%d: missing position field at `%s'\n",
+ entry->file_name, entry->line_nr, chp);
+ }
+
+ /* break out the bit position */
+ start_pos = chp;
+ while (isdigit(*chp))
+ chp++;
+ strlen_pos = chp - start_pos;
+ if (*chp == '.' && strlen_pos > 0)
+ chp++;
+ else {
+ error("%s:%d: missing field value at %s\n",
+ entry->file_name, entry->line_nr, chp);
+ break;
+ }
+
+ /* break out the value */
+ start_val = chp;
+ while ((*start_val == '/' && *chp == '/')
+ || (isdigit(*start_val) && isdigit(*chp))
+ || (isalpha(*start_val) && (isalnum(*chp) || *chp == '_')))
+ chp++;
+ strlen_val = chp - start_val;
+ if (*chp == ',')
+ chp++;
+ else if (*chp != '\0' || strlen_val == 0) {
+ error("%s:%d: missing field terminator at %s\n",
+ entry->file_name, entry->line_nr, chp);
+ break;
+ }
+
+ /* create a new field and insert it */
+ new_field = ZALLOC(insn_field);
+ new_field->next = fields->last;
+ new_field->prev = fields->last->prev;
+ new_field->next->prev = new_field;
+ new_field->prev->next = new_field;
+
+ /* the value */
+ new_field->val_string = (char*)zalloc(strlen_val+1);
+ strncpy(new_field->val_string, start_val, strlen_val);
+ if (isdigit(*new_field->val_string)) {
+ new_field->val_int = a2i(new_field->val_string);
+ new_field->is_int = 1;
+ }
+ else if (new_field->val_string[0] == '/') {
+ new_field->is_slash = 1;
+ }
+ else {
+ new_field->is_string = 1;
+ }
+
+ /* the pos */
+ new_field->pos_string = (char*)zalloc(strlen_pos+1);
+ strncpy(new_field->pos_string, start_pos, strlen_pos);
+ new_field->first = target_a2i(hi_bit_nr, new_field->pos_string);
+ new_field->last = new_field->next->first - 1; /* guess */
+ new_field->width = new_field->last - new_field->first + 1; /* guess */
+ new_field->prev->last = new_field->first-1; /*fix*/
+ new_field->prev->width = new_field->first - new_field->prev->first; /*fix*/
+ }
+
+ /* fiddle first/last so that the sentinals `disapear' */
+ ASSERT(fields->first->last < 0);
+ ASSERT(fields->last->first >= insn_bit_size);
+ fields->first = fields->first->next;
+ fields->last = fields->last->prev;
+
+ /* now go over this again, pointing each bit position at a field
+ record */
+ {
+ int i;
+ insn_field *field;
+ field = fields->first;
+ for (i = 0; i < insn_bit_size; i++) {
+ while (field->last < i)
+ field = field->next;
+ fields->bits[i] = field;
+ }
+ }
+
+ /* go over each of the fields, and compute a `value' for the insn */
+ {
+ insn_field *field;
+ fields->value = 0;
+ for (field = fields->first;
+ field->last < insn_bit_size;
+ field = field->next) {
+ fields->value <<= field->width;
+ if (field->is_int)
+ fields->value |= field->val_int;
+ }
+ }
+ return fields;
+}
+
+
+static void
+model_table_insert(insn_table *table,
+ table_entry *file_entry)
+{
+ int len;
+
+ /* create a new model */
+ model *new_model = ZALLOC(model);
+
+ new_model->name = file_entry->fields[model_identifer];
+ new_model->printable_name = file_entry->fields[model_name];
+ new_model->insn_default = file_entry->fields[model_default];
+
+ while (*new_model->insn_default && isspace(*new_model->insn_default))
+ new_model->insn_default++;
+
+ len = strlen(new_model->insn_default);
+ if (max_model_fields_len < len)
+ max_model_fields_len = len;
+
+ /* append it to the end of the model list */
+ if (last_model)
+ last_model->next = new_model;
+ else
+ models = new_model;
+ last_model = new_model;
+}
+
+static void
+model_table_insert_specific(insn_table *table,
+ table_entry *file_entry,
+ insn **start_ptr,
+ insn **end_ptr)
+{
+ insn *ptr = ZALLOC(insn);
+ ptr->file_entry = file_entry;
+ if (*end_ptr)
+ (*end_ptr)->next = ptr;
+ else
+ (*start_ptr) = ptr;
+ (*end_ptr) = ptr;
+}
+
+
+static void
+insn_table_insert_function(insn_table *table,
+ table_entry *file_entry)
+{
+ /* create a new function */
+ insn *new_function = ZALLOC(insn);
+ new_function->file_entry = file_entry;
+
+ /* append it to the end of the function list */
+ if (table->last_function)
+ table->last_function->next = new_function;
+ else
+ table->functions = new_function;
+ table->last_function = new_function;
+}
+
+extern void
+insn_table_insert_insn(insn_table *table,
+ table_entry *file_entry,
+ insn_fields *fields)
+{
+ insn **ptr_to_cur_insn = &table->insns;
+ insn *cur_insn = *ptr_to_cur_insn;
+ table_model_entry *insn_model_ptr;
+ model *model_ptr;
+
+ /* create a new instruction */
+ insn *new_insn = ZALLOC(insn);
+ new_insn->file_entry = file_entry;
+ new_insn->fields = fields;
+
+ /* Check out any model information returned to make sure the model
+ is correct. */
+ for(insn_model_ptr = file_entry->model_first; insn_model_ptr; insn_model_ptr = insn_model_ptr->next) {
+ char *name = insn_model_ptr->fields[insn_model_name];
+ int len = strlen (insn_model_ptr->fields[insn_model_fields]);
+
+ while (len > 0 && isspace(*insn_model_ptr->fields[insn_model_fields])) {
+ len--;
+ insn_model_ptr->fields[insn_model_fields]++;
+ }
+
+ if (max_model_fields_len < len)
+ max_model_fields_len = len;
+
+ for(model_ptr = models; model_ptr; model_ptr = model_ptr->next) {
+ if (strcmp(name, model_ptr->printable_name) == 0) {
+
+ /* Replace the name field with that of the global model, so that when we
+ want to print it out, we can just compare pointers. */
+ insn_model_ptr->fields[insn_model_name] = model_ptr->printable_name;
+ break;
+ }
+ }
+
+ if (!model_ptr)
+ error("%s:%d: machine model `%s' was not known about\n",
+ file_entry->file_name, file_entry->line_nr, name);
+ }
+
+ /* insert it according to the order of the fields */
+ while (cur_insn != NULL
+ && new_insn->fields->value >= cur_insn->fields->value) {
+ ptr_to_cur_insn = &cur_insn->next;
+ cur_insn = *ptr_to_cur_insn;
+ }
+
+ new_insn->next = cur_insn;
+ *ptr_to_cur_insn = new_insn;
+
+ table->nr_insn++;
+}
+
+
+
+insn_table *
+load_insn_table(const char *file_name,
+ decode_table *decode_rules,
+ filter *filters)
+{
+ table *file = table_open(file_name, nr_insn_table_fields, nr_insn_model_table_fields);
+ insn_table *table = ZALLOC(insn_table);
+ table_entry *file_entry;
+ table->opcode_rule = decode_rules;
+
+ while ((file_entry = table_entry_read(file)) != NULL) {
+ if (it_is("function", file_entry->fields[insn_flags])
+ || it_is("internal", file_entry->fields[insn_flags])) {
+ insn_table_insert_function(table, file_entry);
+ }
+ else if (it_is("model", file_entry->fields[insn_flags])) {
+ model_table_insert(table, file_entry);
+ }
+ else if (it_is("model-macro", file_entry->fields[insn_flags])) {
+ model_table_insert_specific(table, file_entry, &model_macros, &last_model_macro);
+ }
+ else if (it_is("model-function", file_entry->fields[insn_flags])) {
+ model_table_insert_specific(table, file_entry, &model_functions, &last_model_function);
+ }
+ else if (it_is("model-internal", file_entry->fields[insn_flags])) {
+ model_table_insert_specific(table, file_entry, &model_internal, &last_model_internal);
+ }
+ else if (it_is("model-static", file_entry->fields[insn_flags])) {
+ model_table_insert_specific(table, file_entry, &model_static, &last_model_static);
+ }
+ else if (it_is("model-data", file_entry->fields[insn_flags])) {
+ model_table_insert_specific(table, file_entry, &model_data, &last_model_data);
+ }
+ else {
+ insn_fields *fields;
+ /* skip instructions that aren't relevant to the mode */
+ if (is_filtered_out(file_entry->fields[insn_flags], filters)) {
+ fprintf(stderr, "Dropping %s - %s\n",
+ file_entry->fields[insn_name],
+ file_entry->fields[insn_flags]);
+ }
+ else {
+ /* create/insert the new instruction */
+ fields = parse_insn_format(file_entry,
+ file_entry->fields[insn_format]);
+ insn_table_insert_insn(table, file_entry, fields);
+ }
+ }
+ }
+ return table;
+}
+
+
+extern void
+insn_table_traverse_tree(insn_table *table,
+ lf *file,
+ void *data,
+ int depth,
+ leaf_handler *start,
+ insn_handler *leaf,
+ leaf_handler *end,
+ padding_handler *padding)
+{
+ insn_table *entry;
+ int entry_nr;
+
+ ASSERT(table != NULL
+ && table->opcode != NULL
+ && table->nr_entries > 0
+ && table->entries != 0);
+
+ if (start != NULL && depth >= 0)
+ start(table, file, data, depth);
+
+ for (entry_nr = 0, entry = table->entries;
+ entry_nr < (table->opcode->is_boolean
+ ? 2
+ : (1 << (table->opcode->last - table->opcode->first + 1)));
+ entry_nr ++) {
+ if (entry == NULL
+ || (!table->opcode->is_boolean
+ && entry_nr < entry->opcode_nr)) {
+ if (padding != NULL && depth >= 0)
+ padding(table, file, data, depth, entry_nr);
+ }
+ else {
+ ASSERT(entry != NULL && (entry->opcode_nr == entry_nr
+ || table->opcode->is_boolean));
+ if (entry->opcode != NULL && depth != 0) {
+ insn_table_traverse_tree(entry, file, data, depth+1,
+ start, leaf, end, padding);
+ }
+ else if (depth >= 0) {
+ if (leaf != NULL)
+ leaf(entry, file, data, entry->insns, depth);
+ }
+ entry = entry->sibling;
+ }
+ }
+ if (end != NULL && depth >= 0)
+ end(table, file, data, depth);
+}
+
+
+extern void
+insn_table_traverse_function(insn_table *table,
+ lf *file,
+ void *data,
+ function_handler *leaf)
+{
+ insn *function;
+ for (function = table->functions;
+ function != NULL;
+ function = function->next) {
+ leaf(table, file, data, function->file_entry);
+ }
+}
+
+extern void
+insn_table_traverse_insn(insn_table *table,
+ lf *file,
+ void *data,
+ insn_handler *handler)
+{
+ insn *instruction;
+ for (instruction = table->insns;
+ instruction != NULL;
+ instruction = instruction->next) {
+ handler(table, file, data, instruction, 0);
+ }
+}
+
+
+/****************************************************************/
+
+typedef enum {
+ field_constant_int = 1,
+ field_constant_slash = 2,
+ field_constant_string = 3
+} constant_field_types;
+
+
+static int
+insn_field_is_constant(insn_field *field,
+ decode_table *rule)
+{
+ /* field is an integer */
+ if (field->is_int)
+ return field_constant_int;
+ /* field is `/' and treating that as a constant */
+ if (field->is_slash && rule->force_slash)
+ return field_constant_slash;
+ /* field, though variable is on the list */
+ if (field->is_string && rule->force_expansion != NULL) {
+ char *forced_fields = rule->force_expansion;
+ while (*forced_fields != '\0') {
+ int field_len;
+ char *end = strchr(forced_fields, ',');
+ if (end == NULL)
+ field_len = strlen(forced_fields);
+ else
+ field_len = end-forced_fields;
+ if (strncmp(forced_fields, field->val_string, field_len) == 0
+ && field->val_string[field_len] == '\0')
+ return field_constant_string;
+ forced_fields += field_len;
+ if (*forced_fields == ',')
+ forced_fields++;
+ }
+ }
+ return 0;
+}
+
+
+static opcode_field *
+insn_table_find_opcode_field(insn *insns,
+ decode_table *rule,
+ int string_only)
+{
+ opcode_field *curr_opcode = ZALLOC(opcode_field);
+ insn *entry;
+ ASSERT(rule);
+
+ curr_opcode->first = insn_bit_size;
+ curr_opcode->last = -1;
+ for (entry = insns; entry != NULL; entry = entry->next) {
+ insn_fields *fields = entry->fields;
+ opcode_field new_opcode;
+
+ /* find a start point for the opcode field */
+ new_opcode.first = rule->first;
+ while (new_opcode.first <= rule->last
+ && (!string_only
+ || insn_field_is_constant(fields->bits[new_opcode.first],
+ rule) != field_constant_string)
+ && (string_only
+ || !insn_field_is_constant(fields->bits[new_opcode.first],
+ rule)))
+ new_opcode.first = fields->bits[new_opcode.first]->last + 1;
+ ASSERT(new_opcode.first > rule->last
+ || (string_only
+ && insn_field_is_constant(fields->bits[new_opcode.first],
+ rule) == field_constant_string)
+ || (!string_only
+ && insn_field_is_constant(fields->bits[new_opcode.first],
+ rule)));
+
+ /* find the end point for the opcode field */
+ new_opcode.last = rule->last;
+ while (new_opcode.last >= rule->first
+ && (!string_only
+ || insn_field_is_constant(fields->bits[new_opcode.last],
+ rule) != field_constant_string)
+ && (string_only
+ || !insn_field_is_constant(fields->bits[new_opcode.last],
+ rule)))
+ new_opcode.last = fields->bits[new_opcode.last]->first - 1;
+ ASSERT(new_opcode.last < rule->first
+ || (string_only
+ && insn_field_is_constant(fields->bits[new_opcode.last],
+ rule) == field_constant_string)
+ || (!string_only
+ && insn_field_is_constant(fields->bits[new_opcode.last],
+ rule)));
+
+ /* now see if our current opcode needs expanding */
+ if (new_opcode.first <= rule->last
+ && curr_opcode->first > new_opcode.first)
+ curr_opcode->first = new_opcode.first;
+ if (new_opcode.last >= rule->first
+ && curr_opcode->last < new_opcode.last)
+ curr_opcode->last = new_opcode.last;
+
+ }
+
+ /* was any thing interesting found? */
+ if (curr_opcode->first > rule->last) {
+ ASSERT(curr_opcode->last < rule->first);
+ return NULL;
+ }
+ ASSERT(curr_opcode->last >= rule->first);
+ ASSERT(curr_opcode->first <= rule->last);
+
+ /* if something was found, check it includes the forced field range */
+ if (!string_only
+ && curr_opcode->first > rule->force_first) {
+ curr_opcode->first = rule->force_first;
+ }
+ if (!string_only
+ && curr_opcode->last < rule->force_last) {
+ curr_opcode->last = rule->force_last;
+ }
+ /* handle special case elminating any need to do shift after mask */
+ if (string_only
+ && rule->force_last == insn_bit_size-1) {
+ curr_opcode->last = insn_bit_size-1;
+ }
+
+ /* handle any special cases */
+ switch (rule->type) {
+ case normal_decode_rule:
+ /* let the above apply */
+ break;
+ case expand_forced_rule:
+ /* expand a limited nr of bits, ignoring the rest */
+ curr_opcode->first = rule->force_first;
+ curr_opcode->last = rule->force_last;
+ break;
+ case boolean_rule:
+ curr_opcode->is_boolean = 1;
+ curr_opcode->boolean_constant = rule->special_constant;
+ break;
+ default:
+ error("Something is going wrong\n");
+ }
+
+ return curr_opcode;
+}
+
+
+static void
+insn_table_insert_expanded(insn_table *table,
+ insn *old_insn,
+ int new_opcode_nr,
+ insn_bits *new_bits)
+{
+ insn_table **ptr_to_cur_entry = &table->entries;
+ insn_table *cur_entry = *ptr_to_cur_entry;
+
+ /* find the new table for this entry */
+ while (cur_entry != NULL
+ && cur_entry->opcode_nr < new_opcode_nr) {
+ ptr_to_cur_entry = &cur_entry->sibling;
+ cur_entry = *ptr_to_cur_entry;
+ }
+
+ if (cur_entry == NULL || cur_entry->opcode_nr != new_opcode_nr) {
+ insn_table *new_entry = ZALLOC(insn_table);
+ new_entry->opcode_nr = new_opcode_nr;
+ new_entry->expanded_bits = new_bits;
+ new_entry->opcode_rule = table->opcode_rule->next;
+ new_entry->sibling = cur_entry;
+ new_entry->parent = table;
+ *ptr_to_cur_entry = new_entry;
+ cur_entry = new_entry;
+ table->nr_entries++;
+ }
+ /* ASSERT new_bits == cur_entry bits */
+ ASSERT(cur_entry != NULL && cur_entry->opcode_nr == new_opcode_nr);
+ insn_table_insert_insn(cur_entry,
+ old_insn->file_entry,
+ old_insn->fields);
+}
+
+static void
+insn_table_expand_opcode(insn_table *table,
+ insn *instruction,
+ int field_nr,
+ int opcode_nr,
+ insn_bits *bits)
+{
+
+ if (field_nr > table->opcode->last) {
+ insn_table_insert_expanded(table, instruction, opcode_nr, bits);
+ }
+ else {
+ insn_field *field = instruction->fields->bits[field_nr];
+ if (field->is_int || field->is_slash) {
+ ASSERT(field->first >= table->opcode->first
+ && field->last <= table->opcode->last);
+ insn_table_expand_opcode(table, instruction, field->last+1,
+ ((opcode_nr << field->width) + field->val_int),
+ bits);
+ }
+ else {
+ int val;
+ int last_pos = ((field->last < table->opcode->last)
+ ? field->last : table->opcode->last);
+ int first_pos = ((field->first > table->opcode->first)
+ ? field->first : table->opcode->first);
+ int width = last_pos - first_pos + 1;
+ int last_val = (table->opcode->is_boolean
+ ? 2 : (1 << width));
+ for (val = 0; val < last_val; val++) {
+ insn_bits *new_bits = ZALLOC(insn_bits);
+ new_bits->field = field;
+ new_bits->value = val;
+ new_bits->last = bits;
+ new_bits->opcode = table->opcode;
+ insn_table_expand_opcode(table, instruction, last_pos+1,
+ ((opcode_nr << width) | val),
+ new_bits);
+ }
+ }
+ }
+}
+
+static void
+insn_table_insert_expanding(insn_table *table,
+ insn *entry)
+{
+ insn_table_expand_opcode(table,
+ entry,
+ table->opcode->first,
+ 0,
+ table->expanded_bits);
+}
+
+
+extern void
+insn_table_expand_insns(insn_table *table)
+{
+
+ ASSERT(table->nr_insn >= 1);
+
+ /* determine a valid opcode */
+ while (table->opcode_rule) {
+ /* specials only for single instructions */
+ if ((table->nr_insn > 1
+ && table->opcode_rule->special_mask == 0
+ && table->opcode_rule->type == normal_decode_rule)
+ || (table->nr_insn == 1
+ && table->opcode_rule->special_mask != 0
+ && ((table->insns->fields->value
+ & table->opcode_rule->special_mask)
+ == table->opcode_rule->special_value))
+ || (generate_expanded_instructions
+ && table->opcode_rule->special_mask == 0
+ && table->opcode_rule->type == normal_decode_rule))
+ table->opcode =
+ insn_table_find_opcode_field(table->insns,
+ table->opcode_rule,
+ table->nr_insn == 1/*string*/
+ );
+ if (table->opcode != NULL)
+ break;
+ table->opcode_rule = table->opcode_rule->next;
+ }
+
+ /* did we find anything */
+ if (table->opcode == NULL) {
+ return;
+ }
+ ASSERT(table->opcode != NULL);
+
+ /* back link what we found to its parent */
+ if (table->parent != NULL) {
+ ASSERT(table->parent->opcode != NULL);
+ table->opcode->parent = table->parent->opcode;
+ }
+
+ /* expand the raw instructions according to the opcode */
+ {
+ insn *entry;
+ for (entry = table->insns; entry != NULL; entry = entry->next) {
+ insn_table_insert_expanding(table, entry);
+ }
+ }
+
+ /* and do the same for the sub entries */
+ {
+ insn_table *entry;
+ for (entry = table->entries; entry != NULL; entry = entry->sibling) {
+ insn_table_expand_insns(entry);
+ }
+ }
+}
+
+
+
+
+#ifdef MAIN
+
+static void
+dump_insn_field(insn_field *field,
+ int indent)
+{
+
+ printf("(insn_field*)0x%x\n", (unsigned)field);
+
+ dumpf(indent, "(first %d)\n", field->first);
+
+ dumpf(indent, "(last %d)\n", field->last);
+
+ dumpf(indent, "(width %d)\n", field->width);
+
+ if (field->is_int)
+ dumpf(indent, "(is_int %d)\n", field->val_int);
+
+ if (field->is_slash)
+ dumpf(indent, "(is_slash)\n");
+
+ if (field->is_string)
+ dumpf(indent, "(is_string `%s')\n", field->val_string);
+
+ dumpf(indent, "(next 0x%x)\n", field->next);
+
+ dumpf(indent, "(prev 0x%x)\n", field->prev);
+
+
+}
+
+static void
+dump_insn_fields(insn_fields *fields,
+ int indent)
+{
+ int i;
+
+ printf("(insn_fields*)%p\n", fields);
+
+ dumpf(indent, "(first 0x%x)\n", fields->first);
+ dumpf(indent, "(last 0x%x)\n", fields->last);
+
+ dumpf(indent, "(value 0x%x)\n", fields->value);
+
+ for (i = 0; i < insn_bit_size; i++) {
+ dumpf(indent, "(bits[%d] ", i, fields->bits[i]);
+ dump_insn_field(fields->bits[i], indent+1);
+ dumpf(indent, " )\n");
+ }
+
+}
+
+
+static void
+dump_opcode_field(opcode_field *field, int indent, int levels)
+{
+ printf("(opcode_field*)%p\n", field);
+ if (levels && field != NULL) {
+ dumpf(indent, "(first %d)\n", field->first);
+ dumpf(indent, "(last %d)\n", field->last);
+ dumpf(indent, "(is_boolean %d)\n", field->is_boolean);
+ dumpf(indent, "(parent ");
+ dump_opcode_field(field->parent, indent, levels-1);
+ }
+}
+
+
+static void
+dump_insn_bits(insn_bits *bits, int indent, int levels)
+{
+ printf("(insn_bits*)%p\n", bits);
+
+ if (levels && bits != NULL) {
+ dumpf(indent, "(value %d)\n", bits->value);
+ dumpf(indent, "(opcode ");
+ dump_opcode_field(bits->opcode, indent+1, 0);
+ dumpf(indent, " )\n");
+ dumpf(indent, "(field ");
+ dump_insn_field(bits->field, indent+1);
+ dumpf(indent, " )\n");
+ dumpf(indent, "(last ");
+ dump_insn_bits(bits->last, indent+1, levels-1);
+ }
+}
+
+
+
+static void
+dump_insn(insn *entry, int indent, int levels)
+{
+ printf("(insn*)%p\n", entry);
+
+ if (levels && entry != NULL) {
+
+ dumpf(indent, "(file_entry ");
+ dump_table_entry(entry->file_entry, indent+1);
+ dumpf(indent, " )\n");
+
+ dumpf(indent, "(fields ");
+ dump_insn_fields(entry->fields, indent+1);
+ dumpf(indent, " )\n");
+
+ dumpf(indent, "(next ");
+ dump_insn(entry->next, indent+1, levels-1);
+ dumpf(indent, " )\n");
+
+ }
+
+}
+
+
+static void
+dump_insn_table(insn_table *table,
+ int indent, int levels)
+{
+
+ printf("(insn_table*)%p\n", table);
+
+ if (levels && table != NULL) {
+
+ dumpf(indent, "(opcode_nr %d)\n", table->opcode_nr);
+
+ dumpf(indent, "(expanded_bits ");
+ dump_insn_bits(table->expanded_bits, indent+1, -1);
+ dumpf(indent, " )\n");
+
+ dumpf(indent, "(int nr_insn %d)\n", table->nr_insn);
+
+ dumpf(indent, "(insns ");
+ dump_insn(table->insns, indent+1, table->nr_insn);
+ dumpf(indent, " )\n");
+
+ dumpf(indent, "(opcode_rule ");
+ dump_decode_rule(table->opcode_rule, indent+1);
+ dumpf(indent, " )\n");
+
+ dumpf(indent, "(opcode ");
+ dump_opcode_field(table->opcode, indent+1, 1);
+ dumpf(indent, " )\n");
+
+ dumpf(indent, "(nr_entries %d)\n", table->entries);
+ dumpf(indent, "(entries ");
+ dump_insn_table(table->entries, indent+1, table->nr_entries);
+ dumpf(indent, " )\n");
+
+ dumpf(indent, "(sibling ", table->sibling);
+ dump_insn_table(table->sibling, indent+1, levels-1);
+ dumpf(indent, " )\n");
+
+ dumpf(indent, "(parent ", table->parent);
+ dump_insn_table(table->parent, indent+1, 0);
+ dumpf(indent, " )\n");
+
+ }
+}
+
+int insn_bit_size = max_insn_bit_size;
+int hi_bit_nr;
+int generate_expanded_instructions;
+
+int
+main(int argc, char **argv)
+{
+ filter *filters = NULL;
+ decode_table *decode_rules = NULL;
+ insn_table *instructions = NULL;
+
+ if (argc != 5)
+ error("Usage: insn <filter> <hi-bit-nr> <decode-table> <insn-table>\n");
+
+ filters = new_filter(argv[1], filters);
+ hi_bit_nr = a2i(argv[2]);
+ ASSERT(hi_bit_nr < insn_bit_size);
+ decode_rules = load_decode_table(argv[3], hi_bit_nr);
+ instructions = load_insn_table(argv[4], decode_rules, filters);
+ insn_table_expand_insns(instructions);
+
+ dump_insn_table(instructions, 0, -1);
+ return 0;
+}
+
+#endif
diff --git a/gnu/dist/sim/ppc/ld-insn.h b/gnu/dist/sim/ppc/ld-insn.h
new file mode 100644
index 00000000000..e800f0dac23
--- /dev/null
+++ b/gnu/dist/sim/ppc/ld-insn.h
@@ -0,0 +1,281 @@
+/* This file is part of the program psim.
+
+ Copyright (C) 1994,1995,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.
+
+ */
+
+/*
+# --
+#
+#
+# Fields:
+#
+# 1 Instruction format as a `start-bit,content' pairs.
+# the content is one of a digit, field name or `/' (aka.0)
+#
+# 2 Format specifier
+#
+# 3 Flags: 64 - 64bit only
+# f - floating point enabled required
+#
+# 4 short name
+#
+# 5 Description
+#
+#
+# For flags marked 'model', the fields are interpreted as follows:
+#
+# 1 Not used
+#
+# 2 Not used
+#
+# 3 "macro"
+#
+# 4 String name for model
+#
+# 5 Specific CPU model, must be an identifier
+#
+# 6 Comma separated list of functional units
+
+*/
+
+
+/* Global constants */
+
+enum {
+ max_insn_bit_size = 32,
+};
+
+
+typedef struct _insn_field insn_field;
+struct _insn_field {
+ int first;
+ int last;
+ int width;
+ int is_int;
+ int is_slash;
+ int is_string;
+ int val_int;
+ char *pos_string;
+ char *val_string;
+ insn_field *next;
+ insn_field *prev;
+};
+
+typedef struct _insn_fields insn_fields;
+struct _insn_fields {
+ insn_field *bits[max_insn_bit_size];
+ insn_field *first;
+ insn_field *last;
+ unsigned value;
+};
+
+
+/****************************************************************/
+
+typedef struct _opcode_field opcode_field;
+struct _opcode_field {
+ int first;
+ int last;
+ int is_boolean;
+ unsigned boolean_constant;
+ opcode_field *parent;
+};
+
+
+/****************************************************************/
+
+typedef struct _insn_bits insn_bits;
+struct _insn_bits {
+ int is_expanded;
+ int value;
+ insn_field *field;
+ opcode_field *opcode;
+ insn_bits *last;
+};
+
+
+/****************************************************************/
+
+
+typedef enum {
+ insn_format,
+ insn_form,
+ insn_flags,
+ insn_mnemonic,
+ insn_name,
+ insn_comment,
+ nr_insn_table_fields
+} insn_table_fields;
+
+typedef enum {
+ function_type = insn_format,
+ function_name = insn_name,
+ function_param = insn_comment
+} function_table_fields;
+
+typedef enum {
+ model_name = insn_mnemonic,
+ model_identifer = insn_name,
+ model_default = insn_comment,
+} model_table_fields;
+
+typedef struct _insn insn;
+struct _insn {
+ table_entry *file_entry;
+ insn_fields *fields;
+ insn *next;
+};
+
+typedef struct _insn_undef insn_undef;
+struct _insn_undef {
+ insn_undef *next;
+ char *name;
+};
+
+typedef struct _model model;
+struct _model {
+ model *next;
+ char *name;
+ char *printable_name;
+ char *insn_default;
+ table_model_entry *func_unit_start;
+ table_model_entry *func_unit_end;
+};
+
+typedef struct _insn_table insn_table;
+struct _insn_table {
+ int opcode_nr;
+ insn_bits *expanded_bits;
+ int nr_insn;
+ insn *insns;
+ insn *functions;
+ insn *last_function;
+ decode_table *opcode_rule;
+ opcode_field *opcode;
+ int nr_entries;
+ insn_table *entries;
+ insn_table *sibling;
+ insn_table *parent;
+};
+
+typedef enum {
+ insn_model_name,
+ insn_model_fields,
+ nr_insn_model_table_fields
+} insn_model_table_fields;
+
+
+extern insn_table *load_insn_table
+(const char *file_name,
+ decode_table *decode_rules,
+ filter *filters);
+
+model *models;
+model *last_model;
+
+insn *model_macros;
+insn *last_model_macro;
+
+insn *model_functions;
+insn *last_model_function;
+
+insn *model_internal;
+insn *last_model_internal;
+
+insn *model_static;
+insn *last_model_static;
+
+insn *model_data;
+insn *last_model_data;
+
+int max_model_fields_len;
+
+extern void insn_table_insert_insn
+(insn_table *table,
+ table_entry *file_entry,
+ insn_fields *fields);
+
+
+/****************************************************************/
+
+/****************************************************************/
+
+typedef void leaf_handler
+(insn_table *entry,
+ lf *file,
+ void *data,
+ int depth);
+
+typedef void insn_handler
+(insn_table *table,
+ lf *file,
+ void *data,
+ insn *instruction,
+ int depth);
+
+typedef void padding_handler
+(insn_table *table,
+ lf *file,
+ void *data,
+ int depth,
+ int opcode_nr);
+
+
+extern void insn_table_traverse_tree
+(insn_table *table,
+ lf *file,
+ void *data,
+ int depth,
+ leaf_handler *start,
+ insn_handler *handler,
+ leaf_handler *end,
+ padding_handler *padding);
+
+
+extern void insn_table_traverse_insn
+(insn_table *table,
+ lf *file,
+ void *data,
+ insn_handler *handler);
+
+
+
+/****************************************************************/
+
+typedef void function_handler
+(insn_table *table,
+ lf *file,
+ void *data,
+ table_entry *function);
+
+extern void
+insn_table_traverse_function
+(insn_table *table,
+ lf *file,
+ void *data,
+ function_handler *leaf);
+
+/****************************************************************/
+
+
+
+extern void insn_table_expand_insns
+(insn_table *table);
+
+extern int insn_table_depth
+(insn_table *table);
diff --git a/gnu/dist/sim/ppc/lf.c b/gnu/dist/sim/ppc/lf.c
index 7672195c99e..2a420151efa 100644
--- a/gnu/dist/sim/ppc/lf.c
+++ b/gnu/dist/sim/ppc/lf.c
@@ -44,24 +44,27 @@ struct _lf {
int line_nr; /* nr complete lines written, curr line is line_nr+1 */
int indent;
int line_blank;
- char *file_name;
- int number_lines;
+ const char *name;
+ const char *program;
+ lf_file_references references;
+ lf_file_type type;
};
lf *
lf_open(char *name,
char *real_name,
- int number_lines)
+ lf_file_references references,
+ lf_file_type type,
+ const char *program)
{
/* create a file object */
lf *new_lf = ZALLOC(lf);
ASSERT(new_lf != NULL);
- new_lf->number_lines = number_lines;
- new_lf->file_name = (real_name == NULL
- ? name
- : real_name);
-
+ new_lf->references = references;
+ new_lf->type = type;
+ new_lf->name = (real_name == NULL ? name : real_name);
+ new_lf->program = program;
/* attach to stdout if pipe */
if (!strcmp(name, "-")) {
new_lf->stream = stdout;
@@ -69,7 +72,10 @@ lf_open(char *name,
else {
/* create a new file */
new_lf->stream = fopen(name, "w");
- ASSERT(new_lf->stream != NULL);
+ if (new_lf->stream == NULL) {
+ perror(name);
+ exit(1);
+ }
}
return new_lf;
}
@@ -88,10 +94,11 @@ lf_close(lf *file)
}
-void
+int
lf_putchr(lf *file,
const char chr)
{
+ int nr = 0;
if (chr == '\n') {
file->line_nr += 1;
file->line_blank = 1;
@@ -100,9 +107,12 @@ lf_putchr(lf *file,
int pad;
for (pad = file->indent; pad > 0; pad--)
putc(' ', file->stream);
+ nr += file->indent;
file->line_blank = 0;
}
putc(chr, file->stream);
+ nr += 1;
+ return nr;
}
void
@@ -112,52 +122,59 @@ lf_indent_suppress(lf *file)
}
-void
+int
lf_putstr(lf *file,
const char *string)
{
+ int nr = 0;
const char *chp;
if (string != NULL) {
for (chp = string; *chp != '\0'; chp++) {
- lf_putchr(file, *chp);
+ nr += lf_putchr(file, *chp);
}
}
+ return nr;
}
-static void
+static int
do_lf_putunsigned(lf *file,
unsigned u)
{
+ int nr = 0;
if (u > 0) {
- do_lf_putunsigned(file, u / 10);
- lf_putchr(file, (u % 10) + '0');
+ nr += do_lf_putunsigned(file, u / 10);
+ nr += lf_putchr(file, (u % 10) + '0');
}
+ return nr;
}
-void
+int
lf_putint(lf *file,
int decimal)
{
+ int nr = 0;
if (decimal == 0)
- lf_putchr(file, '0');
+ nr += lf_putchr(file, '0');
else if (decimal < 0) {
- lf_putchr(file, '-');
- do_lf_putunsigned(file, -decimal);
+ nr += lf_putchr(file, '-');
+ nr += do_lf_putunsigned(file, -decimal);
}
else if (decimal > 0) {
- do_lf_putunsigned(file, decimal);
+ nr += do_lf_putunsigned(file, decimal);
}
else
ASSERT(0);
+ return nr;
}
-void
+int
lf_printf(lf *file,
const char *fmt,
...)
{
+ int nr = 0;
char buf[1024];
va_list ap;
@@ -165,15 +182,18 @@ lf_printf(lf *file,
vsprintf(buf, fmt, ap);
/* FIXME - this is really stuffed but so is vsprintf() on a sun! */
ASSERT(strlen(buf) > 0 && strlen(buf) < sizeof(buf));
- lf_putstr(file, buf);
+ nr += lf_putstr(file, buf);
va_end(ap);
+ return nr;
}
-void
-lf_print_c_code(lf *file, char *code)
+int
+lf_print__c_code(lf *file,
+ const char *code)
{
- char *chp = code;
+ int nr = 0;
+ const char *chp = code;
int in_bit_field = 0;
while (*chp != '\0') {
if (*chp == '\t')
@@ -183,51 +203,60 @@ lf_print_c_code(lf *file, char *code)
while (*chp != '\0' && *chp != '\n') {
if (chp[0] == '{' && !isspace(chp[1])) {
in_bit_field = 1;
- lf_putchr(file, '_');
+ nr += lf_putchr(file, '_');
}
else if (in_bit_field && chp[0] == ':') {
- lf_putchr(file, '_');
+ nr += lf_putchr(file, '_');
}
else if (in_bit_field && *chp == '}') {
- lf_putchr(file, '_');
+ nr += lf_putchr(file, '_');
in_bit_field = 0;
}
else {
- lf_putchr(file, *chp);
+ nr += lf_putchr(file, *chp);
}
chp++;
}
if (in_bit_field)
error("bit field paren miss match some where\n");
if (*chp == '\n') {
- lf_putchr(file, '\n');
+ nr += lf_putchr(file, '\n');
chp++;
}
}
- lf_putchr(file, '\n');
+ nr += lf_putchr(file, '\n');
+ return nr;
}
-void
-lf_print_c_line_nr(lf *file,
- int line_nr,
- char *file_name)
+int
+lf_print__external_reference(lf *file,
+ int line_nr,
+ const char *file_name)
{
- if (file->number_lines) {
+ int nr = 0;
+ switch (file->references) {
+ case lf_include_references:
lf_indent_suppress(file);
- lf_putstr(file, "#line ");
- lf_putint(file, line_nr);
- lf_putstr(file, " \"");
- lf_putstr(file, file_name);
- lf_putstr(file, "\"\n");
+ nr += lf_putstr(file, "#line ");
+ nr += lf_putint(file, line_nr);
+ nr += lf_putstr(file, " \"");
+ nr += lf_putstr(file, file_name);
+ nr += lf_putstr(file, "\"\n");
+ break;
+ case lf_omit_references:
+ break;
}
+ return nr;
}
-void
-lf_print_lf_c_line_nr(lf *file)
+int
+lf_print__internal_reference(lf *file)
{
- lf_print_c_line_nr(file, file->line_nr+2, file->file_name);
+ int nr = 0;
+ nr += lf_print__external_reference(file, file->line_nr+2, file->name);
/* line_nr == last_line, want to number from next */
+ return nr;
}
void
@@ -237,10 +266,14 @@ lf_indent(lf *file, int delta)
}
-void
-lf_print_copyleft(lf *file)
+int
+lf_print__gnu_copyleft(lf *file)
{
- lf_putstr(file, "\
+ int nr = 0;
+ switch (file->type) {
+ case lf_is_c:
+ case lf_is_h:
+ nr += lf_printf(file, "\
/* This file is part of the program psim.
Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
@@ -261,35 +294,121 @@ lf_print_copyleft(lf *file)
--
- This file was generated by the program gen */
-");
+ This file was generated by the program %s */
+", filter_filename(file->program));
+ break;
+ default:
+ ASSERT(0);
+ break;
+ }
+ return nr;
}
-void
-lf_print_binary(lf *file, int decimal, int width)
+int
+lf_putbin(lf *file, int decimal, int width)
{
+ int nr = 0;
int bit;
ASSERT(width > 0);
-
for (bit = 1 << (width-1); bit != 0; bit >>= 1) {
if (decimal & bit)
- lf_putchr(file, '1');
+ nr += lf_putchr(file, '1');
else
- lf_putchr(file, '0');
+ nr += lf_putchr(file, '0');
}
+ return nr;
+}
+int
+lf_print__this_file_is_empty(lf *file)
+{
+ int nr = 0;
+ switch (file->type) {
+ case lf_is_c:
+ case lf_is_h:
+ nr += lf_printf(file,
+ "/* This generated file (%s) is intentionally left blank */\n",
+ file->name);
+ break;
+ default:
+ ASSERT(0);
+ }
+ return nr;
}
-void
+int
+lf_print__ucase_filename(lf *file)
+{
+ int nr = 0;
+ const char *chp = file->name;
+ while (*chp != '\0') {
+ char ch = *chp;
+ if (islower(ch)) {
+ nr += lf_putchr(file, toupper(ch));
+ }
+ else if (ch == '.')
+ nr += lf_putchr(file, '_');
+ else
+ nr += lf_putchr(file, ch);
+ chp++;
+ }
+ return nr;
+}
+
+int
+lf_print__file_start(lf *file)
+{
+ int nr = 0;
+ switch (file->type) {
+ case lf_is_h:
+ case lf_is_c:
+ nr += lf_print__gnu_copyleft(file);
+ nr += lf_printf(file, "\n");
+ nr += lf_printf(file, "#ifndef _");
+ nr += lf_print__ucase_filename(file);
+ nr += lf_printf(file, "_\n");
+ nr += lf_printf(file, "#define _");
+ nr += lf_print__ucase_filename(file);
+ nr += lf_printf(file, "_\n");
+ nr += lf_printf(file, "\n");
+ break;
+ default:
+ ASSERT(0);
+ }
+ return nr;
+}
+
+
+int
+lf_print__file_finish(lf *file)
+{
+ int nr = 0;
+ switch (file->type) {
+ case lf_is_h:
+ case lf_is_c:
+ nr += lf_printf(file, "\n");
+ nr += lf_printf(file, "#endif /* _");
+ nr += lf_print__ucase_filename(file);
+ nr += lf_printf(file, "_*/\n");
+ break;
+ default:
+ ASSERT(0);
+ }
+ return nr;
+}
+
+
+int
lf_print_function_type(lf *file,
const char *type,
const char *prefix,
const char *trailing_space)
{
- lf_printf(file, "%s\\\n(%s)", prefix, type);
+ int nr = 0;
+ nr += lf_printf(file, "%s\\\n(%s)", prefix, type);
if (trailing_space != NULL)
- lf_printf(file, "%s", trailing_space);
+ nr += lf_printf(file, "%s", trailing_space);
#if 0
const char *type_pointer = strrchr(type, '*');
int type_pointer_offset = (type_pointer != NULL
@@ -316,4 +435,6 @@ lf_print_function_type(lf *file,
if (trailing_space != NULL && type_pointer_offset < strlen(type) - 1)
lf_printf(file, trailing_space);
#endif
+ return nr;
}
+
diff --git a/gnu/dist/sim/ppc/lf.h b/gnu/dist/sim/ppc/lf.h
index 99508872858..7bf6d1cafff 100644
--- a/gnu/dist/sim/ppc/lf.h
+++ b/gnu/dist/sim/ppc/lf.h
@@ -23,74 +23,106 @@
typedef struct _lf lf;
+typedef enum {
+ lf_is_h,
+ lf_is_c,
+ lf_is_text,
+} lf_file_type;
+
+
+typedef enum {
+ lf_include_references,
+ lf_omit_references,
+} lf_file_references;
-#if !defined (__attribute__) && (!defined(__GNUC__) || __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7))
-#define __attribute__(arg)
-#endif
/* Open the file NAME for writing. REAL_NAME is to be included in any
line number outputs. The output of line number information can be
suppressed with LINE_NUMBERS */
+
extern lf *lf_open
(char *name,
char *real_name,
- int number_lines);
+ lf_file_references file_references,
+ lf_file_type type,
+ const char *program);
extern void lf_close
(lf *file);
-/* Suppress indentation for the next new line (current if not yet
- started) */
-extern void lf_indent_suppress
-(lf *file);
+/* Basic output functions */
-extern void lf_putchr
+extern int lf_putchr
(lf *file,
const char ch);
-extern void lf_putstr
+extern int lf_putstr
(lf *file,
const char *string);
-extern void lf_putint
+extern int lf_putint
(lf *file,
int decimal);
-extern void lf_printf
+extern int lf_putbin
+(lf *file,
+ int decimal,
+ int width);
+
+extern int lf_printf
(lf *file,
const char *fmt,
...) __attribute__((format(printf, 2, 3)));
-extern void lf_print_lf_c_line_nr
+
+/* Indentation control.
+
+ lf_indent_suppress suppresses indentation on the next line (current
+ line if that has not yet been started) */
+
+extern void lf_indent_suppress
(lf *file);
extern void lf_indent
(lf *file,
int delta);
-extern void lf_print_copyleft
+
+/* Print generic text: */
+
+
+extern int lf_print__gnu_copyleft
(lf *file);
-extern void lf_print_binary
-(lf *file,
- int decimal,
- int width);
+extern int lf_print__file_start
+(lf *file);
-/* it is assumed that each line of code is prefixed by a tab character
- that should be suppressed */
-extern void lf_print_c_code
-(lf *file,
- char *code);
+extern int lf_print__this_file_is_empty
+(lf *file);
+extern int lf_print__file_finish
+(lf *file);
-extern void lf_print_c_line_nr
+extern int lf_print__internal_reference
+(lf *file);
+
+extern int lf_print__external_reference
(lf *file,
int line_nr,
- char *file_name);
+ const char *file_name);
+
+extern int lf_print__ucase_filename
+(lf *file);
+
+/* Tab prefix is suppressed */
+
+extern int lf_print__c_code
+(lf *file,
+ const char *code);
-extern void lf_print_function_type
+extern int lf_print_function_type
(lf *file,
const char *type,
const char *prefix,
diff --git a/gnu/dist/sim/ppc/main.c b/gnu/dist/sim/ppc/main.c
index ac03f7e6235..ee6331d3308 100644
--- a/gnu/dist/sim/ppc/main.c
+++ b/gnu/dist/sim/ppc/main.c
@@ -1,6 +1,6 @@
/* This file is part of the program psim.
- Copyright (C) 1994-1996, Andrew Cagney <cagney@highland.com.au>
+ 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
@@ -21,10 +21,14 @@
#include <stdarg.h>
#include <stdio.h>
+#include <fcntl.h>
+
+#include <signal.h>
#include "psim.h"
#include "options.h"
#include "device.h" /* FIXME: psim should provide the interface */
+#include "events.h" /* FIXME: psim should provide the interface */
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
@@ -42,13 +46,21 @@
#endif
#endif
+#include <errno.h>
+
+#if !defined(O_NDELAY) || !defined(F_GETFL) || !defined(F_SETFL)
+#undef WITH_STDIO
+#define WITH_STDIO DO_USE_STDIO
+#endif
+
+
extern char **environ;
-static psim *simulation;
+static psim *simulation = NULL;
void
-printf_filtered(const char *msg, ...)
+sim_io_printf_filtered(const char *msg, ...)
{
va_list ap;
va_start(ap, msg);
@@ -57,26 +69,154 @@ printf_filtered(const char *msg, ...)
}
void
-flush_stdoutput(void)
-{
- fflush (stdout);
-}
-
-void
error (char *msg, ...)
{
va_list ap;
va_start(ap, msg);
vprintf(msg, ap);
+ printf("\n");
va_end(ap);
/* any final clean up */
- if (ppc_trace[trace_print_info])
+ if (ppc_trace[trace_print_info] && simulation != NULL)
psim_print_info (simulation, ppc_trace[trace_print_info]);
exit (1);
}
+int
+sim_io_write_stdout(const char *buf,
+ int sizeof_buf)
+{
+ switch (CURRENT_STDIO) {
+ case DO_USE_STDIO:
+ {
+ int i;
+ for (i = 0; i < sizeof_buf; i++) {
+ putchar(buf[i]);
+ }
+ return i;
+ }
+ break;
+ case DONT_USE_STDIO:
+ return write(1, buf, sizeof_buf);
+ break;
+ default:
+ error("sim_io_write_stdout: invalid switch\n");
+ }
+ return 0;
+}
+
+int
+sim_io_write_stderr(const char *buf,
+ int sizeof_buf)
+{
+ switch (CURRENT_STDIO) {
+ case DO_USE_STDIO:
+ {
+ int i;
+ for (i = 0; i < sizeof_buf; i++) {
+ fputc(buf[i], stderr);
+ }
+ return i;
+ }
+ break;
+ case DONT_USE_STDIO:
+ return write(2, buf, sizeof_buf);
+ break;
+ default:
+ error("sim_io_write_stdout: invalid switch\n");
+ }
+ return 0;
+}
+
+int
+sim_io_read_stdin(char *buf,
+ int sizeof_buf)
+{
+ switch (CURRENT_STDIO) {
+ case DO_USE_STDIO:
+ if (sizeof_buf > 1) {
+ if (fgets(buf, sizeof_buf, stdin) != NULL)
+ return strlen(buf);
+ }
+ else if (sizeof_buf == 1) {
+ char b[2];
+ if (fgets(b, sizeof(b), stdin) != NULL) {
+ memcpy(buf, b, strlen(b));
+ return strlen(b);
+ }
+ }
+ else if (sizeof_buf == 0)
+ return 0;
+ return sim_io_eof;
+ break;
+ case DONT_USE_STDIO:
+#if defined(O_NDELAY) && defined(F_GETFL) && defined(F_SETFL)
+ {
+ /* check for input */
+ int flags;
+ int status;
+ int nr_read;
+ int result;
+ /* get the old status */
+ flags = fcntl(0, F_GETFL, 0);
+ if (flags == -1) {
+ perror("sim_io_read_stdin");
+ return sim_io_eof;
+ }
+ /* temp, disable blocking IO */
+ status = fcntl(0, F_SETFL, flags | O_NDELAY);
+ if (status == -1) {
+ perror("sim_io_read_stdin");
+ return sim_io_eof;
+ }
+ /* try for input */
+ nr_read = read(0, buf, sizeof_buf);
+ if (nr_read > 0
+ || (nr_read == 0 && sizeof_buf == 0))
+ result = nr_read;
+ else if (nr_read == 0)
+ result = sim_io_eof;
+ else { /* nr_read < 0 */
+ if (errno == EAGAIN)
+ result = sim_io_not_ready;
+ else
+ result = sim_io_eof;
+ }
+ /* return to regular vewing */
+ status = fcntl(0, F_SETFL, flags);
+ if (status == -1) {
+ perror("sim_io_read_stdin");
+ return sim_io_eof;
+ }
+ return result;
+ }
+ break;
+#endif
+ default:
+ error("sim_io_read_stdin: invalid switch\n");
+ break;
+ }
+ return 0;
+}
+
+void
+sim_io_flush_stdoutput(void)
+{
+ switch (CURRENT_STDIO) {
+ case DO_USE_STDIO:
+ fflush (stdout);
+ break;
+ case DONT_USE_STDIO:
+ break;
+ default:
+ error("sim_io_flush_stdoutput: invalid switch\n");
+ break;
+ }
+}
+
+
void *
zalloc(long size)
{
@@ -93,6 +233,27 @@ zfree(void *chunk)
free(chunk);
}
+/* When a CNTRL-C occures, queue an event to shut down the simulation */
+
+static void
+cntrl_c_simulation(void *data)
+{
+ psim_halt(simulation,
+ psim_nr_cpus(simulation),
+ was_signalled,
+ SIGINT);
+}
+
+static RETSIGTYPE
+cntrl_c(int sig)
+{
+ event_queue_schedule_after_signal(psim_event_queue(simulation),
+ 0 /*NOW*/,
+ cntrl_c_simulation,
+ NULL);
+}
+
+
int
main(int argc, char **argv)
{
@@ -103,8 +264,14 @@ main(int argc, char **argv)
/* parse the arguments */
argv = psim_options(root, argv + 1);
- if (argv[0] == NULL)
- psim_usage(0);
+ if (argv[0] == NULL) {
+ if (ppc_trace[trace_opts]) {
+ print_options ();
+ return 0;
+ } else {
+ psim_usage(0);
+ }
+ }
name_of_file = argv[0];
if (ppc_trace[trace_opts])
@@ -123,7 +290,12 @@ main(int argc, char **argv)
psim_init(simulation);
psim_stack(simulation, argv, environ);
- psim_run(simulation);
+ {
+ RETSIGTYPE (*prev) ();
+ prev = signal(SIGINT, cntrl_c);
+ psim_run(simulation);
+ signal(SIGINT, prev);
+ }
/* any final clean up */
if (ppc_trace[trace_print_info])
diff --git a/gnu/dist/sim/ppc/misc.c b/gnu/dist/sim/ppc/misc.c
index eb499773cd8..d8e54ed497b 100644
--- a/gnu/dist/sim/ppc/misc.c
+++ b/gnu/dist/sim/ppc/misc.c
@@ -1,6 +1,6 @@
/* This file is part of the program psim.
- Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
+ 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
@@ -21,6 +21,7 @@
#include <stdio.h>
#include <stdarg.h>
+#include <ctype.h>
#include "config.h"
#include "misc.h"
@@ -69,30 +70,74 @@ dumpf (int indent, char *msg, ...)
}
-int
-it_is(const char *flag,
- const char *flags)
+unsigned
+a2i(const char *a)
{
- int flag_len = strlen(flag);
- while (*flags != '\0') {
- if (!strncmp(flags, flag, flag_len)
- && (flags[flag_len] == ',' || flags[flag_len] == '\0'))
- return 1;
- while (*flags != ',') {
- if (*flags == '\0')
- return 0;
- flags++;
+ int neg = 0;
+ int base = 10;
+ unsigned num = 0;
+ int looping;
+
+ while (isspace (*a))
+ a++;
+
+ if (*a == '-') {
+ neg = 1;
+ a++;
+ }
+
+ if (*a == '0') {
+ if (a[1] == 'x' || a[1] == 'X') {
+ a += 2;
+ base = 16;
}
- flags++;
+ else
+ base = 8;
}
- return 0;
-}
+ looping = 1;
+ while (looping) {
+ int ch = *a++;
+
+ switch (base) {
+ default:
+ looping = 0;
+ break;
+
+ case 10:
+ if (ch >= '0' && ch <= '9') {
+ num = (num * 10) + (ch - '0');
+ } else {
+ looping = 0;
+ }
+ break;
+
+ case 8:
+ if (ch >= '0' && ch <= '7') {
+ num = (num * 8) + (ch - '0');
+ } else {
+ looping = 0;
+ }
+ break;
+
+ case 16:
+ if (ch >= '0' && ch <= '9') {
+ num = (num * 16) + (ch - '0');
+ } else if (ch >= 'a' && ch <= 'f') {
+ num = (num * 16) + (ch - 'a' + 10);
+ } else if (ch >= 'A' && ch <= 'F') {
+ num = (num * 16) + (ch - 'A' + 10);
+ } else {
+ looping = 0;
+ }
+ break;
+ }
+ }
-unsigned
-a2i(const char *a)
-{
- return strtoul(a, 0, 0);
+ if (neg)
+ num = - num;
+
+ return num;
}
unsigned
@@ -100,9 +145,9 @@ target_a2i(int ms_bit_nr,
const char *a)
{
if (ms_bit_nr)
- return (ms_bit_nr - strtoul(a, 0, 0));
+ return (ms_bit_nr - a2i(a));
else
- return strtoul(a, 0, 0);
+ return a2i(a);
}
unsigned
@@ -116,3 +161,55 @@ i2target(int ms_bit_nr,
}
+int
+name2i(const char *names,
+ const name_map *map)
+{
+ const name_map *curr;
+ const char *name = names;
+ while (*name != '\0') {
+ /* find our name */
+ char *end = strchr(name, ',');
+ char *next;
+ int len;
+ if (end == NULL) {
+ end = strchr(name, '\0');
+ next = end;
+ }
+ else {
+ next = end + 1;
+ }
+ len = end - name;
+ /* look it up */
+ curr = map;
+ while (curr->name != NULL) {
+ if (strncmp(curr->name, name, len) == 0
+ && strlen(curr->name) == len)
+ return curr->i;
+ curr++;
+ }
+ name = next;
+ }
+ /* nothing found, possibly return a default */
+ curr = map;
+ while (curr->name != NULL)
+ curr++;
+ if (curr->i >= 0)
+ return curr->i;
+ else
+ error("%s contains no valid names\n", names);
+ return 0;
+}
+
+const char *
+i2name(const int i,
+ const name_map *map)
+{
+ while (map->name != NULL) {
+ if (map->i == i)
+ return map->name;
+ map++;
+ }
+ error("map lookup failed for %d\n", i);
+ return NULL;
+}
diff --git a/gnu/dist/sim/ppc/misc.h b/gnu/dist/sim/ppc/misc.h
index def46bc7444..041bd6d2cac 100644
--- a/gnu/dist/sim/ppc/misc.h
+++ b/gnu/dist/sim/ppc/misc.h
@@ -19,6 +19,31 @@
*/
+/* Frustrating header junk */
+
+#include "config.h"
+
+#include <stdio.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
+
+#if !defined (__attribute__) && (!defined(__GNUC__) || __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7))
+#define __attribute__(arg)
+#endif
+
+
+
#include "filter_filename.h"
extern void error
@@ -40,10 +65,6 @@ extern void *zalloc
extern void dumpf
(int indent, char *msg, ...);
-extern int it_is
-(const char *flag,
- const char *flags);
-
extern unsigned target_a2i
(int ms_bit_nr,
const char *a);
@@ -54,3 +75,20 @@ extern unsigned i2target
extern unsigned a2i
(const char *a);
+
+/* Try looking for name in the map table (returning the corresponding
+ integer value). If that fails, try converting the name into an
+ integer */
+
+typedef struct _name_map {
+ const char *name;
+ int i;
+} name_map;
+
+extern int name2i
+(const char *name,
+ const name_map *map);
+
+extern const char *i2name
+(const int i,
+ const name_map *map);
diff --git a/gnu/dist/sim/ppc/mkinstalldirs b/gnu/dist/sim/ppc/mkinstalldirs
new file mode 100644
index 00000000000..cc8783edce3
--- /dev/null
+++ b/gnu/dist/sim/ppc/mkinstalldirs
@@ -0,0 +1,36 @@
+#! /bin/sh
+# mkinstalldirs --- make directory hierarchy
+# Author: Noah Friedman <friedman@prep.ai.mit.edu>
+# Created: 1993-05-16
+# Last modified: 1994-03-25
+# Public domain
+
+errstatus=0
+
+for file in ${1+"$@"} ; do
+ set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
+ shift
+
+ pathcomp=
+ for d in ${1+"$@"} ; do
+ pathcomp="$pathcomp$d"
+ case "$pathcomp" in
+ -* ) pathcomp=./$pathcomp ;;
+ esac
+
+ if test ! -d "$pathcomp"; then
+ echo "mkdir $pathcomp" 1>&2
+ mkdir "$pathcomp" > /dev/null 2>&1 || lasterr=$?
+ fi
+
+ if test ! -d "$pathcomp"; then
+ errstatus=$lasterr
+ fi
+
+ pathcomp="$pathcomp/"
+ done
+done
+
+exit $errstatus
+
+# mkinstalldirs ends here
diff --git a/gnu/dist/sim/ppc/mon.c b/gnu/dist/sim/ppc/mon.c
index 4d5264bc3f6..2bdaf474158 100644
--- a/gnu/dist/sim/ppc/mon.c
+++ b/gnu/dist/sim/ppc/mon.c
@@ -1,6 +1,6 @@
/* This file is part of the program psim.
- Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
+ 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
@@ -64,10 +64,15 @@
int getrusage();
#endif
+#define MAX_BYTE_READWRITE 9
+#define MAX_SHIFT_READWRITE 3
+
struct _cpu_mon {
count_type issue_count[nr_itable_entries];
count_type read_count;
+ count_type read_byte_count[MAX_BYTE_READWRITE];
count_type write_count;
+ count_type write_byte_count[MAX_BYTE_READWRITE];
count_type unaligned_read_count;
count_type unaligned_write_count;
count_type event_count[nr_mon_events];
@@ -131,6 +136,7 @@ mon_read(unsigned_word ea,
{
cpu_mon *monitor = cpu_monitor(processor);
monitor->read_count += 1;
+ monitor->read_byte_count[nr_bytes] += 1;
if ((nr_bytes - 1) & ea)
monitor->unaligned_read_count += 1;
}
@@ -146,6 +152,7 @@ mon_write(unsigned_word ea,
{
cpu_mon *monitor = cpu_monitor(processor);
monitor->write_count += 1;
+ monitor->write_byte_count[nr_bytes] += 1;
if ((nr_bytes - 1) & ea)
monitor->unaligned_write_count += 1;
}
@@ -157,22 +164,25 @@ mon_event(mon_events event,
unsigned_word cia)
{
cpu_mon *monitor = cpu_monitor(processor);
- ASSERT(event >= 0 && event < nr_mon_events);
+ ASSERT(event < nr_mon_events);
monitor->event_count[event] += 1;
}
-STATIC_INLINE_MON\
-(count_type)
-mon_get_number_of_insns(cpu_mon *monitor)
+INLINE_MON\
+(unsigned)
+mon_get_number_of_insns(mon *monitor,
+ int cpu_nr)
{
itable_index index;
- count_type total_insns = 0;
+ unsigned total_insns = 0;
+ ASSERT(cpu_nr >= 0 && cpu_nr < monitor->nr_cpus);
for (index = 0; index < nr_itable_entries; index++)
- total_insns += monitor->issue_count[index];
+ total_insns += monitor->cpu_monitor[cpu_nr].issue_count[index];
return total_insns;
}
-static int
+STATIC_INLINE_MON\
+(int)
mon_sort_instruction_names(const void *ptr_a, const void *ptr_b)
{
itable_index a = *(const itable_index *)ptr_a;
@@ -213,21 +223,45 @@ mon_print_info(psim *system,
int verbose)
{
char buffer[20];
+ char buffer1[20];
+ char buffer2[20];
+ char buffer4[20];
+ char buffer8[20];
int cpu_nr;
int len_cpu;
int len_num = 0;
+ int len_sub_num[MAX_BYTE_READWRITE];
int len;
+ int i;
long total_insns = 0;
long cpu_insns_second = 0;
+ long total_sim_cycles = 0;
+ long sim_cycles_second = 0;
double cpu_time = 0.0;
+ for (i = 0; i < MAX_BYTE_READWRITE; i++)
+ len_sub_num[i] = 0;
+
for (cpu_nr = 0; cpu_nr < monitor->nr_cpus; cpu_nr++) {
- count_type num_insns = mon_get_number_of_insns(&monitor->cpu_monitor[cpu_nr]);
+ count_type num_insns = mon_get_number_of_insns(monitor, cpu_nr);
total_insns += num_insns;
len = strlen (mon_add_commas(buffer, sizeof(buffer), num_insns));
if (len_num < len)
len_num = len;
+
+ for (i = 0; i <= MAX_SHIFT_READWRITE; i++) {
+ int size = 1<<i;
+ len = strlen (mon_add_commas(buffer, sizeof(buffer),
+ monitor->cpu_monitor[cpu_nr].read_byte_count[size]));
+ if (len_sub_num[size] < len)
+ len_sub_num[size] = len;
+
+ len = strlen (mon_add_commas(buffer, sizeof(buffer),
+ monitor->cpu_monitor[cpu_nr].write_byte_count[size]));
+ if (len_sub_num[size] < len)
+ len_sub_num[size] = len;
+ }
}
sprintf (buffer, "%d", (int)monitor->nr_cpus + 1);
@@ -242,8 +276,15 @@ mon_print_info(psim *system,
cpu_time = (double)mytime.ru_utime.tv_sec + (((double)mytime.ru_utime.tv_usec) / 1000000.0);
}
}
- if (cpu_time > 0 && total_insns > 0)
- cpu_insns_second = (long)(((double)total_insns / cpu_time) + 0.5);
+ if (WITH_EVENTS)
+ total_sim_cycles = event_queue_time(psim_event_queue(system)) - 1;
+ if (cpu_time > 0) {
+ if (total_insns > 0)
+ cpu_insns_second = (long)(((double)total_insns / cpu_time) + 0.5);
+ if (total_sim_cycles) {
+ sim_cycles_second = (long)(((double)total_sim_cycles / cpu_time) + 0.5);
+ }
+ }
#endif
for (cpu_nr = 0; cpu_nr < monitor->nr_cpus; cpu_nr++) {
@@ -304,36 +345,60 @@ mon_print_info(psim *system,
}
if (monitor->cpu_monitor[cpu_nr].read_count)
- printf_filtered ("CPU #%*d executed %*s data read%s.\n",
+ printf_filtered ("CPU #%*d executed %*s read%s (%*s 1-byte, %*s 2-byte, %*s 4-byte, %*s 8-byte).\n",
len_cpu, cpu_nr+1,
len_num, mon_add_commas(buffer,
sizeof(buffer),
monitor->cpu_monitor[cpu_nr].read_count),
- (monitor->cpu_monitor[cpu_nr].read_count == 1) ? "" : "s");
+ (monitor->cpu_monitor[cpu_nr].read_count == 1) ? "" : "s",
+ len_sub_num[1], mon_add_commas(buffer1,
+ sizeof(buffer1),
+ monitor->cpu_monitor[cpu_nr].read_byte_count[1]),
+ len_sub_num[2], mon_add_commas(buffer2,
+ sizeof(buffer2),
+ monitor->cpu_monitor[cpu_nr].read_byte_count[2]),
+ len_sub_num[4], mon_add_commas(buffer4,
+ sizeof(buffer4),
+ monitor->cpu_monitor[cpu_nr].read_byte_count[4]),
+ len_sub_num[8], mon_add_commas(buffer8,
+ sizeof(buffer8),
+ monitor->cpu_monitor[cpu_nr].read_byte_count[8]));
if (monitor->cpu_monitor[cpu_nr].write_count)
- printf_filtered ("CPU #%*d executed %*s data write%s.\n",
+ printf_filtered ("CPU #%*d executed %*s write%s (%*s 1-byte, %*s 2-byte, %*s 4-byte, %*s 8-byte).\n",
len_cpu, cpu_nr+1,
len_num, mon_add_commas(buffer,
sizeof(buffer),
monitor->cpu_monitor[cpu_nr].write_count),
- (monitor->cpu_monitor[cpu_nr].write_count == 1) ? "" : "s");
+ (monitor->cpu_monitor[cpu_nr].write_count == 1) ? "" : "s",
+ len_sub_num[1], mon_add_commas(buffer1,
+ sizeof(buffer1),
+ monitor->cpu_monitor[cpu_nr].write_byte_count[1]),
+ len_sub_num[2], mon_add_commas(buffer2,
+ sizeof(buffer2),
+ monitor->cpu_monitor[cpu_nr].write_byte_count[2]),
+ len_sub_num[4], mon_add_commas(buffer4,
+ sizeof(buffer4),
+ monitor->cpu_monitor[cpu_nr].write_byte_count[4]),
+ len_sub_num[8], mon_add_commas(buffer8,
+ sizeof(buffer8),
+ monitor->cpu_monitor[cpu_nr].write_byte_count[8]));
if (monitor->cpu_monitor[cpu_nr].unaligned_read_count)
- printf_filtered ("CPU #%*d executed %*s unaligned data read%s.\n",
+ printf_filtered ("CPU #%*d executed %*s unaligned read%s.\n",
len_cpu, cpu_nr+1,
len_num, mon_add_commas(buffer,
sizeof(buffer),
- monitor->cpu_monitor[cpu_nr].read_count),
- (monitor->cpu_monitor[cpu_nr].read_count == 1) ? "" : "s");
+ monitor->cpu_monitor[cpu_nr].unaligned_read_count),
+ (monitor->cpu_monitor[cpu_nr].unaligned_read_count == 1) ? "" : "s");
if (monitor->cpu_monitor[cpu_nr].unaligned_write_count)
- printf_filtered ("CPU #%*d executed %*s unaligned data write%s.\n",
+ printf_filtered ("CPU #%*d executed %*s unaligned write%s.\n",
len_cpu, cpu_nr+1,
len_num, mon_add_commas(buffer,
sizeof(buffer),
- monitor->cpu_monitor[cpu_nr].write_count),
- (monitor->cpu_monitor[cpu_nr].write_count == 1) ? "" : "s");
+ monitor->cpu_monitor[cpu_nr].unaligned_write_count),
+ (monitor->cpu_monitor[cpu_nr].unaligned_write_count == 1) ? "" : "s");
if (monitor->cpu_monitor[cpu_nr].event_count[mon_event_icache_miss])
printf_filtered ("CPU #%*d executed %*s icache miss%s.\n",
@@ -344,7 +409,7 @@ mon_print_info(psim *system,
(monitor->cpu_monitor[cpu_nr].event_count[mon_event_icache_miss] == 1) ? "" : "es");
{
- long nr_insns = mon_get_number_of_insns(&monitor->cpu_monitor[cpu_nr]);
+ long nr_insns = mon_get_number_of_insns(monitor, cpu_nr);
if (nr_insns > 0)
printf_filtered("CPU #%*d executed %*s instructions in total.\n",
len_cpu, cpu_nr+1,
@@ -354,17 +419,27 @@ mon_print_info(psim *system,
}
}
- if (monitor->nr_cpus > 1)
- printf_filtered("\nAll CPUs executed %s instructions in total.\n",
- mon_add_commas(buffer, sizeof(buffer), total_insns));
+ if (total_insns > 0) {
+ if (monitor->nr_cpus > 1)
+ printf_filtered("\nAll CPUs executed %s instructions in total.\n",
+ mon_add_commas(buffer, sizeof(buffer), total_insns));
+ }
+ else if (total_sim_cycles > 0) {
+ printf_filtered("\nSimulator performed %s simulation cycles.\n",
+ mon_add_commas(buffer, sizeof(buffer), total_sim_cycles));
+ }
if (cpu_insns_second)
- printf_filtered ("%sSimulator speed was %s instructions/second\n",
+ printf_filtered ("%sSimulator speed was %s instructions/second.\n",
(monitor->nr_cpus > 1) ? "" : "\n",
mon_add_commas(buffer, sizeof(buffer), cpu_insns_second));
+ else if (sim_cycles_second)
+ printf_filtered ("Simulator speed was %s simulation cycles/second\n",
+ mon_add_commas(buffer, sizeof(buffer), sim_cycles_second));
else if (cpu_time > 0.0)
printf_filtered ("%sSimulator executed for %.2f seconds\n",
(monitor->nr_cpus > 1) ? "" : "\n", cpu_time);
+
}
#endif /* _MON_C_ */
diff --git a/gnu/dist/sim/ppc/mon.h b/gnu/dist/sim/ppc/mon.h
index bd1010b6b4a..ab64b8e13c4 100644
--- a/gnu/dist/sim/ppc/mon.h
+++ b/gnu/dist/sim/ppc/mon.h
@@ -95,6 +95,11 @@ INLINE_MON\
unsigned_word cia);
INLINE_MON\
+(unsigned) mon_get_number_of_insns
+(mon *monitor,
+ int cpu_nr);
+
+INLINE_MON\
(void) mon_print_info
(psim *system,
mon *monitor,
diff --git a/gnu/dist/sim/ppc/options.c b/gnu/dist/sim/ppc/options.c
index 279185358b3..2d31124752a 100644
--- a/gnu/dist/sim/ppc/options.c
+++ b/gnu/dist/sim/ppc/options.c
@@ -138,6 +138,9 @@ print_options (void)
printf_filtered ("WITH_MODEL = %s\n", model_name[WITH_MODEL]);
printf_filtered ("WITH_MODEL_ISSUE = %d\n", WITH_MODEL_ISSUE);
printf_filtered ("WITH_RESERVED_BITS = %d\n", WITH_RESERVED_BITS);
+ printf_filtered ("WITH_STDIO = %d\n", WITH_STDIO);
+ printf_filtered ("WITH_REGPARM = %d\n", WITH_REGPARM);
+ printf_filtered ("WITH_STDCALL = %d\n", WITH_STDCALL);
printf_filtered ("DEFAULT_INLINE = %s\n", options_inline (DEFAULT_INLINE));
printf_filtered ("SIM_ENDIAN_INLINE = %s\n", options_inline (SIM_ENDIAN_INLINE));
printf_filtered ("BITS_INLINE = %s\n", options_inline (BITS_INLINE));
@@ -154,6 +157,7 @@ print_options (void)
printf_filtered ("IDECODE_INLINE = %s\n", options_inline (IDECODE_INLINE));
printf_filtered ("OPTIONS_INLINE = %s\n", options_inline (OPTIONS_INLINE));
printf_filtered ("OS_EMUL_INLINE = %s\n", options_inline (OS_EMUL_INLINE));
+ printf_filtered ("SUPPORT_INLINE = %s\n", options_inline (SUPPORT_INLINE));
#ifdef OPCODE_RULES
printf_filtered ("OPCODE rules = %s\n", OPCODE_RULES);
@@ -166,6 +170,78 @@ print_options (void)
#ifdef DGEN_FLAGS
printf_filtered ("DGEN_FLAGS = %s\n", DGEN_FLAGS);
#endif
+
+ {
+ static const char *const defines[] = {
+#ifdef __GNUC__
+ "__GNUC__",
+#endif
+
+#ifdef __STRICT_ANSI__
+ "__STRICT_ANSI__",
+#endif
+
+#ifdef __CHAR_UNSIGNED__
+ "__CHAR_UNSIGNED__",
+#endif
+
+#ifdef __OPTIMIZE__
+ "__OPTIMIZE__",
+#endif
+
+#ifdef STDC_HEADERS
+ "STDC_HEADERS",
+#endif
+
+#include "defines.h"
+
+#ifdef HAVE_TERMIOS_CLINE
+ "HAVE_TERMIOS_CLINE",
+#endif
+
+#ifdef HAVE_TERMIOS_STRUCTURE
+ "HAVE_TERMIOS_STRUCTURE",
+#endif
+
+#ifdef HAVE_TERMIO_CLINE
+ "HAVE_TERMIO_CLINE",
+#endif
+
+#ifdef HAVE_TERMIO_STRUCTURE
+ "HAVE_TERMIO_STRUCTURE",
+#endif
+
+#ifdef HAVE_DEVZERO
+ "HAVE_DEVZERO",
+#endif
+ };
+
+ int i;
+ int max_len = 0;
+ int cols;
+
+ for (i = 0; i < sizeof (defines) / sizeof (defines[0]); i++) {
+ int len = strlen (defines[i]);
+ if (len > max_len)
+ max_len = len;
+ }
+
+ cols = 78 / (max_len + 2);
+ if (cols < 0)
+ cols = 1;
+
+ printf_filtered ("\n#defines:");
+ for (i = 0; i < sizeof (defines) / sizeof (defines[0]); i++) {
+ const char *const prefix = ((i % cols) == 0) ? "\n" : "";
+ printf_filtered ("%s %s%*s", prefix, defines[i],
+ (((i == (sizeof (defines) / sizeof (defines[0])) - 1)
+ || (((i + 1) % cols) == 0))
+ ? 0
+ : max_len + 4 - strlen (defines[i])),
+ "");
+ }
+ printf_filtered ("\n");
+ }
}
#endif /* _OPTIONS_C_ */
diff --git a/gnu/dist/sim/ppc/os_emul.c b/gnu/dist/sim/ppc/os_emul.c
index fe8e9ed41d6..dc60c8f6641 100644
--- a/gnu/dist/sim/ppc/os_emul.c
+++ b/gnu/dist/sim/ppc/os_emul.c
@@ -28,6 +28,7 @@
#include "emul_generic.h"
#include "emul_netbsd.h"
+#include "emul_unix.h"
#include "emul_chirp.h"
#include "emul_bugapi.h"
@@ -35,6 +36,8 @@ static const os_emul *(os_emulations[]) = {
&emul_chirp,
&emul_bugapi,
&emul_netbsd,
+ &emul_solaris,
+ &emul_linux,
0
};
@@ -73,9 +76,9 @@ os_emul_create(const char *file_name,
}
/* see if the device tree already specifies the required emulation */
- if (device_find_property(root, "/openprom/options/os-emul") != NULL)
+ if (tree_find_property(root, "/openprom/options/os-emul") != NULL)
emulation_name =
- device_find_string_property(root, "/openprom/options/os-emul");
+ tree_find_string_property(root, "/openprom/options/os-emul");
else
emulation_name = NULL;
diff --git a/gnu/dist/sim/ppc/pk_disklabel.c b/gnu/dist/sim/ppc/pk_disklabel.c
new file mode 100644
index 00000000000..91dcf7ce562
--- /dev/null
+++ b/gnu/dist/sim/ppc/pk_disklabel.c
@@ -0,0 +1,401 @@
+/* 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 _PK_DISKLABEL_C_
+#define _PK_DISKLABEL_C_
+
+#ifndef STATIC_INLINE_PK_DISKLABEL
+#define STATIC_INLINE_PK_DISKLABEL STATIC_INLINE
+#endif
+
+#include "device_table.h"
+
+#include "pk.h"
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+
+
+/* PACKAGE
+
+ disk-label - all knowing disk I/O package
+
+ DESCRIPTION
+
+ The disk-label package provides a generic interface to disk
+ devices. It uses the arguments specified when an instance is being
+ created to determine if the raw disk, a partition, or a file within
+ a partition should be opened.
+
+ An instance create call to disk-label could result, for instance,
+ in the opening of a DOS file system contained within a dos
+ partition contained within a physical disk.
+
+ */
+
+/* taken from bfd/ppcboot.c by Michael Meissner */
+
+/* PPCbug location structure */
+typedef struct ppcboot_location {
+ unsigned8 ind;
+ unsigned8 head;
+ unsigned8 sector;
+ unsigned8 cylinder;
+} ppcboot_location_t;
+
+/* PPCbug partition table layout */
+typedef struct ppcboot_partition {
+ ppcboot_location_t partition_begin; /* partition begin */
+ ppcboot_location_t partition_end; /* partition end */
+ unsigned8 sector_begin[4]; /* 32-bit start RBA (zero-based), little endian */
+ unsigned8 sector_length[4]; /* 32-bit RBA count (one-based), little endian */
+} ppcboot_partition_t;
+
+#if 0
+/* PPCbug boot layout. */
+typedef struct ppcboot_hdr {
+ unsigned8 pc_compatibility[446]; /* x86 instruction field */
+ ppcboot_partition_t partition[4]; /* partition information */
+ unsigned8 signature[2]; /* 0x55 and 0xaa */
+ unsigned8 entry_offset[4]; /* entry point offset, little endian */
+ unsigned8 length[4]; /* load image length, little endian */
+ unsigned8 flags; /* flag field */
+ unsigned8 os_id; /* OS_ID */
+ char partition_name[32]; /* partition name */
+ unsigned8 reserved1[470]; /* reserved */
+} ppcboot_hdr_t;
+#endif
+
+
+typedef struct _disklabel {
+ device_instance *parent;
+ device_instance *raw_disk;
+ unsigned_word pos;
+ unsigned_word sector_begin;
+ unsigned_word sector_length;
+} disklabel;
+
+
+static unsigned_word
+sector2uw(unsigned8 s[4])
+{
+ return ((s[3] << 24)
+ + (s[2] << 16)
+ + (s[1] << 8)
+ + (s[0] << 0));
+}
+
+
+static void
+disklabel_delete(device_instance *instance)
+{
+ disklabel *label = device_instance_data(instance);
+ device_instance_delete(label->raw_disk);
+ zfree(label);
+}
+
+
+static int
+disklabel_read(device_instance *instance,
+ void *buf,
+ unsigned_word len)
+{
+ disklabel *label = device_instance_data(instance);
+ int nr_read;
+ if (label->pos + len > label->sector_length)
+ len = label->sector_length - label->pos;
+ if (device_instance_seek(label->raw_disk, 0,
+ label->sector_begin + label->pos) < 0)
+ return -1;
+ nr_read = device_instance_read(label->raw_disk, buf, len);
+ if (nr_read > 0)
+ label->pos += nr_read;
+ return nr_read;
+}
+
+static int
+disklabel_write(device_instance *instance,
+ const void *buf,
+ unsigned_word len)
+{
+ disklabel *label = device_instance_data(instance);
+ int nr_written;
+ if (label->pos + len > label->sector_length)
+ len = label->sector_length - label->pos;
+ if (device_instance_seek(label->raw_disk, 0,
+ label->sector_begin + label->pos) < 0)
+ return -1;
+ nr_written = device_instance_write(label->raw_disk, buf, len);
+ if (nr_written > 0)
+ label->pos += nr_written;
+ return nr_written;
+}
+
+static int
+disklabel_seek(device_instance *instance,
+ unsigned_word pos_hi,
+ unsigned_word pos_lo)
+{
+ disklabel *label = device_instance_data(instance);
+ if (pos_lo >= label->sector_length || pos_hi != 0)
+ return -1;
+ label->pos = pos_lo;
+ return 0;
+}
+
+
+static const device_instance_callbacks package_disklabel_callbacks = {
+ disklabel_delete,
+ disklabel_read,
+ disklabel_write,
+ disklabel_seek,
+};
+
+/* Reconize different types of boot block */
+
+static int
+block0_is_bpb(const unsigned8 block[])
+{
+ const char ebdic_ibma[] = { 0xc9, 0xc2, 0xd4, 0xc1 };
+ /* ref PowerPC Microprocessor CHRP bindings 1.2b - page 47 */
+ /* can't start with IBMA */
+ if (memcmp(block, ebdic_ibma, sizeof(ebdic_ibma)) == 0)
+ return 0;
+ /* must have LE 0xAA55 signature at offset 510 */
+ if (block[511] != 0xAA && block[510] != 0x55)
+ return 0;
+ /* valid 16 bit LE bytes per sector - 256, 512, 1024 */
+ if (block[11] != 0
+ || (block[12] != 1 && block[12] != 2 && block[12] != 4))
+ return 0;
+ /* nr fats is 1 or 2 */
+ if (block[16] != 1 && block[16] != 2)
+ return 0;
+ return 1;
+}
+
+
+/* Verify that the device contains an ISO-9660 File system */
+
+static int
+is_iso9660(device_instance *raw_disk)
+{
+ /* ref PowerPC Microprocessor CHRP bindings 1.2b - page 47 */
+ unsigned8 block[512];
+ if (device_instance_seek(raw_disk, 0, 512 * 64) < 0)
+ return 0;
+ if (device_instance_read(raw_disk, block, sizeof(block)) != sizeof(block))
+ return 0;
+ if (block[0] == 0x01
+ && block[1] == 'C'
+ && block[2] == 'D'
+ && block[3] == '0'
+ && block[4] == '0'
+ && block[5] == '1')
+ return 1;
+ return 0;
+}
+
+
+/* Verify that the disk block contains a valid DOS partition table.
+ While we're at it have a look around for active partitions etc.
+
+ Return 0: invalid
+ Return 1..4: valid, value returned is the first active partition
+ Return -1: no active partition */
+
+static int
+block0_is_fdisk(const unsigned8 block[])
+{
+ const int partition_type_fields[] = { 0, 0x1c2, 0x1d2, 0x1e2, 0x1f2 };
+ const int partition_active_fields[] = { 0, 0x1be, 0x1ce, 0x1de, 0xee };
+ int partition;
+ int active = -1;
+ /* ref PowerPC Microprocessor CHRP bindings 1.2b - page 47 */
+ /* must have LE 0xAA55 signature at offset 510 */
+ if (block[511/*0x1ff*/] != 0xAA && block[510/*0x1fe*/] != 0x55)
+ return 0;
+ /* must contain valid partition types */
+ for (partition = 1; partition <= 4 && active != 0; partition++) {
+ int partition_type = block[partition_type_fields[partition]];
+ int is_active = block[partition_active_fields[partition]] == 0x80;
+ const char *type;
+ switch (partition_type) {
+ case 0x00:
+ type = "UNUSED";
+ break;
+ case 0x01:
+ type = "FAT 12 File system";
+ break;
+ case 0x04:
+ type = "FAT 16 File system";
+ break;
+ case 0x05:
+ case 0x06:
+ type = "rejected - extended/chained partition not supported";
+ active = 0;
+ break;
+ case 0x41:
+ type = "Single program image";
+ break;
+ case 0x82:
+ type = "Solaris?";
+ break;
+ case 0x96:
+ type = "ISO 9660 File system";
+ break;
+ default:
+ type = "rejected - unknown type";
+ active = 0;
+ break;
+ }
+ PTRACE(disklabel, ("partition %d of type 0x%02x - %s%s\n",
+ partition,
+ partition_type,
+ type,
+ is_active && active != 0 ? " (active)" : ""));
+ if (partition_type != 0 && is_active && active < 0)
+ active = partition;
+ }
+ return active;
+}
+
+
+/* Verify that block0 corresponds to a MAC disk */
+
+static int
+block0_is_mac_disk(const unsigned8 block[])
+{
+ /* ref PowerPC Microprocessor CHRP bindings 1.2b - page 47 */
+ /* signature - BEx4552 at offset 0 */
+ if (block[0] != 0x45 || block[1] != 0x52)
+ return 0;
+ return 1;
+}
+
+
+/* Open a logical disk/file */
+
+device_instance *
+pk_disklabel_create_instance(device_instance *raw_disk,
+ const char *args)
+{
+ int partition;
+ char *filename;
+
+ /* parse the arguments */
+ if (args == NULL) {
+ partition = 0;
+ filename = NULL;
+ }
+ else {
+ partition = strtoul((char*)args, &filename, 0);
+ if (filename == args)
+ partition = -1; /* not specified */
+ if (*filename == ',')
+ filename++;
+ if (*filename == '\0')
+ filename = NULL; /* easier */
+ }
+
+ if (partition == 0) {
+ /* select the raw disk */
+ return raw_disk;
+ }
+ else {
+ unsigned8 boot_block[512];
+ /* get the boot block for examination */
+ if (device_instance_seek(raw_disk, 0, 0) < 0)
+ device_error(device_instance_device(raw_disk),
+ "Problem seeking on raw disk");
+ if (device_instance_read(raw_disk, &boot_block, sizeof(boot_block))
+ != sizeof(boot_block))
+ device_error(device_instance_device(raw_disk), "Problem reading boot block");
+
+ if (partition < 0) {
+ /* select the active partition */
+ if (block0_is_bpb(boot_block)) {
+ device_error(device_instance_device(raw_disk), "Unimplemented active BPB");
+ }
+ else if (block0_is_fdisk(boot_block)) {
+ int active = block0_is_fdisk(boot_block);
+ device_error(device_instance_device(raw_disk), "Unimplemented active FDISK (%d)",
+ active);
+ }
+ else if (is_iso9660(raw_disk)) {
+ device_error(device_instance_device(raw_disk), "Unimplemented active ISO9660");
+ }
+ else if (block0_is_mac_disk(boot_block)) {
+ device_error(device_instance_device(raw_disk), "Unimplemented active MAC DISK");
+ }
+ else {
+ device_error(device_instance_device(raw_disk), "Unreconized bootblock");
+ }
+ }
+ else {
+ /* select the specified disk partition */
+ if (block0_is_bpb(boot_block)) {
+ device_error(device_instance_device(raw_disk), "Unimplemented BPB");
+ }
+ else if (block0_is_fdisk(boot_block)) {
+ /* return an instance */
+ ppcboot_partition_t *partition_table = (ppcboot_partition_t*) &boot_block[446];
+ ppcboot_partition_t *partition_entry;
+ disklabel *label;
+ if (partition > 4)
+ device_error(device_instance_device(raw_disk),
+ "Only FDISK partitions 1..4 supported");
+ partition_entry = &partition_table[partition - 1];
+ label = ZALLOC(disklabel);
+ label->raw_disk = raw_disk;
+ label->pos = 0;
+ label->sector_begin = 512 * sector2uw(partition_entry->sector_begin);
+ label->sector_length = 512 * sector2uw(partition_entry->sector_length);
+ PTRACE(disklabel, ("partition %ld, sector-begin %ld, length %ld\n",
+ (long)partition,
+ (long)label->sector_begin,
+ (long)label->sector_length));
+ if (filename != NULL)
+ device_error(device_instance_device(raw_disk),
+ "FDISK file names not yet supported");
+ return device_create_instance_from(NULL, raw_disk,
+ label,
+ NULL, args,
+ &package_disklabel_callbacks);
+ }
+ else if (block0_is_mac_disk(boot_block)) {
+ device_error(device_instance_device(raw_disk), "Unimplemented MAC DISK");
+ }
+ else {
+ device_error(device_instance_device(raw_disk),
+ "Unreconized bootblock");
+ }
+ }
+ }
+
+ return NULL;
+}
+
+
+#endif /* _PK_DISKLABEL_C_ */
+
diff --git a/gnu/dist/sim/ppc/ppc-cache-rules b/gnu/dist/sim/ppc/ppc-cache-rules
index 939b943dd15..2b5f4722175 100644
--- a/gnu/dist/sim/ppc/ppc-cache-rules
+++ b/gnu/dist/sim/ppc/ppc-cache-rules
@@ -17,84 +17,49 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
-#
-# Instruction unpacking:
-#
-# Once the instruction has been decoded, the register (and other)
-# fields within the instruction need to be extracted.
-#
-# The table that follows determines how each field should be treated.
-# Importantly it considers the case where the extracted field is to
-# be used immediatly or stored in an instruction cache.
-#
-# <valid>
-#
-# Zero marks the end of the table. More importantly 1. indicates
-# that the entry is valid and can be cached. 2. indicates that that
-# the entry is valid but can not be cached.
-#
-# <old_name>
-#
-# The field name as given in the instruction spec.
-#
-# <new_name>
-#
-# A name for <old_name> once it has been extracted from the
-# instructioin (and possibly stored in the instruction cache).
-#
-# <type>
-#
-# String specifying the storage type for <new_name> (the extracted
-# field>.
-#
-# <expression>
-#
-# Specifies how to get <new_name> from <old_name>. If null, old and
-# new name had better be the same. */
-#
-#
-1:RA:RA::
-1:RA:rA:signed_word *:(cpu_registers(processor)->gpr + RA)
-1:RA:RA_BITMASK:unsigned32:(1 << RA)
-1:RT:RT::
-1:RT:rT:signed_word *:(cpu_registers(processor)->gpr + RT)
-1:RT:RT_BITMASK:unsigned32:(1 << RT)
-2:RS:RS::
-1:RS:rS:signed_word *:(cpu_registers(processor)->gpr + RS)
-1:RS:RS_BITMASK:unsigned32:(1 << RS)
-2:RB:RB::
-1:RB:rB:signed_word *:(cpu_registers(processor)->gpr + RB)
-1:RB:RB_BITMASK:unsigned32:(1 << RB)
-2:FRA:FRA::
-1:FRA:frA:unsigned64 *:(cpu_registers(processor)->fpr + FRA)
-1:FRA:FRA_BITMASK:unsigned32:(1 << FRA)
-2:FRB:FRB::
-1:FRB:frB:unsigned64 *:(cpu_registers(processor)->fpr + FRB)
-1:FRB:FRB_BITMASK:unsigned32:(1 << FRB)
-2:FRC:FRC::
-1:FRC:frC:unsigned64 *:(cpu_registers(processor)->fpr + FRC)
-1:FRC:FRC_BITMASK:unsigned32:(1 << FRC)
-2:FRS:FRS::
-1:FRS:frS:unsigned64 *:(cpu_registers(processor)->fpr + FRS)
-1:FRS:FRS_BITMASK:unsigned32:(1 << FRS)
-2:FRT:FRT::
-1:FRT:frT:unsigned64 *:(cpu_registers(processor)->fpr + FRT)
-1:FRT:FRT_BITMASK:unsigned32:(1 << FRT)
-1:SI:EXTS_SI:unsigned_word:((signed_word)(signed16)instruction)
-2:BI:BI::
-1:BI:BIT32_BI::BIT32(BI)
-1:BF:BF::
-1:BF:BF_BITMASK:unsigned32:(1 << BF)
-2:BA:BA::
-1:BA:BIT32_BA::BIT32(BA)
-1:BA:BA_BITMASK:unsigned32:(1 << BA)
-2:BB:BB::
-1:BB:BIT32_BB::BIT32(BB)
-1:BB:BB_BITMASK:unsigned32:(1 << BB)
-1:BT:BT::
-1:BT:BT_BITMASK:unsigned32:(1 << BT)
-1:BD:EXTS_BD_0b00:unsigned_word:(((signed_word)(signed16)instruction) & ~3)
-#1:BD:CIA_plus_EXTS_BD_0b00:unsigned_word:CIA + EXTS(BD_0b00)
-1:LI:EXTS_LI_0b00:unsigned_word:((((signed_word)(signed32)(instruction << 6)) >> 6) & ~0x3)
-1:D:EXTS_D:unsigned_word:((signed_word)(signed16)(instruction))
-1:DS:EXTS_DS_0b00:unsigned_word:(((signed_word)(signed16)instruction) & ~0x3)
+cache:RA:RA::
+cache:RA:rA:signed_word *:(cpu_registers(processor)->gpr + RA)
+cache:RA:RA_BITMASK:unsigned32:(1 << RA)
+compute:RA:RA_is_0:int:(RA == 0)
+cache:RT:RT::
+cache:RT:rT:signed_word *:(cpu_registers(processor)->gpr + RT)
+cache:RT:RT_BITMASK:unsigned32:(1 << RT)
+cache:RS:RS::
+cache:RS:rS:signed_word *:(cpu_registers(processor)->gpr + RS)
+cache:RS:RS_BITMASK:unsigned32:(1 << RS)
+cache:RB:RB::
+cache:RB:rB:signed_word *:(cpu_registers(processor)->gpr + RB)
+cache:RB:RB_BITMASK:unsigned32:(1 << RB)
+scratch:FRA:FRA::
+cache:FRA:frA:unsigned64 *:(cpu_registers(processor)->fpr + FRA)
+cache:FRA:FRA_BITMASK:unsigned32:(1 << FRA)
+scratch:FRB:FRB::
+cache:FRB:frB:unsigned64 *:(cpu_registers(processor)->fpr + FRB)
+cache:FRB:FRB_BITMASK:unsigned32:(1 << FRB)
+scratch:FRC:FRC::
+cache:FRC:frC:unsigned64 *:(cpu_registers(processor)->fpr + FRC)
+cache:FRC:FRC_BITMASK:unsigned32:(1 << FRC)
+scratch:FRS:FRS::
+cache:FRS:frS:unsigned64 *:(cpu_registers(processor)->fpr + FRS)
+cache:FRS:FRS_BITMASK:unsigned32:(1 << FRS)
+scratch:FRT:FRT::
+cache:FRT:frT:unsigned64 *:(cpu_registers(processor)->fpr + FRT)
+cache:FRT:FRT_BITMASK:unsigned32:(1 << FRT)
+cache:SI:EXTS_SI:unsigned_word:((signed_word)(signed16)instruction)
+scratch:BI:BI::
+cache:BI:BIT32_BI::BIT32(BI)
+cache:BF:BF::
+cache:BF:BF_BITMASK:unsigned32:(1 << BF)
+scratch:BA:BA::
+cache:BA:BIT32_BA::BIT32(BA)
+cache:BA:BA_BITMASK:unsigned32:(1 << BA)
+scratch:BB:BB::
+cache:BB:BIT32_BB::BIT32(BB)
+cache:BB:BB_BITMASK:unsigned32:(1 << BB)
+cache:BT:BT::
+cache:BT:BT_BITMASK:unsigned32:(1 << BT)
+cache:BD:EXTS_BD_0b00:unsigned_word:(((signed_word)(signed16)instruction) & ~3)
+cache:LI:EXTS_LI_0b00:unsigned_word:((((signed_word)(signed32)(instruction << 6)) >> 6) & ~0x3)
+cache:D:EXTS_D:unsigned_word:((signed_word)(signed16)(instruction))
+cache:DS:EXTS_DS_0b00:unsigned_word:(((signed_word)(signed16)instruction) & ~0x3)
+#compute:SPR:SPR_is_256:int:(SPR == 256)
diff --git a/gnu/dist/sim/ppc/ppc-instructions b/gnu/dist/sim/ppc/ppc-instructions
index a03c66a5eff..8ea32e35c71 100644
--- a/gnu/dist/sim/ppc/ppc-instructions
+++ b/gnu/dist/sim/ppc/ppc-instructions
@@ -1,7 +1,7 @@
#
# This file is part of the program psim.
#
-# Copyright (C) 1994-1996, Andrew Cagney <cagney@highland.com.au>
+# Copyright (C) 1994-1997, Andrew Cagney <cagney@highland.com.au>
#
# --
#
@@ -33,38 +33,6 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
-# --
-#
-#
-# Fields:
-#
-# 1 Instruction format as a `start-bit,content' pairs.
-# the content is one of a digit, field name or `/' (aka.0)
-#
-# 2 Format specifier
-#
-# 3 Flags: 64 - 64bit only
-# f - floating point enabled required
-#
-# 4 short name
-#
-# 5 Description
-#
-#
-# For flags marked 'model', the fields are interpreted as follows:
-#
-# 1 Not used
-#
-# 2 Not used
-#
-# 3 "macro"
-#
-# 4 String name for model
-#
-# 5 Specific CPU model, must be an identifier
-#
-# 6 Comma separated list of functional units
-
# PowerPC models
::model:604:ppc604: PPC_UNIT_BAD, PPC_UNIT_BAD, 1, 1, 0
@@ -78,68 +46,68 @@
do { \
if (CURRENT_MODEL_ISSUE > 0) { \
if (RC) \
- ppc_insn_int(my_index, cpu_model(processor), OUT_MASK, IN_MASK); \
+ ppc_insn_int_cr(MY_INDEX, cpu_model(processor), OUT_MASK, IN_MASK, 1 << 0); \
else \
- ppc_insn_int_cr(my_index, cpu_model(processor), OUT_MASK, IN_MASK, 1 << 0); \
+ ppc_insn_int(MY_INDEX, cpu_model(processor), OUT_MASK, IN_MASK); \
} \
} while (0)
#define PPC_INSN_INT_CR(OUT_MASK, IN_MASK, CR_MASK) \
do { \
if (CURRENT_MODEL_ISSUE > 0) \
- ppc_insn_int_cr(my_index, cpu_model(processor), OUT_MASK, IN_MASK, CR_MASK); \
+ ppc_insn_int_cr(MY_INDEX, cpu_model(processor), OUT_MASK, IN_MASK, CR_MASK); \
} while (0)
#define PPC_INSN_CR(OUT_MASK, IN_MASK) \
do { \
if (CURRENT_MODEL_ISSUE > 0) \
- ppc_insn_cr(my_index, cpu_model(processor), OUT_MASK, IN_MASK); \
+ ppc_insn_cr(MY_INDEX, cpu_model(processor), OUT_MASK, IN_MASK); \
} while (0)
#define PPC_INSN_FLOAT(OUT_MASK, IN_MASK, RC) \
do { \
if (CURRENT_MODEL_ISSUE > 0) { \
if (RC) \
- ppc_insn_float(my_index, cpu_model(processor), OUT_MASK, IN_MASK); \
+ ppc_insn_float(MY_INDEX, cpu_model(processor), OUT_MASK, IN_MASK); \
else \
- ppc_insn_float_cr(my_index, cpu_model(processor), OUT_MASK, IN_MASK, 1 << 0); \
+ ppc_insn_float_cr(MY_INDEX, cpu_model(processor), OUT_MASK, IN_MASK, 1 << 0); \
} \
} while (0)
#define PPC_INSN_FLOAT_CR(OUT_MASK, IN_MASK, CR_MASK) \
do { \
if (CURRENT_MODEL_ISSUE > 0) \
- ppc_insn_float_cr(my_index, cpu_model(processor), OUT_MASK, IN_MASK, CR_MASK); \
+ ppc_insn_float_cr(MY_INDEX, cpu_model(processor), OUT_MASK, IN_MASK, CR_MASK); \
} while (0)
#define PPC_INSN_INT_FLOAT(OUT_INT_MASK, OUT_FP_MASK, IN_INT_MASK, IN_FP_MASK) \
do { \
if (CURRENT_MODEL_ISSUE > 0) \
- ppc_insn_int_float(my_index, cpu_model(processor), OUT_INT_MASK, OUT_FP_MASK, IN_INT_MASK, IN_FP_MASK); \
+ ppc_insn_int_float(MY_INDEX, cpu_model(processor), OUT_INT_MASK, OUT_FP_MASK, IN_INT_MASK, IN_FP_MASK); \
} while (0)
#define PPC_INSN_FROM_SPR(INT_MASK, SPR) \
do { \
if (CURRENT_MODEL_ISSUE > 0) \
- ppc_insn_from_spr(my_index, cpu_model(processor), INT_MASK, SPR); \
+ ppc_insn_from_spr(MY_INDEX, cpu_model(processor), INT_MASK, SPR); \
} while (0)
#define PPC_INSN_TO_SPR(INT_MASK, SPR) \
do { \
if (CURRENT_MODEL_ISSUE > 0) \
- ppc_insn_to_spr(my_index, cpu_model(processor), INT_MASK, SPR); \
+ ppc_insn_to_spr(MY_INDEX, cpu_model(processor), INT_MASK, SPR); \
} while (0)
#define PPC_INSN_MFCR(INT_MASK) \
do { \
if (CURRENT_MODEL_ISSUE > 0) \
- ppc_insn_mfcr(my_index, cpu_model(processor), INT_MASK); \
+ ppc_insn_mfcr(MY_INDEX, cpu_model(processor), INT_MASK); \
} while (0)
#define PPC_INSN_MTCR(INT_MASK, FXM) \
do { \
if (CURRENT_MODEL_ISSUE > 0) \
- ppc_insn_mtcr(my_index, cpu_model(processor), INT_MASK, FXM); \
+ ppc_insn_mtcr(MY_INDEX, cpu_model(processor), INT_MASK, FXM); \
} while (0)
::model-data:::
@@ -187,7 +155,7 @@
signed16 done; /* # of cycles until insn is done */
signed16 nr_writebacks; /* # of registers this unit writes back */
};
-
+
/* Structure to hold the current state information for the simulated CPU model */
struct _model_data {
cpu *processor; /* point back to processor */
@@ -783,6 +751,15 @@ void::model-function::model_halt:model_data *model_ptr
while (model_ptr->busy_head.next)
model_new_cycle(model_ptr);
+unsigned_word::model-function::model_get_number_of_stalls:model_data *model_ptr
+ return (model_ptr->nr_stalls_data
+ + model_ptr->nr_stalls_unit
+ + model_ptr->nr_stalls_serialize
+ + model_ptr->nr_stalls_writeback);
+
+unsigned_word::model-function::model_get_number_of_cycles:model_data *model_ptr
+ return (model_ptr->nr_cycles);
+
model_print *::model-function::model_mon_info:model_data *model_ptr
model_print *head;
model_print *tail;
@@ -829,7 +806,7 @@ model_print *::model-function::model_mon_info:model_data *model_ptr
tail->count = model_ptr->nr_stalls_writeback;
tail->name = "";
tail->suffix_plural = "times a write-back slot was unavailable";
- tail->suffix_singular = "time a writeback was unavilable";
+ tail->suffix_singular = "time a writeback was unavailable";
}
if (model_ptr->nr_branches) {
@@ -942,7 +919,6 @@ void::model-function::model_branch_predict:model_data *model_ptr, int success
::internal::illegal
program_interrupt(processor, cia,
illegal_instruction_program_interrupt);
- return 0;
# The following (floating point unavailable) instruction is `known' by gen
@@ -950,7 +926,6 @@ void::model-function::model_branch_predict:model_data *model_ptr, int success
# executed but floating point is make unavailable by the MSR
::internal::floating_point_unavailable
floating_point_unavailable_interrupt(processor, cia);
- return 0;
#
@@ -1134,59 +1109,60 @@ void::function::convert_to_integer:cpu *processor, unsigned_word cia, unsigned64
int rbit = 0;
int xbit = 0;
int sign = EXTRACTED64(frb, 0, 0);
- if (EXTRACTED64(frb, 1, 11) == 2047 && EXTRACTED64(frb, 12, 63) == 0)
- goto Infinity_Operand;
- if (EXTRACTED64(frb, 1, 11) == 2047 && EXTRACTED64(frb, 12, 12) == 0)
- goto SNaN_Operand;
- if (EXTRACTED64(frb, 1, 11) == 2047 && EXTRACTED64(frb, 12, 12) == 1)
- goto QNaN_Operand;
- if (EXTRACTED64(frb, 1, 11) > 1086) goto Large_Operand;
- if (EXTRACTED64(frb, 1, 11) > 0) exp = EXTRACTED64(frb, 1, 11) - 1023;
- if (EXTRACTED64(frb, 1, 11) == 0) exp = -1022;
- if (EXTRACTED64(frb, 1, 11) > 0) { /* normal */
- frac = BIT64(1) | INSERTED64(EXTRACTED64(frb, 12, 63), 2, 53);
- frac64 = 0;
- }
- if (EXTRACTED64(frb, 1, 11) == 0) { /* denorm */
- frac = INSERTED64(EXTRACTED64(frb, 12, 63), 2, 53);
- frac64 = 0;
- }
- gbit = 0, rbit = 0, xbit = 0;
- for (i = 1; i <= 63 - exp; i++) {
- xbit = rbit | xbit;
- rbit = gbit;
- gbit = frac64;
- frac64 = EXTRACTED64(frac, 63, 63);
- frac = INSERTED64(EXTRACTED64(frac, 0, 62), 1, 63);
- }
- Round_Integer(processor, sign, &frac, &frac64, gbit, rbit, xbit, round_mode);
- if (sign == 1) { /* frac[0:64] = ~frac[0:64] + 1 */
- frac = ~frac;
- frac64 ^= 1;
- frac += (frac64 ? 1 : 0);
- frac64 = (frac64 + 1) & 0x1;
- }
- if (tgt_precision == 32 /* can ignore frac64 in compare */
- && (signed64)frac > (signed64)MASK64(33+1, 63)/*2^31-1 >>1*/)
- goto Large_Operand;
- if (tgt_precision == 64 /* can ignore frac64 in compare */
- && (signed64)frac > (signed64)MASK64(1+1, 63)/*2^63-1 >>1*/)
- goto Large_Operand;
- if (tgt_precision == 32 /* can ignore frac64 in compare */
- && (signed64)frac < (signed64)MASK64(0, 32+1)/*-2^31 >>1*/)
- goto Large_Operand;
- if (tgt_precision == 64 /* can ignore frac64 in compare */
- && (signed64)frac < (signed64)MASK64(0, 0+1)/*-2^63 >>1*/)
- goto Large_Operand;
- FPSCR_SET_XX(FPSCR & fpscr_fi);
- if (tgt_precision == 32)
- *frt = MASKED64(*frt, 0, 31) | (EXTRACTED64(frac, 33, 63) << 1) | frac64;
- if (tgt_precision == 64)
- *frt = (EXTRACTED64(frac, 1, 63) << 1) | frac64;
- /*FPSCR[fprf] = undefined */
- goto Done;
- /**/
- Infinity_Operand:
+ /***/
+ if (EXTRACTED64(frb, 1, 11) == 2047 && EXTRACTED64(frb, 12, 63) == 0)
+ GOTO(Infinity_Operand);
+ if (EXTRACTED64(frb, 1, 11) == 2047 && EXTRACTED64(frb, 12, 12) == 0)
+ GOTO(SNaN_Operand);
+ if (EXTRACTED64(frb, 1, 11) == 2047 && EXTRACTED64(frb, 12, 12) == 1)
+ GOTO(QNaN_Operand);
+ if (EXTRACTED64(frb, 1, 11) > 1086) GOTO(Large_Operand);
+ if (EXTRACTED64(frb, 1, 11) > 0) exp = EXTRACTED64(frb, 1, 11) - 1023;
+ if (EXTRACTED64(frb, 1, 11) == 0) exp = -1022;
+ if (EXTRACTED64(frb, 1, 11) > 0) { /* normal */
+ frac = BIT64(1) | INSERTED64(EXTRACTED64(frb, 12, 63), 2, 53);
+ frac64 = 0;
+ }
+ if (EXTRACTED64(frb, 1, 11) == 0) { /* denorm */
+ frac = INSERTED64(EXTRACTED64(frb, 12, 63), 2, 53);
+ frac64 = 0;
+ }
+ gbit = 0, rbit = 0, xbit = 0;
+ for (i = 1; i <= 63 - exp; i++) {
+ xbit = rbit | xbit;
+ rbit = gbit;
+ gbit = frac64;
+ frac64 = EXTRACTED64(frac, 63, 63);
+ frac = INSERTED64(EXTRACTED64(frac, 0, 62), 1, 63);
+ }
+ Round_Integer(processor, sign, &frac, &frac64, gbit, rbit, xbit, round_mode);
+ if (sign == 1) { /* frac[0:64] = ~frac[0:64] + 1 */
+ frac = ~frac;
+ frac64 ^= 1;
+ frac += (frac64 ? 1 : 0);
+ frac64 = (frac64 + 1) & 0x1;
+ }
+ if (tgt_precision == 32 /* can ignore frac64 in compare */
+ && (signed64)frac > (signed64)MASK64(33+1, 63)/*2^31-1 >>1*/)
+ GOTO(Large_Operand);
+ if (tgt_precision == 64 /* can ignore frac64 in compare */
+ && (signed64)frac > (signed64)MASK64(1+1, 63)/*2^63-1 >>1*/)
+ GOTO(Large_Operand);
+ if (tgt_precision == 32 /* can ignore frac64 in compare */
+ && (signed64)frac < (signed64)MASK64(0, 32+1)/*-2^31 >>1*/)
+ GOTO(Large_Operand);
+ if (tgt_precision == 64 /* can ignore frac64 in compare */
+ && (signed64)frac < (signed64)MASK64(0, 0+1)/*-2^63 >>1*/)
+ GOTO(Large_Operand);
+ FPSCR_SET_XX(FPSCR & fpscr_fi);
+ if (tgt_precision == 32)
+ *frt = MASKED64(*frt, 0, 31) | (EXTRACTED64(frac, 33, 63) << 1) | frac64;
+ if (tgt_precision == 64)
+ *frt = (EXTRACTED64(frac, 1, 63) << 1) | frac64;
+ /*FPSCR[fprf] = undefined */
+ GOTO(Done);
+ /**/
+ LABEL(Infinity_Operand):
FPSCR_SET_FR(0);
FPSCR_SET_FI(0);
FPSCR_OR_VX(fpscr_vxcvi);
@@ -1201,9 +1177,9 @@ void::function::convert_to_integer:cpu *processor, unsigned_word cia, unsigned64
}
/* FPSCR[FPRF] = undefined */
}
- goto Done;
+ GOTO(Done);
/**/
- SNaN_Operand:
+ LABEL(SNaN_Operand):
FPSCR_SET_FR(0);
FPSCR_SET_FI(0);
FPSCR_OR_VX(fpscr_vxsnan | fpscr_vxcvi);
@@ -1212,9 +1188,9 @@ void::function::convert_to_integer:cpu *processor, unsigned_word cia, unsigned64
if (tgt_precision == 64) *frt = BIT64(0); /*0x8000_0000_0000_0000*/
/* FPSCR[fprf] = undefined */
}
- goto Done;
+ GOTO(Done);
/**/
- QNaN_Operand:
+ LABEL(QNaN_Operand):
FPSCR_SET_FR(0);
FPSCR_SET_FI(0);
FPSCR_OR_VX(fpscr_vxcvi);
@@ -1223,9 +1199,9 @@ void::function::convert_to_integer:cpu *processor, unsigned_word cia, unsigned64
if (tgt_precision == 64) *frt = BIT64(0);/*0x8000_0000_0000_0000*/
/* FPSCR[fprf] = undefined */
}
- goto Done;
+ GOTO(Done);
/**/
- Large_Operand:
+ LABEL(Large_Operand):
FPSCR_SET_FR(0);
FPSCR_SET_FI(0);
FPSCR_OR_VX(fpscr_vxcvi);
@@ -1241,7 +1217,7 @@ void::function::convert_to_integer:cpu *processor, unsigned_word cia, unsigned64
/* FPSCR[fprf] = undefined */
}
/**/
- Done:
+ LABEL(Done):
# extract out raw fields of a FP number
@@ -1398,7 +1374,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
}
else { /* arrith, frsp */
*frt = select_qnan(fra, frb, frc,
- instruction_is_frsp, 0/*generate*/, single);
+ instruction_is_frsp, 1/*generate*/, single);
FPSCR_SET_FR(0);
FPSCR_SET_FI(0);
FPSCR_SET_FPRF(fpscr_rf_quiet_nan);
@@ -1419,7 +1395,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
#
# I.2.4.1 Branch Instructions
#
-0.18,6.LI,30.AA,31.LK:I:t::Branch
+0.18,6.LI,30.AA,31.LK:I:::Branch
*601: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
*603: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
*603e:PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
@@ -1430,7 +1406,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
if (CURRENT_MODEL_ISSUE > 0)
model_branches(cpu_model(processor), 1, -1);
-0.16,6.BO,11.BI,16.BD,30.AA,31.LK:B:t::Branch Conditional
+0.16,6.BO,11.BI,16.BD,30.AA,31.LK:B:::Branch Conditional
*601: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
*603: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
*603e:PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
@@ -1464,7 +1440,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
model_branch_predict(cpu_model(processor), reverse ? !succeed : succeed);
}
-0.19,6.BO,11.BI,16./,21.16,31.LK:XL:t::Branch Conditional to Link Register
+0.19,6.BO,11.BI,16./,21.16,31.LK:XL:::Branch Conditional to Link Register
*601: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
*603: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
*603e:PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
@@ -1490,7 +1466,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
model_branch_predict(cpu_model(processor), BO{4} ? !succeed : succeed);
}
-0.19,6.BO,11.BI,16./,21.528,31.LK:XL:t::Branch Conditional to Count Register
+0.19,6.BO,11.BI,16./,21.528,31.LK:XL:::Branch Conditional to Count Register
*601: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
*603: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
*603e:PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
@@ -1515,13 +1491,13 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
#
# I.2.4.2 System Call Instruction
#
-0.17,6./,11./,16./,30.1,31./:SC:t::System Call
+0.17,6./,11./,16./,30.1,31./:SC:::System Call
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, 0
*603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, 0
*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
if (CURRENT_MODEL_ISSUE > 0)
- model_serialize(my_index, cpu_model(processor));
+ model_serialize(MY_INDEX, cpu_model(processor));
system_call_interrupt(processor, cia);
#
@@ -1614,7 +1590,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
unsigned_word b;
unsigned_word EA;
- if (RA == 0) b = 0;
+ if (RA_is_0) b = 0;
else b = *rA;
EA = b + EXTS(D);
*rT = MEM(unsigned, EA, 1);
@@ -1628,7 +1604,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
unsigned_word b;
unsigned_word EA;
- if (RA == 0) b = 0;
+ if (RA_is_0) b = 0;
else b = *rA;
EA = b + *rB;
*rT = MEM(unsigned, EA, 1);
@@ -1640,7 +1616,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
unsigned_word EA;
- if (RA == 0 || RA == RT)
+ if (RA_is_0 || RA == RT)
program_interrupt(processor, cia,
illegal_instruction_program_interrupt);
EA = *rA + EXTS(D);
@@ -1654,7 +1630,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
unsigned_word EA;
- if (RA == 0 || RA == RT)
+ if (RA_is_0 || RA == RT)
program_interrupt(processor, cia,
illegal_instruction_program_interrupt);
EA = *rA + *rB;
@@ -1669,7 +1645,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
unsigned_word b;
unsigned_word EA;
- if (RA == 0) b = 0;
+ if (RA_is_0) b = 0;
else b = *rA;
EA = b + EXTS(D);
*rT = MEM(unsigned, EA, 2);
@@ -1682,7 +1658,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
unsigned_word b;
unsigned_word EA;
- if (RA == 0) b = 0;
+ if (RA_is_0) b = 0;
else b = *rA;
EA = b + *rB;
*rT = MEM(unsigned, EA, 2);
@@ -1694,7 +1670,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
unsigned_word EA;
- if (RA == 0 || RA == RT)
+ if (RA_is_0 || RA == RT)
program_interrupt(processor, cia,
illegal_instruction_program_interrupt);
EA = *rA + EXTS(D);
@@ -1708,7 +1684,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
unsigned_word EA;
- if (RA == 0 || RA == RT)
+ if (RA_is_0 || RA == RT)
program_interrupt(processor, cia,
illegal_instruction_program_interrupt);
EA = *rA + *rB;
@@ -1723,7 +1699,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
unsigned_word b;
unsigned_word EA;
- if (RA == 0) b = 0;
+ if (RA_is_0) b = 0;
else b = *rA;
EA = b + EXTS(D);
*rT = MEM(signed, EA, 2);
@@ -1736,7 +1712,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
unsigned_word b;
unsigned_word EA;
- if (RA == 0) b = 0;
+ if (RA_is_0) b = 0;
else b = *rA;
EA = b + *rB;
*rT = MEM(signed, EA, 2);
@@ -1748,7 +1724,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
unsigned_word EA;
- if (RA == 0 || RA == RT)
+ if (RA_is_0 || RA == RT)
program_interrupt(processor, cia,
illegal_instruction_program_interrupt);
EA = *rA + EXTS(D);
@@ -1761,7 +1737,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
unsigned_word EA;
- if (RA == 0 || RA == RT)
+ if (RA_is_0 || RA == RT)
program_interrupt(processor, cia,
illegal_instruction_program_interrupt);
EA = *rA + *rB;
@@ -1776,7 +1752,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
unsigned_word b;
unsigned_word EA;
- if (RA == 0) b = 0;
+ if (RA_is_0) b = 0;
else b = *rA;
EA = b + EXTS(D);
*rT = MEM(unsigned, EA, 4);
@@ -1789,7 +1765,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
unsigned_word b;
unsigned_word EA;
- if (RA == 0) b = 0;
+ if (RA_is_0) b = 0;
else b = *rA;
EA = b + *rB;
*rT = MEM(unsigned, EA, 4);
@@ -1801,7 +1777,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
unsigned_word EA;
- if (RA == 0 || RA == RT)
+ if (RA_is_0 || RA == RT)
program_interrupt(processor, cia,
illegal_instruction_program_interrupt);
EA = *rA + EXTS(D);
@@ -1815,7 +1791,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
unsigned_word EA;
- if (RA == 0 || RA == RT)
+ if (RA_is_0 || RA == RT)
program_interrupt(processor, cia,
illegal_instruction_program_interrupt);
EA = *rA + *rB;
@@ -1826,7 +1802,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
0.58,6.RT,11.RA,16.DS,30.2:DS:64::Load Word Algebraic
# unsigned_word b;
# unsigned_word EA;
-# if (RA == 0) b = 0;
+# if (RA_is_0) b = 0;
# else b = *rA;
# EA = b + EXTS(DS_0b00);
# *rT = MEM(signed, EA, 4);
@@ -1834,14 +1810,14 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
0.31,6.RT,11.RA,16.RB,21.341,31./:X:64::Load Word Algebraic Indexed
# unsigned_word b;
# unsigned_word EA;
-# if (RA == 0) b = 0;
+# if (RA_is_0) b = 0;
# else b = *rA;
# EA = b + *rB;;
# *rT = MEM(signed, EA, 4);
0.31,6.RT,11.RA,16.RB,21.373,31./:X:64::Load Word Algebraic with Update Indexed
# unsigned_word EA;
-# if (RA == 0 || RA == RT)
+# if (RA_is_0 || RA == RT)
# program_interrupt(processor, cia
# illegal_instruction_program_interrupt);
# EA = *rA + *rB;
@@ -1851,7 +1827,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
0.58,6.RT,11.RA,16.DS,30.0:DS:64::Load Doubleword
# unsigned_word b;
# unsigned_word EA;
-# if (RA == 0) b = 0;
+# if (RA_is_0) b = 0;
# else b = *rA;
# EA = b + EXTS(DS_0b00);
# *rT = MEM(unsigned, EA, 8);
@@ -1859,14 +1835,14 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
0.31,6.RT,11.RA,16.RB,21.21,31./:X:64::Load Doubleword Indexed
# unsigned_word b;
# unsigned_word EA;
-# if (RA == 0) b = 0;
+# if (RA_is_0) b = 0;
# else b = *rA;
# EA = b + *rB;
# *rT = MEM(unsigned, EA, 8);
0.58,6.RT,11.RA,16.DS,30.1:DS:64::Load Doubleword with Update
# unsigned_word EA;
-# if (RA == 0 || RA == RT)
+# if (RA_is_0 || RA == RT)
# program_interrupt(processor, cia
# illegal_instruction_program_interrupt);
# EA = *rA + EXTS(DS_0b00);
@@ -1875,7 +1851,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
0.31,6.RT,11.RA,16.RB,21.53,31./:DS:64::Load Doubleword with Update Indexed
# unsigned_word EA;
-# if (RA == 0 || RA == RT)
+# if (RA_is_0 || RA == RT)
# program_interrupt(processor, cia
# illegal_instruction_program_interrupt);
# EA = *rA + *rB;
@@ -1895,7 +1871,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
unsigned_word b;
unsigned_word EA;
- if (RA == 0) b = 0;
+ if (RA_is_0) b = 0;
else b = *rA;
EA = b + EXTS(D);
STORE(EA, 1, *rS);
@@ -1908,7 +1884,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
unsigned_word b;
unsigned_word EA;
- if (RA == 0) b = 0;
+ if (RA_is_0) b = 0;
else b = *rA;
EA = b + *rB;
STORE(EA, 1, *rS);
@@ -1920,7 +1896,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
unsigned_word EA;
- if (RA == 0)
+ if (RA_is_0)
program_interrupt(processor, cia,
illegal_instruction_program_interrupt);
EA = *rA + EXTS(D);
@@ -1934,7 +1910,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
unsigned_word EA;
- if (RA == 0)
+ if (RA_is_0)
program_interrupt(processor, cia,
illegal_instruction_program_interrupt);
EA = *rA + *rB;
@@ -1949,7 +1925,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
unsigned_word b;
unsigned_word EA;
- if (RA == 0) b = 0;
+ if (RA_is_0) b = 0;
else b = *rA;
EA = b + EXTS(D);
STORE(EA, 2, *rS);
@@ -1962,7 +1938,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
unsigned_word b;
unsigned_word EA;
- if (RA == 0) b = 0;
+ if (RA_is_0) b = 0;
else b = *rA;
EA = b + *rB;
STORE(EA, 2, *rS);
@@ -1974,7 +1950,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
unsigned_word EA;
- if (RA == 0)
+ if (RA_is_0)
program_interrupt(processor, cia,
illegal_instruction_program_interrupt);
EA = *rA + EXTS(D);
@@ -1988,7 +1964,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
unsigned_word EA;
- if (RA == 0)
+ if (RA_is_0)
program_interrupt(processor, cia,
illegal_instruction_program_interrupt);
EA = *rA + *rB;
@@ -2003,7 +1979,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
unsigned_word b;
unsigned_word EA;
- if (RA == 0) b = 0;
+ if (RA_is_0) b = 0;
else b = *rA;
EA = b + EXTS(D);
STORE(EA, 4, *rS);
@@ -2016,7 +1992,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
unsigned_word b;
unsigned_word EA;
- if (RA == 0) b = 0;
+ if (RA_is_0) b = 0;
else b = *rA;
EA = b + *rB;
STORE(EA, 4, *rS);
@@ -2028,7 +2004,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
unsigned_word EA;
- if (RA == 0)
+ if (RA_is_0)
program_interrupt(processor, cia,
illegal_instruction_program_interrupt);
EA = *rA + EXTS(D);
@@ -2042,7 +2018,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
unsigned_word EA;
- if (RA == 0)
+ if (RA_is_0)
program_interrupt(processor, cia,
illegal_instruction_program_interrupt);
EA = *rA + *rB;
@@ -2053,20 +2029,20 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
0.62,6.RS,11.RA,16.DS,30.0:DS:64::Store Doubleword
# unsigned_word b;
# unsigned_word EA;
-# if (RA == 0) b = 0;
+# if (RA_is_0) b = 0;
# else b = *rA;
# EA = b + EXTS(DS_0b00);
# STORE(EA, 8, *rS);
0.31,6.RS,11.RA,16.RB,21.149,31./:X:64::Store Doubleword Indexed
# unsigned_word b;
# unsigned_word EA;
-# if (RA == 0) b = 0;
+# if (RA_is_0) b = 0;
# else b = *rA;
# EA = b + *rB;
# STORE(EA, 8, *rS);
0.62,6.RS,11.RA,16.DS,30.1:DS:64::Store Doubleword with Update
# unsigned_word EA;
-# if (RA == 0)
+# if (RA_is_0)
# program_interrupt(processor, cia
# illegal_instruction_program_interrupt);
# EA = *rA + EXTS(DS_0b00);
@@ -2074,7 +2050,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
# *rA = EA;
0.31,6.RS,11.RA,16.RB,21.181,31./:X:64::Store Doubleword with Update Indexed
# unsigned_word EA;
-# if (RA == 0)
+# if (RA_is_0)
# program_interrupt(processor, cia
# illegal_instruction_program_interrupt);
# EA = *rA + *rB;
@@ -2093,7 +2069,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
unsigned_word b;
unsigned_word EA;
- if (RA == 0) b = 0;
+ if (RA_is_0) b = 0;
else b = *rA;
EA = b + *rB;
*rT = SWAP_2(MEM(unsigned, EA, 2));
@@ -2106,7 +2082,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
unsigned_word b;
unsigned_word EA;
- if (RA == 0) b = 0;
+ if (RA_is_0) b = 0;
else b = *rA;
EA = b + *rB;
*rT = SWAP_4(MEM(unsigned, EA, 4));
@@ -2119,7 +2095,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
unsigned_word b;
unsigned_word EA;
- if (RA == 0) b = 0;
+ if (RA_is_0) b = 0;
else b = *rA;
EA = b + *rB;
STORE(EA, 2, SWAP_2(*rS));
@@ -2132,7 +2108,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
unsigned_word b;
unsigned_word EA;
- if (RA == 0) b = 0;
+ if (RA_is_0) b = 0;
else b = *rA;
EA = b + *rB;
STORE(EA, 4, SWAP_4(*rS));
@@ -2143,22 +2119,158 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
# I.3.3.5 Fixed-Point Load and Store Multiple Instrctions
#
-0.46,6.RT,11.RA,16.D:D:be::Load Multiple Word
+0.46,6.RT,11.RA,16.D:D:::Load Multiple Word
+ unsigned_word EA;
+ unsigned_word b;
+ int r;
+ if (RA_is_0) b = 0;
+ else b = *rA;
+ EA = b + EXTS(D);
+ r = RT;
+ if (RA >= r)
+ program_interrupt(processor, cia,
+ illegal_instruction_program_interrupt);
+ if (CURRENT_ALIGNMENT == STRICT_ALIGNMENT || (EA % 4 != 0))
+ alignment_interrupt(processor, cia, EA);
+ while (r <= 31) {
+ GPR(r) = MEM(unsigned, EA, 4);
+ r = r + 1;
+ EA = EA + 4;
+ }
-0.47,6.RS,11.RA,16.D:D:be::Store Multiple Word
+0.47,6.RS,11.RA,16.D:D:::Store Multiple Word
+ unsigned_word EA;
+ unsigned_word b;
+ int r;
+ if (RA_is_0) b = 0;
+ else b = *rA;
+ EA = b + EXTS(D);
+ if (CURRENT_ALIGNMENT == STRICT_ALIGNMENT
+ || (EA % 4 != 0))
+ alignment_interrupt(processor, cia, EA);
+ r = RS;
+ while (r <= 31) {
+ STORE(EA, 4, GPR(r));
+ r = r + 1;
+ EA = EA + 4;
+ }
#
# I.3.3.6 Fixed-Point Move Assist Instructions
#
-0.31,6.RT,11.RA,16.NB,21.597,31./:X:be::Load String Word Immediate
-
-0.31,6.RT,11.RA,16.RB,21.533,31./:X:be::Load String Word Indexed
+0.31,6.RT,11.RA,16.NB,21.597,31./:X:::Load String Word Immediate
+ unsigned_word EA;
+ int n;
+ int r;
+ int i;
+ int nr;
+ if (RA_is_0) EA = 0;
+ else EA = *rA;
+ if (NB == 0) n = 32;
+ else n = NB;
+ r = RT - 1;
+ i = 32;
+ nr = (n + 3) / 4;
+ if ((RT + nr >= 32)
+ ? (RA >= RT || RA < (RT + nr) % 32)
+ : (RA >= RT && RA < RT + nr))
+ program_interrupt(processor, cia,
+ illegal_instruction_program_interrupt);
+ if (CURRENT_ALIGNMENT == STRICT_ALIGNMENT)
+ alignment_interrupt(processor, cia, EA);
+ while (n > 0) {
+ if (i == 32) {
+ r = (r + 1) % 32;
+ GPR(r) = 0;
+ }
+ GPR(r) |= INSERTED(MEM(unsigned, EA, 1), i, i+7);
+ if (i == 64) i = 32;
+ EA = EA + 1;
+ n = n - 1;
+ }
-0.31,6.RS,11.RA,16.NB,21.725,31./:X:be::Store String Word Immedate
+0.31,6.RT,11.RA,16.RB,21.533,31./:X:::Load String Word Indexed
+ unsigned_word EA;
+ unsigned_word b;
+ int n;
+ int r;
+ int i;
+ int nr;
+ if (RA_is_0) b = 0;
+ else b = *rA;
+ EA = b + *rB;
+ n = EXTRACTED32(XER, 25, 31);
+ r = RT - 1;
+ i = 32;
+ nr = (n + 3) / 4;
+ if (((RT + n >= 32)
+ ? ((RA >= RT || RA < (RT + n) % 32)
+ || (RB >= RT || RB < (RT + n) % 32))
+ : ((RA >= RT && RA < RT + n)
+ || (RB >= RT && RB < RT + n)))
+ || (RT == RA || RT == RB))
+ program_interrupt(processor, cia,
+ illegal_instruction_program_interrupt);
+ if (CURRENT_ALIGNMENT == STRICT_ALIGNMENT)
+ alignment_interrupt(processor, cia, EA);
+ while (n > 0) {
+ if (i == 32) {
+ r = (r + 1) % 32;
+ GPR(i) = 0;
+ }
+ GPR(r) |= INSERTED(MEM(unsigned, EA, 1), i, i+7);
+ i = i + 8;
+ if (i == 64) i = 32;
+ EA = EA + 1;
+ n = n - 1;
+ }
-0.31,6.RS,11.RA,16.RB,21.661,31./:X:be::Store String Word Indexed
+0.31,6.RS,11.RA,16.NB,21.725,31./:X:::Store String Word Immedate
+ unsigned_word EA;
+ int n;
+ int r;
+ int i;
+ if (RA_is_0) EA = 0;
+ else EA = *rA;
+ if (NB == 0) n = 32;
+ else n = NB;
+ r = RS - 1;
+ i = 32;
+ if (CURRENT_ALIGNMENT == STRICT_ALIGNMENT)
+ alignment_interrupt(processor, cia, EA);
+ while (n > 0) {
+ if (i == 32) r = (r + 1) % 32;
+ STORE(EA, 1, EXTRACTED(GPR(r), i, i+7));
+ i = i + 8;
+ if (i == 64) i = 32;
+ EA = EA + 1;
+ n = n - 1;
+ }
+
+0.31,6.RS,11.RA,16.RB,21.661,31./:X:::Store String Word Indexed
+ unsigned_word EA;
+ unsigned_word b;
+ int n;
+ int r;
+ int i;
+ if (RA_is_0) b = 0;
+ else b = *rA;
+ EA = b + *rB;
+ if (CURRENT_ALIGNMENT == STRICT_ALIGNMENT)
+ alignment_interrupt(processor, cia, EA);
+ n = EXTRACTED32(XER, 25, 31);
+ r = RS - 1;
+ i = 32;
+ while (n > 0) {
+ if (i == 32) r = (r + 1) % 32;
+ STORE(EA, 1, EXTRACTED(GPR(r), i, i+7));
+ i = i + 8;
+ if (i == 64) i = 32;
+ EA = EA + 1;
+ n = n - 1;
+ }
#
@@ -2176,7 +2288,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
unsigned_word b;
unsigned_word EA;
- if (RA == 0) b = 0;
+ if (RA_is_0) b = 0;
else b = *rA;
EA = b + *rB;
RESERVE = 1;
@@ -2188,7 +2300,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
0.31,6.RT,11.RA,16.RB,21.84,31./:X:64::Load Doubleword And Reserve Indexed
unsigned_word b;
unsigned_word EA;
- if (RA == 0) b = 0;
+ if (RA_is_0) b = 0;
else b = *rA;
EA = b + *rB;
RESERVE = 1;
@@ -2204,7 +2316,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
*604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 3, 0
unsigned_word b;
unsigned_word EA;
- if (RA == 0) b = 0;
+ if (RA_is_0) b = 0;
else b = *rA;
EA = b + *rB;
if (RESERVE) {
@@ -2227,7 +2339,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
0.31,6.RS,11.RA,16.RB,21.214,31.1:X:64::Store Doubleword Conditional Indexed
unsigned_word b;
unsigned_word EA;
- if (RA == 0) b = 0;
+ if (RA_is_0) b = 0;
else b = *rA;
EA = b + *rB;
if (RESERVE) {
@@ -2259,7 +2371,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
# I.3.3.9 Fixed-Point Arithmetic Instructions
#
-0.14,6.RT,11.RA,16.SI:D:T::Add Immediate
+0.14,6.RT,11.RA,16.SI:D:::Add Immediate
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603e:PPC_UNIT_IU, PPC_UNIT_SRU, 1, 1, 0
@@ -2477,7 +2589,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
0.31,6.RT,11.RA,16.RB,21./,22.9,31.Rc:XO:64::Multiply High Doubleword Unsigned
-0.31,6.RT,11.RA,16.RB,21./,22.11,31.Rc:XO::milhwu:Multiply High Word Unsigned
+0.31,6.RT,11.RA,16.RB,21./,22.11,31.Rc:XO::mulhwu:Multiply High Word Unsigned
*601: PPC_UNIT_IU, PPC_UNIT_IU, 10, 10, 0
*603: PPC_UNIT_IU, PPC_UNIT_IU, 6, 6, 0
*603e:PPC_UNIT_IU, PPC_UNIT_IU, 6, 6, 0
@@ -2962,12 +3074,12 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
# CR0_COMPARE(result, 0, Rc);
0.23,6.RS,11.RA,16.RB,21.MB,26.ME,31.Rc:M:::Rotate Left Word then AND with Mask
-# long n = MASKED(*rB, 59, 63);
-# unsigned32 r = ROTL32(*rS, n);
-# unsigned32 m = MASK(MB+32, ME+32);
-# signed_word result = r & m;
-# *rA = result;
-# CR0_COMPARE(result, 0, Rc);
+ long n = MASKED(*rB, 59, 63);
+ unsigned32 r = ROTL32(*rS, n);
+ unsigned32 m = MASK(MB+32, ME+32);
+ signed_word result = r & m;
+ *rA = result;
+ CR0_COMPARE(result, 0, Rc);
0.30,6.RS,11.RA,16.sh_0_4,21.mb,27.3,30.sh_5,31.Rc:MD:64::Rotate Left Doubleword Immediate then Mask Insert
# long n = (sh_5 << 4) | sh_0_4;
@@ -3142,8 +3254,23 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
program_interrupt(processor, cia,
illegal_instruction_program_interrupt);
else {
- /* HACK - some SPR's need to get their value extracted specially */
- *rT = SPREG(n);
+ /* HACK - time base registers need to be calculated */
+ if (WITH_TIME_BASE) {
+ switch (n) {
+ case spr_dec:
+ *rT = cpu_get_decrementer(processor);
+ break;
+ case spr_tbu:
+ case spr_tbl:
+ /* NOTE - these SPR's are not readable. Use mftb[ul] */
+ default:
+ *rT = SPREG(n);
+ break;
+ }
+ }
+ else {
+ *rT = SPREG(n);
+ }
}
PPC_INSN_FROM_SPR(RT_BITMASK, n);
@@ -3167,6 +3294,8 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
PPC_INSN_MTCR(RS_BITMASK, FXM);
0.31,6.BF,9./,11./,16./,21.512,31./:X:::Move to Condition Register from XER
+# CR_SET(BF, EXTRACTED32(XER, 0, 3));
+# MBLIT32(XER, 0, 3, 0);
0.31,6.RT,11./,16./,21.19,31./:X:::Move From Condition Register
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
@@ -3187,7 +3316,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
unsigned_word b;
unsigned_word EA;
- if (RA == 0) b = 0;
+ if (RA_is_0) b = 0;
else b = *rA;
EA = b + EXTS(D);
*frT = DOUBLE(MEM(unsigned, EA, 4));
@@ -3200,7 +3329,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
unsigned_word b;
unsigned_word EA;
- if (RA == 0) b = 0;
+ if (RA_is_0) b = 0;
else b = *rA;
EA = b + *rB;
*frT = DOUBLE(MEM(unsigned, EA, 4));
@@ -3212,7 +3341,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
unsigned_word EA;
- if (RA == 0)
+ if (RA_is_0)
program_interrupt(processor, cia,
illegal_instruction_program_interrupt);
EA = *rA + EXTS(D);
@@ -3226,7 +3355,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
unsigned_word EA;
- if (RA == 0)
+ if (RA_is_0)
program_interrupt(processor, cia,
illegal_instruction_program_interrupt);
EA = *rA + *rB;
@@ -3241,7 +3370,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
unsigned_word b;
unsigned_word EA;
- if (RA == 0) b = 0;
+ if (RA_is_0) b = 0;
else b = *rA;
EA = b + EXTS(D);
*frT = MEM(unsigned, EA, 8);
@@ -3254,7 +3383,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
unsigned_word b;
unsigned_word EA;
- if (RA == 0) b = 0;
+ if (RA_is_0) b = 0;
else b = *rA;
EA = b + *rB;
*frT = MEM(unsigned, EA, 8);
@@ -3266,7 +3395,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
unsigned_word EA;
- if (RA == 0)
+ if (RA_is_0)
program_interrupt(processor, cia,
illegal_instruction_program_interrupt);
EA = *rA + EXTS(D);
@@ -3280,7 +3409,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
unsigned_word EA;
- if (RA == 0)
+ if (RA_is_0)
program_interrupt(processor, cia,
illegal_instruction_program_interrupt);
EA = *rA + *rB;
@@ -3300,7 +3429,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
unsigned_word b;
unsigned_word EA;
- if (RA == 0) b = 0;
+ if (RA_is_0) b = 0;
else b = *rA;
EA = b + EXTS(D);
STORE(EA, 4, SINGLE(*frS));
@@ -3313,7 +3442,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
unsigned_word b;
unsigned_word EA;
- if (RA == 0) b = 0;
+ if (RA_is_0) b = 0;
else b = *rA;
EA = b + *rB;
STORE(EA, 4, SINGLE(*frS));
@@ -3325,7 +3454,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
unsigned_word EA;
- if (RA == 0)
+ if (RA_is_0)
program_interrupt(processor, cia,
illegal_instruction_program_interrupt);
EA = *rA + EXTS(D);
@@ -3339,7 +3468,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
unsigned_word EA;
- if (RA == 0)
+ if (RA_is_0)
program_interrupt(processor, cia,
illegal_instruction_program_interrupt);
EA = *rA + *rB;
@@ -3354,7 +3483,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
unsigned_word b;
unsigned_word EA;
- if (RA == 0) b = 0;
+ if (RA_is_0) b = 0;
else b = *rA;
EA = b + EXTS(D);
STORE(EA, 8, *frS);
@@ -3367,7 +3496,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
unsigned_word b;
unsigned_word EA;
- if (RA == 0) b = 0;
+ if (RA_is_0) b = 0;
else b = *rA;
EA = b + *rB;
STORE(EA, 8, *frS);
@@ -3379,7 +3508,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
unsigned_word EA;
- if (RA == 0)
+ if (RA_is_0)
program_interrupt(processor, cia,
illegal_instruction_program_interrupt);
EA = *rA + EXTS(D);
@@ -3393,7 +3522,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
unsigned_word EA;
- if (RA == 0)
+ if (RA_is_0)
program_interrupt(processor, cia,
illegal_instruction_program_interrupt);
EA = *rA + *rB;
@@ -4028,28 +4157,29 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
int sign;
int exp;
unsigned64 frac_grx;
- /* split off cases for what to do */
- if (EXTRACTED64(*frB, 1, 11) < 897
- && EXTRACTED64(*frB, 1, 63) > 0) {
- if ((FPSCR & fpscr_ue) == 0) goto Disabled_Exponent_Underflow;
- if ((FPSCR & fpscr_ue) != 0) goto Enabled_Exponent_Underflow;
- }
- if (EXTRACTED64(*frB, 1, 11) > 1150
- && EXTRACTED64(*frB, 1, 11) < 2047) {
- if ((FPSCR & fpscr_oe) == 0) goto Disabled_Exponent_Overflow;
- if ((FPSCR & fpscr_oe) != 0) goto Enabled_Exponent_Overflow;
- }
- if (EXTRACTED64(*frB, 1, 11) > 896
- && EXTRACTED64(*frB, 1, 11) < 1151) goto Normal_Operand;
- if (EXTRACTED64(*frB, 1, 63) == 0) goto Zero_Operand;
- if (EXTRACTED64(*frB, 1, 11) == 2047) {
- if (EXTRACTED64(*frB, 12, 63) == 0) goto Infinity_Operand;
- if (EXTRACTED64(*frB, 12, 12) == 1) goto QNaN_Operand;
- if (EXTRACTED64(*frB, 12, 12) == 0
- && EXTRACTED64(*frB, 13, 63) > 0) goto SNaN_Operand;
- }
- /* handle them */
- Disabled_Exponent_Underflow:
+ /***/
+ /* split off cases for what to do */
+ if (EXTRACTED64(*frB, 1, 11) < 897
+ && EXTRACTED64(*frB, 1, 63) > 0) {
+ if ((FPSCR & fpscr_ue) == 0) GOTO(Disabled_Exponent_Underflow);
+ if ((FPSCR & fpscr_ue) != 0) GOTO(Enabled_Exponent_Underflow);
+ }
+ if (EXTRACTED64(*frB, 1, 11) > 1150
+ && EXTRACTED64(*frB, 1, 11) < 2047) {
+ if ((FPSCR & fpscr_oe) == 0) GOTO(Disabled_Exponent_Overflow);
+ if ((FPSCR & fpscr_oe) != 0) GOTO(Enabled_Exponent_Overflow);
+ }
+ if (EXTRACTED64(*frB, 1, 11) > 896
+ && EXTRACTED64(*frB, 1, 11) < 1151) GOTO(Normal_Operand);
+ if (EXTRACTED64(*frB, 1, 63) == 0) GOTO(Zero_Operand);
+ if (EXTRACTED64(*frB, 1, 11) == 2047) {
+ if (EXTRACTED64(*frB, 12, 63) == 0) GOTO(Infinity_Operand);
+ if (EXTRACTED64(*frB, 12, 12) == 1) GOTO(QNaN_Operand);
+ if (EXTRACTED64(*frB, 12, 12) == 0
+ && EXTRACTED64(*frB, 13, 63) > 0) GOTO(SNaN_Operand);
+ }
+ /**/
+ LABEL(Disabled_Exponent_Underflow):
sign = EXTRACTED64(*frB, 0, 0);
if (EXTRACTED64(*frB, 1, 11) == 0) {
exp = -1022;
@@ -4091,8 +4221,9 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
| INSERTED64(exp + 1023, 1, 11)
| INSERTED64(EXTRACTED64(frac_grx, 1, 52), 12, 63));
}
- goto Done;
- Enabled_Exponent_Underflow:
+ GOTO(Done);
+ /**/
+ LABEL(Enabled_Exponent_Underflow):
FPSCR_SET_UX(1);
sign = EXTRACTED64(*frB, 0, 0);
if (EXTRACTED64(*frB, 1, 11) == 0) {
@@ -4117,8 +4248,9 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
| INSERTED64(EXTRACTED64(frac_grx, 1, 52), 12, 63));
if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
- goto Done;
- Disabled_Exponent_Overflow:
+ GOTO(Done);
+ /**/
+ LABEL(Disabled_Exponent_Overflow):
FPSCR_SET_OX(1);
if ((FPSCR & fpscr_rn) == fpscr_rn_round_to_nearest) {
if (EXTRACTED64(*frB, 0, 0) == 0) {
@@ -4163,43 +4295,49 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
/* FPSCR[FR] <- undefined */
FPSCR_SET_FI(1);
FPSCR_SET_XX(1);
- goto Done;
- Enabled_Exponent_Overflow:
+ GOTO(Done);
+ /**/
+ LABEL(Enabled_Exponent_Overflow):
sign = EXTRACTED64(*frB, 0, 0);
exp = EXTRACTED64(*frB, 1, 11) - 1023;
frac_grx = BIT64(0) | INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52);
Round_Single(processor, sign, &exp, &frac_grx);
FPSCR_SET_XX(FPSCR & fpscr_fi);
- Enabled_Overflow:
- FPSCR_SET_OX(1);
- exp = exp - 192;
- *frT = (INSERTED64(sign, 0, 0)
- | INSERTED64(exp + 1023, 1, 11)
- | INSERTED64(EXTRACTED64(frac_grx, 1, 52), 12, 63));
- if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
- if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
- goto Done;
- Zero_Operand:
+ /**/
+ LABEL(Enabled_Overflow):
+ FPSCR_SET_OX(1);
+ exp = exp - 192;
+ *frT = (INSERTED64(sign, 0, 0)
+ | INSERTED64(exp + 1023, 1, 11)
+ | INSERTED64(EXTRACTED64(frac_grx, 1, 52), 12, 63));
+ if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
+ if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
+ GOTO(Done);
+ /**/
+ LABEL(Zero_Operand):
*frT = *frB;
if (EXTRACTED64(*frB, 0, 0) == 0) FPSCR_SET_FPRF(fpscr_rf_pos_zero);
if (EXTRACTED64(*frB, 0, 0) == 1) FPSCR_SET_FPRF(fpscr_rf_neg_zero);
FPSCR_SET_FR(0);
FPSCR_SET_FI(0);
- goto Done;
- Infinity_Operand:
+ GOTO(Done);
+ /**/
+ LABEL(Infinity_Operand):
*frT = *frB;
if (EXTRACTED64(*frB, 0, 0) == 0) FPSCR_SET_FPRF(fpscr_rf_pos_infinity);
if (EXTRACTED64(*frB, 0, 0) == 1) FPSCR_SET_FPRF(fpscr_rf_neg_infinity);
FPSCR_SET_FR(0);
FPSCR_SET_FI(0);
- goto Done;
- QNaN_Operand:
+ GOTO(Done);
+ /**/
+ LABEL(QNaN_Operand):
*frT = INSERTED64(EXTRACTED64(*frB, 0, 34), 0, 34);
FPSCR_SET_FPRF(fpscr_rf_quiet_nan);
FPSCR_SET_FR(0);
FPSCR_SET_FI(0);
- goto Done;
- SNaN_Operand:
+ GOTO(Done);
+ /**/
+ LABEL(SNaN_Operand):
FPSCR_OR_VX(fpscr_vxsnan);
if ((FPSCR & fpscr_ve) == 0) {
*frT = (MASKED64(*frB, 0, 11)
@@ -4209,29 +4347,35 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
}
FPSCR_SET_FR(0);
FPSCR_SET_FI(0);
- goto Done;
- Normal_Operand:
+ GOTO(Done);
+ /**/
+ LABEL(Normal_Operand):
sign = EXTRACTED64(*frB, 0, 0);
exp = EXTRACTED64(*frB, 1, 11) - 1023;
frac_grx = BIT64(0) | INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52);
Round_Single(processor, sign, &exp, &frac_grx);
FPSCR_SET_XX(FPSCR & fpscr_fi);
- if (exp > 127 && (FPSCR & fpscr_oe) == 0) goto Disabled_Exponent_Overflow;
- if (exp > 127 && (FPSCR & fpscr_oe) != 0) goto Enabled_Overflow;
+ if (exp > 127 && (FPSCR & fpscr_oe) == 0) GOTO(Disabled_Exponent_Overflow);
+ if (exp > 127 && (FPSCR & fpscr_oe) != 0) GOTO(Enabled_Overflow);
*frT = (INSERTED64(sign, 0, 0)
| INSERTED64(exp + 1023, 1, 11)
| INSERTED64(EXTRACTED64(frac_grx, 1, 52), 12, 63));
if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
- goto Done;
- Done:
- PPC_INSN_FLOAT(FRT_BITMASK, FRB_BITMASK, Rc);
+ GOTO(Done);
+ /**/
+ LABEL(Done):
+ PPC_INSN_FLOAT(FRT_BITMASK, FRB_BITMASK, Rc);
+
0.63,6.FRT,11./,16.FRB,21.814,31.Rc:X:64,f::Floating Convert To Integer Doubleword
+ floating_point_assist_interrupt(processor, cia);
0.63,6.FRT,11./,16.FRB,21.815,31.Rc:X:64,f::Floating Convert To Integer Doubleword with round towards Zero
+ floating_point_assist_interrupt(processor, cia);
0.63,6.FRT,11./,16.FRB,21.14,31.Rc:X:f::Floating Convert To Integer Word
+ floating_point_assist_interrupt(processor, cia);
0.63,6.FRT,11./,16.FRB,21.15,31.Rc:X:f:fctiwz:Floating Convert To Integer Word with round towards Zero
*601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
@@ -4249,30 +4393,32 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
int sign = EXTRACTED64(*frB, 0, 0);
int exp = 63;
unsigned64 frac = *frB;
- if (frac == 0) goto Zero_Operand;
- if (sign == 1) frac = ~frac + 1;
- while (EXTRACTED64(frac, 0, 0) == 0) {
- /*??? do the loop 0 times if (FRB) = max negative integer */
- frac = INSERTED64(EXTRACTED64(frac, 1, 63), 0, 62);
- exp = exp - 1;
- }
- Round_Float(processor, sign, &exp, &frac, FPSCR & fpscr_rn);
- if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
- if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
- *frT = (INSERTED64(sign, 0, 0)
- | INSERTED64(exp + 1023, 1, 11)
- | INSERTED64(EXTRACTED64(frac, 1, 52), 12, 63));
- goto Done;
+ /***/
+ if (frac == 0) GOTO(Zero_Operand);
+ if (sign == 1) frac = ~frac + 1;
+ while (EXTRACTED64(frac, 0, 0) == 0) {
+ /*??? do the loop 0 times if (FRB) = max negative integer */
+ frac = INSERTED64(EXTRACTED64(frac, 1, 63), 0, 62);
+ exp = exp - 1;
+ }
+ Round_Float(processor, sign, &exp, &frac, FPSCR & fpscr_rn);
+ if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
+ if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
+ *frT = (INSERTED64(sign, 0, 0)
+ | INSERTED64(exp + 1023, 1, 11)
+ | INSERTED64(EXTRACTED64(frac, 1, 52), 12, 63));
+ GOTO(Done);
/**/
- Zero_Operand:
+ LABEL(Zero_Operand):
FPSCR_SET_FR(0);
FPSCR_SET_FI(0);
FPSCR_SET_FPRF(fpscr_rf_pos_zero);
*frT = 0;
- goto Done;
+ GOTO(Done);
/**/
- Done:
- PPC_INSN_FLOAT(FRT_BITMASK, FRB_BITMASK, Rc);
+ LABEL(Done):
+ PPC_INSN_FLOAT(FRT_BITMASK, FRB_BITMASK, Rc);
+
#
# I.4.6.7 Floating-Point Compare Instructions
@@ -4334,41 +4480,94 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
#
0.63,6.FRT,11./,16./,21.583,31.Rc:X:f::Move From FPSCR
+ FPSCR_BEGIN;
+ *frT = FPSCR;
+ FPSCR_END(Rc);
0.63,6.BF,9./,11.BFA,14./,16./,21.64,31./:X:f::Move to Condition Register from FPSCR
+ FPSCR_BEGIN;
+ unsigned field = FPSCR_FIELD(BFA);
+ CR_SET(BF, field);
+ FPSCR_SET(BFA, 0); /* FPSCR_END fixes up FEX/VX */
+ FPSCR_END(0);
0.64,6.BF,9./,11./,16.U,20./,21.134,31.Rc:X:f::Move To FPSCR Field Immediate
+ FPSCR_BEGIN;
+ FPSCR_SET(BF, U);
+ FPSCR_END(Rc);
0.63,6./,7.FLM,15./,16.FRB,21.711,31.Rc:XFL:f::Move To FPSCR Fields
+ FPSCR_BEGIN;
+ int i;
+ for (i = 0; i < 8; i++) {
+ if ((FLM & BIT8(i))) {
+ FPSCR &= ~MASK32(i*4, i*4+3);
+ FPSCR |= MASKED32(*frB, i*4, i*4+3);
+ }
+ }
+ FPSCR_END(Rc);
0.63,6.BT,11./,16./,21.70,31.Rc:X:f::Move To FPSCR Bit 0
+ FPSCR_BEGIN;
+ unsigned32 bit = BIT32(BT);
+ FPSCR &= ~bit;
+ FPSCR_END(Rc);
0.63,6.BT,11./,16./,21.38,31.Rc:X:f::Move To FPSCR Bit 1
+ FPSCR_BEGIN;
+ unsigned32 bit = BIT32(BT);
+ if (bit & fpscr_fi)
+ bit |= fpscr_xx;
+ if ((bit & fpscr_vx_bits))
+ bit |= fpscr_fx;
+ /* note - omit vx bit */
+ if ((bit & (fpscr_ox | fpscr_ux | fpscr_zx | fpscr_xx)))
+ bit |= fpscr_fx;
+ FPSCR |= bit;
+ FPSCR_END(Rc);
#
# I.A.1.1 Floating-Point Store Instruction
#
-0.31,6.FRS,11.RA,16.RB,21.983,31./:X:f::Store Floating-Point as Integer Word Indexed
+0.31,6.FRS,11.RA,16.RB,21.983,31./:X:f,o::Store Floating-Point as Integer Word Indexed
+ program_interrupt(processor, cia, optional_instruction_program_interrupt);
#
# I.A.1.2 Floating-Point Arithmetic Instructions
#
-0.63,6.FRT,11./,16.FRB,21./,26.22,31.Rc:A:f::Floating Square Root
+0.63,6.FRT,11./,16.FRB,21./,26.22,31.Rc:A:f,o::Floating Square Root
+ program_interrupt(processor, cia, optional_instruction_program_interrupt);
-0.59,6.FRT,11./,16.FRB,21./,26.22,31.Rc:A:f::Floating Square Root Single
+0.59,6.FRT,11./,16.FRB,21./,26.22,31.Rc:A:f,o::Floating Square Root Single
+ program_interrupt(processor, cia, optional_instruction_program_interrupt);
-0.59,6.FRT,11./,16.FRB,21./,26.24,31.Rc:A:f::Floating Reciprocal Estimate Single
+0.59,6.FRT,11./,16.FRB,21./,26.24,31.Rc:A:f,o::Floating Reciprocal Estimate Single
+ program_interrupt(processor, cia, optional_instruction_program_interrupt);
-0.63,6.FRT,11./,16.FRB,21./,26.26,31.Rc:A:f::Floating Reciprocal Square Root Estimate
+0.63,6.FRT,11./,16.FRB,21./,26.26,31.Rc:A:f,o::Floating Reciprocal Square Root Estimate
+ program_interrupt(processor, cia, optional_instruction_program_interrupt);
#
# I.A.1.3 Floating-Point Select Instruction
#
-0.63,6.FRT,11.FRA,16.FRB,21.FRC,26.23,31.Rc:A:f::Floating Select
-
+0.63,6.FRT,11.FRA,16.FRB,21.FRC,26.23,31.Rc:A:f,o::Floating Select
+*601: PPC_UNIT_BAD, PPC_UNIT_BAD, 0, 0, 0
+*603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
+*603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
+*604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
+ if (CURRENT_MODEL == MODEL_ppc601) {
+ program_interrupt(processor, cia, optional_instruction_program_interrupt);
+ } else {
+ unsigned64 zero = 0;
+ FPSCR_BEGIN;
+ if (is_NaN(*frA, 0) || is_less_than (frA, &zero)) *frT = *frB;
+ else *frT = *frC;
+ FPSCR_END(Rc);
+ PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK | FRC_BITMASK, Rc);
+ }
#
# II.3.2 Cache Management Instructions
@@ -4390,7 +4589,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 1, 0
- cpu_synchronize_context(processor);
+ cpu_synchronize_context(processor, cia);
PPC_INSN_INT(0, 0, 0);
@@ -4486,7 +4685,8 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
| MASKED(SRR1, 37, 41)
| MASKED(SRR1, 48, 63));
NIA = MASKED(SRR0, 0, 61);
- cpu_synchronize_context(processor);
+ cpu_synchronize_context(processor, cia);
+ check_masked_interrupts(processor);
}
#
@@ -4503,8 +4703,10 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
if (IS_PROBLEM_STATE(processor))
program_interrupt(processor, cia,
privileged_instruction_program_interrupt);
- else
+ else {
MSR = *rS;
+ check_masked_interrupts(processor);
+ }
0.31,6.RT,11./,16./,21.83,31./:X:::Move From Machine State Register
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
@@ -4514,8 +4716,10 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
if (IS_PROBLEM_STATE(processor))
program_interrupt(processor, cia,
privileged_instruction_program_interrupt);
- else
+ else {
*rT = MSR;
+ check_masked_interrupts(processor);
+ }
#
diff --git a/gnu/dist/sim/ppc/psim.c b/gnu/dist/sim/ppc/psim.c
index 64e0e2d3246..b76429c2de6 100644
--- a/gnu/dist/sim/ppc/psim.c
+++ b/gnu/dist/sim/ppc/psim.c
@@ -1,6 +1,6 @@
/* This file is part of the program psim.
- Copyright (C) 1994-1996, Andrew Cagney <cagney@highland.com.au>
+ 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
@@ -22,7 +22,11 @@
#ifndef _PSIM_C_
#define _PSIM_C_
-#include "inline.c"
+#include "cpu.h" /* includes psim.h */
+#include "idecode.h"
+#include "options.h"
+
+#include "tree.h"
#include <stdio.h>
#include <ctype.h>
@@ -33,10 +37,6 @@
#include <setjmp.h>
-#include "cpu.h" /* includes psim.h */
-#include "idecode.h"
-#include "options.h"
-
#ifdef HAVE_STRING_H
#include <string.h>
#else
@@ -45,6 +45,7 @@
#endif
#endif
+
#include "bfd.h"
@@ -78,6 +79,7 @@ int current_environment;
int current_alignment;
int current_floating_point;
int current_model_issue = MODEL_ISSUE_IGNORE;
+int current_stdio = DO_USE_STDIO;
model_enum current_model = WITH_DEFAULT_MODEL;
@@ -87,16 +89,16 @@ INLINE_PSIM\
(device *)
psim_tree(void)
{
- device *root = core_device_create();
- device_tree_add_parsed(root, "/aliases");
- device_tree_add_parsed(root, "/options");
- device_tree_add_parsed(root, "/chosen");
- device_tree_add_parsed(root, "/packages");
- device_tree_add_parsed(root, "/cpus");
- device_tree_add_parsed(root, "/openprom");
- device_tree_add_parsed(root, "/openprom/init");
- device_tree_add_parsed(root, "/openprom/trace");
- device_tree_add_parsed(root, "/openprom/options");
+ device *root = tree_parse(NULL, "core");
+ tree_parse(root, "/aliases");
+ tree_parse(root, "/options");
+ tree_parse(root, "/chosen");
+ tree_parse(root, "/packages");
+ tree_parse(root, "/cpus");
+ tree_parse(root, "/openprom");
+ tree_parse(root, "/openprom/init");
+ tree_parse(root, "/openprom/trace");
+ tree_parse(root, "/openprom/options");
return root;
}
@@ -122,53 +124,82 @@ psim_usage(int verbose)
printf_filtered("\n");
printf_filtered("Where\n");
printf_filtered("\n");
- printf_filtered("\t<image> Name of the PowerPC program to run.\n");
+ printf_filtered("\t<image> Name of the PowerPC program to run.\n");
if (verbose) {
- printf_filtered("\t This can either be a PowerPC binary or\n");
- printf_filtered("\t a text file containing a device tree\n");
- printf_filtered("\t specification.\n");
- printf_filtered("\t PSIM will attempt to determine from the\n");
- printf_filtered("\t specified <image> the intended emulation\n");
- printf_filtered("\t environment.\n");
- printf_filtered("\t If PSIM gets it wrong, the emulation\n");
- printf_filtered("\t environment can be specified using the\n");
- printf_filtered("\t `-e' option (described below).\n");
+ printf_filtered("\t This can either be a PowerPC binary or\n");
+ printf_filtered("\t a text file containing a device tree\n");
+ printf_filtered("\t specification.\n");
+ printf_filtered("\t PSIM will attempt to determine from the\n");
+ printf_filtered("\t specified <image> the intended emulation\n");
+ printf_filtered("\t environment.\n");
+ printf_filtered("\t If PSIM gets it wrong, the emulation\n");
+ printf_filtered("\t environment can be specified using the\n");
+ printf_filtered("\t `-e' option (described below).\n");
printf_filtered("\n"); }
- printf_filtered("\t<image-arg> Argument to be passed to <image>\n");
+ printf_filtered("\t<image-arg> Argument to be passed to <image>\n");
if (verbose) {
- printf_filtered("\t These arguments will be passed to\n");
- printf_filtered("\t <image> (as standard C argv, argc)\n");
- printf_filtered("\t when <image> is started.\n");
+ printf_filtered("\t These arguments will be passed to\n");
+ printf_filtered("\t <image> (as standard C argv, argc)\n");
+ printf_filtered("\t when <image> is started.\n");
printf_filtered("\n"); }
- printf_filtered("\t<psim-option> See below\n");
+ printf_filtered("\t<psim-option> See below\n");
printf_filtered("\n");
printf_filtered("The following are valid <psim-option>s:\n");
printf_filtered("\n");
- printf_filtered("\t-m <model> Specify the processor to model (604)\n");
- if (verbose) {
- printf_filtered("\t Selects the processor to use when\n");
- printf_filtered("\t modeling execution units. Includes:\n");
- printf_filtered("\t 604, 603 and 603e\n");
- printf_filtered("\n"); }
- printf_filtered("\t-e <os-emul> specify an OS or platform to model\n");
+
+ printf_filtered("\t-c <count> Limit the simulation to <count> iterations\n");
+ if (verbose) {
+ printf_filtered("\n");
+ }
+
+ printf_filtered("\t-i or -i2 Print instruction counting statistics\n");
+ if (verbose) {
+ printf_filtered("\t Specify -i2 for a more detailed display\n");
+ printf_filtered("\n");
+ }
+
+ printf_filtered("\t-I Print execution unit statistics\n");
+ if (verbose) { printf_filtered("\n"); }
+
+ printf_filtered("\t-e <os-emul> specify an OS or platform to model\n");
if (verbose) {
- printf_filtered("\t Can be any of the following:\n");
- printf_filtered("\t bug - OEA + MOTO BUG ROM calls\n");
- printf_filtered("\t netbsd - UEA + NetBSD system calls\n");
- printf_filtered("\t chirp - OEA + a few OpenBoot calls\n");
+ printf_filtered("\t Can be any of the following:\n");
+ printf_filtered("\t bug - OEA + MOTO BUG ROM calls\n");
+ printf_filtered("\t netbsd - UEA + NetBSD system calls\n");
+ printf_filtered("\t solaris - UEA + Solaris system calls\n");
+ printf_filtered("\t linux - UEA + Linux system calls\n");
+ printf_filtered("\t chirp - OEA + a few OpenBoot calls\n");
printf_filtered("\n"); }
- printf_filtered("\t-i Print instruction counting statistics\n");
- if (verbose) { printf_filtered("\n"); }
- printf_filtered("\t-I Print execution unit statistics\n");
+
+ printf_filtered("\t-f <file> Merge <file> into the device tree\n");
if (verbose) { printf_filtered("\n"); }
- printf_filtered("\t-r <size> Set RAM size in bytes (OEA environments)\n");
+
+ printf_filtered("\t-h -? -H give more detailed usage\n");
if (verbose) { printf_filtered("\n"); }
- printf_filtered("\t-t [!]<trace> Enable (disable) <trace> option\n");
+
+ printf_filtered("\t-m <model> Specify the processor to model (604)\n");
+ if (verbose) {
+ printf_filtered("\t Selects the processor to use when\n");
+ printf_filtered("\t modeling execution units. Includes:\n");
+ printf_filtered("\t 604, 603 and 603e\n");
+ printf_filtered("\n"); }
+
+ printf_filtered("\t-n <nr-smp> Specify the number of processors in SMP simulations\n");
+ if (verbose) {
+ printf_filtered("\t Specifies the number of processors that are\n");
+ printf_filtered("\t to be modeled in a symetric multi-processor (SMP)\n");
+ printf_filtered("\t simulation\n");
+ printf_filtered("\n"); }
+
+ printf_filtered("\t-o <dev-spec> Add device <dev-spec> to the device tree\n");
if (verbose) { printf_filtered("\n"); }
- printf_filtered("\t-o <spec> add device <spec> to the device tree\n");
+
+ printf_filtered("\t-r <ram-size> Set RAM size in bytes (OEA environments)\n");
if (verbose) { printf_filtered("\n"); }
- printf_filtered("\t-h -? -H give more detailed usage\n");
+
+ printf_filtered("\t-t [!]<trace> Enable (disable) <trace> option\n");
if (verbose) { printf_filtered("\n"); }
+
printf_filtered("\n");
trace_usage(verbose);
device_usage(verbose);
@@ -198,9 +229,17 @@ psim_options(device *root,
psim_usage(0);
error ("");
break;
+ case 'c':
+ param = find_arg("Missing <count> option for -c (max-iterations)\n", &argp, argv);
+ tree_parse(root, "/openprom/options/max-iterations %s", param);
+ break;
case 'e':
- param = find_arg("Missing <emul> option for -e\n", &argp, argv);
- device_tree_add_parsed(root, "/openprom/options/os-emul %s", param);
+ param = find_arg("Missing <emul> option for -e (os-emul)\n", &argp, argv);
+ tree_parse(root, "/openprom/options/os-emul %s", param);
+ break;
+ case 'f':
+ param = find_arg("Missing <file> option for -f\n", &argp, argv);
+ psim_merge_device_file(root, param);
break;
case 'h':
case '?':
@@ -210,44 +249,87 @@ psim_options(device *root,
psim_usage(2);
break;
case 'i':
- device_tree_add_parsed(root, "/openprom/trace/print-info 1");
+ if (isdigit(p[1])) {
+ tree_parse(root, "/openprom/trace/print-info %c", p[1]);
+ p++;
+ }
+ else {
+ tree_parse(root, "/openprom/trace/print-info 1");
+ }
break;
case 'I':
- device_tree_add_parsed(root, "/openprom/trace/print-info 2");
- device_tree_add_parsed(root, "/openprom/options/model-issue %d",
- MODEL_ISSUE_PROCESS);
+ tree_parse(root, "/openprom/trace/print-info 2");
+ tree_parse(root, "/openprom/options/model-issue %d",
+ MODEL_ISSUE_PROCESS);
break;
case 'm':
- param = find_arg("Missing <model> option for -m\n", &argp, argv);
- device_tree_add_parsed(root, "/openprom/options/model \"%s", param);
+ param = find_arg("Missing <model> option for -m (model)\n", &argp, argv);
+ tree_parse(root, "/openprom/options/model \"%s", param);
+ break;
+ case 'n':
+ param = find_arg("Missing <nr-smp> option for -n (smp)\n", &argp, argv);
+ tree_parse(root, "/openprom/options/smp %s", param);
break;
case 'o':
- param = find_arg("Missing <device> option for -o\n", &argp, argv);
- current = device_tree_add_parsed(current, "%s", param);
+ param = find_arg("Missing <dev-spec> option for -o\n", &argp, argv);
+ current = tree_parse(current, "%s", param);
break;
case 'r':
- param = find_arg("Missing <ram-size> option for -r\n", &argp, argv);
- device_tree_add_parsed(root, "/openprom/options/oea-memory-size 0x%lx",
- atol(param));
+ param = find_arg("Missing <ram-size> option for -r (oea-memory-size)\n", &argp, argv);
+ tree_parse(root, "/openprom/options/oea-memory-size %s",
+ param);
break;
case 't':
- param = find_arg("Missing <trace> option for -t\n", &argp, argv);
+ param = find_arg("Missing <trace> option for -t (trace/*)\n", &argp, argv);
if (param[0] == '!')
- device_tree_add_parsed(root, "/openprom/trace/%s 0", param+1);
+ tree_parse(root, "/openprom/trace/%s 0", param+1);
else
- device_tree_add_parsed(root, "/openprom/trace/%s 1", param);
+ tree_parse(root, "/openprom/trace/%s 1", param);
break;
}
p += 1;
}
argp += 1;
}
- /* force the trace node to (re)process its options */
- device_init_data(device_tree_find_device(root, "/openprom/trace"), NULL);
+ /* force the trace node to process its options now *before* the tree
+ initialization occures */
+ device_ioctl(tree_find_device(root, "/openprom/trace"),
+ NULL, 0,
+ device_ioctl_set_trace);
+
/* return where the options end */
return argv + argp;
}
+INLINE_PSIM\
+(void)
+psim_command(device *root,
+ char **argv)
+{
+ int argp = 0;
+ if (argv[argp] == NULL) {
+ return;
+ }
+ else if (strcmp(argv[argp], "trace") == 0) {
+ const char *opt = find_arg("Missing <trace> option", &argp, argv);
+ if (opt[0] == '!')
+ trace_option(opt + 1, 0);
+ else
+ trace_option(opt, 1);
+ }
+ else if (strcmp(*argv, "change-media") == 0) {
+ char *device = find_arg("Missing device name", &argp, argv);
+ char *media = argv[++argp];
+ device_ioctl(tree_find_device(root, device), NULL, 0,
+ device_ioctl_change_media, media);
+ }
+ else {
+ printf_filtered("Unknown PSIM command %s, try\n", argv[argp]);
+ printf_filtered(" trace <trace-option>\n");
+ printf_filtered(" change-media <device> [ <new-image> ]\n");
+ }
+}
+
/* create the simulator proper from the device tree and executable */
@@ -271,13 +353,13 @@ psim_create(const char *file_name,
error("psim: either file %s was not reconized or unreconized or unknown os-emulation type\n", file_name);
/* fill in the missing real number of CPU's */
- nr_cpus = device_find_integer_property(root, "/openprom/options/smp");
+ nr_cpus = tree_find_integer_property(root, "/openprom/options/smp");
if (MAX_NR_PROCESSORS < nr_cpus)
error("target and configured number of cpus conflict\n");
/* fill in the missing TARGET BYTE ORDER information */
current_target_byte_order
- = (device_find_boolean_property(root, "/options/little-endian?")
+ = (tree_find_boolean_property(root, "/options/little-endian?")
? LITTLE_ENDIAN
: BIG_ENDIAN);
if (CURRENT_TARGET_BYTE_ORDER != current_target_byte_order)
@@ -292,7 +374,7 @@ psim_create(const char *file_name,
error("host and configured byte order conflict\n");
/* fill in the missing OEA/VEA information */
- env = device_find_string_property(root, "/openprom/options/env");
+ env = tree_find_string_property(root, "/openprom/options/env");
current_environment = ((strcmp(env, "user") == 0
|| strcmp(env, "uea") == 0)
? USER_ENVIRONMENT
@@ -310,7 +392,7 @@ psim_create(const char *file_name,
/* fill in the missing ALLIGNMENT information */
current_alignment
- = (device_find_boolean_property(root, "/openprom/options/strict-alignment?")
+ = (tree_find_boolean_property(root, "/openprom/options/strict-alignment?")
? STRICT_ALIGNMENT
: NONSTRICT_ALIGNMENT);
if (CURRENT_ALIGNMENT != current_alignment)
@@ -318,15 +400,23 @@ psim_create(const char *file_name,
/* fill in the missing FLOATING POINT information */
current_floating_point
- = (device_find_boolean_property(root, "/openprom/options/floating-point?")
+ = (tree_find_boolean_property(root, "/openprom/options/floating-point?")
? HARD_FLOATING_POINT
: SOFT_FLOATING_POINT);
if (CURRENT_FLOATING_POINT != current_floating_point)
error("target and configured floating-point conflict\n");
+ /* fill in the missing STDIO information */
+ current_stdio
+ = (tree_find_boolean_property(root, "/openprom/options/use-stdio?")
+ ? DO_USE_STDIO
+ : DONT_USE_STDIO);
+ if (CURRENT_STDIO != current_stdio)
+ error("target and configured stdio interface conflict\n");
+
/* sort out the level of detail for issue modeling */
current_model_issue
- = device_find_integer_property(root, "/openprom/options/model-issue");
+ = tree_find_integer_property(root, "/openprom/options/model-issue");
if (CURRENT_MODEL_ISSUE != current_model_issue)
error("target and configured model-issue conflict\n");
@@ -338,12 +428,12 @@ psim_create(const char *file_name,
ihandle into the corresponding cpu's phandle and then querying
the "name" property, the cpu type can be determined. Ok? */
- model_set(device_find_string_property(root, "/openprom/options/model"));
+ model_set(tree_find_string_property(root, "/openprom/options/model"));
/* create things */
system = ZALLOC(psim);
system->events = event_queue_create();
- system->memory = core_create(root);
+ system->memory = core_from_device(root);
system->monitor = mon_create();
system->nr_cpus = nr_cpus;
system->os_emulation = os_emulation;
@@ -353,7 +443,6 @@ psim_create(const char *file_name,
for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; cpu_nr++) {
system->processors[cpu_nr] = cpu_create(system,
system->memory,
- system->events,
mon_cpu(system->monitor,
cpu_nr),
system->os_emulation,
@@ -362,7 +451,7 @@ psim_create(const char *file_name,
/* dump out the contents of the device tree */
if (ppc_trace[trace_print_device_tree] || ppc_trace[trace_dump_device_tree])
- device_tree_traverse(root, device_tree_print_device, NULL, NULL);
+ tree_print(root);
if (ppc_trace[trace_dump_device_tree])
error("");
@@ -372,7 +461,7 @@ psim_create(const char *file_name,
/* allow the simulation to stop/restart abnormaly */
-STATIC_INLINE_PSIM\
+INLINE_PSIM\
(void)
psim_set_halt_and_restart(psim *system,
void *halt_jmp_buf,
@@ -382,7 +471,7 @@ psim_set_halt_and_restart(psim *system,
system->path_to_restart = restart_jmp_buf;
}
-STATIC_INLINE_PSIM\
+INLINE_PSIM\
(void)
psim_clear_halt_and_restart(psim *system)
{
@@ -395,6 +484,8 @@ INLINE_PSIM\
psim_restart(psim *system,
int current_cpu)
{
+ ASSERT(current_cpu >= 0 && current_cpu < system->nr_cpus);
+ ASSERT(system->path_to_restart != NULL);
system->last_cpu = current_cpu;
longjmp(*(jmp_buf*)(system->path_to_restart), current_cpu + 1);
}
@@ -404,18 +495,42 @@ INLINE_PSIM\
(void)
psim_halt(psim *system,
int current_cpu,
- unsigned_word cia,
stop_reason reason,
int signal)
{
+ ASSERT(current_cpu >= 0 && current_cpu <= system->nr_cpus);
+ ASSERT(system->path_to_halt != NULL);
system->last_cpu = current_cpu;
- system->halt_status.cpu_nr = current_cpu;
system->halt_status.reason = reason;
system->halt_status.signal = signal;
- system->halt_status.program_counter = cia;
+ if (current_cpu == system->nr_cpus) {
+ system->halt_status.cpu_nr = 0;
+ system->halt_status.program_counter =
+ cpu_get_program_counter(system->processors[0]);
+ }
+ else {
+ system->halt_status.cpu_nr = current_cpu;
+ system->halt_status.program_counter =
+ cpu_get_program_counter(system->processors[current_cpu]);
+ }
longjmp(*(jmp_buf*)(system->path_to_halt), current_cpu + 1);
}
+
+INLINE_PSIM\
+(int)
+psim_last_cpu(psim *system)
+{
+ return system->last_cpu;
+}
+
+INLINE_PSIM\
+(int)
+psim_nr_cpus(psim *system)
+{
+ return system->nr_cpus;
+}
+
INLINE_PSIM\
(psim_status)
psim_get_status(psim *system)
@@ -441,11 +556,30 @@ INLINE_PSIM\
psim_device(psim *system,
const char *path)
{
- return device_tree_find_device(system->devices, path);
+ return tree_find_device(system->devices, path);
+}
+
+INLINE_PSIM\
+(event_queue *)
+psim_event_queue(psim *system)
+{
+ return system->events;
}
+STATIC_INLINE_PSIM\
+(void)
+psim_max_iterations_exceeded(void *data)
+{
+ psim *system = data;
+ psim_halt(system,
+ system->nr_cpus, /* halted during an event */
+ was_signalled,
+ -1);
+}
+
+
INLINE_PSIM\
(void)
psim_init(psim *system)
@@ -454,24 +588,40 @@ psim_init(psim *system)
/* scrub the monitor */
mon_init(system->monitor, system->nr_cpus);
- os_emul_init(system->os_emulation, system->nr_cpus);
+
+ /* trash any pending events */
event_queue_init(system->events);
+ /* if needed, schedule a halt event. FIXME - In the future this
+ will be replaced by a more generic change to psim_command(). A
+ new command `schedule NNN halt' being added. */
+ if (tree_find_property(system->devices, "/openprom/options/max-iterations")) {
+ event_queue_schedule(system->events,
+ tree_find_integer_property(system->devices,
+ "/openprom/options/max-iterations") - 2,
+ psim_max_iterations_exceeded,
+ system);
+ }
+
/* scrub all the cpus */
for (cpu_nr = 0; cpu_nr < system->nr_cpus; cpu_nr++)
cpu_init(system->processors[cpu_nr]);
/* init all the devices (which updates the cpus) */
- device_tree_init(system->devices, system);
+ tree_init(system->devices, system);
+
+ /* and the emulation (which needs an initialized device tree) */
+ os_emul_init(system->os_emulation, system->nr_cpus);
/* now sync each cpu against the initialized state of its registers */
for (cpu_nr = 0; cpu_nr < system->nr_cpus; cpu_nr++) {
- cpu_synchronize_context(system->processors[cpu_nr]);
- cpu_page_tlb_invalidate_all(system->processors[cpu_nr]);
+ cpu *processor = system->processors[cpu_nr];
+ cpu_synchronize_context(processor, cpu_get_program_counter(processor));
+ cpu_page_tlb_invalidate_all(processor);
}
- /* force loop to restart */
- system->last_cpu = system->nr_cpus - 1;
+ /* force loop to start with first cpu */
+ system->last_cpu = -1;
}
INLINE_PSIM\
@@ -482,15 +632,15 @@ psim_stack(psim *system,
{
/* pass the stack device the argv/envp and let it work out what to
do with it */
- device *stack_device = device_tree_find_device(system->devices,
- "/openprom/init/stack");
+ device *stack_device = tree_find_device(system->devices,
+ "/openprom/init/stack");
if (stack_device != (device*)0) {
unsigned_word stack_pointer;
psim_read_register(system, 0, &stack_pointer, "sp", cooked_transfer);
device_ioctl(stack_device,
- system,
NULL, /*cpu*/
0, /*cia*/
+ device_ioctl_create_stack,
stack_pointer,
argv,
envp);
@@ -499,219 +649,6 @@ psim_stack(psim *system,
-/* EXECUTE REAL CODE:
-
- Unfortunatly, there are multiple cases to consider vis:
-
- <icache> X <smp> X <events> X <keep-running-flag> X ...
-
- Consequently this function is written in multiple different ways */
-
-STATIC_INLINE_PSIM\
-(void)
-run_until_stop(psim *system,
- volatile int *keep_running)
-{
- jmp_buf halt;
- jmp_buf restart;
-#if WITH_IDECODE_CACHE_SIZE
- int cpu_nr;
- for (cpu_nr = 0; cpu_nr < system->nr_cpus; cpu_nr++)
- cpu_flush_icache(system->processors[cpu_nr]);
-#endif
- psim_set_halt_and_restart(system, &halt, &restart);
-
-#if (!WITH_IDECODE_CACHE_SIZE && WITH_SMP == 0)
-
- /* CASE 1: No instruction cache and no SMP.
-
- In this case, we can take advantage of the fact that the current
- instruction address does not need to be returned to the cpu
- object after every execution of an instruction. Instead it only
- needs to be saved when either A. the main loop exits or B. a
- cpu-{halt,restart} call forces the loop to be re-entered. The
- later functions always save the current cpu instruction
- address. */
-
- if (!setjmp(halt)) {
- do {
- if (!setjmp(restart)) {
- cpu *const processor = system->processors[0];
- unsigned_word cia = cpu_get_program_counter(processor);
- do {
- if (WITH_EVENTS) {
- if (event_queue_tick(system->events)) {
- cpu_set_program_counter(processor, cia);
- event_queue_process(system->events);
- cia = cpu_get_program_counter(processor);
- }
- }
- {
- instruction_word const instruction
- = vm_instruction_map_read(cpu_instruction_map(processor),
- processor, cia);
- cia = idecode_issue(processor, instruction, cia);
- }
- } while (keep_running == NULL || *keep_running);
- cpu_set_program_counter(processor, cia);
- }
- } while(keep_running == NULL || *keep_running);
- }
-#endif
-
-
-#if (WITH_IDECODE_CACHE_SIZE && WITH_SMP == 0)
-
- /* CASE 2: Instruction case but no SMP
-
- Here, the additional complexity comes from there being two
- different cache implementations. A simple function address cache
- or a full cracked instruction cache */
-
- if (!setjmp(halt)) {
- do {
- if (!setjmp(restart)) {
- cpu *const processor = system->processors[0];
- unsigned_word cia = cpu_get_program_counter(processor);
- do {
- if (WITH_EVENTS)
- if (event_queue_tick(system->events)) {
- cpu_set_program_counter(processor, cia);
- event_queue_process(system->events);
- cia = cpu_get_program_counter(processor);
- }
- {
- idecode_cache *const cache_entry = cpu_icache_entry(processor,
- cia);
- if (cache_entry->address == cia) {
- idecode_semantic *const semantic = cache_entry->semantic;
- cia = semantic(processor, cache_entry, cia);
- }
- else {
- instruction_word const instruction
- = vm_instruction_map_read(cpu_instruction_map(processor),
- processor,
- cia);
- idecode_semantic *const semantic = idecode(processor,
- instruction,
- cia,
- cache_entry);
-
- if (WITH_MON != 0)
- mon_event(mon_event_icache_miss, processor, cia);
- cache_entry->address = cia;
- cache_entry->semantic = semantic;
- cia = semantic(processor, cache_entry, cia);
- }
- }
- } while (keep_running == NULL || *keep_running);
- cpu_set_program_counter(processor, cia);
- }
- } while(keep_running == NULL || *keep_running);
- }
-#endif
-
-
-#if (!WITH_IDECODE_CACHE_SIZE && WITH_SMP > 0)
-
- /* CASE 3: No ICACHE but SMP
-
- The complexity here comes from needing to correctly restart the
- system when it is aborted. In particular if cpu0 requests a
- restart, the next cpu is still cpu1. Cpu0 being restarted after
- all the other CPU's and the event queue have been processed */
-
- if (!setjmp(halt)) {
- int first_cpu = setjmp(restart);
- if (first_cpu == 0)
- first_cpu = system->last_cpu + 1;
- do {
- int current_cpu;
- for (current_cpu = first_cpu, first_cpu = 0;
- current_cpu < system->nr_cpus + (WITH_EVENTS ? 1 : 0);
- current_cpu++) {
- if (WITH_EVENTS && current_cpu == system->nr_cpus) {
- if (event_queue_tick(system->events))
- event_queue_process(system->events);
- }
- else {
- cpu *const processor = system->processors[current_cpu];
- unsigned_word const cia = cpu_get_program_counter(processor);
- instruction_word instruction =
- vm_instruction_map_read(cpu_instruction_map(processor),
- processor,
- cia);
- cpu_set_program_counter(processor,
- idecode_issue(processor, instruction, cia));
- }
- if (!(keep_running == NULL || *keep_running)) {
- system->last_cpu = current_cpu;
- break;
- }
- }
- } while (keep_running == NULL || *keep_running);
- }
-#endif
-
-#if (WITH_IDECODE_CACHE_SIZE && WITH_SMP > 0)
-
- /* CASE 4: ICACHE and SMP ...
-
- This time, everything goes wrong. Need to restart loops
- correctly, need to save the program counter and finally need to
- keep track of each processors current address! */
-
- if (!setjmp(halt)) {
- int first_cpu = setjmp(restart);
- if (!first_cpu)
- first_cpu = system->last_cpu + 1;
- do {
- int current_cpu;
- for (current_cpu = first_cpu, first_cpu = 0;
- current_cpu < system->nr_cpus + (WITH_EVENTS ? 1 : 0);
- current_cpu++) {
- if (WITH_EVENTS && current_cpu == system->nr_cpus) {
- if (event_queue_tick(system->events))
- event_queue_process(system->events);
- }
- else {
- cpu *processor = system->processors[current_cpu];
- unsigned_word const cia = cpu_get_program_counter(processor);
- idecode_cache *cache_entry = cpu_icache_entry(processor, cia);
- if (cache_entry->address == cia) {
- idecode_semantic *semantic = cache_entry->semantic;
- cpu_set_program_counter(processor,
- semantic(processor, cache_entry, cia));
- }
- else {
- instruction_word instruction =
- vm_instruction_map_read(cpu_instruction_map(processor),
- processor,
- cia);
- idecode_semantic *semantic = idecode(processor,
- instruction,
- cia,
- cache_entry);
-
- if (WITH_MON != 0)
- mon_event(mon_event_icache_miss, system->processors[current_cpu], cia);
- cache_entry->address = cia;
- cache_entry->semantic = semantic;
- cpu_set_program_counter(processor,
- semantic(processor, cache_entry, cia));
- }
- }
- if (!(keep_running == NULL || *keep_running))
- break;
- }
- } while (keep_running == NULL || *keep_running);
- }
-#endif
-
- psim_clear_halt_and_restart(system);
-}
-
-
/* SIMULATE INSTRUCTIONS, various different ways of achieving the same
thing */
@@ -720,14 +657,16 @@ INLINE_PSIM\
psim_step(psim *system)
{
volatile int keep_running = 0;
- run_until_stop(system, &keep_running);
+ idecode_run_until_stop(system, &keep_running,
+ system->events, system->processors, system->nr_cpus);
}
INLINE_PSIM\
(void)
psim_run(psim *system)
{
- run_until_stop(system, NULL);
+ idecode_run(system,
+ system->events, system->processors, system->nr_cpus);
}
INLINE_PSIM\
@@ -735,7 +674,8 @@ INLINE_PSIM\
psim_run_until_stop(psim *system,
volatile int *keep_running)
{
- run_until_stop(system, keep_running);
+ idecode_run_until_stop(system, keep_running,
+ system->events, system->processors, system->nr_cpus);
}
@@ -751,14 +691,19 @@ psim_read_register(psim *system,
transfer_mode mode)
{
register_descriptions description;
- char cooked_buf[sizeof(natural_word)];
+ char cooked_buf[sizeof(unsigned_8)];
cpu *processor;
/* find our processor */
- if (which_cpu == MAX_NR_PROCESSORS)
- which_cpu = system->last_cpu;
- if (which_cpu < 0 || which_cpu >= system->nr_cpus)
- error("psim_read_register() - invalid processor %d\n", which_cpu);
+ if (which_cpu == MAX_NR_PROCESSORS) {
+ if (system->last_cpu == system->nr_cpus
+ || system->last_cpu == -1)
+ which_cpu = 0;
+ else
+ which_cpu = system->last_cpu;
+ }
+ ASSERT(which_cpu >= 0 && which_cpu < system->nr_cpus);
+
processor = system->processors[which_cpu];
/* find the register description */
@@ -797,6 +742,23 @@ psim_read_register(psim *system,
*(msreg*)cooked_buf = cpu_registers(processor)->msr;
break;
+ case reg_insns:
+ *(unsigned_word*)cooked_buf = mon_get_number_of_insns(system->monitor,
+ which_cpu);
+ break;
+
+ case reg_stalls:
+ if (cpu_model(processor) == NULL)
+ error("$stalls only valid if processor unit model enabled (-I)\n");
+ *(unsigned_word*)cooked_buf = model_get_number_of_stalls(cpu_model(processor));
+ break;
+
+ case reg_cycles:
+ if (cpu_model(processor) == NULL)
+ error("$cycles only valid if processor unit model enabled (-I)\n");
+ *(unsigned_word*)cooked_buf = model_get_number_of_cycles(cpu_model(processor));
+ break;
+
default:
printf_filtered("psim_read_register(processor=0x%lx,buf=0x%lx,reg=%s) %s\n",
(unsigned long)processor, (unsigned long)buf, reg,
@@ -842,20 +804,23 @@ psim_write_register(psim *system,
{
cpu *processor;
register_descriptions description;
- char cooked_buf[sizeof(natural_word)];
+ char cooked_buf[sizeof(unsigned_8)];
/* find our processor */
- if (which_cpu == MAX_NR_PROCESSORS)
- which_cpu = system->last_cpu;
+ if (which_cpu == MAX_NR_PROCESSORS) {
+ if (system->last_cpu == system->nr_cpus
+ || system->last_cpu == -1)
+ which_cpu = 0;
+ else
+ which_cpu = system->last_cpu;
+ }
if (which_cpu == -1) {
int i;
for (i = 0; i < system->nr_cpus; i++)
psim_write_register(system, i, buf, reg, mode);
return;
}
- else if (which_cpu < 0 || which_cpu >= system->nr_cpus) {
- error("psim_read_register() - invalid processor %d\n", which_cpu);
- }
+ ASSERT(which_cpu >= 0 && which_cpu < system->nr_cpus);
processor = system->processors[which_cpu];
@@ -938,13 +903,17 @@ psim_read_memory(psim *system,
unsigned nr_bytes)
{
cpu *processor;
- if (which_cpu == MAX_NR_PROCESSORS)
- which_cpu = system->last_cpu;
- if (which_cpu < 0 || which_cpu >= system->nr_cpus)
- error("psim_read_memory() invalid cpu\n");
+ if (which_cpu == MAX_NR_PROCESSORS) {
+ if (system->last_cpu == system->nr_cpus
+ || system->last_cpu == -1)
+ which_cpu = 0;
+ else
+ which_cpu = system->last_cpu;
+ }
processor = system->processors[which_cpu];
return vm_data_map_read_buffer(cpu_data_map(processor),
- buffer, vaddr, nr_bytes);
+ buffer, vaddr, nr_bytes,
+ NULL, -1);
}
@@ -958,13 +927,18 @@ psim_write_memory(psim *system,
int violate_read_only_section)
{
cpu *processor;
- if (which_cpu == MAX_NR_PROCESSORS)
- which_cpu = system->last_cpu;
- if (which_cpu < 0 || which_cpu >= system->nr_cpus)
- error("psim_read_memory() invalid cpu\n");
+ if (which_cpu == MAX_NR_PROCESSORS) {
+ if (system->last_cpu == system->nr_cpus
+ || system->last_cpu == -1)
+ which_cpu = 0;
+ else
+ which_cpu = system->last_cpu;
+ }
+ ASSERT(which_cpu >= 0 && which_cpu < system->nr_cpus);
processor = system->processors[which_cpu];
return vm_data_map_write_buffer(cpu_data_map(processor),
- buffer, vaddr, nr_bytes, 1);
+ buffer, vaddr, nr_bytes, 1/*violate-read-only*/,
+ NULL, -1);
}
@@ -984,20 +958,61 @@ INLINE_PSIM\
psim_merge_device_file(device *root,
const char *file_name)
{
- FILE *description = fopen(file_name, "r");
- int line_nr = 0;
+ FILE *description;
+ int line_nr;
char device_path[1000];
- device *current = root;
+ device *current;
+
+ /* try opening the file */
+ description = fopen(file_name, "r");
+ if (description == NULL) {
+ perror(file_name);
+ error("Invalid file %s specified", file_name);
+ }
+
+ line_nr = 0;
+ current = root;
while (fgets(device_path, sizeof(device_path), description)) {
- /* check all of line was read */
+ char *device;
+ /* check that the full line was read */
if (strchr(device_path, '\n') == NULL) {
fclose(description);
- error("create_filed_device_tree() line %d to long: %s\n",
- line_nr, device_path);
+ error("%s:%d: line to long - %s",
+ file_name, line_nr, device_path);
}
+ else
+ *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 \ */
+ device_path[curlen] = '\0';
+ /* append the next line */
+ if (!fgets(device_path + curlen, sizeof(device_path) - curlen, description)) {
+ fclose(description);
+ error("%s:%s: unexpected eof in line continuation - %s",
+ file_name, line_nr, device_path);
+ }
+ if (strchr(device_path, '\n') == NULL) {
+ fclose(description);
+ error("%s:%d: line to long - %s",
+ file_name, line_nr, device_path);
+ }
+ else
+ *strchr(device_path, '\n') = '\0';
+ line_nr++;
+ }
/* parse this line */
- current = device_tree_add_parsed(current, "%s", device_path);
+ current = tree_parse(current, "%s", device);
}
fclose(description);
}
diff --git a/gnu/dist/sim/ppc/psim.h b/gnu/dist/sim/ppc/psim.h
index 34a7eb2f328..63eb416afd5 100644
--- a/gnu/dist/sim/ppc/psim.h
+++ b/gnu/dist/sim/ppc/psim.h
@@ -42,7 +42,7 @@ typedef struct _psim_status {
/* create an initial device tree and then populate it using
- information obtained from the command line */
+ information obtained from either the command line or a file */
extern device *psim_tree
(void);
@@ -51,11 +51,20 @@ extern char **psim_options
(device *root,
char **argv);
+extern void psim_command
+(device *root,
+ char **argv);
+
+
+extern void psim_merge_device_file
+(device *root,
+ const char *file_name);
+
extern void psim_usage
(int verbose);
-/* create a new simulator */
+/* create a new simulator from the device tree */
extern psim *psim_create
(const char *file_name,
@@ -89,19 +98,33 @@ extern void psim_restart
(psim *system,
int cpu_nr);
+extern void psim_set_halt_and_restart
+(psim *system,
+ void *halt_jmp_buf,
+ void *restart_jmp_buf);
+
+extern void psim_clear_halt_and_restart
+(psim *system);
+
extern void psim_halt
(psim *system,
int cpu_nr,
- unsigned_word cia,
stop_reason reason,
int signal);
+extern int psim_last_cpu
+(psim *system);
+
+extern int psim_nr_cpus
+(psim *system);
+
+
extern psim_status psim_get_status
(psim *system);
-/* reveal the internals of the simulation, giving access to cpu's and
- devices */
+/* reveal the internals of the simulation. Grant access to the
+ processor (cpu) device tree (device) and events (event_queue). */
extern cpu *psim_cpu
(psim *system,
@@ -111,6 +134,10 @@ extern device *psim_device
(psim *system,
const char *path);
+extern event_queue *psim_event_queue
+(psim *system);
+
+
/* manipulate the state (registers or memory) of a processor within
the system. In the case of memory, the read/write is performed
@@ -152,9 +179,4 @@ extern void psim_print_info
(psim *system,
int verbose);
-/* FIXME: I do not want this here */
-extern void psim_merge_device_file
-(device *root,
- const char *file_name);
-
#endif /* _PSIM_H_ */
diff --git a/gnu/dist/sim/ppc/psim.texinfo b/gnu/dist/sim/ppc/psim.texinfo
new file mode 100644
index 00000000000..f81e46099c4
--- /dev/null
+++ b/gnu/dist/sim/ppc/psim.texinfo
@@ -0,0 +1,1105 @@
+\input texinfo.tex @c -*-texinfo-*-
+@comment %**start of header
+@setfilename texinfo
+@settitle Texinfo @value{edition}
+@syncodeindex vr fn
+@footnotestyle separate
+@paragraphindent 2
+@smallbook
+@comment %**end of header
+
+@c Set smallbook if printing in smallbook format so the example of the
+@c smallbook font is actually written using smallbook; in bigbook, a kludge
+@c is used for TeX output.
+@set smallbook
+@c @@clear smallbook
+
+@ignore
+@ifinfo
+@format
+START-INFO-DIR-ENTRY
+* Texinfo: (texinfo). The documentation format for the GNU Project.
+END-INFO-DIR-ENTRY
+@end format
+@end ifinfo
+@end ignore
+
+@set edition 2.21
+@set update-date 7 June 1995
+@set update-month June 1995
+
+@c Experiment with smaller amounts of whitespace between chapters
+@c and sections.
+@tex
+\global\chapheadingskip = 15pt plus 4pt minus 2pt
+\global\secheadingskip = 12pt plus 3pt minus 2pt
+\global\subsecheadingskip = 9pt plus 2pt minus 2pt
+@end tex
+
+@c Experiment with smaller amounts of whitespace between paragraphs in
+@c the 8.5 by 11 inch format.
+@ifclear smallbook
+@tex
+\global\parskip 6pt plus 1pt
+@end tex
+@end ifclear
+
+@finalout
+
+@c Currently undocumented command, 5 December 1993:
+@c
+@c nwnode (Same as node, but no warnings; for `makeinfo'.)
+
+@ifinfo
+This file documents Texinfo, a documentation system that uses a single
+source file to produce both on-line information and a printed manual.
+
+Copyright (C) 1988, 1990, 1991, 1992, 1993, 1995 Free Software Foundation, Inc.
+
+This is the second edition of the Texinfo documentation,@*
+and is consistent with version 2 of @file{texinfo.tex}.
+
+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.
+
+@ignore
+Permission is granted to process this file through TeX and print the
+results, provided the printed document carries copying permission
+notice identical to this one except for the removal of this paragraph
+(this paragraph not being relevant to the printed manual).
+
+@end ignore
+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.
+
+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 stated in a translation approved
+by the Free Software Foundation.
+@end ifinfo
+
+@setchapternewpage odd
+
+@shorttitlepage Texinfo
+
+@titlepage
+@c use the new format for titles
+@title Texinfo
+@subtitle The GNU Documentation Format
+@subtitle Edition @value{edition}, for Texinfo Version Three
+@subtitle @value{update-month}
+
+@author by Robert J. Chassell and Richard M. Stallman
+
+@comment Include the Distribution inside the titlepage so
+@c that headings are turned off.
+
+@page
+@vskip 0pt plus 1filll
+Copyright @copyright{} 1988, 1990, 1991, 1992, 1993, 1995 Free Software Foundation, Inc.
+
+@sp 2
+This is the second edition of the Texinfo documentation,@*
+and is consistent with version 2 of @file{texinfo.tex}.
+@sp 2
+
+Published by the Free Software Foundation @*
+59 Temple Place Suite 330, @*
+Boston, MA 02111-1307 USA @*
+Printed copies are available for $15 each.@*
+ISBN 1-882114-63-9
+@c ISBN number 1-882114-63-9 is for edition 2.20 of 28 February 1995
+
+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.
+
+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.
+
+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 stated in a translation approved
+by the Free Software Foundation.
+@sp 2
+Cover art by Etienne Suvasa.
+@end titlepage
+
+@ifinfo
+@node Top, Copying, (dir), (dir)
+@top Texinfo
+
+Texinfo is a documentation system that uses a single source file to
+produce both on-line information and printed output.@refill
+
+The first part of this master menu lists the major nodes in this Info
+document, including the @@-command and concept indices. The rest of
+the menu lists all the lower level nodes in the document.@refill
+
+This is Edition @value{edition} of the Texinfo documentation,
+@w{@value{update-date},} for Texinfo Version Three.
+@end ifinfo
+
+@c Here is a spare copy of the chapter menu entry descriptions,
+@c in case they are accidently deleted
+@ignore
+Your rights.
+Texinfo in brief.
+How to use Texinfo mode.
+What is at the beginning of a Texinfo file?
+What is at the end of a Texinfo file?
+How to create chapters, sections, subsections,
+ appendices, and other parts.
+How to provide structure for a document.
+How to write nodes.
+How to write menus.
+How to write cross references.
+How to mark words and phrases as code,
+ keyboard input, meta-syntactic
+ variables, and the like.
+How to write quotations, examples, etc.
+How to write lists and tables.
+How to create indices.
+How to insert @@-signs, braces, etc.
+How to indicate results of evaluation,
+ expansion of macros, errors, etc.
+How to force and prevent line and page breaks.
+How to describe functions and the like in a uniform manner.
+How to write footnotes.
+How to specify text for either @TeX{} or Info.
+How to print hardcopy.
+How to create an Info file.
+How to install an Info file
+A list of all the Texinfo @@-commands.
+Hints on how to write a Texinfo document.
+A sample Texinfo file to look at.
+Tell readers they have the right to copy
+ and distribute.
+How to incorporate other Texinfo files.
+How to write page headings and footings.
+How to find formatting mistakes.
+All about paragraph refilling.
+A description of @@-Command syntax.
+Texinfo second edition features.
+A menu containing commands and variables.
+A menu covering many topics.
+@end ignore
+
+@menu
+* Copying:: Your rights.
+* Overview:: Texinfo in brief.
+* Texinfo Mode:: How to use Texinfo mode.
+* Beginning a File:: What is at the beginning of a Texinfo file?
+* Ending a File:: What is at the end of a Texinfo file?
+* Structuring:: How to create chapters, sections, subsections,
+ appendices, and other parts.
+* Nodes:: How to write nodes.
+* Menus:: How to write menus.
+* Cross References:: How to write cross references.
+* Marking Text:: How to mark words and phrases as code,
+ keyboard input, meta-syntactic
+ variables, and the like.
+* Quotations and Examples:: How to write quotations, examples, etc.
+* Lists and Tables:: How to write lists and tables.
+* Indices:: How to create indices.
+* Insertions:: How to insert @@-signs, braces, etc.
+* Glyphs:: How to indicate results of evaluation,
+ expansion of macros, errors, etc.
+* Breaks:: How to force and prevent line and page breaks.
+* Definition Commands:: How to describe functions and the like
+ in a uniform manner.
+* Footnotes:: How to write footnotes.
+* Conditionals:: How to specify text for either @TeX{} or Info.
+* Format/Print Hardcopy:: How to convert a Texinfo file to a file
+ for printing and how to print that file.
+* Create an Info File:: Convert a Texinfo file into an Info file.
+* Install an Info File:: Make an Info file accessible to users.
+* Command List:: All the Texinfo @@-commands.
+* Tips:: Hints on how to write a Texinfo document.
+* Sample Texinfo File:: A sample Texinfo file to look at.
+* Sample Permissions:: Tell readers they have the right to copy
+ and distribute.
+* Include Files:: How to incorporate other Texinfo files.
+* Headings:: How to write page headings and footings.
+* Catching Mistakes:: How to find formatting mistakes.
+* Refilling Paragraphs:: All about paragraph refilling.
+* Command Syntax:: A description of @@-Command syntax.
+* Obtaining TeX:: How to Obtain @TeX{}.
+* New Features:: Texinfo second edition features.
+* Command and Variable Index:: A menu containing commands and variables.
+* Concept Index:: A menu covering many topics.
+
+ --- The Detailed Node Listing ---
+
+Overview of Texinfo
+
+* Using Texinfo:: Create a conventional printed book
+ or an Info file.
+* Info Files:: What is an Info file?
+* Printed Books:: Characteristics of a printed book or manual.
+* Formatting Commands:: @@-commands are used for formatting.
+* Conventions:: General rules for writing a Texinfo file.
+* Comments:: How to write comments and mark regions that
+ the formatting commands will ignore.
+* Minimum:: What a Texinfo file must have.
+* Six Parts:: Usually, a Texinfo file has six parts.
+* Short Sample:: A short sample Texinfo file.
+* Acknowledgements::
+
+Using Texinfo Mode
+
+* Texinfo Mode Overview:: How Texinfo mode can help you.
+* Emacs Editing:: Texinfo mode adds to GNU Emacs' general
+ purpose editing features.
+* Inserting:: How to insert frequently used @@-commands.
+* Showing the Structure:: How to show the structure of a file.
+* Updating Nodes and Menus:: How to update or create new nodes and menus.
+* Info Formatting:: How to format for Info.
+* Printing:: How to format and print part or all of a file.
+* Texinfo Mode Summary:: Summary of all the Texinfo mode commands.
+
+Updating Nodes and Menus
+
+* Updating Commands:: Five major updating commands.
+* Updating Requirements:: How to structure a Texinfo file for
+ using the updating command.
+* Other Updating Commands:: How to indent descriptions, insert
+ missing nodes lines, and update
+ nodes in sequence.
+
+Beginning a Texinfo File
+
+* Four Parts:: Four parts begin a Texinfo file.
+* Sample Beginning:: Here is a sample beginning for a Texinfo file.
+* Header:: The very beginning of a Texinfo file.
+* Info Summary and Permissions:: Summary and copying permissions for Info.
+* Titlepage & Copyright Page:: Creating the title and copyright pages.
+* The Top Node:: Creating the `Top' node and master menu.
+* Software Copying Permissions:: Ensure that you and others continue to
+ have the right to use and share software.
+
+The Texinfo File Header
+
+* First Line:: The first line of a Texinfo file.
+* Start of Header:: Formatting a region requires this.
+* setfilename:: Tell Info the name of the Info file.
+* settitle:: Create a title for the printed work.
+* setchapternewpage:: Start chapters on right-hand pages.
+* paragraphindent:: An option to specify paragraph indentation.
+* End of Header:: Formatting a region requires this.
+
+The Title and Copyright Pages
+
+* titlepage:: Create a title for the printed document.
+* titlefont center sp:: The @code{@@titlefont}, @code{@@center},
+ and @code{@@sp} commands.
+* title subtitle author:: The @code{@@title}, @code{@@subtitle},
+ and @code{@@author} commands.
+* Copyright & Permissions:: How to write the copyright notice and
+ include copying permissions.
+* end titlepage:: Turn on page headings after the title and
+ copyright pages.
+* headings on off:: An option for turning headings on and off
+ and double or single sided printing.
+
+The `Top' Node and Master Menu
+
+* Title of Top Node:: Sketch what the file is about.
+* Master Menu Parts:: A master menu has three or more parts.
+
+Ending a Texinfo File
+
+* Printing Indices & Menus:: How to print an index in hardcopy and
+ generate index menus in Info.
+* Contents:: How to create a table of contents.
+* File End:: How to mark the end of a file.
+
+Chapter Structuring
+
+* Tree Structuring:: A manual is like an upside down tree @dots{}
+* Structuring Command Types:: How to divide a manual into parts.
+* makeinfo top:: The @code{@@top} command, part of the `Top' node.
+* chapter::
+* unnumbered & appendix::
+* majorheading & chapheading::
+* section::
+* unnumberedsec appendixsec heading::
+* subsection::
+* unnumberedsubsec appendixsubsec subheading::
+* subsubsection:: Commands for the lowest level sections.
+* Raise/lower sections:: How to change commands' hierarchical level.
+
+Nodes
+
+* Two Paths:: Different commands to structure
+ Info output and printed output.
+* Node Menu Illustration:: A diagram, and sample nodes and menus.
+* node:: How to write a node, in detail.
+* makeinfo Pointer Creation:: How to create node pointers with @code{makeinfo}.
+
+The @code{@@node} Command
+
+* Node Names:: How to choose node and pointer names.
+* Writing a Node:: How to write an @code{@@node} line.
+* Node Line Tips:: Keep names short.
+* Node Line Requirements:: Keep names unique, without @@-commands.
+* First Node:: How to write a `Top' node.
+* makeinfo top command:: How to use the @code{@@top} command.
+* Top Node Summary:: Write a brief description for readers.
+
+Menus
+
+* Menu Location:: Put a menu in a short node.
+* Writing a Menu:: What is a menu?
+* Menu Parts:: A menu entry has three parts.
+* Less Cluttered Menu Entry:: Two part menu entry.
+* Menu Example:: Two and three part menu entries.
+* Other Info Files:: How to refer to a different Info file.
+
+Cross References
+
+* References:: What cross references are for.
+* Cross Reference Commands:: A summary of the different commands.
+* Cross Reference Parts:: A cross reference has several parts.
+* xref:: Begin a reference with `See' @dots{}
+* Top Node Naming:: How to refer to the beginning of another file.
+* ref:: A reference for the last part of a sentence.
+* pxref:: How to write a parenthetical cross reference.
+* inforef:: How to refer to an Info-only file.
+
+@code{@@xref}
+
+* Reference Syntax:: What a reference looks like and requires.
+* One Argument:: @code{@@xref} with one argument.
+* Two Arguments:: @code{@@xref} with two arguments.
+* Three Arguments:: @code{@@xref} with three arguments.
+* Four and Five Arguments:: @code{@@xref} with four and five arguments.
+
+Marking Words and Phrases
+
+* Indicating:: How to indicate definitions, files, etc.
+* Emphasis:: How to emphasize text.
+
+Indicating Definitions, Commands, etc.
+
+* Useful Highlighting:: Highlighting provides useful information.
+* code:: How to indicate code.
+* kbd:: How to show keyboard input.
+* key:: How to specify keys.
+* samp:: How to show a literal sequence of characters.
+* var:: How to indicate a metasyntactic variable.
+* file:: How to indicate the name of a file.
+* dfn:: How to specify a definition.
+* cite:: How to refer to a book that is not in Info.
+
+Emphasizing Text
+
+* emph & strong:: How to emphasize text in Texinfo.
+* Smallcaps:: How to use the small caps font.
+* Fonts:: Various font commands for printed output.
+* Customized Highlighting:: How to define highlighting commands.
+
+Quotations and Examples
+
+* Block Enclosing Commands:: Use different constructs for
+ different purposes.
+* quotation:: How to write a quotation.
+* example:: How to write an example in a fixed-width font.
+* noindent:: How to prevent paragraph indentation.
+* Lisp Example:: How to illustrate Lisp code.
+* smallexample & smalllisp:: Forms for the @code{@@smallbook} option.
+* display:: How to write an example in the current font.
+* format:: How to write an example that does not narrow
+ the margins.
+* exdent:: How to undo the indentation of a line.
+* flushleft & flushright:: How to push text flushleft or flushright.
+* cartouche:: How to draw cartouches around examples.
+
+Making Lists and Tables
+
+* Introducing Lists:: Texinfo formats lists for you.
+* itemize:: How to construct a simple list.
+* enumerate:: How to construct a numbered list.
+* Two-column Tables:: How to construct a two-column table.
+
+Making a Two-column Table
+
+* table:: How to construct a two-column table.
+* ftable vtable:: How to construct a two-column table
+ with automatic indexing.
+* itemx:: How to put more entries in the first column.
+
+Creating Indices
+
+* Index Entries:: Choose different words for index entries.
+* Predefined Indices:: Use different indices for different kinds
+ of entry.
+* Indexing Commands:: How to make an index entry.
+* Combining Indices:: How to combine indices.
+* New Indices:: How to define your own indices.
+
+Combining Indices
+
+* syncodeindex:: How to merge two indices, using @code{@@code}
+ font for the merged-from index.
+* synindex:: How to merge two indices, using the
+ default font of the merged-to index.
+
+Special Insertions
+
+* Braces Atsigns Periods:: How to insert braces, @samp{@@} and periods.
+* dmn:: How to format a dimension.
+* Dots Bullets:: How to insert dots and bullets.
+* TeX and copyright:: How to insert the @TeX{} logo
+ and the copyright symbol.
+* minus:: How to insert a minus sign.
+* math:: How to format a mathematical expression.
+
+Inserting @samp{@@}, Braces, and Periods
+
+* Inserting An Atsign::
+* Inserting Braces:: How to insert @samp{@{} and @samp{@}}
+* Controlling Spacing:: How to insert the right amount of space
+ after punctuation within a sentence.
+
+Inserting Ellipsis, Dots, and Bullets
+
+* dots:: How to insert dots @dots{}
+* bullet:: How to insert a bullet.
+
+Inserting @TeX{} and the Copyright Symbol
+
+* tex:: How to insert the @TeX{} logo.
+* copyright symbol:: How to use @code{@@copyright}@{@}.
+
+Glyphs for Examples
+
+* Glyphs Summary::
+* result:: How to show the result of expression.
+* expansion:: How to indicate an expansion.
+* Print Glyph:: How to indicate printed output.
+* Error Glyph:: How to indicate an error message.
+* Equivalence:: How to indicate equivalence.
+* Point Glyph:: How to indicate the location of point.
+
+Making and Preventing Breaks
+
+* Break Commands:: Cause and prevent splits.
+* Line Breaks:: How to force a single line to use two lines.
+* w:: How to prevent unwanted line breaks.
+* sp:: How to insert blank lines.
+* page:: How to force the start of a new page.
+* group:: How to prevent unwanted page breaks.
+* need:: Another way to prevent unwanted page breaks.
+
+Definition Commands
+
+* Def Cmd Template:: How to structure a description using a
+ definition command.
+* Optional Arguments:: How to handle optional and repeated arguments.
+* deffnx:: How to group two or more `first' lines.
+* Def Cmds in Detail:: All the definition commands.
+* Def Cmd Conventions:: Conventions for writing definitions.
+* Sample Function Definition::
+
+The Definition Commands
+
+* Functions Commands:: Commands for functions and similar entities.
+* Variables Commands:: Commands for variables and similar entities.
+* Typed Functions:: Commands for functions in typed languages.
+* Typed Variables:: Commands for variables in typed languages.
+* Abstract Objects:: Commands for object-oriented programming.
+* Data Types:: The definition command for data types.
+
+Footnotes
+
+* Footnote Commands:: How to write a footnote in Texinfo.
+* Footnote Styles:: Controlling how footnotes appear in Info.
+
+Conditionally Visible Text
+
+* Conditional Commands:: How to specify text for Info or @TeX{}.
+* Using Ordinary TeX Commands:: You can use any and all @TeX{} commands.
+* set clear value:: How to designate which text to format (for
+ both Info and @TeX{}); and how to set a
+ flag to a string that you can insert.
+
+@code{@@set}, @code{@@clear}, and @code{@@value}
+
+* ifset ifclear:: Format a region if a flag is set.
+* value:: Replace a flag with a string.
+* value Example:: An easy way to update edition information.
+
+Format and Print Hardcopy
+
+* Use TeX:: Use @TeX{} to format for hardcopy.
+* Format with tex/texindex:: How to format in a shell.
+* Format with texi2dvi:: A simpler way to use the shell.
+* Print with lpr:: How to print.
+* Within Emacs:: How to format and print from an Emacs shell.
+* Texinfo Mode Printing:: How to format and print in Texinfo mode.
+* Compile-Command:: How to print using Emacs's compile command.
+* Requirements Summary:: @TeX{} formatting requirements summary.
+* Preparing for TeX:: What you need to do to use @TeX{}.
+* Overfull hboxes:: What are and what to do with overfull hboxes.
+* smallbook:: How to print small format books and manuals.
+* A4 Paper:: How to print on European A4 paper.
+* Cropmarks and Magnification:: How to print marks to indicate the size
+ of pages and how to print scaled up output.
+
+Creating an Info File
+
+* makeinfo advantages:: @code{makeinfo} provides better error checking.
+* Invoking makeinfo:: How to run @code{makeinfo} from a shell.
+* makeinfo options:: Specify fill-column and other options.
+* Pointer Validation:: How to check that pointers point somewhere.
+* makeinfo in Emacs:: How to run @code{makeinfo} from Emacs.
+* texinfo-format commands:: Two Info formatting commands written
+ in Emacs Lisp are an alternative
+ to @code{makeinfo}.
+* Batch Formatting:: How to format for Info in Emacs Batch mode.
+* Tag and Split Files:: How tagged and split files help Info
+ to run better.
+
+Installing an Info File
+
+* Directory file:: The top level menu for all Info files.
+* New Info File:: Listing a new info file.
+* Other Info Directories:: How to specify Info files that are
+ located in other directories.
+
+Sample Permissions
+
+* Inserting Permissions:: How to put permissions in your document.
+* ifinfo Permissions:: Sample @samp{ifinfo} copying permissions.
+* Titlepage Permissions:: Sample Titlepage copying permissions.
+
+Include Files
+
+* Using Include Files:: How to use the @code{@@include} command.
+* texinfo-multiple-files-update:: How to create and update nodes and
+ menus when using included files.
+* Include File Requirements:: What @code{texinfo-multiple-files-update} expects.
+* Sample Include File:: A sample outer file with included files
+ within it; and a sample included file.
+* Include Files Evolution:: How use of the @code{@@include} command
+ has changed over time.
+
+Page Headings
+
+* Headings Introduced:: Conventions for using page headings.
+* Heading Format:: Standard page heading formats.
+* Heading Choice:: How to specify the type of page heading.
+* Custom Headings:: How to create your own headings and footings.
+
+Formatting Mistakes
+
+* makeinfo preferred:: @code{makeinfo} finds errors.
+* Debugging with Info:: How to catch errors with Info formatting.
+* Debugging with TeX:: How to catch errors with @TeX{} formatting.
+* Using texinfo-show-structure:: How to use @code{texinfo-show-structure}.
+* Using occur:: How to list all lines containing a pattern.
+* Running Info-Validate:: How to find badly referenced nodes.
+
+Finding Badly Referenced Nodes
+
+* Using Info-validate:: How to run @code{Info-validate}.
+* Unsplit:: How to create an unsplit file.
+* Tagifying:: How to tagify a file.
+* Splitting:: How to split a file manually.
+
+Second Edition Features
+
+* New Texinfo Mode Commands:: The updating commands are especially useful.
+* New Commands:: Many newly described @@-commands.
+@end menu
+
+@node Copying, Overview, Top, Top
+@comment node-name, next, previous, up
+@unnumbered Texinfo Copying Conditions
+@cindex Copying conditions
+@cindex Conditions for copying Texinfo
+
+The programs currently being distributed that relate to Texinfo include
+portions of GNU Emacs, plus other separate programs (including
+@code{makeinfo}, @code{info}, @code{texindex}, and @file{texinfo.tex}).
+These programs are @dfn{free}; this means that everyone is free to use
+them and free to redistribute them on a free basis. The Texinfo-related
+programs are not in the public domain; they are copyrighted and there
+are restrictions on their distribution, but these restrictions are
+designed to permit everything that a good cooperating citizen would want
+to do. What is not allowed is to try to prevent others from further
+sharing any version of these programs that they might get from
+you.@refill
+
+ Specifically, we want to make sure that you have the right to give
+away copies of the programs that relate to Texinfo, that you receive
+source code or else can get it if you want it, that you can change these
+programs or use pieces of them in new free programs, and that you know
+you can do these things.@refill
+
+ To make sure that everyone has such rights, we have to forbid you to
+deprive anyone else of these rights. For example, if you distribute
+copies of the Texinfo related programs, you must give the recipients all
+the rights that you have. You must make sure that they, too, receive or
+can get the source code. And you must tell them their rights.@refill
+
+ Also, for our own protection, we must make certain that everyone finds
+out that there is no warranty for the programs that relate to Texinfo.
+If these programs are modified by someone else and passed on, we want
+their recipients to know that what they have is not what we distributed,
+so that any problems introduced by others will not reflect on our
+reputation.@refill
+
+ The precise conditions of the licenses for the programs currently
+being distributed that relate to Texinfo are found in the General Public
+Licenses that accompany them.@refill
+
+@node Overview, Texinfo Mode, Copying, Top
+@comment node-name, next, previous, up
+@chapter Overview of Texinfo
+@cindex Overview of Texinfo
+@cindex Texinfo overview
+
+@dfn{Texinfo}@footnote{Note that the first syllable of ``Texinfo'' is
+pronounced like ``speck'', not ``hex''. This odd pronunciation is
+derived from, but is not the same as, the pronunciation of @TeX{}. In
+the word @TeX{}, the @samp{X} is actually the Greek letter ``chi''
+rather than the English letter ``ex''. Pronounce @TeX{} as if the
+@samp{X} were the last sound in the name `Bach'; but pronounce Texinfo
+as if the @samp{x} were a `k'. Spell ``Texinfo'' with a capital ``T''
+and write the other letters in lower case.}
+is a documentation system that uses a single source file to produce both
+on-line information and printed output. This means that instead of
+writing two different documents, one for the on-line help or other on-line
+information and the other for a typeset manual or other printed work, you
+need write only one document. When the work is revised, you need revise
+only one document. (You can read the on-line information, known as an
+@dfn{Info file}, with an Info documentation-reading program.)@refill
+
+@menu
+* Using Texinfo:: Create a conventional printed book
+ or an Info file.
+* Info Files:: What is an Info file?
+* Printed Books:: Characteristics of a printed book or manual.
+* Formatting Commands:: @@-commands are used for formatting.
+* Conventions:: General rules for writing a Texinfo file.
+* Comments:: How to write comments and mark regions that
+ the formatting commands will ignore.
+* Minimum:: What a Texinfo file must have.
+* Six Parts:: Usually, a Texinfo file has six parts.
+* Short Sample:: A short sample Texinfo file.
+* Acknowledgements::
+@end menu
+
+@c ************************************************************************
+
+
+
+\input texinfo @c -*-texinfo-*-
+@c %**start of header
+@setfilename psim.info
+@settitle PSIM
+@setchapternewpage odd
+@c %**end of header
+
+
+
+@ifinfo
+This file documents the program PSIM.
+
+Copyright (C) 1994-1996, Andrew Cagney.
+
+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.
+
+@ignore
+Permission is granted to process this file through Tex and print the
+results, provided the printed document carries copying permission
+notice identical to this one except for the removal of this paragraph
+(this paragraph not being relevant to the printed manual).
+
+@end ignore
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, subject to the terms
+of the GNU General Public License, which includes the provision that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions.
+@end ifinfo
+
+
+@titlepage
+@title PSIM
+@subtitle Model of the PowerPC Environments
+@author Andrew Cagney
+
+@page
+@vskip Opt plus ifill
+Copyright @copyright{} 1994-1996, Andrew Cagney
+
+This is the first edition of the PSIM manual and is consistent with PSIM
+version 1.0.
+
+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.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, subject to the terms
+of the GNU General Public License, which includes the provision that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions.
+@end titlepage
+
+
+
+@menu
+
+* Copying:: Your rights and freedoms.
+* First Chappeter:: Getting started ....
+* Second Chapter:: Getting finished ....
+
+
+@end menu
+
+
+PSIM is a program written in extended ANSI-C that implements an
+instruction level simulation of the PowerPC environment. It is freely
+available in source code form under the terms of the GNU General
+Public License (version 2 or later).
+
+The PowerPC Architecture is described as having three levels of
+compliance:
+
+ UEA - User Environment Architecture
+ VEA - Virtual Environment Architecture
+ OEA - Operating Environment Architecture
+
+PSIM both implements all three levels of the PowerPC and includes (for
+each level) a corresponding simulated run-time environment.
+
+In addition, PSIM, to the execution unit level, models the performance
+of most of the current PowerPC implementations (contributed by Michael
+Meissner). This detailed performance monitoring (unlike many other
+simulators) resulting in only a relatively marginal reduction in the
+simulators performance.
+
+
+A description of how to build PSIM is contained in the file:
+
+ ftp://ftp.ci.com.au/pub/psim/INSTALL
+ or ftp://cambridge.cygnus.com/pub/psim/INSTALL
+
+while an overview of how to use PSIM is in:
+
+ ftp://ftp.ci.com.au/pub/psim/RUN
+or ftp://cambridge.cygnus.com/pub/psim/RUN
+
+This file is found in:
+
+ ftp://ftp.ci.com.au/pub/psim/README
+or ftp://cambridge.cygnus.com/pub/psim/README
+
+
+Thanks goes firstly to:
+
+ Corinthian Engineering Pty Ltd
+ Cygnus Support
+ Highland Logic Pty Ltd
+
+who provided the resources needed for making this software available
+on the Internet.
+
+More importantly I'd like to thank the following individuals who each
+contributed in their own unique way:
+
+ Allen Briggs, Bett Koch, David Edelsohn, Gordon Irlam,
+ Michael Meissner, Bob Mercier, Richard Perini, Dale Rahn,
+ Richard Stallman, Mitchele Walker
+
+
+ Andrew Cagney
+ Feb, 1995
+
+
+ ----------------------------------------------------------------------
+
+
+ What features does PSIM include?
+
+ Monitoring and modeling
+
+ PSIM includes (thanks to Michael Meissner)
+ a detailed model of most of the PowerPC
+ implementations to the functional unit level.
+
+
+ SMP
+
+ The PowerPC ISA defines SMP synchronizing instructions.
+ This simulator implements a limited, but functional,
+ subset of the PowerPC synchronization instructions
+ behaviour. Programs that restrict their synchronization
+ primitives to those that work with this functional
+ sub-set (eg P() and V()) are able to run on the SMP
+ version of PSIM.
+
+ People intending to use this system should study
+ the code implementing the lwarx instruction.
+
+ ENDIAN SUPPORT
+
+ PSIM implements the PowerPC's big and little (xor
+ endian) modes and correctly simulates code that
+ switches between these two modes.
+
+ In addition, psim can model a true little-endian
+ machine.
+
+ ISA (Instruction Set Architecture) models
+
+ PSIM includes a model of the UEA, VEA and OEA. This
+ includes the time base registers (VEA) and HTAB
+ and BATS (OEA).
+
+ In addition, a preliminary model of the 64 bit
+ PowerPC architecture is implemented.
+
+ IO Hardware
+
+ PSIM's internals are based around the concept
+ of a Device Tree. This tree intentionally
+ resembles that of the Device Tree found in
+ OpenBoot firmware. PSIM is flexible enough
+ to allow the user to fully configure this device
+ tree (and consequently the hardware model) at
+ run time.
+
+ Run-time environments:
+
+ PSIM's UEA model includes emulation for BSD
+ based UNIX system calls.
+
+ PSIM's OEA model includes emulation of either:
+
+ o OpenBoot client interface
+
+ o MOTO's BUG interface.
+
+
+ Floating point
+
+ Preliminary support for floating point is included.
+
+
+ Who would be interested in PSIM?
+
+ o the curious
+
+ Using psim, gdb, gcc and binutils the curious
+ user can construct an environment that allows
+ them to play with PowerPC Environment without
+ the need for real hardware.
+
+
+ o the analyst
+
+ PSIM includes many (contributed) monitoring
+ features which (unlike many other simulators)
+ do not come with a great penalty in performance.
+
+ Thus the performance analyst is able to use
+ this simulator to analyse the performance of
+ the system under test.
+
+ If PSIM doesn't monitor a components of interest,
+ the source code is freely available, and hence
+ there is no hinderance to changing things
+ to meet a specific analysts needs.
+
+
+ o the serious SW developer
+
+ PSIM models all three levels of the PowerPC
+ Architecture: UEA, VEA and OEA. Further,
+ the internal design is such that PSIM can
+ be extended to support additional requirements.
+
+
+ What performance analysis measurements can PSIM perform?
+
+ Below is the output from a recent analysis run
+ (contributed by Michael Meissner):
+
+ For the following program:
+
+ long
+ simple_rand ()
+ {
+ static unsigned long seed = 47114711;
+ unsigned long this = seed * 1103515245 + 12345;
+ seed = this;
+ /* cut-cut-cut - see the file RUN.psim */
+ }
+
+ Here is the current output generated with the -I switch on a P90
+ (the compiler used is the development version of GCC with a new
+ scheduler replacing the old one):
+
+ CPU #1 executed 41,994 AND instructions.
+ CPU #1 executed 519,785 AND Immediate instructions.
+ .
+ .
+ .
+ CPU #1 executed 1 System Call instruction.
+ CPU #1 executed 207,746 XOR instructions.
+
+ CPU #1 executed 23,740,856 cycles.
+ CPU #1 executed 10,242,780 stalls waiting for data.
+ CPU #1 executed 1 stall waiting for a function unit.
+ .
+ .
+ .
+ CPU #1 executed 3,136,229 branch functional unit instructions.
+ CPU #1 executed 16,949,396 instructions that were accounted for in timing info.
+ CPU #1 executed 871,920 data reads.
+ CPU #1 executed 971,926 data writes.
+ CPU #1 executed 221 icache misses.
+ CPU #1 executed 16,949,396 instructions in total.
+
+ Simulator speed was 250,731 instructions/second
+
+
+ What motivated PSIM?
+
+ As an idea, psim was first discussed seriously during mid
+ 1994. At that time its main objectives were:
+
+
+ o good performance
+
+ Many simulators loose out by only providing
+ a binary interface to the internals. This
+ interface eventually becomes a bottle neck
+ in the simulators performance.
+
+ It was intended that PSIM would avoid this
+ problem by giving the user access to the
+ full source code.
+
+ Further, by exploiting the power of modern
+ compilers it was hoped that PSIM would achieve
+ good performance with out having to compromise
+ its internal design.
+
+
+ o practical portability
+
+ Rather than try to be portable to every
+ C compiler on every platform, it was decided
+ that PSIM would restrict its self to supporting
+ ANSI compilers that included the extension
+ of a long long type.
+
+ GCC is one such compiler, consequently PSIM
+ should be portable to any machine running GCC.
+
+
+ o flexibility in its design
+
+ PSIM should allow the user to select the
+ features required and customise the build
+ accordingly. By having the source code,
+ the compiler is able to eliminate any un
+ used features of the simulator.
+
+ After all, let the compiler do the work.
+
+
+ o SMP
+
+ A model that allowed the simulation of
+ SMP platforms with out the large overhead
+ often encountered with such models.
+
+
+ PSIM achieves each of these objectives.
+
+
+ Is PSIM PowerPC Platform (PPCP) (nee CHRP) Compliant?
+
+ No.
+
+ Among other things it does not have an Apple ROM socket.
+
+
+ Could PSIM be extended so that it models a CHRP machine?
+
+ Yes.
+
+ PSIM has been designed with the CHRP spec in mind. To model
+ a CHRP desktop the following would need to be added:
+
+ o An apple ROM socket :-)
+
+ o Model of each of the desktop IO devices
+
+ o An OpenPIC device.
+
+ o RTAS (Run Time Abstraction Services).
+
+ o A fully populated device tree.
+
+
+ Is the source code available?
+
+ Yes.
+
+ The source code to PSIM is available under the terms of
+ the GNU Public Licence. This allows you to distribute
+ the source code for free but with certain conditions.
+
+ See the file:
+
+ ftp://archie.au/gnu/COPYING
+
+ For details of the terms and conditions.
+
+
+ Where do I send bugs or report problems?
+
+ There is a mailing list (subscribe through majordomo@ci.com.au) at:
+
+ powerpc-psim@ci.com.au
+
+ If I get the ftp archive updated I post a note to that mailing list.
+ In addition your welcome to send bugs or problems either to me or to
+ that e-mail list.
+
+ This list currently averages zero articles a day.
+
+
+ Does PSIM have any limitations or problems?
+
+ PSIM can't run rs6000/AIX binaries - At present PSIM can only
+ simulate static executables. Since an AIX executable is
+ never static, PSIM is unable to simulate its execution.
+
+ PSIM is still under development - consequently there are going
+ to be bugs.
+
+ See the file BUGS (included in the distribution) for any
+ other outstanding issues.
+
diff --git a/gnu/dist/sim/ppc/registers.c b/gnu/dist/sim/ppc/registers.c
index ef0aa31046f..34f45ded3af 100644
--- a/gnu/dist/sim/ppc/registers.c
+++ b/gnu/dist/sim/ppc/registers.c
@@ -130,6 +130,21 @@ register_description(const char reg[])
description.index = spr_ctr;
description.size = sizeof(spreg);
}
+ else if (!strcmp(reg, "insns")) {
+ description.type = reg_insns;
+ description.index = spr_ctr;
+ description.size = sizeof(unsigned_word);
+ }
+ else if (!strcmp(reg, "stalls")) {
+ description.type = reg_stalls;
+ description.index = spr_ctr;
+ description.size = sizeof(unsigned_word);
+ }
+ else if (!strcmp(reg, "cycles")) {
+ description.type = reg_cycles;
+ description.index = spr_ctr;
+ description.size = sizeof(unsigned_word);
+ }
else {
sprs spr = find_spr(reg);
if (spr != nr_of_sprs) {
diff --git a/gnu/dist/sim/ppc/registers.h b/gnu/dist/sim/ppc/registers.h
index 922d757159f..4da6ea4bbe6 100644
--- a/gnu/dist/sim/ppc/registers.h
+++ b/gnu/dist/sim/ppc/registers.h
@@ -1,6 +1,6 @@
/* This file is part of the program psim.
- Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
+ 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
@@ -147,6 +147,9 @@ enum {
fpscr_rn_round_towards_zero = MASK32(31,31),
fpscr_rn_round_towards_pos_infinity = MASK32(30,30),
fpscr_rn_round_towards_neg_infinity = MASK32(30,31),
+ fpscr_vx_bits = (fpscr_vxsnan | fpscr_vxisi | fpscr_vxidi
+ | fpscr_vxzdz | fpscr_vximz | fpscr_vxvc
+ | fpscr_vxsoft | fpscr_vxsqrt | fpscr_vxcvi),
};
@@ -277,6 +280,7 @@ typedef enum {
reg_invalid,
reg_gpr, reg_fpr, reg_spr, reg_msr,
reg_cr, reg_fpscr, reg_pc, reg_sr,
+ reg_insns, reg_stalls, reg_cycles,
nr_register_types
} register_types;
@@ -302,6 +306,8 @@ INLINE_REGISTERS\
#define DAR SPREG(spr_dar)
#define DSISR SPREG(spr_dsisr)
+/* general purpose registers - indexed access */
+#define GPR(N) cpu_registers(processor)->gpr[N]
/* segment registers */
#define SEGREG(N) cpu_registers(processor)->sr[N]
diff --git a/gnu/dist/sim/ppc/sim-endian-n.h b/gnu/dist/sim/ppc/sim-endian-n.h
index dffdf115ffc..4d0410a92b2 100644
--- a/gnu/dist/sim/ppc/sim-endian-n.h
+++ b/gnu/dist/sim/ppc/sim-endian-n.h
@@ -31,6 +31,8 @@
#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)
INLINE_SIM_ENDIAN\
@@ -93,6 +95,33 @@ endian_be2h_N(unsigned_N raw_in)
}
}
+
+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);
+ }
+}
+
+
+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);
+ }
+}
+
+
/* NOTE: See start of file for #define */
#undef unsigned_N
#undef endian_t2h_N
@@ -101,3 +130,5 @@ endian_be2h_N(unsigned_N raw_in)
#undef swap_N
#undef endian_h2be_N
#undef endian_be2h_N
+#undef endian_h2le_N
+#undef endian_le2h_N
diff --git a/gnu/dist/sim/ppc/sim-endian.h b/gnu/dist/sim/ppc/sim-endian.h
index c9870987856..ceca97024d3 100644
--- a/gnu/dist/sim/ppc/sim-endian.h
+++ b/gnu/dist/sim/ppc/sim-endian.h
@@ -50,6 +50,16 @@ 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_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_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);
+
/* Host dependant:
@@ -136,7 +146,7 @@ INLINE_SIM_ENDIAN(unsigned_8) endian_be2h_8(unsigned_8 x);
Little endian last time I looked */
-#if defined(i386) || defined(i486) || defined(i586) || defined(__i386__) || defined(__i486__) || defined(__i586__)
+#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
@@ -146,32 +156,94 @@ INLINE_SIM_ENDIAN(unsigned_8) endian_be2h_8(unsigned_8 x);
# endif
#endif
-#if (defined (__i486__) || defined (__i586__)) && defined(__GNUC__) && WITH_BSWAP
+#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
-/* Configure defines WORDS_BIGENDIAN if the host is big endian. */
+/* 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
-#if (WITH_HOST_BYTE_ORDER == 0)
-# undef WITH_HOST_BYTE_ORDER
-# ifdef WORDS_BIGENDIAN
+/* Big endian MIPS */
+#if defined(__MIPSEB__)
+# if (WITH_HOST_BYTE_ORDER == 0)
+# undef WITH_HOST_BYTE_ORDER
# define WITH_HOST_BYTE_ORDER BIG_ENDIAN
-# else
+# 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. */
-
-
/* SWAP */
#define SWAP_1(X) swap_1(X)
@@ -192,6 +264,18 @@ INLINE_SIM_ENDIAN(unsigned_8) endian_be2h_8(unsigned_8 x);
#define BE2H_8(X) endian_be2h_8(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 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)
+
+
/* HOST to TARGET */
#define H2T_1(X) endian_h2t_1(X)
@@ -259,6 +343,27 @@ do { \
} \
} 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; \
+ } \
+} 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; \
+ } \
+} while (0)
+
+
/* TARGET WORD:
@@ -269,6 +374,8 @@ do { \
#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)
@@ -276,9 +383,25 @@ do { \
#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)
+
+
#if (SIM_ENDIAN_INLINE & INCLUDE_MODULE)
# include "sim-endian.c"
#endif
diff --git a/gnu/dist/sim/ppc/sim_callbacks.h b/gnu/dist/sim/ppc/sim_callbacks.h
index 7212597cf66..62c213ad0c4 100644
--- a/gnu/dist/sim/ppc/sim_callbacks.h
+++ b/gnu/dist/sim/ppc/sim_callbacks.h
@@ -22,19 +22,84 @@
#ifndef _SIM_CALLBACKS_H_
#define _SIM_CALLBACKS_H_
-void printf_filtered
-(const char *msg, ...) __attribute__ ((format (printf, 1, 2)));
+/* Simulator output:
-void flush_stdoutput
-(void);
+ Functions to report diagnostic information to the user. */
+
+#define printf_filtered sim_io_printf_filtered
+void sim_io_printf_filtered
+(const char *msg, ...) __attribute__ ((format (printf, 1, 2)));
void NORETURN error
(char *msg, ...);
+
+/* Model I/O:
+
+ These functions provide the interface between the modeled targets
+ standard input and output streams and the hosts external
+ environment.
+
+ The underlying model is responsible for co-ordinating I/O
+ interactions such as:
+
+ main()
+ {
+ const char mess[] = "Hello World\r\n";
+ int out;
+ out = dup(1);
+ close(1);
+ write(out, mess, sizeof(mess))
+ }
+
+ That is to say, the underlying model would, in implementing dup()
+ recorded the fact that any output directed at fid-OUT should be
+ displayed using sim_io_write_stdout(). While for the code stub:
+
+ main()
+ {
+ const char mess[] = "Hello World\r\n";
+ int out;
+ close(1);
+ out = open("output", 0x0001|0x0200, 0); // write+create
+ out = dup(1);
+ write(out, mess, sizeof(mess))
+ }
+
+ would result in output to fid-1 being directed towards the file
+ "output". */
+
+
+int
+sim_io_write_stdout
+(const char *buf,
+ int sizeof_buf);
+
+int
+sim_io_write_stderr
+(const char *buf,
+ int sizeof_buf);
+
+/* read results */
+enum { sim_io_eof = -1, sim_io_not_ready = -2, }; /* See: IEEE 1275 */
+
+int
+sim_io_read_stdin
+(char *buf,
+ int sizeof_buf);
+
+#define flush_stdoutput sim_io_flush_stdoutput
+void sim_io_flush_stdoutput
+(void);
+
+
+/* Memory management with an allocator that clears memory before use. */
+
void *zalloc
(long size);
#define ZALLOC(TYPE) (TYPE*)zalloc(sizeof (TYPE))
+
void zfree(void*);
#endif
diff --git a/gnu/dist/sim/ppc/sim_calls.c b/gnu/dist/sim/ppc/sim_calls.c
index 20342fc01ab..3bcef929c24 100644
--- a/gnu/dist/sim/ppc/sim_calls.c
+++ b/gnu/dist/sim/ppc/sim_calls.c
@@ -1,6 +1,6 @@
/* This file is part of the program psim.
- Copyright (C) 1994-1996, Andrew Cagney <cagney@highland.com.au>
+ 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
@@ -26,6 +26,8 @@
#include "psim.h"
#include "options.h"
+#undef printf_filtered /* blow away the mapping */
+
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
@@ -38,10 +40,9 @@
#endif
#endif
-#include "../../gdb/defs.h"
-
-#include "../../gdb/remote-sim.h"
-#include "../../gdb/callback.h"
+#include "defs.h"
+#include "callback.h"
+#include "remote-sim.h"
/* Structures used by the simulator, for gdb just have static structures */
@@ -59,7 +60,7 @@ sim_open (char *args)
TRACE(trace_gdb, ("sim_open(args=%s) called\n", args ? args : "(null)"));
if (root_device != NULL)
- printf_filtered("Warning - re-open of simulator leaks memory\n");
+ sim_io_printf_filtered("Warning - re-open of simulator leaks memory\n");
root_device = psim_tree();
simulator = NULL;
@@ -78,7 +79,7 @@ void
sim_close (int quitting)
{
TRACE(trace_gdb, ("sim_close(quitting=%d) called\n", quitting));
- if (ppc_trace[trace_print_info])
+ if (ppc_trace[trace_print_info] && simulator != NULL)
psim_print_info (simulator, ppc_trace[trace_print_info]);
}
@@ -243,8 +244,8 @@ sim_stop_reason (enum sim_stop *reason, int *sigrc)
/* Run (or resume) the program. */
-static void
-sim_ctrl_c()
+static RETSIGTYPE
+sim_ctrl_c(int sig)
{
sim_should_run = 0;
}
@@ -252,20 +253,25 @@ sim_ctrl_c()
void
sim_resume (int step, int siggnal)
{
- void (*prev) ();
-
TRACE(trace_gdb, ("sim_resume(step=%d, siggnal=%d)\n",
step, siggnal));
- prev = signal(SIGINT, sim_ctrl_c);
- sim_should_run = 1;
-
if (step)
- psim_step(simulator);
+ {
+ psim_step(simulator);
+ /* sim_stop_reason has a sanity check for stopping while
+ was_continuing. We don't want that here so reset sim_should_run. */
+ sim_should_run = 0;
+ }
else
- psim_run_until_stop(simulator, &sim_should_run);
+ {
+ RETSIGTYPE (*prev) ();
- signal(SIGINT, prev);
+ prev = signal(SIGINT, sim_ctrl_c);
+ sim_should_run = 1;
+ psim_run_until_stop(simulator, &sim_should_run);
+ signal(SIGINT, prev);
+ }
}
void
@@ -273,16 +279,114 @@ sim_do_command (char *cmd)
{
TRACE(trace_gdb, ("sim_do_commands(cmd=%s) called\n",
cmd ? cmd : "(null)"));
- if (cmd) {
+ if (cmd != NULL) {
char **argv = buildargv(cmd);
- psim_options(root_device, argv);
+ psim_command(root_device, argv);
freeargv(argv);
}
}
+
+/* Map simulator IO operations onto the corresponding GDB I/O
+ functions.
+
+ NB: Only a limited subset of operations are mapped across. More
+ advanced operations (such as dup or write) must either be mapped to
+ one of the below calls or handled internally */
+
+static host_callback *callbacks;
+
+int
+sim_io_read_stdin(char *buf,
+ int sizeof_buf)
+{
+ switch (CURRENT_STDIO) {
+ case DO_USE_STDIO:
+ return callbacks->read_stdin(callbacks, buf, sizeof_buf);
+ break;
+ case DONT_USE_STDIO:
+ return callbacks->read(callbacks, 0, buf, sizeof_buf);
+ break;
+ default:
+ error("sim_io_read_stdin: unaccounted switch\n");
+ break;
+ }
+ return 0;
+}
+
+int
+sim_io_write_stdout(const char *buf,
+ int sizeof_buf)
+{
+ switch (CURRENT_STDIO) {
+ case DO_USE_STDIO:
+ return callbacks->write_stdout(callbacks, buf, sizeof_buf);
+ break;
+ case DONT_USE_STDIO:
+ return callbacks->write(callbacks, 1, buf, sizeof_buf);
+ break;
+ default:
+ error("sim_io_write_stdout: unaccounted switch\n");
+ break;
+ }
+ return 0;
+}
+
+int
+sim_io_write_stderr(const char *buf,
+ int sizeof_buf)
+{
+ switch (CURRENT_STDIO) {
+ case DO_USE_STDIO:
+ /* NB: I think there should be an explicit write_stderr callback */
+ return callbacks->write(callbacks, 3, buf, sizeof_buf);
+ break;
+ case DONT_USE_STDIO:
+ return callbacks->write(callbacks, 3, buf, sizeof_buf);
+ break;
+ default:
+ error("sim_io_write_stderr: unaccounted switch\n");
+ break;
+ }
+ return 0;
+}
+
+
+void
+sim_io_printf_filtered(const char *fmt,
+ ...)
+{
+ char message[1024];
+ va_list ap;
+ /* format the message */
+ va_start(ap, fmt);
+ vsprintf(message, fmt, ap);
+ va_end(ap);
+ /* sanity check */
+ if (strlen(message) >= sizeof(message))
+ error("sim_io_printf_filtered: buffer overflow\n");
+ callbacks->printf_filtered(callbacks, "%s", message);
+}
+
+void
+sim_io_flush_stdoutput(void)
+{
+ switch (CURRENT_STDIO) {
+ case DO_USE_STDIO:
+ gdb_flush (gdb_stdout);
+ break;
+ case DONT_USE_STDIO:
+ break;
+ default:
+ error("sim_io_read_stdin: unaccounted switch\n");
+ break;
+ }
+}
+
void
sim_set_callbacks (host_callback *callback)
{
+ callbacks = callback;
TRACE(trace_gdb, ("sim_set_callbacks called\n"));
}
@@ -302,8 +406,3 @@ void zfree(void *data)
{
mfree(NULL, data);
}
-
-void flush_stdoutput(void)
-{
- gdb_flush (gdb_stdout);
-}
diff --git a/gnu/dist/sim/ppc/std-config.h b/gnu/dist/sim/ppc/std-config.h
index 7ab6df1127a..eaf35582346 100644
--- a/gnu/dist/sim/ppc/std-config.h
+++ b/gnu/dist/sim/ppc/std-config.h
@@ -287,6 +287,23 @@ extern int current_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)
+
+
+
/* INLINE CODE SELECTION:
GCC -O3 attempts to inline any function or procedure in scope. The
@@ -308,18 +325,30 @@ extern int current_model_issue;
The following additional values are `bit fields' and can be
combined.
- 1 Include the C file for the module into the file being compiled
+ REVEAL_MODULE:
+
+ Include the C file for the module into the file being compiled
but do not make the functions within the module inline.
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.
- 2 Make external functions within the module `inline'. Thus if
+ INLINE_MODULE:
+
+ Make external functions within the module `inline'. Thus if
the module is included into a file being compiled, calls to
its funtions can be eliminated. 2 implies 1.
- 4 Make internal (static) functions within the module `inline'.
+ INLINE_LOCALS:
+
+ Make internal (static) functions within the module `inline'.
+
+ The following abreviations are available:
+
+ INCLUDE_MODULE == (REVEAL_MODULE | INLINE_MODULE)
+
+ ALL_INLINE == (REVEAL_MODULE | INLINE_MODULE | INLINE_LOCALS)
In addition to this, modules have been put into two categories.
@@ -401,7 +430,7 @@ extern int current_model_issue;
REALITY CHECK:
- This is not for the faint hearted. I've seen GCC get up to 200mb
+ This is not for the faint hearted. I've seen GCC get up to 500mb
trying to compile what this can create.
Some of the modules do not yet implement the WITH_INLINE_STATIC
@@ -433,14 +462,37 @@ extern int current_model_issue;
#endif
#endif
+
/* Your compilers pass parameters in registers reserved word */
+#ifndef WITH_REGPARM
+#define WITH_REGPARM 0
+#endif
+
+/* Your compilers use an alternative calling sequence reserved word */
+
+#ifndef WITH_STDCALL
+#define WITH_STDCALL 0
+#endif
+
#if !defined REGPARM
-#if (defined(i386) || defined(i486) || defined(i586) || defined(__i386__) || defined(__i486__) || defined(__i586__)) && WITH_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
-#define REGPARM
+#if (!WITH_REGPARM && WITH_STDCALL)
+#define REGPARM __attribute__((__stdcall__))
+#endif
+#endif
+#endif
+#endif
#endif
+
+#if !defined REGPARM
+#define REGPARM
#endif
@@ -525,14 +577,18 @@ extern int current_model_issue;
real hardware instead of RAM.
Also, most of the functions in devices.c are always called through
- a jump table.
-
- There seems to be some problem with making either device_tree or
- devices inline. It reports the message: device_tree_find_node()
- not a leaf */
+ a jump table. */
#ifndef DEVICE_INLINE
-#define DEVICE_INLINE DEFAULT_INLINE
+#define DEVICE_INLINE (DEFAULT_INLINE ? INLINE_LOCALS : 0)
+#endif
+
+/* Code called used while the device tree is being built.
+
+ Inlining this is of no benefit */
+
+#ifndef TREE_INLINE
+#define TREE_INLINE (DEFAULT_INLINE ? INLINE_LOCALS : 0)
#endif
/* Code called whenever information on a Special Purpose Register is
@@ -555,14 +611,24 @@ extern int current_model_issue;
inline all of their called functions */
#ifndef SEMANTICS_INLINE
-#define SEMANTICS_INLINE DEFAULT_INLINE
+#define SEMANTICS_INLINE (DEFAULT_INLINE & ~INLINE_MODULE)
+#endif
+
+/* When using the instruction cache, code to decode an instruction and
+ install it into the cache. Normally called when ever there is a
+ miss in the instruction cache. */
+
+#ifndef ICACHE_INLINE
+#define ICACHE_INLINE (DEFAULT_INLINE & ~INLINE_MODULE)
#endif
-/* Code to decode an instruction. Normally called on every instruction
- cycle */
+/* General functions called by semantics functions but part of the
+ instruction table. Although called by the semantic functions the
+ frequency of calls is low. Consequently the need to inline this
+ code is reduced. */
-#ifndef IDECODE_INLINE
-#define IDECODE_INLINE DEFAULT_INLINE
+#ifndef SUPPORT_INLINE
+#define SUPPORT_INLINE INLINE_LOCALS
#endif
/* Model specific code used in simulating functional units. Note, it actaully
@@ -580,18 +646,24 @@ extern int current_model_issue;
routines will be pulled in twice. */
#ifndef OPTIONS_INLINE
-#define OPTIONS_INLINE DEFAULT_INLINE
+#define OPTIONS_INLINE MODEL_INLINE
#endif
-/* The main body of code */
+/* idecode acts as the hub of the system, everything else is imported
+ into this file */
-#ifndef PSIM_INLINE
-#define PSIM_INLINE DEFAULT_INLINE
+#ifndef IDECOCE_INLINE
+#define IDECODE_INLINE INLINE_LOCALS
#endif
+/* psim, isn't actually inlined */
+
+#ifndef PSIM_INLINE
+#define PSIM_INLINE INLINE_LOCALS
+#endif
-/* Code to emulate os or rom compatibility. Called on the rare
- occasion that the OS or ROM code is being emulated. */
+/* Code to emulate os or rom compatibility. This code is called via a
+ table and hence there is little benefit in making it inline */
#ifndef OS_EMUL_INLINE
#define OS_EMUL_INLINE 0
diff --git a/gnu/dist/sim/ppc/table.c b/gnu/dist/sim/ppc/table.c
index 2916f1f673c..7012a6ad9bc 100644
--- a/gnu/dist/sim/ppc/table.c
+++ b/gnu/dist/sim/ppc/table.c
@@ -49,7 +49,7 @@ struct _table {
};
extern table *
-table_open(char *file_name,
+table_open(const char *file_name,
int nr_fields,
int nr_model_fields)
{
@@ -264,10 +264,10 @@ dump_table_entry(table_entry *entry,
extern void
-table_entry_lf_c_line_nr(lf *file,
- table_entry *entry)
+table_entry_print_cpp_line_nr(lf *file,
+ table_entry *entry)
{
- lf_print_c_line_nr(file, entry->line_nr, entry->file_name);
+ lf_print__external_reference(file, entry->line_nr, entry->file_name);
}
diff --git a/gnu/dist/sim/ppc/table.h b/gnu/dist/sim/ppc/table.h
index d2cc2a37962..509fb22870e 100644
--- a/gnu/dist/sim/ppc/table.h
+++ b/gnu/dist/sim/ppc/table.h
@@ -44,7 +44,7 @@ struct _table_entry {
extern table *table_open
-(char *file_name,
+(const char *file_name,
int max_nr_fields,
int max_nr_model_fields);
@@ -55,6 +55,6 @@ extern void dump_table_entry
(table_entry *entry,
int indent);
-extern void table_entry_lf_c_line_nr
+extern void table_entry_print_cpp_line_nr
(lf *file,
table_entry *entry);
diff --git a/gnu/dist/sim/ppc/tree.c b/gnu/dist/sim/ppc/tree.c
new file mode 100644
index 00000000000..360059353ce
--- /dev/null
+++ b/gnu/dist/sim/ppc/tree.c
@@ -0,0 +1,1256 @@
+/* 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 _PARSE_C_
+#define _PARSE_C_
+
+#include <stdio.h>
+#include <stdarg.h>
+
+#include "basics.h"
+
+#include "device.h"
+#include "tree.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 *name;
+ char *base;
+ char *unit;
+ char *args;
+ /* previous device */
+ char *last_name;
+ char *last_base;
+ 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_INLINE_TREE\
+(int)
+split_device_specifier(device *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 != '/') {
+ device *aliases = 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))
+ error("split_device_specifier: buffer overflow");
+ }
+ alias[len] = '\0';
+ if (aliases != NULL
+ && device_find_property(aliases, alias)) {
+ strcpy(spec->buf, device_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))
+ error("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->base = NULL;
+ spec->unit = NULL;
+ spec->args = NULL;
+ spec->last_name = NULL;
+ spec->last_base = 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_INLINE_DEVICE\
+(int)
+split_property_specifier(device *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 device */
+
+STATIC_INLINE_TREE\
+(int)
+split_device_name(name_specifier *spec)
+{
+ char *chp;
+ /* remember what came before */
+ spec->last_name = spec->name;
+ spec->last_base = spec->base;
+ spec->last_unit = spec->unit;
+ spec->last_args = spec->args;
+ /* finished? */
+ if (spec->path[0] == '\0') {
+ spec->name = NULL;
+ spec->base = 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->base = spec->name;
+ }
+ else {
+ *chp = '\0';
+ spec->base = spec->name + 1;
+ spec->name = chp + 1;
+ }
+ }
+ else {
+ spec->base = 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_INLINE_TREE\
+(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_INLINE_TREE\
+(device *)
+split_find_device(device *current,
+ name_specifier *spec)
+{
+ /* strip off (and process) any leading ., .., ./ and / */
+ while (1) {
+ if (strncmp(spec->path, "/", strlen("/")) == 0) {
+ /* cd /... */
+ while (current != NULL && device_parent(current) != NULL)
+ current = device_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 && device_parent(current) != NULL)
+ current = device_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 && device_parent(current) != NULL)
+ current = device_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)) {
+ device *child;
+ for (child = device_child(current);
+ child != NULL; child = device_sibling(child)) {
+ if (strcmp(spec->name, device_name(child)) == 0) {
+ if (spec->unit == NULL)
+ break;
+ else {
+ device_unit phys;
+ device_decode_unit(current, spec->unit, &phys);
+ if (memcmp(&phys, device_unit_address(child),
+ sizeof(device_unit)) == 0)
+ break;
+ }
+ }
+ }
+ if (child == NULL)
+ return current; /* search failed */
+ current = child;
+ }
+
+ return current;
+}
+
+
+STATIC_INLINE_TREE\
+(device *)
+split_fill_path(device *current,
+ const char *device_specifier,
+ name_specifier *spec)
+{
+ /* break it up */
+ if (!split_device_specifier(current, device_specifier, spec))
+ device_error(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 {
+ current = device_create(current, spec->base, spec->name,
+ spec->unit, spec->args);
+ } while (split_device_name(spec));
+ }
+
+ return current;
+}
+
+
+INLINE_TREE\
+(void)
+tree_init(device *root,
+ psim *system)
+{
+ TRACE(trace_device_tree, ("tree_init(root=0x%lx, system=0x%lx)\n",
+ (long)root,
+ (long)system));
+ /* remove the old, rebuild the new */
+ tree_traverse(root, device_clean, NULL, system);
+ tree_traverse(root, device_init_static_properties, NULL, system);
+ tree_traverse(root, device_init_address, NULL, system);
+ tree_traverse(root, device_init_runtime_properties, NULL, system);
+ tree_traverse(root, device_init_data, NULL, system);
+}
+
+
+
+/* <non-white-space> */
+
+STATIC_INLINE_TREE\
+(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_INLINE_TREE\
+(int)
+count_entries(device *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) {
+ device_error(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_INLINE_TREE\
+(const char *)
+parse_address(device *current,
+ device *bus,
+ const char *chp,
+ device_unit *address)
+{
+ if (device_decode_unit(bus, chp, address) < 0)
+ device_error(current, "invalid unit address in %s", chp);
+ return skip_token(chp);
+}
+
+
+/* parse: <size> ::= <number> { "," <number> } ; */
+
+STATIC_INLINE_TREE\
+(const char *)
+parse_size(device *current,
+ device *bus,
+ const char *chp,
+ device_unit *size)
+{
+ int i;
+ int nr;
+ const char *curr = chp;
+ memset(size, 0, sizeof(*size));
+ /* parse the numeric list */
+ size->nr_cells = device_nr_size_cells(bus);
+ nr = 0;
+ while (1) {
+ char *next;
+ size->cells[nr] = strtoul(curr, &next, 0);
+ if (curr == next)
+ device_error(current, "Problem parsing <size> %s", chp);
+ nr += 1;
+ if (next[0] != ',')
+ break;
+ if (nr == size->nr_cells)
+ device_error(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_INLINE_TREE\
+(void)
+parse_reg_property(device *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, device_parent(current),
+ chp, &regs[reg_nr].address);
+ chp = parse_size(current, device_parent(current),
+ chp, &regs[reg_nr].size);
+ }
+
+ /* create it */
+ device_add_reg_array_property(current, property_name,
+ regs, nr_regs);
+
+ zfree(regs);
+}
+
+
+/* { <child-address> <parent-address> <child-size> }* */
+
+STATIC_INLINE_TREE\
+(void)
+parse_ranges_property(device *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, device_parent(current),
+ chp, &ranges[range_nr].parent_address);
+ chp = parse_size(current, current,
+ chp, &ranges[range_nr].size);
+ }
+
+ /* create it */
+ device_add_range_array_property(current, property_name, ranges, nr_ranges);
+
+ zfree(ranges);
+}
+
+
+/* <integer> ... */
+
+STATIC_INLINE_TREE\
+(void)
+parse_integer_property(device *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))
+ device_error(current, "buffer overflow");
+ property_value = end;
+ }
+ if (nr_entries == 0)
+ device_error(current, "error parsing integer property %s (%s)",
+ property_name, property_value);
+ else if (nr_entries == 1)
+ device_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 */
+ device_add_array_property(current, property_name, words,
+ sizeof(words[0]) * nr_entries);
+ }
+}
+
+
+/* <string> ... */
+
+STATIC_INLINE_TREE\
+(void)
+parse_string_property(device *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)
+ device_error(current, "String property %s badly formatted",
+ property_name);
+ }
+ ASSERT(strings[nr_strings] == NULL); /* from zalloc */
+
+ /* install it */
+ if (nr_strings == 0)
+ device_add_string_property(current, property_name, "");
+ else if (nr_strings == 1)
+ device_add_string_property(current, property_name, strings[0]);
+ else {
+ const char **specs = (const char**)strings; /* stop a bogus error */
+ device_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> */
+
+STATIC_INLINE_TREE\
+(void)
+parse_ihandle_property(device *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 */
+ device_add_ihandle_runtime_property(current, property,
+ &ihandle);
+}
+
+
+
+EXTERN_TREE\
+(device *)
+tree_parse(device *current,
+ const char *fmt,
+ ...)
+{
+ char device_specifier[1024];
+ name_specifier spec;
+
+ /* format the path */
+ {
+ va_list ap;
+ va_start(ap, fmt);
+ vsprintf(device_specifier, fmt, ap);
+ va_end(ap);
+ if (strlen(device_specifier) >= sizeof(device_specifier))
+ error("device_tree_add_deviced: buffer overflow\n");
+ }
+
+ /* construct the tree down to the final device */
+ 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_device_name = split_value(&spec);
+ device *dest;
+ /* find my name */
+ my_port = device_interrupt_decode(current, my_port_name,
+ output_port);
+ /* find the dest device and port */
+ dest = split_fill_path(current, dest_device_name, &dest_spec);
+ dest_port = device_interrupt_decode(dest, dest_port_name,
+ input_port);
+ /* connect the two */
+ device_interrupt_attach(current,
+ my_port,
+ dest,
+ dest_port,
+ permenant_object);
+ }
+ break;
+ default:
+ device_error(current, "unreconised interrupt spec %s\n", spec.value);
+ break;
+ }
+ }
+
+ /* is there a property */
+ if (spec.property != NULL) {
+ if (strcmp(spec.value, "true") == 0)
+ device_add_boolean_property(current, spec.property, 1);
+ else if (strcmp(spec.value, "false") == 0)
+ device_add_boolean_property(current, spec.property, 0);
+ else {
+ const device_property *property;
+ switch (spec.value[0]) {
+ case '*':
+ parse_ihandle_property(current, spec.property, spec.value + 1);
+ break;
+ 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;
+ }
+ device_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 = tree_find_property(current, spec.value);
+ if (property == NULL)
+ device_error(current, "property %s not found\n", spec.value);
+ device_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;
+}
+
+
+INLINE_TREE\
+(void)
+tree_traverse(device *root,
+ tree_traverse_function *prefix,
+ tree_traverse_function *postfix,
+ void *data)
+{
+ device *child;
+ if (prefix != NULL)
+ prefix(root, data);
+ for (child = device_child(root);
+ child != NULL;
+ child = device_sibling(child)) {
+ tree_traverse(child, prefix, postfix, data);
+ }
+ if (postfix != NULL)
+ postfix(root, data);
+}
+
+
+STATIC_INLINE_TREE\
+(void)
+print_address(device *bus,
+ const device_unit *phys)
+{
+ char unit[32];
+ device_encode_unit(bus, phys, unit, sizeof(unit));
+ printf_filtered(" %s", unit);
+}
+
+STATIC_INLINE_TREE\
+(void)
+print_size(device *bus,
+ const device_unit *size)
+{
+ int i;
+ for (i = 0; i < size->nr_cells; i++)
+ if (size->cells[i] != 0)
+ break;
+ if (i < size->nr_cells) {
+ printf_filtered(" 0x%lx", (unsigned long)size->cells[i]);
+ i++;
+ for (; i < size->nr_cells; i++)
+ printf_filtered(",0x%lx", (unsigned long)size->cells[i]);
+ }
+ else
+ printf_filtered(" 0");
+}
+
+STATIC_INLINE_TREE\
+(void)
+print_reg_property(device *me,
+ const device_property *property)
+{
+ int reg_nr;
+ reg_property_spec reg;
+ for (reg_nr = 0;
+ device_find_reg_array_property(me, property->name, reg_nr, &reg);
+ reg_nr++) {
+ print_address(device_parent(me), &reg.address);
+ print_size(me, &reg.size);
+ }
+}
+
+STATIC_INLINE_TREE\
+(void)
+print_ranges_property(device *me,
+ const device_property *property)
+{
+ int range_nr;
+ range_property_spec range;
+ for (range_nr = 0;
+ device_find_range_array_property(me, property->name, range_nr, &range);
+ range_nr++) {
+ print_address(me, &range.child_address);
+ print_address(device_parent(me), &range.parent_address);
+ print_size(me, &range.size);
+ }
+}
+
+STATIC_INLINE_TREE\
+(void)
+print_string(const char *string)
+{
+ printf_filtered(" \"");
+ while (*string != '\0') {
+ switch (*string) {
+ case '"':
+ printf_filtered("\\\"");
+ break;
+ case '\\':
+ printf_filtered("\\\\");
+ break;
+ default:
+ printf_filtered("%c", *string);
+ break;
+ }
+ string++;
+ }
+ printf_filtered("\"");
+}
+
+STATIC_INLINE_TREE\
+(void)
+print_string_array_property(device *me,
+ const device_property *property)
+{
+ int nr;
+ string_property_spec string;
+ for (nr = 0;
+ device_find_string_array_property(me, property->name, nr, &string);
+ nr++) {
+ print_string(string);
+ }
+}
+
+STATIC_INLINE_TREE\
+(void)
+print_properties(device *me)
+{
+ const device_property *property;
+ for (property = device_find_property(me, NULL);
+ property != NULL;
+ property = device_next_property(property)) {
+ printf_filtered("%s/%s", device_path(me), property->name);
+ if (property->original != NULL) {
+ printf_filtered(" !");
+ printf_filtered("%s/%s",
+ device_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++) {
+ printf_filtered(" 0x%lx", (unsigned long)BE2H_cell(w[cell_nr]));
+ }
+ }
+ else {
+ unsigned8 *w = (unsigned8*)property->array;
+ printf_filtered(" [");
+ while ((char*)w - (char*)property->array < property->sizeof_array) {
+ printf_filtered(" 0x%2x", BE2H_1(*w));
+ w++;
+ }
+ }
+ break;
+ case boolean_property:
+ {
+ int b = device_find_boolean_property(me, property->name);
+ printf_filtered(" %s", b ? "true" : "false");
+ }
+ break;
+ case ihandle_property:
+ {
+ if (property->array != NULL) {
+ device_instance *instance = device_find_ihandle_property(me, property->name);
+ printf_filtered(" *%s", device_instance_path(instance));
+ }
+ else {
+ /* not yet initialized, ask the device for the path */
+ ihandle_runtime_property_spec spec;
+ device_find_ihandle_runtime_property(me, property->name, &spec);
+ printf_filtered(" *%s", spec.full_path);
+ }
+ }
+ break;
+ case integer_property:
+ {
+ unsigned_word w = device_find_integer_property(me, property->name);
+ printf_filtered(" 0x%lx", (unsigned long)w);
+ }
+ break;
+ case range_array_property:
+ print_ranges_property(me, property);
+ break;
+ case reg_array_property:
+ print_reg_property(me, property);
+ break;
+ case string_property:
+ {
+ const char *s = device_find_string_property(me, property->name);
+ print_string(s);
+ }
+ break;
+ case string_array_property:
+ print_string_array_property(me, property);
+ break;
+ }
+ }
+ printf_filtered("\n");
+ }
+}
+
+STATIC_INLINE_TREE\
+(void)
+print_interrupts(device *me,
+ int my_port,
+ device *dest,
+ int dest_port,
+ void *ignore_or_null)
+{
+ char src[32];
+ char dst[32];
+ device_interrupt_encode(me, my_port, src, sizeof(src), output_port);
+ device_interrupt_encode(dest, dest_port, dst, sizeof(dst), input_port);
+ printf_filtered("%s > %s %s %s\n",
+ device_path(me),
+ src, dst,
+ device_path(dest));
+}
+
+STATIC_INLINE_TREE\
+(void)
+print_device(device *me,
+ void *ignore_or_null)
+{
+ printf_filtered("%s\n", device_path(me));
+ print_properties(me);
+ device_interrupt_traverse(me, print_interrupts, NULL);
+}
+
+INLINE_TREE\
+(void)
+tree_print(device *root)
+{
+ tree_traverse(root,
+ print_device, NULL,
+ NULL);
+}
+
+
+INLINE_TREE\
+(void)
+tree_usage(int verbose)
+{
+ if (verbose == 1) {
+ printf_filtered("\n");
+ printf_filtered("A device/property specifier has the form:\n");
+ printf_filtered("\n");
+ printf_filtered(" /path/to/a/device [ property-value ]\n");
+ printf_filtered("\n");
+ printf_filtered("and a possible device is\n");
+ printf_filtered("\n");
+ }
+ if (verbose > 1) {
+ printf_filtered("\n");
+ printf_filtered("A device/property specifier (<spec>) has the format:\n");
+ printf_filtered("\n");
+ printf_filtered(" <spec> ::= <path> [ <value> ] ;\n");
+ printf_filtered(" <path> ::= { <prefix> } { <node> \"/\" } <node> ;\n");
+ printf_filtered(" <prefix> ::= ( | \"/\" | \"../\" | \"./\" ) ;\n");
+ printf_filtered(" <node> ::= <name> [ \"@\" <unit> ] [ \":\" <args> ] ;\n");
+ printf_filtered(" <unit> ::= <number> { \",\" <number> } ;\n");
+ printf_filtered("\n");
+ printf_filtered("Where:\n");
+ printf_filtered("\n");
+ printf_filtered(" <name> is the name of a device (list below)\n");
+ printf_filtered(" <unit> is the unit-address relative to the parent bus\n");
+ printf_filtered(" <args> additional arguments used when creating the device\n");
+ printf_filtered(" <value> ::= ( <number> # integer property\n");
+ printf_filtered(" | \"[\" { <number> } # array property (byte)\n");
+ printf_filtered(" | \"{\" { <number> } # array property (cell)\n");
+ printf_filtered(" | [ \"true\" | \"false\" ] # boolean property\n");
+ printf_filtered(" | \"*\" <path> # ihandle property\n");
+ printf_filtered(" | \"!\" <path> # copy property\n");
+ printf_filtered(" | \">\" [ <number> ] <path> # attach interrupt\n");
+ printf_filtered(" | \"<\" <path> # attach child interrupt\n");
+ printf_filtered(" | \"\\\"\" <text> # string property\n");
+ printf_filtered(" | <text> # string property\n");
+ printf_filtered(" ) ;\n");
+ printf_filtered("\n");
+ printf_filtered("And the following are valid device names:\n");
+ printf_filtered("\n");
+ }
+}
+
+
+
+INLINE_TREE\
+(device_instance *)
+tree_instance(device *root,
+ const char *device_specifier)
+{
+ /* find the device node */
+ device *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);
+}
+
+
+INLINE_TREE\
+(device *)
+tree_find_device(device *root,
+ const char *path_to_device)
+{
+ device *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;
+}
+
+
+INLINE_TREE\
+(const device_property *)
+tree_find_property(device *root,
+ const char *path_to_property)
+{
+ name_specifier spec;
+ if (!split_property_specifier(root, path_to_property, &spec))
+ device_error(root, "Invalid property path %s", path_to_property);
+ root = split_find_device(root, &spec);
+ return device_find_property(root, spec.property);
+}
+
+INLINE_TREE\
+(int)
+tree_find_boolean_property(device *root,
+ const char *path_to_property)
+{
+ name_specifier spec;
+ if (!split_property_specifier(root, path_to_property, &spec))
+ device_error(root, "Invalid property path %s", path_to_property);
+ root = split_find_device(root, &spec);
+ return device_find_boolean_property(root, spec.property);
+}
+
+INLINE_TREE\
+(signed_cell)
+tree_find_integer_property(device *root,
+ const char *path_to_property)
+{
+ name_specifier spec;
+ if (!split_property_specifier(root, path_to_property, &spec))
+ device_error(root, "Invalid property path %s", path_to_property);
+ root = split_find_device(root, &spec);
+ return device_find_integer_property(root, spec.property);
+}
+
+INLINE_TREE\
+(device_instance *)
+tree_find_ihandle_property(device *root,
+ const char *path_to_property)
+{
+ name_specifier spec;
+ if (!split_property_specifier(root, path_to_property, &spec))
+ device_error(root, "Invalid property path %s", path_to_property);
+ root = split_find_device(root, &spec);
+ return device_find_ihandle_property(root, spec.property);
+}
+
+INLINE_TREE\
+(const char *)
+tree_find_string_property(device *root,
+ const char *path_to_property)
+{
+ name_specifier spec;
+ if (!split_property_specifier(root, path_to_property, &spec))
+ device_error(root, "Invalid property path %s", path_to_property);
+ root = split_find_device(root, &spec);
+ return device_find_string_property(root, spec.property);
+}
+
+
+#endif /* _PARSE_C_ */
diff --git a/gnu/dist/sim/ppc/tree.h b/gnu/dist/sim/ppc/tree.h
new file mode 100644
index 00000000000..46590cb6266
--- /dev/null
+++ b/gnu/dist/sim/ppc/tree.h
@@ -0,0 +1,139 @@
+/* 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.
+
+ */
+
+
+#ifndef _TREE_H_
+#define _TREE_H_
+
+#ifndef INLINE_TREE
+#define INLINE_TREE
+#endif
+
+/* Constructing the device tree:
+
+ The initial device tree populated with devices and basic properties
+ is created using the function <<device_tree_add_parsed()>>. This
+ function parses a PSIM device specification and uses it to populate
+ the tree accordingly.
+
+ This function accepts a printf style formatted string as the
+ argument that describes the entry. Any properties or interrupt
+ connections added to a device tree using this function are marked
+ as having a permenant disposition. When the tree is (re)
+ initialized they will be restored to their initial value.
+
+ */
+
+EXTERN_TREE\
+(device *) tree_parse
+(device *root,
+ const char *fmt,
+ ...) __attribute__ ((format (printf, 2, 3)));
+
+
+INLINE_TREE\
+(void) tree_usage
+(int verbose);
+
+INLINE_TREE\
+(void) tree_print
+(device *root);
+
+INLINE_TREE\
+(device_instance*) tree_instance
+(device *root,
+ const char *device_specifier);
+
+
+/* Tree traversal::
+
+ The entire device tree can be traversed using the
+ <<device_tree_traverse()>> function. The traversal can be in
+ either pre- or postfix order.
+
+ */
+
+typedef void (tree_traverse_function)
+ (device *device,
+ void *data);
+
+INLINE_DEVICE\
+(void) tree_traverse
+(device *root,
+ tree_traverse_function *prefix,
+ tree_traverse_function *postfix,
+ void *data);
+
+
+/* Tree lookup::
+
+ The function <<tree_find_device()>> will attempt to locate
+ the specified device within the tree. If the device is not found a
+ NULL device is returned.
+
+ */
+
+INLINE_TREE\
+(device *) tree_find_device
+(device *root,
+ const char *path);
+
+
+INLINE_TREE\
+(const device_property *) tree_find_property
+(device *root,
+ const char *path_to_property);
+
+INLINE_TREE\
+(int) tree_find_boolean_property
+(device *root,
+ const char *path_to_property);
+
+INLINE_TREE\
+(signed_cell) tree_find_integer_property
+(device *root,
+ const char *path_to_property);
+
+INLINE_TREE\
+(device_instance *) tree_find_ihandle_property
+(device *root,
+ const char *path_to_property);
+
+INLINE_TREE\
+(const char *) tree_find_string_property
+(device *root,
+ const char *path_to_property);
+
+
+/* Initializing the created tree:
+
+ Once a device tree has been created the <<device_tree_init()>>
+ function is used to initialize it. The exact sequence of events
+ that occure during initialization are described separatly.
+
+ */
+
+INLINE_TREE\
+(void) tree_init
+(device *root,
+ psim *system);
+
+
+#endif /* _TREE_H_ */
diff --git a/gnu/dist/sim/ppc/vm.c b/gnu/dist/sim/ppc/vm.c
index e9746d173d7..bff962cc31e 100644
--- a/gnu/dist/sim/ppc/vm.c
+++ b/gnu/dist/sim/ppc/vm.c
@@ -1,6 +1,6 @@
/* This file is part of the program psim.
- Copyright (C) 1994-1996, Andrew Cagney <cagney@highland.com.au>
+ 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
@@ -22,6 +22,7 @@
#ifndef _VM_C_
#define _VM_C_
+#if 0
#include "basics.h"
#include "registers.h"
#include "device.h"
@@ -29,6 +30,9 @@
#include "vm.h"
#include "interrupts.h"
#include "mon.h"
+#endif
+
+#include "cpu.h"
/* OEA vs VEA
@@ -138,7 +142,7 @@ enum _om_segment_tlb_constants {
typedef struct _om_segment_tlb_entry {
int key[nr_om_modes];
om_access_types invalid_access; /* set to instruction if no_execute bit */
- unsigned_word masked_virtual_segment_id; /* aligned ready for pte addr */
+ unsigned_word masked_virtual_segment_id; /* aligned ready for pte group addr */
#if (WITH_TARGET_WORD_BITSIZE == 64)
int is_valid;
unsigned_word masked_effective_segment_id;
@@ -298,11 +302,19 @@ om_hash_page(unsigned_word masked_vsid,
{
unsigned_word extracted_ea = EXTRACTED(ea, 36, 51);
#if (WITH_TARGET_WORD_BITSIZE == 32)
- return masked_vsid ^ INSERTED32(extracted_ea, 7, 31-6);
+ unsigned_word masked_ea = INSERTED32(extracted_ea, 7, 31-6);
+ unsigned_word hash = masked_vsid ^ masked_ea;
#endif
#if (WITH_TARGET_WORD_BITSIZE == 64)
- return masked_vsid ^ INSERTED64(extracted_ea, 18, 63-7);
+ unsigned_word masked_ea = INSERTED64(extracted_ea, 18, 63-7);
+ unsigned_word hash = masked_vsid ^ masked_ea;
#endif
+ TRACE(trace_vm, ("ea=0x%lx - masked-vsid=0x%lx masked-ea=0x%lx hash=0x%lx\n",
+ (unsigned long)ea,
+ (unsigned long)masked_vsid,
+ (unsigned long)masked_ea,
+ (unsigned long)hash));
+ return hash;
}
STATIC_INLINE_VM\
@@ -355,11 +367,17 @@ om_ea_masked_byte(unsigned_word ea)
return MASKED(ea, 52, 63);
}
+/* return the VSID aligned for pte group addr */
STATIC_INLINE_VM\
(unsigned_word)
om_pte_0_masked_vsid(unsigned_word pte_0)
{
- return INSERTED32(EXTRACTED32(pte_0, 1, 24), 7-5, 31-6);
+#if (WITH_TARGET_WORD_BITSIZE == 32)
+ return INSERTED32(EXTRACTED32(pte_0, 1, 24), 31-6-24+1, 31-6);
+#endif
+#if (WITH_TARGET_WORD_BITSIZE == 64)
+ return INSERTED64(EXTRACTED64(pte_0, 0, 51), 63-7-52+1, 63-7);
+#endif
}
STATIC_INLINE_VM\
@@ -439,11 +457,11 @@ vm_create(core *physical)
if (nr_om_segment_tlb_entries
!= (1 << (om_segment_tlb_index_stop_bit
- om_segment_tlb_index_start_bit + 1)))
- error("new_vm() - internal error with om_segment constants\n");
+ error("internal error - vm_create - problem with om_segment constants\n");
if (nr_om_page_tlb_entries
!= (1 << (om_page_tlb_index_stop_bit
- om_page_tlb_index_start_bit + 1)))
- error("new_vm() - internal error with om_page constants\n");
+ error("internal error - vm_create - problem with om_page constants\n");
/* create the new vm register file */
virtual = ZALLOC(vm);
@@ -506,6 +524,12 @@ om_effective_to_virtual(om_map *map,
+ om_segment_tlb_index(ea));
#if (WITH_TARGET_WORD_BITSIZE == 32)
+ TRACE(trace_vm, ("ea=0x%lx - sr[%ld] - masked-vsid=0x%lx va=0x%lx%07lx\n",
+ (unsigned long)ea,
+ (long)om_segment_tlb_index(ea),
+ (unsigned long)segment_tlb_entry->masked_virtual_segment_id,
+ (unsigned long)EXTRACTED32(segment_tlb_entry->masked_virtual_segment_id, 31-6-24+1, 31-6),
+ (unsigned long)EXTRACTED32(ea, 4, 31)));
return segment_tlb_entry;
#endif
@@ -556,7 +580,7 @@ om_effective_to_virtual(om_map *map,
: om_access_any);
segment_tlb_entry->masked_virtual_segment_id =
INSERTED64(EXTRACTED64(segment_table_entry_dword_1, 0, 51),
- 18-13, 63-7); /* align ready for pte addr */
+ 18-13, 63-7); /* aligned ready for pte group addr */
return segment_tlb_entry;
}
}
@@ -602,11 +626,12 @@ om_virtual_to_real(om_map *map,
| (page_hash & map->page_table_hash_mask));
unsigned_word real_address_of_pte_0;
TRACE(trace_vm,
- ("ea=0x%lx - htab search - pteg=0x%lx htab=0x%lx mask=0x%lx hash=0x%lx\n",
- (long)ea, (long)real_address_of_pte_group,
+ ("ea=0x%lx - htab search %d - htab=0x%lx hash=0x%lx mask=0x%lx pteg=0x%lx\n",
+ (long)ea, current_hash,
map->real_address_of_page_table,
+ page_hash,
map->page_table_hash_mask,
- page_hash));
+ (long)real_address_of_pte_group));
for (real_address_of_pte_0 = real_address_of_pte_group;
real_address_of_pte_0 < (real_address_of_pte_group
+ sizeof_pte_group);
@@ -674,8 +699,7 @@ om_interrupt(cpu *processor,
instruction_storage_interrupt(processor, cia, reason);
break;
default:
- error("om_interrupt - unexpected access type %d, cia=0x%x, ea=0x%x\n",
- access, cia, ea);
+ error("internal error - om_interrupt - unexpected access type %d", access);
}
}
@@ -840,14 +864,15 @@ STATIC_INLINE_VM\
(void)
om_unpack_sr(vm *virtual,
sreg *srs,
- int which_sr)
+ int which_sr,
+ cpu *processor,
+ unsigned_word cia)
{
om_segment_tlb_entry *segment_tlb_entry = 0;
sreg new_sr_value = 0;
/* check register in range */
- if (which_sr < 0 || which_sr > nr_om_segment_tlb_entries)
- error("om_set_sr: segment register out of bounds\n");
+ ASSERT(which_sr >= 0 && which_sr < nr_om_segment_tlb_entries);
/* get the working values */
segment_tlb_entry = &virtual->segment_tlb.entry[which_sr];
@@ -855,8 +880,8 @@ om_unpack_sr(vm *virtual,
/* do we support this */
if (MASKED32(new_sr_value, 0, 0))
- error("om_ser_sr(): unsupported value of T in segment register %d\n",
- which_sr);
+ cpu_error(processor, cia, "unsupported value of T in segment register %d",
+ which_sr);
/* update info */
segment_tlb_entry->key[om_supervisor_state] = EXTRACTED32(new_sr_value, 1, 1);
@@ -866,7 +891,7 @@ om_unpack_sr(vm *virtual,
: om_access_any);
segment_tlb_entry->masked_virtual_segment_id =
INSERTED32(EXTRACTED32(new_sr_value, 8, 31),
- 7-5, 31-6); /* align ready for pte address */
+ 31-6-24+1, 31-6); /* aligned ready for pte group addr */
}
#endif
@@ -875,11 +900,14 @@ om_unpack_sr(vm *virtual,
STATIC_INLINE_VM\
(void)
om_unpack_srs(vm *virtual,
- sreg *srs)
+ sreg *srs,
+ cpu *processor,
+ unsigned_word cia)
{
int which_sr;
for (which_sr = 0; which_sr < nr_om_segment_tlb_entries; which_sr++) {
- om_unpack_sr(virtual, srs, which_sr);
+ om_unpack_sr(virtual, srs, which_sr,
+ processor, cia);
}
}
#endif
@@ -892,7 +920,10 @@ INLINE_VM\
vm_synchronize_context(vm *virtual,
spreg *sprs,
sreg *srs,
- msreg msr)
+ msreg msr,
+ /**/
+ cpu *processor,
+ unsigned_word cia)
{
/* enable/disable translation */
@@ -934,7 +965,8 @@ vm_synchronize_context(vm *virtual,
/* unpack the segment tlb registers */
#if (WITH_TARGET_WORD_BITSIZE == 32)
- om_unpack_srs(virtual, srs);
+ om_unpack_srs(virtual, srs,
+ processor, cia);
#endif
/* set up the XOR registers if the current endian mode conflicts
@@ -958,7 +990,7 @@ vm_synchronize_context(vm *virtual,
/* don't allow the processor to change endian modes */
if ((little_endian && CURRENT_TARGET_BYTE_ORDER != LITTLE_ENDIAN)
|| (!little_endian && CURRENT_TARGET_BYTE_ORDER != BIG_ENDIAN))
- error("vm_synchronize_context() - unsuported change of byte order\n");
+ cpu_error(processor, cia, "attempt to change hardwired byte order");
}
}
@@ -1023,7 +1055,7 @@ vm_translate(om_map *map,
processor, cia,
abort);
default:
- error("vm_translate() - unknown environment\n");
+ error("internal error - vm_translate - bad switch");
return 0;
}
}
@@ -1079,7 +1111,9 @@ INLINE_VM\
vm_data_map_read_buffer(vm_data_map *map,
void *target,
unsigned_word addr,
- unsigned nr_bytes)
+ unsigned nr_bytes,
+ cpu *processor,
+ unsigned_word cia)
{
unsigned count;
for (count = 0; count < nr_bytes; count++) {
@@ -1087,9 +1121,9 @@ vm_data_map_read_buffer(vm_data_map *map,
unsigned_word ea = addr + count;
unsigned_word ra = vm_translate(&map->translation,
ea, om_data_read,
- NULL, /*processor*/
- 0, /*cia*/
- 0); /*dont-abort*/
+ processor, /*processor*/
+ cia, /*cia*/
+ processor != NULL); /*abort?*/
if (ra == MASK(0, 63))
break;
if (WITH_XOR_ENDIAN)
@@ -1109,7 +1143,9 @@ vm_data_map_write_buffer(vm_data_map *map,
const void *source,
unsigned_word addr,
unsigned nr_bytes,
- int violate_read_only_section)
+ int violate_read_only_section,
+ cpu *processor,
+ unsigned_word cia)
{
unsigned count;
unsigned_1 byte;
@@ -1117,9 +1153,9 @@ vm_data_map_write_buffer(vm_data_map *map,
unsigned_word ea = addr + count;
unsigned_word ra = vm_translate(&map->translation,
ea, om_data_write,
- NULL/*processor*/,
- 0, /*cia*/
- 0); /*dont-abort*/
+ processor,
+ cia,
+ processor != NULL); /*abort?*/
if (ra == MASK(0, 63))
break;
if (WITH_XOR_ENDIAN)
diff --git a/gnu/dist/sim/ppc/vm.h b/gnu/dist/sim/ppc/vm.h
index 2cb83aa3358..b8c4c8c234b 100644
--- a/gnu/dist/sim/ppc/vm.h
+++ b/gnu/dist/sim/ppc/vm.h
@@ -1,6 +1,6 @@
/* This file is part of the program psim.
- Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
+ 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
@@ -60,14 +60,18 @@ INLINE_VM\
unsigned_word cia);
-/* block transfers */
+/* generic block transfers. Dependant on the presence of the
+ PROCESSOR arg, either returns the number of bytes transfered or (if
+ PROCESSOR is non NULL) aborts the simulation */
INLINE_VM\
(int) vm_data_map_read_buffer
(vm_data_map *map,
void *target,
unsigned_word addr,
- unsigned len);
+ unsigned len,
+ cpu *processor,
+ unsigned_word cia);
INLINE_VM\
(int) vm_data_map_write_buffer
@@ -75,7 +79,9 @@ INLINE_VM\
const void *source,
unsigned_word addr,
unsigned len,
- int violate_read_only_section);
+ int violate_read_only_section,
+ cpu *processor,
+ unsigned_word cia);
/* fetch the next instruction from memory */
@@ -129,7 +135,10 @@ INLINE_VM\
(vm *memory,
spreg *sprs,
sreg *srs,
- msreg msr);
+ msreg msr,
+ /**/
+ cpu *processor,
+ unsigned_word cia);
/* update vm data structures due to a TLB operation */
diff --git a/gnu/dist/sim/ppc/vm_n.h b/gnu/dist/sim/ppc/vm_n.h
index 113e9361ce5..9222ffa2cc0 100644
--- a/gnu/dist/sim/ppc/vm_n.h
+++ b/gnu/dist/sim/ppc/vm_n.h
@@ -1,6 +1,6 @@
/* This file is part of the program psim.
- Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
+ 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
@@ -58,9 +58,11 @@ vm_data_map_read_N(vm_data_map *map,
case NONSTRICT_ALIGNMENT:
{
unsigned_N val;
- if (vm_data_map_read_buffer(map, &val, ea, sizeof(unsigned_N))
- != sizeof(unsigned_N))
- alignment_interrupt(processor, cia, ea);
+ if (vm_data_map_read_buffer(map, &val, ea, sizeof(unsigned_N), processor, cia)
+ != sizeof(unsigned_N)) {
+ cpu_error(processor, cia, "misaligned %d byte read to 0x%lx failed",
+ sizeof(unsigned_N), (unsigned long)ea);
+ }
val = T2H_N(val);
if (WITH_MON & MONITOR_LOAD_STORE_UNIT) {
/* YUCK */
@@ -72,7 +74,7 @@ vm_data_map_read_N(vm_data_map *map,
return val;
}
default:
- error("unknown alignment support\n");
+ error("internal error - vm_data_map_read_N - bad switch");
return 0;
}
}
@@ -104,9 +106,11 @@ vm_data_map_write_N(vm_data_map *map,
case NONSTRICT_ALIGNMENT:
{
unsigned_N data = H2T_N(val);
- if (vm_data_map_write_buffer(map, &data, ea, sizeof(unsigned_N), 0)
- != sizeof(unsigned_N))
- alignment_interrupt(processor, cia, ea);
+ if (vm_data_map_write_buffer(map, &data, ea, sizeof(unsigned_N), 0, processor, cia)
+ != sizeof(unsigned_N)) {
+ cpu_error(processor, cia, "misaligned %d byte write to 0x%lx failed",
+ sizeof(unsigned_N), (unsigned long)ea);
+ }
if (WITH_MON & MONITOR_LOAD_STORE_UNIT) {
/* YUCK */
unsigned ra = vm_real_data_addr(map, ea, 1, processor, cia);
@@ -117,7 +121,7 @@ vm_data_map_write_N(vm_data_map *map,
}
break;
default:
- error("unknown alignment support\n");
+ error("internal error - vm_data_map_write_N - bad switch");
}
}
}
diff --git a/gnu/dist/sim/ppc/words.h b/gnu/dist/sim/ppc/words.h
index bcbaf564f63..c8fe3d676ce 100644
--- a/gnu/dist/sim/ppc/words.h
+++ b/gnu/dist/sim/ppc/words.h
@@ -38,6 +38,8 @@
*_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)
*/
@@ -97,4 +99,9 @@ typedef signed32 signed_word;
/* Other instructions */
typedef unsigned32 instruction_word;
+/* IEEE 1275 cell size - only support 32bit mode at present */
+typedef natural32 natural_cell;
+typedef unsigned32 unsigned_cell;
+typedef signed32 signed_cell;
+
#endif /* _WORDS_H_ */