Commit | Line | Data |
---|---|---|
c906108c SS |
1 | /* run front end support for all the simulators. |
2 | Copyright (C) 1992, 93-96, 1997 Free Software Foundation, Inc. | |
3 | ||
4 | This program is free software; you can redistribute it and/or modify | |
5 | it under the terms of the GNU General Public License as published by | |
6 | the Free Software Foundation; either version 2, or (at your option) | |
7 | any later version. | |
8 | ||
9 | This program is distributed in the hope that it will be useful, | |
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | GNU General Public License for more details. | |
13 | ||
14 | You should have received a copy of the GNU General Public License along | |
15 | with this program; if not, write to the Free Software Foundation, Inc., | |
16 | 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | |
17 | ||
18 | /* Steve Chamberlain sac@cygnus.com, | |
19 | and others at Cygnus. */ | |
20 | ||
21 | #include "config.h" | |
22 | #include "tconfig.h" | |
23 | ||
24 | #include <signal.h> | |
25 | #include <stdio.h> | |
26 | #ifdef __STDC__ | |
27 | #include <stdarg.h> | |
28 | #else | |
29 | #include <varargs.h> | |
30 | #endif | |
31 | ||
32 | #ifdef HAVE_STDLIB_H | |
33 | #include <stdlib.h> | |
34 | #endif | |
35 | ||
36 | #ifdef HAVE_STRING_H | |
37 | #include <string.h> | |
38 | #else | |
39 | #ifdef HAVE_STRINGS_H | |
40 | #include <strings.h> | |
41 | #endif | |
42 | #endif | |
43 | ||
44 | #include "libiberty.h" | |
45 | #include "bfd.h" | |
46 | #include "callback.h" | |
47 | #include "remote-sim.h" | |
6d358e86 | 48 | #include "ansidecl.h" |
c906108c | 49 | |
c906108c SS |
50 | static void usage PARAMS ((void)); |
51 | extern int optind; | |
52 | extern char *optarg; | |
53 | ||
54 | extern host_callback default_callback; | |
55 | ||
56 | static char *myname; | |
57 | ||
c906108c SS |
58 | extern int getopt (); |
59 | ||
7a292a7a SS |
60 | #ifdef NEED_UI_LOOP_HOOK |
61 | /* Gdb foolery. This is only needed for gdb using a gui. */ | |
62 | int (*ui_loop_hook) PARAMS ((int signo)); | |
63 | #endif | |
64 | ||
c906108c SS |
65 | static SIM_DESC sd; |
66 | ||
67 | static RETSIGTYPE | |
6d358e86 | 68 | cntrl_c (int sig ATTRIBUTE_UNUSED) |
c906108c SS |
69 | { |
70 | if (! sim_stop (sd)) | |
71 | { | |
72 | fprintf (stderr, "Quit!\n"); | |
73 | exit (1); | |
74 | } | |
75 | } | |
76 | ||
77 | int | |
78 | main (ac, av) | |
79 | int ac; | |
80 | char **av; | |
81 | { | |
82 | RETSIGTYPE (*prev_sigint) (); | |
83 | bfd *abfd; | |
84 | int i; | |
85 | int verbose = 0; | |
86 | int trace = 0; | |
baa7ae6f AC |
87 | #ifdef SIM_HAVE_ENVIRONMENT |
88 | int operating_p = 0; | |
89 | #endif | |
c906108c SS |
90 | char *name; |
91 | static char *no_args[4]; | |
92 | char **sim_argv = &no_args[0]; | |
93 | char **prog_args; | |
94 | enum sim_stop reason; | |
95 | int sigrc; | |
96 | ||
97 | myname = av[0] + strlen (av[0]); | |
98 | while (myname > av[0] && myname[-1] != '/') | |
99 | --myname; | |
100 | ||
101 | /* The first element of sim_open's argv is the program name. */ | |
102 | no_args[0] = av[0]; | |
103 | #ifdef SIM_HAVE_BIENDIAN | |
104 | no_args[1] = "-E"; | |
105 | no_args[2] = "set-later"; | |
106 | #endif | |
107 | ||
108 | /* FIXME: This is currently being migrated into sim_open. | |
109 | Simulators that use functions such as sim_size() still require | |
110 | this. */ | |
111 | default_callback.init (&default_callback); | |
112 | sim_set_callbacks (&default_callback); | |
113 | ||
114 | /* FIXME: This is currently being rewritten to have each simulator | |
115 | do all argv processing. */ | |
116 | ||
117 | #ifdef SIM_H8300 /* FIXME: quick hack */ | |
baa7ae6f | 118 | while ((i = getopt (ac, av, "a:c:m:op:s:htv")) != EOF) |
c906108c | 119 | #else |
baa7ae6f | 120 | while ((i = getopt (ac, av, "a:c:m:op:s:tv")) != EOF) |
c906108c SS |
121 | #endif |
122 | switch (i) | |
123 | { | |
124 | case 'a': | |
125 | /* FIXME: Temporary hack. */ | |
126 | { | |
127 | int len = strlen (av[0]) + strlen (optarg); | |
128 | char *argbuf = (char *) alloca (len + 2 + 50); | |
129 | sprintf (argbuf, "%s %s", av[0], optarg); | |
130 | #ifdef SIM_HAVE_BIENDIAN | |
131 | /* The desired endianness must be passed to sim_open. | |
132 | The value for "set-later" is set when we know what it is. | |
133 | -E support isn't yet part of the published interface. */ | |
134 | strcat (argbuf, " -E set-later"); | |
135 | #endif | |
136 | sim_argv = buildargv (argbuf); | |
137 | } | |
138 | break; | |
139 | #ifdef SIM_HAVE_SIMCACHE | |
140 | case 'c': | |
141 | sim_set_simcache_size (atoi (optarg)); | |
142 | break; | |
143 | #endif | |
144 | case 'm': | |
145 | /* FIXME: Rename to sim_set_mem_size. */ | |
146 | sim_size (atoi (optarg)); | |
147 | break; | |
baa7ae6f AC |
148 | #ifdef SIM_HAVE_ENVIRONMENT |
149 | case 'o': | |
150 | /* Operating enironment where any signals are delivered to the | |
151 | target. */ | |
152 | operating_p = 1; | |
153 | break; | |
154 | #endif SIM_HAVE_ENVIRONMENT | |
c906108c SS |
155 | #ifdef SIM_HAVE_PROFILE |
156 | case 'p': | |
157 | sim_set_profile (atoi (optarg)); | |
158 | break; | |
159 | case 's': | |
160 | sim_set_profile_size (atoi (optarg)); | |
161 | break; | |
162 | #endif | |
163 | case 't': | |
164 | trace = 1; | |
c906108c SS |
165 | break; |
166 | case 'v': | |
167 | /* Things that are printed with -v are the kinds of things that | |
168 | gcc -v prints. This is not meant to include detailed tracing | |
169 | or debugging information, just summaries. */ | |
170 | verbose = 1; | |
171 | /* sim_set_verbose (1); */ | |
172 | break; | |
173 | /* FIXME: Quick hack, to be replaced by more general facility. */ | |
174 | #ifdef SIM_H8300 | |
175 | case 'h': | |
176 | set_h8300h (1); | |
177 | break; | |
178 | #endif | |
179 | default: | |
180 | usage (); | |
181 | } | |
182 | ||
183 | ac -= optind; | |
184 | av += optind; | |
185 | if (ac <= 0) | |
186 | usage (); | |
187 | ||
188 | name = *av; | |
189 | prog_args = av; | |
190 | ||
191 | if (verbose) | |
192 | { | |
193 | printf ("%s %s\n", myname, name); | |
194 | } | |
195 | ||
196 | abfd = bfd_openr (name, 0); | |
197 | if (!abfd) | |
198 | { | |
199 | fprintf (stderr, "%s: can't open %s: %s\n", | |
200 | myname, name, bfd_errmsg (bfd_get_error ())); | |
201 | exit (1); | |
202 | } | |
203 | ||
204 | if (!bfd_check_format (abfd, bfd_object)) | |
205 | { | |
206 | fprintf (stderr, "%s: can't load %s: %s\n", | |
207 | myname, name, bfd_errmsg (bfd_get_error ())); | |
208 | exit (1); | |
209 | } | |
210 | ||
211 | #ifdef SIM_HAVE_BIENDIAN | |
212 | /* The endianness must be passed to sim_open because one may wish to | |
213 | examine/set registers before calling sim_load [which is the other | |
214 | place where one can determine endianness]. We previously passed the | |
215 | endianness via global `target_byte_order' but that's not a clean | |
216 | interface. */ | |
217 | for (i = 1; sim_argv[i + 1] != NULL; ++i) | |
218 | continue; | |
219 | if (bfd_big_endian (abfd)) | |
220 | sim_argv[i] = "big"; | |
221 | else | |
222 | sim_argv[i] = "little"; | |
223 | #endif | |
224 | ||
225 | /* Ensure that any run-time initialisation that needs to be | |
226 | performed by the simulator can occur. */ | |
227 | sd = sim_open (SIM_OPEN_STANDALONE, &default_callback, abfd, sim_argv); | |
228 | if (sd == 0) | |
229 | exit (1); | |
230 | ||
231 | if (sim_load (sd, name, abfd, 0) == SIM_RC_FAIL) | |
232 | exit (1); | |
233 | ||
234 | if (sim_create_inferior (sd, abfd, prog_args, NULL) == SIM_RC_FAIL) | |
235 | exit (1); | |
236 | ||
baa7ae6f AC |
237 | #ifdef SIM_HAVE_ENVIRONMENT |
238 | /* NOTE: An old simulator supporting the operating environment MUST | |
239 | provide sim_set_trace() and not sim_trace(). That way | |
240 | sim_stop_reason() can be used to determine any stop reason. */ | |
241 | if (trace) | |
242 | sim_set_trace (); | |
781c552e | 243 | sigrc = 0; |
baa7ae6f AC |
244 | do |
245 | { | |
246 | prev_sigint = signal (SIGINT, cntrl_c); | |
247 | sim_resume (sd, 0, sigrc); | |
248 | signal (SIGINT, prev_sigint); | |
249 | sim_stop_reason (sd, &reason, &sigrc); | |
250 | } | |
251 | while (operating_p && reason == sim_stopped && sigrc != SIGINT); | |
252 | #else | |
c906108c SS |
253 | if (trace) |
254 | { | |
255 | int done = 0; | |
7fc5b5ad | 256 | prev_sigint = signal (SIGINT, cntrl_c); |
c906108c SS |
257 | while (!done) |
258 | { | |
259 | done = sim_trace (sd); | |
260 | } | |
7fc5b5ad | 261 | signal (SIGINT, prev_sigint); |
baa7ae6f | 262 | sim_stop_reason (sd, &reason, &sigrc); |
c906108c SS |
263 | } |
264 | else | |
265 | { | |
baa7ae6f | 266 | prev_sigint = signal (SIGINT, cntrl_c); |
781c552e | 267 | sigrc = 0; |
baa7ae6f AC |
268 | sim_resume (sd, 0, sigrc); |
269 | signal (SIGINT, prev_sigint); | |
270 | sim_stop_reason (sd, &reason, &sigrc); | |
c906108c | 271 | } |
baa7ae6f | 272 | #endif |
c906108c SS |
273 | |
274 | if (verbose) | |
275 | sim_info (sd, 0); | |
c906108c SS |
276 | sim_close (sd, 0); |
277 | ||
278 | /* If reason is sim_exited, then sigrc holds the exit code which we want | |
279 | to return. If reason is sim_stopped or sim_signalled, then sigrc holds | |
280 | the signal that the simulator received; we want to return that to | |
281 | indicate failure. */ | |
282 | ||
283 | #ifdef SIM_H8300 /* FIXME: Ugh. grep for SLEEP in compile.c */ | |
284 | if (sigrc == SIGILL) | |
285 | abort (); | |
286 | sigrc = 0; | |
287 | #else | |
288 | /* Why did we stop? */ | |
289 | switch (reason) | |
290 | { | |
291 | case sim_signalled: | |
292 | case sim_stopped: | |
293 | if (sigrc != 0) | |
294 | fprintf (stderr, "program stopped with signal %d.\n", sigrc); | |
295 | break; | |
296 | ||
297 | case sim_exited: | |
298 | break; | |
299 | ||
300 | case sim_running: | |
301 | case sim_polling: /* these indicate a serious problem */ | |
302 | abort (); | |
303 | break; | |
304 | ||
305 | } | |
306 | #endif | |
307 | ||
308 | return sigrc; | |
309 | } | |
310 | ||
311 | static void | |
312 | usage () | |
313 | { | |
314 | fprintf (stderr, "Usage: %s [options] program [program args]\n", myname); | |
315 | fprintf (stderr, "Options:\n"); | |
316 | fprintf (stderr, "-a args Pass `args' to simulator.\n"); | |
317 | #ifdef SIM_HAVE_SIMCACHE | |
318 | fprintf (stderr, "-c size Set simulator cache size to `size'.\n"); | |
319 | #endif | |
320 | #ifdef SIM_H8300 | |
321 | fprintf (stderr, "-h Executable is for h8/300h or h8/300s.\n"); | |
322 | #endif | |
323 | fprintf (stderr, "-m size Set memory size of simulator, in bytes.\n"); | |
baa7ae6f AC |
324 | #ifdef SIM_HAVE_ENVIRONMENT |
325 | fprintf (stderr, "-o Select operating (kernel) environment.\n"); | |
326 | #endif | |
c906108c SS |
327 | #ifdef SIM_HAVE_PROFILE |
328 | fprintf (stderr, "-p freq Set profiling frequency.\n"); | |
329 | fprintf (stderr, "-s size Set profiling size.\n"); | |
330 | #endif | |
331 | fprintf (stderr, "-t Perform instruction tracing.\n"); | |
332 | fprintf (stderr, " Note: Very few simulators support tracing.\n"); | |
333 | fprintf (stderr, "-v Verbose output.\n"); | |
334 | fprintf (stderr, "\n"); | |
335 | fprintf (stderr, "program args Arguments to pass to simulated program.\n"); | |
336 | fprintf (stderr, " Note: Very few simulators support this.\n"); | |
337 | exit (1); | |
338 | } |