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 61extern char **environ; 62 63static psim *simulation = NULL; 64 65 66void 67sim_io_poll_quit (void) 68{ 69 /* nothing to do */ 70} 71 72void 73sim_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 81void 82error (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 97int 98sim_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 120int 121sim_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 143int 144sim_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 214void 215sim_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 229void 230sim_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 246void * 247zalloc(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 256void 257zfree(void *chunk) 258{ 259 free(chunk); 260} 261 262/* When a CNTRL-C occures, queue an event to shut down the simulation */ 263 264static RETSIGTYPE 265cntrl_c(int sig) 266{ 267 psim_stop (simulation); 268} 269 270 271int 272main(int argc, char **argv) 273{ 274 const char *name_of_file; 275 char *arg_; 276 psim_status status; 277 device *root = psim_tree(); 278 279 /* parse the arguments */ 280 argv = psim_options(root, argv + 1); 281 if (argv[0] == NULL) { 282 if (ppc_trace[trace_opts]) { 283 print_options (); 284 return 0; 285 } else { 286 psim_usage(0); 287 } 288 } 289 name_of_file = argv[0]; 290 291 if (ppc_trace[trace_opts]) 292 print_options (); 293 294 /* create the simulator */ 295 simulation = psim_create(name_of_file, root); 296 297 /* fudge the environment so that _=prog-name */ 298 arg_ = (char*)zalloc(strlen(argv[0]) + strlen("_=") + 1); 299 strcpy(arg_, "_="); 300 strcat(arg_, argv[0]); 301 putenv(arg_); 302 303 /* initialize it */ 304 psim_init(simulation); 305 psim_stack(simulation, argv, environ); 306 307 { 308 RETSIGTYPE (*prev) (); 309 prev = signal(SIGINT, cntrl_c); 310 psim_run(simulation); 311 signal(SIGINT, prev); 312 } 313 314 /* any final clean up */ 315 if (ppc_trace[trace_print_info]) 316 psim_print_info (simulation, ppc_trace[trace_print_info]); 317 318 /* why did we stop */ 319 status = psim_get_status(simulation); 320 switch (status.reason) { 321 case was_continuing: 322 error("psim: continuing while stoped!\n"); 323 return 0; 324 case was_trap: 325 error("psim: no trap insn\n"); 326 return 0; 327 case was_exited: 328 return status.signal; 329 case was_signalled: 330 printf ("%s: Caught signal %d at address 0x%lx\n", 331 name_of_file, (int)status.signal, 332 (long)status.program_counter); 333 return status.signal; 334 default: 335 error("unknown halt condition\n"); 336 return 0; 337 } 338} 339