diff options
Diffstat (limited to 'sim/ppc/os_emul.c')
-rw-r--r-- | sim/ppc/os_emul.c | 146 |
1 files changed, 146 insertions, 0 deletions
diff --git a/sim/ppc/os_emul.c b/sim/ppc/os_emul.c new file mode 100644 index 00000000000..dc60c8f6641 --- /dev/null +++ b/sim/ppc/os_emul.c @@ -0,0 +1,146 @@ +/* This file is part of the program psim. + + 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 + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + */ + + +#ifndef _OS_EMUL_C_ +#define _OS_EMUL_C_ + +#include "cpu.h" +#include "idecode.h" +#include "os_emul.h" + +#include "emul_generic.h" +#include "emul_netbsd.h" +#include "emul_unix.h" +#include "emul_chirp.h" +#include "emul_bugapi.h" + +static const os_emul *(os_emulations[]) = { + &emul_chirp, + &emul_bugapi, + &emul_netbsd, + &emul_solaris, + &emul_linux, + 0 +}; + + +INLINE_OS_EMUL\ +(os_emul *) +os_emul_create(const char *file_name, + device *root) +{ + const char *emulation_name = NULL; + bfd *image; + os_emul *chosen_emulation = NULL; + + bfd_init(); /* would never hurt */ + + /* open the file */ + image = bfd_openr(file_name, NULL); + if (image == NULL) { + bfd_perror(file_name); + error("nothing loaded\n"); + } + + /* check it is an executable */ + if (!bfd_check_format(image, bfd_object)) { + TRACE(trace_tbd, + ("FIXME - should check more than just bfd_check_format\n")); + TRACE(trace_os_emul, + ("%s not an executable, assumeing a device file\n", file_name)); + bfd_close(image); + image = NULL; + } + + /* if a device file, load that before trying the emulations on */ + if (image == NULL) { + psim_merge_device_file(root, file_name); + } + + /* see if the device tree already specifies the required emulation */ + if (tree_find_property(root, "/openprom/options/os-emul") != NULL) + emulation_name = + tree_find_string_property(root, "/openprom/options/os-emul"); + else + emulation_name = NULL; + + /* go through each emulation to see if they reconize it. FIXME - + should have some sort of imported table from a separate file */ + { + os_emul_data *emul_data; + const os_emul **possible_emulation; + chosen_emulation = NULL; + for (possible_emulation = os_emulations, emul_data = NULL; + *possible_emulation != NULL && emul_data == NULL; + possible_emulation++) { + emul_data = (*possible_emulation)->create(root, + image, + emulation_name); + if (emul_data != NULL) { + chosen_emulation = ZALLOC(os_emul); + *chosen_emulation = **possible_emulation; + chosen_emulation->data = emul_data; + } + } + } + + /* clean up */ + if (image != NULL) + bfd_close(image); + return chosen_emulation; +} + +INLINE_OS_EMUL\ +(void) +os_emul_init(os_emul *emulation, + int nr_cpus) +{ + if (emulation != (os_emul*)0) + emulation->init(emulation->data, nr_cpus); +} + +INLINE_OS_EMUL\ +(void) +os_emul_system_call(cpu *processor, + unsigned_word cia) +{ + os_emul *emulation = cpu_os_emulation(processor); + if (emulation != (os_emul*)0 && emulation->system_call != 0) + emulation->system_call(processor, cia, emulation->data); + else + error("System call emulation not available\n"); +} + +INLINE_OS_EMUL\ +(int) +os_emul_instruction_call(cpu *processor, + unsigned_word cia, + unsigned_word ra) +{ + os_emul *emulation = cpu_os_emulation(processor); + if (emulation != (os_emul*)0 && emulation->instruction_call != 0) + return emulation->instruction_call(processor, cia, ra, emulation->data); + else + return 0; +} + + +#endif /* _OS_EMUL_C_ */ |