No empty .Rs/.Re
[netbsd-mini2440.git] / gnu / dist / gdb6 / sim / ppc / psim.c
blobbe9d076cd66f0f68e2af8a50fef6c1c1ac7176c3
1 /* This file is part of the program psim.
3 Copyright 1994, 1995, 1996, 1997, 2003 Andrew Cagney
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.
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.
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.
22 #ifndef _PSIM_C_
23 #define _PSIM_C_
25 #include "cpu.h" /* includes psim.h */
26 #include "idecode.h"
27 #include "options.h"
29 #include "tree.h"
31 #include <signal.h>
33 #include <stdio.h>
34 #include <ctype.h>
36 #ifdef HAVE_STDLIB_H
37 #include <stdlib.h>
38 #endif
40 #include <setjmp.h>
42 #ifdef HAVE_STRING_H
43 #include <string.h>
44 #else
45 #ifdef HAVE_STRINGS_H
46 #include <strings.h>
47 #endif
48 #endif
51 #include "bfd.h"
52 #include "libiberty.h"
53 #include "gdb/signals.h"
55 /* system structure, actual size of processor array determined at
56 runtime */
58 struct _psim {
59 event_queue *events;
60 device *devices;
61 mon *monitor;
62 os_emul *os_emulation;
63 core *memory;
65 /* escape routine for inner functions */
66 void *path_to_halt;
67 void *path_to_restart;
69 /* status from last halt */
70 psim_status halt_status;
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];
79 int current_target_byte_order;
80 int current_host_byte_order;
81 int current_environment;
82 int current_alignment;
83 int current_floating_point;
84 int current_model_issue = MODEL_ISSUE_IGNORE;
85 int current_stdio = DO_USE_STDIO;
86 model_enum current_model = WITH_DEFAULT_MODEL;
89 /* create the device tree */
91 INLINE_PSIM\
92 (device *)
93 psim_tree(void)
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;
108 STATIC_INLINE_PSIM\
109 (char *)
110 find_arg(char *err_msg,
111 int *ptr_to_argp,
112 char **argv)
114 *ptr_to_argp += 1;
115 if (argv[*ptr_to_argp] == NULL)
116 error(err_msg);
117 return argv[*ptr_to_argp];
120 INLINE_PSIM\
121 (void)
122 psim_usage(int verbose)
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");
153 printf_filtered("\t-c <count> Limit the simulation to <count> iterations\n");
154 if (verbose) {
155 printf_filtered("\n");
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");
164 printf_filtered("\t-I Print execution unit statistics\n");
165 if (verbose) { printf_filtered("\n"); }
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"); }
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"); }
184 printf_filtered("\t-f <file> Merge <file> into the device tree\n");
185 if (verbose) { printf_filtered("\n"); }
187 printf_filtered("\t-h -? -H give more detailed usage\n");
188 if (verbose) { printf_filtered("\n"); }
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"); }
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"); }
204 printf_filtered("\t-o <dev-spec> Add device <dev-spec> to the device tree\n");
205 if (verbose) { printf_filtered("\n"); }
207 printf_filtered("\t-r <ram-size> Set RAM size in bytes (OEA environments)\n");
208 if (verbose) { printf_filtered("\n"); }
210 printf_filtered("\t-t [!]<trace> Enable (disable) <trace> option\n");
211 if (verbose) { printf_filtered("\n"); }
213 printf_filtered("\n");
214 trace_usage(verbose);
215 device_usage(verbose);
216 if (verbose > 1) {
217 printf_filtered("\n");
218 print_options();
220 error("");
223 /* Test "string" for containing a string of digits that form a number
224 between "min" and "max". The return value is the number or "err". */
225 static
226 int is_num( char *string, int min, int max, int err)
228 int result = 0;
230 for ( ; *string; ++string)
232 if (!isdigit(*string))
234 result = err;
235 break;
237 result = result * 10 + (*string - '0');
239 if (result < min || result > max)
240 result = err;
242 return result;
245 INLINE_PSIM\
246 (char **)
247 psim_options(device *root,
248 char **argv)
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
281 printf_filtered ("Invalid <endian> option for -E (target-endian)\n");
282 psim_usage (0);
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++;
301 else {
302 tree_parse(root, "/openprom/trace/print-info 1");
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);
320 if (memcmp(param, "mpc860c0", 8) == 0)
322 if (param[8] == '\0')
323 tree_parse(root, "/options/mpc860c0 5");
324 else if (param[8] == '=' && is_num(param+9, 1, 10, 0))
326 tree_parse(root, "/options/mpc860c0 %s", param+9);
328 else error("Invalid mpc860c0 option for -o\n");
330 else
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;
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");
355 else
356 error("Unrecognized option");
357 break;
359 p += 1;
361 argp += 1;
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);
370 void semantic_init(device* root);
371 semantic_init(root);
374 /* return where the options end */
375 return argv + argp;
378 INLINE_PSIM\
379 (void)
380 psim_command(device *root,
381 char **argv)
383 int argp = 0;
384 if (argv[argp] == NULL) {
385 return;
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);
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);
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");
408 /* create the simulator proper from the device tree and executable */
410 INLINE_PSIM\
411 (psim *)
412 psim_create(const char *file_name,
413 device *root)
415 int cpu_nr;
416 const char *env;
417 psim *system;
418 os_emul *os_emulation;
419 int nr_cpus;
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. */
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);
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");
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");
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");
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");
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");
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");
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");
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");
497 /* sort out our model architecture - wrong.
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? */
505 model_set(tree_find_string_property(root, "/openprom/options/model"));
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;
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);
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("");
532 return system;
536 /* allow the simulation to stop/restart abnormaly */
538 INLINE_PSIM\
539 (void)
540 psim_set_halt_and_restart(psim *system,
541 void *halt_jmp_buf,
542 void *restart_jmp_buf)
544 system->path_to_halt = halt_jmp_buf;
545 system->path_to_restart = restart_jmp_buf;
548 INLINE_PSIM\
549 (void)
550 psim_clear_halt_and_restart(psim *system)
552 system->path_to_halt = NULL;
553 system->path_to_restart = NULL;
556 INLINE_PSIM\
557 (void)
558 psim_restart(psim *system,
559 int current_cpu)
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);
568 static void
569 cntrl_c_simulation(void *data)
571 psim *system = data;
572 psim_halt(system,
573 psim_nr_cpus(system),
574 was_continuing,
575 TARGET_SIGNAL_INT);
578 INLINE_PSIM\
579 (void)
580 psim_stop(psim *system)
582 event_queue_schedule_after_signal(psim_event_queue(system),
583 0 /*NOW*/,
584 cntrl_c_simulation,
585 system);
588 INLINE_PSIM\
589 (void)
590 psim_halt(psim *system,
591 int current_cpu,
592 stop_reason reason,
593 int signal)
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]);
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]);
610 longjmp(*(jmp_buf*)(system->path_to_halt), current_cpu + 1);
614 INLINE_PSIM\
615 (int)
616 psim_last_cpu(psim *system)
618 return system->last_cpu;
621 INLINE_PSIM\
622 (int)
623 psim_nr_cpus(psim *system)
625 return system->nr_cpus;
628 INLINE_PSIM\
629 (psim_status)
630 psim_get_status(psim *system)
632 return system->halt_status;
636 INLINE_PSIM\
637 (cpu *)
638 psim_cpu(psim *system,
639 int cpu_nr)
641 if (cpu_nr < 0 || cpu_nr >= system->nr_cpus)
642 return NULL;
643 else
644 return system->processors[cpu_nr];
648 INLINE_PSIM\
649 (device *)
650 psim_device(psim *system,
651 const char *path)
653 return tree_find_device(system->devices, path);
656 INLINE_PSIM\
657 (event_queue *)
658 psim_event_queue(psim *system)
660 return system->events;
665 STATIC_INLINE_PSIM\
666 (void)
667 psim_max_iterations_exceeded(void *data)
669 psim *system = data;
670 psim_halt(system,
671 system->nr_cpus, /* halted during an event */
672 was_signalled,
673 -1);
677 INLINE_PSIM\
678 (void)
679 psim_init(psim *system)
681 int cpu_nr;
683 /* scrub the monitor */
684 mon_init(system->monitor, system->nr_cpus);
686 /* trash any pending events */
687 event_queue_init(system->events);
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);
700 /* scrub all the cpus */
701 for (cpu_nr = 0; cpu_nr < system->nr_cpus; cpu_nr++)
702 cpu_init(system->processors[cpu_nr]);
704 /* init all the devices (which updates the cpus) */
705 tree_init(system->devices, system);
707 /* and the emulation (which needs an initialized device tree) */
708 os_emul_init(system->os_emulation, system->nr_cpus);
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);
717 /* force loop to start with first cpu */
718 system->last_cpu = -1;
721 INLINE_PSIM\
722 (void)
723 psim_stack(psim *system,
724 char **argv,
725 char **envp)
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;
733 ASSERT (psim_read_register(system, 0, &stack_pointer, "sp",
734 cooked_transfer) > 0);
735 device_ioctl(stack_device,
736 NULL, /*cpu*/
737 0, /*cia*/
738 device_ioctl_create_stack,
739 stack_pointer,
740 argv,
741 envp);
747 /* SIMULATE INSTRUCTIONS, various different ways of achieving the same
748 thing */
750 INLINE_PSIM\
751 (void)
752 psim_step(psim *system)
754 volatile int keep_running = 0;
755 idecode_run_until_stop(system, &keep_running,
756 system->events, system->processors, system->nr_cpus);
759 INLINE_PSIM\
760 (void)
761 psim_run(psim *system)
763 idecode_run(system,
764 system->events, system->processors, system->nr_cpus);
768 /* storage manipulation functions */
770 INLINE_PSIM\
771 (int)
772 psim_read_register(psim *system,
773 int which_cpu,
774 void *buf,
775 const char reg[],
776 transfer_mode mode)
778 register_descriptions description;
779 char *cooked_buf;
780 cpu *processor;
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;
790 ASSERT(which_cpu >= 0 && which_cpu < system->nr_cpus);
792 processor = system->processors[which_cpu];
794 /* find the register description */
795 description = register_description(reg);
796 if (description.type == reg_invalid)
797 return 0;
798 cooked_buf = alloca (description.size);
800 /* get the cooked value */
801 switch (description.type) {
803 case reg_gpr:
804 *(gpreg*)cooked_buf = cpu_registers(processor)->gpr[description.index];
805 break;
807 case reg_spr:
808 *(spreg*)cooked_buf = cpu_registers(processor)->spr[description.index];
809 break;
811 case reg_sr:
812 *(sreg*)cooked_buf = cpu_registers(processor)->sr[description.index];
813 break;
815 case reg_fpr:
816 *(fpreg*)cooked_buf = cpu_registers(processor)->fpr[description.index];
817 break;
819 case reg_pc:
820 *(unsigned_word*)cooked_buf = cpu_get_program_counter(processor);
821 break;
823 case reg_cr:
824 *(creg*)cooked_buf = cpu_registers(processor)->cr;
825 break;
827 case reg_msr:
828 *(msreg*)cooked_buf = cpu_registers(processor)->msr;
829 break;
831 case reg_fpscr:
832 *(fpscreg*)cooked_buf = cpu_registers(processor)->fpscr;
833 break;
835 case reg_insns:
836 *(unsigned_word*)cooked_buf = mon_get_number_of_insns(system->monitor,
837 which_cpu);
838 break;
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;
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;
852 #ifdef WITH_ALTIVEC
853 case reg_vr:
854 *(vreg*)cooked_buf = cpu_registers(processor)->altivec.vr[description.index];
855 break;
857 case reg_vscr:
858 *(vscreg*)cooked_buf = cpu_registers(processor)->altivec.vscr;
859 break;
860 #endif
862 #ifdef WITH_E500
863 case reg_gprh:
864 *(gpreg*)cooked_buf = cpu_registers(processor)->e500.gprh[description.index];
865 break;
867 case reg_evr:
868 *(unsigned64*)cooked_buf = EVR(description.index);
869 break;
871 case reg_acc:
872 *(accreg*)cooked_buf = cpu_registers(processor)->e500.acc;
873 break;
874 #endif
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;
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;
901 #ifdef WITH_ALTIVEC
902 case 16:
903 if (CURRENT_HOST_BYTE_ORDER != CURRENT_TARGET_BYTE_ORDER)
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;
912 else
913 memcpy(buf/*dest*/, cooked_buf/*src*/, description.size);
914 break;
915 #endif
918 else {
919 memcpy(buf/*dest*/, cooked_buf/*src*/, description.size);
922 return description.size;
927 INLINE_PSIM\
928 (int)
929 psim_write_register(psim *system,
930 int which_cpu,
931 const void *buf,
932 const char reg[],
933 transfer_mode mode)
935 cpu *processor;
936 register_descriptions description;
937 char *cooked_buf;
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;
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);
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);
958 return description.size;
960 ASSERT(which_cpu >= 0 && which_cpu < system->nr_cpus);
962 processor = system->processors[which_cpu];
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;
980 #ifdef WITH_ALTIVEC
981 case 16:
982 if (CURRENT_HOST_BYTE_ORDER != CURRENT_TARGET_BYTE_ORDER)
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;
991 else
992 memcpy(cooked_buf/*dest*/, buf/*src*/, description.size);
993 #endif
996 else {
997 memcpy(cooked_buf/*dest*/, buf/*src*/, description.size);
1000 /* put the cooked value into the register */
1001 switch (description.type) {
1003 case reg_gpr:
1004 cpu_registers(processor)->gpr[description.index] = *(gpreg*)cooked_buf;
1005 break;
1007 case reg_fpr:
1008 cpu_registers(processor)->fpr[description.index] = *(fpreg*)cooked_buf;
1009 break;
1011 case reg_pc:
1012 cpu_set_program_counter(processor, *(unsigned_word*)cooked_buf);
1013 break;
1015 case reg_spr:
1016 cpu_registers(processor)->spr[description.index] = *(spreg*)cooked_buf;
1017 break;
1019 case reg_sr:
1020 cpu_registers(processor)->sr[description.index] = *(sreg*)cooked_buf;
1021 break;
1023 case reg_cr:
1024 cpu_registers(processor)->cr = *(creg*)cooked_buf;
1025 break;
1027 case reg_msr:
1028 cpu_registers(processor)->msr = *(msreg*)cooked_buf;
1029 break;
1031 case reg_fpscr:
1032 cpu_registers(processor)->fpscr = *(fpscreg*)cooked_buf;
1033 break;
1035 #ifdef WITH_E500
1036 case reg_gprh:
1037 cpu_registers(processor)->e500.gprh[description.index] = *(gpreg*)cooked_buf;
1038 break;
1040 case reg_evr:
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;
1049 case reg_acc:
1050 cpu_registers(processor)->e500.acc = *(accreg*)cooked_buf;
1051 break;
1052 #endif
1054 #ifdef WITH_ALTIVEC
1055 case reg_vr:
1056 cpu_registers(processor)->altivec.vr[description.index] = *(vreg*)cooked_buf;
1057 break;
1059 case reg_vscr:
1060 cpu_registers(processor)->altivec.vscr = *(vscreg*)cooked_buf;
1061 break;
1062 #endif
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;
1072 return description.size;
1077 INLINE_PSIM\
1078 (unsigned)
1079 psim_read_memory(psim *system,
1080 int which_cpu,
1081 void *buffer,
1082 unsigned_word vaddr,
1083 unsigned nr_bytes)
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;
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);
1100 INLINE_PSIM\
1101 (unsigned)
1102 psim_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)
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;
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);
1125 INLINE_PSIM\
1126 (void)
1127 psim_print_info(psim *system,
1128 int verbose)
1130 mon_print_info(system, system->monitor, verbose);
1134 /* Merge a device tree and a device file. */
1136 INLINE_PSIM\
1137 (void)
1138 psim_merge_device_file(device *root,
1139 const char *file_name)
1141 FILE *description;
1142 int line_nr;
1143 char device_path[1000];
1144 device *current;
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);
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);
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);
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);
1190 else
1191 *strchr(device_path, '\n') = '\0';
1192 line_nr++;
1194 /* parse this line */
1195 current = tree_parse(current, "%s", device);
1197 fclose(description);
1201 #endif /* _PSIM_C_ */