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