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
;
101 model_enum current_model
= WITH_DEFAULT_MODEL
;
104 /* create a device tree from the image */
108 /* Raw hardware tree:
110 A small default set of devices are configured. Each section of the
111 image is loaded directly into physical memory. */
113 STATIC_INLINE_PSIM
void
114 create_hardware_device_tree(bfd
*image
,
118 const memory_size
= OEA_MEMORY_SIZE
;
121 device_tree_add_passthrough(root
, "/options");
122 device_tree_add_integer(root
, "/options/smp",
124 device_tree_add_boolean(root
, "/options/little-endian?",
125 !image
->xvec
->byteorder_big_p
);
126 device_tree_add_string(root
, "/options/env",
128 device_tree_add_boolean(root
, "/options/strict-alignment?",
129 (WITH_ALIGNMENT
== STRICT_ALIGNMENT
130 || !image
->xvec
->byteorder_big_p
));
131 device_tree_add_boolean(root
, "/options/floating-point?",
132 WITH_FLOATING_POINT
);
135 name
= printd_uw_u_u("/memory", 0, memory_size
, access_read_write_exec
);
136 device_tree_add_found_device(root
, name
);
138 device_tree_add_found_device(root
, "/iobus@0x400000");
139 device_tree_add_found_device(root
, "/iobus/console@0x000000,16");
140 device_tree_add_found_device(root
, "/iobus/halt@0x100000,4");
141 device_tree_add_found_device(root
, "/iobus/icu@0x200000,4");
144 device_tree_add_passthrough(root
, "/init");
145 device_tree_add_found_device(root
, "/init/register@pc,0x0");
146 name
= printd_c_uw("/init/register", "sp", memory_size
);
147 device_tree_add_found_device(root
, name
);
149 name
= printd_c_uw("/init/register", "msr",
150 (image
->xvec
->byteorder_big_p
152 : msr_little_endian_mode
));
153 device_tree_add_found_device(root
, name
);
155 /* AJC puts the PC at zero and wants a stack while MM puts it above
156 zero and doesn't. Really there should be no stack *but* this
157 makes testing easier */
158 device_tree_add_found_device(root
,
159 (bfd_get_start_address(image
) == 0
161 : "/init/stack@none"));
162 name
= printd_c("/init/load-binary", bfd_get_filename(image
));
163 device_tree_add_found_device(root
, name
);
168 /* Openboot model (under development):
170 An extension of the hardware model. The image is read into memory
171 as a single block. Sections of the image are then mapped as
172 required using a HTAB. */
174 STATIC_INLINE_PSIM
void
175 create_openboot_device_tree(bfd
*image
,
178 create_hardware_device_tree(image
, root
);
184 Image sections loaded into virtual addresses as specified. A
185 (large) stack is reserved (but only allocated as needed). System
186 calls that include suport for heap growth are attached. */
188 STATIC_INLINE_PSIM
void
189 create_vea_device_tree(bfd
*image
,
192 unsigned_word top_of_stack
;
197 /* establish a few defaults */
198 if (image
->xvec
->flavour
== bfd_target_elf_flavour
) {
200 top_of_stack
= 0xe0000000;
201 stack_size
= 0x00100000;
205 top_of_stack
= 0x20000000;
206 stack_size
= 0x00100000;
210 device_tree_add_passthrough(root
, "/options");
211 device_tree_add_integer(root
, "/options/smp", 1); /* always */
212 device_tree_add_boolean(root
, "/options/little-endian?",
213 !image
->xvec
->byteorder_big_p
);
214 device_tree_add_string(root
, "/options/env",
215 (WITH_ENVIRONMENT
== USER_ENVIRONMENT
216 ? "user" : "virtual"));
217 device_tree_add_boolean(root
, "/options/strict-alignment?",
218 (WITH_ALIGNMENT
== STRICT_ALIGNMENT
219 || !image
->xvec
->byteorder_big_p
));
220 device_tree_add_boolean(root
, "/options/floating-point?",
221 WITH_FLOATING_POINT
);
223 /* virtual memory - handles growth of stack/heap */
224 name
= printd_uw_u("/vm", top_of_stack
- stack_size
, stack_size
);
225 device_tree_add_found_device(root
, name
);
227 name
= printd_c("/vm/map-binary", bfd_get_filename(image
));
228 device_tree_add_found_device(root
, name
);
231 /* finish the init */
232 device_tree_add_passthrough(root
, "/init");
233 name
= printd_c_uw("/init/register", "pc", bfd_get_start_address(image
));
234 device_tree_add_found_device(root
, name
); /*pc*/
236 name
= printd_c_uw("/init/register", "sp", top_of_stack
);
237 device_tree_add_found_device(root
, name
);
239 name
= printd_c_uw("/init/register", "msr",
240 (image
->xvec
->byteorder_big_p
242 : msr_little_endian_mode
));
243 device_tree_add_found_device(root
, name
);
245 device_tree_add_found_device(root
, (elf_binary
247 : "/init/stack@xcoff"));
253 The file contains lines that specify the describe the device tree
254 to be created, read them in and load them into the tree */
256 STATIC_INLINE_PSIM
void
257 create_filed_device_tree(const char *file_name
,
260 FILE *description
= fopen(file_name
, "r");
262 char device_path
[1000];
263 while (fgets(device_path
, sizeof(device_path
), description
)) {
264 /* check all of line was read */
266 char *end
= strchr(device_path
, '\n');
269 error("create_filed_device_tree() line %d to long: %s\n",
270 line_nr
, device_path
);
275 /* check for leading comment */
276 if (device_path
[0] != '/')
278 /* enter it in varying ways */
279 if (strchr(device_path
, '@') != NULL
) {
280 device_tree_add_found_device(root
, device_path
);
283 char *space
= strchr(device_path
, ' ');
285 /* intermediate node */
286 device_tree_add_passthrough(root
, device_path
);
288 else if (space
[-1] == '?') {
291 device_tree_add_boolean(root
, device_path
, space
[1] != '0');
293 else if (isdigit(space
[1])) {
296 device_tree_add_integer(root
, device_path
, strtoul(space
+1, 0, 0));
298 else if (space
[1] == '"') {
300 char *end
= strchr(space
+2, '\0');
304 device_tree_add_string(root
, device_path
, space
+ 2);
309 device_tree_add_string(root
, device_path
, space
+ 1);
317 /* Given the file containing the `image', create a device tree that
318 defines the machine to be modeled */
320 STATIC_INLINE_PSIM device_tree
*
321 create_device_tree(const char *file_name
,
325 const device
*core_device
= core_device_create(memory
);
326 device_tree
*root
= device_tree_add_device(NULL
, "/", core_device
);
328 bfd_init(); /* could be redundant but ... */
331 image
= bfd_openr(file_name
, NULL
);
333 bfd_perror("open failed:");
334 error("nothing loaded\n");
337 /* check it is valid */
338 if (!bfd_check_format(image
, bfd_object
)) {
339 printf_filtered("create_device_tree() - FIXME - should check more bfd bits\n");
340 printf_filtered("create_device_tree() - %s not an executable, assume device file\n", file_name
);
345 /* depending on what was found about the file, load it */
347 if (bfd_get_start_address(image
) < OEA_START_ADDRESS
) {
348 TRACE(trace_device_tree
, ("create_device_tree() - hardware image\n"));
349 create_hardware_device_tree(image
, root
);
351 else if (bfd_get_start_address(image
) < OPENBOOT_START_ADDRESS
) {
352 TRACE(trace_device_tree
, ("create_device_tree() - vea image\n"));
353 create_vea_device_tree(image
, root
);
356 TRACE(trace_device_tree
, ("create_device_tree() - openboot? image\n"));
357 create_openboot_device_tree(image
, root
);
362 TRACE(trace_device_tree
, ("create_device_tree() - text image\n"));
363 create_filed_device_tree(file_name
, root
);
372 psim_create(const char *file_name
)
379 system
= ZALLOC(psim
);
380 system
->events
= event_queue_create();
381 system
->memory
= core_create();
382 system
->monitor
= mon_create();
383 system
->devices
= create_device_tree(file_name
, system
->memory
);
384 for (cpu_nr
= 0; cpu_nr
< MAX_NR_PROCESSORS
; cpu_nr
++) {
385 system
->processors
[cpu_nr
] = cpu_create(system
,
388 mon_cpu(system
->monitor
,
393 /* fill in the missing real number of CPU's */
394 system
->nr_cpus
= device_tree_find_integer(system
->devices
,
397 /* fill in the missing TARGET BYTE ORDER information */
398 current_target_byte_order
= (device_tree_find_boolean(system
->devices
,
399 "/options/little-endian?")
402 if (CURRENT_TARGET_BYTE_ORDER
!= current_target_byte_order
)
403 error("target byte order conflict\n");
405 /* fill in the missing HOST BYTE ORDER information */
406 current_host_byte_order
= (current_host_byte_order
= 1,
407 (*(char*)(¤t_host_byte_order
)
410 if (CURRENT_HOST_BYTE_ORDER
!= current_host_byte_order
)
411 error("host byte order conflict\n");
413 /* fill in the missing OEA/VEA information */
414 env
= device_tree_find_string(system
->devices
,
416 current_environment
= ((strcmp(env
, "user") == 0
417 || strcmp(env
, "uea") == 0)
419 : (strcmp(env
, "virtual") == 0
420 || strcmp(env
, "vea") == 0)
421 ? VIRTUAL_ENVIRONMENT
422 : (strcmp(env
, "operating") == 0
423 || strcmp(env
, "oea") == 0)
424 ? OPERATING_ENVIRONMENT
426 if (current_environment
== 0)
427 error("unreconized /options/env\n");
428 if (CURRENT_ENVIRONMENT
!= current_environment
)
429 error("target environment conflict\n");
431 /* fill in the missing ALLIGNMENT information */
432 current_alignment
= (device_tree_find_boolean(system
->devices
,
433 "/options/strict-alignment?")
435 : NONSTRICT_ALIGNMENT
);
436 if (CURRENT_ALIGNMENT
!= current_alignment
)
437 error("target alignment conflict\n");
439 /* fill in the missing FLOATING POINT information */
440 current_floating_point
= (device_tree_find_boolean(system
->devices
,
441 "/options/floating-point?")
442 ? HARD_FLOATING_POINT
443 : SOFT_FLOATING_POINT
);
444 if (CURRENT_FLOATING_POINT
!= current_floating_point
)
445 error("target floating-point conflict\n");
451 /* allow the simulation to stop/restart abnormaly */
453 STATIC_INLINE_PSIM
void
454 psim_set_halt_and_restart(psim
*system
,
456 void *restart_jmp_buf
)
458 system
->path_to_halt
= halt_jmp_buf
;
459 system
->path_to_restart
= restart_jmp_buf
;
462 STATIC_INLINE_PSIM
void
463 psim_clear_halt_and_restart(psim
*system
)
465 system
->path_to_halt
= NULL
;
466 system
->path_to_restart
= NULL
;
470 psim_restart(psim
*system
,
473 system
->last_cpu
= current_cpu
;
474 longjmp(*(jmp_buf*)(system
->path_to_restart
), current_cpu
+ 1);
479 psim_halt(psim
*system
,
485 system
->last_cpu
= current_cpu
;
486 system
->halt_status
.cpu_nr
= current_cpu
;
487 system
->halt_status
.reason
= reason
;
488 system
->halt_status
.signal
= signal
;
489 system
->halt_status
.program_counter
= cia
;
490 longjmp(*(jmp_buf*)(system
->path_to_halt
), current_cpu
+ 1);
493 INLINE_PSIM psim_status
494 psim_get_status(psim
*system
)
496 return system
->halt_status
;
501 psim_cpu(psim
*system
,
504 if (cpu_nr
< 0 || cpu_nr
>= system
->nr_cpus
)
507 return system
->processors
[cpu_nr
];
512 psim_device(psim
*system
,
515 return device_tree_find_device(system
->devices
, path
);
521 psim_init(psim
*system
)
525 /* scrub the monitor */
526 mon_init(system
->monitor
, system
->nr_cpus
);
528 /* scrub all the cpus */
529 for (cpu_nr
= 0; cpu_nr
< system
->nr_cpus
; cpu_nr
++)
530 cpu_init(system
->processors
[cpu_nr
]);
532 /* init all the devices */
533 device_tree_init(system
->devices
, system
);
535 /* force loop to restart */
536 system
->last_cpu
= system
->nr_cpus
- 1;
540 psim_stack(psim
*system
,
544 /* pass the stack device the argv/envp and let it work out what to
546 const device
*stack_device
= device_tree_find_device(system
->devices
,
548 unsigned_word stack_pointer
;
549 psim_read_register(system
, 0, &stack_pointer
, "sp", cooked_transfer
);
550 stack_device
->callback
->ioctl(stack_device
,
561 /* EXECUTE REAL CODE:
563 Unfortunatly, there are multiple cases to consider vis:
565 <icache> X <smp> X <events> X <keep-running-flag> X ...
567 Consequently this function is written in multiple different ways */
569 STATIC_INLINE_PSIM
void
570 run_until_stop(psim
*system
,
571 volatile int *keep_running
)
576 #if WITH_IDECODE_CACHE_SIZE
577 for (cpu_nr
= 0; cpu_nr
< system
->nr_cpus
; cpu_nr
++)
578 cpu_flush_icache(system
->processors
[cpu_nr
]);
580 psim_set_halt_and_restart(system
, &halt
, &restart
);
582 #if (!WITH_IDECODE_CACHE_SIZE && WITH_SMP == 0)
584 /* CASE 1: No instruction cache and no SMP.
586 In this case, we can take advantage of the fact that the current
587 instruction address does not need to be returned to the cpu
588 object after every execution of an instruction. Instead it only
589 needs to be saved when either A. the main loop exits or B. a
590 cpu-{halt,restart} call forces the loop to be re-entered. The
591 later functions always save the current cpu instruction
596 if (!setjmp(restart
)) {
597 cpu
*const processor
= system
->processors
[0];
598 unsigned_word cia
= cpu_get_program_counter(processor
);
601 if (event_queue_tick(system
->events
)) {
602 cpu_set_program_counter(processor
, cia
);
603 event_queue_process(system
->events
);
604 cia
= cpu_get_program_counter(processor
);
608 instruction_word
const instruction
609 = vm_instruction_map_read(cpu_instruction_map(processor
),
611 cia
= idecode_issue(processor
, instruction
, cia
);
613 } while (keep_running
== NULL
|| *keep_running
);
614 cpu_set_program_counter(processor
, cia
);
616 } while(keep_running
== NULL
|| *keep_running
);
621 #if (WITH_IDECODE_CACHE_SIZE && WITH_SMP == 0)
623 /* CASE 2: Instruction case but no SMP
625 Here, the additional complexity comes from there being two
626 different cache implementations. A simple function address cache
627 or a full cracked instruction cache */
631 if (!setjmp(restart
)) {
632 cpu
*const processor
= system
->processors
[0];
633 unsigned_word cia
= cpu_get_program_counter(processor
);
636 if (event_queue_tick(system
->events
)) {
637 cpu_set_program_counter(processor
, cia
);
638 event_queue_process(system
->events
);
639 cia
= cpu_get_program_counter(processor
);
642 idecode_cache
*const cache_entry
= cpu_icache_entry(processor
,
644 if (cache_entry
->address
== cia
) {
645 idecode_semantic
*const semantic
= cache_entry
->semantic
;
646 cia
= semantic(processor
, cache_entry
, cia
);
649 instruction_word
const instruction
650 = vm_instruction_map_read(cpu_instruction_map(processor
),
653 idecode_semantic
*const semantic
= idecode(processor
,
658 mon_event(mon_event_icache_miss
, processor
, cia
);
659 cache_entry
->address
= cia
;
660 cache_entry
->semantic
= semantic
;
661 cia
= semantic(processor
, cache_entry
, cia
);
664 } while (keep_running
== NULL
|| *keep_running
);
665 cpu_set_program_counter(processor
, cia
);
667 } while(keep_running
== NULL
|| *keep_running
);
672 #if (!WITH_IDECODE_CACHE_SIZE && WITH_SMP > 0)
674 /* CASE 3: No ICACHE but SMP
676 The complexity here comes from needing to correctly restart the
677 system when it is aborted. In particular if cpu0 requests a
678 restart, the next cpu is still cpu1. Cpu0 being restarted after
679 all the other CPU's and the event queue have been processed */
682 int first_cpu
= setjmp(restart
);
684 first_cpu
= system
->last_cpu
+ 1;
687 for (current_cpu
= first_cpu
, first_cpu
= 0;
688 current_cpu
< system
->nr_cpus
+ (WITH_EVENTS
? 1 : 0);
690 if (WITH_EVENTS
&& current_cpu
== system
->nr_cpus
) {
691 if (event_queue_tick(system
->events
))
692 event_queue_process(system
->events
);
695 cpu
*const processor
= system
->processors
[current_cpu
];
696 unsigned_word
const cia
= cpu_get_program_counter(processor
);
697 instruction_word instruction
=
698 vm_instruction_map_read(cpu_instruction_map(processor
),
701 cpu_set_program_counter(processor
,
702 idecode_issue(processor
, instruction
, cia
));
704 if (!(keep_running
== NULL
|| *keep_running
)) {
705 system
->last_cpu
= current_cpu
;
709 } while (keep_running
== NULL
|| *keep_running
);
713 #if (WITH_IDECODE_CACHE_SIZE && WITH_SMP > 0)
715 /* CASE 4: ICACHE and SMP ...
717 This time, everything goes wrong. Need to restart loops
718 correctly, need to save the program counter and finally need to
719 keep track of each processors current address! */
722 int first_cpu
= setjmp(restart
);
724 first_cpu
= system
->last_cpu
+ 1;
727 for (current_cpu
= first_cpu
, first_cpu
= 0;
728 current_cpu
< system
->nr_cpus
+ (WITH_EVENTS
? 1 : 0);
730 if (WITH_EVENTS
&& current_cpu
== system
->nr_cpus
) {
731 if (event_queue_tick(system
->events
))
732 event_queue_process(system
->events
);
735 cpu
*processor
= system
->processors
[current_cpu
];
736 unsigned_word
const cia
= cpu_get_program_counter(processor
);
737 idecode_cache
*cache_entry
= cpu_icache_entry(processor
, cia
);
738 if (cache_entry
->address
== cia
) {
739 idecode_semantic
*semantic
= cache_entry
->semantic
;
740 cpu_set_program_counter(processor
,
741 semantic(processor
, cache_entry
, cia
));
744 instruction_word instruction
=
745 vm_instruction_map_read(cpu_instruction_map(processor
),
748 idecode_semantic
*semantic
= idecode(processor
,
753 mon_event(mon_event_icache_miss
, system
->processors
[current_cpu
], cia
);
754 cache_entry
->address
= cia
;
755 cache_entry
->semantic
= semantic
;
756 cpu_set_program_counter(processor
,
757 semantic(processor
, cache_entry
, cia
));
760 if (!(keep_running
== NULL
|| *keep_running
))
763 } while (keep_running
== NULL
|| *keep_running
);
767 psim_clear_halt_and_restart(system
);
771 /* SIMULATE INSTRUCTIONS, various different ways of achieving the same
775 psim_step(psim
*system
)
777 volatile int keep_running
= 0;
778 run_until_stop(system
, &keep_running
);
782 psim_run(psim
*system
)
784 run_until_stop(system
, NULL
);
788 psim_run_until_stop(psim
*system
,
789 volatile int *keep_running
)
791 run_until_stop(system
, keep_running
);
796 /* storage manipulation functions */
799 psim_read_register(psim
*system
,
805 register_descriptions description
;
806 char cooked_buf
[sizeof(natural_word
)];
809 /* find our processor */
810 if (which_cpu
== MAX_NR_PROCESSORS
)
811 which_cpu
= system
->last_cpu
;
812 if (which_cpu
< 0 || which_cpu
>= system
->nr_cpus
)
813 error("psim_read_register() - invalid processor %d\n", which_cpu
);
814 processor
= system
->processors
[which_cpu
];
816 /* find the register description */
817 description
= register_description(reg
);
818 if (description
.type
== reg_invalid
)
819 error("psim_read_register() invalid register name `%s'\n", reg
);
821 /* get the cooked value */
822 switch (description
.type
) {
825 *(gpreg
*)cooked_buf
= cpu_registers(processor
)->gpr
[description
.index
];
829 *(spreg
*)cooked_buf
= cpu_registers(processor
)->spr
[description
.index
];
833 *(sreg
*)cooked_buf
= cpu_registers(processor
)->sr
[description
.index
];
837 *(fpreg
*)cooked_buf
= cpu_registers(processor
)->fpr
[description
.index
];
841 *(unsigned_word
*)cooked_buf
= cpu_get_program_counter(processor
);
845 *(creg
*)cooked_buf
= cpu_registers(processor
)->cr
;
849 *(msreg
*)cooked_buf
= cpu_registers(processor
)->msr
;
853 printf_filtered("psim_read_register(processor=0x%x,buf=0x%x,reg=%s) %s\n",
855 "read of this register unimplemented");
860 /* the PSIM internal values are in host order. To fetch raw data,
861 they need to be converted into target order and then returned */
862 if (mode
== raw_transfer
) {
863 /* FIXME - assumes that all registers are simple integers */
864 switch (description
.size
) {
866 *(unsigned_1
*)buf
= H2T_1(*(unsigned_1
*)cooked_buf
);
869 *(unsigned_2
*)buf
= H2T_2(*(unsigned_2
*)cooked_buf
);
872 *(unsigned_4
*)buf
= H2T_4(*(unsigned_4
*)cooked_buf
);
875 *(unsigned_8
*)buf
= H2T_8(*(unsigned_8
*)cooked_buf
);
880 bcopy(cooked_buf
, buf
, description
.size
);
888 psim_write_register(psim
*system
,
895 register_descriptions description
;
896 char cooked_buf
[sizeof(natural_word
)];
898 /* find our processor */
899 if (which_cpu
== MAX_NR_PROCESSORS
)
900 which_cpu
= system
->last_cpu
;
901 if (which_cpu
== -1) {
903 for (i
= 0; i
< system
->nr_cpus
; i
++)
904 psim_write_register(system
, i
, buf
, reg
, mode
);
907 else if (which_cpu
< 0 || which_cpu
>= system
->nr_cpus
) {
908 error("psim_read_register() - invalid processor %d\n", which_cpu
);
911 processor
= system
->processors
[which_cpu
];
913 /* find the description of the register */
914 description
= register_description(reg
);
915 if (description
.type
== reg_invalid
)
916 error("psim_write_register() invalid register name %s\n", reg
);
918 /* If the data is comming in raw (target order), need to cook it
919 into host order before putting it into PSIM's internal structures */
920 if (mode
== raw_transfer
) {
921 switch (description
.size
) {
923 *(unsigned_1
*)cooked_buf
= T2H_1(*(unsigned_1
*)buf
);
926 *(unsigned_2
*)cooked_buf
= T2H_2(*(unsigned_2
*)buf
);
929 *(unsigned_4
*)cooked_buf
= T2H_4(*(unsigned_4
*)buf
);
932 *(unsigned_8
*)cooked_buf
= T2H_8(*(unsigned_8
*)buf
);
937 bcopy(buf
, cooked_buf
, description
.size
);
940 /* put the cooked value into the register */
941 switch (description
.type
) {
944 cpu_registers(processor
)->gpr
[description
.index
] = *(gpreg
*)cooked_buf
;
948 cpu_registers(processor
)->fpr
[description
.index
] = *(fpreg
*)cooked_buf
;
952 cpu_set_program_counter(processor
, *(unsigned_word
*)cooked_buf
);
956 cpu_registers(processor
)->spr
[description
.index
] = *(spreg
*)cooked_buf
;
960 cpu_registers(processor
)->sr
[description
.index
] = *(sreg
*)cooked_buf
;
964 cpu_registers(processor
)->cr
= *(creg
*)cooked_buf
;
968 cpu_registers(processor
)->msr
= *(msreg
*)cooked_buf
;
972 printf_filtered("psim_write_register(processor=0x%x,cooked_buf=0x%x,reg=%s) %s\n",
973 processor
, cooked_buf
, reg
,
974 "read of this register unimplemented");
984 psim_read_memory(psim
*system
,
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_read_buffer(cpu_data_map(processor
),
997 buffer
, vaddr
, nr_bytes
);
1001 INLINE_PSIM
unsigned
1002 psim_write_memory(psim
*system
,
1005 unsigned_word vaddr
,
1007 int violate_read_only_section
)
1010 if (which_cpu
== MAX_NR_PROCESSORS
)
1011 which_cpu
= system
->last_cpu
;
1012 if (which_cpu
< 0 || which_cpu
>= system
->nr_cpus
)
1013 error("psim_read_memory() invalid cpu\n");
1014 processor
= system
->processors
[which_cpu
];
1015 return vm_data_map_write_buffer(cpu_data_map(processor
),
1016 buffer
, vaddr
, nr_bytes
, 1);
1021 psim_print_info(psim
*system
,
1024 mon_print_info(system
, system
->monitor
, verbose
);
1028 #endif /* _PSIM_C_ */