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