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