7cb50368a91eae51a62f3f407de36f3720084cbb
[external/binutils.git] / sim / ppc / main.c
1 /*  This file is part of the program psim.
2
3     Copyright (C) 1994-1997, 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 #include <stdarg.h>
23 #include <stdio.h>
24 #include <fcntl.h>
25
26 #include <signal.h>
27
28 #include "psim.h"
29 #include "options.h"
30 #include "device.h" /* FIXME: psim should provide the interface */
31 #include "events.h" /* FIXME: psim should provide the interface */
32
33 #include "bfd.h"
34 #include "gdb/callback.h"
35 #include "gdb/remote-sim.h"
36
37 #ifdef HAVE_STDLIB_H
38 #include <stdlib.h>
39 #endif
40
41 #ifdef HAVE_UNISTD_H
42 #include <unistd.h>
43 #endif
44
45 #ifdef HAVE_STRING_H
46 #include <string.h>
47 #else
48 #ifdef HAVE_STRINGS_H
49 #include <strings.h>
50 #endif
51 #endif
52
53 #include <errno.h>
54
55 #if !defined(O_NDELAY) || !defined(F_GETFL) || !defined(F_SETFL)
56 #undef WITH_STDIO
57 #define WITH_STDIO DO_USE_STDIO
58 #endif
59
60
61 extern char **environ;
62
63 static psim *simulation = NULL;
64
65
66 void
67 sim_io_poll_quit (void)
68 {
69   /* nothing to do */
70 }
71
72 void
73 sim_io_printf_filtered(const char *msg, ...)
74 {
75   va_list ap;
76   va_start(ap, msg);
77   vprintf(msg, ap);
78   va_end(ap);
79 }
80
81 void
82 error (const char *msg, ...)
83 {
84   va_list ap;
85   va_start(ap, msg);
86   vprintf(msg, ap);
87   printf("\n");
88   va_end(ap);
89
90   /* any final clean up */
91   if (ppc_trace[trace_print_info] && simulation != NULL)
92     psim_print_info (simulation, ppc_trace[trace_print_info]);
93
94   exit (1);
95 }
96
97 int
98 sim_io_write_stdout(const char *buf,
99                     int sizeof_buf)
100 {
101   switch (CURRENT_STDIO) {
102   case DO_USE_STDIO:
103     {
104       int i;
105       for (i = 0; i < sizeof_buf; i++) {
106         putchar(buf[i]);
107       }
108       return i;
109     }
110     break;
111   case DONT_USE_STDIO:
112     return write(1, buf, sizeof_buf);
113     break;
114   default:
115     error("sim_io_write_stdout: invalid switch\n");
116   }
117   return 0;
118 }
119
120 int
121 sim_io_write_stderr(const char *buf,
122                     int sizeof_buf)
123 {
124   switch (CURRENT_STDIO) {
125   case DO_USE_STDIO:
126     {
127       int i;
128       for (i = 0; i < sizeof_buf; i++) {
129         fputc(buf[i], stderr);
130       }
131       return i;
132     }
133     break;
134   case DONT_USE_STDIO:
135     return write(2, buf, sizeof_buf);
136     break;
137   default:
138     error("sim_io_write_stdout: invalid switch\n");
139   }
140   return 0;
141 }
142
143 int
144 sim_io_read_stdin(char *buf,
145                   int sizeof_buf)
146 {
147   switch (CURRENT_STDIO) {
148   case DO_USE_STDIO:
149     if (sizeof_buf > 1) {
150       if (fgets(buf, sizeof_buf, stdin) != NULL)
151         return strlen(buf);
152     }
153     else if (sizeof_buf == 1) {
154       char b[2];
155       if (fgets(b, sizeof(b), stdin) != NULL) {
156         memcpy(buf, b, strlen(b));
157         return strlen(b);
158       }
159     }
160     else if (sizeof_buf == 0)
161       return 0;
162     return sim_io_eof;
163     break;
164   case DONT_USE_STDIO:
165 #if defined(O_NDELAY) && defined(F_GETFL) && defined(F_SETFL)
166     {
167       /* check for input */
168       int flags;
169       int status;
170       int nr_read;
171       int result;
172       /* get the old status */
173       flags = fcntl(0, F_GETFL, 0);
174       if (flags == -1) {
175         perror("sim_io_read_stdin");
176         return sim_io_eof;
177       }
178       /* temp, disable blocking IO */
179       status = fcntl(0, F_SETFL, flags | O_NDELAY);
180       if (status == -1) {
181         perror("sim_io_read_stdin");
182         return sim_io_eof;
183       }
184       /* try for input */
185       nr_read = read(0, buf, sizeof_buf);
186       if (nr_read > 0
187           || (nr_read == 0 && sizeof_buf == 0))
188         result = nr_read;
189       else if (nr_read == 0)
190         result = sim_io_eof;
191       else { /* nr_read < 0 */
192         if (errno == EAGAIN)
193           result = sim_io_not_ready;
194         else 
195           result = sim_io_eof;
196       }
197       /* return to regular vewing */
198       status = fcntl(0, F_SETFL, flags);
199       if (status == -1) {
200         perror("sim_io_read_stdin");
201         return sim_io_eof;
202       }
203       return result;
204     }
205     break;
206 #endif
207   default:
208     error("sim_io_read_stdin: invalid switch\n");
209     break;
210   }
211   return 0;
212 }
213
214 void
215 sim_io_flush_stdoutput(void)
216 {
217   switch (CURRENT_STDIO) {
218   case DO_USE_STDIO:
219     fflush (stdout);
220     break;
221   case DONT_USE_STDIO:
222     break;
223   default:
224     error("sim_io_flush_stdoutput: invalid switch\n");
225     break;
226   }
227 }
228
229 void
230 sim_io_error (SIM_DESC sd, const char *msg, ...)
231 {
232   va_list ap;
233   va_start(ap, msg);
234   vprintf(msg, ap);
235   printf("\n");
236   va_end(ap);
237
238   /* any final clean up */
239   if (ppc_trace[trace_print_info] && simulation != NULL)
240     psim_print_info (simulation, ppc_trace[trace_print_info]);
241
242   exit (1);
243 }
244
245
246 void *
247 zalloc(long size)
248 {
249   void *memory = malloc(size);
250   if (memory == NULL)
251     error("zalloc failed\n");
252   memset(memory, 0, size);
253   return memory;
254 }
255
256 /* When a CNTRL-C occures, queue an event to shut down the simulation */
257
258 static RETSIGTYPE
259 cntrl_c(int sig)
260 {
261   psim_stop (simulation);
262 }
263
264
265 int
266 main(int argc, char **argv)
267 {
268   const char *name_of_file;
269   char *arg_;
270   psim_status status;
271   device *root = psim_tree();
272
273   /* parse the arguments */
274   argv = psim_options(root, argv + 1);
275   if (argv[0] == NULL) {
276     if (ppc_trace[trace_opts]) {
277       print_options ();
278       return 0;
279     } else {
280       psim_usage(0, 0);
281     }
282   }
283   name_of_file = argv[0];
284
285   if (ppc_trace[trace_opts])
286     print_options ();
287
288   /* create the simulator */
289   simulation = psim_create(name_of_file, root);
290
291   /* fudge the environment so that _=prog-name */
292   arg_ = (char*)zalloc(strlen(argv[0]) + strlen("_=") + 1);
293   strcpy(arg_, "_=");
294   strcat(arg_, argv[0]);
295   putenv(arg_);
296
297   /* initialize it */
298   psim_init(simulation);
299   psim_stack(simulation, argv, environ);
300
301   {
302     RETSIGTYPE (*prev) ();
303     prev = signal(SIGINT, cntrl_c);
304     psim_run(simulation);
305     signal(SIGINT, prev);
306   }
307
308   /* any final clean up */
309   if (ppc_trace[trace_print_info])
310     psim_print_info (simulation, ppc_trace[trace_print_info]);
311
312   /* why did we stop */
313   status = psim_get_status(simulation);
314   switch (status.reason) {
315   case was_continuing:
316     error("psim: continuing while stopped!\n");
317     return 0;
318   case was_trap:
319     error("psim: no trap insn\n");
320     return 0;
321   case was_exited:
322     return status.signal;
323   case was_signalled:
324     printf ("%s: Caught signal %d at address 0x%lx\n",
325             name_of_file, (int)status.signal,
326             (long)status.program_counter);
327     return status.signal;
328   default:
329     error("unknown halt condition\n");
330     return 0;
331   }
332 }