This commit was generated by cvs2svn to track changes on a CVS vendor
[deliverable/binutils-gdb.git] / sim / ppc / psim.c
1 /* This file is part of the program psim.
2
3 Copyright (C) 1994-1997, Andrew Cagney <cagney@highland.com.au>
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 psim_read_register(system, 0, &stack_pointer, "sp", cooked_transfer);
733 device_ioctl(stack_device,
734 NULL, /*cpu*/
735 0, /*cia*/
736 device_ioctl_create_stack,
737 stack_pointer,
738 argv,
739 envp);
740 }
741 }
742
743
744
745 /* SIMULATE INSTRUCTIONS, various different ways of achieving the same
746 thing */
747
748 INLINE_PSIM\
749 (void)
750 psim_step(psim *system)
751 {
752 volatile int keep_running = 0;
753 idecode_run_until_stop(system, &keep_running,
754 system->events, system->processors, system->nr_cpus);
755 }
756
757 INLINE_PSIM\
758 (void)
759 psim_run(psim *system)
760 {
761 idecode_run(system,
762 system->events, system->processors, system->nr_cpus);
763 }
764
765
766 /* storage manipulation functions */
767
768 INLINE_PSIM\
769 (void)
770 psim_read_register(psim *system,
771 int which_cpu,
772 void *buf,
773 const char reg[],
774 transfer_mode mode)
775 {
776 register_descriptions description;
777 char cooked_buf[sizeof(unsigned_8)];
778 cpu *processor;
779
780 /* find our processor */
781 if (which_cpu == MAX_NR_PROCESSORS) {
782 if (system->last_cpu == system->nr_cpus
783 || system->last_cpu == -1)
784 which_cpu = 0;
785 else
786 which_cpu = system->last_cpu;
787 }
788 ASSERT(which_cpu >= 0 && which_cpu < system->nr_cpus);
789
790 processor = system->processors[which_cpu];
791
792 /* find the register description */
793 description = register_description(reg);
794 if (description.type == reg_invalid)
795 error("psim_read_register() invalid register name `%s'\n", reg);
796
797 /* get the cooked value */
798 switch (description.type) {
799
800 case reg_gpr:
801 *(gpreg*)cooked_buf = cpu_registers(processor)->gpr[description.index];
802 break;
803
804 case reg_spr:
805 *(spreg*)cooked_buf = cpu_registers(processor)->spr[description.index];
806 break;
807
808 case reg_sr:
809 *(sreg*)cooked_buf = cpu_registers(processor)->sr[description.index];
810 break;
811
812 case reg_fpr:
813 *(fpreg*)cooked_buf = cpu_registers(processor)->fpr[description.index];
814 break;
815
816 case reg_pc:
817 *(unsigned_word*)cooked_buf = cpu_get_program_counter(processor);
818 break;
819
820 case reg_cr:
821 *(creg*)cooked_buf = cpu_registers(processor)->cr;
822 break;
823
824 case reg_msr:
825 *(msreg*)cooked_buf = cpu_registers(processor)->msr;
826 break;
827
828 case reg_fpscr:
829 *(fpscreg*)cooked_buf = cpu_registers(processor)->fpscr;
830 break;
831
832 case reg_insns:
833 *(unsigned_word*)cooked_buf = mon_get_number_of_insns(system->monitor,
834 which_cpu);
835 break;
836
837 case reg_stalls:
838 if (cpu_model(processor) == NULL)
839 error("$stalls only valid if processor unit model enabled (-I)\n");
840 *(unsigned_word*)cooked_buf = model_get_number_of_stalls(cpu_model(processor));
841 break;
842
843 case reg_cycles:
844 if (cpu_model(processor) == NULL)
845 error("$cycles only valid if processor unit model enabled (-I)\n");
846 *(unsigned_word*)cooked_buf = model_get_number_of_cycles(cpu_model(processor));
847 break;
848
849 default:
850 printf_filtered("psim_read_register(processor=0x%lx,buf=0x%lx,reg=%s) %s\n",
851 (unsigned long)processor, (unsigned long)buf, reg,
852 "read of this register unimplemented");
853 break;
854
855 }
856
857 /* the PSIM internal values are in host order. To fetch raw data,
858 they need to be converted into target order and then returned */
859 if (mode == raw_transfer) {
860 /* FIXME - assumes that all registers are simple integers */
861 switch (description.size) {
862 case 1:
863 *(unsigned_1*)buf = H2T_1(*(unsigned_1*)cooked_buf);
864 break;
865 case 2:
866 *(unsigned_2*)buf = H2T_2(*(unsigned_2*)cooked_buf);
867 break;
868 case 4:
869 *(unsigned_4*)buf = H2T_4(*(unsigned_4*)cooked_buf);
870 break;
871 case 8:
872 *(unsigned_8*)buf = H2T_8(*(unsigned_8*)cooked_buf);
873 break;
874 }
875 }
876 else {
877 memcpy(buf/*dest*/, cooked_buf/*src*/, description.size);
878 }
879
880 }
881
882
883
884 INLINE_PSIM\
885 (void)
886 psim_write_register(psim *system,
887 int which_cpu,
888 const void *buf,
889 const char reg[],
890 transfer_mode mode)
891 {
892 cpu *processor;
893 register_descriptions description;
894 char cooked_buf[sizeof(unsigned_8)];
895
896 /* find our processor */
897 if (which_cpu == MAX_NR_PROCESSORS) {
898 if (system->last_cpu == system->nr_cpus
899 || system->last_cpu == -1)
900 which_cpu = 0;
901 else
902 which_cpu = system->last_cpu;
903 }
904 if (which_cpu == -1) {
905 int i;
906 for (i = 0; i < system->nr_cpus; i++)
907 psim_write_register(system, i, buf, reg, mode);
908 return;
909 }
910 ASSERT(which_cpu >= 0 && which_cpu < system->nr_cpus);
911
912 processor = system->processors[which_cpu];
913
914 /* find the description of the register */
915 description = register_description(reg);
916 if (description.type == reg_invalid)
917 error("psim_write_register() invalid register name %s\n", reg);
918
919 /* If the data is comming in raw (target order), need to cook it
920 into host order before putting it into PSIM's internal structures */
921 if (mode == raw_transfer) {
922 switch (description.size) {
923 case 1:
924 *(unsigned_1*)cooked_buf = T2H_1(*(unsigned_1*)buf);
925 break;
926 case 2:
927 *(unsigned_2*)cooked_buf = T2H_2(*(unsigned_2*)buf);
928 break;
929 case 4:
930 *(unsigned_4*)cooked_buf = T2H_4(*(unsigned_4*)buf);
931 break;
932 case 8:
933 *(unsigned_8*)cooked_buf = T2H_8(*(unsigned_8*)buf);
934 break;
935 }
936 }
937 else {
938 memcpy(cooked_buf/*dest*/, buf/*src*/, description.size);
939 }
940
941 /* put the cooked value into the register */
942 switch (description.type) {
943
944 case reg_gpr:
945 cpu_registers(processor)->gpr[description.index] = *(gpreg*)cooked_buf;
946 break;
947
948 case reg_fpr:
949 cpu_registers(processor)->fpr[description.index] = *(fpreg*)cooked_buf;
950 break;
951
952 case reg_pc:
953 cpu_set_program_counter(processor, *(unsigned_word*)cooked_buf);
954 break;
955
956 case reg_spr:
957 cpu_registers(processor)->spr[description.index] = *(spreg*)cooked_buf;
958 break;
959
960 case reg_sr:
961 cpu_registers(processor)->sr[description.index] = *(sreg*)cooked_buf;
962 break;
963
964 case reg_cr:
965 cpu_registers(processor)->cr = *(creg*)cooked_buf;
966 break;
967
968 case reg_msr:
969 cpu_registers(processor)->msr = *(msreg*)cooked_buf;
970 break;
971
972 case reg_fpscr:
973 cpu_registers(processor)->fpscr = *(fpscreg*)cooked_buf;
974 break;
975
976 default:
977 printf_filtered("psim_write_register(processor=0x%lx,cooked_buf=0x%lx,reg=%s) %s\n",
978 (unsigned long)processor, (unsigned long)cooked_buf, reg,
979 "read of this register unimplemented");
980 break;
981
982 }
983
984 }
985
986
987
988 INLINE_PSIM\
989 (unsigned)
990 psim_read_memory(psim *system,
991 int which_cpu,
992 void *buffer,
993 unsigned_word vaddr,
994 unsigned nr_bytes)
995 {
996 cpu *processor;
997 if (which_cpu == MAX_NR_PROCESSORS) {
998 if (system->last_cpu == system->nr_cpus
999 || system->last_cpu == -1)
1000 which_cpu = 0;
1001 else
1002 which_cpu = system->last_cpu;
1003 }
1004 processor = system->processors[which_cpu];
1005 return vm_data_map_read_buffer(cpu_data_map(processor),
1006 buffer, vaddr, nr_bytes,
1007 NULL, -1);
1008 }
1009
1010
1011 INLINE_PSIM\
1012 (unsigned)
1013 psim_write_memory(psim *system,
1014 int which_cpu,
1015 const void *buffer,
1016 unsigned_word vaddr,
1017 unsigned nr_bytes,
1018 int violate_read_only_section)
1019 {
1020 cpu *processor;
1021 if (which_cpu == MAX_NR_PROCESSORS) {
1022 if (system->last_cpu == system->nr_cpus
1023 || system->last_cpu == -1)
1024 which_cpu = 0;
1025 else
1026 which_cpu = system->last_cpu;
1027 }
1028 ASSERT(which_cpu >= 0 && which_cpu < system->nr_cpus);
1029 processor = system->processors[which_cpu];
1030 return vm_data_map_write_buffer(cpu_data_map(processor),
1031 buffer, vaddr, nr_bytes, 1/*violate-read-only*/,
1032 NULL, -1);
1033 }
1034
1035
1036 INLINE_PSIM\
1037 (void)
1038 psim_print_info(psim *system,
1039 int verbose)
1040 {
1041 mon_print_info(system, system->monitor, verbose);
1042 }
1043
1044
1045 /* Merge a device tree and a device file. */
1046
1047 INLINE_PSIM\
1048 (void)
1049 psim_merge_device_file(device *root,
1050 const char *file_name)
1051 {
1052 FILE *description;
1053 int line_nr;
1054 char device_path[1000];
1055 device *current;
1056
1057 /* try opening the file */
1058 description = fopen(file_name, "r");
1059 if (description == NULL) {
1060 perror(file_name);
1061 error("Invalid file %s specified", file_name);
1062 }
1063
1064 line_nr = 0;
1065 current = root;
1066 while (fgets(device_path, sizeof(device_path), description)) {
1067 char *device;
1068 /* check that the full line was read */
1069 if (strchr(device_path, '\n') == NULL) {
1070 fclose(description);
1071 error("%s:%d: line to long - %s",
1072 file_name, line_nr, device_path);
1073 }
1074 else
1075 *strchr(device_path, '\n') = '\0';
1076 line_nr++;
1077 /* skip comments ("#" or ";") and blank lines lines */
1078 for (device = device_path;
1079 *device != '\0' && isspace(*device);
1080 device++);
1081 if (device[0] == '#'
1082 || device[0] == ';'
1083 || device[0] == '\0')
1084 continue;
1085 /* merge any appended lines */
1086 while (device_path[strlen(device_path) - 1] == '\\') {
1087 int curlen = strlen(device_path) - 1;
1088 /* zap \ */
1089 device_path[curlen] = '\0';
1090 /* append the next line */
1091 if (!fgets(device_path + curlen, sizeof(device_path) - curlen, description)) {
1092 fclose(description);
1093 error("%s:%s: unexpected eof in line continuation - %s",
1094 file_name, line_nr, device_path);
1095 }
1096 if (strchr(device_path, '\n') == NULL) {
1097 fclose(description);
1098 error("%s:%d: line to long - %s",
1099 file_name, line_nr, device_path);
1100 }
1101 else
1102 *strchr(device_path, '\n') = '\0';
1103 line_nr++;
1104 }
1105 /* parse this line */
1106 current = tree_parse(current, "%s", device);
1107 }
1108 fclose(description);
1109 }
1110
1111
1112 #endif /* _PSIM_C_ */
This page took 0.0517 seconds and 5 git commands to generate.