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