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