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