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