sim: syscall: unify memory helpers
[deliverable/binutils-gdb.git] / sim / bfin / interp.c
1 /* Simulator for Analog Devices Blackfin processors.
2
3 Copyright (C) 2005-2015 Free Software Foundation, Inc.
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"
35 #include "sim-syscall.h"
36 #include "sim-hw.h"
37
38 #include "targ-vals.h"
39
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. */
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
95 static const char cb_linux_stat_map_32[] =
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"; */
105 static const char cb_linux_stat_map_64[] =
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";
109 static 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";
113 static const char *stat_map_32, *stat_map_64;
114
115 /* Count the number of arguments in an argv. */
116 static int
117 count_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
129 /* Simulate a monitor trap, put the result into r0 and errno into r1
130 return offset by which to adjust pc. */
131
132 void
133 bfin_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;
141 char _tbuf[1024 * 3], *tbuf = _tbuf, tstr[1024];
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;
170 sc.read_mem = sim_syscall_read_mem;
171 sc.write_mem = sim_syscall_write_mem;
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 {
282 #ifdef HAVE_PREAD
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);
292 #else
293 sc.errcode = TARGET_ENOSYS;
294 #endif
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:
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]);
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:
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]);
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 {
488 #ifdef HAVE_KILL
489 sc.result = kill (sc.arg1, sc.arg2);
490 goto sys_finish;
491 #else
492 sc.result = -1;
493 sc.errcode = TARGET_ENOSYS;
494 #endif
495 }
496 break;
497
498 case CB_SYS_open:
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]);
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:
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]);
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:
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);
523 goto case_default;
524 case CB_SYS_truncate:
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]);
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:
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);
539 goto case_default;
540 case CB_SYS_stat:
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]);
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:
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]);
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);
602 SET_DREG (1, sc.result2);
603 SET_DREG (2, sc.errcode);
604 }
605
606 TRACE_SYSCALL (cpu, "%s", _tbuf);
607 }
608
609 void
610 trace_register (SIM_DESC sd,
611 sim_cpu *cpu,
612 const char *fmt,
613 ...)
614 {
615 va_list ap;
616 trace_printf (sd, cpu, "%s %s",
617 "reg: ",
618 TRACE_PREFIX (CPU_TRACE_DATA (cpu)));
619 va_start (ap, fmt);
620 trace_vprintf (sd, cpu, fmt, ap);
621 va_end (ap);
622 trace_printf (sd, cpu, "\n");
623 }
624
625 /* Execute a single instruction. */
626
627 static sim_cia
628 step_once (SIM_CPU *cpu)
629 {
630 SIM_DESC sd = CPU_STATE (cpu);
631 bu32 insn_len, oldpc = PCREG;
632 int i;
633 bool ssstep;
634
635 if (TRACE_ANY_P (cpu))
636 trace_prefix (sd, cpu, NULL_CIA, oldpc, TRACE_LINENUM_P (cpu),
637 NULL, 0, " "); /* Use a space for gcc warnings. */
638
639 /* Handle hardware single stepping when lower than EVT3, and when SYSCFG
640 has already had the SSSTEP bit enabled. */
641 ssstep = false;
642 if (STATE_ENVIRONMENT (sd) == OPERATING_ENVIRONMENT
643 && (SYSCFGREG & SYSCFG_SSSTEP))
644 {
645 int ivg = cec_get_ivg (cpu);
646 if (ivg == -1 || ivg > 3)
647 ssstep = true;
648 }
649
650 #if 0
651 /* XXX: Is this what happens on the hardware ? */
652 if (cec_get_ivg (cpu) == EVT_EMU)
653 cec_return (cpu, EVT_EMU);
654 #endif
655
656 BFIN_CPU_STATE.did_jump = false;
657
658 insn_len = interp_insn_bfin (cpu, oldpc);
659
660 /* If we executed this insn successfully, then we always decrement
661 the loop counter. We don't want to update the PC though if the
662 last insn happened to be a change in code flow (jump/etc...). */
663 if (!BFIN_CPU_STATE.did_jump)
664 SET_PCREG (hwloop_get_next_pc (cpu, oldpc, insn_len));
665 for (i = 1; i >= 0; --i)
666 if (LCREG (i) && oldpc == LBREG (i))
667 {
668 SET_LCREG (i, LCREG (i) - 1);
669 if (LCREG (i))
670 break;
671 }
672
673 ++ PROFILE_TOTAL_INSN_COUNT (CPU_PROFILE_DATA (cpu));
674
675 /* Handle hardware single stepping only if we're still lower than EVT3.
676 XXX: May not be entirely correct wrt EXCPT insns. */
677 if (ssstep)
678 {
679 int ivg = cec_get_ivg (cpu);
680 if (ivg == -1 || ivg > 3)
681 {
682 INSN_LEN = 0;
683 cec_exception (cpu, VEC_STEP);
684 }
685 }
686
687 return oldpc;
688 }
689
690 void
691 sim_engine_run (SIM_DESC sd,
692 int next_cpu_nr, /* ignore */
693 int nr_cpus, /* ignore */
694 int siggnal) /* ignore */
695 {
696 bu32 ticks;
697 SIM_CPU *cpu;
698
699 SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
700
701 cpu = STATE_CPU (sd, 0);
702
703 while (1)
704 {
705 step_once (cpu);
706 /* Process any events -- can't use tickn because it may
707 advance right over the next event. */
708 for (ticks = 0; ticks < CYCLE_DELAY; ++ticks)
709 if (sim_events_tick (sd))
710 sim_events_process (sd);
711 }
712 }
713
714 /* Cover function of sim_state_free to free the cpu buffers as well. */
715
716 static void
717 free_state (SIM_DESC sd)
718 {
719 if (STATE_MODULES (sd) != NULL)
720 sim_module_uninstall (sd);
721 sim_cpu_free_all (sd);
722 sim_state_free (sd);
723 }
724
725 /* Create an instance of the simulator. */
726
727 static void
728 bfin_initialize_cpu (SIM_DESC sd, SIM_CPU *cpu)
729 {
730 memset (&cpu->state, 0, sizeof (cpu->state));
731
732 PROFILE_TOTAL_INSN_COUNT (CPU_PROFILE_DATA (cpu)) = 0;
733
734 bfin_model_cpu_init (sd, cpu);
735
736 /* Set default stack to top of scratch pad. */
737 SET_SPREG (BFIN_DEFAULT_MEM_SIZE);
738 SET_KSPREG (BFIN_DEFAULT_MEM_SIZE);
739 SET_USPREG (BFIN_DEFAULT_MEM_SIZE);
740
741 /* This is what the hardware likes. */
742 SET_SYSCFGREG (0x30);
743 }
744
745 SIM_DESC
746 sim_open (SIM_OPEN_KIND kind, host_callback *callback,
747 struct bfd *abfd, char **argv)
748 {
749 char c;
750 int i;
751 SIM_DESC sd = sim_state_alloc (kind, callback);
752
753 /* The cpu data is kept in a separately allocated chunk of memory. */
754 if (sim_cpu_alloc_all (sd, 1, /*cgen_cpu_max_extra_bytes ()*/0) != SIM_RC_OK)
755 {
756 free_state (sd);
757 return 0;
758 }
759
760 {
761 /* XXX: Only first core gets profiled ? */
762 SIM_CPU *cpu = STATE_CPU (sd, 0);
763 STATE_WATCHPOINTS (sd)->pc = &PCREG;
764 STATE_WATCHPOINTS (sd)->sizeof_pc = sizeof (PCREG);
765 }
766
767 if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
768 {
769 free_state (sd);
770 return 0;
771 }
772
773 /* XXX: Default to the Virtual environment. */
774 if (STATE_ENVIRONMENT (sd) == ALL_ENVIRONMENT)
775 STATE_ENVIRONMENT (sd) = VIRTUAL_ENVIRONMENT;
776
777 /* These options override any module options.
778 Obviously ambiguity should be avoided, however the caller may wish to
779 augment the meaning of an option. */
780 #define e_sim_add_option_table(sd, options) \
781 do { \
782 extern const OPTION options[]; \
783 sim_add_option_table (sd, NULL, options); \
784 } while (0)
785 e_sim_add_option_table (sd, bfin_mmu_options);
786 e_sim_add_option_table (sd, bfin_mach_options);
787
788 /* getopt will print the error message so we just have to exit if this fails.
789 FIXME: Hmmm... in the case of gdb we need getopt to call
790 print_filtered. */
791 if (sim_parse_args (sd, argv) != SIM_RC_OK)
792 {
793 free_state (sd);
794 return 0;
795 }
796
797 /* Allocate external memory if none specified by user.
798 Use address 4 here in case the user wanted address 0 unmapped. */
799 if (sim_core_read_buffer (sd, NULL, read_map, &c, 4, 1) == 0)
800 {
801 bu16 emuexcpt = 0x25;
802 sim_do_commandf (sd, "memory-size 0x%lx", BFIN_DEFAULT_MEM_SIZE);
803 sim_write (sd, 0, (void *)&emuexcpt, 2);
804 }
805
806 /* Check for/establish the a reference program image. */
807 if (sim_analyze_program (sd,
808 (STATE_PROG_ARGV (sd) != NULL
809 ? *STATE_PROG_ARGV (sd)
810 : NULL), abfd) != SIM_RC_OK)
811 {
812 free_state (sd);
813 return 0;
814 }
815
816 /* Establish any remaining configuration options. */
817 if (sim_config (sd) != SIM_RC_OK)
818 {
819 free_state (sd);
820 return 0;
821 }
822
823 if (sim_post_argv_init (sd) != SIM_RC_OK)
824 {
825 free_state (sd);
826 return 0;
827 }
828
829 /* CPU specific initialization. */
830 for (i = 0; i < MAX_NR_PROCESSORS; ++i)
831 {
832 SIM_CPU *cpu = STATE_CPU (sd, i);
833 bfin_initialize_cpu (sd, cpu);
834 }
835
836 return sd;
837 }
838
839 void
840 sim_close (SIM_DESC sd, int quitting)
841 {
842 sim_module_uninstall (sd);
843 }
844
845 /* Some utils don't like having a NULL environ. */
846 static const char * const simple_env[] = { "HOME=/", "PATH=/bin", NULL };
847
848 static bu32 fdpic_load_offset;
849
850 static bool
851 bfin_fdpic_load (SIM_DESC sd, SIM_CPU *cpu, struct bfd *abfd, bu32 *sp,
852 bu32 *elf_addrs, char **ldso_path)
853 {
854 bool ret;
855 int i;
856
857 Elf_Internal_Ehdr *iehdr;
858 Elf32_External_Ehdr ehdr;
859 Elf_Internal_Phdr *phdrs;
860 unsigned char *data;
861 long phdr_size;
862 int phdrc;
863 bu32 nsegs;
864
865 bu32 max_load_addr;
866
867 unsigned char null[4] = { 0, 0, 0, 0 };
868
869 ret = false;
870 *ldso_path = NULL;
871
872 /* See if this an FDPIC ELF. */
873 phdrs = NULL;
874 if (!abfd)
875 goto skip_fdpic_init;
876 if (bfd_seek (abfd, 0, SEEK_SET) != 0)
877 goto skip_fdpic_init;
878 if (bfd_bread (&ehdr, sizeof (ehdr), abfd) != sizeof (ehdr))
879 goto skip_fdpic_init;
880 iehdr = elf_elfheader (abfd);
881 if (!(iehdr->e_flags & EF_BFIN_FDPIC))
882 goto skip_fdpic_init;
883
884 if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG)
885 sim_io_printf (sd, "Loading FDPIC ELF %s\n Load base: %#x\n ELF entry: %#x\n",
886 bfd_get_filename (abfd), fdpic_load_offset, elf_addrs[0]);
887
888 /* Grab the Program Headers to set up the loadsegs on the stack. */
889 phdr_size = bfd_get_elf_phdr_upper_bound (abfd);
890 if (phdr_size == -1)
891 goto skip_fdpic_init;
892 phdrs = xmalloc (phdr_size);
893 phdrc = bfd_get_elf_phdrs (abfd, phdrs);
894 if (phdrc == -1)
895 goto skip_fdpic_init;
896
897 /* Push the Ehdr onto the stack. */
898 *sp -= sizeof (ehdr);
899 elf_addrs[3] = *sp;
900 sim_write (sd, *sp, (void *)&ehdr, sizeof (ehdr));
901 if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG)
902 sim_io_printf (sd, " Elf_Ehdr: %#x\n", *sp);
903
904 /* Since we're relocating things ourselves, we need to relocate
905 the start address as well. */
906 elf_addrs[0] = bfd_get_start_address (abfd) + fdpic_load_offset;
907
908 /* And the Exec's Phdrs onto the stack. */
909 if (STATE_PROG_BFD (sd) == abfd)
910 {
911 elf_addrs[4] = elf_addrs[0];
912
913 phdr_size = iehdr->e_phentsize * iehdr->e_phnum;
914 if (bfd_seek (abfd, iehdr->e_phoff, SEEK_SET) != 0)
915 goto skip_fdpic_init;
916 data = xmalloc (phdr_size);
917 if (bfd_bread (data, phdr_size, abfd) != phdr_size)
918 goto skip_fdpic_init;
919 *sp -= phdr_size;
920 elf_addrs[1] = *sp;
921 elf_addrs[2] = phdrc;
922 sim_write (sd, *sp, data, phdr_size);
923 free (data);
924 if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG)
925 sim_io_printf (sd, " Elf_Phdrs: %#x\n", *sp);
926 }
927
928 /* Now push all the loadsegs. */
929 nsegs = 0;
930 max_load_addr = 0;
931 for (i = phdrc; i >= 0; --i)
932 if (phdrs[i].p_type == PT_LOAD)
933 {
934 Elf_Internal_Phdr *p = &phdrs[i];
935 bu32 paddr, vaddr, memsz, filesz;
936
937 paddr = p->p_paddr + fdpic_load_offset;
938 vaddr = p->p_vaddr;
939 memsz = p->p_memsz;
940 filesz = p->p_filesz;
941
942 if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG)
943 sim_io_printf (sd, " PHDR %i: vma %#x lma %#x filesz %#x memsz %#x\n",
944 i, vaddr, paddr, filesz, memsz);
945
946 data = xmalloc (memsz);
947 if (memsz != filesz)
948 memset (data + filesz, 0, memsz - filesz);
949
950 if (bfd_seek (abfd, p->p_offset, SEEK_SET) == 0
951 && bfd_bread (data, filesz, abfd) == filesz)
952 sim_write (sd, paddr, data, memsz);
953
954 free (data);
955
956 max_load_addr = MAX (paddr + memsz, max_load_addr);
957
958 *sp -= 12;
959 sim_write (sd, *sp+0, (void *)&paddr, 4); /* loadseg.addr */
960 sim_write (sd, *sp+4, (void *)&vaddr, 4); /* loadseg.p_vaddr */
961 sim_write (sd, *sp+8, (void *)&memsz, 4); /* loadseg.p_memsz */
962 ++nsegs;
963 }
964 else if (phdrs[i].p_type == PT_DYNAMIC)
965 {
966 elf_addrs[5] = phdrs[i].p_paddr + fdpic_load_offset;
967 if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG)
968 sim_io_printf (sd, " PT_DYNAMIC: %#x\n", elf_addrs[5]);
969 }
970 else if (phdrs[i].p_type == PT_INTERP)
971 {
972 uint32_t off = phdrs[i].p_offset;
973 uint32_t len = phdrs[i].p_filesz;
974
975 *ldso_path = xmalloc (len);
976 if (bfd_seek (abfd, off, SEEK_SET) != 0
977 || bfd_bread (*ldso_path, len, abfd) != len)
978 {
979 free (*ldso_path);
980 *ldso_path = NULL;
981 }
982 else if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG)
983 sim_io_printf (sd, " PT_INTERP: %s\n", *ldso_path);
984 }
985
986 /* Update the load offset with a few extra pages. */
987 fdpic_load_offset = ALIGN (MAX (max_load_addr, fdpic_load_offset), 0x10000);
988 fdpic_load_offset += 0x10000;
989
990 /* Push the summary loadmap info onto the stack last. */
991 *sp -= 4;
992 sim_write (sd, *sp+0, null, 2); /* loadmap.version */
993 sim_write (sd, *sp+2, (void *)&nsegs, 2); /* loadmap.nsegs */
994
995 ret = true;
996 skip_fdpic_init:
997 free (phdrs);
998
999 return ret;
1000 }
1001
1002 static void
1003 bfin_user_init (SIM_DESC sd, SIM_CPU *cpu, struct bfd *abfd,
1004 const char * const *argv, const char * const *env)
1005 {
1006 /* XXX: Missing host -> target endian ... */
1007 /* Linux starts the user app with the stack:
1008 argc
1009 argv[0] -- pointers to the actual strings
1010 argv[1..N]
1011 NULL
1012 env[0]
1013 env[1..N]
1014 NULL
1015 auxvt[0].type -- ELF Auxiliary Vector Table
1016 auxvt[0].value
1017 auxvt[1..N]
1018 AT_NULL
1019 0
1020 argv[0..N][0..M] -- actual argv/env strings
1021 env[0..N][0..M]
1022 FDPIC loadmaps -- for FDPIC apps
1023 So set things up the same way. */
1024 int i, argc, envc;
1025 bu32 argv_flat, env_flat;
1026
1027 bu32 sp, sp_flat;
1028
1029 /* start, at_phdr, at_phnum, at_base, at_entry, pt_dynamic */
1030 bu32 elf_addrs[6];
1031 bu32 auxvt;
1032 bu32 exec_loadmap, ldso_loadmap;
1033 char *ldso_path;
1034
1035 unsigned char null[4] = { 0, 0, 0, 0 };
1036
1037 host_callback *cb = STATE_CALLBACK (sd);
1038
1039 elf_addrs[0] = elf_addrs[4] = bfd_get_start_address (abfd);
1040 elf_addrs[1] = elf_addrs[2] = elf_addrs[3] = elf_addrs[5] = 0;
1041
1042 /* Keep the load addresses consistent between runs. Also make sure we make
1043 space for the fixed code region (part of the Blackfin Linux ABI). */
1044 fdpic_load_offset = 0x1000;
1045
1046 /* First try to load this as an FDPIC executable. */
1047 sp = SPREG;
1048 if (!bfin_fdpic_load (sd, cpu, STATE_PROG_BFD (sd), &sp, elf_addrs, &ldso_path))
1049 goto skip_fdpic_init;
1050 exec_loadmap = sp;
1051
1052 /* If that worked, then load the fixed code region. We only do this for
1053 FDPIC ELFs atm because they are PIEs and let us relocate them without
1054 manual fixups. FLAT files however require location processing which
1055 we do not do ourselves, and they link with a VMA of 0. */
1056 sim_write (sd, 0x400, bfin_linux_fixed_code, sizeof (bfin_linux_fixed_code));
1057
1058 /* If the FDPIC needs an interpreter, then load it up too. */
1059 if (ldso_path)
1060 {
1061 const char *ldso_full_path = concat (simulator_sysroot, ldso_path, NULL);
1062 struct bfd *ldso_bfd;
1063
1064 ldso_bfd = bfd_openr (ldso_full_path, STATE_TARGET (sd));
1065 if (!ldso_bfd)
1066 {
1067 sim_io_eprintf (sd, "bfin-sim: bfd open failed: %s\n", ldso_full_path);
1068 goto static_fdpic;
1069 }
1070 if (!bfd_check_format (ldso_bfd, bfd_object))
1071 sim_io_eprintf (sd, "bfin-sim: bfd format not valid: %s\n", ldso_full_path);
1072 bfd_set_arch_info (ldso_bfd, STATE_ARCHITECTURE (sd));
1073
1074 if (!bfin_fdpic_load (sd, cpu, ldso_bfd, &sp, elf_addrs, &ldso_path))
1075 sim_io_eprintf (sd, "bfin-sim: FDPIC ldso failed to load: %s\n", ldso_full_path);
1076 if (ldso_path)
1077 sim_io_eprintf (sd, "bfin-sim: FDPIC ldso (%s) needs an interpreter (%s) !?\n",
1078 ldso_full_path, ldso_path);
1079
1080 ldso_loadmap = sp;
1081 }
1082 else
1083 static_fdpic:
1084 ldso_loadmap = 0;
1085
1086 /* Finally setup the registers required by the FDPIC ABI. */
1087 SET_DREG (7, 0); /* Zero out FINI funcptr -- ldso will set this up. */
1088 SET_PREG (0, exec_loadmap); /* Exec loadmap addr. */
1089 SET_PREG (1, ldso_loadmap); /* Interp loadmap addr. */
1090 SET_PREG (2, elf_addrs[5]); /* PT_DYNAMIC map addr. */
1091
1092 auxvt = 1;
1093 SET_SPREG (sp);
1094 skip_fdpic_init:
1095 sim_pc_set (cpu, elf_addrs[0]);
1096
1097 /* Figure out how much storage the argv/env strings need. */
1098 argc = count_argc (argv);
1099 if (argc == -1)
1100 argc = 0;
1101 argv_flat = argc; /* NUL bytes */
1102 for (i = 0; i < argc; ++i)
1103 argv_flat += strlen (argv[i]);
1104
1105 if (!env)
1106 env = simple_env;
1107 envc = count_argc (env);
1108 env_flat = envc; /* NUL bytes */
1109 for (i = 0; i < envc; ++i)
1110 env_flat += strlen (env[i]);
1111
1112 /* Push the Auxiliary Vector Table between argv/env and actual strings. */
1113 sp_flat = sp = ALIGN (SPREG - argv_flat - env_flat - 4, 4);
1114 if (auxvt)
1115 {
1116 # define AT_PUSH(at, val) \
1117 auxvt_size += 8; \
1118 sp -= 4; \
1119 auxvt = (val); \
1120 sim_write (sd, sp, (void *)&auxvt, 4); \
1121 sp -= 4; \
1122 auxvt = (at); \
1123 sim_write (sd, sp, (void *)&auxvt, 4)
1124 unsigned int egid = getegid (), gid = getgid ();
1125 unsigned int euid = geteuid (), uid = getuid ();
1126 bu32 auxvt_size = 0;
1127 AT_PUSH (AT_NULL, 0);
1128 AT_PUSH (AT_SECURE, egid != gid || euid != uid);
1129 AT_PUSH (AT_EGID, egid);
1130 AT_PUSH (AT_GID, gid);
1131 AT_PUSH (AT_EUID, euid);
1132 AT_PUSH (AT_UID, uid);
1133 AT_PUSH (AT_ENTRY, elf_addrs[4]);
1134 AT_PUSH (AT_FLAGS, 0);
1135 AT_PUSH (AT_BASE, elf_addrs[3]);
1136 AT_PUSH (AT_PHNUM, elf_addrs[2]);
1137 AT_PUSH (AT_PHENT, sizeof (Elf32_External_Phdr));
1138 AT_PUSH (AT_PHDR, elf_addrs[1]);
1139 AT_PUSH (AT_CLKTCK, 100); /* XXX: This ever not 100 ? */
1140 AT_PUSH (AT_PAGESZ, 4096);
1141 AT_PUSH (AT_HWCAP, 0);
1142 #undef AT_PUSH
1143 }
1144 SET_SPREG (sp);
1145
1146 /* Push the argc/argv/env after the auxvt. */
1147 sp -= ((1 + argc + 1 + envc + 1) * 4);
1148 SET_SPREG (sp);
1149
1150 /* First push the argc value. */
1151 sim_write (sd, sp, (void *)&argc, 4);
1152 sp += 4;
1153
1154 /* Then the actual argv strings so we know where to point argv[]. */
1155 for (i = 0; i < argc; ++i)
1156 {
1157 unsigned len = strlen (argv[i]) + 1;
1158 sim_write (sd, sp_flat, (void *)argv[i], len);
1159 sim_write (sd, sp, (void *)&sp_flat, 4);
1160 sp_flat += len;
1161 sp += 4;
1162 }
1163 sim_write (sd, sp, null, 4);
1164 sp += 4;
1165
1166 /* Then the actual env strings so we know where to point env[]. */
1167 for (i = 0; i < envc; ++i)
1168 {
1169 unsigned len = strlen (env[i]) + 1;
1170 sim_write (sd, sp_flat, (void *)env[i], len);
1171 sim_write (sd, sp, (void *)&sp_flat, 4);
1172 sp_flat += len;
1173 sp += 4;
1174 }
1175
1176 /* Set some callbacks. */
1177 cb->syscall_map = cb_linux_syscall_map;
1178 cb->errno_map = cb_linux_errno_map;
1179 cb->open_map = cb_linux_open_map;
1180 cb->signal_map = cb_linux_signal_map;
1181 cb->stat_map = stat_map_32 = cb_linux_stat_map_32;
1182 stat_map_64 = cb_linux_stat_map_64;
1183 }
1184
1185 static void
1186 bfin_os_init (SIM_DESC sd, SIM_CPU *cpu, const char * const *argv)
1187 {
1188 /* Pass the command line via a string in R0 like Linux expects. */
1189 int i;
1190 bu8 byte;
1191 bu32 cmdline = BFIN_L1_SRAM_SCRATCH;
1192
1193 SET_DREG (0, cmdline);
1194 if (argv && argv[0])
1195 {
1196 i = 1;
1197 byte = ' ';
1198 while (argv[i])
1199 {
1200 bu32 len = strlen (argv[i]);
1201 sim_write (sd, cmdline, (void *)argv[i], len);
1202 cmdline += len;
1203 sim_write (sd, cmdline, &byte, 1);
1204 ++cmdline;
1205 ++i;
1206 }
1207 }
1208 byte = 0;
1209 sim_write (sd, cmdline, &byte, 1);
1210 }
1211
1212 static void
1213 bfin_virtual_init (SIM_DESC sd, SIM_CPU *cpu)
1214 {
1215 host_callback *cb = STATE_CALLBACK (sd);
1216
1217 cb->stat_map = stat_map_32 = cb_libgloss_stat_map_32;
1218 stat_map_64 = NULL;
1219 }
1220
1221 SIM_RC
1222 sim_create_inferior (SIM_DESC sd, struct bfd *abfd,
1223 char **argv, char **env)
1224 {
1225 SIM_CPU *cpu = STATE_CPU (sd, 0);
1226 SIM_ADDR addr;
1227
1228 /* Set the PC. */
1229 if (abfd != NULL)
1230 addr = bfd_get_start_address (abfd);
1231 else
1232 addr = 0;
1233 sim_pc_set (cpu, addr);
1234
1235 /* Standalone mode (i.e. `bfin-...-run`) will take care of the argv
1236 for us in sim_open() -> sim_parse_args(). But in debug mode (i.e.
1237 'target sim' with `bfin-...-gdb`), we need to handle it. */
1238 if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG)
1239 {
1240 freeargv (STATE_PROG_ARGV (sd));
1241 STATE_PROG_ARGV (sd) = dupargv (argv);
1242 }
1243
1244 switch (STATE_ENVIRONMENT (sd))
1245 {
1246 case USER_ENVIRONMENT:
1247 bfin_user_init (sd, cpu, abfd, (void *)argv, (void *)env);
1248 break;
1249 case OPERATING_ENVIRONMENT:
1250 bfin_os_init (sd, cpu, (void *)argv);
1251 break;
1252 default:
1253 bfin_virtual_init (sd, cpu);
1254 break;
1255 }
1256
1257 return SIM_RC_OK;
1258 }
This page took 0.055717 seconds and 5 git commands to generate.