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