/[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 28 - (hide annotations)
Mon Oct 8 16:20:26 2007 UTC (16 years, 7 months ago) by dpavlin
File MIME type: text/plain
File size: 22537 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1298 2006/07/22 11:27:46 debug Exp $
20060626	Continuing on SPARC emulation (beginning on the 'save'
		instruction, register windows, etc).
20060629	Planning statistics gathering (new -s command line option),
		and renaming speed_tricks to allow_instruction_combinations.
20060630	Some minor manual page updates.
		Various cleanups.
		Implementing the -s command line option.
20060701	FINALLY found the bug which prevented Linux and Ultrix from
		running without the ugly hack in the R2000/R3000 cache isol
		code; it was the phystranslation hint array which was buggy.
		Removing the phystranslation hint code completely, for now.
20060702	Minor dyntrans cleanups; invalidation of physpages now only
		invalidate those parts of a page that have actually been
		translated. (32 parts per page.)
		Some MIPS non-R3000 speed fixes.
		Experimenting with MIPS instruction combination for some
		addiu+bne+sw loops, and sw+sw+sw.
		Adding support (again) for larger-than-4KB pages in MIPS tlbw*.
		Continuing on SPARC emulation: adding load/store instructions.
20060704	Fixing a virtual vs physical page shift bug in the new tlbw*
		implementation. Problem noticed by Jakub Jermar. (Many thanks.)
		Moving rfe and eret to cpu_mips_instr.c, since that is the
		only place that uses them nowadays.
20060705	Removing the BSD license from the "testmachine" include files,
		placing them in the public domain instead; this enables the
		testmachine stuff to be used from projects which are
		incompatible with the BSD license for some reason.
20060707	Adding instruction combinations for the R2000/R3000 L1
		I-cache invalidation code used by NetBSD/pmax 3.0, lui+addiu,
		various branches followed by addiu or nop, and jr ra followed
		by addiu. The time it takes to perform a full NetBSD/pmax R3000
		install on the laptop has dropped from 573 seconds to 539. :-)
20060708	Adding a framebuffer controller device (dev_fbctrl), which so
		far can be used to change the fb resolution during runtime, but
		in the future will also be useful for accelerated block fill/
		copy, and possibly also simplified character output.
		Adding an instruction combination for NetBSD/pmax' strlen.
20060709	Minor fixes: reading raw files in src/file.c wasn't memblock
		aligned, removing buggy multi_sw MIPS instruction combination,
		etc.
20060711	Adding a machine_qemu.c, which contains a "qemu_mips" machine.
		(It mimics QEMU's MIPS machine mode, so that a test kernel
		made for QEMU_MIPS also can run in GXemul... at least to some
		extent.)  Adding a short section about how to run this mode to
		doc/guestoses.html.
20060714	Misc. minor code cleanups.
20060715	Applying a patch which adds getchar() to promemul/yamon.c
		(from Oleksandr Tymoshenko).
		Adding yamon.h from NetBSD, and rewriting yamon.c to use it
		(instead of ugly hardcoded numbers) + some cleanup.
20060716	Found and fixed the bug which broke single-stepping of 64-bit
		programs between 0.4.0 and 0.4.0.1 (caused by too quick
		refactoring and no testing). Hopefully this fix will not
		break too many other things.
20060718	Continuing on the 8253 PIT; it now works with Linux/QEMU_MIPS.
		Re-adding the sw+sw+sw instr comb (the problem was that I had
		ignored endian issues); however, it doesn't seem to give any
		big performance gain.
20060720	Adding a dummy Transputer mode (T414, T800 etc) skeleton (only
		the 'j' and 'ldc' instructions are implemented so far). :-}
20060721	Adding gtreg.h from NetBSD, updating dev_gt.c to use it, plus
		misc. other updates to get Linux 2.6 for evbmips/malta working
		(thanks to Alec Voropay for the details).
		FINALLY found and fixed the bug which made tlbw* for non-R3000
		buggy; it was a reference count problem in the dyntrans core.
20060722	Testing stuff; things seem stable enough for a new release.

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

  ViewVC Help
Powered by ViewVC 1.1.26