ppc sim: Allow --sysroot command-line option
[deliverable/binutils-gdb.git] / sim / ppc / psim.c
1 /* This file is part of the program psim.
2
3 Copyright 1994, 1995, 1996, 1997, 2003 Andrew Cagney
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19 */
20
21
22 #ifndef _PSIM_C_
23 #define _PSIM_C_
24
25 #include "cpu.h" /* includes psim.h */
26 #include "idecode.h"
27 #include "options.h"
28
29 #include "tree.h"
30
31 #include <signal.h>
32
33 #include <stdio.h>
34 #include <ctype.h>
35
36 #ifdef HAVE_STDLIB_H
37 #include <stdlib.h>
38 #endif
39
40 #include <setjmp.h>
41
42 #ifdef HAVE_STRING_H
43 #include <string.h>
44 #else
45 #ifdef HAVE_STRINGS_H
46 #include <strings.h>
47 #endif
48 #endif
49
50
51 #include "bfd.h"
52 #include "libiberty.h"
53 #include "gdb/signals.h"
54
55 /* system structure, actual size of processor array determined at
56 runtime */
57
58 struct _psim {
59 event_queue *events;
60 device *devices;
61 mon *monitor;
62 os_emul *os_emulation;
63 core *memory;
64
65 /* escape routine for inner functions */
66 void *path_to_halt;
67 void *path_to_restart;
68
69 /* status from last halt */
70 psim_status halt_status;
71
72 /* the processors proper */
73 int nr_cpus;
74 int last_cpu; /* CPU that last (tried to) execute an instruction */
75 cpu *processors[MAX_NR_PROCESSORS];
76 };
77
78
79 int current_target_byte_order;
80 int current_host_byte_order;
81 int current_environment;
82 int current_alignment;
83 int current_floating_point;
84 int current_model_issue = MODEL_ISSUE_IGNORE;
85 int current_stdio = DO_USE_STDIO;
86 model_enum current_model = WITH_DEFAULT_MODEL;
87
88
89 /* create the device tree */
90
91 INLINE_PSIM\
92 (device *)
93 psim_tree(void)
94 {
95 device *root = tree_parse(NULL, "core");
96 tree_parse(root, "/aliases");
97 tree_parse(root, "/options");
98 tree_parse(root, "/chosen");
99 tree_parse(root, "/packages");
100 tree_parse(root, "/cpus");
101 tree_parse(root, "/openprom");
102 tree_parse(root, "/openprom/init");
103 tree_parse(root, "/openprom/trace");
104 tree_parse(root, "/openprom/options");
105 return root;
106 }
107
108 STATIC_INLINE_PSIM\
109 (char *)
110 find_arg(char *err_msg,
111 int *ptr_to_argp,
112 char **argv)
113 {
114 *ptr_to_argp += 1;
115 if (argv[*ptr_to_argp] == NULL)
116 error(err_msg);
117 return argv[*ptr_to_argp];
118 }
119
120 INLINE_PSIM\
121 (void)
122 psim_usage(int verbose, int help)
123 {
124 printf_filtered("Usage:\n");
125 printf_filtered("\n");
126 printf_filtered("\tpsim [ <psim-option> ... ] <image> [ <image-arg> ... ]\n");
127 printf_filtered("\n");
128 printf_filtered("Where\n");
129 printf_filtered("\n");
130 printf_filtered("\t<image> Name of the PowerPC program to run.\n");
131 if (verbose) {
132 printf_filtered("\t This can either be a PowerPC binary or\n");
133 printf_filtered("\t a text file containing a device tree\n");
134 printf_filtered("\t specification.\n");
135 printf_filtered("\t PSIM will attempt to determine from the\n");
136 printf_filtered("\t specified <image> the intended emulation\n");
137 printf_filtered("\t environment.\n");
138 printf_filtered("\t If PSIM gets it wrong, the emulation\n");
139 printf_filtered("\t environment can be specified using the\n");
140 printf_filtered("\t `-e' option (described below).\n");
141 printf_filtered("\n"); }
142 printf_filtered("\t<image-arg> Argument to be passed to <image>\n");
143 if (verbose) {
144 printf_filtered("\t These arguments will be passed to\n");
145 printf_filtered("\t <image> (as standard C argv, argc)\n");
146 printf_filtered("\t when <image> is started.\n");
147 printf_filtered("\n"); }
148 printf_filtered("\t<psim-option> See below\n");
149 printf_filtered("\n");
150 printf_filtered("The following are valid <psim-option>s:\n");
151 printf_filtered("\n");
152
153 printf_filtered("\t-c <count> Limit the simulation to <count> iterations\n");
154 if (verbose) {
155 printf_filtered("\n");
156 }
157
158 printf_filtered("\t-i or -i2 Print instruction counting statistics\n");
159 if (verbose) {
160 printf_filtered("\t Specify -i2 for a more detailed display\n");
161 printf_filtered("\n");
162 }
163
164 printf_filtered("\t-I Print execution unit statistics\n");
165 if (verbose) { printf_filtered("\n"); }
166
167 printf_filtered("\t-e <os-emul> specify an OS or platform to model\n");
168 if (verbose) {
169 printf_filtered("\t Can be any of the following:\n");
170 printf_filtered("\t bug - OEA + MOTO BUG ROM calls\n");
171 printf_filtered("\t netbsd - UEA + NetBSD system calls\n");
172 printf_filtered("\t solaris - UEA + Solaris system calls\n");
173 printf_filtered("\t linux - UEA + Linux system calls\n");
174 printf_filtered("\t chirp - OEA + a few OpenBoot calls\n");
175 printf_filtered("\n"); }
176
177 printf_filtered("\t-E <endian> Specify the endianness of the target\n");
178 if (verbose) {
179 printf_filtered("\t Can be any of the following:\n");
180 printf_filtered("\t big - big endian target\n");
181 printf_filtered("\t little - little endian target\n");
182 printf_filtered("\n"); }
183
184 printf_filtered("\t-f <file> Merge <file> into the device tree\n");
185 if (verbose) { printf_filtered("\n"); }
186
187 printf_filtered("\t-h -? -H give more detailed usage\n");
188 if (verbose) { printf_filtered("\n"); }
189
190 printf_filtered("\t-m <model> Specify the processor to model (604)\n");
191 if (verbose) {
192 printf_filtered("\t Selects the processor to use when\n");
193 printf_filtered("\t modeling execution units. Includes:\n");
194 printf_filtered("\t 604, 603 and 603e\n");
195 printf_filtered("\n"); }
196
197 printf_filtered("\t-n <nr-smp> Specify the number of processors in SMP simulations\n");
198 if (verbose) {
199 printf_filtered("\t Specifies the number of processors that are\n");
200 printf_filtered("\t to be modeled in a symetric multi-processor (SMP)\n");
201 printf_filtered("\t simulation\n");
202 printf_filtered("\n"); }
203
204 printf_filtered("\t-o <dev-spec> Add device <dev-spec> to the device tree\n");
205 if (verbose) { printf_filtered("\n"); }
206
207 printf_filtered("\t-r <ram-size> Set RAM size in bytes (OEA environments)\n");
208 if (verbose) { printf_filtered("\n"); }
209
210 printf_filtered("\t-t [!]<trace> Enable (disable) <trace> option\n");
211 if (verbose) { printf_filtered("\n"); }
212
213 printf_filtered("\n");
214 trace_usage(verbose);
215 device_usage(verbose);
216 if (verbose > 1) {
217 printf_filtered("\n");
218 print_options();
219 }
220
221 if (REPORT_BUGS_TO[0])
222 printf ("Report bugs to %s\n", REPORT_BUGS_TO);
223 exit (help ? 0 : 1);
224 }
225
226 /* Test "string" for containing a string of digits that form a number
227 between "min" and "max". The return value is the number or "err". */
228 static
229 int is_num( char *string, int min, int max, int err)
230 {
231 int result = 0;
232
233 for ( ; *string; ++string)
234 {
235 if (!isdigit(*string))
236 {
237 result = err;
238 break;
239 }
240 result = result * 10 + (*string - '0');
241 }
242 if (result < min || result > max)
243 result = err;
244
245 return result;
246 }
247
248 INLINE_PSIM\
249 (char **)
250 psim_options(device *root,
251 char **argv)
252 {
253 device *current = root;
254 int argp;
255 if (argv == NULL)
256 return NULL;
257 argp = 0;
258 while (argv[argp] != NULL && argv[argp][0] == '-') {
259 char *p = argv[argp] + 1;
260 char *param;
261 while (*p != '\0') {
262 switch (*p) {
263 default:
264 psim_usage(0, 0);
265 error ("");
266 break;
267 case 'c':
268 param = find_arg("Missing <count> option for -c (max-iterations)\n", &argp, argv);
269 tree_parse(root, "/openprom/options/max-iterations %s", param);
270 break;
271 case 'e':
272 param = find_arg("Missing <emul> option for -e (os-emul)\n", &argp, argv);
273 tree_parse(root, "/openprom/options/os-emul %s", param);
274 break;
275 case 'E':
276 /* endian spec, ignored for now */
277 param = find_arg("Missing <endian> option for -E (target-endian)\n", &argp, argv);
278 if (strcmp (param, "big") == 0)
279 tree_parse (root, "/options/little-endian? false");
280 else if (strcmp (param, "little") == 0)
281 tree_parse (root, "/options/little-endian? true");
282 else
283 {
284 printf_filtered ("Invalid <endian> option for -E (target-endian)\n");
285 psim_usage (0, 0);
286 }
287 break;
288 case 'f':
289 param = find_arg("Missing <file> option for -f\n", &argp, argv);
290 psim_merge_device_file(root, param);
291 break;
292 case 'h':
293 case '?':
294 psim_usage(1, 1);
295 break;
296 case 'H':
297 psim_usage(2, 1);
298 break;
299 case 'i':
300 if (isdigit(p[1])) {
301 tree_parse(root, "/openprom/trace/print-info %c", p[1]);
302 p++;
303 }
304 else {
305 tree_parse(root, "/openprom/trace/print-info 1");
306 }
307 break;
308 case 'I':
309 tree_parse(root, "/openprom/trace/print-info 2");
310 tree_parse(root, "/openprom/options/model-issue %d",
311 MODEL_ISSUE_PROCESS);
312 break;
313 case 'm':
314 param = find_arg("Missing <model> option for -m (model)\n", &argp, argv);
315 tree_parse(root, "/openprom/options/model \"%s", param);
316 break;
317 case 'n':
318 param = find_arg("Missing <nr-smp> option for -n (smp)\n", &argp, argv);
319 tree_parse(root, "/openprom/options/smp %s", param);
320 break;
321 case 'o':
322 param = find_arg("Missing <dev-spec> option for -o\n", &argp, argv);
323 if (memcmp(param, "mpc860c0", 8) == 0)
324 {
325 if (param[8] == '\0')
326 tree_parse(root, "/options/mpc860c0 5");
327 else if (param[8] == '=' && is_num(param+9, 1, 10, 0))
328 {
329 tree_parse(root, "/options/mpc860c0 %s", param+9);
330 }
331 else error("Invalid mpc860c0 option for -o\n");
332 }
333 else
334 current = tree_parse(current, "%s", param);
335 break;
336 case 'r':
337 param = find_arg("Missing <ram-size> option for -r (oea-memory-size)\n", &argp, argv);
338 tree_parse(root, "/openprom/options/oea-memory-size %s",
339 param);
340 break;
341 case 't':
342 param = find_arg("Missing <trace> option for -t (trace/*)\n", &argp, argv);
343 if (param[0] == '!')
344 tree_parse(root, "/openprom/trace/%s 0", param+1);
345 else
346 tree_parse(root, "/openprom/trace/%s 1", param);
347 break;
348 case '-':
349 /* it's a long option of the form --optionname=optionvalue.
350 Such options can be passed through if we are invoked by
351 gdb. */
352 if (strstr(argv[argp], "architecture") != NULL) {
353 /* we must consume the argument here, so that we get out
354 of the loop. */
355 p = argv[argp] + strlen(argv[argp]) - 1;
356 printf_filtered("Warning - architecture parameter ignored\n");
357 }
358 else if (strcmp (argv[argp], "--help") == 0)
359 psim_usage (0, 1);
360 else if (strncmp (argv[argp], "--sysroot=",
361 sizeof ("--sysroot=")) == 0)
362 /* Ignore this option. */
363 p = argv[argp] + strlen(argv[argp]) - 1;
364 else if (strcmp (argv[argp], "--version") == 0)
365 {
366 extern const char version[];
367 printf ("GNU simulator %s%s\n", PKGVERSION, version);
368 exit (0);
369 }
370 else
371 error("Unrecognized option");
372 break;
373 }
374 p += 1;
375 }
376 argp += 1;
377 }
378 /* force the trace node to process its options now *before* the tree
379 initialization occures */
380 device_ioctl(tree_find_device(root, "/openprom/trace"),
381 NULL, 0,
382 device_ioctl_set_trace);
383
384 {
385 void semantic_init(device* root);
386 semantic_init(root);
387 }
388
389 /* return where the options end */
390 return argv + argp;
391 }
392
393 INLINE_PSIM\
394 (void)
395 psim_command(device *root,
396 char **argv)
397 {
398 int argp = 0;
399 if (argv[argp] == NULL) {
400 return;
401 }
402 else if (strcmp(argv[argp], "trace") == 0) {
403 const char *opt = find_arg("Missing <trace> option", &argp, argv);
404 if (opt[0] == '!')
405 trace_option(opt + 1, 0);
406 else
407 trace_option(opt, 1);
408 }
409 else if (strcmp(*argv, "change-media") == 0) {
410 char *device = find_arg("Missing device name", &argp, argv);
411 char *media = argv[++argp];
412 device_ioctl(tree_find_device(root, device), NULL, 0,
413 device_ioctl_change_media, media);
414 }
415 else {
416 printf_filtered("Unknown PSIM command %s, try\n", argv[argp]);
417 printf_filtered(" trace <trace-option>\n");
418 printf_filtered(" change-media <device> [ <new-image> ]\n");
419 }
420 }
421
422
423 /* create the simulator proper from the device tree and executable */
424
425 INLINE_PSIM\
426 (psim *)
427 psim_create(const char *file_name,
428 device *root)
429 {
430 int cpu_nr;
431 const char *env;
432 psim *system;
433 os_emul *os_emulation;
434 int nr_cpus;
435
436 /* given this partially populated device tree, os_emul_create() uses
437 it and file_name to determine the selected emulation and hence
438 further populate the tree with any other required nodes. */
439
440 os_emulation = os_emul_create(file_name, root);
441 if (os_emulation == NULL)
442 error("psim: either file %s was not reconized or unreconized or unknown os-emulation type\n", file_name);
443
444 /* fill in the missing real number of CPU's */
445 nr_cpus = tree_find_integer_property(root, "/openprom/options/smp");
446 if (MAX_NR_PROCESSORS < nr_cpus)
447 error("target and configured number of cpus conflict\n");
448
449 /* fill in the missing TARGET BYTE ORDER information */
450 current_target_byte_order
451 = (tree_find_boolean_property(root, "/options/little-endian?")
452 ? LITTLE_ENDIAN
453 : BIG_ENDIAN);
454 if (CURRENT_TARGET_BYTE_ORDER != current_target_byte_order)
455 error("target and configured byte order conflict\n");
456
457 /* fill in the missing HOST BYTE ORDER information */
458 current_host_byte_order = (current_host_byte_order = 1,
459 (*(char*)(&current_host_byte_order)
460 ? LITTLE_ENDIAN
461 : BIG_ENDIAN));
462 if (CURRENT_HOST_BYTE_ORDER != current_host_byte_order)
463 error("host and configured byte order conflict\n");
464
465 /* fill in the missing OEA/VEA information */
466 env = tree_find_string_property(root, "/openprom/options/env");
467 current_environment = ((strcmp(env, "user") == 0
468 || strcmp(env, "uea") == 0)
469 ? USER_ENVIRONMENT
470 : (strcmp(env, "virtual") == 0
471 || strcmp(env, "vea") == 0)
472 ? VIRTUAL_ENVIRONMENT
473 : (strcmp(env, "operating") == 0
474 || strcmp(env, "oea") == 0)
475 ? OPERATING_ENVIRONMENT
476 : 0);
477 if (current_environment == 0)
478 error("unreconized /options env property\n");
479 if (CURRENT_ENVIRONMENT != current_environment)
480 error("target and configured environment conflict\n");
481
482 /* fill in the missing ALLIGNMENT information */
483 current_alignment
484 = (tree_find_boolean_property(root, "/openprom/options/strict-alignment?")
485 ? STRICT_ALIGNMENT
486 : NONSTRICT_ALIGNMENT);
487 if (CURRENT_ALIGNMENT != current_alignment)
488 error("target and configured alignment conflict\n");
489
490 /* fill in the missing FLOATING POINT information */
491 current_floating_point
492 = (tree_find_boolean_property(root, "/openprom/options/floating-point?")
493 ? HARD_FLOATING_POINT
494 : SOFT_FLOATING_POINT);
495 if (CURRENT_FLOATING_POINT != current_floating_point)
496 error("target and configured floating-point conflict\n");
497
498 /* fill in the missing STDIO information */
499 current_stdio
500 = (tree_find_boolean_property(root, "/openprom/options/use-stdio?")
501 ? DO_USE_STDIO
502 : DONT_USE_STDIO);
503 if (CURRENT_STDIO != current_stdio)
504 error("target and configured stdio interface conflict\n");
505
506 /* sort out the level of detail for issue modeling */
507 current_model_issue
508 = tree_find_integer_property(root, "/openprom/options/model-issue");
509 if (CURRENT_MODEL_ISSUE != current_model_issue)
510 error("target and configured model-issue conflict\n");
511
512 /* sort out our model architecture - wrong.
513
514 FIXME: this should be obtaining the required information from the
515 device tree via the "/chosen" property "cpu" which is an instance
516 (ihandle) for the only executing processor. By converting that
517 ihandle into the corresponding cpu's phandle and then querying
518 the "name" property, the cpu type can be determined. Ok? */
519
520 model_set(tree_find_string_property(root, "/openprom/options/model"));
521
522 /* create things */
523 system = ZALLOC(psim);
524 system->events = event_queue_create();
525 system->memory = core_from_device(root);
526 system->monitor = mon_create();
527 system->nr_cpus = nr_cpus;
528 system->os_emulation = os_emulation;
529 system->devices = root;
530
531 /* now all the processors attaching to each their per-cpu information */
532 for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; cpu_nr++) {
533 system->processors[cpu_nr] = cpu_create(system,
534 system->memory,
535 mon_cpu(system->monitor,
536 cpu_nr),
537 system->os_emulation,
538 cpu_nr);
539 }
540
541 /* dump out the contents of the device tree */
542 if (ppc_trace[trace_print_device_tree] || ppc_trace[trace_dump_device_tree])
543 tree_print(root);
544 if (ppc_trace[trace_dump_device_tree])
545 error("");
546
547 return system;
548 }
549
550
551 /* allow the simulation to stop/restart abnormaly */
552
553 INLINE_PSIM\
554 (void)
555 psim_set_halt_and_restart(psim *system,
556 void *halt_jmp_buf,
557 void *restart_jmp_buf)
558 {
559 system->path_to_halt = halt_jmp_buf;
560 system->path_to_restart = restart_jmp_buf;
561 }
562
563 INLINE_PSIM\
564 (void)
565 psim_clear_halt_and_restart(psim *system)
566 {
567 system->path_to_halt = NULL;
568 system->path_to_restart = NULL;
569 }
570
571 INLINE_PSIM\
572 (void)
573 psim_restart(psim *system,
574 int current_cpu)
575 {
576 ASSERT(current_cpu >= 0 && current_cpu < system->nr_cpus);
577 ASSERT(system->path_to_restart != NULL);
578 system->last_cpu = current_cpu;
579 longjmp(*(jmp_buf*)(system->path_to_restart), current_cpu + 1);
580 }
581
582
583 static void
584 cntrl_c_simulation(void *data)
585 {
586 psim *system = data;
587 psim_halt(system,
588 psim_nr_cpus(system),
589 was_continuing,
590 TARGET_SIGNAL_INT);
591 }
592
593 INLINE_PSIM\
594 (void)
595 psim_stop(psim *system)
596 {
597 event_queue_schedule_after_signal(psim_event_queue(system),
598 0 /*NOW*/,
599 cntrl_c_simulation,
600 system);
601 }
602
603 INLINE_PSIM\
604 (void)
605 psim_halt(psim *system,
606 int current_cpu,
607 stop_reason reason,
608 int signal)
609 {
610 ASSERT(current_cpu >= 0 && current_cpu <= system->nr_cpus);
611 ASSERT(system->path_to_halt != NULL);
612 system->last_cpu = current_cpu;
613 system->halt_status.reason = reason;
614 system->halt_status.signal = signal;
615 if (current_cpu == system->nr_cpus) {
616 system->halt_status.cpu_nr = 0;
617 system->halt_status.program_counter =
618 cpu_get_program_counter(system->processors[0]);
619 }
620 else {
621 system->halt_status.cpu_nr = current_cpu;
622 system->halt_status.program_counter =
623 cpu_get_program_counter(system->processors[current_cpu]);
624 }
625 longjmp(*(jmp_buf*)(system->path_to_halt), current_cpu + 1);
626 }
627
628
629 INLINE_PSIM\
630 (int)
631 psim_last_cpu(psim *system)
632 {
633 return system->last_cpu;
634 }
635
636 INLINE_PSIM\
637 (int)
638 psim_nr_cpus(psim *system)
639 {
640 return system->nr_cpus;
641 }
642
643 INLINE_PSIM\
644 (psim_status)
645 psim_get_status(psim *system)
646 {
647 return system->halt_status;
648 }
649
650
651 INLINE_PSIM\
652 (cpu *)
653 psim_cpu(psim *system,
654 int cpu_nr)
655 {
656 if (cpu_nr < 0 || cpu_nr >= system->nr_cpus)
657 return NULL;
658 else
659 return system->processors[cpu_nr];
660 }
661
662
663 INLINE_PSIM\
664 (device *)
665 psim_device(psim *system,
666 const char *path)
667 {
668 return tree_find_device(system->devices, path);
669 }
670
671 INLINE_PSIM\
672 (event_queue *)
673 psim_event_queue(psim *system)
674 {
675 return system->events;
676 }
677
678
679
680 STATIC_INLINE_PSIM\
681 (void)
682 psim_max_iterations_exceeded(void *data)
683 {
684 psim *system = data;
685 psim_halt(system,
686 system->nr_cpus, /* halted during an event */
687 was_signalled,
688 -1);
689 }
690
691
692 INLINE_PSIM\
693 (void)
694 psim_init(psim *system)
695 {
696 int cpu_nr;
697
698 /* scrub the monitor */
699 mon_init(system->monitor, system->nr_cpus);
700
701 /* trash any pending events */
702 event_queue_init(system->events);
703
704 /* if needed, schedule a halt event. FIXME - In the future this
705 will be replaced by a more generic change to psim_command(). A
706 new command `schedule NNN halt' being added. */
707 if (tree_find_property(system->devices, "/openprom/options/max-iterations")) {
708 event_queue_schedule(system->events,
709 tree_find_integer_property(system->devices,
710 "/openprom/options/max-iterations") - 2,
711 psim_max_iterations_exceeded,
712 system);
713 }
714
715 /* scrub all the cpus */
716 for (cpu_nr = 0; cpu_nr < system->nr_cpus; cpu_nr++)
717 cpu_init(system->processors[cpu_nr]);
718
719 /* init all the devices (which updates the cpus) */
720 tree_init(system->devices, system);
721
722 /* and the emulation (which needs an initialized device tree) */
723 os_emul_init(system->os_emulation, system->nr_cpus);
724
725 /* now sync each cpu against the initialized state of its registers */
726 for (cpu_nr = 0; cpu_nr < system->nr_cpus; cpu_nr++) {
727 cpu *processor = system->processors[cpu_nr];
728 cpu_synchronize_context(processor, cpu_get_program_counter(processor));
729 cpu_page_tlb_invalidate_all(processor);
730 }
731
732 /* force loop to start with first cpu */
733 system->last_cpu = -1;
734 }
735
736 INLINE_PSIM\
737 (void)
738 psim_stack(psim *system,
739 char **argv,
740 char **envp)
741 {
742 /* pass the stack device the argv/envp and let it work out what to
743 do with it */
744 device *stack_device = tree_find_device(system->devices,
745 "/openprom/init/stack");
746 if (stack_device != (device*)0) {
747 unsigned_word stack_pointer;
748 ASSERT (psim_read_register(system, 0, &stack_pointer, "sp",
749 cooked_transfer) > 0);
750 device_ioctl(stack_device,
751 NULL, /*cpu*/
752 0, /*cia*/
753 device_ioctl_create_stack,
754 stack_pointer,
755 argv,
756 envp);
757 }
758 }
759
760
761
762 /* SIMULATE INSTRUCTIONS, various different ways of achieving the same
763 thing */
764
765 INLINE_PSIM\
766 (void)
767 psim_step(psim *system)
768 {
769 volatile int keep_running = 0;
770 idecode_run_until_stop(system, &keep_running,
771 system->events, system->processors, system->nr_cpus);
772 }
773
774 INLINE_PSIM\
775 (void)
776 psim_run(psim *system)
777 {
778 idecode_run(system,
779 system->events, system->processors, system->nr_cpus);
780 }
781
782
783 /* storage manipulation functions */
784
785 INLINE_PSIM\
786 (int)
787 psim_read_register(psim *system,
788 int which_cpu,
789 void *buf,
790 const char reg[],
791 transfer_mode mode)
792 {
793 register_descriptions description;
794 char *cooked_buf;
795 cpu *processor;
796
797 /* find our processor */
798 if (which_cpu == MAX_NR_PROCESSORS) {
799 if (system->last_cpu == system->nr_cpus
800 || system->last_cpu == -1)
801 which_cpu = 0;
802 else
803 which_cpu = system->last_cpu;
804 }
805 ASSERT(which_cpu >= 0 && which_cpu < system->nr_cpus);
806
807 processor = system->processors[which_cpu];
808
809 /* find the register description */
810 description = register_description(reg);
811 if (description.type == reg_invalid)
812 return 0;
813 cooked_buf = alloca (description.size);
814
815 /* get the cooked value */
816 switch (description.type) {
817
818 case reg_gpr:
819 *(gpreg*)cooked_buf = cpu_registers(processor)->gpr[description.index];
820 break;
821
822 case reg_spr:
823 *(spreg*)cooked_buf = cpu_registers(processor)->spr[description.index];
824 break;
825
826 case reg_sr:
827 *(sreg*)cooked_buf = cpu_registers(processor)->sr[description.index];
828 break;
829
830 case reg_fpr:
831 *(fpreg*)cooked_buf = cpu_registers(processor)->fpr[description.index];
832 break;
833
834 case reg_pc:
835 *(unsigned_word*)cooked_buf = cpu_get_program_counter(processor);
836 break;
837
838 case reg_cr:
839 *(creg*)cooked_buf = cpu_registers(processor)->cr;
840 break;
841
842 case reg_msr:
843 *(msreg*)cooked_buf = cpu_registers(processor)->msr;
844 break;
845
846 case reg_fpscr:
847 *(fpscreg*)cooked_buf = cpu_registers(processor)->fpscr;
848 break;
849
850 case reg_insns:
851 *(unsigned_word*)cooked_buf = mon_get_number_of_insns(system->monitor,
852 which_cpu);
853 break;
854
855 case reg_stalls:
856 if (cpu_model(processor) == NULL)
857 error("$stalls only valid if processor unit model enabled (-I)\n");
858 *(unsigned_word*)cooked_buf = model_get_number_of_stalls(cpu_model(processor));
859 break;
860
861 case reg_cycles:
862 if (cpu_model(processor) == NULL)
863 error("$cycles only valid if processor unit model enabled (-I)\n");
864 *(unsigned_word*)cooked_buf = model_get_number_of_cycles(cpu_model(processor));
865 break;
866
867 #ifdef WITH_ALTIVEC
868 case reg_vr:
869 *(vreg*)cooked_buf = cpu_registers(processor)->altivec.vr[description.index];
870 break;
871
872 case reg_vscr:
873 *(vscreg*)cooked_buf = cpu_registers(processor)->altivec.vscr;
874 break;
875 #endif
876
877 #ifdef WITH_E500
878 case reg_gprh:
879 *(gpreg*)cooked_buf = cpu_registers(processor)->e500.gprh[description.index];
880 break;
881
882 case reg_evr:
883 *(unsigned64*)cooked_buf = EVR(description.index);
884 break;
885
886 case reg_acc:
887 *(accreg*)cooked_buf = cpu_registers(processor)->e500.acc;
888 break;
889 #endif
890
891 default:
892 printf_filtered("psim_read_register(processor=0x%lx,buf=0x%lx,reg=%s) %s\n",
893 (unsigned long)processor, (unsigned long)buf, reg,
894 "read of this register unimplemented");
895 break;
896
897 }
898
899 /* the PSIM internal values are in host order. To fetch raw data,
900 they need to be converted into target order and then returned */
901 if (mode == raw_transfer) {
902 /* FIXME - assumes that all registers are simple integers */
903 switch (description.size) {
904 case 1:
905 *(unsigned_1*)buf = H2T_1(*(unsigned_1*)cooked_buf);
906 break;
907 case 2:
908 *(unsigned_2*)buf = H2T_2(*(unsigned_2*)cooked_buf);
909 break;
910 case 4:
911 *(unsigned_4*)buf = H2T_4(*(unsigned_4*)cooked_buf);
912 break;
913 case 8:
914 *(unsigned_8*)buf = H2T_8(*(unsigned_8*)cooked_buf);
915 break;
916 #ifdef WITH_ALTIVEC
917 case 16:
918 if (CURRENT_HOST_BYTE_ORDER != CURRENT_TARGET_BYTE_ORDER)
919 {
920 union { vreg v; unsigned_8 d[2]; } h, t;
921 memcpy(&h.v/*dest*/, cooked_buf/*src*/, description.size);
922 { _SWAP_8(t.d[0] =, h.d[1]); }
923 { _SWAP_8(t.d[1] =, h.d[0]); }
924 memcpy(buf/*dest*/, &t/*src*/, description.size);
925 break;
926 }
927 else
928 memcpy(buf/*dest*/, cooked_buf/*src*/, description.size);
929 break;
930 #endif
931 }
932 }
933 else {
934 memcpy(buf/*dest*/, cooked_buf/*src*/, description.size);
935 }
936
937 return description.size;
938 }
939
940
941
942 INLINE_PSIM\
943 (int)
944 psim_write_register(psim *system,
945 int which_cpu,
946 const void *buf,
947 const char reg[],
948 transfer_mode mode)
949 {
950 cpu *processor;
951 register_descriptions description;
952 char *cooked_buf;
953
954 /* find our processor */
955 if (which_cpu == MAX_NR_PROCESSORS) {
956 if (system->last_cpu == system->nr_cpus
957 || system->last_cpu == -1)
958 which_cpu = 0;
959 else
960 which_cpu = system->last_cpu;
961 }
962
963 /* find the description of the register */
964 description = register_description(reg);
965 if (description.type == reg_invalid)
966 return 0;
967 cooked_buf = alloca (description.size);
968
969 if (which_cpu == -1) {
970 int i;
971 for (i = 0; i < system->nr_cpus; i++)
972 psim_write_register(system, i, buf, reg, mode);
973 return description.size;
974 }
975 ASSERT(which_cpu >= 0 && which_cpu < system->nr_cpus);
976
977 processor = system->processors[which_cpu];
978
979 /* If the data is comming in raw (target order), need to cook it
980 into host order before putting it into PSIM's internal structures */
981 if (mode == raw_transfer) {
982 switch (description.size) {
983 case 1:
984 *(unsigned_1*)cooked_buf = T2H_1(*(unsigned_1*)buf);
985 break;
986 case 2:
987 *(unsigned_2*)cooked_buf = T2H_2(*(unsigned_2*)buf);
988 break;
989 case 4:
990 *(unsigned_4*)cooked_buf = T2H_4(*(unsigned_4*)buf);
991 break;
992 case 8:
993 *(unsigned_8*)cooked_buf = T2H_8(*(unsigned_8*)buf);
994 break;
995 #ifdef WITH_ALTIVEC
996 case 16:
997 if (CURRENT_HOST_BYTE_ORDER != CURRENT_TARGET_BYTE_ORDER)
998 {
999 union { vreg v; unsigned_8 d[2]; } h, t;
1000 memcpy(&t.v/*dest*/, buf/*src*/, description.size);
1001 { _SWAP_8(h.d[0] =, t.d[1]); }
1002 { _SWAP_8(h.d[1] =, t.d[0]); }
1003 memcpy(cooked_buf/*dest*/, &h/*src*/, description.size);
1004 break;
1005 }
1006 else
1007 memcpy(cooked_buf/*dest*/, buf/*src*/, description.size);
1008 #endif
1009 }
1010 }
1011 else {
1012 memcpy(cooked_buf/*dest*/, buf/*src*/, description.size);
1013 }
1014
1015 /* put the cooked value into the register */
1016 switch (description.type) {
1017
1018 case reg_gpr:
1019 cpu_registers(processor)->gpr[description.index] = *(gpreg*)cooked_buf;
1020 break;
1021
1022 case reg_fpr:
1023 cpu_registers(processor)->fpr[description.index] = *(fpreg*)cooked_buf;
1024 break;
1025
1026 case reg_pc:
1027 cpu_set_program_counter(processor, *(unsigned_word*)cooked_buf);
1028 break;
1029
1030 case reg_spr:
1031 cpu_registers(processor)->spr[description.index] = *(spreg*)cooked_buf;
1032 break;
1033
1034 case reg_sr:
1035 cpu_registers(processor)->sr[description.index] = *(sreg*)cooked_buf;
1036 break;
1037
1038 case reg_cr:
1039 cpu_registers(processor)->cr = *(creg*)cooked_buf;
1040 break;
1041
1042 case reg_msr:
1043 cpu_registers(processor)->msr = *(msreg*)cooked_buf;
1044 break;
1045
1046 case reg_fpscr:
1047 cpu_registers(processor)->fpscr = *(fpscreg*)cooked_buf;
1048 break;
1049
1050 #ifdef WITH_E500
1051 case reg_gprh:
1052 cpu_registers(processor)->e500.gprh[description.index] = *(gpreg*)cooked_buf;
1053 break;
1054
1055 case reg_evr:
1056 {
1057 unsigned64 v;
1058 v = *(unsigned64*)cooked_buf;
1059 cpu_registers(processor)->e500.gprh[description.index] = v >> 32;
1060 cpu_registers(processor)->gpr[description.index] = v;
1061 break;
1062 }
1063
1064 case reg_acc:
1065 cpu_registers(processor)->e500.acc = *(accreg*)cooked_buf;
1066 break;
1067 #endif
1068
1069 #ifdef WITH_ALTIVEC
1070 case reg_vr:
1071 cpu_registers(processor)->altivec.vr[description.index] = *(vreg*)cooked_buf;
1072 break;
1073
1074 case reg_vscr:
1075 cpu_registers(processor)->altivec.vscr = *(vscreg*)cooked_buf;
1076 break;
1077 #endif
1078
1079 default:
1080 printf_filtered("psim_write_register(processor=0x%lx,cooked_buf=0x%lx,reg=%s) %s\n",
1081 (unsigned long)processor, (unsigned long)cooked_buf, reg,
1082 "read of this register unimplemented");
1083 break;
1084
1085 }
1086
1087 return description.size;
1088 }
1089
1090
1091
1092 INLINE_PSIM\
1093 (unsigned)
1094 psim_read_memory(psim *system,
1095 int which_cpu,
1096 void *buffer,
1097 unsigned_word vaddr,
1098 unsigned nr_bytes)
1099 {
1100 cpu *processor;
1101 if (which_cpu == MAX_NR_PROCESSORS) {
1102 if (system->last_cpu == system->nr_cpus
1103 || system->last_cpu == -1)
1104 which_cpu = 0;
1105 else
1106 which_cpu = system->last_cpu;
1107 }
1108 processor = system->processors[which_cpu];
1109 return vm_data_map_read_buffer(cpu_data_map(processor),
1110 buffer, vaddr, nr_bytes,
1111 NULL, -1);
1112 }
1113
1114
1115 INLINE_PSIM\
1116 (unsigned)
1117 psim_write_memory(psim *system,
1118 int which_cpu,
1119 const void *buffer,
1120 unsigned_word vaddr,
1121 unsigned nr_bytes,
1122 int violate_read_only_section)
1123 {
1124 cpu *processor;
1125 if (which_cpu == MAX_NR_PROCESSORS) {
1126 if (system->last_cpu == system->nr_cpus
1127 || system->last_cpu == -1)
1128 which_cpu = 0;
1129 else
1130 which_cpu = system->last_cpu;
1131 }
1132 ASSERT(which_cpu >= 0 && which_cpu < system->nr_cpus);
1133 processor = system->processors[which_cpu];
1134 return vm_data_map_write_buffer(cpu_data_map(processor),
1135 buffer, vaddr, nr_bytes, 1/*violate-read-only*/,
1136 NULL, -1);
1137 }
1138
1139
1140 INLINE_PSIM\
1141 (void)
1142 psim_print_info(psim *system,
1143 int verbose)
1144 {
1145 mon_print_info(system, system->monitor, verbose);
1146 }
1147
1148
1149 /* Merge a device tree and a device file. */
1150
1151 INLINE_PSIM\
1152 (void)
1153 psim_merge_device_file(device *root,
1154 const char *file_name)
1155 {
1156 FILE *description;
1157 int line_nr;
1158 char device_path[1000];
1159 device *current;
1160
1161 /* try opening the file */
1162 description = fopen(file_name, "r");
1163 if (description == NULL) {
1164 perror(file_name);
1165 error("Invalid file %s specified", file_name);
1166 }
1167
1168 line_nr = 0;
1169 current = root;
1170 while (fgets(device_path, sizeof(device_path), description)) {
1171 char *device;
1172 /* check that the full line was read */
1173 if (strchr(device_path, '\n') == NULL) {
1174 fclose(description);
1175 error("%s:%d: line to long - %s",
1176 file_name, line_nr, device_path);
1177 }
1178 else
1179 *strchr(device_path, '\n') = '\0';
1180 line_nr++;
1181 /* skip comments ("#" or ";") and blank lines lines */
1182 for (device = device_path;
1183 *device != '\0' && isspace(*device);
1184 device++);
1185 if (device[0] == '#'
1186 || device[0] == ';'
1187 || device[0] == '\0')
1188 continue;
1189 /* merge any appended lines */
1190 while (device_path[strlen(device_path) - 1] == '\\') {
1191 int curlen = strlen(device_path) - 1;
1192 /* zap \ */
1193 device_path[curlen] = '\0';
1194 /* append the next line */
1195 if (!fgets(device_path + curlen, sizeof(device_path) - curlen, description)) {
1196 fclose(description);
1197 error("%s:%s: unexpected eof in line continuation - %s",
1198 file_name, line_nr, device_path);
1199 }
1200 if (strchr(device_path, '\n') == NULL) {
1201 fclose(description);
1202 error("%s:%d: line to long - %s",
1203 file_name, line_nr, device_path);
1204 }
1205 else
1206 *strchr(device_path, '\n') = '\0';
1207 line_nr++;
1208 }
1209 /* parse this line */
1210 current = tree_parse(current, "%s", device);
1211 }
1212 fclose(description);
1213 }
1214
1215
1216 #endif /* _PSIM_C_ */
This page took 0.077447 seconds and 5 git commands to generate.