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 
35 static 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 
45 INLINE_OS_EMUL\
46 (os_emul *)
os_emul_create(const char * file_name,device * root)47 os_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 
111 INLINE_OS_EMUL\
112 (void)
os_emul_init(os_emul * emulation,int nr_cpus)113 os_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 
120 INLINE_OS_EMUL\
121 (void)
os_emul_system_call(cpu * processor,unsigned_word cia)122 os_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 
132 INLINE_OS_EMUL\
133 (int)
os_emul_instruction_call(cpu * processor,unsigned_word cia,unsigned_word ra)134 os_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