1 /* CRIS exception, interrupt, and trap (EIT) support
2 Copyright (C) 2004, 2005 Free Software Foundation, Inc.
3 Contributed by Axis Communications.
5 This file is part of the GNU simulators.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License along
18 with this program; if not, write to the Free Software Foundation, Inc.,
19 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
22 #include "sim-options.h"
23 #include "targ-vals.h"
34 #ifdef HAVE_SYS_PARAM_H
35 #include <sys/param.h>
37 #ifdef HAVE_SYS_STAT_H
41 /* The verbatim values are from asm-cris/unistd.h. */
43 #define TARGET_SYS_exit 1
44 #define TARGET_SYS_read 3
45 #define TARGET_SYS_write 4
46 #define TARGET_SYS_open 5
47 #define TARGET_SYS_close 6
48 #define TARGET_SYS_unlink 10
49 #define TARGET_SYS_time 13
50 #define TARGET_SYS_lseek 19
51 #define TARGET_SYS_getpid 20
52 #define TARGET_SYS_kill 37
53 #define TARGET_SYS_rename 38
54 #define TARGET_SYS_pipe 42
55 #define TARGET_SYS_brk 45
56 #define TARGET_SYS_ioctl 54
57 #define TARGET_SYS_fcntl 55
58 #define TARGET_SYS_getppid 64
59 #define TARGET_SYS_setrlimit 75
60 #define TARGET_SYS_gettimeofday 78
61 #define TARGET_SYS_readlink 85
62 #define TARGET_SYS_munmap 91
63 #define TARGET_SYS_truncate 92
64 #define TARGET_SYS_ftruncate 93
65 #define TARGET_SYS_socketcall 102
66 #define TARGET_SYS_fstat 108
67 #define TARGET_SYS_wait4 114
68 #define TARGET_SYS_sigreturn 119
69 #define TARGET_SYS_clone 120
70 #define TARGET_SYS_uname 122
71 #define TARGET_SYS_mprotect 125
72 #define TARGET_SYS_llseek 140
73 #define TARGET_SYS__sysctl 149
74 #define TARGET_SYS_sched_setparam 154
75 #define TARGET_SYS_sched_getparam 155
76 #define TARGET_SYS_sched_setscheduler 156
77 #define TARGET_SYS_sched_getscheduler 157
78 #define TARGET_SYS_sched_yield 158
79 #define TARGET_SYS_sched_get_priority_max 159
80 #define TARGET_SYS_sched_get_priority_min 160
81 #define TARGET_SYS_mremap 163
82 #define TARGET_SYS_poll 168
83 #define TARGET_SYS_rt_sigaction 174
84 #define TARGET_SYS_rt_sigprocmask 175
85 #define TARGET_SYS_rt_sigsuspend 179
86 #define TARGET_SYS_getcwd 183
87 #define TARGET_SYS_ugetrlimit 191
88 #define TARGET_SYS_mmap2 192
89 #define TARGET_SYS_stat64 195
90 #define TARGET_SYS_lstat64 196
91 #define TARGET_SYS_fstat64 197
92 #define TARGET_SYS_geteuid32 201
93 #define TARGET_SYS_getuid32 199
94 #define TARGET_SYS_getegid32 202
95 #define TARGET_SYS_getgid32 200
96 #define TARGET_SYS_fcntl64 221
98 #define TARGET_PROT_READ 0x1
99 #define TARGET_PROT_WRITE 0x2
100 #define TARGET_PROT_EXEC 0x4
101 #define TARGET_PROT_NONE 0x0
103 #define TARGET_MAP_SHARED 0x01
104 #define TARGET_MAP_PRIVATE 0x02
105 #define TARGET_MAP_TYPE 0x0f
106 #define TARGET_MAP_FIXED 0x10
107 #define TARGET_MAP_ANONYMOUS 0x20
109 #define TARGET_CTL_KERN 1
110 #define TARGET_CTL_VM 2
111 #define TARGET_CTL_NET 3
112 #define TARGET_CTL_PROC 4
113 #define TARGET_CTL_FS 5
114 #define TARGET_CTL_DEBUG 6
115 #define TARGET_CTL_DEV 7
116 #define TARGET_CTL_BUS 8
117 #define TARGET_CTL_ABI 9
119 #define TARGET_CTL_KERN_VERSION 4
122 #define TARGET_MREMAP_MAYMOVE 1
123 #define TARGET_MREMAP_FIXED 2
125 #define TARGET_TCGETS 0x5401
127 #define TARGET_UTSNAME "#38 Sun Apr 1 00:00:00 MET 2001"
129 /* Seconds since the above date + 10 minutes. */
130 #define TARGET_EPOCH 986080200
132 /* Milliseconds since start of run. We use the number of syscalls to
133 avoid introducing noise in the execution time. */
134 #define TARGET_TIME_MS(cpu) ((cpu)->syscalls)
136 /* Seconds as in time(2). */
137 #define TARGET_TIME(cpu) (TARGET_EPOCH + TARGET_TIME_MS (cpu) / 1000)
139 #define TARGET_SCHED_OTHER 0
141 #define TARGET_RLIMIT_STACK 3
142 #define TARGET_RLIMIT_NOFILE 7
144 #define SIM_TARGET_MAX_THREADS 64
145 #define SIM_MAX_ALLOC_CHUNK (512*1024*1024)
147 /* From linux/sched.h. */
148 #define TARGET_CSIGNAL 0x000000ff
149 #define TARGET_CLONE_VM 0x00000100
150 #define TARGET_CLONE_FS 0x00000200
151 #define TARGET_CLONE_FILES 0x00000400
152 #define TARGET_CLONE_SIGHAND 0x00000800
153 #define TARGET_CLONE_PID 0x00001000
154 #define TARGET_CLONE_PTRACE 0x00002000
155 #define TARGET_CLONE_VFORK 0x00004000
156 #define TARGET_CLONE_PARENT 0x00008000
157 #define TARGET_CLONE_THREAD 0x00010000
158 #define TARGET_CLONE_SIGNAL (TARGET_CLONE_SIGHAND | TARGET_CLONE_THREAD)
160 /* From asm-cris/poll.h. */
161 #define TARGET_POLLIN 1
163 /* From asm-cris/signal.h. */
164 #define TARGET_SIG_BLOCK 0
165 #define TARGET_SIG_UNBLOCK 1
166 #define TARGET_SIG_SETMASK 2
168 #define TARGET_SIG_DFL 0
169 #define TARGET_SIG_IGN 1
170 #define TARGET_SIG_ERR ((USI)-1)
172 #define TARGET_SIGHUP 1
173 #define TARGET_SIGINT 2
174 #define TARGET_SIGQUIT 3
175 #define TARGET_SIGILL 4
176 #define TARGET_SIGTRAP 5
177 #define TARGET_SIGABRT 6
178 #define TARGET_SIGIOT 6
179 #define TARGET_SIGBUS 7
180 #define TARGET_SIGFPE 8
181 #define TARGET_SIGKILL 9
182 #define TARGET_SIGUSR1 10
183 #define TARGET_SIGSEGV 11
184 #define TARGET_SIGUSR2 12
185 #define TARGET_SIGPIPE 13
186 #define TARGET_SIGALRM 14
187 #define TARGET_SIGTERM 15
188 #define TARGET_SIGSTKFLT 16
189 #define TARGET_SIGCHLD 17
190 #define TARGET_SIGCONT 18
191 #define TARGET_SIGSTOP 19
192 #define TARGET_SIGTSTP 20
193 #define TARGET_SIGTTIN 21
194 #define TARGET_SIGTTOU 22
195 #define TARGET_SIGURG 23
196 #define TARGET_SIGXCPU 24
197 #define TARGET_SIGXFSZ 25
198 #define TARGET_SIGVTALRM 26
199 #define TARGET_SIGPROF 27
200 #define TARGET_SIGWINCH 28
201 #define TARGET_SIGIO 29
202 #define TARGET_SIGPOLL SIGIO
203 /* Actually commented out in the kernel header. */
204 #define TARGET_SIGLOST 29
205 #define TARGET_SIGPWR 30
206 #define TARGET_SIGSYS 31
208 /* From include/asm-cris/signal.h. */
209 #define TARGET_SA_NOCLDSTOP 0x00000001
210 #define TARGET_SA_NOCLDWAIT 0x00000002 /* not supported yet */
211 #define TARGET_SA_SIGINFO 0x00000004
212 #define TARGET_SA_ONSTACK 0x08000000
213 #define TARGET_SA_RESTART 0x10000000
214 #define TARGET_SA_NODEFER 0x40000000
215 #define TARGET_SA_RESETHAND 0x80000000
216 #define TARGET_SA_INTERRUPT 0x20000000 /* dummy -- ignored */
217 #define TARGET_SA_RESTORER 0x04000000
219 /* From linux/wait.h. */
220 #define TARGET_WNOHANG 1
221 #define TARGET_WUNTRACED 2
222 #define TARGET___WNOTHREAD 0x20000000
223 #define TARGET___WALL 0x40000000
224 #define TARGET___WCLONE 0x80000000
226 static const char stat_map
[] =
227 "st_dev,2:space,10:space,4:st_mode,4:st_nlink,4:st_uid,4"
228 ":st_gid,4:st_rdev,2:space,10:st_size,8:st_blksize,4:st_blocks,4"
229 ":space,4:st_atime,4:space,4:st_mtime,4:space,4:st_ctime,4:space,4"
232 static const CB_TARGET_DEFS_MAP syscall_map
[] =
234 { CB_SYS_open
, TARGET_SYS_open
},
235 { CB_SYS_close
, TARGET_SYS_close
},
236 { CB_SYS_read
, TARGET_SYS_read
},
237 { CB_SYS_write
, TARGET_SYS_write
},
238 { CB_SYS_lseek
, TARGET_SYS_lseek
},
239 { CB_SYS_unlink
, TARGET_SYS_unlink
},
240 { CB_SYS_getpid
, TARGET_SYS_getpid
},
241 { CB_SYS_fstat
, TARGET_SYS_fstat64
},
242 { CB_SYS_lstat
, TARGET_SYS_lstat64
},
243 { CB_SYS_stat
, TARGET_SYS_stat64
},
244 { CB_SYS_pipe
, TARGET_SYS_pipe
},
245 { CB_SYS_time
, TARGET_SYS_time
},
246 { CB_SYS_rename
, TARGET_SYS_rename
},
247 { CB_SYS_truncate
, TARGET_SYS_truncate
},
248 { CB_SYS_ftruncate
, TARGET_SYS_ftruncate
},
252 /* An older, 32-bit-only stat mapping. */
253 static const char stat32_map
[] =
254 "st_dev,2:space,2:st_ino,4:st_mode,2:st_nlink,2:st_uid,2"
255 ":st_gid,2:st_rdev,2:space,2:st_size,4:st_blksize,4:st_blocks,4"
256 ":st_atime,4:space,4:st_mtime,4:space,4:st_ctime,4:space,12";
258 /* Map for calls using the 32-bit struct stat. Primarily used by the
259 newlib Linux mapping. */
260 static const CB_TARGET_DEFS_MAP syscall_stat32_map
[] =
262 { CB_SYS_fstat
, TARGET_SYS_fstat
},
266 /* Giving the true value for the running sim process will lead to
267 non-time-invariant behavior. */
268 #define TARGET_PID 42
270 /* Unfortunately, we don't get this from cris.cpu at the moment, and if
271 we did, we'd still don't get a register number with the "16" offset. */
272 #define TARGET_SRP_REGNUM (16+11)
274 /* Extracted by applying
275 awk '/^#define/ { printf "#ifdef %s\n { %s, %s },\n#endif\n", $2, $2, $3;}'
276 on .../include/asm/errno.h in a GNU/Linux/CRIS installation and
277 adjusting the synonyms. */
279 static const CB_TARGET_DEFS_MAP errno_map
[] =
387 { ENAMETOOLONG
, 36 },
546 { EDESTADDRREQ
, 89 },
557 #ifdef EPROTONOSUPPORT
558 { EPROTONOSUPPORT
, 93 },
560 #ifdef ESOCKTNOSUPPORT
561 { ESOCKTNOSUPPORT
, 94 },
567 { EPFNOSUPPORT
, 96 },
570 { EAFNOSUPPORT
, 97 },
576 { EADDRNOTAVAIL
, 99 },
582 { ENETUNREACH
, 101 },
588 { ECONNABORTED
, 103 },
606 { ETOOMANYREFS
, 109 },
612 { ECONNREFUSED
, 111 },
618 { EHOSTUNREACH
, 113 },
624 { EINPROGRESS
, 115 },
651 { EMEDIUMTYPE
, 124 },
656 /* Extracted by applying
657 perl -ne 'if ($_ =~ /^#define/) { split;
658 printf "#ifdef $_[1]\n { %s, 0x%x },\n#endif\n",
659 $_[1], $_[2] =~ /^0/ ? oct($_[2]) : $_[2];}'
660 on pertinent parts of .../include/asm/fcntl.h in a GNU/Linux/CRIS
661 installation and removing synonyms and unnecessary items. Don't
662 forget the end-marker. */
664 static const CB_TARGET_DEFS_MAP open_map
[] = {
693 { O_NONBLOCK
, 0x800 },
705 { O_DIRECT
, 0x4000 },
708 { O_LARGEFILE
, 0x8000 },
711 { O_DIRECTORY
, 0x10000 },
714 { O_NOFOLLOW
, 0x20000 },
719 /* Needed for the cris_pipe_nonempty and cris_pipe_empty syscalls. */
720 static SIM_CPU
*current_cpu_for_cb_callback
;
722 static int syscall_read_mem (host_callback
*, struct cb_syscall
*,
723 unsigned long, char *, int);
724 static int syscall_write_mem (host_callback
*, struct cb_syscall
*,
725 unsigned long, const char *, int);
726 static USI
create_map (SIM_DESC
, struct cris_sim_mmapped_page
**,
728 static USI
unmap_pages (SIM_DESC
, struct cris_sim_mmapped_page
**,
730 static USI
is_mapped (SIM_DESC
, struct cris_sim_mmapped_page
**,
732 static void dump_statistics (SIM_CPU
*current_cpu
);
733 static void make_first_thread (SIM_CPU
*current_cpu
);
735 /* Read/write functions for system call interface. */
738 syscall_read_mem (host_callback
*cb ATTRIBUTE_UNUSED
,
739 struct cb_syscall
*sc
,
740 unsigned long taddr
, char *buf
, int bytes
)
742 SIM_DESC sd
= (SIM_DESC
) sc
->p1
;
743 SIM_CPU
*cpu
= (SIM_CPU
*) sc
->p2
;
745 return sim_core_read_buffer (sd
, cpu
, read_map
, buf
, taddr
, bytes
);
749 syscall_write_mem (host_callback
*cb ATTRIBUTE_UNUSED
,
750 struct cb_syscall
*sc
,
751 unsigned long taddr
, const char *buf
, int bytes
)
753 SIM_DESC sd
= (SIM_DESC
) sc
->p1
;
754 SIM_CPU
*cpu
= (SIM_CPU
*) sc
->p2
;
756 return sim_core_write_buffer (sd
, cpu
, write_map
, buf
, taddr
, bytes
);
759 /* When we risk running self-modified code (as in trampolines), this is
760 called from special-case insns. The silicon CRIS CPU:s have enough
761 cache snooping implemented making this a simulator-only issue. Tests:
762 gcc.c-torture/execute/931002-1.c execution, -O3 -g
763 gcc.c-torture/execute/931002-1.c execution, -O3 -fomit-frame-pointer. */
766 cris_flush_simulator_decode_cache (SIM_CPU
*current_cpu
,
767 USI pc ATTRIBUTE_UNUSED
)
769 SIM_DESC sd
= CPU_STATE (current_cpu
);
772 if (USING_SCACHE_P (sd
))
773 scache_flush_cpu (current_cpu
);
777 /* Output statistics at the end of a run. */
779 dump_statistics (SIM_CPU
*current_cpu
)
781 SIM_DESC sd
= CPU_STATE (current_cpu
);
782 CRIS_MISC_PROFILE
*profp
783 = CPU_CRIS_MISC_PROFILE (current_cpu
);
784 unsigned64 total
= profp
->basic_cycle_count
;
785 const char *textmsg
= "Basic clock cycles, total @: %llu\n";
787 /* The --cris-stats={basic|unaligned|schedulable|all} counts affect
788 what's included in the "total" count only. */
789 switch (CPU_CRIS_MISC_PROFILE (current_cpu
)->flags
790 & FLAG_CRIS_MISC_PROFILE_ALL
)
792 case FLAG_CRIS_MISC_PROFILE_SIMPLE
:
795 case (FLAG_CRIS_MISC_PROFILE_UNALIGNED
| FLAG_CRIS_MISC_PROFILE_SIMPLE
):
797 = "Clock cycles including stall cycles for unaligned accesses @: %llu\n";
798 total
+= profp
->unaligned_mem_dword_count
;
801 case (FLAG_CRIS_MISC_PROFILE_SCHEDULABLE
| FLAG_CRIS_MISC_PROFILE_SIMPLE
):
802 textmsg
= "Schedulable clock cycles, total @: %llu\n";
804 += (profp
->memsrc_stall_count
805 + profp
->memraw_stall_count
806 + profp
->movemsrc_stall_count
807 + profp
->movemdst_stall_count
808 + profp
->mulsrc_stall_count
809 + profp
->jumpsrc_stall_count
810 + profp
->unaligned_mem_dword_count
);
813 case FLAG_CRIS_MISC_PROFILE_ALL
:
814 textmsg
= "All accounted clock cycles, total @: %llu\n";
816 += (profp
->memsrc_stall_count
817 + profp
->memraw_stall_count
818 + profp
->movemsrc_stall_count
819 + profp
->movemdst_stall_count
820 + profp
->movemaddr_stall_count
821 + profp
->mulsrc_stall_count
822 + profp
->jumpsrc_stall_count
823 + profp
->branch_stall_count
824 + profp
->jumptarget_stall_count
825 + profp
->unaligned_mem_dword_count
);
832 "Internal inconsistency at %s:%d",
834 sim_engine_halt (sd
, current_cpu
, NULL
, 0,
835 sim_stopped
, SIM_SIGILL
);
838 /* Historically, these messages have gone to stderr, so we'll keep it
839 that way. It's also easier to then tell it from normal program
840 output. FIXME: Add redirect option like "run -e file". */
841 sim_io_eprintf (sd
, textmsg
, total
);
843 /* For v32, unaligned_mem_dword_count should always be 0. For
844 v10, memsrc_stall_count should always be 0. */
845 sim_io_eprintf (sd
, "Memory source stall cycles: %lld\n",
846 profp
->memsrc_stall_count
847 + profp
->unaligned_mem_dword_count
);
848 sim_io_eprintf (sd
, "Memory read-after-write stall cycles: %lld\n",
849 profp
->memraw_stall_count
);
850 sim_io_eprintf (sd
, "Movem source stall cycles: %lld\n",
851 profp
->movemsrc_stall_count
);
852 sim_io_eprintf (sd
, "Movem destination stall cycles: %lld\n",
853 profp
->movemdst_stall_count
);
854 sim_io_eprintf (sd
, "Movem address stall cycles: %lld\n",
855 profp
->movemaddr_stall_count
);
856 sim_io_eprintf (sd
, "Multiplication source stall cycles: %lld\n",
857 profp
->mulsrc_stall_count
);
858 sim_io_eprintf (sd
, "Jump source stall cycles: %lld\n",
859 profp
->jumpsrc_stall_count
);
860 sim_io_eprintf (sd
, "Branch misprediction stall cycles: %lld\n",
861 profp
->branch_stall_count
);
862 sim_io_eprintf (sd
, "Jump target stall cycles: %lld\n",
863 profp
->jumptarget_stall_count
);
866 /* Check whether any part of [addr .. addr + len - 1] is already mapped.
867 Return 1 if a overlap detected, 0 otherwise. */
870 is_mapped (SIM_DESC sd ATTRIBUTE_UNUSED
,
871 struct cris_sim_mmapped_page
**rootp
,
874 struct cris_sim_mmapped_page
*mapp
;
876 if (len
== 0 || (len
& 8191))
879 /* Iterate over the reverse-address sorted pages until we find a page in
880 or lower than the checked area. */
881 for (mapp
= *rootp
; mapp
!= NULL
&& mapp
->addr
>= addr
; mapp
= mapp
->prev
)
882 if (mapp
->addr
< addr
+ len
&& mapp
->addr
>= addr
)
888 /* Create mmapped memory. */
891 create_map (SIM_DESC sd
, struct cris_sim_mmapped_page
**rootp
, USI addr
,
894 struct cris_sim_mmapped_page
*mapp
;
895 struct cris_sim_mmapped_page
**higher_prevp
= rootp
;
896 USI new_addr
= 0x40000000;
901 new_addr
= rootp
[0]->addr
+ 8192;
908 /* Which is better: return an error for this, or just round it up? */
911 /* Do a recursive call for each page in the request. */
912 for (page_addr
= new_addr
; len
!= 0; page_addr
+= 8192, len
-= 8192)
913 if (create_map (sd
, rootp
, page_addr
, 8192) >= (USI
) -8191)
920 mapp
!= NULL
&& mapp
->addr
> new_addr
;
922 higher_prevp
= &mapp
->prev
;
924 /* Allocate the new page, on the next higher page from the last one
925 allocated, and link in the new descriptor before previous ones. */
926 mapp
= malloc (sizeof (*mapp
));
929 return (USI
) -ENOMEM
;
931 sim_core_attach (sd
, NULL
, 0, access_read_write_exec
, 0,
935 mapp
->addr
= new_addr
;
936 mapp
->prev
= *higher_prevp
;
937 *higher_prevp
= mapp
;
942 /* Unmap one or more pages. */
945 unmap_pages (SIM_DESC sd
, struct cris_sim_mmapped_page
**rootp
, USI addr
,
948 struct cris_sim_mmapped_page
*mapp
;
949 struct cris_sim_mmapped_page
**higher_prevp
= rootp
;
956 /* Which is better: return an error for this, or just round it up? */
959 /* Loop backwards to make each call is O(1) over the number of pages
960 allocated, if we're unmapping from the high end of the pages. */
961 for (page_addr
= addr
+ len
- 8192;
964 if (unmap_pages (sd
, rootp
, page_addr
, 8192) != 0)
970 for (mapp
= *rootp
; mapp
!= NULL
&& mapp
->addr
> addr
; mapp
= mapp
->prev
)
971 higher_prevp
= &mapp
->prev
;
973 if (mapp
== NULL
|| mapp
->addr
!= addr
)
976 *higher_prevp
= mapp
->prev
;
977 sim_core_detach (sd
, NULL
, 0, 0, addr
);
982 /* The semantic code invokes this for illegal (unrecognized) instructions. */
985 sim_engine_invalid_insn (SIM_CPU
*current_cpu
, IADDR cia
, SEM_PC vpc
)
987 SIM_DESC sd
= CPU_STATE (current_cpu
);
989 sim_engine_halt (sd
, current_cpu
, NULL
, cia
, sim_stopped
, SIM_SIGILL
);
993 /* Handlers from the CGEN description that should not be called. */
996 cris_bmod_handler (SIM_CPU
*current_cpu ATTRIBUTE_UNUSED
,
997 UINT srcreg ATTRIBUTE_UNUSED
,
998 USI dstreg ATTRIBUTE_UNUSED
)
1004 h_supr_set_handler (SIM_CPU
*current_cpu ATTRIBUTE_UNUSED
,
1005 UINT index ATTRIBUTE_UNUSED
,
1006 USI page ATTRIBUTE_UNUSED
,
1007 USI newval ATTRIBUTE_UNUSED
)
1013 h_supr_get_handler (SIM_CPU
*current_cpu ATTRIBUTE_UNUSED
,
1014 UINT index ATTRIBUTE_UNUSED
,
1015 USI page ATTRIBUTE_UNUSED
)
1020 /* Swap one context for another. */
1023 schedule (SIM_CPU
*current_cpu
, int next
)
1025 /* Need to mark context-switches in the trace output. */
1026 if ((CPU_CRIS_MISC_PROFILE (current_cpu
)->flags
1027 & FLAG_CRIS_MISC_PROFILE_XSIM_TRACE
))
1028 cris_trace_printf (CPU_STATE (current_cpu
), current_cpu
,
1031 /* Copy the current context (if there is one) to its slot. */
1032 if (current_cpu
->thread_data
[current_cpu
->threadno
].cpu_context
)
1033 memcpy (current_cpu
->thread_data
[current_cpu
->threadno
].cpu_context
,
1034 ¤t_cpu
->cpu_data_placeholder
,
1035 current_cpu
->thread_cpu_data_size
);
1037 /* Copy the new context from its slot. */
1038 memcpy (¤t_cpu
->cpu_data_placeholder
,
1039 current_cpu
->thread_data
[next
].cpu_context
,
1040 current_cpu
->thread_cpu_data_size
);
1042 /* Update needed stuff to indicate the new context. */
1043 current_cpu
->threadno
= next
;
1045 /* Handle pending signals. */
1046 if (current_cpu
->thread_data
[next
].sigpending
1047 /* We don't run nested signal handlers. This means that pause(2)
1048 and sigsuspend(2) do not work in sighandlers, but that
1049 shouldn't be too hard a restriction. It also greatly
1050 simplifies the code. */
1051 && current_cpu
->thread_data
[next
].cpu_context_atsignal
== NULL
)
1055 /* See if there's really a pending, non-blocked handler. We don't
1056 queue signals, so just use the first one in ascending order. */
1057 for (sig
= 0; sig
< 64; sig
++)
1058 if (current_cpu
->thread_data
[next
].sigdata
[sig
].pending
1059 && !current_cpu
->thread_data
[next
].sigdata
[sig
].blocked
)
1065 USI pc
= sim_pc_get (current_cpu
);
1067 /* It's simpler to save the CPU context inside the simulator
1068 than on the stack. */
1069 current_cpu
->thread_data
[next
].cpu_context_atsignal
1071 ->make_thread_cpu_data
) (current_cpu
,
1072 current_cpu
->thread_data
[next
]
1075 (*CPU_REG_FETCH (current_cpu
)) (current_cpu
, H_GR_SP
, regbuf
, 4);
1076 sp
= bfd_getl32 (regbuf
);
1078 /* Make sure we have an aligned stack. */
1081 /* Make room for the signal frame, aligned. FIXME: Check that
1082 the memory exists, map it in if absent. (BTW, should also
1083 implement on-access automatic stack allocation). */
1086 /* This isn't the same signal frame as the kernel uses, because
1087 we don't want to bother getting all registers on and off the
1090 /* First, we store the currently blocked signals. */
1092 for (i
= 0; i
< 32; i
++)
1094 |= current_cpu
->thread_data
[next
].sigdata
[i
+ 1].blocked
<< i
;
1095 sim_core_write_aligned_4 (current_cpu
, pc
, 0, sp
, blocked
);
1097 for (i
= 0; i
< 31; i
++)
1099 |= current_cpu
->thread_data
[next
].sigdata
[i
+ 33].blocked
<< i
;
1100 sim_core_write_aligned_4 (current_cpu
, pc
, 0, sp
+ 4, blocked
);
1102 /* Then, the actual instructions. This is CPU-specific, but we
1103 use instructions from the common subset for v10 and v32 which
1104 should be safe for the time being but could be parametrized
1106 /* MOVU.W [PC+],R9. */
1107 sim_core_write_aligned_2 (current_cpu
, pc
, 0, sp
+ 8, 0x9c5f);
1108 /* .WORD TARGET_SYS_sigreturn. */
1109 sim_core_write_aligned_2 (current_cpu
, pc
, 0, sp
+ 10,
1110 TARGET_SYS_sigreturn
);
1112 sim_core_write_aligned_2 (current_cpu
, pc
, 0, sp
+ 12, 0xe93d);
1114 /* NOP (on v32; it's SETF on v10, but is the correct compatible
1115 instruction. Still, it doesn't matter because v10 has no
1116 delay slot for BREAK so it will not be executed). */
1117 sim_core_write_aligned_2 (current_cpu
, pc
, 0, sp
+ 16, 0x05b0);
1119 /* Modify registers to hold the right values for the sighandler
1120 context: updated stackpointer and return address pointing to
1121 the sigreturn stub. */
1122 bfd_putl32 (sp
, regbuf
);
1123 (*CPU_REG_STORE (current_cpu
)) (current_cpu
, H_GR_SP
, regbuf
, 4);
1124 bfd_putl32 (sp
+ 8, regbuf
);
1125 (*CPU_REG_STORE (current_cpu
)) (current_cpu
, TARGET_SRP_REGNUM
,
1128 current_cpu
->thread_data
[next
].sigdata
[sig
].pending
= 0;
1130 /* Block this signal (for the duration of the sighandler). */
1131 current_cpu
->thread_data
[next
].sigdata
[sig
].blocked
= 1;
1133 sim_pc_set (current_cpu
, current_cpu
->sighandler
[sig
]);
1134 bfd_putl32 (sig
, regbuf
);
1135 (*CPU_REG_STORE (current_cpu
)) (current_cpu
, H_GR_R10
,
1138 /* We ignore a SA_SIGINFO flag in the sigaction call; the code I
1139 needed all this for, specifies a SA_SIGINFO call but treats it
1140 like an ordinary sighandler; only the signal number argument is
1141 inspected. To make future need to implement SA_SIGINFO
1142 correctly possible, we set the siginfo argument register to a
1143 magic (hopefully non-address) number. (NB: then, you should
1144 just need to pass the siginfo argument; it seems you probably
1145 don't need to implement the specific rt_sigreturn.) */
1146 bfd_putl32 (0xbad5161f, regbuf
);
1147 (*CPU_REG_STORE (current_cpu
)) (current_cpu
, H_GR_R11
,
1150 /* The third argument is unused and the kernel sets it to 0. */
1151 bfd_putl32 (0, regbuf
);
1152 (*CPU_REG_STORE (current_cpu
)) (current_cpu
, H_GR_R12
,
1157 /* No, there actually was no pending signal for this thread. Reset
1159 current_cpu
->thread_data
[next
].sigpending
= 0;
1163 /* Reschedule the simplest possible way until something else is absolutely
1165 - A. Find the next process (round-robin) that doesn't have at_syscall
1167 - B. If there is none, just run the next process, round-robin.
1168 - Clear at_syscall for the current process. */
1171 reschedule (SIM_CPU
*current_cpu
)
1175 /* Iterate over all thread slots, because after a few thread creations
1176 and exits, we don't know where the live ones are. */
1177 for (i
= (current_cpu
->threadno
+ 1) % SIM_TARGET_MAX_THREADS
;
1178 i
!= current_cpu
->threadno
;
1179 i
= (i
+ 1) % SIM_TARGET_MAX_THREADS
)
1180 if (current_cpu
->thread_data
[i
].cpu_context
1181 && current_cpu
->thread_data
[i
].at_syscall
== 0)
1183 schedule (current_cpu
, i
);
1187 /* Pick any next live thread. */
1188 for (i
= (current_cpu
->threadno
+ 1) % SIM_TARGET_MAX_THREADS
;
1189 i
!= current_cpu
->threadno
;
1190 i
= (i
+ 1) % SIM_TARGET_MAX_THREADS
)
1191 if (current_cpu
->thread_data
[i
].cpu_context
)
1193 schedule (current_cpu
, i
);
1197 /* More than one live thread, but we couldn't find the next one? */
1201 /* Set up everything to receive (or IGN) an incoming signal to the
1205 deliver_signal (SIM_CPU
*current_cpu
, int sig
, unsigned int pid
)
1208 USI pc
= sim_pc_get (current_cpu
);
1210 /* Find the thread index of the pid. */
1211 for (i
= 0; i
< SIM_TARGET_MAX_THREADS
; i
++)
1212 /* Apparently it's ok to send signals to zombies (so a check for
1213 current_cpu->thread_data[i].cpu_context != NULL would be
1215 if (current_cpu
->thread_data
[i
].threadid
== pid
- TARGET_PID
)
1218 switch (current_cpu
->sighandler
[sig
])
1220 case TARGET_SIG_DFL
:
1223 /* The following according to the glibc
1224 documentation. (The kernel code has non-obvious
1225 execution paths.) */
1228 case TARGET_SIGSEGV
:
1230 case TARGET_SIGABRT
:
1231 case TARGET_SIGTRAP
:
1234 case TARGET_SIGTERM
:
1236 case TARGET_SIGQUIT
:
1237 case TARGET_SIGKILL
:
1240 case TARGET_SIGALRM
:
1241 case TARGET_SIGVTALRM
:
1242 case TARGET_SIGPROF
:
1243 case TARGET_SIGSTOP
:
1245 case TARGET_SIGPIPE
:
1246 case TARGET_SIGLOST
:
1247 case TARGET_SIGXCPU
:
1248 case TARGET_SIGXFSZ
:
1249 case TARGET_SIGUSR1
:
1250 case TARGET_SIGUSR2
:
1251 sim_io_eprintf (CPU_STATE (current_cpu
),
1252 "Exiting pid %d due to signal %d\n",
1254 sim_engine_halt (CPU_STATE (current_cpu
), current_cpu
,
1255 NULL
, pc
, sim_stopped
,
1256 sig
== TARGET_SIGABRT
1257 ? SIM_SIGABRT
: SIM_SIGILL
);
1260 /* The default for all other signals is to be ignored. */
1265 case TARGET_SIG_IGN
:
1268 case TARGET_SIGKILL
:
1269 case TARGET_SIGSTOP
:
1270 /* Can't ignore these signals. */
1271 sim_io_eprintf (CPU_STATE (current_cpu
),
1272 "Exiting pid %d due to signal %d\n",
1274 sim_engine_halt (CPU_STATE (current_cpu
), current_cpu
,
1275 NULL
, pc
, sim_stopped
, SIM_SIGILL
);
1284 /* Mark the signal as pending, making schedule () check
1285 closer. The signal will be handled when the thread is
1286 scheduled and the signal is unblocked. */
1287 current_cpu
->thread_data
[i
].sigdata
[sig
].pending
= 1;
1288 current_cpu
->thread_data
[i
].sigpending
= 1;
1293 sim_io_eprintf (CPU_STATE (current_cpu
),
1294 "Unimplemented signal: %d\n", sig
);
1295 sim_engine_halt (CPU_STATE (current_cpu
), current_cpu
, NULL
, pc
,
1296 sim_stopped
, SIM_SIGILL
);
1301 -cb_host_to_target_errno (STATE_CALLBACK (CPU_STATE (current_cpu
)),
1305 /* Make the vector and the first item, the main thread. */
1308 make_first_thread (SIM_CPU
*current_cpu
)
1310 current_cpu
->thread_data
1312 SIM_TARGET_MAX_THREADS
1313 * sizeof (current_cpu
->thread_data
[0]));
1314 current_cpu
->thread_data
[0].cpu_context
1315 = (*current_cpu
->make_thread_cpu_data
) (current_cpu
,
1317 ->cpu_data_placeholder
);
1318 current_cpu
->thread_data
[0].parent_threadid
= -1;
1320 /* For good measure. */
1321 if (TARGET_SIG_DFL
!= 0)
1325 /* Main function: the handler of the "break 13" syscall insn. */
1328 cris_break_13_handler (SIM_CPU
*current_cpu
, USI callnum
, USI arg1
,
1329 USI arg2
, USI arg3
, USI arg4
, USI arg5
, USI arg6
,
1333 SIM_DESC sd
= CPU_STATE (current_cpu
);
1334 host_callback
*cb
= STATE_CALLBACK (sd
);
1336 int threadno
= current_cpu
->threadno
;
1338 current_cpu
->syscalls
++;
1340 CB_SYSCALL_INIT (&s
);
1346 if (callnum
== TARGET_SYS_exit
&& current_cpu
->m1threads
== 0)
1348 if (CPU_CRIS_MISC_PROFILE (current_cpu
)->flags
1349 & FLAG_CRIS_MISC_PROFILE_ALL
)
1350 dump_statistics (current_cpu
);
1351 sim_engine_halt (sd
, current_cpu
, NULL
, pc
, sim_exited
, arg1
);
1355 s
.p2
= (PTR
) current_cpu
;
1356 s
.read_mem
= syscall_read_mem
;
1357 s
.write_mem
= syscall_write_mem
;
1359 current_cpu_for_cb_callback
= current_cpu
;
1361 if (cb_syscall (cb
, &s
) != CB_RC_OK
)
1364 sim_io_eprintf (sd
, "Break 13: invalid %d? Returned %ld\n", callnum
,
1366 sim_engine_halt (sd
, current_cpu
, NULL
, pc
, sim_stopped
, SIM_SIGILL
);
1369 retval
= s
.result
== -1 ? -s
.errcode
: s
.result
;
1371 if (s
.errcode
!= 0 && s
.errcode
== cb_host_to_target_errno (cb
, ENOSYS
))
1373 /* If the generic simulator call said ENOSYS, then let's try the
1374 ones we know ourselves.
1376 The convention is to provide *very limited* functionality on an
1377 as-needed basis, only what's covered by the test-suite, tests
1378 added when functionality changes and abort with a descriptive
1379 message for *everything* else. Where there's no test-case, we
1384 /* It's a pretty safe bet that the "old setup() system call"
1385 number will not be re-used; we can't say the same for higher
1386 numbers. We treat this simulator-generated call as "wait
1387 forever"; we re-run this insn. The wait is ended by a
1388 callback. Sanity check that this is the reason we got
1390 if (current_cpu
->thread_data
== NULL
1391 || (current_cpu
->thread_data
[threadno
].pipe_write_fd
== 0))
1392 goto unimplemented_syscall
;
1394 sim_pc_set (current_cpu
, pc
);
1398 case TARGET_SYS_fcntl64
:
1399 case TARGET_SYS_fcntl
:
1403 Glibc checks stdin, stdout and stderr fd:s for
1404 close-on-exec security sanity. We just need to provide a
1405 OK return value. If we really need to have a
1406 close-on-exec flag true, we could just do a real fcntl
1412 /* F_SETFD. Just ignore attempts to set the close-on-exec
1418 case TARGET_SYS_uname
:
1420 /* Fill in a few constants to appease glibc. */
1421 static const char sim_utsname
[6][65] =
1431 if ((s
.write_mem
) (cb
, &s
, arg1
, (const char *) sim_utsname
,
1432 sizeof (sim_utsname
))
1433 != sizeof (sim_utsname
))
1434 retval
= -cb_host_to_target_errno (cb
, EFAULT
);
1440 case TARGET_SYS_geteuid32
:
1441 /* We tell the truth with these. Maybe we shouldn't, but it
1442 should match the "stat" information. */
1443 retval
= geteuid ();
1446 case TARGET_SYS_getuid32
:
1450 case TARGET_SYS_getegid32
:
1451 retval
= getegid ();
1454 case TARGET_SYS_getgid32
:
1458 case TARGET_SYS_brk
:
1459 /* Most often, we just return the argument, like the Linux
1464 retval
= current_cpu
->endbrk
;
1465 else if (arg1
<= current_cpu
->endmem
)
1466 current_cpu
->endbrk
= arg1
;
1469 USI new_end
= (arg1
+ 8191) & ~8191;
1471 /* If the simulator wants to brk more than a certain very
1472 large amount, something is wrong. FIXME: Return an error
1473 or abort? Have command-line selectable? */
1474 if (new_end
- current_cpu
->endmem
> SIM_MAX_ALLOC_CHUNK
)
1476 current_cpu
->endbrk
= current_cpu
->endmem
;
1477 retval
= current_cpu
->endmem
;
1481 sim_core_attach (sd
, NULL
, 0, access_read_write_exec
, 0,
1482 current_cpu
->endmem
,
1483 new_end
- current_cpu
->endmem
,
1485 current_cpu
->endbrk
= arg1
;
1486 current_cpu
->endmem
= new_end
;
1490 case TARGET_SYS_getpid
:
1491 /* Correct until CLONE_THREAD is implemented. */
1492 retval
= current_cpu
->thread_data
== NULL
1494 : TARGET_PID
+ current_cpu
->thread_data
[threadno
].threadid
;
1497 case TARGET_SYS_getppid
:
1498 /* Correct until CLONE_THREAD is implemented. */
1499 retval
= current_cpu
->thread_data
== NULL
1502 + current_cpu
->thread_data
[threadno
].parent_threadid
);
1505 case TARGET_SYS_mmap2
:
1514 /* If the simulator wants to mmap more than the very large
1515 limit, something is wrong. FIXME: Return an error or
1516 abort? Have command-line selectable? */
1517 if (len
> SIM_MAX_ALLOC_CHUNK
)
1519 retval
= -cb_host_to_target_errno (cb
, ENOMEM
);
1523 if ((prot
!= (TARGET_PROT_READ
| TARGET_PROT_WRITE
)
1525 != (TARGET_PROT_READ
1527 | TARGET_PROT_EXEC
))
1528 && prot
!= TARGET_PROT_READ
)
1529 || (flags
!= (TARGET_MAP_ANONYMOUS
| TARGET_MAP_PRIVATE
)
1530 && flags
!= TARGET_MAP_PRIVATE
1531 && flags
!= TARGET_MAP_SHARED
)
1532 || (fd
!= (USI
) -1 && prot
!= TARGET_PROT_READ
)
1534 || ((len
& 8191) != 0 && fd
== (USI
) -1))
1536 sim_io_eprintf (sd
, "Unimplemented mmap2 call "
1537 "(0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx)\n",
1538 (unsigned long) arg1
,
1539 (unsigned long) arg2
,
1540 (unsigned long) arg3
,
1541 (unsigned long) arg4
,
1542 (unsigned long) arg5
,
1543 (unsigned long) arg6
);
1544 sim_engine_halt (sd
, current_cpu
, NULL
, pc
, sim_stopped
,
1548 else if (fd
!= (USI
) -1)
1555 /* A non-aligned argument is allowed for files. */
1556 USI newlen
= (len
+ 8191) & ~8191;
1558 /* We only support read, which we should already have
1559 checked. Check again anyway. */
1560 if (prot
!= TARGET_PROT_READ
)
1564 = create_map (sd
, ¤t_cpu
->highest_mmapped_page
, addr
,
1567 if (newaddr
>= (USI
) -8191)
1570 retval
= -cb_host_to_target_errno (cb
, -(SI
) newaddr
);
1574 /* Find the current position in the file. */
1575 s
.func
= TARGET_SYS_lseek
;
1579 if (cb_syscall (cb
, &s
) != CB_RC_OK
)
1586 /* Use the standard read callback to read in "len"
1588 s
.func
= TARGET_SYS_read
;
1592 if (cb_syscall (cb
, &s
) != CB_RC_OK
)
1595 if ((USI
) s
.result
!= len
)
1598 /* After reading, we need to go back to the previous
1599 position in the file. */
1600 s
.func
= TARGET_SYS_lseek
;
1604 if (cb_syscall (cb
, &s
) != CB_RC_OK
)
1606 if (pos
!= (USI
) s
.result
)
1614 = create_map (sd
, ¤t_cpu
->highest_mmapped_page
, addr
, len
);
1616 if (newaddr
>= (USI
) -8191)
1617 retval
= -cb_host_to_target_errno (cb
, -(SI
) newaddr
);
1624 case TARGET_SYS_mprotect
:
1626 /* We only cover the case of linuxthreads mprotecting out its
1627 stack guard page. */
1632 if ((addr
& 8191) != 0
1634 || prot
!= TARGET_PROT_NONE
1635 || !is_mapped (sd
, ¤t_cpu
->highest_mmapped_page
, addr
,
1638 sim_io_eprintf (sd
, "Unimplemented mprotect call "
1639 "(0x%lx, 0x%lx, 0x%lx)\n",
1640 (unsigned long) arg1
,
1641 (unsigned long) arg2
,
1642 (unsigned long) arg3
);
1643 sim_engine_halt (sd
, current_cpu
, NULL
, pc
, sim_stopped
,
1648 /* FIXME: We should account for pages like this that are
1649 "mprotected out". For now, we just tell the simulator
1650 core to remove that page from its map. */
1651 sim_core_detach (sd
, NULL
, 0, 0, addr
);
1656 case TARGET_SYS_ioctl
:
1658 /* We support only a very limited functionality: checking
1659 stdout with TCGETS to perform the isatty function. The
1660 TCGETS ioctl isn't actually performed or the result used by
1661 an isatty () caller in a "hello, world" program; only the
1662 return value is then used. Maybe we shouldn't care about
1663 the environment of the simulator regarding isatty, but
1664 that's been working before, in the xsim simulator. */
1665 if (arg2
== TARGET_TCGETS
&& arg1
== 1)
1666 retval
= isatty (1) ? 0 : cb_host_to_target_errno (cb
, EINVAL
);
1668 retval
= -cb_host_to_target_errno (cb
, EINVAL
);
1672 case TARGET_SYS_munmap
:
1677 = unmap_pages (sd
, ¤t_cpu
->highest_mmapped_page
, addr
,
1679 retval
= result
!= 0 ? -cb_host_to_target_errno (cb
, result
) : 0;
1683 case TARGET_SYS_wait4
:
1691 /* FIXME: We're not properly implementing __WCLONE, and we
1692 don't really need the special casing so we might as well
1693 make this general. */
1694 if ((!(pid
== (USI
) -1
1695 && options
== (TARGET___WCLONE
| TARGET_WNOHANG
)
1698 && (options
== TARGET___WCLONE
1699 || options
== TARGET___WALL
)))
1701 || current_cpu
->thread_data
== NULL
)
1703 sim_io_eprintf (sd
, "Unimplemented wait4 call "
1704 "(0x%lx, 0x%lx, 0x%lx, 0x%lx)\n",
1705 (unsigned long) arg1
,
1706 (unsigned long) arg2
,
1707 (unsigned long) arg3
,
1708 (unsigned long) arg4
);
1709 sim_engine_halt (sd
, current_cpu
, NULL
, pc
, sim_stopped
,
1714 if (pid
== (USI
) -1)
1715 for (i
= 1; i
< SIM_TARGET_MAX_THREADS
; i
++)
1717 if (current_cpu
->thread_data
[threadno
].threadid
1718 == current_cpu
->thread_data
[i
].parent_threadid
1719 && current_cpu
->thread_data
[i
].threadid
!= 0
1720 && current_cpu
->thread_data
[i
].cpu_context
== NULL
)
1722 /* A zombied child. Get the exit value and clear the
1723 zombied entry so it will be reused. */
1724 sim_core_write_unaligned_4 (current_cpu
, pc
, 0, saddr
,
1726 ->thread_data
[i
].exitval
);
1728 = current_cpu
->thread_data
[i
].threadid
+ TARGET_PID
;
1729 memset (¤t_cpu
->thread_data
[i
], 0,
1730 sizeof (current_cpu
->thread_data
[i
]));
1736 /* We're waiting for a specific PID. If we don't find
1737 it zombied on this run, rerun the syscall. */
1738 for (i
= 1; i
< SIM_TARGET_MAX_THREADS
; i
++)
1739 if (pid
== current_cpu
->thread_data
[i
].threadid
+ TARGET_PID
1740 && current_cpu
->thread_data
[i
].cpu_context
== NULL
)
1743 /* Get the exit value if the caller wants it. */
1744 sim_core_write_unaligned_4 (current_cpu
, pc
, 0,
1751 = current_cpu
->thread_data
[i
].threadid
+ TARGET_PID
;
1752 memset (¤t_cpu
->thread_data
[i
], 0,
1753 sizeof (current_cpu
->thread_data
[i
]));
1758 sim_pc_set (current_cpu
, pc
);
1761 retval
= -cb_host_to_target_errno (cb
, ECHILD
);
1766 case TARGET_SYS_rt_sigaction
:
1774 __sighandler_t sa_handler;
1775 unsigned long sa_flags;
1776 void (*sa_restorer)(void);
1782 sim_core_write_unaligned_4 (current_cpu
, pc
, 0, old_sa
+ 0,
1783 current_cpu
->sighandler
[signum
]);
1784 sim_core_write_unaligned_4 (current_cpu
, pc
, 0, arg3
+ 4, 0);
1785 sim_core_write_unaligned_4 (current_cpu
, pc
, 0, arg3
+ 8, 0);
1787 /* We'll assume _NSIG_WORDS is 2 for the kernel. */
1788 sim_core_write_unaligned_4 (current_cpu
, pc
, 0, arg3
+ 12, 0);
1789 sim_core_write_unaligned_4 (current_cpu
, pc
, 0, arg3
+ 16, 0);
1794 = sim_core_read_unaligned_4 (current_cpu
, pc
, 0, new_sa
);
1796 = sim_core_read_unaligned_4 (current_cpu
, pc
, 0, new_sa
+ 4);
1798 = sim_core_read_unaligned_4 (current_cpu
, pc
, 0, new_sa
+ 8);
1800 = sim_core_read_unaligned_4 (current_cpu
, pc
, 0, new_sa
+ 12);
1802 = sim_core_read_unaligned_4 (current_cpu
, pc
, 0, new_sa
+ 16);
1804 /* We won't interrupt a syscall so we won't restart it,
1805 but a signal(2) call ends up syscalling rt_sigaction
1806 with this flag, so we have to handle it. The
1807 sa_restorer field contains garbage when not
1808 TARGET_SA_RESTORER, so don't look at it. For the
1809 time being, we don't nest sighandlers, so we
1810 ignore the sa_mask, which simplifies things. */
1812 && sa_flags
!= TARGET_SA_RESTART
1813 && sa_flags
!= (TARGET_SA_RESTART
|TARGET_SA_SIGINFO
))
1816 sim_io_eprintf (sd
, "Unimplemented rt_sigaction "
1818 "0x%lx: [0x%x, 0x%x, 0x%x, "
1821 (unsigned long) arg1
,
1822 (unsigned long) arg2
,
1823 sa_handler
, sa_flags
, sa_restorer
,
1824 sa_mask_low
, sa_mask_high
,
1825 (unsigned long) arg3
);
1826 sim_engine_halt (sd
, current_cpu
, NULL
, pc
, sim_stopped
,
1830 current_cpu
->sighandler
[signum
] = sa_handler
;
1832 /* Because we may have unblocked signals, one may now be
1833 pending, if there are threads, that is. */
1834 if (current_cpu
->thread_data
)
1835 current_cpu
->thread_data
[threadno
].sigpending
= 1;
1841 case TARGET_SYS_mremap
:
1847 USI new_addr
= arg5
;
1850 if (new_len
== old_len
)
1851 /* The program and/or library is possibly confused but
1852 this is a valid call. Happens with ipps-1.40 on file
1855 else if (new_len
< old_len
)
1857 /* Shrinking is easy. */
1858 if (unmap_pages (sd
, ¤t_cpu
->highest_mmapped_page
,
1859 addr
+ new_len
, old_len
- new_len
) != 0)
1860 retval
= -cb_host_to_target_errno (cb
, EINVAL
);
1864 else if (! is_mapped (sd
, ¤t_cpu
->highest_mmapped_page
,
1865 addr
+ old_len
, new_len
- old_len
))
1867 /* If the extension isn't mapped, we can just add it. */
1869 = create_map (sd
, ¤t_cpu
->highest_mmapped_page
,
1870 addr
+ old_len
, new_len
- old_len
);
1872 if (mapped_addr
> (USI
) -8192)
1873 retval
= -cb_host_to_target_errno (cb
, -(SI
) mapped_addr
);
1877 else if (flags
& TARGET_MREMAP_MAYMOVE
)
1879 /* Create a whole new map and copy the contents
1880 block-by-block there. We ignore the new_addr argument
1883 USI prev_addr
= addr
;
1884 USI prev_len
= old_len
;
1887 = create_map (sd
, ¤t_cpu
->highest_mmapped_page
,
1890 if (mapped_addr
> (USI
) -8192)
1892 retval
= -cb_host_to_target_errno (cb
, -(SI
) new_addr
);
1896 retval
= mapped_addr
;
1899 old_len
-= 8192, mapped_addr
+= 8192, addr
+= 8192)
1901 if (sim_core_read_buffer (sd
, current_cpu
, read_map
, buf
,
1903 || sim_core_write_buffer (sd
, current_cpu
, 0, buf
,
1904 mapped_addr
, 8192) != 8192)
1908 if (unmap_pages (sd
, ¤t_cpu
->highest_mmapped_page
,
1909 prev_addr
, prev_len
) != 0)
1913 retval
= -cb_host_to_target_errno (cb
, -ENOMEM
);
1917 case TARGET_SYS_poll
:
1919 int npollfds
= arg2
;
1935 /* Check that this is the expected poll call from
1936 linuxthreads/manager.c; we don't support anything else.
1937 Remember, fd == 0 isn't supported. */
1939 || ((fd
= sim_core_read_unaligned_4 (current_cpu
, pc
,
1941 || ((events
= sim_core_read_unaligned_2 (current_cpu
, pc
,
1944 || ((cb
->fstat
) (cb
, fd
, &buf
) != 0
1945 || (buf
.st_mode
& S_IFIFO
) == 0)
1946 || current_cpu
->thread_data
== NULL
)
1948 sim_io_eprintf (sd
, "Unimplemented poll syscall "
1949 "(0x%lx: [0x%x, 0x%x, x], 0x%lx, 0x%lx)\n",
1950 (unsigned long) arg1
, fd
, events
,
1951 (unsigned long) arg2
, (unsigned long) arg3
);
1952 sim_engine_halt (sd
, current_cpu
, NULL
, pc
, sim_stopped
, SIM_SIGILL
);
1958 /* Iterate over threads; find a marker that a writer is
1959 sleeping, waiting for a reader. */
1960 for (i
= 0; i
< SIM_TARGET_MAX_THREADS
; i
++)
1961 if (current_cpu
->thread_data
[i
].cpu_context
!= NULL
1962 && current_cpu
->thread_data
[i
].pipe_read_fd
== fd
)
1964 revents
= TARGET_POLLIN
;
1969 /* Timeout decreases with whatever time passed between the
1970 last syscall and this. That's not exactly right for the
1971 first call, but it's close enough that it isn't
1972 worthwhile to complicate matters by making that a special
1975 -= (TARGET_TIME_MS (current_cpu
)
1976 - (current_cpu
->thread_data
[threadno
].last_execution
));
1978 /* Arrange to repeat this syscall until timeout or event,
1979 decreasing timeout at each iteration. */
1980 if (timeout
> 0 && revents
== 0)
1982 bfd_byte timeout_buf
[4];
1984 bfd_putl32 (timeout
, timeout_buf
);
1985 (*CPU_REG_STORE (current_cpu
)) (current_cpu
,
1986 H_GR_R12
, timeout_buf
, 4);
1987 sim_pc_set (current_cpu
, pc
);
1992 sim_core_write_unaligned_2 (current_cpu
, pc
, 0, ufds
+ 4 + 2,
1997 case TARGET_SYS_gettimeofday
:
2000 USI ts
= TARGET_TIME (current_cpu
);
2001 USI tms
= TARGET_TIME_MS (current_cpu
);
2003 /* First dword is seconds since TARGET_EPOCH. */
2004 sim_core_write_unaligned_4 (current_cpu
, pc
, 0, arg1
, ts
);
2006 /* Second dword is microseconds. */
2007 sim_core_write_unaligned_4 (current_cpu
, pc
, 0, arg1
+ 4,
2008 (tms
% 1000) * 1000);
2012 /* Time-zone info is always cleared. */
2013 sim_core_write_unaligned_4 (current_cpu
, pc
, 0, arg2
, 0);
2014 sim_core_write_unaligned_4 (current_cpu
, pc
, 0, arg2
+ 4, 0);
2019 case TARGET_SYS_llseek
:
2021 /* If it fits, tweak parameters to fit the "generic" 32-bit
2022 lseek and use that. */
2030 if (!((offs_hi
== 0 && offs_lo
>= 0)
2031 || (offs_hi
== -1 && offs_lo
< 0)))
2034 "Unimplemented llseek offset,"
2035 " fd %d: 0x%x:0x%x\n",
2036 fd
, (unsigned) arg2
, (unsigned) arg3
);
2037 sim_engine_halt (sd
, current_cpu
, NULL
, pc
, sim_stopped
,
2041 s
.func
= TARGET_SYS_lseek
;
2044 if (cb_syscall (cb
, &s
) != CB_RC_OK
)
2046 sim_io_eprintf (sd
, "Break 13: invalid %d? Returned %ld\n", callnum
,
2048 sim_engine_halt (sd
, current_cpu
, NULL
, pc
, sim_stopped
, SIM_SIGILL
);
2051 retval
= -s
.errcode
;
2054 sim_core_write_unaligned_4 (current_cpu
, pc
, 0, resultp
,
2056 sim_core_write_unaligned_4 (current_cpu
, pc
, 0, resultp
+ 4,
2057 s
.result
< 0 ? -1 : 0);
2062 /* This one does have a generic callback function, but at the time
2063 of this writing, cb_syscall does not have code for it, and we
2064 need target-specific code for the threads implementation
2066 case TARGET_SYS_kill
:
2073 /* At kill(2), glibc sets signal masks such that the thread
2074 machinery is initialized. Still, there is and was only
2076 if (current_cpu
->max_threadid
== 0)
2078 if (pid
!= TARGET_PID
)
2080 retval
= -cb_host_to_target_errno (cb
, EPERM
);
2084 /* FIXME: Signal infrastructure (target-to-sim mapping). */
2085 if (sig
== TARGET_SIGABRT
)
2086 /* A call "abort ()", i.e. "kill (getpid(), SIGABRT)" is
2087 the end-point for failing GCC test-cases. */
2088 sim_engine_halt (sd
, current_cpu
, NULL
, pc
, sim_stopped
,
2092 sim_io_eprintf (sd
, "Unimplemented signal: %d\n", sig
);
2093 sim_engine_halt (sd
, current_cpu
, NULL
, pc
, sim_stopped
,
2097 /* This will not be reached. */
2101 retval
= deliver_signal (current_cpu
, sig
, pid
);
2105 case TARGET_SYS_rt_sigprocmask
:
2112 if (how
!= TARGET_SIG_BLOCK
2113 && how
!= TARGET_SIG_SETMASK
2114 && how
!= TARGET_SIG_UNBLOCK
)
2116 sim_io_eprintf (sd
, "Unimplemented rt_sigprocmask syscall "
2117 "(0x%x, 0x%x, 0x%x)\n", arg1
, arg2
, arg3
);
2118 sim_engine_halt (sd
, current_cpu
, NULL
, pc
, sim_stopped
,
2127 = sim_core_read_unaligned_4 (current_cpu
, pc
, 0,
2130 = sim_core_read_unaligned_4 (current_cpu
, pc
, 0,
2133 /* The sigmask is kept in the per-thread data, so we may
2134 need to create the first one. */
2135 if (current_cpu
->thread_data
== NULL
)
2136 make_first_thread (current_cpu
);
2138 if (how
== TARGET_SIG_SETMASK
)
2139 for (i
= 0; i
< 64; i
++)
2140 current_cpu
->thread_data
[threadno
].sigdata
[i
].blocked
= 0;
2142 for (i
= 0; i
< 32; i
++)
2143 if ((set_low
& (1 << i
)))
2144 current_cpu
->thread_data
[threadno
].sigdata
[i
+ 1].blocked
2145 = (how
!= TARGET_SIG_UNBLOCK
);
2147 for (i
= 0; i
< 31; i
++)
2148 if ((set_high
& (1 << i
)))
2149 current_cpu
->thread_data
[threadno
].sigdata
[i
+ 33].blocked
2150 = (how
!= TARGET_SIG_UNBLOCK
);
2152 /* The mask changed, so a signal may be unblocked for
2154 current_cpu
->thread_data
[threadno
].sigpending
= 1;
2162 for (i
= 0; i
< 32; i
++)
2163 if (current_cpu
->thread_data
[threadno
]
2164 .sigdata
[i
+ 1].blocked
)
2166 for (i
= 0; i
< 31; i
++)
2167 if (current_cpu
->thread_data
[threadno
]
2168 .sigdata
[i
+ 33].blocked
)
2171 sim_core_write_unaligned_4 (current_cpu
, pc
, 0, oldsetp
+ 0, set_low
);
2172 sim_core_write_unaligned_4 (current_cpu
, pc
, 0, oldsetp
+ 4, set_high
);
2179 case TARGET_SYS_sigreturn
:
2183 int was_sigsuspended
;
2185 if (current_cpu
->thread_data
== NULL
2186 /* The CPU context is saved with the simulator data, not
2187 on the stack as in the real world. */
2188 || (current_cpu
->thread_data
[threadno
].cpu_context_atsignal
2191 sim_io_eprintf (sd
, "Invalid sigreturn syscall: no signal"
2193 "(0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx)\n",
2194 (unsigned long) arg1
,
2195 (unsigned long) arg2
,
2196 (unsigned long) arg3
,
2197 (unsigned long) arg4
,
2198 (unsigned long) arg5
,
2199 (unsigned long) arg6
);
2200 sim_engine_halt (sd
, current_cpu
, NULL
, pc
, sim_stopped
,
2205 = current_cpu
->thread_data
[threadno
].sigsuspended
;
2207 /* Restore the sigmask, either from the stack copy made when
2208 the sighandler was called, or from the saved state
2209 specifically for sigsuspend(2). */
2210 if (was_sigsuspended
)
2212 current_cpu
->thread_data
[threadno
].sigsuspended
= 0;
2213 for (i
= 0; i
< 64; i
++)
2214 current_cpu
->thread_data
[threadno
].sigdata
[i
].blocked
2215 = current_cpu
->thread_data
[threadno
]
2216 .sigdata
[i
].blocked_suspendsave
;
2224 (*CPU_REG_FETCH (current_cpu
)) (current_cpu
,
2225 H_GR_SP
, regbuf
, 4);
2226 sp
= bfd_getl32 (regbuf
);
2228 = sim_core_read_unaligned_4 (current_cpu
, pc
, 0, sp
);
2230 = sim_core_read_unaligned_4 (current_cpu
, pc
, 0, sp
+ 4);
2232 for (i
= 0; i
< 32; i
++)
2233 current_cpu
->thread_data
[threadno
].sigdata
[i
+ 1].blocked
2234 = (set_low
& (1 << i
)) != 0;
2235 for (i
= 0; i
< 31; i
++)
2236 current_cpu
->thread_data
[threadno
].sigdata
[i
+ 33].blocked
2237 = (set_high
& (1 << i
)) != 0;
2240 /* The mask changed, so a signal may be unblocked for
2242 current_cpu
->thread_data
[threadno
].sigpending
= 1;
2244 memcpy (¤t_cpu
->cpu_data_placeholder
,
2245 current_cpu
->thread_data
[threadno
].cpu_context_atsignal
,
2246 current_cpu
->thread_cpu_data_size
);
2247 free (current_cpu
->thread_data
[threadno
].cpu_context_atsignal
);
2248 current_cpu
->thread_data
[threadno
].cpu_context_atsignal
= NULL
;
2250 /* The return value must come from the saved R10. */
2251 (*CPU_REG_FETCH (current_cpu
)) (current_cpu
, H_GR_R10
, regbuf
, 4);
2252 retval
= bfd_getl32 (regbuf
);
2254 /* We must also break the "sigsuspension loop". */
2255 if (was_sigsuspended
)
2256 sim_pc_set (current_cpu
, sim_pc_get (current_cpu
) + 2);
2260 case TARGET_SYS_rt_sigsuspend
:
2267 sim_io_eprintf (sd
, "Unimplemented rt_sigsuspend syscall"
2268 " arguments (0x%lx, 0x%lx)\n",
2269 (unsigned long) arg1
, (unsigned long) arg2
);
2270 sim_engine_halt (sd
, current_cpu
, NULL
, pc
, sim_stopped
,
2274 /* Don't change the signal mask if we're already in
2275 sigsuspend state (i.e. this syscall is a rerun). */
2276 else if (!current_cpu
->thread_data
[threadno
].sigsuspended
)
2279 = sim_core_read_unaligned_4 (current_cpu
, pc
, 0,
2282 = sim_core_read_unaligned_4 (current_cpu
, pc
, 0,
2286 /* Save the current sigmask and insert the user-supplied
2288 for (i
= 0; i
< 32; i
++)
2290 current_cpu
->thread_data
[threadno
]
2291 .sigdata
[i
+ 1].blocked_suspendsave
2292 = current_cpu
->thread_data
[threadno
]
2293 .sigdata
[i
+ 1].blocked
;
2295 current_cpu
->thread_data
[threadno
]
2296 .sigdata
[i
+ 1].blocked
= (set_low
& (1 << i
)) != 0;
2298 for (i
= 0; i
< 31; i
++)
2300 current_cpu
->thread_data
[threadno
]
2301 .sigdata
[i
+ 33].blocked_suspendsave
2302 = current_cpu
->thread_data
[threadno
]
2303 .sigdata
[i
+ 33].blocked
;
2304 current_cpu
->thread_data
[threadno
]
2305 .sigdata
[i
+ 33].blocked
= (set_high
& (1 << i
)) != 0;
2308 current_cpu
->thread_data
[threadno
].sigsuspended
= 1;
2310 /* The mask changed, so a signal may be unblocked for
2312 current_cpu
->thread_data
[threadno
].sigpending
= 1;
2315 /* Because we don't use arg1 (newsetp) when this syscall is
2316 rerun, it doesn't matter that we overwrite it with the
2317 (constant) return value. */
2318 retval
= -cb_host_to_target_errno (cb
, EINTR
);
2319 sim_pc_set (current_cpu
, pc
);
2323 /* Add case labels here for other syscalls using the 32-bit
2324 "struct stat", provided they have a corresponding simulator
2325 function of course. */
2326 case TARGET_SYS_fstat
:
2328 /* As long as the infrastructure doesn't cache anything
2329 related to the stat mapping, this trick gets us a dual
2330 "struct stat"-type mapping in the least error-prone way. */
2331 const char *saved_map
= cb
->stat_map
;
2332 CB_TARGET_DEFS_MAP
*saved_syscall_map
= cb
->syscall_map
;
2334 cb
->syscall_map
= (CB_TARGET_DEFS_MAP
*) syscall_stat32_map
;
2335 cb
->stat_map
= stat32_map
;
2337 if (cb_syscall (cb
, &s
) != CB_RC_OK
)
2340 sim_engine_halt (sd
, current_cpu
, NULL
, pc
, sim_stopped
,
2343 retval
= s
.result
== -1 ? -s
.errcode
: s
.result
;
2345 cb
->stat_map
= saved_map
;
2346 cb
->syscall_map
= saved_syscall_map
;
2350 case TARGET_SYS_getcwd
:
2355 char *cwd
= xmalloc (MAXPATHLEN
);
2356 if (cwd
!= getcwd (cwd
, MAXPATHLEN
))
2359 /* FIXME: When and if we support chdir, we need something
2360 a bit more elaborate. */
2361 if (simulator_sysroot
[0] != '\0')
2364 retval
= -cb_host_to_target_errno (cb
, ERANGE
);
2365 if (strlen (cwd
) + 1 <= size
)
2367 retval
= strlen (cwd
) + 1;
2368 if (sim_core_write_buffer (sd
, current_cpu
, 0, cwd
,
2370 != (unsigned int) retval
)
2371 retval
= -cb_host_to_target_errno (cb
, EFAULT
);
2377 case TARGET_SYS_readlink
:
2382 char *pbuf
= xmalloc (MAXPATHLEN
);
2383 char *lbuf
= xmalloc (MAXPATHLEN
);
2384 char *lbuf_alloc
= lbuf
;
2389 if (sim_core_read_unaligned_1 (current_cpu
, pc
, 0, path
) == '/')
2391 strcpy (pbuf
, simulator_sysroot
);
2392 o
+= strlen (simulator_sysroot
);
2395 for (i
= 0; i
+ o
< MAXPATHLEN
; i
++)
2398 = sim_core_read_unaligned_1 (current_cpu
, pc
, 0, path
+ i
);
2399 if (pbuf
[i
+ o
] == 0)
2403 if (i
+ o
== MAXPATHLEN
)
2405 retval
= -cb_host_to_target_errno (cb
, ENAMETOOLONG
);
2409 /* Intervene calls for certain files expected in the target
2410 proc file system. */
2411 if (strcmp (pbuf
+ strlen (simulator_sysroot
),
2412 "/proc/" XSTRING (TARGET_PID
) "/exe") == 0)
2415 = (STATE_PROG_ARGV (sd
) != NULL
2416 ? *STATE_PROG_ARGV (sd
) : NULL
);
2418 if (argv0
== NULL
|| *argv0
== '.')
2420 sim_io_eprintf (sd
, "Unimplemented readlink syscall "
2421 "(0x%lx: [\"%s\"], 0x%lx)\n",
2422 (unsigned long) arg1
, pbuf
,
2423 (unsigned long) arg2
);
2424 sim_engine_halt (sd
, current_cpu
, NULL
, pc
, sim_stopped
,
2428 else if (*argv0
== '/')
2430 if (strncmp (simulator_sysroot
, argv0
,
2431 strlen (simulator_sysroot
)) == 0)
2432 argv0
+= strlen (simulator_sysroot
);
2434 strcpy (lbuf
, argv0
);
2435 nchars
= strlen (argv0
) + 1;
2439 if (getcwd (lbuf
, MAXPATHLEN
) != NULL
2440 && strlen (lbuf
) + 2 + strlen (argv0
) < MAXPATHLEN
)
2442 if (strncmp (simulator_sysroot
, lbuf
,
2443 strlen (simulator_sysroot
)) == 0)
2444 lbuf
+= strlen (simulator_sysroot
);
2447 strcat (lbuf
, argv0
);
2448 nchars
= strlen (lbuf
) + 1;
2455 nchars
= readlink (pbuf
, lbuf
, MAXPATHLEN
);
2457 /* We trust that the readlink result returns a *relative*
2458 link, or one already adjusted for the file-path-prefix.
2459 (We can't generally tell the difference, so we go with
2460 the easiest decision; no adjustment.) */
2464 retval
= -cb_host_to_target_errno (cb
, errno
);
2468 if (bufsiz
< nchars
)
2471 if (sim_core_write_buffer (sd
, current_cpu
, write_map
, lbuf
,
2472 buf
, nchars
) != (unsigned int) nchars
)
2473 retval
= -cb_host_to_target_errno (cb
, EFAULT
);
2482 case TARGET_SYS_sched_getscheduler
:
2486 /* FIXME: Search (other) existing threads. */
2487 if (pid
!= 0 && pid
!= TARGET_PID
)
2488 retval
= -cb_host_to_target_errno (cb
, ESRCH
);
2490 retval
= TARGET_SCHED_OTHER
;
2494 case TARGET_SYS_sched_getparam
:
2500 struct sched_param {
2504 if (pid
!= 0 && pid
!= TARGET_PID
)
2505 retval
= -cb_host_to_target_errno (cb
, ESRCH
);
2508 /* FIXME: Save scheduler setting before threads are
2510 sim_core_write_unaligned_4 (current_cpu
, pc
, 0, paramp
,
2511 current_cpu
->thread_data
!= NULL
2513 ->thread_data
[threadno
]
2521 case TARGET_SYS_sched_setparam
:
2526 if ((pid
!= 0 && pid
!= TARGET_PID
)
2527 || sim_core_read_unaligned_4 (current_cpu
, pc
, 0,
2529 retval
= -cb_host_to_target_errno (cb
, EINVAL
);
2535 case TARGET_SYS_sched_setscheduler
:
2541 if ((pid
!= 0 && pid
!= TARGET_PID
)
2542 || policy
!= TARGET_SCHED_OTHER
2543 || sim_core_read_unaligned_4 (current_cpu
, pc
, 0,
2545 retval
= -cb_host_to_target_errno (cb
, EINVAL
);
2547 /* FIXME: Save scheduler setting to be read in later
2548 sched_getparam calls. */
2553 case TARGET_SYS_sched_yield
:
2554 /* We reschedule to the next thread after a syscall anyway, so
2555 we don't have to do anything here than to set the return
2560 case TARGET_SYS_sched_get_priority_min
:
2561 case TARGET_SYS_sched_get_priority_max
:
2563 retval
= -cb_host_to_target_errno (cb
, EINVAL
);
2568 case TARGET_SYS_ugetrlimit
:
2570 unsigned int curlim
, maxlim
;
2571 if (arg1
!= TARGET_RLIMIT_STACK
&& arg1
!= TARGET_RLIMIT_NOFILE
)
2573 retval
= -cb_host_to_target_errno (cb
, EINVAL
);
2579 unsigned long rlim_cur;
2580 unsigned long rlim_max;
2582 if (arg1
== TARGET_RLIMIT_NOFILE
)
2584 /* Sadly a very low limit. Better not lie, though. */
2585 maxlim
= curlim
= MAX_CALLBACK_FDS
;
2587 else /* arg1 == TARGET_RLIMIT_STACK */
2589 maxlim
= 0xffffffff;
2592 sim_core_write_unaligned_4 (current_cpu
, pc
, 0, arg2
, curlim
);
2593 sim_core_write_unaligned_4 (current_cpu
, pc
, 0, arg2
+ 4, maxlim
);
2598 case TARGET_SYS_setrlimit
:
2599 if (arg1
!= TARGET_RLIMIT_STACK
)
2601 retval
= -cb_host_to_target_errno (cb
, EINVAL
);
2604 /* FIXME: Save values for future ugetrlimit calls. */
2608 /* Provide a very limited subset of the sysctl functions, and
2609 abort for the rest. */
2610 case TARGET_SYS__sysctl
:
2613 struct __sysctl_args {
2620 unsigned long __unused[4];
2622 SI name
= sim_core_read_unaligned_4 (current_cpu
, pc
, 0, arg1
);
2623 SI name0
= name
== 0
2624 ? 0 : sim_core_read_unaligned_4 (current_cpu
, pc
, 0, name
);
2625 SI name1
= name
== 0
2626 ? 0 : sim_core_read_unaligned_4 (current_cpu
, pc
, 0, name
+ 4);
2628 = sim_core_read_unaligned_4 (current_cpu
, pc
, 0, arg1
+ 4);
2630 = sim_core_read_unaligned_4 (current_cpu
, pc
, 0, arg1
+ 8);
2632 = sim_core_read_unaligned_4 (current_cpu
, pc
, 0, arg1
+ 12);
2633 SI oldlen
= oldlenp
== 0
2634 ? 0 : sim_core_read_unaligned_4 (current_cpu
, pc
, 0, oldlenp
);
2636 = sim_core_read_unaligned_4 (current_cpu
, pc
, 0, arg1
+ 16);
2638 = sim_core_read_unaligned_4 (current_cpu
, pc
, 0, arg1
+ 20);
2640 if (name0
== TARGET_CTL_KERN
&& name1
== TARGET_CTL_KERN_VERSION
)
2642 SI to_write
= oldlen
< (SI
) sizeof (TARGET_UTSNAME
)
2643 ? oldlen
: (SI
) sizeof (TARGET_UTSNAME
);
2645 sim_core_write_unaligned_4 (current_cpu
, pc
, 0, oldlenp
,
2646 sizeof (TARGET_UTSNAME
));
2648 if (sim_core_write_buffer (sd
, current_cpu
, write_map
,
2649 TARGET_UTSNAME
, oldval
,
2651 != (unsigned int) to_write
)
2652 retval
= -cb_host_to_target_errno (cb
, EFAULT
);
2658 sim_io_eprintf (sd
, "Unimplemented _sysctl syscall "
2659 "(0x%lx: [0x%lx, 0x%lx],"
2660 " 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx)\n",
2661 (unsigned long) name
,
2662 (unsigned long) name0
,
2663 (unsigned long) name1
,
2664 (unsigned long) nlen
,
2665 (unsigned long) oldval
,
2666 (unsigned long) oldlenp
,
2667 (unsigned long) newval
,
2668 (unsigned long) newlen
);
2669 sim_engine_halt (sd
, current_cpu
, NULL
, pc
, sim_stopped
,
2674 case TARGET_SYS_exit
:
2676 /* Here for all but the last thread. */
2679 = current_cpu
->thread_data
[threadno
].threadid
+ TARGET_PID
;
2681 = (current_cpu
->thread_data
[threadno
].parent_threadid
2683 int exitsig
= current_cpu
->thread_data
[threadno
].exitsig
;
2685 /* Any children are now all orphans. */
2686 for (i
= 0; i
< SIM_TARGET_MAX_THREADS
; i
++)
2687 if (current_cpu
->thread_data
[i
].parent_threadid
2688 == current_cpu
->thread_data
[threadno
].threadid
)
2689 /* Make getppid(2) return 1 for them, poor little ones. */
2690 current_cpu
->thread_data
[i
].parent_threadid
= -TARGET_PID
+ 1;
2692 /* Free the cpu context data. When the parent has received
2693 the exit status, we'll clear the entry too. */
2694 free (current_cpu
->thread_data
[threadno
].cpu_context
);
2695 current_cpu
->thread_data
[threadno
].cpu_context
= NULL
;
2696 current_cpu
->m1threads
--;
2699 sim_io_eprintf (sd
, "Thread %d exited with status %d\n",
2701 sim_engine_halt (sd
, current_cpu
, NULL
, pc
, sim_stopped
,
2705 /* Still, we may want to support non-zero exit values. */
2706 current_cpu
->thread_data
[threadno
].exitval
= arg1
<< 8;
2709 deliver_signal (current_cpu
, exitsig
, ppid
);
2713 case TARGET_SYS_clone
:
2715 int nthreads
= current_cpu
->m1threads
+ 1;
2716 void *thread_cpu_data
;
2717 bfd_byte old_sp_buf
[4];
2719 const bfd_byte zeros
[4] = { 0, 0, 0, 0 };
2722 /* That's right, the syscall clone arguments are reversed
2723 compared to sys_clone notes in clone(2) and compared to
2724 other Linux ports (i.e. it's the same order as in the
2725 clone(2) libcall). */
2729 if (nthreads
== SIM_TARGET_MAX_THREADS
)
2731 retval
= -cb_host_to_target_errno (cb
, EAGAIN
);
2735 /* FIXME: Implement the low byte. */
2736 if ((flags
& ~TARGET_CSIGNAL
) !=
2739 | TARGET_CLONE_FILES
2740 | TARGET_CLONE_SIGHAND
)
2744 "Unimplemented clone syscall (0x%lx, 0x%lx)\n",
2745 (unsigned long) arg1
, (unsigned long) arg2
);
2746 sim_engine_halt (sd
, current_cpu
, NULL
, pc
, sim_stopped
,
2750 if (current_cpu
->thread_data
== NULL
)
2751 make_first_thread (current_cpu
);
2753 /* The created thread will get the new SP and a cleared R10.
2754 Since it's created out of a copy of the old thread and we
2755 don't have a set-register-function that just take the
2756 cpu_data as a parameter, we set the childs values first,
2757 and write back or overwrite them in the parent after the
2759 (*CPU_REG_FETCH (current_cpu
)) (current_cpu
,
2760 H_GR_SP
, old_sp_buf
, 4);
2761 bfd_putl32 (newsp
, sp_buf
);
2762 (*CPU_REG_STORE (current_cpu
)) (current_cpu
,
2763 H_GR_SP
, sp_buf
, 4);
2764 (*CPU_REG_STORE (current_cpu
)) (current_cpu
,
2765 H_GR_R10
, (bfd_byte
*) zeros
, 4);
2768 ->make_thread_cpu_data
) (current_cpu
,
2769 ¤t_cpu
->cpu_data_placeholder
);
2770 (*CPU_REG_STORE (current_cpu
)) (current_cpu
,
2771 H_GR_SP
, old_sp_buf
, 4);
2773 retval
= ++current_cpu
->max_threadid
+ TARGET_PID
;
2775 /* Find an unused slot. After a few threads have been created
2776 and exited, the array is expected to be a bit fragmented.
2777 We don't reuse the first entry, though, that of the
2779 for (i
= 1; i
< SIM_TARGET_MAX_THREADS
; i
++)
2780 if (current_cpu
->thread_data
[i
].cpu_context
== NULL
2781 /* Don't reuse a zombied entry. */
2782 && current_cpu
->thread_data
[i
].threadid
== 0)
2785 memcpy (¤t_cpu
->thread_data
[i
],
2786 ¤t_cpu
->thread_data
[threadno
],
2787 sizeof (current_cpu
->thread_data
[i
]));
2788 current_cpu
->thread_data
[i
].cpu_context
= thread_cpu_data
;
2789 current_cpu
->thread_data
[i
].cpu_context_atsignal
= NULL
;
2790 current_cpu
->thread_data
[i
].threadid
= current_cpu
->max_threadid
;
2791 current_cpu
->thread_data
[i
].parent_threadid
2792 = current_cpu
->thread_data
[threadno
].threadid
;
2793 current_cpu
->thread_data
[i
].pipe_read_fd
= 0;
2794 current_cpu
->thread_data
[i
].pipe_write_fd
= 0;
2795 current_cpu
->thread_data
[i
].at_syscall
= 0;
2796 current_cpu
->thread_data
[i
].sigpending
= 0;
2797 current_cpu
->thread_data
[i
].sigsuspended
= 0;
2798 current_cpu
->thread_data
[i
].exitsig
= flags
& TARGET_CSIGNAL
;
2799 current_cpu
->m1threads
= nthreads
;
2803 /* Better watch these in case they do something necessary. */
2804 case TARGET_SYS_socketcall
:
2805 retval
= -cb_host_to_target_errno (cb
, ENOSYS
);
2808 unimplemented_syscall
:
2810 sim_io_eprintf (sd
, "Unimplemented syscall: %d "
2811 "(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n", callnum
,
2812 arg1
, arg2
, arg3
, arg4
, arg5
, arg6
);
2813 sim_engine_halt (sd
, current_cpu
, NULL
, pc
, sim_stopped
,
2818 /* A system call is a rescheduling point. For the time being, we don't
2819 reschedule anywhere else. */
2820 if (current_cpu
->m1threads
!= 0
2821 /* We need to schedule off from an exiting thread that is the
2823 || (current_cpu
->thread_data
!= NULL
2824 && current_cpu
->thread_data
[threadno
].cpu_context
== NULL
))
2826 bfd_byte retval_buf
[4];
2828 current_cpu
->thread_data
[threadno
].last_execution
2829 = TARGET_TIME_MS (current_cpu
);
2830 bfd_putl32 (retval
, retval_buf
);
2831 (*CPU_REG_STORE (current_cpu
)) (current_cpu
, H_GR_R10
, retval_buf
, 4);
2833 current_cpu
->thread_data
[threadno
].at_syscall
= 1;
2834 reschedule (current_cpu
);
2836 (*CPU_REG_FETCH (current_cpu
)) (current_cpu
, H_GR_R10
, retval_buf
, 4);
2837 retval
= bfd_getl32 (retval_buf
);
2843 /* Callback from simulator write saying that the pipe at (reader, writer)
2844 is now non-empty (so the writer should wait until the pipe is empty, at
2845 least not write to this or any other pipe). Simplest is to just wait
2846 until the pipe is empty. */
2849 cris_pipe_nonempty (host_callback
*cb ATTRIBUTE_UNUSED
,
2850 int reader
, int writer
)
2852 SIM_CPU
*cpu
= current_cpu_for_cb_callback
;
2853 const bfd_byte zeros
[4] = { 0, 0, 0, 0 };
2855 /* It's the current thread: we just have to re-run the current
2856 syscall instruction (presumably "break 13") and change the syscall
2857 to the special simulator-wait code. Oh, and set a marker that
2858 we're waiting, so we can disambiguate the special call from a
2861 This function may be called multiple times between cris_pipe_empty,
2862 but we must avoid e.g. decreasing PC every time. Check fd markers
2864 if (cpu
->thread_data
== NULL
)
2866 sim_io_eprintf (CPU_STATE (cpu
),
2867 "Terminating simulation due to writing pipe rd:wr %d:%d"
2868 " from one single thread\n", reader
, writer
);
2869 sim_engine_halt (CPU_STATE (cpu
), cpu
,
2870 NULL
, sim_pc_get (cpu
), sim_stopped
, SIM_SIGILL
);
2872 else if (cpu
->thread_data
[cpu
->threadno
].pipe_write_fd
== 0)
2874 cpu
->thread_data
[cpu
->threadno
].pipe_write_fd
= writer
;
2875 cpu
->thread_data
[cpu
->threadno
].pipe_read_fd
= reader
;
2876 /* FIXME: We really shouldn't change registers other than R10 in
2877 syscalls (like R9), here or elsewhere. */
2878 (*CPU_REG_STORE (cpu
)) (cpu
, H_GR_R9
, (bfd_byte
*) zeros
, 4);
2879 sim_pc_set (cpu
, sim_pc_get (cpu
) - 2);
2883 /* Callback from simulator close or read call saying that the pipe at
2884 (reader, writer) is now empty (so the writer can write again, perhaps
2885 leave a waiting state). If there are bytes remaining, they couldn't be
2886 consumed (perhaps due to the pipe closing). */
2889 cris_pipe_empty (host_callback
*cb
,
2890 int reader ATTRIBUTE_UNUSED
,
2894 SIM_CPU
*cpu
= current_cpu_for_cb_callback
;
2895 bfd_byte r10_buf
[4];
2896 int remaining
= cb
->pipe_buffer
[writer
].size
;
2898 /* We need to find the thread that waits for this pipe. */
2899 for (i
= 0; i
< SIM_TARGET_MAX_THREADS
; i
++)
2900 if (cpu
->thread_data
[i
].cpu_context
2901 && cpu
->thread_data
[i
].pipe_write_fd
== writer
)
2904 /* Temporarily switch to this cpu context, so we can change the
2905 PC by ordinary calls. */
2907 memcpy (cpu
->thread_data
[cpu
->threadno
].cpu_context
,
2908 &cpu
->cpu_data_placeholder
,
2909 cpu
->thread_cpu_data_size
);
2910 memcpy (&cpu
->cpu_data_placeholder
,
2911 cpu
->thread_data
[i
].cpu_context
,
2912 cpu
->thread_cpu_data_size
);
2914 /* The return value is supposed to contain the number of written
2915 bytes, which is the number of bytes requested and returned at
2916 the write call. We subtract the remaining bytes from that,
2917 but making sure we still get a positive number.
2918 The return value may also be a negative number; an error
2919 value. We cover this case by comparing against remaining,
2920 which is always >= 0. */
2921 (*CPU_REG_FETCH (cpu
)) (cpu
, H_GR_R10
, r10_buf
, 4);
2922 retval
= (int) bfd_getl_signed_32 (r10_buf
);
2923 if (retval
>= remaining
)
2924 bfd_putl32 (retval
- remaining
, r10_buf
);
2925 (*CPU_REG_STORE (cpu
)) (cpu
, H_GR_R10
, r10_buf
, 4);
2927 sim_pc_set (cpu
, sim_pc_get (cpu
) + 2);
2928 memcpy (cpu
->thread_data
[i
].cpu_context
,
2929 &cpu
->cpu_data_placeholder
,
2930 cpu
->thread_cpu_data_size
);
2931 memcpy (&cpu
->cpu_data_placeholder
,
2932 cpu
->thread_data
[cpu
->threadno
].cpu_context
,
2933 cpu
->thread_cpu_data_size
);
2934 cpu
->thread_data
[i
].pipe_read_fd
= 0;
2935 cpu
->thread_data
[i
].pipe_write_fd
= 0;
2942 /* We have a simulator-specific notion of time. See TARGET_TIME. */
2945 cris_time (host_callback
*cb ATTRIBUTE_UNUSED
, long *t
)
2947 long retval
= TARGET_TIME (current_cpu_for_cb_callback
);
2953 /* Set target-specific callback data. */
2956 cris_set_callbacks (host_callback
*cb
)
2958 /* Yeargh, have to cast away constness to avoid warnings. */
2959 cb
->syscall_map
= (CB_TARGET_DEFS_MAP
*) syscall_map
;
2960 cb
->errno_map
= (CB_TARGET_DEFS_MAP
*) errno_map
;
2962 /* The kernel stat64 layout. If we see a file > 2G, the "long"
2963 parameter to cb_store_target_endian will make st_size negative.
2964 Similarly for st_ino. FIXME: Find a 64-bit type, and use it
2965 *unsigned*, and/or add syntax for signed-ness. */
2966 cb
->stat_map
= stat_map
;
2967 cb
->open_map
= (CB_TARGET_DEFS_MAP
*) open_map
;
2968 cb
->pipe_nonempty
= cris_pipe_nonempty
;
2969 cb
->pipe_empty
= cris_pipe_empty
;
2970 cb
->time
= cris_time
;
2973 /* Process an address exception. */
2976 cris_core_signal (SIM_DESC sd
, SIM_CPU
*current_cpu
, sim_cia cia
,
2977 unsigned int map
, int nr_bytes
, address_word addr
,
2978 transfer_type transfer
, sim_core_signals sig
)
2980 sim_core_signal (sd
, current_cpu
, cia
, map
, nr_bytes
, addr
,