From: Michael Meissner Date: Wed, 10 Jan 1996 20:42:29 +0000 (+0000) Subject: Latest changes from Andrew X-Git-Url: http://git.efficios.com/?a=commitdiff_plain;h=52edddb97066df42beacf09a2f1d2e04605ce717;p=deliverable%2Fbinutils-gdb.git Latest changes from Andrew --- diff --git a/sim/ppc/.Sanitize b/sim/ppc/.Sanitize index 9a6c7a794d..c0984a454a 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 2e62ae6d73..1e022a87b0 100644 --- a/sim/ppc/ChangeLog +++ b/sim/ppc/ChangeLog @@ -1,3 +1,17 @@ +Tue Jan 9 15:10:27 1996 Andrew Cagney + + * 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 + + * 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 * device_table.c (register_init): Make format type correct. diff --git a/sim/ppc/Makefile.in b/sim/ppc/Makefile.in index e5684bbdda..9e11058ec0 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 0000000000..d88daa4a2f --- /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 55136f962e..cb34a378f7 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 . @@ -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 acdb679e21..9bf61e26fb 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 e723085e6e..15ef95a842 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 252c3ce1ea..f3259017e7 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 9c2026218b..9eb3a4e15a 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,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); - 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); 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,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, - ¬e->desc, sizeof(head) + head.namesz, - head.descsz)) + ¬e->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*)¬e->desc.real_mode); note->desc.real_base = bfd_get_32(image, (void*)¬e->desc.real_base); note->desc.real_size = bfd_get_32(image, (void*)¬e->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 f7642055b3..8f8ae09e32 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 0000000000..ee8f076ca6 --- /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 + + This program is free software; you can redistribute 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_ */