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;
102 /* create a device tree from the image */
106 /* Raw hardware tree:
108 A small default set of devices are configured. Each section of the
109 image is loaded directly into physical memory. */
111 STATIC_INLINE_PSIM void
112 create_hardware_device_tree(bfd *image,
116 const memory_size = OEA_MEMORY_SIZE;
119 device_tree_add_passthrough(root, "/options");
120 device_tree_add_integer(root, "/options/smp",
122 device_tree_add_boolean(root, "/options/little-endian?",
123 !image->xvec->byteorder_big_p);
124 device_tree_add_string(root, "/options/environment-architecture",
126 device_tree_add_boolean(root, "/options/strict-alignment?",
127 (WITH_ALIGNMENT == STRICT_ALIGNMENT
128 || !image->xvec->byteorder_big_p));
129 device_tree_add_boolean(root, "/options/floating-point?",
130 WITH_FLOATING_POINT);
133 name = printd_uw_u_u("/memory", 0, memory_size, access_read_write_exec);
134 device_tree_add_found_device(root, name);
136 device_tree_add_found_device(root, "/iobus@0x400000");
137 device_tree_add_found_device(root, "/iobus/console@0x000000,16");
138 device_tree_add_found_device(root, "/iobus/halt@0x100000,4");
139 device_tree_add_found_device(root, "/iobus/icu@0x200000,4");
142 device_tree_add_passthrough(root, "/init");
143 device_tree_add_found_device(root, "/init/register@pc,0x0");
144 name = printd_c_uw("/init/register", "sp", memory_size);
145 device_tree_add_found_device(root, name);
147 name = printd_c_uw("/init/register", "msr",
148 (image->xvec->byteorder_big_p
150 : msr_little_endian_mode));
151 device_tree_add_found_device(root, name);
153 /* AJC puts the PC at zero and wants a stack while MM puts it above
154 zero and doesn't. Really there should be no stack *but* this
155 makes testing easier */
156 device_tree_add_found_device(root,
157 (bfd_get_start_address(image) == 0
159 : "/init/stack@none"));
160 name = printd_c("/init/load-binary", bfd_get_filename(image));
161 device_tree_add_found_device(root, name);
166 /* Openboot model (under development):
168 An extension of the hardware model. The image is read into memory
169 as a single block. Sections of the image are then mapped as
170 required using a HTAB. */
172 STATIC_INLINE_PSIM void
173 create_openboot_device_tree(bfd *image,
176 create_hardware_device_tree(image, root);
182 Image sections loaded into virtual addresses as specified. A
183 (large) stack is reserved (but only allocated as needed). System
184 calls that include suport for heap growth are attached. */
186 STATIC_INLINE_PSIM void
187 create_vea_device_tree(bfd *image,
190 unsigned_word top_of_stack;
195 /* establish a few defaults */
196 if (image->xvec->flavour == bfd_target_elf_flavour) {
198 top_of_stack = 0xe0000000;
199 stack_size = 0x00100000;
203 top_of_stack = 0x20000000;
204 stack_size = 0x00100000;
208 device_tree_add_passthrough(root, "/options");
209 device_tree_add_integer(root, "/options/smp", 1); /* always */
210 device_tree_add_boolean(root, "/options/little-endian?",
211 !image->xvec->byteorder_big_p);
212 device_tree_add_string(root, "/options/environment-architecture",
213 (WITH_ENVIRONMENT == USER_ENVIRONMENT
214 ? "user" : "virtual"));
215 device_tree_add_boolean(root, "/options/strict-alignment?",
216 (WITH_ALIGNMENT == STRICT_ALIGNMENT
217 || !image->xvec->byteorder_big_p));
218 device_tree_add_boolean(root, "/options/floating-point?",
219 WITH_FLOATING_POINT);
221 /* virtual memory - handles growth of stack/heap */
222 name = printd_uw_u("/vm", top_of_stack - stack_size, stack_size);
223 device_tree_add_found_device(root, name);
225 name = printd_c("/vm/map-binary", bfd_get_filename(image));
226 device_tree_add_found_device(root, name);
229 /* finish the init */
230 device_tree_add_passthrough(root, "/init");
231 name = printd_c_uw("/init/register", "pc", bfd_get_start_address(image));
232 device_tree_add_found_device(root, name); /*pc*/
234 name = printd_c_uw("/init/register", "sp", top_of_stack);
235 device_tree_add_found_device(root, name);
237 name = printd_c_uw("/init/register", "msr",
238 (image->xvec->byteorder_big_p
240 : msr_little_endian_mode));
241 device_tree_add_found_device(root, name);
243 device_tree_add_found_device(root, (elf_binary
245 : "/init/stack@xcoff"));
251 The file contains lines that specify the describe the device tree
252 to be created, read them in and load them into the tree */
254 STATIC_INLINE_PSIM void
255 create_filed_device_tree(const char *file_name,
258 FILE *description = fopen(file_name, "r");
260 char device_path[1000];
261 while (fgets(device_path, sizeof(device_path), description)) {
262 /* check all of line was read */
264 char *end = strchr(device_path, '\n');
267 error("create_filed_device_tree() line %d to long: %s\n",
268 line_nr, device_path);
273 /* check for leading comment */
274 if (device_path[0] != '/')
276 /* enter it in varying ways */
277 if (strchr(device_path, '@') != NULL) {
278 device_tree_add_found_device(root, device_path);
281 char *space = strchr(device_path, ' ');
283 /* intermediate node */
284 device_tree_add_passthrough(root, device_path);
286 else if (space[-1] == '?') {
289 device_tree_add_boolean(root, device_path, space[1] != '0');
291 else if (isdigit(space[1])) {
294 device_tree_add_integer(root, device_path, strtoul(space+1, 0, 0));
296 else if (space[1] == '"') {
298 char *end = strchr(space+2, '\0');
302 device_tree_add_string(root, device_path, space + 2);
307 device_tree_add_string(root, device_path, space + 1);
315 /* Given the file containing the `image', create a device tree that
316 defines the machine to be modeled */
318 STATIC_INLINE_PSIM device_tree *
319 create_device_tree(const char *file_name,
323 const device *core_device = core_device_create(memory);
324 device_tree *root = device_tree_add_device(NULL, "/", core_device);
326 bfd_init(); /* could be redundant but ... */
329 image = bfd_openr(file_name, NULL);
331 bfd_perror("open failed:");
332 error("nothing loaded\n");
335 /* check it is valid */
336 if (!bfd_check_format(image, bfd_object)) {
337 printf_filtered("create_device_tree() - FIXME - should check more bfd bits\n");
338 printf_filtered("create_device_tree() - %s not an executable, assume device file\n", file_name);
343 /* depending on what was found about the file, load it */
345 if (bfd_get_start_address(image) < OEA_START_ADDRESS) {
346 TRACE(trace_device_tree, ("create_device_tree() - hardware image\n"));
347 create_hardware_device_tree(image, root);
349 else if (bfd_get_start_address(image) < OPENBOOT_START_ADDRESS) {
350 TRACE(trace_device_tree, ("create_device_tree() - vea image\n"));
351 create_vea_device_tree(image, root);
354 TRACE(trace_device_tree, ("create_device_tree() - openboot? image\n"));
355 create_openboot_device_tree(image, root);
360 TRACE(trace_device_tree, ("create_device_tree() - text image\n"));
361 create_filed_device_tree(file_name, root);
370 psim_create(const char *file_name)
377 system = ZALLOC(psim);
378 system->events = event_queue_create();
379 system->memory = core_create();
380 system->monitor = mon_create();
381 system->devices = create_device_tree(file_name, system->memory);
382 for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; cpu_nr++) {
383 system->processors[cpu_nr] = cpu_create(system,
386 mon_cpu(system->monitor,
391 /* fill in the missing real number of CPU's */
392 system->nr_cpus = device_tree_find_integer(system->devices,
395 /* fill in the missing TARGET BYTE ORDER information */
396 current_target_byte_order = (device_tree_find_boolean(system->devices,
397 "/options/little-endian?")
400 if (CURRENT_TARGET_BYTE_ORDER != current_target_byte_order)
401 error("target byte order conflict\n");
403 /* fill in the missing HOST BYTE ORDER information */
404 current_host_byte_order = (current_host_byte_order = 1,
405 (*(char*)(¤t_host_byte_order)
408 if (CURRENT_HOST_BYTE_ORDER != current_host_byte_order)
409 error("host byte order conflict\n");
411 /* fill in the missing OEA/VEA information */
412 env = device_tree_find_string(system->devices,
413 "/options/environment-architecture");
414 current_environment = (strcmp(env, "user") == 0
416 : strcmp(env, "virtual") == 0
417 ? VIRTUAL_ENVIRONMENT
418 : strcmp(env, "operating") == 0
419 ? OPERATING_ENVIRONMENT
421 if (current_environment == 0)
422 error("unreconized /options/environment-architecture\n");
423 if (CURRENT_ENVIRONMENT != current_environment)
424 error("target environment conflict\n");
426 /* fill in the missing ALLIGNMENT information */
427 current_alignment = (device_tree_find_boolean(system->devices,
428 "/options/strict-alignment?")
430 : NONSTRICT_ALIGNMENT);
431 if (CURRENT_ALIGNMENT != current_alignment)
432 error("target alignment conflict\n");
434 /* fill in the missing FLOATING POINT information */
435 current_floating_point = (device_tree_find_boolean(system->devices,
436 "/options/floating-point?")
437 ? HARD_FLOATING_POINT
438 : SOFT_FLOATING_POINT);
439 if (CURRENT_FLOATING_POINT != current_floating_point)
440 error("target floating-point conflict\n");
446 /* allow the simulation to stop/restart abnormaly */
448 STATIC_INLINE_PSIM void
449 psim_set_halt_and_restart(psim *system,
451 void *restart_jmp_buf)
453 system->path_to_halt = halt_jmp_buf;
454 system->path_to_restart = restart_jmp_buf;
457 STATIC_INLINE_PSIM void
458 psim_clear_halt_and_restart(psim *system)
460 system->path_to_halt = NULL;
461 system->path_to_restart = NULL;
465 psim_restart(psim *system,
468 system->last_cpu = current_cpu;
469 longjmp(*(jmp_buf*)(system->path_to_restart), current_cpu + 1);
474 psim_halt(psim *system,
480 system->last_cpu = current_cpu;
481 system->halt_status.cpu_nr = current_cpu;
482 system->halt_status.reason = reason;
483 system->halt_status.signal = signal;
484 system->halt_status.program_counter = cia;
485 longjmp(*(jmp_buf*)(system->path_to_halt), current_cpu + 1);
488 INLINE_PSIM psim_status
489 psim_get_status(psim *system)
491 return system->halt_status;
496 psim_cpu(psim *system,
499 if (cpu_nr < 0 || cpu_nr >= system->nr_cpus)
502 return system->processors[cpu_nr];
507 psim_device(psim *system,
510 return device_tree_find_device(system->devices, path);
516 psim_init(psim *system)
520 /* scrub the monitor */
521 mon_init(system->monitor, system->nr_cpus);
523 /* scrub all the cpus */
524 for (cpu_nr = 0; cpu_nr < system->nr_cpus; cpu_nr++)
525 cpu_init(system->processors[cpu_nr]);
527 /* init all the devices */
528 device_tree_init(system->devices, system);
530 /* force loop to restart */
531 system->last_cpu = system->nr_cpus - 1;
535 psim_stack(psim *system,
539 /* pass the stack device the argv/envp and let it work out what to
541 const device *stack_device = device_tree_find_device(system->devices,
543 unsigned_word stack_pointer;
544 psim_read_register(system, 0, &stack_pointer, "sp", cooked_transfer);
545 stack_device->callback->ioctl(stack_device,
556 /* EXECUTE REAL CODE:
558 Unfortunatly, there are multiple cases to consider vis:
560 <icache> X <smp> X <events> X <keep-running-flag> X ...
562 Consequently this function is written in multiple different ways */
564 STATIC_INLINE_PSIM void
565 run_until_stop(psim *system,
566 volatile int *keep_running)
571 #if WITH_IDECODE_CACHE_SIZE
572 for (cpu_nr = 0; cpu_nr < system->nr_cpus; cpu_nr++)
573 cpu_flush_icache(system->processors[cpu_nr]);
575 psim_set_halt_and_restart(system, &halt, &restart);
577 #if (!WITH_IDECODE_CACHE_SIZE && WITH_SMP == 0)
579 /* CASE 1: No instruction cache and no SMP.
581 In this case, we can take advantage of the fact that the current
582 instruction address does not need to be returned to the cpu
583 object after every execution of an instruction. Instead it only
584 needs to be saved when either A. the main loop exits or B. a
585 cpu-{halt,restart} call forces the loop to be re-entered. The
586 later functions always save the current cpu instruction
591 if (!setjmp(restart)) {
592 cpu *const processor = system->processors[0];
593 unsigned_word cia = cpu_get_program_counter(processor);
596 if (event_queue_tick(system->events)) {
597 cpu_set_program_counter(processor, cia);
598 event_queue_process(system->events);
599 cia = cpu_get_program_counter(processor);
603 instruction_word const instruction
604 = vm_instruction_map_read(cpu_instruction_map(processor),
606 cia = idecode_issue(processor, instruction, cia);
608 } while (keep_running == NULL || *keep_running);
609 cpu_set_program_counter(processor, cia);
611 } while(keep_running == NULL || *keep_running);
616 #if (WITH_IDECODE_CACHE_SIZE && WITH_SMP == 0)
618 /* CASE 2: Instruction case but no SMP
620 Here, the additional complexity comes from there being two
621 different cache implementations. A simple function address cache
622 or a full cracked instruction cache */
626 if (!setjmp(restart)) {
627 cpu *const processor = system->processors[0];
628 unsigned_word cia = cpu_get_program_counter(processor);
631 if (event_queue_tick(system->events)) {
632 cpu_set_program_counter(processor, cia);
633 event_queue_process(system->events);
634 cia = cpu_get_program_counter(processor);
637 idecode_cache *const cache_entry = cpu_icache_entry(processor,
639 if (cache_entry->address == cia) {
640 idecode_semantic *const semantic = cache_entry->semantic;
641 cia = semantic(processor, cache_entry, cia);
644 instruction_word const instruction
645 = vm_instruction_map_read(cpu_instruction_map(processor),
648 idecode_semantic *const semantic = idecode(processor,
652 cache_entry->address = cia;
653 cache_entry->semantic = semantic;
654 cia = semantic(processor, cache_entry, cia);
657 } while (keep_running == NULL || *keep_running);
658 cpu_set_program_counter(processor, cia);
660 } while(keep_running == NULL || *keep_running);
665 #if (!WITH_IDECODE_CACHE_SIZE && WITH_SMP > 0)
667 /* CASE 3: No ICACHE but SMP
669 The complexity here comes from needing to correctly restart the
670 system when it is aborted. In particular if cpu0 requests a
671 restart, the next cpu is still cpu1. Cpu0 being restarted after
672 all the other CPU's and the event queue have been processed */
675 int first_cpu = setjmp(restart);
677 first_cpu = system->last_cpu + 1;
680 for (current_cpu = first_cpu, first_cpu = 0;
681 current_cpu < system->nr_cpus + (WITH_EVENTS ? 1 : 0);
683 if (WITH_EVENTS && current_cpu == system->nr_cpus) {
684 if (event_queue_tick(system->events))
685 event_queue_process(system->events);
688 cpu *const processor = system->processors[current_cpu];
689 unsigned_word const cia = cpu_get_program_counter(processor);
690 instruction_word instruction =
691 vm_instruction_map_read(cpu_instruction_map(processor),
694 cpu_set_program_counter(processor,
695 idecode_issue(processor, instruction, cia));
697 if (!(keep_running == NULL || *keep_running)) {
698 system->last_cpu = current_cpu;
702 } while (keep_running == NULL || *keep_running);
706 #if (WITH_IDECODE_CACHE_SIZE && WITH_SMP > 0)
708 /* CASE 4: ICACHE and SMP ...
710 This time, everything goes wrong. Need to restart loops
711 correctly, need to save the program counter and finally need to
712 keep track of each processors current address! */
715 int first_cpu = setjmp(restart);
717 first_cpu = system->last_cpu + 1;
720 for (current_cpu = first_cpu, first_cpu = 0;
721 current_cpu < system->nr_cpus + (WITH_EVENTS ? 1 : 0);
723 if (WITH_EVENTS && current_cpu == system->nr_cpus) {
724 if (event_queue_tick(system->events))
725 event_queue_process(system->events);
728 cpu *processor = system->processors[current_cpu];
729 unsigned_word const cia = cpu_get_program_counter(processor);
730 idecode_cache *cache_entry = cpu_icache_entry(processor, cia);
731 if (cache_entry->address == cia) {
732 idecode_semantic *semantic = cache_entry->semantic;
733 cpu_set_program_counter(processor,
734 semantic(processor, cache_entry, cia));
737 instruction_word instruction =
738 vm_instruction_map_read(cpu_instruction_map(processor),
741 idecode_semantic *semantic = idecode(processor,
745 cache_entry->address = cia;
746 cache_entry->semantic = semantic;
747 cpu_set_program_counter(processor,
748 semantic(processor, cache_entry, cia));
751 if (!(keep_running == NULL || *keep_running))
754 } while (keep_running == NULL || *keep_running);
758 psim_clear_halt_and_restart(system);
762 /* SIMULATE INSTRUCTIONS, various different ways of achieving the same
766 psim_step(psim *system)
768 volatile int keep_running = 0;
769 run_until_stop(system, &keep_running);
773 psim_run(psim *system)
775 run_until_stop(system, NULL);
779 psim_run_until_stop(psim *system,
780 volatile int *keep_running)
782 run_until_stop(system, keep_running);
787 /* storage manipulation functions */
790 psim_read_register(psim *system,
796 register_descriptions description;
797 char cooked_buf[sizeof(natural_word)];
800 /* find our processor */
801 if (which_cpu == MAX_NR_PROCESSORS)
802 which_cpu = system->last_cpu;
803 if (which_cpu < 0 || which_cpu >= system->nr_cpus)
804 error("psim_read_register() - invalid processor %d\n", which_cpu);
805 processor = system->processors[which_cpu];
807 /* find the register description */
808 description = register_description(reg);
809 if (description.type == reg_invalid)
810 error("psim_read_register() invalid register name `%s'\n", reg);
812 /* get the cooked value */
813 switch (description.type) {
816 *(gpreg*)cooked_buf = cpu_registers(processor)->gpr[description.index];
820 *(spreg*)cooked_buf = cpu_registers(processor)->spr[description.index];
824 *(sreg*)cooked_buf = cpu_registers(processor)->sr[description.index];
828 *(fpreg*)cooked_buf = cpu_registers(processor)->fpr[description.index];
832 *(unsigned_word*)cooked_buf = cpu_get_program_counter(processor);
836 *(creg*)cooked_buf = cpu_registers(processor)->cr;
840 *(msreg*)cooked_buf = cpu_registers(processor)->msr;
844 printf_filtered("psim_read_register(processor=0x%x,buf=0x%x,reg=%s) %s\n",
846 "read of this register unimplemented");
851 /* the PSIM internal values are in host order. To fetch raw data,
852 they need to be converted into target order and then returned */
853 if (mode == raw_transfer) {
854 /* FIXME - assumes that all registers are simple integers */
855 switch (description.size) {
857 *(unsigned_1*)buf = H2T_1(*(unsigned_1*)cooked_buf);
860 *(unsigned_2*)buf = H2T_2(*(unsigned_2*)cooked_buf);
863 *(unsigned_4*)buf = H2T_4(*(unsigned_4*)cooked_buf);
866 *(unsigned_8*)buf = H2T_8(*(unsigned_8*)cooked_buf);
871 bcopy(cooked_buf, buf, description.size);
879 psim_write_register(psim *system,
886 register_descriptions description;
887 char cooked_buf[sizeof(natural_word)];
889 /* find our processor */
890 if (which_cpu == MAX_NR_PROCESSORS)
891 which_cpu = system->last_cpu;
892 if (which_cpu == -1) {
894 for (i = 0; i < system->nr_cpus; i++)
895 psim_write_register(system, i, buf, reg, mode);
898 else if (which_cpu < 0 || which_cpu >= system->nr_cpus) {
899 error("psim_read_register() - invalid processor %d\n", which_cpu);
902 processor = system->processors[which_cpu];
904 /* find the description of the register */
905 description = register_description(reg);
906 if (description.type == reg_invalid)
907 error("psim_write_register() invalid register name %s\n", reg);
909 /* If the data is comming in raw (target order), need to cook it
910 into host order before putting it into PSIM's internal structures */
911 if (mode == raw_transfer) {
912 switch (description.size) {
914 *(unsigned_1*)cooked_buf = T2H_1(*(unsigned_1*)buf);
917 *(unsigned_2*)cooked_buf = T2H_2(*(unsigned_2*)buf);
920 *(unsigned_4*)cooked_buf = T2H_4(*(unsigned_4*)buf);
923 *(unsigned_8*)cooked_buf = T2H_8(*(unsigned_8*)buf);
928 bcopy(buf, cooked_buf, description.size);
931 /* put the cooked value into the register */
932 switch (description.type) {
935 cpu_registers(processor)->gpr[description.index] = *(gpreg*)cooked_buf;
939 cpu_registers(processor)->fpr[description.index] = *(fpreg*)cooked_buf;
943 cpu_set_program_counter(processor, *(unsigned_word*)cooked_buf);
947 cpu_registers(processor)->spr[description.index] = *(spreg*)cooked_buf;
951 cpu_registers(processor)->sr[description.index] = *(sreg*)cooked_buf;
955 cpu_registers(processor)->cr = *(creg*)cooked_buf;
959 cpu_registers(processor)->msr = *(msreg*)cooked_buf;
963 printf_filtered("psim_write_register(processor=0x%x,cooked_buf=0x%x,reg=%s) %s\n",
964 processor, cooked_buf, reg,
965 "read of this register unimplemented");
975 psim_read_memory(psim *system,
982 if (which_cpu == MAX_NR_PROCESSORS)
983 which_cpu = system->last_cpu;
984 if (which_cpu < 0 || which_cpu >= system->nr_cpus)
985 error("psim_read_memory() invalid cpu\n");
986 processor = system->processors[which_cpu];
987 return vm_data_map_read_buffer(cpu_data_map(processor),
988 buffer, vaddr, nr_bytes);
993 psim_write_memory(psim *system,
998 int violate_read_only_section)
1001 if (which_cpu == MAX_NR_PROCESSORS)
1002 which_cpu = system->last_cpu;
1003 if (which_cpu < 0 || which_cpu >= system->nr_cpus)
1004 error("psim_read_memory() invalid cpu\n");
1005 processor = system->processors[which_cpu];
1006 return vm_data_map_write_buffer(cpu_data_map(processor),
1007 buffer, vaddr, nr_bytes, 1);
1012 psim_print_info(psim *system,
1015 mon_print_info(system->monitor, verbose);
1019 #endif /* _PSIM_C_ */