Update sim copyright headers from GPLv2-or-later to GPLv3-or-later.
[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 3 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 printf_filtered ("Invalid Option: %s\n", argv[argp]);
265 psim_usage(0, 0);
266 error ("");
267 break;
268 case 'c':
269 param = find_arg("Missing <count> option for -c (max-iterations)\n", &argp, argv);
270 tree_parse(root, "/openprom/options/max-iterations %s", param);
271 break;
272 case 'e':
273 param = find_arg("Missing <emul> option for -e (os-emul)\n", &argp, argv);
274 tree_parse(root, "/openprom/options/os-emul %s", param);
275 break;
276 case 'E':
277 /* endian spec, ignored for now */
278 param = find_arg("Missing <endian> option for -E (target-endian)\n", &argp, argv);
279 if (strcmp (param, "big") == 0)
280 tree_parse (root, "/options/little-endian? false");
281 else if (strcmp (param, "little") == 0)
282 tree_parse (root, "/options/little-endian? true");
283 else
284 {
285 printf_filtered ("Invalid <endian> option for -E (target-endian)\n");
286 psim_usage (0, 0);
287 }
288 break;
289 case 'f':
290 param = find_arg("Missing <file> option for -f\n", &argp, argv);
291 psim_merge_device_file(root, param);
292 break;
293 case 'h':
294 case '?':
295 psim_usage(1, 1);
296 break;
297 case 'H':
298 psim_usage(2, 1);
299 break;
300 case 'i':
301 if (isdigit(p[1])) {
302 tree_parse(root, "/openprom/trace/print-info %c", p[1]);
303 p++;
304 }
305 else {
306 tree_parse(root, "/openprom/trace/print-info 1");
307 }
308 break;
309 case 'I':
310 tree_parse(root, "/openprom/trace/print-info 2");
311 tree_parse(root, "/openprom/options/model-issue %d",
312 MODEL_ISSUE_PROCESS);
313 break;
314 case 'm':
315 param = find_arg("Missing <model> option for -m (model)\n", &argp, argv);
316 tree_parse(root, "/openprom/options/model \"%s", param);
317 break;
318 case 'n':
319 param = find_arg("Missing <nr-smp> option for -n (smp)\n", &argp, argv);
320 tree_parse(root, "/openprom/options/smp %s", param);
321 break;
322 case 'o':
323 param = find_arg("Missing <dev-spec> option for -o\n", &argp, argv);
324 if (memcmp(param, "mpc860c0", 8) == 0)
325 {
326 if (param[8] == '\0')
327 tree_parse(root, "/options/mpc860c0 5");
328 else if (param[8] == '=' && is_num(param+9, 1, 10, 0))
329 {
330 tree_parse(root, "/options/mpc860c0 %s", param+9);
331 }
332 else error("Invalid mpc860c0 option for -o\n");
333 }
334 else
335 current = tree_parse(current, "%s", param);
336 break;
337 case 'r':
338 param = find_arg("Missing <ram-size> option for -r (oea-memory-size)\n", &argp, argv);
339 tree_parse(root, "/openprom/options/oea-memory-size %s",
340 param);
341 break;
342 case 't':
343 param = find_arg("Missing <trace> option for -t (trace/*)\n", &argp, argv);
344 if (param[0] == '!')
345 tree_parse(root, "/openprom/trace/%s 0", param+1);
346 else
347 tree_parse(root, "/openprom/trace/%s 1", param);
348 break;
349 case '-':
350 /* it's a long option of the form --optionname=optionvalue.
351 Such options can be passed through if we are invoked by
352 gdb. */
353 if (strstr(argv[argp], "architecture") != NULL) {
354 /* we must consume the argument here, so that we get out
355 of the loop. */
356 p = argv[argp] + strlen(argv[argp]) - 1;
357 printf_filtered("Warning - architecture parameter ignored\n");
358 }
359 else if (strcmp (argv[argp], "--help") == 0)
360 psim_usage (0, 1);
361 else if (strncmp (argv[argp], "--sysroot=",
362 sizeof ("--sysroot=") - 1) == 0)
363 /* Ignore this option. */
364 p = argv[argp] + strlen(argv[argp]) - 1;
365 else if (strcmp (argv[argp], "--version") == 0)
366 {
367 extern const char version[];
368 printf ("GNU simulator %s%s\n", PKGVERSION, version);
369 exit (0);
370 }
371 else
372 {
373 printf_filtered ("Invalid option: %s\n", argv[argp]);
374 psim_usage (0, 0);
375 error ("");
376 }
377 break;
378 }
379 p += 1;
380 }
381 argp += 1;
382 }
383 /* force the trace node to process its options now *before* the tree
384 initialization occures */
385 device_ioctl(tree_find_device(root, "/openprom/trace"),
386 NULL, 0,
387 device_ioctl_set_trace);
388
389 {
390 void semantic_init(device* root);
391 semantic_init(root);
392 }
393
394 /* return where the options end */
395 return argv + argp;
396 }
397
398 INLINE_PSIM\
399 (void)
400 psim_command(device *root,
401 char **argv)
402 {
403 int argp = 0;
404 if (argv[argp] == NULL) {
405 return;
406 }
407 else if (strcmp(argv[argp], "trace") == 0) {
408 const char *opt = find_arg("Missing <trace> option", &argp, argv);
409 if (opt[0] == '!')
410 trace_option(opt + 1, 0);
411 else
412 trace_option(opt, 1);
413 }
414 else if (strcmp(*argv, "change-media") == 0) {
415 char *device = find_arg("Missing device name", &argp, argv);
416 char *media = argv[++argp];
417 device_ioctl(tree_find_device(root, device), NULL, 0,
418 device_ioctl_change_media, media);
419 }
420 else {
421 printf_filtered("Unknown PSIM command %s, try\n", argv[argp]);
422 printf_filtered(" trace <trace-option>\n");
423 printf_filtered(" change-media <device> [ <new-image> ]\n");
424 }
425 }
426
427
428 /* create the simulator proper from the device tree and executable */
429
430 INLINE_PSIM\
431 (psim *)
432 psim_create(const char *file_name,
433 device *root)
434 {
435 int cpu_nr;
436 const char *env;
437 psim *system;
438 os_emul *os_emulation;
439 int nr_cpus;
440
441 /* given this partially populated device tree, os_emul_create() uses
442 it and file_name to determine the selected emulation and hence
443 further populate the tree with any other required nodes. */
444
445 os_emulation = os_emul_create(file_name, root);
446 if (os_emulation == NULL)
447 error("psim: either file %s was not reconized or unreconized or unknown os-emulation type\n", file_name);
448
449 /* fill in the missing real number of CPU's */
450 nr_cpus = tree_find_integer_property(root, "/openprom/options/smp");
451 if (MAX_NR_PROCESSORS < nr_cpus)
452 error("target and configured number of cpus conflict\n");
453
454 /* fill in the missing TARGET BYTE ORDER information */
455 current_target_byte_order
456 = (tree_find_boolean_property(root, "/options/little-endian?")
457 ? LITTLE_ENDIAN
458 : BIG_ENDIAN);
459 if (CURRENT_TARGET_BYTE_ORDER != current_target_byte_order)
460 error("target and configured byte order conflict\n");
461
462 /* fill in the missing HOST BYTE ORDER information */
463 current_host_byte_order = (current_host_byte_order = 1,
464 (*(char*)(&current_host_byte_order)
465 ? LITTLE_ENDIAN
466 : BIG_ENDIAN));
467 if (CURRENT_HOST_BYTE_ORDER != current_host_byte_order)
468 error("host and configured byte order conflict\n");
469
470 /* fill in the missing OEA/VEA information */
471 env = tree_find_string_property(root, "/openprom/options/env");
472 current_environment = ((strcmp(env, "user") == 0
473 || strcmp(env, "uea") == 0)
474 ? USER_ENVIRONMENT
475 : (strcmp(env, "virtual") == 0
476 || strcmp(env, "vea") == 0)
477 ? VIRTUAL_ENVIRONMENT
478 : (strcmp(env, "operating") == 0
479 || strcmp(env, "oea") == 0)
480 ? OPERATING_ENVIRONMENT
481 : 0);
482 if (current_environment == 0)
483 error("unreconized /options env property\n");
484 if (CURRENT_ENVIRONMENT != current_environment)
485 error("target and configured environment conflict\n");
486
487 /* fill in the missing ALLIGNMENT information */
488 current_alignment
489 = (tree_find_boolean_property(root, "/openprom/options/strict-alignment?")
490 ? STRICT_ALIGNMENT
491 : NONSTRICT_ALIGNMENT);
492 if (CURRENT_ALIGNMENT != current_alignment)
493 error("target and configured alignment conflict\n");
494
495 /* fill in the missing FLOATING POINT information */
496 current_floating_point
497 = (tree_find_boolean_property(root, "/openprom/options/floating-point?")
498 ? HARD_FLOATING_POINT
499 : SOFT_FLOATING_POINT);
500 if (CURRENT_FLOATING_POINT != current_floating_point)
501 error("target and configured floating-point conflict\n");
502
503 /* fill in the missing STDIO information */
504 current_stdio
505 = (tree_find_boolean_property(root, "/openprom/options/use-stdio?")
506 ? DO_USE_STDIO
507 : DONT_USE_STDIO);
508 if (CURRENT_STDIO != current_stdio)
509 error("target and configured stdio interface conflict\n");
510
511 /* sort out the level of detail for issue modeling */
512 current_model_issue
513 = tree_find_integer_property(root, "/openprom/options/model-issue");
514 if (CURRENT_MODEL_ISSUE != current_model_issue)
515 error("target and configured model-issue conflict\n");
516
517 /* sort out our model architecture - wrong.
518
519 FIXME: this should be obtaining the required information from the
520 device tree via the "/chosen" property "cpu" which is an instance
521 (ihandle) for the only executing processor. By converting that
522 ihandle into the corresponding cpu's phandle and then querying
523 the "name" property, the cpu type can be determined. Ok? */
524
525 model_set(tree_find_string_property(root, "/openprom/options/model"));
526
527 /* create things */
528 system = ZALLOC(psim);
529 system->events = event_queue_create();
530 system->memory = core_from_device(root);
531 system->monitor = mon_create();
532 system->nr_cpus = nr_cpus;
533 system->os_emulation = os_emulation;
534 system->devices = root;
535
536 /* now all the processors attaching to each their per-cpu information */
537 for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; cpu_nr++) {
538 system->processors[cpu_nr] = cpu_create(system,
539 system->memory,
540 mon_cpu(system->monitor,
541 cpu_nr),
542 system->os_emulation,
543 cpu_nr);
544 }
545
546 /* dump out the contents of the device tree */
547 if (ppc_trace[trace_print_device_tree] || ppc_trace[trace_dump_device_tree])
548 tree_print(root);
549 if (ppc_trace[trace_dump_device_tree])
550 error("");
551
552 return system;
553 }
554
555
556 /* allow the simulation to stop/restart abnormaly */
557
558 INLINE_PSIM\
559 (void)
560 psim_set_halt_and_restart(psim *system,
561 void *halt_jmp_buf,
562 void *restart_jmp_buf)
563 {
564 system->path_to_halt = halt_jmp_buf;
565 system->path_to_restart = restart_jmp_buf;
566 }
567
568 INLINE_PSIM\
569 (void)
570 psim_clear_halt_and_restart(psim *system)
571 {
572 system->path_to_halt = NULL;
573 system->path_to_restart = NULL;
574 }
575
576 INLINE_PSIM\
577 (void)
578 psim_restart(psim *system,
579 int current_cpu)
580 {
581 ASSERT(current_cpu >= 0 && current_cpu < system->nr_cpus);
582 ASSERT(system->path_to_restart != NULL);
583 system->last_cpu = current_cpu;
584 longjmp(*(jmp_buf*)(system->path_to_restart), current_cpu + 1);
585 }
586
587
588 static void
589 cntrl_c_simulation(void *data)
590 {
591 psim *system = data;
592 psim_halt(system,
593 psim_nr_cpus(system),
594 was_continuing,
595 GDB_SIGNAL_INT);
596 }
597
598 INLINE_PSIM\
599 (void)
600 psim_stop(psim *system)
601 {
602 event_queue_schedule_after_signal(psim_event_queue(system),
603 0 /*NOW*/,
604 cntrl_c_simulation,
605 system);
606 }
607
608 INLINE_PSIM\
609 (void)
610 psim_halt(psim *system,
611 int current_cpu,
612 stop_reason reason,
613 int signal)
614 {
615 ASSERT(current_cpu >= 0 && current_cpu <= system->nr_cpus);
616 ASSERT(system->path_to_halt != NULL);
617 system->last_cpu = current_cpu;
618 system->halt_status.reason = reason;
619 system->halt_status.signal = signal;
620 if (current_cpu == system->nr_cpus) {
621 system->halt_status.cpu_nr = 0;
622 system->halt_status.program_counter =
623 cpu_get_program_counter(system->processors[0]);
624 }
625 else {
626 system->halt_status.cpu_nr = current_cpu;
627 system->halt_status.program_counter =
628 cpu_get_program_counter(system->processors[current_cpu]);
629 }
630 longjmp(*(jmp_buf*)(system->path_to_halt), current_cpu + 1);
631 }
632
633
634 INLINE_PSIM\
635 (int)
636 psim_last_cpu(psim *system)
637 {
638 return system->last_cpu;
639 }
640
641 INLINE_PSIM\
642 (int)
643 psim_nr_cpus(psim *system)
644 {
645 return system->nr_cpus;
646 }
647
648 INLINE_PSIM\
649 (psim_status)
650 psim_get_status(psim *system)
651 {
652 return system->halt_status;
653 }
654
655
656 INLINE_PSIM\
657 (cpu *)
658 psim_cpu(psim *system,
659 int cpu_nr)
660 {
661 if (cpu_nr < 0 || cpu_nr >= system->nr_cpus)
662 return NULL;
663 else
664 return system->processors[cpu_nr];
665 }
666
667
668 INLINE_PSIM\
669 (device *)
670 psim_device(psim *system,
671 const char *path)
672 {
673 return tree_find_device(system->devices, path);
674 }
675
676 INLINE_PSIM\
677 (event_queue *)
678 psim_event_queue(psim *system)
679 {
680 return system->events;
681 }
682
683
684
685 STATIC_INLINE_PSIM\
686 (void)
687 psim_max_iterations_exceeded(void *data)
688 {
689 psim *system = data;
690 psim_halt(system,
691 system->nr_cpus, /* halted during an event */
692 was_signalled,
693 -1);
694 }
695
696
697 INLINE_PSIM\
698 (void)
699 psim_init(psim *system)
700 {
701 int cpu_nr;
702
703 /* scrub the monitor */
704 mon_init(system->monitor, system->nr_cpus);
705
706 /* trash any pending events */
707 event_queue_init(system->events);
708
709 /* if needed, schedule a halt event. FIXME - In the future this
710 will be replaced by a more generic change to psim_command(). A
711 new command `schedule NNN halt' being added. */
712 if (tree_find_property(system->devices, "/openprom/options/max-iterations")) {
713 event_queue_schedule(system->events,
714 tree_find_integer_property(system->devices,
715 "/openprom/options/max-iterations") - 2,
716 psim_max_iterations_exceeded,
717 system);
718 }
719
720 /* scrub all the cpus */
721 for (cpu_nr = 0; cpu_nr < system->nr_cpus; cpu_nr++)
722 cpu_init(system->processors[cpu_nr]);
723
724 /* init all the devices (which updates the cpus) */
725 tree_init(system->devices, system);
726
727 /* and the emulation (which needs an initialized device tree) */
728 os_emul_init(system->os_emulation, system->nr_cpus);
729
730 /* now sync each cpu against the initialized state of its registers */
731 for (cpu_nr = 0; cpu_nr < system->nr_cpus; cpu_nr++) {
732 cpu *processor = system->processors[cpu_nr];
733 cpu_synchronize_context(processor, cpu_get_program_counter(processor));
734 cpu_page_tlb_invalidate_all(processor);
735 }
736
737 /* force loop to start with first cpu */
738 system->last_cpu = -1;
739 }
740
741 INLINE_PSIM\
742 (void)
743 psim_stack(psim *system,
744 char **argv,
745 char **envp)
746 {
747 /* pass the stack device the argv/envp and let it work out what to
748 do with it */
749 device *stack_device = tree_find_device(system->devices,
750 "/openprom/init/stack");
751 if (stack_device != (device*)0) {
752 unsigned_word stack_pointer;
753 ASSERT (psim_read_register(system, 0, &stack_pointer, "sp",
754 cooked_transfer) > 0);
755 device_ioctl(stack_device,
756 NULL, /*cpu*/
757 0, /*cia*/
758 device_ioctl_create_stack,
759 stack_pointer,
760 argv,
761 envp);
762 }
763 }
764
765
766
767 /* SIMULATE INSTRUCTIONS, various different ways of achieving the same
768 thing */
769
770 INLINE_PSIM\
771 (void)
772 psim_step(psim *system)
773 {
774 volatile int keep_running = 0;
775 idecode_run_until_stop(system, &keep_running,
776 system->events, system->processors, system->nr_cpus);
777 }
778
779 INLINE_PSIM\
780 (void)
781 psim_run(psim *system)
782 {
783 idecode_run(system,
784 system->events, system->processors, system->nr_cpus);
785 }
786
787
788 /* storage manipulation functions */
789
790 INLINE_PSIM\
791 (int)
792 psim_read_register(psim *system,
793 int which_cpu,
794 void *buf,
795 const char reg[],
796 transfer_mode mode)
797 {
798 register_descriptions description;
799 char *cooked_buf;
800 cpu *processor;
801
802 /* find our processor */
803 if (which_cpu == MAX_NR_PROCESSORS) {
804 if (system->last_cpu == system->nr_cpus
805 || system->last_cpu == -1)
806 which_cpu = 0;
807 else
808 which_cpu = system->last_cpu;
809 }
810 ASSERT(which_cpu >= 0 && which_cpu < system->nr_cpus);
811
812 processor = system->processors[which_cpu];
813
814 /* find the register description */
815 description = register_description(reg);
816 if (description.type == reg_invalid)
817 return 0;
818 cooked_buf = alloca (description.size);
819
820 /* get the cooked value */
821 switch (description.type) {
822
823 case reg_gpr:
824 *(gpreg*)cooked_buf = cpu_registers(processor)->gpr[description.index];
825 break;
826
827 case reg_spr:
828 *(spreg*)cooked_buf = cpu_registers(processor)->spr[description.index];
829 break;
830
831 case reg_sr:
832 *(sreg*)cooked_buf = cpu_registers(processor)->sr[description.index];
833 break;
834
835 case reg_fpr:
836 *(fpreg*)cooked_buf = cpu_registers(processor)->fpr[description.index];
837 break;
838
839 case reg_pc:
840 *(unsigned_word*)cooked_buf = cpu_get_program_counter(processor);
841 break;
842
843 case reg_cr:
844 *(creg*)cooked_buf = cpu_registers(processor)->cr;
845 break;
846
847 case reg_msr:
848 *(msreg*)cooked_buf = cpu_registers(processor)->msr;
849 break;
850
851 case reg_fpscr:
852 *(fpscreg*)cooked_buf = cpu_registers(processor)->fpscr;
853 break;
854
855 case reg_insns:
856 *(unsigned_word*)cooked_buf = mon_get_number_of_insns(system->monitor,
857 which_cpu);
858 break;
859
860 case reg_stalls:
861 if (cpu_model(processor) == NULL)
862 error("$stalls only valid if processor unit model enabled (-I)\n");
863 *(unsigned_word*)cooked_buf = model_get_number_of_stalls(cpu_model(processor));
864 break;
865
866 case reg_cycles:
867 if (cpu_model(processor) == NULL)
868 error("$cycles only valid if processor unit model enabled (-I)\n");
869 *(unsigned_word*)cooked_buf = model_get_number_of_cycles(cpu_model(processor));
870 break;
871
872 #ifdef WITH_ALTIVEC
873 case reg_vr:
874 *(vreg*)cooked_buf = cpu_registers(processor)->altivec.vr[description.index];
875 break;
876
877 case reg_vscr:
878 *(vscreg*)cooked_buf = cpu_registers(processor)->altivec.vscr;
879 break;
880 #endif
881
882 #ifdef WITH_E500
883 case reg_gprh:
884 *(gpreg*)cooked_buf = cpu_registers(processor)->e500.gprh[description.index];
885 break;
886
887 case reg_evr:
888 *(unsigned64*)cooked_buf = EVR(description.index);
889 break;
890
891 case reg_acc:
892 *(accreg*)cooked_buf = cpu_registers(processor)->e500.acc;
893 break;
894 #endif
895
896 default:
897 printf_filtered("psim_read_register(processor=0x%lx,buf=0x%lx,reg=%s) %s\n",
898 (unsigned long)processor, (unsigned long)buf, reg,
899 "read of this register unimplemented");
900 break;
901
902 }
903
904 /* the PSIM internal values are in host order. To fetch raw data,
905 they need to be converted into target order and then returned */
906 if (mode == raw_transfer) {
907 /* FIXME - assumes that all registers are simple integers */
908 switch (description.size) {
909 case 1:
910 *(unsigned_1*)buf = H2T_1(*(unsigned_1*)cooked_buf);
911 break;
912 case 2:
913 *(unsigned_2*)buf = H2T_2(*(unsigned_2*)cooked_buf);
914 break;
915 case 4:
916 *(unsigned_4*)buf = H2T_4(*(unsigned_4*)cooked_buf);
917 break;
918 case 8:
919 *(unsigned_8*)buf = H2T_8(*(unsigned_8*)cooked_buf);
920 break;
921 #ifdef WITH_ALTIVEC
922 case 16:
923 if (CURRENT_HOST_BYTE_ORDER != CURRENT_TARGET_BYTE_ORDER)
924 {
925 union { vreg v; unsigned_8 d[2]; } h, t;
926 memcpy(&h.v/*dest*/, cooked_buf/*src*/, description.size);
927 { _SWAP_8(t.d[0] =, h.d[1]); }
928 { _SWAP_8(t.d[1] =, h.d[0]); }
929 memcpy(buf/*dest*/, &t/*src*/, description.size);
930 break;
931 }
932 else
933 memcpy(buf/*dest*/, cooked_buf/*src*/, description.size);
934 break;
935 #endif
936 }
937 }
938 else {
939 memcpy(buf/*dest*/, cooked_buf/*src*/, description.size);
940 }
941
942 return description.size;
943 }
944
945
946
947 INLINE_PSIM\
948 (int)
949 psim_write_register(psim *system,
950 int which_cpu,
951 const void *buf,
952 const char reg[],
953 transfer_mode mode)
954 {
955 cpu *processor;
956 register_descriptions description;
957 char *cooked_buf;
958
959 /* find our processor */
960 if (which_cpu == MAX_NR_PROCESSORS) {
961 if (system->last_cpu == system->nr_cpus
962 || system->last_cpu == -1)
963 which_cpu = 0;
964 else
965 which_cpu = system->last_cpu;
966 }
967
968 /* find the description of the register */
969 description = register_description(reg);
970 if (description.type == reg_invalid)
971 return 0;
972 cooked_buf = alloca (description.size);
973
974 if (which_cpu == -1) {
975 int i;
976 for (i = 0; i < system->nr_cpus; i++)
977 psim_write_register(system, i, buf, reg, mode);
978 return description.size;
979 }
980 ASSERT(which_cpu >= 0 && which_cpu < system->nr_cpus);
981
982 processor = system->processors[which_cpu];
983
984 /* If the data is comming in raw (target order), need to cook it
985 into host order before putting it into PSIM's internal structures */
986 if (mode == raw_transfer) {
987 switch (description.size) {
988 case 1:
989 *(unsigned_1*)cooked_buf = T2H_1(*(unsigned_1*)buf);
990 break;
991 case 2:
992 *(unsigned_2*)cooked_buf = T2H_2(*(unsigned_2*)buf);
993 break;
994 case 4:
995 *(unsigned_4*)cooked_buf = T2H_4(*(unsigned_4*)buf);
996 break;
997 case 8:
998 *(unsigned_8*)cooked_buf = T2H_8(*(unsigned_8*)buf);
999 break;
1000 #ifdef WITH_ALTIVEC
1001 case 16:
1002 if (CURRENT_HOST_BYTE_ORDER != CURRENT_TARGET_BYTE_ORDER)
1003 {
1004 union { vreg v; unsigned_8 d[2]; } h, t;
1005 memcpy(&t.v/*dest*/, buf/*src*/, description.size);
1006 { _SWAP_8(h.d[0] =, t.d[1]); }
1007 { _SWAP_8(h.d[1] =, t.d[0]); }
1008 memcpy(cooked_buf/*dest*/, &h/*src*/, description.size);
1009 break;
1010 }
1011 else
1012 memcpy(cooked_buf/*dest*/, buf/*src*/, description.size);
1013 #endif
1014 }
1015 }
1016 else {
1017 memcpy(cooked_buf/*dest*/, buf/*src*/, description.size);
1018 }
1019
1020 /* put the cooked value into the register */
1021 switch (description.type) {
1022
1023 case reg_gpr:
1024 cpu_registers(processor)->gpr[description.index] = *(gpreg*)cooked_buf;
1025 break;
1026
1027 case reg_fpr:
1028 cpu_registers(processor)->fpr[description.index] = *(fpreg*)cooked_buf;
1029 break;
1030
1031 case reg_pc:
1032 cpu_set_program_counter(processor, *(unsigned_word*)cooked_buf);
1033 break;
1034
1035 case reg_spr:
1036 cpu_registers(processor)->spr[description.index] = *(spreg*)cooked_buf;
1037 break;
1038
1039 case reg_sr:
1040 cpu_registers(processor)->sr[description.index] = *(sreg*)cooked_buf;
1041 break;
1042
1043 case reg_cr:
1044 cpu_registers(processor)->cr = *(creg*)cooked_buf;
1045 break;
1046
1047 case reg_msr:
1048 cpu_registers(processor)->msr = *(msreg*)cooked_buf;
1049 break;
1050
1051 case reg_fpscr:
1052 cpu_registers(processor)->fpscr = *(fpscreg*)cooked_buf;
1053 break;
1054
1055 #ifdef WITH_E500
1056 case reg_gprh:
1057 cpu_registers(processor)->e500.gprh[description.index] = *(gpreg*)cooked_buf;
1058 break;
1059
1060 case reg_evr:
1061 {
1062 unsigned64 v;
1063 v = *(unsigned64*)cooked_buf;
1064 cpu_registers(processor)->e500.gprh[description.index] = v >> 32;
1065 cpu_registers(processor)->gpr[description.index] = v;
1066 break;
1067 }
1068
1069 case reg_acc:
1070 cpu_registers(processor)->e500.acc = *(accreg*)cooked_buf;
1071 break;
1072 #endif
1073
1074 #ifdef WITH_ALTIVEC
1075 case reg_vr:
1076 cpu_registers(processor)->altivec.vr[description.index] = *(vreg*)cooked_buf;
1077 break;
1078
1079 case reg_vscr:
1080 cpu_registers(processor)->altivec.vscr = *(vscreg*)cooked_buf;
1081 break;
1082 #endif
1083
1084 default:
1085 printf_filtered("psim_write_register(processor=0x%lx,cooked_buf=0x%lx,reg=%s) %s\n",
1086 (unsigned long)processor, (unsigned long)cooked_buf, reg,
1087 "read of this register unimplemented");
1088 break;
1089
1090 }
1091
1092 return description.size;
1093 }
1094
1095
1096
1097 INLINE_PSIM\
1098 (unsigned)
1099 psim_read_memory(psim *system,
1100 int which_cpu,
1101 void *buffer,
1102 unsigned_word vaddr,
1103 unsigned nr_bytes)
1104 {
1105 cpu *processor;
1106 if (which_cpu == MAX_NR_PROCESSORS) {
1107 if (system->last_cpu == system->nr_cpus
1108 || system->last_cpu == -1)
1109 which_cpu = 0;
1110 else
1111 which_cpu = system->last_cpu;
1112 }
1113 processor = system->processors[which_cpu];
1114 return vm_data_map_read_buffer(cpu_data_map(processor),
1115 buffer, vaddr, nr_bytes,
1116 NULL, -1);
1117 }
1118
1119
1120 INLINE_PSIM\
1121 (unsigned)
1122 psim_write_memory(psim *system,
1123 int which_cpu,
1124 const void *buffer,
1125 unsigned_word vaddr,
1126 unsigned nr_bytes,
1127 int violate_read_only_section)
1128 {
1129 cpu *processor;
1130 if (which_cpu == MAX_NR_PROCESSORS) {
1131 if (system->last_cpu == system->nr_cpus
1132 || system->last_cpu == -1)
1133 which_cpu = 0;
1134 else
1135 which_cpu = system->last_cpu;
1136 }
1137 ASSERT(which_cpu >= 0 && which_cpu < system->nr_cpus);
1138 processor = system->processors[which_cpu];
1139 return vm_data_map_write_buffer(cpu_data_map(processor),
1140 buffer, vaddr, nr_bytes, 1/*violate-read-only*/,
1141 NULL, -1);
1142 }
1143
1144
1145 INLINE_PSIM\
1146 (void)
1147 psim_print_info(psim *system,
1148 int verbose)
1149 {
1150 mon_print_info(system, system->monitor, verbose);
1151 }
1152
1153
1154 /* Merge a device tree and a device file. */
1155
1156 INLINE_PSIM\
1157 (void)
1158 psim_merge_device_file(device *root,
1159 const char *file_name)
1160 {
1161 FILE *description;
1162 int line_nr;
1163 char device_path[1000];
1164 device *current;
1165
1166 /* try opening the file */
1167 description = fopen(file_name, "r");
1168 if (description == NULL) {
1169 perror(file_name);
1170 error("Invalid file %s specified", file_name);
1171 }
1172
1173 line_nr = 0;
1174 current = root;
1175 while (fgets(device_path, sizeof(device_path), description)) {
1176 char *device;
1177 /* check that the full line was read */
1178 if (strchr(device_path, '\n') == NULL) {
1179 fclose(description);
1180 error("%s:%d: line to long - %s",
1181 file_name, line_nr, device_path);
1182 }
1183 else
1184 *strchr(device_path, '\n') = '\0';
1185 line_nr++;
1186 /* skip comments ("#" or ";") and blank lines lines */
1187 for (device = device_path;
1188 *device != '\0' && isspace(*device);
1189 device++);
1190 if (device[0] == '#'
1191 || device[0] == ';'
1192 || device[0] == '\0')
1193 continue;
1194 /* merge any appended lines */
1195 while (device_path[strlen(device_path) - 1] == '\\') {
1196 int curlen = strlen(device_path) - 1;
1197 /* zap \ */
1198 device_path[curlen] = '\0';
1199 /* append the next line */
1200 if (!fgets(device_path + curlen, sizeof(device_path) - curlen, description)) {
1201 fclose(description);
1202 error("%s:%s: unexpected eof in line continuation - %s",
1203 file_name, line_nr, device_path);
1204 }
1205 if (strchr(device_path, '\n') == NULL) {
1206 fclose(description);
1207 error("%s:%d: line to long - %s",
1208 file_name, line_nr, device_path);
1209 }
1210 else
1211 *strchr(device_path, '\n') = '\0';
1212 line_nr++;
1213 }
1214 /* parse this line */
1215 current = tree_parse(current, "%s", device);
1216 }
1217 fclose(description);
1218 }
1219
1220
1221 #endif /* _PSIM_C_ */
This page took 0.054332 seconds and 4 git commands to generate.