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