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