]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - sim/cris/traps.c
sim: reg: constify store helper
[thirdparty/binutils-gdb.git] / sim / cris / traps.c
CommitLineData
f6bcefef 1/* CRIS exception, interrupt, and trap (EIT) support
4a94e368 2 Copyright (C) 2004-2022 Free Software Foundation, Inc.
f6bcefef
HPN
3 Contributed by Axis Communications.
4
5This file is part of the GNU simulators.
6
7This program is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
4744ac1b
JB
9the Free Software Foundation; either version 3 of the License, or
10(at your option) any later version.
f6bcefef
HPN
11
12This program is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
4744ac1b
JB
17You should have received a copy of the GNU General Public License
18along with this program. If not, see <http://www.gnu.org/licenses/>. */
f6bcefef 19
6df01ab8
MF
20/* This must come before any other includes. */
21#include "defs.h"
22
ad9cc209 23#include "portability.h"
f6bcefef 24#include "sim-main.h"
61a0c964 25#include "sim-syscall.h"
f6bcefef 26#include "sim-options.h"
1fef66b0 27#include "sim-signal.h"
ef5058ae 28#include "sim/callback.h"
f6bcefef 29#include "bfd.h"
ed1f044a
HPN
30/* FIXME: get rid of targ-vals.h usage everywhere else. */
31
32a046ab 32#include <stdlib.h>
466b1d33 33#include <stdarg.h>
f6bcefef 34#include <errno.h>
f6bcefef
HPN
35#ifdef HAVE_UNISTD_H
36#include <unistd.h>
37#endif
38#ifdef HAVE_FCNTL_H
39#include <fcntl.h>
40#endif
41#ifdef HAVE_SYS_PARAM_H
42#include <sys/param.h>
43#endif
44#ifdef HAVE_SYS_STAT_H
45#include <sys/stat.h>
46#endif
3ca4d560
HPN
47/* For PATH_MAX, originally. */
48#ifdef HAVE_LIMITS_H
49#include <limits.h>
50#endif
51
52/* From ld/sysdep.h. */
53#ifdef PATH_MAX
54# define SIM_PATHMAX PATH_MAX
55#else
56# ifdef MAXPATHLEN
57# define SIM_PATHMAX MAXPATHLEN
58# else
59# define SIM_PATHMAX 1024
60# endif
61#endif
f6bcefef
HPN
62
63/* The verbatim values are from asm-cris/unistd.h. */
64
65#define TARGET_SYS_exit 1
66#define TARGET_SYS_read 3
67#define TARGET_SYS_write 4
68#define TARGET_SYS_open 5
69#define TARGET_SYS_close 6
70#define TARGET_SYS_unlink 10
71#define TARGET_SYS_time 13
72#define TARGET_SYS_lseek 19
73#define TARGET_SYS_getpid 20
e7fcaaa4 74#define TARGET_SYS_access 33
f6bcefef
HPN
75#define TARGET_SYS_kill 37
76#define TARGET_SYS_rename 38
77#define TARGET_SYS_pipe 42
78#define TARGET_SYS_brk 45
79#define TARGET_SYS_ioctl 54
80#define TARGET_SYS_fcntl 55
81#define TARGET_SYS_getppid 64
82#define TARGET_SYS_setrlimit 75
83#define TARGET_SYS_gettimeofday 78
84#define TARGET_SYS_readlink 85
85#define TARGET_SYS_munmap 91
86#define TARGET_SYS_truncate 92
87#define TARGET_SYS_ftruncate 93
88#define TARGET_SYS_socketcall 102
5457266c 89#define TARGET_SYS_stat 106
f6bcefef
HPN
90#define TARGET_SYS_fstat 108
91#define TARGET_SYS_wait4 114
92#define TARGET_SYS_sigreturn 119
93#define TARGET_SYS_clone 120
94#define TARGET_SYS_uname 122
95#define TARGET_SYS_mprotect 125
96#define TARGET_SYS_llseek 140
c06ccdf1 97#define TARGET_SYS_writev 146
f6bcefef
HPN
98#define TARGET_SYS__sysctl 149
99#define TARGET_SYS_sched_setparam 154
100#define TARGET_SYS_sched_getparam 155
101#define TARGET_SYS_sched_setscheduler 156
102#define TARGET_SYS_sched_getscheduler 157
103#define TARGET_SYS_sched_yield 158
104#define TARGET_SYS_sched_get_priority_max 159
105#define TARGET_SYS_sched_get_priority_min 160
106#define TARGET_SYS_mremap 163
107#define TARGET_SYS_poll 168
108#define TARGET_SYS_rt_sigaction 174
109#define TARGET_SYS_rt_sigprocmask 175
110#define TARGET_SYS_rt_sigsuspend 179
111#define TARGET_SYS_getcwd 183
112#define TARGET_SYS_ugetrlimit 191
113#define TARGET_SYS_mmap2 192
114#define TARGET_SYS_stat64 195
115#define TARGET_SYS_lstat64 196
116#define TARGET_SYS_fstat64 197
117#define TARGET_SYS_geteuid32 201
118#define TARGET_SYS_getuid32 199
119#define TARGET_SYS_getegid32 202
120#define TARGET_SYS_getgid32 200
121#define TARGET_SYS_fcntl64 221
ddf2c972 122#define TARGET_SYS_set_thread_area 243
e56b67ed 123#define TARGET_SYS_exit_group 252
f6bcefef
HPN
124
125#define TARGET_PROT_READ 0x1
126#define TARGET_PROT_WRITE 0x2
127#define TARGET_PROT_EXEC 0x4
128#define TARGET_PROT_NONE 0x0
129
130#define TARGET_MAP_SHARED 0x01
131#define TARGET_MAP_PRIVATE 0x02
132#define TARGET_MAP_TYPE 0x0f
133#define TARGET_MAP_FIXED 0x10
134#define TARGET_MAP_ANONYMOUS 0x20
a349c9b6 135#define TARGET_MAP_DENYWRITE 0x800
f6bcefef
HPN
136
137#define TARGET_CTL_KERN 1
138#define TARGET_CTL_VM 2
139#define TARGET_CTL_NET 3
140#define TARGET_CTL_PROC 4
141#define TARGET_CTL_FS 5
142#define TARGET_CTL_DEBUG 6
143#define TARGET_CTL_DEV 7
144#define TARGET_CTL_BUS 8
145#define TARGET_CTL_ABI 9
146
147#define TARGET_CTL_KERN_VERSION 4
148
149/* linux/mman.h */
150#define TARGET_MREMAP_MAYMOVE 1
151#define TARGET_MREMAP_FIXED 2
152
153#define TARGET_TCGETS 0x5401
154
ffc67e7a 155#define TARGET_UTSNAME "#7 Thu Jan 1 00:00:00 MET 2009"
f6bcefef 156
ffc67e7a
HPN
157/* Seconds since 1970-01-01 to the above date + 10 minutes;
158 'date -d "Thu Jan 1 00:00:10 MET 2009" +%s'. */
159#define TARGET_EPOCH 1230764410
f6bcefef
HPN
160
161/* Milliseconds since start of run. We use the number of syscalls to
162 avoid introducing noise in the execution time. */
163#define TARGET_TIME_MS(cpu) ((cpu)->syscalls)
164
165/* Seconds as in time(2). */
166#define TARGET_TIME(cpu) (TARGET_EPOCH + TARGET_TIME_MS (cpu) / 1000)
167
168#define TARGET_SCHED_OTHER 0
169
170#define TARGET_RLIMIT_STACK 3
171#define TARGET_RLIMIT_NOFILE 7
172
173#define SIM_TARGET_MAX_THREADS 64
174#define SIM_MAX_ALLOC_CHUNK (512*1024*1024)
175
176/* From linux/sched.h. */
177#define TARGET_CSIGNAL 0x000000ff
178#define TARGET_CLONE_VM 0x00000100
179#define TARGET_CLONE_FS 0x00000200
180#define TARGET_CLONE_FILES 0x00000400
181#define TARGET_CLONE_SIGHAND 0x00000800
182#define TARGET_CLONE_PID 0x00001000
183#define TARGET_CLONE_PTRACE 0x00002000
184#define TARGET_CLONE_VFORK 0x00004000
185#define TARGET_CLONE_PARENT 0x00008000
186#define TARGET_CLONE_THREAD 0x00010000
187#define TARGET_CLONE_SIGNAL (TARGET_CLONE_SIGHAND | TARGET_CLONE_THREAD)
188
189/* From asm-cris/poll.h. */
190#define TARGET_POLLIN 1
191
192/* From asm-cris/signal.h. */
193#define TARGET_SIG_BLOCK 0
194#define TARGET_SIG_UNBLOCK 1
195#define TARGET_SIG_SETMASK 2
196
197#define TARGET_SIG_DFL 0
198#define TARGET_SIG_IGN 1
199#define TARGET_SIG_ERR ((USI)-1)
200
201#define TARGET_SIGHUP 1
202#define TARGET_SIGINT 2
203#define TARGET_SIGQUIT 3
204#define TARGET_SIGILL 4
205#define TARGET_SIGTRAP 5
206#define TARGET_SIGABRT 6
207#define TARGET_SIGIOT 6
208#define TARGET_SIGBUS 7
209#define TARGET_SIGFPE 8
210#define TARGET_SIGKILL 9
211#define TARGET_SIGUSR1 10
212#define TARGET_SIGSEGV 11
213#define TARGET_SIGUSR2 12
214#define TARGET_SIGPIPE 13
215#define TARGET_SIGALRM 14
216#define TARGET_SIGTERM 15
217#define TARGET_SIGSTKFLT 16
218#define TARGET_SIGCHLD 17
219#define TARGET_SIGCONT 18
220#define TARGET_SIGSTOP 19
221#define TARGET_SIGTSTP 20
222#define TARGET_SIGTTIN 21
223#define TARGET_SIGTTOU 22
224#define TARGET_SIGURG 23
225#define TARGET_SIGXCPU 24
226#define TARGET_SIGXFSZ 25
227#define TARGET_SIGVTALRM 26
228#define TARGET_SIGPROF 27
229#define TARGET_SIGWINCH 28
230#define TARGET_SIGIO 29
231#define TARGET_SIGPOLL SIGIO
232/* Actually commented out in the kernel header. */
233#define TARGET_SIGLOST 29
234#define TARGET_SIGPWR 30
235#define TARGET_SIGSYS 31
236
237/* From include/asm-cris/signal.h. */
238#define TARGET_SA_NOCLDSTOP 0x00000001
239#define TARGET_SA_NOCLDWAIT 0x00000002 /* not supported yet */
240#define TARGET_SA_SIGINFO 0x00000004
241#define TARGET_SA_ONSTACK 0x08000000
242#define TARGET_SA_RESTART 0x10000000
243#define TARGET_SA_NODEFER 0x40000000
244#define TARGET_SA_RESETHAND 0x80000000
245#define TARGET_SA_INTERRUPT 0x20000000 /* dummy -- ignored */
246#define TARGET_SA_RESTORER 0x04000000
247
248/* From linux/wait.h. */
249#define TARGET_WNOHANG 1
250#define TARGET_WUNTRACED 2
251#define TARGET___WNOTHREAD 0x20000000
252#define TARGET___WALL 0x40000000
253#define TARGET___WCLONE 0x80000000
254
eccd787e
HPN
255/* From linux/limits.h. */
256#define TARGET_PIPE_BUF 4096
257
e7fcaaa4
HPN
258/* From unistd.h. */
259#define TARGET_R_OK 4
260#define TARGET_W_OK 2
261#define TARGET_X_OK 1
262#define TARGET_F_OK 0
263
f6bcefef
HPN
264static const char stat_map[] =
265"st_dev,2:space,10:space,4:st_mode,4:st_nlink,4:st_uid,4"
266":st_gid,4:st_rdev,2:space,10:st_size,8:st_blksize,4:st_blocks,4"
267":space,4:st_atime,4:space,4:st_mtime,4:space,4:st_ctime,4:space,4"
268":st_ino,8";
269
270static const CB_TARGET_DEFS_MAP syscall_map[] =
271{
6362a3f8
MF
272 { "open", CB_SYS_open, TARGET_SYS_open },
273 { "close", CB_SYS_close, TARGET_SYS_close },
274 { "read", CB_SYS_read, TARGET_SYS_read },
275 { "write", CB_SYS_write, TARGET_SYS_write },
276 { "lseek", CB_SYS_lseek, TARGET_SYS_lseek },
277 { "unlink", CB_SYS_unlink, TARGET_SYS_unlink },
278 { "getpid", CB_SYS_getpid, TARGET_SYS_getpid },
279 { "fstat", CB_SYS_fstat, TARGET_SYS_fstat64 },
280 { "lstat", CB_SYS_lstat, TARGET_SYS_lstat64 },
281 { "stat", CB_SYS_stat, TARGET_SYS_stat64 },
282 { "pipe", CB_SYS_pipe, TARGET_SYS_pipe },
283 { "rename", CB_SYS_rename, TARGET_SYS_rename },
284 { "truncate", CB_SYS_truncate, TARGET_SYS_truncate },
285 { "ftruncate", CB_SYS_ftruncate, TARGET_SYS_ftruncate },
286 { 0, -1, -1 }
f6bcefef
HPN
287};
288
289/* An older, 32-bit-only stat mapping. */
290static const char stat32_map[] =
291"st_dev,2:space,2:st_ino,4:st_mode,2:st_nlink,2:st_uid,2"
292":st_gid,2:st_rdev,2:space,2:st_size,4:st_blksize,4:st_blocks,4"
293":st_atime,4:space,4:st_mtime,4:space,4:st_ctime,4:space,12";
294
295/* Map for calls using the 32-bit struct stat. Primarily used by the
296 newlib Linux mapping. */
297static const CB_TARGET_DEFS_MAP syscall_stat32_map[] =
298{
6362a3f8
MF
299 { "fstat", CB_SYS_fstat, TARGET_SYS_fstat },
300 { "stat", CB_SYS_stat, TARGET_SYS_stat },
301 { 0, -1, -1 }
f6bcefef
HPN
302};
303
304/* Giving the true value for the running sim process will lead to
305 non-time-invariant behavior. */
306#define TARGET_PID 42
307
308/* Unfortunately, we don't get this from cris.cpu at the moment, and if
309 we did, we'd still don't get a register number with the "16" offset. */
310#define TARGET_SRP_REGNUM (16+11)
311
312/* Extracted by applying
313 awk '/^#define/ { printf "#ifdef %s\n { %s, %s },\n#endif\n", $2, $2, $3;}'
314 on .../include/asm/errno.h in a GNU/Linux/CRIS installation and
315 adjusting the synonyms. */
316
317static const CB_TARGET_DEFS_MAP errno_map[] =
318{
319#ifdef EPERM
6362a3f8 320 { "EPERM", EPERM, 1 },
f6bcefef
HPN
321#endif
322#ifdef ENOENT
6362a3f8 323 { "ENOENT", ENOENT, 2 },
f6bcefef
HPN
324#endif
325#ifdef ESRCH
6362a3f8 326 { "ESRCH", ESRCH, 3 },
f6bcefef
HPN
327#endif
328#ifdef EINTR
6362a3f8 329 { "EINTR", EINTR, 4 },
f6bcefef
HPN
330#endif
331#ifdef EIO
6362a3f8 332 { "EIO", EIO, 5 },
f6bcefef
HPN
333#endif
334#ifdef ENXIO
6362a3f8 335 { "ENXIO", ENXIO, 6 },
f6bcefef
HPN
336#endif
337#ifdef E2BIG
6362a3f8 338 { "E2BIG", E2BIG, 7 },
f6bcefef
HPN
339#endif
340#ifdef ENOEXEC
6362a3f8 341 { "ENOEXEC", ENOEXEC, 8 },
f6bcefef
HPN
342#endif
343#ifdef EBADF
6362a3f8 344 { "EBADF", EBADF, 9 },
f6bcefef
HPN
345#endif
346#ifdef ECHILD
6362a3f8 347 { "ECHILD", ECHILD, 10 },
f6bcefef
HPN
348#endif
349#ifdef EAGAIN
6362a3f8 350 { "EAGAIN", EAGAIN, 11 },
f6bcefef
HPN
351#endif
352#ifdef ENOMEM
6362a3f8 353 { "ENOMEM", ENOMEM, 12 },
f6bcefef
HPN
354#endif
355#ifdef EACCES
6362a3f8 356 { "EACCES", EACCES, 13 },
f6bcefef
HPN
357#endif
358#ifdef EFAULT
6362a3f8 359 { "EFAULT", EFAULT, 14 },
f6bcefef
HPN
360#endif
361#ifdef ENOTBLK
6362a3f8 362 { "ENOTBLK", ENOTBLK, 15 },
f6bcefef
HPN
363#endif
364#ifdef EBUSY
6362a3f8 365 { "EBUSY", EBUSY, 16 },
f6bcefef
HPN
366#endif
367#ifdef EEXIST
6362a3f8 368 { "EEXIST", EEXIST, 17 },
f6bcefef
HPN
369#endif
370#ifdef EXDEV
6362a3f8 371 { "EXDEV", EXDEV, 18 },
f6bcefef
HPN
372#endif
373#ifdef ENODEV
6362a3f8 374 { "ENODEV", ENODEV, 19 },
f6bcefef
HPN
375#endif
376#ifdef ENOTDIR
6362a3f8 377 { "ENOTDIR", ENOTDIR, 20 },
f6bcefef
HPN
378#endif
379#ifdef EISDIR
6362a3f8 380 { "EISDIR", EISDIR, 21 },
f6bcefef
HPN
381#endif
382#ifdef EINVAL
6362a3f8 383 { "EINVAL", EINVAL, 22 },
f6bcefef
HPN
384#endif
385#ifdef ENFILE
6362a3f8 386 { "ENFILE", ENFILE, 23 },
f6bcefef
HPN
387#endif
388#ifdef EMFILE
6362a3f8 389 { "EMFILE", EMFILE, 24 },
f6bcefef
HPN
390#endif
391#ifdef ENOTTY
6362a3f8 392 { "ENOTTY", ENOTTY, 25 },
f6bcefef
HPN
393#endif
394#ifdef ETXTBSY
6362a3f8 395 { "ETXTBSY", ETXTBSY, 26 },
f6bcefef
HPN
396#endif
397#ifdef EFBIG
6362a3f8 398 { "EFBIG", EFBIG, 27 },
f6bcefef
HPN
399#endif
400#ifdef ENOSPC
6362a3f8 401 { "ENOSPC", ENOSPC, 28 },
f6bcefef
HPN
402#endif
403#ifdef ESPIPE
6362a3f8 404 { "ESPIPE", ESPIPE, 29 },
f6bcefef
HPN
405#endif
406#ifdef EROFS
6362a3f8 407 { "EROFS", EROFS, 30 },
f6bcefef
HPN
408#endif
409#ifdef EMLINK
6362a3f8 410 { "EMLINK", EMLINK, 31 },
f6bcefef
HPN
411#endif
412#ifdef EPIPE
6362a3f8 413 { "EPIPE", EPIPE, 32 },
f6bcefef
HPN
414#endif
415#ifdef EDOM
6362a3f8 416 { "EDOM", EDOM, 33 },
f6bcefef
HPN
417#endif
418#ifdef ERANGE
6362a3f8 419 { "ERANGE", ERANGE, 34 },
f6bcefef
HPN
420#endif
421#ifdef EDEADLK
6362a3f8 422 { "EDEADLK", EDEADLK, 35 },
f6bcefef
HPN
423#endif
424#ifdef ENAMETOOLONG
6362a3f8 425 { "ENAMETOOLONG", ENAMETOOLONG, 36 },
f6bcefef
HPN
426#endif
427#ifdef ENOLCK
6362a3f8 428 { "ENOLCK", ENOLCK, 37 },
f6bcefef
HPN
429#endif
430#ifdef ENOSYS
6362a3f8 431 { "ENOSYS", ENOSYS, 38 },
f6bcefef
HPN
432#endif
433#ifdef ENOTEMPTY
6362a3f8 434 { "ENOTEMPTY", ENOTEMPTY, 39 },
f6bcefef
HPN
435#endif
436#ifdef ELOOP
6362a3f8 437 { "ELOOP", ELOOP, 40 },
f6bcefef
HPN
438#endif
439#ifdef EWOULDBLOCK
6362a3f8 440 { "EWOULDBLOCK", EWOULDBLOCK, 11 },
f6bcefef
HPN
441#endif
442#ifdef ENOMSG
6362a3f8 443 { "ENOMSG", ENOMSG, 42 },
f6bcefef
HPN
444#endif
445#ifdef EIDRM
6362a3f8 446 { "EIDRM", EIDRM, 43 },
f6bcefef
HPN
447#endif
448#ifdef ECHRNG
6362a3f8 449 { "ECHRNG", ECHRNG, 44 },
f6bcefef
HPN
450#endif
451#ifdef EL2NSYNC
6362a3f8 452 { "EL2NSYNC", EL2NSYNC, 45 },
f6bcefef
HPN
453#endif
454#ifdef EL3HLT
6362a3f8 455 { "EL3HLT", EL3HLT, 46 },
f6bcefef
HPN
456#endif
457#ifdef EL3RST
6362a3f8 458 { "EL3RST", EL3RST, 47 },
f6bcefef
HPN
459#endif
460#ifdef ELNRNG
6362a3f8 461 { "ELNRNG", ELNRNG, 48 },
f6bcefef
HPN
462#endif
463#ifdef EUNATCH
6362a3f8 464 { "EUNATCH", EUNATCH, 49 },
f6bcefef
HPN
465#endif
466#ifdef ENOCSI
6362a3f8 467 { "ENOCSI", ENOCSI, 50 },
f6bcefef
HPN
468#endif
469#ifdef EL2HLT
6362a3f8 470 { "EL2HLT", EL2HLT, 51 },
f6bcefef
HPN
471#endif
472#ifdef EBADE
6362a3f8 473 { "EBADE", EBADE, 52 },
f6bcefef
HPN
474#endif
475#ifdef EBADR
6362a3f8 476 { "EBADR", EBADR, 53 },
f6bcefef
HPN
477#endif
478#ifdef EXFULL
6362a3f8 479 { "EXFULL", EXFULL, 54 },
f6bcefef
HPN
480#endif
481#ifdef ENOANO
6362a3f8 482 { "ENOANO", ENOANO, 55 },
f6bcefef
HPN
483#endif
484#ifdef EBADRQC
6362a3f8 485 { "EBADRQC", EBADRQC, 56 },
f6bcefef
HPN
486#endif
487#ifdef EBADSLT
6362a3f8 488 { "EBADSLT", EBADSLT, 57 },
f6bcefef
HPN
489#endif
490#ifdef EDEADLOCK
6362a3f8 491 { "EDEADLOCK", EDEADLOCK, 35 },
f6bcefef
HPN
492#endif
493#ifdef EBFONT
6362a3f8 494 { "EBFONT", EBFONT, 59 },
f6bcefef
HPN
495#endif
496#ifdef ENOSTR
6362a3f8 497 { "ENOSTR", ENOSTR, 60 },
f6bcefef
HPN
498#endif
499#ifdef ENODATA
6362a3f8 500 { "ENODATA", ENODATA, 61 },
f6bcefef
HPN
501#endif
502#ifdef ETIME
6362a3f8 503 { "ETIME", ETIME, 62 },
f6bcefef
HPN
504#endif
505#ifdef ENOSR
6362a3f8 506 { "ENOSR", ENOSR, 63 },
f6bcefef
HPN
507#endif
508#ifdef ENONET
6362a3f8 509 { "ENONET", ENONET, 64 },
f6bcefef
HPN
510#endif
511#ifdef ENOPKG
6362a3f8 512 { "ENOPKG", ENOPKG, 65 },
f6bcefef
HPN
513#endif
514#ifdef EREMOTE
6362a3f8 515 { "EREMOTE", EREMOTE, 66 },
f6bcefef
HPN
516#endif
517#ifdef ENOLINK
6362a3f8 518 { "ENOLINK", ENOLINK, 67 },
f6bcefef
HPN
519#endif
520#ifdef EADV
6362a3f8 521 { "EADV", EADV, 68 },
f6bcefef
HPN
522#endif
523#ifdef ESRMNT
6362a3f8 524 { "ESRMNT", ESRMNT, 69 },
f6bcefef
HPN
525#endif
526#ifdef ECOMM
6362a3f8 527 { "ECOMM", ECOMM, 70 },
f6bcefef
HPN
528#endif
529#ifdef EPROTO
6362a3f8 530 { "EPROTO", EPROTO, 71 },
f6bcefef
HPN
531#endif
532#ifdef EMULTIHOP
6362a3f8 533 { "EMULTIHOP", EMULTIHOP, 72 },
f6bcefef
HPN
534#endif
535#ifdef EDOTDOT
6362a3f8 536 { "EDOTDOT", EDOTDOT, 73 },
f6bcefef
HPN
537#endif
538#ifdef EBADMSG
6362a3f8 539 { "EBADMSG", EBADMSG, 74 },
f6bcefef
HPN
540#endif
541#ifdef EOVERFLOW
6362a3f8 542 { "EOVERFLOW", EOVERFLOW, 75 },
f6bcefef
HPN
543#endif
544#ifdef ENOTUNIQ
6362a3f8 545 { "ENOTUNIQ", ENOTUNIQ, 76 },
f6bcefef
HPN
546#endif
547#ifdef EBADFD
6362a3f8 548 { "EBADFD", EBADFD, 77 },
f6bcefef
HPN
549#endif
550#ifdef EREMCHG
6362a3f8 551 { "EREMCHG", EREMCHG, 78 },
f6bcefef
HPN
552#endif
553#ifdef ELIBACC
6362a3f8 554 { "ELIBACC", ELIBACC, 79 },
f6bcefef
HPN
555#endif
556#ifdef ELIBBAD
6362a3f8 557 { "ELIBBAD", ELIBBAD, 80 },
f6bcefef
HPN
558#endif
559#ifdef ELIBSCN
6362a3f8 560 { "ELIBSCN", ELIBSCN, 81 },
f6bcefef
HPN
561#endif
562#ifdef ELIBMAX
6362a3f8 563 { "ELIBMAX", ELIBMAX, 82 },
f6bcefef
HPN
564#endif
565#ifdef ELIBEXEC
6362a3f8 566 { "ELIBEXEC", ELIBEXEC, 83 },
f6bcefef
HPN
567#endif
568#ifdef EILSEQ
6362a3f8 569 { "EILSEQ", EILSEQ, 84 },
f6bcefef
HPN
570#endif
571#ifdef ERESTART
6362a3f8 572 { "ERESTART", ERESTART, 85 },
f6bcefef
HPN
573#endif
574#ifdef ESTRPIPE
6362a3f8 575 { "ESTRPIPE", ESTRPIPE, 86 },
f6bcefef
HPN
576#endif
577#ifdef EUSERS
6362a3f8 578 { "EUSERS", EUSERS, 87 },
f6bcefef
HPN
579#endif
580#ifdef ENOTSOCK
6362a3f8 581 { "ENOTSOCK", ENOTSOCK, 88 },
f6bcefef
HPN
582#endif
583#ifdef EDESTADDRREQ
6362a3f8 584 { "EDESTADDRREQ", EDESTADDRREQ, 89 },
f6bcefef
HPN
585#endif
586#ifdef EMSGSIZE
6362a3f8 587 { "EMSGSIZE", EMSGSIZE, 90 },
f6bcefef
HPN
588#endif
589#ifdef EPROTOTYPE
6362a3f8 590 { "EPROTOTYPE", EPROTOTYPE, 91 },
f6bcefef
HPN
591#endif
592#ifdef ENOPROTOOPT
6362a3f8 593 { "ENOPROTOOPT", ENOPROTOOPT, 92 },
f6bcefef
HPN
594#endif
595#ifdef EPROTONOSUPPORT
6362a3f8 596 { "EPROTONOSUPPORT", EPROTONOSUPPORT, 93 },
f6bcefef
HPN
597#endif
598#ifdef ESOCKTNOSUPPORT
6362a3f8 599 { "ESOCKTNOSUPPORT", ESOCKTNOSUPPORT, 94 },
f6bcefef
HPN
600#endif
601#ifdef EOPNOTSUPP
6362a3f8 602 { "EOPNOTSUPP", EOPNOTSUPP, 95 },
f6bcefef
HPN
603#endif
604#ifdef EPFNOSUPPORT
6362a3f8 605 { "EPFNOSUPPORT", EPFNOSUPPORT, 96 },
f6bcefef
HPN
606#endif
607#ifdef EAFNOSUPPORT
6362a3f8 608 { "EAFNOSUPPORT", EAFNOSUPPORT, 97 },
f6bcefef
HPN
609#endif
610#ifdef EADDRINUSE
6362a3f8 611 { "EADDRINUSE", EADDRINUSE, 98 },
f6bcefef
HPN
612#endif
613#ifdef EADDRNOTAVAIL
6362a3f8 614 { "EADDRNOTAVAIL", EADDRNOTAVAIL, 99 },
f6bcefef
HPN
615#endif
616#ifdef ENETDOWN
6362a3f8 617 { "ENETDOWN", ENETDOWN, 100 },
f6bcefef
HPN
618#endif
619#ifdef ENETUNREACH
6362a3f8 620 { "ENETUNREACH", ENETUNREACH, 101 },
f6bcefef
HPN
621#endif
622#ifdef ENETRESET
6362a3f8 623 { "ENETRESET", ENETRESET, 102 },
f6bcefef
HPN
624#endif
625#ifdef ECONNABORTED
6362a3f8 626 { "ECONNABORTED", ECONNABORTED, 103 },
f6bcefef
HPN
627#endif
628#ifdef ECONNRESET
6362a3f8 629 { "ECONNRESET", ECONNRESET, 104 },
f6bcefef
HPN
630#endif
631#ifdef ENOBUFS
6362a3f8 632 { "ENOBUFS", ENOBUFS, 105 },
f6bcefef
HPN
633#endif
634#ifdef EISCONN
6362a3f8 635 { "EISCONN", EISCONN, 106 },
f6bcefef
HPN
636#endif
637#ifdef ENOTCONN
6362a3f8 638 { "ENOTCONN", ENOTCONN, 107 },
f6bcefef
HPN
639#endif
640#ifdef ESHUTDOWN
6362a3f8 641 { "ESHUTDOWN", ESHUTDOWN, 108 },
f6bcefef
HPN
642#endif
643#ifdef ETOOMANYREFS
6362a3f8 644 { "ETOOMANYREFS", ETOOMANYREFS, 109 },
f6bcefef
HPN
645#endif
646#ifdef ETIMEDOUT
6362a3f8 647 { "ETIMEDOUT", ETIMEDOUT, 110 },
f6bcefef
HPN
648#endif
649#ifdef ECONNREFUSED
6362a3f8 650 { "ECONNREFUSED", ECONNREFUSED, 111 },
f6bcefef
HPN
651#endif
652#ifdef EHOSTDOWN
6362a3f8 653 { "EHOSTDOWN", EHOSTDOWN, 112 },
f6bcefef
HPN
654#endif
655#ifdef EHOSTUNREACH
6362a3f8 656 { "EHOSTUNREACH", EHOSTUNREACH, 113 },
f6bcefef
HPN
657#endif
658#ifdef EALREADY
6362a3f8 659 { "EALREADY", EALREADY, 114 },
f6bcefef
HPN
660#endif
661#ifdef EINPROGRESS
6362a3f8 662 { "EINPROGRESS", EINPROGRESS, 115 },
f6bcefef
HPN
663#endif
664#ifdef ESTALE
6362a3f8 665 { "ESTALE", ESTALE, 116 },
f6bcefef
HPN
666#endif
667#ifdef EUCLEAN
6362a3f8 668 { "EUCLEAN", EUCLEAN, 117 },
f6bcefef
HPN
669#endif
670#ifdef ENOTNAM
6362a3f8 671 { "ENOTNAM", ENOTNAM, 118 },
f6bcefef
HPN
672#endif
673#ifdef ENAVAIL
6362a3f8 674 { "ENAVAIL", ENAVAIL, 119 },
f6bcefef
HPN
675#endif
676#ifdef EISNAM
6362a3f8 677 { "EISNAM", EISNAM, 120 },
f6bcefef
HPN
678#endif
679#ifdef EREMOTEIO
6362a3f8 680 { "EREMOTEIO", EREMOTEIO, 121 },
f6bcefef
HPN
681#endif
682#ifdef EDQUOT
6362a3f8 683 { "EDQUOT", EDQUOT, 122 },
f6bcefef
HPN
684#endif
685#ifdef ENOMEDIUM
6362a3f8 686 { "ENOMEDIUM", ENOMEDIUM, 123 },
f6bcefef
HPN
687#endif
688#ifdef EMEDIUMTYPE
6362a3f8 689 { "EMEDIUMTYPE", EMEDIUMTYPE, 124 },
f6bcefef 690#endif
6362a3f8 691 { 0, 0, 0 }
f6bcefef
HPN
692};
693
694/* Extracted by applying
695 perl -ne 'if ($_ =~ /^#define/) { split;
696 printf "#ifdef $_[1]\n { %s, 0x%x },\n#endif\n",
697 $_[1], $_[2] =~ /^0/ ? oct($_[2]) : $_[2];}'
698 on pertinent parts of .../include/asm/fcntl.h in a GNU/Linux/CRIS
699 installation and removing synonyms and unnecessary items. Don't
700 forget the end-marker. */
701
8b9b39f4
HPN
702/* These we treat specially, as they're used in the fcntl F_GETFL
703 syscall. For consistency, open_map is also manually edited to use
704 these macros. */
705#define TARGET_O_ACCMODE 0x3
706#define TARGET_O_RDONLY 0x0
707#define TARGET_O_WRONLY 0x1
ed1f044a 708
f6bcefef
HPN
709static const CB_TARGET_DEFS_MAP open_map[] = {
710#ifdef O_ACCMODE
6362a3f8 711 { "O_ACCMODE", O_ACCMODE, TARGET_O_ACCMODE },
f6bcefef
HPN
712#endif
713#ifdef O_RDONLY
6362a3f8 714 { "O_RDONLY", O_RDONLY, TARGET_O_RDONLY },
f6bcefef
HPN
715#endif
716#ifdef O_WRONLY
6362a3f8 717 { "O_WRONLY", O_WRONLY, TARGET_O_WRONLY },
f6bcefef
HPN
718#endif
719#ifdef O_RDWR
6362a3f8 720 { "O_RDWR", O_RDWR, 0x2 },
f6bcefef
HPN
721#endif
722#ifdef O_CREAT
6362a3f8 723 { "O_CREAT", O_CREAT, 0x40 },
f6bcefef
HPN
724#endif
725#ifdef O_EXCL
6362a3f8 726 { "O_EXCL", O_EXCL, 0x80 },
f6bcefef
HPN
727#endif
728#ifdef O_NOCTTY
6362a3f8 729 { "O_NOCTTY", O_NOCTTY, 0x100 },
f6bcefef
HPN
730#endif
731#ifdef O_TRUNC
6362a3f8 732 { "O_TRUNC", O_TRUNC, 0x200 },
f6bcefef
HPN
733#endif
734#ifdef O_APPEND
6362a3f8 735 { "O_APPEND", O_APPEND, 0x400 },
f6bcefef
HPN
736#endif
737#ifdef O_NONBLOCK
6362a3f8 738 { "O_NONBLOCK", O_NONBLOCK, 0x800 },
f6bcefef
HPN
739#endif
740#ifdef O_NDELAY
6362a3f8 741 { "O_NDELAY", O_NDELAY, 0x0 },
f6bcefef
HPN
742#endif
743#ifdef O_SYNC
6362a3f8 744 { "O_SYNC", O_SYNC, 0x1000 },
f6bcefef
HPN
745#endif
746#ifdef FASYNC
6362a3f8 747 { "FASYNC", FASYNC, 0x2000 },
f6bcefef
HPN
748#endif
749#ifdef O_DIRECT
6362a3f8 750 { "O_DIRECT", O_DIRECT, 0x4000 },
f6bcefef
HPN
751#endif
752#ifdef O_LARGEFILE
6362a3f8 753 { "O_LARGEFILE", O_LARGEFILE, 0x8000 },
f6bcefef
HPN
754#endif
755#ifdef O_DIRECTORY
6362a3f8 756 { "O_DIRECTORY", O_DIRECTORY, 0x10000 },
f6bcefef
HPN
757#endif
758#ifdef O_NOFOLLOW
6362a3f8 759 { "O_NOFOLLOW", O_NOFOLLOW, 0x20000 },
f6bcefef 760#endif
6362a3f8 761 { 0, -1, -1 }
f6bcefef
HPN
762};
763
fc887f09
HPN
764/* Let's be less drastic and more traceable. FIXME: mark as noreturn. */
765#define abort() \
766 sim_io_error (sd, "simulator unhandled condition at %s:%d", \
767 __FUNCTION__, __LINE__)
768
f6bcefef
HPN
769/* Needed for the cris_pipe_nonempty and cris_pipe_empty syscalls. */
770static SIM_CPU *current_cpu_for_cb_callback;
771
f6bcefef
HPN
772static USI create_map (SIM_DESC, struct cris_sim_mmapped_page **,
773 USI addr, USI len);
774static USI unmap_pages (SIM_DESC, struct cris_sim_mmapped_page **,
775 USI addr, USI len);
776static USI is_mapped (SIM_DESC, struct cris_sim_mmapped_page **,
777 USI addr, USI len);
778static void dump_statistics (SIM_CPU *current_cpu);
779static void make_first_thread (SIM_CPU *current_cpu);
780
f6bcefef
HPN
781/* When we risk running self-modified code (as in trampolines), this is
782 called from special-case insns. The silicon CRIS CPU:s have enough
783 cache snooping implemented making this a simulator-only issue. Tests:
784 gcc.c-torture/execute/931002-1.c execution, -O3 -g
785 gcc.c-torture/execute/931002-1.c execution, -O3 -fomit-frame-pointer. */
786
787void
788cris_flush_simulator_decode_cache (SIM_CPU *current_cpu,
789 USI pc ATTRIBUTE_UNUSED)
790{
791 SIM_DESC sd = CPU_STATE (current_cpu);
792
793#if WITH_SCACHE
794 if (USING_SCACHE_P (sd))
795 scache_flush_cpu (current_cpu);
796#endif
797}
798
799/* Output statistics at the end of a run. */
800static void
801dump_statistics (SIM_CPU *current_cpu)
802{
803 SIM_DESC sd = CPU_STATE (current_cpu);
804 CRIS_MISC_PROFILE *profp
805 = CPU_CRIS_MISC_PROFILE (current_cpu);
2875d098 806 uint64_t total = profp->basic_cycle_count;
1b40d569
MF
807
808 /* Historically, these messages have gone to stderr, so we'll keep it
809 that way. It's also easier to then tell it from normal program
810 output. FIXME: Add redirect option like "run -e file". */
f6bcefef
HPN
811
812 /* The --cris-stats={basic|unaligned|schedulable|all} counts affect
813 what's included in the "total" count only. */
814 switch (CPU_CRIS_MISC_PROFILE (current_cpu)->flags
815 & FLAG_CRIS_MISC_PROFILE_ALL)
816 {
817 case FLAG_CRIS_MISC_PROFILE_SIMPLE:
1b40d569 818 sim_io_eprintf (sd, "Basic clock cycles, total @: %" PRIu64 "\n", total);
f6bcefef
HPN
819 break;
820
821 case (FLAG_CRIS_MISC_PROFILE_UNALIGNED | FLAG_CRIS_MISC_PROFILE_SIMPLE):
f6bcefef 822 total += profp->unaligned_mem_dword_count;
1b40d569
MF
823 sim_io_eprintf (sd,
824 "Clock cycles including stall cycles for unaligned "
825 "accesses @: %" PRIu64 "\n",
826 total);
f6bcefef
HPN
827 break;
828
829 case (FLAG_CRIS_MISC_PROFILE_SCHEDULABLE | FLAG_CRIS_MISC_PROFILE_SIMPLE):
f6bcefef
HPN
830 total
831 += (profp->memsrc_stall_count
832 + profp->memraw_stall_count
833 + profp->movemsrc_stall_count
834 + profp->movemdst_stall_count
835 + profp->mulsrc_stall_count
836 + profp->jumpsrc_stall_count
837 + profp->unaligned_mem_dword_count);
1b40d569
MF
838 sim_io_eprintf (sd, "Schedulable clock cycles, total @: %" PRIu64 "\n",
839 total);
f6bcefef
HPN
840 break;
841
842 case FLAG_CRIS_MISC_PROFILE_ALL:
f6bcefef
HPN
843 total
844 += (profp->memsrc_stall_count
845 + profp->memraw_stall_count
846 + profp->movemsrc_stall_count
847 + profp->movemdst_stall_count
848 + profp->movemaddr_stall_count
849 + profp->mulsrc_stall_count
850 + profp->jumpsrc_stall_count
851 + profp->branch_stall_count
852 + profp->jumptarget_stall_count
853 + profp->unaligned_mem_dword_count);
1b40d569
MF
854 sim_io_eprintf (sd, "All accounted clock cycles, total @: %" PRIu64 "\n",
855 total);
f6bcefef
HPN
856 break;
857
858 default:
1b40d569
MF
859 sim_engine_abort (sd, current_cpu, 0,
860 "Internal inconsistency at %s:%d",
861 __FILE__, __LINE__);
f6bcefef
HPN
862 }
863
f6bcefef
HPN
864 /* For v32, unaligned_mem_dword_count should always be 0. For
865 v10, memsrc_stall_count should always be 0. */
1b40d569
MF
866 sim_io_eprintf (sd, "Memory source stall cycles: %" PRIu64 "\n",
867 profp->memsrc_stall_count + profp->unaligned_mem_dword_count);
868 sim_io_eprintf (sd, "Memory read-after-write stall cycles: %" PRIu64 "\n",
869 profp->memraw_stall_count);
870 sim_io_eprintf (sd, "Movem source stall cycles: %" PRIu64 "\n",
871 profp->movemsrc_stall_count);
872 sim_io_eprintf (sd, "Movem destination stall cycles: %" PRIu64 "\n",
873 profp->movemdst_stall_count);
874 sim_io_eprintf (sd, "Movem address stall cycles: %" PRIu64 "\n",
875 profp->movemaddr_stall_count);
876 sim_io_eprintf (sd, "Multiplication source stall cycles: %" PRIu64 "\n",
877 profp->mulsrc_stall_count);
878 sim_io_eprintf (sd, "Jump source stall cycles: %" PRIu64 "\n",
879 profp->jumpsrc_stall_count);
880 sim_io_eprintf (sd, "Branch misprediction stall cycles: %" PRIu64 "\n",
881 profp->branch_stall_count);
882 sim_io_eprintf (sd, "Jump target stall cycles: %" PRIu64 "\n",
883 profp->jumptarget_stall_count);
f6bcefef
HPN
884}
885
886/* Check whether any part of [addr .. addr + len - 1] is already mapped.
887 Return 1 if a overlap detected, 0 otherwise. */
888
889static USI
890is_mapped (SIM_DESC sd ATTRIBUTE_UNUSED,
891 struct cris_sim_mmapped_page **rootp,
892 USI addr, USI len)
893{
894 struct cris_sim_mmapped_page *mapp;
895
896 if (len == 0 || (len & 8191))
897 abort ();
898
899 /* Iterate over the reverse-address sorted pages until we find a page in
900 or lower than the checked area. */
901 for (mapp = *rootp; mapp != NULL && mapp->addr >= addr; mapp = mapp->prev)
902 if (mapp->addr < addr + len && mapp->addr >= addr)
903 return 1;
904
905 return 0;
906}
907
c06ccdf1
HPN
908/* Check whether any part of [addr .. addr + len - 1] is *un*mapped.
909 Return 1 if the whole area is mapped, 0 otherwise. */
910
911static USI
912is_mapped_only (SIM_DESC sd ATTRIBUTE_UNUSED,
913 struct cris_sim_mmapped_page **rootp,
914 USI addr, USI len)
915{
916 struct cris_sim_mmapped_page *mapp;
917
918 if (len == 0 || (len & 8191))
919 abort ();
920
921 /* Iterate over the reverse-address sorted pages until we find a page
922 lower than the checked area. */
923 for (mapp = *rootp; mapp != NULL && mapp->addr >= addr; mapp = mapp->prev)
924 if (addr == mapp->addr && len == 8192)
925 return 1;
926 else if (addr + len > mapp->addr)
927 len -= 8192;
928
929 return 0;
930}
931
a7cde6df
MF
932/* Provide a prototype to silence -Wmissing-prototypes. */
933void cris_dump_map (SIM_CPU *current_cpu);
c06ccdf1 934
a7cde6df 935/* Debug helper; to be run from gdb. */
c06ccdf1
HPN
936void
937cris_dump_map (SIM_CPU *current_cpu)
938{
939 struct cris_sim_mmapped_page *mapp;
940 USI start, end;
941
942 for (mapp = current_cpu->highest_mmapped_page,
943 start = mapp == NULL ? 0 : mapp->addr + 8192,
944 end = mapp == NULL ? 0 : mapp->addr + 8191;
945 mapp != NULL;
946 mapp = mapp->prev)
947 {
948 if (mapp->addr != start - 8192)
949 {
950 sim_io_eprintf (CPU_STATE (current_cpu), "0x%x..0x%x\n", start, end);
951 end = mapp->addr + 8191;
952 }
953
954 start = mapp->addr;
955 }
956
957 if (current_cpu->highest_mmapped_page != NULL)
958 sim_io_eprintf (CPU_STATE (current_cpu), "0x%x..0x%x\n", start, end);
959}
960
fc887f09
HPN
961/* Create mmapped memory. ADDR is -1 if any address will do. Caller
962 must make sure that the address isn't already mapped. */
f6bcefef
HPN
963
964static USI
965create_map (SIM_DESC sd, struct cris_sim_mmapped_page **rootp, USI addr,
966 USI len)
967{
968 struct cris_sim_mmapped_page *mapp;
969 struct cris_sim_mmapped_page **higher_prevp = rootp;
970 USI new_addr = 0x40000000;
971
fc887f09 972 if (addr != (USI) -1)
f6bcefef 973 new_addr = addr;
fc887f09 974 else if (*rootp && rootp[0]->addr >= new_addr)
f6bcefef
HPN
975 new_addr = rootp[0]->addr + 8192;
976
977 if (len != 8192)
978 {
979 USI page_addr;
980
981 if (len & 8191)
982 /* Which is better: return an error for this, or just round it up? */
983 abort ();
984
985 /* Do a recursive call for each page in the request. */
986 for (page_addr = new_addr; len != 0; page_addr += 8192, len -= 8192)
987 if (create_map (sd, rootp, page_addr, 8192) >= (USI) -8191)
988 abort ();
989
990 return new_addr;
991 }
992
993 for (mapp = *rootp;
994 mapp != NULL && mapp->addr > new_addr;
995 mapp = mapp->prev)
996 higher_prevp = &mapp->prev;
997
fc887f09
HPN
998 /* Assert for consistency that we don't create duplicate maps. */
999 if (is_mapped (sd, rootp, new_addr, len))
1000 abort ();
1001
f6bcefef
HPN
1002 /* Allocate the new page, on the next higher page from the last one
1003 allocated, and link in the new descriptor before previous ones. */
1004 mapp = malloc (sizeof (*mapp));
1005
1006 if (mapp == NULL)
1007 return (USI) -ENOMEM;
1008
1009 sim_core_attach (sd, NULL, 0, access_read_write_exec, 0,
1010 new_addr, len,
1011 0, NULL, NULL);
1012
1013 mapp->addr = new_addr;
1014 mapp->prev = *higher_prevp;
1015 *higher_prevp = mapp;
1016
1017 return new_addr;
1018}
1019
1020/* Unmap one or more pages. */
1021
1022static USI
1023unmap_pages (SIM_DESC sd, struct cris_sim_mmapped_page **rootp, USI addr,
1024 USI len)
1025{
1026 struct cris_sim_mmapped_page *mapp;
1027 struct cris_sim_mmapped_page **higher_prevp = rootp;
1028
1029 if (len != 8192)
1030 {
1031 USI page_addr;
fc887f09 1032 int ret = 0;
f6bcefef
HPN
1033
1034 if (len & 8191)
1035 /* Which is better: return an error for this, or just round it up? */
1036 abort ();
1037
1038 /* Loop backwards to make each call is O(1) over the number of pages
1039 allocated, if we're unmapping from the high end of the pages. */
1040 for (page_addr = addr + len - 8192;
fc887f09 1041 page_addr > addr;
f6bcefef 1042 page_addr -= 8192)
fc887f09
HPN
1043 if (unmap_pages (sd, rootp, page_addr, 8192))
1044 ret = EINVAL;
f6bcefef 1045
fc887f09
HPN
1046 if (unmap_pages (sd, rootp, addr, 8192))
1047 ret = EINVAL;
1048
1049 return ret;
f6bcefef
HPN
1050 }
1051
1052 for (mapp = *rootp; mapp != NULL && mapp->addr > addr; mapp = mapp->prev)
1053 higher_prevp = &mapp->prev;
1054
1055 if (mapp == NULL || mapp->addr != addr)
1056 return EINVAL;
1057
1058 *higher_prevp = mapp->prev;
1059 sim_core_detach (sd, NULL, 0, 0, addr);
1060 free (mapp);
1061 return 0;
1062}
1063
1064/* The semantic code invokes this for illegal (unrecognized) instructions. */
1065
1066SEM_PC
1067sim_engine_invalid_insn (SIM_CPU *current_cpu, IADDR cia, SEM_PC vpc)
1068{
1069 SIM_DESC sd = CPU_STATE (current_cpu);
1070
1071 sim_engine_halt (sd, current_cpu, NULL, cia, sim_stopped, SIM_SIGILL);
1072 return vpc;
1073}
1074
f6bcefef
HPN
1075/* Swap one context for another. */
1076
1077static void
1078schedule (SIM_CPU *current_cpu, int next)
1079{
1080 /* Need to mark context-switches in the trace output. */
1081 if ((CPU_CRIS_MISC_PROFILE (current_cpu)->flags
1082 & FLAG_CRIS_MISC_PROFILE_XSIM_TRACE))
1083 cris_trace_printf (CPU_STATE (current_cpu), current_cpu,
1084 "\t#:%d\n", next);
1085
1086 /* Copy the current context (if there is one) to its slot. */
1087 if (current_cpu->thread_data[current_cpu->threadno].cpu_context)
1088 memcpy (current_cpu->thread_data[current_cpu->threadno].cpu_context,
1089 &current_cpu->cpu_data_placeholder,
1090 current_cpu->thread_cpu_data_size);
1091
1092 /* Copy the new context from its slot. */
1093 memcpy (&current_cpu->cpu_data_placeholder,
1094 current_cpu->thread_data[next].cpu_context,
1095 current_cpu->thread_cpu_data_size);
1096
1097 /* Update needed stuff to indicate the new context. */
1098 current_cpu->threadno = next;
1099
1100 /* Handle pending signals. */
1101 if (current_cpu->thread_data[next].sigpending
1102 /* We don't run nested signal handlers. This means that pause(2)
1103 and sigsuspend(2) do not work in sighandlers, but that
1104 shouldn't be too hard a restriction. It also greatly
1105 simplifies the code. */
1106 && current_cpu->thread_data[next].cpu_context_atsignal == NULL)
1107 {
1108 int sig;
1109
1110 /* See if there's really a pending, non-blocked handler. We don't
1111 queue signals, so just use the first one in ascending order. */
1112 for (sig = 0; sig < 64; sig++)
1113 if (current_cpu->thread_data[next].sigdata[sig].pending
1114 && !current_cpu->thread_data[next].sigdata[sig].blocked)
1115 {
1116 bfd_byte regbuf[4];
1117 USI sp;
1118 int i;
1119 USI blocked;
1120 USI pc = sim_pc_get (current_cpu);
1121
1122 /* It's simpler to save the CPU context inside the simulator
1123 than on the stack. */
1124 current_cpu->thread_data[next].cpu_context_atsignal
1125 = (*current_cpu
1126 ->make_thread_cpu_data) (current_cpu,
1127 current_cpu->thread_data[next]
1128 .cpu_context);
1129
1130 (*CPU_REG_FETCH (current_cpu)) (current_cpu, H_GR_SP, regbuf, 4);
1131 sp = bfd_getl32 (regbuf);
1132
1133 /* Make sure we have an aligned stack. */
1134 sp &= ~3;
1135
1136 /* Make room for the signal frame, aligned. FIXME: Check that
1137 the memory exists, map it in if absent. (BTW, should also
1138 implement on-access automatic stack allocation). */
1139 sp -= 20;
1140
1141 /* This isn't the same signal frame as the kernel uses, because
1142 we don't want to bother getting all registers on and off the
1143 stack. */
1144
1145 /* First, we store the currently blocked signals. */
1146 blocked = 0;
1147 for (i = 0; i < 32; i++)
1148 blocked
1149 |= current_cpu->thread_data[next].sigdata[i + 1].blocked << i;
1150 sim_core_write_aligned_4 (current_cpu, pc, 0, sp, blocked);
1151 blocked = 0;
1152 for (i = 0; i < 31; i++)
1153 blocked
1154 |= current_cpu->thread_data[next].sigdata[i + 33].blocked << i;
1155 sim_core_write_aligned_4 (current_cpu, pc, 0, sp + 4, blocked);
1156
1157 /* Then, the actual instructions. This is CPU-specific, but we
1158 use instructions from the common subset for v10 and v32 which
1159 should be safe for the time being but could be parametrized
1160 if need be. */
1161 /* MOVU.W [PC+],R9. */
1162 sim_core_write_aligned_2 (current_cpu, pc, 0, sp + 8, 0x9c5f);
1163 /* .WORD TARGET_SYS_sigreturn. */
1164 sim_core_write_aligned_2 (current_cpu, pc, 0, sp + 10,
1165 TARGET_SYS_sigreturn);
1166 /* BREAK 13. */
1167 sim_core_write_aligned_2 (current_cpu, pc, 0, sp + 12, 0xe93d);
1168
1169 /* NOP (on v32; it's SETF on v10, but is the correct compatible
1170 instruction. Still, it doesn't matter because v10 has no
1171 delay slot for BREAK so it will not be executed). */
1172 sim_core_write_aligned_2 (current_cpu, pc, 0, sp + 16, 0x05b0);
1173
1174 /* Modify registers to hold the right values for the sighandler
1175 context: updated stackpointer and return address pointing to
1176 the sigreturn stub. */
1177 bfd_putl32 (sp, regbuf);
1178 (*CPU_REG_STORE (current_cpu)) (current_cpu, H_GR_SP, regbuf, 4);
1179 bfd_putl32 (sp + 8, regbuf);
1180 (*CPU_REG_STORE (current_cpu)) (current_cpu, TARGET_SRP_REGNUM,
1181 regbuf, 4);
1182
1183 current_cpu->thread_data[next].sigdata[sig].pending = 0;
1184
1185 /* Block this signal (for the duration of the sighandler). */
1186 current_cpu->thread_data[next].sigdata[sig].blocked = 1;
1187
1188 sim_pc_set (current_cpu, current_cpu->sighandler[sig]);
1189 bfd_putl32 (sig, regbuf);
1190 (*CPU_REG_STORE (current_cpu)) (current_cpu, H_GR_R10,
1191 regbuf, 4);
1192
1193 /* We ignore a SA_SIGINFO flag in the sigaction call; the code I
1194 needed all this for, specifies a SA_SIGINFO call but treats it
1195 like an ordinary sighandler; only the signal number argument is
1196 inspected. To make future need to implement SA_SIGINFO
1197 correctly possible, we set the siginfo argument register to a
1198 magic (hopefully non-address) number. (NB: then, you should
1199 just need to pass the siginfo argument; it seems you probably
1200 don't need to implement the specific rt_sigreturn.) */
1201 bfd_putl32 (0xbad5161f, regbuf);
1202 (*CPU_REG_STORE (current_cpu)) (current_cpu, H_GR_R11,
1203 regbuf, 4);
1204
1205 /* The third argument is unused and the kernel sets it to 0. */
1206 bfd_putl32 (0, regbuf);
1207 (*CPU_REG_STORE (current_cpu)) (current_cpu, H_GR_R12,
1208 regbuf, 4);
1209 return;
1210 }
1211
1212 /* No, there actually was no pending signal for this thread. Reset
1213 this flag. */
1214 current_cpu->thread_data[next].sigpending = 0;
1215 }
1216}
1217
1218/* Reschedule the simplest possible way until something else is absolutely
1219 necessary:
1220 - A. Find the next process (round-robin) that doesn't have at_syscall
1221 set, schedule it.
1222 - B. If there is none, just run the next process, round-robin.
1223 - Clear at_syscall for the current process. */
1224
1225static void
1226reschedule (SIM_CPU *current_cpu)
1227{
fc887f09 1228 SIM_DESC sd = CPU_STATE (current_cpu);
f6bcefef
HPN
1229 int i;
1230
1231 /* Iterate over all thread slots, because after a few thread creations
1232 and exits, we don't know where the live ones are. */
1233 for (i = (current_cpu->threadno + 1) % SIM_TARGET_MAX_THREADS;
1234 i != current_cpu->threadno;
1235 i = (i + 1) % SIM_TARGET_MAX_THREADS)
1236 if (current_cpu->thread_data[i].cpu_context
1237 && current_cpu->thread_data[i].at_syscall == 0)
1238 {
1239 schedule (current_cpu, i);
1240 return;
1241 }
1242
1243 /* Pick any next live thread. */
1244 for (i = (current_cpu->threadno + 1) % SIM_TARGET_MAX_THREADS;
1245 i != current_cpu->threadno;
1246 i = (i + 1) % SIM_TARGET_MAX_THREADS)
1247 if (current_cpu->thread_data[i].cpu_context)
1248 {
1249 schedule (current_cpu, i);
1250 return;
1251 }
1252
1253 /* More than one live thread, but we couldn't find the next one? */
1254 abort ();
1255}
1256
1257/* Set up everything to receive (or IGN) an incoming signal to the
1258 current context. */
1259
1260static int
1261deliver_signal (SIM_CPU *current_cpu, int sig, unsigned int pid)
1262{
1263 int i;
1264 USI pc = sim_pc_get (current_cpu);
1265
1266 /* Find the thread index of the pid. */
1267 for (i = 0; i < SIM_TARGET_MAX_THREADS; i++)
1268 /* Apparently it's ok to send signals to zombies (so a check for
1269 current_cpu->thread_data[i].cpu_context != NULL would be
1270 wrong). */
1271 if (current_cpu->thread_data[i].threadid == pid - TARGET_PID)
1272 {
1273 if (sig < 64)
1274 switch (current_cpu->sighandler[sig])
1275 {
1276 case TARGET_SIG_DFL:
1277 switch (sig)
1278 {
1279 /* The following according to the glibc
1280 documentation. (The kernel code has non-obvious
1281 execution paths.) */
1282 case TARGET_SIGFPE:
1283 case TARGET_SIGILL:
1284 case TARGET_SIGSEGV:
1285 case TARGET_SIGBUS:
1286 case TARGET_SIGABRT:
1287 case TARGET_SIGTRAP:
1288 case TARGET_SIGSYS:
1289
1290 case TARGET_SIGTERM:
1291 case TARGET_SIGINT:
1292 case TARGET_SIGQUIT:
1293 case TARGET_SIGKILL:
1294 case TARGET_SIGHUP:
1295
1296 case TARGET_SIGALRM:
1297 case TARGET_SIGVTALRM:
1298 case TARGET_SIGPROF:
1299 case TARGET_SIGSTOP:
1300
1301 case TARGET_SIGPIPE:
1302 case TARGET_SIGLOST:
1303 case TARGET_SIGXCPU:
1304 case TARGET_SIGXFSZ:
1305 case TARGET_SIGUSR1:
1306 case TARGET_SIGUSR2:
1307 sim_io_eprintf (CPU_STATE (current_cpu),
1308 "Exiting pid %d due to signal %d\n",
1309 pid, sig);
1310 sim_engine_halt (CPU_STATE (current_cpu), current_cpu,
1311 NULL, pc, sim_stopped,
1312 sig == TARGET_SIGABRT
1313 ? SIM_SIGABRT : SIM_SIGILL);
1314 return 0;
1315
1316 /* The default for all other signals is to be ignored. */
1317 default:
1318 return 0;
1319 }
1320
1321 case TARGET_SIG_IGN:
1322 switch (sig)
1323 {
1324 case TARGET_SIGKILL:
1325 case TARGET_SIGSTOP:
1326 /* Can't ignore these signals. */
1327 sim_io_eprintf (CPU_STATE (current_cpu),
1328 "Exiting pid %d due to signal %d\n",
1329 pid, sig);
1330 sim_engine_halt (CPU_STATE (current_cpu), current_cpu,
1331 NULL, pc, sim_stopped, SIM_SIGILL);
1332 return 0;
1333
1334 default:
1335 return 0;
1336 }
1337 break;
1338
1339 default:
1340 /* Mark the signal as pending, making schedule () check
1341 closer. The signal will be handled when the thread is
1342 scheduled and the signal is unblocked. */
1343 current_cpu->thread_data[i].sigdata[sig].pending = 1;
1344 current_cpu->thread_data[i].sigpending = 1;
1345 return 0;
1346 }
1347 else
1348 {
1349 sim_io_eprintf (CPU_STATE (current_cpu),
1350 "Unimplemented signal: %d\n", sig);
1351 sim_engine_halt (CPU_STATE (current_cpu), current_cpu, NULL, pc,
1352 sim_stopped, SIM_SIGILL);
1353 }
1354 }
1355
1356 return
1357 -cb_host_to_target_errno (STATE_CALLBACK (CPU_STATE (current_cpu)),
1358 ESRCH);
1359}
1360
1361/* Make the vector and the first item, the main thread. */
1362
1363static void
1364make_first_thread (SIM_CPU *current_cpu)
1365{
fc887f09 1366 SIM_DESC sd = CPU_STATE (current_cpu);
f6bcefef
HPN
1367 current_cpu->thread_data
1368 = xcalloc (1,
1369 SIM_TARGET_MAX_THREADS
1370 * sizeof (current_cpu->thread_data[0]));
1371 current_cpu->thread_data[0].cpu_context
1372 = (*current_cpu->make_thread_cpu_data) (current_cpu,
1373 &current_cpu
1374 ->cpu_data_placeholder);
1375 current_cpu->thread_data[0].parent_threadid = -1;
1376
1377 /* For good measure. */
1378 if (TARGET_SIG_DFL != 0)
1379 abort ();
1380}
1381
466b1d33
HPN
1382/* Handle unknown system calls. Returns (if it does) the syscall
1383 return value. */
1384
a26c7ec2 1385static USI ATTRIBUTE_PRINTF (3, 4)
466b1d33
HPN
1386cris_unknown_syscall (SIM_CPU *current_cpu, USI pc, char *s, ...)
1387{
1388 SIM_DESC sd = CPU_STATE (current_cpu);
1389 host_callback *cb = STATE_CALLBACK (sd);
1390
1391 if (cris_unknown_syscall_action == CRIS_USYSC_MSG_STOP
1392 || cris_unknown_syscall_action == CRIS_USYSC_MSG_ENOSYS)
1393 {
1394 va_list ap;
1395
1396 va_start (ap, s);
1397 sim_io_evprintf (sd, s, ap);
1398 va_end (ap);
1399
1400 if (cris_unknown_syscall_action == CRIS_USYSC_MSG_STOP)
1401 sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped, SIM_SIGILL);
1402 }
1403
1404 return -cb_host_to_target_errno (cb, ENOSYS);
1405}
1406
f6bcefef
HPN
1407/* Main function: the handler of the "break 13" syscall insn. */
1408
1409USI
1410cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
1411 USI arg2, USI arg3, USI arg4, USI arg5, USI arg6,
1412 USI pc)
1413{
1414 CB_SYSCALL s;
1415 SIM_DESC sd = CPU_STATE (current_cpu);
1416 host_callback *cb = STATE_CALLBACK (sd);
1417 int retval;
1418 int threadno = current_cpu->threadno;
1419
1420 current_cpu->syscalls++;
1421
1422 CB_SYSCALL_INIT (&s);
1423 s.func = callnum;
1424 s.arg1 = arg1;
1425 s.arg2 = arg2;
1426 s.arg3 = arg3;
1427
7cf1d8af
HPN
1428 /* The type of s.arg2 is long, so for hosts with 64-bit longs, we need
1429 to sign-extend the lseek offset to be passed as a signed number,
1430 else we'll truncate it to something > 2GB on hosts where sizeof
1431 long > sizeof USI. We avoid doing it for all syscalls, as arg2 is
1432 e.g. an address for some syscalls. */
1433 if (callnum == TARGET_SYS_lseek)
1434 s.arg2 = (SI) arg2;
1435
e56b67ed
HPN
1436 if (callnum == TARGET_SYS_exit_group
1437 || (callnum == TARGET_SYS_exit && current_cpu->m1threads == 0))
f6bcefef
HPN
1438 {
1439 if (CPU_CRIS_MISC_PROFILE (current_cpu)->flags
1440 & FLAG_CRIS_MISC_PROFILE_ALL)
1441 dump_statistics (current_cpu);
1442 sim_engine_halt (sd, current_cpu, NULL, pc, sim_exited, arg1);
1443 }
1444
845cbaa9
AM
1445 s.p1 = sd;
1446 s.p2 = current_cpu;
61a0c964
MF
1447 s.read_mem = sim_syscall_read_mem;
1448 s.write_mem = sim_syscall_write_mem;
f6bcefef
HPN
1449
1450 current_cpu_for_cb_callback = current_cpu;
1451
1452 if (cb_syscall (cb, &s) != CB_RC_OK)
1453 {
1b40d569
MF
1454 sim_engine_abort (sd, current_cpu, pc,
1455 "Break 13: invalid %d? Returned %ld\n", callnum,
1456 s.result);
f6bcefef
HPN
1457 }
1458
1459 retval = s.result == -1 ? -s.errcode : s.result;
1460
1461 if (s.errcode != 0 && s.errcode == cb_host_to_target_errno (cb, ENOSYS))
1462 {
1463 /* If the generic simulator call said ENOSYS, then let's try the
1464 ones we know ourselves.
1465
1466 The convention is to provide *very limited* functionality on an
1467 as-needed basis, only what's covered by the test-suite, tests
1468 added when functionality changes and abort with a descriptive
1469 message for *everything* else. Where there's no test-case, we
1470 just abort. */
1471 switch (callnum)
1472 {
1473 case 0:
1474 /* It's a pretty safe bet that the "old setup() system call"
1475 number will not be re-used; we can't say the same for higher
1476 numbers. We treat this simulator-generated call as "wait
1477 forever"; we re-run this insn. The wait is ended by a
1478 callback. Sanity check that this is the reason we got
1479 here. */
1480 if (current_cpu->thread_data == NULL
1481 || (current_cpu->thread_data[threadno].pipe_write_fd == 0))
1482 goto unimplemented_syscall;
1483
1484 sim_pc_set (current_cpu, pc);
1485 retval = arg1;
1486 break;
1487
1488 case TARGET_SYS_fcntl64:
1489 case TARGET_SYS_fcntl:
ed1f044a 1490 switch (arg2)
f6bcefef 1491 {
ed1f044a 1492 case 1:
f6bcefef
HPN
1493 /* F_GETFD.
1494 Glibc checks stdin, stdout and stderr fd:s for
1495 close-on-exec security sanity. We just need to provide a
1496 OK return value. If we really need to have a
1497 close-on-exec flag true, we could just do a real fcntl
1498 here. */
1499 retval = 0;
ed1f044a
HPN
1500 break;
1501
1502 case 2:
f6bcefef
HPN
1503 /* F_SETFD. Just ignore attempts to set the close-on-exec
1504 flag. */
1505 retval = 0;
ed1f044a
HPN
1506 break;
1507
1508 case 3:
1509 /* F_GETFL. Check for the special case for open+fdopen. */
1510 if (current_cpu->last_syscall == TARGET_SYS_open
1511 && arg1 == current_cpu->last_open_fd)
1512 {
1513 retval = current_cpu->last_open_flags & TARGET_O_ACCMODE;
1514 break;
1515 }
8b9b39f4
HPN
1516 else if (arg1 == 0)
1517 {
1518 /* Because we can't freopen fd:s 0, 1, 2 to mean
1519 something else than stdin, stdout and stderr
1520 (sim/common/syscall.c:cb_syscall special cases fd
1521 0, 1 and 2), we know what flags that we can
1522 sanely return for these fd:s. */
1523 retval = TARGET_O_RDONLY;
1524 break;
1525 }
1526 else if (arg1 == 1 || arg1 == 2)
1527 {
1528 retval = TARGET_O_WRONLY;
1529 break;
1530 }
ed1f044a 1531 /* FALLTHROUGH */
ed1f044a 1532 default:
466b1d33
HPN
1533 /* Nothing else is implemented. */
1534 retval
1535 = cris_unknown_syscall (current_cpu, pc,
1536 "Unimplemented %s syscall "
1537 "(fd: 0x%lx: cmd: 0x%lx arg: "
1538 "0x%lx)\n",
1539 callnum == TARGET_SYS_fcntl
1540 ? "fcntl" : "fcntl64",
1541 (unsigned long) (USI) arg1,
1542 (unsigned long) (USI) arg2,
1543 (unsigned long) (USI) arg3);
ed1f044a 1544 break;
f6bcefef
HPN
1545 }
1546 break;
1547
1548 case TARGET_SYS_uname:
1549 {
1550 /* Fill in a few constants to appease glibc. */
ffc67e7a 1551 static char sim_utsname[6][65] =
f6bcefef
HPN
1552 {
1553 "Linux",
1554 "sim-target",
ffc67e7a 1555 "2.6.27",
f6bcefef 1556 TARGET_UTSNAME,
ffc67e7a 1557 "cris", /* Overwritten below. */
f6bcefef
HPN
1558 "localdomain"
1559 };
1560
ffc67e7a
HPN
1561 /* Having the hardware type in Linux equal to the bfd
1562 printable name is deliberate: if you make config.guess
1563 work on your Linux-type system the usual way, it
1564 probably will; either the bfd printable_name or the
1565 ambiguous arch_name. */
1566 strcpy (sim_utsname[4], STATE_ARCHITECTURE (sd)->printable_name);
1567
f6bcefef
HPN
1568 if ((s.write_mem) (cb, &s, arg1, (const char *) sim_utsname,
1569 sizeof (sim_utsname))
1570 != sizeof (sim_utsname))
1571 retval = -cb_host_to_target_errno (cb, EFAULT);
1572 else
1573 retval = 0;
1574 break;
1575 }
1576
1577 case TARGET_SYS_geteuid32:
1578 /* We tell the truth with these. Maybe we shouldn't, but it
1579 should match the "stat" information. */
1580 retval = geteuid ();
1581 break;
1582
1583 case TARGET_SYS_getuid32:
1584 retval = getuid ();
1585 break;
1586
1587 case TARGET_SYS_getegid32:
1588 retval = getegid ();
1589 break;
1590
1591 case TARGET_SYS_getgid32:
1592 retval = getgid ();
1593 break;
1594
1595 case TARGET_SYS_brk:
1596 /* Most often, we just return the argument, like the Linux
1597 kernel. */
1598 retval = arg1;
1599
1600 if (arg1 == 0)
1601 retval = current_cpu->endbrk;
1602 else if (arg1 <= current_cpu->endmem)
1603 current_cpu->endbrk = arg1;
1604 else
1605 {
1606 USI new_end = (arg1 + 8191) & ~8191;
1607
1608 /* If the simulator wants to brk more than a certain very
1609 large amount, something is wrong. FIXME: Return an error
1610 or abort? Have command-line selectable? */
1611 if (new_end - current_cpu->endmem > SIM_MAX_ALLOC_CHUNK)
1612 {
1613 current_cpu->endbrk = current_cpu->endmem;
1614 retval = current_cpu->endmem;
1615 break;
1616 }
1617
1618 sim_core_attach (sd, NULL, 0, access_read_write_exec, 0,
1619 current_cpu->endmem,
1620 new_end - current_cpu->endmem,
1621 0, NULL, NULL);
1622 current_cpu->endbrk = arg1;
1623 current_cpu->endmem = new_end;
1624 }
1625 break;
1626
1627 case TARGET_SYS_getpid:
1628 /* Correct until CLONE_THREAD is implemented. */
1629 retval = current_cpu->thread_data == NULL
1630 ? TARGET_PID
1631 : TARGET_PID + current_cpu->thread_data[threadno].threadid;
1632 break;
1633
1634 case TARGET_SYS_getppid:
1635 /* Correct until CLONE_THREAD is implemented. */
1636 retval = current_cpu->thread_data == NULL
1637 ? TARGET_PID - 1
1638 : (TARGET_PID
1639 + current_cpu->thread_data[threadno].parent_threadid);
1640 break;
1641
1642 case TARGET_SYS_mmap2:
1643 {
1644 USI addr = arg1;
1645 USI len = arg2;
1646 USI prot = arg3;
1647 USI flags = arg4;
1648 USI fd = arg5;
1649 USI pgoff = arg6;
1650
a349c9b6
HPN
1651 /* At 2.6.27, Linux (many (all?) ports, in the mmap2 syscalls)
1652 still masked away this bit, so let's just ignore
1653 it. */
1654 flags &= ~TARGET_MAP_DENYWRITE;
1655
f6bcefef
HPN
1656 /* If the simulator wants to mmap more than the very large
1657 limit, something is wrong. FIXME: Return an error or
1658 abort? Have command-line selectable? */
1659 if (len > SIM_MAX_ALLOC_CHUNK)
1660 {
1661 retval = -cb_host_to_target_errno (cb, ENOMEM);
1662 break;
1663 }
1664
1665 if ((prot != (TARGET_PROT_READ | TARGET_PROT_WRITE)
1666 && (prot
1667 != (TARGET_PROT_READ
1668 | TARGET_PROT_WRITE
1669 | TARGET_PROT_EXEC))
c06ccdf1 1670 && (prot != (TARGET_PROT_READ | TARGET_PROT_EXEC))
f6bcefef
HPN
1671 && prot != TARGET_PROT_READ)
1672 || (flags != (TARGET_MAP_ANONYMOUS | TARGET_MAP_PRIVATE)
1673 && flags != TARGET_MAP_PRIVATE
c06ccdf1
HPN
1674 && flags != (TARGET_MAP_ANONYMOUS
1675 | TARGET_MAP_PRIVATE | TARGET_MAP_FIXED)
1676 && flags != (TARGET_MAP_PRIVATE | TARGET_MAP_FIXED)
f6bcefef 1677 && flags != TARGET_MAP_SHARED)
c06ccdf1
HPN
1678 || (fd != (USI) -1
1679 && prot != TARGET_PROT_READ
1680 && prot != (TARGET_PROT_READ | TARGET_PROT_EXEC)
1681 && prot != (TARGET_PROT_READ | TARGET_PROT_WRITE))
1682 || (fd == (USI) -1 && pgoff != 0)
fc887f09 1683 || (fd != (USI) -1 && (flags & TARGET_MAP_ANONYMOUS)))
f6bcefef 1684 {
466b1d33
HPN
1685 retval
1686 = cris_unknown_syscall (current_cpu, pc,
1687 "Unimplemented mmap2 call "
1688 "(0x%lx, 0x%lx, 0x%lx, "
1689 "0x%lx, 0x%lx, 0x%lx)\n",
1690 (unsigned long) arg1,
1691 (unsigned long) arg2,
1692 (unsigned long) arg3,
1693 (unsigned long) arg4,
1694 (unsigned long) arg5,
1695 (unsigned long) arg6);
f6bcefef
HPN
1696 break;
1697 }
1698 else if (fd != (USI) -1)
1699 {
1700 /* Map a file. */
1701
1702 USI newaddr;
1703 USI pos;
1704
1705 /* A non-aligned argument is allowed for files. */
1706 USI newlen = (len + 8191) & ~8191;
1707
c06ccdf1
HPN
1708 /* We only support read, read|exec, and read|write,
1709 which we should already have checked. Check again
1710 anyway. */
1711 if (prot != TARGET_PROT_READ
1712 && prot != (TARGET_PROT_READ | TARGET_PROT_EXEC)
1713 && prot != (TARGET_PROT_READ | TARGET_PROT_WRITE))
1714 abort ();
1715
fc887f09
HPN
1716 if (flags & TARGET_MAP_FIXED)
1717 unmap_pages (sd, &current_cpu->highest_mmapped_page,
1718 addr, newlen);
1719 else if (is_mapped (sd, &current_cpu->highest_mmapped_page,
1720 addr, newlen))
1721 addr = 0;
f6bcefef
HPN
1722
1723 newaddr
fc887f09
HPN
1724 = create_map (sd, &current_cpu->highest_mmapped_page,
1725 addr != 0 || (flags & TARGET_MAP_FIXED)
1726 ? addr : -1,
f6bcefef
HPN
1727 newlen);
1728
1729 if (newaddr >= (USI) -8191)
1730 {
1731 abort ();
1732 retval = -cb_host_to_target_errno (cb, -(SI) newaddr);
1733 break;
1734 }
1735
c06ccdf1
HPN
1736 /* We were asked for MAP_FIXED, but couldn't. */
1737 if ((flags & TARGET_MAP_FIXED) && newaddr != addr)
1738 {
1739 abort ();
1740 unmap_pages (sd, &current_cpu->highest_mmapped_page,
1741 newaddr, newlen);
1742 retval = -cb_host_to_target_errno (cb, EINVAL);
1743 break;
1744 }
1745
f6bcefef
HPN
1746 /* Find the current position in the file. */
1747 s.func = TARGET_SYS_lseek;
1748 s.arg1 = fd;
1749 s.arg2 = 0;
1750 s.arg3 = SEEK_CUR;
1751 if (cb_syscall (cb, &s) != CB_RC_OK)
1752 abort ();
1753 pos = s.result;
1754
c06ccdf1
HPN
1755 if (s.result < 0)
1756 abort ();
1757
1758 /* Move to the correct offset in the file. */
1759 s.func = TARGET_SYS_lseek;
1760 s.arg1 = fd;
1761 s.arg2 = pgoff*8192;
1762 s.arg3 = SEEK_SET;
1763 if (cb_syscall (cb, &s) != CB_RC_OK)
1764 abort ();
1765
f6bcefef
HPN
1766 if (s.result < 0)
1767 abort ();
1768
1769 /* Use the standard read callback to read in "len"
1770 bytes. */
1771 s.func = TARGET_SYS_read;
1772 s.arg1 = fd;
1773 s.arg2 = newaddr;
1774 s.arg3 = len;
1775 if (cb_syscall (cb, &s) != CB_RC_OK)
1776 abort ();
1777
fc887f09
HPN
1778 /* If the result is a page or more lesser than what
1779 was requested, something went wrong. */
1780 if (len >= 8192 && (USI) s.result <= len - 8192)
f6bcefef
HPN
1781 abort ();
1782
1783 /* After reading, we need to go back to the previous
1784 position in the file. */
1785 s.func = TARGET_SYS_lseek;
1786 s.arg1 = fd;
1787 s.arg2 = pos;
1788 s.arg3 = SEEK_SET;
1789 if (cb_syscall (cb, &s) != CB_RC_OK)
1790 abort ();
1791 if (pos != (USI) s.result)
1792 abort ();
1793
1794 retval = newaddr;
1795 }
1796 else
1797 {
c06ccdf1
HPN
1798 USI newlen = (len + 8191) & ~8191;
1799 USI newaddr;
1800
fc887f09
HPN
1801 if (flags & TARGET_MAP_FIXED)
1802 unmap_pages (sd, &current_cpu->highest_mmapped_page,
1803 addr, newlen);
1804 else if (is_mapped (sd, &current_cpu->highest_mmapped_page,
1805 addr, newlen))
1806 addr = 0;
c06ccdf1 1807
fc887f09
HPN
1808 newaddr = create_map (sd, &current_cpu->highest_mmapped_page,
1809 addr != 0 || (flags & TARGET_MAP_FIXED)
1810 ? addr : -1,
1811 newlen);
f6bcefef
HPN
1812
1813 if (newaddr >= (USI) -8191)
1814 retval = -cb_host_to_target_errno (cb, -(SI) newaddr);
1815 else
1816 retval = newaddr;
c06ccdf1
HPN
1817
1818 if ((flags & TARGET_MAP_FIXED) && newaddr != addr)
1819 {
1820 abort ();
1821 unmap_pages (sd, &current_cpu->highest_mmapped_page,
1822 newaddr, newlen);
1823 retval = -cb_host_to_target_errno (cb, EINVAL);
1824 break;
1825 }
f6bcefef
HPN
1826 }
1827 break;
1828 }
1829
1830 case TARGET_SYS_mprotect:
1831 {
c06ccdf1
HPN
1832 /* We only cover the case of linuxthreads mprotecting out
1833 its stack guard page and of dynamic loading mprotecting
1834 away the data (for some reason the whole library, then
1835 mprotects away the data part and mmap-FIX:es it again. */
f6bcefef
HPN
1836 USI addr = arg1;
1837 USI len = arg2;
1838 USI prot = arg3;
1839
c06ccdf1
HPN
1840 if (prot != TARGET_PROT_NONE
1841 || !is_mapped_only (sd, &current_cpu->highest_mmapped_page,
1842 addr, (len + 8191) & ~8191))
f6bcefef 1843 {
466b1d33
HPN
1844 retval
1845 = cris_unknown_syscall (current_cpu, pc,
1846 "Unimplemented mprotect call "
1847 "(0x%lx, 0x%lx, 0x%lx)\n",
1848 (unsigned long) arg1,
1849 (unsigned long) arg2,
1850 (unsigned long) arg3);
f6bcefef
HPN
1851 break;
1852 }
1853
c06ccdf1
HPN
1854 /* Just ignore this. We could make this equal to munmap,
1855 but then we'd have to make sure no anon mmaps gets this
1856 address before a subsequent MAP_FIXED mmap intended to
1857 override it. */
f6bcefef
HPN
1858 retval = 0;
1859 break;
1860 }
1861
1862 case TARGET_SYS_ioctl:
1863 {
1864 /* We support only a very limited functionality: checking
1865 stdout with TCGETS to perform the isatty function. The
1866 TCGETS ioctl isn't actually performed or the result used by
1867 an isatty () caller in a "hello, world" program; only the
1868 return value is then used. Maybe we shouldn't care about
1869 the environment of the simulator regarding isatty, but
1870 that's been working before, in the xsim simulator. */
1871 if (arg2 == TARGET_TCGETS && arg1 == 1)
1872 retval = isatty (1) ? 0 : cb_host_to_target_errno (cb, EINVAL);
1873 else
1874 retval = -cb_host_to_target_errno (cb, EINVAL);
1875 break;
1876 }
1877
1878 case TARGET_SYS_munmap:
1879 {
1880 USI addr = arg1;
1881 USI len = arg2;
1882 USI result
1883 = unmap_pages (sd, &current_cpu->highest_mmapped_page, addr,
1884 len);
1885 retval = result != 0 ? -cb_host_to_target_errno (cb, result) : 0;
1886 break;
1887 }
1888
1889 case TARGET_SYS_wait4:
1890 {
1891 int i;
1892 USI pid = arg1;
1893 USI saddr = arg2;
1894 USI options = arg3;
1895 USI rusagep = arg4;
1896
1897 /* FIXME: We're not properly implementing __WCLONE, and we
1898 don't really need the special casing so we might as well
1899 make this general. */
1900 if ((!(pid == (USI) -1
1901 && options == (TARGET___WCLONE | TARGET_WNOHANG)
1902 && saddr != 0)
1903 && !(pid > 0
1904 && (options == TARGET___WCLONE
1905 || options == TARGET___WALL)))
1906 || rusagep != 0
1907 || current_cpu->thread_data == NULL)
1908 {
466b1d33
HPN
1909 retval
1910 = cris_unknown_syscall (current_cpu, pc,
1911 "Unimplemented wait4 call "
1912 "(0x%lx, 0x%lx, 0x%lx, 0x%lx)\n",
1913 (unsigned long) arg1,
1914 (unsigned long) arg2,
1915 (unsigned long) arg3,
1916 (unsigned long) arg4);
f6bcefef
HPN
1917 break;
1918 }
1919
1920 if (pid == (USI) -1)
1921 for (i = 1; i < SIM_TARGET_MAX_THREADS; i++)
1922 {
1923 if (current_cpu->thread_data[threadno].threadid
1924 == current_cpu->thread_data[i].parent_threadid
1925 && current_cpu->thread_data[i].threadid != 0
1926 && current_cpu->thread_data[i].cpu_context == NULL)
1927 {
1928 /* A zombied child. Get the exit value and clear the
1929 zombied entry so it will be reused. */
1930 sim_core_write_unaligned_4 (current_cpu, pc, 0, saddr,
1931 current_cpu
1932 ->thread_data[i].exitval);
1933 retval
1934 = current_cpu->thread_data[i].threadid + TARGET_PID;
1935 memset (&current_cpu->thread_data[i], 0,
1936 sizeof (current_cpu->thread_data[i]));
1937 goto outer_break;
1938 }
1939 }
1940 else
1941 {
1942 /* We're waiting for a specific PID. If we don't find
1943 it zombied on this run, rerun the syscall. */
1944 for (i = 1; i < SIM_TARGET_MAX_THREADS; i++)
1945 if (pid == current_cpu->thread_data[i].threadid + TARGET_PID
1946 && current_cpu->thread_data[i].cpu_context == NULL)
1947 {
1948 if (saddr != 0)
1949 /* Get the exit value if the caller wants it. */
1950 sim_core_write_unaligned_4 (current_cpu, pc, 0,
1951 saddr,
1952 current_cpu
1953 ->thread_data[i]
1954 .exitval);
1955
1956 retval
1957 = current_cpu->thread_data[i].threadid + TARGET_PID;
1958 memset (&current_cpu->thread_data[i], 0,
1959 sizeof (current_cpu->thread_data[i]));
1960
1961 goto outer_break;
1962 }
1963
1964 sim_pc_set (current_cpu, pc);
1965 }
1966
1967 retval = -cb_host_to_target_errno (cb, ECHILD);
1968 outer_break:
1969 break;
1970 }
1971
1972 case TARGET_SYS_rt_sigaction:
1973 {
1974 USI signum = arg1;
1975 USI old_sa = arg3;
1976 USI new_sa = arg2;
1977
1978 /* The kernel says:
1979 struct sigaction {
1980 __sighandler_t sa_handler;
1981 unsigned long sa_flags;
1982 void (*sa_restorer)(void);
1983 sigset_t sa_mask;
1984 }; */
1985
1986 if (old_sa != 0)
1987 {
1988 sim_core_write_unaligned_4 (current_cpu, pc, 0, old_sa + 0,
1989 current_cpu->sighandler[signum]);
1990 sim_core_write_unaligned_4 (current_cpu, pc, 0, arg3 + 4, 0);
1991 sim_core_write_unaligned_4 (current_cpu, pc, 0, arg3 + 8, 0);
1992
1993 /* We'll assume _NSIG_WORDS is 2 for the kernel. */
1994 sim_core_write_unaligned_4 (current_cpu, pc, 0, arg3 + 12, 0);
1995 sim_core_write_unaligned_4 (current_cpu, pc, 0, arg3 + 16, 0);
1996 }
1997 if (new_sa != 0)
1998 {
2ecb8390 1999 USI target_sa_handler
f6bcefef 2000 = sim_core_read_unaligned_4 (current_cpu, pc, 0, new_sa);
2ecb8390 2001 USI target_sa_flags
f6bcefef 2002 = sim_core_read_unaligned_4 (current_cpu, pc, 0, new_sa + 4);
2ecb8390 2003 USI target_sa_restorer
f6bcefef 2004 = sim_core_read_unaligned_4 (current_cpu, pc, 0, new_sa + 8);
2ecb8390 2005 USI target_sa_mask_low
f6bcefef 2006 = sim_core_read_unaligned_4 (current_cpu, pc, 0, new_sa + 12);
2ecb8390 2007 USI target_sa_mask_high
f6bcefef
HPN
2008 = sim_core_read_unaligned_4 (current_cpu, pc, 0, new_sa + 16);
2009
2010 /* We won't interrupt a syscall so we won't restart it,
2011 but a signal(2) call ends up syscalling rt_sigaction
2012 with this flag, so we have to handle it. The
2013 sa_restorer field contains garbage when not
2014 TARGET_SA_RESTORER, so don't look at it. For the
2015 time being, we don't nest sighandlers, so we
2016 ignore the sa_mask, which simplifies things. */
2ecb8390
HPN
2017 if ((target_sa_flags != 0
2018 && target_sa_flags != TARGET_SA_RESTART
2019 && target_sa_flags != (TARGET_SA_RESTART|TARGET_SA_SIGINFO))
2020 || target_sa_handler == 0)
f6bcefef 2021 {
466b1d33
HPN
2022 retval
2023 = cris_unknown_syscall (current_cpu, pc,
2024 "Unimplemented rt_sigaction "
2025 "syscall "
2026 "(0x%lx, 0x%lx: "
2027 "[0x%x, 0x%x, 0x%x, "
2028 "{0x%x, 0x%x}], 0x%lx)\n",
2029 (unsigned long) arg1,
2030 (unsigned long) arg2,
2031 target_sa_handler,
2032 target_sa_flags,
2033 target_sa_restorer,
2034 target_sa_mask_low,
2035 target_sa_mask_high,
2036 (unsigned long) arg3);
2037 break;
f6bcefef
HPN
2038 }
2039
2ecb8390 2040 current_cpu->sighandler[signum] = target_sa_handler;
f6bcefef
HPN
2041
2042 /* Because we may have unblocked signals, one may now be
2043 pending, if there are threads, that is. */
2044 if (current_cpu->thread_data)
2045 current_cpu->thread_data[threadno].sigpending = 1;
2046 }
2047 retval = 0;
2048 break;
2049 }
2050
2051 case TARGET_SYS_mremap:
2052 {
2053 USI addr = arg1;
2054 USI old_len = arg2;
2055 USI new_len = arg3;
2056 USI flags = arg4;
2057 USI new_addr = arg5;
2058 USI mapped_addr;
2059
2060 if (new_len == old_len)
2061 /* The program and/or library is possibly confused but
2062 this is a valid call. Happens with ipps-1.40 on file
2063 svs_all. */
2064 retval = addr;
2065 else if (new_len < old_len)
2066 {
2067 /* Shrinking is easy. */
2068 if (unmap_pages (sd, &current_cpu->highest_mmapped_page,
2069 addr + new_len, old_len - new_len) != 0)
2070 retval = -cb_host_to_target_errno (cb, EINVAL);
2071 else
2072 retval = addr;
2073 }
2074 else if (! is_mapped (sd, &current_cpu->highest_mmapped_page,
2075 addr + old_len, new_len - old_len))
2076 {
2077 /* If the extension isn't mapped, we can just add it. */
2078 mapped_addr
2079 = create_map (sd, &current_cpu->highest_mmapped_page,
2080 addr + old_len, new_len - old_len);
2081
2082 if (mapped_addr > (USI) -8192)
2083 retval = -cb_host_to_target_errno (cb, -(SI) mapped_addr);
2084 else
2085 retval = addr;
2086 }
2087 else if (flags & TARGET_MREMAP_MAYMOVE)
2088 {
2089 /* Create a whole new map and copy the contents
2090 block-by-block there. We ignore the new_addr argument
2091 for now. */
2092 char buf[8192];
2093 USI prev_addr = addr;
2094 USI prev_len = old_len;
2095
2096 mapped_addr
2097 = create_map (sd, &current_cpu->highest_mmapped_page,
fc887f09 2098 -1, new_len);
f6bcefef
HPN
2099
2100 if (mapped_addr > (USI) -8192)
2101 {
2102 retval = -cb_host_to_target_errno (cb, -(SI) new_addr);
2103 break;
2104 }
2105
2106 retval = mapped_addr;
2107
2108 for (; old_len > 0;
2109 old_len -= 8192, mapped_addr += 8192, addr += 8192)
2110 {
2111 if (sim_core_read_buffer (sd, current_cpu, read_map, buf,
2112 addr, 8192) != 8192
2113 || sim_core_write_buffer (sd, current_cpu, 0, buf,
2114 mapped_addr, 8192) != 8192)
2115 abort ();
2116 }
2117
2118 if (unmap_pages (sd, &current_cpu->highest_mmapped_page,
2119 prev_addr, prev_len) != 0)
2120 abort ();
2121 }
2122 else
2123 retval = -cb_host_to_target_errno (cb, -ENOMEM);
2124 break;
2125 }
2126
2127 case TARGET_SYS_poll:
2128 {
2129 int npollfds = arg2;
2130 int timeout = arg3;
2131 SI ufds = arg1;
2132 SI fd = -1;
2133 HI events = -1;
2134 HI revents = 0;
2135 struct stat buf;
2136 int i;
2137
2138 /* The kernel says:
2139 struct pollfd {
2140 int fd;
2141 short events;
2142 short revents;
2143 }; */
2144
2145 /* Check that this is the expected poll call from
2146 linuxthreads/manager.c; we don't support anything else.
2147 Remember, fd == 0 isn't supported. */
2148 if (npollfds != 1
2149 || ((fd = sim_core_read_unaligned_4 (current_cpu, pc,
2150 0, ufds)) <= 0)
2151 || ((events = sim_core_read_unaligned_2 (current_cpu, pc,
2152 0, ufds + 4))
2153 != TARGET_POLLIN)
2d7bb758 2154 || ((cb->to_fstat) (cb, fd, &buf) != 0
f6bcefef
HPN
2155 || (buf.st_mode & S_IFIFO) == 0)
2156 || current_cpu->thread_data == NULL)
2157 {
466b1d33
HPN
2158 retval
2159 = cris_unknown_syscall (current_cpu, pc,
2160 "Unimplemented poll syscall "
2161 "(0x%lx: [0x%x, 0x%x, x], "
2162 "0x%lx, 0x%lx)\n",
2163 (unsigned long) arg1, fd, events,
2164 (unsigned long) arg2,
2165 (unsigned long) arg3);
f6bcefef
HPN
2166 break;
2167 }
2168
2169 retval = 0;
2170
2171 /* Iterate over threads; find a marker that a writer is
2172 sleeping, waiting for a reader. */
2173 for (i = 0; i < SIM_TARGET_MAX_THREADS; i++)
2174 if (current_cpu->thread_data[i].cpu_context != NULL
2175 && current_cpu->thread_data[i].pipe_read_fd == fd)
2176 {
2177 revents = TARGET_POLLIN;
2178 retval = 1;
2179 break;
2180 }
2181
2182 /* Timeout decreases with whatever time passed between the
2183 last syscall and this. That's not exactly right for the
2184 first call, but it's close enough that it isn't
2185 worthwhile to complicate matters by making that a special
2186 case. */
2187 timeout
2188 -= (TARGET_TIME_MS (current_cpu)
2189 - (current_cpu->thread_data[threadno].last_execution));
2190
2191 /* Arrange to repeat this syscall until timeout or event,
2192 decreasing timeout at each iteration. */
2193 if (timeout > 0 && revents == 0)
2194 {
2195 bfd_byte timeout_buf[4];
2196
2197 bfd_putl32 (timeout, timeout_buf);
2198 (*CPU_REG_STORE (current_cpu)) (current_cpu,
2199 H_GR_R12, timeout_buf, 4);
2200 sim_pc_set (current_cpu, pc);
2201 retval = arg1;
2202 break;
2203 }
2204
2205 sim_core_write_unaligned_2 (current_cpu, pc, 0, ufds + 4 + 2,
2206 revents);
2207 break;
2208 }
2209
d022998d
HPN
2210 case TARGET_SYS_time:
2211 {
00330cd1 2212 retval = (int) (*cb->time) (cb);
d022998d
HPN
2213
2214 /* At time of this writing, CB_SYSCALL_time doesn't do the
2215 part of setting *arg1 to the return value. */
2216 if (arg1)
2217 sim_core_write_unaligned_4 (current_cpu, pc, 0, arg1, retval);
2218 break;
2219 }
2220
f6bcefef
HPN
2221 case TARGET_SYS_gettimeofday:
2222 if (arg1 != 0)
2223 {
2224 USI ts = TARGET_TIME (current_cpu);
2225 USI tms = TARGET_TIME_MS (current_cpu);
2226
2227 /* First dword is seconds since TARGET_EPOCH. */
2228 sim_core_write_unaligned_4 (current_cpu, pc, 0, arg1, ts);
2229
2230 /* Second dword is microseconds. */
2231 sim_core_write_unaligned_4 (current_cpu, pc, 0, arg1 + 4,
2232 (tms % 1000) * 1000);
2233 }
2234 if (arg2 != 0)
2235 {
2236 /* Time-zone info is always cleared. */
2237 sim_core_write_unaligned_4 (current_cpu, pc, 0, arg2, 0);
2238 sim_core_write_unaligned_4 (current_cpu, pc, 0, arg2 + 4, 0);
2239 }
2240 retval = 0;
2241 break;
2242
2243 case TARGET_SYS_llseek:
2244 {
2245 /* If it fits, tweak parameters to fit the "generic" 32-bit
2246 lseek and use that. */
2247 SI fd = arg1;
2248 SI offs_hi = arg2;
2249 SI offs_lo = arg3;
2250 SI resultp = arg4;
2251 SI whence = arg5;
2252 retval = 0;
2253
2254 if (!((offs_hi == 0 && offs_lo >= 0)
2255 || (offs_hi == -1 && offs_lo < 0)))
2256 {
466b1d33
HPN
2257 retval
2258 = cris_unknown_syscall (current_cpu, pc,
2259 "Unimplemented llseek offset,"
2260 " fd %d: 0x%x:0x%x\n",
2261 fd, (unsigned) arg2,
2262 (unsigned) arg3);
2263 break;
f6bcefef
HPN
2264 }
2265
2266 s.func = TARGET_SYS_lseek;
2267 s.arg2 = offs_lo;
2268 s.arg3 = whence;
2269 if (cb_syscall (cb, &s) != CB_RC_OK)
2270 {
2271 sim_io_eprintf (sd, "Break 13: invalid %d? Returned %ld\n", callnum,
2272 s.result);
2273 sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped, SIM_SIGILL);
2274 }
2275 if (s.result < 0)
2276 retval = -s.errcode;
2277 else
2278 {
2279 sim_core_write_unaligned_4 (current_cpu, pc, 0, resultp,
2280 s.result);
2281 sim_core_write_unaligned_4 (current_cpu, pc, 0, resultp + 4,
2282 s.result < 0 ? -1 : 0);
2283 }
2284 break;
2285 }
2286
c06ccdf1
HPN
2287 /* ssize_t writev(int fd, const struct iovec *iov, int iovcnt);
2288 where:
2289 struct iovec {
2290 void *iov_base; Starting address
2291 size_t iov_len; Number of bytes to transfer
2292 }; */
2293 case TARGET_SYS_writev:
2294 {
2295 SI fd = arg1;
2296 SI iov = arg2;
2297 SI iovcnt = arg3;
2298 SI retcnt = 0;
2299 int i;
2300
2301 /* We'll ignore strict error-handling and just do multiple write calls. */
2302 for (i = 0; i < iovcnt; i++)
2303 {
2304 int sysret;
2305 USI iov_base
2306 = sim_core_read_unaligned_4 (current_cpu, pc, 0,
2307 iov + 8*i);
2308 USI iov_len
2309 = sim_core_read_unaligned_4 (current_cpu, pc, 0,
2310 iov + 8*i + 4);
2311
2312 s.func = TARGET_SYS_write;
2313 s.arg1 = fd;
2314 s.arg2 = iov_base;
2315 s.arg3 = iov_len;
2316
2317 if (cb_syscall (cb, &s) != CB_RC_OK)
2318 abort ();
2319 sysret = s.result == -1 ? -s.errcode : s.result;
2320
2321 if (sysret != iov_len)
2322 {
2323 if (i != 0)
2324 abort ();
2325 retcnt = sysret;
2326 break;
2327 }
2328
2329 retcnt += iov_len;
2330 }
2331
2332 retval = retcnt;
2333 }
2334 break;
2335
f6bcefef
HPN
2336 /* This one does have a generic callback function, but at the time
2337 of this writing, cb_syscall does not have code for it, and we
2338 need target-specific code for the threads implementation
2339 anyway. */
2340 case TARGET_SYS_kill:
2341 {
2342 USI pid = arg1;
2343 USI sig = arg2;
2344
2345 retval = 0;
2346
2347 /* At kill(2), glibc sets signal masks such that the thread
2348 machinery is initialized. Still, there is and was only
2349 one thread. */
2350 if (current_cpu->max_threadid == 0)
2351 {
2352 if (pid != TARGET_PID)
2353 {
2354 retval = -cb_host_to_target_errno (cb, EPERM);
2355 break;
2356 }
2357
2358 /* FIXME: Signal infrastructure (target-to-sim mapping). */
2359 if (sig == TARGET_SIGABRT)
2360 /* A call "abort ()", i.e. "kill (getpid(), SIGABRT)" is
2361 the end-point for failing GCC test-cases. */
2362 sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
2363 SIM_SIGABRT);
2364 else
2365 {
2366 sim_io_eprintf (sd, "Unimplemented signal: %d\n", sig);
2367 sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
2368 SIM_SIGILL);
2369 }
2370
2371 /* This will not be reached. */
2372 abort ();
2373 }
2374 else
2375 retval = deliver_signal (current_cpu, sig, pid);
2376 break;
2377 }
2378
2379 case TARGET_SYS_rt_sigprocmask:
2380 {
2381 int i;
2382 USI how = arg1;
2383 USI newsetp = arg2;
2384 USI oldsetp = arg3;
2385
2386 if (how != TARGET_SIG_BLOCK
2387 && how != TARGET_SIG_SETMASK
2388 && how != TARGET_SIG_UNBLOCK)
2389 {
466b1d33
HPN
2390 retval
2391 = cris_unknown_syscall (current_cpu, pc,
2392 "Unimplemented rt_sigprocmask "
2393 "syscall (0x%x, 0x%x, 0x%x)\n",
2394 arg1, arg2, arg3);
f6bcefef
HPN
2395 break;
2396 }
2397
2398 if (newsetp)
2399 {
2400 USI set_low
2401 = sim_core_read_unaligned_4 (current_cpu, pc, 0,
2402 newsetp);
2403 USI set_high
2404 = sim_core_read_unaligned_4 (current_cpu, pc, 0,
2405 newsetp + 4);
2406
2407 /* The sigmask is kept in the per-thread data, so we may
2408 need to create the first one. */
2409 if (current_cpu->thread_data == NULL)
2410 make_first_thread (current_cpu);
2411
2412 if (how == TARGET_SIG_SETMASK)
2413 for (i = 0; i < 64; i++)
2414 current_cpu->thread_data[threadno].sigdata[i].blocked = 0;
2415
2416 for (i = 0; i < 32; i++)
2417 if ((set_low & (1 << i)))
2418 current_cpu->thread_data[threadno].sigdata[i + 1].blocked
2419 = (how != TARGET_SIG_UNBLOCK);
2420
2421 for (i = 0; i < 31; i++)
2422 if ((set_high & (1 << i)))
2423 current_cpu->thread_data[threadno].sigdata[i + 33].blocked
2424 = (how != TARGET_SIG_UNBLOCK);
2425
2426 /* The mask changed, so a signal may be unblocked for
2427 execution. */
2428 current_cpu->thread_data[threadno].sigpending = 1;
2429 }
2430
2431 if (oldsetp != 0)
2432 {
2433 USI set_low = 0;
2434 USI set_high = 0;
2435
2436 for (i = 0; i < 32; i++)
2437 if (current_cpu->thread_data[threadno]
2438 .sigdata[i + 1].blocked)
2439 set_low |= 1 << i;
2440 for (i = 0; i < 31; i++)
2441 if (current_cpu->thread_data[threadno]
2442 .sigdata[i + 33].blocked)
2443 set_high |= 1 << i;
2444
2445 sim_core_write_unaligned_4 (current_cpu, pc, 0, oldsetp + 0, set_low);
2446 sim_core_write_unaligned_4 (current_cpu, pc, 0, oldsetp + 4, set_high);
2447 }
2448
2449 retval = 0;
2450 break;
2451 }
2452
2453 case TARGET_SYS_sigreturn:
2454 {
2455 int i;
2456 bfd_byte regbuf[4];
2457 int was_sigsuspended;
2458
2459 if (current_cpu->thread_data == NULL
2460 /* The CPU context is saved with the simulator data, not
2461 on the stack as in the real world. */
2462 || (current_cpu->thread_data[threadno].cpu_context_atsignal
2463 == NULL))
2464 {
466b1d33
HPN
2465 retval
2466 = cris_unknown_syscall (current_cpu, pc,
2467 "Invalid sigreturn syscall: "
2468 "no signal handler active "
2469 "(0x%lx, 0x%lx, 0x%lx, 0x%lx, "
2470 "0x%lx, 0x%lx)\n",
2471 (unsigned long) arg1,
2472 (unsigned long) arg2,
2473 (unsigned long) arg3,
2474 (unsigned long) arg4,
2475 (unsigned long) arg5,
2476 (unsigned long) arg6);
2477 break;
f6bcefef
HPN
2478 }
2479
2480 was_sigsuspended
2481 = current_cpu->thread_data[threadno].sigsuspended;
2482
2483 /* Restore the sigmask, either from the stack copy made when
2484 the sighandler was called, or from the saved state
2485 specifically for sigsuspend(2). */
2486 if (was_sigsuspended)
2487 {
2488 current_cpu->thread_data[threadno].sigsuspended = 0;
2489 for (i = 0; i < 64; i++)
2490 current_cpu->thread_data[threadno].sigdata[i].blocked
2491 = current_cpu->thread_data[threadno]
2492 .sigdata[i].blocked_suspendsave;
2493 }
2494 else
2495 {
2496 USI sp;
2497 USI set_low;
2498 USI set_high;
2499
2500 (*CPU_REG_FETCH (current_cpu)) (current_cpu,
2501 H_GR_SP, regbuf, 4);
2502 sp = bfd_getl32 (regbuf);
2503 set_low
2504 = sim_core_read_unaligned_4 (current_cpu, pc, 0, sp);
2505 set_high
2506 = sim_core_read_unaligned_4 (current_cpu, pc, 0, sp + 4);
2507
2508 for (i = 0; i < 32; i++)
2509 current_cpu->thread_data[threadno].sigdata[i + 1].blocked
2510 = (set_low & (1 << i)) != 0;
2511 for (i = 0; i < 31; i++)
2512 current_cpu->thread_data[threadno].sigdata[i + 33].blocked
2513 = (set_high & (1 << i)) != 0;
2514 }
2515
2516 /* The mask changed, so a signal may be unblocked for
2517 execution. */
2518 current_cpu->thread_data[threadno].sigpending = 1;
2519
2520 memcpy (&current_cpu->cpu_data_placeholder,
2521 current_cpu->thread_data[threadno].cpu_context_atsignal,
2522 current_cpu->thread_cpu_data_size);
2523 free (current_cpu->thread_data[threadno].cpu_context_atsignal);
2524 current_cpu->thread_data[threadno].cpu_context_atsignal = NULL;
2525
2526 /* The return value must come from the saved R10. */
2527 (*CPU_REG_FETCH (current_cpu)) (current_cpu, H_GR_R10, regbuf, 4);
2528 retval = bfd_getl32 (regbuf);
2529
2530 /* We must also break the "sigsuspension loop". */
2531 if (was_sigsuspended)
2532 sim_pc_set (current_cpu, sim_pc_get (current_cpu) + 2);
2533 break;
2534 }
2535
2536 case TARGET_SYS_rt_sigsuspend:
2537 {
2538 USI newsetp = arg1;
2539 USI setsize = arg2;
2540
2541 if (setsize != 8)
2542 {
466b1d33
HPN
2543 retval
2544 = cris_unknown_syscall (current_cpu, pc,
2545 "Unimplemented rt_sigsuspend syscall"
2546 " arguments (0x%lx, 0x%lx)\n",
2547 (unsigned long) arg1,
2548 (unsigned long) arg2);
2549 break;
f6bcefef
HPN
2550 }
2551
2552 /* Don't change the signal mask if we're already in
2553 sigsuspend state (i.e. this syscall is a rerun). */
2554 else if (!current_cpu->thread_data[threadno].sigsuspended)
2555 {
2556 USI set_low
2557 = sim_core_read_unaligned_4 (current_cpu, pc, 0,
2558 newsetp);
2559 USI set_high
2560 = sim_core_read_unaligned_4 (current_cpu, pc, 0,
2561 newsetp + 4);
2562 int i;
2563
2564 /* Save the current sigmask and insert the user-supplied
2565 one. */
2566 for (i = 0; i < 32; i++)
2567 {
2568 current_cpu->thread_data[threadno]
2569 .sigdata[i + 1].blocked_suspendsave
2570 = current_cpu->thread_data[threadno]
2571 .sigdata[i + 1].blocked;
2572
2573 current_cpu->thread_data[threadno]
2574 .sigdata[i + 1].blocked = (set_low & (1 << i)) != 0;
2575 }
2576 for (i = 0; i < 31; i++)
2577 {
2578 current_cpu->thread_data[threadno]
2579 .sigdata[i + 33].blocked_suspendsave
2580 = current_cpu->thread_data[threadno]
2581 .sigdata[i + 33].blocked;
2582 current_cpu->thread_data[threadno]
2583 .sigdata[i + 33].blocked = (set_high & (1 << i)) != 0;
2584 }
2585
2586 current_cpu->thread_data[threadno].sigsuspended = 1;
2587
2588 /* The mask changed, so a signal may be unblocked for
2589 execution. */
2590 current_cpu->thread_data[threadno].sigpending = 1;
2591 }
2592
2593 /* Because we don't use arg1 (newsetp) when this syscall is
2594 rerun, it doesn't matter that we overwrite it with the
2595 (constant) return value. */
2596 retval = -cb_host_to_target_errno (cb, EINTR);
2597 sim_pc_set (current_cpu, pc);
2598 break;
2599 }
2600
2601 /* Add case labels here for other syscalls using the 32-bit
2602 "struct stat", provided they have a corresponding simulator
2603 function of course. */
5457266c 2604 case TARGET_SYS_stat:
f6bcefef
HPN
2605 case TARGET_SYS_fstat:
2606 {
2607 /* As long as the infrastructure doesn't cache anything
2608 related to the stat mapping, this trick gets us a dual
2609 "struct stat"-type mapping in the least error-prone way. */
2610 const char *saved_map = cb->stat_map;
2611 CB_TARGET_DEFS_MAP *saved_syscall_map = cb->syscall_map;
2612
2613 cb->syscall_map = (CB_TARGET_DEFS_MAP *) syscall_stat32_map;
2614 cb->stat_map = stat32_map;
2615
2616 if (cb_syscall (cb, &s) != CB_RC_OK)
2617 {
2618 abort ();
2619 sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
2620 SIM_SIGILL);
2621 }
2622 retval = s.result == -1 ? -s.errcode : s.result;
2623
2624 cb->stat_map = saved_map;
2625 cb->syscall_map = saved_syscall_map;
2626 break;
2627 }
2628
2629 case TARGET_SYS_getcwd:
2630 {
2631 USI buf = arg1;
2632 USI size = arg2;
2633
3ca4d560
HPN
2634 char *cwd = xmalloc (SIM_PATHMAX);
2635 if (cwd != getcwd (cwd, SIM_PATHMAX))
f6bcefef
HPN
2636 abort ();
2637
2638 /* FIXME: When and if we support chdir, we need something
2639 a bit more elaborate. */
2640 if (simulator_sysroot[0] != '\0')
2641 strcpy (cwd, "/");
2642
2643 retval = -cb_host_to_target_errno (cb, ERANGE);
2644 if (strlen (cwd) + 1 <= size)
2645 {
2646 retval = strlen (cwd) + 1;
2647 if (sim_core_write_buffer (sd, current_cpu, 0, cwd,
2648 buf, retval)
2649 != (unsigned int) retval)
2650 retval = -cb_host_to_target_errno (cb, EFAULT);
2651 }
2652 free (cwd);
2653 break;
2654 }
2655
e7fcaaa4
HPN
2656 case TARGET_SYS_access:
2657 {
2658 SI path = arg1;
2659 SI mode = arg2;
2660 char *pbuf = xmalloc (SIM_PATHMAX);
2661 int i;
2662 int o = 0;
2663 int hmode = 0;
2664
2665 if (sim_core_read_unaligned_1 (current_cpu, pc, 0, path) == '/')
2666 {
2667 strcpy (pbuf, simulator_sysroot);
2668 o += strlen (simulator_sysroot);
2669 }
2670
2671 for (i = 0; i + o < SIM_PATHMAX; i++)
2672 {
2673 pbuf[i + o]
2674 = sim_core_read_unaligned_1 (current_cpu, pc, 0, path + i);
2675 if (pbuf[i + o] == 0)
2676 break;
2677 }
2678
2679 if (i + o == SIM_PATHMAX)
2680 {
2681 retval = -cb_host_to_target_errno (cb, ENAMETOOLONG);
2682 break;
2683 }
2684
2685 /* Assert that we don't get calls for files for which we
2686 don't have support. */
2687 if (strncmp (pbuf + strlen (simulator_sysroot),
2688 "/proc/", 6) == 0)
2689 abort ();
2690#define X_AFLAG(x) if (mode & TARGET_ ## x) hmode |= x
2691 X_AFLAG (R_OK);
2692 X_AFLAG (W_OK);
2693 X_AFLAG (X_OK);
2694 X_AFLAG (F_OK);
2695#undef X_AFLAG
2696
2697 if (access (pbuf, hmode) != 0)
2698 retval = -cb_host_to_target_errno (cb, errno);
2699 else
2700 retval = 0;
2701
2702 free (pbuf);
2703 break;
2704 }
2705
f6bcefef
HPN
2706 case TARGET_SYS_readlink:
2707 {
2708 SI path = arg1;
2709 SI buf = arg2;
2710 SI bufsiz = arg3;
3ca4d560
HPN
2711 char *pbuf = xmalloc (SIM_PATHMAX);
2712 char *lbuf = xmalloc (SIM_PATHMAX);
f6bcefef
HPN
2713 char *lbuf_alloc = lbuf;
2714 int nchars = -1;
2715 int i;
2716 int o = 0;
2717
2718 if (sim_core_read_unaligned_1 (current_cpu, pc, 0, path) == '/')
2719 {
2720 strcpy (pbuf, simulator_sysroot);
2721 o += strlen (simulator_sysroot);
2722 }
2723
3ca4d560 2724 for (i = 0; i + o < SIM_PATHMAX; i++)
f6bcefef
HPN
2725 {
2726 pbuf[i + o]
2727 = sim_core_read_unaligned_1 (current_cpu, pc, 0, path + i);
2728 if (pbuf[i + o] == 0)
2729 break;
2730 }
2731
3ca4d560 2732 if (i + o == SIM_PATHMAX)
f6bcefef
HPN
2733 {
2734 retval = -cb_host_to_target_errno (cb, ENAMETOOLONG);
2735 break;
2736 }
2737
2738 /* Intervene calls for certain files expected in the target
2739 proc file system. */
2740 if (strcmp (pbuf + strlen (simulator_sysroot),
2741 "/proc/" XSTRING (TARGET_PID) "/exe") == 0)
2742 {
2743 char *argv0
2744 = (STATE_PROG_ARGV (sd) != NULL
2745 ? *STATE_PROG_ARGV (sd) : NULL);
2746
2747 if (argv0 == NULL || *argv0 == '.')
2748 {
466b1d33
HPN
2749 retval
2750 = cris_unknown_syscall (current_cpu, pc,
2751 "Unimplemented readlink syscall "
2752 "(0x%lx: [\"%s\"], 0x%lx)\n",
2753 (unsigned long) arg1, pbuf,
2754 (unsigned long) arg2);
f6bcefef
HPN
2755 break;
2756 }
2757 else if (*argv0 == '/')
2758 {
2759 if (strncmp (simulator_sysroot, argv0,
2760 strlen (simulator_sysroot)) == 0)
2761 argv0 += strlen (simulator_sysroot);
2762
2763 strcpy (lbuf, argv0);
2764 nchars = strlen (argv0) + 1;
2765 }
2766 else
2767 {
3ca4d560
HPN
2768 if (getcwd (lbuf, SIM_PATHMAX) != NULL
2769 && strlen (lbuf) + 2 + strlen (argv0) < SIM_PATHMAX)
f6bcefef
HPN
2770 {
2771 if (strncmp (simulator_sysroot, lbuf,
2772 strlen (simulator_sysroot)) == 0)
2773 lbuf += strlen (simulator_sysroot);
2774
2775 strcat (lbuf, "/");
2776 strcat (lbuf, argv0);
2777 nchars = strlen (lbuf) + 1;
2778 }
2779 else
2780 abort ();
2781 }
2782 }
2783 else
3ca4d560 2784 nchars = readlink (pbuf, lbuf, SIM_PATHMAX);
f6bcefef
HPN
2785
2786 /* We trust that the readlink result returns a *relative*
2787 link, or one already adjusted for the file-path-prefix.
2788 (We can't generally tell the difference, so we go with
2789 the easiest decision; no adjustment.) */
2790
2791 if (nchars == -1)
2792 {
2793 retval = -cb_host_to_target_errno (cb, errno);
2794 break;
2795 }
2796
2797 if (bufsiz < nchars)
2798 nchars = bufsiz;
2799
2800 if (sim_core_write_buffer (sd, current_cpu, write_map, lbuf,
2801 buf, nchars) != (unsigned int) nchars)
2802 retval = -cb_host_to_target_errno (cb, EFAULT);
2803 else
2804 retval = nchars;
2805
2806 free (pbuf);
2807 free (lbuf_alloc);
2808 break;
2809 }
2810
2811 case TARGET_SYS_sched_getscheduler:
2812 {
2813 USI pid = arg1;
2814
2815 /* FIXME: Search (other) existing threads. */
2816 if (pid != 0 && pid != TARGET_PID)
2817 retval = -cb_host_to_target_errno (cb, ESRCH);
2818 else
2819 retval = TARGET_SCHED_OTHER;
2820 break;
2821 }
2822
2823 case TARGET_SYS_sched_getparam:
2824 {
2825 USI pid = arg1;
2826 USI paramp = arg2;
2827
2828 /* The kernel says:
2829 struct sched_param {
2830 int sched_priority;
2831 }; */
2832
2833 if (pid != 0 && pid != TARGET_PID)
2834 retval = -cb_host_to_target_errno (cb, ESRCH);
2835 else
2836 {
2837 /* FIXME: Save scheduler setting before threads are
2838 created too. */
2839 sim_core_write_unaligned_4 (current_cpu, pc, 0, paramp,
2840 current_cpu->thread_data != NULL
2841 ? (current_cpu
2842 ->thread_data[threadno]
2843 .priority)
2844 : 0);
2845 retval = 0;
2846 }
2847 break;
2848 }
2849
2850 case TARGET_SYS_sched_setparam:
2851 {
2852 USI pid = arg1;
2853 USI paramp = arg2;
2854
2855 if ((pid != 0 && pid != TARGET_PID)
2856 || sim_core_read_unaligned_4 (current_cpu, pc, 0,
2857 paramp) != 0)
2858 retval = -cb_host_to_target_errno (cb, EINVAL);
2859 else
2860 retval = 0;
2861 break;
2862 }
2863
2864 case TARGET_SYS_sched_setscheduler:
2865 {
2866 USI pid = arg1;
2867 USI policy = arg2;
2868 USI paramp = arg3;
2869
2870 if ((pid != 0 && pid != TARGET_PID)
2871 || policy != TARGET_SCHED_OTHER
2872 || sim_core_read_unaligned_4 (current_cpu, pc, 0,
2873 paramp) != 0)
2874 retval = -cb_host_to_target_errno (cb, EINVAL);
2875 else
2876 /* FIXME: Save scheduler setting to be read in later
2877 sched_getparam calls. */
2878 retval = 0;
2879 break;
2880 }
2881
2882 case TARGET_SYS_sched_yield:
2883 /* We reschedule to the next thread after a syscall anyway, so
2884 we don't have to do anything here than to set the return
2885 value. */
2886 retval = 0;
2887 break;
2888
2889 case TARGET_SYS_sched_get_priority_min:
2890 case TARGET_SYS_sched_get_priority_max:
2891 if (arg1 != 0)
2892 retval = -cb_host_to_target_errno (cb, EINVAL);
2893 else
2894 retval = 0;
2895 break;
2896
2897 case TARGET_SYS_ugetrlimit:
2898 {
2899 unsigned int curlim, maxlim;
2900 if (arg1 != TARGET_RLIMIT_STACK && arg1 != TARGET_RLIMIT_NOFILE)
2901 {
2902 retval = -cb_host_to_target_errno (cb, EINVAL);
2903 break;
2904 }
2905
2906 /* The kernel says:
2907 struct rlimit {
2908 unsigned long rlim_cur;
2909 unsigned long rlim_max;
2910 }; */
2911 if (arg1 == TARGET_RLIMIT_NOFILE)
2912 {
2913 /* Sadly a very low limit. Better not lie, though. */
2914 maxlim = curlim = MAX_CALLBACK_FDS;
2915 }
2916 else /* arg1 == TARGET_RLIMIT_STACK */
2917 {
2918 maxlim = 0xffffffff;
2919 curlim = 0x800000;
2920 }
2921 sim_core_write_unaligned_4 (current_cpu, pc, 0, arg2, curlim);
2922 sim_core_write_unaligned_4 (current_cpu, pc, 0, arg2 + 4, maxlim);
2923 retval = 0;
2924 break;
2925 }
2926
2927 case TARGET_SYS_setrlimit:
2928 if (arg1 != TARGET_RLIMIT_STACK)
2929 {
2930 retval = -cb_host_to_target_errno (cb, EINVAL);
2931 break;
2932 }
2933 /* FIXME: Save values for future ugetrlimit calls. */
2934 retval = 0;
2935 break;
2936
2937 /* Provide a very limited subset of the sysctl functions, and
2938 abort for the rest. */
2939 case TARGET_SYS__sysctl:
2940 {
2941 /* The kernel says:
2942 struct __sysctl_args {
2943 int *name;
2944 int nlen;
2945 void *oldval;
2946 size_t *oldlenp;
2947 void *newval;
2948 size_t newlen;
2949 unsigned long __unused[4];
2950 }; */
2951 SI name = sim_core_read_unaligned_4 (current_cpu, pc, 0, arg1);
2952 SI name0 = name == 0
2953 ? 0 : sim_core_read_unaligned_4 (current_cpu, pc, 0, name);
2954 SI name1 = name == 0
2955 ? 0 : sim_core_read_unaligned_4 (current_cpu, pc, 0, name + 4);
2956 SI nlen
2957 = sim_core_read_unaligned_4 (current_cpu, pc, 0, arg1 + 4);
2958 SI oldval
2959 = sim_core_read_unaligned_4 (current_cpu, pc, 0, arg1 + 8);
2960 SI oldlenp
2961 = sim_core_read_unaligned_4 (current_cpu, pc, 0, arg1 + 12);
2962 SI oldlen = oldlenp == 0
2963 ? 0 : sim_core_read_unaligned_4 (current_cpu, pc, 0, oldlenp);
2964 SI newval
2965 = sim_core_read_unaligned_4 (current_cpu, pc, 0, arg1 + 16);
2966 SI newlen
2967 = sim_core_read_unaligned_4 (current_cpu, pc, 0, arg1 + 20);
2968
2969 if (name0 == TARGET_CTL_KERN && name1 == TARGET_CTL_KERN_VERSION)
2970 {
2971 SI to_write = oldlen < (SI) sizeof (TARGET_UTSNAME)
2972 ? oldlen : (SI) sizeof (TARGET_UTSNAME);
2973
2974 sim_core_write_unaligned_4 (current_cpu, pc, 0, oldlenp,
2975 sizeof (TARGET_UTSNAME));
2976
2977 if (sim_core_write_buffer (sd, current_cpu, write_map,
2978 TARGET_UTSNAME, oldval,
2979 to_write)
2980 != (unsigned int) to_write)
2981 retval = -cb_host_to_target_errno (cb, EFAULT);
2982 else
2983 retval = 0;
2984 break;
2985 }
2986
466b1d33
HPN
2987 retval
2988 = cris_unknown_syscall (current_cpu, pc,
2989 "Unimplemented _sysctl syscall "
2990 "(0x%lx: [0x%lx, 0x%lx],"
2991 " 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx)\n",
2992 (unsigned long) name,
2993 (unsigned long) name0,
2994 (unsigned long) name1,
2995 (unsigned long) nlen,
2996 (unsigned long) oldval,
2997 (unsigned long) oldlenp,
2998 (unsigned long) newval,
2999 (unsigned long) newlen);
f6bcefef
HPN
3000 break;
3001 }
3002
3003 case TARGET_SYS_exit:
3004 {
3005 /* Here for all but the last thread. */
3006 int i;
3007 int pid
3008 = current_cpu->thread_data[threadno].threadid + TARGET_PID;
3009 int ppid
3010 = (current_cpu->thread_data[threadno].parent_threadid
3011 + TARGET_PID);
3012 int exitsig = current_cpu->thread_data[threadno].exitsig;
3013
3014 /* Any children are now all orphans. */
3015 for (i = 0; i < SIM_TARGET_MAX_THREADS; i++)
3016 if (current_cpu->thread_data[i].parent_threadid
3017 == current_cpu->thread_data[threadno].threadid)
3018 /* Make getppid(2) return 1 for them, poor little ones. */
3019 current_cpu->thread_data[i].parent_threadid = -TARGET_PID + 1;
3020
3021 /* Free the cpu context data. When the parent has received
3022 the exit status, we'll clear the entry too. */
3023 free (current_cpu->thread_data[threadno].cpu_context);
3024 current_cpu->thread_data[threadno].cpu_context = NULL;
3025 current_cpu->m1threads--;
3026 if (arg1 != 0)
3027 {
3028 sim_io_eprintf (sd, "Thread %d exited with status %d\n",
3029 pid, arg1);
3030 sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
3031 SIM_SIGILL);
3032 }
3033
3034 /* Still, we may want to support non-zero exit values. */
3035 current_cpu->thread_data[threadno].exitval = arg1 << 8;
3036
3037 if (exitsig)
3038 deliver_signal (current_cpu, exitsig, ppid);
3039 break;
3040 }
3041
3042 case TARGET_SYS_clone:
3043 {
3044 int nthreads = current_cpu->m1threads + 1;
3045 void *thread_cpu_data;
3046 bfd_byte old_sp_buf[4];
3047 bfd_byte sp_buf[4];
3048 const bfd_byte zeros[4] = { 0, 0, 0, 0 };
3049 int i;
3050
3051 /* That's right, the syscall clone arguments are reversed
3052 compared to sys_clone notes in clone(2) and compared to
3053 other Linux ports (i.e. it's the same order as in the
3054 clone(2) libcall). */
3055 USI flags = arg2;
3056 USI newsp = arg1;
3057
3058 if (nthreads == SIM_TARGET_MAX_THREADS)
3059 {
3060 retval = -cb_host_to_target_errno (cb, EAGAIN);
3061 break;
3062 }
3063
3064 /* FIXME: Implement the low byte. */
3065 if ((flags & ~TARGET_CSIGNAL) !=
3066 (TARGET_CLONE_VM
3067 | TARGET_CLONE_FS
3068 | TARGET_CLONE_FILES
3069 | TARGET_CLONE_SIGHAND)
3070 || newsp == 0)
3071 {
466b1d33
HPN
3072 retval
3073 = cris_unknown_syscall (current_cpu, pc,
3074 "Unimplemented clone syscall "
3075 "(0x%lx, 0x%lx)\n",
3076 (unsigned long) arg1,
3077 (unsigned long) arg2);
3078 break;
f6bcefef
HPN
3079 }
3080
3081 if (current_cpu->thread_data == NULL)
3082 make_first_thread (current_cpu);
3083
3084 /* The created thread will get the new SP and a cleared R10.
3085 Since it's created out of a copy of the old thread and we
3086 don't have a set-register-function that just take the
3087 cpu_data as a parameter, we set the childs values first,
3088 and write back or overwrite them in the parent after the
3089 copy. */
3090 (*CPU_REG_FETCH (current_cpu)) (current_cpu,
3091 H_GR_SP, old_sp_buf, 4);
3092 bfd_putl32 (newsp, sp_buf);
3093 (*CPU_REG_STORE (current_cpu)) (current_cpu,
3094 H_GR_SP, sp_buf, 4);
3095 (*CPU_REG_STORE (current_cpu)) (current_cpu,
3096 H_GR_R10, (bfd_byte *) zeros, 4);
3097 thread_cpu_data
3098 = (*current_cpu
3099 ->make_thread_cpu_data) (current_cpu,
3100 &current_cpu->cpu_data_placeholder);
3101 (*CPU_REG_STORE (current_cpu)) (current_cpu,
3102 H_GR_SP, old_sp_buf, 4);
3103
3104 retval = ++current_cpu->max_threadid + TARGET_PID;
3105
3106 /* Find an unused slot. After a few threads have been created
3107 and exited, the array is expected to be a bit fragmented.
3108 We don't reuse the first entry, though, that of the
3109 original thread. */
3110 for (i = 1; i < SIM_TARGET_MAX_THREADS; i++)
3111 if (current_cpu->thread_data[i].cpu_context == NULL
3112 /* Don't reuse a zombied entry. */
3113 && current_cpu->thread_data[i].threadid == 0)
3114 break;
3115
3116 memcpy (&current_cpu->thread_data[i],
3117 &current_cpu->thread_data[threadno],
3118 sizeof (current_cpu->thread_data[i]));
3119 current_cpu->thread_data[i].cpu_context = thread_cpu_data;
3120 current_cpu->thread_data[i].cpu_context_atsignal = NULL;
3121 current_cpu->thread_data[i].threadid = current_cpu->max_threadid;
3122 current_cpu->thread_data[i].parent_threadid
3123 = current_cpu->thread_data[threadno].threadid;
3124 current_cpu->thread_data[i].pipe_read_fd = 0;
3125 current_cpu->thread_data[i].pipe_write_fd = 0;
3126 current_cpu->thread_data[i].at_syscall = 0;
3127 current_cpu->thread_data[i].sigpending = 0;
3128 current_cpu->thread_data[i].sigsuspended = 0;
3129 current_cpu->thread_data[i].exitsig = flags & TARGET_CSIGNAL;
3130 current_cpu->m1threads = nthreads;
3131 break;
3132 }
3133
3134 /* Better watch these in case they do something necessary. */
3135 case TARGET_SYS_socketcall:
3136 retval = -cb_host_to_target_errno (cb, ENOSYS);
3137 break;
3138
ddf2c972
HPN
3139 case TARGET_SYS_set_thread_area:
3140 /* Do the same error check as Linux. */
3141 if (arg1 & 255)
3142 {
3143 retval = -cb_host_to_target_errno (cb, EINVAL);
3144 break;
3145 }
3146 (*current_cpu->set_target_thread_data) (current_cpu, arg1);
3147 retval = 0;
3148 break;
3149
f6bcefef
HPN
3150 unimplemented_syscall:
3151 default:
466b1d33
HPN
3152 retval
3153 = cris_unknown_syscall (current_cpu, pc,
3154 "Unimplemented syscall: %d "
3155 "(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",
3156 callnum, arg1, arg2, arg3, arg4, arg5,
3157 arg6);
f6bcefef
HPN
3158 }
3159 }
3160
ed1f044a
HPN
3161 /* Minimal support for fcntl F_GETFL as used in open+fdopen. */
3162 if (callnum == TARGET_SYS_open)
3163 {
3164 current_cpu->last_open_fd = retval;
3165 current_cpu->last_open_flags = arg2;
3166 }
466b1d33 3167
ed1f044a
HPN
3168 current_cpu->last_syscall = callnum;
3169
f6bcefef
HPN
3170 /* A system call is a rescheduling point. For the time being, we don't
3171 reschedule anywhere else. */
3172 if (current_cpu->m1threads != 0
3173 /* We need to schedule off from an exiting thread that is the
3174 second-last one. */
3175 || (current_cpu->thread_data != NULL
3176 && current_cpu->thread_data[threadno].cpu_context == NULL))
3177 {
3178 bfd_byte retval_buf[4];
3179
3180 current_cpu->thread_data[threadno].last_execution
3181 = TARGET_TIME_MS (current_cpu);
3182 bfd_putl32 (retval, retval_buf);
3183 (*CPU_REG_STORE (current_cpu)) (current_cpu, H_GR_R10, retval_buf, 4);
3184
3185 current_cpu->thread_data[threadno].at_syscall = 1;
3186 reschedule (current_cpu);
3187
3188 (*CPU_REG_FETCH (current_cpu)) (current_cpu, H_GR_R10, retval_buf, 4);
3189 retval = bfd_getl32 (retval_buf);
3190 }
3191
3192 return retval;
3193}
3194
3195/* Callback from simulator write saying that the pipe at (reader, writer)
3196 is now non-empty (so the writer should wait until the pipe is empty, at
3197 least not write to this or any other pipe). Simplest is to just wait
3198 until the pipe is empty. */
3199
3200static void
3201cris_pipe_nonempty (host_callback *cb ATTRIBUTE_UNUSED,
3202 int reader, int writer)
3203{
3204 SIM_CPU *cpu = current_cpu_for_cb_callback;
3205 const bfd_byte zeros[4] = { 0, 0, 0, 0 };
3206
3207 /* It's the current thread: we just have to re-run the current
3208 syscall instruction (presumably "break 13") and change the syscall
3209 to the special simulator-wait code. Oh, and set a marker that
3210 we're waiting, so we can disambiguate the special call from a
3211 program error.
3212
3213 This function may be called multiple times between cris_pipe_empty,
3214 but we must avoid e.g. decreasing PC every time. Check fd markers
3215 to tell. */
3216 if (cpu->thread_data == NULL)
3217 {
3218 sim_io_eprintf (CPU_STATE (cpu),
3219 "Terminating simulation due to writing pipe rd:wr %d:%d"
3220 " from one single thread\n", reader, writer);
3221 sim_engine_halt (CPU_STATE (cpu), cpu,
3222 NULL, sim_pc_get (cpu), sim_stopped, SIM_SIGILL);
3223 }
3224 else if (cpu->thread_data[cpu->threadno].pipe_write_fd == 0)
3225 {
3226 cpu->thread_data[cpu->threadno].pipe_write_fd = writer;
3227 cpu->thread_data[cpu->threadno].pipe_read_fd = reader;
3228 /* FIXME: We really shouldn't change registers other than R10 in
3229 syscalls (like R9), here or elsewhere. */
3230 (*CPU_REG_STORE (cpu)) (cpu, H_GR_R9, (bfd_byte *) zeros, 4);
3231 sim_pc_set (cpu, sim_pc_get (cpu) - 2);
3232 }
3233}
3234
3235/* Callback from simulator close or read call saying that the pipe at
3236 (reader, writer) is now empty (so the writer can write again, perhaps
3237 leave a waiting state). If there are bytes remaining, they couldn't be
3238 consumed (perhaps due to the pipe closing). */
3239
3240static void
3241cris_pipe_empty (host_callback *cb,
eccd787e 3242 int reader,
f6bcefef
HPN
3243 int writer)
3244{
3245 int i;
3246 SIM_CPU *cpu = current_cpu_for_cb_callback;
fc887f09 3247 SIM_DESC sd = CPU_STATE (current_cpu_for_cb_callback);
f6bcefef 3248 bfd_byte r10_buf[4];
eccd787e
HPN
3249 int remaining
3250 = cb->pipe_buffer[writer].size - cb->pipe_buffer[reader].size;
f6bcefef
HPN
3251
3252 /* We need to find the thread that waits for this pipe. */
3253 for (i = 0; i < SIM_TARGET_MAX_THREADS; i++)
3254 if (cpu->thread_data[i].cpu_context
3255 && cpu->thread_data[i].pipe_write_fd == writer)
3256 {
3257 int retval;
eccd787e 3258
f6bcefef
HPN
3259 /* Temporarily switch to this cpu context, so we can change the
3260 PC by ordinary calls. */
3261
3262 memcpy (cpu->thread_data[cpu->threadno].cpu_context,
3263 &cpu->cpu_data_placeholder,
3264 cpu->thread_cpu_data_size);
3265 memcpy (&cpu->cpu_data_placeholder,
3266 cpu->thread_data[i].cpu_context,
3267 cpu->thread_cpu_data_size);
3268
eccd787e
HPN
3269 /* The return value is supposed to contain the number of
3270 written bytes, which is the number of bytes requested and
3271 returned at the write call. You might think the right
3272 thing is to adjust the return-value to be only the
3273 *consumed* number of bytes, but it isn't. We're only
3274 called if the pipe buffer is fully consumed or it is being
3275 closed, possibly with remaining bytes. For the latter
3276 case, the writer is still supposed to see success for
3277 PIPE_BUF bytes (a constant which we happen to know and is
3278 unlikely to change). The return value may also be a
3279 negative number; an error value. This case is covered
3280 because "remaining" is always >= 0. */
f6bcefef
HPN
3281 (*CPU_REG_FETCH (cpu)) (cpu, H_GR_R10, r10_buf, 4);
3282 retval = (int) bfd_getl_signed_32 (r10_buf);
eccd787e
HPN
3283 if (retval - remaining > TARGET_PIPE_BUF)
3284 {
3285 bfd_putl32 (retval - remaining, r10_buf);
3286 (*CPU_REG_STORE (cpu)) (cpu, H_GR_R10, r10_buf, 4);
3287 }
f6bcefef
HPN
3288 sim_pc_set (cpu, sim_pc_get (cpu) + 2);
3289 memcpy (cpu->thread_data[i].cpu_context,
3290 &cpu->cpu_data_placeholder,
3291 cpu->thread_cpu_data_size);
3292 memcpy (&cpu->cpu_data_placeholder,
3293 cpu->thread_data[cpu->threadno].cpu_context,
3294 cpu->thread_cpu_data_size);
3295 cpu->thread_data[i].pipe_read_fd = 0;
3296 cpu->thread_data[i].pipe_write_fd = 0;
3297 return;
3298 }
3299
3300 abort ();
3301}
3302
3303/* We have a simulator-specific notion of time. See TARGET_TIME. */
3304
00330cd1
MF
3305static int64_t
3306cris_time (host_callback *cb ATTRIBUTE_UNUSED)
f6bcefef 3307{
00330cd1 3308 return TARGET_TIME (current_cpu_for_cb_callback);
f6bcefef
HPN
3309}
3310
e91488f7
MF
3311static int
3312cris_getpid (host_callback *cb ATTRIBUTE_UNUSED)
3313{
3314 return TARGET_PID;
3315}
3316
f6bcefef
HPN
3317/* Set target-specific callback data. */
3318
3319void
3320cris_set_callbacks (host_callback *cb)
3321{
3322 /* Yeargh, have to cast away constness to avoid warnings. */
3323 cb->syscall_map = (CB_TARGET_DEFS_MAP *) syscall_map;
3324 cb->errno_map = (CB_TARGET_DEFS_MAP *) errno_map;
3325
e91488f7
MF
3326 cb->getpid = cris_getpid;
3327
f6bcefef
HPN
3328 /* The kernel stat64 layout. If we see a file > 2G, the "long"
3329 parameter to cb_store_target_endian will make st_size negative.
3330 Similarly for st_ino. FIXME: Find a 64-bit type, and use it
3331 *unsigned*, and/or add syntax for signed-ness. */
3332 cb->stat_map = stat_map;
3333 cb->open_map = (CB_TARGET_DEFS_MAP *) open_map;
3334 cb->pipe_nonempty = cris_pipe_nonempty;
3335 cb->pipe_empty = cris_pipe_empty;
3336 cb->time = cris_time;
3337}
3338
3339/* Process an address exception. */
3340
3341void
3342cris_core_signal (SIM_DESC sd, SIM_CPU *current_cpu, sim_cia cia,
3343 unsigned int map, int nr_bytes, address_word addr,
3344 transfer_type transfer, sim_core_signals sig)
3345{
3346 sim_core_signal (sd, current_cpu, cia, map, nr_bytes, addr,
3347 transfer, sig);
3348}