xref: /netbsd/external/gpl3/gdb/dist/sim/cris/traps.c (revision 1424dfb3)
166e63ce3Schristos /* CRIS exception, interrupt, and trap (EIT) support
2*1424dfb3Schristos    Copyright (C) 2004-2020 Free Software Foundation, Inc.
366e63ce3Schristos    Contributed by Axis Communications.
466e63ce3Schristos 
566e63ce3Schristos This file is part of the GNU simulators.
666e63ce3Schristos 
766e63ce3Schristos This program is free software; you can redistribute it and/or modify
866e63ce3Schristos it under the terms of the GNU General Public License as published by
966e63ce3Schristos the Free Software Foundation; either version 3 of the License, or
1066e63ce3Schristos (at your option) any later version.
1166e63ce3Schristos 
1266e63ce3Schristos This program is distributed in the hope that it will be useful,
1366e63ce3Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of
1466e63ce3Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1566e63ce3Schristos GNU General Public License for more details.
1666e63ce3Schristos 
1766e63ce3Schristos You should have received a copy of the GNU General Public License
1866e63ce3Schristos along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
1966e63ce3Schristos 
2066e63ce3Schristos #include "sim-main.h"
21ed6a76a9Schristos #include "sim-syscall.h"
2266e63ce3Schristos #include "sim-options.h"
2366e63ce3Schristos #include "bfd.h"
2466e63ce3Schristos /* FIXME: get rid of targ-vals.h usage everywhere else.  */
2566e63ce3Schristos 
2666e63ce3Schristos #include <stdarg.h>
2766e63ce3Schristos #ifdef HAVE_ERRNO_H
2866e63ce3Schristos #include <errno.h>
2966e63ce3Schristos #endif
3066e63ce3Schristos #ifdef HAVE_UNISTD_H
3166e63ce3Schristos #include <unistd.h>
3266e63ce3Schristos #endif
3366e63ce3Schristos #ifdef HAVE_FCNTL_H
3466e63ce3Schristos #include <fcntl.h>
3566e63ce3Schristos #endif
3666e63ce3Schristos #ifdef HAVE_SYS_PARAM_H
3766e63ce3Schristos #include <sys/param.h>
3866e63ce3Schristos #endif
3966e63ce3Schristos #ifdef HAVE_SYS_STAT_H
4066e63ce3Schristos #include <sys/stat.h>
4166e63ce3Schristos #endif
4266e63ce3Schristos /* For PATH_MAX, originally. */
4366e63ce3Schristos #ifdef HAVE_LIMITS_H
4466e63ce3Schristos #include <limits.h>
4566e63ce3Schristos #endif
4666e63ce3Schristos 
4766e63ce3Schristos /* From ld/sysdep.h.  */
4866e63ce3Schristos #ifdef PATH_MAX
4966e63ce3Schristos # define SIM_PATHMAX PATH_MAX
5066e63ce3Schristos #else
5166e63ce3Schristos # ifdef MAXPATHLEN
5266e63ce3Schristos #  define SIM_PATHMAX MAXPATHLEN
5366e63ce3Schristos # else
5466e63ce3Schristos #  define SIM_PATHMAX 1024
5566e63ce3Schristos # endif
5666e63ce3Schristos #endif
5766e63ce3Schristos 
5866e63ce3Schristos /* The verbatim values are from asm-cris/unistd.h.  */
5966e63ce3Schristos 
6066e63ce3Schristos #define TARGET_SYS_exit 1
6166e63ce3Schristos #define TARGET_SYS_read 3
6266e63ce3Schristos #define TARGET_SYS_write 4
6366e63ce3Schristos #define TARGET_SYS_open 5
6466e63ce3Schristos #define TARGET_SYS_close 6
6566e63ce3Schristos #define TARGET_SYS_unlink 10
6666e63ce3Schristos #define TARGET_SYS_time 13
6766e63ce3Schristos #define TARGET_SYS_lseek 19
6866e63ce3Schristos #define TARGET_SYS_getpid 20
6966e63ce3Schristos #define TARGET_SYS_access 33
7066e63ce3Schristos #define TARGET_SYS_kill 37
7166e63ce3Schristos #define TARGET_SYS_rename 38
7266e63ce3Schristos #define TARGET_SYS_pipe 42
7366e63ce3Schristos #define TARGET_SYS_brk 45
7466e63ce3Schristos #define TARGET_SYS_ioctl 54
7566e63ce3Schristos #define TARGET_SYS_fcntl 55
7666e63ce3Schristos #define TARGET_SYS_getppid 64
7766e63ce3Schristos #define TARGET_SYS_setrlimit 75
7866e63ce3Schristos #define TARGET_SYS_gettimeofday	 78
7966e63ce3Schristos #define TARGET_SYS_readlink 85
8066e63ce3Schristos #define TARGET_SYS_munmap 91
8166e63ce3Schristos #define TARGET_SYS_truncate 92
8266e63ce3Schristos #define TARGET_SYS_ftruncate 93
8366e63ce3Schristos #define TARGET_SYS_socketcall 102
8466e63ce3Schristos #define TARGET_SYS_stat 106
8566e63ce3Schristos #define TARGET_SYS_fstat 108
8666e63ce3Schristos #define TARGET_SYS_wait4 114
8766e63ce3Schristos #define TARGET_SYS_sigreturn 119
8866e63ce3Schristos #define TARGET_SYS_clone 120
8966e63ce3Schristos #define TARGET_SYS_uname 122
9066e63ce3Schristos #define TARGET_SYS_mprotect 125
9166e63ce3Schristos #define TARGET_SYS_llseek 140
9266e63ce3Schristos #define TARGET_SYS_writev 146
9366e63ce3Schristos #define TARGET_SYS__sysctl 149
9466e63ce3Schristos #define TARGET_SYS_sched_setparam 154
9566e63ce3Schristos #define TARGET_SYS_sched_getparam 155
9666e63ce3Schristos #define TARGET_SYS_sched_setscheduler 156
9766e63ce3Schristos #define TARGET_SYS_sched_getscheduler 157
9866e63ce3Schristos #define TARGET_SYS_sched_yield 158
9966e63ce3Schristos #define TARGET_SYS_sched_get_priority_max 159
10066e63ce3Schristos #define TARGET_SYS_sched_get_priority_min 160
10166e63ce3Schristos #define TARGET_SYS_mremap 163
10266e63ce3Schristos #define TARGET_SYS_poll 168
10366e63ce3Schristos #define TARGET_SYS_rt_sigaction 174
10466e63ce3Schristos #define TARGET_SYS_rt_sigprocmask 175
10566e63ce3Schristos #define TARGET_SYS_rt_sigsuspend 179
10666e63ce3Schristos #define TARGET_SYS_getcwd 183
10766e63ce3Schristos #define TARGET_SYS_ugetrlimit 191
10866e63ce3Schristos #define TARGET_SYS_mmap2 192
10966e63ce3Schristos #define TARGET_SYS_stat64 195
11066e63ce3Schristos #define TARGET_SYS_lstat64 196
11166e63ce3Schristos #define TARGET_SYS_fstat64 197
11266e63ce3Schristos #define TARGET_SYS_geteuid32 201
11366e63ce3Schristos #define TARGET_SYS_getuid32 199
11466e63ce3Schristos #define TARGET_SYS_getegid32 202
11566e63ce3Schristos #define TARGET_SYS_getgid32 200
11666e63ce3Schristos #define TARGET_SYS_fcntl64 221
11766e63ce3Schristos #define TARGET_SYS_set_thread_area 243
11866e63ce3Schristos #define TARGET_SYS_exit_group 252
11966e63ce3Schristos 
12066e63ce3Schristos #define TARGET_PROT_READ	0x1
12166e63ce3Schristos #define TARGET_PROT_WRITE	0x2
12266e63ce3Schristos #define TARGET_PROT_EXEC	0x4
12366e63ce3Schristos #define TARGET_PROT_NONE	0x0
12466e63ce3Schristos 
12566e63ce3Schristos #define TARGET_MAP_SHARED	0x01
12666e63ce3Schristos #define TARGET_MAP_PRIVATE	0x02
12766e63ce3Schristos #define TARGET_MAP_TYPE		0x0f
12866e63ce3Schristos #define TARGET_MAP_FIXED	0x10
12966e63ce3Schristos #define TARGET_MAP_ANONYMOUS	0x20
13066e63ce3Schristos #define TARGET_MAP_DENYWRITE	0x800
13166e63ce3Schristos 
13266e63ce3Schristos #define TARGET_CTL_KERN		1
13366e63ce3Schristos #define TARGET_CTL_VM		2
13466e63ce3Schristos #define TARGET_CTL_NET		3
13566e63ce3Schristos #define TARGET_CTL_PROC		4
13666e63ce3Schristos #define TARGET_CTL_FS		5
13766e63ce3Schristos #define TARGET_CTL_DEBUG	6
13866e63ce3Schristos #define TARGET_CTL_DEV		7
13966e63ce3Schristos #define TARGET_CTL_BUS		8
14066e63ce3Schristos #define TARGET_CTL_ABI		9
14166e63ce3Schristos 
14266e63ce3Schristos #define TARGET_CTL_KERN_VERSION	4
14366e63ce3Schristos 
14466e63ce3Schristos /* linux/mman.h */
14566e63ce3Schristos #define TARGET_MREMAP_MAYMOVE  1
14666e63ce3Schristos #define TARGET_MREMAP_FIXED    2
14766e63ce3Schristos 
14866e63ce3Schristos #define TARGET_TCGETS 0x5401
14966e63ce3Schristos 
15066e63ce3Schristos #define TARGET_UTSNAME "#7 Thu Jan 1 00:00:00 MET 2009"
15166e63ce3Schristos 
15266e63ce3Schristos /* Seconds since 1970-01-01 to the above date + 10 minutes;
15366e63ce3Schristos    'date -d "Thu Jan 1 00:00:10 MET 2009" +%s'.  */
15466e63ce3Schristos #define TARGET_EPOCH 1230764410
15566e63ce3Schristos 
15666e63ce3Schristos /* Milliseconds since start of run.  We use the number of syscalls to
15766e63ce3Schristos    avoid introducing noise in the execution time.  */
15866e63ce3Schristos #define TARGET_TIME_MS(cpu) ((cpu)->syscalls)
15966e63ce3Schristos 
16066e63ce3Schristos /* Seconds as in time(2).  */
16166e63ce3Schristos #define TARGET_TIME(cpu) (TARGET_EPOCH + TARGET_TIME_MS (cpu) / 1000)
16266e63ce3Schristos 
16366e63ce3Schristos #define TARGET_SCHED_OTHER 0
16466e63ce3Schristos 
16566e63ce3Schristos #define TARGET_RLIMIT_STACK 3
16666e63ce3Schristos #define TARGET_RLIMIT_NOFILE 7
16766e63ce3Schristos 
16866e63ce3Schristos #define SIM_TARGET_MAX_THREADS 64
16966e63ce3Schristos #define SIM_MAX_ALLOC_CHUNK (512*1024*1024)
17066e63ce3Schristos 
17166e63ce3Schristos /* From linux/sched.h.  */
17266e63ce3Schristos #define TARGET_CSIGNAL 0x000000ff
17366e63ce3Schristos #define TARGET_CLONE_VM	0x00000100
17466e63ce3Schristos #define TARGET_CLONE_FS	0x00000200
17566e63ce3Schristos #define TARGET_CLONE_FILES 0x00000400
17666e63ce3Schristos #define TARGET_CLONE_SIGHAND 0x00000800
17766e63ce3Schristos #define TARGET_CLONE_PID 0x00001000
17866e63ce3Schristos #define TARGET_CLONE_PTRACE 0x00002000
17966e63ce3Schristos #define TARGET_CLONE_VFORK 0x00004000
18066e63ce3Schristos #define TARGET_CLONE_PARENT 0x00008000
18166e63ce3Schristos #define TARGET_CLONE_THREAD 0x00010000
18266e63ce3Schristos #define TARGET_CLONE_SIGNAL (TARGET_CLONE_SIGHAND | TARGET_CLONE_THREAD)
18366e63ce3Schristos 
18466e63ce3Schristos /* From asm-cris/poll.h.  */
18566e63ce3Schristos #define TARGET_POLLIN 1
18666e63ce3Schristos 
18766e63ce3Schristos /* From asm-cris/signal.h.  */
18866e63ce3Schristos #define TARGET_SIG_BLOCK 0
18966e63ce3Schristos #define TARGET_SIG_UNBLOCK 1
19066e63ce3Schristos #define TARGET_SIG_SETMASK 2
19166e63ce3Schristos 
19266e63ce3Schristos #define TARGET_SIG_DFL 0
19366e63ce3Schristos #define TARGET_SIG_IGN 1
19466e63ce3Schristos #define TARGET_SIG_ERR ((USI)-1)
19566e63ce3Schristos 
19666e63ce3Schristos #define TARGET_SIGHUP 1
19766e63ce3Schristos #define TARGET_SIGINT 2
19866e63ce3Schristos #define TARGET_SIGQUIT 3
19966e63ce3Schristos #define TARGET_SIGILL 4
20066e63ce3Schristos #define TARGET_SIGTRAP 5
20166e63ce3Schristos #define TARGET_SIGABRT 6
20266e63ce3Schristos #define TARGET_SIGIOT 6
20366e63ce3Schristos #define TARGET_SIGBUS 7
20466e63ce3Schristos #define TARGET_SIGFPE 8
20566e63ce3Schristos #define TARGET_SIGKILL 9
20666e63ce3Schristos #define TARGET_SIGUSR1 10
20766e63ce3Schristos #define TARGET_SIGSEGV 11
20866e63ce3Schristos #define TARGET_SIGUSR2 12
20966e63ce3Schristos #define TARGET_SIGPIPE 13
21066e63ce3Schristos #define TARGET_SIGALRM 14
21166e63ce3Schristos #define TARGET_SIGTERM 15
21266e63ce3Schristos #define TARGET_SIGSTKFLT 16
21366e63ce3Schristos #define TARGET_SIGCHLD 17
21466e63ce3Schristos #define TARGET_SIGCONT 18
21566e63ce3Schristos #define TARGET_SIGSTOP 19
21666e63ce3Schristos #define TARGET_SIGTSTP 20
21766e63ce3Schristos #define TARGET_SIGTTIN 21
21866e63ce3Schristos #define TARGET_SIGTTOU 22
21966e63ce3Schristos #define TARGET_SIGURG 23
22066e63ce3Schristos #define TARGET_SIGXCPU 24
22166e63ce3Schristos #define TARGET_SIGXFSZ 25
22266e63ce3Schristos #define TARGET_SIGVTALRM 26
22366e63ce3Schristos #define TARGET_SIGPROF 27
22466e63ce3Schristos #define TARGET_SIGWINCH 28
22566e63ce3Schristos #define TARGET_SIGIO 29
22666e63ce3Schristos #define TARGET_SIGPOLL SIGIO
22766e63ce3Schristos /* Actually commented out in the kernel header.  */
22866e63ce3Schristos #define TARGET_SIGLOST 29
22966e63ce3Schristos #define TARGET_SIGPWR 30
23066e63ce3Schristos #define TARGET_SIGSYS 31
23166e63ce3Schristos 
23266e63ce3Schristos /* From include/asm-cris/signal.h.  */
23366e63ce3Schristos #define TARGET_SA_NOCLDSTOP 0x00000001
23466e63ce3Schristos #define TARGET_SA_NOCLDWAIT 0x00000002 /* not supported yet */
23566e63ce3Schristos #define TARGET_SA_SIGINFO 0x00000004
23666e63ce3Schristos #define TARGET_SA_ONSTACK 0x08000000
23766e63ce3Schristos #define TARGET_SA_RESTART 0x10000000
23866e63ce3Schristos #define TARGET_SA_NODEFER 0x40000000
23966e63ce3Schristos #define TARGET_SA_RESETHAND 0x80000000
24066e63ce3Schristos #define TARGET_SA_INTERRUPT 0x20000000 /* dummy -- ignored */
24166e63ce3Schristos #define TARGET_SA_RESTORER 0x04000000
24266e63ce3Schristos 
24366e63ce3Schristos /* From linux/wait.h.  */
24466e63ce3Schristos #define TARGET_WNOHANG 1
24566e63ce3Schristos #define TARGET_WUNTRACED 2
24666e63ce3Schristos #define TARGET___WNOTHREAD 0x20000000
24766e63ce3Schristos #define TARGET___WALL 0x40000000
24866e63ce3Schristos #define TARGET___WCLONE 0x80000000
24966e63ce3Schristos 
25066e63ce3Schristos /* From linux/limits.h. */
25166e63ce3Schristos #define TARGET_PIPE_BUF 4096
25266e63ce3Schristos 
25366e63ce3Schristos /* From unistd.h.  */
25466e63ce3Schristos #define	TARGET_R_OK 4
25566e63ce3Schristos #define	TARGET_W_OK 2
25666e63ce3Schristos #define	TARGET_X_OK 1
25766e63ce3Schristos #define	TARGET_F_OK 0
25866e63ce3Schristos 
25966e63ce3Schristos static const char stat_map[] =
26066e63ce3Schristos "st_dev,2:space,10:space,4:st_mode,4:st_nlink,4:st_uid,4"
26166e63ce3Schristos ":st_gid,4:st_rdev,2:space,10:st_size,8:st_blksize,4:st_blocks,4"
26266e63ce3Schristos ":space,4:st_atime,4:space,4:st_mtime,4:space,4:st_ctime,4:space,4"
26366e63ce3Schristos ":st_ino,8";
26466e63ce3Schristos 
26566e63ce3Schristos static const CB_TARGET_DEFS_MAP syscall_map[] =
26666e63ce3Schristos {
267ed6a76a9Schristos   { "open", CB_SYS_open, TARGET_SYS_open },
268ed6a76a9Schristos   { "close", CB_SYS_close, TARGET_SYS_close },
269ed6a76a9Schristos   { "read", CB_SYS_read, TARGET_SYS_read },
270ed6a76a9Schristos   { "write", CB_SYS_write, TARGET_SYS_write },
271ed6a76a9Schristos   { "lseek", CB_SYS_lseek, TARGET_SYS_lseek },
272ed6a76a9Schristos   { "unlink", CB_SYS_unlink, TARGET_SYS_unlink },
273ed6a76a9Schristos   { "getpid", CB_SYS_getpid, TARGET_SYS_getpid },
274ed6a76a9Schristos   { "fstat", CB_SYS_fstat, TARGET_SYS_fstat64 },
275ed6a76a9Schristos   { "lstat", CB_SYS_lstat, TARGET_SYS_lstat64 },
276ed6a76a9Schristos   { "stat", CB_SYS_stat, TARGET_SYS_stat64 },
277ed6a76a9Schristos   { "pipe", CB_SYS_pipe, TARGET_SYS_pipe },
278ed6a76a9Schristos   { "rename", CB_SYS_rename, TARGET_SYS_rename },
279ed6a76a9Schristos   { "truncate", CB_SYS_truncate, TARGET_SYS_truncate },
280ed6a76a9Schristos   { "ftruncate", CB_SYS_ftruncate, TARGET_SYS_ftruncate },
281ed6a76a9Schristos   { 0, -1, -1 }
28266e63ce3Schristos };
28366e63ce3Schristos 
28466e63ce3Schristos /* An older, 32-bit-only stat mapping.  */
28566e63ce3Schristos static const char stat32_map[] =
28666e63ce3Schristos "st_dev,2:space,2:st_ino,4:st_mode,2:st_nlink,2:st_uid,2"
28766e63ce3Schristos ":st_gid,2:st_rdev,2:space,2:st_size,4:st_blksize,4:st_blocks,4"
28866e63ce3Schristos ":st_atime,4:space,4:st_mtime,4:space,4:st_ctime,4:space,12";
28966e63ce3Schristos 
29066e63ce3Schristos /* Map for calls using the 32-bit struct stat.  Primarily used by the
29166e63ce3Schristos    newlib Linux mapping.  */
29266e63ce3Schristos static const CB_TARGET_DEFS_MAP syscall_stat32_map[] =
29366e63ce3Schristos {
294ed6a76a9Schristos   { "fstat", CB_SYS_fstat, TARGET_SYS_fstat },
295ed6a76a9Schristos   { "stat", CB_SYS_stat, TARGET_SYS_stat },
296ed6a76a9Schristos   { 0, -1, -1 }
29766e63ce3Schristos };
29866e63ce3Schristos 
29966e63ce3Schristos /* Giving the true value for the running sim process will lead to
30066e63ce3Schristos    non-time-invariant behavior.  */
30166e63ce3Schristos #define TARGET_PID 42
30266e63ce3Schristos 
30366e63ce3Schristos /* Unfortunately, we don't get this from cris.cpu at the moment, and if
30466e63ce3Schristos    we did, we'd still don't get a register number with the "16" offset.  */
30566e63ce3Schristos #define TARGET_SRP_REGNUM (16+11)
30666e63ce3Schristos 
30766e63ce3Schristos /* Extracted by applying
30866e63ce3Schristos    awk '/^#define/ { printf "#ifdef %s\n  { %s, %s },\n#endif\n", $2, $2, $3;}'
30966e63ce3Schristos    on .../include/asm/errno.h in a GNU/Linux/CRIS installation and
31066e63ce3Schristos    adjusting the synonyms.  */
31166e63ce3Schristos 
31266e63ce3Schristos static const CB_TARGET_DEFS_MAP errno_map[] =
31366e63ce3Schristos {
31466e63ce3Schristos #ifdef EPERM
315ed6a76a9Schristos   { "EPERM", EPERM, 1 },
31666e63ce3Schristos #endif
31766e63ce3Schristos #ifdef ENOENT
318ed6a76a9Schristos   { "ENOENT", ENOENT, 2 },
31966e63ce3Schristos #endif
32066e63ce3Schristos #ifdef ESRCH
321ed6a76a9Schristos   { "ESRCH", ESRCH, 3 },
32266e63ce3Schristos #endif
32366e63ce3Schristos #ifdef EINTR
324ed6a76a9Schristos   { "EINTR", EINTR, 4 },
32566e63ce3Schristos #endif
32666e63ce3Schristos #ifdef EIO
327ed6a76a9Schristos   { "EIO", EIO, 5 },
32866e63ce3Schristos #endif
32966e63ce3Schristos #ifdef ENXIO
330ed6a76a9Schristos   { "ENXIO", ENXIO, 6 },
33166e63ce3Schristos #endif
33266e63ce3Schristos #ifdef E2BIG
333ed6a76a9Schristos   { "E2BIG", E2BIG, 7 },
33466e63ce3Schristos #endif
33566e63ce3Schristos #ifdef ENOEXEC
336ed6a76a9Schristos   { "ENOEXEC", ENOEXEC, 8 },
33766e63ce3Schristos #endif
33866e63ce3Schristos #ifdef EBADF
339ed6a76a9Schristos   { "EBADF", EBADF, 9 },
34066e63ce3Schristos #endif
34166e63ce3Schristos #ifdef ECHILD
342ed6a76a9Schristos   { "ECHILD", ECHILD, 10 },
34366e63ce3Schristos #endif
34466e63ce3Schristos #ifdef EAGAIN
345ed6a76a9Schristos   { "EAGAIN", EAGAIN, 11 },
34666e63ce3Schristos #endif
34766e63ce3Schristos #ifdef ENOMEM
348ed6a76a9Schristos   { "ENOMEM", ENOMEM, 12 },
34966e63ce3Schristos #endif
35066e63ce3Schristos #ifdef EACCES
351ed6a76a9Schristos   { "EACCES", EACCES, 13 },
35266e63ce3Schristos #endif
35366e63ce3Schristos #ifdef EFAULT
354ed6a76a9Schristos   { "EFAULT", EFAULT, 14 },
35566e63ce3Schristos #endif
35666e63ce3Schristos #ifdef ENOTBLK
357ed6a76a9Schristos   { "ENOTBLK", ENOTBLK, 15 },
35866e63ce3Schristos #endif
35966e63ce3Schristos #ifdef EBUSY
360ed6a76a9Schristos   { "EBUSY", EBUSY, 16 },
36166e63ce3Schristos #endif
36266e63ce3Schristos #ifdef EEXIST
363ed6a76a9Schristos   { "EEXIST", EEXIST, 17 },
36466e63ce3Schristos #endif
36566e63ce3Schristos #ifdef EXDEV
366ed6a76a9Schristos   { "EXDEV", EXDEV, 18 },
36766e63ce3Schristos #endif
36866e63ce3Schristos #ifdef ENODEV
369ed6a76a9Schristos   { "ENODEV", ENODEV, 19 },
37066e63ce3Schristos #endif
37166e63ce3Schristos #ifdef ENOTDIR
372ed6a76a9Schristos   { "ENOTDIR", ENOTDIR, 20 },
37366e63ce3Schristos #endif
37466e63ce3Schristos #ifdef EISDIR
375ed6a76a9Schristos   { "EISDIR", EISDIR, 21 },
37666e63ce3Schristos #endif
37766e63ce3Schristos #ifdef EINVAL
378ed6a76a9Schristos   { "EINVAL", EINVAL, 22 },
37966e63ce3Schristos #endif
38066e63ce3Schristos #ifdef ENFILE
381ed6a76a9Schristos   { "ENFILE", ENFILE, 23 },
38266e63ce3Schristos #endif
38366e63ce3Schristos #ifdef EMFILE
384ed6a76a9Schristos   { "EMFILE", EMFILE, 24 },
38566e63ce3Schristos #endif
38666e63ce3Schristos #ifdef ENOTTY
387ed6a76a9Schristos   { "ENOTTY", ENOTTY, 25 },
38866e63ce3Schristos #endif
38966e63ce3Schristos #ifdef ETXTBSY
390ed6a76a9Schristos   { "ETXTBSY", ETXTBSY, 26 },
39166e63ce3Schristos #endif
39266e63ce3Schristos #ifdef EFBIG
393ed6a76a9Schristos   { "EFBIG", EFBIG, 27 },
39466e63ce3Schristos #endif
39566e63ce3Schristos #ifdef ENOSPC
396ed6a76a9Schristos   { "ENOSPC", ENOSPC, 28 },
39766e63ce3Schristos #endif
39866e63ce3Schristos #ifdef ESPIPE
399ed6a76a9Schristos   { "ESPIPE", ESPIPE, 29 },
40066e63ce3Schristos #endif
40166e63ce3Schristos #ifdef EROFS
402ed6a76a9Schristos   { "EROFS", EROFS, 30 },
40366e63ce3Schristos #endif
40466e63ce3Schristos #ifdef EMLINK
405ed6a76a9Schristos   { "EMLINK", EMLINK, 31 },
40666e63ce3Schristos #endif
40766e63ce3Schristos #ifdef EPIPE
408ed6a76a9Schristos   { "EPIPE", EPIPE, 32 },
40966e63ce3Schristos #endif
41066e63ce3Schristos #ifdef EDOM
411ed6a76a9Schristos   { "EDOM", EDOM, 33 },
41266e63ce3Schristos #endif
41366e63ce3Schristos #ifdef ERANGE
414ed6a76a9Schristos   { "ERANGE", ERANGE, 34 },
41566e63ce3Schristos #endif
41666e63ce3Schristos #ifdef EDEADLK
417ed6a76a9Schristos   { "EDEADLK", EDEADLK, 35 },
41866e63ce3Schristos #endif
41966e63ce3Schristos #ifdef ENAMETOOLONG
420ed6a76a9Schristos   { "ENAMETOOLONG", ENAMETOOLONG, 36 },
42166e63ce3Schristos #endif
42266e63ce3Schristos #ifdef ENOLCK
423ed6a76a9Schristos   { "ENOLCK", ENOLCK, 37 },
42466e63ce3Schristos #endif
42566e63ce3Schristos #ifdef ENOSYS
426ed6a76a9Schristos   { "ENOSYS", ENOSYS, 38 },
42766e63ce3Schristos #endif
42866e63ce3Schristos #ifdef ENOTEMPTY
429ed6a76a9Schristos   { "ENOTEMPTY", ENOTEMPTY, 39 },
43066e63ce3Schristos #endif
43166e63ce3Schristos #ifdef ELOOP
432ed6a76a9Schristos   { "ELOOP", ELOOP, 40 },
43366e63ce3Schristos #endif
43466e63ce3Schristos #ifdef EWOULDBLOCK
435ed6a76a9Schristos   { "EWOULDBLOCK", EWOULDBLOCK, 11 },
43666e63ce3Schristos #endif
43766e63ce3Schristos #ifdef ENOMSG
438ed6a76a9Schristos   { "ENOMSG", ENOMSG, 42 },
43966e63ce3Schristos #endif
44066e63ce3Schristos #ifdef EIDRM
441ed6a76a9Schristos   { "EIDRM", EIDRM, 43 },
44266e63ce3Schristos #endif
44366e63ce3Schristos #ifdef ECHRNG
444ed6a76a9Schristos   { "ECHRNG", ECHRNG, 44 },
44566e63ce3Schristos #endif
44666e63ce3Schristos #ifdef EL2NSYNC
447ed6a76a9Schristos   { "EL2NSYNC", EL2NSYNC, 45 },
44866e63ce3Schristos #endif
44966e63ce3Schristos #ifdef EL3HLT
450ed6a76a9Schristos   { "EL3HLT", EL3HLT, 46 },
45166e63ce3Schristos #endif
45266e63ce3Schristos #ifdef EL3RST
453ed6a76a9Schristos   { "EL3RST", EL3RST, 47 },
45466e63ce3Schristos #endif
45566e63ce3Schristos #ifdef ELNRNG
456ed6a76a9Schristos   { "ELNRNG", ELNRNG, 48 },
45766e63ce3Schristos #endif
45866e63ce3Schristos #ifdef EUNATCH
459ed6a76a9Schristos   { "EUNATCH", EUNATCH, 49 },
46066e63ce3Schristos #endif
46166e63ce3Schristos #ifdef ENOCSI
462ed6a76a9Schristos   { "ENOCSI", ENOCSI, 50 },
46366e63ce3Schristos #endif
46466e63ce3Schristos #ifdef EL2HLT
465ed6a76a9Schristos   { "EL2HLT", EL2HLT, 51 },
46666e63ce3Schristos #endif
46766e63ce3Schristos #ifdef EBADE
468ed6a76a9Schristos   { "EBADE", EBADE, 52 },
46966e63ce3Schristos #endif
47066e63ce3Schristos #ifdef EBADR
471ed6a76a9Schristos   { "EBADR", EBADR, 53 },
47266e63ce3Schristos #endif
47366e63ce3Schristos #ifdef EXFULL
474ed6a76a9Schristos   { "EXFULL", EXFULL, 54 },
47566e63ce3Schristos #endif
47666e63ce3Schristos #ifdef ENOANO
477ed6a76a9Schristos   { "ENOANO", ENOANO, 55 },
47866e63ce3Schristos #endif
47966e63ce3Schristos #ifdef EBADRQC
480ed6a76a9Schristos   { "EBADRQC", EBADRQC, 56 },
48166e63ce3Schristos #endif
48266e63ce3Schristos #ifdef EBADSLT
483ed6a76a9Schristos   { "EBADSLT", EBADSLT, 57 },
48466e63ce3Schristos #endif
48566e63ce3Schristos #ifdef EDEADLOCK
486ed6a76a9Schristos   { "EDEADLOCK", EDEADLOCK, 35 },
48766e63ce3Schristos #endif
48866e63ce3Schristos #ifdef EBFONT
489ed6a76a9Schristos   { "EBFONT", EBFONT, 59 },
49066e63ce3Schristos #endif
49166e63ce3Schristos #ifdef ENOSTR
492ed6a76a9Schristos   { "ENOSTR", ENOSTR, 60 },
49366e63ce3Schristos #endif
49466e63ce3Schristos #ifdef ENODATA
495ed6a76a9Schristos   { "ENODATA", ENODATA, 61 },
49666e63ce3Schristos #endif
49766e63ce3Schristos #ifdef ETIME
498ed6a76a9Schristos   { "ETIME", ETIME, 62 },
49966e63ce3Schristos #endif
50066e63ce3Schristos #ifdef ENOSR
501ed6a76a9Schristos   { "ENOSR", ENOSR, 63 },
50266e63ce3Schristos #endif
50366e63ce3Schristos #ifdef ENONET
504ed6a76a9Schristos   { "ENONET", ENONET, 64 },
50566e63ce3Schristos #endif
50666e63ce3Schristos #ifdef ENOPKG
507ed6a76a9Schristos   { "ENOPKG", ENOPKG, 65 },
50866e63ce3Schristos #endif
50966e63ce3Schristos #ifdef EREMOTE
510ed6a76a9Schristos   { "EREMOTE", EREMOTE, 66 },
51166e63ce3Schristos #endif
51266e63ce3Schristos #ifdef ENOLINK
513ed6a76a9Schristos   { "ENOLINK", ENOLINK, 67 },
51466e63ce3Schristos #endif
51566e63ce3Schristos #ifdef EADV
516ed6a76a9Schristos   { "EADV", EADV, 68 },
51766e63ce3Schristos #endif
51866e63ce3Schristos #ifdef ESRMNT
519ed6a76a9Schristos   { "ESRMNT", ESRMNT, 69 },
52066e63ce3Schristos #endif
52166e63ce3Schristos #ifdef ECOMM
522ed6a76a9Schristos   { "ECOMM", ECOMM, 70 },
52366e63ce3Schristos #endif
52466e63ce3Schristos #ifdef EPROTO
525ed6a76a9Schristos   { "EPROTO", EPROTO, 71 },
52666e63ce3Schristos #endif
52766e63ce3Schristos #ifdef EMULTIHOP
528ed6a76a9Schristos   { "EMULTIHOP", EMULTIHOP, 72 },
52966e63ce3Schristos #endif
53066e63ce3Schristos #ifdef EDOTDOT
531ed6a76a9Schristos   { "EDOTDOT", EDOTDOT, 73 },
53266e63ce3Schristos #endif
53366e63ce3Schristos #ifdef EBADMSG
534ed6a76a9Schristos   { "EBADMSG", EBADMSG, 74 },
53566e63ce3Schristos #endif
53666e63ce3Schristos #ifdef EOVERFLOW
537ed6a76a9Schristos   { "EOVERFLOW", EOVERFLOW, 75 },
53866e63ce3Schristos #endif
53966e63ce3Schristos #ifdef ENOTUNIQ
540ed6a76a9Schristos   { "ENOTUNIQ", ENOTUNIQ, 76 },
54166e63ce3Schristos #endif
54266e63ce3Schristos #ifdef EBADFD
543ed6a76a9Schristos   { "EBADFD", EBADFD, 77 },
54466e63ce3Schristos #endif
54566e63ce3Schristos #ifdef EREMCHG
546ed6a76a9Schristos   { "EREMCHG", EREMCHG, 78 },
54766e63ce3Schristos #endif
54866e63ce3Schristos #ifdef ELIBACC
549ed6a76a9Schristos   { "ELIBACC", ELIBACC, 79 },
55066e63ce3Schristos #endif
55166e63ce3Schristos #ifdef ELIBBAD
552ed6a76a9Schristos   { "ELIBBAD", ELIBBAD, 80 },
55366e63ce3Schristos #endif
55466e63ce3Schristos #ifdef ELIBSCN
555ed6a76a9Schristos   { "ELIBSCN", ELIBSCN, 81 },
55666e63ce3Schristos #endif
55766e63ce3Schristos #ifdef ELIBMAX
558ed6a76a9Schristos   { "ELIBMAX", ELIBMAX, 82 },
55966e63ce3Schristos #endif
56066e63ce3Schristos #ifdef ELIBEXEC
561ed6a76a9Schristos   { "ELIBEXEC", ELIBEXEC, 83 },
56266e63ce3Schristos #endif
56366e63ce3Schristos #ifdef EILSEQ
564ed6a76a9Schristos   { "EILSEQ", EILSEQ, 84 },
56566e63ce3Schristos #endif
56666e63ce3Schristos #ifdef ERESTART
567ed6a76a9Schristos   { "ERESTART", ERESTART, 85 },
56866e63ce3Schristos #endif
56966e63ce3Schristos #ifdef ESTRPIPE
570ed6a76a9Schristos   { "ESTRPIPE", ESTRPIPE, 86 },
57166e63ce3Schristos #endif
57266e63ce3Schristos #ifdef EUSERS
573ed6a76a9Schristos   { "EUSERS", EUSERS, 87 },
57466e63ce3Schristos #endif
57566e63ce3Schristos #ifdef ENOTSOCK
576ed6a76a9Schristos   { "ENOTSOCK", ENOTSOCK, 88 },
57766e63ce3Schristos #endif
57866e63ce3Schristos #ifdef EDESTADDRREQ
579ed6a76a9Schristos   { "EDESTADDRREQ", EDESTADDRREQ, 89 },
58066e63ce3Schristos #endif
58166e63ce3Schristos #ifdef EMSGSIZE
582ed6a76a9Schristos   { "EMSGSIZE", EMSGSIZE, 90 },
58366e63ce3Schristos #endif
58466e63ce3Schristos #ifdef EPROTOTYPE
585ed6a76a9Schristos   { "EPROTOTYPE", EPROTOTYPE, 91 },
58666e63ce3Schristos #endif
58766e63ce3Schristos #ifdef ENOPROTOOPT
588ed6a76a9Schristos   { "ENOPROTOOPT", ENOPROTOOPT, 92 },
58966e63ce3Schristos #endif
59066e63ce3Schristos #ifdef EPROTONOSUPPORT
591ed6a76a9Schristos   { "EPROTONOSUPPORT", EPROTONOSUPPORT, 93 },
59266e63ce3Schristos #endif
59366e63ce3Schristos #ifdef ESOCKTNOSUPPORT
594ed6a76a9Schristos   { "ESOCKTNOSUPPORT", ESOCKTNOSUPPORT, 94 },
59566e63ce3Schristos #endif
59666e63ce3Schristos #ifdef EOPNOTSUPP
597ed6a76a9Schristos   { "EOPNOTSUPP", EOPNOTSUPP, 95 },
59866e63ce3Schristos #endif
59966e63ce3Schristos #ifdef EPFNOSUPPORT
600ed6a76a9Schristos   { "EPFNOSUPPORT", EPFNOSUPPORT, 96 },
60166e63ce3Schristos #endif
60266e63ce3Schristos #ifdef EAFNOSUPPORT
603ed6a76a9Schristos   { "EAFNOSUPPORT", EAFNOSUPPORT, 97 },
60466e63ce3Schristos #endif
60566e63ce3Schristos #ifdef EADDRINUSE
606ed6a76a9Schristos   { "EADDRINUSE", EADDRINUSE, 98 },
60766e63ce3Schristos #endif
60866e63ce3Schristos #ifdef EADDRNOTAVAIL
609ed6a76a9Schristos   { "EADDRNOTAVAIL", EADDRNOTAVAIL, 99 },
61066e63ce3Schristos #endif
61166e63ce3Schristos #ifdef ENETDOWN
612ed6a76a9Schristos   { "ENETDOWN", ENETDOWN, 100 },
61366e63ce3Schristos #endif
61466e63ce3Schristos #ifdef ENETUNREACH
615ed6a76a9Schristos   { "ENETUNREACH", ENETUNREACH, 101 },
61666e63ce3Schristos #endif
61766e63ce3Schristos #ifdef ENETRESET
618ed6a76a9Schristos   { "ENETRESET", ENETRESET, 102 },
61966e63ce3Schristos #endif
62066e63ce3Schristos #ifdef ECONNABORTED
621ed6a76a9Schristos   { "ECONNABORTED", ECONNABORTED, 103 },
62266e63ce3Schristos #endif
62366e63ce3Schristos #ifdef ECONNRESET
624ed6a76a9Schristos   { "ECONNRESET", ECONNRESET, 104 },
62566e63ce3Schristos #endif
62666e63ce3Schristos #ifdef ENOBUFS
627ed6a76a9Schristos   { "ENOBUFS", ENOBUFS, 105 },
62866e63ce3Schristos #endif
62966e63ce3Schristos #ifdef EISCONN
630ed6a76a9Schristos   { "EISCONN", EISCONN, 106 },
63166e63ce3Schristos #endif
63266e63ce3Schristos #ifdef ENOTCONN
633ed6a76a9Schristos   { "ENOTCONN", ENOTCONN, 107 },
63466e63ce3Schristos #endif
63566e63ce3Schristos #ifdef ESHUTDOWN
636ed6a76a9Schristos   { "ESHUTDOWN", ESHUTDOWN, 108 },
63766e63ce3Schristos #endif
63866e63ce3Schristos #ifdef ETOOMANYREFS
639ed6a76a9Schristos   { "ETOOMANYREFS", ETOOMANYREFS, 109 },
64066e63ce3Schristos #endif
64166e63ce3Schristos #ifdef ETIMEDOUT
642ed6a76a9Schristos   { "ETIMEDOUT", ETIMEDOUT, 110 },
64366e63ce3Schristos #endif
64466e63ce3Schristos #ifdef ECONNREFUSED
645ed6a76a9Schristos   { "ECONNREFUSED", ECONNREFUSED, 111 },
64666e63ce3Schristos #endif
64766e63ce3Schristos #ifdef EHOSTDOWN
648ed6a76a9Schristos   { "EHOSTDOWN", EHOSTDOWN, 112 },
64966e63ce3Schristos #endif
65066e63ce3Schristos #ifdef EHOSTUNREACH
651ed6a76a9Schristos   { "EHOSTUNREACH", EHOSTUNREACH, 113 },
65266e63ce3Schristos #endif
65366e63ce3Schristos #ifdef EALREADY
654ed6a76a9Schristos   { "EALREADY", EALREADY, 114 },
65566e63ce3Schristos #endif
65666e63ce3Schristos #ifdef EINPROGRESS
657ed6a76a9Schristos   { "EINPROGRESS", EINPROGRESS, 115 },
65866e63ce3Schristos #endif
65966e63ce3Schristos #ifdef ESTALE
660ed6a76a9Schristos   { "ESTALE", ESTALE, 116 },
66166e63ce3Schristos #endif
66266e63ce3Schristos #ifdef EUCLEAN
663ed6a76a9Schristos   { "EUCLEAN", EUCLEAN, 117 },
66466e63ce3Schristos #endif
66566e63ce3Schristos #ifdef ENOTNAM
666ed6a76a9Schristos   { "ENOTNAM", ENOTNAM, 118 },
66766e63ce3Schristos #endif
66866e63ce3Schristos #ifdef ENAVAIL
669ed6a76a9Schristos   { "ENAVAIL", ENAVAIL, 119 },
67066e63ce3Schristos #endif
67166e63ce3Schristos #ifdef EISNAM
672ed6a76a9Schristos   { "EISNAM", EISNAM, 120 },
67366e63ce3Schristos #endif
67466e63ce3Schristos #ifdef EREMOTEIO
675ed6a76a9Schristos   { "EREMOTEIO", EREMOTEIO, 121 },
67666e63ce3Schristos #endif
67766e63ce3Schristos #ifdef EDQUOT
678ed6a76a9Schristos   { "EDQUOT", EDQUOT, 122 },
67966e63ce3Schristos #endif
68066e63ce3Schristos #ifdef ENOMEDIUM
681ed6a76a9Schristos   { "ENOMEDIUM", ENOMEDIUM, 123 },
68266e63ce3Schristos #endif
68366e63ce3Schristos #ifdef EMEDIUMTYPE
684ed6a76a9Schristos   { "EMEDIUMTYPE", EMEDIUMTYPE, 124 },
68566e63ce3Schristos #endif
686ed6a76a9Schristos   { 0, 0, 0 }
68766e63ce3Schristos };
68866e63ce3Schristos 
68966e63ce3Schristos /* Extracted by applying
69066e63ce3Schristos    perl -ne 'if ($_ =~ /^#define/) { split;
69166e63ce3Schristos      printf "#ifdef $_[1]\n  { %s, 0x%x },\n#endif\n",
69266e63ce3Schristos              $_[1], $_[2] =~ /^0/ ? oct($_[2]) : $_[2];}'
69366e63ce3Schristos    on pertinent parts of .../include/asm/fcntl.h in a GNU/Linux/CRIS
69466e63ce3Schristos    installation and removing synonyms and unnecessary items.  Don't
69566e63ce3Schristos    forget the end-marker.  */
69666e63ce3Schristos 
69766e63ce3Schristos /* These we treat specially, as they're used in the fcntl F_GETFL
69866e63ce3Schristos    syscall.  For consistency, open_map is also manually edited to use
69966e63ce3Schristos    these macros.  */
70066e63ce3Schristos #define TARGET_O_ACCMODE 0x3
70166e63ce3Schristos #define TARGET_O_RDONLY 0x0
70266e63ce3Schristos #define TARGET_O_WRONLY 0x1
70366e63ce3Schristos 
70466e63ce3Schristos static const CB_TARGET_DEFS_MAP open_map[] = {
70566e63ce3Schristos #ifdef O_ACCMODE
706ed6a76a9Schristos   { "O_ACCMODE", O_ACCMODE, TARGET_O_ACCMODE },
70766e63ce3Schristos #endif
70866e63ce3Schristos #ifdef O_RDONLY
709ed6a76a9Schristos   { "O_RDONLY", O_RDONLY, TARGET_O_RDONLY },
71066e63ce3Schristos #endif
71166e63ce3Schristos #ifdef O_WRONLY
712ed6a76a9Schristos   { "O_WRONLY", O_WRONLY, TARGET_O_WRONLY },
71366e63ce3Schristos #endif
71466e63ce3Schristos #ifdef O_RDWR
715ed6a76a9Schristos   { "O_RDWR", O_RDWR, 0x2 },
71666e63ce3Schristos #endif
71766e63ce3Schristos #ifdef O_CREAT
718ed6a76a9Schristos   { "O_CREAT", O_CREAT, 0x40 },
71966e63ce3Schristos #endif
72066e63ce3Schristos #ifdef O_EXCL
721ed6a76a9Schristos   { "O_EXCL", O_EXCL, 0x80 },
72266e63ce3Schristos #endif
72366e63ce3Schristos #ifdef O_NOCTTY
724ed6a76a9Schristos   { "O_NOCTTY", O_NOCTTY, 0x100 },
72566e63ce3Schristos #endif
72666e63ce3Schristos #ifdef O_TRUNC
727ed6a76a9Schristos   { "O_TRUNC", O_TRUNC, 0x200 },
72866e63ce3Schristos #endif
72966e63ce3Schristos #ifdef O_APPEND
730ed6a76a9Schristos   { "O_APPEND", O_APPEND, 0x400 },
73166e63ce3Schristos #endif
73266e63ce3Schristos #ifdef O_NONBLOCK
733ed6a76a9Schristos   { "O_NONBLOCK", O_NONBLOCK, 0x800 },
73466e63ce3Schristos #endif
73566e63ce3Schristos #ifdef O_NDELAY
736ed6a76a9Schristos   { "O_NDELAY", O_NDELAY, 0x0 },
73766e63ce3Schristos #endif
73866e63ce3Schristos #ifdef O_SYNC
739ed6a76a9Schristos   { "O_SYNC", O_SYNC, 0x1000 },
74066e63ce3Schristos #endif
74166e63ce3Schristos #ifdef FASYNC
742ed6a76a9Schristos   { "FASYNC", FASYNC, 0x2000 },
74366e63ce3Schristos #endif
74466e63ce3Schristos #ifdef O_DIRECT
745ed6a76a9Schristos   { "O_DIRECT", O_DIRECT, 0x4000 },
74666e63ce3Schristos #endif
74766e63ce3Schristos #ifdef O_LARGEFILE
748ed6a76a9Schristos   { "O_LARGEFILE", O_LARGEFILE, 0x8000 },
74966e63ce3Schristos #endif
75066e63ce3Schristos #ifdef O_DIRECTORY
751ed6a76a9Schristos   { "O_DIRECTORY", O_DIRECTORY, 0x10000 },
75266e63ce3Schristos #endif
75366e63ce3Schristos #ifdef O_NOFOLLOW
754ed6a76a9Schristos   { "O_NOFOLLOW", O_NOFOLLOW, 0x20000 },
75566e63ce3Schristos #endif
756ed6a76a9Schristos   { 0, -1, -1 }
75766e63ce3Schristos };
75866e63ce3Schristos 
75966e63ce3Schristos /* Let's be less drastic and more traceable.  FIXME: mark as noreturn.  */
76066e63ce3Schristos #define abort()							\
76166e63ce3Schristos   sim_io_error (sd, "simulator unhandled condition at %s:%d",	\
76266e63ce3Schristos 		__FUNCTION__, __LINE__)
76366e63ce3Schristos 
76466e63ce3Schristos /* Needed for the cris_pipe_nonempty and cris_pipe_empty syscalls.  */
76566e63ce3Schristos static SIM_CPU *current_cpu_for_cb_callback;
76666e63ce3Schristos 
76766e63ce3Schristos static USI create_map (SIM_DESC, struct cris_sim_mmapped_page **,
76866e63ce3Schristos 		       USI addr, USI len);
76966e63ce3Schristos static USI unmap_pages (SIM_DESC, struct cris_sim_mmapped_page **,
77066e63ce3Schristos 		       USI addr, USI len);
77166e63ce3Schristos static USI is_mapped (SIM_DESC, struct cris_sim_mmapped_page **,
77266e63ce3Schristos 		       USI addr, USI len);
77366e63ce3Schristos static void dump_statistics (SIM_CPU *current_cpu);
77466e63ce3Schristos static void make_first_thread (SIM_CPU *current_cpu);
77566e63ce3Schristos 
77666e63ce3Schristos /* When we risk running self-modified code (as in trampolines), this is
77766e63ce3Schristos    called from special-case insns.  The silicon CRIS CPU:s have enough
77866e63ce3Schristos    cache snooping implemented making this a simulator-only issue.  Tests:
77966e63ce3Schristos    gcc.c-torture/execute/931002-1.c execution, -O3 -g
78066e63ce3Schristos    gcc.c-torture/execute/931002-1.c execution, -O3 -fomit-frame-pointer.  */
78166e63ce3Schristos 
78266e63ce3Schristos void
cris_flush_simulator_decode_cache(SIM_CPU * current_cpu,USI pc ATTRIBUTE_UNUSED)78366e63ce3Schristos cris_flush_simulator_decode_cache (SIM_CPU *current_cpu,
78466e63ce3Schristos 				   USI pc ATTRIBUTE_UNUSED)
78566e63ce3Schristos {
78666e63ce3Schristos   SIM_DESC sd = CPU_STATE (current_cpu);
78766e63ce3Schristos 
78866e63ce3Schristos #if WITH_SCACHE
78966e63ce3Schristos   if (USING_SCACHE_P (sd))
79066e63ce3Schristos     scache_flush_cpu (current_cpu);
79166e63ce3Schristos #endif
79266e63ce3Schristos }
79366e63ce3Schristos 
79466e63ce3Schristos /* Output statistics at the end of a run.  */
79566e63ce3Schristos static void
dump_statistics(SIM_CPU * current_cpu)79666e63ce3Schristos dump_statistics (SIM_CPU *current_cpu)
79766e63ce3Schristos {
79866e63ce3Schristos   SIM_DESC sd = CPU_STATE (current_cpu);
79966e63ce3Schristos   CRIS_MISC_PROFILE *profp
80066e63ce3Schristos     = CPU_CRIS_MISC_PROFILE (current_cpu);
80166e63ce3Schristos   unsigned64 total = profp->basic_cycle_count;
80266e63ce3Schristos   const char *textmsg = "Basic clock cycles, total @: %llu\n";
80366e63ce3Schristos 
80466e63ce3Schristos   /* The --cris-stats={basic|unaligned|schedulable|all} counts affect
80566e63ce3Schristos      what's included in the "total" count only.  */
80666e63ce3Schristos   switch (CPU_CRIS_MISC_PROFILE (current_cpu)->flags
80766e63ce3Schristos 	  & FLAG_CRIS_MISC_PROFILE_ALL)
80866e63ce3Schristos     {
80966e63ce3Schristos     case FLAG_CRIS_MISC_PROFILE_SIMPLE:
81066e63ce3Schristos       break;
81166e63ce3Schristos 
81266e63ce3Schristos     case (FLAG_CRIS_MISC_PROFILE_UNALIGNED | FLAG_CRIS_MISC_PROFILE_SIMPLE):
81366e63ce3Schristos       textmsg
81466e63ce3Schristos 	= "Clock cycles including stall cycles for unaligned accesses @: %llu\n";
81566e63ce3Schristos       total += profp->unaligned_mem_dword_count;
81666e63ce3Schristos       break;
81766e63ce3Schristos 
81866e63ce3Schristos     case (FLAG_CRIS_MISC_PROFILE_SCHEDULABLE | FLAG_CRIS_MISC_PROFILE_SIMPLE):
81966e63ce3Schristos       textmsg = "Schedulable clock cycles, total @: %llu\n";
82066e63ce3Schristos       total
82166e63ce3Schristos 	+= (profp->memsrc_stall_count
82266e63ce3Schristos 	    + profp->memraw_stall_count
82366e63ce3Schristos 	    + profp->movemsrc_stall_count
82466e63ce3Schristos 	    + profp->movemdst_stall_count
82566e63ce3Schristos 	    + profp->mulsrc_stall_count
82666e63ce3Schristos 	    + profp->jumpsrc_stall_count
82766e63ce3Schristos 	    + profp->unaligned_mem_dword_count);
82866e63ce3Schristos       break;
82966e63ce3Schristos 
83066e63ce3Schristos     case FLAG_CRIS_MISC_PROFILE_ALL:
83166e63ce3Schristos       textmsg = "All accounted clock cycles, total @: %llu\n";
83266e63ce3Schristos       total
83366e63ce3Schristos 	+= (profp->memsrc_stall_count
83466e63ce3Schristos 	    + profp->memraw_stall_count
83566e63ce3Schristos 	    + profp->movemsrc_stall_count
83666e63ce3Schristos 	    + profp->movemdst_stall_count
83766e63ce3Schristos 	    + profp->movemaddr_stall_count
83866e63ce3Schristos 	    + profp->mulsrc_stall_count
83966e63ce3Schristos 	    + profp->jumpsrc_stall_count
84066e63ce3Schristos 	    + profp->branch_stall_count
84166e63ce3Schristos 	    + profp->jumptarget_stall_count
84266e63ce3Schristos 	    + profp->unaligned_mem_dword_count);
84366e63ce3Schristos       break;
84466e63ce3Schristos 
84566e63ce3Schristos     default:
84666e63ce3Schristos       abort ();
84766e63ce3Schristos 
84866e63ce3Schristos       sim_io_eprintf (sd,
84966e63ce3Schristos 		      "Internal inconsistency at %s:%d",
85066e63ce3Schristos 		      __FILE__, __LINE__);
85166e63ce3Schristos       sim_engine_halt (sd, current_cpu, NULL, 0,
85266e63ce3Schristos 		       sim_stopped, SIM_SIGILL);
85366e63ce3Schristos     }
85466e63ce3Schristos 
85566e63ce3Schristos   /* Historically, these messages have gone to stderr, so we'll keep it
85666e63ce3Schristos      that way.  It's also easier to then tell it from normal program
85766e63ce3Schristos      output.  FIXME: Add redirect option like "run -e file".  */
85866e63ce3Schristos   sim_io_eprintf (sd, textmsg, total);
85966e63ce3Schristos 
86066e63ce3Schristos   /* For v32, unaligned_mem_dword_count should always be 0.  For
86166e63ce3Schristos      v10, memsrc_stall_count should always be 0.  */
86266e63ce3Schristos   sim_io_eprintf (sd, "Memory source stall cycles: %llu\n",
86366e63ce3Schristos 		  (unsigned long long) (profp->memsrc_stall_count
86466e63ce3Schristos 					+ profp->unaligned_mem_dword_count));
86566e63ce3Schristos   sim_io_eprintf (sd, "Memory read-after-write stall cycles: %llu\n",
86666e63ce3Schristos 		  (unsigned long long) profp->memraw_stall_count);
86766e63ce3Schristos   sim_io_eprintf (sd, "Movem source stall cycles: %llu\n",
86866e63ce3Schristos 		  (unsigned long long) profp->movemsrc_stall_count);
86966e63ce3Schristos   sim_io_eprintf (sd, "Movem destination stall cycles: %llu\n",
87066e63ce3Schristos 		  (unsigned long long) profp->movemdst_stall_count);
87166e63ce3Schristos   sim_io_eprintf (sd, "Movem address stall cycles: %llu\n",
87266e63ce3Schristos 		  (unsigned long long) profp->movemaddr_stall_count);
87366e63ce3Schristos   sim_io_eprintf (sd, "Multiplication source stall cycles: %llu\n",
87466e63ce3Schristos 		  (unsigned long long) profp->mulsrc_stall_count);
87566e63ce3Schristos   sim_io_eprintf (sd, "Jump source stall cycles: %llu\n",
87666e63ce3Schristos 		  (unsigned long long) profp->jumpsrc_stall_count);
87766e63ce3Schristos   sim_io_eprintf (sd, "Branch misprediction stall cycles: %llu\n",
87866e63ce3Schristos 		  (unsigned long long) profp->branch_stall_count);
87966e63ce3Schristos   sim_io_eprintf (sd, "Jump target stall cycles: %llu\n",
88066e63ce3Schristos 		  (unsigned long long) profp->jumptarget_stall_count);
88166e63ce3Schristos }
88266e63ce3Schristos 
88366e63ce3Schristos /* Check whether any part of [addr .. addr + len - 1] is already mapped.
88466e63ce3Schristos    Return 1 if a overlap detected, 0 otherwise.  */
88566e63ce3Schristos 
88666e63ce3Schristos static USI
is_mapped(SIM_DESC sd ATTRIBUTE_UNUSED,struct cris_sim_mmapped_page ** rootp,USI addr,USI len)88766e63ce3Schristos is_mapped (SIM_DESC sd ATTRIBUTE_UNUSED,
88866e63ce3Schristos 	   struct cris_sim_mmapped_page **rootp,
88966e63ce3Schristos 	   USI addr, USI len)
89066e63ce3Schristos {
89166e63ce3Schristos   struct cris_sim_mmapped_page *mapp;
89266e63ce3Schristos 
89366e63ce3Schristos   if (len == 0 || (len & 8191))
89466e63ce3Schristos     abort ();
89566e63ce3Schristos 
89666e63ce3Schristos   /* Iterate over the reverse-address sorted pages until we find a page in
89766e63ce3Schristos      or lower than the checked area.  */
89866e63ce3Schristos   for (mapp = *rootp; mapp != NULL && mapp->addr >= addr; mapp = mapp->prev)
89966e63ce3Schristos     if (mapp->addr < addr + len && mapp->addr >= addr)
90066e63ce3Schristos       return 1;
90166e63ce3Schristos 
90266e63ce3Schristos   return 0;
90366e63ce3Schristos }
90466e63ce3Schristos 
90566e63ce3Schristos /* Check whether any part of [addr .. addr + len - 1] is *un*mapped.
90666e63ce3Schristos    Return 1 if the whole area is mapped, 0 otherwise.  */
90766e63ce3Schristos 
90866e63ce3Schristos static USI
is_mapped_only(SIM_DESC sd ATTRIBUTE_UNUSED,struct cris_sim_mmapped_page ** rootp,USI addr,USI len)90966e63ce3Schristos is_mapped_only (SIM_DESC sd ATTRIBUTE_UNUSED,
91066e63ce3Schristos 		struct cris_sim_mmapped_page **rootp,
91166e63ce3Schristos 		USI addr, USI len)
91266e63ce3Schristos {
91366e63ce3Schristos   struct cris_sim_mmapped_page *mapp;
91466e63ce3Schristos 
91566e63ce3Schristos   if (len == 0 || (len & 8191))
91666e63ce3Schristos     abort ();
91766e63ce3Schristos 
91866e63ce3Schristos   /* Iterate over the reverse-address sorted pages until we find a page
91966e63ce3Schristos      lower than the checked area.  */
92066e63ce3Schristos   for (mapp = *rootp; mapp != NULL && mapp->addr >= addr; mapp = mapp->prev)
92166e63ce3Schristos     if (addr == mapp->addr && len == 8192)
92266e63ce3Schristos       return 1;
92366e63ce3Schristos     else if (addr + len > mapp->addr)
92466e63ce3Schristos       len -= 8192;
92566e63ce3Schristos 
92666e63ce3Schristos   return 0;
92766e63ce3Schristos }
92866e63ce3Schristos 
92966e63ce3Schristos /* Debug helper; to be run from gdb.  */
93066e63ce3Schristos 
93166e63ce3Schristos void
cris_dump_map(SIM_CPU * current_cpu)93266e63ce3Schristos cris_dump_map (SIM_CPU *current_cpu)
93366e63ce3Schristos {
93466e63ce3Schristos   struct cris_sim_mmapped_page *mapp;
93566e63ce3Schristos   USI start, end;
93666e63ce3Schristos 
93766e63ce3Schristos   for (mapp = current_cpu->highest_mmapped_page,
93866e63ce3Schristos 	 start = mapp == NULL ? 0 : mapp->addr + 8192,
93966e63ce3Schristos 	 end = mapp == NULL ? 0 : mapp->addr + 8191;
94066e63ce3Schristos        mapp != NULL;
94166e63ce3Schristos        mapp = mapp->prev)
94266e63ce3Schristos     {
94366e63ce3Schristos       if (mapp->addr != start - 8192)
94466e63ce3Schristos 	{
94566e63ce3Schristos 	  sim_io_eprintf (CPU_STATE (current_cpu), "0x%x..0x%x\n", start, end);
94666e63ce3Schristos 	  end = mapp->addr + 8191;
94766e63ce3Schristos 	}
94866e63ce3Schristos 
94966e63ce3Schristos       start = mapp->addr;
95066e63ce3Schristos     }
95166e63ce3Schristos 
95266e63ce3Schristos   if (current_cpu->highest_mmapped_page != NULL)
95366e63ce3Schristos     sim_io_eprintf (CPU_STATE (current_cpu), "0x%x..0x%x\n", start, end);
95466e63ce3Schristos }
95566e63ce3Schristos 
95666e63ce3Schristos /* Create mmapped memory.  ADDR is -1 if any address will do.  Caller
95766e63ce3Schristos    must make sure that the address isn't already mapped.  */
95866e63ce3Schristos 
95966e63ce3Schristos static USI
create_map(SIM_DESC sd,struct cris_sim_mmapped_page ** rootp,USI addr,USI len)96066e63ce3Schristos create_map (SIM_DESC sd, struct cris_sim_mmapped_page **rootp, USI addr,
96166e63ce3Schristos 	    USI len)
96266e63ce3Schristos {
96366e63ce3Schristos   struct cris_sim_mmapped_page *mapp;
96466e63ce3Schristos   struct cris_sim_mmapped_page **higher_prevp = rootp;
96566e63ce3Schristos   USI new_addr = 0x40000000;
96666e63ce3Schristos 
96766e63ce3Schristos   if (addr != (USI) -1)
96866e63ce3Schristos     new_addr = addr;
96966e63ce3Schristos   else if (*rootp && rootp[0]->addr >= new_addr)
97066e63ce3Schristos     new_addr = rootp[0]->addr + 8192;
97166e63ce3Schristos 
97266e63ce3Schristos   if (len != 8192)
97366e63ce3Schristos     {
97466e63ce3Schristos       USI page_addr;
97566e63ce3Schristos 
97666e63ce3Schristos       if (len & 8191)
97766e63ce3Schristos 	/* Which is better: return an error for this, or just round it up?  */
97866e63ce3Schristos 	abort ();
97966e63ce3Schristos 
98066e63ce3Schristos       /* Do a recursive call for each page in the request.  */
98166e63ce3Schristos       for (page_addr = new_addr; len != 0; page_addr += 8192, len -= 8192)
98266e63ce3Schristos 	if (create_map (sd, rootp, page_addr, 8192) >= (USI) -8191)
98366e63ce3Schristos 	  abort ();
98466e63ce3Schristos 
98566e63ce3Schristos       return new_addr;
98666e63ce3Schristos     }
98766e63ce3Schristos 
98866e63ce3Schristos   for (mapp = *rootp;
98966e63ce3Schristos        mapp != NULL && mapp->addr > new_addr;
99066e63ce3Schristos        mapp = mapp->prev)
99166e63ce3Schristos     higher_prevp = &mapp->prev;
99266e63ce3Schristos 
99366e63ce3Schristos   /* Assert for consistency that we don't create duplicate maps.  */
99466e63ce3Schristos   if (is_mapped (sd, rootp, new_addr, len))
99566e63ce3Schristos     abort ();
99666e63ce3Schristos 
99766e63ce3Schristos   /* Allocate the new page, on the next higher page from the last one
99866e63ce3Schristos      allocated, and link in the new descriptor before previous ones.  */
99966e63ce3Schristos   mapp = malloc (sizeof (*mapp));
100066e63ce3Schristos 
100166e63ce3Schristos   if (mapp == NULL)
100266e63ce3Schristos     return (USI) -ENOMEM;
100366e63ce3Schristos 
100466e63ce3Schristos   sim_core_attach (sd, NULL, 0, access_read_write_exec, 0,
100566e63ce3Schristos 		   new_addr, len,
100666e63ce3Schristos 		   0, NULL, NULL);
100766e63ce3Schristos 
100866e63ce3Schristos   mapp->addr = new_addr;
100966e63ce3Schristos   mapp->prev = *higher_prevp;
101066e63ce3Schristos   *higher_prevp = mapp;
101166e63ce3Schristos 
101266e63ce3Schristos   return new_addr;
101366e63ce3Schristos }
101466e63ce3Schristos 
101566e63ce3Schristos /* Unmap one or more pages.  */
101666e63ce3Schristos 
101766e63ce3Schristos static USI
unmap_pages(SIM_DESC sd,struct cris_sim_mmapped_page ** rootp,USI addr,USI len)101866e63ce3Schristos unmap_pages (SIM_DESC sd, struct cris_sim_mmapped_page **rootp, USI addr,
101966e63ce3Schristos 	    USI len)
102066e63ce3Schristos {
102166e63ce3Schristos   struct cris_sim_mmapped_page *mapp;
102266e63ce3Schristos   struct cris_sim_mmapped_page **higher_prevp = rootp;
102366e63ce3Schristos 
102466e63ce3Schristos   if (len != 8192)
102566e63ce3Schristos     {
102666e63ce3Schristos       USI page_addr;
102766e63ce3Schristos       int ret = 0;
102866e63ce3Schristos 
102966e63ce3Schristos       if (len & 8191)
103066e63ce3Schristos 	/* Which is better: return an error for this, or just round it up?  */
103166e63ce3Schristos 	abort ();
103266e63ce3Schristos 
103366e63ce3Schristos       /* Loop backwards to make each call is O(1) over the number of pages
103466e63ce3Schristos 	 allocated, if we're unmapping from the high end of the pages.  */
103566e63ce3Schristos       for (page_addr = addr + len - 8192;
103666e63ce3Schristos 	   page_addr > addr;
103766e63ce3Schristos 	   page_addr -= 8192)
103866e63ce3Schristos 	if (unmap_pages (sd, rootp, page_addr, 8192))
103966e63ce3Schristos 	  ret = EINVAL;
104066e63ce3Schristos 
104166e63ce3Schristos       if (unmap_pages (sd, rootp, addr, 8192))
104266e63ce3Schristos 	ret = EINVAL;
104366e63ce3Schristos 
104466e63ce3Schristos       return ret;
104566e63ce3Schristos     }
104666e63ce3Schristos 
104766e63ce3Schristos   for (mapp = *rootp; mapp != NULL && mapp->addr > addr; mapp = mapp->prev)
104866e63ce3Schristos     higher_prevp = &mapp->prev;
104966e63ce3Schristos 
105066e63ce3Schristos   if (mapp == NULL || mapp->addr != addr)
105166e63ce3Schristos     return EINVAL;
105266e63ce3Schristos 
105366e63ce3Schristos   *higher_prevp = mapp->prev;
105466e63ce3Schristos   sim_core_detach (sd, NULL, 0, 0, addr);
105566e63ce3Schristos   free (mapp);
105666e63ce3Schristos   return 0;
105766e63ce3Schristos }
105866e63ce3Schristos 
105966e63ce3Schristos /* The semantic code invokes this for illegal (unrecognized) instructions.  */
106066e63ce3Schristos 
106166e63ce3Schristos SEM_PC
sim_engine_invalid_insn(SIM_CPU * current_cpu,IADDR cia,SEM_PC vpc)106266e63ce3Schristos sim_engine_invalid_insn (SIM_CPU *current_cpu, IADDR cia, SEM_PC vpc)
106366e63ce3Schristos {
106466e63ce3Schristos   SIM_DESC sd = CPU_STATE (current_cpu);
106566e63ce3Schristos 
106666e63ce3Schristos   sim_engine_halt (sd, current_cpu, NULL, cia, sim_stopped, SIM_SIGILL);
106766e63ce3Schristos   return vpc;
106866e63ce3Schristos }
106966e63ce3Schristos 
107066e63ce3Schristos /* Handlers from the CGEN description that should not be called.  */
107166e63ce3Schristos 
107266e63ce3Schristos USI
cris_bmod_handler(SIM_CPU * current_cpu ATTRIBUTE_UNUSED,UINT srcreg ATTRIBUTE_UNUSED,USI dstreg ATTRIBUTE_UNUSED)107366e63ce3Schristos cris_bmod_handler (SIM_CPU *current_cpu ATTRIBUTE_UNUSED,
107466e63ce3Schristos 		   UINT srcreg ATTRIBUTE_UNUSED,
107566e63ce3Schristos 		   USI dstreg ATTRIBUTE_UNUSED)
107666e63ce3Schristos {
107766e63ce3Schristos   SIM_DESC sd = CPU_STATE (current_cpu);
107866e63ce3Schristos   abort ();
107966e63ce3Schristos }
108066e63ce3Schristos 
108166e63ce3Schristos void
h_supr_set_handler(SIM_CPU * current_cpu ATTRIBUTE_UNUSED,UINT index ATTRIBUTE_UNUSED,USI page ATTRIBUTE_UNUSED,USI newval ATTRIBUTE_UNUSED)108266e63ce3Schristos h_supr_set_handler (SIM_CPU *current_cpu ATTRIBUTE_UNUSED,
108366e63ce3Schristos 		    UINT index ATTRIBUTE_UNUSED,
108466e63ce3Schristos 		    USI page ATTRIBUTE_UNUSED,
108566e63ce3Schristos 		    USI newval ATTRIBUTE_UNUSED)
108666e63ce3Schristos {
108766e63ce3Schristos   SIM_DESC sd = CPU_STATE (current_cpu);
108866e63ce3Schristos   abort ();
108966e63ce3Schristos }
109066e63ce3Schristos 
109166e63ce3Schristos USI
h_supr_get_handler(SIM_CPU * current_cpu ATTRIBUTE_UNUSED,UINT index ATTRIBUTE_UNUSED,USI page ATTRIBUTE_UNUSED)109266e63ce3Schristos h_supr_get_handler (SIM_CPU *current_cpu ATTRIBUTE_UNUSED,
109366e63ce3Schristos 		    UINT index ATTRIBUTE_UNUSED,
109466e63ce3Schristos 		    USI page ATTRIBUTE_UNUSED)
109566e63ce3Schristos {
109666e63ce3Schristos   SIM_DESC sd = CPU_STATE (current_cpu);
109766e63ce3Schristos   abort ();
109866e63ce3Schristos }
109966e63ce3Schristos 
110066e63ce3Schristos /* Swap one context for another.  */
110166e63ce3Schristos 
110266e63ce3Schristos static void
schedule(SIM_CPU * current_cpu,int next)110366e63ce3Schristos schedule (SIM_CPU *current_cpu, int next)
110466e63ce3Schristos {
110566e63ce3Schristos   /* Need to mark context-switches in the trace output.  */
110666e63ce3Schristos   if ((CPU_CRIS_MISC_PROFILE (current_cpu)->flags
110766e63ce3Schristos        & FLAG_CRIS_MISC_PROFILE_XSIM_TRACE))
110866e63ce3Schristos     cris_trace_printf (CPU_STATE (current_cpu), current_cpu,
110966e63ce3Schristos 		       "\t#:%d\n", next);
111066e63ce3Schristos 
111166e63ce3Schristos   /* Copy the current context (if there is one) to its slot.  */
111266e63ce3Schristos   if (current_cpu->thread_data[current_cpu->threadno].cpu_context)
111366e63ce3Schristos     memcpy (current_cpu->thread_data[current_cpu->threadno].cpu_context,
111466e63ce3Schristos 	    &current_cpu->cpu_data_placeholder,
111566e63ce3Schristos 	    current_cpu->thread_cpu_data_size);
111666e63ce3Schristos 
111766e63ce3Schristos   /* Copy the new context from its slot.  */
111866e63ce3Schristos   memcpy (&current_cpu->cpu_data_placeholder,
111966e63ce3Schristos 	  current_cpu->thread_data[next].cpu_context,
112066e63ce3Schristos 	  current_cpu->thread_cpu_data_size);
112166e63ce3Schristos 
112266e63ce3Schristos   /* Update needed stuff to indicate the new context.  */
112366e63ce3Schristos   current_cpu->threadno = next;
112466e63ce3Schristos 
112566e63ce3Schristos   /* Handle pending signals.  */
112666e63ce3Schristos   if (current_cpu->thread_data[next].sigpending
112766e63ce3Schristos       /* We don't run nested signal handlers.  This means that pause(2)
112866e63ce3Schristos 	 and sigsuspend(2) do not work in sighandlers, but that
112966e63ce3Schristos 	 shouldn't be too hard a restriction.  It also greatly
113066e63ce3Schristos 	 simplifies the code.  */
113166e63ce3Schristos       && current_cpu->thread_data[next].cpu_context_atsignal == NULL)
113266e63ce3Schristos   {
113366e63ce3Schristos     int sig;
113466e63ce3Schristos 
113566e63ce3Schristos     /* See if there's really a pending, non-blocked handler.  We don't
113666e63ce3Schristos        queue signals, so just use the first one in ascending order.  */
113766e63ce3Schristos     for (sig = 0; sig < 64; sig++)
113866e63ce3Schristos       if (current_cpu->thread_data[next].sigdata[sig].pending
113966e63ce3Schristos 	  && !current_cpu->thread_data[next].sigdata[sig].blocked)
114066e63ce3Schristos       {
114166e63ce3Schristos 	bfd_byte regbuf[4];
114266e63ce3Schristos 	USI sp;
114366e63ce3Schristos 	int i;
114466e63ce3Schristos 	USI blocked;
114566e63ce3Schristos 	USI pc = sim_pc_get (current_cpu);
114666e63ce3Schristos 
114766e63ce3Schristos 	/* It's simpler to save the CPU context inside the simulator
114866e63ce3Schristos 	   than on the stack.  */
114966e63ce3Schristos 	current_cpu->thread_data[next].cpu_context_atsignal
115066e63ce3Schristos 	  = (*current_cpu
115166e63ce3Schristos 	     ->make_thread_cpu_data) (current_cpu,
115266e63ce3Schristos 				      current_cpu->thread_data[next]
115366e63ce3Schristos 				      .cpu_context);
115466e63ce3Schristos 
115566e63ce3Schristos 	(*CPU_REG_FETCH (current_cpu)) (current_cpu, H_GR_SP, regbuf, 4);
115666e63ce3Schristos 	sp = bfd_getl32 (regbuf);
115766e63ce3Schristos 
115866e63ce3Schristos 	/* Make sure we have an aligned stack.  */
115966e63ce3Schristos 	sp &= ~3;
116066e63ce3Schristos 
116166e63ce3Schristos 	/* Make room for the signal frame, aligned.  FIXME: Check that
116266e63ce3Schristos 	   the memory exists, map it in if absent.  (BTW, should also
116366e63ce3Schristos 	   implement on-access automatic stack allocation).  */
116466e63ce3Schristos 	sp -= 20;
116566e63ce3Schristos 
116666e63ce3Schristos 	/* This isn't the same signal frame as the kernel uses, because
116766e63ce3Schristos            we don't want to bother getting all registers on and off the
116866e63ce3Schristos            stack.  */
116966e63ce3Schristos 
117066e63ce3Schristos 	/* First, we store the currently blocked signals.  */
117166e63ce3Schristos 	blocked = 0;
117266e63ce3Schristos 	for (i = 0; i < 32; i++)
117366e63ce3Schristos 	  blocked
117466e63ce3Schristos 	    |= current_cpu->thread_data[next].sigdata[i + 1].blocked << i;
117566e63ce3Schristos 	sim_core_write_aligned_4 (current_cpu, pc, 0, sp, blocked);
117666e63ce3Schristos 	blocked = 0;
117766e63ce3Schristos 	for (i = 0; i < 31; i++)
117866e63ce3Schristos 	  blocked
117966e63ce3Schristos 	    |= current_cpu->thread_data[next].sigdata[i + 33].blocked << i;
118066e63ce3Schristos 	sim_core_write_aligned_4 (current_cpu, pc, 0, sp + 4, blocked);
118166e63ce3Schristos 
118266e63ce3Schristos 	/* Then, the actual instructions.  This is CPU-specific, but we
118366e63ce3Schristos 	   use instructions from the common subset for v10 and v32 which
118466e63ce3Schristos 	   should be safe for the time being but could be parametrized
118566e63ce3Schristos 	   if need be.  */
118666e63ce3Schristos 	/* MOVU.W [PC+],R9.  */
118766e63ce3Schristos 	sim_core_write_aligned_2 (current_cpu, pc, 0, sp + 8, 0x9c5f);
118866e63ce3Schristos 	/* .WORD TARGET_SYS_sigreturn.  */
118966e63ce3Schristos 	sim_core_write_aligned_2 (current_cpu, pc, 0, sp + 10,
119066e63ce3Schristos 				  TARGET_SYS_sigreturn);
119166e63ce3Schristos 	/* BREAK 13.  */
119266e63ce3Schristos 	sim_core_write_aligned_2 (current_cpu, pc, 0, sp + 12, 0xe93d);
119366e63ce3Schristos 
119466e63ce3Schristos 	/* NOP (on v32; it's SETF on v10, but is the correct compatible
119566e63ce3Schristos 	   instruction.  Still, it doesn't matter because v10 has no
119666e63ce3Schristos 	   delay slot for BREAK so it will not be executed).  */
119766e63ce3Schristos 	sim_core_write_aligned_2 (current_cpu, pc, 0, sp + 16, 0x05b0);
119866e63ce3Schristos 
119966e63ce3Schristos 	/* Modify registers to hold the right values for the sighandler
120066e63ce3Schristos 	   context: updated stackpointer and return address pointing to
120166e63ce3Schristos 	   the sigreturn stub.  */
120266e63ce3Schristos 	bfd_putl32 (sp, regbuf);
120366e63ce3Schristos 	(*CPU_REG_STORE (current_cpu)) (current_cpu, H_GR_SP, regbuf, 4);
120466e63ce3Schristos 	bfd_putl32 (sp + 8, regbuf);
120566e63ce3Schristos 	(*CPU_REG_STORE (current_cpu)) (current_cpu, TARGET_SRP_REGNUM,
120666e63ce3Schristos 					regbuf, 4);
120766e63ce3Schristos 
120866e63ce3Schristos 	current_cpu->thread_data[next].sigdata[sig].pending = 0;
120966e63ce3Schristos 
121066e63ce3Schristos 	/* Block this signal (for the duration of the sighandler).  */
121166e63ce3Schristos 	current_cpu->thread_data[next].sigdata[sig].blocked = 1;
121266e63ce3Schristos 
121366e63ce3Schristos 	sim_pc_set (current_cpu, current_cpu->sighandler[sig]);
121466e63ce3Schristos 	bfd_putl32 (sig, regbuf);
121566e63ce3Schristos 	(*CPU_REG_STORE (current_cpu)) (current_cpu, H_GR_R10,
121666e63ce3Schristos 					regbuf, 4);
121766e63ce3Schristos 
121866e63ce3Schristos 	/* We ignore a SA_SIGINFO flag in the sigaction call; the code I
121966e63ce3Schristos 	   needed all this for, specifies a SA_SIGINFO call but treats it
122066e63ce3Schristos 	   like an ordinary sighandler; only the signal number argument is
122166e63ce3Schristos 	   inspected.  To make future need to implement SA_SIGINFO
122266e63ce3Schristos 	   correctly possible, we set the siginfo argument register to a
122366e63ce3Schristos 	   magic (hopefully non-address) number.  (NB: then, you should
122466e63ce3Schristos 	   just need to pass the siginfo argument; it seems you probably
122566e63ce3Schristos 	   don't need to implement the specific rt_sigreturn.)  */
122666e63ce3Schristos 	bfd_putl32 (0xbad5161f, regbuf);
122766e63ce3Schristos 	(*CPU_REG_STORE (current_cpu)) (current_cpu, H_GR_R11,
122866e63ce3Schristos 					regbuf, 4);
122966e63ce3Schristos 
123066e63ce3Schristos 	/* The third argument is unused and the kernel sets it to 0.  */
123166e63ce3Schristos 	bfd_putl32 (0, regbuf);
123266e63ce3Schristos 	(*CPU_REG_STORE (current_cpu)) (current_cpu, H_GR_R12,
123366e63ce3Schristos 					regbuf, 4);
123466e63ce3Schristos 	return;
123566e63ce3Schristos       }
123666e63ce3Schristos 
123766e63ce3Schristos     /* No, there actually was no pending signal for this thread.  Reset
123866e63ce3Schristos        this flag.  */
123966e63ce3Schristos     current_cpu->thread_data[next].sigpending = 0;
124066e63ce3Schristos   }
124166e63ce3Schristos }
124266e63ce3Schristos 
124366e63ce3Schristos /* Reschedule the simplest possible way until something else is absolutely
124466e63ce3Schristos    necessary:
124566e63ce3Schristos    - A. Find the next process (round-robin) that doesn't have at_syscall
124666e63ce3Schristos         set, schedule it.
124766e63ce3Schristos    - B. If there is none, just run the next process, round-robin.
124866e63ce3Schristos    - Clear at_syscall for the current process.  */
124966e63ce3Schristos 
125066e63ce3Schristos static void
reschedule(SIM_CPU * current_cpu)125166e63ce3Schristos reschedule (SIM_CPU *current_cpu)
125266e63ce3Schristos {
125366e63ce3Schristos   SIM_DESC sd = CPU_STATE (current_cpu);
125466e63ce3Schristos   int i;
125566e63ce3Schristos 
125666e63ce3Schristos   /* Iterate over all thread slots, because after a few thread creations
125766e63ce3Schristos      and exits, we don't know where the live ones are.  */
125866e63ce3Schristos   for (i = (current_cpu->threadno + 1) % SIM_TARGET_MAX_THREADS;
125966e63ce3Schristos        i != current_cpu->threadno;
126066e63ce3Schristos        i = (i + 1) % SIM_TARGET_MAX_THREADS)
126166e63ce3Schristos     if (current_cpu->thread_data[i].cpu_context
126266e63ce3Schristos 	&& current_cpu->thread_data[i].at_syscall == 0)
126366e63ce3Schristos       {
126466e63ce3Schristos 	schedule (current_cpu, i);
126566e63ce3Schristos 	return;
126666e63ce3Schristos       }
126766e63ce3Schristos 
126866e63ce3Schristos   /* Pick any next live thread.  */
126966e63ce3Schristos   for (i = (current_cpu->threadno + 1) % SIM_TARGET_MAX_THREADS;
127066e63ce3Schristos        i != current_cpu->threadno;
127166e63ce3Schristos        i = (i + 1) % SIM_TARGET_MAX_THREADS)
127266e63ce3Schristos     if (current_cpu->thread_data[i].cpu_context)
127366e63ce3Schristos       {
127466e63ce3Schristos 	schedule (current_cpu, i);
127566e63ce3Schristos 	return;
127666e63ce3Schristos       }
127766e63ce3Schristos 
127866e63ce3Schristos   /* More than one live thread, but we couldn't find the next one?  */
127966e63ce3Schristos   abort ();
128066e63ce3Schristos }
128166e63ce3Schristos 
128266e63ce3Schristos /* Set up everything to receive (or IGN) an incoming signal to the
128366e63ce3Schristos    current context.  */
128466e63ce3Schristos 
128566e63ce3Schristos static int
deliver_signal(SIM_CPU * current_cpu,int sig,unsigned int pid)128666e63ce3Schristos deliver_signal (SIM_CPU *current_cpu, int sig, unsigned int pid)
128766e63ce3Schristos {
128866e63ce3Schristos   int i;
128966e63ce3Schristos   USI pc = sim_pc_get (current_cpu);
129066e63ce3Schristos 
129166e63ce3Schristos   /* Find the thread index of the pid. */
129266e63ce3Schristos   for (i = 0; i < SIM_TARGET_MAX_THREADS; i++)
129366e63ce3Schristos     /* Apparently it's ok to send signals to zombies (so a check for
129466e63ce3Schristos        current_cpu->thread_data[i].cpu_context != NULL would be
129566e63ce3Schristos        wrong). */
129666e63ce3Schristos     if (current_cpu->thread_data[i].threadid == pid - TARGET_PID)
129766e63ce3Schristos       {
129866e63ce3Schristos 	if (sig < 64)
129966e63ce3Schristos 	  switch (current_cpu->sighandler[sig])
130066e63ce3Schristos 	    {
130166e63ce3Schristos 	    case TARGET_SIG_DFL:
130266e63ce3Schristos 	      switch (sig)
130366e63ce3Schristos 		{
130466e63ce3Schristos 		  /* The following according to the glibc
130566e63ce3Schristos 		     documentation. (The kernel code has non-obvious
130666e63ce3Schristos 		     execution paths.)  */
130766e63ce3Schristos 		case TARGET_SIGFPE:
130866e63ce3Schristos 		case TARGET_SIGILL:
130966e63ce3Schristos 		case TARGET_SIGSEGV:
131066e63ce3Schristos 		case TARGET_SIGBUS:
131166e63ce3Schristos 		case TARGET_SIGABRT:
131266e63ce3Schristos 		case TARGET_SIGTRAP:
131366e63ce3Schristos 		case TARGET_SIGSYS:
131466e63ce3Schristos 
131566e63ce3Schristos 		case TARGET_SIGTERM:
131666e63ce3Schristos 		case TARGET_SIGINT:
131766e63ce3Schristos 		case TARGET_SIGQUIT:
131866e63ce3Schristos 		case TARGET_SIGKILL:
131966e63ce3Schristos 		case TARGET_SIGHUP:
132066e63ce3Schristos 
132166e63ce3Schristos 		case TARGET_SIGALRM:
132266e63ce3Schristos 		case TARGET_SIGVTALRM:
132366e63ce3Schristos 		case TARGET_SIGPROF:
132466e63ce3Schristos 		case TARGET_SIGSTOP:
132566e63ce3Schristos 
132666e63ce3Schristos 		case TARGET_SIGPIPE:
132766e63ce3Schristos 		case TARGET_SIGLOST:
132866e63ce3Schristos 		case TARGET_SIGXCPU:
132966e63ce3Schristos 		case TARGET_SIGXFSZ:
133066e63ce3Schristos 		case TARGET_SIGUSR1:
133166e63ce3Schristos 		case TARGET_SIGUSR2:
133266e63ce3Schristos 		  sim_io_eprintf (CPU_STATE (current_cpu),
133366e63ce3Schristos 				  "Exiting pid %d due to signal %d\n",
133466e63ce3Schristos 				  pid, sig);
133566e63ce3Schristos 		  sim_engine_halt (CPU_STATE (current_cpu), current_cpu,
133666e63ce3Schristos 				   NULL, pc, sim_stopped,
133766e63ce3Schristos 				   sig == TARGET_SIGABRT
133866e63ce3Schristos 				   ? SIM_SIGABRT : SIM_SIGILL);
133966e63ce3Schristos 		  return 0;
134066e63ce3Schristos 
134166e63ce3Schristos 		  /* The default for all other signals is to be ignored.  */
134266e63ce3Schristos 		default:
134366e63ce3Schristos 		  return 0;
134466e63ce3Schristos 		}
134566e63ce3Schristos 
134666e63ce3Schristos 	    case TARGET_SIG_IGN:
134766e63ce3Schristos 	      switch (sig)
134866e63ce3Schristos 		{
134966e63ce3Schristos 		case TARGET_SIGKILL:
135066e63ce3Schristos 		case TARGET_SIGSTOP:
135166e63ce3Schristos 		  /* Can't ignore these signals.  */
135266e63ce3Schristos 		  sim_io_eprintf (CPU_STATE (current_cpu),
135366e63ce3Schristos 				  "Exiting pid %d due to signal %d\n",
135466e63ce3Schristos 				  pid, sig);
135566e63ce3Schristos 		  sim_engine_halt (CPU_STATE (current_cpu), current_cpu,
135666e63ce3Schristos 				   NULL, pc, sim_stopped, SIM_SIGILL);
135766e63ce3Schristos 		  return 0;
135866e63ce3Schristos 
135966e63ce3Schristos 		default:
136066e63ce3Schristos 		  return 0;
136166e63ce3Schristos 		}
136266e63ce3Schristos 	      break;
136366e63ce3Schristos 
136466e63ce3Schristos 	    default:
136566e63ce3Schristos 	      /* Mark the signal as pending, making schedule () check
136666e63ce3Schristos 		 closer.  The signal will be handled when the thread is
136766e63ce3Schristos 		 scheduled and the signal is unblocked.  */
136866e63ce3Schristos 	      current_cpu->thread_data[i].sigdata[sig].pending = 1;
136966e63ce3Schristos 	      current_cpu->thread_data[i].sigpending = 1;
137066e63ce3Schristos 	      return 0;
137166e63ce3Schristos 	    }
137266e63ce3Schristos 	else
137366e63ce3Schristos 	  {
137466e63ce3Schristos 	    sim_io_eprintf (CPU_STATE (current_cpu),
137566e63ce3Schristos 			    "Unimplemented signal: %d\n", sig);
137666e63ce3Schristos 	    sim_engine_halt (CPU_STATE (current_cpu), current_cpu, NULL, pc,
137766e63ce3Schristos 			     sim_stopped, SIM_SIGILL);
137866e63ce3Schristos 	  }
137966e63ce3Schristos       }
138066e63ce3Schristos 
138166e63ce3Schristos   return
138266e63ce3Schristos     -cb_host_to_target_errno (STATE_CALLBACK (CPU_STATE (current_cpu)),
138366e63ce3Schristos 			      ESRCH);
138466e63ce3Schristos }
138566e63ce3Schristos 
138666e63ce3Schristos /* Make the vector and the first item, the main thread.  */
138766e63ce3Schristos 
138866e63ce3Schristos static void
make_first_thread(SIM_CPU * current_cpu)138966e63ce3Schristos make_first_thread (SIM_CPU *current_cpu)
139066e63ce3Schristos {
139166e63ce3Schristos   SIM_DESC sd = CPU_STATE (current_cpu);
139266e63ce3Schristos   current_cpu->thread_data
139366e63ce3Schristos     = xcalloc (1,
139466e63ce3Schristos 	       SIM_TARGET_MAX_THREADS
139566e63ce3Schristos 	       * sizeof (current_cpu->thread_data[0]));
139666e63ce3Schristos   current_cpu->thread_data[0].cpu_context
139766e63ce3Schristos     = (*current_cpu->make_thread_cpu_data) (current_cpu,
139866e63ce3Schristos 					    &current_cpu
139966e63ce3Schristos 					    ->cpu_data_placeholder);
140066e63ce3Schristos   current_cpu->thread_data[0].parent_threadid = -1;
140166e63ce3Schristos 
140266e63ce3Schristos   /* For good measure.  */
140366e63ce3Schristos   if (TARGET_SIG_DFL != 0)
140466e63ce3Schristos     abort ();
140566e63ce3Schristos }
140666e63ce3Schristos 
140766e63ce3Schristos /* Handle unknown system calls.  Returns (if it does) the syscall
140866e63ce3Schristos    return value.  */
140966e63ce3Schristos 
141066e63ce3Schristos static USI
cris_unknown_syscall(SIM_CPU * current_cpu,USI pc,char * s,...)141166e63ce3Schristos cris_unknown_syscall (SIM_CPU *current_cpu, USI pc, char *s, ...)
141266e63ce3Schristos {
141366e63ce3Schristos   SIM_DESC sd = CPU_STATE (current_cpu);
141466e63ce3Schristos   host_callback *cb = STATE_CALLBACK (sd);
141566e63ce3Schristos 
141666e63ce3Schristos   if (cris_unknown_syscall_action == CRIS_USYSC_MSG_STOP
141766e63ce3Schristos       || cris_unknown_syscall_action == CRIS_USYSC_MSG_ENOSYS)
141866e63ce3Schristos     {
141966e63ce3Schristos       va_list ap;
142066e63ce3Schristos 
142166e63ce3Schristos       va_start (ap, s);
142266e63ce3Schristos       sim_io_evprintf (sd, s, ap);
142366e63ce3Schristos       va_end (ap);
142466e63ce3Schristos 
142566e63ce3Schristos       if (cris_unknown_syscall_action == CRIS_USYSC_MSG_STOP)
142666e63ce3Schristos 	sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped, SIM_SIGILL);
142766e63ce3Schristos     }
142866e63ce3Schristos 
142966e63ce3Schristos   return -cb_host_to_target_errno (cb, ENOSYS);
143066e63ce3Schristos }
143166e63ce3Schristos 
143266e63ce3Schristos /* Main function: the handler of the "break 13" syscall insn.  */
143366e63ce3Schristos 
143466e63ce3Schristos USI
cris_break_13_handler(SIM_CPU * current_cpu,USI callnum,USI arg1,USI arg2,USI arg3,USI arg4,USI arg5,USI arg6,USI pc)143566e63ce3Schristos cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
143666e63ce3Schristos 		       USI arg2, USI arg3, USI arg4, USI arg5, USI arg6,
143766e63ce3Schristos 		       USI pc)
143866e63ce3Schristos {
143966e63ce3Schristos   CB_SYSCALL s;
144066e63ce3Schristos   SIM_DESC sd = CPU_STATE (current_cpu);
144166e63ce3Schristos   host_callback *cb = STATE_CALLBACK (sd);
144266e63ce3Schristos   int retval;
144366e63ce3Schristos   int threadno = current_cpu->threadno;
144466e63ce3Schristos 
144566e63ce3Schristos   current_cpu->syscalls++;
144666e63ce3Schristos 
144766e63ce3Schristos   CB_SYSCALL_INIT (&s);
144866e63ce3Schristos   s.func = callnum;
144966e63ce3Schristos   s.arg1 = arg1;
145066e63ce3Schristos   s.arg2 = arg2;
145166e63ce3Schristos   s.arg3 = arg3;
145266e63ce3Schristos 
145366e63ce3Schristos   /* The type of s.arg2 is long, so for hosts with 64-bit longs, we need
145466e63ce3Schristos      to sign-extend the lseek offset to be passed as a signed number,
145566e63ce3Schristos      else we'll truncate it to something > 2GB on hosts where sizeof
145666e63ce3Schristos      long > sizeof USI.  We avoid doing it for all syscalls, as arg2 is
145766e63ce3Schristos      e.g. an address for some syscalls.  */
145866e63ce3Schristos   if (callnum == TARGET_SYS_lseek)
145966e63ce3Schristos     s.arg2 = (SI) arg2;
146066e63ce3Schristos 
146166e63ce3Schristos   if (callnum == TARGET_SYS_exit_group
146266e63ce3Schristos       || (callnum == TARGET_SYS_exit && current_cpu->m1threads == 0))
146366e63ce3Schristos     {
146466e63ce3Schristos       if (CPU_CRIS_MISC_PROFILE (current_cpu)->flags
146566e63ce3Schristos 	  & FLAG_CRIS_MISC_PROFILE_ALL)
146666e63ce3Schristos 	dump_statistics (current_cpu);
146766e63ce3Schristos       sim_engine_halt (sd, current_cpu, NULL, pc, sim_exited, arg1);
146866e63ce3Schristos     }
146966e63ce3Schristos 
147066e63ce3Schristos   s.p1 = (PTR) sd;
147166e63ce3Schristos   s.p2 = (PTR) current_cpu;
1472ed6a76a9Schristos   s.read_mem = sim_syscall_read_mem;
1473ed6a76a9Schristos   s.write_mem = sim_syscall_write_mem;
147466e63ce3Schristos 
147566e63ce3Schristos   current_cpu_for_cb_callback = current_cpu;
147666e63ce3Schristos 
147766e63ce3Schristos   if (cb_syscall (cb, &s) != CB_RC_OK)
147866e63ce3Schristos     {
147966e63ce3Schristos       abort ();
148066e63ce3Schristos       sim_io_eprintf (sd, "Break 13: invalid %d?  Returned %ld\n", callnum,
148166e63ce3Schristos 		      s.result);
148266e63ce3Schristos       sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped, SIM_SIGILL);
148366e63ce3Schristos     }
148466e63ce3Schristos 
148566e63ce3Schristos   retval = s.result == -1 ? -s.errcode : s.result;
148666e63ce3Schristos 
148766e63ce3Schristos   if (s.errcode != 0 && s.errcode == cb_host_to_target_errno (cb, ENOSYS))
148866e63ce3Schristos     {
148966e63ce3Schristos       /* If the generic simulator call said ENOSYS, then let's try the
149066e63ce3Schristos 	 ones we know ourselves.
149166e63ce3Schristos 
149266e63ce3Schristos 	 The convention is to provide *very limited* functionality on an
149366e63ce3Schristos 	 as-needed basis, only what's covered by the test-suite, tests
149466e63ce3Schristos 	 added when functionality changes and abort with a descriptive
149566e63ce3Schristos 	 message for *everything* else.  Where there's no test-case, we
149666e63ce3Schristos 	 just abort.  */
149766e63ce3Schristos       switch (callnum)
149866e63ce3Schristos 	{
149966e63ce3Schristos 	case 0:
150066e63ce3Schristos 	  /* It's a pretty safe bet that the "old setup() system call"
150166e63ce3Schristos 	     number will not be re-used; we can't say the same for higher
150266e63ce3Schristos 	     numbers.  We treat this simulator-generated call as "wait
150366e63ce3Schristos 	     forever"; we re-run this insn.  The wait is ended by a
150466e63ce3Schristos 	     callback.  Sanity check that this is the reason we got
150566e63ce3Schristos 	     here. */
150666e63ce3Schristos 	  if (current_cpu->thread_data == NULL
150766e63ce3Schristos 	      || (current_cpu->thread_data[threadno].pipe_write_fd == 0))
150866e63ce3Schristos 	    goto unimplemented_syscall;
150966e63ce3Schristos 
151066e63ce3Schristos 	  sim_pc_set (current_cpu, pc);
151166e63ce3Schristos 	  retval = arg1;
151266e63ce3Schristos 	  break;
151366e63ce3Schristos 
151466e63ce3Schristos 	case TARGET_SYS_fcntl64:
151566e63ce3Schristos 	case TARGET_SYS_fcntl:
151666e63ce3Schristos 	  switch (arg2)
151766e63ce3Schristos 	    {
151866e63ce3Schristos 	    case 1:
151966e63ce3Schristos 	      /* F_GETFD.
152066e63ce3Schristos 		 Glibc checks stdin, stdout and stderr fd:s for
152166e63ce3Schristos 		 close-on-exec security sanity.  We just need to provide a
152266e63ce3Schristos 		 OK return value.  If we really need to have a
152366e63ce3Schristos 		 close-on-exec flag true, we could just do a real fcntl
152466e63ce3Schristos 		 here.  */
152566e63ce3Schristos 	      retval = 0;
152666e63ce3Schristos 	      break;
152766e63ce3Schristos 
152866e63ce3Schristos 	    case 2:
152966e63ce3Schristos 	      /* F_SETFD.  Just ignore attempts to set the close-on-exec
153066e63ce3Schristos 		 flag.  */
153166e63ce3Schristos 	      retval = 0;
153266e63ce3Schristos 	      break;
153366e63ce3Schristos 
153466e63ce3Schristos 	    case 3:
153566e63ce3Schristos 	      /* F_GETFL.  Check for the special case for open+fdopen.  */
153666e63ce3Schristos 	      if (current_cpu->last_syscall == TARGET_SYS_open
153766e63ce3Schristos 		  && arg1 == current_cpu->last_open_fd)
153866e63ce3Schristos 		{
153966e63ce3Schristos 		  retval = current_cpu->last_open_flags & TARGET_O_ACCMODE;
154066e63ce3Schristos 		  break;
154166e63ce3Schristos 		}
154266e63ce3Schristos 	      else if (arg1 == 0)
154366e63ce3Schristos 		{
154466e63ce3Schristos 		  /* Because we can't freopen fd:s 0, 1, 2 to mean
154566e63ce3Schristos 		     something else than stdin, stdout and stderr
154666e63ce3Schristos 		     (sim/common/syscall.c:cb_syscall special cases fd
154766e63ce3Schristos 		     0, 1 and 2), we know what flags that we can
154866e63ce3Schristos 		     sanely return for these fd:s.  */
154966e63ce3Schristos 		  retval = TARGET_O_RDONLY;
155066e63ce3Schristos 		  break;
155166e63ce3Schristos 		}
155266e63ce3Schristos 	      else if (arg1 == 1 || arg1 == 2)
155366e63ce3Schristos 		{
155466e63ce3Schristos 		  retval = TARGET_O_WRONLY;
155566e63ce3Schristos 		  break;
155666e63ce3Schristos 		}
155766e63ce3Schristos 	      /* FALLTHROUGH */
155866e63ce3Schristos 	    default:
155966e63ce3Schristos 	      /* Nothing else is implemented.  */
156066e63ce3Schristos 	      retval
156166e63ce3Schristos 		= cris_unknown_syscall (current_cpu, pc,
156266e63ce3Schristos 					"Unimplemented %s syscall "
156366e63ce3Schristos 					"(fd: 0x%lx: cmd: 0x%lx arg: "
156466e63ce3Schristos 					"0x%lx)\n",
156566e63ce3Schristos 					callnum == TARGET_SYS_fcntl
156666e63ce3Schristos 					? "fcntl" : "fcntl64",
156766e63ce3Schristos 					(unsigned long) (USI) arg1,
156866e63ce3Schristos 					(unsigned long) (USI) arg2,
156966e63ce3Schristos 					(unsigned long) (USI) arg3);
157066e63ce3Schristos 	      break;
157166e63ce3Schristos 	    }
157266e63ce3Schristos 	  break;
157366e63ce3Schristos 
157466e63ce3Schristos 	case TARGET_SYS_uname:
157566e63ce3Schristos 	  {
157666e63ce3Schristos 	    /* Fill in a few constants to appease glibc.  */
157766e63ce3Schristos 	    static char sim_utsname[6][65] =
157866e63ce3Schristos 	    {
157966e63ce3Schristos 	      "Linux",
158066e63ce3Schristos 	      "sim-target",
158166e63ce3Schristos 	      "2.6.27",
158266e63ce3Schristos 	      TARGET_UTSNAME,
158366e63ce3Schristos 	      "cris",		/* Overwritten below.  */
158466e63ce3Schristos 	      "localdomain"
158566e63ce3Schristos 	    };
158666e63ce3Schristos 
158766e63ce3Schristos 	    /* Having the hardware type in Linux equal to the bfd
158866e63ce3Schristos 	       printable name is deliberate: if you make config.guess
158966e63ce3Schristos 	       work on your Linux-type system the usual way, it
159066e63ce3Schristos 	       probably will; either the bfd printable_name or the
159166e63ce3Schristos 	       ambiguous arch_name.  */
159266e63ce3Schristos 	    strcpy (sim_utsname[4], STATE_ARCHITECTURE (sd)->printable_name);
159366e63ce3Schristos 
159466e63ce3Schristos 	    if ((s.write_mem) (cb, &s, arg1, (const char *) sim_utsname,
159566e63ce3Schristos 			       sizeof (sim_utsname))
159666e63ce3Schristos 		!= sizeof (sim_utsname))
159766e63ce3Schristos 	      retval = -cb_host_to_target_errno (cb, EFAULT);
159866e63ce3Schristos 	    else
159966e63ce3Schristos 	      retval = 0;
160066e63ce3Schristos 	    break;
160166e63ce3Schristos 	  }
160266e63ce3Schristos 
160366e63ce3Schristos 	case TARGET_SYS_geteuid32:
160466e63ce3Schristos 	  /* We tell the truth with these.  Maybe we shouldn't, but it
160566e63ce3Schristos 	     should match the "stat" information.  */
160666e63ce3Schristos 	  retval = geteuid ();
160766e63ce3Schristos 	  break;
160866e63ce3Schristos 
160966e63ce3Schristos 	case TARGET_SYS_getuid32:
161066e63ce3Schristos 	  retval = getuid ();
161166e63ce3Schristos 	  break;
161266e63ce3Schristos 
161366e63ce3Schristos 	case TARGET_SYS_getegid32:
161466e63ce3Schristos 	  retval = getegid ();
161566e63ce3Schristos 	  break;
161666e63ce3Schristos 
161766e63ce3Schristos 	case TARGET_SYS_getgid32:
161866e63ce3Schristos 	  retval = getgid ();
161966e63ce3Schristos 	  break;
162066e63ce3Schristos 
162166e63ce3Schristos 	case TARGET_SYS_brk:
162266e63ce3Schristos 	  /* Most often, we just return the argument, like the Linux
162366e63ce3Schristos 	     kernel.  */
162466e63ce3Schristos 	  retval = arg1;
162566e63ce3Schristos 
162666e63ce3Schristos 	  if (arg1 == 0)
162766e63ce3Schristos 	    retval = current_cpu->endbrk;
162866e63ce3Schristos 	  else if (arg1 <= current_cpu->endmem)
162966e63ce3Schristos 	    current_cpu->endbrk = arg1;
163066e63ce3Schristos 	  else
163166e63ce3Schristos 	    {
163266e63ce3Schristos 	      USI new_end = (arg1 + 8191) & ~8191;
163366e63ce3Schristos 
163466e63ce3Schristos 	      /* If the simulator wants to brk more than a certain very
163566e63ce3Schristos 		 large amount, something is wrong.  FIXME: Return an error
163666e63ce3Schristos 		 or abort?  Have command-line selectable?  */
163766e63ce3Schristos 	      if (new_end - current_cpu->endmem > SIM_MAX_ALLOC_CHUNK)
163866e63ce3Schristos 		{
163966e63ce3Schristos 		  current_cpu->endbrk = current_cpu->endmem;
164066e63ce3Schristos 		  retval = current_cpu->endmem;
164166e63ce3Schristos 		  break;
164266e63ce3Schristos 		}
164366e63ce3Schristos 
164466e63ce3Schristos 	      sim_core_attach (sd, NULL, 0, access_read_write_exec, 0,
164566e63ce3Schristos 			       current_cpu->endmem,
164666e63ce3Schristos 			       new_end - current_cpu->endmem,
164766e63ce3Schristos 			       0, NULL, NULL);
164866e63ce3Schristos 	      current_cpu->endbrk = arg1;
164966e63ce3Schristos 	      current_cpu->endmem = new_end;
165066e63ce3Schristos 	    }
165166e63ce3Schristos 	  break;
165266e63ce3Schristos 
165366e63ce3Schristos 	case TARGET_SYS_getpid:
165466e63ce3Schristos 	  /* Correct until CLONE_THREAD is implemented.  */
165566e63ce3Schristos 	  retval = current_cpu->thread_data == NULL
165666e63ce3Schristos 	    ? TARGET_PID
165766e63ce3Schristos 	    : TARGET_PID + current_cpu->thread_data[threadno].threadid;
165866e63ce3Schristos 	  break;
165966e63ce3Schristos 
166066e63ce3Schristos 	case TARGET_SYS_getppid:
166166e63ce3Schristos 	  /* Correct until CLONE_THREAD is implemented.  */
166266e63ce3Schristos 	  retval = current_cpu->thread_data == NULL
166366e63ce3Schristos 	    ? TARGET_PID - 1
166466e63ce3Schristos 	    : (TARGET_PID
166566e63ce3Schristos 	       + current_cpu->thread_data[threadno].parent_threadid);
166666e63ce3Schristos 	  break;
166766e63ce3Schristos 
166866e63ce3Schristos 	case TARGET_SYS_mmap2:
166966e63ce3Schristos 	  {
167066e63ce3Schristos 	    USI addr = arg1;
167166e63ce3Schristos 	    USI len = arg2;
167266e63ce3Schristos 	    USI prot = arg3;
167366e63ce3Schristos 	    USI flags = arg4;
167466e63ce3Schristos 	    USI fd = arg5;
167566e63ce3Schristos 	    USI pgoff = arg6;
167666e63ce3Schristos 
167766e63ce3Schristos 	    /* At 2.6.27, Linux (many (all?) ports, in the mmap2 syscalls)
167866e63ce3Schristos 	       still masked away this bit, so let's just ignore
167966e63ce3Schristos 	       it.  */
168066e63ce3Schristos 	    flags &= ~TARGET_MAP_DENYWRITE;
168166e63ce3Schristos 
168266e63ce3Schristos 	    /* If the simulator wants to mmap more than the very large
168366e63ce3Schristos 	       limit, something is wrong.  FIXME: Return an error or
168466e63ce3Schristos 	       abort?  Have command-line selectable?  */
168566e63ce3Schristos 	    if (len > SIM_MAX_ALLOC_CHUNK)
168666e63ce3Schristos 	      {
168766e63ce3Schristos 		retval = -cb_host_to_target_errno (cb, ENOMEM);
168866e63ce3Schristos 		break;
168966e63ce3Schristos 	      }
169066e63ce3Schristos 
169166e63ce3Schristos 	    if ((prot != (TARGET_PROT_READ | TARGET_PROT_WRITE)
169266e63ce3Schristos 		 && (prot
169366e63ce3Schristos 		     != (TARGET_PROT_READ
169466e63ce3Schristos 			 | TARGET_PROT_WRITE
169566e63ce3Schristos 			 | TARGET_PROT_EXEC))
169666e63ce3Schristos 		 && (prot != (TARGET_PROT_READ | TARGET_PROT_EXEC))
169766e63ce3Schristos 		 && prot != TARGET_PROT_READ)
169866e63ce3Schristos 		|| (flags != (TARGET_MAP_ANONYMOUS | TARGET_MAP_PRIVATE)
169966e63ce3Schristos 		    && flags != TARGET_MAP_PRIVATE
170066e63ce3Schristos 		    && flags != (TARGET_MAP_ANONYMOUS
170166e63ce3Schristos 				 | TARGET_MAP_PRIVATE | TARGET_MAP_FIXED)
170266e63ce3Schristos 		    && flags != (TARGET_MAP_PRIVATE | TARGET_MAP_FIXED)
170366e63ce3Schristos 		    && flags != TARGET_MAP_SHARED)
170466e63ce3Schristos 		|| (fd != (USI) -1
170566e63ce3Schristos 		    && prot != TARGET_PROT_READ
170666e63ce3Schristos 		    && prot != (TARGET_PROT_READ | TARGET_PROT_EXEC)
170766e63ce3Schristos 		    && prot != (TARGET_PROT_READ | TARGET_PROT_WRITE))
170866e63ce3Schristos 		|| (fd == (USI) -1 && pgoff != 0)
170966e63ce3Schristos 		|| (fd != (USI) -1 && (flags & TARGET_MAP_ANONYMOUS)))
171066e63ce3Schristos 	      {
171166e63ce3Schristos 		retval
171266e63ce3Schristos 		  = cris_unknown_syscall (current_cpu, pc,
171366e63ce3Schristos 						 "Unimplemented mmap2 call "
171466e63ce3Schristos 						 "(0x%lx, 0x%lx, 0x%lx, "
171566e63ce3Schristos 						 "0x%lx, 0x%lx, 0x%lx)\n",
171666e63ce3Schristos 						 (unsigned long) arg1,
171766e63ce3Schristos 						 (unsigned long) arg2,
171866e63ce3Schristos 						 (unsigned long) arg3,
171966e63ce3Schristos 						 (unsigned long) arg4,
172066e63ce3Schristos 						 (unsigned long) arg5,
172166e63ce3Schristos 						 (unsigned long) arg6);
172266e63ce3Schristos 		break;
172366e63ce3Schristos 	      }
172466e63ce3Schristos 	    else if (fd != (USI) -1)
172566e63ce3Schristos 	      {
172666e63ce3Schristos 		/* Map a file.  */
172766e63ce3Schristos 
172866e63ce3Schristos 		USI newaddr;
172966e63ce3Schristos 		USI pos;
173066e63ce3Schristos 
173166e63ce3Schristos 		/* A non-aligned argument is allowed for files.  */
173266e63ce3Schristos 		USI newlen = (len + 8191) & ~8191;
173366e63ce3Schristos 
173466e63ce3Schristos 		/* We only support read, read|exec, and read|write,
173566e63ce3Schristos 		   which we should already have checked.  Check again
173666e63ce3Schristos 		   anyway.  */
173766e63ce3Schristos 		if (prot != TARGET_PROT_READ
173866e63ce3Schristos 		    && prot != (TARGET_PROT_READ | TARGET_PROT_EXEC)
173966e63ce3Schristos 		    && prot != (TARGET_PROT_READ | TARGET_PROT_WRITE))
174066e63ce3Schristos 		  abort ();
174166e63ce3Schristos 
174266e63ce3Schristos 		if (flags & TARGET_MAP_FIXED)
174366e63ce3Schristos 		  unmap_pages (sd, &current_cpu->highest_mmapped_page,
174466e63ce3Schristos 			       addr, newlen);
174566e63ce3Schristos 		else if (is_mapped (sd, &current_cpu->highest_mmapped_page,
174666e63ce3Schristos 				    addr, newlen))
174766e63ce3Schristos 		  addr = 0;
174866e63ce3Schristos 
174966e63ce3Schristos 		newaddr
175066e63ce3Schristos 		  = create_map (sd, &current_cpu->highest_mmapped_page,
175166e63ce3Schristos 				addr != 0 || (flags & TARGET_MAP_FIXED)
175266e63ce3Schristos 				? addr : -1,
175366e63ce3Schristos 				newlen);
175466e63ce3Schristos 
175566e63ce3Schristos 		if (newaddr >= (USI) -8191)
175666e63ce3Schristos 		  {
175766e63ce3Schristos 		    abort ();
175866e63ce3Schristos 		    retval = -cb_host_to_target_errno (cb, -(SI) newaddr);
175966e63ce3Schristos 		    break;
176066e63ce3Schristos 		  }
176166e63ce3Schristos 
176266e63ce3Schristos 		/* We were asked for MAP_FIXED, but couldn't.  */
176366e63ce3Schristos 		if ((flags & TARGET_MAP_FIXED) && newaddr != addr)
176466e63ce3Schristos 		  {
176566e63ce3Schristos 		    abort ();
176666e63ce3Schristos 		    unmap_pages (sd, &current_cpu->highest_mmapped_page,
176766e63ce3Schristos 				 newaddr, newlen);
176866e63ce3Schristos 		    retval = -cb_host_to_target_errno (cb, EINVAL);
176966e63ce3Schristos 		    break;
177066e63ce3Schristos 		  }
177166e63ce3Schristos 
177266e63ce3Schristos 		/* Find the current position in the file.  */
177366e63ce3Schristos 		s.func = TARGET_SYS_lseek;
177466e63ce3Schristos 		s.arg1 = fd;
177566e63ce3Schristos 		s.arg2 = 0;
177666e63ce3Schristos 		s.arg3 = SEEK_CUR;
177766e63ce3Schristos 		if (cb_syscall (cb, &s) != CB_RC_OK)
177866e63ce3Schristos 		  abort ();
177966e63ce3Schristos 		pos = s.result;
178066e63ce3Schristos 
178166e63ce3Schristos 		if (s.result < 0)
178266e63ce3Schristos 		  abort ();
178366e63ce3Schristos 
178466e63ce3Schristos 		/* Move to the correct offset in the file.  */
178566e63ce3Schristos 		s.func = TARGET_SYS_lseek;
178666e63ce3Schristos 		s.arg1 = fd;
178766e63ce3Schristos 		s.arg2 = pgoff*8192;
178866e63ce3Schristos 		s.arg3 = SEEK_SET;
178966e63ce3Schristos 		if (cb_syscall (cb, &s) != CB_RC_OK)
179066e63ce3Schristos 		  abort ();
179166e63ce3Schristos 
179266e63ce3Schristos 		if (s.result < 0)
179366e63ce3Schristos 		  abort ();
179466e63ce3Schristos 
179566e63ce3Schristos 		/* Use the standard read callback to read in "len"
179666e63ce3Schristos 		   bytes.  */
179766e63ce3Schristos 		s.func = TARGET_SYS_read;
179866e63ce3Schristos 		s.arg1 = fd;
179966e63ce3Schristos 		s.arg2 = newaddr;
180066e63ce3Schristos 		s.arg3 = len;
180166e63ce3Schristos 		if (cb_syscall (cb, &s) != CB_RC_OK)
180266e63ce3Schristos 		  abort ();
180366e63ce3Schristos 
180466e63ce3Schristos 		/* If the result is a page or more lesser than what
180566e63ce3Schristos 		   was requested, something went wrong.  */
180666e63ce3Schristos 		if (len >= 8192 && (USI) s.result <= len - 8192)
180766e63ce3Schristos 		  abort ();
180866e63ce3Schristos 
180966e63ce3Schristos 		/* After reading, we need to go back to the previous
181066e63ce3Schristos                    position in the file.  */
181166e63ce3Schristos 		s.func = TARGET_SYS_lseek;
181266e63ce3Schristos 		s.arg1 = fd;
181366e63ce3Schristos 		s.arg2 = pos;
181466e63ce3Schristos 		s.arg3 = SEEK_SET;
181566e63ce3Schristos 		if (cb_syscall (cb, &s) != CB_RC_OK)
181666e63ce3Schristos 		  abort ();
181766e63ce3Schristos 		if (pos != (USI) s.result)
181866e63ce3Schristos 		  abort ();
181966e63ce3Schristos 
182066e63ce3Schristos 		retval = newaddr;
182166e63ce3Schristos 	      }
182266e63ce3Schristos 	    else
182366e63ce3Schristos 	      {
182466e63ce3Schristos 		USI newlen = (len + 8191) & ~8191;
182566e63ce3Schristos 		USI newaddr;
182666e63ce3Schristos 
182766e63ce3Schristos 		if (flags & TARGET_MAP_FIXED)
182866e63ce3Schristos 		  unmap_pages (sd, &current_cpu->highest_mmapped_page,
182966e63ce3Schristos 			       addr, newlen);
183066e63ce3Schristos 		else if (is_mapped (sd, &current_cpu->highest_mmapped_page,
183166e63ce3Schristos 				    addr, newlen))
183266e63ce3Schristos 		  addr = 0;
183366e63ce3Schristos 
183466e63ce3Schristos 		newaddr = create_map (sd, &current_cpu->highest_mmapped_page,
183566e63ce3Schristos 				      addr != 0 || (flags & TARGET_MAP_FIXED)
183666e63ce3Schristos 				      ? addr : -1,
183766e63ce3Schristos 				      newlen);
183866e63ce3Schristos 
183966e63ce3Schristos 		if (newaddr >= (USI) -8191)
184066e63ce3Schristos 		  retval = -cb_host_to_target_errno (cb, -(SI) newaddr);
184166e63ce3Schristos 		else
184266e63ce3Schristos 		  retval = newaddr;
184366e63ce3Schristos 
184466e63ce3Schristos 		if ((flags & TARGET_MAP_FIXED) && newaddr != addr)
184566e63ce3Schristos 		  {
184666e63ce3Schristos 		    abort ();
184766e63ce3Schristos 		    unmap_pages (sd, &current_cpu->highest_mmapped_page,
184866e63ce3Schristos 				 newaddr, newlen);
184966e63ce3Schristos 		    retval = -cb_host_to_target_errno (cb, EINVAL);
185066e63ce3Schristos 		    break;
185166e63ce3Schristos 		  }
185266e63ce3Schristos 	      }
185366e63ce3Schristos 	    break;
185466e63ce3Schristos 	  }
185566e63ce3Schristos 
185666e63ce3Schristos 	case TARGET_SYS_mprotect:
185766e63ce3Schristos 	  {
185866e63ce3Schristos 	    /* We only cover the case of linuxthreads mprotecting out
185966e63ce3Schristos 	       its stack guard page and of dynamic loading mprotecting
186066e63ce3Schristos 	       away the data (for some reason the whole library, then
186166e63ce3Schristos 	       mprotects away the data part and mmap-FIX:es it again.  */
186266e63ce3Schristos 	    USI addr = arg1;
186366e63ce3Schristos 	    USI len = arg2;
186466e63ce3Schristos 	    USI prot = arg3;
186566e63ce3Schristos 
186666e63ce3Schristos 	    if (prot != TARGET_PROT_NONE
186766e63ce3Schristos 		|| !is_mapped_only (sd, &current_cpu->highest_mmapped_page,
186866e63ce3Schristos 				    addr, (len + 8191) & ~8191))
186966e63ce3Schristos 	      {
187066e63ce3Schristos 		retval
187166e63ce3Schristos 		  = cris_unknown_syscall (current_cpu, pc,
187266e63ce3Schristos 					  "Unimplemented mprotect call "
187366e63ce3Schristos 					  "(0x%lx, 0x%lx, 0x%lx)\n",
187466e63ce3Schristos 					  (unsigned long) arg1,
187566e63ce3Schristos 					  (unsigned long) arg2,
187666e63ce3Schristos 					  (unsigned long) arg3);
187766e63ce3Schristos 		break;
187866e63ce3Schristos 	      }
187966e63ce3Schristos 
188066e63ce3Schristos 	    /* Just ignore this.  We could make this equal to munmap,
188166e63ce3Schristos 	       but then we'd have to make sure no anon mmaps gets this
188266e63ce3Schristos 	       address before a subsequent MAP_FIXED mmap intended to
188366e63ce3Schristos 	       override it.  */
188466e63ce3Schristos 	    retval = 0;
188566e63ce3Schristos 	    break;
188666e63ce3Schristos 	  }
188766e63ce3Schristos 
188866e63ce3Schristos 	case TARGET_SYS_ioctl:
188966e63ce3Schristos 	  {
189066e63ce3Schristos 	    /* We support only a very limited functionality: checking
189166e63ce3Schristos 	       stdout with TCGETS to perform the isatty function.  The
189266e63ce3Schristos 	       TCGETS ioctl isn't actually performed or the result used by
189366e63ce3Schristos 	       an isatty () caller in a "hello, world" program; only the
189466e63ce3Schristos 	       return value is then used.  Maybe we shouldn't care about
189566e63ce3Schristos 	       the environment of the simulator regarding isatty, but
189666e63ce3Schristos 	       that's been working before, in the xsim simulator.  */
189766e63ce3Schristos 	    if (arg2 == TARGET_TCGETS && arg1 == 1)
189866e63ce3Schristos 	      retval = isatty (1) ? 0 : cb_host_to_target_errno (cb, EINVAL);
189966e63ce3Schristos 	    else
190066e63ce3Schristos 	      retval = -cb_host_to_target_errno (cb, EINVAL);
190166e63ce3Schristos 	    break;
190266e63ce3Schristos 	  }
190366e63ce3Schristos 
190466e63ce3Schristos 	case TARGET_SYS_munmap:
190566e63ce3Schristos 	  {
190666e63ce3Schristos 	    USI addr = arg1;
190766e63ce3Schristos 	    USI len = arg2;
190866e63ce3Schristos 	    USI result
190966e63ce3Schristos 	      = unmap_pages (sd, &current_cpu->highest_mmapped_page, addr,
191066e63ce3Schristos 			     len);
191166e63ce3Schristos 	    retval = result != 0 ? -cb_host_to_target_errno (cb, result) : 0;
191266e63ce3Schristos 	    break;
191366e63ce3Schristos 	  }
191466e63ce3Schristos 
191566e63ce3Schristos 	case TARGET_SYS_wait4:
191666e63ce3Schristos 	  {
191766e63ce3Schristos 	    int i;
191866e63ce3Schristos 	    USI pid = arg1;
191966e63ce3Schristos 	    USI saddr = arg2;
192066e63ce3Schristos 	    USI options = arg3;
192166e63ce3Schristos 	    USI rusagep = arg4;
192266e63ce3Schristos 
192366e63ce3Schristos 	    /* FIXME: We're not properly implementing __WCLONE, and we
192466e63ce3Schristos 	       don't really need the special casing so we might as well
192566e63ce3Schristos 	       make this general.  */
192666e63ce3Schristos 	    if ((!(pid == (USI) -1
192766e63ce3Schristos 		   && options == (TARGET___WCLONE | TARGET_WNOHANG)
192866e63ce3Schristos 		   && saddr != 0)
192966e63ce3Schristos 		 && !(pid > 0
193066e63ce3Schristos 		      && (options == TARGET___WCLONE
193166e63ce3Schristos 			  || options == TARGET___WALL)))
193266e63ce3Schristos 		|| rusagep != 0
193366e63ce3Schristos 		|| current_cpu->thread_data == NULL)
193466e63ce3Schristos 	      {
193566e63ce3Schristos 		retval
193666e63ce3Schristos 		  = cris_unknown_syscall (current_cpu, pc,
193766e63ce3Schristos 					  "Unimplemented wait4 call "
193866e63ce3Schristos 					  "(0x%lx, 0x%lx, 0x%lx, 0x%lx)\n",
193966e63ce3Schristos 					  (unsigned long) arg1,
194066e63ce3Schristos 					  (unsigned long) arg2,
194166e63ce3Schristos 					  (unsigned long) arg3,
194266e63ce3Schristos 					  (unsigned long) arg4);
194366e63ce3Schristos 		break;
194466e63ce3Schristos 	      }
194566e63ce3Schristos 
194666e63ce3Schristos 	    if (pid == (USI) -1)
194766e63ce3Schristos 	      for (i = 1; i < SIM_TARGET_MAX_THREADS; i++)
194866e63ce3Schristos 		{
194966e63ce3Schristos 		  if (current_cpu->thread_data[threadno].threadid
195066e63ce3Schristos 		      == current_cpu->thread_data[i].parent_threadid
195166e63ce3Schristos 		      && current_cpu->thread_data[i].threadid != 0
195266e63ce3Schristos 		      && current_cpu->thread_data[i].cpu_context == NULL)
195366e63ce3Schristos 		    {
195466e63ce3Schristos 		      /* A zombied child.  Get the exit value and clear the
195566e63ce3Schristos 			 zombied entry so it will be reused.  */
195666e63ce3Schristos 		      sim_core_write_unaligned_4 (current_cpu, pc, 0, saddr,
195766e63ce3Schristos 						  current_cpu
195866e63ce3Schristos 						  ->thread_data[i].exitval);
195966e63ce3Schristos 		      retval
196066e63ce3Schristos 			= current_cpu->thread_data[i].threadid + TARGET_PID;
196166e63ce3Schristos 		      memset (&current_cpu->thread_data[i], 0,
196266e63ce3Schristos 			      sizeof (current_cpu->thread_data[i]));
196366e63ce3Schristos 		      goto outer_break;
196466e63ce3Schristos 		    }
196566e63ce3Schristos 		}
196666e63ce3Schristos 	    else
196766e63ce3Schristos 	      {
196866e63ce3Schristos 		/* We're waiting for a specific PID.  If we don't find
196966e63ce3Schristos 		   it zombied on this run, rerun the syscall.  */
197066e63ce3Schristos 		for (i = 1; i < SIM_TARGET_MAX_THREADS; i++)
197166e63ce3Schristos 		  if (pid == current_cpu->thread_data[i].threadid + TARGET_PID
197266e63ce3Schristos 		      && current_cpu->thread_data[i].cpu_context == NULL)
197366e63ce3Schristos 		    {
197466e63ce3Schristos 		      if (saddr != 0)
197566e63ce3Schristos 			/* Get the exit value if the caller wants it.  */
197666e63ce3Schristos 			sim_core_write_unaligned_4 (current_cpu, pc, 0,
197766e63ce3Schristos 						    saddr,
197866e63ce3Schristos 						    current_cpu
197966e63ce3Schristos 						    ->thread_data[i]
198066e63ce3Schristos 						    .exitval);
198166e63ce3Schristos 
198266e63ce3Schristos 		      retval
198366e63ce3Schristos 			= current_cpu->thread_data[i].threadid + TARGET_PID;
198466e63ce3Schristos 		      memset (&current_cpu->thread_data[i], 0,
198566e63ce3Schristos 			      sizeof (current_cpu->thread_data[i]));
198666e63ce3Schristos 
198766e63ce3Schristos 		      goto outer_break;
198866e63ce3Schristos 		    }
198966e63ce3Schristos 
199066e63ce3Schristos 		sim_pc_set (current_cpu, pc);
199166e63ce3Schristos 	      }
199266e63ce3Schristos 
199366e63ce3Schristos 	    retval = -cb_host_to_target_errno (cb, ECHILD);
199466e63ce3Schristos 	  outer_break:
199566e63ce3Schristos 	    break;
199666e63ce3Schristos 	  }
199766e63ce3Schristos 
199866e63ce3Schristos 	case TARGET_SYS_rt_sigaction:
199966e63ce3Schristos 	  {
200066e63ce3Schristos 	    USI signum = arg1;
200166e63ce3Schristos 	    USI old_sa = arg3;
200266e63ce3Schristos 	    USI new_sa = arg2;
200366e63ce3Schristos 
200466e63ce3Schristos 	    /* The kernel says:
200566e63ce3Schristos 	       struct sigaction {
200666e63ce3Schristos 			__sighandler_t sa_handler;
200766e63ce3Schristos 			unsigned long sa_flags;
200866e63ce3Schristos 			void (*sa_restorer)(void);
200966e63ce3Schristos 			sigset_t sa_mask;
201066e63ce3Schristos 	       }; */
201166e63ce3Schristos 
201266e63ce3Schristos 	    if (old_sa != 0)
201366e63ce3Schristos 	      {
201466e63ce3Schristos 		sim_core_write_unaligned_4 (current_cpu, pc, 0, old_sa + 0,
201566e63ce3Schristos 					    current_cpu->sighandler[signum]);
201666e63ce3Schristos 		sim_core_write_unaligned_4 (current_cpu, pc, 0, arg3 + 4, 0);
201766e63ce3Schristos 		sim_core_write_unaligned_4 (current_cpu, pc, 0, arg3 + 8, 0);
201866e63ce3Schristos 
201966e63ce3Schristos 		/* We'll assume _NSIG_WORDS is 2 for the kernel.  */
202066e63ce3Schristos 		sim_core_write_unaligned_4 (current_cpu, pc, 0, arg3 + 12, 0);
202166e63ce3Schristos 		sim_core_write_unaligned_4 (current_cpu, pc, 0, arg3 + 16, 0);
202266e63ce3Schristos 	      }
202366e63ce3Schristos 	    if (new_sa != 0)
202466e63ce3Schristos 	      {
202566e63ce3Schristos 		USI target_sa_handler
202666e63ce3Schristos 		  = sim_core_read_unaligned_4 (current_cpu, pc, 0, new_sa);
202766e63ce3Schristos 		USI target_sa_flags
202866e63ce3Schristos 		  = sim_core_read_unaligned_4 (current_cpu, pc, 0, new_sa + 4);
202966e63ce3Schristos 		USI target_sa_restorer
203066e63ce3Schristos 		  = sim_core_read_unaligned_4 (current_cpu, pc, 0, new_sa + 8);
203166e63ce3Schristos 		USI target_sa_mask_low
203266e63ce3Schristos 		  = sim_core_read_unaligned_4 (current_cpu, pc, 0, new_sa + 12);
203366e63ce3Schristos 		USI target_sa_mask_high
203466e63ce3Schristos 		  = sim_core_read_unaligned_4 (current_cpu, pc, 0, new_sa + 16);
203566e63ce3Schristos 
203666e63ce3Schristos 		/* We won't interrupt a syscall so we won't restart it,
203766e63ce3Schristos 		   but a signal(2) call ends up syscalling rt_sigaction
203866e63ce3Schristos 		   with this flag, so we have to handle it.  The
203966e63ce3Schristos 		   sa_restorer field contains garbage when not
204066e63ce3Schristos 		   TARGET_SA_RESTORER, so don't look at it.  For the
204166e63ce3Schristos 		   time being, we don't nest sighandlers, so we
204266e63ce3Schristos 		   ignore the sa_mask, which simplifies things.  */
204366e63ce3Schristos 		if ((target_sa_flags != 0
204466e63ce3Schristos 		     && target_sa_flags != TARGET_SA_RESTART
204566e63ce3Schristos 		     && target_sa_flags != (TARGET_SA_RESTART|TARGET_SA_SIGINFO))
204666e63ce3Schristos 		    || target_sa_handler == 0)
204766e63ce3Schristos 		  {
204866e63ce3Schristos 		    retval
204966e63ce3Schristos 		      = cris_unknown_syscall (current_cpu, pc,
205066e63ce3Schristos 					      "Unimplemented rt_sigaction "
205166e63ce3Schristos 					      "syscall "
205266e63ce3Schristos 					      "(0x%lx, 0x%lx: "
205366e63ce3Schristos 					      "[0x%x, 0x%x, 0x%x, "
205466e63ce3Schristos 					      "{0x%x, 0x%x}], 0x%lx)\n",
205566e63ce3Schristos 					      (unsigned long) arg1,
205666e63ce3Schristos 					      (unsigned long) arg2,
205766e63ce3Schristos 					      target_sa_handler,
205866e63ce3Schristos 					      target_sa_flags,
205966e63ce3Schristos 					      target_sa_restorer,
206066e63ce3Schristos 					      target_sa_mask_low,
206166e63ce3Schristos 					      target_sa_mask_high,
206266e63ce3Schristos 					      (unsigned long) arg3);
206366e63ce3Schristos 		    break;
206466e63ce3Schristos 		  }
206566e63ce3Schristos 
206666e63ce3Schristos 		current_cpu->sighandler[signum] = target_sa_handler;
206766e63ce3Schristos 
206866e63ce3Schristos 		/* Because we may have unblocked signals, one may now be
206966e63ce3Schristos 		   pending, if there are threads, that is.  */
207066e63ce3Schristos 		if (current_cpu->thread_data)
207166e63ce3Schristos 		  current_cpu->thread_data[threadno].sigpending = 1;
207266e63ce3Schristos 	      }
207366e63ce3Schristos 	    retval = 0;
207466e63ce3Schristos 	    break;
207566e63ce3Schristos 	  }
207666e63ce3Schristos 
207766e63ce3Schristos 	case TARGET_SYS_mremap:
207866e63ce3Schristos 	  {
207966e63ce3Schristos 	    USI addr = arg1;
208066e63ce3Schristos 	    USI old_len = arg2;
208166e63ce3Schristos 	    USI new_len = arg3;
208266e63ce3Schristos 	    USI flags = arg4;
208366e63ce3Schristos 	    USI new_addr = arg5;
208466e63ce3Schristos 	    USI mapped_addr;
208566e63ce3Schristos 
208666e63ce3Schristos 	    if (new_len == old_len)
208766e63ce3Schristos 	      /* The program and/or library is possibly confused but
208866e63ce3Schristos 		 this is a valid call.  Happens with ipps-1.40 on file
208966e63ce3Schristos 		 svs_all.  */
209066e63ce3Schristos 	      retval = addr;
209166e63ce3Schristos 	    else if (new_len < old_len)
209266e63ce3Schristos 	      {
209366e63ce3Schristos 		/* Shrinking is easy.  */
209466e63ce3Schristos 		if (unmap_pages (sd, &current_cpu->highest_mmapped_page,
209566e63ce3Schristos 				 addr + new_len, old_len - new_len) != 0)
209666e63ce3Schristos 		  retval = -cb_host_to_target_errno (cb, EINVAL);
209766e63ce3Schristos 		else
209866e63ce3Schristos 		  retval = addr;
209966e63ce3Schristos 	      }
210066e63ce3Schristos 	    else if (! is_mapped (sd, &current_cpu->highest_mmapped_page,
210166e63ce3Schristos 				  addr + old_len, new_len - old_len))
210266e63ce3Schristos 	      {
210366e63ce3Schristos 		/* If the extension isn't mapped, we can just add it.  */
210466e63ce3Schristos 		mapped_addr
210566e63ce3Schristos 		  = create_map (sd, &current_cpu->highest_mmapped_page,
210666e63ce3Schristos 				addr + old_len, new_len - old_len);
210766e63ce3Schristos 
210866e63ce3Schristos 		if (mapped_addr > (USI) -8192)
210966e63ce3Schristos 		  retval = -cb_host_to_target_errno (cb, -(SI) mapped_addr);
211066e63ce3Schristos 		else
211166e63ce3Schristos 		  retval = addr;
211266e63ce3Schristos 	      }
211366e63ce3Schristos 	    else if (flags & TARGET_MREMAP_MAYMOVE)
211466e63ce3Schristos 	      {
211566e63ce3Schristos 		/* Create a whole new map and copy the contents
211666e63ce3Schristos 		   block-by-block there.  We ignore the new_addr argument
211766e63ce3Schristos 		   for now.  */
211866e63ce3Schristos 		char buf[8192];
211966e63ce3Schristos 		USI prev_addr = addr;
212066e63ce3Schristos 		USI prev_len = old_len;
212166e63ce3Schristos 
212266e63ce3Schristos 		mapped_addr
212366e63ce3Schristos 		  = create_map (sd, &current_cpu->highest_mmapped_page,
212466e63ce3Schristos 				-1, new_len);
212566e63ce3Schristos 
212666e63ce3Schristos 		if (mapped_addr > (USI) -8192)
212766e63ce3Schristos 		  {
212866e63ce3Schristos 		    retval = -cb_host_to_target_errno (cb, -(SI) new_addr);
212966e63ce3Schristos 		    break;
213066e63ce3Schristos 		  }
213166e63ce3Schristos 
213266e63ce3Schristos 		retval = mapped_addr;
213366e63ce3Schristos 
213466e63ce3Schristos 		for (; old_len > 0;
213566e63ce3Schristos 		     old_len -= 8192, mapped_addr += 8192, addr += 8192)
213666e63ce3Schristos 		  {
213766e63ce3Schristos 		    if (sim_core_read_buffer (sd, current_cpu, read_map, buf,
213866e63ce3Schristos 					      addr, 8192) != 8192
213966e63ce3Schristos 			|| sim_core_write_buffer (sd, current_cpu, 0, buf,
214066e63ce3Schristos 						  mapped_addr, 8192) != 8192)
214166e63ce3Schristos 		      abort ();
214266e63ce3Schristos 		  }
214366e63ce3Schristos 
214466e63ce3Schristos 		if (unmap_pages (sd, &current_cpu->highest_mmapped_page,
214566e63ce3Schristos 				 prev_addr, prev_len) != 0)
214666e63ce3Schristos 		  abort ();
214766e63ce3Schristos 	      }
214866e63ce3Schristos 	    else
214966e63ce3Schristos 	      retval = -cb_host_to_target_errno (cb, -ENOMEM);
215066e63ce3Schristos 	    break;
215166e63ce3Schristos 	  }
215266e63ce3Schristos 
215366e63ce3Schristos 	case TARGET_SYS_poll:
215466e63ce3Schristos 	  {
215566e63ce3Schristos 	    int npollfds = arg2;
215666e63ce3Schristos 	    int timeout = arg3;
215766e63ce3Schristos 	    SI ufds = arg1;
215866e63ce3Schristos 	    SI fd = -1;
215966e63ce3Schristos 	    HI events = -1;
216066e63ce3Schristos 	    HI revents = 0;
216166e63ce3Schristos 	    struct stat buf;
216266e63ce3Schristos 	    int i;
216366e63ce3Schristos 
216466e63ce3Schristos 	    /* The kernel says:
216566e63ce3Schristos 		struct pollfd {
216666e63ce3Schristos 		     int fd;
216766e63ce3Schristos 		     short events;
216866e63ce3Schristos 		     short revents;
216966e63ce3Schristos 		}; */
217066e63ce3Schristos 
217166e63ce3Schristos 	    /* Check that this is the expected poll call from
217266e63ce3Schristos 	       linuxthreads/manager.c; we don't support anything else.
217366e63ce3Schristos 	       Remember, fd == 0 isn't supported.  */
217466e63ce3Schristos 	    if (npollfds != 1
217566e63ce3Schristos 		|| ((fd = sim_core_read_unaligned_4 (current_cpu, pc,
217666e63ce3Schristos 						     0, ufds)) <= 0)
217766e63ce3Schristos 		|| ((events = sim_core_read_unaligned_2 (current_cpu, pc,
217866e63ce3Schristos 							 0, ufds + 4))
217966e63ce3Schristos 		    != TARGET_POLLIN)
21805e098073Schristos 		|| ((cb->to_fstat) (cb, fd, &buf) != 0
218166e63ce3Schristos 		    || (buf.st_mode & S_IFIFO) == 0)
218266e63ce3Schristos 		|| current_cpu->thread_data == NULL)
218366e63ce3Schristos 	      {
218466e63ce3Schristos 		retval
218566e63ce3Schristos 		  = cris_unknown_syscall (current_cpu, pc,
218666e63ce3Schristos 					  "Unimplemented poll syscall "
218766e63ce3Schristos 					  "(0x%lx: [0x%x, 0x%x, x], "
218866e63ce3Schristos 					  "0x%lx, 0x%lx)\n",
218966e63ce3Schristos 					  (unsigned long) arg1, fd, events,
219066e63ce3Schristos 					  (unsigned long) arg2,
219166e63ce3Schristos 					  (unsigned long) arg3);
219266e63ce3Schristos 		break;
219366e63ce3Schristos 	      }
219466e63ce3Schristos 
219566e63ce3Schristos 	    retval = 0;
219666e63ce3Schristos 
219766e63ce3Schristos 	    /* Iterate over threads; find a marker that a writer is
219866e63ce3Schristos 	       sleeping, waiting for a reader.  */
219966e63ce3Schristos 	    for (i = 0; i < SIM_TARGET_MAX_THREADS; i++)
220066e63ce3Schristos 	      if (current_cpu->thread_data[i].cpu_context != NULL
220166e63ce3Schristos 		  && current_cpu->thread_data[i].pipe_read_fd == fd)
220266e63ce3Schristos 		{
220366e63ce3Schristos 		  revents = TARGET_POLLIN;
220466e63ce3Schristos 		  retval = 1;
220566e63ce3Schristos 		  break;
220666e63ce3Schristos 		}
220766e63ce3Schristos 
220866e63ce3Schristos 	    /* Timeout decreases with whatever time passed between the
220966e63ce3Schristos 	       last syscall and this.  That's not exactly right for the
221066e63ce3Schristos 	       first call, but it's close enough that it isn't
221166e63ce3Schristos 	       worthwhile to complicate matters by making that a special
221266e63ce3Schristos 	       case.  */
221366e63ce3Schristos 	    timeout
221466e63ce3Schristos 	      -= (TARGET_TIME_MS (current_cpu)
221566e63ce3Schristos 		  - (current_cpu->thread_data[threadno].last_execution));
221666e63ce3Schristos 
221766e63ce3Schristos 	    /* Arrange to repeat this syscall until timeout or event,
221866e63ce3Schristos                decreasing timeout at each iteration.  */
221966e63ce3Schristos 	    if (timeout > 0 && revents == 0)
222066e63ce3Schristos 	      {
222166e63ce3Schristos 		bfd_byte timeout_buf[4];
222266e63ce3Schristos 
222366e63ce3Schristos 		bfd_putl32 (timeout, timeout_buf);
222466e63ce3Schristos 		(*CPU_REG_STORE (current_cpu)) (current_cpu,
222566e63ce3Schristos 						H_GR_R12, timeout_buf, 4);
222666e63ce3Schristos 		sim_pc_set (current_cpu, pc);
222766e63ce3Schristos 		retval = arg1;
222866e63ce3Schristos 		break;
222966e63ce3Schristos 	      }
223066e63ce3Schristos 
223166e63ce3Schristos 	    sim_core_write_unaligned_2 (current_cpu, pc, 0, ufds + 4 + 2,
223266e63ce3Schristos 					revents);
223366e63ce3Schristos 	    break;
223466e63ce3Schristos 	  }
223566e63ce3Schristos 
223666e63ce3Schristos 	case TARGET_SYS_time:
223766e63ce3Schristos 	  {
223866e63ce3Schristos 	    retval = (int) (*cb->time) (cb, 0L);
223966e63ce3Schristos 
224066e63ce3Schristos 	    /* At time of this writing, CB_SYSCALL_time doesn't do the
224166e63ce3Schristos 	       part of setting *arg1 to the return value.  */
224266e63ce3Schristos 	    if (arg1)
224366e63ce3Schristos 	      sim_core_write_unaligned_4 (current_cpu, pc, 0, arg1, retval);
224466e63ce3Schristos 	    break;
224566e63ce3Schristos 	  }
224666e63ce3Schristos 
224766e63ce3Schristos 	case TARGET_SYS_gettimeofday:
224866e63ce3Schristos 	  if (arg1 != 0)
224966e63ce3Schristos 	    {
225066e63ce3Schristos 	      USI ts = TARGET_TIME (current_cpu);
225166e63ce3Schristos 	      USI tms = TARGET_TIME_MS (current_cpu);
225266e63ce3Schristos 
225366e63ce3Schristos 	      /* First dword is seconds since TARGET_EPOCH.  */
225466e63ce3Schristos 	      sim_core_write_unaligned_4 (current_cpu, pc, 0, arg1, ts);
225566e63ce3Schristos 
225666e63ce3Schristos 	      /* Second dword is microseconds.  */
225766e63ce3Schristos 	      sim_core_write_unaligned_4 (current_cpu, pc, 0, arg1 + 4,
225866e63ce3Schristos 					  (tms % 1000) * 1000);
225966e63ce3Schristos 	    }
226066e63ce3Schristos 	  if (arg2 != 0)
226166e63ce3Schristos 	    {
226266e63ce3Schristos 	      /* Time-zone info is always cleared.  */
226366e63ce3Schristos 	      sim_core_write_unaligned_4 (current_cpu, pc, 0, arg2, 0);
226466e63ce3Schristos 	      sim_core_write_unaligned_4 (current_cpu, pc, 0, arg2 + 4, 0);
226566e63ce3Schristos 	    }
226666e63ce3Schristos 	  retval = 0;
226766e63ce3Schristos 	  break;
226866e63ce3Schristos 
226966e63ce3Schristos 	case TARGET_SYS_llseek:
227066e63ce3Schristos 	  {
227166e63ce3Schristos 	    /* If it fits, tweak parameters to fit the "generic" 32-bit
227266e63ce3Schristos 	       lseek and use that.  */
227366e63ce3Schristos 	    SI fd = arg1;
227466e63ce3Schristos 	    SI offs_hi = arg2;
227566e63ce3Schristos 	    SI offs_lo = arg3;
227666e63ce3Schristos 	    SI resultp = arg4;
227766e63ce3Schristos 	    SI whence = arg5;
227866e63ce3Schristos 	    retval = 0;
227966e63ce3Schristos 
228066e63ce3Schristos 	    if (!((offs_hi == 0 && offs_lo >= 0)
228166e63ce3Schristos 		  || (offs_hi == -1 &&  offs_lo < 0)))
228266e63ce3Schristos 	      {
228366e63ce3Schristos 		retval
228466e63ce3Schristos 		  = cris_unknown_syscall (current_cpu, pc,
228566e63ce3Schristos 					  "Unimplemented llseek offset,"
228666e63ce3Schristos 					  " fd %d: 0x%x:0x%x\n",
228766e63ce3Schristos 					  fd, (unsigned) arg2,
228866e63ce3Schristos 					  (unsigned) arg3);
228966e63ce3Schristos 		break;
229066e63ce3Schristos 	      }
229166e63ce3Schristos 
229266e63ce3Schristos 	    s.func = TARGET_SYS_lseek;
229366e63ce3Schristos 	    s.arg2 = offs_lo;
229466e63ce3Schristos 	    s.arg3 = whence;
229566e63ce3Schristos 	    if (cb_syscall (cb, &s) != CB_RC_OK)
229666e63ce3Schristos 	      {
229766e63ce3Schristos 		sim_io_eprintf (sd, "Break 13: invalid %d?  Returned %ld\n", callnum,
229866e63ce3Schristos 				s.result);
229966e63ce3Schristos 		sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped, SIM_SIGILL);
230066e63ce3Schristos 	      }
230166e63ce3Schristos 	    if (s.result < 0)
230266e63ce3Schristos 	      retval = -s.errcode;
230366e63ce3Schristos 	    else
230466e63ce3Schristos 	      {
230566e63ce3Schristos 		sim_core_write_unaligned_4 (current_cpu, pc, 0, resultp,
230666e63ce3Schristos 					    s.result);
230766e63ce3Schristos 		sim_core_write_unaligned_4 (current_cpu, pc, 0, resultp + 4,
230866e63ce3Schristos 					    s.result < 0 ? -1 : 0);
230966e63ce3Schristos 	      }
231066e63ce3Schristos 	    break;
231166e63ce3Schristos 	  }
231266e63ce3Schristos 
231366e63ce3Schristos 	  /* ssize_t writev(int fd, const struct iovec *iov, int iovcnt);
231466e63ce3Schristos 	      where:
231566e63ce3Schristos 	     struct iovec {
231666e63ce3Schristos 	       void  *iov_base;    Starting address
231766e63ce3Schristos                size_t iov_len;     Number of bytes to transfer
231866e63ce3Schristos 	     }; */
231966e63ce3Schristos 	case TARGET_SYS_writev:
232066e63ce3Schristos 	  {
232166e63ce3Schristos 	    SI fd = arg1;
232266e63ce3Schristos 	    SI iov = arg2;
232366e63ce3Schristos 	    SI iovcnt = arg3;
232466e63ce3Schristos 	    SI retcnt = 0;
232566e63ce3Schristos 	    int i;
232666e63ce3Schristos 
232766e63ce3Schristos 	    /* We'll ignore strict error-handling and just do multiple write calls.  */
232866e63ce3Schristos 	    for (i = 0; i < iovcnt; i++)
232966e63ce3Schristos 	      {
233066e63ce3Schristos 		int sysret;
233166e63ce3Schristos 		USI iov_base
233266e63ce3Schristos 		  = sim_core_read_unaligned_4 (current_cpu, pc, 0,
233366e63ce3Schristos 					       iov + 8*i);
233466e63ce3Schristos 		USI iov_len
233566e63ce3Schristos 		  = sim_core_read_unaligned_4 (current_cpu, pc, 0,
233666e63ce3Schristos 					       iov + 8*i + 4);
233766e63ce3Schristos 
233866e63ce3Schristos 		s.func = TARGET_SYS_write;
233966e63ce3Schristos 		s.arg1 = fd;
234066e63ce3Schristos 		s.arg2 = iov_base;
234166e63ce3Schristos 		s.arg3 = iov_len;
234266e63ce3Schristos 
234366e63ce3Schristos 		if (cb_syscall (cb, &s) != CB_RC_OK)
234466e63ce3Schristos 		  abort ();
234566e63ce3Schristos 		sysret = s.result == -1 ? -s.errcode : s.result;
234666e63ce3Schristos 
234766e63ce3Schristos 		if (sysret != iov_len)
234866e63ce3Schristos 		  {
234966e63ce3Schristos 		    if (i != 0)
235066e63ce3Schristos 		      abort ();
235166e63ce3Schristos 		    retcnt = sysret;
235266e63ce3Schristos 		    break;
235366e63ce3Schristos 		  }
235466e63ce3Schristos 
235566e63ce3Schristos 		retcnt += iov_len;
235666e63ce3Schristos 	      }
235766e63ce3Schristos 
235866e63ce3Schristos 	    retval = retcnt;
235966e63ce3Schristos 	  }
236066e63ce3Schristos 	  break;
236166e63ce3Schristos 
236266e63ce3Schristos 	/* This one does have a generic callback function, but at the time
236366e63ce3Schristos 	   of this writing, cb_syscall does not have code for it, and we
236466e63ce3Schristos 	   need target-specific code for the threads implementation
236566e63ce3Schristos 	   anyway.  */
236666e63ce3Schristos 	case TARGET_SYS_kill:
236766e63ce3Schristos 	  {
236866e63ce3Schristos 	    USI pid = arg1;
236966e63ce3Schristos 	    USI sig = arg2;
237066e63ce3Schristos 
237166e63ce3Schristos 	    retval = 0;
237266e63ce3Schristos 
237366e63ce3Schristos 	    /* At kill(2), glibc sets signal masks such that the thread
237466e63ce3Schristos 	       machinery is initialized.  Still, there is and was only
237566e63ce3Schristos 	       one thread.  */
237666e63ce3Schristos 	    if (current_cpu->max_threadid == 0)
237766e63ce3Schristos 	      {
237866e63ce3Schristos 		if (pid != TARGET_PID)
237966e63ce3Schristos 		  {
238066e63ce3Schristos 		    retval = -cb_host_to_target_errno (cb, EPERM);
238166e63ce3Schristos 		    break;
238266e63ce3Schristos 		  }
238366e63ce3Schristos 
238466e63ce3Schristos 		/* FIXME: Signal infrastructure (target-to-sim mapping).  */
238566e63ce3Schristos 		if (sig == TARGET_SIGABRT)
238666e63ce3Schristos 		  /* A call "abort ()", i.e. "kill (getpid(), SIGABRT)" is
238766e63ce3Schristos 		     the end-point for failing GCC test-cases.  */
238866e63ce3Schristos 		  sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
238966e63ce3Schristos 				   SIM_SIGABRT);
239066e63ce3Schristos 		else
239166e63ce3Schristos 		  {
239266e63ce3Schristos 		    sim_io_eprintf (sd, "Unimplemented signal: %d\n", sig);
239366e63ce3Schristos 		    sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
239466e63ce3Schristos 				     SIM_SIGILL);
239566e63ce3Schristos 		  }
239666e63ce3Schristos 
239766e63ce3Schristos 		/* This will not be reached.  */
239866e63ce3Schristos 		abort ();
239966e63ce3Schristos 	      }
240066e63ce3Schristos 	    else
240166e63ce3Schristos 	      retval = deliver_signal (current_cpu, sig, pid);
240266e63ce3Schristos 	    break;
240366e63ce3Schristos 	  }
240466e63ce3Schristos 
240566e63ce3Schristos 	case TARGET_SYS_rt_sigprocmask:
240666e63ce3Schristos 	  {
240766e63ce3Schristos 	    int i;
240866e63ce3Schristos 	    USI how = arg1;
240966e63ce3Schristos 	    USI newsetp = arg2;
241066e63ce3Schristos 	    USI oldsetp = arg3;
241166e63ce3Schristos 
241266e63ce3Schristos 	    if (how != TARGET_SIG_BLOCK
241366e63ce3Schristos 		&& how != TARGET_SIG_SETMASK
241466e63ce3Schristos 		&& how != TARGET_SIG_UNBLOCK)
241566e63ce3Schristos 	      {
241666e63ce3Schristos 		retval
241766e63ce3Schristos 		  = cris_unknown_syscall (current_cpu, pc,
241866e63ce3Schristos 					  "Unimplemented rt_sigprocmask "
241966e63ce3Schristos 					  "syscall (0x%x, 0x%x, 0x%x)\n",
242066e63ce3Schristos 					  arg1, arg2, arg3);
242166e63ce3Schristos 		break;
242266e63ce3Schristos 	      }
242366e63ce3Schristos 
242466e63ce3Schristos 	    if (newsetp)
242566e63ce3Schristos 	      {
242666e63ce3Schristos 		USI set_low
242766e63ce3Schristos 		  = sim_core_read_unaligned_4 (current_cpu, pc, 0,
242866e63ce3Schristos 					       newsetp);
242966e63ce3Schristos 		USI set_high
243066e63ce3Schristos 		  = sim_core_read_unaligned_4 (current_cpu, pc, 0,
243166e63ce3Schristos 					       newsetp + 4);
243266e63ce3Schristos 
243366e63ce3Schristos 		/* The sigmask is kept in the per-thread data, so we may
243466e63ce3Schristos 		   need to create the first one.  */
243566e63ce3Schristos 		if (current_cpu->thread_data == NULL)
243666e63ce3Schristos 		  make_first_thread (current_cpu);
243766e63ce3Schristos 
243866e63ce3Schristos 		if (how == TARGET_SIG_SETMASK)
243966e63ce3Schristos 		  for (i = 0; i < 64; i++)
244066e63ce3Schristos 		    current_cpu->thread_data[threadno].sigdata[i].blocked = 0;
244166e63ce3Schristos 
244266e63ce3Schristos 		for (i = 0; i < 32; i++)
244366e63ce3Schristos 		  if ((set_low & (1 << i)))
244466e63ce3Schristos 		    current_cpu->thread_data[threadno].sigdata[i + 1].blocked
244566e63ce3Schristos 		      = (how != TARGET_SIG_UNBLOCK);
244666e63ce3Schristos 
244766e63ce3Schristos 		for (i = 0; i < 31; i++)
244866e63ce3Schristos 		  if ((set_high & (1 << i)))
244966e63ce3Schristos 		    current_cpu->thread_data[threadno].sigdata[i + 33].blocked
245066e63ce3Schristos 		      = (how != TARGET_SIG_UNBLOCK);
245166e63ce3Schristos 
245266e63ce3Schristos 		/* The mask changed, so a signal may be unblocked for
245366e63ce3Schristos                    execution.  */
245466e63ce3Schristos 		current_cpu->thread_data[threadno].sigpending = 1;
245566e63ce3Schristos 	      }
245666e63ce3Schristos 
245766e63ce3Schristos 	    if (oldsetp != 0)
245866e63ce3Schristos 	      {
245966e63ce3Schristos 		USI set_low = 0;
246066e63ce3Schristos 		USI set_high = 0;
246166e63ce3Schristos 
246266e63ce3Schristos 		for (i = 0; i < 32; i++)
246366e63ce3Schristos 		  if (current_cpu->thread_data[threadno]
246466e63ce3Schristos 		      .sigdata[i + 1].blocked)
246566e63ce3Schristos 		    set_low |= 1 << i;
246666e63ce3Schristos 		for (i = 0; i < 31; i++)
246766e63ce3Schristos 		  if (current_cpu->thread_data[threadno]
246866e63ce3Schristos 		      .sigdata[i + 33].blocked)
246966e63ce3Schristos 		    set_high |= 1 << i;
247066e63ce3Schristos 
247166e63ce3Schristos 		sim_core_write_unaligned_4 (current_cpu, pc, 0, oldsetp + 0, set_low);
247266e63ce3Schristos 		sim_core_write_unaligned_4 (current_cpu, pc, 0, oldsetp + 4, set_high);
247366e63ce3Schristos 	      }
247466e63ce3Schristos 
247566e63ce3Schristos 	    retval = 0;
247666e63ce3Schristos 	    break;
247766e63ce3Schristos 	  }
247866e63ce3Schristos 
247966e63ce3Schristos 	case TARGET_SYS_sigreturn:
248066e63ce3Schristos 	  {
248166e63ce3Schristos 	    int i;
248266e63ce3Schristos 	    bfd_byte regbuf[4];
248366e63ce3Schristos 	    int was_sigsuspended;
248466e63ce3Schristos 
248566e63ce3Schristos 	    if (current_cpu->thread_data == NULL
248666e63ce3Schristos 		/* The CPU context is saved with the simulator data, not
248766e63ce3Schristos 		   on the stack as in the real world.  */
248866e63ce3Schristos 		|| (current_cpu->thread_data[threadno].cpu_context_atsignal
248966e63ce3Schristos 		    == NULL))
249066e63ce3Schristos 	      {
249166e63ce3Schristos 		retval
249266e63ce3Schristos 		  = cris_unknown_syscall (current_cpu, pc,
249366e63ce3Schristos 					  "Invalid sigreturn syscall: "
249466e63ce3Schristos 					  "no signal handler active "
249566e63ce3Schristos 					  "(0x%lx, 0x%lx, 0x%lx, 0x%lx, "
249666e63ce3Schristos 					  "0x%lx, 0x%lx)\n",
249766e63ce3Schristos 					  (unsigned long) arg1,
249866e63ce3Schristos 					  (unsigned long) arg2,
249966e63ce3Schristos 					  (unsigned long) arg3,
250066e63ce3Schristos 					  (unsigned long) arg4,
250166e63ce3Schristos 					  (unsigned long) arg5,
250266e63ce3Schristos 					  (unsigned long) arg6);
250366e63ce3Schristos 		break;
250466e63ce3Schristos 	      }
250566e63ce3Schristos 
250666e63ce3Schristos 	    was_sigsuspended
250766e63ce3Schristos 	      = current_cpu->thread_data[threadno].sigsuspended;
250866e63ce3Schristos 
250966e63ce3Schristos 	    /* Restore the sigmask, either from the stack copy made when
251066e63ce3Schristos 	       the sighandler was called, or from the saved state
251166e63ce3Schristos 	       specifically for sigsuspend(2).  */
251266e63ce3Schristos 	    if (was_sigsuspended)
251366e63ce3Schristos 	      {
251466e63ce3Schristos 		current_cpu->thread_data[threadno].sigsuspended = 0;
251566e63ce3Schristos 		for (i = 0; i < 64; i++)
251666e63ce3Schristos 		  current_cpu->thread_data[threadno].sigdata[i].blocked
251766e63ce3Schristos 		    = current_cpu->thread_data[threadno]
251866e63ce3Schristos 		    .sigdata[i].blocked_suspendsave;
251966e63ce3Schristos 	      }
252066e63ce3Schristos 	    else
252166e63ce3Schristos 	      {
252266e63ce3Schristos 		USI sp;
252366e63ce3Schristos 		USI set_low;
252466e63ce3Schristos 		USI set_high;
252566e63ce3Schristos 
252666e63ce3Schristos 		(*CPU_REG_FETCH (current_cpu)) (current_cpu,
252766e63ce3Schristos 					    H_GR_SP, regbuf, 4);
252866e63ce3Schristos 		sp = bfd_getl32 (regbuf);
252966e63ce3Schristos 		set_low
253066e63ce3Schristos 		  = sim_core_read_unaligned_4 (current_cpu, pc, 0, sp);
253166e63ce3Schristos 		set_high
253266e63ce3Schristos 		  = sim_core_read_unaligned_4 (current_cpu, pc, 0, sp + 4);
253366e63ce3Schristos 
253466e63ce3Schristos 		for (i = 0; i < 32; i++)
253566e63ce3Schristos 		  current_cpu->thread_data[threadno].sigdata[i + 1].blocked
253666e63ce3Schristos 		    = (set_low & (1 << i)) != 0;
253766e63ce3Schristos 		for (i = 0; i < 31; i++)
253866e63ce3Schristos 		  current_cpu->thread_data[threadno].sigdata[i + 33].blocked
253966e63ce3Schristos 		    = (set_high & (1 << i)) != 0;
254066e63ce3Schristos 	      }
254166e63ce3Schristos 
254266e63ce3Schristos 	    /* The mask changed, so a signal may be unblocked for
254366e63ce3Schristos 	       execution.  */
254466e63ce3Schristos 	    current_cpu->thread_data[threadno].sigpending = 1;
254566e63ce3Schristos 
254666e63ce3Schristos 	    memcpy (&current_cpu->cpu_data_placeholder,
254766e63ce3Schristos 		    current_cpu->thread_data[threadno].cpu_context_atsignal,
254866e63ce3Schristos 		    current_cpu->thread_cpu_data_size);
254966e63ce3Schristos 	    free (current_cpu->thread_data[threadno].cpu_context_atsignal);
255066e63ce3Schristos 	    current_cpu->thread_data[threadno].cpu_context_atsignal = NULL;
255166e63ce3Schristos 
255266e63ce3Schristos 	    /* The return value must come from the saved R10.  */
255366e63ce3Schristos 	    (*CPU_REG_FETCH (current_cpu)) (current_cpu, H_GR_R10, regbuf, 4);
255466e63ce3Schristos 	    retval = bfd_getl32 (regbuf);
255566e63ce3Schristos 
255666e63ce3Schristos 	    /* We must also break the "sigsuspension loop".  */
255766e63ce3Schristos 	    if (was_sigsuspended)
255866e63ce3Schristos 	      sim_pc_set (current_cpu, sim_pc_get (current_cpu) + 2);
255966e63ce3Schristos 	    break;
256066e63ce3Schristos 	  }
256166e63ce3Schristos 
256266e63ce3Schristos 	case TARGET_SYS_rt_sigsuspend:
256366e63ce3Schristos 	  {
256466e63ce3Schristos 	    USI newsetp = arg1;
256566e63ce3Schristos 	    USI setsize = arg2;
256666e63ce3Schristos 
256766e63ce3Schristos 	    if (setsize != 8)
256866e63ce3Schristos 	      {
256966e63ce3Schristos 		retval
257066e63ce3Schristos 		  = cris_unknown_syscall (current_cpu, pc,
257166e63ce3Schristos 					  "Unimplemented rt_sigsuspend syscall"
257266e63ce3Schristos 					  " arguments (0x%lx, 0x%lx)\n",
257366e63ce3Schristos 					  (unsigned long) arg1,
257466e63ce3Schristos 					  (unsigned long) arg2);
257566e63ce3Schristos 		break;
257666e63ce3Schristos 	      }
257766e63ce3Schristos 
257866e63ce3Schristos 	    /* Don't change the signal mask if we're already in
257966e63ce3Schristos 	       sigsuspend state (i.e. this syscall is a rerun).  */
258066e63ce3Schristos 	    else if (!current_cpu->thread_data[threadno].sigsuspended)
258166e63ce3Schristos 	      {
258266e63ce3Schristos 		USI set_low
258366e63ce3Schristos 		  = sim_core_read_unaligned_4 (current_cpu, pc, 0,
258466e63ce3Schristos 					       newsetp);
258566e63ce3Schristos 		USI set_high
258666e63ce3Schristos 		  = sim_core_read_unaligned_4 (current_cpu, pc, 0,
258766e63ce3Schristos 					       newsetp + 4);
258866e63ce3Schristos 		int i;
258966e63ce3Schristos 
259066e63ce3Schristos 		/* Save the current sigmask and insert the user-supplied
259166e63ce3Schristos                    one.  */
259266e63ce3Schristos 		for (i = 0; i < 32; i++)
259366e63ce3Schristos 		  {
259466e63ce3Schristos 		    current_cpu->thread_data[threadno]
259566e63ce3Schristos 		      .sigdata[i + 1].blocked_suspendsave
259666e63ce3Schristos 		      = current_cpu->thread_data[threadno]
259766e63ce3Schristos 		      .sigdata[i + 1].blocked;
259866e63ce3Schristos 
259966e63ce3Schristos 		    current_cpu->thread_data[threadno]
260066e63ce3Schristos 		      .sigdata[i + 1].blocked = (set_low & (1 << i)) != 0;
260166e63ce3Schristos 		  }
260266e63ce3Schristos 		for (i = 0; i < 31; i++)
260366e63ce3Schristos 		  {
260466e63ce3Schristos 		    current_cpu->thread_data[threadno]
260566e63ce3Schristos 		      .sigdata[i + 33].blocked_suspendsave
260666e63ce3Schristos 		      = current_cpu->thread_data[threadno]
260766e63ce3Schristos 		      .sigdata[i + 33].blocked;
260866e63ce3Schristos 		    current_cpu->thread_data[threadno]
260966e63ce3Schristos 		      .sigdata[i + 33].blocked = (set_high & (1 << i)) != 0;
261066e63ce3Schristos 		  }
261166e63ce3Schristos 
261266e63ce3Schristos 		current_cpu->thread_data[threadno].sigsuspended = 1;
261366e63ce3Schristos 
261466e63ce3Schristos 		/* The mask changed, so a signal may be unblocked for
261566e63ce3Schristos                    execution. */
261666e63ce3Schristos 		current_cpu->thread_data[threadno].sigpending = 1;
261766e63ce3Schristos 	      }
261866e63ce3Schristos 
261966e63ce3Schristos 	    /* Because we don't use arg1 (newsetp) when this syscall is
262066e63ce3Schristos 	       rerun, it doesn't matter that we overwrite it with the
262166e63ce3Schristos 	       (constant) return value.  */
262266e63ce3Schristos 	    retval = -cb_host_to_target_errno (cb, EINTR);
262366e63ce3Schristos 	    sim_pc_set (current_cpu, pc);
262466e63ce3Schristos 	    break;
262566e63ce3Schristos 	  }
262666e63ce3Schristos 
262766e63ce3Schristos 	  /* Add case labels here for other syscalls using the 32-bit
262866e63ce3Schristos 	     "struct stat", provided they have a corresponding simulator
262966e63ce3Schristos 	     function of course.  */
263066e63ce3Schristos 	case TARGET_SYS_stat:
263166e63ce3Schristos 	case TARGET_SYS_fstat:
263266e63ce3Schristos 	  {
263366e63ce3Schristos 	    /* As long as the infrastructure doesn't cache anything
263466e63ce3Schristos 	       related to the stat mapping, this trick gets us a dual
263566e63ce3Schristos 	       "struct stat"-type mapping in the least error-prone way.  */
263666e63ce3Schristos 	    const char *saved_map = cb->stat_map;
263766e63ce3Schristos 	    CB_TARGET_DEFS_MAP *saved_syscall_map = cb->syscall_map;
263866e63ce3Schristos 
263966e63ce3Schristos 	    cb->syscall_map = (CB_TARGET_DEFS_MAP *) syscall_stat32_map;
264066e63ce3Schristos 	    cb->stat_map = stat32_map;
264166e63ce3Schristos 
264266e63ce3Schristos 	    if (cb_syscall (cb, &s) != CB_RC_OK)
264366e63ce3Schristos 	      {
264466e63ce3Schristos 		abort ();
264566e63ce3Schristos 		sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
264666e63ce3Schristos 				 SIM_SIGILL);
264766e63ce3Schristos 	      }
264866e63ce3Schristos 	    retval = s.result == -1 ? -s.errcode : s.result;
264966e63ce3Schristos 
265066e63ce3Schristos 	    cb->stat_map = saved_map;
265166e63ce3Schristos 	    cb->syscall_map = saved_syscall_map;
265266e63ce3Schristos 	    break;
265366e63ce3Schristos 	  }
265466e63ce3Schristos 
265566e63ce3Schristos 	case TARGET_SYS_getcwd:
265666e63ce3Schristos 	  {
265766e63ce3Schristos 	    USI buf = arg1;
265866e63ce3Schristos 	    USI size = arg2;
265966e63ce3Schristos 
266066e63ce3Schristos 	    char *cwd = xmalloc (SIM_PATHMAX);
266166e63ce3Schristos 	    if (cwd != getcwd (cwd, SIM_PATHMAX))
266266e63ce3Schristos 	      abort ();
266366e63ce3Schristos 
266466e63ce3Schristos 	    /* FIXME: When and if we support chdir, we need something
266566e63ce3Schristos                a bit more elaborate.  */
266666e63ce3Schristos 	    if (simulator_sysroot[0] != '\0')
266766e63ce3Schristos 	      strcpy (cwd, "/");
266866e63ce3Schristos 
266966e63ce3Schristos 	    retval = -cb_host_to_target_errno (cb, ERANGE);
267066e63ce3Schristos 	    if (strlen (cwd) + 1 <= size)
267166e63ce3Schristos 	      {
267266e63ce3Schristos 		retval = strlen (cwd) + 1;
267366e63ce3Schristos 		if (sim_core_write_buffer (sd, current_cpu, 0, cwd,
267466e63ce3Schristos 					   buf, retval)
267566e63ce3Schristos 		    != (unsigned int) retval)
267666e63ce3Schristos 		  retval = -cb_host_to_target_errno (cb, EFAULT);
267766e63ce3Schristos 	      }
267866e63ce3Schristos 	    free (cwd);
267966e63ce3Schristos 	    break;
268066e63ce3Schristos 	  }
268166e63ce3Schristos 
268266e63ce3Schristos 	case TARGET_SYS_access:
268366e63ce3Schristos 	  {
268466e63ce3Schristos 	    SI path = arg1;
268566e63ce3Schristos 	    SI mode = arg2;
268666e63ce3Schristos 	    char *pbuf = xmalloc (SIM_PATHMAX);
268766e63ce3Schristos 	    int i;
268866e63ce3Schristos 	    int o = 0;
268966e63ce3Schristos 	    int hmode = 0;
269066e63ce3Schristos 
269166e63ce3Schristos 	    if (sim_core_read_unaligned_1 (current_cpu, pc, 0, path) == '/')
269266e63ce3Schristos 	      {
269366e63ce3Schristos 		strcpy (pbuf, simulator_sysroot);
269466e63ce3Schristos 		o += strlen (simulator_sysroot);
269566e63ce3Schristos 	      }
269666e63ce3Schristos 
269766e63ce3Schristos 	    for (i = 0; i + o < SIM_PATHMAX; i++)
269866e63ce3Schristos 	      {
269966e63ce3Schristos 		pbuf[i + o]
270066e63ce3Schristos 		  = sim_core_read_unaligned_1 (current_cpu, pc, 0, path + i);
270166e63ce3Schristos 		if (pbuf[i + o] == 0)
270266e63ce3Schristos 		  break;
270366e63ce3Schristos 	      }
270466e63ce3Schristos 
270566e63ce3Schristos 	    if (i + o == SIM_PATHMAX)
270666e63ce3Schristos 	      {
270766e63ce3Schristos 		retval = -cb_host_to_target_errno (cb, ENAMETOOLONG);
270866e63ce3Schristos 		break;
270966e63ce3Schristos 	      }
271066e63ce3Schristos 
271166e63ce3Schristos 	    /* Assert that we don't get calls for files for which we
271266e63ce3Schristos 	       don't have support.  */
271366e63ce3Schristos 	    if (strncmp (pbuf + strlen (simulator_sysroot),
271466e63ce3Schristos 			 "/proc/", 6) == 0)
271566e63ce3Schristos 	      abort ();
271666e63ce3Schristos #define X_AFLAG(x) if (mode & TARGET_ ## x) hmode |= x
271766e63ce3Schristos 	    X_AFLAG (R_OK);
271866e63ce3Schristos 	    X_AFLAG (W_OK);
271966e63ce3Schristos 	    X_AFLAG (X_OK);
272066e63ce3Schristos 	    X_AFLAG (F_OK);
272166e63ce3Schristos #undef X_AFLAG
272266e63ce3Schristos 
272366e63ce3Schristos 	    if (access (pbuf, hmode) != 0)
272466e63ce3Schristos 	      retval = -cb_host_to_target_errno (cb, errno);
272566e63ce3Schristos 	    else
272666e63ce3Schristos 	      retval = 0;
272766e63ce3Schristos 
272866e63ce3Schristos 	    free (pbuf);
272966e63ce3Schristos 	    break;
273066e63ce3Schristos 	  }
273166e63ce3Schristos 
273266e63ce3Schristos 	case TARGET_SYS_readlink:
273366e63ce3Schristos 	  {
273466e63ce3Schristos 	    SI path = arg1;
273566e63ce3Schristos 	    SI buf = arg2;
273666e63ce3Schristos 	    SI bufsiz = arg3;
273766e63ce3Schristos 	    char *pbuf = xmalloc (SIM_PATHMAX);
273866e63ce3Schristos 	    char *lbuf = xmalloc (SIM_PATHMAX);
273966e63ce3Schristos 	    char *lbuf_alloc = lbuf;
274066e63ce3Schristos 	    int nchars = -1;
274166e63ce3Schristos 	    int i;
274266e63ce3Schristos 	    int o = 0;
274366e63ce3Schristos 
274466e63ce3Schristos 	    if (sim_core_read_unaligned_1 (current_cpu, pc, 0, path) == '/')
274566e63ce3Schristos 	      {
274666e63ce3Schristos 		strcpy (pbuf, simulator_sysroot);
274766e63ce3Schristos 		o += strlen (simulator_sysroot);
274866e63ce3Schristos 	      }
274966e63ce3Schristos 
275066e63ce3Schristos 	    for (i = 0; i + o < SIM_PATHMAX; i++)
275166e63ce3Schristos 	      {
275266e63ce3Schristos 		pbuf[i + o]
275366e63ce3Schristos 		  = sim_core_read_unaligned_1 (current_cpu, pc, 0, path + i);
275466e63ce3Schristos 		if (pbuf[i + o] == 0)
275566e63ce3Schristos 		  break;
275666e63ce3Schristos 	      }
275766e63ce3Schristos 
275866e63ce3Schristos 	    if (i + o == SIM_PATHMAX)
275966e63ce3Schristos 	      {
276066e63ce3Schristos 		retval = -cb_host_to_target_errno (cb, ENAMETOOLONG);
276166e63ce3Schristos 		break;
276266e63ce3Schristos 	      }
276366e63ce3Schristos 
276466e63ce3Schristos 	    /* Intervene calls for certain files expected in the target
276566e63ce3Schristos                proc file system.  */
276666e63ce3Schristos 	    if (strcmp (pbuf + strlen (simulator_sysroot),
276766e63ce3Schristos 			"/proc/" XSTRING (TARGET_PID) "/exe") == 0)
276866e63ce3Schristos 	      {
276966e63ce3Schristos 		char *argv0
277066e63ce3Schristos 		  = (STATE_PROG_ARGV (sd) != NULL
277166e63ce3Schristos 		     ? *STATE_PROG_ARGV (sd) : NULL);
277266e63ce3Schristos 
277366e63ce3Schristos 		if (argv0 == NULL || *argv0 == '.')
277466e63ce3Schristos 		  {
277566e63ce3Schristos 		    retval
277666e63ce3Schristos 		      = cris_unknown_syscall (current_cpu, pc,
277766e63ce3Schristos 					      "Unimplemented readlink syscall "
277866e63ce3Schristos 					      "(0x%lx: [\"%s\"], 0x%lx)\n",
277966e63ce3Schristos 					      (unsigned long) arg1, pbuf,
278066e63ce3Schristos 					      (unsigned long) arg2);
278166e63ce3Schristos 		    break;
278266e63ce3Schristos 		  }
278366e63ce3Schristos 		else if (*argv0 == '/')
278466e63ce3Schristos 		  {
278566e63ce3Schristos 		    if (strncmp (simulator_sysroot, argv0,
278666e63ce3Schristos 				 strlen (simulator_sysroot)) == 0)
278766e63ce3Schristos 		      argv0 += strlen (simulator_sysroot);
278866e63ce3Schristos 
278966e63ce3Schristos 		    strcpy (lbuf, argv0);
279066e63ce3Schristos 		    nchars = strlen (argv0) + 1;
279166e63ce3Schristos 		  }
279266e63ce3Schristos 		else
279366e63ce3Schristos 		  {
279466e63ce3Schristos 		    if (getcwd (lbuf, SIM_PATHMAX) != NULL
279566e63ce3Schristos 			&& strlen (lbuf) + 2 + strlen (argv0) < SIM_PATHMAX)
279666e63ce3Schristos 		      {
279766e63ce3Schristos 			if (strncmp (simulator_sysroot, lbuf,
279866e63ce3Schristos 				     strlen (simulator_sysroot)) == 0)
279966e63ce3Schristos 			  lbuf += strlen (simulator_sysroot);
280066e63ce3Schristos 
280166e63ce3Schristos 			strcat (lbuf, "/");
280266e63ce3Schristos 			strcat (lbuf, argv0);
280366e63ce3Schristos 			nchars = strlen (lbuf) + 1;
280466e63ce3Schristos 		      }
280566e63ce3Schristos 		    else
280666e63ce3Schristos 		      abort ();
280766e63ce3Schristos 		  }
280866e63ce3Schristos 	      }
280966e63ce3Schristos 	    else
281066e63ce3Schristos 	      nchars = readlink (pbuf, lbuf, SIM_PATHMAX);
281166e63ce3Schristos 
281266e63ce3Schristos 	    /* We trust that the readlink result returns a *relative*
281366e63ce3Schristos 	       link, or one already adjusted for the file-path-prefix.
281466e63ce3Schristos 	       (We can't generally tell the difference, so we go with
281566e63ce3Schristos 	       the easiest decision; no adjustment.)  */
281666e63ce3Schristos 
281766e63ce3Schristos 	    if (nchars == -1)
281866e63ce3Schristos 	      {
281966e63ce3Schristos 		retval = -cb_host_to_target_errno (cb, errno);
282066e63ce3Schristos 		break;
282166e63ce3Schristos 	      }
282266e63ce3Schristos 
282366e63ce3Schristos 	    if (bufsiz < nchars)
282466e63ce3Schristos 	      nchars = bufsiz;
282566e63ce3Schristos 
282666e63ce3Schristos 	    if (sim_core_write_buffer (sd, current_cpu, write_map, lbuf,
282766e63ce3Schristos 				       buf, nchars) != (unsigned int) nchars)
282866e63ce3Schristos 	      retval = -cb_host_to_target_errno (cb, EFAULT);
282966e63ce3Schristos 	    else
283066e63ce3Schristos 	      retval = nchars;
283166e63ce3Schristos 
283266e63ce3Schristos 	    free (pbuf);
283366e63ce3Schristos 	    free (lbuf_alloc);
283466e63ce3Schristos 	    break;
283566e63ce3Schristos 	  }
283666e63ce3Schristos 
283766e63ce3Schristos 	case TARGET_SYS_sched_getscheduler:
283866e63ce3Schristos 	  {
283966e63ce3Schristos 	    USI pid = arg1;
284066e63ce3Schristos 
284166e63ce3Schristos 	    /* FIXME: Search (other) existing threads.  */
284266e63ce3Schristos 	    if (pid != 0 && pid != TARGET_PID)
284366e63ce3Schristos 	      retval = -cb_host_to_target_errno (cb, ESRCH);
284466e63ce3Schristos 	    else
284566e63ce3Schristos 	      retval = TARGET_SCHED_OTHER;
284666e63ce3Schristos 	    break;
284766e63ce3Schristos 	  }
284866e63ce3Schristos 
284966e63ce3Schristos 	case TARGET_SYS_sched_getparam:
285066e63ce3Schristos 	  {
285166e63ce3Schristos 	    USI pid = arg1;
285266e63ce3Schristos 	    USI paramp = arg2;
285366e63ce3Schristos 
285466e63ce3Schristos 	    /* The kernel says:
285566e63ce3Schristos 	       struct sched_param {
285666e63ce3Schristos 			int sched_priority;
285766e63ce3Schristos 	       }; */
285866e63ce3Schristos 
285966e63ce3Schristos 	    if (pid != 0 && pid != TARGET_PID)
286066e63ce3Schristos 	      retval = -cb_host_to_target_errno (cb, ESRCH);
286166e63ce3Schristos 	    else
286266e63ce3Schristos 	      {
286366e63ce3Schristos 		/* FIXME: Save scheduler setting before threads are
286466e63ce3Schristos 		   created too.  */
286566e63ce3Schristos 		sim_core_write_unaligned_4 (current_cpu, pc, 0, paramp,
286666e63ce3Schristos 					    current_cpu->thread_data != NULL
286766e63ce3Schristos 					    ? (current_cpu
286866e63ce3Schristos 					       ->thread_data[threadno]
286966e63ce3Schristos 					       .priority)
287066e63ce3Schristos 					    : 0);
287166e63ce3Schristos 		retval = 0;
287266e63ce3Schristos 	      }
287366e63ce3Schristos 	    break;
287466e63ce3Schristos 	  }
287566e63ce3Schristos 
287666e63ce3Schristos 	case TARGET_SYS_sched_setparam:
287766e63ce3Schristos 	  {
287866e63ce3Schristos 	    USI pid = arg1;
287966e63ce3Schristos 	    USI paramp = arg2;
288066e63ce3Schristos 
288166e63ce3Schristos 	    if ((pid != 0 && pid != TARGET_PID)
288266e63ce3Schristos 		|| sim_core_read_unaligned_4 (current_cpu, pc, 0,
288366e63ce3Schristos 					      paramp) != 0)
288466e63ce3Schristos 	      retval = -cb_host_to_target_errno (cb, EINVAL);
288566e63ce3Schristos 	    else
288666e63ce3Schristos 	      retval = 0;
288766e63ce3Schristos 	    break;
288866e63ce3Schristos 	  }
288966e63ce3Schristos 
289066e63ce3Schristos 	case TARGET_SYS_sched_setscheduler:
289166e63ce3Schristos 	  {
289266e63ce3Schristos 	    USI pid = arg1;
289366e63ce3Schristos 	    USI policy = arg2;
289466e63ce3Schristos 	    USI paramp = arg3;
289566e63ce3Schristos 
289666e63ce3Schristos 	    if ((pid != 0 && pid != TARGET_PID)
289766e63ce3Schristos 		|| policy != TARGET_SCHED_OTHER
289866e63ce3Schristos 		|| sim_core_read_unaligned_4 (current_cpu, pc, 0,
289966e63ce3Schristos 					      paramp) != 0)
290066e63ce3Schristos 	      retval = -cb_host_to_target_errno (cb, EINVAL);
290166e63ce3Schristos 	    else
290266e63ce3Schristos 	      /* FIXME: Save scheduler setting to be read in later
290366e63ce3Schristos 		 sched_getparam calls.  */
290466e63ce3Schristos 	      retval = 0;
290566e63ce3Schristos 	    break;
290666e63ce3Schristos 	  }
290766e63ce3Schristos 
290866e63ce3Schristos 	case TARGET_SYS_sched_yield:
290966e63ce3Schristos 	  /* We reschedule to the next thread after a syscall anyway, so
291066e63ce3Schristos 	     we don't have to do anything here than to set the return
291166e63ce3Schristos 	     value.  */
291266e63ce3Schristos 	  retval = 0;
291366e63ce3Schristos 	  break;
291466e63ce3Schristos 
291566e63ce3Schristos 	case TARGET_SYS_sched_get_priority_min:
291666e63ce3Schristos 	case TARGET_SYS_sched_get_priority_max:
291766e63ce3Schristos 	  if (arg1 != 0)
291866e63ce3Schristos 	    retval = -cb_host_to_target_errno (cb, EINVAL);
291966e63ce3Schristos 	  else
292066e63ce3Schristos 	    retval = 0;
292166e63ce3Schristos 	  break;
292266e63ce3Schristos 
292366e63ce3Schristos 	case TARGET_SYS_ugetrlimit:
292466e63ce3Schristos 	  {
292566e63ce3Schristos 	    unsigned int curlim, maxlim;
292666e63ce3Schristos 	    if (arg1 != TARGET_RLIMIT_STACK && arg1 != TARGET_RLIMIT_NOFILE)
292766e63ce3Schristos 	      {
292866e63ce3Schristos 		retval = -cb_host_to_target_errno (cb, EINVAL);
292966e63ce3Schristos 		break;
293066e63ce3Schristos 	      }
293166e63ce3Schristos 
293266e63ce3Schristos 	    /* The kernel says:
293366e63ce3Schristos 	       struct rlimit {
293466e63ce3Schristos 		       unsigned long   rlim_cur;
293566e63ce3Schristos 		       unsigned long   rlim_max;
293666e63ce3Schristos 	       }; */
293766e63ce3Schristos 	    if (arg1 == TARGET_RLIMIT_NOFILE)
293866e63ce3Schristos 	      {
293966e63ce3Schristos 		/* Sadly a very low limit.  Better not lie, though.  */
294066e63ce3Schristos 		maxlim = curlim = MAX_CALLBACK_FDS;
294166e63ce3Schristos 	      }
294266e63ce3Schristos 	    else /* arg1 == TARGET_RLIMIT_STACK */
294366e63ce3Schristos 	      {
294466e63ce3Schristos 		maxlim = 0xffffffff;
294566e63ce3Schristos 		curlim = 0x800000;
294666e63ce3Schristos 	      }
294766e63ce3Schristos 	    sim_core_write_unaligned_4 (current_cpu, pc, 0, arg2, curlim);
294866e63ce3Schristos 	    sim_core_write_unaligned_4 (current_cpu, pc, 0, arg2 + 4, maxlim);
294966e63ce3Schristos 	    retval = 0;
295066e63ce3Schristos 	    break;
295166e63ce3Schristos 	  }
295266e63ce3Schristos 
295366e63ce3Schristos 	case TARGET_SYS_setrlimit:
295466e63ce3Schristos 	  if (arg1 != TARGET_RLIMIT_STACK)
295566e63ce3Schristos 	    {
295666e63ce3Schristos 	      retval = -cb_host_to_target_errno (cb, EINVAL);
295766e63ce3Schristos 	      break;
295866e63ce3Schristos 	    }
295966e63ce3Schristos 	  /* FIXME: Save values for future ugetrlimit calls.  */
296066e63ce3Schristos 	  retval = 0;
296166e63ce3Schristos 	  break;
296266e63ce3Schristos 
296366e63ce3Schristos 	/* Provide a very limited subset of the sysctl functions, and
296466e63ce3Schristos 	   abort for the rest. */
296566e63ce3Schristos 	case TARGET_SYS__sysctl:
296666e63ce3Schristos 	  {
296766e63ce3Schristos 	    /* The kernel says:
296866e63ce3Schristos 	       struct __sysctl_args {
296966e63ce3Schristos 		int *name;
297066e63ce3Schristos 		int nlen;
297166e63ce3Schristos 		void *oldval;
297266e63ce3Schristos 		size_t *oldlenp;
297366e63ce3Schristos 		void *newval;
297466e63ce3Schristos 		size_t newlen;
297566e63ce3Schristos 		unsigned long __unused[4];
297666e63ce3Schristos 	       }; */
297766e63ce3Schristos 	    SI name = sim_core_read_unaligned_4 (current_cpu, pc, 0, arg1);
297866e63ce3Schristos 	    SI name0 = name == 0
297966e63ce3Schristos 	      ? 0 : sim_core_read_unaligned_4 (current_cpu, pc, 0, name);
298066e63ce3Schristos 	    SI name1 = name == 0
298166e63ce3Schristos 	      ? 0 : sim_core_read_unaligned_4 (current_cpu, pc, 0, name + 4);
298266e63ce3Schristos 	    SI nlen
298366e63ce3Schristos 	      =  sim_core_read_unaligned_4 (current_cpu, pc, 0, arg1 + 4);
298466e63ce3Schristos 	    SI oldval
298566e63ce3Schristos 	      =  sim_core_read_unaligned_4 (current_cpu, pc, 0, arg1 + 8);
298666e63ce3Schristos 	    SI oldlenp
298766e63ce3Schristos 	      =  sim_core_read_unaligned_4 (current_cpu, pc, 0, arg1 + 12);
298866e63ce3Schristos 	    SI oldlen = oldlenp == 0
298966e63ce3Schristos 	      ? 0 : sim_core_read_unaligned_4 (current_cpu, pc, 0, oldlenp);
299066e63ce3Schristos 	    SI newval
299166e63ce3Schristos 	      =  sim_core_read_unaligned_4 (current_cpu, pc, 0, arg1 + 16);
299266e63ce3Schristos 	    SI newlen
299366e63ce3Schristos 	      = sim_core_read_unaligned_4 (current_cpu, pc, 0, arg1 + 20);
299466e63ce3Schristos 
299566e63ce3Schristos 	    if (name0 == TARGET_CTL_KERN && name1 == TARGET_CTL_KERN_VERSION)
299666e63ce3Schristos 	      {
299766e63ce3Schristos 		SI to_write = oldlen < (SI) sizeof (TARGET_UTSNAME)
299866e63ce3Schristos 		  ? oldlen : (SI) sizeof (TARGET_UTSNAME);
299966e63ce3Schristos 
300066e63ce3Schristos 		sim_core_write_unaligned_4 (current_cpu, pc, 0, oldlenp,
300166e63ce3Schristos 					    sizeof (TARGET_UTSNAME));
300266e63ce3Schristos 
300366e63ce3Schristos 		if (sim_core_write_buffer (sd, current_cpu, write_map,
300466e63ce3Schristos 					   TARGET_UTSNAME, oldval,
300566e63ce3Schristos 					   to_write)
300666e63ce3Schristos 		    != (unsigned int) to_write)
300766e63ce3Schristos 		  retval = -cb_host_to_target_errno (cb, EFAULT);
300866e63ce3Schristos 		else
300966e63ce3Schristos 		  retval = 0;
301066e63ce3Schristos 		break;
301166e63ce3Schristos 	      }
301266e63ce3Schristos 
301366e63ce3Schristos 	    retval
301466e63ce3Schristos 	      = cris_unknown_syscall (current_cpu, pc,
301566e63ce3Schristos 				      "Unimplemented _sysctl syscall "
301666e63ce3Schristos 				      "(0x%lx: [0x%lx, 0x%lx],"
301766e63ce3Schristos 				      " 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx)\n",
301866e63ce3Schristos 				      (unsigned long) name,
301966e63ce3Schristos 				      (unsigned long) name0,
302066e63ce3Schristos 				      (unsigned long) name1,
302166e63ce3Schristos 				      (unsigned long) nlen,
302266e63ce3Schristos 				      (unsigned long) oldval,
302366e63ce3Schristos 				      (unsigned long) oldlenp,
302466e63ce3Schristos 				      (unsigned long) newval,
302566e63ce3Schristos 				      (unsigned long) newlen);
302666e63ce3Schristos 	    break;
302766e63ce3Schristos 	  }
302866e63ce3Schristos 
302966e63ce3Schristos 	case TARGET_SYS_exit:
303066e63ce3Schristos 	  {
303166e63ce3Schristos 	    /* Here for all but the last thread.  */
303266e63ce3Schristos 	    int i;
303366e63ce3Schristos 	    int pid
303466e63ce3Schristos 	      = current_cpu->thread_data[threadno].threadid + TARGET_PID;
303566e63ce3Schristos 	    int ppid
303666e63ce3Schristos 	      = (current_cpu->thread_data[threadno].parent_threadid
303766e63ce3Schristos 		 + TARGET_PID);
303866e63ce3Schristos 	    int exitsig = current_cpu->thread_data[threadno].exitsig;
303966e63ce3Schristos 
304066e63ce3Schristos 	    /* Any children are now all orphans.  */
304166e63ce3Schristos 	    for (i = 0; i < SIM_TARGET_MAX_THREADS; i++)
304266e63ce3Schristos 	      if (current_cpu->thread_data[i].parent_threadid
304366e63ce3Schristos 		  == current_cpu->thread_data[threadno].threadid)
304466e63ce3Schristos 		/* Make getppid(2) return 1 for them, poor little ones.  */
304566e63ce3Schristos 		current_cpu->thread_data[i].parent_threadid = -TARGET_PID + 1;
304666e63ce3Schristos 
304766e63ce3Schristos 	    /* Free the cpu context data.  When the parent has received
304866e63ce3Schristos 	       the exit status, we'll clear the entry too.  */
304966e63ce3Schristos 	    free (current_cpu->thread_data[threadno].cpu_context);
305066e63ce3Schristos 	    current_cpu->thread_data[threadno].cpu_context = NULL;
305166e63ce3Schristos 	    current_cpu->m1threads--;
305266e63ce3Schristos 	    if (arg1 != 0)
305366e63ce3Schristos 	      {
305466e63ce3Schristos 		sim_io_eprintf (sd, "Thread %d exited with status %d\n",
305566e63ce3Schristos 				pid, arg1);
305666e63ce3Schristos 		sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
305766e63ce3Schristos 				 SIM_SIGILL);
305866e63ce3Schristos 	      }
305966e63ce3Schristos 
306066e63ce3Schristos 	    /* Still, we may want to support non-zero exit values.  */
306166e63ce3Schristos 	    current_cpu->thread_data[threadno].exitval = arg1 << 8;
306266e63ce3Schristos 
306366e63ce3Schristos 	    if (exitsig)
306466e63ce3Schristos 	      deliver_signal (current_cpu, exitsig, ppid);
306566e63ce3Schristos 	    break;
306666e63ce3Schristos 	  }
306766e63ce3Schristos 
306866e63ce3Schristos 	case TARGET_SYS_clone:
306966e63ce3Schristos 	  {
307066e63ce3Schristos 	    int nthreads = current_cpu->m1threads + 1;
307166e63ce3Schristos 	    void *thread_cpu_data;
307266e63ce3Schristos 	    bfd_byte old_sp_buf[4];
307366e63ce3Schristos 	    bfd_byte sp_buf[4];
307466e63ce3Schristos 	    const bfd_byte zeros[4] = { 0, 0, 0, 0 };
307566e63ce3Schristos 	    int i;
307666e63ce3Schristos 
307766e63ce3Schristos 	    /* That's right, the syscall clone arguments are reversed
307866e63ce3Schristos 	       compared to sys_clone notes in clone(2) and compared to
307966e63ce3Schristos 	       other Linux ports (i.e. it's the same order as in the
308066e63ce3Schristos 	       clone(2) libcall).  */
308166e63ce3Schristos 	    USI flags = arg2;
308266e63ce3Schristos 	    USI newsp = arg1;
308366e63ce3Schristos 
308466e63ce3Schristos 	    if (nthreads == SIM_TARGET_MAX_THREADS)
308566e63ce3Schristos 	      {
308666e63ce3Schristos 		retval = -cb_host_to_target_errno (cb, EAGAIN);
308766e63ce3Schristos 		break;
308866e63ce3Schristos 	      }
308966e63ce3Schristos 
309066e63ce3Schristos 	    /* FIXME: Implement the low byte.  */
309166e63ce3Schristos 	    if ((flags & ~TARGET_CSIGNAL) !=
309266e63ce3Schristos 		(TARGET_CLONE_VM
309366e63ce3Schristos 		 | TARGET_CLONE_FS
309466e63ce3Schristos 		 | TARGET_CLONE_FILES
309566e63ce3Schristos 		 | TARGET_CLONE_SIGHAND)
309666e63ce3Schristos 		|| newsp == 0)
309766e63ce3Schristos 	      {
309866e63ce3Schristos 		retval
309966e63ce3Schristos 		  = cris_unknown_syscall (current_cpu, pc,
310066e63ce3Schristos 					  "Unimplemented clone syscall "
310166e63ce3Schristos 					  "(0x%lx, 0x%lx)\n",
310266e63ce3Schristos 					  (unsigned long) arg1,
310366e63ce3Schristos 					  (unsigned long) arg2);
310466e63ce3Schristos 		break;
310566e63ce3Schristos 	      }
310666e63ce3Schristos 
310766e63ce3Schristos 	    if (current_cpu->thread_data == NULL)
310866e63ce3Schristos 	      make_first_thread (current_cpu);
310966e63ce3Schristos 
311066e63ce3Schristos 	    /* The created thread will get the new SP and a cleared R10.
311166e63ce3Schristos 	       Since it's created out of a copy of the old thread and we
311266e63ce3Schristos 	       don't have a set-register-function that just take the
311366e63ce3Schristos 	       cpu_data as a parameter, we set the childs values first,
311466e63ce3Schristos 	       and write back or overwrite them in the parent after the
311566e63ce3Schristos 	       copy.  */
311666e63ce3Schristos 	    (*CPU_REG_FETCH (current_cpu)) (current_cpu,
311766e63ce3Schristos 					    H_GR_SP, old_sp_buf, 4);
311866e63ce3Schristos 	    bfd_putl32 (newsp, sp_buf);
311966e63ce3Schristos 	    (*CPU_REG_STORE (current_cpu)) (current_cpu,
312066e63ce3Schristos 					    H_GR_SP, sp_buf, 4);
312166e63ce3Schristos 	    (*CPU_REG_STORE (current_cpu)) (current_cpu,
312266e63ce3Schristos 					    H_GR_R10, (bfd_byte *) zeros, 4);
312366e63ce3Schristos 	    thread_cpu_data
312466e63ce3Schristos 	      = (*current_cpu
312566e63ce3Schristos 		 ->make_thread_cpu_data) (current_cpu,
312666e63ce3Schristos 					  &current_cpu->cpu_data_placeholder);
312766e63ce3Schristos 	    (*CPU_REG_STORE (current_cpu)) (current_cpu,
312866e63ce3Schristos 					    H_GR_SP, old_sp_buf, 4);
312966e63ce3Schristos 
313066e63ce3Schristos 	    retval = ++current_cpu->max_threadid + TARGET_PID;
313166e63ce3Schristos 
313266e63ce3Schristos 	    /* Find an unused slot.  After a few threads have been created
313366e63ce3Schristos 	       and exited, the array is expected to be a bit fragmented.
313466e63ce3Schristos 	       We don't reuse the first entry, though, that of the
313566e63ce3Schristos 	       original thread.  */
313666e63ce3Schristos 	    for (i = 1; i < SIM_TARGET_MAX_THREADS; i++)
313766e63ce3Schristos 	      if (current_cpu->thread_data[i].cpu_context == NULL
313866e63ce3Schristos 		  /* Don't reuse a zombied entry.  */
313966e63ce3Schristos 		  && current_cpu->thread_data[i].threadid == 0)
314066e63ce3Schristos 		break;
314166e63ce3Schristos 
314266e63ce3Schristos 	    memcpy (&current_cpu->thread_data[i],
314366e63ce3Schristos 		    &current_cpu->thread_data[threadno],
314466e63ce3Schristos 		    sizeof (current_cpu->thread_data[i]));
314566e63ce3Schristos 	    current_cpu->thread_data[i].cpu_context = thread_cpu_data;
314666e63ce3Schristos 	    current_cpu->thread_data[i].cpu_context_atsignal = NULL;
314766e63ce3Schristos 	    current_cpu->thread_data[i].threadid = current_cpu->max_threadid;
314866e63ce3Schristos 	    current_cpu->thread_data[i].parent_threadid
314966e63ce3Schristos 	      = current_cpu->thread_data[threadno].threadid;
315066e63ce3Schristos 	    current_cpu->thread_data[i].pipe_read_fd = 0;
315166e63ce3Schristos 	    current_cpu->thread_data[i].pipe_write_fd = 0;
315266e63ce3Schristos 	    current_cpu->thread_data[i].at_syscall = 0;
315366e63ce3Schristos 	    current_cpu->thread_data[i].sigpending = 0;
315466e63ce3Schristos 	    current_cpu->thread_data[i].sigsuspended = 0;
315566e63ce3Schristos 	    current_cpu->thread_data[i].exitsig = flags & TARGET_CSIGNAL;
315666e63ce3Schristos 	    current_cpu->m1threads = nthreads;
315766e63ce3Schristos 	    break;
315866e63ce3Schristos 	  }
315966e63ce3Schristos 
316066e63ce3Schristos 	/* Better watch these in case they do something necessary.  */
316166e63ce3Schristos 	case TARGET_SYS_socketcall:
316266e63ce3Schristos 	  retval = -cb_host_to_target_errno (cb, ENOSYS);
316366e63ce3Schristos 	  break;
316466e63ce3Schristos 
316566e63ce3Schristos 	case TARGET_SYS_set_thread_area:
316666e63ce3Schristos 	  /* Do the same error check as Linux.  */
316766e63ce3Schristos 	  if (arg1 & 255)
316866e63ce3Schristos 	    {
316966e63ce3Schristos 	      retval = -cb_host_to_target_errno (cb, EINVAL);
317066e63ce3Schristos 	      break;
317166e63ce3Schristos 	    }
317266e63ce3Schristos 	  (*current_cpu->set_target_thread_data) (current_cpu, arg1);
317366e63ce3Schristos 	  retval = 0;
317466e63ce3Schristos 	  break;
317566e63ce3Schristos 
317666e63ce3Schristos 	unimplemented_syscall:
317766e63ce3Schristos 	default:
317866e63ce3Schristos 	  retval
317966e63ce3Schristos 	    = cris_unknown_syscall (current_cpu, pc,
318066e63ce3Schristos 				    "Unimplemented syscall: %d "
318166e63ce3Schristos 				    "(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",
318266e63ce3Schristos 				    callnum, arg1, arg2, arg3, arg4, arg5,
318366e63ce3Schristos 				    arg6);
318466e63ce3Schristos 	}
318566e63ce3Schristos     }
318666e63ce3Schristos 
318766e63ce3Schristos   /* Minimal support for fcntl F_GETFL as used in open+fdopen.  */
318866e63ce3Schristos   if (callnum == TARGET_SYS_open)
318966e63ce3Schristos     {
319066e63ce3Schristos       current_cpu->last_open_fd = retval;
319166e63ce3Schristos       current_cpu->last_open_flags = arg2;
319266e63ce3Schristos     }
319366e63ce3Schristos 
319466e63ce3Schristos   current_cpu->last_syscall = callnum;
319566e63ce3Schristos 
319666e63ce3Schristos   /* A system call is a rescheduling point.  For the time being, we don't
319766e63ce3Schristos      reschedule anywhere else.  */
319866e63ce3Schristos   if (current_cpu->m1threads != 0
319966e63ce3Schristos       /* We need to schedule off from an exiting thread that is the
320066e63ce3Schristos 	 second-last one.  */
320166e63ce3Schristos       || (current_cpu->thread_data != NULL
320266e63ce3Schristos 	  && current_cpu->thread_data[threadno].cpu_context == NULL))
320366e63ce3Schristos     {
320466e63ce3Schristos       bfd_byte retval_buf[4];
320566e63ce3Schristos 
320666e63ce3Schristos       current_cpu->thread_data[threadno].last_execution
320766e63ce3Schristos 	= TARGET_TIME_MS (current_cpu);
320866e63ce3Schristos       bfd_putl32 (retval, retval_buf);
320966e63ce3Schristos       (*CPU_REG_STORE (current_cpu)) (current_cpu, H_GR_R10, retval_buf, 4);
321066e63ce3Schristos 
321166e63ce3Schristos       current_cpu->thread_data[threadno].at_syscall = 1;
321266e63ce3Schristos       reschedule (current_cpu);
321366e63ce3Schristos 
321466e63ce3Schristos       (*CPU_REG_FETCH (current_cpu)) (current_cpu, H_GR_R10, retval_buf, 4);
321566e63ce3Schristos       retval = bfd_getl32 (retval_buf);
321666e63ce3Schristos     }
321766e63ce3Schristos 
321866e63ce3Schristos   return retval;
321966e63ce3Schristos }
322066e63ce3Schristos 
322166e63ce3Schristos /* Callback from simulator write saying that the pipe at (reader, writer)
322266e63ce3Schristos    is now non-empty (so the writer should wait until the pipe is empty, at
322366e63ce3Schristos    least not write to this or any other pipe).  Simplest is to just wait
322466e63ce3Schristos    until the pipe is empty.  */
322566e63ce3Schristos 
322666e63ce3Schristos static void
cris_pipe_nonempty(host_callback * cb ATTRIBUTE_UNUSED,int reader,int writer)322766e63ce3Schristos cris_pipe_nonempty (host_callback *cb ATTRIBUTE_UNUSED,
322866e63ce3Schristos 		    int reader, int writer)
322966e63ce3Schristos {
323066e63ce3Schristos   SIM_CPU *cpu = current_cpu_for_cb_callback;
323166e63ce3Schristos   const bfd_byte zeros[4] = { 0, 0, 0, 0 };
323266e63ce3Schristos 
323366e63ce3Schristos   /* It's the current thread: we just have to re-run the current
323466e63ce3Schristos      syscall instruction (presumably "break 13") and change the syscall
323566e63ce3Schristos      to the special simulator-wait code.  Oh, and set a marker that
323666e63ce3Schristos      we're waiting, so we can disambiguate the special call from a
323766e63ce3Schristos      program error.
323866e63ce3Schristos 
323966e63ce3Schristos      This function may be called multiple times between cris_pipe_empty,
324066e63ce3Schristos      but we must avoid e.g. decreasing PC every time.  Check fd markers
324166e63ce3Schristos      to tell.  */
324266e63ce3Schristos   if (cpu->thread_data == NULL)
324366e63ce3Schristos     {
324466e63ce3Schristos       sim_io_eprintf (CPU_STATE (cpu),
324566e63ce3Schristos 		      "Terminating simulation due to writing pipe rd:wr %d:%d"
324666e63ce3Schristos 		      " from one single thread\n", reader, writer);
324766e63ce3Schristos       sim_engine_halt (CPU_STATE (cpu), cpu,
324866e63ce3Schristos 		       NULL, sim_pc_get (cpu), sim_stopped, SIM_SIGILL);
324966e63ce3Schristos     }
325066e63ce3Schristos   else if (cpu->thread_data[cpu->threadno].pipe_write_fd == 0)
325166e63ce3Schristos     {
325266e63ce3Schristos       cpu->thread_data[cpu->threadno].pipe_write_fd = writer;
325366e63ce3Schristos       cpu->thread_data[cpu->threadno].pipe_read_fd = reader;
325466e63ce3Schristos       /* FIXME: We really shouldn't change registers other than R10 in
325566e63ce3Schristos 	 syscalls (like R9), here or elsewhere.  */
325666e63ce3Schristos       (*CPU_REG_STORE (cpu)) (cpu, H_GR_R9, (bfd_byte *) zeros, 4);
325766e63ce3Schristos       sim_pc_set (cpu, sim_pc_get (cpu) - 2);
325866e63ce3Schristos     }
325966e63ce3Schristos }
326066e63ce3Schristos 
326166e63ce3Schristos /* Callback from simulator close or read call saying that the pipe at
326266e63ce3Schristos    (reader, writer) is now empty (so the writer can write again, perhaps
326366e63ce3Schristos    leave a waiting state).  If there are bytes remaining, they couldn't be
326466e63ce3Schristos    consumed (perhaps due to the pipe closing).  */
326566e63ce3Schristos 
326666e63ce3Schristos static void
cris_pipe_empty(host_callback * cb,int reader,int writer)326766e63ce3Schristos cris_pipe_empty (host_callback *cb,
326866e63ce3Schristos 		 int reader,
326966e63ce3Schristos 		 int writer)
327066e63ce3Schristos {
327166e63ce3Schristos   int i;
327266e63ce3Schristos   SIM_CPU *cpu = current_cpu_for_cb_callback;
327366e63ce3Schristos   SIM_DESC sd = CPU_STATE (current_cpu_for_cb_callback);
327466e63ce3Schristos   bfd_byte r10_buf[4];
327566e63ce3Schristos   int remaining
327666e63ce3Schristos     = cb->pipe_buffer[writer].size - cb->pipe_buffer[reader].size;
327766e63ce3Schristos 
327866e63ce3Schristos   /* We need to find the thread that waits for this pipe.  */
327966e63ce3Schristos   for (i = 0; i < SIM_TARGET_MAX_THREADS; i++)
328066e63ce3Schristos     if (cpu->thread_data[i].cpu_context
328166e63ce3Schristos 	&& cpu->thread_data[i].pipe_write_fd == writer)
328266e63ce3Schristos       {
328366e63ce3Schristos 	int retval;
328466e63ce3Schristos 
328566e63ce3Schristos 	/* Temporarily switch to this cpu context, so we can change the
328666e63ce3Schristos 	   PC by ordinary calls.  */
328766e63ce3Schristos 
328866e63ce3Schristos 	memcpy (cpu->thread_data[cpu->threadno].cpu_context,
328966e63ce3Schristos 		&cpu->cpu_data_placeholder,
329066e63ce3Schristos 		cpu->thread_cpu_data_size);
329166e63ce3Schristos 	memcpy (&cpu->cpu_data_placeholder,
329266e63ce3Schristos 		cpu->thread_data[i].cpu_context,
329366e63ce3Schristos 		cpu->thread_cpu_data_size);
329466e63ce3Schristos 
329566e63ce3Schristos 	/* The return value is supposed to contain the number of
329666e63ce3Schristos 	   written bytes, which is the number of bytes requested and
329766e63ce3Schristos 	   returned at the write call.  You might think the right
329866e63ce3Schristos 	   thing is to adjust the return-value to be only the
329966e63ce3Schristos 	   *consumed* number of bytes, but it isn't.  We're only
330066e63ce3Schristos 	   called if the pipe buffer is fully consumed or it is being
330166e63ce3Schristos 	   closed, possibly with remaining bytes.  For the latter
330266e63ce3Schristos 	   case, the writer is still supposed to see success for
330366e63ce3Schristos 	   PIPE_BUF bytes (a constant which we happen to know and is
330466e63ce3Schristos 	   unlikely to change).  The return value may also be a
330566e63ce3Schristos 	   negative number; an error value.  This case is covered
330666e63ce3Schristos 	   because "remaining" is always >= 0.  */
330766e63ce3Schristos 	(*CPU_REG_FETCH (cpu)) (cpu, H_GR_R10, r10_buf, 4);
330866e63ce3Schristos 	retval = (int) bfd_getl_signed_32 (r10_buf);
330966e63ce3Schristos 	if (retval - remaining > TARGET_PIPE_BUF)
331066e63ce3Schristos 	  {
331166e63ce3Schristos 	    bfd_putl32 (retval - remaining, r10_buf);
331266e63ce3Schristos 	    (*CPU_REG_STORE (cpu)) (cpu, H_GR_R10, r10_buf, 4);
331366e63ce3Schristos 	  }
331466e63ce3Schristos 	sim_pc_set (cpu, sim_pc_get (cpu) + 2);
331566e63ce3Schristos 	memcpy (cpu->thread_data[i].cpu_context,
331666e63ce3Schristos 		&cpu->cpu_data_placeholder,
331766e63ce3Schristos 		cpu->thread_cpu_data_size);
331866e63ce3Schristos 	memcpy (&cpu->cpu_data_placeholder,
331966e63ce3Schristos 		cpu->thread_data[cpu->threadno].cpu_context,
332066e63ce3Schristos 		cpu->thread_cpu_data_size);
332166e63ce3Schristos 	cpu->thread_data[i].pipe_read_fd = 0;
332266e63ce3Schristos 	cpu->thread_data[i].pipe_write_fd = 0;
332366e63ce3Schristos 	return;
332466e63ce3Schristos       }
332566e63ce3Schristos 
332666e63ce3Schristos   abort ();
332766e63ce3Schristos }
332866e63ce3Schristos 
332966e63ce3Schristos /* We have a simulator-specific notion of time.  See TARGET_TIME.  */
333066e63ce3Schristos 
333166e63ce3Schristos static long
cris_time(host_callback * cb ATTRIBUTE_UNUSED,long * t)333266e63ce3Schristos cris_time (host_callback *cb ATTRIBUTE_UNUSED, long *t)
333366e63ce3Schristos {
333466e63ce3Schristos   long retval = TARGET_TIME (current_cpu_for_cb_callback);
333566e63ce3Schristos   if (t)
333666e63ce3Schristos     *t = retval;
333766e63ce3Schristos   return retval;
333866e63ce3Schristos }
333966e63ce3Schristos 
334066e63ce3Schristos /* Set target-specific callback data. */
334166e63ce3Schristos 
334266e63ce3Schristos void
cris_set_callbacks(host_callback * cb)334366e63ce3Schristos cris_set_callbacks (host_callback *cb)
334466e63ce3Schristos {
334566e63ce3Schristos   /* Yeargh, have to cast away constness to avoid warnings.  */
334666e63ce3Schristos   cb->syscall_map = (CB_TARGET_DEFS_MAP *) syscall_map;
334766e63ce3Schristos   cb->errno_map = (CB_TARGET_DEFS_MAP *) errno_map;
334866e63ce3Schristos 
334966e63ce3Schristos   /* The kernel stat64 layout.  If we see a file > 2G, the "long"
335066e63ce3Schristos      parameter to cb_store_target_endian will make st_size negative.
335166e63ce3Schristos      Similarly for st_ino.  FIXME: Find a 64-bit type, and use it
335266e63ce3Schristos      *unsigned*, and/or add syntax for signed-ness.  */
335366e63ce3Schristos   cb->stat_map = stat_map;
335466e63ce3Schristos   cb->open_map = (CB_TARGET_DEFS_MAP *) open_map;
335566e63ce3Schristos   cb->pipe_nonempty = cris_pipe_nonempty;
335666e63ce3Schristos   cb->pipe_empty = cris_pipe_empty;
335766e63ce3Schristos   cb->time = cris_time;
335866e63ce3Schristos }
335966e63ce3Schristos 
336066e63ce3Schristos /* Process an address exception.  */
336166e63ce3Schristos 
336266e63ce3Schristos void
cris_core_signal(SIM_DESC sd,SIM_CPU * current_cpu,sim_cia cia,unsigned int map,int nr_bytes,address_word addr,transfer_type transfer,sim_core_signals sig)336366e63ce3Schristos cris_core_signal (SIM_DESC sd, SIM_CPU *current_cpu, sim_cia cia,
336466e63ce3Schristos 		  unsigned int map, int nr_bytes, address_word addr,
336566e63ce3Schristos 		  transfer_type transfer, sim_core_signals sig)
336666e63ce3Schristos {
336766e63ce3Schristos   sim_core_signal (sd, current_cpu, cia, map, nr_bytes, addr,
336866e63ce3Schristos 		   transfer, sig);
336966e63ce3Schristos }
3370