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