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

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


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

  ViewVC Help
Powered by ViewVC 1.1.26