aboutsummaryrefslogtreecommitdiff
path: root/sim/ppc
diff options
context:
space:
mode:
Diffstat (limited to 'sim/ppc')
-rw-r--r--sim/ppc/.Sanitize1
-rw-r--r--sim/ppc/ChangeLog14
-rw-r--r--sim/ppc/Makefile.in2
-rw-r--r--sim/ppc/PROBLEMS34
-rw-r--r--sim/ppc/README.psim279
-rw-r--r--sim/ppc/configure.in2
-rw-r--r--sim/ppc/device_table.c2
-rw-r--r--sim/ppc/emul_bugapi.c8
-rw-r--r--sim/ppc/emul_chirp.c762
-rw-r--r--sim/ppc/emul_generic.c133
-rw-r--r--sim/ppc/emul_generic.h158
11 files changed, 994 insertions, 401 deletions
diff --git a/sim/ppc/.Sanitize b/sim/ppc/.Sanitize
index 9a6c7a7..c0984a4 100644
--- a/sim/ppc/.Sanitize
+++ b/sim/ppc/.Sanitize
@@ -28,6 +28,7 @@ COPYING.LIB
ChangeLog
Makefile.in
README.psim
+PROBLEMS
basics.h
bits.c
bits.h
diff --git a/sim/ppc/ChangeLog b/sim/ppc/ChangeLog
index 2e62ae6..1e022a8 100644
--- a/sim/ppc/ChangeLog
+++ b/sim/ppc/ChangeLog
@@ -1,3 +1,17 @@
+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.
diff --git a/sim/ppc/Makefile.in b/sim/ppc/Makefile.in
index e5684bb..9e11058 100644
--- a/sim/ppc/Makefile.in
+++ b/sim/ppc/Makefile.in
@@ -417,7 +417,7 @@ distclean realclean: clean
rm -f TAGS Makefile config.cache config.status config.h stamp-h
maintainer-clean: distclean
- rm -f *~ ppc-config.h
+ rm -f *~ *.log ppc-config.h core *.core
Makefile: Makefile.in config.status
CONFIG_FILES=Makefile CONFIG_HEADERS= $(SHELL) ./config.status
diff --git a/sim/ppc/PROBLEMS b/sim/ppc/PROBLEMS
new file mode 100644
index 0000000..d88daa4
--- /dev/null
+++ b/sim/ppc/PROBLEMS
@@ -0,0 +1,34 @@
+ See the ChangeLog file looking for lines taged with the word FIXME.
+
+ 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.
+
+ 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.
+
+ Missing VEA system calls.
+
+ Missing or commented out instructions.
+
+ 64bit target untested.
+
+ 64bit host broken. For instance use of scanf "%x", &long long.
+
+ Event code for pending events from within signal handlers not
+ finished/tested.
+
+ 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.
+
+
diff --git a/sim/ppc/README.psim b/sim/ppc/README.psim
index 55136f9..cb34a37 100644
--- a/sim/ppc/README.psim
+++ b/sim/ppc/README.psim
@@ -1,5 +1,5 @@
- PSIM - model of a PowerPC platform
+ PSIM - model a PowerPC platform
Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>.
@@ -18,15 +18,17 @@
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-This directory contains the program PSIM that implements a model of a
-PowerPC platform. PSIM can either be built standalone or as part of
-the debugger GDB.
+This directory contains the source code to the program PSIM that
+implements a model of a PowerPC platform. PSIM can either be built
+standalone or as part of the debugger GDB.
What is PSIM?
- PSIM is an ANSI C program that models a PowerPC platform.
- The platform it implements can vary from:
+ PSIM is an ANSI C program that can be configured to model
+ various PowerPC platforms.
+
+ The platform that is modeled can vary from:
o A user program environment (UEA) complete
with emulated system calls
@@ -34,7 +36,17 @@ What is PSIM?
to
o A hardware platform with several processors
- interacting with each other and modeled hardware.
+ interacting with each other and various
+ modeled hardware devices.
+
+
+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.
What motivated PSIM?
@@ -155,31 +167,40 @@ What features does PSIM have?
ENDIAN SUPORT
- PSIM implements all of Big-endian, little-endian
- and PowerPC little endian (XOR endian).
+ 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 models
+ ISA models (Instruction Set Architecture)
- PSIM includes a model of UEA, VEA and OEA. This
+ PSIM includes a model of the UEA, VEA and OEA. This
inclues the time base registers (VEA) and HTAB
and BATS (OEA).
In addition, a preliminary model of the 64 bit
- PowerPC architecture is included.
+ PowerPC architecture is implemented.
Hardware
PSIM's internals are based around the concept
of a Device Tree. This tree intentionaly
resembles that of the Device Tree found in
- OpenBoot firmware. Psim is flexable enough
+ OpenBoot firmware. PSIM is flexable enough
to allow the user to fully configure the
actual hardware model from a device tree
- specification taken from a file.
+ specification that is read in from a file.
+
+ A user can either run a program using one of
+ PSIM's built in hardware models specify a
+ custom hardware model that should be simulated.
+
+ A user is also able to quickly add a model
+ of new hardware devices so that they can be
+ included in a custom hardware model.
- PSIM also contains several built in device
- trees.
-
Emulation
PSIM is able (UEA) to emulate UNIX calls
@@ -187,84 +208,97 @@ What features does PSIM have?
the ROM rom calls found in common firmware
(OpenBoot and BUGAPI).
- floating point
+ Floating point
Preliminary suport for floating point is included.
Real kernels don't need floating point.
-Can PSIM model a CHRP a.k.a. PowerPC Platform machine?
+Is PSIM CHRP Compliant?
+
+ No.
+
+ However, PSIM does include all the hooks that are needed to
+ construct a model of a CHRP compliant platform.
+
+ That is:
+
+ o OpenBoot client software
+
+ o OpenPIC interrupt controller
+
+ o Hooks to implement a RTAS interface
- No. but that is now one of its main objectives. (Did you notice
- it was written PowerPC Platform instead of PowerPC platform?).
+ o the ability to add a model of each of the
+ hardware devices required by a CHRP compliant
+ desktop.
How do I build PSIM?
- To build PSIM you will need the following:
+ To build PSIM you will need the following files:
+
gdb-4.15.tar.gz From your favorite GNU ftp site.
I've also tested psim-951016 with
- gdb-4.15.1.
+ gdb-4.15.1. If you would prefer
+ a graphical development environment
+ then PSIM can also be built with
+ gdbtk.
ftp://ftp.ci.com.au/pub/clayton/README.pim
This file.
+
ftp://ftp.ci.com.au/pub/clayton/gdb-4.15+psim-951016.diff.gz
This contains a few minor patches to
gdb-4.15 so that will include psim
when it is built.
- ftp://ftp.ci.com.au/pub/clayton/gdb-4.15+psim-951016.tar.gz
-
- This contains the psim files propper.
ftp://ftp.ci.com.au/pub/clayton/psim-test-951016.tar.gz
(Optional) A scattering of pre-compiled
programs that run under the simulator.
+
+ ftp://ftp.ci.com.au/pub/clayton/gdb-4.15+psim-951016.tar.gz
+
+ This contains the psim files proper.
+
+
gcc Again available from your favorite
GNU ftp site.
+
patch Sun's patch behaves a little wierd
and doesn't appear to like creating
- empty files.
-
-
- Since PSIM is still being developed, from time to time, to meet
- a specific analysts needsfurther psim snap shots are occasionally
- made available. These snapshots may or may not work with GDB-4.15.
- Several of the more recent snapshots are:
+ empty files. You may want to consider
+ installing gnu's patch.
- ftp://ftp.ci.com.au/pub/clayton/psim-951218.tar.gz
- Hopefully merges in Michael stuff
- with mine, adds multiple emulations
- (OpenBoot and NetBSD), revamps
- inline stuff, rearanges devices so
- that phandls and ihandles can be
- implemented.
+ In addition, I'm slowly building up a set of useful patches
+ to gdb-4.15 that are useful. You will want to also apply
+ these patches:
- ftp://ftp.ci.com.au/pub/clayton/psim-951203.tar.gz
- A good snapshot
+ ftp://ftp.ci.com.au/pub/clayton/gdb-4.15+attach.diff.gz
- This includes extensions from Michael
- Meissner that add monitoring of the
- PowerPC's register and bus architectures.
+ Patch to gdb that allows the `attach'
+ command to be used when connecting to a
+ simulator.
+ See that file for more information.
- ftp://ftp.ci.com.au/pub/clayton/psim-test-951218.tar.gz
+ ftp://ftp.ci.com.au/pub/clayton/gdb-4.15+note.diff.gz
- Prebuilt test programs for PSIM.
- Includes examples of UEA, VEA and
- OEA code.
- Requires gcc-2.7.2 and binutils-2.6
- to rebuild.
+ Patch to gdb's bfd that adds basic support
+ for a .note section. OpenBoot makes
+ use of a .note section when loading a
+ boot image.
Procedure:
@@ -294,6 +328,15 @@ How do I build PSIM?
$ gunzip < ../gdb-4.15+psim-951016.tar.gz | tar tvf -
$ gunzip < ../gdb-4.15+psim-951016.tar.gz | tar xvf -
+ You may also want to consider applying the `attach' and
+ `note' patches that are available vis:
+
+ $ gunzip < ../gdb-4.15+attach.diff.gz | more
+ $ gunzip < ../gdb-4.15+attach.diff.gz | patch -p
+
+ $ gunzip < ../gdb-4.15+note.diff.gz | more
+ $ gunzip < ../gdb-4.15+note.diff.gz | patch -p
+
3. Configure gdb
@@ -329,24 +372,97 @@ How do I build PSIM?
$ cp sim/ppc/run ~/bin/powerpc-unknown-eabisim-run
+Is there a more recent version of PSIM and if so, how would I build it?
+
+ A PSIM is an ongoing development, occasional snapshots
+ (that include new features) are made available. Several of
+ the more recent snapshots are:
+
+ ftp://ftp.ci.com.au/pub/clayton/psim-951219.tar.gz
+
+ Hopefully merges in Michael stuff
+ with mine, adds multiple emulations
+ (OpenBoot and NetBSD), revamps
+ inline stuff, rearanges devices so
+ that phandls and ihandles can be
+ implemented.
+
+ ftp://ftp.ci.com.au/pub/clayton/psim-951203.tar.gz
+
+ A good snapshot
+
+ This includes extensions from Michael
+ Meissner that add monitoring of the
+ PowerPC's register and bus architectures.
+
+
+ To build/install one of these snapshots, you replace the
+ current gdb/sim/ppc directory with the one in the update,
+ re-configure and rebuild.
+
+ Procedure:
+
+ 0. A starting point
+
+ $ cd gdb-4.15
+
+
+ 1. Remove the old psim directory
+
+ $ mv sim/ppc sim/old.ppc
+
+
+ 2. Unpack the new one
+
+ $ gunzip < ../psim-960105.tar.gz | tar tf -
+ $ gunzip < ../psim-960105.tar.gz | tar tf -
+
+
+ 3. Reconfig/rebuild (as seen above):
+
+ $ CC=gcc ./configure --target=powerpc-unknown-eabisim
+ $ make CC=gcc
+
+
+Are there any example programs that can be run on PSIM?
+
+ Psim has a simple test suite that is used to ensure
+ that fixes do not introduce new bugs. This test suite
+ like psim is updated:
+
+ ftp://ftp.ci.com.au/pub/clayton/psim-test-951218.tar.gz
+
+ Prebuilt test programs for PSIM.
+ Includes examples of UEA, VEA and
+ OEA code.
+ Requires gcc-2.7.2 and binutils-2.6
+ to rebuild.
+
+ ftp://ftp.ci.com.au/pub/clayton/psim-test-951016.tar.gz
+
+ (Optional) A scattering of pre-compiled
+ programs that run under the simulator.
+
+
How do I use the simulator?
- (I assume that you've unpacked the psim-test archive).
+ I assume that you've unpacked a psim-test archive.
+
1. As a standalone program
Print out the users environment:
- $ powerpc-unknown-eabisim-run envp
+ $ powerpc-unknown-eabisim-run psim-test/uea/envp
Print out the arguments:
- $ powerpc-unknown-eabisim-run argv a b c
+ $ powerpc-unknown-eabisim-run psim-test/uea/argv a b c
Check that sbrk works:
- $ powerpc-unknown-eabisim-run break
+ $ powerpc-unknown-eabisim-run psim-test/uea/break
2. Example of running GDB:
@@ -354,7 +470,7 @@ How do I use the simulator?
The main thing to note is that before you can run the simulator
you must enable it. The example below illustrates this:
- $ powerpc-unknown-eabisim-gdb envp
+ $ powerpc-unknown-eabisim-gdb psim-test/uea/envp
(gdb) target sim
(gdb) load
(gdb) break main
@@ -364,6 +480,21 @@ How do I use the simulator?
.
+ 3. Using a device tree as a description of a machine
+ (I assume that you have applied the attach bug).
+
+ $ cd psim-test/tree
+ $ powerpc-unknown-eabisim-gdb
+ (gdb) target sim
+ (gdb) attach device-tree
+ (gdb) run
+
+ or
+
+ $ cd psim-test/tree
+ $ powerpc-unknown-eabisim-run device-tree
+
+
Where do I send bugs or report problems?
There is a mailing list (subscribe through majordomo@ci.com.au) (that
@@ -376,40 +507,10 @@ Where do I send bugs or report problems?
that e-mail list.
-Are there any known problems?
-
- See the ChangeLog file looking for lines taged with the word FIXME.
-
- 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.
-
- 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.
-
- Missing VEA system calls.
-
- Missing or commented out instructions.
-
- 64bit target untested.
-
- 64bit host broken. For instance use of scanf "%x", &long long.
-
- Event code for pending events from within signal handlers not
- finished/tested.
-
- Better and more devices.
+Does PSIM have any limitations or problems?
- 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.
+ See the file PROBLEMS (included in the distribution) for any
+ outstanding issues.
Who helped?
diff --git a/sim/ppc/configure.in b/sim/ppc/configure.in
index acdb679..9bf61e2 100644
--- a/sim/ppc/configure.in
+++ b/sim/ppc/configure.in
@@ -73,7 +73,7 @@ AC_ARG_ENABLE(sim-switch,
esac
if test x"$silent" != x"yes" && test x"$sim_switch" != x""; then
echo "Setting switch flags = $sim_switch" 6>&1
-fi],[sim_switch="-s";
+fi],[sim_switch="";
if test x"$silent" != x"yes"; then
echo "Setting switch flags = $sim_switch" 6>&1
fi])dnl
diff --git a/sim/ppc/device_table.c b/sim/ppc/device_table.c
index e723085..15ef95a 100644
--- a/sim/ppc/device_table.c
+++ b/sim/ppc/device_table.c
@@ -685,7 +685,7 @@ register_init(device *me,
if (isdigit(name[0]) && name[1] == '.') {
processor = atol(name);
name += 2;
- DTRACE(register, ("%ld.%s=0x%lx\n", (long)name, processor, (unsigned long)value));
+ DTRACE(register, ("%d.%s=0x%lx\n", processor, name, (unsigned long)value));
}
else {
processor = -1;
diff --git a/sim/ppc/emul_bugapi.c b/sim/ppc/emul_bugapi.c
index 252c3ce..f325901 100644
--- a/sim/ppc/emul_bugapi.c
+++ b/sim/ppc/emul_bugapi.c
@@ -156,15 +156,15 @@ emul_bugapi_create(device *root,
device_tree_add_found_uw_u_u(init, "",
"data",
OEA_SYSTEM_CALL_ADDRESS,
- 4, 0x1); /*emul-call*/
+ 4, emul_call_instruction);
device_tree_add_found_uw_u_u(init, "",
"data",
OEA_SYSTEM_CALL_ADDRESS + 4,
- 4, 0x4c000064); /*rfi*/
+ 4, emul_rfi_instruction);
device_tree_add_found_uw_u_u(init, "",
"data",
OEA_STALL_CPU_LOOP_ADDRESS,
- 4, 0x48000000); /*b .*/
+ 4, emul_loop_instruction);
}
{
device *init_stack = device_tree_add_found(init, "", "stack");
@@ -204,7 +204,7 @@ emul_bugapi_instruction_call(cpu *processor,
return 0;
switch (call_id) {
case _OUTCHR:
- printf_filtered("%c", cpu_registers(processor)->gpr[3]);
+ printf_filtered("%c", (char)cpu_registers(processor)->gpr[3]);
break;
case _OUTLN:
printf_filtered("\n");
diff --git a/sim/ppc/emul_chirp.c b/sim/ppc/emul_chirp.c
index 9c20262..9eb3a4e 100644
--- a/sim/ppc/emul_chirp.c
+++ b/sim/ppc/emul_chirp.c
@@ -74,11 +74,135 @@ struct _os_emul_data {
unsigned_word catching_instruction_ea;
cap *phandles;
device *root;
+ chirp_services *services;
};
+/* Read in the argument list and make the most basic check that number
+ of argumnets are consistent with what was expected */
+
+static int
+chirp_read_args(void *args,
+ int sizeof_args,
+ int n_args,
+ int n_returns,
+ os_emul_data *data,
+ cpu *processor,
+ unsigned_word cia)
+{
+ struct base_args {
+ unsigned32 service;
+ unsigned32 n_args;
+ unsigned32 n_returns;
+ } *base;
+ emul_read_buffer(args, data->arguments,
+ sizeof_args,
+ processor, cia);
+ base = (struct base_args*)args;
+ if (T2H_4(base->n_args) != n_args || T2H_4(base->n_returns) != n_returns) {
+ TRACE(trace_os_emul, ("invalid nr of args - n_args=%ld, n_returns=%ld\n",
+ (long)T2H_4(base->n_args),
+ (long)T2H_4(base->n_returns)));
+ return -1;
+ }
+ return 0;
+}
+
+
/* OpenBoot emulation functions */
+/* client interface */
+
+static int
+chirp_emul_test(os_emul_data *data,
+ cpu *processor,
+ unsigned_word cia)
+{
+ struct test_args {
+ unsigned32 service;
+ unsigned32 n_args;
+ unsigned32 n_returns;
+ /*in*/
+ unsigned32 name; /*string*/
+ /*out*/
+ unsigned32 missing;
+ } args;
+ char name[32];
+ chirp_services *service = data->services;
+ /* read in the arguments */
+ if (chirp_read_args(&args, sizeof(args), 1, 1, data, processor, cia))
+ return -1;
+ emul_read_string(name, T2H_4(args.name), sizeof(name),
+ processor, cia);
+ TRACE(trace_os_emul, ("test - in - name=`%s'\n", name));
+ /* see if we know about the service */
+ while (service->name != NULL && strcmp(service->name, name) != 0) {
+ service++;
+ }
+ if (service->name == NULL)
+ args.missing = -1;
+ else
+ args.missing = 0;
+ /* write the arguments back out */
+ TRACE(trace_os_emul, ("test - out - missing=%ld\n",
+ (long)args.missing));
+ emul_write_buffer(&args, data->arguments,
+ sizeof(args),
+ processor, cia);
+ return 0;
+}
+
+
+/* Device tree */
+
+static int
+chirp_emul_peer(os_emul_data *data,
+ cpu *processor,
+ unsigned_word cia)
+{
+ struct peer_args {
+ unsigned32 service;
+ unsigned32 n_args;
+ unsigned32 n_returns;
+ /*in*/
+ unsigned32 phandle;
+ /*out*/
+ unsigned32 sibling_phandle;
+ } args;
+ device *dev;
+ device *sibling_dev = NULL;
+ /* read in the arguments */
+ if (chirp_read_args(&args, sizeof(args), 1, 1, data, processor, cia))
+ return -1;
+ dev = cap_internal(data->phandles, args.phandle);
+ TRACE(trace_os_emul, ("peer - in - phandle=0x%lx(0x%lx`%s')\n",
+ (unsigned long)T2H_4(args.phandle),
+ (unsigned long)dev,
+ (dev == NULL ? "" : device_name(dev))));
+ /* find the peer */
+ if (dev == NULL && args.phandle != 0)
+ return -1;
+ if (args.phandle == 0)
+ sibling_dev = data->root;
+ else
+ sibling_dev = device_sibling(dev);
+ if (sibling_dev == NULL)
+ args.sibling_phandle = 0;
+ else
+ args.sibling_phandle = cap_external(data->phandles, sibling_dev);
+ /* write the arguments back out */
+ TRACE(trace_os_emul, ("peer - out - sibling_phandle=0x%lx(0x%lx`%s')\n",
+ (unsigned long)T2H_4(args.sibling_phandle),
+ (unsigned long)sibling_dev,
+ (sibling_dev == NULL
+ ? ""
+ : device_name(sibling_dev))));
+ emul_write_buffer(&args, data->arguments,
+ sizeof(args),
+ processor, cia);
+ return 0;
+}
+
static int
chirp_emul_child(os_emul_data *data,
cpu *processor,
@@ -95,21 +219,15 @@ chirp_emul_child(os_emul_data *data,
} args;
device *dev;
device *child_dev;
- emul_read_buffer(&args, data->arguments,
- sizeof(args),
- processor, cia);
- if (T2H_4(args.n_args) != 1 || T2H_4(args.n_returns) != 1) {
- TRACE(trace_os_emul, ("child - invalid nr - n_args=%ld, n_returns=%ld\n",
- (long)T2H_4(args.n_args),
- (long)T2H_4(args.n_returns)));
+ /* read the arguments in */
+ if (chirp_read_args(&args, sizeof(args), 1, 1, data, processor, cia))
return -1;
- }
- /* read in the arguments */
dev = cap_internal(data->phandles, args.phandle);
TRACE(trace_os_emul, ("child - in - phandle=0x%lx(0x%lx`%s')\n",
(unsigned long)T2H_4(args.phandle),
(unsigned long)dev,
(dev == NULL ? "" : device_name(dev))));
+ /* find a child */
if (dev == (device*)0)
return -1;
child_dev = device_child(dev);
@@ -117,6 +235,7 @@ chirp_emul_child(os_emul_data *data,
args.child_phandle = 0;
else
args.child_phandle = cap_external(data->phandles, child_dev);
+ /* write the result out */
TRACE(trace_os_emul, ("child - out - child_phandle=0x%lx(0x%lx`%s')\n",
(unsigned long)T2H_4(args.child_phandle),
(unsigned long)child_dev,
@@ -128,55 +247,101 @@ chirp_emul_child(os_emul_data *data,
}
static int
-chirp_emul_exit(os_emul_data *data,
- cpu *processor,
- unsigned_word cia)
+chirp_emul_parent(os_emul_data *data,
+ cpu *processor,
+ unsigned_word cia)
{
- cpu_halt(processor, cia, was_exited, 0); /* always succeeds */
+ struct parent_args {
+ unsigned32 service;
+ unsigned32 n_args;
+ unsigned32 n_returns;
+ /*in*/
+ unsigned32 phandle;
+ /*out*/
+ unsigned32 parent_phandle;
+ } args;
+ device *dev;
+ device *parent_dev;
+ /* read the args in */
+ if (chirp_read_args(&args, sizeof(args), 1, 1, data, processor, cia))
+ return -1;
+ dev = cap_internal(data->phandles, args.phandle);
+ TRACE(trace_os_emul, ("parent - in - phandle=0x%lx(0x%lx`%s')\n",
+ (unsigned long)T2H_4(args.phandle),
+ (unsigned long)dev,
+ (dev == NULL ? "" : device_name(dev))));
+ /* find a parent */
+ if (dev == (device*)0)
+ return -1;
+ parent_dev = device_parent(dev);
+ if (parent_dev == NULL)
+ args.parent_phandle = 0;
+ else
+ args.parent_phandle = cap_external(data->phandles, parent_dev);
+ /* return the result */
+ TRACE(trace_os_emul, ("parent - out - parent_phandle=0x%lx(0x%lx`%s')\n",
+ (unsigned long)T2H_4(args.parent_phandle),
+ (unsigned long)parent_dev,
+ (parent_dev == NULL ? "" : device_name(parent_dev))));
+ emul_write_buffer(&args, data->arguments,
+ sizeof(args),
+ processor, cia);
return 0;
}
static int
-chirp_emul_finddevice(os_emul_data *data,
+chirp_emul_instance_to_package(os_emul_data *data,
+ cpu *processor,
+ unsigned_word cia)
+{
+ error("chirp: instance-to-package unimplemented\n");
+ return 0;
+}
+
+static int
+chirp_emul_getproplen(os_emul_data *data,
cpu *processor,
unsigned_word cia)
{
- struct finddevice_args {
+ struct getproplen_args {
unsigned32 service;
unsigned32 n_args;
unsigned32 n_returns;
/*in*/
- unsigned32 device_specifier;
- /*out*/
unsigned32 phandle;
+ unsigned32 name;
+ /*out*/
+ unsigned32 proplen;
} args;
- char device_specifier[1024];
+ char name[32];
device *dev;
- emul_read_buffer(&args, data->arguments,
- sizeof(args),
- processor, cia);
- if (T2H_4(args.n_args) != 1 || T2H_4(args.n_returns) != 1) {
- TRACE(trace_os_emul, ("finddevice - invalid nr - n_args=%ld, n_returns=%ld\n",
- (long)T2H_4(args.n_args),
- (long)T2H_4(args.n_returns)));
+ const device_property *prop;
+ /* read the args in */
+ if (chirp_read_args(&args, sizeof(args), 2, 1, data, processor, cia))
return -1;
- }
- emul_read_string(device_specifier,
- T2H_4(args.device_specifier),
- sizeof(device_specifier),
- processor, cia);
- TRACE(trace_os_emul, ("finddevice - in - device_specifier=`%s'\n",
- device_specifier));
- dev = device_tree_find_device(data->root,
- device_specifier);
+ dev = cap_internal(data->phandles, args.phandle);
+ /* find our prop and get its length */
if (dev == (device*)0)
- args.phandle = -1;
- else
- args.phandle = cap_external(data->phandles, dev);
- TRACE(trace_os_emul, ("finddevice - out - phandle=0x%lx(0x%lx`%s')\n",
+ return -1;
+ emul_read_string(name,
+ T2H_4(args.name),
+ sizeof(name),
+ processor, cia);
+ TRACE(trace_os_emul, ("getproplen - in - phandle=0x%lx(0x%lx`%s') name=`%s'\n",
(unsigned long)T2H_4(args.phandle),
(unsigned long)dev,
- (dev == NULL ? "" : device_name(dev))));
+ (dev == NULL ? "" : device_name(dev)),
+ name));
+ prop = device_find_property(dev, name);
+ if (prop == (device_property*)0) {
+ args.proplen = -1;
+ }
+ else {
+ args.proplen = H2T_4(prop->sizeof_array);
+ }
+ /* return the result */
+ TRACE(trace_os_emul, ("getproplen - out - proplen=%ld\n",
+ (unsigned long)T2H_4(args.proplen)));
emul_write_buffer(&args, data->arguments,
sizeof(args),
processor, cia);
@@ -203,16 +368,9 @@ chirp_emul_getprop(os_emul_data *data,
char name[32];
device *dev;
const device_property *prop;
- emul_read_buffer(&args, data->arguments,
- sizeof(args),
- processor, cia);
- if (T2H_4(args.n_args) != 4 || T2H_4(args.n_returns) != 1) {
- TRACE(trace_os_emul, ("getprop - invalid nr - n_args=%ld, n_returns=%ld\n",
- (long)T2H_4(args.n_args),
- (long)T2H_4(args.n_returns)));
+ /* read in the args */
+ if (chirp_read_args(&args, sizeof(args), 4, 1, data, processor, cia))
return -1;
- }
- /* read in the arguments */
dev = cap_internal(data->phandles, args.phandle);
emul_read_string(name,
T2H_4(args.name),
@@ -225,6 +383,7 @@ chirp_emul_getprop(os_emul_data *data,
name,
(unsigned long)T2H_4(args.buf),
(unsigned long)T2H_4(args.buflen)));
+ /* get the property */
if (dev == (device*)0)
return -1;
prop = device_find_property(dev, name);
@@ -248,6 +407,7 @@ chirp_emul_getprop(os_emul_data *data,
default:
break;
}
+ /* write back the result */
TRACE(trace_os_emul, ("getprop - out - size=%ld\n",
(unsigned long)T2H_4(args.size)));
emul_write_buffer(&args, data->arguments,
@@ -257,54 +417,69 @@ chirp_emul_getprop(os_emul_data *data,
}
static int
-chirp_emul_getproplen(os_emul_data *data,
+chirp_emul_nextprop(os_emul_data *data,
+ cpu *processor,
+ unsigned_word cia)
+{
+ error("chirp: nextprop not implemented\n");
+ return 0;
+}
+
+static int
+chirp_emul_setprop(os_emul_data *data,
+ cpu *processor,
+ unsigned_word cia)
+{
+ error("chirp: setprop not implemented\n");
+ return 0;
+}
+
+static int
+chirp_emul_canon(os_emul_data *data,
+ cpu *processor,
+ unsigned_word cia)
+{
+ error("chirp: canon not implemented\n");
+ return 0;
+}
+
+static int
+chirp_emul_finddevice(os_emul_data *data,
cpu *processor,
unsigned_word cia)
{
- struct getproplen_args {
+ struct finddevice_args {
unsigned32 service;
unsigned32 n_args;
unsigned32 n_returns;
/*in*/
- unsigned32 phandle;
- unsigned32 name;
+ unsigned32 device_specifier;
/*out*/
- unsigned32 proplen;
+ unsigned32 phandle;
} args;
- char name[32];
+ char device_specifier[1024];
device *dev;
- const device_property *prop;
- emul_read_buffer(&args, data->arguments,
- sizeof(args),
- processor, cia);
- if (T2H_4(args.n_args) != 2 || T2H_4(args.n_returns) != 1) {
- TRACE(trace_os_emul, ("getproplen - invalid nr - n_args=%ld, n_returns=%ld\n",
- (long)T2H_4(args.n_args),
- (long)T2H_4(args.n_returns)));
+ /* get the args */
+ if (chirp_read_args(&args, sizeof(args), 1, 1, data, processor, cia))
return -1;
- }
- /* read in the arguments */
- dev = cap_internal(data->phandles, args.phandle);
- if (dev == (device*)0)
- return -1;
- emul_read_string(name,
- T2H_4(args.name),
- sizeof(name),
+ emul_read_string(device_specifier,
+ T2H_4(args.device_specifier),
+ sizeof(device_specifier),
processor, cia);
- TRACE(trace_os_emul, ("getproplen - in - phandle=0x%lx(0x%lx`%s') name=`%s'\n",
+ TRACE(trace_os_emul, ("finddevice - in - device_specifier=`%s'\n",
+ device_specifier));
+ /* find the device */
+ dev = device_tree_find_device(data->root,
+ device_specifier);
+ if (dev == (device*)0)
+ args.phandle = -1;
+ else
+ args.phandle = cap_external(data->phandles, dev);
+ /* return its phandle */
+ TRACE(trace_os_emul, ("finddevice - out - phandle=0x%lx(0x%lx`%s')\n",
(unsigned long)T2H_4(args.phandle),
(unsigned long)dev,
- (dev == NULL ? "" : device_name(dev)),
- name));
- prop = device_find_property(dev, name);
- if (prop == (device_property*)0) {
- args.proplen = -1;
- }
- else {
- args.proplen = H2T_4(prop->sizeof_array);
- }
- TRACE(trace_os_emul, ("getproplen - out - proplen=%ld\n",
- (unsigned long)T2H_4(args.proplen)));
+ (dev == NULL ? "" : device_name(dev))));
emul_write_buffer(&args, data->arguments,
sizeof(args),
processor, cia);
@@ -312,6 +487,36 @@ chirp_emul_getproplen(os_emul_data *data,
}
static int
+chirp_emul_instance_to_path(os_emul_data *data,
+ cpu *processor,
+ unsigned_word cia)
+{
+ error("chirp: instance_to_path not implemented\n");
+ return 0;
+}
+
+static int
+chirp_emul_package_to_path(os_emul_data *data,
+ cpu *processor,
+ unsigned_word cia)
+{
+ error("chirp: package_to_path not implemented\n");
+ return 0;
+}
+
+static int
+chirp_emul_call_method(os_emul_data *data,
+ cpu *processor,
+ unsigned_word cia)
+{
+ error("chirp: call-method implemented\n");
+ return 0;
+}
+
+
+/* Device I/O */
+
+static int
chirp_emul_open(os_emul_data *data,
cpu *processor,
unsigned_word cia)
@@ -326,24 +531,19 @@ chirp_emul_open(os_emul_data *data,
unsigned32 ihandle;
} args;
char name[1024];
- emul_read_buffer(&args, data->arguments,
- sizeof(args),
- processor, cia);
- if (T2H_4(args.n_args) != 1 || T2H_4(args.n_returns) != 1) {
- TRACE(trace_os_emul, ("open - invalid nr - n_args=%ld, n_returns=%ld\n",
- (long)T2H_4(args.n_args),
- (long)T2H_4(args.n_returns)));
+ /* read the args */
+ if (chirp_read_args(&args, sizeof(args), 1, 1, data, processor, cia))
return -1;
- }
- /* read in the arguments */
emul_read_string(name,
T2H_4(args.device_specifier),
sizeof(name),
processor, cia);
TRACE(trace_os_emul, ("open - in - device_specifier=`%s'\n",
name));
+ /* open the device */
printf_filtered("OpenBoot - open unimplemented for %s\n", name);
args.ihandle = -1;
+ /* return the ihandle result */
TRACE(trace_os_emul, ("open - out - ihandle=0x%lx\n",
(unsigned long)T2H_4(args.ihandle)));
emul_write_buffer(&args, data->arguments,
@@ -353,98 +553,59 @@ chirp_emul_open(os_emul_data *data,
}
static int
-chirp_emul_parent(os_emul_data *data,
- cpu *processor,
- unsigned_word cia)
+chirp_emul_close(os_emul_data *data,
+ cpu *processor,
+ unsigned_word cia)
{
- struct parent_args {
- unsigned32 service;
- unsigned32 n_args;
- unsigned32 n_returns;
- /*in*/
- unsigned32 phandle;
- /*out*/
- unsigned32 parent_phandle;
- } args;
- device *dev;
- device *parent_dev;
- emul_read_buffer(&args, data->arguments,
- sizeof(args),
- processor, cia);
- if (T2H_4(args.n_args) != 1 || T2H_4(args.n_returns) != 1) {
- TRACE(trace_os_emul, ("parent - invalid nr - n_args=%ld, n_returns=%ld\n",
- (long)T2H_4(args.n_args),
- (long)T2H_4(args.n_returns)));
- return -1;
- }
- /* read in the arguments */
- dev = cap_internal(data->phandles, args.phandle);
- TRACE(trace_os_emul, ("parent - in - phandle=0x%lx(0x%lx`%s')\n",
- (unsigned long)T2H_4(args.phandle),
- (unsigned long)dev,
- (dev == NULL ? "" : device_name(dev))));
- if (dev == (device*)0)
- return -1;
- parent_dev = device_parent(dev);
- if (parent_dev == NULL)
- args.parent_phandle = 0;
- else
- args.parent_phandle = cap_external(data->phandles, parent_dev);
- TRACE(trace_os_emul, ("parent - out - parent_phandle=0x%lx(0x%lx`%s')\n",
- (unsigned long)T2H_4(args.parent_phandle),
- (unsigned long)parent_dev,
- (parent_dev == NULL ? "" : device_name(parent_dev))));
- emul_write_buffer(&args, data->arguments,
- sizeof(args),
- processor, cia);
+ error("chirp: close not implemented\n");
return 0;
}
static int
-chirp_emul_peer(os_emul_data *data,
+chirp_emul_read(os_emul_data *data,
cpu *processor,
unsigned_word cia)
{
- struct peer_args {
+ struct read_args {
unsigned32 service;
unsigned32 n_args;
unsigned32 n_returns;
/*in*/
- unsigned32 phandle;
+ unsigned32 ihandle;
+ unsigned32 addr;
+ unsigned32 len;
/*out*/
- unsigned32 sibling_phandle;
+ unsigned32 actual;
} args;
- device *dev;
- device *sibling_dev = NULL;
- emul_read_buffer(&args, data->arguments,
- sizeof(args),
- processor, cia);
- if (T2H_4(args.n_args) != 1 || T2H_4(args.n_returns) != 1) {
- TRACE(trace_os_emul, ("peer - invalid nr - n_args=%ld, n_returns=%ld\n",
- (long)T2H_4(args.n_args),
- (long)T2H_4(args.n_returns)));
+ char buf[1024];
+ int actual;
+ /* read the args */
+ if (chirp_read_args(&args, sizeof(args), 3, 1, data, processor, cia))
return -1;
+ TRACE(trace_os_emul, ("read - in - ihandle=0x%lx addr=0x%lx len=%ld\n",
+ (unsigned long)args.ihandle,
+ (unsigned long)T2H_4(args.addr),
+ (unsigned long)T2H_4(args.len)));
+ /* do the read */
+ actual = T2H_4(args.len);
+ if (actual >= sizeof(buf))
+ actual = sizeof(buf) - 1;
+ actual = read(BE2H_4(args.ihandle), buf, actual);
+ if (actual >= 0) {
+ emul_write_buffer(buf,
+ T2H_4(args.addr),
+ actual,
+ processor, cia);
+ args.actual = H2T_4(actual);
+ buf[actual] = '\0';
}
- /* read in the arguments */
- dev = cap_internal(data->phandles, args.phandle);
- TRACE(trace_os_emul, ("peer - in - phandle=0x%lx(0x%lx`%s')\n",
- (unsigned long)T2H_4(args.phandle),
- (unsigned long)dev,
- (dev == NULL ? "" : device_name(dev))));
- if (dev == NULL && args.phandle != 0)
- return -1;
- if (args.phandle == 0)
- sibling_dev = data->root;
- else
- sibling_dev = device_sibling(dev);
- if (sibling_dev == NULL)
- args.sibling_phandle = 0;
- else
- args.sibling_phandle = cap_external(data->phandles, sibling_dev);
- TRACE(trace_os_emul, ("peer - out - sibling_phandle=0x%lx(0x%lx`%s')\n",
- (unsigned long)T2H_4(args.sibling_phandle),
- (unsigned long)sibling_dev,
- (sibling_dev == NULL ? "" : device_name(sibling_dev))));
+ else {
+ args.actual = 0;
+ }
+ /* return the result */
+ TRACE(trace_os_emul, ("read - out - actual=%ld `%s'\n",
+ (long)T2H_4(args.actual),
+ (actual >= 0 ? buf : "")));
emul_write_buffer(&args, data->arguments,
sizeof(args),
processor, cia);
@@ -452,11 +613,11 @@ chirp_emul_peer(os_emul_data *data,
}
static int
-chirp_emul_read(os_emul_data *data,
+chirp_emul_write(os_emul_data *data,
cpu *processor,
unsigned_word cia)
{
- struct read_args {
+ struct write_args {
unsigned32 service;
unsigned32 n_args;
unsigned32 n_returns;
@@ -469,16 +630,9 @@ chirp_emul_read(os_emul_data *data,
} args;
char buf[1024];
int actual;
- emul_read_buffer(&args, data->arguments,
- sizeof(args),
- processor, cia);
- if (T2H_4(args.n_args) != 3 || T2H_4(args.n_returns) != 1) {
- TRACE(trace_os_emul, ("read - invalid nr - n_args=%ld, n_returns=%ld\n",
- (long)T2H_4(args.n_args),
- (long)T2H_4(args.n_returns)));
+ /* get the args */
+ if (chirp_read_args(&args, sizeof(args), 3, 1, data, processor, cia))
return -1;
- }
- /* read in the arguments */
actual = T2H_4(args.len);
if (actual >= sizeof(buf))
actual = sizeof(buf) - 1;
@@ -487,12 +641,16 @@ chirp_emul_read(os_emul_data *data,
actual,
processor, cia);
buf[actual] = '\0';
- /* read it in */
- TRACE(trace_os_emul, ("read - in - ihandle=0x%lx `%s' (%ld)\n",
+ TRACE(trace_os_emul, ("write - in - ihandle=0x%lx `%s' (%ld)\n",
(unsigned long)args.ihandle, buf, (long)actual));
- read(BE2H_4(args.ihandle), buf, actual);
- args.actual = H2T_4(actual);
- TRACE(trace_os_emul, ("read - out - actual=%ld\n",
+ /* write it out */
+ actual = write(BE2H_4(args.ihandle), buf, actual);
+ if (actual < 0)
+ args.actual = 0;
+ else
+ args.actual = H2T_4(actual);
+ /* return the result */
+ TRACE(trace_os_emul, ("write - out - actual=%ld\n",
(long)T2H_4(args.actual)));
emul_write_buffer(&args, data->arguments,
sizeof(args),
@@ -501,48 +659,130 @@ chirp_emul_read(os_emul_data *data,
}
static int
-chirp_emul_write(os_emul_data *data,
+chirp_emul_seek(os_emul_data *data,
cpu *processor,
unsigned_word cia)
{
- struct write_args {
+ error("chirp: seek not implemented\n");
+ return 0;
+}
+
+
+/* memory */
+
+static int
+chirp_emul_claim(os_emul_data *data,
+ cpu *processor,
+ unsigned_word cia)
+{
+ error("chirp: claim not implemented\n");
+ return 0;
+}
+
+static int
+chirp_emul_release(os_emul_data *data,
+ cpu *processor,
+ unsigned_word cia)
+{
+ error("chirp: release not implemented\n");
+ return 0;
+}
+
+
+/* Control transfer */
+
+static int
+chirp_emul_boot(os_emul_data *data,
+ cpu *processor,
+ unsigned_word cia)
+{
+ error("chirp: boot not implemented\n");
+ return 0;
+}
+
+static int
+chirp_emul_enter(os_emul_data *data,
+ cpu *processor,
+ unsigned_word cia)
+{
+ error("chirp: enter not implemented\n");
+ return 0;
+}
+
+static int
+chirp_emul_exit(os_emul_data *data,
+ cpu *processor,
+ unsigned_word cia)
+{
+ cpu_halt(processor, cia, was_exited, 0); /* always succeeds */
+ return 0;
+}
+
+static int
+chirp_emul_chain(os_emul_data *data,
+ cpu *processor,
+ unsigned_word cia)
+{
+ error("chirp: chain not implemented\n");
+ return 0;
+}
+
+
+/* user interface */
+
+static int
+chirp_emul_interpret(os_emul_data *data,
+ cpu *processor,
+ unsigned_word cia)
+{
+ error("chirp: interpret not implemented\n");
+ return 0;
+}
+
+static int
+chirp_emul_set_callback(os_emul_data *data,
+ cpu *processor,
+ unsigned_word cia)
+{
+ error("chirp: set_callback not implemented\n");
+ return 0;
+}
+
+static int
+chirp_emul_set_symbol_lookup(os_emul_data *data,
+ cpu *processor,
+ unsigned_word cia)
+{
+ error("chirp: set_symbol_lookup not implemented\n");
+ return 0;
+}
+
+
+/* Time */
+
+static int
+chirp_emul_milliseconds(os_emul_data *data,
+ cpu *processor,
+ unsigned_word cia)
+{
+ struct test_args {
unsigned32 service;
unsigned32 n_args;
unsigned32 n_returns;
/*in*/
- unsigned32 ihandle;
- unsigned32 addr;
- unsigned32 len;
/*out*/
- unsigned32 actual;
+ unsigned32 ms;
} args;
- char buf[1024];
- int actual;
- emul_read_buffer(&args, data->arguments,
- sizeof(args),
- processor, cia);
- if (T2H_4(args.n_args) != 3 || T2H_4(args.n_returns) != 1) {
- TRACE(trace_os_emul, ("write - invalid nr - n_args=%ld, n_returns=%ld\n",
- (long)T2H_4(args.n_args),
- (long)T2H_4(args.n_returns)));
- return -1;
- }
+ unsigned64 time;
/* read in the arguments */
- actual = T2H_4(args.len);
- if (actual >= sizeof(buf))
- actual = sizeof(buf) - 1;
- emul_read_buffer(buf,
- T2H_4(args.addr),
- actual,
- processor, cia);
- buf[actual] = '\0';
- /* write it out */
- TRACE(trace_os_emul, ("write - in - ihandle=0x%lx `%s' (%ld)\n",
- (unsigned long)args.ihandle, buf, (long)actual));
- write(BE2H_4(args.ihandle), buf, actual);
- args.actual = H2T_4(actual);
- TRACE(trace_os_emul, ("write - out - actual=%ld\n",
- (long)T2H_4(args.actual)));
+ if (chirp_read_args(&args, sizeof(args), 1, 1, data, processor, cia))
+ return -1;
+ /* make up a number */
+ time = event_queue_time(cpu_event_queue(processor)) / 1000000;
+ args.ms = H2T_4(time);
+ /* write the arguments back out */
+ TRACE(trace_os_emul, ("milliseconds - out - ms=%ld\n",
+ (unsigned long)T2H_4(args.ms)));
emul_write_buffer(&args, data->arguments,
sizeof(args),
processor, cia);
@@ -550,17 +790,54 @@ chirp_emul_write(os_emul_data *data,
}
-chirp_services services[] = {
+
+
+static chirp_services services[] = {
+
+ /* client interface */
+ { "test", chirp_emul_test },
+
+ /* device tree */
+ { "peer", chirp_emul_peer },
{ "child", chirp_emul_child },
- { "exit", chirp_emul_exit },
- { "finddevice", chirp_emul_finddevice },
- { "getprop", chirp_emul_getprop },
+ { "parent", chirp_emul_parent },
+ { "instance-to-package", chirp_emul_instance_to_package },
{ "getproplen", chirp_emul_getproplen },
+ { "getprop", chirp_emul_getprop },
+ { "nextprop", chirp_emul_nextprop },
+ { "setprop", chirp_emul_setprop },
+ { "canon", chirp_emul_canon },
+ { "finddevice", chirp_emul_finddevice },
+ { "instance-to-path", chirp_emul_instance_to_path },
+ { "package-to-path", chirp_emul_package_to_path },
+ { "call-method", chirp_emul_call_method },
+
+ /* device I/O */
{ "open", chirp_emul_open },
- { "parent", chirp_emul_parent },
- { "peer", chirp_emul_peer },
+ { "close", chirp_emul_close },
{ "read", chirp_emul_read },
{ "write", chirp_emul_write },
+ { "seek", chirp_emul_seek },
+ { "write", chirp_emul_write },
+
+ /* memory */
+ { "claim", chirp_emul_claim },
+ { "release", chirp_emul_release },
+
+ /* control transfer */
+ { "boot", chirp_emul_boot },
+ { "enter", chirp_emul_enter },
+ { "exit", chirp_emul_exit },
+ { "chain", chirp_emul_chain },
+
+ /* user interface */
+ { "interpret", chirp_emul_interpret },
+ { "set_callback", chirp_emul_set_callback },
+ { "set_symbol_lookup", chirp_emul_set_symbol_lookup },
+
+ /* time */
+ { "milliseconds", chirp_emul_milliseconds },
+
{ 0, /* sentinal */ },
};
@@ -613,18 +890,33 @@ map_over_chirp_note(bfd *image,
return;
note->found = 1;
/* check the name field */
- if (head.namesz > sizeof(name))
+ if (head.namesz > sizeof(name)) {
+ printf_filtered("open-boot warning: note name too long (%ld)\n",
+ (long)head.namesz);
return;
+ }
if (!bfd_get_section_contents(image, sect,
- name, sizeof(head), head.namesz))
+ name, sizeof(head), head.namesz)) {
+ printf_filtered("open-boot warning: note name unreadable\n");
return;
- if (strcmp(name, "PowerPC") != 0)
+ }
+ if (strcmp(name, "PowerPC") != 0) {
+ printf_filtered("open-boot warning: note name (%s) not `PowerPC'\n",
+ name);
return;
+ }
/* get the contents */
+ if (head.descsz != sizeof(note->desc)) {
+ printf_filtered("open-boot warning: note descriptor of wrong size\n");
+ return;
+ }
if (!bfd_get_section_contents(image, sect,
- &note->desc, sizeof(head) + head.namesz,
- head.descsz))
+ &note->desc, /* page align start */
+ ((sizeof(head) + head.namesz) + 3) & ~3,
+ head.descsz)) {
+ printf_filtered("open-boot warning: note descriptor unreadable\n");
return;
+ }
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);
@@ -753,18 +1045,25 @@ emul_chirp_create(device *root,
device_add_integer_property(init_register,
"r5",
code_client_va);
+ /* client interface */
device_tree_add_found_uw_u_u(init, "",
"data",
code_ra + (code_client_va - code_va),
- 4, 0x1); /*emul-call*/
+ 4, emul_call_instruction);
+ device_tree_add_found_uw_u_u(init, "",
+ "data",
+ code_ra + (code_client_va - code_va) + 4,
+ 4, emul_blr_instruction);
+ /* callback return address */
device_tree_add_found_uw_u_u(init, "",
"data",
code_ra + (code_callback_va - code_va),
- 4, 0x1); /*emul-call*/
+ 4, emul_call_instruction);
+ /* loop to keep other processors busy */
device_tree_add_found_uw_u_u(init, "",
"data",
code_ra + (code_loop_va - code_va),
- 4, 0x48000000); /*b .*/
+ 4, emul_loop_instruction);
device_add_integer_property(init_register,
"msr",
(msr_machine_check_enable
@@ -843,6 +1142,7 @@ emul_chirp_create(device *root,
data->catching_instruction_ea = code_callback_va;
data->phandles = cap_create("chirp");
data->root = root;
+ data->services = services;
return data;
}
}
@@ -923,9 +1223,7 @@ emul_chirp_instruction_call(cpu *processor,
}
- /* return to caller */
- cpu_registers(processor)->gpr[3] = result;
- cpu_restart(processor, emul_data->return_address);
+ /* return to caller - instruction following this is a function return */
return 1;
}
diff --git a/sim/ppc/emul_generic.c b/sim/ppc/emul_generic.c
index f764205..8f8ae09 100644
--- a/sim/ppc/emul_generic.c
+++ b/sim/ppc/emul_generic.c
@@ -16,16 +16,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- ----
-
- Code to output system call traces Copyright (C) 1991 Gordon Irlam.
- All rights reserved.
-
- This tool is part of the Spa(7) package. The Spa(7) package
- may be redistributed and/or modified under the terms of the
- GNU General Public License Version 2 (GPL(7)) as published
- by the Free Software Foundation.
-
*/
@@ -39,33 +29,32 @@
#endif
-INLINE_EMUL_GENERIC void
-emul_enter_call(emulation *emul,
- int call,
- int arg0,
- cpu *processor,
- unsigned_word cia)
+STATIC_INLINE_EMUL_GENERIC void
+emul_syscall_enter(emul_syscall *emul,
+ int call,
+ int arg0,
+ cpu *processor,
+ unsigned_word cia)
{
- printf_filtered("%d:0x%x:%s(",
+ printf_filtered("%d:0x%lx:%s(",
cpu_nr(processor) + 1,
- cia,
- emul->call_descriptor[call].name);
+ (long)cia,
+ emul->syscall_descriptor[call].name);
}
-INLINE_EMUL_GENERIC void
-emul_exit_call(emulation *emul,
- int call,
- int arg0,
- cpu *processor,
- unsigned_word cia)
+STATIC_INLINE_EMUL_GENERIC void
+emul_syscall_exit(emul_syscall *emul,
+ int call,
+ int arg0,
+ cpu *processor,
+ unsigned_word cia)
{
int status = cpu_registers(processor)->gpr[3];
int error = cpu_registers(processor)->gpr[0];
printf_filtered(")=%d", status);
if (error > 0 && error < emul->nr_error_names)
- printf_filtered("[%s]",
- emul->error_names[cpu_registers(processor)->gpr[0]]);
+ printf_filtered("[%s]", emul->error_names[error]);
printf_filtered("\n");
}
@@ -117,12 +106,9 @@ emul_read_string(char *dest,
if (addr == 0)
return NULL;
while (1) {
- if (vm_data_map_read_buffer(cpu_data_map(processor),
- &dest[nr_moved],
- addr + nr_moved,
- sizeof(dest[nr_moved]))
- != sizeof(dest[nr_moved]))
- return NULL;
+ dest[nr_moved] = vm_data_map_read_1(cpu_data_map(processor),
+ addr + nr_moved,
+ processor, cia);
if (dest[nr_moved] == '\0' || nr_moved >= nr_bytes)
break;
nr_moved++;
@@ -145,24 +131,27 @@ emul_write_status(cpu *processor,
}
+INLINE_EMUL_GENERIC unsigned_word
+emul_read_word(unsigned_word addr,
+ cpu *processor,
+ unsigned_word cia)
+{
+ return vm_data_map_read_word(cpu_data_map(processor),
+ addr,
+ processor, cia);
+}
+
+
INLINE_EMUL_GENERIC void
emul_write_word(unsigned_word addr,
unsigned_word buf,
cpu *processor,
unsigned_word cia)
{
- int nr_moved;
- H2T(buf);
- nr_moved = vm_data_map_write_buffer(cpu_data_map(processor),
- &buf,
- addr,
- sizeof(buf),
- 0/*violate_ro*/);
- if (nr_moved != sizeof(buf)) {
- printf_filtered("emul_write_word() write failed, %d out of %d written\n",
- nr_moved, sizeof(buf));
- cpu_halt(processor, cia, was_exited, 14/*EFAULT*/);
- }
+ vm_data_map_write_word(cpu_data_map(processor),
+ addr,
+ buf,
+ processor, cia);
}
@@ -173,15 +162,12 @@ emul_write_buffer(const void *source,
cpu *processor,
unsigned_word cia)
{
- int nr_moved = vm_data_map_write_buffer(cpu_data_map(processor),
- source,
- addr,
- nr_bytes,
- 0/*violate_ro*/);
- if (nr_moved != nr_bytes) {
- printf_filtered("emul_write_buffer() write failed %d out of %d written\n",
- nr_moved, nr_bytes);
- cpu_halt(processor, cia, was_exited, 14/*EFAULT*/);
+ int nr_moved;
+ for (nr_moved = 0; nr_moved < nr_bytes; nr_moved++) {
+ vm_data_map_write_1(cpu_data_map(processor),
+ addr + nr_moved,
+ ((const char*)source)[nr_moved],
+ processor, cia);
}
}
@@ -193,38 +179,39 @@ emul_read_buffer(void *dest,
cpu *processor,
unsigned_word cia)
{
- int nr_moved = vm_data_map_read_buffer(cpu_data_map(processor),
- dest,
- addr,
- nr_bytes);
- if (nr_moved != nr_bytes) {
- printf_filtered("emul_read_buffer() read failed %d out of %d read\n",
- nr_moved, nr_bytes);
- cpu_halt(processor, cia, was_exited, 14/*EFAULT*/);
+ int nr_moved;
+ for (nr_moved = 0; nr_moved < nr_bytes; nr_moved++) {
+ ((char*)dest)[nr_moved] = vm_data_map_read_1(cpu_data_map(processor),
+ addr + nr_moved,
+ processor, cia);
}
}
INLINE_EMUL_GENERIC void
-emul_do_call(emulation *emul,
- unsigned call,
- const int arg0,
- cpu *processor,
- unsigned_word cia)
+emul_do_system_call(os_emul_data *emul_data,
+ emul_syscall *emul,
+ unsigned call,
+ const int arg0,
+ cpu *processor,
+ unsigned_word cia)
{
- emul_call_handler *handler = NULL;
+ emul_syscall_handler *handler = NULL;
if (call >= emul->nr_system_calls)
error("do_call() os_emul call %d out-of-range\n", call);
- handler = emul->call_descriptor[call].handler;
+ handler = emul->syscall_descriptor[call].handler;
if (handler == NULL)
error("do_call() unimplemented call %d\n", call);
- ENTER_CALL;
+ if (WITH_TRACE && ppc_trace[trace_os_emul])
+ emul_syscall_enter(emul, call, arg0, processor, cia);
+
cpu_registers(processor)->gpr[0] = 0; /* default success */
- handler(emul, call, arg0, processor, cia);
- EXIT_CALL;
-}
+ handler(emul_data, call, arg0, processor, cia);
+ if (WITH_TRACE && ppc_trace[trace_os_emul])
+ emul_syscall_exit(emul, call, arg0, processor, cia);
+}
#endif /* _SYSTEM_C_ */
diff --git a/sim/ppc/emul_generic.h b/sim/ppc/emul_generic.h
new file mode 100644
index 0000000..ee8f076
--- /dev/null
+++ b/sim/ppc/emul_generic.h
@@ -0,0 +1,158 @@
+/* This file is part of the program psim.
+
+ Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ */
+
+
+#ifndef _EMUL_GENERIC_H_
+#define _EMUL_GENERIC_H_
+
+#include "cpu.h"
+#include "idecode.h"
+#include "os_emul.h"
+
+#include "bfd.h"
+
+#ifndef INLINE_EMUL_GENERIC
+#define INLINE_EMUL_GENERIC
+#endif
+
+/* various PowerPC instructions for writing into memory */
+enum {
+ emul_call_instruction = 0x1,
+ emul_loop_instruction = 0x48000000, /* branch to . */
+ emul_rfi_instruction = 0x4c000064,
+ emul_blr_instruction = 0x4e800020,
+};
+
+
+/* emulation specific data */
+
+typedef struct _os_emul_data os_emul_data;
+
+typedef os_emul_data *(os_emul_create_handler)
+ (device *tree,
+ bfd *image,
+ const char *emul_name);
+typedef void (os_emul_init_handler)
+ (os_emul_data *emul_data,
+ int nr_cpus);
+typedef void (os_emul_system_call_handler)
+ (cpu *processor,
+ unsigned_word cia,
+ os_emul_data *emul_data);
+typedef int (os_emul_instruction_call_handler)
+ (cpu *processor,
+ unsigned_word cia,
+ unsigned_word ra,
+ os_emul_data *emul_data);
+
+struct _os_emul {
+ const char *name;
+ os_emul_create_handler *create;
+ os_emul_init_handler *init;
+ os_emul_system_call_handler *system_call;
+ os_emul_instruction_call_handler *instruction_call;
+ os_emul_data *data;
+};
+
+
+/* One class of emulation - system call is pretty general, provide a
+ common template for implementing this */
+
+typedef struct _emul_syscall emul_syscall;
+typedef struct _emul_syscall_descriptor emul_syscall_descriptor;
+
+typedef void (emul_syscall_handler)
+ (os_emul_data *emul_data,
+ unsigned call,
+ const int arg0,
+ cpu *processor,
+ unsigned_word cia);
+
+struct _emul_syscall_descriptor {
+ emul_syscall_handler *handler;
+ const char *name;
+};
+
+struct _emul_syscall {
+ emul_syscall_descriptor *syscall_descriptor;
+ int nr_system_calls;
+ char **error_names;
+ int nr_error_names;
+ char **signal_names;
+ int nr_signal_names;
+};
+
+
+INLINE_EMUL_GENERIC void emul_do_system_call
+(os_emul_data *emul_data,
+ emul_syscall *syscall,
+ unsigned call,
+ const int arg0,
+ cpu *processor,
+ unsigned_word cia);
+
+
+INLINE_EMUL_GENERIC unsigned64 emul_read_gpr64
+(cpu *processor,
+ int g);
+
+INLINE_EMUL_GENERIC void emul_write_gpr64
+(cpu *processor,
+ int g,
+ unsigned64 val);
+
+INLINE_EMUL_GENERIC void emul_write_status
+(cpu *processor,
+ int status,
+ int errno);
+
+INLINE_EMUL_GENERIC char *emul_read_string
+(char *dest,
+ unsigned_word addr,
+ unsigned nr_bytes,
+ cpu *processor,
+ unsigned_word cia);
+
+INLINE_EMUL_GENERIC unsigned_word emul_read_word
+(unsigned_word addr,
+ cpu *processor,
+ unsigned_word cia);
+
+INLINE_EMUL_GENERIC void emul_write_word
+(unsigned_word addr,
+ unsigned_word buf,
+ cpu *processor,
+ unsigned_word cia);
+
+INLINE_EMUL_GENERIC void emul_read_buffer
+(void *dest,
+ unsigned_word addr,
+ unsigned nr_bytes,
+ cpu *processor,
+ unsigned_word cia);
+
+INLINE_EMUL_GENERIC void emul_write_buffer
+(const void *source,
+ unsigned_word addr,
+ unsigned nr_bytes,
+ cpu *processor,
+ unsigned_word cia);
+
+#endif /* _EMUL_GENERIC_H_ */