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