Inline abbrev lookup
[deliverable/binutils-gdb.git] / sim / cris / traps.c
index 607f72c6345c830b6c0190e5e72420eaf2b92823..98d1e03294ed89f211859cf2523ed751728492df 100644 (file)
@@ -1,28 +1,29 @@
 /* CRIS exception, interrupt, and trap (EIT) support
 /* CRIS exception, interrupt, and trap (EIT) support
-   Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+   Copyright (C) 2004-2020 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
    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.
 
 
 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-main.h"
+#include "sim-syscall.h"
 #include "sim-options.h"
 #include "bfd.h"
 /* FIXME: get rid of targ-vals.h usage everywhere else.  */
 
 #include "sim-options.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
 #ifdef HAVE_ERRNO_H
 #include <errno.h>
 #endif
@@ -38,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
 #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.  */
 
 
 /* The verbatim values are from asm-cris/unistd.h.  */
 
@@ -50,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_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
 #define TARGET_SYS_kill 37
 #define TARGET_SYS_rename 38
 #define TARGET_SYS_pipe 42
@@ -72,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_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
 #define TARGET_SYS__sysctl 149
 #define TARGET_SYS_sched_setparam 154
 #define TARGET_SYS_sched_getparam 155
@@ -96,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_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
 
 #define TARGET_PROT_READ       0x1
 #define TARGET_PROT_WRITE      0x2
@@ -107,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_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
 
 #define TARGET_CTL_KERN                1
 #define TARGET_CTL_VM          2
@@ -126,10 +147,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 
 #define TARGET_TCGETS 0x5401
 
 
 #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.  */
 
 /* Milliseconds since start of run.  We use the number of syscalls to
    avoid introducing noise in the execution time.  */
@@ -225,6 +247,15 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #define TARGET___WALL 0x40000000
 #define TARGET___WCLONE 0x80000000
 
 #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"
 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"
@@ -233,22 +264,21 @@ static const char stat_map[] =
 
 static const CB_TARGET_DEFS_MAP syscall_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.  */
 };
 
 /* An older, 32-bit-only stat mapping.  */
@@ -261,9 +291,9 @@ static const char stat32_map[] =
    newlib Linux mapping.  */
 static const CB_TARGET_DEFS_MAP syscall_stat32_map[] =
 {
    newlib Linux mapping.  */
 static const CB_TARGET_DEFS_MAP syscall_stat32_map[] =
 {
-  { CB_SYS_fstat, TARGET_SYS_fstat },
-  { CB_SYS_stat, TARGET_SYS_stat },
-  { 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
 };
 
 /* Giving the true value for the running sim process will lead to
@@ -282,378 +312,378 @@ static const CB_TARGET_DEFS_MAP syscall_stat32_map[] =
 static const CB_TARGET_DEFS_MAP errno_map[] =
 {
 #ifdef EPERM
 static const CB_TARGET_DEFS_MAP errno_map[] =
 {
 #ifdef EPERM
-  { EPERM, 1 },
+  { "EPERM", EPERM, 1 },
 #endif
 #ifdef ENOENT
 #endif
 #ifdef ENOENT
-  { ENOENT, 2 },
+  { "ENOENT", ENOENT, 2 },
 #endif
 #ifdef ESRCH
 #endif
 #ifdef ESRCH
-  { ESRCH, 3 },
+  { "ESRCH", ESRCH, 3 },
 #endif
 #ifdef EINTR
 #endif
 #ifdef EINTR
-  { EINTR, 4 },
+  { "EINTR", EINTR, 4 },
 #endif
 #ifdef EIO
 #endif
 #ifdef EIO
-  { EIO, 5 },
+  { "EIO", EIO, 5 },
 #endif
 #ifdef ENXIO
 #endif
 #ifdef ENXIO
-  { ENXIO, 6 },
+  { "ENXIO", ENXIO, 6 },
 #endif
 #ifdef E2BIG
 #endif
 #ifdef E2BIG
-  { E2BIG, 7 },
+  { "E2BIG", E2BIG, 7 },
 #endif
 #ifdef ENOEXEC
 #endif
 #ifdef ENOEXEC
-  { ENOEXEC, 8 },
+  { "ENOEXEC", ENOEXEC, 8 },
 #endif
 #ifdef EBADF
 #endif
 #ifdef EBADF
-  { EBADF, 9 },
+  { "EBADF", EBADF, 9 },
 #endif
 #ifdef ECHILD
 #endif
 #ifdef ECHILD
-  { ECHILD, 10 },
+  { "ECHILD", ECHILD, 10 },
 #endif
 #ifdef EAGAIN
 #endif
 #ifdef EAGAIN
-  { EAGAIN, 11 },
+  { "EAGAIN", EAGAIN, 11 },
 #endif
 #ifdef ENOMEM
 #endif
 #ifdef ENOMEM
-  { ENOMEM, 12 },
+  { "ENOMEM", ENOMEM, 12 },
 #endif
 #ifdef EACCES
 #endif
 #ifdef EACCES
-  { EACCES, 13 },
+  { "EACCES", EACCES, 13 },
 #endif
 #ifdef EFAULT
 #endif
 #ifdef EFAULT
-  { EFAULT, 14 },
+  { "EFAULT", EFAULT, 14 },
 #endif
 #ifdef ENOTBLK
 #endif
 #ifdef ENOTBLK
-  { ENOTBLK, 15 },
+  { "ENOTBLK", ENOTBLK, 15 },
 #endif
 #ifdef EBUSY
 #endif
 #ifdef EBUSY
-  { EBUSY, 16 },
+  { "EBUSY", EBUSY, 16 },
 #endif
 #ifdef EEXIST
 #endif
 #ifdef EEXIST
-  { EEXIST, 17 },
+  { "EEXIST", EEXIST, 17 },
 #endif
 #ifdef EXDEV
 #endif
 #ifdef EXDEV
-  { EXDEV, 18 },
+  { "EXDEV", EXDEV, 18 },
 #endif
 #ifdef ENODEV
 #endif
 #ifdef ENODEV
-  { ENODEV, 19 },
+  { "ENODEV", ENODEV, 19 },
 #endif
 #ifdef ENOTDIR
 #endif
 #ifdef ENOTDIR
-  { ENOTDIR, 20 },
+  { "ENOTDIR", ENOTDIR, 20 },
 #endif
 #ifdef EISDIR
 #endif
 #ifdef EISDIR
-  { EISDIR, 21 },
+  { "EISDIR", EISDIR, 21 },
 #endif
 #ifdef EINVAL
 #endif
 #ifdef EINVAL
-  { EINVAL, 22 },
+  { "EINVAL", EINVAL, 22 },
 #endif
 #ifdef ENFILE
 #endif
 #ifdef ENFILE
-  { ENFILE, 23 },
+  { "ENFILE", ENFILE, 23 },
 #endif
 #ifdef EMFILE
 #endif
 #ifdef EMFILE
-  { EMFILE, 24 },
+  { "EMFILE", EMFILE, 24 },
 #endif
 #ifdef ENOTTY
 #endif
 #ifdef ENOTTY
-  { ENOTTY, 25 },
+  { "ENOTTY", ENOTTY, 25 },
 #endif
 #ifdef ETXTBSY
 #endif
 #ifdef ETXTBSY
-  { ETXTBSY, 26 },
+  { "ETXTBSY", ETXTBSY, 26 },
 #endif
 #ifdef EFBIG
 #endif
 #ifdef EFBIG
-  { EFBIG, 27 },
+  { "EFBIG", EFBIG, 27 },
 #endif
 #ifdef ENOSPC
 #endif
 #ifdef ENOSPC
-  { ENOSPC, 28 },
+  { "ENOSPC", ENOSPC, 28 },
 #endif
 #ifdef ESPIPE
 #endif
 #ifdef ESPIPE
-  { ESPIPE, 29 },
+  { "ESPIPE", ESPIPE, 29 },
 #endif
 #ifdef EROFS
 #endif
 #ifdef EROFS
-  { EROFS, 30 },
+  { "EROFS", EROFS, 30 },
 #endif
 #ifdef EMLINK
 #endif
 #ifdef EMLINK
-  { EMLINK, 31 },
+  { "EMLINK", EMLINK, 31 },
 #endif
 #ifdef EPIPE
 #endif
 #ifdef EPIPE
-  { EPIPE, 32 },
+  { "EPIPE", EPIPE, 32 },
 #endif
 #ifdef EDOM
 #endif
 #ifdef EDOM
-  { EDOM, 33 },
+  { "EDOM", EDOM, 33 },
 #endif
 #ifdef ERANGE
 #endif
 #ifdef ERANGE
-  { ERANGE, 34 },
+  { "ERANGE", ERANGE, 34 },
 #endif
 #ifdef EDEADLK
 #endif
 #ifdef EDEADLK
-  { EDEADLK, 35 },
+  { "EDEADLK", EDEADLK, 35 },
 #endif
 #ifdef ENAMETOOLONG
 #endif
 #ifdef ENAMETOOLONG
-  { ENAMETOOLONG, 36 },
+  { "ENAMETOOLONG", ENAMETOOLONG, 36 },
 #endif
 #ifdef ENOLCK
 #endif
 #ifdef ENOLCK
-  { ENOLCK, 37 },
+  { "ENOLCK", ENOLCK, 37 },
 #endif
 #ifdef ENOSYS
 #endif
 #ifdef ENOSYS
-  { ENOSYS, 38 },
+  { "ENOSYS", ENOSYS, 38 },
 #endif
 #ifdef ENOTEMPTY
 #endif
 #ifdef ENOTEMPTY
-  { ENOTEMPTY, 39 },
+  { "ENOTEMPTY", ENOTEMPTY, 39 },
 #endif
 #ifdef ELOOP
 #endif
 #ifdef ELOOP
-  { ELOOP, 40 },
+  { "ELOOP", ELOOP, 40 },
 #endif
 #ifdef EWOULDBLOCK
 #endif
 #ifdef EWOULDBLOCK
-  { EWOULDBLOCK, 11 },
+  { "EWOULDBLOCK", EWOULDBLOCK, 11 },
 #endif
 #ifdef ENOMSG
 #endif
 #ifdef ENOMSG
-  { ENOMSG, 42 },
+  { "ENOMSG", ENOMSG, 42 },
 #endif
 #ifdef EIDRM
 #endif
 #ifdef EIDRM
-  { EIDRM, 43 },
+  { "EIDRM", EIDRM, 43 },
 #endif
 #ifdef ECHRNG
 #endif
 #ifdef ECHRNG
-  { ECHRNG, 44 },
+  { "ECHRNG", ECHRNG, 44 },
 #endif
 #ifdef EL2NSYNC
 #endif
 #ifdef EL2NSYNC
-  { EL2NSYNC, 45 },
+  { "EL2NSYNC", EL2NSYNC, 45 },
 #endif
 #ifdef EL3HLT
 #endif
 #ifdef EL3HLT
-  { EL3HLT, 46 },
+  { "EL3HLT", EL3HLT, 46 },
 #endif
 #ifdef EL3RST
 #endif
 #ifdef EL3RST
-  { EL3RST, 47 },
+  { "EL3RST", EL3RST, 47 },
 #endif
 #ifdef ELNRNG
 #endif
 #ifdef ELNRNG
-  { ELNRNG, 48 },
+  { "ELNRNG", ELNRNG, 48 },
 #endif
 #ifdef EUNATCH
 #endif
 #ifdef EUNATCH
-  { EUNATCH, 49 },
+  { "EUNATCH", EUNATCH, 49 },
 #endif
 #ifdef ENOCSI
 #endif
 #ifdef ENOCSI
-  { ENOCSI, 50 },
+  { "ENOCSI", ENOCSI, 50 },
 #endif
 #ifdef EL2HLT
 #endif
 #ifdef EL2HLT
-  { EL2HLT, 51 },
+  { "EL2HLT", EL2HLT, 51 },
 #endif
 #ifdef EBADE
 #endif
 #ifdef EBADE
-  { EBADE, 52 },
+  { "EBADE", EBADE, 52 },
 #endif
 #ifdef EBADR
 #endif
 #ifdef EBADR
-  { EBADR, 53 },
+  { "EBADR", EBADR, 53 },
 #endif
 #ifdef EXFULL
 #endif
 #ifdef EXFULL
-  { EXFULL, 54 },
+  { "EXFULL", EXFULL, 54 },
 #endif
 #ifdef ENOANO
 #endif
 #ifdef ENOANO
-  { ENOANO, 55 },
+  { "ENOANO", ENOANO, 55 },
 #endif
 #ifdef EBADRQC
 #endif
 #ifdef EBADRQC
-  { EBADRQC, 56 },
+  { "EBADRQC", EBADRQC, 56 },
 #endif
 #ifdef EBADSLT
 #endif
 #ifdef EBADSLT
-  { EBADSLT, 57 },
+  { "EBADSLT", EBADSLT, 57 },
 #endif
 #ifdef EDEADLOCK
 #endif
 #ifdef EDEADLOCK
-  { EDEADLOCK, 35 },
+  { "EDEADLOCK", EDEADLOCK, 35 },
 #endif
 #ifdef EBFONT
 #endif
 #ifdef EBFONT
-  { EBFONT, 59 },
+  { "EBFONT", EBFONT, 59 },
 #endif
 #ifdef ENOSTR
 #endif
 #ifdef ENOSTR
-  { ENOSTR, 60 },
+  { "ENOSTR", ENOSTR, 60 },
 #endif
 #ifdef ENODATA
 #endif
 #ifdef ENODATA
-  { ENODATA, 61 },
+  { "ENODATA", ENODATA, 61 },
 #endif
 #ifdef ETIME
 #endif
 #ifdef ETIME
-  { ETIME, 62 },
+  { "ETIME", ETIME, 62 },
 #endif
 #ifdef ENOSR
 #endif
 #ifdef ENOSR
-  { ENOSR, 63 },
+  { "ENOSR", ENOSR, 63 },
 #endif
 #ifdef ENONET
 #endif
 #ifdef ENONET
-  { ENONET, 64 },
+  { "ENONET", ENONET, 64 },
 #endif
 #ifdef ENOPKG
 #endif
 #ifdef ENOPKG
-  { ENOPKG, 65 },
+  { "ENOPKG", ENOPKG, 65 },
 #endif
 #ifdef EREMOTE
 #endif
 #ifdef EREMOTE
-  { EREMOTE, 66 },
+  { "EREMOTE", EREMOTE, 66 },
 #endif
 #ifdef ENOLINK
 #endif
 #ifdef ENOLINK
-  { ENOLINK, 67 },
+  { "ENOLINK", ENOLINK, 67 },
 #endif
 #ifdef EADV
 #endif
 #ifdef EADV
-  { EADV, 68 },
+  { "EADV", EADV, 68 },
 #endif
 #ifdef ESRMNT
 #endif
 #ifdef ESRMNT
-  { ESRMNT, 69 },
+  { "ESRMNT", ESRMNT, 69 },
 #endif
 #ifdef ECOMM
 #endif
 #ifdef ECOMM
-  { ECOMM, 70 },
+  { "ECOMM", ECOMM, 70 },
 #endif
 #ifdef EPROTO
 #endif
 #ifdef EPROTO
-  { EPROTO, 71 },
+  { "EPROTO", EPROTO, 71 },
 #endif
 #ifdef EMULTIHOP
 #endif
 #ifdef EMULTIHOP
-  { EMULTIHOP, 72 },
+  { "EMULTIHOP", EMULTIHOP, 72 },
 #endif
 #ifdef EDOTDOT
 #endif
 #ifdef EDOTDOT
-  { EDOTDOT, 73 },
+  { "EDOTDOT", EDOTDOT, 73 },
 #endif
 #ifdef EBADMSG
 #endif
 #ifdef EBADMSG
-  { EBADMSG, 74 },
+  { "EBADMSG", EBADMSG, 74 },
 #endif
 #ifdef EOVERFLOW
 #endif
 #ifdef EOVERFLOW
-  { EOVERFLOW, 75 },
+  { "EOVERFLOW", EOVERFLOW, 75 },
 #endif
 #ifdef ENOTUNIQ
 #endif
 #ifdef ENOTUNIQ
-  { ENOTUNIQ, 76 },
+  { "ENOTUNIQ", ENOTUNIQ, 76 },
 #endif
 #ifdef EBADFD
 #endif
 #ifdef EBADFD
-  { EBADFD, 77 },
+  { "EBADFD", EBADFD, 77 },
 #endif
 #ifdef EREMCHG
 #endif
 #ifdef EREMCHG
-  { EREMCHG, 78 },
+  { "EREMCHG", EREMCHG, 78 },
 #endif
 #ifdef ELIBACC
 #endif
 #ifdef ELIBACC
-  { ELIBACC, 79 },
+  { "ELIBACC", ELIBACC, 79 },
 #endif
 #ifdef ELIBBAD
 #endif
 #ifdef ELIBBAD
-  { ELIBBAD, 80 },
+  { "ELIBBAD", ELIBBAD, 80 },
 #endif
 #ifdef ELIBSCN
 #endif
 #ifdef ELIBSCN
-  { ELIBSCN, 81 },
+  { "ELIBSCN", ELIBSCN, 81 },
 #endif
 #ifdef ELIBMAX
 #endif
 #ifdef ELIBMAX
-  { ELIBMAX, 82 },
+  { "ELIBMAX", ELIBMAX, 82 },
 #endif
 #ifdef ELIBEXEC
 #endif
 #ifdef ELIBEXEC
-  { ELIBEXEC, 83 },
+  { "ELIBEXEC", ELIBEXEC, 83 },
 #endif
 #ifdef EILSEQ
 #endif
 #ifdef EILSEQ
-  { EILSEQ, 84 },
+  { "EILSEQ", EILSEQ, 84 },
 #endif
 #ifdef ERESTART
 #endif
 #ifdef ERESTART
-  { ERESTART, 85 },
+  { "ERESTART", ERESTART, 85 },
 #endif
 #ifdef ESTRPIPE
 #endif
 #ifdef ESTRPIPE
-  { ESTRPIPE, 86 },
+  { "ESTRPIPE", ESTRPIPE, 86 },
 #endif
 #ifdef EUSERS
 #endif
 #ifdef EUSERS
-  { EUSERS, 87 },
+  { "EUSERS", EUSERS, 87 },
 #endif
 #ifdef ENOTSOCK
 #endif
 #ifdef ENOTSOCK
-  { ENOTSOCK, 88 },
+  { "ENOTSOCK", ENOTSOCK, 88 },
 #endif
 #ifdef EDESTADDRREQ
 #endif
 #ifdef EDESTADDRREQ
-  { EDESTADDRREQ, 89 },
+  { "EDESTADDRREQ", EDESTADDRREQ, 89 },
 #endif
 #ifdef EMSGSIZE
 #endif
 #ifdef EMSGSIZE
-  { EMSGSIZE, 90 },
+  { "EMSGSIZE", EMSGSIZE, 90 },
 #endif
 #ifdef EPROTOTYPE
 #endif
 #ifdef EPROTOTYPE
-  { EPROTOTYPE, 91 },
+  { "EPROTOTYPE", EPROTOTYPE, 91 },
 #endif
 #ifdef ENOPROTOOPT
 #endif
 #ifdef ENOPROTOOPT
-  { ENOPROTOOPT, 92 },
+  { "ENOPROTOOPT", ENOPROTOOPT, 92 },
 #endif
 #ifdef EPROTONOSUPPORT
 #endif
 #ifdef EPROTONOSUPPORT
-  { EPROTONOSUPPORT, 93 },
+  { "EPROTONOSUPPORT", EPROTONOSUPPORT, 93 },
 #endif
 #ifdef ESOCKTNOSUPPORT
 #endif
 #ifdef ESOCKTNOSUPPORT
-  { ESOCKTNOSUPPORT, 94 },
+  { "ESOCKTNOSUPPORT", ESOCKTNOSUPPORT, 94 },
 #endif
 #ifdef EOPNOTSUPP
 #endif
 #ifdef EOPNOTSUPP
-  { EOPNOTSUPP, 95 },
+  { "EOPNOTSUPP", EOPNOTSUPP, 95 },
 #endif
 #ifdef EPFNOSUPPORT
 #endif
 #ifdef EPFNOSUPPORT
-  { EPFNOSUPPORT, 96 },
+  { "EPFNOSUPPORT", EPFNOSUPPORT, 96 },
 #endif
 #ifdef EAFNOSUPPORT
 #endif
 #ifdef EAFNOSUPPORT
-  { EAFNOSUPPORT, 97 },
+  { "EAFNOSUPPORT", EAFNOSUPPORT, 97 },
 #endif
 #ifdef EADDRINUSE
 #endif
 #ifdef EADDRINUSE
-  { EADDRINUSE, 98 },
+  { "EADDRINUSE", EADDRINUSE, 98 },
 #endif
 #ifdef EADDRNOTAVAIL
 #endif
 #ifdef EADDRNOTAVAIL
-  { EADDRNOTAVAIL, 99 },
+  { "EADDRNOTAVAIL", EADDRNOTAVAIL, 99 },
 #endif
 #ifdef ENETDOWN
 #endif
 #ifdef ENETDOWN
-  { ENETDOWN, 100 },
+  { "ENETDOWN", ENETDOWN, 100 },
 #endif
 #ifdef ENETUNREACH
 #endif
 #ifdef ENETUNREACH
-  { ENETUNREACH, 101 },
+  { "ENETUNREACH", ENETUNREACH, 101 },
 #endif
 #ifdef ENETRESET
 #endif
 #ifdef ENETRESET
-  { ENETRESET, 102 },
+  { "ENETRESET", ENETRESET, 102 },
 #endif
 #ifdef ECONNABORTED
 #endif
 #ifdef ECONNABORTED
-  { ECONNABORTED, 103 },
+  { "ECONNABORTED", ECONNABORTED, 103 },
 #endif
 #ifdef ECONNRESET
 #endif
 #ifdef ECONNRESET
-  { ECONNRESET, 104 },
+  { "ECONNRESET", ECONNRESET, 104 },
 #endif
 #ifdef ENOBUFS
 #endif
 #ifdef ENOBUFS
-  { ENOBUFS, 105 },
+  { "ENOBUFS", ENOBUFS, 105 },
 #endif
 #ifdef EISCONN
 #endif
 #ifdef EISCONN
-  { EISCONN, 106 },
+  { "EISCONN", EISCONN, 106 },
 #endif
 #ifdef ENOTCONN
 #endif
 #ifdef ENOTCONN
-  { ENOTCONN, 107 },
+  { "ENOTCONN", ENOTCONN, 107 },
 #endif
 #ifdef ESHUTDOWN
 #endif
 #ifdef ESHUTDOWN
-  { ESHUTDOWN, 108 },
+  { "ESHUTDOWN", ESHUTDOWN, 108 },
 #endif
 #ifdef ETOOMANYREFS
 #endif
 #ifdef ETOOMANYREFS
-  { ETOOMANYREFS, 109 },
+  { "ETOOMANYREFS", ETOOMANYREFS, 109 },
 #endif
 #ifdef ETIMEDOUT
 #endif
 #ifdef ETIMEDOUT
-  { ETIMEDOUT, 110 },
+  { "ETIMEDOUT", ETIMEDOUT, 110 },
 #endif
 #ifdef ECONNREFUSED
 #endif
 #ifdef ECONNREFUSED
-  { ECONNREFUSED, 111 },
+  { "ECONNREFUSED", ECONNREFUSED, 111 },
 #endif
 #ifdef EHOSTDOWN
 #endif
 #ifdef EHOSTDOWN
-  { EHOSTDOWN, 112 },
+  { "EHOSTDOWN", EHOSTDOWN, 112 },
 #endif
 #ifdef EHOSTUNREACH
 #endif
 #ifdef EHOSTUNREACH
-  { EHOSTUNREACH, 113 },
+  { "EHOSTUNREACH", EHOSTUNREACH, 113 },
 #endif
 #ifdef EALREADY
 #endif
 #ifdef EALREADY
-  { EALREADY, 114 },
+  { "EALREADY", EALREADY, 114 },
 #endif
 #ifdef EINPROGRESS
 #endif
 #ifdef EINPROGRESS
-  { EINPROGRESS, 115 },
+  { "EINPROGRESS", EINPROGRESS, 115 },
 #endif
 #ifdef ESTALE
 #endif
 #ifdef ESTALE
-  { ESTALE, 116 },
+  { "ESTALE", ESTALE, 116 },
 #endif
 #ifdef EUCLEAN
 #endif
 #ifdef EUCLEAN
-  { EUCLEAN, 117 },
+  { "EUCLEAN", EUCLEAN, 117 },
 #endif
 #ifdef ENOTNAM
 #endif
 #ifdef ENOTNAM
-  { ENOTNAM, 118 },
+  { "ENOTNAM", ENOTNAM, 118 },
 #endif
 #ifdef ENAVAIL
 #endif
 #ifdef ENAVAIL
-  { ENAVAIL, 119 },
+  { "ENAVAIL", ENAVAIL, 119 },
 #endif
 #ifdef EISNAM
 #endif
 #ifdef EISNAM
-  { EISNAM, 120 },
+  { "EISNAM", EISNAM, 120 },
 #endif
 #ifdef EREMOTEIO
 #endif
 #ifdef EREMOTEIO
-  { EREMOTEIO, 121 },
+  { "EREMOTEIO", EREMOTEIO, 121 },
 #endif
 #ifdef EDQUOT
 #endif
 #ifdef EDQUOT
-  { EDQUOT, 122 },
+  { "EDQUOT", EDQUOT, 122 },
 #endif
 #ifdef ENOMEDIUM
 #endif
 #ifdef ENOMEDIUM
-  { ENOMEDIUM, 123 },
+  { "ENOMEDIUM", ENOMEDIUM, 123 },
 #endif
 #ifdef EMEDIUMTYPE
 #endif
 #ifdef EMEDIUMTYPE
-  { EMEDIUMTYPE, 124 },
+  { "EMEDIUMTYPE", EMEDIUMTYPE, 124 },
 #endif
 #endif
-  { 0, -1 }
+  { 0, 0, 0 }
 };
 
 /* Extracted by applying
 };
 
 /* Extracted by applying
@@ -664,71 +694,76 @@ static const CB_TARGET_DEFS_MAP errno_map[] =
    installation and removing synonyms and unnecessary items.  Don't
    forget the end-marker.  */
 
    installation and removing synonyms and unnecessary items.  Don't
    forget the end-marker.  */
 
-/* This one we treat specially, as it's used in the fcntl syscall.  */
-#define TARGET_O_ACCMODE 3
+/* 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
 
 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
 #endif
 #ifdef O_RDONLY
-  { O_RDONLY, 0x0 },
+  { "O_RDONLY", O_RDONLY, TARGET_O_RDONLY },
 #endif
 #ifdef O_WRONLY
 #endif
 #ifdef O_WRONLY
-  { O_WRONLY, 0x1 },
+  { "O_WRONLY", O_WRONLY, TARGET_O_WRONLY },
 #endif
 #ifdef O_RDWR
 #endif
 #ifdef O_RDWR
-  { O_RDWR, 0x2 },
+  { "O_RDWR", O_RDWR, 0x2 },
 #endif
 #ifdef O_CREAT
 #endif
 #ifdef O_CREAT
-  { O_CREAT, 0x40 },
+  { "O_CREAT", O_CREAT, 0x40 },
 #endif
 #ifdef O_EXCL
 #endif
 #ifdef O_EXCL
-  { O_EXCL, 0x80 },
+  { "O_EXCL", O_EXCL, 0x80 },
 #endif
 #ifdef O_NOCTTY
 #endif
 #ifdef O_NOCTTY
-  { O_NOCTTY, 0x100 },
+  { "O_NOCTTY", O_NOCTTY, 0x100 },
 #endif
 #ifdef O_TRUNC
 #endif
 #ifdef O_TRUNC
-  { O_TRUNC, 0x200 },
+  { "O_TRUNC", O_TRUNC, 0x200 },
 #endif
 #ifdef O_APPEND
 #endif
 #ifdef O_APPEND
-  { O_APPEND, 0x400 },
+  { "O_APPEND", O_APPEND, 0x400 },
 #endif
 #ifdef O_NONBLOCK
 #endif
 #ifdef O_NONBLOCK
-  { O_NONBLOCK, 0x800 },
+  { "O_NONBLOCK", O_NONBLOCK, 0x800 },
 #endif
 #ifdef O_NDELAY
 #endif
 #ifdef O_NDELAY
-  { O_NDELAY, 0x0 },
+  { "O_NDELAY", O_NDELAY, 0x0 },
 #endif
 #ifdef O_SYNC
 #endif
 #ifdef O_SYNC
-  { O_SYNC, 0x1000 },
+  { "O_SYNC", O_SYNC, 0x1000 },
 #endif
 #ifdef FASYNC
 #endif
 #ifdef FASYNC
-  { FASYNC, 0x2000 },
+  { "FASYNC", FASYNC, 0x2000 },
 #endif
 #ifdef O_DIRECT
 #endif
 #ifdef O_DIRECT
-  { O_DIRECT, 0x4000 },
+  { "O_DIRECT", O_DIRECT, 0x4000 },
 #endif
 #ifdef O_LARGEFILE
 #endif
 #ifdef O_LARGEFILE
-  { O_LARGEFILE, 0x8000 },
+  { "O_LARGEFILE", O_LARGEFILE, 0x8000 },
 #endif
 #ifdef O_DIRECTORY
 #endif
 #ifdef O_DIRECTORY
-  { O_DIRECTORY, 0x10000 },
+  { "O_DIRECTORY", O_DIRECTORY, 0x10000 },
 #endif
 #ifdef O_NOFOLLOW
 #endif
 #ifdef O_NOFOLLOW
-  { O_NOFOLLOW, 0x20000 },
+  { "O_NOFOLLOW", O_NOFOLLOW, 0x20000 },
 #endif
 #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;
 
 /* 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 **,
 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 **,
@@ -738,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);
 
 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:
 /* 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:
@@ -848,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.  */
 
   /* 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.
 }
 
 /* Check whether any part of [addr .. addr + len - 1] is already mapped.
@@ -891,7 +902,59 @@ is_mapped (SIM_DESC sd ATTRIBUTE_UNUSED,
   return 0;
 }
 
   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,
 
 static USI
 create_map (SIM_DESC sd, struct cris_sim_mmapped_page **rootp, USI addr,
@@ -901,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;
 
   struct cris_sim_mmapped_page **higher_prevp = rootp;
   USI new_addr = 0x40000000;
 
-  if (addr != 0)
+  if (addr != (USI) -1)
     new_addr = addr;
     new_addr = addr;
-  else if (*rootp)
+  else if (*rootp && rootp[0]->addr >= new_addr)
     new_addr = rootp[0]->addr + 8192;
 
   if (len != 8192)
     new_addr = rootp[0]->addr + 8192;
 
   if (len != 8192)
@@ -927,6 +990,10 @@ create_map (SIM_DESC sd, struct cris_sim_mmapped_page **rootp, USI addr,
        mapp = mapp->prev)
     higher_prevp = &mapp->prev;
 
        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));
   /* 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));
@@ -957,6 +1024,7 @@ unmap_pages (SIM_DESC sd, struct cris_sim_mmapped_page **rootp, USI addr,
   if (len != 8192)
     {
       USI page_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?  */
 
       if (len & 8191)
        /* Which is better: return an error for this, or just round it up?  */
@@ -965,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;
       /* 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)
           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)
     }
 
   for (mapp = *rootp; mapp != NULL && mapp->addr > addr; mapp = mapp->prev)
@@ -1003,6 +1074,7 @@ cris_bmod_handler (SIM_CPU *current_cpu ATTRIBUTE_UNUSED,
                   UINT srcreg ATTRIBUTE_UNUSED,
                   USI dstreg ATTRIBUTE_UNUSED)
 {
                   UINT srcreg ATTRIBUTE_UNUSED,
                   USI dstreg ATTRIBUTE_UNUSED)
 {
+  SIM_DESC sd = CPU_STATE (current_cpu);
   abort ();
 }
 
   abort ();
 }
 
@@ -1012,6 +1084,7 @@ h_supr_set_handler (SIM_CPU *current_cpu ATTRIBUTE_UNUSED,
                    USI page ATTRIBUTE_UNUSED,
                    USI newval ATTRIBUTE_UNUSED)
 {
                    USI page ATTRIBUTE_UNUSED,
                    USI newval ATTRIBUTE_UNUSED)
 {
+  SIM_DESC sd = CPU_STATE (current_cpu);
   abort ();
 }
 
   abort ();
 }
 
@@ -1020,6 +1093,7 @@ h_supr_get_handler (SIM_CPU *current_cpu ATTRIBUTE_UNUSED,
                    UINT index ATTRIBUTE_UNUSED,
                    USI page ATTRIBUTE_UNUSED)
 {
                    UINT index ATTRIBUTE_UNUSED,
                    USI page ATTRIBUTE_UNUSED)
 {
+  SIM_DESC sd = CPU_STATE (current_cpu);
   abort ();
 }
 
   abort ();
 }
 
@@ -1176,6 +1250,7 @@ schedule (SIM_CPU *current_cpu, int next)
 static void
 reschedule (SIM_CPU *current_cpu)
 {
 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
   int i;
 
   /* Iterate over all thread slots, because after a few thread creations
@@ -1313,6 +1388,7 @@ deliver_signal (SIM_CPU *current_cpu, int sig, unsigned int pid)
 static void
 make_first_thread (SIM_CPU *current_cpu)
 {
 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
   current_cpu->thread_data
     = xcalloc (1,
               SIM_TARGET_MAX_THREADS
@@ -1328,6 +1404,31 @@ make_first_thread (SIM_CPU *current_cpu)
     abort ();
 }
 
     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
 /* Main function: the handler of the "break 13" syscall insn.  */
 
 USI
@@ -1349,7 +1450,16 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
   s.arg2 = arg2;
   s.arg3 = arg3;
 
   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)
     {
       if (CPU_CRIS_MISC_PROFILE (current_cpu)->flags
          & FLAG_CRIS_MISC_PROFILE_ALL)
@@ -1359,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.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;
 
 
   current_cpu_for_cb_callback = current_cpu;
 
@@ -1429,18 +1539,34 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
                  retval = current_cpu->last_open_flags & TARGET_O_ACCMODE;
                  break;
                }
                  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 */
              /* FALLTHROUGH */
-             /* Abort for all other cases.  */
            default:
            default:
-             sim_io_eprintf (sd, "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);
-             sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
-                              SIM_SIGILL);
+             /* 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;
              break;
            }
          break;
@@ -1448,16 +1574,23 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
        case TARGET_SYS_uname:
          {
            /* Fill in a few constants to appease glibc.  */
        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",
            {
              "Linux",
              "sim-target",
-             "2.4.5",
+             "2.6.27",
              TARGET_UTSNAME,
              TARGET_UTSNAME,
-             "cris",
+             "cris",           /* Overwritten below.  */
              "localdomain"
            };
 
              "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))
            if ((s.write_mem) (cb, &s, arg1, (const char *) sim_utsname,
                               sizeof (sim_utsname))
                != sizeof (sim_utsname))
@@ -1541,6 +1674,11 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
            USI fd = arg5;
            USI pgoff = arg6;
 
            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?  */
            /* 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?  */
@@ -1555,23 +1693,32 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
                     != (TARGET_PROT_READ
                         | TARGET_PROT_WRITE
                         | TARGET_PROT_EXEC))
                     != (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
                 && 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)
                    && 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)
                break;
              }
            else if (fd != (USI) -1)
@@ -1584,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;
 
                /* 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 ();
 
                  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
                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)
                                newlen);
 
                if (newaddr >= (USI) -8191)
@@ -1600,6 +1759,16 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
                    break;
                  }
 
                    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;
                /* Find the current position in the file.  */
                s.func = TARGET_SYS_lseek;
                s.arg1 = fd;
@@ -1609,6 +1778,17 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
                  abort ();
                pos = s.result;
 
                  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 ();
 
                if (s.result < 0)
                  abort ();
 
@@ -1621,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 (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
                  abort ();
 
                /* After reading, we need to go back to the previous
@@ -1639,46 +1821,66 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
              }
            else
              {
              }
            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 (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:
          {
              }
            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;
 
            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;
              }
 
                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;
          }
            retval = 0;
            break;
          }
@@ -1730,14 +1932,14 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
                || rusagep != 0
                || current_cpu->thread_data == NULL)
              {
                || 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;
              }
 
                break;
              }
 
@@ -1843,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)
                  {
                     && 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;
                  }
 
                current_cpu->sighandler[signum] = target_sa_handler;
@@ -1916,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,
 
                mapped_addr
                  = create_map (sd, &current_cpu->highest_mmapped_page,
-                               0, new_len);
+                               -1, new_len);
 
                if (mapped_addr > (USI) -8192)
                  {
 
                if (mapped_addr > (USI) -8192)
                  {
@@ -1972,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)
                || ((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)
              {
                    || (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;
              }
 
                break;
              }
 
@@ -2025,6 +2233,17 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
            break;
          }
 
            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)
            {
        case TARGET_SYS_gettimeofday:
          if (arg1 != 0)
            {
@@ -2061,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)))
              {
            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;
              }
 
            s.func = TARGET_SYS_lseek;
@@ -2090,6 +2310,55 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
            break;
          }
 
            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
        /* 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
@@ -2144,11 +2413,11 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
                && how != TARGET_SIG_SETMASK
                && how != TARGET_SIG_UNBLOCK)
              {
                && 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;
              }
 
                break;
              }
 
@@ -2219,17 +2488,19 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
                || (current_cpu->thread_data[threadno].cpu_context_atsignal
                    == NULL))
              {
                || (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
              }
 
            was_sigsuspended
@@ -2295,11 +2566,13 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
 
            if (setsize != 8)
              {
 
            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
              }
 
            /* Don't change the signal mask if we're already in
@@ -2384,8 +2657,8 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
            USI buf = arg1;
            USI size = arg2;
 
            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
              abort ();
 
            /* FIXME: When and if we support chdir, we need something
@@ -2406,13 +2679,63 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
            break;
          }
 
            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;
        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;
            char *lbuf_alloc = lbuf;
            int nchars = -1;
            int i;
@@ -2424,7 +2747,7 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
                o += strlen (simulator_sysroot);
              }
 
                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);
              {
                pbuf[i + o]
                  = sim_core_read_unaligned_1 (current_cpu, pc, 0, path + i);
@@ -2432,7 +2755,7 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
                  break;
              }
 
                  break;
              }
 
-           if (i + o == MAXPATHLEN)
+           if (i + o == SIM_PATHMAX)
              {
                retval = -cb_host_to_target_errno (cb, ENAMETOOLONG);
                break;
              {
                retval = -cb_host_to_target_errno (cb, ENAMETOOLONG);
                break;
@@ -2449,12 +2772,12 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
 
                if (argv0 == NULL || *argv0 == '.')
                  {
 
                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 == '/')
                    break;
                  }
                else if (*argv0 == '/')
@@ -2468,8 +2791,8 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
                  }
                else
                  {
                  }
                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)
                      {
                        if (strncmp (simulator_sysroot, lbuf,
                                     strlen (simulator_sysroot)) == 0)
@@ -2484,7 +2807,7 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
                  }
              }
            else
                  }
              }
            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.
 
            /* We trust that the readlink result returns a *relative*
               link, or one already adjusted for the file-path-prefix.
@@ -2687,19 +3010,19 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
                break;
              }
 
                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;
          }
 
            break;
          }
 
@@ -2772,11 +3095,13 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
                 | TARGET_CLONE_SIGHAND)
                || newsp == 0)
              {
                 | 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)
              }
 
            if (current_cpu->thread_data == NULL)
@@ -2837,13 +3162,25 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
          retval = -cb_host_to_target_errno (cb, ENOSYS);
          break;
 
          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:
        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);
        }
     }
 
        }
     }
 
@@ -2853,6 +3190,7 @@ cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
       current_cpu->last_open_fd = retval;
       current_cpu->last_open_flags = arg2;
     }
       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
   current_cpu->last_syscall = callnum;
 
   /* A system call is a rescheduling point.  For the time being, we don't
@@ -2927,13 +3265,15 @@ cris_pipe_nonempty (host_callback *cb ATTRIBUTE_UNUSED,
 
 static void
 cris_pipe_empty (host_callback *cb,
 
 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;
                 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];
   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++)
 
   /* We need to find the thread that waits for this pipe.  */
   for (i = 0; i < SIM_TARGET_MAX_THREADS; i++)
@@ -2941,6 +3281,7 @@ cris_pipe_empty (host_callback *cb,
        && cpu->thread_data[i].pipe_write_fd == writer)
       {
        int retval;
        && 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.  */
 
        /* Temporarily switch to this cpu context, so we can change the
           PC by ordinary calls.  */
 
@@ -2951,19 +3292,25 @@ cris_pipe_empty (host_callback *cb,
                cpu->thread_data[i].cpu_context,
                cpu->thread_cpu_data_size);
 
                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);
        (*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,
        sim_pc_set (cpu, sim_pc_get (cpu) + 2);
        memcpy (cpu->thread_data[i].cpu_context,
                &cpu->cpu_data_placeholder,
This page took 0.050453 seconds and 4 git commands to generate.