Add a test case for skip with inlined functions
[deliverable/binutils-gdb.git] / sim / cris / traps.c
index 5b3718d3900bcfb7b5bd04c43619834f66412ba4..ba7bb9f85370944169fa9d6792799d29d27bc37f 100644 (file)
@@ -1,27 +1,29 @@
 /* CRIS exception, interrupt, and trap (EIT) support
-   Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+   Copyright (C) 2004-2019 Free Software Foundation, Inc.
    Contributed by Axis Communications.
 
 This file is part of the GNU simulators.
 
 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, or (at your option)
-any later version.
+the Free Software Foundation; either version 3 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.  */
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "sim-main.h"
+#include "sim-syscall.h"
 #include "sim-options.h"
-#include "targ-vals.h"
 #include "bfd.h"
+/* FIXME: get rid of targ-vals.h usage everywhere else.  */
+
+#include <stdarg.h>
 #ifdef HAVE_ERRNO_H
 #include <errno.h>
 #endif
@@ -37,6 +39,21 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #ifdef HAVE_SYS_STAT_H
 #include <sys/stat.h>
 #endif
+/* For PATH_MAX, originally. */
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+
+/* From ld/sysdep.h.  */
+#ifdef PATH_MAX
+# define SIM_PATHMAX PATH_MAX
+#else
+# ifdef MAXPATHLEN
+#  define SIM_PATHMAX MAXPATHLEN
+# else
+#  define SIM_PATHMAX 1024
+# endif
+#endif
 
 /* The verbatim values are from asm-cris/unistd.h.  */
 
@@ -49,6 +66,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #define TARGET_SYS_time 13
 #define TARGET_SYS_lseek 19
 #define TARGET_SYS_getpid 20
+#define TARGET_SYS_access 33
 #define TARGET_SYS_kill 37
 #define TARGET_SYS_rename 38
 #define TARGET_SYS_pipe 42
@@ -63,6 +81,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #define TARGET_SYS_truncate 92
 #define TARGET_SYS_ftruncate 93
 #define TARGET_SYS_socketcall 102
+#define TARGET_SYS_stat 106
 #define TARGET_SYS_fstat 108
 #define TARGET_SYS_wait4 114
 #define TARGET_SYS_sigreturn 119
@@ -70,6 +89,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #define TARGET_SYS_uname 122
 #define TARGET_SYS_mprotect 125
 #define TARGET_SYS_llseek 140
+#define TARGET_SYS_writev 146
 #define TARGET_SYS__sysctl 149
 #define TARGET_SYS_sched_setparam 154
 #define TARGET_SYS_sched_getparam 155
@@ -94,6 +114,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #define TARGET_SYS_getegid32 202
 #define TARGET_SYS_getgid32 200
 #define TARGET_SYS_fcntl64 221
+#define TARGET_SYS_set_thread_area 243
+#define TARGET_SYS_exit_group 252
 
 #define TARGET_PROT_READ       0x1
 #define TARGET_PROT_WRITE      0x2
@@ -105,6 +127,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #define TARGET_MAP_TYPE                0x0f
 #define TARGET_MAP_FIXED       0x10
 #define TARGET_MAP_ANONYMOUS   0x20
+#define TARGET_MAP_DENYWRITE   0x800
 
 #define TARGET_CTL_KERN                1
 #define TARGET_CTL_VM          2
@@ -124,10 +147,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 
 #define TARGET_TCGETS 0x5401
 
-#define TARGET_UTSNAME "#38 Sun Apr 1 00:00:00 MET 2001"
+#define TARGET_UTSNAME "#7 Thu Jan 1 00:00:00 MET 2009"
 
-/* Seconds since the above date + 10 minutes.  */
-#define TARGET_EPOCH 986080200
+/* Seconds since 1970-01-01 to the above date + 10 minutes;
+   'date -d "Thu Jan 1 00:00:10 MET 2009" +%s'.  */
+#define TARGET_EPOCH 1230764410
 
 /* Milliseconds since start of run.  We use the number of syscalls to
    avoid introducing noise in the execution time.  */
@@ -223,6 +247,15 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #define TARGET___WALL 0x40000000
 #define TARGET___WCLONE 0x80000000
 
+/* From linux/limits.h. */
+#define TARGET_PIPE_BUF 4096
+
+/* From unistd.h.  */
+#define        TARGET_R_OK 4
+#define        TARGET_W_OK 2
+#define        TARGET_X_OK 1
+#define        TARGET_F_OK 0
+
 static const char stat_map[] =
 "st_dev,2:space,10:space,4:st_mode,4:st_nlink,4:st_uid,4"
 ":st_gid,4:st_rdev,2:space,10:st_size,8:st_blksize,4:st_blocks,4"
@@ -231,22 +264,21 @@ static const char stat_map[] =
 
 static const CB_TARGET_DEFS_MAP syscall_map[] =
 {
-  { CB_SYS_open, TARGET_SYS_open },
-  { CB_SYS_close, TARGET_SYS_close },
-  { CB_SYS_read, TARGET_SYS_read },
-  { CB_SYS_write, TARGET_SYS_write },
-  { CB_SYS_lseek, TARGET_SYS_lseek },
-  { CB_SYS_unlink, TARGET_SYS_unlink },
-  { CB_SYS_getpid, TARGET_SYS_getpid },
-  { CB_SYS_fstat, TARGET_SYS_fstat64 },
-  { CB_SYS_lstat, TARGET_SYS_lstat64 },
-  { CB_SYS_stat, TARGET_SYS_stat64 },
-  { CB_SYS_pipe, TARGET_SYS_pipe },
-  { CB_SYS_time, TARGET_SYS_time },
-  { CB_SYS_rename, TARGET_SYS_rename },
-  { CB_SYS_truncate, TARGET_SYS_truncate },
-  { CB_SYS_ftruncate, TARGET_SYS_ftruncate },
-  { 0, -1 }
+  { "open", CB_SYS_open, TARGET_SYS_open },
+  { "close", CB_SYS_close, TARGET_SYS_close },
+  { "read", CB_SYS_read, TARGET_SYS_read },
+  { "write", CB_SYS_write, TARGET_SYS_write },
+  { "lseek", CB_SYS_lseek, TARGET_SYS_lseek },
+  { "unlink", CB_SYS_unlink, TARGET_SYS_unlink },
+  { "getpid", CB_SYS_getpid, TARGET_SYS_getpid },
+  { "fstat", CB_SYS_fstat, TARGET_SYS_fstat64 },
+  { "lstat", CB_SYS_lstat, TARGET_SYS_lstat64 },
+  { "stat", CB_SYS_stat, TARGET_SYS_stat64 },
+  { "pipe", CB_SYS_pipe, TARGET_SYS_pipe },
+  { "rename", CB_SYS_rename, TARGET_SYS_rename },
+  { "truncate", CB_SYS_truncate, TARGET_SYS_truncate },
+  { "ftruncate", CB_SYS_ftruncate, TARGET_SYS_ftruncate },
+  { 0, -1, -1 }
 };
 
 /* An older, 32-bit-only stat mapping.  */
@@ -259,8 +291,9 @@ static const char stat32_map[] =
    newlib Linux mapping.  */
 static const CB_TARGET_DEFS_MAP syscall_stat32_map[] =
 {
-  { CB_SYS_fstat, TARGET_SYS_fstat },
-  { 0, -1 }
+  { "fstat", CB_SYS_fstat, TARGET_SYS_fstat },
+  { "stat", CB_SYS_stat, TARGET_SYS_stat },
+  { 0, -1, -1 }
 };
 
 /* Giving the true value for the running sim process will lead to
@@ -279,378 +312,378 @@ static const CB_TARGET_DEFS_MAP syscall_stat32_map[] =
 static const CB_TARGET_DEFS_MAP errno_map[] =
 {
 #ifdef EPERM
-  { EPERM, 1 },
+  { "EPERM", EPERM, 1 },
 #endif
 #ifdef ENOENT
-  { ENOENT, 2 },
+  { "ENOENT", ENOENT, 2 },
 #endif
 #ifdef ESRCH
-  { ESRCH, 3 },
+  { "ESRCH", ESRCH, 3 },
 #endif
 #ifdef EINTR
-  { EINTR, 4 },
+  { "EINTR", EINTR, 4 },
 #endif
 #ifdef EIO
-  { EIO, 5 },
+  { "EIO", EIO, 5 },
 #endif
 #ifdef ENXIO
-  { ENXIO, 6 },
+  { "ENXIO", ENXIO, 6 },
 #endif
 #ifdef E2BIG
-  { E2BIG, 7 },
+  { "E2BIG", E2BIG, 7 },
 #endif
 #ifdef ENOEXEC
-  { ENOEXEC, 8 },
+  { "ENOEXEC", ENOEXEC, 8 },
 #endif
 #ifdef EBADF
-  { EBADF, 9 },
+  { "EBADF", EBADF, 9 },
 #endif
 #ifdef ECHILD
-  { ECHILD, 10 },
+  { "ECHILD", ECHILD, 10 },
 #endif
 #ifdef EAGAIN
-  { EAGAIN, 11 },
+  { "EAGAIN", EAGAIN, 11 },
 #endif
 #ifdef ENOMEM
-  { ENOMEM, 12 },
+  { "ENOMEM", ENOMEM, 12 },
 #endif
 #ifdef EACCES
-  { EACCES, 13 },
+  { "EACCES", EACCES, 13 },
 #endif
 #ifdef EFAULT
-  { EFAULT, 14 },
+  { "EFAULT", EFAULT, 14 },
 #endif
 #ifdef ENOTBLK
-  { ENOTBLK, 15 },
+  { "ENOTBLK", ENOTBLK, 15 },
 #endif
 #ifdef EBUSY
-  { EBUSY, 16 },
+  { "EBUSY", EBUSY, 16 },
 #endif
 #ifdef EEXIST
-  { EEXIST, 17 },
+  { "EEXIST", EEXIST, 17 },
 #endif
 #ifdef EXDEV
-  { EXDEV, 18 },
+  { "EXDEV", EXDEV, 18 },
 #endif
 #ifdef ENODEV
-  { ENODEV, 19 },
+  { "ENODEV", ENODEV, 19 },
 #endif
 #ifdef ENOTDIR
-  { ENOTDIR, 20 },
+  { "ENOTDIR", ENOTDIR, 20 },
 #endif
 #ifdef EISDIR
-  { EISDIR, 21 },
+  { "EISDIR", EISDIR, 21 },
 #endif
 #ifdef EINVAL
-  { EINVAL, 22 },
+  { "EINVAL", EINVAL, 22 },
 #endif
 #ifdef ENFILE
-  { ENFILE, 23 },
+  { "ENFILE", ENFILE, 23 },
 #endif
 #ifdef EMFILE
-  { EMFILE, 24 },
+  { "EMFILE", EMFILE, 24 },
 #endif
 #ifdef ENOTTY
-  { ENOTTY, 25 },
+  { "ENOTTY", ENOTTY, 25 },
 #endif
 #ifdef ETXTBSY
-  { ETXTBSY, 26 },
+  { "ETXTBSY", ETXTBSY, 26 },
 #endif
 #ifdef EFBIG
-  { EFBIG, 27 },
+  { "EFBIG", EFBIG, 27 },
 #endif
 #ifdef ENOSPC
-  { ENOSPC, 28 },
+  { "ENOSPC", ENOSPC, 28 },
 #endif
 #ifdef ESPIPE
-  { ESPIPE, 29 },
+  { "ESPIPE", ESPIPE, 29 },
 #endif
 #ifdef EROFS
-  { EROFS, 30 },
+  { "EROFS", EROFS, 30 },
 #endif
 #ifdef EMLINK
-  { EMLINK, 31 },
+  { "EMLINK", EMLINK, 31 },
 #endif
 #ifdef EPIPE
-  { EPIPE, 32 },
+  { "EPIPE", EPIPE, 32 },
 #endif
 #ifdef EDOM
-  { EDOM, 33 },
+  { "EDOM", EDOM, 33 },
 #endif
 #ifdef ERANGE
-  { ERANGE, 34 },
+  { "ERANGE", ERANGE, 34 },
 #endif
 #ifdef EDEADLK
-  { EDEADLK, 35 },
+  { "EDEADLK", EDEADLK, 35 },
 #endif
 #ifdef ENAMETOOLONG
-  { ENAMETOOLONG, 36 },
+  { "ENAMETOOLONG", ENAMETOOLONG, 36 },
 #endif
 #ifdef ENOLCK
-  { ENOLCK, 37 },
+  { "ENOLCK", ENOLCK, 37 },
 #endif
 #ifdef ENOSYS
-  { ENOSYS, 38 },
+  { "ENOSYS", ENOSYS, 38 },
 #endif
 #ifdef ENOTEMPTY
-  { ENOTEMPTY, 39 },
+  { "ENOTEMPTY", ENOTEMPTY, 39 },
 #endif
 #ifdef ELOOP
-  { ELOOP, 40 },
+  { "ELOOP", ELOOP, 40 },
 #endif
 #ifdef EWOULDBLOCK
-  { EWOULDBLOCK, 11 },
+  { "EWOULDBLOCK", EWOULDBLOCK, 11 },
 #endif
 #ifdef ENOMSG
-  { ENOMSG, 42 },
+  { "ENOMSG", ENOMSG, 42 },
 #endif
 #ifdef EIDRM
-  { EIDRM, 43 },
+  { "EIDRM", EIDRM, 43 },
 #endif
 #ifdef ECHRNG
-  { ECHRNG, 44 },
+  { "ECHRNG", ECHRNG, 44 },
 #endif
 #ifdef EL2NSYNC
-  { EL2NSYNC, 45 },
+  { "EL2NSYNC", EL2NSYNC, 45 },
 #endif
 #ifdef EL3HLT
-  { EL3HLT, 46 },
+  { "EL3HLT", EL3HLT, 46 },
 #endif
 #ifdef EL3RST
-  { EL3RST, 47 },
+  { "EL3RST", EL3RST, 47 },
 #endif
 #ifdef ELNRNG
-  { ELNRNG, 48 },
+  { "ELNRNG", ELNRNG, 48 },
 #endif
 #ifdef EUNATCH
-  { EUNATCH, 49 },
+  { "EUNATCH", EUNATCH, 49 },
 #endif
 #ifdef ENOCSI
-  { ENOCSI, 50 },
+  { "ENOCSI", ENOCSI, 50 },
 #endif
 #ifdef EL2HLT
-  { EL2HLT, 51 },
+  { "EL2HLT", EL2HLT, 51 },
 #endif
 #ifdef EBADE
-  { EBADE, 52 },
+  { "EBADE", EBADE, 52 },
 #endif
 #ifdef EBADR
-  { EBADR, 53 },
+  { "EBADR", EBADR, 53 },
 #endif
 #ifdef EXFULL
-  { EXFULL, 54 },
+  { "EXFULL", EXFULL, 54 },
 #endif
 #ifdef ENOANO
-  { ENOANO, 55 },
+  { "ENOANO", ENOANO, 55 },
 #endif
 #ifdef EBADRQC
-  { EBADRQC, 56 },
+  { "EBADRQC", EBADRQC, 56 },
 #endif
 #ifdef EBADSLT
-  { EBADSLT, 57 },
+  { "EBADSLT", EBADSLT, 57 },
 #endif
 #ifdef EDEADLOCK
-  { EDEADLOCK, 35 },
+  { "EDEADLOCK", EDEADLOCK, 35 },
 #endif
 #ifdef EBFONT
-  { EBFONT, 59 },
+  { "EBFONT", EBFONT, 59 },
 #endif
 #ifdef ENOSTR
-  { ENOSTR, 60 },
+  { "ENOSTR", ENOSTR, 60 },
 #endif
 #ifdef ENODATA
-  { ENODATA, 61 },
+  { "ENODATA", ENODATA, 61 },
 #endif
 #ifdef ETIME
-  { ETIME, 62 },
+  { "ETIME", ETIME, 62 },
 #endif
 #ifdef ENOSR
-  { ENOSR, 63 },
+  { "ENOSR", ENOSR, 63 },
 #endif
 #ifdef ENONET
-  { ENONET, 64 },
+  { "ENONET", ENONET, 64 },
 #endif
 #ifdef ENOPKG
-  { ENOPKG, 65 },
+  { "ENOPKG", ENOPKG, 65 },
 #endif
 #ifdef EREMOTE
-  { EREMOTE, 66 },
+  { "EREMOTE", EREMOTE, 66 },
 #endif
 #ifdef ENOLINK
-  { ENOLINK, 67 },
+  { "ENOLINK", ENOLINK, 67 },
 #endif
 #ifdef EADV
-  { EADV, 68 },
+  { "EADV", EADV, 68 },
 #endif
 #ifdef ESRMNT
-  { ESRMNT, 69 },
+  { "ESRMNT", ESRMNT, 69 },
 #endif
 #ifdef ECOMM
-  { ECOMM, 70 },
+  { "ECOMM", ECOMM, 70 },
 #endif
 #ifdef EPROTO
-  { EPROTO, 71 },
+  { "EPROTO", EPROTO, 71 },
 #endif
 #ifdef EMULTIHOP
-  { EMULTIHOP, 72 },
+  { "EMULTIHOP", EMULTIHOP, 72 },
 #endif
 #ifdef EDOTDOT
-  { EDOTDOT, 73 },
+  { "EDOTDOT", EDOTDOT, 73 },
 #endif
 #ifdef EBADMSG
-  { EBADMSG, 74 },
+  { "EBADMSG", EBADMSG, 74 },
 #endif
 #ifdef EOVERFLOW
-  { EOVERFLOW, 75 },
+  { "EOVERFLOW", EOVERFLOW, 75 },
 #endif
 #ifdef ENOTUNIQ
-  { ENOTUNIQ, 76 },
+  { "ENOTUNIQ", ENOTUNIQ, 76 },
 #endif
 #ifdef EBADFD
-  { EBADFD, 77 },
+  { "EBADFD", EBADFD, 77 },
 #endif
 #ifdef EREMCHG
-  { EREMCHG, 78 },
+  { "EREMCHG", EREMCHG, 78 },
 #endif
 #ifdef ELIBACC
-  { ELIBACC, 79 },
+  { "ELIBACC", ELIBACC, 79 },
 #endif
 #ifdef ELIBBAD
-  { ELIBBAD, 80 },
+  { "ELIBBAD", ELIBBAD, 80 },
 #endif
 #ifdef ELIBSCN
-  { ELIBSCN, 81 },
+  { "ELIBSCN", ELIBSCN, 81 },
 #endif
 #ifdef ELIBMAX
-  { ELIBMAX, 82 },
+  { "ELIBMAX", ELIBMAX, 82 },
 #endif
 #ifdef ELIBEXEC
-  { ELIBEXEC, 83 },
+  { "ELIBEXEC", ELIBEXEC, 83 },
 #endif
 #ifdef EILSEQ
-  { EILSEQ, 84 },
+  { "EILSEQ", EILSEQ, 84 },
 #endif
 #ifdef ERESTART
-  { ERESTART, 85 },
+  { "ERESTART", ERESTART, 85 },
 #endif
 #ifdef ESTRPIPE
-  { ESTRPIPE, 86 },
+  { "ESTRPIPE", ESTRPIPE, 86 },
 #endif
 #ifdef EUSERS
-  { EUSERS, 87 },
+  { "EUSERS", EUSERS, 87 },
 #endif
 #ifdef ENOTSOCK
-  { ENOTSOCK, 88 },
+  { "ENOTSOCK", ENOTSOCK, 88 },
 #endif
 #ifdef EDESTADDRREQ
-  { EDESTADDRREQ, 89 },
+  { "EDESTADDRREQ", EDESTADDRREQ, 89 },
 #endif
 #ifdef EMSGSIZE
-  { EMSGSIZE, 90 },
+  { "EMSGSIZE", EMSGSIZE, 90 },
 #endif
 #ifdef EPROTOTYPE
-  { EPROTOTYPE, 91 },
+  { "EPROTOTYPE", EPROTOTYPE, 91 },
 #endif
 #ifdef ENOPROTOOPT
-  { ENOPROTOOPT, 92 },
+  { "ENOPROTOOPT", ENOPROTOOPT, 92 },
 #endif
 #ifdef EPROTONOSUPPORT
-  { EPROTONOSUPPORT, 93 },
+  { "EPROTONOSUPPORT", EPROTONOSUPPORT, 93 },
 #endif
 #ifdef ESOCKTNOSUPPORT
-  { ESOCKTNOSUPPORT, 94 },
+  { "ESOCKTNOSUPPORT", ESOCKTNOSUPPORT, 94 },
 #endif
 #ifdef EOPNOTSUPP
-  { EOPNOTSUPP, 95 },
+  { "EOPNOTSUPP", EOPNOTSUPP, 95 },
 #endif
 #ifdef EPFNOSUPPORT
-  { EPFNOSUPPORT, 96 },
+  { "EPFNOSUPPORT", EPFNOSUPPORT, 96 },
 #endif
 #ifdef EAFNOSUPPORT
-  { EAFNOSUPPORT, 97 },
+  { "EAFNOSUPPORT", EAFNOSUPPORT, 97 },
 #endif
 #ifdef EADDRINUSE
-  { EADDRINUSE, 98 },
+  { "EADDRINUSE", EADDRINUSE, 98 },
 #endif
 #ifdef EADDRNOTAVAIL
-  { EADDRNOTAVAIL, 99 },
+  { "EADDRNOTAVAIL", EADDRNOTAVAIL, 99 },
 #endif
 #ifdef ENETDOWN
-  { ENETDOWN, 100 },
+  { "ENETDOWN", ENETDOWN, 100 },
 #endif
 #ifdef ENETUNREACH
-  { ENETUNREACH, 101 },
+  { "ENETUNREACH", ENETUNREACH, 101 },
 #endif
 #ifdef ENETRESET
-  { ENETRESET, 102 },
+  { "ENETRESET", ENETRESET, 102 },
 #endif
 #ifdef ECONNABORTED
-  { ECONNABORTED, 103 },
+  { "ECONNABORTED", ECONNABORTED, 103 },
 #endif
 #ifdef ECONNRESET
-  { ECONNRESET, 104 },
+  { "ECONNRESET", ECONNRESET, 104 },
 #endif
 #ifdef ENOBUFS
-  { ENOBUFS, 105 },
+  { "ENOBUFS", ENOBUFS, 105 },
 #endif
 #ifdef EISCONN
-  { EISCONN, 106 },
+  { "EISCONN", EISCONN, 106 },
 #endif
 #ifdef ENOTCONN
-  { ENOTCONN, 107 },
+  { "ENOTCONN", ENOTCONN, 107 },
 #endif
 #ifdef ESHUTDOWN
-  { ESHUTDOWN, 108 },
+  { "ESHUTDOWN", ESHUTDOWN, 108 },
 #endif
 #ifdef ETOOMANYREFS
-  { ETOOMANYREFS, 109 },
+  { "ETOOMANYREFS", ETOOMANYREFS, 109 },
 #endif
 #ifdef ETIMEDOUT
-  { ETIMEDOUT, 110 },
+  { "ETIMEDOUT", ETIMEDOUT, 110 },
 #endif
 #ifdef ECONNREFUSED
-  { ECONNREFUSED, 111 },
+  { "ECONNREFUSED", ECONNREFUSED, 111 },
 #endif
 #ifdef EHOSTDOWN
-  { EHOSTDOWN, 112 },
+  { "EHOSTDOWN", EHOSTDOWN, 112 },
 #endif
 #ifdef EHOSTUNREACH
-  { EHOSTUNREACH, 113 },
+  { "EHOSTUNREACH", EHOSTUNREACH, 113 },
 #endif
 #ifdef EALREADY
-  { EALREADY, 114 },
+  { "EALREADY", EALREADY, 114 },
 #endif
 #ifdef EINPROGRESS
-  { EINPROGRESS, 115 },
+  { "EINPROGRESS", EINPROGRESS, 115 },
 #endif
 #ifdef ESTALE
-  { ESTALE, 116 },
+  { "ESTALE", ESTALE, 116 },
 #endif
 #ifdef EUCLEAN
-  { EUCLEAN, 117 },
+  { "EUCLEAN", EUCLEAN, 117 },
 #endif
 #ifdef ENOTNAM
-  { ENOTNAM, 118 },
+  { "ENOTNAM", ENOTNAM, 118 },
 #endif
 #ifdef ENAVAIL
-  { ENAVAIL, 119 },
+  { "ENAVAIL", ENAVAIL, 119 },
 #endif
 #ifdef EISNAM
-  { EISNAM, 120 },
+  { "EISNAM", EISNAM, 120 },
 #endif
 #ifdef EREMOTEIO
-  { EREMOTEIO, 121 },
+  { "EREMOTEIO", EREMOTEIO, 121 },
 #endif
 #ifdef EDQUOT
-  { EDQUOT, 122 },
+  { "EDQUOT", EDQUOT, 122 },
 #endif
 #ifdef ENOMEDIUM
-  { ENOMEDIUM, 123 },
+  { "ENOMEDIUM", ENOMEDIUM, 123 },
 #endif
 #ifdef EMEDIUMTYPE
-  { EMEDIUMTYPE, 124 },
+  { "EMEDIUMTYPE", EMEDIUMTYPE, 124 },
 #endif
-  { 0, -1 }
+  { 0, 0, 0 }
 };
 
 /* Extracted by applying
@@ -661,68 +694,76 @@ static const CB_TARGET_DEFS_MAP errno_map[] =
    installation and removing synonyms and unnecessary items.  Don't
    forget the end-marker.  */
 
+/* These we treat specially, as they're used in the fcntl F_GETFL
+   syscall.  For consistency, open_map is also manually edited to use
+   these macros.  */
+#define TARGET_O_ACCMODE 0x3
+#define TARGET_O_RDONLY 0x0
+#define TARGET_O_WRONLY 0x1
+
 static const CB_TARGET_DEFS_MAP open_map[] = {
 #ifdef O_ACCMODE
-  { O_ACCMODE, 0x3 },
+  { "O_ACCMODE", O_ACCMODE, TARGET_O_ACCMODE },
 #endif
 #ifdef O_RDONLY
-  { O_RDONLY, 0x0 },
+  { "O_RDONLY", O_RDONLY, TARGET_O_RDONLY },
 #endif
 #ifdef O_WRONLY
-  { O_WRONLY, 0x1 },
+  { "O_WRONLY", O_WRONLY, TARGET_O_WRONLY },
 #endif
 #ifdef O_RDWR
-  { O_RDWR, 0x2 },
+  { "O_RDWR", O_RDWR, 0x2 },
 #endif
 #ifdef O_CREAT
-  { O_CREAT, 0x40 },
+  { "O_CREAT", O_CREAT, 0x40 },
 #endif
 #ifdef O_EXCL
-  { O_EXCL, 0x80 },
+  { "O_EXCL", O_EXCL, 0x80 },
 #endif
 #ifdef O_NOCTTY
-  { O_NOCTTY, 0x100 },
+  { "O_NOCTTY", O_NOCTTY, 0x100 },
 #endif
 #ifdef O_TRUNC
-  { O_TRUNC, 0x200 },
+  { "O_TRUNC", O_TRUNC, 0x200 },
 #endif
 #ifdef O_APPEND
-  { O_APPEND, 0x400 },
+  { "O_APPEND", O_APPEND, 0x400 },
 #endif
 #ifdef O_NONBLOCK
-  { O_NONBLOCK, 0x800 },
+  { "O_NONBLOCK", O_NONBLOCK, 0x800 },
 #endif
 #ifdef O_NDELAY
-  { O_NDELAY, 0x0 },
+  { "O_NDELAY", O_NDELAY, 0x0 },
 #endif
 #ifdef O_SYNC
-  { O_SYNC, 0x1000 },
+  { "O_SYNC", O_SYNC, 0x1000 },
 #endif
 #ifdef FASYNC
-  { FASYNC, 0x2000 },
+  { "FASYNC", FASYNC, 0x2000 },
 #endif
 #ifdef O_DIRECT
-  { O_DIRECT, 0x4000 },
+  { "O_DIRECT", O_DIRECT, 0x4000 },
 #endif
 #ifdef O_LARGEFILE
-  { O_LARGEFILE, 0x8000 },
+  { "O_LARGEFILE", O_LARGEFILE, 0x8000 },
 #endif
 #ifdef O_DIRECTORY
-  { O_DIRECTORY, 0x10000 },
+  { "O_DIRECTORY", O_DIRECTORY, 0x10000 },
 #endif
 #ifdef O_NOFOLLOW
-  { O_NOFOLLOW, 0x20000 },
+  { "O_NOFOLLOW", O_NOFOLLOW, 0x20000 },
 #endif
-  { -1, -1 }
+  { 0, -1, -1 }
 };
 
+/* Let's be less drastic and more traceable.  FIXME: mark as noreturn.  */
+#define abort()                                                        \
+  sim_io_error (sd, "simulator unhandled condition at %s:%d",  \
+               __FUNCTION__, __LINE__)
+
 /* Needed for the cris_pipe_nonempty and cris_pipe_empty syscalls.  */
 static SIM_CPU *current_cpu_for_cb_callback;
 
-static int syscall_read_mem (host_callback *, struct cb_syscall *,
-                            unsigned long, char *, int);
-static int syscall_write_mem (host_callback *, struct cb_syscall *,
-                             unsigned long, const char *, int);
 static USI create_map (SIM_DESC, struct cris_sim_mmapped_page **,
                       USI addr, USI len);
 static USI unmap_pages (SIM_DESC, struct cris_sim_mmapped_page **,
@@ -732,30 +773,6 @@ static USI is_mapped (SIM_DESC, struct cris_sim_mmapped_page **,
 static void dump_statistics (SIM_CPU *current_cpu);
 static void make_first_thread (SIM_CPU *current_cpu);
 
-/* Read/write functions for system call interface.  */
-
-static int
-syscall_read_mem (host_callback *cb ATTRIBUTE_UNUSED,
-                 struct cb_syscall *sc,
-                 unsigned long taddr, char *buf, int bytes)
-{
-  SIM_DESC sd = (SIM_DESC) sc->p1;
-  SIM_CPU *cpu = (SIM_CPU *) sc->p2;
-
-  return sim_core_read_buffer (sd, cpu, read_map, buf, taddr, bytes);
-}
-
-static int
-syscall_write_mem (host_callback *cb ATTRIBUTE_UNUSED,
-                  struct cb_syscall *sc,
-                  unsigned long taddr, const char *buf, int bytes)
-{
-  SIM_DESC sd = (SIM_DESC) sc->p1;
-  SIM_CPU *cpu = (SIM_CPU *) sc->p2;
-
-  return sim_core_write_buffer (sd, cpu, write_map, buf, taddr, bytes);
-}
-
 /* When we risk running self-modified code (as in trampolines), this is
    called from special-case insns.  The silicon CRIS CPU:s have enough
    cache snooping implemented making this a simulator-only issue.  Tests:
@@ -842,25 +859,25 @@ dump_statistics (SIM_CPU *current_cpu)
 
   /* For v32, unaligned_mem_dword_count should always be 0.  For
      v10, memsrc_stall_count should always be 0.  */
-  sim_io_eprintf (sd, "Memory source stall cycles: %lld\n",
-                 profp->memsrc_stall_count
-                 + profp->unaligned_mem_dword_count);
-  sim_io_eprintf (sd, "Memory read-after-write stall cycles: %lld\n",
-                 profp->memraw_stall_count);
-  sim_io_eprintf (sd, "Movem source stall cycles: %lld\n",
-                 profp->movemsrc_stall_count);
-  sim_io_eprintf (sd, "Movem destination stall cycles: %lld\n",
-                 profp->movemdst_stall_count);
-  sim_io_eprintf (sd, "Movem address stall cycles: %lld\n",
-                 profp->movemaddr_stall_count);
-  sim_io_eprintf (sd, "Multiplication source stall cycles: %lld\n",
-                 profp->mulsrc_stall_count);
-  sim_io_eprintf (sd, "Jump source stall cycles: %lld\n",
-                 profp->jumpsrc_stall_count);
-  sim_io_eprintf (sd, "Branch misprediction stall cycles: %lld\n",
-                 profp->branch_stall_count);
-  sim_io_eprintf (sd, "Jump target stall cycles: %lld\n",
-                 profp->jumptarget_stall_count);
+  sim_io_eprintf (sd, "Memory source stall cycles: %llu\n",
+                 (unsigned long long) (profp->memsrc_stall_count
+                                       + profp->unaligned_mem_dword_count));
+  sim_io_eprintf (sd, "Memory read-after-write stall cycles: %llu\n",
+                 (unsigned long long) profp->memraw_stall_count);
+  sim_io_eprintf (sd, "Movem source stall cycles: %llu\n",
+                 (unsigned long long) profp->movemsrc_stall_count);
+  sim_io_eprintf (sd, "Movem destination stall cycles: %llu\n",
+                 (unsigned long long) profp->movemdst_stall_count);
+  sim_io_eprintf (sd, "Movem address stall cycles: %llu\n",
+                 (unsigned long long) profp->movemaddr_stall_count);
+  sim_io_eprintf (sd, "Multiplication source stall cycles: %llu\n",
+                 (unsigned long long) profp->mulsrc_stall_count);
+  sim_io_eprintf (sd, "Jump source stall cycles: %llu\n",
+                 (unsigned long long) profp->jumpsrc_stall_count);
+  sim_io_eprintf (sd, "Branch misprediction stall cycles: %llu\n",
+                 (unsigned long long) profp->branch_stall_count);
+  sim_io_eprintf (sd, "Jump target stall cycles: %llu\n",
+                 (unsigned long long) profp->jumptarget_stall_count);
 }
 
 /* Check whether any part of [addr .. addr + len - 1] is already mapped.
@@ -885,7 +902,59 @@ is_mapped (SIM_DESC sd ATTRIBUTE_UNUSED,
   return 0;
 }
 
-/* Create mmapped memory.  */
+/* Check whether any part of [addr .. addr + len - 1] is *un*mapped.
+   Return 1 if the whole area is mapped, 0 otherwise.  */
+
+static USI
+is_mapped_only (SIM_DESC sd ATTRIBUTE_UNUSED,
+               struct cris_sim_mmapped_page **rootp,
+               USI addr, USI len)
+{
+  struct cris_sim_mmapped_page *mapp;
+
+  if (len == 0 || (len & 8191))
+    abort ();
+
+  /* Iterate over the reverse-address sorted pages until we find a page
+     lower than the checked area.  */
+  for (mapp = *rootp; mapp != NULL && mapp->addr >= addr; mapp = mapp->prev)
+    if (addr == mapp->addr && len == 8192)
+      return 1;
+    else if (addr + len > mapp->addr)
+      len -= 8192;
+
+  return 0;
+}
+
+/* Debug helper; to be run from gdb.  */
+
+void
+cris_dump_map (SIM_CPU *current_cpu)
+{
+  struct cris_sim_mmapped_page *mapp;
+  USI start, end;
+
+  for (mapp = current_cpu->highest_mmapped_page,
+        start = mapp == NULL ? 0 : mapp->addr + 8192,
+        end = mapp == NULL ? 0 : mapp->addr + 8191;
+       mapp != NULL;
+       mapp = mapp->prev)
+    {
+      if (mapp->addr != start - 8192)
+       {
+         sim_io_eprintf (CPU_STATE (current_cpu), "0x%x..0x%x\n", start, end);
+         end = mapp->addr + 8191;
+       }
+
+      start = mapp->addr;
+    }
+
+  if (current_cpu->highest_mmapped_page != NULL)
+    sim_io_eprintf (CPU_STATE (current_cpu), "0x%x..0x%x\n", start, end);
+}
+
+/* Create mmapped memory.  ADDR is -1 if any address will do.  Caller
+   must make sure that the address isn't already mapped.  */
 
 static USI
 create_map (SIM_DESC sd, struct cris_sim_mmapped_page **rootp, USI addr,
@@ -895,9 +964,9 @@ create_map (SIM_DESC sd, struct cris_sim_mmapped_page **rootp, USI addr,
   struct cris_sim_mmapped_page **higher_prevp = rootp;
   USI new_addr = 0x40000000;
 
-  if (addr != 0)
+  if (addr != (USI) -1)
     new_addr = addr;
-  else if (*rootp)
+  else if (*rootp && rootp[0]->addr >= new_addr)
     new_addr = rootp[0]->addr + 8192;
 
   if (len != 8192)
@@ -921,6 +990,10 @@ create_map (SIM_DESC sd, struct cris_sim_mmapped_page **rootp, USI addr,
        mapp = mapp->prev)
     higher_prevp = &mapp->prev;
 
+  /* Assert for consistency that we don't create duplicate maps.  */
+  if (is_mapped (sd, rootp, new_addr, len))
+    abort ();
+
   /* Allocate the new page, on the next higher page from the last one
      allocated, and link in the new descriptor before previous ones.  */
   mapp = malloc (sizeof (*mapp));
@@ -951,6 +1024,7 @@ unmap_pages (SIM_DESC sd, struct cris_sim_mmapped_page **rootp, USI addr,
   if (len != 8192)
     {
       USI page_addr;
+      int ret = 0;
 
       if (len & 8191)
        /* Which is better: return an error for this, or just round it up?  */
@@ -959,12 +1033,15 @@ unmap_pages (SIM_DESC sd, struct cris_sim_mmapped_page **rootp, USI addr,
       /* Loop backwards to make each call is O(1) over the number of pages
         allocated, if we're unmapping from the high end of the pages.  */
       for (page_addr = addr + len - 8192;
-          page_addr >= addr;
+          page_addr > addr;
           page_addr -= 8192)
-       if (unmap_pages (sd, rootp, page_addr, 8192) != 0)
-         abort ();
+       if (unmap_pages (sd, rootp, page_addr, 8192))
+         ret = EINVAL;
+
+      if (unmap_pages (sd, rootp, addr, 8192))
+       ret = EINVAL;
 
-      return 0;
+      return ret;
     }
 
   for (mapp = *rootp; mapp != NULL && mapp->addr > addr; mapp = mapp->prev)
@@ -997,6 +1074,7 @@ cris_bmod_handler (SIM_CPU *current_cpu ATTRIBUTE_UNUSED,
                   UINT srcreg ATTRIBUTE_UNUSED,
                   USI dstreg ATTRIBUTE_UNUSED)
 {
+  SIM_DESC sd = CPU_STATE (current_cpu);
   abort ();
 }
 
@@ -1006,6 +1084,7 @@ h_supr_set_handler (SIM_CPU *current_cpu ATTRIBUTE_UNUSED,
                    USI page ATTRIBUTE_UNUSED,
                    USI newval ATTRIBUTE_UNUSED)
 {
+  SIM_DESC sd = CPU_STATE (current_cpu);
   abort ();
 }
 
@@ -1014,6 +1093,7 @@ h_supr_get_handler (SIM_CPU *current_cpu ATTRIBUTE_UNUSED,
                    UINT index ATTRIBUTE_UNUSED,
                    USI page ATTRIBUTE_UNUSED)
 {
+  SIM_DESC sd = CPU_STATE (current_cpu);
   abort ();
 }
 
@@ -1170,6 +1250,7 @@ schedule (SIM_CPU *current_cpu, int next)
 static void
 reschedule (SIM_CPU *current_cpu)
 {
+  SIM_DESC sd = CPU_STATE (current_cpu);
   int i;
 
   /* Iterate over all thread slots, because after a few thread creations
@@ -1307,6 +1388,7 @@ deliver_signal (SIM_CPU *current_cpu, int sig, unsigned int pid)
 static void
 make_first_thread (SIM_CPU *current_cpu)
 {
+  SIM_DESC sd = CPU_STATE (current_cpu);
   current_cpu->thread_data
     = xcalloc (1,
               SIM_TARGET_MAX_THREADS
@@ -1322,6 +1404,31 @@ make_first_thread (SIM_CPU *current_cpu)
     abort ();
 }
 
+/* Handle unknown system calls.  Returns (if it does) the syscall
+   return value.  */
+
+static USI
+cris_unknown_syscall (SIM_CPU *current_cpu, USI pc, char *s, ...)
+{
+  SIM_DESC sd = CPU_STATE (current_cpu);
+  host_callback *cb = STATE_CALLBACK (sd);
+
+  if (cris_unknown_syscall_action == CRIS_USYSC_MSG_STOP
+      || cris_unknown_syscall_action == CRIS_USYSC_MSG_ENOSYS)
+    {
+      va_list ap;
+
+      va_start (ap, s);
+      sim_io_evprintf (sd, s, ap);
+      va_end (ap);
+
+      if (cris_unknown_syscall_action == CRIS_USYSC_MSG_STOP)
+       sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped, SIM_SIGILL);
+    }
+
+  return -cb_host_to_target_errno (cb, ENOSYS);
+}
+
 /* Main function: the handler of the "break 13" syscall insn.  */
 
 USI
@@ -1343,7 +1450,16 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
   s.arg2 = arg2;
   s.arg3 = arg3;
 
-  if (callnum == TARGET_SYS_exit && current_cpu->m1threads == 0)
+  /* The type of s.arg2 is long, so for hosts with 64-bit longs, we need
+     to sign-extend the lseek offset to be passed as a signed number,
+     else we'll truncate it to something > 2GB on hosts where sizeof
+     long > sizeof USI.  We avoid doing it for all syscalls, as arg2 is
+     e.g. an address for some syscalls.  */
+  if (callnum == TARGET_SYS_lseek)
+    s.arg2 = (SI) arg2;
+
+  if (callnum == TARGET_SYS_exit_group
+      || (callnum == TARGET_SYS_exit && current_cpu->m1threads == 0))
     {
       if (CPU_CRIS_MISC_PROFILE (current_cpu)->flags
          & FLAG_CRIS_MISC_PROFILE_ALL)
@@ -1353,8 +1469,8 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
 
   s.p1 = (PTR) sd;
   s.p2 = (PTR) current_cpu;
-  s.read_mem = syscall_read_mem;
-  s.write_mem = syscall_write_mem;
+  s.read_mem = sim_syscall_read_mem;
+  s.write_mem = sim_syscall_write_mem;
 
   current_cpu_for_cb_callback = current_cpu;
 
@@ -1397,8 +1513,9 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
 
        case TARGET_SYS_fcntl64:
        case TARGET_SYS_fcntl:
-         if (arg2 == 1)
+         switch (arg2)
            {
+           case 1:
              /* F_GETFD.
                 Glibc checks stdin, stdout and stderr fd:s for
                 close-on-exec security sanity.  We just need to provide a
@@ -1406,28 +1523,74 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
                 close-on-exec flag true, we could just do a real fcntl
                 here.  */
              retval = 0;
-           }
-         else if (arg2 == 2)
-           {
+             break;
+
+           case 2:
              /* F_SETFD.  Just ignore attempts to set the close-on-exec
                 flag.  */
              retval = 0;
+             break;
+
+           case 3:
+             /* F_GETFL.  Check for the special case for open+fdopen.  */
+             if (current_cpu->last_syscall == TARGET_SYS_open
+                 && arg1 == current_cpu->last_open_fd)
+               {
+                 retval = current_cpu->last_open_flags & TARGET_O_ACCMODE;
+                 break;
+               }
+             else if (arg1 == 0)
+               {
+                 /* Because we can't freopen fd:s 0, 1, 2 to mean
+                    something else than stdin, stdout and stderr
+                    (sim/common/syscall.c:cb_syscall special cases fd
+                    0, 1 and 2), we know what flags that we can
+                    sanely return for these fd:s.  */
+                 retval = TARGET_O_RDONLY;
+                 break;
+               }
+             else if (arg1 == 1 || arg1 == 2)
+               {
+                 retval = TARGET_O_WRONLY;
+                 break;
+               }
+             /* FALLTHROUGH */
+           default:
+             /* Nothing else is implemented.  */
+             retval
+               = cris_unknown_syscall (current_cpu, pc,
+                                       "Unimplemented %s syscall "
+                                       "(fd: 0x%lx: cmd: 0x%lx arg: "
+                                       "0x%lx)\n",
+                                       callnum == TARGET_SYS_fcntl
+                                       ? "fcntl" : "fcntl64",
+                                       (unsigned long) (USI) arg1,
+                                       (unsigned long) (USI) arg2,
+                                       (unsigned long) (USI) arg3);
+             break;
            }
          break;
 
        case TARGET_SYS_uname:
          {
            /* Fill in a few constants to appease glibc.  */
-           static const char sim_utsname[6][65] =
+           static char sim_utsname[6][65] =
            {
              "Linux",
              "sim-target",
-             "2.4.5",
+             "2.6.27",
              TARGET_UTSNAME,
-             "cris",
+             "cris",           /* Overwritten below.  */
              "localdomain"
            };
 
+           /* Having the hardware type in Linux equal to the bfd
+              printable name is deliberate: if you make config.guess
+              work on your Linux-type system the usual way, it
+              probably will; either the bfd printable_name or the
+              ambiguous arch_name.  */
+           strcpy (sim_utsname[4], STATE_ARCHITECTURE (sd)->printable_name);
+
            if ((s.write_mem) (cb, &s, arg1, (const char *) sim_utsname,
                               sizeof (sim_utsname))
                != sizeof (sim_utsname))
@@ -1511,6 +1674,11 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
            USI fd = arg5;
            USI pgoff = arg6;
 
+           /* At 2.6.27, Linux (many (all?) ports, in the mmap2 syscalls)
+              still masked away this bit, so let's just ignore
+              it.  */
+           flags &= ~TARGET_MAP_DENYWRITE;
+
            /* If the simulator wants to mmap more than the very large
               limit, something is wrong.  FIXME: Return an error or
               abort?  Have command-line selectable?  */
@@ -1525,23 +1693,32 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
                     != (TARGET_PROT_READ
                         | TARGET_PROT_WRITE
                         | TARGET_PROT_EXEC))
+                && (prot != (TARGET_PROT_READ | TARGET_PROT_EXEC))
                 && prot != TARGET_PROT_READ)
                || (flags != (TARGET_MAP_ANONYMOUS | TARGET_MAP_PRIVATE)
                    && flags != TARGET_MAP_PRIVATE
+                   && flags != (TARGET_MAP_ANONYMOUS
+                                | TARGET_MAP_PRIVATE | TARGET_MAP_FIXED)
+                   && flags != (TARGET_MAP_PRIVATE | TARGET_MAP_FIXED)
                    && flags != TARGET_MAP_SHARED)
-               || (fd != (USI) -1 && prot != TARGET_PROT_READ)
-               || pgoff != 0)
+               || (fd != (USI) -1
+                   && prot != TARGET_PROT_READ
+                   && prot != (TARGET_PROT_READ | TARGET_PROT_EXEC)
+                   && prot != (TARGET_PROT_READ | TARGET_PROT_WRITE))
+               || (fd == (USI) -1 && pgoff != 0)
+               || (fd != (USI) -1 && (flags & TARGET_MAP_ANONYMOUS)))
              {
-               sim_io_eprintf (sd, "Unimplemented mmap2 call "
-                               "(0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx)\n",
-                               (unsigned long) arg1,
-                               (unsigned long) arg2,
-                               (unsigned long) arg3,
-                               (unsigned long) arg4,
-                               (unsigned long) arg5,
-                               (unsigned long) arg6);
-               sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
-                                SIM_SIGILL);
+               retval
+                 = cris_unknown_syscall (current_cpu, pc,
+                                                "Unimplemented mmap2 call "
+                                                "(0x%lx, 0x%lx, 0x%lx, "
+                                                "0x%lx, 0x%lx, 0x%lx)\n",
+                                                (unsigned long) arg1,
+                                                (unsigned long) arg2,
+                                                (unsigned long) arg3,
+                                                (unsigned long) arg4,
+                                                (unsigned long) arg5,
+                                                (unsigned long) arg6);
                break;
              }
            else if (fd != (USI) -1)
@@ -1554,13 +1731,25 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
                /* A non-aligned argument is allowed for files.  */
                USI newlen = (len + 8191) & ~8191;
 
-               /* We only support read, which we should already have
-                  checked.  Check again anyway.  */
-               if (prot != TARGET_PROT_READ)
+               /* We only support read, read|exec, and read|write,
+                  which we should already have checked.  Check again
+                  anyway.  */
+               if (prot != TARGET_PROT_READ
+                   && prot != (TARGET_PROT_READ | TARGET_PROT_EXEC)
+                   && prot != (TARGET_PROT_READ | TARGET_PROT_WRITE))
                  abort ();
 
+               if (flags & TARGET_MAP_FIXED)
+                 unmap_pages (sd, &current_cpu->highest_mmapped_page,
+                              addr, newlen);
+               else if (is_mapped (sd, &current_cpu->highest_mmapped_page,
+                                   addr, newlen))
+                 addr = 0;
+
                newaddr
-                 = create_map (sd, &current_cpu->highest_mmapped_page, addr,
+                 = create_map (sd, &current_cpu->highest_mmapped_page,
+                               addr != 0 || (flags & TARGET_MAP_FIXED)
+                               ? addr : -1,
                                newlen);
 
                if (newaddr >= (USI) -8191)
@@ -1570,6 +1759,16 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
                    break;
                  }
 
+               /* We were asked for MAP_FIXED, but couldn't.  */
+               if ((flags & TARGET_MAP_FIXED) && newaddr != addr)
+                 {
+                   abort ();
+                   unmap_pages (sd, &current_cpu->highest_mmapped_page,
+                                newaddr, newlen);
+                   retval = -cb_host_to_target_errno (cb, EINVAL);
+                   break;
+                 }
+
                /* Find the current position in the file.  */
                s.func = TARGET_SYS_lseek;
                s.arg1 = fd;
@@ -1579,6 +1778,17 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
                  abort ();
                pos = s.result;
 
+               if (s.result < 0)
+                 abort ();
+
+               /* Move to the correct offset in the file.  */
+               s.func = TARGET_SYS_lseek;
+               s.arg1 = fd;
+               s.arg2 = pgoff*8192;
+               s.arg3 = SEEK_SET;
+               if (cb_syscall (cb, &s) != CB_RC_OK)
+                 abort ();
+
                if (s.result < 0)
                  abort ();
 
@@ -1591,7 +1801,9 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
                if (cb_syscall (cb, &s) != CB_RC_OK)
                  abort ();
 
-               if ((USI) s.result != len)
+               /* If the result is a page or more lesser than what
+                  was requested, something went wrong.  */
+               if (len >= 8192 && (USI) s.result <= len - 8192)
                  abort ();
 
                /* After reading, we need to go back to the previous
@@ -1609,46 +1821,66 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
              }
            else
              {
-               USI newaddr
-                 = create_map (sd, &current_cpu->highest_mmapped_page, addr,
-                               (len + 8191) & ~8191);
+               USI newlen = (len + 8191) & ~8191;
+               USI newaddr;
+
+               if (flags & TARGET_MAP_FIXED)
+                 unmap_pages (sd, &current_cpu->highest_mmapped_page,
+                              addr, newlen);
+               else if (is_mapped (sd, &current_cpu->highest_mmapped_page,
+                                   addr, newlen))
+                 addr = 0;
+
+               newaddr = create_map (sd, &current_cpu->highest_mmapped_page,
+                                     addr != 0 || (flags & TARGET_MAP_FIXED)
+                                     ? addr : -1,
+                                     newlen);
 
                if (newaddr >= (USI) -8191)
                  retval = -cb_host_to_target_errno (cb, -(SI) newaddr);
                else
                  retval = newaddr;
+
+               if ((flags & TARGET_MAP_FIXED) && newaddr != addr)
+                 {
+                   abort ();
+                   unmap_pages (sd, &current_cpu->highest_mmapped_page,
+                                newaddr, newlen);
+                   retval = -cb_host_to_target_errno (cb, EINVAL);
+                   break;
+                 }
              }
            break;
          }
 
        case TARGET_SYS_mprotect:
          {
-           /* We only cover the case of linuxthreads mprotecting out its
-              stack guard page.  */
+           /* We only cover the case of linuxthreads mprotecting out
+              its stack guard page and of dynamic loading mprotecting
+              away the data (for some reason the whole library, then
+              mprotects away the data part and mmap-FIX:es it again.  */
            USI addr = arg1;
            USI len = arg2;
            USI prot = arg3;
 
-           if ((addr & 8191) != 0
-               || len != 8192
-               || prot != TARGET_PROT_NONE
-               || !is_mapped (sd, &current_cpu->highest_mmapped_page, addr,
-                              len))
+           if (prot != TARGET_PROT_NONE
+               || !is_mapped_only (sd, &current_cpu->highest_mmapped_page,
+                                   addr, (len + 8191) & ~8191))
              {
-               sim_io_eprintf (sd, "Unimplemented mprotect call "
-                               "(0x%lx, 0x%lx, 0x%lx)\n",
-                               (unsigned long) arg1,
-                               (unsigned long) arg2,
-                               (unsigned long) arg3);
-               sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
-                                SIM_SIGILL);
+               retval
+                 = cris_unknown_syscall (current_cpu, pc,
+                                         "Unimplemented mprotect call "
+                                         "(0x%lx, 0x%lx, 0x%lx)\n",
+                                         (unsigned long) arg1,
+                                         (unsigned long) arg2,
+                                         (unsigned long) arg3);
                break;
              }
 
-           /* FIXME: We should account for pages like this that are
-              "mprotected out".  For now, we just tell the simulator
-              core to remove that page from its map.  */
-           sim_core_detach (sd, NULL, 0, 0, addr);
+           /* Just ignore this.  We could make this equal to munmap,
+              but then we'd have to make sure no anon mmaps gets this
+              address before a subsequent MAP_FIXED mmap intended to
+              override it.  */
            retval = 0;
            break;
          }
@@ -1700,14 +1932,14 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
                || rusagep != 0
                || current_cpu->thread_data == NULL)
              {
-               sim_io_eprintf (sd, "Unimplemented wait4 call "
-                               "(0x%lx, 0x%lx, 0x%lx, 0x%lx)\n",
-                               (unsigned long) arg1,
-                               (unsigned long) arg2,
-                               (unsigned long) arg3,
-                               (unsigned long) arg4);
-               sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
-                                SIM_SIGILL);
+               retval
+                 = cris_unknown_syscall (current_cpu, pc,
+                                         "Unimplemented wait4 call "
+                                         "(0x%lx, 0x%lx, 0x%lx, 0x%lx)\n",
+                                         (unsigned long) arg1,
+                                         (unsigned long) arg2,
+                                         (unsigned long) arg3,
+                                         (unsigned long) arg4);
                break;
              }
 
@@ -1813,19 +2045,22 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
                     && target_sa_flags != (TARGET_SA_RESTART|TARGET_SA_SIGINFO))
                    || target_sa_handler == 0)
                  {
-                   sim_io_eprintf (sd, "Unimplemented rt_sigaction "
-                                   "syscall (0x%lx, "
-                                   "0x%lx: [0x%x, 0x%x, 0x%x, "
-                                   "{0x%x, 0x%x}], "
-                                   "0x%lx)\n",
-                                   (unsigned long) arg1,
-                                   (unsigned long) arg2,
-                                   target_sa_handler, target_sa_flags,
-                                   target_sa_restorer,
-                                   target_sa_mask_low, target_sa_mask_high,
-                                   (unsigned long) arg3);
-                   sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
-                                    SIM_SIGILL);
+                   retval
+                     = cris_unknown_syscall (current_cpu, pc,
+                                             "Unimplemented rt_sigaction "
+                                             "syscall "
+                                             "(0x%lx, 0x%lx: "
+                                             "[0x%x, 0x%x, 0x%x, "
+                                             "{0x%x, 0x%x}], 0x%lx)\n",
+                                             (unsigned long) arg1,
+                                             (unsigned long) arg2,
+                                             target_sa_handler,
+                                             target_sa_flags,
+                                             target_sa_restorer,
+                                             target_sa_mask_low,
+                                             target_sa_mask_high,
+                                             (unsigned long) arg3);
+                   break;
                  }
 
                current_cpu->sighandler[signum] = target_sa_handler;
@@ -1886,7 +2121,7 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
 
                mapped_addr
                  = create_map (sd, &current_cpu->highest_mmapped_page,
-                               0, new_len);
+                               -1, new_len);
 
                if (mapped_addr > (USI) -8192)
                  {
@@ -1942,15 +2177,18 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
                || ((events = sim_core_read_unaligned_2 (current_cpu, pc,
                                                         0, ufds + 4))
                    != TARGET_POLLIN)
-               || ((cb->fstat) (cb, fd, &buf) != 0
+               || ((cb->to_fstat) (cb, fd, &buf) != 0
                    || (buf.st_mode & S_IFIFO) == 0)
                || current_cpu->thread_data == NULL)
              {
-               sim_io_eprintf (sd, "Unimplemented poll syscall "
-                               "(0x%lx: [0x%x, 0x%x, x], 0x%lx, 0x%lx)\n",
-                               (unsigned long) arg1, fd, events,
-                               (unsigned long) arg2, (unsigned long) arg3);
-               sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped, SIM_SIGILL);
+               retval
+                 = cris_unknown_syscall (current_cpu, pc,
+                                         "Unimplemented poll syscall "
+                                         "(0x%lx: [0x%x, 0x%x, x], "
+                                         "0x%lx, 0x%lx)\n",
+                                         (unsigned long) arg1, fd, events,
+                                         (unsigned long) arg2,
+                                         (unsigned long) arg3);
                break;
              }
 
@@ -1995,6 +2233,17 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
            break;
          }
 
+       case TARGET_SYS_time:
+         {
+           retval = (int) (*cb->time) (cb, 0L);
+
+           /* At time of this writing, CB_SYSCALL_time doesn't do the
+              part of setting *arg1 to the return value.  */
+           if (arg1)
+             sim_core_write_unaligned_4 (current_cpu, pc, 0, arg1, retval);
+           break;
+         }
+
        case TARGET_SYS_gettimeofday:
          if (arg1 != 0)
            {
@@ -2031,12 +2280,13 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
            if (!((offs_hi == 0 && offs_lo >= 0)
                  || (offs_hi == -1 &&  offs_lo < 0)))
              {
-               sim_io_eprintf (sd,
-                               "Unimplemented llseek offset,"
-                               " fd %d: 0x%x:0x%x\n",
-                               fd, (unsigned) arg2, (unsigned) arg3);
-               sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
-                                SIM_SIGILL);
+               retval
+                 = cris_unknown_syscall (current_cpu, pc,
+                                         "Unimplemented llseek offset,"
+                                         " fd %d: 0x%x:0x%x\n",
+                                         fd, (unsigned) arg2,
+                                         (unsigned) arg3);
+               break;
              }
 
            s.func = TARGET_SYS_lseek;
@@ -2060,6 +2310,55 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
            break;
          }
 
+         /* ssize_t writev(int fd, const struct iovec *iov, int iovcnt);
+             where:
+            struct iovec {
+              void  *iov_base;    Starting address
+               size_t iov_len;     Number of bytes to transfer
+            }; */
+       case TARGET_SYS_writev:
+         {
+           SI fd = arg1;
+           SI iov = arg2;
+           SI iovcnt = arg3;
+           SI retcnt = 0;
+           int i;
+
+           /* We'll ignore strict error-handling and just do multiple write calls.  */
+           for (i = 0; i < iovcnt; i++)
+             {
+               int sysret;
+               USI iov_base
+                 = sim_core_read_unaligned_4 (current_cpu, pc, 0,
+                                              iov + 8*i);
+               USI iov_len
+                 = sim_core_read_unaligned_4 (current_cpu, pc, 0,
+                                              iov + 8*i + 4);
+               
+               s.func = TARGET_SYS_write;
+               s.arg1 = fd;
+               s.arg2 = iov_base;
+               s.arg3 = iov_len;
+
+               if (cb_syscall (cb, &s) != CB_RC_OK)
+                 abort ();
+               sysret = s.result == -1 ? -s.errcode : s.result;
+
+               if (sysret != iov_len)
+                 {
+                   if (i != 0)
+                     abort ();
+                   retcnt = sysret;
+                   break;
+                 }
+
+               retcnt += iov_len;
+             }
+
+           retval = retcnt;
+         }
+         break;
+
        /* This one does have a generic callback function, but at the time
           of this writing, cb_syscall does not have code for it, and we
           need target-specific code for the threads implementation
@@ -2114,11 +2413,11 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
                && how != TARGET_SIG_SETMASK
                && how != TARGET_SIG_UNBLOCK)
              {
-               sim_io_eprintf (sd, "Unimplemented rt_sigprocmask syscall "
-                              "(0x%x, 0x%x, 0x%x)\n", arg1, arg2, arg3);
-               sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
-                                SIM_SIGILL);
-               retval = 0;
+               retval
+                 = cris_unknown_syscall (current_cpu, pc,
+                                         "Unimplemented rt_sigprocmask "
+                                         "syscall (0x%x, 0x%x, 0x%x)\n",
+                                         arg1, arg2, arg3);
                break;
              }
 
@@ -2189,17 +2488,19 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
                || (current_cpu->thread_data[threadno].cpu_context_atsignal
                    == NULL))
              {
-               sim_io_eprintf (sd, "Invalid sigreturn syscall: no signal"
-                               " handler active "
-                               "(0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx)\n",
-                               (unsigned long) arg1,
-                               (unsigned long) arg2,
-                               (unsigned long) arg3,
-                               (unsigned long) arg4,
-                               (unsigned long) arg5,
-                               (unsigned long) arg6);
-               sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
-                                SIM_SIGILL);
+               retval
+                 = cris_unknown_syscall (current_cpu, pc,
+                                         "Invalid sigreturn syscall: "
+                                         "no signal handler active "
+                                         "(0x%lx, 0x%lx, 0x%lx, 0x%lx, "
+                                         "0x%lx, 0x%lx)\n",
+                                         (unsigned long) arg1,
+                                         (unsigned long) arg2,
+                                         (unsigned long) arg3,
+                                         (unsigned long) arg4,
+                                         (unsigned long) arg5,
+                                         (unsigned long) arg6);
+               break;
              }
 
            was_sigsuspended
@@ -2265,11 +2566,13 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
 
            if (setsize != 8)
              {
-               sim_io_eprintf (sd, "Unimplemented rt_sigsuspend syscall"
-                              " arguments (0x%lx, 0x%lx)\n",
-                               (unsigned long) arg1, (unsigned long) arg2);
-               sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
-                                SIM_SIGILL);
+               retval
+                 = cris_unknown_syscall (current_cpu, pc,
+                                         "Unimplemented rt_sigsuspend syscall"
+                                         " arguments (0x%lx, 0x%lx)\n",
+                                         (unsigned long) arg1,
+                                         (unsigned long) arg2);
+               break;
              }
 
            /* Don't change the signal mask if we're already in
@@ -2324,6 +2627,7 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
          /* Add case labels here for other syscalls using the 32-bit
             "struct stat", provided they have a corresponding simulator
             function of course.  */
+       case TARGET_SYS_stat:
        case TARGET_SYS_fstat:
          {
            /* As long as the infrastructure doesn't cache anything
@@ -2353,8 +2657,8 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
            USI buf = arg1;
            USI size = arg2;
 
-           char *cwd = xmalloc (MAXPATHLEN);
-           if (cwd != getcwd (cwd, MAXPATHLEN))
+           char *cwd = xmalloc (SIM_PATHMAX);
+           if (cwd != getcwd (cwd, SIM_PATHMAX))
              abort ();
 
            /* FIXME: When and if we support chdir, we need something
@@ -2375,13 +2679,63 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
            break;
          }
 
+       case TARGET_SYS_access:
+         {
+           SI path = arg1;
+           SI mode = arg2;
+           char *pbuf = xmalloc (SIM_PATHMAX);
+           int i;
+           int o = 0;
+           int hmode = 0;
+
+           if (sim_core_read_unaligned_1 (current_cpu, pc, 0, path) == '/')
+             {
+               strcpy (pbuf, simulator_sysroot);
+               o += strlen (simulator_sysroot);
+             }
+
+           for (i = 0; i + o < SIM_PATHMAX; i++)
+             {
+               pbuf[i + o]
+                 = sim_core_read_unaligned_1 (current_cpu, pc, 0, path + i);
+               if (pbuf[i + o] == 0)
+                 break;
+             }
+
+           if (i + o == SIM_PATHMAX)
+             {
+               retval = -cb_host_to_target_errno (cb, ENAMETOOLONG);
+               break;
+             }
+
+           /* Assert that we don't get calls for files for which we
+              don't have support.  */
+           if (strncmp (pbuf + strlen (simulator_sysroot),
+                        "/proc/", 6) == 0)
+             abort ();
+#define X_AFLAG(x) if (mode & TARGET_ ## x) hmode |= x
+           X_AFLAG (R_OK);
+           X_AFLAG (W_OK);
+           X_AFLAG (X_OK);
+           X_AFLAG (F_OK);
+#undef X_AFLAG
+
+           if (access (pbuf, hmode) != 0)
+             retval = -cb_host_to_target_errno (cb, errno);
+           else
+             retval = 0;
+
+           free (pbuf);
+           break;
+         }
+
        case TARGET_SYS_readlink:
          {
            SI path = arg1;
            SI buf = arg2;
            SI bufsiz = arg3;
-           char *pbuf = xmalloc (MAXPATHLEN);
-           char *lbuf = xmalloc (MAXPATHLEN);
+           char *pbuf = xmalloc (SIM_PATHMAX);
+           char *lbuf = xmalloc (SIM_PATHMAX);
            char *lbuf_alloc = lbuf;
            int nchars = -1;
            int i;
@@ -2393,7 +2747,7 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
                o += strlen (simulator_sysroot);
              }
 
-           for (i = 0; i + o < MAXPATHLEN; i++)
+           for (i = 0; i + o < SIM_PATHMAX; i++)
              {
                pbuf[i + o]
                  = sim_core_read_unaligned_1 (current_cpu, pc, 0, path + i);
@@ -2401,7 +2755,7 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
                  break;
              }
 
-           if (i + o == MAXPATHLEN)
+           if (i + o == SIM_PATHMAX)
              {
                retval = -cb_host_to_target_errno (cb, ENAMETOOLONG);
                break;
@@ -2418,12 +2772,12 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
 
                if (argv0 == NULL || *argv0 == '.')
                  {
-                   sim_io_eprintf (sd, "Unimplemented readlink syscall "
-                                   "(0x%lx: [\"%s\"], 0x%lx)\n",
-                                   (unsigned long) arg1, pbuf,
-                                   (unsigned long) arg2);
-                   sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
-                                    SIM_SIGILL);
+                   retval
+                     = cris_unknown_syscall (current_cpu, pc,
+                                             "Unimplemented readlink syscall "
+                                             "(0x%lx: [\"%s\"], 0x%lx)\n",
+                                             (unsigned long) arg1, pbuf,
+                                             (unsigned long) arg2);
                    break;
                  }
                else if (*argv0 == '/')
@@ -2437,8 +2791,8 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
                  }
                else
                  {
-                   if (getcwd (lbuf, MAXPATHLEN) != NULL
-                       && strlen (lbuf) + 2 + strlen (argv0) < MAXPATHLEN)
+                   if (getcwd (lbuf, SIM_PATHMAX) != NULL
+                       && strlen (lbuf) + 2 + strlen (argv0) < SIM_PATHMAX)
                      {
                        if (strncmp (simulator_sysroot, lbuf,
                                     strlen (simulator_sysroot)) == 0)
@@ -2453,7 +2807,7 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
                  }
              }
            else
-             nchars = readlink (pbuf, lbuf, MAXPATHLEN);
+             nchars = readlink (pbuf, lbuf, SIM_PATHMAX);
 
            /* We trust that the readlink result returns a *relative*
               link, or one already adjusted for the file-path-prefix.
@@ -2656,19 +3010,19 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
                break;
              }
 
-           sim_io_eprintf (sd, "Unimplemented _sysctl syscall "
-                           "(0x%lx: [0x%lx, 0x%lx],"
-                           " 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx)\n",
-                           (unsigned long) name,
-                           (unsigned long) name0,
-                           (unsigned long) name1,
-                           (unsigned long) nlen,
-                           (unsigned long) oldval,
-                           (unsigned long) oldlenp,
-                           (unsigned long) newval,
-                           (unsigned long) newlen);
-           sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
-                            SIM_SIGILL);
+           retval
+             = cris_unknown_syscall (current_cpu, pc,
+                                     "Unimplemented _sysctl syscall "
+                                     "(0x%lx: [0x%lx, 0x%lx],"
+                                     " 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx)\n",
+                                     (unsigned long) name,
+                                     (unsigned long) name0,
+                                     (unsigned long) name1,
+                                     (unsigned long) nlen,
+                                     (unsigned long) oldval,
+                                     (unsigned long) oldlenp,
+                                     (unsigned long) newval,
+                                     (unsigned long) newlen);
            break;
          }
 
@@ -2741,11 +3095,13 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
                 | TARGET_CLONE_SIGHAND)
                || newsp == 0)
              {
-               sim_io_eprintf (sd,
-                               "Unimplemented clone syscall (0x%lx, 0x%lx)\n",
-                               (unsigned long) arg1, (unsigned long) arg2);
-               sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
-                                SIM_SIGILL);
+               retval
+                 = cris_unknown_syscall (current_cpu, pc,
+                                         "Unimplemented clone syscall "
+                                         "(0x%lx, 0x%lx)\n",
+                                         (unsigned long) arg1,
+                                         (unsigned long) arg2);
+               break;
              }
 
            if (current_cpu->thread_data == NULL)
@@ -2806,16 +3162,37 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
          retval = -cb_host_to_target_errno (cb, ENOSYS);
          break;
 
+       case TARGET_SYS_set_thread_area:
+         /* Do the same error check as Linux.  */
+         if (arg1 & 255)
+           {
+             retval = -cb_host_to_target_errno (cb, EINVAL);
+             break;
+           }
+         (*current_cpu->set_target_thread_data) (current_cpu, arg1);
+         retval = 0;
+         break;
+
        unimplemented_syscall:
        default:
-         sim_io_eprintf (sd, "Unimplemented syscall: %d "
-                         "(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n", callnum,
-                         arg1, arg2, arg3, arg4, arg5, arg6);
-         sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
-                          SIM_SIGILL);
+         retval
+           = cris_unknown_syscall (current_cpu, pc,
+                                   "Unimplemented syscall: %d "
+                                   "(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",
+                                   callnum, arg1, arg2, arg3, arg4, arg5,
+                                   arg6);
        }
     }
 
+  /* Minimal support for fcntl F_GETFL as used in open+fdopen.  */
+  if (callnum == TARGET_SYS_open)
+    {
+      current_cpu->last_open_fd = retval;
+      current_cpu->last_open_flags = arg2;
+    }
+
+  current_cpu->last_syscall = callnum;
+
   /* A system call is a rescheduling point.  For the time being, we don't
      reschedule anywhere else.  */
   if (current_cpu->m1threads != 0
@@ -2888,13 +3265,15 @@ cris_pipe_nonempty (host_callback *cb ATTRIBUTE_UNUSED,
 
 static void
 cris_pipe_empty (host_callback *cb,
-                int reader ATTRIBUTE_UNUSED,
+                int reader,
                 int writer)
 {
   int i;
   SIM_CPU *cpu = current_cpu_for_cb_callback;
+  SIM_DESC sd = CPU_STATE (current_cpu_for_cb_callback);
   bfd_byte r10_buf[4];
-  int remaining = cb->pipe_buffer[writer].size;
+  int remaining
+    = cb->pipe_buffer[writer].size - cb->pipe_buffer[reader].size;
 
   /* We need to find the thread that waits for this pipe.  */
   for (i = 0; i < SIM_TARGET_MAX_THREADS; i++)
@@ -2902,6 +3281,7 @@ cris_pipe_empty (host_callback *cb,
        && cpu->thread_data[i].pipe_write_fd == writer)
       {
        int retval;
+
        /* Temporarily switch to this cpu context, so we can change the
           PC by ordinary calls.  */
 
@@ -2912,19 +3292,25 @@ cris_pipe_empty (host_callback *cb,
                cpu->thread_data[i].cpu_context,
                cpu->thread_cpu_data_size);
 
-       /* The return value is supposed to contain the number of written
-          bytes, which is the number of bytes requested and returned at
-          the write call.  We subtract the remaining bytes from that,
-          but making sure we still get a positive number.
-          The return value may also be a negative number; an error
-          value.  We cover this case by comparing against remaining,
-          which is always >= 0.  */
+       /* The return value is supposed to contain the number of
+          written bytes, which is the number of bytes requested and
+          returned at the write call.  You might think the right
+          thing is to adjust the return-value to be only the
+          *consumed* number of bytes, but it isn't.  We're only
+          called if the pipe buffer is fully consumed or it is being
+          closed, possibly with remaining bytes.  For the latter
+          case, the writer is still supposed to see success for
+          PIPE_BUF bytes (a constant which we happen to know and is
+          unlikely to change).  The return value may also be a
+          negative number; an error value.  This case is covered
+          because "remaining" is always >= 0.  */
        (*CPU_REG_FETCH (cpu)) (cpu, H_GR_R10, r10_buf, 4);
        retval = (int) bfd_getl_signed_32 (r10_buf);
-       if (retval >= remaining)
-         bfd_putl32 (retval - remaining, r10_buf);
-       (*CPU_REG_STORE (cpu)) (cpu, H_GR_R10, r10_buf, 4);
-
+       if (retval - remaining > TARGET_PIPE_BUF)
+         {
+           bfd_putl32 (retval - remaining, r10_buf);
+           (*CPU_REG_STORE (cpu)) (cpu, H_GR_R10, r10_buf, 4);
+         }
        sim_pc_set (cpu, sim_pc_get (cpu) + 2);
        memcpy (cpu->thread_data[i].cpu_context,
                &cpu->cpu_data_placeholder,
This page took 0.050691 seconds and 4 git commands to generate.