1 /* This file is part of the program psim.
3 Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
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.
29 #include "ppc-config.h"
36 #ifndef STATIC_INLINE_PSIM
37 #define STATIC_INLINE_PSIM STATIC_INLINE
42 #include "cpu.h" /* includes psim.h */
58 /* Any starting address less than this is assumed to be an OEA program
60 #ifndef OEA_START_ADDRESS
61 #define OEA_START_ADDRESS 4096
64 /* Any starting address greater than this is assumed to be an OpenBoot
66 #ifndef OPENBOOT_START_ADDRESS
67 #define OPENBOOT_START_ADDRESS 0x80000000
70 #ifndef OEA_MEMORY_SIZE
71 #define OEA_MEMORY_SIZE 0x100000
75 /* system structure, actual size of processor array determined at
83 /* escape routine for inner functions */
85 void *path_to_restart
;
86 /* status from last halt */
87 psim_status halt_status
;
88 /* the processes proper */
90 int last_cpu
; /* CPU that last (tried to) execute an instruction */
91 cpu
*processors
[MAX_NR_PROCESSORS
];
95 int current_target_byte_order
;
96 int current_host_byte_order
;
97 int current_environment
;
98 int current_alignment
;
99 int current_floating_point
;
100 ppc_model current_ppc_model
= WITH_DEFAULT_PPC_MODEL
;
103 /* create a device tree from the image */
107 /* Raw hardware tree:
109 A small default set of devices are configured. Each section of the
110 image is loaded directly into physical memory. */
112 STATIC_INLINE_PSIM
void
113 create_hardware_device_tree(bfd
*image
,
117 const memory_size
= OEA_MEMORY_SIZE
;
120 device_tree_add_passthrough(root
, "/options");
121 device_tree_add_integer(root
, "/options/smp",
123 device_tree_add_boolean(root
, "/options/little-endian?",
124 !image
->xvec
->byteorder_big_p
);
125 device_tree_add_string(root
, "/options/env",
127 device_tree_add_boolean(root
, "/options/strict-alignment?",
128 (WITH_ALIGNMENT
== STRICT_ALIGNMENT
129 || !image
->xvec
->byteorder_big_p
));
130 device_tree_add_boolean(root
, "/options/floating-point?",
131 WITH_FLOATING_POINT
);
134 name
= printd_uw_u_u("/memory", 0, memory_size
, access_read_write_exec
);
135 device_tree_add_found_device(root
, name
);
137 device_tree_add_found_device(root
, "/iobus@0x400000");
138 device_tree_add_found_device(root
, "/iobus/console@0x000000,16");
139 device_tree_add_found_device(root
, "/iobus/halt@0x100000,4");
140 device_tree_add_found_device(root
, "/iobus/icu@0x200000,4");
143 device_tree_add_passthrough(root
, "/init");
144 device_tree_add_found_device(root
, "/init/register@pc,0x0");
145 name
= printd_c_uw("/init/register", "sp", memory_size
);
146 device_tree_add_found_device(root
, name
);
148 name
= printd_c_uw("/init/register", "msr",
149 (image
->xvec
->byteorder_big_p
151 : msr_little_endian_mode
));
152 device_tree_add_found_device(root
, name
);
154 /* AJC puts the PC at zero and wants a stack while MM puts it above
155 zero and doesn't. Really there should be no stack *but* this
156 makes testing easier */
157 device_tree_add_found_device(root
,
158 (bfd_get_start_address(image
) == 0
160 : "/init/stack@none"));
161 name
= printd_c("/init/load-binary", bfd_get_filename(image
));
162 device_tree_add_found_device(root
, name
);
167 /* Openboot model (under development):
169 An extension of the hardware model. The image is read into memory
170 as a single block. Sections of the image are then mapped as
171 required using a HTAB. */
173 STATIC_INLINE_PSIM
void
174 create_openboot_device_tree(bfd
*image
,
177 create_hardware_device_tree(image
, root
);
183 Image sections loaded into virtual addresses as specified. A
184 (large) stack is reserved (but only allocated as needed). System
185 calls that include suport for heap growth are attached. */
187 STATIC_INLINE_PSIM
void
188 create_vea_device_tree(bfd
*image
,
191 unsigned_word top_of_stack
;
196 /* establish a few defaults */
197 if (image
->xvec
->flavour
== bfd_target_elf_flavour
) {
199 top_of_stack
= 0xe0000000;
200 stack_size
= 0x00100000;
204 top_of_stack
= 0x20000000;
205 stack_size
= 0x00100000;
209 device_tree_add_passthrough(root
, "/options");
210 device_tree_add_integer(root
, "/options/smp", 1); /* always */
211 device_tree_add_boolean(root
, "/options/little-endian?",
212 !image
->xvec
->byteorder_big_p
);
213 device_tree_add_string(root
, "/options/env",
214 (WITH_ENVIRONMENT
== USER_ENVIRONMENT
215 ? "user" : "virtual"));
216 device_tree_add_boolean(root
, "/options/strict-alignment?",
217 (WITH_ALIGNMENT
== STRICT_ALIGNMENT
218 || !image
->xvec
->byteorder_big_p
));
219 device_tree_add_boolean(root
, "/options/floating-point?",
220 WITH_FLOATING_POINT
);
222 /* virtual memory - handles growth of stack/heap */
223 name
= printd_uw_u("/vm", top_of_stack
- stack_size
, stack_size
);
224 device_tree_add_found_device(root
, name
);
226 name
= printd_c("/vm/map-binary", bfd_get_filename(image
));
227 device_tree_add_found_device(root
, name
);
230 /* finish the init */
231 device_tree_add_passthrough(root
, "/init");
232 name
= printd_c_uw("/init/register", "pc", bfd_get_start_address(image
));
233 device_tree_add_found_device(root
, name
); /*pc*/
235 name
= printd_c_uw("/init/register", "sp", top_of_stack
);
236 device_tree_add_found_device(root
, name
);
238 name
= printd_c_uw("/init/register", "msr",
239 (image
->xvec
->byteorder_big_p
241 : msr_little_endian_mode
));
242 device_tree_add_found_device(root
, name
);
244 device_tree_add_found_device(root
, (elf_binary
246 : "/init/stack@xcoff"));
252 The file contains lines that specify the describe the device tree
253 to be created, read them in and load them into the tree */
255 STATIC_INLINE_PSIM
void
256 create_filed_device_tree(const char *file_name
,
259 FILE *description
= fopen(file_name
, "r");
261 char device_path
[1000];
262 while (fgets(device_path
, sizeof(device_path
), description
)) {
263 /* check all of line was read */
265 char *end
= strchr(device_path
, '\n');
268 error("create_filed_device_tree() line %d to long: %s\n",
269 line_nr
, device_path
);
274 /* check for leading comment */
275 if (device_path
[0] != '/')
277 /* enter it in varying ways */
278 if (strchr(device_path
, '@') != NULL
) {
279 device_tree_add_found_device(root
, device_path
);
282 char *space
= strchr(device_path
, ' ');
284 /* intermediate node */
285 device_tree_add_passthrough(root
, device_path
);
287 else if (space
[-1] == '?') {
290 device_tree_add_boolean(root
, device_path
, space
[1] != '0');
292 else if (isdigit(space
[1])) {
295 device_tree_add_integer(root
, device_path
, strtoul(space
+1, 0, 0));
297 else if (space
[1] == '"') {
299 char *end
= strchr(space
+2, '\0');
303 device_tree_add_string(root
, device_path
, space
+ 2);
308 device_tree_add_string(root
, device_path
, space
+ 1);
316 /* Given the file containing the `image', create a device tree that
317 defines the machine to be modeled */
319 STATIC_INLINE_PSIM device_tree
*
320 create_device_tree(const char *file_name
,
324 const device
*core_device
= core_device_create(memory
);
325 device_tree
*root
= device_tree_add_device(NULL
, "/", core_device
);
327 bfd_init(); /* could be redundant but ... */
330 image
= bfd_openr(file_name
, NULL
);
332 bfd_perror("open failed:");
333 error("nothing loaded\n");
336 /* check it is valid */
337 if (!bfd_check_format(image
, bfd_object
)) {
338 printf_filtered("create_device_tree() - FIXME - should check more bfd bits\n");
339 printf_filtered("create_device_tree() - %s not an executable, assume device file\n", file_name
);
344 /* depending on what was found about the file, load it */
346 if (bfd_get_start_address(image
) < OEA_START_ADDRESS
) {
347 TRACE(trace_device_tree
, ("create_device_tree() - hardware image\n"));
348 create_hardware_device_tree(image
, root
);
350 else if (bfd_get_start_address(image
) < OPENBOOT_START_ADDRESS
) {
351 TRACE(trace_device_tree
, ("create_device_tree() - vea image\n"));
352 create_vea_device_tree(image
, root
);
355 TRACE(trace_device_tree
, ("create_device_tree() - openboot? image\n"));
356 create_openboot_device_tree(image
, root
);
361 TRACE(trace_device_tree
, ("create_device_tree() - text image\n"));
362 create_filed_device_tree(file_name
, root
);
371 psim_create(const char *file_name
)
378 system
= ZALLOC(psim
);
379 system
->events
= event_queue_create();
380 system
->memory
= core_create();
381 system
->monitor
= mon_create();
382 system
->devices
= create_device_tree(file_name
, system
->memory
);
383 for (cpu_nr
= 0; cpu_nr
< MAX_NR_PROCESSORS
; cpu_nr
++) {
384 system
->processors
[cpu_nr
] = cpu_create(system
,
387 mon_cpu(system
->monitor
,
392 /* fill in the missing real number of CPU's */
393 system
->nr_cpus
= device_tree_find_integer(system
->devices
,
396 /* fill in the missing TARGET BYTE ORDER information */
397 current_target_byte_order
= (device_tree_find_boolean(system
->devices
,
398 "/options/little-endian?")
401 if (CURRENT_TARGET_BYTE_ORDER
!= current_target_byte_order
)
402 error("target byte order conflict\n");
404 /* fill in the missing HOST BYTE ORDER information */
405 current_host_byte_order
= (current_host_byte_order
= 1,
406 (*(char*)(¤t_host_byte_order
)
409 if (CURRENT_HOST_BYTE_ORDER
!= current_host_byte_order
)
410 error("host byte order conflict\n");
412 /* fill in the missing OEA/VEA information */
413 env
= device_tree_find_string(system
->devices
,
415 current_environment
= ((strcmp(env
, "user") == 0
416 || strcmp(env
, "uea") == 0)
418 : (strcmp(env
, "virtual") == 0
419 || strcmp(env
, "vea") == 0)
420 ? VIRTUAL_ENVIRONMENT
421 : (strcmp(env
, "operating") == 0
422 || strcmp(env
, "oea") == 0)
423 ? OPERATING_ENVIRONMENT
425 if (current_environment
== 0)
426 error("unreconized /options/env\n");
427 if (CURRENT_ENVIRONMENT
!= current_environment
)
428 error("target environment conflict\n");
430 /* fill in the missing ALLIGNMENT information */
431 current_alignment
= (device_tree_find_boolean(system
->devices
,
432 "/options/strict-alignment?")
434 : NONSTRICT_ALIGNMENT
);
435 if (CURRENT_ALIGNMENT
!= current_alignment
)
436 error("target alignment conflict\n");
438 /* fill in the missing FLOATING POINT information */
439 current_floating_point
= (device_tree_find_boolean(system
->devices
,
440 "/options/floating-point?")
441 ? HARD_FLOATING_POINT
442 : SOFT_FLOATING_POINT
);
443 if (CURRENT_FLOATING_POINT
!= current_floating_point
)
444 error("target floating-point conflict\n");
450 /* allow the simulation to stop/restart abnormaly */
452 STATIC_INLINE_PSIM
void
453 psim_set_halt_and_restart(psim
*system
,
455 void *restart_jmp_buf
)
457 system
->path_to_halt
= halt_jmp_buf
;
458 system
->path_to_restart
= restart_jmp_buf
;
461 STATIC_INLINE_PSIM
void
462 psim_clear_halt_and_restart(psim
*system
)
464 system
->path_to_halt
= NULL
;
465 system
->path_to_restart
= NULL
;
469 psim_restart(psim
*system
,
472 system
->last_cpu
= current_cpu
;
473 longjmp(*(jmp_buf*)(system
->path_to_restart
), current_cpu
+ 1);
478 psim_halt(psim
*system
,
484 system
->last_cpu
= current_cpu
;
485 system
->halt_status
.cpu_nr
= current_cpu
;
486 system
->halt_status
.reason
= reason
;
487 system
->halt_status
.signal
= signal
;
488 system
->halt_status
.program_counter
= cia
;
489 longjmp(*(jmp_buf*)(system
->path_to_halt
), current_cpu
+ 1);
492 INLINE_PSIM psim_status
493 psim_get_status(psim
*system
)
495 return system
->halt_status
;
500 psim_cpu(psim
*system
,
503 if (cpu_nr
< 0 || cpu_nr
>= system
->nr_cpus
)
506 return system
->processors
[cpu_nr
];
511 psim_device(psim
*system
,
514 return device_tree_find_device(system
->devices
, path
);
520 psim_init(psim
*system
)
524 /* scrub the monitor */
525 mon_init(system
->monitor
, system
->nr_cpus
);
527 /* scrub all the cpus */
528 for (cpu_nr
= 0; cpu_nr
< system
->nr_cpus
; cpu_nr
++)
529 cpu_init(system
->processors
[cpu_nr
]);
531 /* init all the devices */
532 device_tree_init(system
->devices
, system
);
534 /* force loop to restart */
535 system
->last_cpu
= system
->nr_cpus
- 1;
539 psim_stack(psim
*system
,
543 /* pass the stack device the argv/envp and let it work out what to
545 const device
*stack_device
= device_tree_find_device(system
->devices
,
547 unsigned_word stack_pointer
;
548 psim_read_register(system
, 0, &stack_pointer
, "sp", cooked_transfer
);
549 stack_device
->callback
->ioctl(stack_device
,
560 /* EXECUTE REAL CODE:
562 Unfortunatly, there are multiple cases to consider vis:
564 <icache> X <smp> X <events> X <keep-running-flag> X ...
566 Consequently this function is written in multiple different ways */
568 STATIC_INLINE_PSIM
void
569 run_until_stop(psim
*system
,
570 volatile int *keep_running
)
575 #if WITH_IDECODE_CACHE_SIZE
576 for (cpu_nr
= 0; cpu_nr
< system
->nr_cpus
; cpu_nr
++)
577 cpu_flush_icache(system
->processors
[cpu_nr
]);
579 psim_set_halt_and_restart(system
, &halt
, &restart
);
581 #if (!WITH_IDECODE_CACHE_SIZE && WITH_SMP == 0)
583 /* CASE 1: No instruction cache and no SMP.
585 In this case, we can take advantage of the fact that the current
586 instruction address does not need to be returned to the cpu
587 object after every execution of an instruction. Instead it only
588 needs to be saved when either A. the main loop exits or B. a
589 cpu-{halt,restart} call forces the loop to be re-entered. The
590 later functions always save the current cpu instruction
595 if (!setjmp(restart
)) {
596 cpu
*const processor
= system
->processors
[0];
597 unsigned_word cia
= cpu_get_program_counter(processor
);
600 if (event_queue_tick(system
->events
)) {
601 cpu_set_program_counter(processor
, cia
);
602 event_queue_process(system
->events
);
603 cia
= cpu_get_program_counter(processor
);
607 instruction_word
const instruction
608 = vm_instruction_map_read(cpu_instruction_map(processor
),
610 cia
= idecode_issue(processor
, instruction
, cia
);
612 } while (keep_running
== NULL
|| *keep_running
);
613 cpu_set_program_counter(processor
, cia
);
615 } while(keep_running
== NULL
|| *keep_running
);
620 #if (WITH_IDECODE_CACHE_SIZE && WITH_SMP == 0)
622 /* CASE 2: Instruction case but no SMP
624 Here, the additional complexity comes from there being two
625 different cache implementations. A simple function address cache
626 or a full cracked instruction cache */
630 if (!setjmp(restart
)) {
631 cpu
*const processor
= system
->processors
[0];
632 unsigned_word cia
= cpu_get_program_counter(processor
);
635 if (event_queue_tick(system
->events
)) {
636 cpu_set_program_counter(processor
, cia
);
637 event_queue_process(system
->events
);
638 cia
= cpu_get_program_counter(processor
);
641 idecode_cache
*const cache_entry
= cpu_icache_entry(processor
,
643 if (cache_entry
->address
== cia
) {
644 idecode_semantic
*const semantic
= cache_entry
->semantic
;
645 cia
= semantic(processor
, cache_entry
, cia
);
648 instruction_word
const instruction
649 = vm_instruction_map_read(cpu_instruction_map(processor
),
652 idecode_semantic
*const semantic
= idecode(processor
,
656 cache_entry
->address
= cia
;
657 cache_entry
->semantic
= semantic
;
658 cia
= semantic(processor
, cache_entry
, cia
);
661 } while (keep_running
== NULL
|| *keep_running
);
662 cpu_set_program_counter(processor
, cia
);
664 } while(keep_running
== NULL
|| *keep_running
);
669 #if (!WITH_IDECODE_CACHE_SIZE && WITH_SMP > 0)
671 /* CASE 3: No ICACHE but SMP
673 The complexity here comes from needing to correctly restart the
674 system when it is aborted. In particular if cpu0 requests a
675 restart, the next cpu is still cpu1. Cpu0 being restarted after
676 all the other CPU's and the event queue have been processed */
679 int first_cpu
= setjmp(restart
);
681 first_cpu
= system
->last_cpu
+ 1;
684 for (current_cpu
= first_cpu
, first_cpu
= 0;
685 current_cpu
< system
->nr_cpus
+ (WITH_EVENTS
? 1 : 0);
687 if (WITH_EVENTS
&& current_cpu
== system
->nr_cpus
) {
688 if (event_queue_tick(system
->events
))
689 event_queue_process(system
->events
);
692 cpu
*const processor
= system
->processors
[current_cpu
];
693 unsigned_word
const cia
= cpu_get_program_counter(processor
);
694 instruction_word instruction
=
695 vm_instruction_map_read(cpu_instruction_map(processor
),
698 cpu_set_program_counter(processor
,
699 idecode_issue(processor
, instruction
, cia
));
701 if (!(keep_running
== NULL
|| *keep_running
)) {
702 system
->last_cpu
= current_cpu
;
706 } while (keep_running
== NULL
|| *keep_running
);
710 #if (WITH_IDECODE_CACHE_SIZE && WITH_SMP > 0)
712 /* CASE 4: ICACHE and SMP ...
714 This time, everything goes wrong. Need to restart loops
715 correctly, need to save the program counter and finally need to
716 keep track of each processors current address! */
719 int first_cpu
= setjmp(restart
);
721 first_cpu
= system
->last_cpu
+ 1;
724 for (current_cpu
= first_cpu
, first_cpu
= 0;
725 current_cpu
< system
->nr_cpus
+ (WITH_EVENTS
? 1 : 0);
727 if (WITH_EVENTS
&& current_cpu
== system
->nr_cpus
) {
728 if (event_queue_tick(system
->events
))
729 event_queue_process(system
->events
);
732 cpu
*processor
= system
->processors
[current_cpu
];
733 unsigned_word
const cia
= cpu_get_program_counter(processor
);
734 idecode_cache
*cache_entry
= cpu_icache_entry(processor
, cia
);
735 if (cache_entry
->address
== cia
) {
736 idecode_semantic
*semantic
= cache_entry
->semantic
;
737 cpu_set_program_counter(processor
,
738 semantic(processor
, cache_entry
, cia
));
741 instruction_word instruction
=
742 vm_instruction_map_read(cpu_instruction_map(processor
),
745 idecode_semantic
*semantic
= idecode(processor
,
749 cache_entry
->address
= cia
;
750 cache_entry
->semantic
= semantic
;
751 cpu_set_program_counter(processor
,
752 semantic(processor
, cache_entry
, cia
));
755 if (!(keep_running
== NULL
|| *keep_running
))
758 } while (keep_running
== NULL
|| *keep_running
);
762 psim_clear_halt_and_restart(system
);
766 /* SIMULATE INSTRUCTIONS, various different ways of achieving the same
770 psim_step(psim
*system
)
772 volatile int keep_running
= 0;
773 run_until_stop(system
, &keep_running
);
777 psim_run(psim
*system
)
779 run_until_stop(system
, NULL
);
783 psim_run_until_stop(psim
*system
,
784 volatile int *keep_running
)
786 run_until_stop(system
, keep_running
);
791 /* storage manipulation functions */
794 psim_read_register(psim
*system
,
800 register_descriptions description
;
801 char cooked_buf
[sizeof(natural_word
)];
804 /* find our processor */
805 if (which_cpu
== MAX_NR_PROCESSORS
)
806 which_cpu
= system
->last_cpu
;
807 if (which_cpu
< 0 || which_cpu
>= system
->nr_cpus
)
808 error("psim_read_register() - invalid processor %d\n", which_cpu
);
809 processor
= system
->processors
[which_cpu
];
811 /* find the register description */
812 description
= register_description(reg
);
813 if (description
.type
== reg_invalid
)
814 error("psim_read_register() invalid register name `%s'\n", reg
);
816 /* get the cooked value */
817 switch (description
.type
) {
820 *(gpreg
*)cooked_buf
= cpu_registers(processor
)->gpr
[description
.index
];
824 *(spreg
*)cooked_buf
= cpu_registers(processor
)->spr
[description
.index
];
828 *(sreg
*)cooked_buf
= cpu_registers(processor
)->sr
[description
.index
];
832 *(fpreg
*)cooked_buf
= cpu_registers(processor
)->fpr
[description
.index
];
836 *(unsigned_word
*)cooked_buf
= cpu_get_program_counter(processor
);
840 *(creg
*)cooked_buf
= cpu_registers(processor
)->cr
;
844 *(msreg
*)cooked_buf
= cpu_registers(processor
)->msr
;
848 printf_filtered("psim_read_register(processor=0x%x,buf=0x%x,reg=%s) %s\n",
850 "read of this register unimplemented");
855 /* the PSIM internal values are in host order. To fetch raw data,
856 they need to be converted into target order and then returned */
857 if (mode
== raw_transfer
) {
858 /* FIXME - assumes that all registers are simple integers */
859 switch (description
.size
) {
861 *(unsigned_1
*)buf
= H2T_1(*(unsigned_1
*)cooked_buf
);
864 *(unsigned_2
*)buf
= H2T_2(*(unsigned_2
*)cooked_buf
);
867 *(unsigned_4
*)buf
= H2T_4(*(unsigned_4
*)cooked_buf
);
870 *(unsigned_8
*)buf
= H2T_8(*(unsigned_8
*)cooked_buf
);
875 bcopy(cooked_buf
, buf
, description
.size
);
883 psim_write_register(psim
*system
,
890 register_descriptions description
;
891 char cooked_buf
[sizeof(natural_word
)];
893 /* find our processor */
894 if (which_cpu
== MAX_NR_PROCESSORS
)
895 which_cpu
= system
->last_cpu
;
896 if (which_cpu
== -1) {
898 for (i
= 0; i
< system
->nr_cpus
; i
++)
899 psim_write_register(system
, i
, buf
, reg
, mode
);
902 else if (which_cpu
< 0 || which_cpu
>= system
->nr_cpus
) {
903 error("psim_read_register() - invalid processor %d\n", which_cpu
);
906 processor
= system
->processors
[which_cpu
];
908 /* find the description of the register */
909 description
= register_description(reg
);
910 if (description
.type
== reg_invalid
)
911 error("psim_write_register() invalid register name %s\n", reg
);
913 /* If the data is comming in raw (target order), need to cook it
914 into host order before putting it into PSIM's internal structures */
915 if (mode
== raw_transfer
) {
916 switch (description
.size
) {
918 *(unsigned_1
*)cooked_buf
= T2H_1(*(unsigned_1
*)buf
);
921 *(unsigned_2
*)cooked_buf
= T2H_2(*(unsigned_2
*)buf
);
924 *(unsigned_4
*)cooked_buf
= T2H_4(*(unsigned_4
*)buf
);
927 *(unsigned_8
*)cooked_buf
= T2H_8(*(unsigned_8
*)buf
);
932 bcopy(buf
, cooked_buf
, description
.size
);
935 /* put the cooked value into the register */
936 switch (description
.type
) {
939 cpu_registers(processor
)->gpr
[description
.index
] = *(gpreg
*)cooked_buf
;
943 cpu_registers(processor
)->fpr
[description
.index
] = *(fpreg
*)cooked_buf
;
947 cpu_set_program_counter(processor
, *(unsigned_word
*)cooked_buf
);
951 cpu_registers(processor
)->spr
[description
.index
] = *(spreg
*)cooked_buf
;
955 cpu_registers(processor
)->sr
[description
.index
] = *(sreg
*)cooked_buf
;
959 cpu_registers(processor
)->cr
= *(creg
*)cooked_buf
;
963 cpu_registers(processor
)->msr
= *(msreg
*)cooked_buf
;
967 printf_filtered("psim_write_register(processor=0x%x,cooked_buf=0x%x,reg=%s) %s\n",
968 processor
, cooked_buf
, reg
,
969 "read of this register unimplemented");
979 psim_read_memory(psim
*system
,
986 if (which_cpu
== MAX_NR_PROCESSORS
)
987 which_cpu
= system
->last_cpu
;
988 if (which_cpu
< 0 || which_cpu
>= system
->nr_cpus
)
989 error("psim_read_memory() invalid cpu\n");
990 processor
= system
->processors
[which_cpu
];
991 return vm_data_map_read_buffer(cpu_data_map(processor
),
992 buffer
, vaddr
, nr_bytes
);
997 psim_write_memory(psim
*system
,
1000 unsigned_word vaddr
,
1002 int violate_read_only_section
)
1005 if (which_cpu
== MAX_NR_PROCESSORS
)
1006 which_cpu
= system
->last_cpu
;
1007 if (which_cpu
< 0 || which_cpu
>= system
->nr_cpus
)
1008 error("psim_read_memory() invalid cpu\n");
1009 processor
= system
->processors
[which_cpu
];
1010 return vm_data_map_write_buffer(cpu_data_map(processor
),
1011 buffer
, vaddr
, nr_bytes
, 1);
1016 psim_print_info(psim
*system
,
1019 mon_print_info(system
, system
->monitor
, verbose
);
1023 #endif /* _PSIM_C_ */