/[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 4 - (hide annotations)
Mon Oct 8 16:18:00 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 22347 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.707 2005/04/27 16:37:33 debug Exp $
20050408	Some minor updates to the wdc. Linux now doesn't complain
		anymore if a disk is non-present.
20050409	Various minor fixes (a bintrans bug, and some other things).
		The wdc seems to work with Playstation2 emulation, but there
		is a _long_ annoying delay when disks are detected.
		Fixing a really important bintrans bug (when devices and RAM
		are mixed within 4KB pages), which was triggered with
		NetBSD/playstation2 kernels.
20050410	Adding a dummy dev_ps2_ether (just so that NetBSD doesn't
		complain as much during bootup).
		Symbols starting with '$' are now ignored.
		Renaming dev_ps2_ohci.c to dev_ohci.c, etc.
20050411	Moving the bintrans-cache-isolation check from cpu_mips.c to
		cpu_mips_coproc.c. (I thought this would give a speedup, but
		it's not noticable.)
		Better playstation2 sbus interrupt code.
		Skip ahead many ticks if the count register is read manually.
		(This increases the speed of delay-loops that simply read
		the count register.)
20050412	Updates to the playstation2 timer/interrupt code.
		Some other minor updates.
20050413	NetBSD/cobalt runs from a disk image :-) including userland;
		updating the documentation on how to install NetBSD/cobalt
		using NetBSD/pmax (!).
		Some minor bintrans updates (no real speed improvement) and
		other minor updates (playstation2 now uses the -o options).
20050414	Adding a dummy x86 (and AMD64) mode.
20050415	Adding some (32-bit and 16-bit) x86 instructions.
		Adding some initial support for non-SCSI, non-IDE floppy
		images. (The x86 mode can boot from these, more or less.)
		Moving the devices/ and include/ directories to src/devices/
		and src/include/, respectively.
20050416	Continuing on the x86 stuff. (Adding pc_bios.c and some simple
		support for software interrupts in 16-bit mode.)
20050417	Ripping out most of the x86 instruction decoding stuff, trying
		to rewrite it in a cleaner way.
		Disabling some of the least working CPU families in the
		configure script (sparc, x86, alpha, hppa), so that they are
		not enabled by default.
20050418	Trying to fix the bug which caused problems when turning on
		and off bintrans interactively, by flushing the bintrans cache
		whenever bintrans is manually (re)enabled.
20050419	Adding the 'lswi' ppc instruction.
		Minor updates to the x86 instruction decoding.
20050420	Renaming x86 register name indices from R_xx to X86_R_xx (this
		makes building on Tru64 nicer).
20050422	Adding a check for duplicate MIPS TLB entries on tlbwr/tlbwi.
20050427	Adding screenshots to guestoses.html.
		Some minor fixes and testing for the next release.

==============  RELEASE 0.3.2  ==============


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

  ViewVC Help
Powered by ViewVC 1.1.26