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 } 333