fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
1/*****************************************************************************
2 * pce *
3 *****************************************************************************/
4
5/*****************************************************************************
6 * File name: src/arch/simarm/main.c *
7 * Created: 2004-11-04 by Hampa Hug <hampa@hampa.ch> *
8 * Copyright: (C) 2004-2022 Hampa Hug <hampa@hampa.ch> *
9 * Copyright: (C) 2004-2006 Lukas Ruf <ruf@lpr.ch> *
10 *****************************************************************************/
11
12/*****************************************************************************
13 * This program is free software. You can redistribute it and / or modify it *
14 * under the terms of the GNU General Public License version 2 as published *
15 * by the Free Software Foundation. *
16 * *
17 * This program is distributed in the hope that it will be useful, but *
18 * WITHOUT ANY WARRANTY, without even the implied warranty of *
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General *
20 * Public License for more details. *
21 *****************************************************************************/
22
23/*****************************************************************************
24 * This software was developed at the Computer Engineering and Networks *
25 * Laboratory (TIK), Swiss Federal Institute of Technology (ETH) Zurich. *
26 *****************************************************************************/
27
28
29#include "main.h"
30
31#include <stdio.h>
32#include <stdlib.h>
33#include <stdarg.h>
34#include <signal.h>
35
36#include "cmd_arm.h"
37#include "simarm.h"
38
39#include <lib/cfg.h>
40#include <lib/cmd.h>
41#include <lib/console.h>
42#include <lib/getopt.h>
43#include <lib/log.h>
44#include <lib/monitor.h>
45#include <lib/path.h>
46#include <lib/sysdep.h>
47
48#include <libini/libini.h>
49
50
51static pce_option_t opts[] = {
52 { '?', 0, "help", NULL, "Print usage information" },
53 { 'c', 1, "config", "string", "Set the config file name [none]" },
54 { 'd', 1, "path", "string", "Add a directory to the search path" },
55 { 'i', 1, "ini-prefix", "string", "Add an ini string before the config file" },
56 { 'I', 1, "ini-append", "string", "Add an ini string after the config file" },
57 { 'l', 1, "log", "string", "Set the log file name [none]" },
58 { 'q', 0, "quiet", NULL, "Set the log level to error [no]" },
59 { 'r', 0, "run", NULL, "Start running immediately [no]" },
60 { 'v', 0, "verbose", NULL, "Set the log level to debug [no]" },
61 { 'V', 0, "version", NULL, "Print version information" },
62 { -1, 0, NULL, NULL, NULL }
63};
64
65
66unsigned par_xlat = ARM_XLAT_CPU;
67
68simarm_t *par_sim = NULL;
69
70unsigned par_sig_int = 0;
71
72ini_sct_t *par_cfg = NULL;
73
74static ini_strings_t par_ini_str;
75
76
77static
78void print_help (void)
79{
80 pce_getopt_help (
81 "pce-simarm: ARM emulator",
82 "usage: pce-simarm [options]",
83 opts
84 );
85
86 fflush (stdout);
87}
88
89static
90void print_version (void)
91{
92 fputs (
93 "pce-simarm version " PCE_VERSION_STR
94 "\n\n"
95 "Copyright (C) 1995-" PCE_YEAR " Hampa Hug <hampa@hampa.ch>\n",
96 stdout
97 );
98
99 fflush (stdout);
100}
101
102static
103void sim_log_banner (void)
104{
105 pce_log_inf (
106 "pce-simarm version " PCE_VERSION_STR "\n"
107 "Copyright (C) 2004-" PCE_YEAR " Hampa Hug <hampa@hampa.ch>\n"
108 );
109}
110
111static
112void sig_int (int s)
113{
114 fprintf (stderr, "\npce-simarm: sigint\n");
115 fflush (stderr);
116
117 par_sim->brk = PCE_BRK_STOP;
118}
119
120static
121void sig_term (int s)
122{
123 fprintf (stderr, "\npce-simarm: sigterm\n");
124 fflush (stderr);
125
126 if (par_sim->brk == PCE_BRK_ABORT) {
127 pce_set_fd_interactive (0, 1);
128 exit (1);
129 }
130
131 par_sim->brk = PCE_BRK_ABORT;
132}
133
134static
135void sig_segv (int s)
136{
137 fprintf (stderr, "pce-simarm: segmentation fault\n");
138
139 if ((par_sim != NULL) && (par_sim->cpu != NULL)) {
140 sarm_prt_state_cpu (par_sim->cpu, stderr);
141 }
142
143 fflush (stderr);
144
145 pce_set_fd_interactive (0, 1);
146
147 exit (1);
148}
149
150static
151int cmd_get_sym (simarm_t *sim, const char *sym, unsigned long *val)
152{
153 if (arm_get_reg (sim->cpu, sym, val) == 0) {
154 return (0);
155 }
156
157 return (1);
158}
159
160static
161int cmd_set_sym (simarm_t *sim, const char *sym, unsigned long val)
162{
163 if (arm_set_reg (sim->cpu, sym, val) == 0) {
164 return (0);
165 }
166
167 return (1);
168}
169
170static
171unsigned char sim_get_mem8 (simarm_t *sim, unsigned long addr)
172{
173 unsigned char val;
174
175 if (arm_get_mem8 (sim->cpu, addr, par_xlat, &val)) {
176 val = 0xff;
177 }
178
179 return (val);
180}
181
182static
183void sim_set_mem8 (simarm_t *sim, unsigned long addr, unsigned char val)
184{
185 if (arm_set_mem8 (sim->cpu, addr, par_xlat, val)) {
186 ; /* TLB miss */
187 }
188}
189
190int main (int argc, char *argv[])
191{
192 int r;
193 char **optarg;
194 int run;
195 char *cfg;
196 ini_sct_t *sct;
197 monitor_t mon;
198
199 cfg = NULL;
200 run = 0;
201
202 pce_log_init();
203 pce_log_add_fp (stderr, 0, MSG_INF);
204
205 par_cfg = ini_sct_new (NULL);
206
207 if (par_cfg == NULL) {
208 return (1);
209 }
210
211 ini_str_init (&par_ini_str);
212
213 while (1) {
214 r = pce_getopt (argc, argv, &optarg, opts);
215
216 if (r == GETOPT_DONE) {
217 break;
218 }
219
220 if (r < 0) {
221 return (1);
222 }
223
224 switch (r) {
225 case '?':
226 print_help();
227 return (0);
228
229 case 'V':
230 print_version();
231 return (0);
232
233 case 'c':
234 cfg = optarg[0];
235 break;
236
237 case 'd':
238 pce_path_set (optarg[0]);
239 break;
240
241 case 'i':
242 if (ini_read_str (par_cfg, optarg[0])) {
243 fprintf (stderr,
244 "%s: error parsing ini string (%s)\n",
245 argv[0], optarg[0]
246 );
247 return (1);
248 }
249 break;
250
251 case 'I':
252 ini_str_add (&par_ini_str, optarg[0], "\n", NULL);
253 break;
254
255 case 'l':
256 pce_log_add_fname (optarg[0], MSG_DEB);
257 break;
258
259 case 'q':
260 pce_log_set_level (stderr, MSG_ERR);
261 break;
262
263 case 'r':
264 run = 1;
265 break;
266
267 case 'v':
268 pce_log_set_level (stderr, MSG_DEB);
269 break;
270
271 case 0:
272 fprintf (stderr, "%s: unknown option (%s)\n",
273 argv[0], optarg[0]
274 );
275 return (1);
276
277 default:
278 return (1);
279 }
280 }
281
282 sim_log_banner();
283
284 if (pce_load_config (par_cfg, cfg)) {
285 return (1);
286 }
287
288 sct = ini_next_sct (par_cfg, NULL, "simarm");
289
290 if (sct == NULL) {
291 sct = par_cfg;
292 }
293
294 if (ini_str_eval (&par_ini_str, sct, 1)) {
295 return (1);
296 }
297
298 pce_path_ini (sct);
299
300 par_sim = sarm_new (sct);
301
302 signal (SIGINT, sig_int);
303 signal (SIGTERM, sig_term);
304 signal (SIGSEGV, sig_segv);
305
306#ifdef SIGPIPE
307 signal (SIGPIPE, SIG_IGN);
308#endif
309
310 pce_console_init (stdin, stdout);
311
312 mon_init (&mon);
313 mon_set_cmd_fct (&mon, sarm_do_cmd, par_sim);
314 mon_set_msg_fct (&mon, sarm_set_msg, par_sim);
315 mon_set_get_mem_fct (&mon, par_sim, sim_get_mem8);
316 mon_set_set_mem_fct (&mon, par_sim, sim_set_mem8);
317 mon_set_memory_mode (&mon, 0);
318
319 cmd_init (par_sim, cmd_get_sym, cmd_set_sym);
320 sarm_cmd_init (par_sim, &mon);
321
322 sarm_reset (par_sim);
323
324 if (run) {
325 sarm_run (par_sim);
326 if (par_sim->brk != PCE_BRK_ABORT) {
327 fputs ("\n", stdout);
328 }
329 }
330 else {
331 pce_puts ("type 'h' for help\n");
332 }
333
334 mon_run (&mon);
335
336 sarm_del (par_sim);
337
338 mon_free (&mon);
339 pce_console_done();
340 pce_log_done();
341
342 return (0);
343}