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