xref: /netbsd/external/gpl3/gdb.old/dist/sim/bfin/interp.c (revision 184b2d41)
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