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

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


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

  ViewVC Help
Powered by ViewVC 1.1.26