/[gxemul]/trunk/src/main.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /trunk/src/main.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 26 - (show annotations)
Mon Oct 8 16:20:10 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 22186 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1264 2006/06/25 11:08:04 debug Exp $
20060624	Replacing the error-prone machine type initialization stuff
		with something more reasonable.
		Finally removing the old "cpu_run" kludge; moving around stuff
		in machine.c and emul.c to better suit the dyntrans system.
		Various minor dyntrans cleanups (renaming translate_address to
		translate_v2p, and experimenting with template physpages).
20060625	Removing the speed hack which separated the vph entries into
		two halves (code vs data); things seem a lot more stable now.
		Minor performance hack: R2000/R3000 cache isolation now only
		clears address translations when going into isolation, not
		when going out of it.
		Fixing the MIPS interrupt problems by letting mtc0 immediately
		cause interrupts.

==============  RELEASE 0.4.0.1  ==============


1 /*
2 * Copyright (C) 2003-2006 Anders Gavare. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 *
28 * $Id: main.c,v 1.275 2006/06/24 19:52:28 debug Exp $
29 */
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <stdarg.h>
34 #include <string.h>
35 #include <time.h>
36 #include <unistd.h>
37
38 #include "console.h"
39 #include "cpu.h"
40 #include "debugger.h"
41 #include "device.h"
42 #include "diskimage.h"
43 #include "emul.h"
44 #include "machine.h"
45 #include "misc.h"
46 #include "settings.h"
47
48
49 extern volatile int single_step;
50 extern int force_debugger_at_exit;
51
52 extern int optind;
53 extern char *optarg;
54
55 struct settings *global_settings;
56
57 int extra_argc;
58 char **extra_argv;
59 char *progname;
60
61 int fully_deterministic = 0;
62
63
64 /*****************************************************************************
65 *
66 * NOTE: debug(), fatal(), and debug_indentation() are not re-entrant.
67 * The global variable quiet_mode can be used to suppress the output
68 * of debug(), but not the output of fatal().
69 *
70 *****************************************************************************/
71
72 int verbose = 0;
73 int quiet_mode = 0;
74
75 static int debug_indent = 0;
76 static int debug_currently_at_start_of_line = 1;
77
78
79 /*
80 * va_debug():
81 *
82 * Used internally by debug() and fatal().
83 */
84 static void va_debug(va_list argp, char *fmt)
85 {
86 char buf[DEBUG_BUFSIZE + 1];
87 char *s;
88 int i;
89
90 buf[0] = buf[DEBUG_BUFSIZE] = 0;
91 vsnprintf(buf, DEBUG_BUFSIZE, fmt, argp);
92
93 s = buf;
94 while (*s) {
95 if (debug_currently_at_start_of_line) {
96 for (i=0; i<debug_indent; i++)
97 printf(" ");
98 }
99
100 printf("%c", *s);
101
102 debug_currently_at_start_of_line = 0;
103 if (*s == '\n' || *s == '\r')
104 debug_currently_at_start_of_line = 1;
105 s++;
106 }
107 }
108
109
110 /*
111 * debug_indentation():
112 *
113 * Modify the debug indentation.
114 */
115 void debug_indentation(int diff)
116 {
117 debug_indent += diff;
118 if (debug_indent < 0)
119 fprintf(stderr, "WARNING: debug_indent less than 0!\n");
120 }
121
122
123 /*
124 * debug():
125 *
126 * Debug output (ignored if quiet_mode is set).
127 */
128 void debug(char *fmt, ...)
129 {
130 va_list argp;
131
132 if (quiet_mode)
133 return;
134
135 va_start(argp, fmt);
136 va_debug(argp, fmt);
137 va_end(argp);
138 }
139
140
141 /*
142 * fatal():
143 *
144 * Fatal works like debug(), but doesn't care about the quiet_mode
145 * setting.
146 */
147 void fatal(char *fmt, ...)
148 {
149 va_list argp;
150
151 va_start(argp, fmt);
152 va_debug(argp, fmt);
153 va_end(argp);
154 }
155
156
157 /*****************************************************************************/
158
159
160 /*
161 * internal_w():
162 *
163 * For internal use by gxemul itself.
164 */
165 void internal_w(char *arg)
166 {
167 if (arg == NULL || strncmp(arg, "W@", 2) != 0) {
168 fprintf(stderr, "-W is for internal use by gxemul,"
169 " not for manual use.\n");
170 exit(1);
171 }
172
173 arg += 2;
174
175 switch (arg[0]) {
176 case 'S':
177 console_slave(arg + 1);
178 break;
179 default:
180 fprintf(stderr, "internal_w(): UNIMPLEMENTED arg = '%s'\n",
181 arg);
182 }
183 }
184
185
186 /*****************************************************************************/
187
188
189 /*
190 * usage():
191 *
192 * Prints program usage to stdout.
193 */
194 static void usage(int longusage)
195 {
196 printf("GXemul");
197 #ifdef VERSION
198 printf("-" VERSION);
199 #endif
200 printf(" Copyright (C) 2003-2006 Anders Gavare\n");
201 printf("Read the source code and/or documentation for "
202 "other Copyright messages.\n");
203
204 printf("\nusage: %s [machine, other, and general options] [file "
205 "[...]]\n", progname);
206 printf(" or %s [general options] @configfile\n", progname);
207 #ifdef UNSTABLE_DEVEL
208 printf(" or %s [userland, other, and general options] file "
209 "[args ...]\n", progname);
210 #endif
211
212 if (!longusage) {
213 printf("\nRun %s -h for help on command line options.\n",
214 progname);
215 return;
216 }
217
218 printf("\nMachine selection options:\n");
219 printf(" -E t try to emulate machine type t. (Use -H to get "
220 "a list of types.)\n");
221 printf(" -e st try to emulate machine subtype st. (Use this "
222 "with -E.)\n");
223
224 printf("\nOther options:\n");
225 printf(" -A disable alignment checks in some cases (for higher"
226 " speed)\n");
227 printf(" -C x try to emulate a specific CPU. (Use -H to get a "
228 "list of types.)\n");
229 printf(" -d fname add fname as a disk image. You can add \"xxx:\""
230 " as a prefix\n");
231 printf(" where xxx is one or more of the following:\n");
232 printf(" b specifies that this is the boot"
233 " device\n");
234 printf(" c CD-ROM\n");
235 printf(" d DISK\n");
236 printf(" f FLOPPY\n");
237 printf(" gH;S; set geometry to H heads and S"
238 " sectors-per-track\n");
239 printf(" i IDE\n");
240 printf(" r read-only (don't allow changes to the"
241 " file)\n");
242 printf(" s SCSI\n");
243 printf(" t tape\n");
244 printf(" 0-7 force a specific ID\n");
245 printf(" -G port listen to gdb remote connections on this port\n");
246 printf(" -I x emulate clock interrupts at x Hz (affects"
247 " rtc devices only, not\n");
248 printf(" actual runtime speed) (this disables automatic"
249 " clock adjustments)\n");
250 printf(" -i display each instruction as it is executed\n");
251 printf(" -J disable some speed tricks\n");
252 printf(" -j name set the name of the kernel; for DECstation "
253 "emulation, this passes\n the name to the bootloader,"
254 " for example:\n");
255 printf(" -j netbsd (NetBSD/pmax) "
256 "-j bsd (OpenBSD/pmax)\n");
257 printf(" -j vmsprite (Sprite/pmax) "
258 "-j vmunix (Ultrix/RISC)\n");
259 printf(" For other emulation modes, if the boot disk is an"
260 " ISO9660\n filesystem, -j sets the name of the"
261 " kernel to load.\n");
262 printf(" -M m emulate m MBs of physical RAM\n");
263 printf(" -N display nr of instructions/second average, at"
264 " regular intervals\n");
265 printf(" -n nr set nr of CPUs (for SMP experiments)\n");
266 printf(" -O force netboot (tftp instead of disk), even when"
267 " a disk image is\n"
268 " present (for DECstation, SGI, and ARC emulation)\n");
269 printf(" -o arg set the boot argument, for DEC, ARC, or SGI"
270 " emulation\n");
271 printf(" (default arg for DEC is -a, for ARC/SGI -aN)\n");
272 printf(" -p pc add a breakpoint (remember to use the '0x' "
273 "prefix for hex!)\n");
274 printf(" -Q no built-in PROM emulation (use this for "
275 "running ROM images)\n");
276 printf(" -R use random bootstrap cpu, instead of nr 0\n");
277 printf(" -r register dumps before every instruction\n");
278 printf(" -S initialize emulated RAM to random bytes, "
279 "instead of zeroes\n");
280 printf(" -t show function trace tree\n");
281 printf(" -U enable slow_serial_interrupts_hack_for_linux\n");
282 #ifdef WITH_X11
283 printf(" -X use X11\n");
284 printf(" -x open up new xterms for emulated serial ports "
285 "(default is on when\n using configuration files or"
286 " when X11 is used, off otherwise)\n");
287 printf(" -Y n scale down framebuffer windows by n x n times\n");
288 #endif /* WITH_X11 */
289 printf(" -Z n set nr of graphics cards, for emulating a "
290 "dual-head or tripple-head\n"
291 " environment (only for DECstation emulation)\n");
292 printf(" -z disp add disp as an X11 display to use for "
293 "framebuffers\n");
294
295 #ifdef UNSTABLE_DEVEL
296 printf("\nUserland options:\n");
297 printf(" -u emul userland-only (syscall) emulation (use -H to"
298 " get a list of\n available emulation modes)\n");
299 #endif
300
301 printf("\nGeneral options:\n");
302 printf(" -c cmd add cmd as a command to run before starting "
303 "the simulation\n");
304 printf(" -D guarantee (almost) fully deterministic "
305 "behaviour\n");
306 printf(" -H display a list of possible CPU and "
307 "machine types\n");
308 printf(" -h display this help message\n");
309 printf(" -K force the debugger to be entered at the end "
310 "of a simulation\n");
311 printf(" -q quiet mode (don't print startup messages)\n");
312 printf(" -V start up in the single-step debugger, paused\n");
313 printf(" -v verbose debug messages\n");
314 printf("\n");
315 printf("If you are selecting a machine type to emulate directly "
316 "on the command line,\nthen you must specify one or more names"
317 " of files that you wish to load into\n"
318 "memory. Supported formats are: ELF a.out ecoff srec syms raw\n"
319 "where syms is the text produced by running 'nm' (or 'nm -S') "
320 "on a binary.\n"
321 "To load a raw binary into memory, add \"address:\" in front "
322 "of the filename,\n"
323 "or \"address:skiplen:\" or \"address:skiplen:initialpc:\".\n"
324 "Examples:\n"
325 " 0xbfc00000:rom.bin for a raw ROM image\n"
326 " 0xbfc00000:0x100:rom.bin for an image with "
327 "0x100 bytes header\n"
328 " 0xbfc00000:0x100:0xbfc00884:rom.bin "
329 "start with pc=0xbfc00884\n");
330 }
331
332
333 /*
334 * get_cmd_args():
335 *
336 * Reads command line arguments.
337 */
338 int get_cmd_args(int argc, char *argv[], struct emul *emul,
339 char ***diskimagesp, int *n_diskimagesp)
340 {
341 int ch, res, using_switch_d = 0, using_switch_Z = 0;
342 int using_switch_e = 0, using_switch_E = 0;
343 char *type = NULL, *subtype = NULL;
344 int n_cpus_set = 0;
345 int msopts = 0; /* Machine-specific options used */
346 struct machine *m = emul_add_machine(emul, "default");
347
348 char *opts =
349 "A"
350 "C:c:Dd:E:e:G:HhI:iJj:KM:Nn:Oo:p:QqRrStU"
351 #ifdef UNSTABLE_DEVEL
352 "u:"
353 #endif
354 "VvW:"
355 #ifdef WITH_X11
356 "XxY:"
357 #endif
358 "Z:z:";
359
360 while ((ch = getopt(argc, argv, opts)) != -1) {
361 switch (ch) {
362 case 'A':
363 fprintf(stderr, "NOTE: The -A command line option"
364 " is DEPRECATED and will be removed soon.\n");
365 m->dyntrans_alignment_check = 0;
366 msopts = 1;
367 break;
368 case 'C':
369 m->cpu_name = strdup(optarg);
370 msopts = 1;
371 break;
372 case 'c':
373 emul->n_debugger_cmds ++;
374 emul->debugger_cmds = realloc(emul->debugger_cmds,
375 emul->n_debugger_cmds * sizeof(char *));
376 if (emul->debugger_cmds == NULL) {
377 fatal("out of memory\n");
378 exit(1);
379 }
380 emul->debugger_cmds[emul->n_debugger_cmds-1] =
381 strdup(optarg);
382 break;
383 case 'D':
384 fully_deterministic = 1;
385 break;
386 case 'd':
387 /* diskimage_add() is called further down */
388 (*n_diskimagesp) ++;
389 (*diskimagesp) = realloc(*diskimagesp,
390 sizeof(char *) * (*n_diskimagesp));
391 if (*diskimagesp == NULL) {
392 fprintf(stderr, "out of memory\n");
393 exit(1);
394 }
395 (*diskimagesp)[(*n_diskimagesp) - 1] = strdup(optarg);
396 using_switch_d = 1;
397 msopts = 1;
398 break;
399 case 'E':
400 if (using_switch_E ++ > 0) {
401 fprintf(stderr, "-E already used.\n");
402 exit(1);
403 }
404 type = optarg;
405 msopts = 1;
406 break;
407 case 'e':
408 if (using_switch_e ++ > 0) {
409 fprintf(stderr, "-e already used.\n");
410 exit(1);
411 }
412 subtype = optarg;
413 msopts = 1;
414 break;
415 case 'G':
416 m->gdb.port = atoi(optarg);
417 if (m->gdb.port < 1 || m->gdb.port > 65535) {
418 fprintf(stderr, "Invalid debugger port %i.\n",
419 m->gdb.port);
420 exit(1);
421 }
422 /* Note: implicit -V */
423 single_step = ENTER_SINGLE_STEPPING;
424 msopts = 1;
425 break;
426 case 'H':
427 machine_list_available_types_and_cpus();
428 exit(1);
429 case 'h':
430 usage(1);
431 exit(1);
432 case 'I':
433 m->emulated_hz = atoi(optarg);
434 m->automatic_clock_adjustment = 0;
435 msopts = 1;
436 break;
437 case 'i':
438 m->instruction_trace = 1;
439 msopts = 1;
440 break;
441 case 'J':
442 m->speed_tricks = 0;
443 msopts = 1;
444 break;
445 case 'j':
446 m->boot_kernel_filename = strdup(optarg);
447 if (m->boot_kernel_filename == NULL) {
448 fprintf(stderr, "out of memory\n");
449 exit(1);
450 }
451 msopts = 1;
452 break;
453 case 'K':
454 force_debugger_at_exit = 1;
455 break;
456 case 'M':
457 m->physical_ram_in_mb = atoi(optarg);
458 msopts = 1;
459 break;
460 case 'N':
461 m->show_nr_of_instructions = 1;
462 msopts = 1;
463 break;
464 case 'n':
465 m->ncpus = atoi(optarg);
466 n_cpus_set = 1;
467 msopts = 1;
468 break;
469 case 'O':
470 m->force_netboot = 1;
471 msopts = 1;
472 break;
473 case 'o':
474 m->boot_string_argument = strdup(optarg);
475 if (m->boot_string_argument == NULL) {
476 fprintf(stderr, "out of memory\n");
477 exit(1);
478 }
479 msopts = 1;
480 break;
481 case 'p':
482 if (m->n_breakpoints >= MAX_BREAKPOINTS) {
483 fprintf(stderr, "too many breakpoints\n");
484 exit(1);
485 }
486 m->breakpoint_string[m->n_breakpoints] = strdup(optarg);
487 if (m->breakpoint_string[m->n_breakpoints] == NULL) {
488 fprintf(stderr, "out of memory\n");
489 exit(1);
490 }
491 m->breakpoint_flags[m->n_breakpoints] = 0;
492 m->n_breakpoints ++;
493 msopts = 1;
494 break;
495 case 'Q':
496 m->prom_emulation = 0;
497 msopts = 1;
498 break;
499 case 'q':
500 quiet_mode = 1;
501 break;
502 case 'R':
503 m->use_random_bootstrap_cpu = 1;
504 msopts = 1;
505 break;
506 case 'r':
507 m->register_dump = 1;
508 msopts = 1;
509 break;
510 case 'S':
511 m->random_mem_contents = 1;
512 msopts = 1;
513 break;
514 case 't':
515 m->show_trace_tree = 1;
516 msopts = 1;
517 break;
518 case 'U':
519 m->slow_serial_interrupts_hack_for_linux = 1;
520 msopts = 1;
521 break;
522 case 'u':
523 m->userland_emul = strdup(optarg);
524 if (m->userland_emul == NULL) {
525 fprintf(stderr, "out of memory\n");
526 exit(1);
527 }
528 m->machine_type = MACHINE_USERLAND;
529 msopts = 1;
530 break;
531 case 'V':
532 single_step = ENTER_SINGLE_STEPPING;
533 break;
534 case 'v':
535 verbose ++;
536 break;
537 case 'W':
538 internal_w(optarg);
539 exit(0);
540 case 'X':
541 m->use_x11 = 1;
542 msopts = 1;
543 /* FALL-THROUGH */
544 case 'x':
545 console_allow_slaves(1);
546 break;
547 case 'Y':
548 m->x11_scaledown = atoi(optarg);
549 if (m->x11_scaledown < -1) {
550 m->x11_scaleup = - m->x11_scaledown;
551 m->x11_scaledown = 1;
552 }
553 if (m->x11_scaledown < 1) {
554 fprintf(stderr, "Invalid scaledown value.\n");
555 exit(1);
556 }
557 msopts = 1;
558 break;
559 case 'Z':
560 m->n_gfx_cards = atoi(optarg);
561 using_switch_Z = 1;
562 msopts = 1;
563 break;
564 case 'z':
565 m->x11_n_display_names ++;
566 m->x11_display_names = realloc(
567 m->x11_display_names,
568 m->x11_n_display_names * sizeof(char *));
569 if (m->x11_display_names == NULL) {
570 fprintf(stderr, "out of memory\n");
571 exit(1);
572 }
573 m->x11_display_names[m->x11_n_display_names-1] =
574 strdup(optarg);
575 if (m->x11_display_names
576 [m->x11_n_display_names-1] == NULL) {
577 fprintf(stderr, "out of memory\n");
578 exit(1);
579 }
580 msopts = 1;
581 break;
582 default:
583 fprintf(stderr, "Run %s -h for help on command "
584 "line options.\n", progname);
585 exit(1);
586 }
587 }
588
589 if (type != NULL || subtype != NULL) {
590 if (type == NULL)
591 type = "";
592 if (subtype == NULL)
593 subtype = "";
594 res = machine_name_to_type(type, subtype,
595 &m->machine_type, &m->machine_subtype, &m->arch);
596 if (!res)
597 exit(1);
598 }
599
600 argc -= optind;
601 argv += optind;
602
603 extra_argc = argc;
604 extra_argv = argv;
605
606
607 if (m->machine_type == MACHINE_NONE && msopts) {
608 fprintf(stderr, "Machine specific options used directly on "
609 "the command line, but no machine\nemulation specified?\n");
610 exit(1);
611 }
612
613
614 /* -i and -r are pretty verbose: */
615
616 if (m->instruction_trace && !verbose) {
617 fprintf(stderr, "Implicitly %sturning on -v, because"
618 " of -i\n", quiet_mode? "turning off -q and " : "");
619 verbose = 1;
620 quiet_mode = 0;
621 }
622
623 if (m->register_dump && !verbose) {
624 fprintf(stderr, "Implicitly %sturning on -v, because"
625 " of -r\n", quiet_mode? "turning off -q and " : "");
626 verbose = 1;
627 quiet_mode = 0;
628 }
629
630
631 /*
632 * Usually, an executable filename must be supplied.
633 *
634 * However, it is possible to boot directly from a harddisk image
635 * file. If no kernel is supplied, but a diskimage is being used,
636 * then try to boot from disk.
637 */
638 if (extra_argc == 0) {
639 if (using_switch_d) {
640 /* Booting directly from a disk image... */
641 } else {
642 usage(0);
643 fprintf(stderr, "\nNo filename given. Aborting.\n");
644 exit(1);
645 }
646 } else if (m->boot_kernel_filename[0] == '\0') {
647 /*
648 * Default boot_kernel_filename is "", which can be overriden
649 * by the -j command line option. If it is still "" here,
650 * and we're not booting directly from a disk image, then
651 * try to set it to the last part of the last file name
652 * given on the command line. (Last part = the stuff after
653 * the last slash.)
654 */
655 char *s = extra_argv[extra_argc - 1];
656 char *s2;
657
658 s2 = strrchr(s, '/');
659 if (s2 == NULL)
660 s2 = s;
661 else
662 s2 ++;
663
664 m->boot_kernel_filename = strdup(s2);
665 if (m->boot_kernel_filename == NULL) {
666 fprintf(stderr, "out of memory\n");
667 exit(1);
668 }
669 }
670
671 if (m->n_gfx_cards < 0 || m->n_gfx_cards > 3) {
672 fprintf(stderr, "Bad number of gfx cards (-Z).\n");
673 exit(1);
674 }
675
676 if (!using_switch_Z && !m->use_x11)
677 m->n_gfx_cards = 0;
678
679 return 0;
680 }
681
682
683 /*
684 * main():
685 *
686 * Two kinds of emulations are started from here:
687 *
688 * o) Simple emulations, using command line arguments, compatible with
689 * earlier version of GXemul/mips64emul.
690 *
691 * o) Emulations set up by parsing special config files. (0 or more.)
692 */
693 int main(int argc, char *argv[])
694 {
695 struct emul **emuls;
696 char **diskimages = NULL;
697 int n_diskimages = 0;
698 int n_emuls;
699 int i;
700
701 progname = argv[0];
702
703 /* Create the settings object, and add global settings to it: */
704 global_settings = settings_new();
705
706 settings_add(global_settings, "single_step", 0,
707 SETTINGS_TYPE_INT, SETTINGS_FORMAT_YESNO, (void *)&single_step);
708 settings_add(global_settings, "force_debugger_at_exit", 1,
709 SETTINGS_TYPE_INT, SETTINGS_FORMAT_YESNO,
710 (void *)&force_debugger_at_exit);
711 settings_add(global_settings, "fully_deterministic", 0,
712 SETTINGS_TYPE_INT, SETTINGS_FORMAT_YESNO,
713 (void *)&fully_deterministic);
714 settings_add(global_settings, "verbose", 1,
715 SETTINGS_TYPE_INT, SETTINGS_FORMAT_YESNO, (void *)&verbose);
716 settings_add(global_settings, "quiet_mode", 1,
717 SETTINGS_TYPE_INT, SETTINGS_FORMAT_YESNO, (void *)&quiet_mode);
718
719 /* Initialize all emulator subsystems: */
720 console_init();
721 cpu_init();
722 device_init();
723 machine_init();
724 useremul_init();
725
726 emuls = malloc(sizeof(struct emul *));
727 if (emuls == NULL) {
728 fprintf(stderr, "out of memory\n");
729 exit(1);
730 }
731
732 /* Allocate space for a simple emul setup: */
733 n_emuls = 1;
734 emuls[0] = emul_new(NULL);
735 if (emuls[0] == NULL) {
736 fprintf(stderr, "out of memory\n");
737 exit(1);
738 }
739
740 get_cmd_args(argc, argv, emuls[0], &diskimages, &n_diskimages);
741
742 if (!fully_deterministic) {
743 /* TODO: More than just time(). Use gettimeofday(). */
744 srandom(time(NULL) ^ (getpid() << 12));
745 } else {
746 /* Fully deterministic. -I must have been supplied. */
747 if (emuls[0]->machines[0]->automatic_clock_adjustment) {
748 fatal("Cannot have -D without -I.\n");
749 exit(1);
750 }
751 }
752
753 /* Print startup message: */
754 debug("GXemul");
755 #ifdef VERSION
756 debug("-" VERSION);
757 #endif
758 debug(" Copyright (C) 2003-2006 Anders Gavare\n");
759 debug("Read the source code and/or documentation for "
760 "other Copyright messages.\n\n");
761
762 if (emuls[0]->machines[0]->machine_type == MACHINE_NONE)
763 n_emuls --;
764 else {
765 for (i=0; i<n_diskimages; i++)
766 diskimage_add(emuls[0]->machines[0], diskimages[i]);
767 }
768
769 /* Simple initialization, from command line arguments: */
770 if (n_emuls > 0) {
771 /* Make sure that there are no configuration files as well: */
772 for (i=1; i<argc; i++)
773 if (argv[i][0] == '@') {
774 fprintf(stderr, "You can either start one "
775 "emulation with one machine directly from "
776 "the command\nline, or start one or more "
777 "emulations using configuration files."
778 " Not both.\n");
779 exit(1);
780 }
781
782 /* Initialize one emul: */
783 emul_simple_init(emuls[0]);
784 }
785
786 /* Initialize emulations from config files: */
787 for (i=1; i<argc; i++) {
788 if (argv[i][0] == '@') {
789 char *s = argv[i] + 1;
790 if (strlen(s) == 0 && i+1 < argc &&
791 argv[i+1][0] != '@') {
792 i++;
793 s = argv[i];
794 }
795 n_emuls ++;
796 emuls = realloc(emuls, sizeof(struct emul *) * n_emuls);
797 if (emuls == NULL) {
798 fprintf(stderr, "out of memory\n");
799 exit(1);
800 }
801
802 /* Always allow slave xterms when using multiple
803 emulations: */
804 console_allow_slaves(1);
805
806 emuls[n_emuls - 1] =
807 emul_create_from_configfile(s);
808 }
809 }
810
811 if (n_emuls == 0) {
812 fprintf(stderr, "No emulations defined. Maybe you forgot to "
813 "use -E xx and/or -e yy, to specify\nthe machine type."
814 " For example:\n\n %s -e 3max -d disk.img\n\n"
815 "to boot an emulated DECstation 5000/200 with a disk "
816 "image.\n", progname);
817 exit(1);
818 }
819
820 device_set_exit_on_error(0);
821 console_warn_if_slaves_are_needed(1);
822
823 /* Run all emulations: */
824 emul_run(emuls, n_emuls);
825
826 settings_destroy(global_settings);
827
828 return 0;
829 }
830

  ViewVC Help
Powered by ViewVC 1.1.26