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