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