1 /* main.c --- main function for stand-alone RX simulator. 2 3 Copyright (C) 2005, 2007, 2008, 2009, 2010, 2011 4 Free Software Foundation, Inc. 5 Contributed by Red Hat, Inc. 6 7 This file is part of the GNU simulators. 8 9 This program is free software; you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation; either version 3 of the License, or 12 (at your option) any later version. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 21 22 23 #include "config.h" 24 #include <stdio.h> 25 #include <string.h> 26 #ifdef HAVE_STDLIB_H 27 #include <stdlib.h> 28 #endif 29 #ifdef HAVE_UNISTD_H 30 #include <unistd.h> 31 #endif 32 #include <assert.h> 33 #include <setjmp.h> 34 #include <signal.h> 35 #ifdef HAVE_GETOPT_H 36 #include <getopt.h> 37 #endif 38 39 #include "bfd.h" 40 41 #include "cpu.h" 42 #include "mem.h" 43 #include "misc.h" 44 #include "load.h" 45 #include "trace.h" 46 #include "err.h" 47 48 static int disassemble = 0; 49 50 /* This must be higher than any other option index. */ 51 #define OPT_ACT 400 52 53 #define ACT(E,A) (OPT_ACT + SIM_ERR_##E * SIM_ERRACTION_NUM_ACTIONS + SIM_ERRACTION_##A) 54 55 static struct option sim_options[] = 56 { 57 { "end-sim-args", 0, NULL, 'E' }, 58 { "exit-null-deref", 0, NULL, ACT(NULL_POINTER_DEREFERENCE,EXIT) }, 59 { "warn-null-deref", 0, NULL, ACT(NULL_POINTER_DEREFERENCE,WARN) }, 60 { "ignore-null-deref", 0, NULL, ACT(NULL_POINTER_DEREFERENCE,IGNORE) }, 61 { "exit-unwritten-pages", 0, NULL, ACT(READ_UNWRITTEN_PAGES,EXIT) }, 62 { "warn-unwritten-pages", 0, NULL, ACT(READ_UNWRITTEN_PAGES,WARN) }, 63 { "ignore-unwritten-pages", 0, NULL, ACT(READ_UNWRITTEN_PAGES,IGNORE) }, 64 { "exit-unwritten-bytes", 0, NULL, ACT(READ_UNWRITTEN_BYTES,EXIT) }, 65 { "warn-unwritten-bytes", 0, NULL, ACT(READ_UNWRITTEN_BYTES,WARN) }, 66 { "ignore-unwritten-bytes", 0, NULL, ACT(READ_UNWRITTEN_BYTES,IGNORE) }, 67 { "exit-corrupt-stack", 0, NULL, ACT(CORRUPT_STACK,EXIT) }, 68 { "warn-corrupt-stack", 0, NULL, ACT(CORRUPT_STACK,WARN) }, 69 { "ignore-corrupt-stack", 0, NULL, ACT(CORRUPT_STACK,IGNORE) }, 70 { 0, 0, 0, 0 } 71 }; 72 73 static void 74 done (int exit_code) 75 { 76 if (verbose) 77 { 78 stack_heap_stats (); 79 mem_usage_stats (); 80 /* Only use comma separated numbers when being very verbose. 81 Comma separated numbers are hard to parse in awk scripts. */ 82 if (verbose > 1) 83 printf ("insns: %14s\n", comma (rx_cycles)); 84 else 85 printf ("insns: %u\n", rx_cycles); 86 87 pipeline_stats (); 88 } 89 exit (exit_code); 90 } 91 92 int 93 main (int argc, char **argv) 94 { 95 int o; 96 int save_trace; 97 bfd *prog; 98 int rc; 99 100 /* By default, we exit when an execution error occurs. */ 101 execution_error_init_standalone (); 102 103 while ((o = getopt_long (argc, argv, "tvdeEwi", sim_options, NULL)) != -1) 104 { 105 if (o == 'E') 106 /* Stop processing the command line. This is so that any remaining 107 words on the command line that look like arguments will be passed 108 on to the program being simulated. */ 109 break; 110 111 if (o >= OPT_ACT) 112 { 113 int e, a; 114 115 o -= OPT_ACT; 116 e = o / SIM_ERRACTION_NUM_ACTIONS; 117 a = o % SIM_ERRACTION_NUM_ACTIONS; 118 execution_error_set_action (e, a); 119 } 120 else switch (o) 121 { 122 case 't': 123 trace++; 124 break; 125 case 'v': 126 verbose++; 127 break; 128 case 'd': 129 disassemble++; 130 break; 131 case 'e': 132 execution_error_init_standalone (); 133 break; 134 case 'w': 135 execution_error_warn_all (); 136 break; 137 case 'i': 138 execution_error_ignore_all (); 139 break; 140 case '?': 141 { 142 int i; 143 fprintf (stderr, 144 "usage: run [options] program [arguments]\n"); 145 fprintf (stderr, 146 "\t-v\t- increase verbosity.\n" 147 "\t-t\t- trace.\n" 148 "\t-d\t- disassemble.\n" 149 "\t-E\t- stop processing sim args\n" 150 "\t-e\t- exit on all execution errors.\n" 151 "\t-w\t- warn (do not exit) on all execution errors.\n" 152 "\t-i\t- ignore all execution errors.\n"); 153 for (i=0; sim_options[i].name; i++) 154 fprintf (stderr, "\t--%s\n", sim_options[i].name); 155 exit (1); 156 } 157 } 158 } 159 160 prog = bfd_openr (argv[optind], 0); 161 if (!prog) 162 { 163 fprintf (stderr, "Can't read %s\n", argv[optind]); 164 exit (1); 165 } 166 167 if (!bfd_check_format (prog, bfd_object)) 168 { 169 fprintf (stderr, "%s not a rx program\n", argv[optind]); 170 exit (1); 171 } 172 173 init_regs (); 174 175 rx_in_gdb = 0; 176 save_trace = trace; 177 trace = 0; 178 rx_load (prog); 179 trace = save_trace; 180 181 sim_disasm_init (prog); 182 183 enable_counting = verbose; 184 185 rc = setjmp (decode_jmp_buf); 186 187 if (rc == 0) 188 { 189 if (!trace && !disassemble) 190 { 191 /* This will longjmp to the above if an exception 192 happens. */ 193 for (;;) 194 decode_opcode (); 195 } 196 else 197 while (1) 198 { 199 200 if (trace) 201 printf ("\n"); 202 203 if (disassemble) 204 { 205 enable_counting = 0; 206 sim_disasm_one (); 207 enable_counting = verbose; 208 } 209 210 rc = decode_opcode (); 211 212 if (trace) 213 trace_register_changes (); 214 } 215 } 216 217 if (RX_HIT_BREAK (rc)) 218 done (1); 219 else if (RX_EXITED (rc)) 220 done (RX_EXIT_STATUS (rc)); 221 else if (RX_STOPPED (rc)) 222 { 223 if (verbose) 224 printf("Stopped on signal %d\n", RX_STOP_SIG (rc)); 225 exit(1); 226 } 227 done (0); 228 exit (0); 229 } 230