/[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 6 - (show annotations)
Mon Oct 8 16:18:11 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 21480 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.772 2005/06/04 12:02:16 debug Exp $
20050428	Disabling the "-fmove-all-movables" option in the configure
		script, because it causes the compile to fail on OpenBSD/sgi.
20050502	Minor updates.
20050503	Removing the WRT54G mode (it was bogus anyway), and adding a
		comment about Windows NT for MIPS in doc/experiments.html.
		Minor updates to the x86 instruction decoding.
20050504	Adding some more x86 instructions.
		Adding support for reading files from ISO9660 CDROMs (including
		gzipped files). It's an ugly hack, but it seems to work.
		Various other minor updates (dev_vga.c, pc_bios.c etc).
20050505	Some more x86-related updates.
		Beginning (what I hope will be) a major code cleanup phase.
		"bootris" (an x86 bootsector) runs :-)
20050506	Adding some more x86 instructions.
20050507	tmpnam => mkstemp.
		Working on a hack to allow VGA charcells to be shown even when
		not running with X11.
		Adding more x86 instructions.
20050508	x86 32-bit SIB addressing fix, and more instructions.
20050509	Adding more x86 instructions.
20050510	Minor documentation updates, and other updates (x86 stuff etc.)
20050511	More x86-related updates.
20050513	Various updates, mostly x86-related. (Trying to fix flag 
		calculation, factoring out the ugly shift/rotate code, and
		some other things.)
20050514	Adding support for loading some old i386 a.out executables.
		Finally beginning the cleanup of machine/PROM/bios dependant
		info.
		Some minor documentation updates.
		Trying to clean up ARCBIOS stuff a little.
20050515	Trying to make it possible to actually use more than one disk
		type per machine (floppy, ide, scsi).
		Trying to clean up the kbd vs PROM console stuff. (For PC and
		ARC emulation modes, mostly.)
		Beginning to add an 8259 interrupt controller, and connecting
		it to the x86 emulation.
20050516	The first x86 interrupts seem to work (keyboard stuff).
		Adding a 8253/8254 programmable interval timer skeleton.
		FreeDOS now reaches a command prompt and can be interacted
		with.
20050517	After some bugfixes, MS-DOS also (sometimes) reaches a
		command prompt now.
		Trying to fix the pckbc to work with MS-DOS' keyb.com, but no
		success yet.
20050518	Adding a simple 32-bit x86 MMU skeleton.
20050519	Some more work on the x86 stuff. (Beginning the work on paging,
		and various other fixes).
20050520	More updates. Working on dev_vga (4-bit graphics modes), adding
		40 columns support to the PC bios emulation.
		Trying to add support for resizing windows when switching
		between graphics modes.
20050521	Many more x86-related updates.
20050522	Correcting the initial stack pointer's sign-extension for
		ARCBIOS emulation (thanks to Alec Voropay for noticing the
		error).
		Continuing on the cleanup (ARCBIOS etc).
		dev_vga updates.
20050523	More x86 updates: trying to add some support for protected mode
		interrupts (via gate descriptors) and many other fixes.
		More ARCBIOS cleanup.
		Adding a device flag which indicates that reads cause no
		side-effects. (Useful for the "dump" command in the debugger,
		and other things.)
		Adding support for directly starting up x86 ELFs, skipping the
		bootloader stage. (Most ELFs, however, are not suitable for
		this.)
20050524	Adding simple 32-bit x86 TSS task switching, but no privilege
		level support yet.
		More work on dev_vga. A small "Copper bars" demo works. :-)
		Adding support for Trap Flag (single-step exceptions), at least
		in real mode, and various other x86-related fixes.
20050525	Adding a new disk image prefix (gH;S;) which can be used to
		override the default nr of heads and sectors per track.
20050527	Various bug fixes, more work on the x86 mode (stack change on
		interrupts between different priv.levels), and some minor
		documentation updates.
20050528	Various fixes (x86 stuff).
20050529	More x86 fixes. An OpenBSD/i386 bootfloppy reaches userland
		and can be interacted with (although there are problems with
		key repetition). NetBSD/i386 triggers a serious CISC-related
		problem: instruction fetches across page boundaries, where
		the later part isn't actually part of the instruction.
20050530	Various minor updates. (Documentation updates, etc.)
20050531	Adding some experimental code (experiments/new_test_*) which
		could be useful for dynamic (but not binary) translation in
		the future.
20050602	Adding a dummy ARM skeleton.
		Fixing the pckbc key repetition problem (by adding release
		scancodes for all keypresses).
20050603	Minor updates for the next release.
20050604	Release testing. Minor updates.

==============  RELEASE 0.3.3  ==============

20050604	There'll probably be a 0.3.3.1 release soon, with some very
		very tiny updates.


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

  ViewVC Help
Powered by ViewVC 1.1.26