/[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

Annotation of /trunk/src/main.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 26 - (hide 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 dpavlin 2 /*
2 dpavlin 22 * Copyright (C) 2003-2006 Anders Gavare. All rights reserved.
3 dpavlin 2 *
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 dpavlin 26 * $Id: main.c,v 1.275 2006/06/24 19:52:28 debug Exp $
29 dpavlin 2 */
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 dpavlin 26 #include "debugger.h"
41 dpavlin 2 #include "device.h"
42     #include "diskimage.h"
43     #include "emul.h"
44     #include "machine.h"
45     #include "misc.h"
46 dpavlin 24 #include "settings.h"
47 dpavlin 2
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 dpavlin 24 struct settings *global_settings;
56    
57 dpavlin 2 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 dpavlin 22 printf(" Copyright (C) 2003-2006 Anders Gavare\n");
201 dpavlin 2 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 dpavlin 14 printf(" or %s [general options] @configfile\n", progname);
207 dpavlin 24 #ifdef UNSTABLE_DEVEL
208 dpavlin 2 printf(" or %s [userland, other, and general options] file "
209     "[args ...]\n", progname);
210 dpavlin 24 #endif
211 dpavlin 2
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 dpavlin 12 printf(" -A disable alignment checks in some cases (for higher"
226     " speed)\n");
227 dpavlin 2 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 dpavlin 6 printf(" b specifies that this is the boot"
233 dpavlin 2 " device\n");
234 dpavlin 6 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 dpavlin 2 " file)\n");
242 dpavlin 6 printf(" s SCSI\n");
243     printf(" t tape\n");
244     printf(" 0-7 force a specific ID\n");
245 dpavlin 24 printf(" -G port listen to gdb remote connections on this port\n");
246 dpavlin 2 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 dpavlin 24 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 dpavlin 2 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 dpavlin 24 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 dpavlin 2 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 dpavlin 22 "(default is on when\n using configuration files or"
286     " when X11 is used, off otherwise)\n");
287 dpavlin 2 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 dpavlin 24 #ifdef UNSTABLE_DEVEL
296 dpavlin 2 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 dpavlin 24 #endif
300 dpavlin 2
301     printf("\nGeneral options:\n");
302 dpavlin 22 printf(" -c cmd add cmd as a command to run before starting "
303     "the simulation\n");
304 dpavlin 24 printf(" -D guarantee (almost) fully deterministic "
305     "behaviour\n");
306 dpavlin 2 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 dpavlin 4 "or \"address:skiplen:\" or \"address:skiplen:initialpc:\".\n"
324 dpavlin 2 "Examples:\n"
325 dpavlin 4 " 0xbfc00000:rom.bin for a raw ROM image\n"
326     " 0xbfc00000:0x100:rom.bin for an image with "
327 dpavlin 2 "0x100 bytes header\n"
328 dpavlin 4 " 0xbfc00000:0x100:0xbfc00884:rom.bin "
329 dpavlin 2 "start with pc=0xbfc00884\n");
330     }
331    
332    
333     /*
334     * get_cmd_args():
335     *
336     * Reads command line arguments.
337     */
338 dpavlin 4 int get_cmd_args(int argc, char *argv[], struct emul *emul,
339     char ***diskimagesp, int *n_diskimagesp)
340 dpavlin 2 {
341     int ch, res, using_switch_d = 0, using_switch_Z = 0;
342 dpavlin 24 int using_switch_e = 0, using_switch_E = 0;
343 dpavlin 2 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 dpavlin 24 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 dpavlin 2 switch (ch) {
362 dpavlin 12 case 'A':
363 dpavlin 24 fprintf(stderr, "NOTE: The -A command line option"
364     " is DEPRECATED and will be removed soon.\n");
365 dpavlin 12 m->dyntrans_alignment_check = 0;
366     msopts = 1;
367     break;
368 dpavlin 2 case 'C':
369     m->cpu_name = strdup(optarg);
370     msopts = 1;
371     break;
372 dpavlin 22 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 dpavlin 2 case 'D':
384     fully_deterministic = 1;
385     break;
386     case 'd':
387 dpavlin 4 /* 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 dpavlin 2 using_switch_d = 1;
397     msopts = 1;
398     break;
399     case 'E':
400 dpavlin 24 if (using_switch_E ++ > 0) {
401     fprintf(stderr, "-E already used.\n");
402     exit(1);
403     }
404 dpavlin 2 type = optarg;
405     msopts = 1;
406     break;
407     case 'e':
408 dpavlin 24 if (using_switch_e ++ > 0) {
409     fprintf(stderr, "-e already used.\n");
410     exit(1);
411     }
412 dpavlin 2 subtype = optarg;
413     msopts = 1;
414     break;
415 dpavlin 24 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 dpavlin 26 /* Note: implicit -V */
423     single_step = ENTER_SINGLE_STEPPING;
424 dpavlin 24 msopts = 1;
425     break;
426 dpavlin 2 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 dpavlin 26 single_step = ENTER_SINGLE_STEPPING;
533 dpavlin 2 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 dpavlin 22 /* FALL-THROUGH */
544 dpavlin 2 case 'x':
545     console_allow_slaves(1);
546     break;
547     case 'Y':
548     m->x11_scaledown = atoi(optarg);
549 dpavlin 20 if (m->x11_scaledown < -1) {
550     m->x11_scaleup = - m->x11_scaledown;
551     m->x11_scaledown = 1;
552     }
553 dpavlin 4 if (m->x11_scaledown < 1) {
554     fprintf(stderr, "Invalid scaledown value.\n");
555     exit(1);
556     }
557 dpavlin 2 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 dpavlin 10 fprintf(stderr, "Run %s -h for help on command "
584     "line options.\n", progname);
585 dpavlin 2 exit(1);
586     }
587     }
588    
589 dpavlin 12 if (type != NULL || subtype != NULL) {
590     if (type == NULL)
591     type = "";
592 dpavlin 2 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 dpavlin 12 /* -i and -r are pretty verbose: */
615 dpavlin 2
616     if (m->instruction_trace && !verbose) {
617 dpavlin 4 fprintf(stderr, "Implicitly %sturning on -v, because"
618     " of -i\n", quiet_mode? "turning off -q and " : "");
619 dpavlin 2 verbose = 1;
620     quiet_mode = 0;
621     }
622    
623     if (m->register_dump && !verbose) {
624 dpavlin 4 fprintf(stderr, "Implicitly %sturning on -v, because"
625     " of -r\n", quiet_mode? "turning off -q and " : "");
626 dpavlin 2 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 dpavlin 4 * file. If no kernel is supplied, but a diskimage is being used,
636     * then try to boot from disk.
637 dpavlin 2 */
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 dpavlin 4 char **diskimages = NULL;
697     int n_diskimages = 0;
698 dpavlin 2 int n_emuls;
699     int i;
700    
701     progname = argv[0];
702    
703 dpavlin 24 /* 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 dpavlin 2 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 dpavlin 4 get_cmd_args(argc, argv, emuls[0], &diskimages, &n_diskimages);
741 dpavlin 2
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 dpavlin 22 debug(" Copyright (C) 2003-2006 Anders Gavare\n");
759 dpavlin 2 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 dpavlin 4 else {
765     for (i=0; i<n_diskimages; i++)
766     diskimage_add(emuls[0]->machines[0], diskimages[i]);
767     }
768 dpavlin 2
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 dpavlin 22
806     emuls[n_emuls - 1] =
807     emul_create_from_configfile(s);
808 dpavlin 2 }
809     }
810    
811     if (n_emuls == 0) {
812 dpavlin 6 fprintf(stderr, "No emulations defined. Maybe you forgot to "
813 dpavlin 12 "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 dpavlin 6 "to boot an emulated DECstation 5000/200 with a disk "
816     "image.\n", progname);
817 dpavlin 2 exit(1);
818     }
819    
820     device_set_exit_on_error(0);
821 dpavlin 22 console_warn_if_slaves_are_needed(1);
822 dpavlin 2
823     /* Run all emulations: */
824     emul_run(emuls, n_emuls);
825    
826 dpavlin 24 settings_destroy(global_settings);
827    
828 dpavlin 2 return 0;
829     }
830    

  ViewVC Help
Powered by ViewVC 1.1.26