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