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.
30 #include "ppc-config.h"
33 #ifndef STATIC_INLINE_PSIM
34 #define STATIC_INLINE_PSIM STATIC_INLINE
40 #include "cpu.h" /* includes psim.h */
48 /* Any starting address less than this is assumed to be an OEA program
50 #ifndef OEA_START_ADDRESS
51 #define OEA_START_ADDRESS 4096
54 /* Any starting address greater than this is assumed to be an OpenBoot
56 #ifndef OPENBOOT_START_ADDRESS
57 #define OPENBOOT_START_ADDRESS 0x80000000
60 #ifndef OEA_MEMORY_SIZE
61 #define OEA_MEMORY_SIZE 0x100000
65 /* system structure, actual size of processor array determined at
73 /* escape routine for inner functions */
75 void *path_to_restart;
76 /* status from last halt */
77 psim_status halt_status;
78 /* the processes proper */
80 int last_cpu; /* CPU that last (tried to) execute an instruction */
81 cpu *processors[MAX_NR_PROCESSORS];
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;
92 /* create a device tree from the image */
98 A small default set of devices are configured. Each section of the
99 image is loaded directly into physical memory. */
101 STATIC_INLINE_PSIM void
102 create_hardware_device_tree(bfd *image,
106 const memory_size = OEA_MEMORY_SIZE;
109 device_tree_add_passthrough(root, "/options");
110 device_tree_add_integer(root, "/options/smp",
112 device_tree_add_boolean(root, "/options/little-endian?",
113 !image->xvec->byteorder_big_p);
114 device_tree_add_string(root, "/options/environment-architecture",
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);
123 name = printd_uw_u_u("/memory", 0, memory_size, access_read_write_exec);
124 device_tree_add_found_device(root, 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");
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);
137 name = printd_c_uw("/init/register", "msr",
138 (image->xvec->byteorder_big_p
140 : msr_little_endian_mode));
141 device_tree_add_found_device(root, 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
149 : "/init/stack@none"));
150 name = printd_c("/init/load-binary", bfd_get_filename(image));
151 device_tree_add_found_device(root, name);
156 /* Openboot model (under development):
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. */
162 STATIC_INLINE_PSIM void
163 create_openboot_device_tree(bfd *image,
166 create_hardware_device_tree(image, root);
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. */
176 STATIC_INLINE_PSIM void
177 create_vea_device_tree(bfd *image,
180 unsigned_word top_of_stack;
185 /* establish a few defaults */
186 if (image->xvec->flavour == bfd_target_elf_flavour) {
188 top_of_stack = 0xe0000000;
189 stack_size = 0x00100000;
193 top_of_stack = 0x20000000;
194 stack_size = 0x00100000;
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);
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);
215 name = printd_c("/vm/map-binary", bfd_get_filename(image));
216 device_tree_add_found_device(root, name);
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*/
224 name = printd_c_uw("/init/register", "sp", top_of_stack);
225 device_tree_add_found_device(root, name);
227 name = printd_c_uw("/init/register", "msr",
228 (image->xvec->byteorder_big_p
230 : msr_little_endian_mode));
231 device_tree_add_found_device(root, name);
233 device_tree_add_found_device(root, (elf_binary
235 : "/init/stack@xcoff"));
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 */
244 STATIC_INLINE_PSIM void
245 create_filed_device_tree(const char *file_name,
248 FILE *description = fopen(file_name, "r");
250 char device_path[1000];
251 while (fgets(device_path, sizeof(device_path), description)) {
252 /* check all of line was read */
254 char *end = strchr(device_path, '\n');
257 error("create_filed_device_tree() line %d to long: %s\n",
258 line_nr, device_path);
263 /* check for leading comment */
264 if (device_path[0] != '/')
266 /* enter it in varying ways */
267 if (strchr(device_path, '@') != NULL) {
268 device_tree_add_found_device(root, device_path);
271 char *space = strchr(device_path, ' ');
273 /* intermediate node */
274 device_tree_add_passthrough(root, device_path);
276 else if (space[-1] == '?') {
279 device_tree_add_boolean(root, device_path, space[1] != '0');
281 else if (isdigit(space[1])) {
284 device_tree_add_integer(root, device_path, strtoul(space+1, 0, 0));
286 else if (space[1] == '"') {
288 char *end = strchr(space+2, '\0');
292 device_tree_add_string(root, device_path, space + 2);
297 device_tree_add_string(root, device_path, space + 1);
305 /* Given the file containing the `image', create a device tree that
306 defines the machine to be modeled */
308 STATIC_INLINE_PSIM device_tree *
309 create_device_tree(const char *file_name,
313 const device *core_device = core_device_create(memory);
314 device_tree *root = device_tree_add_device(NULL, "/", core_device);
316 bfd_init(); /* could be redundant but ... */
319 image = bfd_openr(file_name, NULL);
321 bfd_perror("open failed:");
322 error("nothing loaded\n");
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);
333 /* depending on what was found about the file, load it */
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);
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);
344 TRACE(trace_device_tree, ("create_device_tree() - openboot? image\n"));
345 create_openboot_device_tree(image, root);
350 TRACE(trace_device_tree, ("create_device_tree() - text image\n"));
351 create_filed_device_tree(file_name, root);
360 psim_create(const char *file_name)
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,
376 mon_cpu(system->monitor,
381 /* fill in the missing real number of CPU's */
382 system->nr_cpus = device_tree_find_integer(system->devices,
385 /* fill in the missing TARGET BYTE ORDER information */
386 current_target_byte_order = (device_tree_find_boolean(system->devices,
387 "/options/little-endian?")
390 if (CURRENT_TARGET_BYTE_ORDER != current_target_byte_order)
391 error("target byte order conflict\n");
393 /* fill in the missing HOST BYTE ORDER information */
394 current_host_byte_order = (current_host_byte_order = 1,
395 (*(char*)(¤t_host_byte_order)
398 if (CURRENT_HOST_BYTE_ORDER != current_host_byte_order)
399 error("host byte order conflict\n");
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
406 : strcmp(env, "virtual") == 0
407 ? VIRTUAL_ENVIRONMENT
408 : strcmp(env, "operating") == 0
409 ? OPERATING_ENVIRONMENT
411 if (current_environment == 0)
412 error("unreconized /options/environment-architecture\n");
413 if (CURRENT_ENVIRONMENT != current_environment)
414 error("target environment conflict\n");
416 /* fill in the missing ALLIGNMENT information */
417 current_alignment = (device_tree_find_boolean(system->devices,
418 "/options/strict-alignment?")
420 : NONSTRICT_ALIGNMENT);
421 if (CURRENT_ALIGNMENT != current_alignment)
422 error("target alignment conflict\n");
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");
436 /* allow the simulation to stop/restart abnormaly */
438 STATIC_INLINE_PSIM void
439 psim_set_halt_and_restart(psim *system,
441 void *restart_jmp_buf)
443 system->path_to_halt = halt_jmp_buf;
444 system->path_to_restart = restart_jmp_buf;
447 STATIC_INLINE_PSIM void
448 psim_clear_halt_and_restart(psim *system)
450 system->path_to_halt = NULL;
451 system->path_to_restart = NULL;
455 psim_restart(psim *system,
458 system->last_cpu = current_cpu;
459 longjmp(*(jmp_buf*)(system->path_to_restart), current_cpu + 1);
464 psim_halt(psim *system,
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);
478 INLINE_PSIM psim_status
479 psim_get_status(psim *system)
481 return system->halt_status;
486 psim_cpu(psim *system,
489 if (cpu_nr < 0 || cpu_nr >= system->nr_cpus)
492 return system->processors[cpu_nr];
497 psim_device(psim *system,
500 return device_tree_find_device(system->devices, path);
506 psim_init(psim *system)
510 /* scrub the monitor */
511 mon_init(system->monitor, system->nr_cpus);
513 /* scrub all the cpus */
514 for (cpu_nr = 0; cpu_nr < system->nr_cpus; cpu_nr++)
515 cpu_init(system->processors[cpu_nr]);
517 /* init all the devices */
518 device_tree_init(system->devices, system);
520 /* force loop to restart */
521 system->last_cpu = system->nr_cpus - 1;
525 psim_stack(psim *system,
529 /* pass the stack device the argv/envp and let it work out what to
531 const device *stack_device = device_tree_find_device(system->devices,
533 unsigned_word stack_pointer;
534 psim_read_register(system, 0, &stack_pointer, "sp", cooked_transfer);
535 stack_device->callback->ioctl(stack_device,
546 /* EXECUTE REAL CODE:
548 Unfortunatly, there are multiple cases to consider vis:
550 <icache> X <smp> X <events> X <keep-running-flag> X ...
552 Consequently this function is written in multiple different ways */
554 STATIC_INLINE_PSIM void
555 run_until_stop(psim *system,
556 volatile int *keep_running)
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]);
565 psim_set_halt_and_restart(system, &halt, &restart);
567 #if (!WITH_IDECODE_CACHE_SIZE && WITH_SMP == 0)
569 /* CASE 1: No instruction cache and no SMP.
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
581 if (!setjmp(restart)) {
582 cpu *const processor = system->processors[0];
583 unsigned_word cia = cpu_get_program_counter(processor);
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);
593 instruction_word const instruction
594 = vm_instruction_map_read(cpu_instruction_map(processor),
596 cia = idecode_issue(processor, instruction, cia);
598 } while (keep_running == NULL || *keep_running);
599 cpu_set_program_counter(processor, cia);
601 } while(keep_running == NULL || *keep_running);
606 #if (WITH_IDECODE_CACHE_SIZE && WITH_SMP == 0)
608 /* CASE 2: Instruction case but no SMP
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 */
616 if (!setjmp(restart)) {
617 cpu *const processor = system->processors[0];
618 unsigned_word cia = cpu_get_program_counter(processor);
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);
627 idecode_cache *const cache_entry = cpu_icache_entry(processor,
629 if (cache_entry->address == cia) {
630 idecode_semantic *const semantic = cache_entry->semantic;
631 cia = semantic(processor, cache_entry, cia);
634 instruction_word const instruction
635 = vm_instruction_map_read(cpu_instruction_map(processor),
638 idecode_semantic *const semantic = idecode(processor,
642 cache_entry->address = cia;
643 cache_entry->semantic = semantic;
644 cia = semantic(processor, cache_entry, cia);
647 } while (keep_running == NULL || *keep_running);
648 cpu_set_program_counter(processor, cia);
650 } while(keep_running == NULL || *keep_running);
655 #if (!WITH_IDECODE_CACHE_SIZE && WITH_SMP > 0)
657 /* CASE 3: No ICACHE but SMP
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 */
665 int first_cpu = setjmp(restart);
667 first_cpu = system->last_cpu + 1;
670 for (current_cpu = first_cpu, first_cpu = 0;
671 current_cpu < system->nr_cpus + (WITH_EVENTS ? 1 : 0);
673 if (WITH_EVENTS && current_cpu == system->nr_cpus) {
674 if (event_queue_tick(system->events))
675 event_queue_process(system->events);
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),
684 cpu_set_program_counter(processor,
685 idecode_issue(processor, instruction, cia));
687 if (!(keep_running == NULL || *keep_running)) {
688 system->last_cpu = current_cpu;
692 } while (keep_running == NULL || *keep_running);
696 #if (WITH_IDECODE_CACHE_SIZE && WITH_SMP > 0)
698 /* CASE 4: ICACHE and SMP ...
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! */
705 int first_cpu = setjmp(restart);
707 first_cpu = system->last_cpu + 1;
710 for (current_cpu = first_cpu, first_cpu = 0;
711 current_cpu < system->nr_cpus + (WITH_EVENTS ? 1 : 0);
713 if (WITH_EVENTS && current_cpu == system->nr_cpus) {
714 if (event_queue_tick(system->events))
715 event_queue_process(system->events);
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));
727 instruction_word instruction =
728 vm_instruction_map_read(cpu_instruction_map(processor),
731 idecode_semantic *semantic = idecode(processor,
735 cache_entry->address = cia;
736 cache_entry->semantic = semantic;
737 cpu_set_program_counter(processor,
738 semantic(processor, cache_entry, cia));
741 if (!(keep_running == NULL || *keep_running))
744 } while (keep_running == NULL || *keep_running);
748 psim_clear_halt_and_restart(system);
752 /* SIMULATE INSTRUCTIONS, various different ways of achieving the same
756 psim_step(psim *system)
758 volatile int keep_running = 0;
759 run_until_stop(system, &keep_running);
763 psim_run(psim *system)
765 run_until_stop(system, NULL);
769 psim_run_until_stop(psim *system,
770 volatile int *keep_running)
772 run_until_stop(system, keep_running);
777 /* storage manipulation functions */
780 psim_read_register(psim *system,
786 register_descriptions description;
787 char cooked_buf[sizeof(natural_word)];
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];
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);
802 /* get the cooked value */
803 switch (description.type) {
806 *(gpreg*)cooked_buf = cpu_registers(processor)->gpr[description.index];
810 *(spreg*)cooked_buf = cpu_registers(processor)->spr[description.index];
814 *(sreg*)cooked_buf = cpu_registers(processor)->sr[description.index];
818 *(fpreg*)cooked_buf = cpu_registers(processor)->fpr[description.index];
822 *(unsigned_word*)cooked_buf = cpu_get_program_counter(processor);
826 *(creg*)cooked_buf = cpu_registers(processor)->cr;
830 *(msreg*)cooked_buf = cpu_registers(processor)->msr;
834 printf_filtered("psim_read_register(processor=0x%x,buf=0x%x,reg=%s) %s\n",
836 "read of this register unimplemented");
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) {
847 *(unsigned_1*)buf = H2T_1(*(unsigned_1*)cooked_buf);
850 *(unsigned_2*)buf = H2T_2(*(unsigned_2*)cooked_buf);
853 *(unsigned_4*)buf = H2T_4(*(unsigned_4*)cooked_buf);
856 *(unsigned_8*)buf = H2T_8(*(unsigned_8*)cooked_buf);
861 bcopy(cooked_buf, buf, description.size);
869 psim_write_register(psim *system,
876 register_descriptions description;
877 char cooked_buf[sizeof(natural_word)];
879 /* find our processor */
880 if (which_cpu == MAX_NR_PROCESSORS)
881 which_cpu = system->last_cpu;
882 if (which_cpu == -1) {
884 for (i = 0; i < system->nr_cpus; i++)
885 psim_write_register(system, i, buf, reg, mode);
888 else if (which_cpu < 0 || which_cpu >= system->nr_cpus) {
889 error("psim_read_register() - invalid processor %d\n", which_cpu);
892 processor = system->processors[which_cpu];
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);
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) {
904 *(unsigned_1*)cooked_buf = T2H_1(*(unsigned_1*)buf);
907 *(unsigned_2*)cooked_buf = T2H_2(*(unsigned_2*)buf);
910 *(unsigned_4*)cooked_buf = T2H_4(*(unsigned_4*)buf);
913 *(unsigned_8*)cooked_buf = T2H_8(*(unsigned_8*)buf);
918 bcopy(buf, cooked_buf, description.size);
921 /* put the cooked value into the register */
922 switch (description.type) {
925 cpu_registers(processor)->gpr[description.index] = *(gpreg*)cooked_buf;
929 cpu_registers(processor)->fpr[description.index] = *(fpreg*)cooked_buf;
933 cpu_set_program_counter(processor, *(unsigned_word*)cooked_buf);
937 cpu_registers(processor)->spr[description.index] = *(spreg*)cooked_buf;
941 cpu_registers(processor)->sr[description.index] = *(sreg*)cooked_buf;
945 cpu_registers(processor)->cr = *(creg*)cooked_buf;
949 cpu_registers(processor)->msr = *(msreg*)cooked_buf;
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");
965 psim_read_memory(psim *system,
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);
983 psim_write_memory(psim *system,
988 int violate_read_only_section)
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);
1002 psim_print_info(psim *system,
1005 mon_print_info(system->monitor, verbose);
1009 #endif /* _PSIM_C_ */