fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
1/*****************************************************************************
2 * pce *
3 *****************************************************************************/
4
5/*****************************************************************************
6 * File name: src/arch/sim405/main.c *
7 * Created: 2004-06-01 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_ppc.h"
37#include "msg.h"
38#include "sim405.h"
39
40#include <lib/cfg.h>
41#include <lib/cmd.h>
42#include <lib/console.h>
43#include <lib/getopt.h>
44#include <lib/log.h>
45#include <lib/monitor.h>
46#include <lib/path.h>
47#include <lib/sysdep.h>
48
49#include <libini/libini.h>
50
51
52static pce_option_t opts[] = {
53 { '?', 0, "help", NULL, "Print usage information" },
54 { 'c', 1, "config", "string", "Set the config file name [none]" },
55 { 'd', 1, "path", "string", "Add a directory to the search path" },
56 { 'i', 1, "ini-prefix", "string", "Add an ini string before the config file" },
57 { 'I', 1, "ini-append", "string", "Add an ini string after the config file" },
58 { 'l', 1, "log", "string", "Set the log file name [none]" },
59 { 'p', 1, "cpu", "string", "Set the CPU model" },
60 { 'q', 0, "quiet", NULL, "Set the log level to error [no]" },
61 { 'r', 0, "run", NULL, "Start running immediately [no]" },
62 { 'v', 0, "verbose", NULL, "Set the log level to debug [no]" },
63 { 'V', 0, "version", NULL, "Print version information" },
64 { -1, 0, NULL, NULL, NULL }
65};
66
67
68char *par_cpu = NULL;
69
70unsigned par_xlat = P405_XLAT_CPU;
71
72sim405_t *par_sim = NULL;
73
74unsigned par_sig_int = 0;
75
76ini_sct_t *par_cfg = NULL;
77
78static ini_strings_t par_ini_str;
79
80
81static
82void print_help (void)
83{
84 pce_getopt_help (
85 "pce-sim405: PowerPC 405 emulator",
86 "usage: pce-sim405 [options]",
87 opts
88 );
89
90 fflush (stdout);
91}
92
93static
94void print_version (void)
95{
96 fputs (
97 "pce-sim405 version " PCE_VERSION_STR
98 "\n\n"
99 "Copyright (C) 2004-" PCE_YEAR " Hampa Hug <hampa@hampa.ch>\n",
100 stdout
101 );
102
103 fflush (stdout);
104}
105
106static
107void s405_log_banner (void)
108{
109 pce_log_inf (
110 "pce-sim405 version " PCE_VERSION_STR "\n"
111 "Copyright (C) 2004-" PCE_YEAR " Hampa Hug <hampa@hampa.ch>\n"
112 );
113}
114
115static
116void sig_int (int s)
117{
118 signal (SIGINT, sig_int);
119
120 par_sig_int = 1;
121}
122
123static
124void sig_terminate (int s)
125{
126 fprintf (stderr, "pce-sim405: signal %d\n", s);
127
128 if ((par_sim != NULL) && (par_sim->ppc != NULL)) {
129 fprintf (stderr, " PC=%08lX\n",
130 (unsigned long) p405_get_pc (par_sim->ppc)
131 );
132 }
133
134 fflush (stderr);
135
136 pce_set_fd_interactive (0, 1);
137
138 exit (1);
139}
140
141static
142int cmd_get_sym (sim405_t *sim, const char *sym, unsigned long *val)
143{
144 if (p405_get_reg (sim->ppc, sym, val) == 0) {
145 return (0);
146 }
147
148 return (1);
149}
150
151static
152int cmd_set_sym (sim405_t *sim, const char *sym, unsigned long val)
153{
154 if (p405_set_reg (sim->ppc, sym, val) == 0) {
155 return (0);
156 }
157
158 return (1);
159}
160
161static
162unsigned char s405_get_mem8 (sim405_t *sim, unsigned long addr)
163{
164 unsigned char val;
165
166 if (p405_get_xlat8 (sim->ppc, addr, par_xlat, &val)) {
167 val = 0xff;
168 }
169
170 return (val);
171}
172
173static
174void s405_set_mem8 (sim405_t *sim, unsigned long addr, unsigned char val)
175{
176 if (p405_set_xlat8 (sim->ppc, addr, par_xlat, val)) {
177 ; /* TLB miss */
178 }
179}
180
181int main (int argc, char *argv[])
182{
183 int r;
184 char **optarg;
185 int run;
186 char *cfg;
187 ini_sct_t *sct;
188 monitor_t mon;
189
190 cfg = NULL;
191 run = 0;
192
193 pce_log_init();
194 pce_log_add_fp (stderr, 0, MSG_INF);
195
196 par_cfg = ini_sct_new (NULL);
197
198 if (par_cfg == NULL) {
199 return (1);
200 }
201
202 ini_str_init (&par_ini_str);
203
204 while (1) {
205 r = pce_getopt (argc, argv, &optarg, opts);
206
207 if (r == GETOPT_DONE) {
208 break;
209 }
210
211 if (r < 0) {
212 return (1);
213 }
214
215 switch (r) {
216 case '?':
217 print_help();
218 return (0);
219
220 case 'V':
221 print_version();
222 return (0);
223
224 case 'c':
225 cfg = optarg[0];
226 break;
227
228 case 'd':
229 pce_path_set (optarg[0]);
230 break;
231
232 case 'i':
233 if (ini_read_str (par_cfg, optarg[0])) {
234 fprintf (stderr,
235 "%s: error parsing ini string (%s)\n",
236 argv[0], optarg[0]
237 );
238 return (1);
239 }
240 break;
241
242 case 'I':
243 ini_str_add (&par_ini_str, optarg[0], "\n", NULL);
244 break;
245
246 case 'l':
247 pce_log_add_fname (optarg[0], MSG_DEB);
248 break;
249
250 case 'p':
251 ini_str_add (&par_ini_str, "cpu.model = \"",
252 optarg[0], "\"\n"
253 );
254 break;
255
256 case 'q':
257 pce_log_set_level (stderr, MSG_ERR);
258 break;
259
260 case 'r':
261 run = 1;
262 break;
263
264 case 'v':
265 pce_log_set_level (stderr, MSG_DEB);
266 break;
267
268 case 0:
269 fprintf (stderr, "%s: unknown option (%s)\n",
270 argv[0], optarg[0]
271 );
272 return (1);
273
274 default:
275 return (1);
276 }
277 }
278
279 s405_log_banner();
280
281 if (pce_load_config (par_cfg, cfg)) {
282 return (1);
283 }
284
285 sct = ini_next_sct (par_cfg, NULL, "sim405");
286
287 if (sct == NULL) {
288 sct = par_cfg;
289 }
290
291 if (ini_str_eval (&par_ini_str, sct, 1)) {
292 return (1);
293 }
294
295 pce_path_ini (sct);
296
297 par_sim = s405_new (sct);
298
299 signal (SIGINT, sig_int);
300 signal (SIGTERM, sig_terminate);
301 signal (SIGSEGV, sig_terminate);
302
303#ifdef SIGPIPE
304 signal (SIGPIPE, SIG_IGN);
305#endif
306
307 pce_console_init (stdin, stdout);
308
309 mon_init (&mon);
310 mon_set_cmd_fct (&mon, ppc_do_cmd, par_sim);
311 mon_set_msg_fct (&mon, s405_set_msg, par_sim);
312 mon_set_get_mem_fct (&mon, par_sim, s405_get_mem8);
313 mon_set_set_mem_fct (&mon, par_sim, s405_set_mem8);
314 mon_set_memory_mode (&mon, 0);
315
316 cmd_init (par_sim, cmd_get_sym, cmd_set_sym);
317 ppc_cmd_init (par_sim, &mon);
318
319 s405_reset (par_sim);
320
321 if (run) {
322 ppc_run (par_sim);
323 if (par_sim->brk != PCE_BRK_ABORT) {
324 fputs ("\n", stdout);
325 }
326 }
327 else {
328 pce_puts ("type 'h' for help\n");
329 }
330
331 mon_run (&mon);
332
333 s405_del (par_sim);
334
335 mon_free (&mon);
336 pce_console_done();
337 pce_log_done();
338
339 return (0);
340}