Andrew's latest changes & print all instruction counts if -I
[deliverable/binutils-gdb.git] / sim / ppc / psim.c
1 /* This file is part of the program psim.
2
3 Copyright (C) 1994-1995, 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 <stdio.h>
26 #include <ctype.h>
27 #include <stdlib.h>
28
29 #include "config.h"
30 #include "ppc-config.h"
31 #include "inline.h"
32
33 #ifndef STATIC_INLINE_PSIM
34 #define STATIC_INLINE_PSIM STATIC_INLINE
35 #endif
36
37 #include <string.h>
38 #include <setjmp.h>
39
40 #include "cpu.h" /* includes psim.h */
41 #include "idecode.h"
42
43 #include "bfd.h"
44
45
46 #include "inline.c"
47
48 /* Any starting address less than this is assumed to be an OEA program
49 rather than VEA. */
50 #ifndef OEA_START_ADDRESS
51 #define OEA_START_ADDRESS 4096
52 #endif
53
54 /* Any starting address greater than this is assumed to be an OpenBoot
55 rather than VEA */
56 #ifndef OPENBOOT_START_ADDRESS
57 #define OPENBOOT_START_ADDRESS 0x80000000
58 #endif
59
60 #ifndef OEA_MEMORY_SIZE
61 #define OEA_MEMORY_SIZE 0x100000
62 #endif
63
64
65 /* system structure, actual size of processor array determined at
66 runtime */
67
68 struct _psim {
69 event_queue *events;
70 device_tree *devices;
71 mon *monitor;
72 core *memory;
73 /* escape routine for inner functions */
74 void *path_to_halt;
75 void *path_to_restart;
76 /* status from last halt */
77 psim_status halt_status;
78 /* the processes proper */
79 int nr_cpus;
80 int last_cpu; /* CPU that last (tried to) execute an instruction */
81 cpu *processors[MAX_NR_PROCESSORS];
82 };
83
84
85 int current_target_byte_order;
86 int current_host_byte_order;
87 int current_environment;
88 int current_alignment;
89 int current_floating_point;
90
91
92 /* create a device tree from the image */
93
94
95
96 /* Raw hardware tree:
97
98 A small default set of devices are configured. Each section of the
99 image is loaded directly into physical memory. */
100
101 STATIC_INLINE_PSIM void
102 create_hardware_device_tree(bfd *image,
103 device_tree *root)
104 {
105 char *name;
106 const memory_size = OEA_MEMORY_SIZE;
107
108 /* options */
109 device_tree_add_passthrough(root, "/options");
110 device_tree_add_integer(root, "/options/smp",
111 MAX_NR_PROCESSORS);
112 device_tree_add_boolean(root, "/options/little-endian?",
113 !image->xvec->byteorder_big_p);
114 device_tree_add_string(root, "/options/environment-architecture",
115 "operating");
116 device_tree_add_boolean(root, "/options/strict-alignment?",
117 (WITH_ALIGNMENT == STRICT_ALIGNMENT
118 || !image->xvec->byteorder_big_p));
119 device_tree_add_boolean(root, "/options/floating-point?",
120 WITH_FLOATING_POINT);
121
122 /* hardware */
123 name = printd_uw_u_u("/memory", 0, memory_size, access_read_write_exec);
124 device_tree_add_found_device(root, name);
125 zfree(name);
126 device_tree_add_found_device(root, "/iobus@0x400000");
127 device_tree_add_found_device(root, "/iobus/console@0x000000,16");
128 device_tree_add_found_device(root, "/iobus/halt@0x100000,4");
129 device_tree_add_found_device(root, "/iobus/icu@0x200000,4");
130
131 /* initialization */
132 device_tree_add_passthrough(root, "/init");
133 device_tree_add_found_device(root, "/init/register@pc,0x0");
134 name = printd_c_uw("/init/register", "sp", memory_size);
135 device_tree_add_found_device(root, name);
136 zfree(name);
137 name = printd_c_uw("/init/register", "msr",
138 (image->xvec->byteorder_big_p
139 ? 0
140 : msr_little_endian_mode));
141 device_tree_add_found_device(root, name);
142 zfree(name);
143 /* AJC puts the PC at zero and wants a stack while MM puts it above
144 zero and doesn't. Really there should be no stack *but* this
145 makes testing easier */
146 device_tree_add_found_device(root,
147 (bfd_get_start_address(image) == 0
148 ? "/init/stack@elf"
149 : "/init/stack@none"));
150 name = printd_c("/init/load-binary", bfd_get_filename(image));
151 device_tree_add_found_device(root, name);
152 zfree(name);
153 }
154
155
156 /* Openboot model (under development):
157
158 An extension of the hardware model. The image is read into memory
159 as a single block. Sections of the image are then mapped as
160 required using a HTAB. */
161
162 STATIC_INLINE_PSIM void
163 create_openboot_device_tree(bfd *image,
164 device_tree *root)
165 {
166 create_hardware_device_tree(image, root);
167 }
168
169
170 /* User mode model:
171
172 Image sections loaded into virtual addresses as specified. A
173 (large) stack is reserved (but only allocated as needed). System
174 calls that include suport for heap growth are attached. */
175
176 STATIC_INLINE_PSIM void
177 create_vea_device_tree(bfd *image,
178 device_tree *root)
179 {
180 unsigned_word top_of_stack;
181 unsigned stack_size;
182 int elf_binary;
183 char *name;
184
185 /* establish a few defaults */
186 if (image->xvec->flavour == bfd_target_elf_flavour) {
187 elf_binary = 1;
188 top_of_stack = 0xe0000000;
189 stack_size = 0x00100000;
190 }
191 else {
192 elf_binary = 0;
193 top_of_stack = 0x20000000;
194 stack_size = 0x00100000;
195 }
196
197 /* options */
198 device_tree_add_passthrough(root, "/options");
199 device_tree_add_integer(root, "/options/smp", 1); /* always */
200 device_tree_add_boolean(root, "/options/little-endian?",
201 !image->xvec->byteorder_big_p);
202 device_tree_add_string(root, "/options/environment-architecture",
203 (WITH_ENVIRONMENT == USER_ENVIRONMENT
204 ? "user" : "virtual"));
205 device_tree_add_boolean(root, "/options/strict-alignment?",
206 (WITH_ALIGNMENT == STRICT_ALIGNMENT
207 || !image->xvec->byteorder_big_p));
208 device_tree_add_boolean(root, "/options/floating-point?",
209 WITH_FLOATING_POINT);
210
211 /* virtual memory - handles growth of stack/heap */
212 name = printd_uw_u("/vm", top_of_stack - stack_size, stack_size);
213 device_tree_add_found_device(root, name);
214 zfree(name);
215 name = printd_c("/vm/map-binary", bfd_get_filename(image));
216 device_tree_add_found_device(root, name);
217 zfree(name);
218
219 /* finish the init */
220 device_tree_add_passthrough(root, "/init");
221 name = printd_c_uw("/init/register", "pc", bfd_get_start_address(image));
222 device_tree_add_found_device(root, name); /*pc*/
223 zfree(name);
224 name = printd_c_uw("/init/register", "sp", top_of_stack);
225 device_tree_add_found_device(root, name);
226 zfree(name);
227 name = printd_c_uw("/init/register", "msr",
228 (image->xvec->byteorder_big_p
229 ? 0
230 : msr_little_endian_mode));
231 device_tree_add_found_device(root, name);
232 zfree(name);
233 device_tree_add_found_device(root, (elf_binary
234 ? "/init/stack@elf"
235 : "/init/stack@xcoff"));
236 }
237
238
239 /* File device:
240
241 The file contains lines that specify the describe the device tree
242 to be created, read them in and load them into the tree */
243
244 STATIC_INLINE_PSIM void
245 create_filed_device_tree(const char *file_name,
246 device_tree *root)
247 {
248 FILE *description = fopen(file_name, "r");
249 int line_nr = 0;
250 char device_path[1000];
251 while (fgets(device_path, sizeof(device_path), description)) {
252 /* check all of line was read */
253 {
254 char *end = strchr(device_path, '\n');
255 if (end == NULL) {
256 fclose(description);
257 error("create_filed_device_tree() line %d to long: %s\n",
258 line_nr, device_path);
259 }
260 line_nr++;
261 *end = '\0';
262 }
263 /* check for leading comment */
264 if (device_path[0] != '/')
265 continue;
266 /* enter it in varying ways */
267 if (strchr(device_path, '@') != NULL) {
268 device_tree_add_found_device(root, device_path);
269 }
270 else {
271 char *space = strchr(device_path, ' ');
272 if (space == NULL) {
273 /* intermediate node */
274 device_tree_add_passthrough(root, device_path);
275 }
276 else if (space[-1] == '?') {
277 /* boolean */
278 *space = '\0';
279 device_tree_add_boolean(root, device_path, space[1] != '0');
280 }
281 else if (isdigit(space[1])) {
282 /* integer */
283 *space = '\0';
284 device_tree_add_integer(root, device_path, strtoul(space+1, 0, 0));
285 }
286 else if (space[1] == '"') {
287 /* quoted string */
288 char *end = strchr(space+2, '\0');
289 if (end[-1] == '"')
290 end[-1] = '\0';
291 *space = '\0';
292 device_tree_add_string(root, device_path, space + 2);
293 }
294 else {
295 /* any thing else */
296 space = '\0';
297 device_tree_add_string(root, device_path, space + 1);
298 }
299 }
300 }
301 fclose(description);
302 }
303
304
305 /* Given the file containing the `image', create a device tree that
306 defines the machine to be modeled */
307
308 STATIC_INLINE_PSIM device_tree *
309 create_device_tree(const char *file_name,
310 core *memory)
311 {
312 bfd *image;
313 const device *core_device = core_device_create(memory);
314 device_tree *root = device_tree_add_device(NULL, "/", core_device);
315
316 bfd_init(); /* could be redundant but ... */
317
318 /* open the file */
319 image = bfd_openr(file_name, NULL);
320 if (image == NULL) {
321 bfd_perror("open failed:");
322 error("nothing loaded\n");
323 }
324
325 /* check it is valid */
326 if (!bfd_check_format(image, bfd_object)) {
327 printf_filtered("create_device_tree() - FIXME - should check more bfd bits\n");
328 printf_filtered("create_device_tree() - %s not an executable, assume device file\n", file_name);
329 bfd_close(image);
330 image = NULL;
331 }
332
333 /* depending on what was found about the file, load it */
334 if (image != NULL) {
335 if (bfd_get_start_address(image) < OEA_START_ADDRESS) {
336 TRACE(trace_device_tree, ("create_device_tree() - hardware image\n"));
337 create_hardware_device_tree(image, root);
338 }
339 else if (bfd_get_start_address(image) < OPENBOOT_START_ADDRESS) {
340 TRACE(trace_device_tree, ("create_device_tree() - vea image\n"));
341 create_vea_device_tree(image, root);
342 }
343 else {
344 TRACE(trace_device_tree, ("create_device_tree() - openboot? image\n"));
345 create_openboot_device_tree(image, root);
346 }
347 bfd_close(image);
348 }
349 else {
350 TRACE(trace_device_tree, ("create_device_tree() - text image\n"));
351 create_filed_device_tree(file_name, root);
352 }
353
354 return root;
355 }
356
357
358
359 INLINE_PSIM psim *
360 psim_create(const char *file_name)
361 {
362 int cpu_nr;
363 const char *env;
364 psim *system;
365
366 /* create things */
367 system = ZALLOC(psim);
368 system->events = event_queue_create();
369 system->memory = core_create();
370 system->monitor = mon_create();
371 system->devices = create_device_tree(file_name, system->memory);
372 for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; cpu_nr++) {
373 system->processors[cpu_nr] = cpu_create(system,
374 system->memory,
375 system->events,
376 mon_cpu(system->monitor,
377 cpu_nr),
378 cpu_nr);
379 }
380
381 /* fill in the missing real number of CPU's */
382 system->nr_cpus = device_tree_find_integer(system->devices,
383 "/options/smp");
384
385 /* fill in the missing TARGET BYTE ORDER information */
386 current_target_byte_order = (device_tree_find_boolean(system->devices,
387 "/options/little-endian?")
388 ? LITTLE_ENDIAN
389 : BIG_ENDIAN);
390 if (CURRENT_TARGET_BYTE_ORDER != current_target_byte_order)
391 error("target byte order conflict\n");
392
393 /* fill in the missing HOST BYTE ORDER information */
394 current_host_byte_order = (current_host_byte_order = 1,
395 (*(char*)(&current_host_byte_order)
396 ? LITTLE_ENDIAN
397 : BIG_ENDIAN));
398 if (CURRENT_HOST_BYTE_ORDER != current_host_byte_order)
399 error("host byte order conflict\n");
400
401 /* fill in the missing OEA/VEA information */
402 env = device_tree_find_string(system->devices,
403 "/options/environment-architecture");
404 current_environment = (strcmp(env, "user") == 0
405 ? USER_ENVIRONMENT
406 : strcmp(env, "virtual") == 0
407 ? VIRTUAL_ENVIRONMENT
408 : strcmp(env, "operating") == 0
409 ? OPERATING_ENVIRONMENT
410 : 0);
411 if (current_environment == 0)
412 error("unreconized /options/environment-architecture\n");
413 if (CURRENT_ENVIRONMENT != current_environment)
414 error("target environment conflict\n");
415
416 /* fill in the missing ALLIGNMENT information */
417 current_alignment = (device_tree_find_boolean(system->devices,
418 "/options/strict-alignment?")
419 ? STRICT_ALIGNMENT
420 : NONSTRICT_ALIGNMENT);
421 if (CURRENT_ALIGNMENT != current_alignment)
422 error("target alignment conflict\n");
423
424 /* fill in the missing FLOATING POINT information */
425 current_floating_point = (device_tree_find_boolean(system->devices,
426 "/options/floating-point?")
427 ? HARD_FLOATING_POINT
428 : SOFT_FLOATING_POINT);
429 if (CURRENT_FLOATING_POINT != current_floating_point)
430 error("target floating-point conflict\n");
431
432 return system;
433 }
434
435
436 /* allow the simulation to stop/restart abnormaly */
437
438 STATIC_INLINE_PSIM void
439 psim_set_halt_and_restart(psim *system,
440 void *halt_jmp_buf,
441 void *restart_jmp_buf)
442 {
443 system->path_to_halt = halt_jmp_buf;
444 system->path_to_restart = restart_jmp_buf;
445 }
446
447 STATIC_INLINE_PSIM void
448 psim_clear_halt_and_restart(psim *system)
449 {
450 system->path_to_halt = NULL;
451 system->path_to_restart = NULL;
452 }
453
454 INLINE_PSIM void
455 psim_restart(psim *system,
456 int current_cpu)
457 {
458 system->last_cpu = current_cpu;
459 longjmp(*(jmp_buf*)(system->path_to_restart), current_cpu + 1);
460 }
461
462
463 INLINE_PSIM void
464 psim_halt(psim *system,
465 int current_cpu,
466 unsigned_word cia,
467 stop_reason reason,
468 int signal)
469 {
470 system->last_cpu = current_cpu;
471 system->halt_status.cpu_nr = current_cpu;
472 system->halt_status.reason = reason;
473 system->halt_status.signal = signal;
474 system->halt_status.program_counter = cia;
475 longjmp(*(jmp_buf*)(system->path_to_halt), current_cpu + 1);
476 }
477
478 INLINE_PSIM psim_status
479 psim_get_status(psim *system)
480 {
481 return system->halt_status;
482 }
483
484
485 cpu *
486 psim_cpu(psim *system,
487 int cpu_nr)
488 {
489 if (cpu_nr < 0 || cpu_nr >= system->nr_cpus)
490 return NULL;
491 else
492 return system->processors[cpu_nr];
493 }
494
495
496 const device *
497 psim_device(psim *system,
498 const char *path)
499 {
500 return device_tree_find_device(system->devices, path);
501 }
502
503
504
505 INLINE_PSIM void
506 psim_init(psim *system)
507 {
508 int cpu_nr;
509
510 /* scrub the monitor */
511 mon_init(system->monitor, system->nr_cpus);
512
513 /* scrub all the cpus */
514 for (cpu_nr = 0; cpu_nr < system->nr_cpus; cpu_nr++)
515 cpu_init(system->processors[cpu_nr]);
516
517 /* init all the devices */
518 device_tree_init(system->devices, system);
519
520 /* force loop to restart */
521 system->last_cpu = system->nr_cpus - 1;
522 }
523
524 INLINE_PSIM void
525 psim_stack(psim *system,
526 char **argv,
527 char **envp)
528 {
529 /* pass the stack device the argv/envp and let it work out what to
530 do with it */
531 const device *stack_device = device_tree_find_device(system->devices,
532 "/init/stack");
533 unsigned_word stack_pointer;
534 psim_read_register(system, 0, &stack_pointer, "sp", cooked_transfer);
535 stack_device->callback->ioctl(stack_device,
536 system,
537 NULL, /*cpu*/
538 0, /*cia*/
539 stack_pointer,
540 argv,
541 envp);
542 }
543
544
545
546 /* EXECUTE REAL CODE:
547
548 Unfortunatly, there are multiple cases to consider vis:
549
550 <icache> X <smp> X <events> X <keep-running-flag> X ...
551
552 Consequently this function is written in multiple different ways */
553
554 STATIC_INLINE_PSIM void
555 run_until_stop(psim *system,
556 volatile int *keep_running)
557 {
558 jmp_buf halt;
559 jmp_buf restart;
560 int cpu_nr;
561 #if WITH_IDECODE_CACHE_SIZE
562 for (cpu_nr = 0; cpu_nr < system->nr_cpus; cpu_nr++)
563 cpu_flush_icache(system->processors[cpu_nr]);
564 #endif
565 psim_set_halt_and_restart(system, &halt, &restart);
566
567 #if (!WITH_IDECODE_CACHE_SIZE && WITH_SMP == 0)
568
569 /* CASE 1: No instruction cache and no SMP.
570
571 In this case, we can take advantage of the fact that the current
572 instruction address does not need to be returned to the cpu
573 object after every execution of an instruction. Instead it only
574 needs to be saved when either A. the main loop exits or B. a
575 cpu-{halt,restart} call forces the loop to be re-entered. The
576 later functions always save the current cpu instruction
577 address. */
578
579 if (!setjmp(halt)) {
580 do {
581 if (!setjmp(restart)) {
582 cpu *const processor = system->processors[0];
583 unsigned_word cia = cpu_get_program_counter(processor);
584 do {
585 if (WITH_EVENTS) {
586 if (event_queue_tick(system->events)) {
587 cpu_set_program_counter(processor, cia);
588 event_queue_process(system->events);
589 cia = cpu_get_program_counter(processor);
590 }
591 }
592 {
593 instruction_word const instruction
594 = vm_instruction_map_read(cpu_instruction_map(processor),
595 processor, cia);
596 cia = idecode_issue(processor, instruction, cia);
597 }
598 } while (keep_running == NULL || *keep_running);
599 cpu_set_program_counter(processor, cia);
600 }
601 } while(keep_running == NULL || *keep_running);
602 }
603 #endif
604
605
606 #if (WITH_IDECODE_CACHE_SIZE && WITH_SMP == 0)
607
608 /* CASE 2: Instruction case but no SMP
609
610 Here, the additional complexity comes from there being two
611 different cache implementations. A simple function address cache
612 or a full cracked instruction cache */
613
614 if (!setjmp(halt)) {
615 do {
616 if (!setjmp(restart)) {
617 cpu *const processor = system->processors[0];
618 unsigned_word cia = cpu_get_program_counter(processor);
619 do {
620 if (WITH_EVENTS)
621 if (event_queue_tick(system->events)) {
622 cpu_set_program_counter(processor, cia);
623 event_queue_process(system->events);
624 cia = cpu_get_program_counter(processor);
625 }
626 {
627 idecode_cache *const cache_entry = cpu_icache_entry(processor,
628 cia);
629 if (cache_entry->address == cia) {
630 idecode_semantic *const semantic = cache_entry->semantic;
631 cia = semantic(processor, cache_entry, cia);
632 }
633 else {
634 instruction_word const instruction
635 = vm_instruction_map_read(cpu_instruction_map(processor),
636 processor,
637 cia);
638 idecode_semantic *const semantic = idecode(processor,
639 instruction,
640 cia,
641 cache_entry);
642 cache_entry->address = cia;
643 cache_entry->semantic = semantic;
644 cia = semantic(processor, cache_entry, cia);
645 }
646 }
647 } while (keep_running == NULL || *keep_running);
648 cpu_set_program_counter(processor, cia);
649 }
650 } while(keep_running == NULL || *keep_running);
651 }
652 #endif
653
654
655 #if (!WITH_IDECODE_CACHE_SIZE && WITH_SMP > 0)
656
657 /* CASE 3: No ICACHE but SMP
658
659 The complexity here comes from needing to correctly restart the
660 system when it is aborted. In particular if cpu0 requests a
661 restart, the next cpu is still cpu1. Cpu0 being restarted after
662 all the other CPU's and the event queue have been processed */
663
664 if (!setjmp(halt)) {
665 int first_cpu = setjmp(restart);
666 if (first_cpu == 0)
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 *const processor = system->processors[current_cpu];
679 unsigned_word const cia = cpu_get_program_counter(processor);
680 instruction_word instruction =
681 vm_instruction_map_read(cpu_instruction_map(processor),
682 processor,
683 cia);
684 cpu_set_program_counter(processor,
685 idecode_issue(processor, instruction, cia));
686 }
687 if (!(keep_running == NULL || *keep_running)) {
688 system->last_cpu = current_cpu;
689 break;
690 }
691 }
692 } while (keep_running == NULL || *keep_running);
693 }
694 #endif
695
696 #if (WITH_IDECODE_CACHE_SIZE && WITH_SMP > 0)
697
698 /* CASE 4: ICACHE and SMP ...
699
700 This time, everything goes wrong. Need to restart loops
701 correctly, need to save the program counter and finally need to
702 keep track of each processors current address! */
703
704 if (!setjmp(halt)) {
705 int first_cpu = setjmp(restart);
706 if (!first_cpu)
707 first_cpu = system->last_cpu + 1;
708 do {
709 int current_cpu;
710 for (current_cpu = first_cpu, first_cpu = 0;
711 current_cpu < system->nr_cpus + (WITH_EVENTS ? 1 : 0);
712 current_cpu++) {
713 if (WITH_EVENTS && current_cpu == system->nr_cpus) {
714 if (event_queue_tick(system->events))
715 event_queue_process(system->events);
716 }
717 else {
718 cpu *processor = system->processors[current_cpu];
719 unsigned_word const cia = cpu_get_program_counter(processor);
720 idecode_cache *cache_entry = cpu_icache_entry(processor, cia);
721 if (cache_entry->address == cia) {
722 idecode_semantic *semantic = cache_entry->semantic;
723 cpu_set_program_counter(processor,
724 semantic(processor, cache_entry, cia));
725 }
726 else {
727 instruction_word instruction =
728 vm_instruction_map_read(cpu_instruction_map(processor),
729 processor,
730 cia);
731 idecode_semantic *semantic = idecode(processor,
732 instruction,
733 cia,
734 cache_entry);
735 cache_entry->address = cia;
736 cache_entry->semantic = semantic;
737 cpu_set_program_counter(processor,
738 semantic(processor, cache_entry, cia));
739 }
740 }
741 if (!(keep_running == NULL || *keep_running))
742 break;
743 }
744 } while (keep_running == NULL || *keep_running);
745 }
746 #endif
747
748 psim_clear_halt_and_restart(system);
749 }
750
751
752 /* SIMULATE INSTRUCTIONS, various different ways of achieving the same
753 thing */
754
755 INLINE_PSIM void
756 psim_step(psim *system)
757 {
758 volatile int keep_running = 0;
759 run_until_stop(system, &keep_running);
760 }
761
762 INLINE_PSIM void
763 psim_run(psim *system)
764 {
765 run_until_stop(system, NULL);
766 }
767
768 INLINE_PSIM void
769 psim_run_until_stop(psim *system,
770 volatile int *keep_running)
771 {
772 run_until_stop(system, keep_running);
773 }
774
775
776
777 /* storage manipulation functions */
778
779 INLINE_PSIM void
780 psim_read_register(psim *system,
781 int which_cpu,
782 void *buf,
783 const char reg[],
784 transfer_mode mode)
785 {
786 register_descriptions description;
787 char cooked_buf[sizeof(natural_word)];
788 cpu *processor;
789
790 /* find our processor */
791 if (which_cpu == MAX_NR_PROCESSORS)
792 which_cpu = system->last_cpu;
793 if (which_cpu < 0 || which_cpu >= system->nr_cpus)
794 error("psim_read_register() - invalid processor %d\n", which_cpu);
795 processor = system->processors[which_cpu];
796
797 /* find the register description */
798 description = register_description(reg);
799 if (description.type == reg_invalid)
800 error("psim_read_register() invalid register name `%s'\n", reg);
801
802 /* get the cooked value */
803 switch (description.type) {
804
805 case reg_gpr:
806 *(gpreg*)cooked_buf = cpu_registers(processor)->gpr[description.index];
807 break;
808
809 case reg_spr:
810 *(spreg*)cooked_buf = cpu_registers(processor)->spr[description.index];
811 break;
812
813 case reg_sr:
814 *(sreg*)cooked_buf = cpu_registers(processor)->sr[description.index];
815 break;
816
817 case reg_fpr:
818 *(fpreg*)cooked_buf = cpu_registers(processor)->fpr[description.index];
819 break;
820
821 case reg_pc:
822 *(unsigned_word*)cooked_buf = cpu_get_program_counter(processor);
823 break;
824
825 case reg_cr:
826 *(creg*)cooked_buf = cpu_registers(processor)->cr;
827 break;
828
829 case reg_msr:
830 *(msreg*)cooked_buf = cpu_registers(processor)->msr;
831 break;
832
833 default:
834 printf_filtered("psim_read_register(processor=0x%x,buf=0x%x,reg=%s) %s\n",
835 processor, buf, reg,
836 "read of this register unimplemented");
837 break;
838
839 }
840
841 /* the PSIM internal values are in host order. To fetch raw data,
842 they need to be converted into target order and then returned */
843 if (mode == raw_transfer) {
844 /* FIXME - assumes that all registers are simple integers */
845 switch (description.size) {
846 case 1:
847 *(unsigned_1*)buf = H2T_1(*(unsigned_1*)cooked_buf);
848 break;
849 case 2:
850 *(unsigned_2*)buf = H2T_2(*(unsigned_2*)cooked_buf);
851 break;
852 case 4:
853 *(unsigned_4*)buf = H2T_4(*(unsigned_4*)cooked_buf);
854 break;
855 case 8:
856 *(unsigned_8*)buf = H2T_8(*(unsigned_8*)cooked_buf);
857 break;
858 }
859 }
860 else {
861 bcopy(cooked_buf, buf, description.size);
862 }
863
864 }
865
866
867
868 INLINE_PSIM void
869 psim_write_register(psim *system,
870 int which_cpu,
871 const void *buf,
872 const char reg[],
873 transfer_mode mode)
874 {
875 cpu *processor;
876 register_descriptions description;
877 char cooked_buf[sizeof(natural_word)];
878
879 /* find our processor */
880 if (which_cpu == MAX_NR_PROCESSORS)
881 which_cpu = system->last_cpu;
882 if (which_cpu == -1) {
883 int i;
884 for (i = 0; i < system->nr_cpus; i++)
885 psim_write_register(system, i, buf, reg, mode);
886 return;
887 }
888 else if (which_cpu < 0 || which_cpu >= system->nr_cpus) {
889 error("psim_read_register() - invalid processor %d\n", which_cpu);
890 }
891
892 processor = system->processors[which_cpu];
893
894 /* find the description of the register */
895 description = register_description(reg);
896 if (description.type == reg_invalid)
897 error("psim_write_register() invalid register name %s\n", reg);
898
899 /* If the data is comming in raw (target order), need to cook it
900 into host order before putting it into PSIM's internal structures */
901 if (mode == raw_transfer) {
902 switch (description.size) {
903 case 1:
904 *(unsigned_1*)cooked_buf = T2H_1(*(unsigned_1*)buf);
905 break;
906 case 2:
907 *(unsigned_2*)cooked_buf = T2H_2(*(unsigned_2*)buf);
908 break;
909 case 4:
910 *(unsigned_4*)cooked_buf = T2H_4(*(unsigned_4*)buf);
911 break;
912 case 8:
913 *(unsigned_8*)cooked_buf = T2H_8(*(unsigned_8*)buf);
914 break;
915 }
916 }
917 else {
918 bcopy(buf, cooked_buf, description.size);
919 }
920
921 /* put the cooked value into the register */
922 switch (description.type) {
923
924 case reg_gpr:
925 cpu_registers(processor)->gpr[description.index] = *(gpreg*)cooked_buf;
926 break;
927
928 case reg_fpr:
929 cpu_registers(processor)->fpr[description.index] = *(fpreg*)cooked_buf;
930 break;
931
932 case reg_pc:
933 cpu_set_program_counter(processor, *(unsigned_word*)cooked_buf);
934 break;
935
936 case reg_spr:
937 cpu_registers(processor)->spr[description.index] = *(spreg*)cooked_buf;
938 break;
939
940 case reg_sr:
941 cpu_registers(processor)->sr[description.index] = *(sreg*)cooked_buf;
942 break;
943
944 case reg_cr:
945 cpu_registers(processor)->cr = *(creg*)cooked_buf;
946 break;
947
948 case reg_msr:
949 cpu_registers(processor)->msr = *(msreg*)cooked_buf;
950 break;
951
952 default:
953 printf_filtered("psim_write_register(processor=0x%x,cooked_buf=0x%x,reg=%s) %s\n",
954 processor, cooked_buf, reg,
955 "read of this register unimplemented");
956 break;
957
958 }
959
960 }
961
962
963
964 INLINE_PSIM unsigned
965 psim_read_memory(psim *system,
966 int which_cpu,
967 void *buffer,
968 unsigned_word vaddr,
969 unsigned nr_bytes)
970 {
971 cpu *processor;
972 if (which_cpu == MAX_NR_PROCESSORS)
973 which_cpu = system->last_cpu;
974 if (which_cpu < 0 || which_cpu >= system->nr_cpus)
975 error("psim_read_memory() invalid cpu\n");
976 processor = system->processors[which_cpu];
977 return vm_data_map_read_buffer(cpu_data_map(processor),
978 buffer, vaddr, nr_bytes);
979 }
980
981
982 INLINE_PSIM unsigned
983 psim_write_memory(psim *system,
984 int which_cpu,
985 const void *buffer,
986 unsigned_word vaddr,
987 unsigned nr_bytes,
988 int violate_read_only_section)
989 {
990 cpu *processor;
991 if (which_cpu == MAX_NR_PROCESSORS)
992 which_cpu = system->last_cpu;
993 if (which_cpu < 0 || which_cpu >= system->nr_cpus)
994 error("psim_read_memory() invalid cpu\n");
995 processor = system->processors[which_cpu];
996 return vm_data_map_write_buffer(cpu_data_map(processor),
997 buffer, vaddr, nr_bytes, 1);
998 }
999
1000
1001 INLINE_PSIM void
1002 psim_print_info(psim *system,
1003 int verbose)
1004 {
1005 mon_print_info(system->monitor, verbose);
1006 }
1007
1008
1009 #endif /* _PSIM_C_ */
This page took 0.049431 seconds and 4 git commands to generate.