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