Automatic date update in version.in
[binutils-gdb.git] / sim / bfin / interp.c
blob4312adc75f82b19fe51f2aaf866077b4d10b2026
1 /* Simulator for Analog Devices Blackfin processors.
3 Copyright (C) 2005-2024 Free Software Foundation, Inc.
4 Contributed by Analog Devices, Inc.
6 This file is part of simulators.
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.
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.
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/>. */
21 /* This must come before any other includes. */
22 #include "defs.h"
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>
33 #include "portability.h"
34 #include "sim/callback.h"
35 #include "gdb/signals.h"
36 #include "sim-main.h"
37 #include "sim-options.h"
38 #include "sim-syscall.h"
39 #include "sim-hw.h"
41 #include "bfin-sim.h"
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. */
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"
70 #include "elf/common.h"
71 #include "elf/external.h"
72 #include "elf/internal.h"
73 #include "elf/bfin.h"
74 #include "bfd/elf-bfd.h"
76 #include "dv-bfin_cec.h"
77 #include "dv-bfin_mmu.h"
79 static const char cb_linux_stat_map_32[] =
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"; */
89 static const char cb_linux_stat_map_64[] =
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";
93 static 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";
97 static const char *stat_map_32, *stat_map_64;
99 /* Simulate a monitor trap, put the result into r0 and errno into r1
100 return offset by which to adjust pc. */
102 void
103 bfin_syscall (SIM_CPU *cpu)
105 SIM_DESC sd = CPU_STATE (cpu);
106 host_callback *cb = STATE_CALLBACK (sd);
107 bu32 args[6];
108 CB_SYSCALL sc;
109 char *p;
110 char _tbuf[1024 * 3], *tbuf = _tbuf, tstr[1024];
111 int fmt_ret_hex = 0;
113 CB_SYSCALL_INIT (&sc);
115 if (STATE_ENVIRONMENT (sd) == USER_ENVIRONMENT)
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);
123 sc.arg5 = args[4] = DREG (4);
124 sc.arg6 = args[5] = DREG (5);
126 else
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);
134 sc.arg5 = args[4] = GET_LONG (DREG (0) + 16);
135 sc.arg6 = args[5] = GET_LONG (DREG (0) + 20);
137 sc.p1 = sd;
138 sc.p2 = cpu;
139 sc.read_mem = sim_syscall_read_mem;
140 sc.write_mem = sim_syscall_write_mem;
142 /* Common cb_syscall() handles most functions. */
143 switch (cb_target_to_host_syscall (cb, sc.func))
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);
149 case CB_SYS_gettimeofday:
151 struct timeval _tv, *tv = &_tv;
152 struct timezone _tz, *tz = &_tz;
154 tbuf += sprintf (tbuf, "gettimeofday(%#x, %#x)", args[0], args[1]);
156 if (sc.arg1 == 0)
157 tv = NULL;
158 if (sc.arg2 == 0)
159 tz = NULL;
160 sc.result = gettimeofday (tv, tz);
162 if (sc.result == 0)
164 bu32 t;
166 if (tv)
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);
174 if (sc.arg2)
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);
182 else
183 goto sys_finish;
185 break;
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)
192 sc.result = !isatty (sc.arg1);
193 sc.errcode = 0;
195 else
197 sc.result = -1;
198 sc.errcode = cb_host_to_target_errno (cb, EINVAL);
200 break;
202 case CB_SYS_mmap2:
204 static bu32 heap = BFIN_DEFAULT_MEM_SIZE / 2;
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]);
210 sc.errcode = 0;
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)
215 sc.errcode = cb_host_to_target_errno (cb, ENOSYS);
216 else
218 #ifdef HAVE_PREAD
219 char *data = xmalloc (sc.arg2);
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
225 sc.errcode = cb_host_to_target_errno (cb, EINVAL);
227 free (data);
228 #else
229 sc.errcode = cb_host_to_target_errno (cb, ENOSYS);
230 #endif
233 if (sc.errcode)
235 sc.result = -1;
236 break;
239 sc.result = heap;
240 heap += sc.arg2;
241 /* Keep it page aligned. */
242 heap = align_up (heap, 4096);
244 break;
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;
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)
257 sc.result = -1;
258 sc.errcode = cb_host_to_target_errno (cb, EINVAL);
260 else
262 sc.result = dup2 (cb->fdmap[sc.arg1], cb->fdmap[sc.arg2]);
263 goto sys_finish;
265 break;
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)
273 sc.result = -1;
274 sc.errcode = cb_host_to_target_errno (cb, EINVAL);
276 else
278 sc.arg2 = sc.arg3;
279 sc.arg3 = args[4];
280 cb_syscall (cb, &sc);
281 if (sc.result != -1)
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);
288 break;
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)
296 sc.result = -1;
297 sc.errcode = cb_host_to_target_errno (cb, EINVAL);
299 else
301 long old_pos, read_result, read_errcode;
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;
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;
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;
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);
334 sc.result = read_result;
335 sc.errcode = read_errcode;
337 break;
339 case CB_SYS_getcwd:
340 tbuf += sprintf (tbuf, "getcwd(%#x, %u)", args[0], args[1]);
342 p = alloca (sc.arg2);
343 if (getcwd (p, sc.arg2) == NULL)
345 sc.result = -1;
346 sc.errcode = cb_host_to_target_errno (cb, EINVAL);
348 else
350 sc.write_mem (cb, &sc, sc.arg1, p, sc.arg2);
351 sc.result = sc.arg1;
353 break;
355 case CB_SYS_stat64:
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]);
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:
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]);
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;
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;
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;
399 ATTRIBUTE_FALLTHROUGH;
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;
406 ATTRIBUTE_FALLTHROUGH;
407 case CB_SYS_setgid32:
408 tbuf += sprintf (tbuf, "setgid(%u)", args[0]);
409 sc.result = setgid (sc.arg1);
410 goto sys_finish;
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 ())
417 sc.result = -1;
418 sc.errcode = cb_host_to_target_errno (cb, EPERM);
420 else
422 #ifdef HAVE_KILL
423 sc.result = kill (sc.arg1, sc.arg2);
424 goto sys_finish;
425 #else
426 sc.result = -1;
427 sc.errcode = cb_host_to_target_errno (cb, ENOSYS);
428 #endif
430 break;
432 case CB_SYS_open:
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]);
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:
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]);
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:
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);
457 goto case_default;
458 case CB_SYS_truncate:
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]);
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:
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);
473 goto case_default;
474 case CB_SYS_stat:
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]);
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:
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]);
486 goto case_default;
487 case CB_SYS_pipe:
488 tbuf += sprintf (tbuf, "pipe(%#x, %#x)", args[0], args[1]);
489 goto case_default;
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;
498 sys_finish:
499 if (sc.result == -1)
501 cb->last_errno = errno;
502 sc.errcode = cb->get_errno (cb);
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);
510 tbuf += sprintf (tbuf, " = ");
511 if (STATE_ENVIRONMENT (sd) == USER_ENVIRONMENT)
513 if (sc.result == -1)
515 tbuf += sprintf (tbuf, "-1 (error = %i)", sc.errcode);
516 if (sc.errcode == cb_host_to_target_errno (cb, ENOSYS))
518 sim_io_eprintf (sd, "bfin-sim: %#x: unimplemented syscall %i\n",
519 PCREG, sc.func);
521 SET_DREG (0, -sc.errcode);
523 else
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);
532 else
534 tbuf += sprintf (tbuf, "%lu (error = %i)", sc.result, sc.errcode);
535 SET_DREG (0, sc.result);
536 SET_DREG (1, sc.result2);
537 SET_DREG (2, sc.errcode);
540 TRACE_SYSCALL (cpu, "%s", _tbuf);
543 /* Execute a single instruction. */
545 static sim_cia
546 step_once (SIM_CPU *cpu)
548 SIM_DESC sd = CPU_STATE (cpu);
549 bu32 insn_len, oldpc = PCREG;
550 int i;
551 bool ssstep;
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. */
557 TRACE_DISASM (cpu, oldpc);
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))
565 int ivg = cec_get_ivg (cpu);
566 if (ivg == -1 || ivg > 3)
567 ssstep = true;
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
576 BFIN_CPU_STATE.did_jump = false;
578 insn_len = interp_insn_bfin (cpu, oldpc);
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))
588 SET_LCREG (i, LCREG (i) - 1);
589 if (LCREG (i))
590 break;
593 ++ PROFILE_TOTAL_INSN_COUNT (CPU_PROFILE_DATA (cpu));
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)
599 int ivg = cec_get_ivg (cpu);
600 if (ivg == -1 || ivg > 3)
602 INSN_LEN = 0;
603 cec_exception (cpu, VEC_STEP);
607 return oldpc;
610 void
611 sim_engine_run (SIM_DESC sd,
612 int next_cpu_nr, /* ignore */
613 int nr_cpus, /* ignore */
614 int siggnal) /* ignore */
616 bu32 ticks;
617 SIM_CPU *cpu;
619 SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
621 cpu = STATE_CPU (sd, 0);
623 while (1)
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);
634 /* Cover function of sim_state_free to free the cpu buffers as well. */
636 static void
637 free_state (SIM_DESC sd)
639 if (STATE_MODULES (sd) != NULL)
640 sim_module_uninstall (sd);
641 sim_cpu_free_all (sd);
642 sim_state_free (sd);
645 /* Create an instance of the simulator. */
647 static void
648 bfin_initialize_cpu (SIM_DESC sd, SIM_CPU *cpu)
650 PROFILE_TOTAL_INSN_COUNT (CPU_PROFILE_DATA (cpu)) = 0;
652 bfin_model_cpu_init (sd, cpu);
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);
659 /* This is what the hardware likes. */
660 SET_SYSCFGREG (0x30);
663 SIM_DESC
664 sim_open (SIM_OPEN_KIND kind, host_callback *callback,
665 struct bfd *abfd, char * const *argv)
667 char c;
668 int i;
669 SIM_DESC sd = sim_state_alloc_extra (kind, callback,
670 sizeof (struct bfin_board_data));
672 /* Set default options before parsing user options. */
673 STATE_MACHS (sd) = bfin_sim_machs;
674 STATE_MODEL_NAME (sd) = "bf537";
675 current_alignment = STRICT_ALIGNMENT;
676 current_target_byte_order = BFD_ENDIAN_LITTLE;
678 /* The cpu data is kept in a separately allocated chunk of memory. */
679 if (sim_cpu_alloc_all_extra (sd, 0, sizeof (struct bfin_cpu_state))
680 != SIM_RC_OK)
682 free_state (sd);
683 return 0;
686 if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
688 free_state (sd);
689 return 0;
692 /* XXX: Default to the Virtual environment. */
693 if (STATE_ENVIRONMENT (sd) == ALL_ENVIRONMENT)
694 STATE_ENVIRONMENT (sd) = VIRTUAL_ENVIRONMENT;
696 /* The parser will print an error message for us, so we silently return. */
697 if (sim_parse_args (sd, argv) != SIM_RC_OK)
699 free_state (sd);
700 return 0;
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)
707 bu16 emuexcpt = 0x25;
708 sim_do_commandf (sd, "memory-size 0x%x", BFIN_DEFAULT_MEM_SIZE);
709 sim_write (sd, 0, &emuexcpt, 2);
712 /* Check for/establish the a reference program image. */
713 if (sim_analyze_program (sd, STATE_PROG_FILE (sd), abfd) != SIM_RC_OK)
715 free_state (sd);
716 return 0;
719 /* Establish any remaining configuration options. */
720 if (sim_config (sd) != SIM_RC_OK)
722 free_state (sd);
723 return 0;
726 if (sim_post_argv_init (sd) != SIM_RC_OK)
728 free_state (sd);
729 return 0;
732 /* CPU specific initialization. */
733 for (i = 0; i < MAX_NR_PROCESSORS; ++i)
735 SIM_CPU *cpu = STATE_CPU (sd, i);
736 bfin_initialize_cpu (sd, cpu);
739 return sd;
742 /* Some utils don't like having a NULL environ. */
743 static char * const simple_env[] = { "HOME=/", "PATH=/bin", NULL };
745 static bu32 fdpic_load_offset;
747 static bool
748 bfin_fdpic_load (SIM_DESC sd, SIM_CPU *cpu, struct bfd *abfd, bu32 *sp,
749 bu32 *elf_addrs, char **ldso_path)
751 bool ret;
752 int i;
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;
762 bu32 max_load_addr;
764 unsigned char null[4] = { 0, 0, 0, 0 };
766 ret = false;
767 *ldso_path = NULL;
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;
775 if (bfd_read (&ehdr, sizeof (ehdr), abfd) != sizeof (ehdr))
776 goto skip_fdpic_init;
777 iehdr = elf_elfheader (abfd);
778 if (!(iehdr->e_flags & EF_BFIN_FDPIC))
779 goto skip_fdpic_init;
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]);
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;
794 /* Push the Ehdr onto the stack. */
795 *sp -= sizeof (ehdr);
796 elf_addrs[3] = *sp;
797 sim_write (sd, *sp, &ehdr, sizeof (ehdr));
798 if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG)
799 sim_io_printf (sd, " Elf_Ehdr: %#x\n", *sp);
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;
805 /* And the Exec's Phdrs onto the stack. */
806 if (STATE_PROG_BFD (sd) == abfd)
808 elf_addrs[4] = elf_addrs[0];
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);
814 if (bfd_read (data, phdr_size, abfd) != phdr_size)
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);
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)
831 Elf_Internal_Phdr *p = &phdrs[i];
832 bu32 paddr, vaddr, memsz, filesz;
834 paddr = p->p_paddr + fdpic_load_offset;
835 vaddr = p->p_vaddr;
836 memsz = p->p_memsz;
837 filesz = p->p_filesz;
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);
843 data = xmalloc (memsz);
844 if (memsz != filesz)
845 memset (data + filesz, 0, memsz - filesz);
847 if (bfd_seek (abfd, p->p_offset, SEEK_SET) == 0
848 && bfd_read (data, filesz, abfd) == filesz)
849 sim_write (sd, paddr, data, memsz);
851 free (data);
853 max_load_addr = max (paddr + memsz, max_load_addr);
855 *sp -= 12;
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 */
859 ++nsegs;
861 else if (phdrs[i].p_type == PT_DYNAMIC)
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]);
867 else if (phdrs[i].p_type == PT_INTERP)
869 uint32_t off = phdrs[i].p_offset;
870 uint32_t len = phdrs[i].p_filesz;
872 *ldso_path = xmalloc (len);
873 if (bfd_seek (abfd, off, SEEK_SET) != 0
874 || bfd_read (*ldso_path, len, abfd) != len)
876 free (*ldso_path);
877 *ldso_path = NULL;
879 else if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG)
880 sim_io_printf (sd, " PT_INTERP: %s\n", *ldso_path);
883 /* Update the load offset with a few extra pages. */
884 fdpic_load_offset = align_up (max (max_load_addr, fdpic_load_offset),
885 0x10000);
886 fdpic_load_offset += 0x10000;
888 /* Push the summary loadmap info onto the stack last. */
889 *sp -= 4;
890 sim_write (sd, *sp+0, null, 2); /* loadmap.version */
891 sim_write (sd, *sp+2, &nsegs, 2); /* loadmap.nsegs */
893 ret = true;
894 skip_fdpic_init:
895 free (phdrs);
897 return ret;
900 static void
901 bfin_user_init (SIM_DESC sd, SIM_CPU *cpu, struct bfd *abfd,
902 char * const *argv, char * const *env)
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
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;
925 bu32 sp, sp_flat;
927 /* start, at_phdr, at_phnum, at_base, at_entry, pt_dynamic */
928 bu32 elf_addrs[6];
929 bu32 auxvt;
930 bu32 exec_loadmap, ldso_loadmap;
931 char *ldso_path;
933 unsigned char null[4] = { 0, 0, 0, 0 };
935 host_callback *cb = STATE_CALLBACK (sd);
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;
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;
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;
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));
956 /* If the FDPIC needs an interpreter, then load it up too. */
957 if (ldso_path)
959 const char *ldso_full_path = concat (simulator_sysroot, ldso_path, NULL);
960 struct bfd *ldso_bfd;
962 ldso_bfd = bfd_openr (ldso_full_path, STATE_TARGET (sd));
963 if (!ldso_bfd)
965 sim_io_eprintf (sd, "bfin-sim: bfd open failed: %s\n", ldso_full_path);
966 goto static_fdpic;
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));
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);
978 ldso_loadmap = sp;
980 else
981 static_fdpic:
982 ldso_loadmap = 0;
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. */
990 auxvt = 1;
991 SET_SPREG (sp);
992 skip_fdpic_init:
993 sim_pc_set (cpu, elf_addrs[0]);
995 /* Figure out how much storage the argv/env strings need. */
996 argc = countargv ((char **)argv);
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]);
1003 if (!env)
1004 env = simple_env;
1005 envc = countargv ((char **)env);
1006 env_flat = envc; /* NUL bytes */
1007 for (i = 0; i < envc; ++i)
1008 env_flat += strlen (env[i]);
1010 /* Push the Auxiliary Vector Table between argv/env and actual strings. */
1011 sp_flat = sp = align_up (SPREG - argv_flat - env_flat - 4, 4);
1012 if (auxvt)
1014 # define AT_PUSH(at, val) \
1015 sp -= 4; \
1016 auxvt = (val); \
1017 sim_write (sd, sp, &auxvt, 4); \
1018 sp -= 4; \
1019 auxvt = (at); \
1020 sim_write (sd, sp, &auxvt, 4)
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
1040 SET_SPREG (sp);
1042 /* Push the argc/argv/env after the auxvt. */
1043 sp -= ((1 + argc + 1 + envc + 1) * 4);
1044 SET_SPREG (sp);
1046 /* First push the argc value. */
1047 sim_write (sd, sp, &argc, 4);
1048 sp += 4;
1050 /* Then the actual argv strings so we know where to point argv[]. */
1051 for (i = 0; i < argc; ++i)
1053 unsigned len = strlen (argv[i]) + 1;
1054 sim_write (sd, sp_flat, argv[i], len);
1055 sim_write (sd, sp, &sp_flat, 4);
1056 sp_flat += len;
1057 sp += 4;
1059 sim_write (sd, sp, null, 4);
1060 sp += 4;
1062 /* Then the actual env strings so we know where to point env[]. */
1063 for (i = 0; i < envc; ++i)
1065 unsigned len = strlen (env[i]) + 1;
1066 sim_write (sd, sp_flat, env[i], len);
1067 sim_write (sd, sp, &sp_flat, 4);
1068 sp_flat += len;
1069 sp += 4;
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;
1077 cb->stat_map = stat_map_32 = cb_linux_stat_map_32;
1078 stat_map_64 = cb_linux_stat_map_64;
1081 static void
1082 bfin_os_init (SIM_DESC sd, SIM_CPU *cpu, char * const *argv)
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;
1089 SET_DREG (0, cmdline);
1090 if (argv && argv[0])
1092 i = 1;
1093 byte = ' ';
1094 while (argv[i])
1096 bu32 len = strlen (argv[i]);
1097 sim_write (sd, cmdline, argv[i], len);
1098 cmdline += len;
1099 sim_write (sd, cmdline, &byte, 1);
1100 ++cmdline;
1101 ++i;
1104 byte = 0;
1105 sim_write (sd, cmdline, &byte, 1);
1108 static void
1109 bfin_virtual_init (SIM_DESC sd, SIM_CPU *cpu)
1111 host_callback *cb = STATE_CALLBACK (sd);
1113 cb->stat_map = stat_map_32 = cb_libgloss_stat_map_32;
1114 stat_map_64 = NULL;
1117 SIM_RC
1118 sim_create_inferior (SIM_DESC sd, struct bfd *abfd,
1119 char * const *argv, char * const *env)
1121 SIM_CPU *cpu = STATE_CPU (sd, 0);
1122 host_callback *cb = STATE_CALLBACK (sd);
1123 bfd_vma addr;
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);
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)
1138 freeargv (STATE_PROG_ARGV (sd));
1139 STATE_PROG_ARGV (sd) = dupargv (argv);
1142 if (STATE_PROG_ENVP (sd) != env)
1144 freeargv (STATE_PROG_ENVP (sd));
1145 STATE_PROG_ENVP (sd) = dupargv (env);
1148 cb->argv = STATE_PROG_ARGV (sd);
1149 cb->envp = STATE_PROG_ENVP (sd);
1151 switch (STATE_ENVIRONMENT (sd))
1153 case USER_ENVIRONMENT:
1154 bfin_user_init (sd, cpu, abfd, argv, env);
1155 break;
1156 case OPERATING_ENVIRONMENT:
1157 bfin_os_init (sd, cpu, argv);
1158 break;
1159 default:
1160 bfin_virtual_init (sd, cpu);
1161 break;
1164 return SIM_RC_OK;