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

Contents of /trunk/src/main.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 28 - (show annotations)
Mon Oct 8 16:20:26 2007 UTC (16 years, 6 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 /*
2 * Copyright (C) 2003-2006 Anders Gavare. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 *
28 * $Id: main.c,v 1.277 2006/06/30 20:22:53 debug Exp $
29 */
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <stdarg.h>
34 #include <string.h>
35 #include <time.h>
36 #include <unistd.h>
37
38 #include "console.h"
39 #include "cpu.h"
40 #include "debugger.h"
41 #include "device.h"
42 #include "diskimage.h"
43 #include "emul.h"
44 #include "machine.h"
45 #include "misc.h"
46 #include "settings.h"
47
48
49 extern volatile int single_step;
50 extern int force_debugger_at_exit;
51
52 extern int optind;
53 extern char *optarg;
54
55 struct settings *global_settings;
56
57 int extra_argc;
58 char **extra_argv;
59 char *progname;
60
61 int fully_deterministic = 0;
62
63
64 /*****************************************************************************
65 *
66 * NOTE: debug(), fatal(), and debug_indentation() are not re-entrant.
67 * The global variable quiet_mode can be used to suppress the output
68 * of debug(), but not the output of fatal().
69 *
70 *****************************************************************************/
71
72 int verbose = 0;
73 int quiet_mode = 0;
74
75 static int debug_indent = 0;
76 static int debug_currently_at_start_of_line = 1;
77
78
79 /*
80 * va_debug():
81 *
82 * Used internally by debug() and fatal().
83 */
84 static void va_debug(va_list argp, char *fmt)
85 {
86 char buf[DEBUG_BUFSIZE + 1];
87 char *s;
88 int i;
89
90 buf[0] = buf[DEBUG_BUFSIZE] = 0;
91 vsnprintf(buf, DEBUG_BUFSIZE, fmt, argp);
92
93 s = buf;
94 while (*s) {
95 if (debug_currently_at_start_of_line) {
96 for (i=0; i<debug_indent; i++)
97 printf(" ");
98 }
99
100 printf("%c", *s);
101
102 debug_currently_at_start_of_line = 0;
103 if (*s == '\n' || *s == '\r')
104 debug_currently_at_start_of_line = 1;
105 s++;
106 }
107 }
108
109
110 /*
111 * debug_indentation():
112 *
113 * Modify the debug indentation.
114 */
115 void debug_indentation(int diff)
116 {
117 debug_indent += diff;
118 if (debug_indent < 0)
119 fprintf(stderr, "WARNING: debug_indent less than 0!\n");
120 }
121
122
123 /*
124 * debug():
125 *
126 * Debug output (ignored if quiet_mode is set).
127 */
128 void debug(char *fmt, ...)
129 {
130 va_list argp;
131
132 if (quiet_mode)
133 return;
134
135 va_start(argp, fmt);
136 va_debug(argp, fmt);
137 va_end(argp);
138 }
139
140
141 /*
142 * fatal():
143 *
144 * Fatal works like debug(), but doesn't care about the quiet_mode
145 * setting.
146 */
147 void fatal(char *fmt, ...)
148 {
149 va_list argp;
150
151 va_start(argp, fmt);
152 va_debug(argp, fmt);
153 va_end(argp);
154 }
155
156
157 /*****************************************************************************/
158
159
160 /*
161 * internal_w():
162 *
163 * For internal use by gxemul itself.
164 */
165 void internal_w(char *arg)
166 {
167 if (arg == NULL || strncmp(arg, "W@", 2) != 0) {
168 fprintf(stderr, "-W is for internal use by gxemul,"
169 " not for manual use.\n");
170 exit(1);
171 }
172
173 arg += 2;
174
175 switch (arg[0]) {
176 case 'S':
177 console_slave(arg + 1);
178 break;
179 default:
180 fprintf(stderr, "internal_w(): UNIMPLEMENTED arg = '%s'\n",
181 arg);
182 }
183 }
184
185
186 /*****************************************************************************/
187
188
189 /*
190 * usage():
191 *
192 * Prints program usage to stdout.
193 */
194 static void usage(int longusage)
195 {
196 printf("GXemul");
197 #ifdef VERSION
198 printf(" " VERSION);
199 #endif
200 printf(" Copyright (C) 2003-2006 Anders Gavare\n");
201 printf("Read the source code and/or documentation for "
202 "other Copyright messages.\n");
203
204 printf("\nusage: %s [machine, other, and general options] [file "
205 "[...]]\n", progname);
206 printf(" or %s [general options] @configfile\n", progname);
207 #ifdef UNSTABLE_DEVEL
208 printf(" or %s [userland, other, and general options] file "
209 "[args ...]\n", progname);
210 #endif
211
212 if (!longusage) {
213 printf("\nRun %s -h for help on command line options.\n",
214 progname);
215 return;
216 }
217
218 printf("\nMachine selection options:\n");
219 printf(" -E t try to emulate machine type t. (Use -H to get "
220 "a list of types.)\n");
221 printf(" -e st try to emulate machine subtype st. (Use this "
222 "with -E.)\n");
223
224 printf("\nOther options:\n");
225 printf(" -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 printf(" b specifies that this is the boot"
231 " device\n");
232 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 " file)\n");
240 printf(" s SCSI\n");
241 printf(" t tape\n");
242 printf(" 0-7 force a specific ID\n");
243 printf(" -G port listen to gdb remote connections on this port\n");
244 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 printf(" -J disable dyntrans instruction combinations\n");
250 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 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 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 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 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 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 "(default is on when\n using configuration files or"
294 " when X11 is used, off otherwise)\n");
295 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 #ifdef UNSTABLE_DEVEL
304 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 #endif
308
309 printf("\nGeneral options:\n");
310 printf(" -c cmd add cmd as a command to run before starting "
311 "the simulation\n");
312 printf(" -D guarantee (almost) fully deterministic "
313 "behaviour\n");
314 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 "or \"address:skiplen:\" or \"address:skiplen:initialpc:\".\n"
332 "Examples:\n"
333 " 0xbfc00000:rom.bin for a raw ROM image\n"
334 " 0xbfc00000:0x100:rom.bin for an image with "
335 "0x100 bytes header\n"
336 " 0xbfc00000:0x100:0xbfc00884:rom.bin "
337 "start with pc=0xbfc00884\n");
338 }
339
340
341 /*
342 * get_cmd_args():
343 *
344 * Reads command line arguments.
345 */
346 int get_cmd_args(int argc, char *argv[], struct emul *emul,
347 char ***diskimagesp, int *n_diskimagesp)
348 {
349 int ch, res, using_switch_d = 0, using_switch_Z = 0;
350 int using_switch_e = 0, using_switch_E = 0;
351 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 char *opts =
357 "C:c:Dd:E:e:G:HhI:iJj:KM:Nn:Oo:p:QqRrSs:tU"
358 #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 switch (ch) {
369 case 'C':
370 m->cpu_name = strdup(optarg);
371 msopts = 1;
372 break;
373 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 case 'D':
385 fully_deterministic = 1;
386 break;
387 case 'd':
388 /* 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 using_switch_d = 1;
398 msopts = 1;
399 break;
400 case 'E':
401 if (using_switch_E ++ > 0) {
402 fprintf(stderr, "-E already used.\n");
403 exit(1);
404 }
405 type = optarg;
406 msopts = 1;
407 break;
408 case 'e':
409 if (using_switch_e ++ > 0) {
410 fprintf(stderr, "-e already used.\n");
411 exit(1);
412 }
413 subtype = optarg;
414 msopts = 1;
415 break;
416 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 /* Note: implicit -V */
424 single_step = ENTER_SINGLE_STEPPING;
425 msopts = 1;
426 break;
427 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 m->allow_instruction_combinations = 0;
444 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 case 's':
516 machine_statistics_init(m, optarg);
517 msopts = 1;
518 break;
519 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 single_step = ENTER_SINGLE_STEPPING;
538 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 /* FALL-THROUGH */
549 case 'x':
550 console_allow_slaves(1);
551 break;
552 case 'Y':
553 m->x11_scaledown = atoi(optarg);
554 if (m->x11_scaledown < -1) {
555 m->x11_scaleup = - m->x11_scaledown;
556 m->x11_scaledown = 1;
557 }
558 if (m->x11_scaledown < 1) {
559 fprintf(stderr, "Invalid scaledown value.\n");
560 exit(1);
561 }
562 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 fprintf(stderr, "Run %s -h for help on command "
589 "line options.\n", progname);
590 exit(1);
591 }
592 }
593
594 if (type != NULL || subtype != NULL) {
595 if (type == NULL)
596 type = "";
597 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 /* -i and -r are pretty verbose: */
620
621 if (m->instruction_trace && !verbose) {
622 fprintf(stderr, "Implicitly %sturning on -v, because"
623 " of -i\n", quiet_mode? "turning off -q and " : "");
624 verbose = 1;
625 quiet_mode = 0;
626 }
627
628 if (m->register_dump && !verbose) {
629 fprintf(stderr, "Implicitly %sturning on -v, because"
630 " of -r\n", quiet_mode? "turning off -q and " : "");
631 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 * file. If no kernel is supplied, but a diskimage is being used,
641 * then try to boot from disk.
642 */
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 char **diskimages = NULL;
702 int n_diskimages = 0;
703 int n_emuls;
704 int i;
705
706 progname = argv[0];
707
708 /* 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 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 get_cmd_args(argc, argv, emuls[0], &diskimages, &n_diskimages);
746
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 debug(" " VERSION);
762 #endif
763 debug(" Copyright (C) 2003-2006 Anders Gavare\n");
764 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 else {
770 for (i=0; i<n_diskimages; i++)
771 diskimage_add(emuls[0]->machines[0], diskimages[i]);
772 }
773
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
811 emuls[n_emuls - 1] =
812 emul_create_from_configfile(s);
813 }
814 }
815
816 if (n_emuls == 0) {
817 fprintf(stderr, "No emulations defined. Maybe you forgot to "
818 "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 "to boot an emulated DECstation 5000/200 with a disk "
821 "image.\n", progname);
822 exit(1);
823 }
824
825 device_set_exit_on_error(0);
826 console_warn_if_slaves_are_needed(1);
827
828 /* Run all emulations: */
829 emul_run(emuls, n_emuls);
830
831 settings_destroy(global_settings);
832
833 return 0;
834 }
835

  ViewVC Help
Powered by ViewVC 1.1.26