]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - sim/bfin/interp.c
sim: trace: add a basic cpu register class
[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
823void
824sim_close (SIM_DESC sd, int quitting)
825{
826 sim_module_uninstall (sd);
827}
828
829/* Some utils don't like having a NULL environ. */
830static const char * const simple_env[] = { "HOME=/", "PATH=/bin", NULL };
831
832static bu32 fdpic_load_offset;
833
834static bool
835bfin_fdpic_load (SIM_DESC sd, SIM_CPU *cpu, struct bfd *abfd, bu32 *sp,
836 bu32 *elf_addrs, char **ldso_path)
837{
838 bool ret;
839 int i;
840
841 Elf_Internal_Ehdr *iehdr;
842 Elf32_External_Ehdr ehdr;
843 Elf_Internal_Phdr *phdrs;
844 unsigned char *data;
845 long phdr_size;
846 int phdrc;
847 bu32 nsegs;
848
849 bu32 max_load_addr;
850
851 unsigned char null[4] = { 0, 0, 0, 0 };
852
853 ret = false;
854 *ldso_path = NULL;
855
856 /* See if this an FDPIC ELF. */
857 phdrs = NULL;
858 if (!abfd)
859 goto skip_fdpic_init;
860 if (bfd_seek (abfd, 0, SEEK_SET) != 0)
861 goto skip_fdpic_init;
862 if (bfd_bread (&ehdr, sizeof (ehdr), abfd) != sizeof (ehdr))
863 goto skip_fdpic_init;
864 iehdr = elf_elfheader (abfd);
865 if (!(iehdr->e_flags & EF_BFIN_FDPIC))
866 goto skip_fdpic_init;
867
868 if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG)
869 sim_io_printf (sd, "Loading FDPIC ELF %s\n Load base: %#x\n ELF entry: %#x\n",
870 bfd_get_filename (abfd), fdpic_load_offset, elf_addrs[0]);
871
872 /* Grab the Program Headers to set up the loadsegs on the stack. */
873 phdr_size = bfd_get_elf_phdr_upper_bound (abfd);
874 if (phdr_size == -1)
875 goto skip_fdpic_init;
876 phdrs = xmalloc (phdr_size);
877 phdrc = bfd_get_elf_phdrs (abfd, phdrs);
878 if (phdrc == -1)
879 goto skip_fdpic_init;
880
881 /* Push the Ehdr onto the stack. */
882 *sp -= sizeof (ehdr);
883 elf_addrs[3] = *sp;
884 sim_write (sd, *sp, (void *)&ehdr, sizeof (ehdr));
885 if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG)
886 sim_io_printf (sd, " Elf_Ehdr: %#x\n", *sp);
887
888 /* Since we're relocating things ourselves, we need to relocate
889 the start address as well. */
890 elf_addrs[0] = bfd_get_start_address (abfd) + fdpic_load_offset;
891
892 /* And the Exec's Phdrs onto the stack. */
893 if (STATE_PROG_BFD (sd) == abfd)
894 {
895 elf_addrs[4] = elf_addrs[0];
896
897 phdr_size = iehdr->e_phentsize * iehdr->e_phnum;
898 if (bfd_seek (abfd, iehdr->e_phoff, SEEK_SET) != 0)
899 goto skip_fdpic_init;
900 data = xmalloc (phdr_size);
901 if (bfd_bread (data, phdr_size, abfd) != phdr_size)
902 goto skip_fdpic_init;
903 *sp -= phdr_size;
904 elf_addrs[1] = *sp;
905 elf_addrs[2] = phdrc;
906 sim_write (sd, *sp, data, phdr_size);
907 free (data);
908 if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG)
909 sim_io_printf (sd, " Elf_Phdrs: %#x\n", *sp);
910 }
911
912 /* Now push all the loadsegs. */
913 nsegs = 0;
914 max_load_addr = 0;
915 for (i = phdrc; i >= 0; --i)
916 if (phdrs[i].p_type == PT_LOAD)
917 {
918 Elf_Internal_Phdr *p = &phdrs[i];
919 bu32 paddr, vaddr, memsz, filesz;
920
921 paddr = p->p_paddr + fdpic_load_offset;
922 vaddr = p->p_vaddr;
923 memsz = p->p_memsz;
924 filesz = p->p_filesz;
925
926 if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG)
927 sim_io_printf (sd, " PHDR %i: vma %#x lma %#x filesz %#x memsz %#x\n",
928 i, vaddr, paddr, filesz, memsz);
929
930 data = xmalloc (memsz);
931 if (memsz != filesz)
932 memset (data + filesz, 0, memsz - filesz);
933
934 if (bfd_seek (abfd, p->p_offset, SEEK_SET) == 0
935 && bfd_bread (data, filesz, abfd) == filesz)
936 sim_write (sd, paddr, data, memsz);
937
938 free (data);
939
940 max_load_addr = MAX (paddr + memsz, max_load_addr);
941
942 *sp -= 12;
943 sim_write (sd, *sp+0, (void *)&paddr, 4); /* loadseg.addr */
944 sim_write (sd, *sp+4, (void *)&vaddr, 4); /* loadseg.p_vaddr */
945 sim_write (sd, *sp+8, (void *)&memsz, 4); /* loadseg.p_memsz */
946 ++nsegs;
947 }
948 else if (phdrs[i].p_type == PT_DYNAMIC)
949 {
950 elf_addrs[5] = phdrs[i].p_paddr + fdpic_load_offset;
951 if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG)
952 sim_io_printf (sd, " PT_DYNAMIC: %#x\n", elf_addrs[5]);
953 }
954 else if (phdrs[i].p_type == PT_INTERP)
955 {
956 uint32_t off = phdrs[i].p_offset;
957 uint32_t len = phdrs[i].p_filesz;
958
959 *ldso_path = xmalloc (len);
960 if (bfd_seek (abfd, off, SEEK_SET) != 0
961 || bfd_bread (*ldso_path, len, abfd) != len)
962 {
963 free (*ldso_path);
964 *ldso_path = NULL;
965 }
966 else if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG)
967 sim_io_printf (sd, " PT_INTERP: %s\n", *ldso_path);
968 }
969
970 /* Update the load offset with a few extra pages. */
971 fdpic_load_offset = ALIGN (MAX (max_load_addr, fdpic_load_offset), 0x10000);
972 fdpic_load_offset += 0x10000;
973
974 /* Push the summary loadmap info onto the stack last. */
975 *sp -= 4;
976 sim_write (sd, *sp+0, null, 2); /* loadmap.version */
977 sim_write (sd, *sp+2, (void *)&nsegs, 2); /* loadmap.nsegs */
978
979 ret = true;
980 skip_fdpic_init:
981 free (phdrs);
982
983 return ret;
984}
985
986static void
987bfin_user_init (SIM_DESC sd, SIM_CPU *cpu, struct bfd *abfd,
988 const char * const *argv, const char * const *env)
989{
990 /* XXX: Missing host -> target endian ... */
991 /* Linux starts the user app with the stack:
992 argc
993 argv[0] -- pointers to the actual strings
994 argv[1..N]
995 NULL
996 env[0]
997 env[1..N]
998 NULL
999 auxvt[0].type -- ELF Auxiliary Vector Table
1000 auxvt[0].value
1001 auxvt[1..N]
1002 AT_NULL
1003 0
1004 argv[0..N][0..M] -- actual argv/env strings
1005 env[0..N][0..M]
1006 FDPIC loadmaps -- for FDPIC apps
1007 So set things up the same way. */
1008 int i, argc, envc;
1009 bu32 argv_flat, env_flat;
1010
1011 bu32 sp, sp_flat;
1012
1013 /* start, at_phdr, at_phnum, at_base, at_entry, pt_dynamic */
1014 bu32 elf_addrs[6];
e4967d72 1015 bu32 auxvt;
ef016f83
MF
1016 bu32 exec_loadmap, ldso_loadmap;
1017 char *ldso_path;
1018
1019 unsigned char null[4] = { 0, 0, 0, 0 };
1020
1021 host_callback *cb = STATE_CALLBACK (sd);
1022
1023 elf_addrs[0] = elf_addrs[4] = bfd_get_start_address (abfd);
1024 elf_addrs[1] = elf_addrs[2] = elf_addrs[3] = elf_addrs[5] = 0;
1025
1026 /* Keep the load addresses consistent between runs. Also make sure we make
1027 space for the fixed code region (part of the Blackfin Linux ABI). */
1028 fdpic_load_offset = 0x1000;
1029
1030 /* First try to load this as an FDPIC executable. */
1031 sp = SPREG;
1032 if (!bfin_fdpic_load (sd, cpu, STATE_PROG_BFD (sd), &sp, elf_addrs, &ldso_path))
1033 goto skip_fdpic_init;
1034 exec_loadmap = sp;
1035
1036 /* If that worked, then load the fixed code region. We only do this for
1037 FDPIC ELFs atm because they are PIEs and let us relocate them without
1038 manual fixups. FLAT files however require location processing which
1039 we do not do ourselves, and they link with a VMA of 0. */
1040 sim_write (sd, 0x400, bfin_linux_fixed_code, sizeof (bfin_linux_fixed_code));
1041
1042 /* If the FDPIC needs an interpreter, then load it up too. */
1043 if (ldso_path)
1044 {
1045 const char *ldso_full_path = concat (simulator_sysroot, ldso_path, NULL);
1046 struct bfd *ldso_bfd;
1047
1048 ldso_bfd = bfd_openr (ldso_full_path, STATE_TARGET (sd));
1049 if (!ldso_bfd)
1050 {
1051 sim_io_eprintf (sd, "bfin-sim: bfd open failed: %s\n", ldso_full_path);
1052 goto static_fdpic;
1053 }
1054 if (!bfd_check_format (ldso_bfd, bfd_object))
1055 sim_io_eprintf (sd, "bfin-sim: bfd format not valid: %s\n", ldso_full_path);
1056 bfd_set_arch_info (ldso_bfd, STATE_ARCHITECTURE (sd));
1057
1058 if (!bfin_fdpic_load (sd, cpu, ldso_bfd, &sp, elf_addrs, &ldso_path))
1059 sim_io_eprintf (sd, "bfin-sim: FDPIC ldso failed to load: %s\n", ldso_full_path);
1060 if (ldso_path)
1061 sim_io_eprintf (sd, "bfin-sim: FDPIC ldso (%s) needs an interpreter (%s) !?\n",
1062 ldso_full_path, ldso_path);
1063
1064 ldso_loadmap = sp;
1065 }
1066 else
1067 static_fdpic:
1068 ldso_loadmap = 0;
1069
1070 /* Finally setup the registers required by the FDPIC ABI. */
1071 SET_DREG (7, 0); /* Zero out FINI funcptr -- ldso will set this up. */
1072 SET_PREG (0, exec_loadmap); /* Exec loadmap addr. */
1073 SET_PREG (1, ldso_loadmap); /* Interp loadmap addr. */
1074 SET_PREG (2, elf_addrs[5]); /* PT_DYNAMIC map addr. */
1075
1076 auxvt = 1;
1077 SET_SPREG (sp);
1078 skip_fdpic_init:
1079 sim_pc_set (cpu, elf_addrs[0]);
1080
1081 /* Figure out how much storage the argv/env strings need. */
1082 argc = count_argc (argv);
1083 if (argc == -1)
1084 argc = 0;
1085 argv_flat = argc; /* NUL bytes */
1086 for (i = 0; i < argc; ++i)
1087 argv_flat += strlen (argv[i]);
1088
1089 if (!env)
1090 env = simple_env;
1091 envc = count_argc (env);
1092 env_flat = envc; /* NUL bytes */
1093 for (i = 0; i < envc; ++i)
1094 env_flat += strlen (env[i]);
1095
1096 /* Push the Auxiliary Vector Table between argv/env and actual strings. */
1097 sp_flat = sp = ALIGN (SPREG - argv_flat - env_flat - 4, 4);
1098 if (auxvt)
1099 {
1100# define AT_PUSH(at, val) \
1101 auxvt_size += 8; \
1102 sp -= 4; \
1103 auxvt = (val); \
1104 sim_write (sd, sp, (void *)&auxvt, 4); \
1105 sp -= 4; \
1106 auxvt = (at); \
1107 sim_write (sd, sp, (void *)&auxvt, 4)
ef016f83
MF
1108 unsigned int egid = getegid (), gid = getgid ();
1109 unsigned int euid = geteuid (), uid = getuid ();
e4967d72 1110 bu32 auxvt_size = 0;
ef016f83
MF
1111 AT_PUSH (AT_NULL, 0);
1112 AT_PUSH (AT_SECURE, egid != gid || euid != uid);
1113 AT_PUSH (AT_EGID, egid);
1114 AT_PUSH (AT_GID, gid);
1115 AT_PUSH (AT_EUID, euid);
1116 AT_PUSH (AT_UID, uid);
1117 AT_PUSH (AT_ENTRY, elf_addrs[4]);
1118 AT_PUSH (AT_FLAGS, 0);
1119 AT_PUSH (AT_BASE, elf_addrs[3]);
1120 AT_PUSH (AT_PHNUM, elf_addrs[2]);
1121 AT_PUSH (AT_PHENT, sizeof (Elf32_External_Phdr));
1122 AT_PUSH (AT_PHDR, elf_addrs[1]);
1123 AT_PUSH (AT_CLKTCK, 100); /* XXX: This ever not 100 ? */
1124 AT_PUSH (AT_PAGESZ, 4096);
1125 AT_PUSH (AT_HWCAP, 0);
1126#undef AT_PUSH
1127 }
1128 SET_SPREG (sp);
1129
1130 /* Push the argc/argv/env after the auxvt. */
1131 sp -= ((1 + argc + 1 + envc + 1) * 4);
1132 SET_SPREG (sp);
1133
1134 /* First push the argc value. */
1135 sim_write (sd, sp, (void *)&argc, 4);
1136 sp += 4;
1137
1138 /* Then the actual argv strings so we know where to point argv[]. */
1139 for (i = 0; i < argc; ++i)
1140 {
1141 unsigned len = strlen (argv[i]) + 1;
1142 sim_write (sd, sp_flat, (void *)argv[i], len);
1143 sim_write (sd, sp, (void *)&sp_flat, 4);
1144 sp_flat += len;
1145 sp += 4;
1146 }
1147 sim_write (sd, sp, null, 4);
1148 sp += 4;
1149
1150 /* Then the actual env strings so we know where to point env[]. */
1151 for (i = 0; i < envc; ++i)
1152 {
1153 unsigned len = strlen (env[i]) + 1;
1154 sim_write (sd, sp_flat, (void *)env[i], len);
1155 sim_write (sd, sp, (void *)&sp_flat, 4);
1156 sp_flat += len;
1157 sp += 4;
1158 }
1159
1160 /* Set some callbacks. */
1161 cb->syscall_map = cb_linux_syscall_map;
1162 cb->errno_map = cb_linux_errno_map;
1163 cb->open_map = cb_linux_open_map;
1164 cb->signal_map = cb_linux_signal_map;
a931db6a
MF
1165 cb->stat_map = stat_map_32 = cb_linux_stat_map_32;
1166 stat_map_64 = cb_linux_stat_map_64;
ef016f83
MF
1167}
1168
1169static void
1170bfin_os_init (SIM_DESC sd, SIM_CPU *cpu, const char * const *argv)
1171{
1172 /* Pass the command line via a string in R0 like Linux expects. */
1173 int i;
1174 bu8 byte;
1175 bu32 cmdline = BFIN_L1_SRAM_SCRATCH;
1176
1177 SET_DREG (0, cmdline);
1178 if (argv && argv[0])
1179 {
1180 i = 1;
1181 byte = ' ';
1182 while (argv[i])
1183 {
1184 bu32 len = strlen (argv[i]);
1185 sim_write (sd, cmdline, (void *)argv[i], len);
1186 cmdline += len;
1187 sim_write (sd, cmdline, &byte, 1);
1188 ++cmdline;
1189 ++i;
1190 }
1191 }
1192 byte = 0;
1193 sim_write (sd, cmdline, &byte, 1);
1194}
1195
a931db6a
MF
1196static void
1197bfin_virtual_init (SIM_DESC sd, SIM_CPU *cpu)
1198{
1199 host_callback *cb = STATE_CALLBACK (sd);
1200
1201 cb->stat_map = stat_map_32 = cb_libgloss_stat_map_32;
1202 stat_map_64 = NULL;
1203}
1204
ef016f83
MF
1205SIM_RC
1206sim_create_inferior (SIM_DESC sd, struct bfd *abfd,
1207 char **argv, char **env)
1208{
1209 SIM_CPU *cpu = STATE_CPU (sd, 0);
1210 SIM_ADDR addr;
1211
1212 /* Set the PC. */
1213 if (abfd != NULL)
1214 addr = bfd_get_start_address (abfd);
1215 else
1216 addr = 0;
1217 sim_pc_set (cpu, addr);
1218
1219 /* Standalone mode (i.e. `bfin-...-run`) will take care of the argv
1220 for us in sim_open() -> sim_parse_args(). But in debug mode (i.e.
1221 'target sim' with `bfin-...-gdb`), we need to handle it. */
1222 if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG)
1223 {
886ea33b 1224 freeargv (STATE_PROG_ARGV (sd));
ef016f83
MF
1225 STATE_PROG_ARGV (sd) = dupargv (argv);
1226 }
1227
1228 switch (STATE_ENVIRONMENT (sd))
1229 {
1230 case USER_ENVIRONMENT:
1231 bfin_user_init (sd, cpu, abfd, (void *)argv, (void *)env);
1232 break;
1233 case OPERATING_ENVIRONMENT:
1234 bfin_os_init (sd, cpu, (void *)argv);
1235 break;
1236 default:
a931db6a 1237 bfin_virtual_init (sd, cpu);
ef016f83
MF
1238 break;
1239 }
1240
1241 return SIM_RC_OK;
1242}