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