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