1a1ba9ba4Schristos /* Simulator for Analog Devices Blackfin processors.
2a1ba9ba4Schristos
3*184b2d41Schristos Copyright (C) 2005-2020 Free Software Foundation, Inc.
4a1ba9ba4Schristos Contributed by Analog Devices, Inc.
5a1ba9ba4Schristos
6a1ba9ba4Schristos This file is part of simulators.
7a1ba9ba4Schristos
8a1ba9ba4Schristos This program is free software; you can redistribute it and/or modify
9a1ba9ba4Schristos it under the terms of the GNU General Public License as published by
10a1ba9ba4Schristos the Free Software Foundation; either version 3 of the License, or
11a1ba9ba4Schristos (at your option) any later version.
12a1ba9ba4Schristos
13a1ba9ba4Schristos This program is distributed in the hope that it will be useful,
14a1ba9ba4Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of
15a1ba9ba4Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16a1ba9ba4Schristos GNU General Public License for more details.
17a1ba9ba4Schristos
18a1ba9ba4Schristos You should have received a copy of the GNU General Public License
19a1ba9ba4Schristos along with this program. If not, see <http://www.gnu.org/licenses/>. */
20a1ba9ba4Schristos
21a1ba9ba4Schristos #include "config.h"
22a1ba9ba4Schristos
23a1ba9ba4Schristos #include <stdio.h>
24a1ba9ba4Schristos #include <stdlib.h>
25a1ba9ba4Schristos #include <string.h>
26a1ba9ba4Schristos #include <signal.h>
27a1ba9ba4Schristos #include <errno.h>
28a1ba9ba4Schristos #include <fcntl.h>
29a1ba9ba4Schristos #include <unistd.h>
30a1ba9ba4Schristos #include <sys/time.h>
31a1ba9ba4Schristos
32a1ba9ba4Schristos #include "gdb/callback.h"
33a1ba9ba4Schristos #include "gdb/signals.h"
34a1ba9ba4Schristos #include "sim-main.h"
35a1ba9ba4Schristos #include "sim-syscall.h"
36a1ba9ba4Schristos #include "sim-hw.h"
37a1ba9ba4Schristos
38a1ba9ba4Schristos #include "targ-vals.h"
39a1ba9ba4Schristos
40a1ba9ba4Schristos /* The numbers here do not matter. They just need to be unique. They also
41a1ba9ba4Schristos need not be static across releases -- they're used internally only. The
42a1ba9ba4Schristos mapping from the Linux ABI to the CB values is in linux-targ-map.h. */
43a1ba9ba4Schristos #define CB_SYS_ioctl 201
44a1ba9ba4Schristos #define CB_SYS_mmap2 202
45a1ba9ba4Schristos #define CB_SYS_munmap 203
46a1ba9ba4Schristos #define CB_SYS_dup2 204
47a1ba9ba4Schristos #define CB_SYS_getuid 205
48a1ba9ba4Schristos #define CB_SYS_getuid32 206
49a1ba9ba4Schristos #define CB_SYS_getgid 207
50a1ba9ba4Schristos #define CB_SYS_getgid32 208
51a1ba9ba4Schristos #define CB_SYS_setuid 209
52a1ba9ba4Schristos #define CB_SYS_setuid32 210
53a1ba9ba4Schristos #define CB_SYS_setgid 211
54a1ba9ba4Schristos #define CB_SYS_setgid32 212
55a1ba9ba4Schristos #define CB_SYS_pread 213
56a1ba9ba4Schristos #define CB_SYS__llseek 214
57a1ba9ba4Schristos #define CB_SYS_getcwd 215
58a1ba9ba4Schristos #define CB_SYS_stat64 216
59a1ba9ba4Schristos #define CB_SYS_lstat64 217
60a1ba9ba4Schristos #define CB_SYS_fstat64 218
61a1ba9ba4Schristos #define CB_SYS_ftruncate64 219
62a1ba9ba4Schristos #define CB_SYS_gettimeofday 220
63a1ba9ba4Schristos #define CB_SYS_access 221
64a1ba9ba4Schristos #include "linux-targ-map.h"
65a1ba9ba4Schristos #include "linux-fixed-code.h"
66a1ba9ba4Schristos
67a1ba9ba4Schristos #include "elf/common.h"
68a1ba9ba4Schristos #include "elf/external.h"
69a1ba9ba4Schristos #include "elf/internal.h"
70a1ba9ba4Schristos #include "elf/bfin.h"
71a1ba9ba4Schristos #include "elf-bfd.h"
72a1ba9ba4Schristos
73a1ba9ba4Schristos #include "dv-bfin_cec.h"
74a1ba9ba4Schristos #include "dv-bfin_mmu.h"
75a1ba9ba4Schristos
76a1ba9ba4Schristos #ifndef HAVE_GETUID
77a1ba9ba4Schristos # define getuid() 0
78a1ba9ba4Schristos #endif
79a1ba9ba4Schristos #ifndef HAVE_GETGID
80a1ba9ba4Schristos # define getgid() 0
81a1ba9ba4Schristos #endif
82a1ba9ba4Schristos #ifndef HAVE_GETEUID
83a1ba9ba4Schristos # define geteuid() 0
84a1ba9ba4Schristos #endif
85a1ba9ba4Schristos #ifndef HAVE_GETEGID
86a1ba9ba4Schristos # define getegid() 0
87a1ba9ba4Schristos #endif
88a1ba9ba4Schristos #ifndef HAVE_SETUID
89a1ba9ba4Schristos # define setuid(uid) -1
90a1ba9ba4Schristos #endif
91a1ba9ba4Schristos #ifndef HAVE_SETGID
92a1ba9ba4Schristos # define setgid(gid) -1
93a1ba9ba4Schristos #endif
94a1ba9ba4Schristos
95a1ba9ba4Schristos static const char cb_linux_stat_map_32[] =
96a1ba9ba4Schristos /* Linux kernel 32bit layout: */
97a1ba9ba4Schristos "st_dev,2:space,2:st_ino,4:st_mode,2:st_nlink,2:st_uid,2:st_gid,2:st_rdev,2:"
98a1ba9ba4Schristos "space,2:st_size,4:st_blksize,4:st_blocks,4:st_atime,4:st_atimensec,4:"
99a1ba9ba4Schristos "st_mtime,4:st_mtimensec,4:st_ctime,4:st_ctimensec,4:space,4:space,4";
100a1ba9ba4Schristos /* uClibc public ABI 32bit layout:
101a1ba9ba4Schristos "st_dev,8:space,2:space,2:st_ino,4:st_mode,4:st_nlink,4:st_uid,4:st_gid,4:"
102a1ba9ba4Schristos "st_rdev,8:space,2:space,2:st_size,4:st_blksiez,4:st_blocks,4:st_atime,4:"
103a1ba9ba4Schristos "st_atimensec,4:st_mtime,4:st_mtimensec,4:st_ctime,4:st_ctimensec,4:space,4:"
104a1ba9ba4Schristos "space,4"; */
105a1ba9ba4Schristos static const char cb_linux_stat_map_64[] =
106a1ba9ba4Schristos "st_dev,8:space,4:space,4:st_mode,4:st_nlink,4:st_uid,4:st_gid,4:st_rdev,8:"
107a1ba9ba4Schristos "space,4:st_size,8:st_blksize,4:st_blocks,8:st_atime,4:st_atimensec,4:"
108a1ba9ba4Schristos "st_mtime,4:st_mtimensec,4:st_ctime,4:st_ctimensec,4:st_ino,8";
109a1ba9ba4Schristos static const char cb_libgloss_stat_map_32[] =
110a1ba9ba4Schristos "st_dev,2:st_ino,2:st_mode,4:st_nlink,2:st_uid,2:st_gid,2:st_rdev,2:"
111a1ba9ba4Schristos "st_size,4:st_atime,4:space,4:st_mtime,4:space,4:st_ctime,4:"
112a1ba9ba4Schristos "space,4:st_blksize,4:st_blocks,4:space,8";
113a1ba9ba4Schristos static const char *stat_map_32, *stat_map_64;
114a1ba9ba4Schristos
115a1ba9ba4Schristos /* Simulate a monitor trap, put the result into r0 and errno into r1
116a1ba9ba4Schristos return offset by which to adjust pc. */
117a1ba9ba4Schristos
118a1ba9ba4Schristos void
bfin_syscall(SIM_CPU * cpu)119a1ba9ba4Schristos bfin_syscall (SIM_CPU *cpu)
120a1ba9ba4Schristos {
121a1ba9ba4Schristos SIM_DESC sd = CPU_STATE (cpu);
122b2396a7bSchristos char * const *argv = (void *)STATE_PROG_ARGV (sd);
123a1ba9ba4Schristos host_callback *cb = STATE_CALLBACK (sd);
124a1ba9ba4Schristos bu32 args[6];
125a1ba9ba4Schristos CB_SYSCALL sc;
126a1ba9ba4Schristos char *p;
127a1ba9ba4Schristos char _tbuf[1024 * 3], *tbuf = _tbuf, tstr[1024];
128a1ba9ba4Schristos int fmt_ret_hex = 0;
129a1ba9ba4Schristos
130a1ba9ba4Schristos CB_SYSCALL_INIT (&sc);
131a1ba9ba4Schristos
132a1ba9ba4Schristos if (STATE_ENVIRONMENT (sd) == USER_ENVIRONMENT)
133a1ba9ba4Schristos {
134a1ba9ba4Schristos /* Linux syscall. */
135a1ba9ba4Schristos sc.func = PREG (0);
136a1ba9ba4Schristos sc.arg1 = args[0] = DREG (0);
137a1ba9ba4Schristos sc.arg2 = args[1] = DREG (1);
138a1ba9ba4Schristos sc.arg3 = args[2] = DREG (2);
139a1ba9ba4Schristos sc.arg4 = args[3] = DREG (3);
140a1ba9ba4Schristos /*sc.arg5 =*/ args[4] = DREG (4);
141a1ba9ba4Schristos /*sc.arg6 =*/ args[5] = DREG (5);
142a1ba9ba4Schristos }
143a1ba9ba4Schristos else
144a1ba9ba4Schristos {
145a1ba9ba4Schristos /* libgloss syscall. */
146a1ba9ba4Schristos sc.func = PREG (0);
147a1ba9ba4Schristos sc.arg1 = args[0] = GET_LONG (DREG (0));
148a1ba9ba4Schristos sc.arg2 = args[1] = GET_LONG (DREG (0) + 4);
149a1ba9ba4Schristos sc.arg3 = args[2] = GET_LONG (DREG (0) + 8);
150a1ba9ba4Schristos sc.arg4 = args[3] = GET_LONG (DREG (0) + 12);
151a1ba9ba4Schristos /*sc.arg5 =*/ args[4] = GET_LONG (DREG (0) + 16);
152a1ba9ba4Schristos /*sc.arg6 =*/ args[5] = GET_LONG (DREG (0) + 20);
153a1ba9ba4Schristos }
154a1ba9ba4Schristos sc.p1 = (PTR) sd;
155a1ba9ba4Schristos sc.p2 = (PTR) cpu;
156a1ba9ba4Schristos sc.read_mem = sim_syscall_read_mem;
157a1ba9ba4Schristos sc.write_mem = sim_syscall_write_mem;
158a1ba9ba4Schristos
159a1ba9ba4Schristos /* Common cb_syscall() handles most functions. */
160a1ba9ba4Schristos switch (cb_target_to_host_syscall (cb, sc.func))
161a1ba9ba4Schristos {
162a1ba9ba4Schristos case CB_SYS_exit:
163a1ba9ba4Schristos tbuf += sprintf (tbuf, "exit(%i)", args[0]);
164a1ba9ba4Schristos sim_engine_halt (sd, cpu, NULL, PCREG, sim_exited, sc.arg1);
165a1ba9ba4Schristos
166a1ba9ba4Schristos #ifdef CB_SYS_argc
167a1ba9ba4Schristos case CB_SYS_argc:
168a1ba9ba4Schristos tbuf += sprintf (tbuf, "argc()");
169b2396a7bSchristos sc.result = countargv ((char **)argv);
170a1ba9ba4Schristos break;
171a1ba9ba4Schristos case CB_SYS_argnlen:
172a1ba9ba4Schristos {
173a1ba9ba4Schristos tbuf += sprintf (tbuf, "argnlen(%u)", args[0]);
174b2396a7bSchristos if (sc.arg1 < countargv ((char **)argv))
175a1ba9ba4Schristos sc.result = strlen (argv[sc.arg1]);
176a1ba9ba4Schristos else
177a1ba9ba4Schristos sc.result = -1;
178a1ba9ba4Schristos }
179a1ba9ba4Schristos break;
180a1ba9ba4Schristos case CB_SYS_argn:
181a1ba9ba4Schristos {
182a1ba9ba4Schristos tbuf += sprintf (tbuf, "argn(%u)", args[0]);
183b2396a7bSchristos if (sc.arg1 < countargv ((char **)argv))
184a1ba9ba4Schristos {
185a1ba9ba4Schristos const char *argn = argv[sc.arg1];
186a1ba9ba4Schristos int len = strlen (argn);
187a1ba9ba4Schristos int written = sc.write_mem (cb, &sc, sc.arg2, argn, len + 1);
188a1ba9ba4Schristos if (written == len + 1)
189a1ba9ba4Schristos sc.result = sc.arg2;
190a1ba9ba4Schristos else
191a1ba9ba4Schristos sc.result = -1;
192a1ba9ba4Schristos }
193a1ba9ba4Schristos else
194a1ba9ba4Schristos sc.result = -1;
195a1ba9ba4Schristos }
196a1ba9ba4Schristos break;
197a1ba9ba4Schristos #endif
198a1ba9ba4Schristos
199a1ba9ba4Schristos case CB_SYS_gettimeofday:
200a1ba9ba4Schristos {
201a1ba9ba4Schristos struct timeval _tv, *tv = &_tv;
202a1ba9ba4Schristos struct timezone _tz, *tz = &_tz;
203a1ba9ba4Schristos
204a1ba9ba4Schristos tbuf += sprintf (tbuf, "gettimeofday(%#x, %#x)", args[0], args[1]);
205a1ba9ba4Schristos
206a1ba9ba4Schristos if (sc.arg1 == 0)
207a1ba9ba4Schristos tv = NULL;
208a1ba9ba4Schristos if (sc.arg2 == 0)
209a1ba9ba4Schristos tz = NULL;
210a1ba9ba4Schristos sc.result = gettimeofday (tv, tz);
211a1ba9ba4Schristos
212a1ba9ba4Schristos if (sc.result == 0)
213a1ba9ba4Schristos {
214a1ba9ba4Schristos bu32 t;
215a1ba9ba4Schristos
216a1ba9ba4Schristos if (tv)
217a1ba9ba4Schristos {
218a1ba9ba4Schristos t = tv->tv_sec;
219a1ba9ba4Schristos sc.write_mem (cb, &sc, sc.arg1, (void *)&t, 4);
220a1ba9ba4Schristos t = tv->tv_usec;
221a1ba9ba4Schristos sc.write_mem (cb, &sc, sc.arg1 + 4, (void *)&t, 4);
222a1ba9ba4Schristos }
223a1ba9ba4Schristos
224a1ba9ba4Schristos if (sc.arg2)
225a1ba9ba4Schristos {
226a1ba9ba4Schristos t = tz->tz_minuteswest;
227a1ba9ba4Schristos sc.write_mem (cb, &sc, sc.arg1, (void *)&t, 4);
228a1ba9ba4Schristos t = tz->tz_dsttime;
229a1ba9ba4Schristos sc.write_mem (cb, &sc, sc.arg1 + 4, (void *)&t, 4);
230a1ba9ba4Schristos }
231a1ba9ba4Schristos }
232a1ba9ba4Schristos else
233a1ba9ba4Schristos goto sys_finish;
234a1ba9ba4Schristos }
235a1ba9ba4Schristos break;
236a1ba9ba4Schristos
237a1ba9ba4Schristos case CB_SYS_ioctl:
238a1ba9ba4Schristos /* XXX: hack just enough to get basic stdio w/uClibc ... */
239a1ba9ba4Schristos tbuf += sprintf (tbuf, "ioctl(%i, %#x, %u)", args[0], args[1], args[2]);
240a1ba9ba4Schristos if (sc.arg2 == 0x5401)
241a1ba9ba4Schristos {
242a1ba9ba4Schristos sc.result = !isatty (sc.arg1);
243a1ba9ba4Schristos sc.errcode = 0;
244a1ba9ba4Schristos }
245a1ba9ba4Schristos else
246a1ba9ba4Schristos {
247a1ba9ba4Schristos sc.result = -1;
248a1ba9ba4Schristos sc.errcode = TARGET_EINVAL;
249a1ba9ba4Schristos }
250a1ba9ba4Schristos break;
251a1ba9ba4Schristos
252a1ba9ba4Schristos case CB_SYS_mmap2:
253a1ba9ba4Schristos {
254a1ba9ba4Schristos static bu32 heap = BFIN_DEFAULT_MEM_SIZE / 2;
255a1ba9ba4Schristos
256a1ba9ba4Schristos fmt_ret_hex = 1;
257a1ba9ba4Schristos tbuf += sprintf (tbuf, "mmap2(%#x, %u, %#x, %#x, %i, %u)",
258a1ba9ba4Schristos args[0], args[1], args[2], args[3], args[4], args[5]);
259a1ba9ba4Schristos
260a1ba9ba4Schristos sc.errcode = 0;
261a1ba9ba4Schristos
262a1ba9ba4Schristos if (sc.arg4 & 0x20 /*MAP_ANONYMOUS*/)
263a1ba9ba4Schristos /* XXX: We don't handle zeroing, but default is all zeros. */;
264a1ba9ba4Schristos else if (args[4] >= MAX_CALLBACK_FDS)
265a1ba9ba4Schristos sc.errcode = TARGET_ENOSYS;
266a1ba9ba4Schristos else
267a1ba9ba4Schristos {
268a1ba9ba4Schristos #ifdef HAVE_PREAD
269a1ba9ba4Schristos char *data = xmalloc (sc.arg2);
270a1ba9ba4Schristos
271a1ba9ba4Schristos /* XXX: Should add a cb->pread. */
272a1ba9ba4Schristos if (pread (cb->fdmap[args[4]], data, sc.arg2, args[5] << 12) == sc.arg2)
273a1ba9ba4Schristos sc.write_mem (cb, &sc, heap, data, sc.arg2);
274a1ba9ba4Schristos else
275a1ba9ba4Schristos sc.errcode = TARGET_EINVAL;
276a1ba9ba4Schristos
277a1ba9ba4Schristos free (data);
278a1ba9ba4Schristos #else
279a1ba9ba4Schristos sc.errcode = TARGET_ENOSYS;
280a1ba9ba4Schristos #endif
281a1ba9ba4Schristos }
282a1ba9ba4Schristos
283a1ba9ba4Schristos if (sc.errcode)
284a1ba9ba4Schristos {
285a1ba9ba4Schristos sc.result = -1;
286a1ba9ba4Schristos break;
287a1ba9ba4Schristos }
288a1ba9ba4Schristos
289a1ba9ba4Schristos sc.result = heap;
290a1ba9ba4Schristos heap += sc.arg2;
291a1ba9ba4Schristos /* Keep it page aligned. */
292a1ba9ba4Schristos heap = ALIGN (heap, 4096);
293a1ba9ba4Schristos
294a1ba9ba4Schristos break;
295a1ba9ba4Schristos }
296a1ba9ba4Schristos
297a1ba9ba4Schristos case CB_SYS_munmap:
298a1ba9ba4Schristos /* XXX: meh, just lie for mmap(). */
299a1ba9ba4Schristos tbuf += sprintf (tbuf, "munmap(%#x, %u)", args[0], args[1]);
300a1ba9ba4Schristos sc.result = 0;
301a1ba9ba4Schristos break;
302a1ba9ba4Schristos
303a1ba9ba4Schristos case CB_SYS_dup2:
304a1ba9ba4Schristos tbuf += sprintf (tbuf, "dup2(%i, %i)", args[0], args[1]);
305a1ba9ba4Schristos if (sc.arg1 >= MAX_CALLBACK_FDS || sc.arg2 >= MAX_CALLBACK_FDS)
306a1ba9ba4Schristos {
307a1ba9ba4Schristos sc.result = -1;
308a1ba9ba4Schristos sc.errcode = TARGET_EINVAL;
309a1ba9ba4Schristos }
310a1ba9ba4Schristos else
311a1ba9ba4Schristos {
312a1ba9ba4Schristos sc.result = dup2 (cb->fdmap[sc.arg1], cb->fdmap[sc.arg2]);
313a1ba9ba4Schristos goto sys_finish;
314a1ba9ba4Schristos }
315a1ba9ba4Schristos break;
316a1ba9ba4Schristos
317a1ba9ba4Schristos case CB_SYS__llseek:
318a1ba9ba4Schristos tbuf += sprintf (tbuf, "llseek(%i, %u, %u, %#x, %u)",
319a1ba9ba4Schristos args[0], args[1], args[2], args[3], args[4]);
320a1ba9ba4Schristos sc.func = TARGET_LINUX_SYS_lseek;
321a1ba9ba4Schristos if (sc.arg2)
322a1ba9ba4Schristos {
323a1ba9ba4Schristos sc.result = -1;
324a1ba9ba4Schristos sc.errcode = TARGET_EINVAL;
325a1ba9ba4Schristos }
326a1ba9ba4Schristos else
327a1ba9ba4Schristos {
328a1ba9ba4Schristos sc.arg2 = sc.arg3;
329a1ba9ba4Schristos sc.arg3 = args[4];
330a1ba9ba4Schristos cb_syscall (cb, &sc);
331a1ba9ba4Schristos if (sc.result != -1)
332a1ba9ba4Schristos {
333a1ba9ba4Schristos bu32 z = 0;
334a1ba9ba4Schristos sc.write_mem (cb, &sc, args[3], (void *)&sc.result, 4);
335a1ba9ba4Schristos sc.write_mem (cb, &sc, args[3] + 4, (void *)&z, 4);
336a1ba9ba4Schristos }
337a1ba9ba4Schristos }
338a1ba9ba4Schristos break;
339a1ba9ba4Schristos
340a1ba9ba4Schristos /* XXX: Should add a cb->pread. */
341a1ba9ba4Schristos case CB_SYS_pread:
342a1ba9ba4Schristos tbuf += sprintf (tbuf, "pread(%i, %#x, %u, %i)",
343a1ba9ba4Schristos args[0], args[1], args[2], args[3]);
344a1ba9ba4Schristos if (sc.arg1 >= MAX_CALLBACK_FDS)
345a1ba9ba4Schristos {
346a1ba9ba4Schristos sc.result = -1;
347a1ba9ba4Schristos sc.errcode = TARGET_EINVAL;
348a1ba9ba4Schristos }
349a1ba9ba4Schristos else
350a1ba9ba4Schristos {
351a1ba9ba4Schristos long old_pos, read_result, read_errcode;
352a1ba9ba4Schristos
353a1ba9ba4Schristos /* Get current filepos. */
354a1ba9ba4Schristos sc.func = TARGET_LINUX_SYS_lseek;
355a1ba9ba4Schristos sc.arg2 = 0;
356a1ba9ba4Schristos sc.arg3 = SEEK_CUR;
357a1ba9ba4Schristos cb_syscall (cb, &sc);
358a1ba9ba4Schristos if (sc.result == -1)
359a1ba9ba4Schristos break;
360a1ba9ba4Schristos old_pos = sc.result;
361a1ba9ba4Schristos
362a1ba9ba4Schristos /* Move to the new pos. */
363a1ba9ba4Schristos sc.func = TARGET_LINUX_SYS_lseek;
364a1ba9ba4Schristos sc.arg2 = args[3];
365a1ba9ba4Schristos sc.arg3 = SEEK_SET;
366a1ba9ba4Schristos cb_syscall (cb, &sc);
367a1ba9ba4Schristos if (sc.result == -1)
368a1ba9ba4Schristos break;
369a1ba9ba4Schristos
370a1ba9ba4Schristos /* Read the data. */
371a1ba9ba4Schristos sc.func = TARGET_LINUX_SYS_read;
372a1ba9ba4Schristos sc.arg2 = args[1];
373a1ba9ba4Schristos sc.arg3 = args[2];
374a1ba9ba4Schristos cb_syscall (cb, &sc);
375a1ba9ba4Schristos read_result = sc.result;
376a1ba9ba4Schristos read_errcode = sc.errcode;
377a1ba9ba4Schristos
378a1ba9ba4Schristos /* Move back to the old pos. */
379a1ba9ba4Schristos sc.func = TARGET_LINUX_SYS_lseek;
380a1ba9ba4Schristos sc.arg2 = old_pos;
381a1ba9ba4Schristos sc.arg3 = SEEK_SET;
382a1ba9ba4Schristos cb_syscall (cb, &sc);
383a1ba9ba4Schristos
384a1ba9ba4Schristos sc.result = read_result;
385a1ba9ba4Schristos sc.errcode = read_errcode;
386a1ba9ba4Schristos }
387a1ba9ba4Schristos break;
388a1ba9ba4Schristos
389a1ba9ba4Schristos case CB_SYS_getcwd:
390a1ba9ba4Schristos tbuf += sprintf (tbuf, "getcwd(%#x, %u)", args[0], args[1]);
391a1ba9ba4Schristos
392a1ba9ba4Schristos p = alloca (sc.arg2);
393a1ba9ba4Schristos if (getcwd (p, sc.arg2) == NULL)
394a1ba9ba4Schristos {
395a1ba9ba4Schristos sc.result = -1;
396a1ba9ba4Schristos sc.errcode = TARGET_EINVAL;
397a1ba9ba4Schristos }
398a1ba9ba4Schristos else
399a1ba9ba4Schristos {
400a1ba9ba4Schristos sc.write_mem (cb, &sc, sc.arg1, p, sc.arg2);
401a1ba9ba4Schristos sc.result = sc.arg1;
402a1ba9ba4Schristos }
403a1ba9ba4Schristos break;
404a1ba9ba4Schristos
405a1ba9ba4Schristos case CB_SYS_stat64:
406a1ba9ba4Schristos if (cb_get_string (cb, &sc, tstr, sizeof (tstr), args[0]))
407a1ba9ba4Schristos strcpy (tstr, "???");
408a1ba9ba4Schristos tbuf += sprintf (tbuf, "stat64(%#x:\"%s\", %u)", args[0], tstr, args[1]);
409a1ba9ba4Schristos cb->stat_map = stat_map_64;
410a1ba9ba4Schristos sc.func = TARGET_LINUX_SYS_stat;
411a1ba9ba4Schristos cb_syscall (cb, &sc);
412a1ba9ba4Schristos cb->stat_map = stat_map_32;
413a1ba9ba4Schristos break;
414a1ba9ba4Schristos case CB_SYS_lstat64:
415a1ba9ba4Schristos if (cb_get_string (cb, &sc, tstr, sizeof (tstr), args[0]))
416a1ba9ba4Schristos strcpy (tstr, "???");
417a1ba9ba4Schristos tbuf += sprintf (tbuf, "lstat64(%#x:\"%s\", %u)", args[0], tstr, args[1]);
418a1ba9ba4Schristos cb->stat_map = stat_map_64;
419a1ba9ba4Schristos sc.func = TARGET_LINUX_SYS_lstat;
420a1ba9ba4Schristos cb_syscall (cb, &sc);
421a1ba9ba4Schristos cb->stat_map = stat_map_32;
422a1ba9ba4Schristos break;
423a1ba9ba4Schristos case CB_SYS_fstat64:
424a1ba9ba4Schristos tbuf += sprintf (tbuf, "fstat64(%#x, %u)", args[0], args[1]);
425a1ba9ba4Schristos cb->stat_map = stat_map_64;
426a1ba9ba4Schristos sc.func = TARGET_LINUX_SYS_fstat;
427a1ba9ba4Schristos cb_syscall (cb, &sc);
428a1ba9ba4Schristos cb->stat_map = stat_map_32;
429a1ba9ba4Schristos break;
430a1ba9ba4Schristos
431a1ba9ba4Schristos case CB_SYS_ftruncate64:
432a1ba9ba4Schristos tbuf += sprintf (tbuf, "ftruncate64(%u, %u)", args[0], args[1]);
433a1ba9ba4Schristos sc.func = TARGET_LINUX_SYS_ftruncate;
434a1ba9ba4Schristos cb_syscall (cb, &sc);
435a1ba9ba4Schristos break;
436a1ba9ba4Schristos
437a1ba9ba4Schristos case CB_SYS_getuid:
438a1ba9ba4Schristos case CB_SYS_getuid32:
439a1ba9ba4Schristos tbuf += sprintf (tbuf, "getuid()");
440a1ba9ba4Schristos sc.result = getuid ();
441a1ba9ba4Schristos goto sys_finish;
442a1ba9ba4Schristos case CB_SYS_getgid:
443a1ba9ba4Schristos case CB_SYS_getgid32:
444a1ba9ba4Schristos tbuf += sprintf (tbuf, "getgid()");
445a1ba9ba4Schristos sc.result = getgid ();
446a1ba9ba4Schristos goto sys_finish;
447a1ba9ba4Schristos case CB_SYS_setuid:
448a1ba9ba4Schristos sc.arg1 &= 0xffff;
449a1ba9ba4Schristos case CB_SYS_setuid32:
450a1ba9ba4Schristos tbuf += sprintf (tbuf, "setuid(%u)", args[0]);
451a1ba9ba4Schristos sc.result = setuid (sc.arg1);
452a1ba9ba4Schristos goto sys_finish;
453a1ba9ba4Schristos case CB_SYS_setgid:
454a1ba9ba4Schristos sc.arg1 &= 0xffff;
455a1ba9ba4Schristos case CB_SYS_setgid32:
456a1ba9ba4Schristos tbuf += sprintf (tbuf, "setgid(%u)", args[0]);
457a1ba9ba4Schristos sc.result = setgid (sc.arg1);
458a1ba9ba4Schristos goto sys_finish;
459a1ba9ba4Schristos
460a1ba9ba4Schristos case CB_SYS_getpid:
461a1ba9ba4Schristos tbuf += sprintf (tbuf, "getpid()");
462a1ba9ba4Schristos sc.result = getpid ();
463a1ba9ba4Schristos goto sys_finish;
464a1ba9ba4Schristos case CB_SYS_kill:
465a1ba9ba4Schristos tbuf += sprintf (tbuf, "kill(%u, %i)", args[0], args[1]);
466a1ba9ba4Schristos /* Only let the app kill itself. */
467a1ba9ba4Schristos if (sc.arg1 != getpid ())
468a1ba9ba4Schristos {
469a1ba9ba4Schristos sc.result = -1;
470a1ba9ba4Schristos sc.errcode = TARGET_EPERM;
471a1ba9ba4Schristos }
472a1ba9ba4Schristos else
473a1ba9ba4Schristos {
474a1ba9ba4Schristos #ifdef HAVE_KILL
475a1ba9ba4Schristos sc.result = kill (sc.arg1, sc.arg2);
476a1ba9ba4Schristos goto sys_finish;
477a1ba9ba4Schristos #else
478a1ba9ba4Schristos sc.result = -1;
479a1ba9ba4Schristos sc.errcode = TARGET_ENOSYS;
480a1ba9ba4Schristos #endif
481a1ba9ba4Schristos }
482a1ba9ba4Schristos break;
483a1ba9ba4Schristos
484a1ba9ba4Schristos case CB_SYS_open:
485a1ba9ba4Schristos if (cb_get_string (cb, &sc, tstr, sizeof (tstr), args[0]))
486a1ba9ba4Schristos strcpy (tstr, "???");
487a1ba9ba4Schristos tbuf += sprintf (tbuf, "open(%#x:\"%s\", %#x, %o)",
488a1ba9ba4Schristos args[0], tstr, args[1], args[2]);
489a1ba9ba4Schristos goto case_default;
490a1ba9ba4Schristos case CB_SYS_close:
491a1ba9ba4Schristos tbuf += sprintf (tbuf, "close(%i)", args[0]);
492a1ba9ba4Schristos goto case_default;
493a1ba9ba4Schristos case CB_SYS_read:
494a1ba9ba4Schristos tbuf += sprintf (tbuf, "read(%i, %#x, %u)", args[0], args[1], args[2]);
495a1ba9ba4Schristos goto case_default;
496a1ba9ba4Schristos case CB_SYS_write:
497a1ba9ba4Schristos if (cb_get_string (cb, &sc, tstr, sizeof (tstr), args[1]))
498a1ba9ba4Schristos strcpy (tstr, "???");
499a1ba9ba4Schristos tbuf += sprintf (tbuf, "write(%i, %#x:\"%s\", %u)",
500a1ba9ba4Schristos args[0], args[1], tstr, args[2]);
501a1ba9ba4Schristos goto case_default;
502a1ba9ba4Schristos case CB_SYS_lseek:
503a1ba9ba4Schristos tbuf += sprintf (tbuf, "lseek(%i, %i, %i)", args[0], args[1], args[2]);
504a1ba9ba4Schristos goto case_default;
505a1ba9ba4Schristos case CB_SYS_unlink:
506a1ba9ba4Schristos if (cb_get_string (cb, &sc, tstr, sizeof (tstr), args[0]))
507a1ba9ba4Schristos strcpy (tstr, "???");
508a1ba9ba4Schristos tbuf += sprintf (tbuf, "unlink(%#x:\"%s\")", args[0], tstr);
509a1ba9ba4Schristos goto case_default;
510a1ba9ba4Schristos case CB_SYS_truncate:
511a1ba9ba4Schristos if (cb_get_string (cb, &sc, tstr, sizeof (tstr), args[0]))
512a1ba9ba4Schristos strcpy (tstr, "???");
513a1ba9ba4Schristos tbuf += sprintf (tbuf, "truncate(%#x:\"%s\", %i)", args[0], tstr, args[1]);
514a1ba9ba4Schristos goto case_default;
515a1ba9ba4Schristos case CB_SYS_ftruncate:
516a1ba9ba4Schristos tbuf += sprintf (tbuf, "ftruncate(%i, %i)", args[0], args[1]);
517a1ba9ba4Schristos goto case_default;
518a1ba9ba4Schristos case CB_SYS_rename:
519a1ba9ba4Schristos if (cb_get_string (cb, &sc, tstr, sizeof (tstr), args[0]))
520a1ba9ba4Schristos strcpy (tstr, "???");
521a1ba9ba4Schristos tbuf += sprintf (tbuf, "rename(%#x:\"%s\", ", args[0], tstr);
522a1ba9ba4Schristos if (cb_get_string (cb, &sc, tstr, sizeof (tstr), args[1]))
523a1ba9ba4Schristos strcpy (tstr, "???");
524a1ba9ba4Schristos tbuf += sprintf (tbuf, "%#x:\"%s\")", args[1], tstr);
525a1ba9ba4Schristos goto case_default;
526a1ba9ba4Schristos case CB_SYS_stat:
527a1ba9ba4Schristos if (cb_get_string (cb, &sc, tstr, sizeof (tstr), args[0]))
528a1ba9ba4Schristos strcpy (tstr, "???");
529a1ba9ba4Schristos tbuf += sprintf (tbuf, "stat(%#x:\"%s\", %#x)", args[0], tstr, args[1]);
530a1ba9ba4Schristos goto case_default;
531a1ba9ba4Schristos case CB_SYS_fstat:
532a1ba9ba4Schristos tbuf += sprintf (tbuf, "fstat(%i, %#x)", args[0], args[1]);
533a1ba9ba4Schristos goto case_default;
534a1ba9ba4Schristos case CB_SYS_lstat:
535a1ba9ba4Schristos if (cb_get_string (cb, &sc, tstr, sizeof (tstr), args[0]))
536a1ba9ba4Schristos strcpy (tstr, "???");
537a1ba9ba4Schristos tbuf += sprintf (tbuf, "lstat(%#x:\"%s\", %#x)", args[0], tstr, args[1]);
538a1ba9ba4Schristos goto case_default;
539a1ba9ba4Schristos case CB_SYS_pipe:
540a1ba9ba4Schristos tbuf += sprintf (tbuf, "pipe(%#x, %#x)", args[0], args[1]);
541a1ba9ba4Schristos goto case_default;
542a1ba9ba4Schristos
543a1ba9ba4Schristos default:
544a1ba9ba4Schristos tbuf += sprintf (tbuf, "???_%i(%#x, %#x, %#x, %#x, %#x, %#x)", sc.func,
545a1ba9ba4Schristos args[0], args[1], args[2], args[3], args[4], args[5]);
546a1ba9ba4Schristos case_default:
547a1ba9ba4Schristos cb_syscall (cb, &sc);
548a1ba9ba4Schristos break;
549a1ba9ba4Schristos
550a1ba9ba4Schristos sys_finish:
551a1ba9ba4Schristos if (sc.result == -1)
552a1ba9ba4Schristos {
553a1ba9ba4Schristos cb->last_errno = errno;
554a1ba9ba4Schristos sc.errcode = cb->get_errno (cb);
555a1ba9ba4Schristos }
556a1ba9ba4Schristos }
557a1ba9ba4Schristos
558a1ba9ba4Schristos TRACE_EVENTS (cpu, "syscall_%i(%#x, %#x, %#x, %#x, %#x, %#x) = %li (error = %i)",
559a1ba9ba4Schristos sc.func, args[0], args[1], args[2], args[3], args[4], args[5],
560a1ba9ba4Schristos sc.result, sc.errcode);
561a1ba9ba4Schristos
562a1ba9ba4Schristos tbuf += sprintf (tbuf, " = ");
563a1ba9ba4Schristos if (STATE_ENVIRONMENT (sd) == USER_ENVIRONMENT)
564a1ba9ba4Schristos {
565a1ba9ba4Schristos if (sc.result == -1)
566a1ba9ba4Schristos {
567a1ba9ba4Schristos tbuf += sprintf (tbuf, "-1 (error = %i)", sc.errcode);
568a1ba9ba4Schristos if (sc.errcode == cb_host_to_target_errno (cb, ENOSYS))
569a1ba9ba4Schristos {
570a1ba9ba4Schristos sim_io_eprintf (sd, "bfin-sim: %#x: unimplemented syscall %i\n",
571a1ba9ba4Schristos PCREG, sc.func);
572a1ba9ba4Schristos }
573a1ba9ba4Schristos SET_DREG (0, -sc.errcode);
574a1ba9ba4Schristos }
575a1ba9ba4Schristos else
576a1ba9ba4Schristos {
577a1ba9ba4Schristos if (fmt_ret_hex)
578a1ba9ba4Schristos tbuf += sprintf (tbuf, "%#lx", sc.result);
579a1ba9ba4Schristos else
580a1ba9ba4Schristos tbuf += sprintf (tbuf, "%lu", sc.result);
581a1ba9ba4Schristos SET_DREG (0, sc.result);
582a1ba9ba4Schristos }
583a1ba9ba4Schristos }
584a1ba9ba4Schristos else
585a1ba9ba4Schristos {
586a1ba9ba4Schristos tbuf += sprintf (tbuf, "%lu (error = %i)", sc.result, sc.errcode);
587a1ba9ba4Schristos SET_DREG (0, sc.result);
588a1ba9ba4Schristos SET_DREG (1, sc.result2);
589a1ba9ba4Schristos SET_DREG (2, sc.errcode);
590a1ba9ba4Schristos }
591a1ba9ba4Schristos
592a1ba9ba4Schristos TRACE_SYSCALL (cpu, "%s", _tbuf);
593a1ba9ba4Schristos }
594a1ba9ba4Schristos
595a1ba9ba4Schristos /* Execute a single instruction. */
596a1ba9ba4Schristos
597a1ba9ba4Schristos static sim_cia
step_once(SIM_CPU * cpu)598a1ba9ba4Schristos step_once (SIM_CPU *cpu)
599a1ba9ba4Schristos {
600a1ba9ba4Schristos SIM_DESC sd = CPU_STATE (cpu);
601a1ba9ba4Schristos bu32 insn_len, oldpc = PCREG;
602a1ba9ba4Schristos int i;
603a1ba9ba4Schristos bool ssstep;
604a1ba9ba4Schristos
605a1ba9ba4Schristos if (TRACE_ANY_P (cpu))
606a1ba9ba4Schristos trace_prefix (sd, cpu, NULL_CIA, oldpc, TRACE_LINENUM_P (cpu),
607a1ba9ba4Schristos NULL, 0, " "); /* Use a space for gcc warnings. */
608a1ba9ba4Schristos
609b2396a7bSchristos TRACE_DISASM (cpu, oldpc);
610b2396a7bSchristos
611a1ba9ba4Schristos /* Handle hardware single stepping when lower than EVT3, and when SYSCFG
612a1ba9ba4Schristos has already had the SSSTEP bit enabled. */
613a1ba9ba4Schristos ssstep = false;
614a1ba9ba4Schristos if (STATE_ENVIRONMENT (sd) == OPERATING_ENVIRONMENT
615a1ba9ba4Schristos && (SYSCFGREG & SYSCFG_SSSTEP))
616a1ba9ba4Schristos {
617a1ba9ba4Schristos int ivg = cec_get_ivg (cpu);
618a1ba9ba4Schristos if (ivg == -1 || ivg > 3)
619a1ba9ba4Schristos ssstep = true;
620a1ba9ba4Schristos }
621a1ba9ba4Schristos
622a1ba9ba4Schristos #if 0
623a1ba9ba4Schristos /* XXX: Is this what happens on the hardware ? */
624a1ba9ba4Schristos if (cec_get_ivg (cpu) == EVT_EMU)
625a1ba9ba4Schristos cec_return (cpu, EVT_EMU);
626a1ba9ba4Schristos #endif
627a1ba9ba4Schristos
628a1ba9ba4Schristos BFIN_CPU_STATE.did_jump = false;
629a1ba9ba4Schristos
630a1ba9ba4Schristos insn_len = interp_insn_bfin (cpu, oldpc);
631a1ba9ba4Schristos
632a1ba9ba4Schristos /* If we executed this insn successfully, then we always decrement
633a1ba9ba4Schristos the loop counter. We don't want to update the PC though if the
634a1ba9ba4Schristos last insn happened to be a change in code flow (jump/etc...). */
635a1ba9ba4Schristos if (!BFIN_CPU_STATE.did_jump)
636a1ba9ba4Schristos SET_PCREG (hwloop_get_next_pc (cpu, oldpc, insn_len));
637a1ba9ba4Schristos for (i = 1; i >= 0; --i)
638a1ba9ba4Schristos if (LCREG (i) && oldpc == LBREG (i))
639a1ba9ba4Schristos {
640a1ba9ba4Schristos SET_LCREG (i, LCREG (i) - 1);
641a1ba9ba4Schristos if (LCREG (i))
642a1ba9ba4Schristos break;
643a1ba9ba4Schristos }
644a1ba9ba4Schristos
645a1ba9ba4Schristos ++ PROFILE_TOTAL_INSN_COUNT (CPU_PROFILE_DATA (cpu));
646a1ba9ba4Schristos
647a1ba9ba4Schristos /* Handle hardware single stepping only if we're still lower than EVT3.
648a1ba9ba4Schristos XXX: May not be entirely correct wrt EXCPT insns. */
649a1ba9ba4Schristos if (ssstep)
650a1ba9ba4Schristos {
651a1ba9ba4Schristos int ivg = cec_get_ivg (cpu);
652a1ba9ba4Schristos if (ivg == -1 || ivg > 3)
653a1ba9ba4Schristos {
654a1ba9ba4Schristos INSN_LEN = 0;
655a1ba9ba4Schristos cec_exception (cpu, VEC_STEP);
656a1ba9ba4Schristos }
657a1ba9ba4Schristos }
658a1ba9ba4Schristos
659a1ba9ba4Schristos return oldpc;
660a1ba9ba4Schristos }
661a1ba9ba4Schristos
662a1ba9ba4Schristos void
sim_engine_run(SIM_DESC sd,int next_cpu_nr,int nr_cpus,int siggnal)663a1ba9ba4Schristos sim_engine_run (SIM_DESC sd,
664a1ba9ba4Schristos int next_cpu_nr, /* ignore */
665a1ba9ba4Schristos int nr_cpus, /* ignore */
666a1ba9ba4Schristos int siggnal) /* ignore */
667a1ba9ba4Schristos {
668a1ba9ba4Schristos bu32 ticks;
669a1ba9ba4Schristos SIM_CPU *cpu;
670a1ba9ba4Schristos
671a1ba9ba4Schristos SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
672a1ba9ba4Schristos
673a1ba9ba4Schristos cpu = STATE_CPU (sd, 0);
674a1ba9ba4Schristos
675a1ba9ba4Schristos while (1)
676a1ba9ba4Schristos {
677a1ba9ba4Schristos step_once (cpu);
678a1ba9ba4Schristos /* Process any events -- can't use tickn because it may
679a1ba9ba4Schristos advance right over the next event. */
680a1ba9ba4Schristos for (ticks = 0; ticks < CYCLE_DELAY; ++ticks)
681a1ba9ba4Schristos if (sim_events_tick (sd))
682a1ba9ba4Schristos sim_events_process (sd);
683a1ba9ba4Schristos }
684a1ba9ba4Schristos }
685a1ba9ba4Schristos
686a1ba9ba4Schristos /* Cover function of sim_state_free to free the cpu buffers as well. */
687a1ba9ba4Schristos
688a1ba9ba4Schristos static void
free_state(SIM_DESC sd)689a1ba9ba4Schristos free_state (SIM_DESC sd)
690a1ba9ba4Schristos {
691a1ba9ba4Schristos if (STATE_MODULES (sd) != NULL)
692a1ba9ba4Schristos sim_module_uninstall (sd);
693a1ba9ba4Schristos sim_cpu_free_all (sd);
694a1ba9ba4Schristos sim_state_free (sd);
695a1ba9ba4Schristos }
696a1ba9ba4Schristos
697a1ba9ba4Schristos /* Create an instance of the simulator. */
698a1ba9ba4Schristos
699a1ba9ba4Schristos static void
bfin_initialize_cpu(SIM_DESC sd,SIM_CPU * cpu)700a1ba9ba4Schristos bfin_initialize_cpu (SIM_DESC sd, SIM_CPU *cpu)
701a1ba9ba4Schristos {
702a1ba9ba4Schristos memset (&cpu->state, 0, sizeof (cpu->state));
703a1ba9ba4Schristos
704a1ba9ba4Schristos PROFILE_TOTAL_INSN_COUNT (CPU_PROFILE_DATA (cpu)) = 0;
705a1ba9ba4Schristos
706a1ba9ba4Schristos bfin_model_cpu_init (sd, cpu);
707a1ba9ba4Schristos
708a1ba9ba4Schristos /* Set default stack to top of scratch pad. */
709a1ba9ba4Schristos SET_SPREG (BFIN_DEFAULT_MEM_SIZE);
710a1ba9ba4Schristos SET_KSPREG (BFIN_DEFAULT_MEM_SIZE);
711a1ba9ba4Schristos SET_USPREG (BFIN_DEFAULT_MEM_SIZE);
712a1ba9ba4Schristos
713a1ba9ba4Schristos /* This is what the hardware likes. */
714a1ba9ba4Schristos SET_SYSCFGREG (0x30);
715a1ba9ba4Schristos }
716a1ba9ba4Schristos
717a1ba9ba4Schristos SIM_DESC
sim_open(SIM_OPEN_KIND kind,host_callback * callback,struct bfd * abfd,char * const * argv)718a1ba9ba4Schristos sim_open (SIM_OPEN_KIND kind, host_callback *callback,
719b2396a7bSchristos struct bfd *abfd, char * const *argv)
720a1ba9ba4Schristos {
721a1ba9ba4Schristos char c;
722a1ba9ba4Schristos int i;
723a1ba9ba4Schristos SIM_DESC sd = sim_state_alloc (kind, callback);
724a1ba9ba4Schristos
725a1ba9ba4Schristos /* The cpu data is kept in a separately allocated chunk of memory. */
726a1ba9ba4Schristos if (sim_cpu_alloc_all (sd, 1, /*cgen_cpu_max_extra_bytes ()*/0) != SIM_RC_OK)
727a1ba9ba4Schristos {
728a1ba9ba4Schristos free_state (sd);
729a1ba9ba4Schristos return 0;
730a1ba9ba4Schristos }
731a1ba9ba4Schristos
732a1ba9ba4Schristos {
733a1ba9ba4Schristos /* XXX: Only first core gets profiled ? */
734a1ba9ba4Schristos SIM_CPU *cpu = STATE_CPU (sd, 0);
735a1ba9ba4Schristos STATE_WATCHPOINTS (sd)->pc = &PCREG;
736a1ba9ba4Schristos STATE_WATCHPOINTS (sd)->sizeof_pc = sizeof (PCREG);
737a1ba9ba4Schristos }
738a1ba9ba4Schristos
739a1ba9ba4Schristos if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
740a1ba9ba4Schristos {
741a1ba9ba4Schristos free_state (sd);
742a1ba9ba4Schristos return 0;
743a1ba9ba4Schristos }
744a1ba9ba4Schristos
745a1ba9ba4Schristos /* XXX: Default to the Virtual environment. */
746a1ba9ba4Schristos if (STATE_ENVIRONMENT (sd) == ALL_ENVIRONMENT)
747a1ba9ba4Schristos STATE_ENVIRONMENT (sd) = VIRTUAL_ENVIRONMENT;
748a1ba9ba4Schristos
749a1ba9ba4Schristos /* These options override any module options.
750a1ba9ba4Schristos Obviously ambiguity should be avoided, however the caller may wish to
751a1ba9ba4Schristos augment the meaning of an option. */
752a1ba9ba4Schristos #define e_sim_add_option_table(sd, options) \
753a1ba9ba4Schristos do { \
754a1ba9ba4Schristos extern const OPTION options[]; \
755a1ba9ba4Schristos sim_add_option_table (sd, NULL, options); \
756a1ba9ba4Schristos } while (0)
757a1ba9ba4Schristos e_sim_add_option_table (sd, bfin_mmu_options);
758a1ba9ba4Schristos e_sim_add_option_table (sd, bfin_mach_options);
759a1ba9ba4Schristos
760b2396a7bSchristos /* The parser will print an error message for us, so we silently return. */
761a1ba9ba4Schristos if (sim_parse_args (sd, argv) != SIM_RC_OK)
762a1ba9ba4Schristos {
763a1ba9ba4Schristos free_state (sd);
764a1ba9ba4Schristos return 0;
765a1ba9ba4Schristos }
766a1ba9ba4Schristos
767a1ba9ba4Schristos /* Allocate external memory if none specified by user.
768a1ba9ba4Schristos Use address 4 here in case the user wanted address 0 unmapped. */
769a1ba9ba4Schristos if (sim_core_read_buffer (sd, NULL, read_map, &c, 4, 1) == 0)
770a1ba9ba4Schristos {
771a1ba9ba4Schristos bu16 emuexcpt = 0x25;
772a1ba9ba4Schristos sim_do_commandf (sd, "memory-size 0x%lx", BFIN_DEFAULT_MEM_SIZE);
773a1ba9ba4Schristos sim_write (sd, 0, (void *)&emuexcpt, 2);
774a1ba9ba4Schristos }
775a1ba9ba4Schristos
776a1ba9ba4Schristos /* Check for/establish the a reference program image. */
777a1ba9ba4Schristos if (sim_analyze_program (sd,
778a1ba9ba4Schristos (STATE_PROG_ARGV (sd) != NULL
779a1ba9ba4Schristos ? *STATE_PROG_ARGV (sd)
780a1ba9ba4Schristos : NULL), abfd) != SIM_RC_OK)
781a1ba9ba4Schristos {
782a1ba9ba4Schristos free_state (sd);
783a1ba9ba4Schristos return 0;
784a1ba9ba4Schristos }
785a1ba9ba4Schristos
786a1ba9ba4Schristos /* Establish any remaining configuration options. */
787a1ba9ba4Schristos if (sim_config (sd) != SIM_RC_OK)
788a1ba9ba4Schristos {
789a1ba9ba4Schristos free_state (sd);
790a1ba9ba4Schristos return 0;
791a1ba9ba4Schristos }
792a1ba9ba4Schristos
793a1ba9ba4Schristos if (sim_post_argv_init (sd) != SIM_RC_OK)
794a1ba9ba4Schristos {
795a1ba9ba4Schristos free_state (sd);
796a1ba9ba4Schristos return 0;
797a1ba9ba4Schristos }
798a1ba9ba4Schristos
799a1ba9ba4Schristos /* CPU specific initialization. */
800a1ba9ba4Schristos for (i = 0; i < MAX_NR_PROCESSORS; ++i)
801a1ba9ba4Schristos {
802a1ba9ba4Schristos SIM_CPU *cpu = STATE_CPU (sd, i);
803a1ba9ba4Schristos bfin_initialize_cpu (sd, cpu);
804a1ba9ba4Schristos }
805a1ba9ba4Schristos
806a1ba9ba4Schristos return sd;
807a1ba9ba4Schristos }
808a1ba9ba4Schristos
809a1ba9ba4Schristos /* Some utils don't like having a NULL environ. */
810b2396a7bSchristos static char * const simple_env[] = { "HOME=/", "PATH=/bin", NULL };
811a1ba9ba4Schristos
812a1ba9ba4Schristos static bu32 fdpic_load_offset;
813a1ba9ba4Schristos
814a1ba9ba4Schristos static bool
bfin_fdpic_load(SIM_DESC sd,SIM_CPU * cpu,struct bfd * abfd,bu32 * sp,bu32 * elf_addrs,char ** ldso_path)815a1ba9ba4Schristos bfin_fdpic_load (SIM_DESC sd, SIM_CPU *cpu, struct bfd *abfd, bu32 *sp,
816a1ba9ba4Schristos bu32 *elf_addrs, char **ldso_path)
817a1ba9ba4Schristos {
818a1ba9ba4Schristos bool ret;
819a1ba9ba4Schristos int i;
820a1ba9ba4Schristos
821a1ba9ba4Schristos Elf_Internal_Ehdr *iehdr;
822a1ba9ba4Schristos Elf32_External_Ehdr ehdr;
823a1ba9ba4Schristos Elf_Internal_Phdr *phdrs;
824a1ba9ba4Schristos unsigned char *data;
825a1ba9ba4Schristos long phdr_size;
826a1ba9ba4Schristos int phdrc;
827a1ba9ba4Schristos bu32 nsegs;
828a1ba9ba4Schristos
829a1ba9ba4Schristos bu32 max_load_addr;
830a1ba9ba4Schristos
831a1ba9ba4Schristos unsigned char null[4] = { 0, 0, 0, 0 };
832a1ba9ba4Schristos
833a1ba9ba4Schristos ret = false;
834a1ba9ba4Schristos *ldso_path = NULL;
835a1ba9ba4Schristos
836a1ba9ba4Schristos /* See if this an FDPIC ELF. */
837a1ba9ba4Schristos phdrs = NULL;
838a1ba9ba4Schristos if (!abfd)
839a1ba9ba4Schristos goto skip_fdpic_init;
840a1ba9ba4Schristos if (bfd_seek (abfd, 0, SEEK_SET) != 0)
841a1ba9ba4Schristos goto skip_fdpic_init;
842a1ba9ba4Schristos if (bfd_bread (&ehdr, sizeof (ehdr), abfd) != sizeof (ehdr))
843a1ba9ba4Schristos goto skip_fdpic_init;
844a1ba9ba4Schristos iehdr = elf_elfheader (abfd);
845a1ba9ba4Schristos if (!(iehdr->e_flags & EF_BFIN_FDPIC))
846a1ba9ba4Schristos goto skip_fdpic_init;
847a1ba9ba4Schristos
848a1ba9ba4Schristos if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG)
849a1ba9ba4Schristos sim_io_printf (sd, "Loading FDPIC ELF %s\n Load base: %#x\n ELF entry: %#x\n",
850a1ba9ba4Schristos bfd_get_filename (abfd), fdpic_load_offset, elf_addrs[0]);
851a1ba9ba4Schristos
852a1ba9ba4Schristos /* Grab the Program Headers to set up the loadsegs on the stack. */
853a1ba9ba4Schristos phdr_size = bfd_get_elf_phdr_upper_bound (abfd);
854a1ba9ba4Schristos if (phdr_size == -1)
855a1ba9ba4Schristos goto skip_fdpic_init;
856a1ba9ba4Schristos phdrs = xmalloc (phdr_size);
857a1ba9ba4Schristos phdrc = bfd_get_elf_phdrs (abfd, phdrs);
858a1ba9ba4Schristos if (phdrc == -1)
859a1ba9ba4Schristos goto skip_fdpic_init;
860a1ba9ba4Schristos
861a1ba9ba4Schristos /* Push the Ehdr onto the stack. */
862a1ba9ba4Schristos *sp -= sizeof (ehdr);
863a1ba9ba4Schristos elf_addrs[3] = *sp;
864a1ba9ba4Schristos sim_write (sd, *sp, (void *)&ehdr, sizeof (ehdr));
865a1ba9ba4Schristos if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG)
866a1ba9ba4Schristos sim_io_printf (sd, " Elf_Ehdr: %#x\n", *sp);
867a1ba9ba4Schristos
868a1ba9ba4Schristos /* Since we're relocating things ourselves, we need to relocate
869a1ba9ba4Schristos the start address as well. */
870a1ba9ba4Schristos elf_addrs[0] = bfd_get_start_address (abfd) + fdpic_load_offset;
871a1ba9ba4Schristos
872a1ba9ba4Schristos /* And the Exec's Phdrs onto the stack. */
873a1ba9ba4Schristos if (STATE_PROG_BFD (sd) == abfd)
874a1ba9ba4Schristos {
875a1ba9ba4Schristos elf_addrs[4] = elf_addrs[0];
876a1ba9ba4Schristos
877a1ba9ba4Schristos phdr_size = iehdr->e_phentsize * iehdr->e_phnum;
878a1ba9ba4Schristos if (bfd_seek (abfd, iehdr->e_phoff, SEEK_SET) != 0)
879a1ba9ba4Schristos goto skip_fdpic_init;
880a1ba9ba4Schristos data = xmalloc (phdr_size);
881a1ba9ba4Schristos if (bfd_bread (data, phdr_size, abfd) != phdr_size)
882a1ba9ba4Schristos goto skip_fdpic_init;
883a1ba9ba4Schristos *sp -= phdr_size;
884a1ba9ba4Schristos elf_addrs[1] = *sp;
885a1ba9ba4Schristos elf_addrs[2] = phdrc;
886a1ba9ba4Schristos sim_write (sd, *sp, data, phdr_size);
887a1ba9ba4Schristos free (data);
888a1ba9ba4Schristos if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG)
889a1ba9ba4Schristos sim_io_printf (sd, " Elf_Phdrs: %#x\n", *sp);
890a1ba9ba4Schristos }
891a1ba9ba4Schristos
892a1ba9ba4Schristos /* Now push all the loadsegs. */
893a1ba9ba4Schristos nsegs = 0;
894a1ba9ba4Schristos max_load_addr = 0;
895a1ba9ba4Schristos for (i = phdrc; i >= 0; --i)
896a1ba9ba4Schristos if (phdrs[i].p_type == PT_LOAD)
897a1ba9ba4Schristos {
898a1ba9ba4Schristos Elf_Internal_Phdr *p = &phdrs[i];
899a1ba9ba4Schristos bu32 paddr, vaddr, memsz, filesz;
900a1ba9ba4Schristos
901a1ba9ba4Schristos paddr = p->p_paddr + fdpic_load_offset;
902a1ba9ba4Schristos vaddr = p->p_vaddr;
903a1ba9ba4Schristos memsz = p->p_memsz;
904a1ba9ba4Schristos filesz = p->p_filesz;
905a1ba9ba4Schristos
906a1ba9ba4Schristos if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG)
907a1ba9ba4Schristos sim_io_printf (sd, " PHDR %i: vma %#x lma %#x filesz %#x memsz %#x\n",
908a1ba9ba4Schristos i, vaddr, paddr, filesz, memsz);
909a1ba9ba4Schristos
910a1ba9ba4Schristos data = xmalloc (memsz);
911a1ba9ba4Schristos if (memsz != filesz)
912a1ba9ba4Schristos memset (data + filesz, 0, memsz - filesz);
913a1ba9ba4Schristos
914a1ba9ba4Schristos if (bfd_seek (abfd, p->p_offset, SEEK_SET) == 0
915a1ba9ba4Schristos && bfd_bread (data, filesz, abfd) == filesz)
916a1ba9ba4Schristos sim_write (sd, paddr, data, memsz);
917a1ba9ba4Schristos
918a1ba9ba4Schristos free (data);
919a1ba9ba4Schristos
920b2396a7bSchristos max_load_addr = max (paddr + memsz, max_load_addr);
921a1ba9ba4Schristos
922a1ba9ba4Schristos *sp -= 12;
923a1ba9ba4Schristos sim_write (sd, *sp+0, (void *)&paddr, 4); /* loadseg.addr */
924a1ba9ba4Schristos sim_write (sd, *sp+4, (void *)&vaddr, 4); /* loadseg.p_vaddr */
925a1ba9ba4Schristos sim_write (sd, *sp+8, (void *)&memsz, 4); /* loadseg.p_memsz */
926a1ba9ba4Schristos ++nsegs;
927a1ba9ba4Schristos }
928a1ba9ba4Schristos else if (phdrs[i].p_type == PT_DYNAMIC)
929a1ba9ba4Schristos {
930a1ba9ba4Schristos elf_addrs[5] = phdrs[i].p_paddr + fdpic_load_offset;
931a1ba9ba4Schristos if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG)
932a1ba9ba4Schristos sim_io_printf (sd, " PT_DYNAMIC: %#x\n", elf_addrs[5]);
933a1ba9ba4Schristos }
934a1ba9ba4Schristos else if (phdrs[i].p_type == PT_INTERP)
935a1ba9ba4Schristos {
936a1ba9ba4Schristos uint32_t off = phdrs[i].p_offset;
937a1ba9ba4Schristos uint32_t len = phdrs[i].p_filesz;
938a1ba9ba4Schristos
939a1ba9ba4Schristos *ldso_path = xmalloc (len);
940a1ba9ba4Schristos if (bfd_seek (abfd, off, SEEK_SET) != 0
941a1ba9ba4Schristos || bfd_bread (*ldso_path, len, abfd) != len)
942a1ba9ba4Schristos {
943a1ba9ba4Schristos free (*ldso_path);
944a1ba9ba4Schristos *ldso_path = NULL;
945a1ba9ba4Schristos }
946a1ba9ba4Schristos else if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG)
947a1ba9ba4Schristos sim_io_printf (sd, " PT_INTERP: %s\n", *ldso_path);
948a1ba9ba4Schristos }
949a1ba9ba4Schristos
950a1ba9ba4Schristos /* Update the load offset with a few extra pages. */
951b2396a7bSchristos fdpic_load_offset = ALIGN (max (max_load_addr, fdpic_load_offset), 0x10000);
952a1ba9ba4Schristos fdpic_load_offset += 0x10000;
953a1ba9ba4Schristos
954a1ba9ba4Schristos /* Push the summary loadmap info onto the stack last. */
955a1ba9ba4Schristos *sp -= 4;
956a1ba9ba4Schristos sim_write (sd, *sp+0, null, 2); /* loadmap.version */
957a1ba9ba4Schristos sim_write (sd, *sp+2, (void *)&nsegs, 2); /* loadmap.nsegs */
958a1ba9ba4Schristos
959a1ba9ba4Schristos ret = true;
960a1ba9ba4Schristos skip_fdpic_init:
961a1ba9ba4Schristos free (phdrs);
962a1ba9ba4Schristos
963a1ba9ba4Schristos return ret;
964a1ba9ba4Schristos }
965a1ba9ba4Schristos
966a1ba9ba4Schristos static void
bfin_user_init(SIM_DESC sd,SIM_CPU * cpu,struct bfd * abfd,char * const * argv,char * const * env)967a1ba9ba4Schristos bfin_user_init (SIM_DESC sd, SIM_CPU *cpu, struct bfd *abfd,
968b2396a7bSchristos char * const *argv, char * const *env)
969a1ba9ba4Schristos {
970a1ba9ba4Schristos /* XXX: Missing host -> target endian ... */
971a1ba9ba4Schristos /* Linux starts the user app with the stack:
972a1ba9ba4Schristos argc
973a1ba9ba4Schristos argv[0] -- pointers to the actual strings
974a1ba9ba4Schristos argv[1..N]
975a1ba9ba4Schristos NULL
976a1ba9ba4Schristos env[0]
977a1ba9ba4Schristos env[1..N]
978a1ba9ba4Schristos NULL
979a1ba9ba4Schristos auxvt[0].type -- ELF Auxiliary Vector Table
980a1ba9ba4Schristos auxvt[0].value
981a1ba9ba4Schristos auxvt[1..N]
982a1ba9ba4Schristos AT_NULL
983a1ba9ba4Schristos 0
984a1ba9ba4Schristos argv[0..N][0..M] -- actual argv/env strings
985a1ba9ba4Schristos env[0..N][0..M]
986a1ba9ba4Schristos FDPIC loadmaps -- for FDPIC apps
987a1ba9ba4Schristos So set things up the same way. */
988a1ba9ba4Schristos int i, argc, envc;
989a1ba9ba4Schristos bu32 argv_flat, env_flat;
990a1ba9ba4Schristos
991a1ba9ba4Schristos bu32 sp, sp_flat;
992a1ba9ba4Schristos
993a1ba9ba4Schristos /* start, at_phdr, at_phnum, at_base, at_entry, pt_dynamic */
994a1ba9ba4Schristos bu32 elf_addrs[6];
995a1ba9ba4Schristos bu32 auxvt;
996a1ba9ba4Schristos bu32 exec_loadmap, ldso_loadmap;
997a1ba9ba4Schristos char *ldso_path;
998a1ba9ba4Schristos
999a1ba9ba4Schristos unsigned char null[4] = { 0, 0, 0, 0 };
1000a1ba9ba4Schristos
1001a1ba9ba4Schristos host_callback *cb = STATE_CALLBACK (sd);
1002a1ba9ba4Schristos
1003a1ba9ba4Schristos elf_addrs[0] = elf_addrs[4] = bfd_get_start_address (abfd);
1004a1ba9ba4Schristos elf_addrs[1] = elf_addrs[2] = elf_addrs[3] = elf_addrs[5] = 0;
1005a1ba9ba4Schristos
1006a1ba9ba4Schristos /* Keep the load addresses consistent between runs. Also make sure we make
1007a1ba9ba4Schristos space for the fixed code region (part of the Blackfin Linux ABI). */
1008a1ba9ba4Schristos fdpic_load_offset = 0x1000;
1009a1ba9ba4Schristos
1010a1ba9ba4Schristos /* First try to load this as an FDPIC executable. */
1011a1ba9ba4Schristos sp = SPREG;
1012a1ba9ba4Schristos if (!bfin_fdpic_load (sd, cpu, STATE_PROG_BFD (sd), &sp, elf_addrs, &ldso_path))
1013a1ba9ba4Schristos goto skip_fdpic_init;
1014a1ba9ba4Schristos exec_loadmap = sp;
1015a1ba9ba4Schristos
1016a1ba9ba4Schristos /* If that worked, then load the fixed code region. We only do this for
1017a1ba9ba4Schristos FDPIC ELFs atm because they are PIEs and let us relocate them without
1018a1ba9ba4Schristos manual fixups. FLAT files however require location processing which
1019a1ba9ba4Schristos we do not do ourselves, and they link with a VMA of 0. */
1020a1ba9ba4Schristos sim_write (sd, 0x400, bfin_linux_fixed_code, sizeof (bfin_linux_fixed_code));
1021a1ba9ba4Schristos
1022a1ba9ba4Schristos /* If the FDPIC needs an interpreter, then load it up too. */
1023a1ba9ba4Schristos if (ldso_path)
1024a1ba9ba4Schristos {
1025a1ba9ba4Schristos const char *ldso_full_path = concat (simulator_sysroot, ldso_path, NULL);
1026a1ba9ba4Schristos struct bfd *ldso_bfd;
1027a1ba9ba4Schristos
1028a1ba9ba4Schristos ldso_bfd = bfd_openr (ldso_full_path, STATE_TARGET (sd));
1029a1ba9ba4Schristos if (!ldso_bfd)
1030a1ba9ba4Schristos {
1031a1ba9ba4Schristos sim_io_eprintf (sd, "bfin-sim: bfd open failed: %s\n", ldso_full_path);
1032a1ba9ba4Schristos goto static_fdpic;
1033a1ba9ba4Schristos }
1034a1ba9ba4Schristos if (!bfd_check_format (ldso_bfd, bfd_object))
1035a1ba9ba4Schristos sim_io_eprintf (sd, "bfin-sim: bfd format not valid: %s\n", ldso_full_path);
1036a1ba9ba4Schristos bfd_set_arch_info (ldso_bfd, STATE_ARCHITECTURE (sd));
1037a1ba9ba4Schristos
1038a1ba9ba4Schristos if (!bfin_fdpic_load (sd, cpu, ldso_bfd, &sp, elf_addrs, &ldso_path))
1039a1ba9ba4Schristos sim_io_eprintf (sd, "bfin-sim: FDPIC ldso failed to load: %s\n", ldso_full_path);
1040a1ba9ba4Schristos if (ldso_path)
1041a1ba9ba4Schristos sim_io_eprintf (sd, "bfin-sim: FDPIC ldso (%s) needs an interpreter (%s) !?\n",
1042a1ba9ba4Schristos ldso_full_path, ldso_path);
1043a1ba9ba4Schristos
1044a1ba9ba4Schristos ldso_loadmap = sp;
1045a1ba9ba4Schristos }
1046a1ba9ba4Schristos else
1047a1ba9ba4Schristos static_fdpic:
1048a1ba9ba4Schristos ldso_loadmap = 0;
1049a1ba9ba4Schristos
1050a1ba9ba4Schristos /* Finally setup the registers required by the FDPIC ABI. */
1051a1ba9ba4Schristos SET_DREG (7, 0); /* Zero out FINI funcptr -- ldso will set this up. */
1052a1ba9ba4Schristos SET_PREG (0, exec_loadmap); /* Exec loadmap addr. */
1053a1ba9ba4Schristos SET_PREG (1, ldso_loadmap); /* Interp loadmap addr. */
1054a1ba9ba4Schristos SET_PREG (2, elf_addrs[5]); /* PT_DYNAMIC map addr. */
1055a1ba9ba4Schristos
1056a1ba9ba4Schristos auxvt = 1;
1057a1ba9ba4Schristos SET_SPREG (sp);
1058a1ba9ba4Schristos skip_fdpic_init:
1059a1ba9ba4Schristos sim_pc_set (cpu, elf_addrs[0]);
1060a1ba9ba4Schristos
1061a1ba9ba4Schristos /* Figure out how much storage the argv/env strings need. */
1062b2396a7bSchristos argc = countargv ((char **)argv);
1063a1ba9ba4Schristos if (argc == -1)
1064a1ba9ba4Schristos argc = 0;
1065a1ba9ba4Schristos argv_flat = argc; /* NUL bytes */
1066a1ba9ba4Schristos for (i = 0; i < argc; ++i)
1067a1ba9ba4Schristos argv_flat += strlen (argv[i]);
1068a1ba9ba4Schristos
1069a1ba9ba4Schristos if (!env)
1070a1ba9ba4Schristos env = simple_env;
1071b2396a7bSchristos envc = countargv ((char **)env);
1072a1ba9ba4Schristos env_flat = envc; /* NUL bytes */
1073a1ba9ba4Schristos for (i = 0; i < envc; ++i)
1074a1ba9ba4Schristos env_flat += strlen (env[i]);
1075a1ba9ba4Schristos
1076a1ba9ba4Schristos /* Push the Auxiliary Vector Table between argv/env and actual strings. */
1077a1ba9ba4Schristos sp_flat = sp = ALIGN (SPREG - argv_flat - env_flat - 4, 4);
1078a1ba9ba4Schristos if (auxvt)
1079a1ba9ba4Schristos {
1080a1ba9ba4Schristos # define AT_PUSH(at, val) \
1081a1ba9ba4Schristos auxvt_size += 8; \
1082a1ba9ba4Schristos sp -= 4; \
1083a1ba9ba4Schristos auxvt = (val); \
1084a1ba9ba4Schristos sim_write (sd, sp, (void *)&auxvt, 4); \
1085a1ba9ba4Schristos sp -= 4; \
1086a1ba9ba4Schristos auxvt = (at); \
1087a1ba9ba4Schristos sim_write (sd, sp, (void *)&auxvt, 4)
1088a1ba9ba4Schristos unsigned int egid = getegid (), gid = getgid ();
1089a1ba9ba4Schristos unsigned int euid = geteuid (), uid = getuid ();
1090a1ba9ba4Schristos bu32 auxvt_size = 0;
1091a1ba9ba4Schristos AT_PUSH (AT_NULL, 0);
1092a1ba9ba4Schristos AT_PUSH (AT_SECURE, egid != gid || euid != uid);
1093a1ba9ba4Schristos AT_PUSH (AT_EGID, egid);
1094a1ba9ba4Schristos AT_PUSH (AT_GID, gid);
1095a1ba9ba4Schristos AT_PUSH (AT_EUID, euid);
1096a1ba9ba4Schristos AT_PUSH (AT_UID, uid);
1097a1ba9ba4Schristos AT_PUSH (AT_ENTRY, elf_addrs[4]);
1098a1ba9ba4Schristos AT_PUSH (AT_FLAGS, 0);
1099a1ba9ba4Schristos AT_PUSH (AT_BASE, elf_addrs[3]);
1100a1ba9ba4Schristos AT_PUSH (AT_PHNUM, elf_addrs[2]);
1101a1ba9ba4Schristos AT_PUSH (AT_PHENT, sizeof (Elf32_External_Phdr));
1102a1ba9ba4Schristos AT_PUSH (AT_PHDR, elf_addrs[1]);
1103a1ba9ba4Schristos AT_PUSH (AT_CLKTCK, 100); /* XXX: This ever not 100 ? */
1104a1ba9ba4Schristos AT_PUSH (AT_PAGESZ, 4096);
1105a1ba9ba4Schristos AT_PUSH (AT_HWCAP, 0);
1106a1ba9ba4Schristos #undef AT_PUSH
1107a1ba9ba4Schristos }
1108a1ba9ba4Schristos SET_SPREG (sp);
1109a1ba9ba4Schristos
1110a1ba9ba4Schristos /* Push the argc/argv/env after the auxvt. */
1111a1ba9ba4Schristos sp -= ((1 + argc + 1 + envc + 1) * 4);
1112a1ba9ba4Schristos SET_SPREG (sp);
1113a1ba9ba4Schristos
1114a1ba9ba4Schristos /* First push the argc value. */
1115a1ba9ba4Schristos sim_write (sd, sp, (void *)&argc, 4);
1116a1ba9ba4Schristos sp += 4;
1117a1ba9ba4Schristos
1118a1ba9ba4Schristos /* Then the actual argv strings so we know where to point argv[]. */
1119a1ba9ba4Schristos for (i = 0; i < argc; ++i)
1120a1ba9ba4Schristos {
1121a1ba9ba4Schristos unsigned len = strlen (argv[i]) + 1;
1122a1ba9ba4Schristos sim_write (sd, sp_flat, (void *)argv[i], len);
1123a1ba9ba4Schristos sim_write (sd, sp, (void *)&sp_flat, 4);
1124a1ba9ba4Schristos sp_flat += len;
1125a1ba9ba4Schristos sp += 4;
1126a1ba9ba4Schristos }
1127a1ba9ba4Schristos sim_write (sd, sp, null, 4);
1128a1ba9ba4Schristos sp += 4;
1129a1ba9ba4Schristos
1130a1ba9ba4Schristos /* Then the actual env strings so we know where to point env[]. */
1131a1ba9ba4Schristos for (i = 0; i < envc; ++i)
1132a1ba9ba4Schristos {
1133a1ba9ba4Schristos unsigned len = strlen (env[i]) + 1;
1134a1ba9ba4Schristos sim_write (sd, sp_flat, (void *)env[i], len);
1135a1ba9ba4Schristos sim_write (sd, sp, (void *)&sp_flat, 4);
1136a1ba9ba4Schristos sp_flat += len;
1137a1ba9ba4Schristos sp += 4;
1138a1ba9ba4Schristos }
1139a1ba9ba4Schristos
1140a1ba9ba4Schristos /* Set some callbacks. */
1141a1ba9ba4Schristos cb->syscall_map = cb_linux_syscall_map;
1142a1ba9ba4Schristos cb->errno_map = cb_linux_errno_map;
1143a1ba9ba4Schristos cb->open_map = cb_linux_open_map;
1144a1ba9ba4Schristos cb->signal_map = cb_linux_signal_map;
1145a1ba9ba4Schristos cb->stat_map = stat_map_32 = cb_linux_stat_map_32;
1146a1ba9ba4Schristos stat_map_64 = cb_linux_stat_map_64;
1147a1ba9ba4Schristos }
1148a1ba9ba4Schristos
1149a1ba9ba4Schristos static void
bfin_os_init(SIM_DESC sd,SIM_CPU * cpu,char * const * argv)1150b2396a7bSchristos bfin_os_init (SIM_DESC sd, SIM_CPU *cpu, char * const *argv)
1151a1ba9ba4Schristos {
1152a1ba9ba4Schristos /* Pass the command line via a string in R0 like Linux expects. */
1153a1ba9ba4Schristos int i;
1154a1ba9ba4Schristos bu8 byte;
1155a1ba9ba4Schristos bu32 cmdline = BFIN_L1_SRAM_SCRATCH;
1156a1ba9ba4Schristos
1157a1ba9ba4Schristos SET_DREG (0, cmdline);
1158a1ba9ba4Schristos if (argv && argv[0])
1159a1ba9ba4Schristos {
1160a1ba9ba4Schristos i = 1;
1161a1ba9ba4Schristos byte = ' ';
1162a1ba9ba4Schristos while (argv[i])
1163a1ba9ba4Schristos {
1164a1ba9ba4Schristos bu32 len = strlen (argv[i]);
1165a1ba9ba4Schristos sim_write (sd, cmdline, (void *)argv[i], len);
1166a1ba9ba4Schristos cmdline += len;
1167a1ba9ba4Schristos sim_write (sd, cmdline, &byte, 1);
1168a1ba9ba4Schristos ++cmdline;
1169a1ba9ba4Schristos ++i;
1170a1ba9ba4Schristos }
1171a1ba9ba4Schristos }
1172a1ba9ba4Schristos byte = 0;
1173a1ba9ba4Schristos sim_write (sd, cmdline, &byte, 1);
1174a1ba9ba4Schristos }
1175a1ba9ba4Schristos
1176a1ba9ba4Schristos static void
bfin_virtual_init(SIM_DESC sd,SIM_CPU * cpu)1177a1ba9ba4Schristos bfin_virtual_init (SIM_DESC sd, SIM_CPU *cpu)
1178a1ba9ba4Schristos {
1179a1ba9ba4Schristos host_callback *cb = STATE_CALLBACK (sd);
1180a1ba9ba4Schristos
1181a1ba9ba4Schristos cb->stat_map = stat_map_32 = cb_libgloss_stat_map_32;
1182a1ba9ba4Schristos stat_map_64 = NULL;
1183a1ba9ba4Schristos }
1184a1ba9ba4Schristos
1185a1ba9ba4Schristos SIM_RC
sim_create_inferior(SIM_DESC sd,struct bfd * abfd,char * const * argv,char * const * env)1186a1ba9ba4Schristos sim_create_inferior (SIM_DESC sd, struct bfd *abfd,
1187b2396a7bSchristos char * const *argv, char * const *env)
1188a1ba9ba4Schristos {
1189a1ba9ba4Schristos SIM_CPU *cpu = STATE_CPU (sd, 0);
1190a1ba9ba4Schristos SIM_ADDR addr;
1191a1ba9ba4Schristos
1192a1ba9ba4Schristos /* Set the PC. */
1193a1ba9ba4Schristos if (abfd != NULL)
1194a1ba9ba4Schristos addr = bfd_get_start_address (abfd);
1195a1ba9ba4Schristos else
1196a1ba9ba4Schristos addr = 0;
1197a1ba9ba4Schristos sim_pc_set (cpu, addr);
1198a1ba9ba4Schristos
1199b2396a7bSchristos /* Standalone mode (i.e. `run`) will take care of the argv for us in
1200b2396a7bSchristos sim_open() -> sim_parse_args(). But in debug mode (i.e. 'target sim'
1201b2396a7bSchristos with `gdb`), we need to handle it because the user can change the
1202b2396a7bSchristos argv on the fly via gdb's 'run'. */
1203b2396a7bSchristos if (STATE_PROG_ARGV (sd) != argv)
1204a1ba9ba4Schristos {
1205a1ba9ba4Schristos freeargv (STATE_PROG_ARGV (sd));
1206a1ba9ba4Schristos STATE_PROG_ARGV (sd) = dupargv (argv);
1207a1ba9ba4Schristos }
1208a1ba9ba4Schristos
1209a1ba9ba4Schristos switch (STATE_ENVIRONMENT (sd))
1210a1ba9ba4Schristos {
1211a1ba9ba4Schristos case USER_ENVIRONMENT:
1212b2396a7bSchristos bfin_user_init (sd, cpu, abfd, argv, env);
1213a1ba9ba4Schristos break;
1214a1ba9ba4Schristos case OPERATING_ENVIRONMENT:
1215b2396a7bSchristos bfin_os_init (sd, cpu, argv);
1216a1ba9ba4Schristos break;
1217a1ba9ba4Schristos default:
1218a1ba9ba4Schristos bfin_virtual_init (sd, cpu);
1219a1ba9ba4Schristos break;
1220a1ba9ba4Schristos }
1221a1ba9ba4Schristos
1222a1ba9ba4Schristos return SIM_RC_OK;
1223a1ba9ba4Schristos }
1224