diff options
-rw-r--r-- | sim/ppc/ChangeLog | 46 | ||||
-rw-r--r-- | sim/ppc/config.in | 5 | ||||
-rw-r--r-- | sim/ppc/cpu.c | 106 | ||||
-rw-r--r-- | sim/ppc/emul_bugapi.c | 204 | ||||
-rw-r--r-- | sim/ppc/emul_generic.c | 80 | ||||
-rw-r--r-- | sim/ppc/emul_netbsd.c | 19 | ||||
-rw-r--r-- | sim/ppc/psim.c | 676 |
7 files changed, 643 insertions, 493 deletions
diff --git a/sim/ppc/ChangeLog b/sim/ppc/ChangeLog index b9976a1..613eea1 100644 --- a/sim/ppc/ChangeLog +++ b/sim/ppc/ChangeLog @@ -1,3 +1,49 @@ +Wed Feb 21 10:39:35 1996 Michael Meissner <meissner@tiktok.cygnus.com> + + * emul_bugapi.c (emul_bugapi_create): Make formats type + compatible. + +Mon Feb 19 22:54:40 1996 Andrew Cagney <cagney@highland.com.au> + + * ppc-instructions (TLB Invalidate Entry, TLB Invalidate ALL): + Implement by passing on request to all processors. + * ppc-instructions (TLB Synchronize): Implement as empty, processor + tlb's are always in sync. + + * cpu.c (cpu_page_tlb_invalidate_all): New function. Pass on TLB + invalidate request to processors VM sub-system. + * cpu.c (cpu_page_tlb_invalidate_entry): Ditto. + + * vm.c (vm_page_tlb_invalidate_all): New function. Mark all page + TLB entries as invalid. + * vm.c (vm_page_tlb_invalidate_entry): New function. Ditt but only + invalidate one TLB entry. + + * psim.c (psim_init): Invalidate TLB's before (re)starting. + +Mon Feb 19 21:25:56 1996 Andrew Cagney <cagney@highland.com.au> + + * emul_generic.c (emul_add_tree_options): Add argument + oea_interrupt_prefix (0 or 1) that specifies the prefix MSR[IP] + and hence the location of the interrupt vectors. Add this to the + device tree. + + * emul_chirp.c (emul_chirp_create): Allow configuration of + floating-point and interrupt prefix (default 0) using the above. + + * emul_netbsd.c (emul_netbsd_create): Pass dummy arg for + interrupt-prefix. + + * emul_bugapi.c (emul_bugapi_create): Allow configuration of + interrupt prefix (default 1) and configure interrupt table traps + accordingly. + + * emul_generic.c (emul_add_tree_hardware): Include a small eeprom + in the list of devices. + + * device_table.c: For moment fake eeprom device by a memory + device. In future will need a proper eeprom device. + Tue Feb 20 17:01:26 1996 J.T. Conklin <jtc@rtl.cygnus.com> * config.in: Regenerated. diff --git a/sim/ppc/config.in b/sim/ppc/config.in index 7434926..e081c74 100644 --- a/sim/ppc/config.in +++ b/sim/ppc/config.in @@ -1,5 +1,8 @@ /* config.in. Generated automatically from configure.in by autoheader. */ +#ifndef CONFIG_H +#define CONFIG_H + /* Define if your processor stores words with the most significant byte first (like Motorola and SPARC, unlike Intel and VAX). */ #undef WORDS_BIGENDIAN @@ -45,3 +48,5 @@ /* Define if you have the <unistd.h> header file. */ #undef HAVE_UNISTD_H + +#endif diff --git a/sim/ppc/cpu.c b/sim/ppc/cpu.c index ef8cfeb..9e9e7e7 100644 --- a/sim/ppc/cpu.c +++ b/sim/ppc/cpu.c @@ -22,10 +22,6 @@ #ifndef _CPU_C_ #define _CPU_C_ -#ifndef STATIC_INLINE_CPU -#define STATIC_INLINE_CPU STATIC_INLINE -#endif - #include <setjmp.h> #include "cpu.h" @@ -58,6 +54,7 @@ struct _cpu { /* the system this processor is contained within */ cpu_mon *monitor; + os_emul *os_emulation; psim *system; event_queue *events; int cpu_nr; @@ -81,12 +78,13 @@ struct _cpu { }; - -INLINE_CPU cpu * +INLINE_CPU\ +(cpu *) cpu_create(psim *system, core *memory, event_queue *events, cpu_mon *monitor, + os_emul *os_emulation, int cpu_nr) { cpu *processor = ZALLOC(cpu); @@ -105,17 +103,19 @@ cpu_create(psim *system, processor->events = events; processor->cpu_nr = cpu_nr; processor->monitor = monitor; + processor->os_emulation = os_emulation; return processor; } -INLINE_CPU void +INLINE_CPU\ +(void) cpu_init(cpu *processor) { memset(&processor->regs, 0, sizeof(processor->regs)); - /* FIXME - should any of VM be inited also ? */ - + /* vm init is delayed until after the device tree has been init as + the devices may further init the cpu */ if (CURRENT_MODEL_ISSUE > 0) model_init (processor->model_ptr); } @@ -123,31 +123,43 @@ cpu_init(cpu *processor) /* find ones way home */ -INLINE_CPU psim * +INLINE_CPU\ +(psim *) cpu_system(cpu *processor) { return processor->system; } -INLINE_CPU int +INLINE_CPU\ +(int) cpu_nr(cpu *processor) { return processor->cpu_nr; } -INLINE_CPU event_queue * +INLINE_CPU\ +(event_queue *) cpu_event_queue(cpu *processor) { return processor->events; } -INLINE_CPU cpu_mon * +INLINE_CPU\ +(cpu_mon *) cpu_monitor(cpu *processor) { return processor->monitor; } -INLINE_CPU model_data * +INLINE_CPU\ +(os_emul *) +cpu_os_emulation(cpu *processor) +{ + return processor->os_emulation; +} + +INLINE_CPU\ +(model_data *) cpu_model(cpu *processor) { return processor->model_ptr; @@ -155,14 +167,16 @@ cpu_model(cpu *processor) /* The processors local concept of time */ -INLINE_CPU signed64 +INLINE_CPU\ +(signed64) cpu_get_time_base(cpu *processor) { return (event_queue_time(processor->events) - processor->time_base_local_time); } -INLINE_CPU void +INLINE_CPU\ +(void) cpu_set_time_base(cpu *processor, signed64 time_base) { @@ -170,14 +184,16 @@ cpu_set_time_base(cpu *processor, - time_base); } -INLINE_CPU signed32 +INLINE_CPU\ +(signed32) cpu_get_decrementer(cpu *processor) { return (processor->decrementer_local_time - event_queue_time(processor->events)); } -STATIC_INLINE_CPU void +STATIC_INLINE_CPU\ +(void) cpu_decrement_event(event_queue *queue, void *data) { @@ -190,7 +206,8 @@ cpu_decrement_event(event_queue *queue, } } -INLINE_CPU void +INLINE_CPU\ +(void) cpu_set_decrementer(cpu *processor, signed32 decrementer) { @@ -216,20 +233,23 @@ cpu_set_decrementer(cpu *processor, /* program counter manipulation */ -INLINE_CPU void +INLINE_CPU\ +(void) cpu_set_program_counter(cpu *processor, unsigned_word new_program_counter) { processor->program_counter = new_program_counter; } -INLINE_CPU unsigned_word +INLINE_CPU\ +(unsigned_word) cpu_get_program_counter(cpu *processor) { return processor->program_counter; } -INLINE_CPU void +INLINE_CPU\ +(void) cpu_restart(cpu *processor, unsigned_word nia) { @@ -237,7 +257,8 @@ cpu_restart(cpu *processor, psim_restart(processor->system, processor->cpu_nr); } -INLINE_CPU void +INLINE_CPU\ +(void) cpu_halt(cpu *processor, unsigned_word cia, stop_reason reason, @@ -261,7 +282,8 @@ cpu_halt(cpu *processor, #if WITH_IDECODE_CACHE_SIZE /* allow access to the cpu's instruction cache */ -INLINE_CPU idecode_cache * +INLINE_CPU\ +(idecode_cache *) cpu_icache_entry(cpu *processor, unsigned_word cia) { @@ -269,7 +291,8 @@ cpu_icache_entry(cpu *processor, } -INLINE_CPU void +INLINE_CPU\ +(void) cpu_flush_icache(cpu *processor) { int i; @@ -282,22 +305,40 @@ cpu_flush_icache(cpu *processor) /* address map revelation */ -INLINE_CPU vm_instruction_map * +INLINE_CPU\ +(vm_instruction_map *) cpu_instruction_map(cpu *processor) { return processor->instruction_map; } -INLINE_CPU vm_data_map * +INLINE_CPU\ +(vm_data_map *) cpu_data_map(cpu *processor) { return processor->data_map; } +INLINE_CPU\ +(void) +cpu_page_tlb_invalidate_entry(cpu *processor, + unsigned_word ea) +{ + vm_page_tlb_invalidate_entry(processor->virtual, ea); +} + +INLINE_CPU\ +(void) +cpu_page_tlb_invalidate_all(cpu *processor) +{ + vm_page_tlb_invalidate_all(processor->virtual); +} + /* reservation access */ -INLINE_CPU memory_reservation * +INLINE_CPU\ +(memory_reservation *) cpu_reservation(cpu *processor) { return &processor->reservation; @@ -306,13 +347,15 @@ cpu_reservation(cpu *processor) /* register access */ -INLINE_CPU registers * +INLINE_CPU\ +(registers *) cpu_registers(cpu *processor) { return &processor->regs; } -INLINE_CPU void +INLINE_CPU\ +(void) cpu_synchronize_context(cpu *processor) { #if (WITH_IDECODE_CACHE) @@ -330,7 +373,8 @@ cpu_synchronize_context(cpu *processor) /* might again be useful one day */ -INLINE_CPU void +INLINE_CPU\ +(void) cpu_print_info(cpu *processor, int verbose) { } diff --git a/sim/ppc/emul_bugapi.c b/sim/ppc/emul_bugapi.c index f325901..a202541 100644 --- a/sim/ppc/emul_bugapi.c +++ b/sim/ppc/emul_bugapi.c @@ -1,6 +1,6 @@ /* This file is part of the program psim. - Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au> + Copyright (C) 1994-1996, Andrew Cagney <cagney@highland.com.au> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -50,28 +50,23 @@ #include "emul_generic.h" #include "emul_bugapi.h" -/* Any starting address less than this is assumed to be an OEA program - rather than VEA. */ -#ifndef OEA_START_ADDRESS -#define OEA_START_ADDRESS 0x4000 -#endif -#ifndef OEA_MEMORY_SIZE -#define OEA_MEMORY_SIZE 0x100000 +#ifndef OEA_START_ADDRESS +#define OEA_START_ADDRESS 0x100000 #endif -/* All but CPU 0 are put into an infinate loop, this loop instruction - is stored at the address below */ -#ifndef OEA_STALL_CPU_LOOP_ADDRESS -#define OEA_STALL_CPU_LOOP_ADDRESS 0x00c10 -#endif -/* At initiallization, the system call exception branches to the BUG - emulation code */ -#ifndef OEA_SYSTEM_CALL_ADDRESS -#define OEA_SYSTEM_CALL_ADDRESS 0x00c00 -#endif +struct _os_emul_data { + unsigned_word memory_size; + unsigned_word top_of_stack; + int interrupt_prefix; + unsigned_word interrupt_vector_address; + unsigned_word system_call_address; + unsigned_word stall_cpu_loop_address; + int little_endian; + int floating_point_available; +}; static os_emul_data * @@ -79,6 +74,9 @@ emul_bugapi_create(device *root, bfd *image, const char *name) { + int elf_binary; + device *node; + os_emul_data *bugapi; /* check it really is for us */ if (name != NULL @@ -90,99 +88,85 @@ emul_bugapi_create(device *root, && bfd_get_start_address(image) > OEA_START_ADDRESS) return NULL; - { - - const memory_size = OEA_MEMORY_SIZE; - const elf_binary = (image != NULL - && image->xvec->flavour == bfd_target_elf_flavour); -#ifdef bfd_little_endian /* new bfd */ - const little_endian = (image != NULL && bfd_little_endian(image)); -#else - const little_endian = (image != NULL && - !image->xvec->byteorder_big_p); -#endif - - { /* options */ - device *options = device_tree_add_found(root, "/", "options"); - device_add_integer_property(options, - "smp", - MAX_NR_PROCESSORS); - device_add_boolean_property(options, - "little-endian?", - little_endian); - device_add_string_property(options, - "env", - "operating"); - device_add_boolean_property(options, - "strict-alignment?", - (WITH_ALIGNMENT == STRICT_ALIGNMENT - || little_endian)); - device_add_boolean_property(options, - "floating-point?", - WITH_FLOATING_POINT); - device_add_string_property(options, - "os-emul", - "bugapi"); - } + bugapi = ZALLOC(os_emul_data); + + /* some defaults */ + elf_binary = image->xvec->flavour == bfd_target_elf_flavour; + + /* options */ + emul_add_tree_options(root, image, "bug", "oea", + 1 /*oea-interrupt-prefix*/); + + /* add some real hardware */ + emul_add_tree_hardware(root); + + bugapi->memory_size + = device_find_integer_property(root, "/openprom/options/oea-memory-size"); + bugapi->interrupt_prefix = + device_find_integer_property(root, "/openprom/options/oea-interrupt-prefix"); + bugapi->interrupt_vector_address = (bugapi->interrupt_prefix + ? MASK(0, 43) + : 0); + bugapi->system_call_address = (bugapi->interrupt_vector_address + 0x00c00); + bugapi->stall_cpu_loop_address = (bugapi->system_call_address + 0x000f0); + bugapi->top_of_stack = bugapi->memory_size - 0x1000; + bugapi->little_endian + = device_find_boolean_property(root, "/options/little-endian?"); + bugapi->floating_point_available + = device_find_boolean_property(root, "/openprom/options/floating-point?"); + + /* initialization */ + device_tree_add_parsed(root, "/openprom/init/register/0.pc 0x%lx", + (unsigned long)bfd_get_start_address(image)); + device_tree_add_parsed(root, "/openprom/init/register/pc 0x%lx", + (unsigned long)bugapi->stall_cpu_loop_address); + device_tree_add_parsed(root, "/openprom/init/register/sp 0x%lx", + (unsigned long)(bugapi->top_of_stack - 16)); + device_tree_add_parsed(root, "/openprom/init/register/msr 0x%x", + (msr_recoverable_interrupt + | (bugapi->little_endian + ? (msr_little_endian_mode + | msr_interrupt_little_endian_mode) + : 0) + | (bugapi->floating_point_available + ? msr_floating_point_available + : 0) + | (bugapi->interrupt_prefix + ? msr_interrupt_prefix + : 0) + )); + + /* patch the system call instruction to call this emulation and then + do an rfi */ + node = device_tree_add_parsed(root, "/openprom/init/data@0x%lx", + (long)bugapi->system_call_address); + device_tree_add_parsed(node, "./real-address 0x%lx", + (long)bugapi->system_call_address); + device_tree_add_parsed(node, "./data 0x%x", + emul_call_instruction); + node = device_tree_add_parsed(root, "/openprom/init/data@0x%lx", + (long)(bugapi->system_call_address + 4)); + device_tree_add_parsed(node, "./real-address 0x%lx", + (long)(bugapi->system_call_address + 4)); + device_tree_add_parsed(node, "./data 0x%x", + emul_rfi_instruction); + + /* patch the end of the system call instruction so that it contains + a loop to self instruction and point all the cpu's at this */ + node = device_tree_add_parsed(root, "/openprom/init/data@0x%lx", + (unsigned long)bugapi->stall_cpu_loop_address); + device_tree_add_parsed(node, "./real-address 0x%lx", + (unsigned long)bugapi->stall_cpu_loop_address); + device_tree_add_parsed(node, "./data 0x%lx", + (unsigned long)emul_loop_instruction); - /* hardware */ - device_tree_add_found_uw_u_u(root, "/", "memory", - 0, memory_size, access_read_write_exec); - device_tree_add_found(root, "/", "iobus@0x400000"); - device_tree_add_found(root, "/iobus", "console@0x000000,16"); - device_tree_add_found(root, "/iobus", "halt@0x100000,4"); - device_tree_add_found(root, "/iobus", "icu@0x200000,4"); + device_tree_add_parsed(root, "/openprom/init/stack/stack-type %s", + elf_binary ? "elf" : "aix"); - { /* initialization */ - device *init = device_tree_add_found(root, "/", "init"); - { - device *init_register = device_tree_add_found(init, "", "register"); - device_add_integer_property(init_register, - "pc", - OEA_STALL_CPU_LOOP_ADDRESS); - device_add_integer_property(init_register, - "0.pc", - bfd_get_start_address(image)); - device_add_integer_property(init_register, - "sp", - memory_size-16); - device_add_integer_property(init_register, - "msr", - (msr_recoverable_interrupt - | (little_endian - ? msr_little_endian_mode - : 0) - )); - device_tree_add_found_uw_u_u(init, "", - "data", - OEA_SYSTEM_CALL_ADDRESS, - 4, emul_call_instruction); - device_tree_add_found_uw_u_u(init, "", - "data", - OEA_SYSTEM_CALL_ADDRESS + 4, - 4, emul_rfi_instruction); - device_tree_add_found_uw_u_u(init, "", - "data", - OEA_STALL_CPU_LOOP_ADDRESS, - 4, emul_loop_instruction); - } - { - device *init_stack = device_tree_add_found(init, "", "stack"); - device_add_null_property(init_stack, - (elf_binary - ? "elf" - : "aix")); - } - { - device *init_load_binary = device_tree_add_found(init, "", - "load-binary"); - device_add_null_property(init_load_binary, - bfd_get_filename(image)); - } - } - } - - return (os_emul_data*)-1; + device_tree_add_parsed(root, "/openprom/init/load-binary/file-name \"%s", + bfd_get_filename(image)); + + return bugapi; } static void @@ -200,7 +184,7 @@ emul_bugapi_instruction_call(cpu *processor, { const int call_id = cpu_registers(processor)->gpr[10]; /* check that this isn't an invalid instruction */ - if (cia != OEA_SYSTEM_CALL_ADDRESS) + if (cia != emul_data->system_call_address) return 0; switch (call_id) { case _OUTCHR: diff --git a/sim/ppc/emul_generic.c b/sim/ppc/emul_generic.c index 8f8ae09..f45df6c 100644 --- a/sim/ppc/emul_generic.c +++ b/sim/ppc/emul_generic.c @@ -1,6 +1,6 @@ /* This file is part of the program psim. - Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au> + Copyright (C) 1994-1996, Andrew Cagney <cagney@highland.com.au> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -214,4 +214,82 @@ emul_do_system_call(os_emul_data *emul_data, emul_syscall_exit(emul, call, arg0, processor, cia); } + +/* default size for the first bank of memory */ + +#ifndef OEA_MEMORY_SIZE +#define OEA_MEMORY_SIZE 0x100000 +#endif + + +/* Add options to the device tree */ + +INLINE_EMUL_GENERIC void +emul_add_tree_options(device *tree, + bfd *image, + const char *emul, + const char *env, + int oea_interrupt_prefix) +{ + int little_endian = 0; + + /* sort out little endian */ + if (device_find_property(tree, "/options/little-endian?")) + little_endian = device_find_boolean_property(tree, "/options/little-endian?"); + else { +#ifdef bfd_little_endian /* new bfd */ + little_endian = (image != NULL && bfd_little_endian(image)); +#else + little_endian = (image != NULL && + !image->xvec->byteorder_big_p); +#endif + device_tree_add_parsed(tree, "/options/little-endian? %s", + little_endian ? "true" : "false"); + } + + /* misc other stuff */ + device_tree_add_parsed(tree, "/openprom/options/oea-memory-size 0x%x", + OEA_MEMORY_SIZE); + device_tree_add_parsed(tree, "/openprom/options/oea-interrupt-prefix %d", + oea_interrupt_prefix); + device_tree_add_parsed(tree, "/openprom/options/smp 1"); + device_tree_add_parsed(tree, "/openprom/options/env %s", env); + device_tree_add_parsed(tree, "/openprom/options/os-emul %s", emul); + device_tree_add_parsed(tree, "/openprom/options/strict-alignment? %s", + (WITH_ALIGNMENT == STRICT_ALIGNMENT || little_endian) + ? "true" : "false"); + device_tree_add_parsed(tree, "/openprom/options/floating-point? %s", + WITH_FLOATING_POINT ? "true" : "false"); + device_tree_add_parsed(tree, "/openprom/options/model \"%s", + model_name[WITH_DEFAULT_MODEL]); + device_tree_add_parsed(tree, "/openprom/options/model-issue %d", + MODEL_ISSUE_IGNORE); +} + +INLINE_EMUL_GENERIC void +emul_add_tree_hardware(device *root) +{ + /* add some memory */ + if (device_tree_find_device(root, "/memory") == NULL) { + unsigned_word memory_size = + device_find_integer_property(root, "/openprom/options/oea-memory-size"); + device_tree_add_parsed(root, "/memory@0/reg { 0x0 0x%lx", + (unsigned long)memory_size); + /* what about allocated? */ + } + /* an eeprom */ + device_tree_add_parsed(root, "/openprom/eeprom@0xfff00000/reg { 0xfff00000 0x3000"); + /* the IO bus */ + device_tree_add_parsed(root, "/iobus@0x400000/reg { 0x400000 0x400000"); + device_tree_add_parsed(root, "/iobus/console@0x000000/reg { 0x000000 16"); + device_tree_add_parsed(root, "/iobus/halt@0x100000/reg { 0x100000 4"); + device_tree_add_parsed(root, "/iobus/icu@0x200000/reg { 0x200000 8"); + device_tree_add_parsed(root, "/iobus/icu > 0 0 /iobus/icu"); + device_tree_add_parsed(root, "/iobus/icu > 1 1 /iobus/icu"); + /* chosen etc */ + device_tree_add_parsed(root, "/chosen/stdin */iobus/console"); + device_tree_add_parsed(root, "/chosen/stdout !/chosen/stdin"); + device_tree_add_parsed(root, "/chosen/memory */memory"); +} + #endif /* _SYSTEM_C_ */ diff --git a/sim/ppc/emul_netbsd.c b/sim/ppc/emul_netbsd.c index 6db39a4..27de365 100644 --- a/sim/ppc/emul_netbsd.c +++ b/sim/ppc/emul_netbsd.c @@ -45,8 +45,17 @@ #include <sys/errno.h> #include <sys/param.h> #include <sys/time.h> + +#ifdef HAVE_GETRUSAGE +#ifndef HAVE_SYS_RESOURCE_H +#undef HAVE_GETRUSAGE +#endif +#endif + +#ifdef HAVE_GETRUSAGE #include <sys/resource.h> int getrusage(); +#endif #include <sys/ioctl.h> #include <sys/mount.h> @@ -224,6 +233,7 @@ write_direntries(unsigned_word addr, #endif +#ifdef HAVE_GETRUSAGE STATIC_INLINE_EMUL_NETBSD void write_rusage(unsigned_word addr, struct rusage rusage, @@ -250,7 +260,7 @@ write_rusage(unsigned_word addr, H2T(rusage.ru_nivcsw); /* involuntary context switches */ emul_write_buffer(&rusage, addr, sizeof(rusage), processor, cia); } - +#endif static void do_exit(os_emul_data *emul, @@ -648,6 +658,9 @@ do_gettimeofday(os_emul_data *emul, } +#ifndef HAVE_GETRUSAGE +#define do_getrusage 0 +#else static void do_getrusage(os_emul_data *emul, unsigned call, @@ -670,6 +683,7 @@ do_getrusage(os_emul_data *emul, write_rusage(rusage_addr, rusage, processor, cia); } } +#endif #if !WITH_NetBSD_HOST @@ -1277,7 +1291,8 @@ emul_netbsd_create(device *root, /* options */ emul_add_tree_options(root, image, "netbsd", (WITH_ENVIRONMENT == USER_ENVIRONMENT - ? "user" : "virtual")); + ? "user" : "virtual"), + 0 /*oea-interrupt-prefix*/); /* virtual memory - handles growth of stack/heap */ vm = device_tree_add_parsed(root, "/openprom/vm@0x%lx", diff --git a/sim/ppc/psim.c b/sim/ppc/psim.c index e12556c..cbdc35e 100644 --- a/sim/ppc/psim.c +++ b/sim/ppc/psim.c @@ -1,6 +1,6 @@ /* This file is part of the program psim. - Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au> + Copyright (C) 1994-1996, Andrew Cagney <cagney@highland.com.au> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -22,25 +22,20 @@ #ifndef _PSIM_C_ #define _PSIM_C_ +#include "inline.c" + #include <stdio.h> #include <ctype.h> -#include "config.h" -#include "ppc-config.h" -#include "inline.h" - #ifdef HAVE_STDLIB_H #include <stdlib.h> #endif -#ifndef STATIC_INLINE_PSIM -#define STATIC_INLINE_PSIM STATIC_INLINE -#endif - #include <setjmp.h> #include "cpu.h" /* includes psim.h */ #include "idecode.h" +#include "options.h" #ifdef HAVE_STRING_H #include <string.h> @@ -53,39 +48,24 @@ #include "bfd.h" -#include "inline.c" - -/* Any starting address less than this is assumed to be an OEA program - rather than VEA. */ -#ifndef OEA_START_ADDRESS -#define OEA_START_ADDRESS 4096 -#endif - -/* Any starting address greater than this is assumed to be an OpenBoot - rather than VEA */ -#ifndef OPENBOOT_START_ADDRESS -#define OPENBOOT_START_ADDRESS 0x80000000 -#endif - -#ifndef OEA_MEMORY_SIZE -#define OEA_MEMORY_SIZE 0x100000 -#endif - - /* system structure, actual size of processor array determined at runtime */ struct _psim { event_queue *events; - device_tree *devices; + device *devices; mon *monitor; + os_emul *os_emulation; core *memory; + /* escape routine for inner functions */ void *path_to_halt; void *path_to_restart; + /* status from last halt */ psim_status halt_status; - /* the processes proper */ + + /* the processors proper */ int nr_cpus; int last_cpu; /* CPU that last (tried to) execute an instruction */ cpu *processors[MAX_NR_PROCESSORS]; @@ -101,306 +81,207 @@ int current_model_issue = MODEL_ISSUE_IGNORE; model_enum current_model = WITH_DEFAULT_MODEL; -/* create a device tree from the image */ - - +/* create the device tree */ -/* Raw hardware tree: - - A small default set of devices are configured. Each section of the - image is loaded directly into physical memory. */ - -STATIC_INLINE_PSIM void -create_hardware_device_tree(bfd *image, - device_tree *root) +INLINE_PSIM\ +(device *) +psim_tree(void) { - char *name; - const memory_size = OEA_MEMORY_SIZE; - - /* options */ - device_tree_add_passthrough(root, "/options"); - device_tree_add_integer(root, "/options/smp", - MAX_NR_PROCESSORS); - device_tree_add_boolean(root, "/options/little-endian?", - !image->xvec->byteorder_big_p); - device_tree_add_string(root, "/options/env", - "operating"); - device_tree_add_boolean(root, "/options/strict-alignment?", - (WITH_ALIGNMENT == STRICT_ALIGNMENT - || !image->xvec->byteorder_big_p)); - device_tree_add_boolean(root, "/options/floating-point?", - WITH_FLOATING_POINT); - - /* hardware */ - name = printd_uw_u_u("/memory", 0, memory_size, access_read_write_exec); - device_tree_add_found_device(root, name); - zfree(name); - device_tree_add_found_device(root, "/iobus@0x400000"); - device_tree_add_found_device(root, "/iobus/console@0x000000,16"); - device_tree_add_found_device(root, "/iobus/halt@0x100000,4"); - device_tree_add_found_device(root, "/iobus/icu@0x200000,4"); - - /* initialization */ - device_tree_add_passthrough(root, "/init"); - device_tree_add_found_device(root, "/init/register@pc,0x0"); - name = printd_c_uw("/init/register", "sp", memory_size); - device_tree_add_found_device(root, name); - zfree(name); - name = printd_c_uw("/init/register", "msr", - (image->xvec->byteorder_big_p - ? 0 - : msr_little_endian_mode)); - device_tree_add_found_device(root, name); - zfree(name); - /* AJC puts the PC at zero and wants a stack while MM puts it above - zero and doesn't. Really there should be no stack *but* this - makes testing easier */ - device_tree_add_found_device(root, - (bfd_get_start_address(image) == 0 - ? "/init/stack@elf" - : "/init/stack@none")); - name = printd_c("/init/load-binary", bfd_get_filename(image)); - device_tree_add_found_device(root, name); - zfree(name); + device *root = core_device_create(); + device_tree_add_parsed(root, "/aliases"); + device_tree_add_parsed(root, "/options"); + device_tree_add_parsed(root, "/chosen"); + device_tree_add_parsed(root, "/packages"); + device_tree_add_parsed(root, "/cpus"); + device_tree_add_parsed(root, "/openprom"); + device_tree_add_parsed(root, "/openprom/init"); + device_tree_add_parsed(root, "/openprom/trace"); + device_tree_add_parsed(root, "/openprom/options"); + return root; } - -/* Openboot model (under development): - - An extension of the hardware model. The image is read into memory - as a single block. Sections of the image are then mapped as - required using a HTAB. */ - -STATIC_INLINE_PSIM void -create_openboot_device_tree(bfd *image, - device_tree *root) +STATIC_INLINE_PSIM\ +(char *) +find_arg(char *err_msg, + int *ptr_to_argp, + char **argv) { - create_hardware_device_tree(image, root); + *ptr_to_argp += 1; + if (argv[*ptr_to_argp] == NULL) + error(err_msg); + return argv[*ptr_to_argp]; } - -/* User mode model: - - Image sections loaded into virtual addresses as specified. A - (large) stack is reserved (but only allocated as needed). System - calls that include suport for heap growth are attached. */ - -STATIC_INLINE_PSIM void -create_vea_device_tree(bfd *image, - device_tree *root) +INLINE_PSIM\ +(void) +psim_usage(int verbose) { - unsigned_word top_of_stack; - unsigned stack_size; - int elf_binary; - char *name; - - /* establish a few defaults */ - if (image->xvec->flavour == bfd_target_elf_flavour) { - elf_binary = 1; - top_of_stack = 0xe0000000; - stack_size = 0x00100000; - } - else { - elf_binary = 0; - top_of_stack = 0x20000000; - stack_size = 0x00100000; + printf_filtered("Usage:\n"); + printf_filtered("\n"); + printf_filtered("\tpsim [ <psim-option> ... ] <image> [ <image-arg> ... ]\n"); + printf_filtered("\n"); + printf_filtered("Where\n"); + printf_filtered("\n"); + printf_filtered("\t<image> Name of the PowerPC program to run.\n"); + if (verbose) { + printf_filtered("\t This can either be a PowerPC binary or\n"); + printf_filtered("\t a text file containing a device tree\n"); + printf_filtered("\t specification.\n"); + printf_filtered("\t PSIM will attempt to determine from the\n"); + printf_filtered("\t specified <image> the intended emulation\n"); + printf_filtered("\t environment.\n"); + printf_filtered("\t If PSIM gets it wrong, the emulation\n"); + printf_filtered("\t environment can be specified using the\n"); + printf_filtered("\t `-e' option (described below).\n"); + printf_filtered("\n"); } + printf_filtered("\t<image-arg> Argument to be passed to <image>\n"); + if (verbose) { + printf_filtered("\t These arguments will be passed to\n"); + printf_filtered("\t <image> (as standard C argv, argc)\n"); + printf_filtered("\t when <image> is started.\n"); + printf_filtered("\n"); } + printf_filtered("\t<psim-option> See below\n"); + printf_filtered("\n"); + printf_filtered("The following are valid <psim-option>s:\n"); + printf_filtered("\n"); + printf_filtered("\t-m <model> Specify the processor to model (604)\n"); + if (verbose) { + printf_filtered("\t Selects the processor to use when\n"); + printf_filtered("\t modeling execution units. Includes:\n"); + printf_filtered("\t 604, 603 and 603e\n"); + printf_filtered("\n"); } + printf_filtered("\t-e <os-emul> specify an OS or platform to model\n"); + if (verbose) { + printf_filtered("\t Can be any of the following:\n"); + printf_filtered("\t bug - OEA + MOTO BUG ROM calls\n"); + printf_filtered("\t netbsd - UEA + NetBSD system calls\n"); + printf_filtered("\t chirp - OEA + a few OpenBoot calls\n"); + printf_filtered("\n"); } + printf_filtered("\t-i Print instruction counting statistics\n"); + if (verbose) { printf_filtered("\n"); } + printf_filtered("\t-I Print execution unit statistics\n"); + if (verbose) { printf_filtered("\n"); } + printf_filtered("\t-r <size> Set RAM size in bytes (OEA environments)\n"); + if (verbose) { printf_filtered("\n"); } + printf_filtered("\t-t [!]<trace> Enable (disable) <trace> option\n"); + if (verbose) { printf_filtered("\n"); } + printf_filtered("\t-o <spec> add device <spec> to the device tree\n"); + if (verbose) { printf_filtered("\n"); } + printf_filtered("\t-h -? -H give more detailed usage\n"); + if (verbose) { printf_filtered("\n"); } + printf_filtered("\n"); + trace_usage(verbose); + device_usage(verbose); + if (verbose > 1) { + printf_filtered("\n"); + print_options(); } - - /* options */ - device_tree_add_passthrough(root, "/options"); - device_tree_add_integer(root, "/options/smp", 1); /* always */ - device_tree_add_boolean(root, "/options/little-endian?", - !image->xvec->byteorder_big_p); - device_tree_add_string(root, "/options/env", - (WITH_ENVIRONMENT == USER_ENVIRONMENT - ? "user" : "virtual")); - device_tree_add_boolean(root, "/options/strict-alignment?", - (WITH_ALIGNMENT == STRICT_ALIGNMENT - || !image->xvec->byteorder_big_p)); - device_tree_add_boolean(root, "/options/floating-point?", - WITH_FLOATING_POINT); - - /* virtual memory - handles growth of stack/heap */ - name = printd_uw_u("/vm", top_of_stack - stack_size, stack_size); - device_tree_add_found_device(root, name); - zfree(name); - name = printd_c("/vm/map-binary", bfd_get_filename(image)); - device_tree_add_found_device(root, name); - zfree(name); - - /* finish the init */ - device_tree_add_passthrough(root, "/init"); - name = printd_c_uw("/init/register", "pc", bfd_get_start_address(image)); - device_tree_add_found_device(root, name); /*pc*/ - zfree(name); - name = printd_c_uw("/init/register", "sp", top_of_stack); - device_tree_add_found_device(root, name); - zfree(name); - name = printd_c_uw("/init/register", "msr", - (image->xvec->byteorder_big_p - ? 0 - : msr_little_endian_mode)); - device_tree_add_found_device(root, name); - zfree(name); - device_tree_add_found_device(root, (elf_binary - ? "/init/stack@elf" - : "/init/stack@xcoff")); + error(""); } - -/* File device: - - The file contains lines that specify the describe the device tree - to be created, read them in and load them into the tree */ - -STATIC_INLINE_PSIM void -create_filed_device_tree(const char *file_name, - device_tree *root) +INLINE_PSIM\ +(char **) +psim_options(device *root, + char **argv) { - FILE *description = fopen(file_name, "r"); - int line_nr = 0; - char device_path[1000]; - while (fgets(device_path, sizeof(device_path), description)) { - /* check all of line was read */ - { - char *end = strchr(device_path, '\n'); - if (end == NULL) { - fclose(description); - error("create_filed_device_tree() line %d to long: %s\n", - line_nr, device_path); - } - line_nr++; - *end = '\0'; - } - /* check for leading comment */ - if (device_path[0] != '/') - continue; - /* enter it in varying ways */ - if (strchr(device_path, '@') != NULL) { - device_tree_add_found_device(root, device_path); - } - else { - char *space = strchr(device_path, ' '); - if (space == NULL) { - /* intermediate node */ - device_tree_add_passthrough(root, device_path); - } - else if (space[-1] == '?') { - /* boolean */ - *space = '\0'; - device_tree_add_boolean(root, device_path, space[1] != '0'); - } - else if (isdigit(space[1])) { - /* integer */ - *space = '\0'; - device_tree_add_integer(root, device_path, strtoul(space+1, 0, 0)); - } - else if (space[1] == '"') { - /* quoted string */ - char *end = strchr(space+2, '\0'); - if (end[-1] == '"') - end[-1] = '\0'; - *space = '\0'; - device_tree_add_string(root, device_path, space + 2); - } - else { - /* any thing else */ - *space = '\0'; - device_tree_add_string(root, device_path, space + 1); + device *current = root; + int argp; + if (argv == NULL) + return NULL; + argp = 0; + while (argv[argp] != NULL && argv[argp][0] == '-') { + char *p = argv[argp] + 1; + char *param; + while (*p != '\0') { + switch (*p) { + default: + psim_usage(0); + error (""); + break; + case 'e': + param = find_arg("Missing <emul> option for -e\n", &argp, argv); + device_tree_add_parsed(root, "/openprom/options/os-emul %s", param); + break; + case 'h': + case '?': + psim_usage(1); + break; + case 'H': + psim_usage(2); + break; + case 'i': + device_tree_add_parsed(root, "/openprom/trace/print-info 1"); + break; + case 'I': + device_tree_add_parsed(root, "/openprom/trace/print-info 2"); + device_tree_add_parsed(root, "/openprom/options/model-issue %d", + MODEL_ISSUE_PROCESS); + break; + case 'm': + param = find_arg("Missing <model> option for -m\n", &argp, argv); + device_tree_add_parsed(root, "/openprom/options/model %s", param); + break; + case 'o': + param = find_arg("Missing <device> option for -o\n", &argp, argv); + current = device_tree_add_parsed(current, "%s", param); + break; + case 'r': + param = find_arg("Missing <ram-size> option for -r\n", &argp, argv); + device_tree_add_parsed(root, "/openprom/options/oea-memory-size 0x%lx", + atol(param)); + break; + case 't': + param = find_arg("Missing <trace> option for -t\n", &argp, argv); + if (param[0] == '!') + device_tree_add_parsed(root, "/openprom/trace/%s 0", param+1); + else + device_tree_add_parsed(root, "/openprom/trace/%s 1", param); + break; } + p += 1; } + argp += 1; } - fclose(description); -} - - -/* Given the file containing the `image', create a device tree that - defines the machine to be modeled */ - -STATIC_INLINE_PSIM device_tree * -create_device_tree(const char *file_name, - core *memory) -{ - bfd *image; - const device *core_device = core_device_create(memory); - device_tree *root = device_tree_add_device(NULL, "/", core_device); - - bfd_init(); /* could be redundant but ... */ - - /* open the file */ - image = bfd_openr(file_name, NULL); - if (image == NULL) { - bfd_perror("open failed:"); - error("nothing loaded\n"); - } - - /* check it is valid */ - if (!bfd_check_format(image, bfd_object)) { - printf_filtered("create_device_tree() - FIXME - should check more bfd bits\n"); - printf_filtered("create_device_tree() - %s not an executable, assume device file\n", file_name); - bfd_close(image); - image = NULL; - } - - /* depending on what was found about the file, load it */ - if (image != NULL) { - if (bfd_get_start_address(image) < OEA_START_ADDRESS) { - TRACE(trace_device_tree, ("create_device_tree() - hardware image\n")); - create_hardware_device_tree(image, root); - } - else if (bfd_get_start_address(image) < OPENBOOT_START_ADDRESS) { - TRACE(trace_device_tree, ("create_device_tree() - vea image\n")); - create_vea_device_tree(image, root); - } - else { - TRACE(trace_device_tree, ("create_device_tree() - openboot? image\n")); - create_openboot_device_tree(image, root); - } - bfd_close(image); - } - else { - TRACE(trace_device_tree, ("create_device_tree() - text image\n")); - create_filed_device_tree(file_name, root); - } - - return root; + /* force the trace node to (re)process its options */ + device_init_data(device_tree_find_device(root, "/openprom/trace"), NULL); + /* return where the options end */ + return argv + argp; } +/* create the simulator proper from the device tree and executable */ -INLINE_PSIM psim * -psim_create(const char *file_name) +INLINE_PSIM\ +(psim *) +psim_create(const char *file_name, + device *root) { int cpu_nr; const char *env; psim *system; + os_emul *os_emulation; + int nr_cpus; - /* create things */ - system = ZALLOC(psim); - system->events = event_queue_create(); - system->memory = core_create(); - system->monitor = mon_create(); - system->devices = create_device_tree(file_name, system->memory); - for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; cpu_nr++) { - system->processors[cpu_nr] = cpu_create(system, - system->memory, - system->events, - mon_cpu(system->monitor, - cpu_nr), - cpu_nr); - } + /* given this partially populated device tree, os_emul_create() uses + it and file_name to determine the selected emulation and hence + further populate the tree with any other required nodes. */ + + os_emulation = os_emul_create(file_name, root); + if (os_emulation == NULL) + error("psim: either file %s was not reconized or unreconized or unknown os-emulation type\n", file_name); /* fill in the missing real number of CPU's */ - system->nr_cpus = device_tree_find_integer(system->devices, - "/options/smp"); + nr_cpus = device_find_integer_property(root, "/openprom/options/smp"); + if (MAX_NR_PROCESSORS < nr_cpus) + error("target and configured number of cpus conflict\n"); /* fill in the missing TARGET BYTE ORDER information */ - current_target_byte_order = (device_tree_find_boolean(system->devices, - "/options/little-endian?") - ? LITTLE_ENDIAN - : BIG_ENDIAN); + current_target_byte_order + = (device_find_boolean_property(root, "/options/little-endian?") + ? LITTLE_ENDIAN + : BIG_ENDIAN); if (CURRENT_TARGET_BYTE_ORDER != current_target_byte_order) - error("target byte order conflict\n"); + error("target and configured byte order conflict\n"); /* fill in the missing HOST BYTE ORDER information */ current_host_byte_order = (current_host_byte_order = 1, @@ -408,11 +289,10 @@ psim_create(const char *file_name) ? LITTLE_ENDIAN : BIG_ENDIAN)); if (CURRENT_HOST_BYTE_ORDER != current_host_byte_order) - error("host byte order conflict\n"); + error("host and configured byte order conflict\n"); /* fill in the missing OEA/VEA information */ - env = device_tree_find_string(system->devices, - "/options/env"); + env = device_find_string_property(root, "/openprom/options/env"); current_environment = ((strcmp(env, "user") == 0 || strcmp(env, "uea") == 0) ? USER_ENVIRONMENT @@ -424,25 +304,67 @@ psim_create(const char *file_name) ? OPERATING_ENVIRONMENT : 0); if (current_environment == 0) - error("unreconized /options/env\n"); + error("unreconized /options env property\n"); if (CURRENT_ENVIRONMENT != current_environment) - error("target environment conflict\n"); + error("target and configured environment conflict\n"); /* fill in the missing ALLIGNMENT information */ - current_alignment = (device_tree_find_boolean(system->devices, - "/options/strict-alignment?") - ? STRICT_ALIGNMENT - : NONSTRICT_ALIGNMENT); + current_alignment + = (device_find_boolean_property(root, "/openprom/options/strict-alignment?") + ? STRICT_ALIGNMENT + : NONSTRICT_ALIGNMENT); if (CURRENT_ALIGNMENT != current_alignment) - error("target alignment conflict\n"); + error("target and configured alignment conflict\n"); /* fill in the missing FLOATING POINT information */ - current_floating_point = (device_tree_find_boolean(system->devices, - "/options/floating-point?") - ? HARD_FLOATING_POINT - : SOFT_FLOATING_POINT); + current_floating_point + = (device_find_boolean_property(root, "/openprom/options/floating-point?") + ? HARD_FLOATING_POINT + : SOFT_FLOATING_POINT); if (CURRENT_FLOATING_POINT != current_floating_point) - error("target floating-point conflict\n"); + error("target and configured floating-point conflict\n"); + + /* sort out the level of detail for issue modeling */ + current_model_issue + = device_find_integer_property(root, "/openprom/options/model-issue"); + if (CURRENT_MODEL_ISSUE != current_model_issue) + error("target and configured model-issue conflict\n"); + + /* sort out our model architecture - wrong. + + FIXME: this should be obtaining the required information from the + device tree via the "/chosen" property "cpu" which is an instance + (ihandle) for the only executing processor. By converting that + ihandle into the corresponding cpu's phandle and then querying + the "name" property, the cpu type can be determined. Ok? */ + + model_set(device_find_string_property(root, "/openprom/options/model")); + + /* create things */ + system = ZALLOC(psim); + system->events = event_queue_create(); + system->memory = core_create(root); + system->monitor = mon_create(); + system->nr_cpus = nr_cpus; + system->os_emulation = os_emulation; + system->devices = root; + + /* now all the processors attaching to each their per-cpu information */ + for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; cpu_nr++) { + system->processors[cpu_nr] = cpu_create(system, + system->memory, + system->events, + mon_cpu(system->monitor, + cpu_nr), + system->os_emulation, + cpu_nr); + } + + /* dump out the contents of the device tree */ + if (ppc_trace[trace_print_device_tree] || ppc_trace[trace_dump_device_tree]) + device_tree_traverse(root, device_tree_print_device, NULL, NULL); + if (ppc_trace[trace_dump_device_tree]) + error(""); return system; } @@ -450,7 +372,8 @@ psim_create(const char *file_name) /* allow the simulation to stop/restart abnormaly */ -STATIC_INLINE_PSIM void +STATIC_INLINE_PSIM\ +(void) psim_set_halt_and_restart(psim *system, void *halt_jmp_buf, void *restart_jmp_buf) @@ -459,14 +382,16 @@ psim_set_halt_and_restart(psim *system, system->path_to_restart = restart_jmp_buf; } -STATIC_INLINE_PSIM void +STATIC_INLINE_PSIM\ +(void) psim_clear_halt_and_restart(psim *system) { system->path_to_halt = NULL; system->path_to_restart = NULL; } -INLINE_PSIM void +INLINE_PSIM\ +(void) psim_restart(psim *system, int current_cpu) { @@ -475,7 +400,8 @@ psim_restart(psim *system, } -INLINE_PSIM void +INLINE_PSIM\ +(void) psim_halt(psim *system, int current_cpu, unsigned_word cia, @@ -490,14 +416,16 @@ psim_halt(psim *system, longjmp(*(jmp_buf*)(system->path_to_halt), current_cpu + 1); } -INLINE_PSIM psim_status +INLINE_PSIM\ +(psim_status) psim_get_status(psim *system) { return system->halt_status; } -cpu * +INLINE_PSIM\ +(cpu *) psim_cpu(psim *system, int cpu_nr) { @@ -508,7 +436,8 @@ psim_cpu(psim *system, } -const device * +INLINE_PSIM\ +(device *) psim_device(psim *system, const char *path) { @@ -517,43 +446,55 @@ psim_device(psim *system, -INLINE_PSIM void +INLINE_PSIM\ +(void) psim_init(psim *system) { int cpu_nr; /* scrub the monitor */ mon_init(system->monitor, system->nr_cpus); + os_emul_init(system->os_emulation, system->nr_cpus); + event_queue_init(system->events); /* scrub all the cpus */ for (cpu_nr = 0; cpu_nr < system->nr_cpus; cpu_nr++) cpu_init(system->processors[cpu_nr]); - /* init all the devices */ + /* init all the devices (which updates the cpus) */ device_tree_init(system->devices, system); + /* now sync each cpu against the initialized state of its registers */ + for (cpu_nr = 0; cpu_nr < system->nr_cpus; cpu_nr++) { + cpu_synchronize_context(system->processors[cpu_nr]); + cpu_page_tlb_invalidate_all(system->processors[cpu_nr]); + } + /* force loop to restart */ system->last_cpu = system->nr_cpus - 1; } -INLINE_PSIM void +INLINE_PSIM\ +(void) psim_stack(psim *system, char **argv, char **envp) { /* pass the stack device the argv/envp and let it work out what to do with it */ - const device *stack_device = device_tree_find_device(system->devices, - "/init/stack"); - unsigned_word stack_pointer; - psim_read_register(system, 0, &stack_pointer, "sp", cooked_transfer); - stack_device->callback->ioctl(stack_device, - system, - NULL, /*cpu*/ - 0, /*cia*/ - stack_pointer, - argv, - envp); + device *stack_device = device_tree_find_device(system->devices, + "/openprom/init/stack"); + if (stack_device != (device*)0) { + unsigned_word stack_pointer; + psim_read_register(system, 0, &stack_pointer, "sp", cooked_transfer); + device_ioctl(stack_device, + system, + NULL, /*cpu*/ + 0, /*cia*/ + stack_pointer, + argv, + envp); + } } @@ -566,14 +507,15 @@ psim_stack(psim *system, Consequently this function is written in multiple different ways */ -STATIC_INLINE_PSIM void +STATIC_INLINE_PSIM\ +(void) run_until_stop(psim *system, volatile int *keep_running) { jmp_buf halt; jmp_buf restart; - int cpu_nr; #if WITH_IDECODE_CACHE_SIZE + int cpu_nr; for (cpu_nr = 0; cpu_nr < system->nr_cpus; cpu_nr++) cpu_flush_icache(system->processors[cpu_nr]); #endif @@ -655,7 +597,8 @@ run_until_stop(psim *system, cia, cache_entry); - mon_event(mon_event_icache_miss, processor, cia); + if (WITH_MON != 0) + mon_event(mon_event_icache_miss, processor, cia); cache_entry->address = cia; cache_entry->semantic = semantic; cia = semantic(processor, cache_entry, cia); @@ -750,7 +693,8 @@ run_until_stop(psim *system, cia, cache_entry); - mon_event(mon_event_icache_miss, system->processors[current_cpu], cia); + if (WITH_MON != 0) + mon_event(mon_event_icache_miss, system->processors[current_cpu], cia); cache_entry->address = cia; cache_entry->semantic = semantic; cpu_set_program_counter(processor, @@ -771,20 +715,23 @@ run_until_stop(psim *system, /* SIMULATE INSTRUCTIONS, various different ways of achieving the same thing */ -INLINE_PSIM void +INLINE_PSIM\ +(void) psim_step(psim *system) { volatile int keep_running = 0; run_until_stop(system, &keep_running); } -INLINE_PSIM void +INLINE_PSIM\ +(void) psim_run(psim *system) { run_until_stop(system, NULL); } -INLINE_PSIM void +INLINE_PSIM\ +(void) psim_run_until_stop(psim *system, volatile int *keep_running) { @@ -795,7 +742,8 @@ psim_run_until_stop(psim *system, /* storage manipulation functions */ -INLINE_PSIM void +INLINE_PSIM\ +(void) psim_read_register(psim *system, int which_cpu, void *buf, @@ -884,7 +832,8 @@ psim_read_register(psim *system, -INLINE_PSIM void +INLINE_PSIM\ +(void) psim_write_register(psim *system, int which_cpu, const void *buf, @@ -980,7 +929,8 @@ psim_write_register(psim *system, -INLINE_PSIM unsigned +INLINE_PSIM\ +(unsigned) psim_read_memory(psim *system, int which_cpu, void *buffer, @@ -998,7 +948,8 @@ psim_read_memory(psim *system, } -INLINE_PSIM unsigned +INLINE_PSIM\ +(unsigned) psim_write_memory(psim *system, int which_cpu, const void *buffer, @@ -1017,7 +968,8 @@ psim_write_memory(psim *system, } -INLINE_PSIM void +INLINE_PSIM\ +(void) psim_print_info(psim *system, int verbose) { @@ -1025,4 +977,30 @@ psim_print_info(psim *system, } +/* Merge a device tree and a device file. */ + +INLINE_PSIM\ +(void) +psim_merge_device_file(device *root, + const char *file_name) +{ + FILE *description = fopen(file_name, "r"); + int line_nr = 0; + char device_path[1000]; + device *current = root; + while (fgets(device_path, sizeof(device_path), description)) { + /* check all of line was read */ + if (strchr(device_path, '\n') == NULL) { + fclose(description); + error("create_filed_device_tree() line %d to long: %s\n", + line_nr, device_path); + } + line_nr++; + /* parse this line */ + current = device_tree_add_parsed(current, "%s", device_path); + } + fclose(description); +} + + #endif /* _PSIM_C_ */ |