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