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