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