/[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 10 - (hide annotations)
Mon Oct 8 16:18:27 2007 UTC (13 years ago) by dpavlin
File MIME type: text/plain
File size: 21325 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.815 2005/06/27 23:04:35 debug Exp $
20050617	Experimenting some more with netbooting OpenBSD/sgi. Adding
		a hack which allows emulated ethernet networks to be
		distributed across multiple emulator processes.
20050618	Minor updates (documentation, dummy YAMON emulation, etc).
20050620	strcpy/strcat -> strlcpy/strlcat updates.
		Some more progress on evbmips (Malta).
20050621	Adding a section to doc/configfiles.html about ethernet
		emulation across multiple hosts.
		Beginning the work on the ARM translation engine (using the
		dynamic-but-not-binary translation method).
		Fixing a bintrans bug: 0x9fc00000 should always be treated as
		PROM area, just as 0xbfc00000 is.
		Minor progress on Malta emulation (the PCI-ISA bus).
20050622	NetBSD/evbmips can now be installed (using another emulated
		machine) and run (including userland and so on). :-)
		Spliting up the bintrans haddr_entry field into two (one for
		read, one for write). Probably not much of a speed increase,
		though.
		Updating some NetBSD 2.0 -> 2.0.2 in the documentation.
20050623	Minor updates (documentation, the TODO file, etc).
		gzipped kernels are now always automagically gunzipped when
		loaded.
20050624	Adding a dummy Playstation Portable (PSP) mode, just barely
		enough to run Hello World (in weird colors :-).
		Removing the -b command line option; old bintrans is enabled
		by default instead. It makes more sense.
		Trying to finally fix the non-working performance measurement
		thing (instr/second etc).
20050625	Continuing on the essential basics for ARM emulation. Two
		instructions seem to work, a branch and a simple "mov". (The
		mov arguments are not correct yet.) Performance is definitely
		reasonable.
		Various other minor updates.
		Adding the ARM "bl" instruction.
		Adding support for combining multiple ARM instructions into one
		function call. ("mov" + "mov" is the only one implemented so
		far, but it seems to work.)
		Cleaning up some IP32 interrupt things (crime/mace); disabling
		the PS/2 keyboard controller on IP32, so that NetBSD/sgimips
		boots into userland again.
20050626	Finally! NetBSD/sgimips netboots. Adding instructions to
		doc/guestoses.html on how to set up an nfs server etc.
		Various other minor fixes.
		Playstation Portable ".pbp" files can now be used directly.
		(The ELF part of the .pbp is extracted transparently.)
		Converting some sprintf -> snprintf.
		Adding some more instructions to the ARM disassembler.
20050627	More ARM updates. Adding some simple ldr(b), str(b),
		cmps, and conditional branch instructions, enough to run
		a simple Hello World program.
		All ARM instructions are now inlined/generated for all possible
		condition codes.
		Adding add and sub, and more load/store instructions.
		Removing dummy files: cpu_alpha.c, cpu_hppa.c, and cpu_sparc.c.
		Some minor documentation updates; preparing for a 0.3.4
		release. Updating some URLs.

==============  RELEASE 0.3.4  ==============


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

  ViewVC Help
Powered by ViewVC 1.1.26