Latest changes from Andrew

This commit is contained in:
Michael Meissner 1996-01-10 20:42:29 +00:00
parent 0374a10562
commit 52edddb970
11 changed files with 1010 additions and 417 deletions

View File

@ -28,6 +28,7 @@ COPYING.LIB
ChangeLog
Makefile.in
README.psim
PROBLEMS
basics.h
bits.c
bits.h

View File

@ -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.

View File

@ -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

34
sim/ppc/PROBLEMS Normal file
View File

@ -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.

View File

@ -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.
ISA models
In addition, psim can model a true little-endian
machine.
PSIM includes a model of UEA, VEA and OEA. This
ISA models (Instruction Set Architecture)
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. but that is now one of its main objectives. (Did you notice
it was written PowerPC Platform instead of PowerPC platform?).
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
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.
empty files. You may want to consider
installing gnu's patch.
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:
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.
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.
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-test-951218.tar.gz
ftp://ftp.ci.com.au/pub/clayton/gdb-4.15+attach.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 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/gdb-4.15+note.diff.gz
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?
Does PSIM have any limitations or 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.
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?

View File

@ -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

View File

@ -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;

View File

@ -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");

View File

@ -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 */
return 0;
}
static int
chirp_emul_finddevice(os_emul_data *data,
cpu *processor,
unsigned_word cia)
{
struct finddevice_args {
struct parent_args {
unsigned32 service;
unsigned32 n_args;
unsigned32 n_returns;
/*in*/
unsigned32 device_specifier;
/*out*/
unsigned32 phandle;
/*out*/
unsigned32 parent_phandle;
} args;
char device_specifier[1024];
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)));
device *parent_dev;
/* read the args in */
if (chirp_read_args(&args, sizeof(args), 1, 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);
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",
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_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 getproplen_args {
unsigned32 service;
unsigned32 n_args;
unsigned32 n_returns;
/*in*/
unsigned32 phandle;
unsigned32 name;
/*out*/
unsigned32 proplen;
} args;
char name[32];
device *dev;
const device_property *prop;
/* read the args in */
if (chirp_read_args(&args, sizeof(args), 2, 1, data, processor, cia))
return -1;
dev = cap_internal(data->phandles, args.phandle);
/* find our prop and get its length */
if (dev == (device*)0)
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)),
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,60 +417,105 @@ 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);
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));
/* find the device */
dev = device_tree_find_device(data->root,
device_specifier);
if (dev == (device*)0)
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",
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);
return 0;
}
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,
@ -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,101 +553,11 @@ 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);
return 0;
}
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;
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)));
return -1;
}
/* 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))));
emul_write_buffer(&args, data->arguments,
sizeof(args),
processor, cia);
error("chirp: close not implemented\n");
return 0;
}
@ -469,31 +579,33 @@ 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)));
/* read the args */
if (chirp_read_args(&args, sizeof(args), 3, 1, data, processor, cia))
return -1;
}
/* read in the arguments */
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;
emul_read_buffer(buf,
T2H_4(args.addr),
actual,
processor, cia);
buf[actual] = '\0';
/* read it in */
TRACE(trace_os_emul, ("read - 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",
(long)T2H_4(args.actual)));
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';
}
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);
@ -518,16 +630,9 @@ chirp_emul_write(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, ("write - 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;
@ -536,11 +641,15 @@ chirp_emul_write(os_emul_data *data,
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);
/* 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,
@ -549,18 +658,186 @@ chirp_emul_write(os_emul_data *data,
return 0;
}
static int
chirp_emul_seek(os_emul_data *data,
cpu *processor,
unsigned_word cia)
{
error("chirp: seek not implemented\n");
return 0;
}
chirp_services services[] = {
{ "child", chirp_emul_child },
{ "exit", chirp_emul_exit },
{ "finddevice", chirp_emul_finddevice },
{ "getprop", chirp_emul_getprop },
{ "getproplen", chirp_emul_getproplen },
{ "open", chirp_emul_open },
{ "parent", chirp_emul_parent },
/* 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*/
/*out*/
unsigned32 ms;
} args;
unsigned64 time;
/* read in the arguments */
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);
return 0;
}
static chirp_services services[] = {
/* client interface */
{ "test", chirp_emul_test },
/* device tree */
{ "peer", chirp_emul_peer },
{ "child", chirp_emul_child },
{ "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 },
{ "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 (!bfd_get_section_contents(image, sect,
&note->desc, sizeof(head) + head.namesz,
head.descsz))
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, /* 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;
}

View File

@ -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_ */

158
sim/ppc/emul_generic.h Normal file
View File

@ -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_ */