1/*  This file is part of the program psim.
2
3    Copyright (C) 1994-1996, Andrew Cagney <cagney@highland.com.au>
4
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.
9
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.
14
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.
18
19    */
20
21
22#ifndef _OS_EMUL_C_
23#define _OS_EMUL_C_
24
25#include "cpu.h"
26#include "idecode.h"
27#include "os_emul.h"
28
29#include "emul_generic.h"
30#include "emul_netbsd.h"
31#include "emul_unix.h"
32#include "emul_chirp.h"
33#include "emul_bugapi.h"
34
35static const os_emul *(os_emulations[]) = {
36  &emul_chirp,
37  &emul_bugapi,
38  &emul_netbsd,
39  &emul_solaris,
40  &emul_linux,
41  0
42};
43
44
45INLINE_OS_EMUL\
46(os_emul *)
47os_emul_create(const char *file_name,
48	       device *root)
49{
50  const char *emulation_name = NULL;
51  bfd *image;
52  os_emul *chosen_emulation = NULL;
53
54  bfd_init(); /* would never hurt */
55
56  /* open the file */
57  image = bfd_openr(file_name, NULL);
58  if (image == NULL) {
59    bfd_perror(file_name);
60    error("nothing loaded\n");
61  }
62
63  /* check it is an executable */
64  if (!bfd_check_format(image, bfd_object)) {
65    TRACE(trace_tbd,
66	  ("FIXME - should check more than just bfd_check_format\n"));
67    TRACE(trace_os_emul,
68	  ("%s not an executable, assumeing a device file\n", file_name));
69    bfd_close(image);
70    image = NULL;
71  }
72
73  /* if a device file, load that before trying the emulations on */
74  if (image == NULL) {
75    psim_merge_device_file(root, file_name);
76  }
77
78  /* see if the device tree already specifies the required emulation */
79  if (tree_find_property(root, "/openprom/options/os-emul") != NULL)
80    emulation_name =
81      tree_find_string_property(root, "/openprom/options/os-emul");
82  else
83    emulation_name = NULL;
84
85  /* go through each emulation to see if they reconize it. FIXME -
86     should have some sort of imported table from a separate file */
87  {
88    os_emul_data *emul_data;
89    const os_emul **possible_emulation;
90    chosen_emulation = NULL;
91    for (possible_emulation = os_emulations, emul_data = NULL;
92	 *possible_emulation != NULL && emul_data == NULL;
93	 possible_emulation++) {
94      emul_data = (*possible_emulation)->create(root,
95						image,
96						emulation_name);
97      if (emul_data != NULL) {
98	chosen_emulation = ZALLOC(os_emul);
99	*chosen_emulation = **possible_emulation;
100	chosen_emulation->data = emul_data;
101      }
102    }
103  }
104
105  /* clean up */
106  if (image != NULL)
107    bfd_close(image);
108  return chosen_emulation;
109}
110
111INLINE_OS_EMUL\
112(void)
113os_emul_init(os_emul *emulation,
114	     int nr_cpus)
115{
116  if (emulation != (os_emul*)0)
117    emulation->init(emulation->data, nr_cpus);
118}
119
120INLINE_OS_EMUL\
121(void)
122os_emul_system_call(cpu *processor,
123		    unsigned_word cia)
124{
125  os_emul *emulation = cpu_os_emulation(processor);
126  if (emulation != (os_emul*)0 && emulation->system_call != 0)
127    emulation->system_call(processor, cia, emulation->data);
128  else
129    error("System call emulation not available\n");
130}
131
132INLINE_OS_EMUL\
133(int)
134os_emul_instruction_call(cpu *processor,
135			 unsigned_word cia,
136			 unsigned_word ra)
137{
138  os_emul *emulation = cpu_os_emulation(processor);
139  if (emulation != (os_emul*)0 && emulation->instruction_call != 0)
140    return emulation->instruction_call(processor, cia, ra, emulation->data);
141  else
142    return 0;
143}
144
145
146#endif /* _OS_EMUL_C_ */
147