Add Solaris and Linux emulations
authorMichael Meissner <gnu@the-meissners.org>
Sun, 2 Jun 1996 15:40:16 +0000 (15:40 +0000)
committerMichael Meissner <gnu@the-meissners.org>
Sun, 2 Jun 1996 15:40:16 +0000 (15:40 +0000)
sim/ppc/.Sanitize
sim/ppc/ChangeLog
sim/ppc/Makefile.in
sim/ppc/config.in
sim/ppc/configure
sim/ppc/configure.in
sim/ppc/emul_generic.c
sim/ppc/emul_netbsd.c
sim/ppc/emul_unix.c [new file with mode: 0644]
sim/ppc/emul_unix.h [new file with mode: 0644]
sim/ppc/psim.c

index 459eeb33405ab51ab706247b885e411db67b1c2e..0e10881dfced77481c5e11e5b31f4c53fa16a22c 100644 (file)
@@ -64,6 +64,8 @@ emul_generic.c
 emul_generic.h
 emul_netbsd.c
 emul_netbsd.h
+emul_unix.c
+emul_unix.h
 events.c
 events.h
 filter_filename.c
index cd7813b7ac7e67d47ca09dc532bea79d19465d8f..1786be3af7b2eca3e59702d80154582e4f3dd494 100644 (file)
@@ -1,3 +1,35 @@
+Sun Jun  2 11:21:17 1996  Michael Meissner  <meissner@tiktok.cygnus.com>
+
+       * emul_unix.{h,c}: New files to provide Solaris and Linux system
+       call emulations.
+
+       * Makefile.in (LIB_{SRC,OBJ}): Add emul_unix.{c,o}.
+       (os_emul.o): Depend on emul_unix.h.
+       (emul_unix.o): New dependency.
+
+       * configure.in (--enable-sim-alignment): Add 0|default to mean set
+       alignment to 0, which means use appropriate alignment for mode.
+       (AC_CHECK_FUNCS): Add new functions needed by emul_unix.c.
+       (AC_CHECK_HEADERS): Add new include files needed by emul_unix.c.
+       * config.in: Regenerate.
+       * configure: Regenerate.
+
+       * emul_generic.c (emul_write2_status): New function to return
+       results in r3 and r4 for Solaris system calls.
+       (emul_do_system_call): If the system call is not support, but
+       there is a string for the system call name, print out the string
+       instead of the system call number.
+
+       * emul_generic.h (emul_write2_status): Declare it.
+
+       * emul_netbsd.c: Use /* */ around comment on #endif.
+
+       * os_emul.c: Include emul_unix.h.
+       (os_emulations): Add emulations for Solaris, and Linux.
+
+       * psim.c (psim_usage): Add message about solaris, linux
+       emulations.
+
 Fri May 24 10:08:10 1996  Michael Meissner  <meissner@tiktok.cygnus.com>
 
        * configure.in (AC_STRUCT_ST_{BLKSIZE,BLOCKS,RDEV}): Use these
index e1532d6c0f0328c627380208bf21f8ed8974792b..e2c13e0b429172fb87db78b766e91bf268eab711 100644 (file)
@@ -228,6 +228,7 @@ LIB_SRC = \
        os_emul.c \
        emul_generic.c \
        emul_netbsd.c \
+       emul_unix.c \
        emul_chirp.c \
        emul_bugapi.c \
        registers.c \
@@ -255,6 +256,7 @@ LIB_OBJ = \
        os_emul.o \
        emul_generic.o \
        emul_netbsd.o \
+       emul_unix.o \
        emul_chirp.o \
        emul_bugapi.o \
        registers.o \
@@ -317,10 +319,11 @@ filter_filename.o: filter_filename.c filter_filename.h config.h ppc-config.h
 
 sim-endian.o: sim-endian.c sim-endian-n.h $(BASICS_H)
 
-os_emul.o: os_emul.c emul_netbsd.h emul_chirp.h emul_bugapi.h $(EMUL_GENERIC_H)
+os_emul.o: os_emul.c emul_netbsd.h emul_unix.h emul_chirp.h emul_bugapi.h $(EMUL_GENERIC_H)
 emul_generic.o: emul_generic.c $(EMUL_GENERIC_H)
 
 emul_netbsd.o: emul_netbsd.c emul_netbsd.h $(EMUL_GENERIC_H)
+emul_unix.o: emul_unix.c emul_unix.h $(EMUL_GENERIC_H)
 emul_chirp.o: emul_chirp.c emul_chirp.h $(EMUL_GENERIC_H)
 emul_bugapi.o: emul_bugapi.c emul_bugapi.h $(EMUL_GENERIC_H)
 
@@ -346,7 +349,7 @@ events.o: events.c events.h $(BASICS_H)
 
 sim_calls.o: sim_calls.c $(PSIM_H) itable.h ../../gdb/tm.h options.h
 
-spreg.o: spreg.h spreg.c $(BASICS_H)
+spreg.o: spreg.c spreg.h spreg.c $(BASICS_H)
 
 main.o: main.c $(PSIM_H) itable.h options.h
 
@@ -418,10 +421,10 @@ itable.h itable.c icache.h idecode.h idecode.c semantics.h semantics.c model.h m
 spreg.h spreg.c: tmp-dgen
 
 dgen: dgen.o table.o lf.o misc.o filter_host.o
-       $(CC_FOR_BUILD) $(BUILD_CFLAGS) -o dgen dgen.o table.o lf.o misc.o filter_host.o $(LIBIBERTY_LIB) $(LIBS)
+       $(CC_FOR_BUILD) $(BUILD_CFLAGS) -o dgen dgen.o table.o lf.o misc.o filter_host.o $(BUILD_LIBS)
 
 igen: igen.o table.o lf.o misc.o filter_host.o
-       $(CC_FOR_BUILD) $(BUILD_CFLAGS) $(BUILD_LDFLAGS) -o igen igen.o table.o lf.o misc.o filter_host.o $(LIBIBERTY_LIB) $(LIBS)
+       $(CC_FOR_BUILD) $(BUILD_CFLAGS) $(BUILD_LDFLAGS) -o igen igen.o table.o lf.o misc.o filter_host.o $(BUILD_LIBS)
 
 filter_host.c: filter_filename.c
        cat $(srcdir)/filter_filename.c > filter_host.c
@@ -441,7 +444,7 @@ dgen.o: dgen.c misc.h filter_filename.h lf.h table.h
 igen.o: igen.c misc.h filter_filename.h lf.h table.h
        $(CC_FOR_BUILD) $(BUILD_CFLAGS) -c $(srcdir)/igen.c
 
-misc.o: misc.h filter_filename.h
+misc.o: misc.c misc.h filter_filename.h
        $(CC_FOR_BUILD) $(BUILD_CFLAGS) -c $(srcdir)/misc.c
 
 # With out this #, make thinks that misc.o doesn't have a rule
index eb713cd72ce692943e10cd40fb11bdd23b952680..3b4b53ad0d22360279ab38269288a5ca13830acb 100644 (file)
    byte first (like Motorola and SPARC, unlike Intel and VAX).  */
 #undef WORDS_BIGENDIAN
 
+/* Define if you have the cfgetispeed function.  */
+#undef HAVE_CFGETISPEED
+
+/* Define if you have the cfgetospeed function.  */
+#undef HAVE_CFGETOSPEED
+
+/* Define if you have the cfsetispeed function.  */
+#undef HAVE_CFSETISPEED
+
+/* Define if you have the cfsetospeed function.  */
+#undef HAVE_CFSETOSPEED
+
+/* Define if you have the chdir function.  */
+#undef HAVE_CHDIR
+
+/* Define if you have the chmod function.  */
+#undef HAVE_CHMOD
+
+/* Define if you have the chown function.  */
+#undef HAVE_CHOWN
+
 /* Define if you have the dup function.  */
 #undef HAVE_DUP
 
 /* Define if you have the dup2 function.  */
 #undef HAVE_DUP2
 
+/* Define if you have the fchmod function.  */
+#undef HAVE_FCHMOD
+
+/* Define if you have the fchown function.  */
+#undef HAVE_FCHOWN
+
 /* Define if you have the fcntl function.  */
 #undef HAVE_FCNTL
 
@@ -53,6 +80,9 @@
 /* Define if you have the getpid function.  */
 #undef HAVE_GETPID
 
+/* Define if you have the getppid function.  */
+#undef HAVE_GETPPID
+
 /* Define if you have the getrusage function.  */
 #undef HAVE_GETRUSAGE
 
 /* Define if you have the kill function.  */
 #undef HAVE_KILL
 
+/* Define if you have the link function.  */
+#undef HAVE_LINK
+
 /* Define if you have the lseek function.  */
 #undef HAVE_LSEEK
 
 /* Define if you have the lstat function.  */
 #undef HAVE_LSTAT
 
+/* Define if you have the mkdir function.  */
+#undef HAVE_MKDIR
+
+/* Define if you have the pipe function.  */
+#undef HAVE_PIPE
+
+/* Define if you have the readlink function.  */
+#undef HAVE_READLINK
+
+/* Define if you have the rmdir function.  */
+#undef HAVE_RMDIR
+
+/* Define if you have the setregid function.  */
+#undef HAVE_SETREGID
+
+/* Define if you have the setreuid function.  */
+#undef HAVE_SETREUID
+
 /* Define if you have the sigprocmask function.  */
 #undef HAVE_SIGPROCMASK
 
 /* Define if you have the stat function.  */
 #undef HAVE_STAT
 
+/* Define if you have the symlink function.  */
+#undef HAVE_SYMLINK
+
+/* Define if you have the tcdrain function.  */
+#undef HAVE_TCDRAIN
+
+/* Define if you have the tcflow function.  */
+#undef HAVE_TCFLOW
+
+/* Define if you have the tcflush function.  */
+#undef HAVE_TCFLUSH
+
+/* Define if you have the tcgetattr function.  */
+#undef HAVE_TCGETATTR
+
+/* Define if you have the tcgetpgrp function.  */
+#undef HAVE_TCGETPGRP
+
+/* Define if you have the tcsendbreak function.  */
+#undef HAVE_TCSENDBREAK
+
+/* Define if you have the tcsetattr function.  */
+#undef HAVE_TCSETATTR
+
+/* Define if you have the tcsetpgrp function.  */
+#undef HAVE_TCSETPGRP
+
+/* Define if you have the time function.  */
+#undef HAVE_TIME
+
 /* Define if you have the umask function.  */
 #undef HAVE_UMASK
 
+/* Define if you have the unlink function.  */
+#undef HAVE_UNLINK
+
 /* Define if you have the <dirent.h> header file.  */
 #undef HAVE_DIRENT_H
 
+/* Define if you have the <fcntl.h> header file.  */
+#undef HAVE_FCNTL_H
+
 /* Define if you have the <ndir.h> header file.  */
 #undef HAVE_NDIR_H
 
 /* Define if you have the <sys/ndir.h> header file.  */
 #undef HAVE_SYS_NDIR_H
 
+/* Define if you have the <sys/param.h> header file.  */
+#undef HAVE_SYS_PARAM_H
+
 /* Define if you have the <sys/resource.h> header file.  */
 #undef HAVE_SYS_RESOURCE_H
 
+/* Define if you have the <sys/stat.h> header file.  */
+#undef HAVE_SYS_STAT_H
+
+/* Define if you have the <sys/termio.h> header file.  */
+#undef HAVE_SYS_TERMIO_H
+
+/* Define if you have the <sys/termios.h> header file.  */
+#undef HAVE_SYS_TERMIOS_H
+
 /* Define if you have the <sys/time.h> header file.  */
 #undef HAVE_SYS_TIME_H
 
index ed023a7c570f29a5f2fc6c93075e5e90b9c4e1f8..60240e7810339cde9d3d5fb0ab810e601cb46634 100755 (executable)
@@ -1,8 +1,8 @@
 #! /bin/sh
 
 # Guess values for system-dependent variables and create Makefiles.
-# Generated automatically using autoconf version 2.8 
-# Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc.
+# Generated automatically using autoconf version 2.10 
+# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
 #
 # This configure script is free software; the Free Software Foundation
 # gives unlimited permission to copy, distribute and modify it.
@@ -386,7 +386,7 @@ EOF
     verbose=yes ;;
 
   -version | --version | --versio | --versi | --vers)
-    echo "configure generated by autoconf version 2.8"
+    echo "configure generated by autoconf version 2.10"
     exit 0 ;;
 
   -with-* | --with-*)
@@ -1160,6 +1160,7 @@ if test "${enable_sim_alignment+set}" = set; then
   case "${enableval}" in
   yes | strict | STRICT)       sim_alignment="-DWITH_ALIGNMENT=STRICT_ALIGNMENT";;
   no | nonstrict | NONSTRICT)  sim_alignment="-DWITH_ALIGNMENT=NONSTRICT_ALIGNMENT";;
+  0 | default | DEFAULT)       sim_alignment="-DWITH_ALIGNMENT=0";;
   *)                           { echo "configure: error: "Unknown value $enableval passed to --enable-sim-alignment"" 1>&2; exit 1; }; sim_alignment="";;
 esac
 if test x"$silent" != x"yes" && test x"$sim_alignment" != x""; then
@@ -1500,7 +1501,7 @@ if eval "test \"`echo '$''{'ac_cv_struct_st_blksize'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1504 "configure"
+#line 1505 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -1509,7 +1510,7 @@ int t() {
 struct stat s; s.st_blksize;
 ; return 0; }
 EOF
-if { (eval echo configure:1513: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1514: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_struct_st_blksize=yes
 else
@@ -1533,7 +1534,7 @@ if eval "test \"`echo '$''{'ac_cv_struct_st_blocks'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1537 "configure"
+#line 1538 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -1542,7 +1543,7 @@ int t() {
 struct stat s; s.st_blocks;
 ; return 0; }
 EOF
-if { (eval echo configure:1546: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1547: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_struct_st_blocks=yes
 else
@@ -1568,7 +1569,7 @@ if eval "test \"`echo '$''{'ac_cv_struct_st_rdev'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1572 "configure"
+#line 1573 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -1577,7 +1578,7 @@ int t() {
 struct stat s; s.st_rdev;
 ; return 0; }
 EOF
-if { (eval echo configure:1581: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1582: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_struct_st_rdev=yes
 else
@@ -1601,7 +1602,7 @@ if eval "test \"`echo '$''{'ac_cv_struct_tm'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1605 "configure"
+#line 1606 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <time.h>
@@ -1610,7 +1611,7 @@ int t() {
 struct tm *tp; tp->tm_sec;
 ; return 0; }
 EOF
-if { (eval echo configure:1614: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1615: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_struct_tm=time.h
 else
@@ -1634,7 +1635,7 @@ if eval "test \"`echo '$''{'ac_cv_struct_tm_zone'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1638 "configure"
+#line 1639 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <$ac_cv_struct_tm>
@@ -1643,7 +1644,7 @@ int t() {
 struct tm tm; tm.tm_zone;
 ; return 0; }
 EOF
-if { (eval echo configure:1647: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1648: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_struct_tm_zone=yes
 else
@@ -1666,7 +1667,7 @@ if eval "test \"`echo '$''{'ac_cv_var_tzname'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1670 "configure"
+#line 1671 "configure"
 #include "confdefs.h"
 #include <time.h>
 #ifndef tzname /* For SGI.  */
@@ -1677,7 +1678,7 @@ int t() {
 atoi(*tzname);
 ; return 0; }
 EOF
-if { (eval echo configure:1681: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+if { (eval echo configure:1682: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
   rm -rf conftest*
   ac_cv_var_tzname=yes
 else
@@ -1698,19 +1699,21 @@ EOF
 fi
 
 
-for ac_func in dup dup2 fcntl fstat fstatfs getdirentries getegid geteuid getgid getpid getrusage gettimeofday getuid ioctl kill lseek lstat sigprocmask stat umask
+for ac_func in cfgetispeed cfgetospeed cfsetispeed cfsetospeed chdir chmod chown dup dup2 fchmod fchown fcntl fstat fstatfs getdirentries getegid geteuid getgid getpid getppid getrusage gettimeofday getuid ioctl kill link lseek lstat mkdir pipe readlink rmdir setreuid setregid stat sigprocmask stat symlink tcgetattr tcsetattr tcsendbreak tcdrain tcflush tcflow tcgetpgrp tcsetpgrp time umask unlink
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1709 "configure"
+#line 1710 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
 #include <assert.h>
 /* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
 char $ac_func();
 
 int main() { return 0; }
@@ -1727,7 +1730,7 @@ $ac_func();
 
 ; return 0; }
 EOF
-if { (eval echo configure:1731: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+if { (eval echo configure:1734: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -1765,13 +1768,13 @@ else
   # On the NeXT, cc -E runs the code through the compiler's parser,
   # not just through cpp.
   cat > conftest.$ac_ext <<EOF
-#line 1769 "configure"
+#line 1772 "configure"
 #include "confdefs.h"
 #include <assert.h>
 Syntax Error
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1775: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:1778: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out`
 if test -z "$ac_err"; then
   :
@@ -1780,13 +1783,13 @@ else
   rm -rf conftest*
   CPP="${CC-cc} -E -traditional-cpp"
   cat > conftest.$ac_ext <<EOF
-#line 1784 "configure"
+#line 1787 "configure"
 #include "confdefs.h"
 #include <assert.h>
 Syntax Error
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1790: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:1793: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out`
 if test -z "$ac_err"; then
   :
@@ -1806,7 +1809,7 @@ else
 fi
 echo "$ac_t""$CPP" 1>&6
 
-for ac_hdr in string.h strings.h stdlib.h time.h sys/mount.h sys/types.h sys/time.h sys/times.h unistd.h sys/resource.h sys/ioctl.h
+for ac_hdr in fcntl.h stdlib.h string.h strings.h sys/ioctl.h sys/mount.h sys/param.h sys/resource.h sys/stat.h sys/termio.h sys/termios.h sys/time.h sys/times.h sys/types.h time.h unistd.h
 do
 ac_safe=`echo "$ac_hdr" | tr './\055' '___'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
@@ -1814,12 +1817,12 @@ if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1818 "configure"
+#line 1821 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1823: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:1826: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -1852,7 +1855,7 @@ if eval "test \"`echo '$''{'ac_cv_header_dirent_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1856 "configure"
+#line 1859 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <$ac_hdr>
@@ -1861,7 +1864,7 @@ int t() {
 DIR *dirp = 0;
 ; return 0; }
 EOF
-if { (eval echo configure:1865: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1868: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   eval "ac_cv_header_dirent_$ac_safe=yes"
 else
@@ -1885,22 +1888,26 @@ done
 # Two versions of opendir et al. are in -ldir and -lx on SCO Xenix.
 if test $ac_header_dirent = dirent.h; then
 echo $ac_n "checking for -ldir""... $ac_c" 1>&6
-ac_lib_var=`echo dir_opendir | tr '.-/+' '___p'`
+ac_lib_var=`echo dir'_'opendir | tr './+\055' '__p_'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   ac_save_LIBS="$LIBS"
 LIBS="-ldir  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 1896 "configure"
+#line 1899 "configure"
 #include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char opendir();
 
 int main() { return 0; }
 int t() {
 opendir()
 ; return 0; }
 EOF
-if { (eval echo configure:1904: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+if { (eval echo configure:1911: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -1920,22 +1927,26 @@ fi
 
 else
 echo $ac_n "checking for -lx""... $ac_c" 1>&6
-ac_lib_var=`echo x_opendir | tr '.-/+' '___p'`
+ac_lib_var=`echo x'_'opendir | tr './+\055' '__p_'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   ac_save_LIBS="$LIBS"
 LIBS="-lx  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 1931 "configure"
+#line 1938 "configure"
 #include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char opendir();
 
 int main() { return 0; }
 int t() {
 opendir()
 ; return 0; }
 EOF
-if { (eval echo configure:1939: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+if { (eval echo configure:1950: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -2032,7 +2043,7 @@ do
     echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
     exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
   -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
-    echo "$CONFIG_STATUS generated by autoconf version 2.8"
+    echo "$CONFIG_STATUS generated by autoconf version 2.10"
     exit 0 ;;
   -help | --help | --hel | --he | --h)
     echo "\$ac_cs_usage"; exit 0 ;;
@@ -2221,7 +2232,7 @@ rm -f conftest.vals
 cat > conftest.hdr <<\EOF
 s/[\\&%]/\\&/g
 s%[\\$`]%\\&%g
-s%#define \([A-Za-z_][A-Za-z0-9_]*\) \(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp
+s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp
 s%ac_d%ac_u%gp
 s%ac_u%ac_e%gp
 EOF
@@ -2269,6 +2280,12 @@ cat >> $CONFIG_STATUS <<\EOF
     echo "$ac_file is unchanged"
     rm -f conftest.h
   else
+    # Remove last slash and all that follows it.  Not all systems have dirname.
+      ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+      if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+      # The file is in a subdirectory.
+      test ! -d "$ac_dir" && mkdir "$ac_dir"
+    fi
     rm -f $ac_file
     mv conftest.h $ac_file
   fi
index f81a2cc3304520dbba4e03381cc36e4a695ce4ec..fb662a0f322962d823845ddc1ae712c321036873 100644 (file)
@@ -290,6 +290,7 @@ AC_ARG_ENABLE(sim-alignment,
 [case "${enableval}" in
   yes | strict | STRICT)       sim_alignment="-DWITH_ALIGNMENT=STRICT_ALIGNMENT";;
   no | nonstrict | NONSTRICT)  sim_alignment="-DWITH_ALIGNMENT=NONSTRICT_ALIGNMENT";;
+  0 | default | DEFAULT)       sim_alignment="-DWITH_ALIGNMENT=0";;
   *)                           AC_MSG_ERROR("Unknown value $enableval passed to --enable-sim-alignment"); sim_alignment="";;
 esac
 if test x"$silent" != x"yes" && test x"$sim_alignment" != x""; then
@@ -443,9 +444,9 @@ AC_STRUCT_ST_BLOCKS
 AC_STRUCT_ST_RDEV
 AC_STRUCT_TIMEZONE
 
-AC_CHECK_FUNCS(dup dup2 fcntl fstat fstatfs getdirentries getegid geteuid getgid getpid getrusage gettimeofday getuid ioctl kill lseek lstat sigprocmask stat umask)
+AC_CHECK_FUNCS(cfgetispeed cfgetospeed cfsetispeed cfsetospeed chdir chmod chown dup dup2 fchmod fchown fcntl fstat fstatfs getdirentries getegid geteuid getgid getpid getppid getrusage gettimeofday getuid ioctl kill link lseek lstat mkdir pipe readlink rmdir setreuid setregid stat sigprocmask stat symlink tcgetattr tcsetattr tcsendbreak tcdrain tcflush tcflow tcgetpgrp tcsetpgrp time umask unlink)
 
-AC_CHECK_HEADERS(string.h strings.h stdlib.h time.h sys/mount.h sys/types.h sys/time.h sys/times.h unistd.h sys/resource.h sys/ioctl.h)
+AC_CHECK_HEADERS(fcntl.h stdlib.h string.h strings.h sys/ioctl.h sys/mount.h sys/param.h sys/resource.h sys/stat.h sys/termio.h sys/termios.h sys/time.h sys/times.h sys/types.h time.h unistd.h)
 AC_HEADER_DIRENT
 
 AC_OUTPUT(Makefile,
index f45df6c54b2d775f5c7040b88dc300427f58ff1e..3883d0316e2e25950383ed0dd314efa0c8a2fb4d 100644 (file)
@@ -123,11 +123,32 @@ emul_write_status(cpu *processor,
                  int status,
                  int errno)
 {
-  cpu_registers(processor)->gpr[3] = status;
-  if (status < 0)
-    cpu_registers(processor)->gpr[0] = errno;
-  else
-    cpu_registers(processor)->gpr[0] = 0;
+  if (status == -1 && errno != 0) {
+    cpu_registers(processor)->gpr[3] = errno;
+    CR_SET(0, cr_i_summary_overflow);
+  }
+  else {
+    cpu_registers(processor)->gpr[3] = status;
+    CR_SET(0, 0);
+  }
+}
+
+
+INLINE_EMUL_GENERIC void
+emul_write2_status(cpu *processor,
+                  int status1,
+                  int status2,
+                  int errno)
+{
+  if (status1 == -1 && errno != 0) {
+    cpu_registers(processor)->gpr[3] = errno;
+    CR_SET(0, cr_i_summary_overflow);
+  }
+  else {
+    cpu_registers(processor)->gpr[3] = status1;
+    cpu_registers(processor)->gpr[4] = status2;
+    CR_SET(0, 0);
+  }
 }
 
 
@@ -201,8 +222,13 @@ emul_do_system_call(os_emul_data *emul_data,
     error("do_call() os_emul call %d out-of-range\n", call);
 
   handler = emul->syscall_descriptor[call].handler;
-  if (handler == NULL)
-    error("do_call() unimplemented call %d\n", call);
+  if (handler == NULL) {
+    if (emul->syscall_descriptor[call].name) {
+      error("do_call() unimplemented call %s\n", emul->syscall_descriptor[call].name);
+    } else {
+      error("do_call() unimplemented call %d\n", call);
+    }
+  }
 
   if (WITH_TRACE && ppc_trace[trace_os_emul])
     emul_syscall_enter(emul, call, arg0, processor, cia);
@@ -269,6 +295,9 @@ emul_add_tree_options(device *tree,
 INLINE_EMUL_GENERIC void
 emul_add_tree_hardware(device *root)
 {
+  int i;
+  int nr_cpus = device_find_integer_property(root, "/openprom/options/smp");
+
   /* add some memory */
   if (device_tree_find_device(root, "/memory") == NULL) {
     unsigned_word memory_size =
@@ -277,19 +306,30 @@ emul_add_tree_hardware(device *root)
                           (unsigned long)memory_size);
     /* what about allocated? */
   }
-  /* an eeprom */
-  device_tree_add_parsed(root, "/openprom/eeprom@0xfff00000/reg { 0xfff00000 0x3000");
-  /* the IO bus */
-  device_tree_add_parsed(root, "/iobus@0x400000/reg { 0x400000 0x400000");
-  device_tree_add_parsed(root, "/iobus/console@0x000000/reg { 0x000000 16");
-  device_tree_add_parsed(root, "/iobus/halt@0x100000/reg    { 0x100000  4");
-  device_tree_add_parsed(root, "/iobus/icu@0x200000/reg     { 0x200000  8");
-  device_tree_add_parsed(root, "/iobus/icu > 0 0 /iobus/icu");
-  device_tree_add_parsed(root, "/iobus/icu > 1 1 /iobus/icu");
+
+  /* our processors */
+  for (i = 0; i < nr_cpus; i++) {
+    device_tree_add_parsed(root, "/cpus/cpu@%d/cpu-nr %d", i, i);
+  }
+
+  /* a fake eeprom - need to be able to write to it */
+  device_tree_add_parsed(root, "/openprom/memory@0xfff00000/reg { 0xfff00000 0x3000");
+
+  /* A local bus containing basic devices */
+  device_tree_add_parsed(root, "/iobus@0xf0000000/reg { 0xf0000000 0x0f000000");
+  device_tree_add_parsed(root, "/iobus/nvram@0x0/reg   { 0 0x1000");
+  device_tree_add_parsed(root, "/iobus/nvram/timezone 600");
+
+  /* the debugging pal. Wire interrupts up directly */
+  device_tree_add_parsed(root, "/iobus/pal@0x0x1000/reg  { 0x1000 32");
+  for (i = 0; i < nr_cpus; i++) {
+    device_tree_add_parsed(root, "/iobus/pal > %d int /cpus/cpu@%d", i, i);
+  }
+
   /* chosen etc */
-  device_tree_add_parsed(root, "/chosen/stdin */iobus/console");
+  device_tree_add_parsed(root, "/chosen/stdin */iobus/pal");
   device_tree_add_parsed(root, "/chosen/stdout !/chosen/stdin");
   device_tree_add_parsed(root, "/chosen/memory */memory");
 }
 
-#endif /* _SYSTEM_C_ */
+#endif /* _EMUL_GENERIC_C_ */
index 51af331691e052d87d4a1b415f08f65dda3a2d33..fae6f914121d33a12d49952d3d29df55ac539a37 100644 (file)
@@ -1422,4 +1422,4 @@ const os_emul emul_netbsd = {
   0 /*data*/
 };
 
-#endif _EMUL_NETBSD_C_
+#endif /* _EMUL_NETBSD_C_ */
diff --git a/sim/ppc/emul_unix.c b/sim/ppc/emul_unix.c
new file mode 100644 (file)
index 0000000..6003204
--- /dev/null
@@ -0,0 +1,2525 @@
+/*  This file is part of the program psim.
+
+    Copyright (C) 1996, Andrew Cagney <cagney@highland.com.au>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+    */
+
+
+#ifndef _EMUL_UNIX_C_
+#define _EMUL_UNIX_C_
+
+
+/* Note: this module is called via a table.  There is no benefit in
+   making it inline */
+
+#include "emul_generic.h"
+#include "emul_unix.h"
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/stat.h>
+#else
+#undef HAVE_STAT
+#undef HAVE_LSTAT
+#undef HAVE_FSTAT
+#endif
+
+#include <stdio.h>
+#include <signal.h>
+#include <errno.h>
+
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+
+#ifdef HAVE_SYS_TERMIOS_H
+#include <sys/termios.h>
+#endif
+
+#ifdef HAVE_SYS_TERMIO_H
+#include <sys/termio.h>
+#endif
+
+#ifdef HAVE_GETRUSAGE
+#ifndef HAVE_SYS_RESOURCE_H
+#undef HAVE_GETRUSAGE
+#endif
+#endif
+
+#ifdef HAVE_GETRUSAGE
+#include <sys/resource.h>
+int getrusage();
+#endif
+
+#if HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+
+#if HAVE_SYS_MOUNT_H
+#include <sys/mount.h>
+#endif
+
+#if HAVE_DIRENT_H
+# include <dirent.h>
+# define NAMLEN(dirent) strlen((dirent)->d_name)
+#else
+# define dirent direct
+# define NAMLEN(dirent) (dirent)->d_namlen
+# if HAVE_SYS_NDIR_H
+#  include <sys/ndir.h>
+# endif
+# if HAVE_SYS_DIR_H
+#  include <sys/dir.h>
+# endif
+# if HAVE_NDIR_H
+#  include <ndir.h>
+# endif
+#endif
+
+#ifdef HAVE_UNISTD_H
+#undef MAXPATHLEN              /* sys/param.h might define this also */
+#include <unistd.h>
+#endif
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#if defined(BSD) && !defined(errno) && (BSD < 199306)  /* here BSD as just a bug */
+extern int errno;
+#endif
+
+#ifndef STATIC_INLINE_EMUL_UNIX
+#define STATIC_INLINE_EMUL_UNIX STATIC_INLINE
+#endif
+
+#ifndef PATH_MAX
+#define PATH_MAX 1024
+#endif
+
+#ifndef EINVAL
+#define EINVAL -1
+#endif
+
+/* UNIX's idea of what is needed to implement emulations */
+
+struct _os_emul_data {
+  device *vm;
+  emul_syscall *syscalls;
+};
+
+
+/* Emulation of simple UNIX system calls that are common on all systems.  */
+static void
+do_unix_exit(os_emul_data *emul,
+            unsigned call,
+            const int arg0,
+            cpu *processor,
+            unsigned_word cia)
+{
+  int status = (int)cpu_registers(processor)->gpr[arg0];
+  if (WITH_TRACE && ppc_trace[trace_os_emul])
+    printf_filtered ("%d)\n", status);
+
+  cpu_halt(processor, cia, was_exited, status);
+}
+
+
+static void
+do_unix_read(os_emul_data *emul,
+            unsigned call,
+            const int arg0,
+            cpu *processor,
+            unsigned_word cia)
+{
+  void *scratch_buffer;
+  int d = (int)cpu_registers(processor)->gpr[arg0];
+  unsigned_word buf = cpu_registers(processor)->gpr[arg0+1];
+  int nbytes = cpu_registers(processor)->gpr[arg0+2];
+  int status;
+
+  if (WITH_TRACE && ppc_trace[trace_os_emul])
+    printf_filtered ("%d, 0x%lx, %d", d, (long)buf, nbytes);
+
+  /* get a tempoary bufer */
+  scratch_buffer = zalloc(nbytes);
+
+  /* check if buffer exists by reading it */
+  emul_read_buffer(scratch_buffer, buf, nbytes, processor, cia);
+
+  /* read */
+  status = read (d, scratch_buffer, nbytes);
+
+  emul_write_status(processor, status, errno);
+  if (status > 0)
+    emul_write_buffer(scratch_buffer, buf, status, processor, cia);
+
+  zfree(scratch_buffer);
+}
+
+
+static void
+do_unix_write(os_emul_data *emul,
+             unsigned call,
+             const int arg0,
+             cpu *processor,
+             unsigned_word cia)
+{
+  void *scratch_buffer = NULL;
+  int nr_moved;
+  int d = (int)cpu_registers(processor)->gpr[arg0];
+  unsigned_word buf = cpu_registers(processor)->gpr[arg0+1];
+  int nbytes = cpu_registers(processor)->gpr[arg0+2];
+  int status;
+
+  if (WITH_TRACE && ppc_trace[trace_os_emul])
+    printf_filtered ("%d, 0x%lx, %d", d, (long)buf, nbytes);
+
+  /* get a tempoary bufer */
+  scratch_buffer = zalloc(nbytes); /* FIXME - nbytes == 0 */
+
+  /* copy in */
+  nr_moved = vm_data_map_read_buffer(cpu_data_map(processor),
+                                    scratch_buffer,
+                                    buf,
+                                    nbytes);
+  if (nr_moved != nbytes) {
+    /* FIXME - should handle better */
+    error("system_call()write copy failed (nr_moved=%d != nbytes=%d)\n",
+         nr_moved, nbytes);
+  }
+
+  /* write */
+  status = write(d, scratch_buffer, nbytes);
+  emul_write_status(processor, status, errno);
+  zfree(scratch_buffer);
+
+  flush_stdoutput();
+}
+
+
+static void
+do_unix_open(os_emul_data *emul,
+            unsigned call,
+            const int arg0,
+            cpu *processor,
+            unsigned_word cia)
+{
+  unsigned_word path_addr = cpu_registers(processor)->gpr[arg0];
+  char path_buf[PATH_MAX];
+  char *path = emul_read_string(path_buf, path_addr, PATH_MAX, processor, cia);
+  int flags = (int)cpu_registers(processor)->gpr[arg0+1];
+  int mode = (int)cpu_registers(processor)->gpr[arg0+2];
+  int status;
+
+  if (WITH_TRACE && ppc_trace[trace_os_emul])
+    printf_filtered ("0x%lx [%s], 0x%x, 0x%x", (long)path_addr, path, flags, mode);
+
+  status = open(path, flags, mode);
+  emul_write_status(processor, status, errno);
+}
+
+
+static void
+do_unix_close(os_emul_data *emul,
+             unsigned call,
+             const int arg0,
+             cpu *processor,
+             unsigned_word cia)
+{
+  int d = (int)cpu_registers(processor)->gpr[arg0];
+  int status;
+
+  if (WITH_TRACE && ppc_trace[trace_os_emul])
+    printf_filtered ("%d", d);
+
+  status = close(d);
+  emul_write_status(processor, status, errno);
+}
+
+
+static void
+do_unix_break(os_emul_data *emul,
+             unsigned call,
+             const int arg0,
+             cpu *processor,
+             unsigned_word cia)
+{
+  /* just pass this onto the `vm' device */
+  psim *system = cpu_system(processor);
+  unsigned_word new_break = cpu_registers(processor)->gpr[arg0];
+  int status;
+
+  if (WITH_TRACE && ppc_trace[trace_os_emul])
+    printf_filtered ("0x%lx", (long)cpu_registers(processor)->gpr[arg0]);
+
+  status = device_ioctl(emul->vm,
+                       system,
+                       processor,
+                       cia,
+                       new_break); /*ioctl-data*/
+
+  emul_write_status(processor, 0, status);
+}
+
+#ifndef HAVE_GETPID
+#define do_unix_getpid 0
+#else
+static void
+do_unix_getpid(os_emul_data *emul,
+              unsigned call,
+              const int arg0,
+              cpu *processor,
+              unsigned_word cia)
+{
+  int status = (int)getpid();
+  emul_write_status(processor, status, errno);
+}
+#endif
+
+#ifndef HAVE_GETPPID
+#define do_unix_getppid 0
+#else
+static void
+do_unix_getppid(os_emul_data *emul,
+               unsigned call,
+               const int arg0,
+               cpu *processor,
+               unsigned_word cia)
+{
+  int status = (int)getppid();
+  emul_write_status(processor, status, errno);
+}
+#endif
+
+#if !defined(HAVE_GETPID) || !defined(HAVE_GETPPID)
+#define do_unix_getpid2 0
+#else
+static void
+do_unix_getpid2(os_emul_data *emul,
+               unsigned call,
+               const int arg0,
+               cpu *processor,
+               unsigned_word cia)
+{
+  int pid  = (int)getpid();
+  int ppid = (int)getppid();
+  emul_write2_status(processor, pid, ppid, errno);
+}
+#endif
+
+#if !defined(HAVE_GETUID) || !defined(HAVE_GETEUID)
+#define do_unix_getuid2 0
+#else
+static void
+do_unix_getuid2(os_emul_data *emul,
+               unsigned call,
+               const int arg0,
+               cpu *processor,
+               unsigned_word cia)
+{
+  int uid  = (int)getuid();
+  int euid = (int)geteuid();
+  emul_write2_status(processor, uid, euid, errno);
+}
+#endif
+
+#ifndef HAVE_GETUID
+#define do_unix_getuid 0
+#else
+static void
+do_unix_getuid(os_emul_data *emul,
+              unsigned call,
+              const int arg0,
+              cpu *processor,
+              unsigned_word cia)
+{
+  int status = (int)getuid();
+  emul_write_status(processor, status, errno);
+}
+#endif
+
+#ifndef HAVE_GETEUID
+#define do_unix_geteuid 0
+#else
+static void
+do_unix_geteuid(os_emul_data *emul,
+               unsigned call,
+               const int arg0,
+               cpu *processor,
+               unsigned_word cia)
+{
+  int status = (int)geteuid();
+  emul_write_status(processor, status, errno);
+}
+#endif
+
+#if 0
+#ifndef HAVE_KILL
+#define do_unix_kill 0
+#else
+static void
+do_unix_kill(os_emul_data *emul,
+            unsigned call,
+            const int arg0,
+            cpu *processor,
+            unsigned_word cia)
+{
+  pid_t pid = cpu_registers(processor)->gpr[arg0];
+  int sig = cpu_registers(processor)->gpr[arg0+1];
+
+  if (WITH_TRACE && ppc_trace[trace_os_emul])
+    printf_filtered ("%d, %d", (int)pid, sig);
+
+  printf_filtered("SYS_kill at 0x%lx - more to this than just being killed\n",
+                 (long)cia);
+
+  cpu_halt(processor, cia, was_signalled, sig);
+}
+#endif
+#endif
+
+#ifndef HAVE_DUP
+#define do_unix_dup 0
+#else
+static void
+do_unix_dup(os_emul_data *emul,
+           unsigned call,
+           const int arg0,
+           cpu *processor,
+           unsigned_word cia)
+{
+  int oldd = cpu_registers(processor)->gpr[arg0];
+  int status = dup(oldd);
+  int err = errno;
+
+  if (WITH_TRACE && ppc_trace[trace_os_emul])
+    printf_filtered ("%d", oldd);
+
+  emul_write_status(processor, status, err);
+}
+#endif
+
+#ifndef HAVE_DUP2
+#define do_unix_dup2 0
+#else
+static void
+do_unix_dup2(os_emul_data *emul,
+            unsigned call,
+            const int arg0,
+            cpu *processor,
+            unsigned_word cia)
+{
+  int oldd = cpu_registers(processor)->gpr[arg0];
+  int newd = cpu_registers(processor)->gpr[arg0+1];
+  int status = dup2(oldd, newd);
+  int err = errno;
+
+  if (WITH_TRACE && ppc_trace[trace_os_emul])
+    printf_filtered ("%d, %d", oldd, newd);
+
+  emul_write_status(processor, status, err);
+}
+#endif
+
+#ifndef HAVE_LSEEK
+#define do_unix_lseek 0
+#else
+static void
+do_unix_lseek(os_emul_data *emul,
+             unsigned call,
+             const int arg0,
+             cpu *processor,
+             unsigned_word cia)
+{
+  int fildes = cpu_registers(processor)->gpr[arg0];
+  off_t offset = emul_read_gpr64(processor, arg0+2);
+  int whence = cpu_registers(processor)->gpr[arg0+4];
+  off_t status;
+
+  if (WITH_TRACE && ppc_trace[trace_os_emul])
+    printf_filtered ("%d %ld %d", fildes, (long)offset, whence);
+
+  status = lseek(fildes, offset, whence);
+  if (status == -1)
+    emul_write_status(processor, -1, errno);
+  else {
+    emul_write_status(processor, 0, 0); /* success */
+    emul_write_gpr64(processor, 3, status);
+  }
+}
+#endif
+
+
+#if !defined(HAVE_GETGID) || !defined(HAVE_GETEGID)
+#define do_unix_getgid2 0
+#else
+static void
+do_unix_getgid2(os_emul_data *emul,
+               unsigned call,
+               const int arg0,
+               cpu *processor,
+               unsigned_word cia)
+{
+  int gid  = (int)getgid();
+  int egid = (int)getegid();
+  emul_write2_status(processor, gid, egid, errno);
+}
+#endif
+
+#ifndef HAVE_GETGID
+#define do_unix_getgid 0
+#else
+static void
+do_unix_getgid(os_emul_data *emul,
+              unsigned call,
+              const int arg0,
+              cpu *processor,
+              unsigned_word cia)
+{
+  int status = (int)getgid();
+  emul_write_status(processor, status, 0);
+}
+#endif
+
+#ifndef HAVE_GETEGID
+#define do_unix_getegid 0
+#else
+static void
+do_unix_getegid(os_emul_data *emul,
+               unsigned call,
+               const int arg0,
+               cpu *processor,
+               unsigned_word cia)
+{
+  int status = (int)getegid();
+  emul_write_status(processor, status, errno);
+}
+#endif
+
+#ifndef HAVE_UMASK
+#define do_unix_umask 0
+#else
+static void
+do_unix_umask(os_emul_data *emul,
+             unsigned call,
+             const int arg0,
+             cpu *processor,
+             unsigned_word cia)
+{
+  int mask = cpu_registers(processor)->gpr[arg0];
+  int status = umask(mask);
+
+  if (WITH_TRACE && ppc_trace[trace_os_emul])
+    printf_filtered ("0%o", mask);
+
+  emul_write_status(processor, status, errno);
+}
+#endif
+
+#ifndef HAVE_CHDIR
+#define do_unix_chdir 0
+#else
+static void
+do_unix_chdir(os_emul_data *emul,
+             unsigned call,
+             const int arg0,
+             cpu *processor,
+             unsigned_word cia)
+{
+  unsigned_word path_addr = cpu_registers(processor)->gpr[arg0];
+  char path_buf[PATH_MAX];
+  char *path = emul_read_string(path_buf, path_addr, PATH_MAX, processor, cia);
+  int status;
+
+  if (WITH_TRACE && ppc_trace[trace_os_emul])
+    printf_filtered ("0x%lx [%s]", (long)path_addr, path);
+
+  status = chdir(path);
+  emul_write_status(processor, status, errno);
+}
+#endif
+
+#ifndef HAVE_LINK
+#define do_unix_link 0
+#else
+static void
+do_unix_link(os_emul_data *emul,
+            unsigned call,
+            const int arg0,
+            cpu *processor,
+            unsigned_word cia)
+{
+  unsigned_word path1_addr = cpu_registers(processor)->gpr[arg0];
+  char path1_buf[PATH_MAX];
+  char *path1 = emul_read_string(path1_buf, path1_addr, PATH_MAX, processor, cia);
+  unsigned_word path2_addr = cpu_registers(processor)->gpr[arg0+1];
+  char path2_buf[PATH_MAX];
+  char *path2 = emul_read_string(path2_buf, path2_addr, PATH_MAX, processor, cia);
+  int status;
+
+  if (WITH_TRACE && ppc_trace[trace_os_emul])
+    printf_filtered ("0x%lx [%s], 0x%lx [%s]", (long)path1_addr, path1, (long)path2_addr, path2);
+
+  status = link(path1, path2);
+  emul_write_status(processor, status, errno);
+}
+#endif
+
+#ifndef HAVE_SYMLINK
+#define do_unix_symlink 0
+#else
+static void
+do_unix_symlink(os_emul_data *emul,
+               unsigned call,
+               const int arg0,
+               cpu *processor,
+               unsigned_word cia)
+{
+  unsigned_word path1_addr = cpu_registers(processor)->gpr[arg0];
+  char path1_buf[PATH_MAX];
+  char *path1 = emul_read_string(path1_buf, path1_addr, PATH_MAX, processor, cia);
+  unsigned_word path2_addr = cpu_registers(processor)->gpr[arg0+1];
+  char path2_buf[PATH_MAX];
+  char *path2 = emul_read_string(path2_buf, path2_addr, PATH_MAX, processor, cia);
+  int status;
+
+  if (WITH_TRACE && ppc_trace[trace_os_emul])
+    printf_filtered ("0x%lx [%s], 0x%lx [%s]", (long)path1_addr, path1, (long)path2_addr, path2);
+
+  status = symlink(path1, path2);
+  emul_write_status(processor, status, errno);
+}
+#endif
+
+#ifndef HAVE_UNLINK
+#define do_unix_unlink 0
+#else
+static void
+do_unix_unlink(os_emul_data *emul,
+              unsigned call,
+              const int arg0,
+              cpu *processor,
+              unsigned_word cia)
+{
+  unsigned_word path_addr = cpu_registers(processor)->gpr[arg0];
+  char path_buf[PATH_MAX];
+  char *path = emul_read_string(path_buf, path_addr, PATH_MAX, processor, cia);
+  int status;
+
+  if (WITH_TRACE && ppc_trace[trace_os_emul])
+    printf_filtered ("0x%lx [%s]", (long)path_addr, path);
+
+  status = unlink(path);
+  emul_write_status(processor, status, errno);
+}
+#endif
+
+#ifndef HAVE_MKDIR
+#define do_unix_mkdir 0
+#else
+static void
+do_unix_mkdir(os_emul_data *emul,
+             unsigned call,
+             const int arg0,
+             cpu *processor,
+             unsigned_word cia)
+{
+  unsigned_word path_addr = cpu_registers(processor)->gpr[arg0];
+  char path_buf[PATH_MAX];
+  char *path = emul_read_string(path_buf, path_addr, PATH_MAX, processor, cia);
+  int mode = (int)cpu_registers(processor)->gpr[arg0+1];
+  int status;
+
+  if (WITH_TRACE && ppc_trace[trace_os_emul])
+    printf_filtered ("0x%lx [%s], 0%3o", (long)path_addr, path, mode);
+
+  status = mkdir(path, mode);
+  emul_write_status(processor, status, errno);
+}
+#endif
+
+#ifndef HAVE_RMDIR
+#define do_unix_rmdir 0
+#else
+static void
+do_unix_rmdir(os_emul_data *emul,
+             unsigned call,
+             const int arg0,
+             cpu *processor,
+             unsigned_word cia)
+{
+  unsigned_word path_addr = cpu_registers(processor)->gpr[arg0];
+  char path_buf[PATH_MAX];
+  char *path = emul_read_string(path_buf, path_addr, PATH_MAX, processor, cia);
+  int status;
+
+  if (WITH_TRACE && ppc_trace[trace_os_emul])
+    printf_filtered ("0x%lx [%s]", (long)path_addr, path);
+
+  status = rmdir(path);
+  emul_write_status(processor, status, errno);
+}
+#endif
+
+\f
+/* Common code for initializing the system call stuff */
+
+static os_emul_data *
+emul_unix_create(device *root,
+                bfd *image,
+                const char *name,
+                emul_syscall *syscall)
+{
+  unsigned_word top_of_stack;
+  unsigned stack_size;
+  int elf_binary;
+  os_emul_data *data;
+  device *vm;
+
+  /* merge any emulation specific entries into the device tree */
+
+  /* establish a few defaults */
+  if (image->xvec->flavour == bfd_target_elf_flavour) {
+    elf_binary = 1;
+    top_of_stack = 0xe0000000;
+    stack_size =   0x00100000;
+  }
+  else {
+    elf_binary = 0;
+    top_of_stack = 0x20000000;
+    stack_size =   0x00100000;
+  }
+
+  /* options */
+  emul_add_tree_options(root, image, name,
+                       (WITH_ENVIRONMENT == USER_ENVIRONMENT
+                        ? "user" : "virtual"),
+                       0 /*oea-interrupt-prefix*/);
+
+  /* virtual memory - handles growth of stack/heap */
+  vm = device_tree_add_parsed(root, "/openprom/vm@0x%lx",
+                             (unsigned long)(top_of_stack - stack_size));
+  device_tree_add_parsed(vm, "./stack-base 0x%lx",
+                        (unsigned long)(top_of_stack - stack_size));
+  device_tree_add_parsed(vm, "./nr-bytes 0x%x", stack_size);
+
+  device_tree_add_parsed(root, "/openprom/vm/map-binary/file-name %s",
+                        bfd_get_filename(image));
+
+  /* finish the init */
+  device_tree_add_parsed(root, "/openprom/init/register/pc 0x%lx",
+                        (unsigned long)bfd_get_start_address(image));
+  device_tree_add_parsed(root, "/openprom/init/register/sp 0x%lx",
+                        (unsigned long)top_of_stack);
+  device_tree_add_parsed(root, "/openprom/init/register/msr 0x%x", msr_little_endian_mode);
+  device_tree_add_parsed(root, "/openprom/init/stack/stack-type %s",
+                        (elf_binary ? "elf" : "xcoff"));
+
+  /* finally our emulation data */
+  data = ZALLOC(os_emul_data);
+  data->vm = vm;
+  data->syscalls = syscall;
+  return data;
+}
+
+\f
+/* Solaris specific implementation */
+
+typedef        signed32        solaris_uid_t;
+typedef        signed32        solaris_gid_t;
+typedef signed32       solaris_off_t;
+typedef signed32       solaris_pid_t;
+typedef signed32       solaris_time_t;
+typedef unsigned32     solaris_dev_t;
+typedef unsigned32     solaris_ino_t;
+typedef unsigned32     solaris_mode_t;
+typedef        unsigned32      solaris_nlink_t;
+
+#ifdef HAVE_SYS_STAT_H
+#define        SOLARIS_ST_FSTYPSZ 16           /* array size for file system type name */
+
+typedef struct {
+  solaris_time_t       tv_sec;
+  signed32             tv_usec;
+} solaris_timestruc_t;
+
+struct solaris_stat {
+  solaris_dev_t                st_dev;
+  signed32             st_pad1[3];     /* reserved for network id */
+  solaris_ino_t                st_ino;
+  solaris_mode_t       st_mode;
+  solaris_nlink_t      st_nlink;
+  solaris_uid_t        st_uid;
+  solaris_gid_t        st_gid;
+  solaris_dev_t                st_rdev;
+  signed32             st_pad2[2];
+  solaris_off_t                st_size;
+  signed32             st_pad3;        /* future off_t expansion */
+  solaris_timestruc_t  st_atim;
+  solaris_timestruc_t  st_mtim;
+  solaris_timestruc_t  st_ctim;
+  signed32             st_blksize;
+  signed32             st_blocks;
+  char                 st_fstype[SOLARIS_ST_FSTYPSZ];
+  signed32             st_pad4[8];     /* expansion area */
+};
+
+/* Convert from host stat structure to solaris stat structure */
+STATIC_INLINE_EMUL_UNIX void
+convert_to_solaris_stat(unsigned_word addr,
+                       struct stat *host,
+                       cpu *processor,
+                       unsigned_word cia)
+{
+  struct solaris_stat target;
+  int i;
+
+  target.st_dev   = H2T_4(host->st_dev);
+  target.st_ino   = H2T_4(host->st_ino);
+  target.st_mode  = H2T_4(host->st_mode);
+  target.st_nlink = H2T_4(host->st_nlink);
+  target.st_uid   = H2T_4(host->st_uid);
+  target.st_gid   = H2T_4(host->st_gid);
+  target.st_size  = H2T_4(host->st_size);
+
+#ifdef HAVE_ST_RDEV
+  target.st_rdev  = H2T_4(host->st_rdev);
+#else
+  target.st_rdev  = 0;
+#endif
+
+#ifdef HAVE_ST_BLKSIZE
+  target.st_blksize = H2T_4(host->st_blksize);
+#else
+  target.st_blksize = 0;
+#endif
+
+#ifdef HAVE_ST_BLOCKS
+  target.st_blocks  = H2T_4(host->st_blocks);
+#else
+  target.st_blocks  = 0;
+#endif
+
+  target.st_atim.tv_sec  = H2T_4(host->st_atime);
+  target.st_atim.tv_usec = 0;
+
+  target.st_ctim.tv_sec  = H2T_4(host->st_ctime);
+  target.st_ctim.tv_usec = 0;
+
+  target.st_mtim.tv_sec  = H2T_4(host->st_mtime);
+  target.st_mtim.tv_usec = 0;
+
+  for (i = 0; i < sizeof (target.st_pad1) / sizeof (target.st_pad1[0]); i++)
+    target.st_pad1[i] = 0;
+
+  for (i = 0; i < sizeof (target.st_pad2) / sizeof (target.st_pad2[0]); i++)
+    target.st_pad2[i] = 0;
+
+  target.st_pad3 = 0;
+
+  for (i = 0; i < sizeof (target.st_pad4) / sizeof (target.st_pad4[0]); i++)
+    target.st_pad4[i] = 0;
+
+  /* For now, just punt and always say it is a ufs file */
+  strcpy (target.st_fstype, "ufs");
+
+  emul_write_buffer(&target, addr, sizeof(target), processor, cia);
+}
+#endif /* HAVE_SYS_STAT_H */
+
+#ifndef HAVE_STAT
+#define do_solaris_stat 0
+#else
+static void
+do_solaris_stat(os_emul_data *emul,
+               unsigned call,
+               const int arg0,
+               cpu *processor,
+               unsigned_word cia)
+{
+  unsigned_word path_addr = cpu_registers(processor)->gpr[arg0];
+  unsigned_word stat_pkt = cpu_registers(processor)->gpr[arg0+1];
+  char path_buf[PATH_MAX];
+  struct stat buf;
+  char *path = emul_read_string(path_buf, path_addr, PATH_MAX, processor, cia);
+  int status;
+
+  if (WITH_TRACE && ppc_trace[trace_os_emul])
+    printf_filtered ("0x%lx [%s], 0x%lx", (long)path_addr, path, (long)stat_pkt);
+
+  status = stat (path, &buf);
+  if (status == 0)
+    convert_to_solaris_stat (stat_pkt, &buf, processor, cia);
+
+  emul_write_status(processor, status, errno);
+}
+#endif
+
+#ifndef HAVE_LSTAT
+#define do_solaris_lstat 0
+#else
+static void
+do_solaris_lstat(os_emul_data *emul,
+                unsigned call,
+                const int arg0,
+                cpu *processor,
+                unsigned_word cia)
+{
+  unsigned_word path_addr = cpu_registers(processor)->gpr[arg0];
+  unsigned_word stat_pkt = cpu_registers(processor)->gpr[arg0+1];
+  char path_buf[PATH_MAX];
+  struct stat buf;
+  char *path = emul_read_string(path_buf, path_addr, PATH_MAX, processor, cia);
+  int status;
+
+  if (WITH_TRACE && ppc_trace[trace_os_emul])
+    printf_filtered ("0x%lx [%s], 0x%lx", (long)path_addr, path, (long)stat_pkt);
+
+  status = lstat (path, &buf);
+  if (status == 0)
+    convert_to_solaris_stat (stat_pkt, &buf, processor, cia);
+
+  emul_write_status(processor, status, errno);
+}
+#endif
+
+#ifndef HAVE_FSTAT
+#define do_solaris_fstat 0
+#else
+static void
+do_solaris_fstat(os_emul_data *emul,
+                unsigned call,
+                const int arg0,
+                cpu *processor,
+                unsigned_word cia)
+{
+  int fildes = (int)cpu_registers(processor)->gpr[arg0];
+  unsigned_word stat_pkt = cpu_registers(processor)->gpr[arg0+1];
+  struct stat buf;
+  int status;
+
+  if (WITH_TRACE && ppc_trace[trace_os_emul])
+    printf_filtered ("%d, 0x%lx", fildes, (long)stat_pkt);
+
+  status = fstat (fildes, &buf);
+  if (status == 0)
+    convert_to_solaris_stat (stat_pkt, &buf, processor, cia);
+
+  emul_write_status(processor, status, errno);
+}
+#endif
+
+#if defined(HAVE_SYS_TERMIO_H) || defined(HAVE_SYS_TERMIOS_H)
+#define        SOLARIS_TIOC      ('T'<<8)
+#define SOLARIS_NCC      8
+#define SOLARIS_NCCS     19
+
+#define        SOLARIS_VINTR     0
+#define        SOLARIS_VQUIT     1
+#define        SOLARIS_VERASE    2
+#define        SOLARIS_VKILL     3
+#define        SOLARIS_VEOF      4
+#define        SOLARIS_VEOL      5
+#define        SOLARIS_VEOL2     6
+#define        SOLARIS_VSWTCH    7
+#define        SOLARIS_VSTART    8
+#define        SOLARIS_VSTOP     9
+#define        SOLARIS_VSUSP    10
+#define        SOLARIS_VDSUSP   11
+#define        SOLARIS_VREPRINT 12
+#define        SOLARIS_VDISCARD 13
+#define        SOLARIS_VWERASE  14
+#define        SOLARIS_VLNEXT   15
+#endif
+
+#ifdef HAVE_SYS_TERMIO_H
+/* Convert to/from host termio structure */
+
+struct solaris_termio {
+       unsigned16      c_iflag;                /* input modes */
+       unsigned16      c_oflag;                /* output modes */
+       unsigned16      c_cflag;                /* control modes */
+       unsigned16      c_lflag;                /* line discipline modes */
+       unsigned8       c_line;                 /* line discipline */
+       unsigned8       c_cc[SOLARIS_NCC];      /* control chars */
+};
+
+STATIC_INLINE_EMUL_UNIX void
+convert_to_solaris_termio(unsigned_word addr,
+                         struct termio *host,
+                         cpu *processor,
+                         unsigned_word cia)
+{
+  struct solaris_termio target;
+  int i;
+
+  target.c_iflag = H2T_2 (host->c_iflag);
+  target.c_oflag = H2T_2 (host->c_oflag);
+  target.c_cflag = H2T_2 (host->c_cflag);
+  target.c_lflag = H2T_2 (host->c_lflag);
+  target.c_line  = host->c_line;
+
+  for (i = 0; i < SOLARIS_NCC; i++)
+    target.c_cc[i] = 0;
+
+#ifdef VINTR
+  target.c_cc[SOLARIS_VINTR] = host->c_cc[VINTR];
+#endif
+
+#ifdef VQUIT
+  target.c_cc[SOLARIS_VQUIT] = host->c_cc[VQUIT];
+#endif
+
+#ifdef VERASE
+  target.c_cc[SOLARIS_VERASE] = host->c_cc[VERASE];
+#endif
+
+#ifdef VKILL
+  target.c_cc[SOLARIS_VKILL] = host->c_cc[VKILL];
+#endif
+
+#ifdef VEOF
+  target.c_cc[SOLARIS_VEOF] = host->c_cc[VEOF];
+#endif
+
+#ifdef VEOL
+  target.c_cc[SOLARIS_VEOL] = host->c_cc[VEOL];
+#endif
+
+#ifdef VEOL2
+  target.c_cc[SOLARIS_VEOL2] = host->c_cc[VEOL2];
+#endif
+
+#ifdef VSWTCH
+  target.c_cc[SOLARIS_VSWTCH] = host->c_cc[VSWTCH];
+
+#else
+#ifdef VSWTC
+  target.c_cc[SOLARIS_VSWTCH] = host->c_cc[VSWTC];
+#endif
+#endif
+
+  emul_write_buffer(&target, addr, sizeof(target), processor, cia);
+}
+#endif /* HAVE_SYS_TERMIO_H */
+
+#ifdef HAVE_SYS_TERMIOS_H
+/* Convert to/from host termios structure */
+
+typedef unsigned32 solaris_tcflag_t;
+typedef unsigned8  solaris_cc_t;
+typedef unsigned32 solaris_speed_t;
+
+struct solaris_termios {
+  solaris_tcflag_t     c_iflag;
+  solaris_tcflag_t     c_oflag;
+  solaris_tcflag_t     c_cflag;
+  solaris_tcflag_t     c_lflag;
+  solaris_cc_t         c_cc[SOLARIS_NCCS];
+};
+
+STATIC_INLINE_EMUL_UNIX void
+convert_to_solaris_termios(unsigned_word addr,
+                          struct termios *host,
+                          cpu *processor,
+                          unsigned_word cia)
+{
+  struct solaris_termios target;
+  int i;
+
+  target.c_iflag = H2T_4 (host->c_iflag);
+  target.c_oflag = H2T_4 (host->c_oflag);
+  target.c_cflag = H2T_4 (host->c_cflag);
+  target.c_lflag = H2T_4 (host->c_lflag);
+
+  for (i = 0; i < SOLARIS_NCCS; i++)
+    target.c_cc[i] = 0;
+
+#ifdef VINTR
+  target.c_cc[SOLARIS_VINTR] = host->c_cc[VINTR];
+#endif
+
+#ifdef VQUIT
+  target.c_cc[SOLARIS_VQUIT] = host->c_cc[VQUIT];
+#endif
+
+#ifdef VERASE
+  target.c_cc[SOLARIS_VERASE] = host->c_cc[VERASE];
+#endif
+
+#ifdef VKILL
+  target.c_cc[SOLARIS_VKILL] = host->c_cc[VKILL];
+#endif
+
+#ifdef VEOF
+  target.c_cc[SOLARIS_VEOF] = host->c_cc[VEOF];
+#endif
+
+#ifdef VEOL
+  target.c_cc[SOLARIS_VEOL] = host->c_cc[VEOL];
+#endif
+
+#ifdef VEOL2
+  target.c_cc[SOLARIS_VEOL2] = host->c_cc[VEOL2];
+#endif
+
+#ifdef VSWTCH
+  target.c_cc[SOLARIS_VSWTCH] = host->c_cc[VSWTCH];
+
+#else
+#ifdef VSWTC
+  target.c_cc[SOLARIS_VSWTCH] = host->c_cc[VSWTC];
+#endif
+#endif
+
+#ifdef VSTART
+  target.c_cc[SOLARIS_VSTART] = host->c_cc[VSTART];
+#endif
+
+#ifdef VSTOP
+  target.c_cc[SOLARIS_VSTOP] = host->c_cc[VSTOP];
+#endif
+
+#ifdef VSUSP
+  target.c_cc[SOLARIS_VSUSP] = host->c_cc[VSUSP];
+#endif
+
+#ifdef VDSUSP
+  target.c_cc[SOLARIS_VDSUSP] = host->c_cc[VDSUSP];
+#endif
+
+#ifdef VREPRINT
+  target.c_cc[SOLARIS_VREPRINT] = host->c_cc[VREPRINT];
+#endif
+
+#ifdef VDISCARD
+  target.c_cc[SOLARIS_VDISCARD] = host->c_cc[VDISCARD];
+#endif
+
+#ifdef VWERASE
+  target.c_cc[SOLARIS_VWERASE] = host->c_cc[VWERASE];
+#endif
+
+#ifdef VLNEXT
+  target.c_cc[SOLARIS_VLNEXT] = host->c_cc[VLNEXT];
+#endif
+
+  emul_write_buffer(&target, addr, sizeof(target), processor, cia);
+}
+#endif /* HAVE_SYS_TERMIOS_H */
+
+#ifndef HAVE_IOCTL
+#define do_solaris_ioctl 0
+#else
+static void
+do_solaris_ioctl(os_emul_data *emul,
+                unsigned call,
+                const int arg0,
+                cpu *processor,
+                unsigned_word cia)
+{
+  int fildes = cpu_registers(processor)->gpr[arg0];
+  unsigned request = cpu_registers(processor)->gpr[arg0+1];
+  unsigned_word argp_addr = cpu_registers(processor)->gpr[arg0+2];
+  int status = 0;
+  const char *name = "<unknown>";
+
+#ifdef HAVE_SYS_TERMIO_H
+  struct termio host_termio;
+#endif
+
+#ifdef HAVE_SYS_TERMIOS_H
+  struct termios host_termios;
+#endif
+
+  switch (request)
+    {
+    case 0:                                    /* make sure we have at least one case */
+    default:
+      status = -1;
+      errno = EINVAL;
+      break;
+
+#ifdef HAVE_SYS_TERMIO_H
+#ifdef TCGETA
+    case SOLARIS_TIOC | 1:                     /* TCGETA */
+      name = "TCGETA";
+      status = ioctl (fildes, TCGETA, &host_termio);
+      if (status == 0)
+       convert_to_solaris_termio (argp_addr, &host_termio, processor, cia);
+      break;
+#endif /* TCGETA */
+#endif /* HAVE_SYS_TERMIO_H */
+
+#ifdef HAVE_SYS_TERMIOS_H
+#if defined(TCGETS) || defined(HAVE_TCGETATTR)
+    case SOLARIS_TIOC | 13:                    /* TCGETS */
+      name = "TCGETS";
+#ifdef HAVE_TCGETATTR
+      status = tcgetattr(fildes, &host_termios);
+#else
+      status = ioctl (fildes, TCGETS, &host_termios);
+#endif
+      if (status == 0)
+       convert_to_solaris_termios (argp_addr, &host_termios, processor, cia);
+      break;
+#endif /* TCGETS */
+#endif /* HAVE_SYS_TERMIOS_H */
+    }
+
+  emul_write_status(processor, status, errno);
+
+  if (WITH_TRACE && ppc_trace[trace_os_emul])
+    printf_filtered ("%d, 0x%x [%s], 0x%lx", fildes, request, name, (long)argp_addr);
+}
+#endif /* HAVE_IOCTL */
+
+static emul_syscall_descriptor solaris_descriptors[] = {
+  /*   0 */ { 0, "syscall" },
+  /*   1 */ { do_unix_exit, "exit" },
+  /*   2 */ { 0, "fork" },
+  /*   3 */ { do_unix_read, "read" },
+  /*   4 */ { do_unix_write, "write" },
+  /*   5 */ { do_unix_open, "open" },
+  /*   6 */ { do_unix_close, "close" },
+  /*   7 */ { 0, "wait" },
+  /*   8 */ { 0, "creat" },
+  /*   9 */ { do_unix_link, "link" },
+  /*  10 */ { do_unix_unlink, "unlink" },
+  /*  11 */ { 0, "exec" },
+  /*  12 */ { do_unix_chdir, "chdir" },
+  /*  13 */ { 0, "time" },
+  /*  14 */ { 0, "mknod" },
+  /*  15 */ { 0, "chmod" },
+  /*  16 */ { 0, "chown" },
+  /*  17 */ { do_unix_break, "brk" },
+  /*  18 */ { do_solaris_stat, "stat" },
+  /*  19 */ { do_unix_lseek, "lseek" },
+  /*  20 */ { do_unix_getpid2, "getpid" },
+  /*  21 */ { 0, "mount" },
+  /*  22 */ { 0, "umount" },
+  /*  23 */ { 0, "setuid" },
+  /*  24 */ { do_unix_getuid2, "getuid" },
+  /*  25 */ { 0, "stime" },
+  /*  26 */ { 0, "ptrace" },
+  /*  27 */ { 0, "alarm" },
+  /*  28 */ { do_solaris_fstat, "fstat" },
+  /*  29 */ { 0, "pause" },
+  /*  30 */ { 0, "utime" },
+  /*  31 */ { 0, "stty" },
+  /*  32 */ { 0, "gtty" },
+  /*  33 */ { 0, "access" },
+  /*  34 */ { 0, "nice" },
+  /*  35 */ { 0, "statfs" },
+  /*  36 */ { 0, "sync" },
+  /*  37 */ { 0, "kill" },
+  /*  38 */ { 0, "fstatfs" },
+  /*  39 */ { 0, "pgrpsys" },
+  /*  40 */ { 0, "xenix" },
+  /*  41 */ { do_unix_dup, "dup" },
+  /*  42 */ { 0, "pipe" },
+  /*  43 */ { 0, "times" },
+  /*  44 */ { 0, "profil" },
+  /*  45 */ { 0, "plock" },
+  /*  46 */ { 0, "setgid" },
+  /*  47 */ { do_unix_getgid2, "getgid" },
+  /*  48 */ { 0, "signal" },
+  /*  49 */ { 0, "msgsys" },
+  /*  50 */ { 0, "syssun" },
+  /*  51 */ { 0, "acct" },
+  /*  52 */ { 0, "shmsys" },
+  /*  53 */ { 0, "semsys" },
+  /*  54 */ { do_solaris_ioctl, "ioctl" },
+  /*  55 */ { 0, "uadmin" },
+  /*  56 */ { 0, 0 /* reserved for exch */ },
+  /*  57 */ { 0, "utssys" },
+  /*  58 */ { 0, "fdsync" },
+  /*  59 */ { 0, "execve" },
+  /*  60 */ { do_unix_umask, "umask" },
+  /*  61 */ { 0, "chroot" },
+  /*  62 */ { 0, "fcntl" },
+  /*  63 */ { 0, "ulimit" },
+  /*  64 */ { 0, 0 /* reserved for UNIX PC */ },
+  /*  64 */ { 0, 0 /* reserved for UNIX PC */ },
+  /*  65 */ { 0, 0 /* reserved for UNIX PC */ },
+  /*  66 */ { 0, 0 /* reserved for UNIX PC */ },
+  /*  67 */ { 0, 0 /* reserved for UNIX PC */ },
+  /*  68 */ { 0, 0 /* reserved for UNIX PC */ },
+  /*  69 */ { 0, 0 /* reserved for UNIX PC */ },
+  /*  70 */ { 0, 0 /* was advfs */ },
+  /*  71 */ { 0, 0 /* was unadvfs */ },
+  /*  72 */ { 0, 0 /* was rmount */ },
+  /*  73 */ { 0, 0 /* was rumount */ },
+  /*  74 */ { 0, 0 /* was rfstart */ },
+  /*  75 */ { 0, 0 /* was sigret */ },
+  /*  76 */ { 0, 0 /* was rdebug */ },
+  /*  77 */ { 0, 0 /* was rfstop */ },
+  /*  78 */ { 0, 0 /* was rfsys */ },
+  /*  79 */ { do_unix_rmdir, "rmdir" },
+  /*  80 */ { do_unix_mkdir, "mkdir" },
+  /*  81 */ { 0, "getdents" },
+  /*  82 */ { 0, 0 /* was libattach */ },
+  /*  83 */ { 0, 0 /* was libdetach */ },
+  /*  84 */ { 0, "sysfs" },
+  /*  85 */ { 0, "getmsg" },
+  /*  86 */ { 0, "putmsg" },
+  /*  87 */ { 0, "poll" },
+  /*  88 */ { do_solaris_lstat, "lstat" },
+  /*  89 */ { do_unix_symlink, "symlink" },
+  /*  90 */ { 0, "readlink" },
+  /*  91 */ { 0, "setgroups" },
+  /*  92 */ { 0, "getgroups" },
+  /*  93 */ { 0, "fchmod" },
+  /*  94 */ { 0, "fchown" },
+  /*  95 */ { 0, "sigprocmask" },
+  /*  96 */ { 0, "sigsuspend" },
+  /*  97 */ { 0, "sigaltstack" },
+  /*  98 */ { 0, "sigaction" },
+  /*  99 */ { 0, "sigpending" },
+  /* 100 */ { 0, "context" },
+  /* 101 */ { 0, "evsys" },
+  /* 102 */ { 0, "evtrapret" },
+  /* 103 */ { 0, "statvfs" },
+  /* 104 */ { 0, "fstatvfs" },
+  /* 105 */ { 0, 0 /* reserved */ },
+  /* 106 */ { 0, "nfssys" },
+  /* 107 */ { 0, "waitsys" },
+  /* 108 */ { 0, "sigsendsys" },
+  /* 109 */ { 0, "hrtsys" },
+  /* 110 */ { 0, "acancel" },
+  /* 111 */ { 0, "async" },
+  /* 112 */ { 0, "priocntlsys" },
+  /* 113 */ { 0, "pathconf" },
+  /* 114 */ { 0, "mincore" },
+  /* 115 */ { 0, "mmap" },
+  /* 116 */ { 0, "mprotect" },
+  /* 117 */ { 0, "munmap" },
+  /* 118 */ { 0, "fpathconf" },
+  /* 119 */ { 0, "vfork" },
+  /* 120 */ { 0, "fchdir" },
+  /* 121 */ { 0, "readv" },
+  /* 122 */ { 0, "writev" },
+  /* 123 */ { 0, "xstat" },
+  /* 124 */ { 0, "lxstat" },
+  /* 125 */ { 0, "fxstat" },
+  /* 126 */ { 0, "xmknod" },
+  /* 127 */ { 0, "clocal" },
+  /* 128 */ { 0, "setrlimit" },
+  /* 129 */ { 0, "getrlimit" },
+  /* 130 */ { 0, "lchown" },
+  /* 131 */ { 0, "memcntl" },
+  /* 132 */ { 0, "getpmsg" },
+  /* 133 */ { 0, "putpmsg" },
+  /* 134 */ { 0, "rename" },
+  /* 135 */ { 0, "uname" },
+  /* 136 */ { 0, "setegid" },
+  /* 137 */ { 0, "sysconfig" },
+  /* 138 */ { 0, "adjtime" },
+  /* 139 */ { 0, "systeminfo" },
+  /* 140 */ { 0, 0 /* reserved */ },
+  /* 141 */ { 0, "seteuid" },
+  /* 142 */ { 0, "vtrace" },
+  /* 143 */ { 0, "fork1" },
+  /* 144 */ { 0, "sigtimedwait" },
+  /* 145 */ { 0, "lwp_info" },
+  /* 146 */ { 0, "yield" },
+  /* 147 */ { 0, "lwp_sema_wait" },
+  /* 148 */ { 0, "lwp_sema_post" },
+  /* 149 */ { 0, 0 /* reserved */ },
+  /* 150 */ { 0, 0 /* reserved */ },
+  /* 151 */ { 0, 0 /* reserved */ },
+  /* 152 */ { 0, "modctl" },
+  /* 153 */ { 0, "fchroot" },
+  /* 154 */ { 0, "utimes" },
+  /* 155 */ { 0, "vhangup" },
+  /* 156 */ { 0, "gettimeofday" },
+  /* 157 */ { 0, "getitimer" },
+  /* 158 */ { 0, "setitimer" },
+  /* 159 */ { 0, "lwp_create" },
+  /* 160 */ { 0, "lwp_exit" },
+  /* 161 */ { 0, "lwp_suspend" },
+  /* 162 */ { 0, "lwp_continue" },
+  /* 163 */ { 0, "lwp_kill" },
+  /* 164 */ { 0, "lwp_self" },
+  /* 165 */ { 0, "lwp_setprivate" },
+  /* 166 */ { 0, "lwp_getprivate" },
+  /* 167 */ { 0, "lwp_wait" },
+  /* 168 */ { 0, "lwp_mutex_unlock" },
+  /* 169 */ { 0, "lwp_mutex_lock" },
+  /* 170 */ { 0, "lwp_cond_wait" },
+  /* 171 */ { 0, "lwp_cond_signal" },
+  /* 172 */ { 0, "lwp_cond_broadcast" },
+  /* 173 */ { 0, "pread" },
+  /* 174 */ { 0, "pwrite" },
+  /* 175 */ { 0, "llseek" },
+  /* 176 */ { 0, "inst_sync" },
+  /* 177 */ { 0, 0 /* reserved */ },
+  /* 178 */ { 0, "kaio" },
+  /* 179 */ { 0, 0 /* reserved */ },
+  /* 180 */ { 0, 0 /* reserved */ },
+  /* 181 */ { 0, 0 /* reserved */ },
+  /* 182 */ { 0, 0 /* reserved */ },
+  /* 183 */ { 0, 0 /* reserved */ },
+  /* 184 */ { 0, "tsolsys" },
+  /* 185 */ { 0, "acl" },
+  /* 186 */ { 0, "auditsys" },
+  /* 187 */ { 0, "processor_bind" },
+  /* 188 */ { 0, "processor_info" },
+  /* 189 */ { 0, "p_online" },
+  /* 190 */ { 0, "sigqueue" },
+  /* 191 */ { 0, "clock_gettime" },
+  /* 192 */ { 0, "clock_settime" },
+  /* 193 */ { 0, "clock_getres" },
+  /* 194 */ { 0, "timer_create" },
+  /* 195 */ { 0, "timer_delete" },
+  /* 196 */ { 0, "timer_settime" },
+  /* 197 */ { 0, "timer_gettime" },
+  /* 198 */ { 0, "timer_getoverrun" },
+  /* 199 */ { 0, "nanosleep" },
+  /* 200 */ { 0, "facl" },
+  /* 201 */ { 0, "door" },
+  /* 202 */ { 0, "setreuid" },
+  /* 203 */ { 0, "setregid" },
+  /* 204 */ { 0, "install_utrap" },
+  /* 205 */ { 0, 0 /* reserved */ },
+  /* 206 */ { 0, 0 /* reserved */ },
+  /* 207 */ { 0, 0 /* reserved */ },
+  /* 208 */ { 0, 0 /* reserved */ },
+  /* 209 */ { 0, 0 /* reserved */ },
+  /* 210 */ { 0, "signotifywait" },
+  /* 211 */ { 0, "lwp_sigredirect" },
+  /* 212 */ { 0, "lwp_alarm" },
+};
+
+static char *(solaris_error_names[]) = {
+  /*   0 */ "ESUCCESS",
+  /*   1 */ "EPERM",
+  /*   2 */ "ENOENT",
+  /*   3 */ "ESRCH",
+  /*   4 */ "EINTR",
+  /*   5 */ "EIO",
+  /*   6 */ "ENXIO",
+  /*   7 */ "E2BIG",
+  /*   8 */ "ENOEXEC",
+  /*   9 */ "EBADF",
+  /*  10 */ "ECHILD",
+  /*  11 */ "EAGAIN",
+  /*  12 */ "ENOMEM",
+  /*  13 */ "EACCES",
+  /*  14 */ "EFAULT",
+  /*  15 */ "ENOTBLK",
+  /*  16 */ "EBUSY",
+  /*  17 */ "EEXIST",
+  /*  18 */ "EXDEV",
+  /*  19 */ "ENODEV",
+  /*  20 */ "ENOTDIR",
+  /*  21 */ "EISDIR",
+  /*  22 */ "EINVAL",
+  /*  23 */ "ENFILE",
+  /*  24 */ "EMFILE",
+  /*  25 */ "ENOTTY",
+  /*  26 */ "ETXTBSY",
+  /*  27 */ "EFBIG",
+  /*  28 */ "ENOSPC",
+  /*  29 */ "ESPIPE",
+  /*  30 */ "EROFS",
+  /*  31 */ "EMLINK",
+  /*  32 */ "EPIPE",
+  /*  33 */ "EDOM",
+  /*  34 */ "ERANGE",
+  /*  35 */ "ENOMSG",
+  /*  36 */ "EIDRM",
+  /*  37 */ "ECHRNG",
+  /*  38 */ "EL2NSYNC",
+  /*  39 */ "EL3HLT",
+  /*  40 */ "EL3RST",
+  /*  41 */ "ELNRNG",
+  /*  42 */ "EUNATCH",
+  /*  43 */ "ENOCSI",
+  /*  44 */ "EL2HLT",
+  /*  45 */ "EDEADLK",
+  /*  46 */ "ENOLCK",
+  /*  47 */ "ECANCELED",
+  /*  48 */ "ENOTSUP",
+  /*  49 */ "EDQUOT",
+  /*  50 */ "EBADE",
+  /*  51 */ "EBADR",
+  /*  52 */ "EXFULL",
+  /*  53 */ "ENOANO",
+  /*  54 */ "EBADRQC",
+  /*  55 */ "EBADSLT",
+  /*  56 */ "EDEADLOCK",
+  /*  57 */ "EBFONT",
+  /*  58 */ "Error code 58",
+  /*  59 */ "Error code 59",
+  /*  60 */ "ENOSTR",
+  /*  61 */ "ENODATA",
+  /*  62 */ "ETIME",
+  /*  63 */ "ENOSR",
+  /*  64 */ "ENONET",
+  /*  65 */ "ENOPKG",
+  /*  66 */ "EREMOTE",
+  /*  67 */ "ENOLINK",
+  /*  68 */ "EADV",
+  /*  69 */ "ESRMNT",
+  /*  70 */ "ECOMM",
+  /*  71 */ "EPROTO",
+  /*  72 */ "Error code 72",
+  /*  73 */ "Error code 73",
+  /*  74 */ "EMULTIHOP",
+  /*  75 */ "Error code 75",
+  /*  76 */ "Error code 76",
+  /*  77 */ "EBADMSG",
+  /*  78 */ "ENAMETOOLONG",
+  /*  79 */ "EOVERFLOW",
+  /*  80 */ "ENOTUNIQ",
+  /*  81 */ "EBADFD",
+  /*  82 */ "EREMCHG",
+  /*  83 */ "ELIBACC",
+  /*  84 */ "ELIBBAD",
+  /*  85 */ "ELIBSCN",
+  /*  86 */ "ELIBMAX",
+  /*  87 */ "ELIBEXEC",
+  /*  88 */ "EILSEQ",
+  /*  89 */ "ENOSYS",
+  /*  90 */ "ELOOP",
+  /*  91 */ "ERESTART",
+  /*  92 */ "ESTRPIPE",
+  /*  93 */ "ENOTEMPTY",
+  /*  94 */ "EUSERS",
+  /*  95 */ "ENOTSOCK",
+  /*  96 */ "EDESTADDRREQ",
+  /*  97 */ "EMSGSIZE",
+  /*  98 */ "EPROTOTYPE",
+  /*  99 */ "ENOPROTOOPT",
+  /* 100 */ "Error code 100",
+  /* 101 */ "Error code 101",
+  /* 102 */ "Error code 102",
+  /* 103 */ "Error code 103",
+  /* 104 */ "Error code 104",
+  /* 105 */ "Error code 105",
+  /* 106 */ "Error code 106",
+  /* 107 */ "Error code 107",
+  /* 108 */ "Error code 108",
+  /* 109 */ "Error code 109",
+  /* 110 */ "Error code 110",
+  /* 111 */ "Error code 111",
+  /* 112 */ "Error code 112",
+  /* 113 */ "Error code 113",
+  /* 114 */ "Error code 114",
+  /* 115 */ "Error code 115",
+  /* 116 */ "Error code 116",
+  /* 117 */ "Error code 117",
+  /* 118 */ "Error code 118",
+  /* 119 */ "Error code 119",
+  /* 120 */ "EPROTONOSUPPORT",
+  /* 121 */ "ESOCKTNOSUPPORT",
+  /* 122 */ "EOPNOTSUPP",
+  /* 123 */ "EPFNOSUPPORT",
+  /* 124 */ "EAFNOSUPPORT",
+  /* 125 */ "EADDRINUSE",
+  /* 126 */ "EADDRNOTAVAIL",
+  /* 127 */ "ENETDOWN",
+  /* 128 */ "ENETUNREACH",
+  /* 129 */ "ENETRESET",
+  /* 130 */ "ECONNABORTED",
+  /* 131 */ "ECONNRESET",
+  /* 132 */ "ENOBUFS",
+  /* 133 */ "EISCONN",
+  /* 134 */ "ENOTCONN",
+  /* 135 */ "Error code 135",  /* XENIX has 135 - 142 */
+  /* 136 */ "Error code 136",
+  /* 137 */ "Error code 137",
+  /* 138 */ "Error code 138",
+  /* 139 */ "Error code 139",
+  /* 140 */ "Error code 140",
+  /* 141 */ "Error code 141",
+  /* 142 */ "Error code 142",
+  /* 143 */ "ESHUTDOWN",
+  /* 144 */ "ETOOMANYREFS",
+  /* 145 */ "ETIMEDOUT",
+  /* 146 */ "ECONNREFUSED",
+  /* 147 */ "EHOSTDOWN",
+  /* 148 */ "EHOSTUNREACH",
+  /* 149 */ "EALREADY",
+  /* 150 */ "EINPROGRESS",
+  /* 151 */ "ESTALE",
+};
+
+static char *(solaris_signal_names[]) = {
+  /*  0 */ 0,
+  /*  1 */ "SIGHUP",
+  /*  2 */ "SIGINT",
+  /*  3 */ "SIGQUIT",
+  /*  4 */ "SIGILL",
+  /*  5 */ "SIGTRAP",
+  /*  6 */ "SIGABRT",
+  /*  7 */ "SIGEMT",
+  /*  8 */ "SIGFPE",
+  /*  9 */ "SIGKILL",
+  /* 10 */ "SIGBUS",
+  /* 11 */ "SIGSEGV",
+  /* 12 */ "SIGSYS",
+  /* 13 */ "SIGPIPE",
+  /* 14 */ "SIGALRM",
+  /* 15 */ "SIGTERM",
+  /* 16 */ "SIGUSR1",
+  /* 17 */ "SIGUSR2",
+  /* 18 */ "SIGCHLD",
+  /* 19 */ "SIGPWR",
+  /* 20 */ "SIGWINCH",
+  /* 21 */ "SIGURG",
+  /* 22 */ "SIGPOLL",
+  /* 23 */ "SIGSTOP",
+  /* 24 */ "SIGTSTP",
+  /* 25 */ "SIGCONT",
+  /* 26 */ "SIGTTIN",
+  /* 27 */ "SIGTTOU",
+  /* 28 */ "SIGVTALRM",
+  /* 29 */ "SIGPROF",
+  /* 30 */ "SIGXCPU",
+  /* 31 */ "SIGXFSZ",
+  /* 32 */ "SIGWAITING",
+  /* 33 */ "SIGLWP",
+  /* 34 */ "SIGFREEZE",
+  /* 35 */ "SIGTHAW",
+  /* 36 */ "SIGCANCEL",
+};
+
+static emul_syscall emul_solaris_syscalls = {
+  solaris_descriptors,
+  sizeof(solaris_descriptors) / sizeof(solaris_descriptors[0]),
+  solaris_error_names,
+  sizeof(solaris_error_names) / sizeof(solaris_error_names[0]),
+  solaris_signal_names,
+  sizeof(solaris_signal_names) / sizeof(solaris_signal_names[0]),
+};
+
+
+/* Solaris's os_emul interface, most are just passed on to the generic
+   syscall stuff */
+
+static os_emul_data *
+emul_solaris_create(device *root,
+                   bfd *image,
+                   const char *name)
+{
+  /* check that this emulation is really for us */
+  if (name != NULL && strcmp(name, "solaris") != 0)
+    return NULL;
+
+  if (image == NULL)
+    return NULL;
+
+  return emul_unix_create(root, image, "solaris", &emul_solaris_syscalls);
+}
+
+static void
+emul_solaris_init(os_emul_data *emul_data,
+                 int nr_cpus)
+{
+  /* nothing yet */
+}
+
+static void
+emul_solaris_system_call(cpu *processor,
+                        unsigned_word cia,
+                        os_emul_data *emul_data)
+{
+  emul_do_system_call(emul_data,
+                     emul_data->syscalls,
+                     cpu_registers(processor)->gpr[0],
+                     3, /*r3 contains arg0*/
+                     processor,
+                     cia);
+}
+
+const os_emul emul_solaris = {
+  "solaris",
+  emul_solaris_create,
+  emul_solaris_init,
+  emul_solaris_system_call,
+  0, /*instruction_call*/
+  0  /*data*/
+};
+
+\f
+/* Linux specific implementation */
+
+typedef unsigned32     linux_dev_t;
+typedef unsigned32     linux_ino_t;
+typedef unsigned32     linux_mode_t;
+typedef unsigned16     linux_nlink_t;
+typedef signed32       linux_off_t;
+typedef signed32       linux_pid_t;
+typedef unsigned32     linux_uid_t;
+typedef unsigned32     linux_gid_t;
+typedef unsigned32     linux_size_t;
+typedef signed32       linux_ssize_t;
+typedef signed32       linux_ptrdiff_t;
+typedef signed32       linux_time_t;
+typedef signed32       linux_clock_t;
+typedef signed32       linux_daddr_t;
+
+#ifdef HAVE_SYS_STAT_H
+/* For the PowerPC, don't both with the 'old' stat structure, since there
+   should be no extant binaries with that structure.  */
+
+struct linux_stat {
+       linux_dev_t     st_dev;
+       linux_ino_t     st_ino;
+       linux_mode_t    st_mode;
+       linux_nlink_t   st_nlink;
+       linux_uid_t     st_uid;
+       linux_gid_t     st_gid;
+       linux_dev_t     st_rdev;
+       linux_off_t     st_size;
+       unsigned32      st_blksize;
+       unsigned32      st_blocks;
+       unsigned32      st_atimx;       /* don't use st_{a,c,m}time, that might a macro */
+       unsigned32      __unused1;      /* defined by the host's stat.h */
+       unsigned32      st_mtimx;
+       unsigned32      __unused2;
+       unsigned32      st_ctimx;
+       unsigned32      __unused3;
+       unsigned32      __unused4;
+       unsigned32      __unused5;
+};
+
+/* Convert from host stat structure to solaris stat structure */
+STATIC_INLINE_EMUL_UNIX void
+convert_to_linux_stat(unsigned_word addr,
+                     struct stat *host,
+                     cpu *processor,
+                     unsigned_word cia)
+{
+  struct linux_stat target;
+
+  target.st_dev   = H2T_4(host->st_dev);
+  target.st_ino   = H2T_4(host->st_ino);
+  target.st_mode  = H2T_4(host->st_mode);
+  target.st_nlink = H2T_2(host->st_nlink);
+  target.st_uid   = H2T_4(host->st_uid);
+  target.st_gid   = H2T_4(host->st_gid);
+  target.st_size  = H2T_4(host->st_size);
+
+#ifdef HAVE_ST_RDEV
+  target.st_rdev  = H2T_4(host->st_rdev);
+#else
+  target.st_rdev  = 0;
+#endif
+
+#ifdef HAVE_ST_BLKSIZE
+  target.st_blksize = H2T_4(host->st_blksize);
+#else
+  target.st_blksize = 0;
+#endif
+
+#ifdef HAVE_ST_BLOCKS
+  target.st_blocks  = H2T_4(host->st_blocks);
+#else
+  target.st_blocks  = 0;
+#endif
+
+  target.st_atimx   = H2T_4(host->st_atime);
+  target.st_ctimx   = H2T_4(host->st_ctime);
+  target.st_mtimx   = H2T_4(host->st_mtime);
+  target.__unused1  = 0;
+  target.__unused2  = 0;
+  target.__unused3  = 0;
+  target.__unused4  = 0;
+  target.__unused5  = 0;
+
+  emul_write_buffer(&target, addr, sizeof(target), processor, cia);
+}
+#endif /* HAVE_SYS_STAT_H */
+
+#ifndef HAVE_STAT
+#define do_linux_stat 0
+#else
+static void
+do_linux_stat(os_emul_data *emul,
+             unsigned call,
+             const int arg0,
+             cpu *processor,
+             unsigned_word cia)
+{
+  unsigned_word path_addr = cpu_registers(processor)->gpr[arg0];
+  unsigned_word stat_pkt = cpu_registers(processor)->gpr[arg0+1];
+  char path_buf[PATH_MAX];
+  struct stat buf;
+  char *path = emul_read_string(path_buf, path_addr, PATH_MAX, processor, cia);
+  int status;
+
+  if (WITH_TRACE && ppc_trace[trace_os_emul])
+    printf_filtered ("0x%lx [%s], 0x%lx", (long)path_addr, path, (long)stat_pkt);
+
+  status = stat (path, &buf);
+  if (status == 0)
+    convert_to_linux_stat (stat_pkt, &buf, processor, cia);
+
+  emul_write_status(processor, status, errno);
+}
+#endif
+
+#ifndef HAVE_LSTAT
+#define do_linux_lstat 0
+#else
+static void
+do_linux_lstat(os_emul_data *emul,
+              unsigned call,
+              const int arg0,
+              cpu *processor,
+              unsigned_word cia)
+{
+  unsigned_word path_addr = cpu_registers(processor)->gpr[arg0];
+  unsigned_word stat_pkt = cpu_registers(processor)->gpr[arg0+1];
+  char path_buf[PATH_MAX];
+  struct stat buf;
+  char *path = emul_read_string(path_buf, path_addr, PATH_MAX, processor, cia);
+  int status;
+
+  if (WITH_TRACE && ppc_trace[trace_os_emul])
+    printf_filtered ("0x%lx [%s], 0x%lx", (long)path_addr, path, (long)stat_pkt);
+
+  status = lstat (path, &buf);
+  if (status == 0)
+    convert_to_linux_stat (stat_pkt, &buf, processor, cia);
+
+  emul_write_status(processor, status, errno);
+}
+#endif
+
+#ifndef HAVE_FSTAT
+#define do_linux_fstat 0
+#else
+static void
+do_linux_fstat(os_emul_data *emul,
+              unsigned call,
+              const int arg0,
+              cpu *processor,
+              unsigned_word cia)
+{
+  int fildes = (int)cpu_registers(processor)->gpr[arg0];
+  unsigned_word stat_pkt = cpu_registers(processor)->gpr[arg0+1];
+  struct stat buf;
+  int status;
+
+  if (WITH_TRACE && ppc_trace[trace_os_emul])
+    printf_filtered ("%d, 0x%lx", fildes, (long)stat_pkt);
+
+  status = fstat (fildes, &buf);
+  if (status == 0)
+    convert_to_linux_stat (stat_pkt, &buf, processor, cia);
+
+  emul_write_status(processor, status, errno);
+}
+#endif
+
+#if defined(HAVE_SYS_TERMIO_H) || defined(HAVE_SYS_TERMIOS_H)
+#define LINUX_NCC              10
+#define LINUX_NCCS             19
+       
+#define        LINUX_VINTR              0
+#define        LINUX_VQUIT              1
+#define        LINUX_VERASE             2
+#define        LINUX_VKILL              3
+#define        LINUX_VEOF               4
+#define LINUX_VMIN              5
+#define        LINUX_VEOL               6
+#define        LINUX_VTIME              7
+#define LINUX_VEOL2             8
+#define LINUX_VSWTC             9
+#define LINUX_VWERASE          10
+#define LINUX_VREPRINT         11
+#define LINUX_VSUSP            12
+#define LINUX_VSTART           13
+#define LINUX_VSTOP            14
+#define LINUX_VLNEXT           15
+#define LINUX_VDISCARD         16
+       
+#define LINUX_IOC_NRBITS        8
+#define LINUX_IOC_TYPEBITS      8
+#define LINUX_IOC_SIZEBITS     13
+#define LINUX_IOC_DIRBITS       3
+
+#define LINUX_IOC_NRMASK       ((1 << LINUX_IOC_NRBITS)-1)
+#define LINUX_IOC_TYPEMASK     ((1 << LINUX_IOC_TYPEBITS)-1)
+#define LINUX_IOC_SIZEMASK     ((1 << LINUX_IOC_SIZEBITS)-1)
+#define LINUX_IOC_DIRMASK      ((1 << LINUX_IOC_DIRBITS)-1)
+
+#define LINUX_IOC_NRSHIFT      0
+#define LINUX_IOC_TYPESHIFT    (LINUX_IOC_NRSHIFT+LINUX_IOC_NRBITS)
+#define LINUX_IOC_SIZESHIFT    (LINUX_IOC_TYPESHIFT+LINUX_IOC_TYPEBITS)
+#define LINUX_IOC_DIRSHIFT     (LINUX_IOC_SIZESHIFT+LINUX_IOC_SIZEBITS)
+
+/*
+ * Direction bits _IOC_NONE could be 0, but OSF/1 gives it a bit.
+ * And this turns out useful to catch old ioctl numbers in header
+ * files for us.
+ */
+#define LINUX_IOC_NONE         1U
+#define LINUX_IOC_READ         2U
+#define LINUX_IOC_WRITE                4U
+
+#define LINUX_IOC(dir,type,nr,size) \
+       (((dir)  << LINUX_IOC_DIRSHIFT) | \
+        ((type) << LINUX_IOC_TYPESHIFT) | \
+        ((nr)   << LINUX_IOC_NRSHIFT) | \
+        ((size) << LINUX_IOC_SIZESHIFT))
+
+/* used to create numbers */
+#define LINUX_IO(type,nr)       LINUX_IOC(LINUX_IOC_NONE,(type),(nr),0)
+#define LINUX_IOR(type,nr,size)         LINUX_IOC(LINUX_IOC_READ,(type),(nr),sizeof(size))
+#define LINUX_IOW(type,nr,size)         LINUX_IOC(LINUX_IOC_WRITE,(type),(nr),sizeof(size))
+#define LINUX_IOWR(type,nr,size) LINUX_IOC(LINUX_IOC_READ|LINUX_IOC_WRITE,(type),(nr),sizeof(size))
+#endif
+
+#ifdef HAVE_SYS_TERMIO_H
+/* Convert to/from host termio structure */
+
+struct linux_termio {
+       unsigned16      c_iflag;                /* input modes */
+       unsigned16      c_oflag;                /* output modes */
+       unsigned16      c_cflag;                /* control modes */
+       unsigned16      c_lflag;                /* line discipline modes */
+       unsigned8       c_line;                 /* line discipline */
+       unsigned8       c_cc[LINUX_NCC];        /* control chars */
+};
+
+STATIC_INLINE_EMUL_UNIX void
+convert_to_linux_termio(unsigned_word addr,
+                       struct termio *host,
+                       cpu *processor,
+                       unsigned_word cia)
+{
+  struct linux_termio target;
+  int i;
+
+  target.c_iflag = H2T_2 (host->c_iflag);
+  target.c_oflag = H2T_2 (host->c_oflag);
+  target.c_cflag = H2T_2 (host->c_cflag);
+  target.c_lflag = H2T_2 (host->c_lflag);
+  target.c_line  = host->c_line;
+
+  for (i = 0; i < LINUX_NCC; i++)
+    target.c_cc[i] = 0;
+
+#ifdef VINTR
+  target.c_cc[LINUX_VINTR] = host->c_cc[VINTR];
+#endif
+
+#ifdef VQUIT
+  target.c_cc[LINUX_VQUIT] = host->c_cc[VQUIT];
+#endif
+
+#ifdef VERASE
+  target.c_cc[LINUX_VERASE] = host->c_cc[VERASE];
+#endif
+
+#ifdef VKILL
+  target.c_cc[LINUX_VKILL] = host->c_cc[VKILL];
+#endif
+
+#ifdef VEOF
+  target.c_cc[LINUX_VEOF] = host->c_cc[VEOF];
+#endif
+
+#ifdef VMIN
+  target.c_cc[LINUX_VMIN] = host->c_cc[VMIN];
+#endif
+
+#ifdef VEOL
+  target.c_cc[LINUX_VEOL] = host->c_cc[VEOL];
+#endif
+
+#ifdef VTIME
+  target.c_cc[LINUX_VTIME] = host->c_cc[VTIME];
+#endif
+
+#ifdef VEOL2
+  target.c_cc[LINUX_VEOL2] = host->c_cc[VEOL2];
+#endif
+
+#ifdef VSWTC
+  target.c_cc[LINUX_VSWTC] = host->c_cc[VSWTC];
+#endif
+
+#ifdef VSWTCH
+  target.c_cc[LINUX_VSWTC] = host->c_cc[VSWTCH];
+#endif
+
+  emul_write_buffer(&target, addr, sizeof(target), processor, cia);
+}
+#endif /* HAVE_SYS_TERMIO_H */
+
+#ifdef HAVE_SYS_TERMIOS_H
+/* Convert to/from host termios structure */
+
+typedef unsigned32 linux_tcflag_t;
+typedef unsigned8  linux_cc_t;
+typedef unsigned32 linux_speed_t;
+
+struct linux_termios {
+  linux_tcflag_t       c_iflag;
+  linux_tcflag_t       c_oflag;
+  linux_tcflag_t       c_cflag;
+  linux_tcflag_t       c_lflag;
+  linux_cc_t           c_cc[LINUX_NCCS];
+  linux_cc_t           c_line;
+  signed32             c_ispeed;
+  signed32             c_ospeed;
+};
+
+STATIC_INLINE_EMUL_UNIX void
+convert_to_linux_termios(unsigned_word addr,
+                        struct termios *host,
+                        cpu *processor,
+                        unsigned_word cia)
+{
+  struct linux_termios target;
+  int i;
+
+  target.c_iflag = H2T_4 (host->c_iflag);
+  target.c_oflag = H2T_4 (host->c_oflag);
+  target.c_cflag = H2T_4 (host->c_cflag);
+  target.c_lflag = H2T_4 (host->c_lflag);
+
+  for (i = 0; i < LINUX_NCCS; i++)
+    target.c_cc[i] = 0;
+
+#ifdef VINTR
+  target.c_cc[LINUX_VINTR] = host->c_cc[VINTR];
+#endif
+
+#ifdef VQUIT
+  target.c_cc[LINUX_VQUIT] = host->c_cc[VQUIT];
+#endif
+
+#ifdef VERASE
+  target.c_cc[LINUX_VERASE] = host->c_cc[VERASE];
+#endif
+
+#ifdef VKILL
+  target.c_cc[LINUX_VKILL] = host->c_cc[VKILL];
+#endif
+
+#ifdef VEOF
+  target.c_cc[LINUX_VEOF] = host->c_cc[VEOF];
+#endif
+
+#ifdef VEOL
+  target.c_cc[LINUX_VEOL] = host->c_cc[VEOL];
+#endif
+
+#ifdef VEOL2
+  target.c_cc[LINUX_VEOL2] = host->c_cc[VEOL2];
+#endif
+
+#ifdef VSWTCH
+  target.c_cc[LINUX_VSWTCH] = host->c_cc[VSWTCH];
+#endif
+
+  target.c_line   = 0;
+
+#ifdef HAVE_CFGETISPEED
+  target.c_ispeed = cfgetispeed (host);
+#else
+  target.c_ispeed = 0;
+#endif
+
+#ifdef HAVE_CFGETOSPEED
+  target.c_ospeed = cfgetospeed (host);
+#else
+  target.c_ospeed = 0;
+#endif
+
+  emul_write_buffer(&target, addr, sizeof(target), processor, cia);
+}
+#endif /* HAVE_SYS_TERMIOS_H */
+
+#ifndef HAVE_IOCTL
+#define do_linux_ioctl 0
+#else
+static void
+do_linux_ioctl(os_emul_data *emul,
+                unsigned call,
+                const int arg0,
+                cpu *processor,
+                unsigned_word cia)
+{
+  int fildes = cpu_registers(processor)->gpr[arg0];
+  unsigned request = cpu_registers(processor)->gpr[arg0+1];
+  unsigned_word argp_addr = cpu_registers(processor)->gpr[arg0+2];
+  int status = 0;
+  const char *name = "<unknown>";
+
+#ifdef HAVE_SYS_TERMIO_H
+  struct termio host_termio;
+#endif
+
+#ifdef HAVE_SYS_TERMIOS_H
+  struct termios host_termios;
+#endif
+
+  switch (request)
+    {
+    case 0:                                    /* make sure we have at least one case */
+    default:
+      status = -1;
+      errno = EINVAL;
+      break;
+
+#ifdef HAVE_SYS_TERMIO_H
+#ifdef TCGETA
+    case LINUX_IOR('t', 23, struct linux_termio):      /* TCGETA */
+      name = "TCGETA";
+      status = ioctl (fildes, TCGETA, &host_termio);
+      if (status == 0)
+       convert_to_linux_termio (argp_addr, &host_termio, processor, cia);
+      break;
+#endif /* TCGETA */
+#endif /* HAVE_SYS_TERMIO_H */
+
+#ifdef HAVE_SYS_TERMIOS_H
+#if defined(TCGETS) || defined(HAVE_TCGETATTR)
+    case LINUX_IOR('t', 19, struct linux_termios):     /* TCGETS */
+      name = "TCGETS";
+#ifdef HAVE_TCGETATTR
+      status = tcgetattr(fildes, &host_termios);
+#else
+      status = ioctl (fildes, TCGETS, &host_termios);
+#endif
+      if (status == 0)
+       convert_to_linux_termios (argp_addr, &host_termios, processor, cia);
+      break;
+#endif /* TCGETS */
+#endif /* HAVE_SYS_TERMIOS_H */
+    }
+
+  emul_write_status(processor, status, errno);
+
+  if (WITH_TRACE && ppc_trace[trace_os_emul])
+    printf_filtered ("%d, 0x%x [%s], 0x%lx", fildes, request, name, (long)argp_addr);
+}
+#endif /* HAVE_IOCTL */
+
+static emul_syscall_descriptor linux_descriptors[] = {
+  /*   0 */ { 0, "setup" },
+  /*   1 */ { do_unix_exit, "exit" },
+  /*   2 */ { 0, "fork" },
+  /*   3 */ { do_unix_read, "read" },
+  /*   4 */ { do_unix_write, "write" },
+  /*   5 */ { do_unix_open, "open" },
+  /*   6 */ { do_unix_close, "close" },
+  /*   7 */ { 0, "waitpid" },
+  /*   8 */ { 0, "creat" },
+  /*   9 */ { do_unix_link, "link" },
+  /*  10 */ { do_unix_unlink, "unlink" },
+  /*  11 */ { 0, "execve" },
+  /*  12 */ { do_unix_chdir, "chdir" },
+  /*  13 */ { 0, "time" },
+  /*  14 */ { 0, "mknod" },
+  /*  15 */ { 0, "chmod" },
+  /*  16 */ { 0, "chown" },
+  /*  17 */ { 0, "break" },
+  /*  18 */ { 0, "stat" },
+  /*  19 */ { do_unix_lseek, "lseek" },
+  /*  20 */ { do_unix_getpid, "getpid" },
+  /*  21 */ { 0, "mount" },
+  /*  22 */ { 0, "umount" },
+  /*  23 */ { 0, "setuid" },
+  /*  24 */ { do_unix_getuid, "getuid" },
+  /*  25 */ { 0, "stime" },
+  /*  26 */ { 0, "ptrace" },
+  /*  27 */ { 0, "alarm" },
+  /*  28 */ { 0, "fstat" },
+  /*  29 */ { 0, "pause" },
+  /*  30 */ { 0, "utime" },
+  /*  31 */ { 0, "stty" },
+  /*  32 */ { 0, "gtty" },
+  /*  33 */ { 0, "access" },
+  /*  34 */ { 0, "nice" },
+  /*  35 */ { 0, "ftime" },
+  /*  36 */ { 0, "sync" },
+  /*  37 */ { 0, "kill" },
+  /*  38 */ { 0, "rename" },
+  /*  39 */ { do_unix_mkdir, "mkdir" },
+  /*  40 */ { do_unix_rmdir, "rmdir" },
+  /*  41 */ { do_unix_dup, "dup" },
+  /*  42 */ { 0, "pipe" },
+  /*  43 */ { 0, "times" },
+  /*  44 */ { 0, "prof" },
+  /*  45 */ { do_unix_break, "brk" },
+  /*  46 */ { 0, "setgid" },
+  /*  47 */ { do_unix_getgid, "getgid" },
+  /*  48 */ { 0, "signal" },
+  /*  49 */ { do_unix_geteuid, "geteuid" },
+  /*  50 */ { do_unix_getegid, "getegid" },
+  /*  51 */ { 0, "acct" },
+  /*  52 */ { 0, "phys" },
+  /*  53 */ { 0, "lock" },
+  /*  54 */ { do_linux_ioctl, "ioctl" },
+  /*  55 */ { 0, "fcntl" },
+  /*  56 */ { 0, "mpx" },
+  /*  57 */ { 0, "setpgid" },
+  /*  58 */ { 0, "ulimit" },
+  /*  59 */ { 0, "olduname" },
+  /*  60 */ { do_unix_umask, "umask" },
+  /*  61 */ { 0, "chroot" },
+  /*  62 */ { 0, "ustat" },
+  /*  63 */ { do_unix_dup2, "dup2" },
+  /*  64 */ { do_unix_getppid, "getppid" },
+  /*  65 */ { 0, "getpgrp" },
+  /*  66 */ { 0, "setsid" },
+  /*  67 */ { 0, "sigaction" },
+  /*  68 */ { 0, "sgetmask" },
+  /*  69 */ { 0, "ssetmask" },
+  /*  70 */ { 0, "setreuid" },
+  /*  71 */ { 0, "setregid" },
+  /*  72 */ { 0, "sigsuspend" },
+  /*  73 */ { 0, "sigpending" },
+  /*  74 */ { 0, "sethostname" },
+  /*  75 */ { 0, "setrlimit" },
+  /*  76 */ { 0, "getrlimit" },
+  /*  77 */ { 0, "getrusage" },
+  /*  78 */ { 0, "gettimeofday" },
+  /*  79 */ { 0, "settimeofday" },
+  /*  80 */ { 0, "getgroups" },
+  /*  81 */ { 0, "setgroups" },
+  /*  82 */ { 0, "select" },
+  /*  83 */ { do_unix_symlink, "symlink" },
+  /*  84 */ { 0, "lstat" },
+  /*  85 */ { 0, "readlink" },
+  /*  86 */ { 0, "uselib" },
+  /*  87 */ { 0, "swapon" },
+  /*  88 */ { 0, "reboot" },
+  /*  89 */ { 0, "readdir" },
+  /*  90 */ { 0, "mmap" },
+  /*  91 */ { 0, "munmap" },
+  /*  92 */ { 0, "truncate" },
+  /*  93 */ { 0, "ftruncate" },
+  /*  94 */ { 0, "fchmod" },
+  /*  95 */ { 0, "fchown" },
+  /*  96 */ { 0, "getpriority" },
+  /*  97 */ { 0, "setpriority" },
+  /*  98 */ { 0, "profil" },
+  /*  99 */ { 0, "statfs" },
+  /* 100 */ { 0, "fstatfs" },
+  /* 101 */ { 0, "ioperm" },
+  /* 102 */ { 0, "socketcall" },
+  /* 103 */ { 0, "syslog" },
+  /* 104 */ { 0, "setitimer" },
+  /* 105 */ { 0, "getitimer" },
+  /* 106 */ { do_linux_stat, "newstat" },
+  /* 107 */ { do_linux_lstat, "newlstat" },
+  /* 108 */ { do_linux_fstat, "newfstat" },
+  /* 109 */ { 0, "uname" },
+  /* 110 */ { 0, "iopl" },
+  /* 111 */ { 0, "vhangup" },
+  /* 112 */ { 0, "idle" },
+  /* 113 */ { 0, "vm86" },
+  /* 114 */ { 0, "wait4" },
+  /* 115 */ { 0, "swapoff" },
+  /* 116 */ { 0, "sysinfo" },
+  /* 117 */ { 0, "ipc" },
+  /* 118 */ { 0, "fsync" },
+  /* 119 */ { 0, "sigreturn" },
+  /* 120 */ { 0, "clone" },
+  /* 121 */ { 0, "setdomainname" },
+  /* 122 */ { 0, "newuname" },
+  /* 123 */ { 0, "modify_ldt" },
+  /* 124 */ { 0, "adjtimex" },
+  /* 125 */ { 0, "mprotect" },
+  /* 126 */ { 0, "sigprocmask" },
+  /* 127 */ { 0, "create_module" },
+  /* 128 */ { 0, "init_module" },
+  /* 129 */ { 0, "delete_module" },
+  /* 130 */ { 0, "get_kernel_syms" },
+  /* 131 */ { 0, "quotactl" },
+  /* 132 */ { 0, "getpgid" },
+  /* 133 */ { 0, "fchdir" },
+  /* 134 */ { 0, "bdflush" },
+  /* 135 */ { 0, "sysfs" },
+  /* 136 */ { 0, "personality" },
+  /* 137 */ { 0, "afs_syscall" },
+  /* 138 */ { 0, "setfsuid" },
+  /* 139 */ { 0, "setfsgid" },
+  /* 140 */ { 0, "llseek" },
+  /* 141 */ { 0, "getdents" },
+  /* 142 */ { 0, "newselect" },
+  /* 143 */ { 0, "flock" },
+  /* 144 */ { 0, "msync" },
+  /* 145 */ { 0, "readv" },
+  /* 146 */ { 0, "writev" },
+  /* 147 */ { 0, "getsid" },
+  /* 148 */ { 0, "fdatasync" },
+  /* 149 */ { 0, "sysctl" },
+  /* 150 */ { 0, "mlock" },
+  /* 151 */ { 0, "munlock" },
+  /* 152 */ { 0, "mlockall" },
+  /* 153 */ { 0, "munlockall" },
+  /* 154 */ { 0, "sched_setparam" },
+  /* 155 */ { 0, "sched_getparam" },
+  /* 156 */ { 0, "sched_setscheduler" },
+  /* 157 */ { 0, "sched_getscheduler" },
+  /* 158 */ { 0, "sched_yield" },
+  /* 159 */ { 0, "sched_get_priority_max" },
+  /* 160 */ { 0, "sched_get_priority_min" },
+  /* 161 */ { 0, "sched_rr_get_interval" },
+};
+
+static char *(linux_error_names[]) = {
+  /*   0 */ "ESUCCESS",
+  /*   1 */ "EPERM",
+  /*   2 */ "ENOENT",
+  /*   3 */ "ESRCH",
+  /*   4 */ "EINTR",
+  /*   5 */ "EIO",
+  /*   6 */ "ENXIO",
+  /*   7 */ "E2BIG",
+  /*   8 */ "ENOEXEC",
+  /*   9 */ "EBADF",
+  /*  10 */ "ECHILD",
+  /*  11 */ "EAGAIN",
+  /*  12 */ "ENOMEM",
+  /*  13 */ "EACCES",
+  /*  14 */ "EFAULT",
+  /*  15 */ "ENOTBLK",
+  /*  16 */ "EBUSY",
+  /*  17 */ "EEXIST",
+  /*  18 */ "EXDEV",
+  /*  19 */ "ENODEV",
+  /*  20 */ "ENOTDIR",
+  /*  21 */ "EISDIR",
+  /*  22 */ "EINVAL",
+  /*  23 */ "ENFILE",
+  /*  24 */ "EMFILE",
+  /*  25 */ "ENOTTY",
+  /*  26 */ "ETXTBSY",
+  /*  27 */ "EFBIG",
+  /*  28 */ "ENOSPC",
+  /*  29 */ "ESPIPE",
+  /*  30 */ "EROFS",
+  /*  31 */ "EMLINK",
+  /*  32 */ "EPIPE",
+  /*  33 */ "EDOM",
+  /*  34 */ "ERANGE",
+  /*  35 */ "EDEADLK",
+  /*  36 */ "ENAMETOOLONG",
+  /*  37 */ "ENOLCK",
+  /*  38 */ "ENOSYS",
+  /*  39 */ "ENOTEMPTY",
+  /*  40 */ "ELOOP",
+  /*  41 */ 0,
+  /*  42 */ "ENOMSG",
+  /*  43 */ "EIDRM",
+  /*  44 */ "ECHRNG",
+  /*  45 */ "EL2NSYNC",
+  /*  46 */ "EL3HLT",
+  /*  47 */ "EL3RST",
+  /*  48 */ "ELNRNG",
+  /*  49 */ "EUNATCH",
+  /*  50 */ "ENOCSI",
+  /*  51 */ "EL2HLT",
+  /*  52 */ "EBADE",
+  /*  53 */ "EBADR",
+  /*  54 */ "EXFULL",
+  /*  55 */ "ENOANO",
+  /*  56 */ "EBADRQC",
+  /*  57 */ "EBADSLT",
+  /*  58 */ "EDEADLOCK",
+  /*  59 */ "EBFONT",
+  /*  60 */ "ENOSTR",
+  /*  61 */ "ENODATA",
+  /*  62 */ "ETIME",
+  /*  63 */ "ENOSR",
+  /*  64 */ "ENONET",
+  /*  65 */ "ENOPKG",
+  /*  66 */ "EREMOTE",
+  /*  67 */ "ENOLINK",
+  /*  68 */ "EADV",
+  /*  69 */ "ESRMNT",
+  /*  70 */ "ECOMM",
+  /*  71 */ "EPROTO",
+  /*  72 */ "EMULTIHOP",
+  /*  73 */ "EDOTDOT",
+  /*  74 */ "EBADMSG",
+  /*  75 */ "EOVERFLOW",
+  /*  76 */ "ENOTUNIQ",
+  /*  77 */ "EBADFD",
+  /*  78 */ "EREMCHG",
+  /*  79 */ "ELIBACC",
+  /*  80 */ "ELIBBAD",
+  /*  81 */ "ELIBSCN",
+  /*  82 */ "ELIBMAX",
+  /*  83 */ "ELIBEXEC",
+  /*  84 */ "EILSEQ",
+  /*  85 */ "ERESTART",
+  /*  86 */ "ESTRPIPE",
+  /*  87 */ "EUSERS",
+  /*  88 */ "ENOTSOCK",
+  /*  89 */ "EDESTADDRREQ",
+  /*  90 */ "EMSGSIZE",
+  /*  91 */ "EPROTOTYPE",
+  /*  92 */ "ENOPROTOOPT",
+  /*  93 */ "EPROTONOSUPPORT",
+  /*  94 */ "ESOCKTNOSUPPORT",
+  /*  95 */ "EOPNOTSUPP",
+  /*  96 */ "EPFNOSUPPORT",
+  /*  97 */ "EAFNOSUPPORT",
+  /*  98 */ "EADDRINUSE",
+  /*  99 */ "EADDRNOTAVAIL",
+  /* 100 */ "ENETDOWN",
+  /* 101 */ "ENETUNREACH",
+  /* 102 */ "ENETRESET",
+  /* 103 */ "ECONNABORTED",
+  /* 104 */ "ECONNRESET",
+  /* 105 */ "ENOBUFS",
+  /* 106 */ "EISCONN",
+  /* 107 */ "ENOTCONN",
+  /* 108 */ "ESHUTDOWN",
+  /* 109 */ "ETOOMANYREFS",
+  /* 110 */ "ETIMEDOUT",
+  /* 111 */ "ECONNREFUSED",
+  /* 112 */ "EHOSTDOWN",
+  /* 113 */ "EHOSTUNREACH",
+  /* 114 */ "EALREADY",
+  /* 115 */ "EINPROGRESS",
+  /* 116 */ "ESTALE",
+  /* 117 */ "EUCLEAN",
+  /* 118 */ "ENOTNAM",
+  /* 119 */ "ENAVAIL",
+  /* 120 */ "EISNAM",
+  /* 121 */ "EREMOTEIO",
+  /* 122 */ "EDQUOT",
+};
+
+static char *(linux_signal_names[]) = {
+  /*  0 */ 0,
+  /*  1 */ "SIGHUP",
+  /*  2 */ "SIGINT",
+  /*  3 */ "SIGQUIT",
+  /*  4 */ "SIGILL",
+  /*  5 */ "SIGTRAP",
+  /*  6 */ "SIGABRT",
+  /*  6 */ "SIGIOT",
+  /*  7 */ "SIGBUS",
+  /*  8 */ "SIGFPE",
+  /*  9 */ "SIGKILL",
+  /* 10 */ "SIGUSR1",
+  /* 11 */ "SIGSEGV",
+  /* 12 */ "SIGUSR2",
+  /* 13 */ "SIGPIPE",
+  /* 14 */ "SIGALRM",
+  /* 15 */ "SIGTERM",
+  /* 16 */ "SIGSTKFLT",
+  /* 17 */ "SIGCHLD",
+  /* 18 */ "SIGCONT",
+  /* 19 */ "SIGSTOP",
+  /* 20 */ "SIGTSTP",
+  /* 21 */ "SIGTTIN",
+  /* 22 */ "SIGTTOU",
+  /* 23 */ "SIGURG",
+  /* 24 */ "SIGXCPU",
+  /* 25 */ "SIGXFSZ",
+  /* 26 */ "SIGVTALRM",
+  /* 27 */ "SIGPROF",
+  /* 28 */ "SIGWINCH",
+  /* 29 */ "SIGIO",
+  /* 30 */ "SIGPWR",
+  /* 31 */ "SIGUNUSED",
+};
+
+static emul_syscall emul_linux_syscalls = {
+  linux_descriptors,
+  sizeof(linux_descriptors) / sizeof(linux_descriptors[0]),
+  linux_error_names,
+  sizeof(linux_error_names) / sizeof(linux_error_names[0]),
+  linux_signal_names,
+  sizeof(linux_signal_names) / sizeof(linux_signal_names[0]),
+};
+
+
+/* Linux's os_emul interface, most are just passed on to the generic
+   syscall stuff */
+
+static os_emul_data *
+emul_linux_create(device *root,
+                   bfd *image,
+                   const char *name)
+{
+  /* check that this emulation is really for us */
+  if (name != NULL && strcmp(name, "linux") != 0)
+    return NULL;
+
+  if (image == NULL)
+    return NULL;
+
+  return emul_unix_create(root, image, "linux", &emul_linux_syscalls);
+}
+
+static void
+emul_linux_init(os_emul_data *emul_data,
+                 int nr_cpus)
+{
+  /* nothing yet */
+}
+
+static void
+emul_linux_system_call(cpu *processor,
+                        unsigned_word cia,
+                        os_emul_data *emul_data)
+{
+  emul_do_system_call(emul_data,
+                     emul_data->syscalls,
+                     cpu_registers(processor)->gpr[0],
+                     3, /*r3 contains arg0*/
+                     processor,
+                     cia);
+}
+
+const os_emul emul_linux = {
+  "linux",
+  emul_linux_create,
+  emul_linux_init,
+  emul_linux_system_call,
+  0, /*instruction_call*/
+  0  /*data*/
+};
+
+#endif /* _EMUL_UNIX_C_ */
diff --git a/sim/ppc/emul_unix.h b/sim/ppc/emul_unix.h
new file mode 100644 (file)
index 0000000..6695cc7
--- /dev/null
@@ -0,0 +1,28 @@
+/*  This file is part of the program psim.
+
+    Copyright (C) 1996, Andrew Cagney <cagney@highland.com.au>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+    */
+
+
+#ifndef _EMUL_UNIX_H_
+#define _EMUL_UNIX_H_
+
+extern const os_emul emul_solaris;
+extern const os_emul emul_linux;
+
+#endif
index 4be73d94dbcdc72925a3830af6cd44ba296b2b07..2a89782deb2f6403e48420fce03496b955c582bb 100644 (file)
@@ -155,6 +155,8 @@ psim_usage(int verbose)
   printf_filtered("\t              Can be any of the following:\n");
   printf_filtered("\t              bug - OEA + MOTO BUG ROM calls\n");
   printf_filtered("\t              netbsd - UEA + NetBSD system calls\n");
+  printf_filtered("\t              solaris - UEA + Solaris system calls\n");
+  printf_filtered("\t              linux - UEA + Linux system calls\n");
   printf_filtered("\t              chirp - OEA + a few OpenBoot calls\n");
   printf_filtered("\n"); }
   printf_filtered("\t-i            Print instruction counting statistics\n");
@@ -353,7 +355,6 @@ psim_create(const char *file_name,
   for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; cpu_nr++) {
     system->processors[cpu_nr] = cpu_create(system,
                                            system->memory,
-                                           system->events,
                                            mon_cpu(system->monitor,
                                                    cpu_nr),
                                            system->os_emulation,
@@ -404,15 +405,16 @@ INLINE_PSIM\
 (void)
 psim_halt(psim *system,
          int current_cpu,
-         unsigned_word cia,
          stop_reason reason,
          int signal)
 {
+  ASSERT(current_cpu >= 0 && current_cpu < system->nr_cpus);
   system->last_cpu = current_cpu;
   system->halt_status.cpu_nr = current_cpu;
   system->halt_status.reason = reason;
   system->halt_status.signal = signal;
-  system->halt_status.program_counter = cia;
+  system->halt_status.program_counter =
+    cpu_get_program_counter(system->processors[current_cpu]);
   longjmp(*(jmp_buf*)(system->path_to_halt), current_cpu + 1);
 }
 
@@ -444,6 +446,13 @@ psim_device(psim *system,
   return device_tree_find_device(system->devices, path);
 }
 
+INLINE_PSIM\
+(event_queue *)
+psim_event_queue(psim *system)
+{
+  return system->events;
+}
+
 
 
 INLINE_PSIM\