/[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 44 - (show annotations)
Mon Oct 8 16:22:56 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 22372 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1632 2007/09/11 21:46:35 debug Exp $
20070616	Implementing the MIPS32/64 revision 2 "ror" instruction.
20070617	Adding a struct for each physpage which keeps track of which
		ranges within that page (base offset, length) that are
		continuously translatable. When running with native code
		generation enabled (-b), a range is added after each read-
		ahead loop.
		Experimenting with using the physical program counter sample
		data (implemented 20070608) together with the "translatable
		range" information, to figure out which physical address ranges
		would be worth translating to native code (if the number of
		samples falling within a range is above a certain threshold).
20070618	Adding automagic building of .index comment files for
		src/file/, src/promemul/, src src/useremul/ as well.
		Adding a "has been translated" bit to the ranges, so that only
		not-yet-translated ranges will be sampled.
20070619	Moving src/cpu.c and src/memory_rw.c into src/cpus/,
		src/device.c into src/devices/, and src/machine.c into
		src/machines/.
		Creating a skeleton cc/ld native backend module; beginning on
		the function which will detect cc command line, etc.
20070620	Continuing on the native code generation infrastructure.
20070621	Moving src/x11.c and src/console.c into a new src/console/
		subdir (for everything that is console or framebuffer related).
		Moving src/symbol*.c into a new src/symbol/, which should
		contain anything that is symbol handling related.
20070624	Making the program counter sampling threshold a "settings
		variable" (sampling_threshold), i.e. it can now be changed
		during runtime.
		Switching the RELEASE notes format from plain text to HTML.
		If the TMPDIR environment variable is set, it is used instead
		of "/tmp" for temporary files.
		Continuing on the cc/ld backend: simple .c code is generated,
		the compiler and linker are called, etc.
		Adding detection of host architecture to the configure script
		(again), and adding icache invalidation support (only
		implemented for Alpha hosts so far).
20070625	Simplifying the program counter sampling mechanism.
20070626	Removing the cc/ld native code generation stuff, program
		counter sampling, etc; it would not have worked well in the
		general case.
20070627	Removing everything related to native code generation.
20070629	Removing the (practically unusable) support for multiple
		emulations. (The single emulation allowed now still supports
		multiple simultaneous machines, as before.)
		Beginning on PCCTWO and M88K interrupts.
20070723	Adding a dummy skeleton for emulation of M32R processors.
20070901	Fixing a warning found by "gcc version 4.3.0 20070817
		(experimental)" on amd64.
20070905	Removing some more traces of the old "multiple emulations"
		code.
		Also looking in /usr/local/include and /usr/local/lib for
		X11 libs, when running configure.
20070909	Minor updates to the guest OS install instructions, in
		preparation for the NetBSD 4.0 release.
20070918	More testing of NetBSD 4.0 RC1.

1 /*
2 * Copyright (C) 2003-2007 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.311 2007/06/28 14:58:38 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 #include "timer.h"
48 #include "useremul.h"
49
50
51 extern int single_step;
52 extern int force_debugger_at_exit;
53
54 extern int optind;
55 extern char *optarg;
56
57 struct settings *global_settings;
58
59 int extra_argc;
60 char **extra_argv;
61 char *progname;
62
63 size_t dyntrans_cache_size = DEFAULT_DYNTRANS_CACHE_SIZE;
64 static int skip_srandom_call = 0;
65
66
67 /*****************************************************************************
68 *
69 * NOTE: debug(), fatal(), and debug_indentation() are not re-entrant.
70 * The global variable quiet_mode can be used to suppress the output
71 * of debug(), but not the output of fatal().
72 *
73 *****************************************************************************/
74
75 int verbose = 0;
76 int quiet_mode = 0;
77
78 static int debug_indent = 0;
79 static int debug_currently_at_start_of_line = 1;
80
81
82 /*
83 * va_debug():
84 *
85 * Used internally by debug() and fatal().
86 */
87 static void va_debug(va_list argp, char *fmt)
88 {
89 char buf[DEBUG_BUFSIZE + 1];
90 char *s;
91 int i;
92
93 buf[0] = buf[DEBUG_BUFSIZE] = 0;
94 vsnprintf(buf, DEBUG_BUFSIZE, fmt, argp);
95
96 s = buf;
97 while (*s) {
98 if (debug_currently_at_start_of_line) {
99 for (i=0; i<debug_indent; i++)
100 printf(" ");
101 }
102
103 printf("%c", *s);
104
105 debug_currently_at_start_of_line = 0;
106 if (*s == '\n' || *s == '\r')
107 debug_currently_at_start_of_line = 1;
108 s++;
109 }
110 }
111
112
113 /*
114 * debug_indentation():
115 *
116 * Modify the debug indentation.
117 */
118 void debug_indentation(int diff)
119 {
120 debug_indent += diff;
121 if (debug_indent < 0)
122 fprintf(stderr, "WARNING: debug_indent less than 0!\n");
123 }
124
125
126 /*
127 * debug():
128 *
129 * Debug output (ignored if quiet_mode is set).
130 */
131 void debug(char *fmt, ...)
132 {
133 va_list argp;
134
135 if (quiet_mode)
136 return;
137
138 va_start(argp, fmt);
139 va_debug(argp, fmt);
140 va_end(argp);
141 }
142
143
144 /*
145 * fatal():
146 *
147 * Fatal works like debug(), but doesn't care about the quiet_mode
148 * setting.
149 */
150 void fatal(char *fmt, ...)
151 {
152 va_list argp;
153
154 va_start(argp, fmt);
155 va_debug(argp, fmt);
156 va_end(argp);
157 }
158
159
160 /*****************************************************************************/
161
162
163 /*
164 * internal_w():
165 *
166 * For internal use by gxemul itself.
167 */
168 void internal_w(char *arg)
169 {
170 if (arg == NULL || strncmp(arg, "W@", 2) != 0) {
171 fprintf(stderr, "-W is for internal use by gxemul,"
172 " not for manual use.\n");
173 exit(1);
174 }
175
176 arg += 2;
177
178 switch (arg[0]) {
179 case 'S':
180 console_slave(arg + 1);
181 break;
182 default:
183 fprintf(stderr, "internal_w(): UNIMPLEMENTED arg = '%s'\n",
184 arg);
185 }
186 }
187
188
189 /*****************************************************************************/
190
191
192 /*
193 * usage():
194 *
195 * Prints program usage to stdout.
196 */
197 static void usage(int longusage)
198 {
199 printf("GXemul "VERSION" Copyright (C) 2003-2007 Anders Gavare\n");
200 printf("Read the source code and/or documentation for "
201 "other Copyright messages.\n");
202
203 printf("\nusage: %s [machine, other, and general options] [file "
204 "[...]]\n", progname);
205 printf(" or %s [general options] @configfile\n", progname);
206 printf(" or %s [userland, other, and general options] file "
207 "[args ...]\n", progname);
208
209 if (!longusage) {
210 printf("\nRun %s -h for help on command line options.\n",
211 progname);
212 return;
213 }
214
215 printf("\nMachine selection options:\n");
216 printf(" -E t try to emulate machine type t. (Use -H to get "
217 "a list of types.)\n");
218 printf(" -e st try to emulate machine subtype st. (Use this "
219 "with -E.)\n");
220
221 printf("\nOther options:\n");
222 printf(" -C x try to emulate a specific CPU. (Use -H to get a "
223 "list of types.)\n");
224 printf(" -d fname add fname as a disk image. You can add \"xxx:\""
225 " as a prefix\n");
226 printf(" where xxx is one or more of the following:\n");
227 printf(" b specifies that this is the boot"
228 " device\n");
229 printf(" c CD-ROM\n");
230 printf(" d DISK\n");
231 printf(" f FLOPPY\n");
232 printf(" gH;S; set geometry to H heads and S"
233 " sectors-per-track\n");
234 printf(" i IDE\n");
235 printf(" oOFS; set base offset to OFS (for ISO9660"
236 " filesystems)\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(" V add an overlay\n");
242 printf(" 0-7 force a specific ID\n");
243 printf(" -I hz set the main cpu frequency to hz (not used by "
244 "all combinations\n of machines and guest OSes)\n");
245 printf(" -i display each instruction as it is executed\n");
246 printf(" -J disable dyntrans instruction combinations\n");
247 printf(" -j name set the name of the kernel; for DECstation "
248 "emulation, this passes\n the name to the bootloader,"
249 " for example:\n");
250 printf(" -j netbsd (NetBSD/pmax) "
251 "-j bsd (OpenBSD/pmax)\n");
252 printf(" -j vmsprite (Sprite/pmax) "
253 "-j vmunix (Ultrix/RISC)\n");
254 printf(" For other emulation modes, if the boot disk is an"
255 " ISO9660\n filesystem, -j sets the name of the"
256 " kernel to load.\n");
257 printf(" -M m emulate m MBs of physical RAM\n");
258 printf(" -N display nr of instructions/second average, at"
259 " regular intervals\n");
260 printf(" -n nr set nr of CPUs (for SMP experiments)\n");
261 printf(" -O force netboot (tftp instead of disk), even when"
262 " a disk image is\n"
263 " present (for DECstation, SGI, and ARC emulation)\n");
264 printf(" -o arg set the boot argument, for DEC, ARC, or SGI"
265 " emulation\n");
266 printf(" (default arg for DEC is -a, for ARC/SGI -aN)\n");
267 printf(" -p pc add a breakpoint (remember to use the '0x' "
268 "prefix for hex!)\n");
269 printf(" -Q no built-in PROM emulation (use this for "
270 "running ROM images)\n");
271 printf(" -R use random bootstrap cpu, instead of nr 0\n");
272 printf(" -r register dumps before every instruction\n");
273 printf(" -S initialize emulated RAM to random bytes, "
274 "instead of zeroes\n");
275 printf(" -s f:name write statistics to file 'name', "
276 "f is one or more of the following:\n");
277 printf(" v virtual program counter\n");
278 printf(" p physical equivalent of program counter\n");
279 printf(" i internal ic->f representation of "
280 "the program counter\n");
281 printf(" and optionally:\n");
282 printf(" d disable statistics gathering at "
283 "startup\n");
284 printf(" o overwrite instead of append\n");
285 printf(" -T halt on non-existant memory accesses\n");
286 printf(" -t show function trace tree\n");
287 printf(" -U enable slow_serial_interrupts_hack_for_linux\n");
288 #ifdef WITH_X11
289 printf(" -X use X11\n");
290 printf(" -x open up new xterms for emulated serial ports "
291 "(default is on when\n using configuration files or"
292 " when X11 is used, off otherwise)\n");
293 printf(" -Y n scale down framebuffer windows by n x n times\n");
294 #endif /* WITH_X11 */
295 printf(" -Z n set nr of graphics cards, for emulating a "
296 "dual-head or tripple-head\n"
297 " environment (only for DECstation emulation)\n");
298 printf(" -z disp add disp as an X11 display to use for "
299 "framebuffers\n");
300
301 printf("\nUserland options:\n");
302 printf(" -u emul userland-only (syscall) emulation (use -H to"
303 " get a list of\n available emulation modes)\n");
304
305 printf("\nGeneral options:\n");
306 printf(" -c cmd add cmd as a command to run before starting "
307 "the simulation\n");
308 printf(" -D skip the srandom call at startup\n");
309 printf(" -H display a list of possible CPU and "
310 "machine types\n");
311 printf(" -h display this help message\n");
312 printf(" -k n set dyntrans translation caches to n MB (default"
313 " size is %i MB)\n", DEFAULT_DYNTRANS_CACHE_SIZE / 1048576);
314 printf(" -K force the debugger to be entered at the end "
315 "of a simulation\n");
316 printf(" -q quiet mode (don't print startup messages)\n");
317 printf(" -V start up in the single-step debugger, paused\n");
318 printf(" -v verbose debug messages\n");
319 printf("\n");
320 printf("If you are selecting a machine type to emulate directly "
321 "on the command line,\nthen you must specify one or more names"
322 " of files that you wish to load into\n"
323 "memory. Supported formats are: ELF a.out ecoff srec syms raw\n"
324 "where syms is the text produced by running 'nm' (or 'nm -S') "
325 "on a binary.\n"
326 "To load a raw binary into memory, add \"address:\" in front "
327 "of the filename,\n"
328 "or \"address:skiplen:\" or \"address:skiplen:initialpc:\".\n"
329 "\nExamples:\n"
330 " 0xbfc00000:rom.bin for a raw ROM image\n"
331 " 0xbfc00000:0x100:rom.bin for an image with "
332 "0x100 bytes header\n"
333 " 0xbfc00000:0x100:0xbfc00884:rom.bin "
334 "start with pc=0xbfc00884\n\n");
335 }
336
337
338 /*
339 * get_cmd_args():
340 *
341 * Reads command line arguments.
342 */
343 int get_cmd_args(int argc, char *argv[], struct emul *emul,
344 char ***diskimagesp, int *n_diskimagesp)
345 {
346 int ch, res, using_switch_d = 0, using_switch_Z = 0;
347 int using_switch_e = 0, using_switch_E = 0;
348 char *type = NULL, *subtype = NULL;
349 int n_cpus_set = 0;
350 int msopts = 0; /* Machine-specific options used */
351 struct machine *m = emul_add_machine(emul, NULL);
352
353 char *opts =
354 "C:c:Dd:E:e:HhI:iJj:k:KM:Nn:Oo:p:QqRrSs:TtUu:VvW:"
355 #ifdef WITH_X11
356 "XxY:"
357 #endif
358 "Z:z:";
359
360 while ((ch = getopt(argc, argv, opts)) != -1) {
361 switch (ch) {
362 case 'C':
363 CHECK_ALLOCATION(m->cpu_name = strdup(optarg));
364 msopts = 1;
365 break;
366 case 'c':
367 emul->n_debugger_cmds ++;
368 CHECK_ALLOCATION(emul->debugger_cmds =
369 realloc(emul->debugger_cmds,
370 emul->n_debugger_cmds * sizeof(char *)));
371 CHECK_ALLOCATION(emul->debugger_cmds[emul->
372 n_debugger_cmds-1] = strdup(optarg));
373 break;
374 case 'D':
375 skip_srandom_call = 1;
376 break;
377 case 'd':
378 /* diskimage_add() is called further down */
379 (*n_diskimagesp) ++;
380 CHECK_ALLOCATION( (*diskimagesp) =
381 realloc(*diskimagesp,
382 sizeof(char *) * (*n_diskimagesp)) );
383 CHECK_ALLOCATION( (*diskimagesp)[(*n_diskimagesp) - 1] =
384 strdup(optarg) );
385 using_switch_d = 1;
386 msopts = 1;
387 break;
388 case 'E':
389 if (using_switch_E ++ > 0) {
390 fprintf(stderr, "-E already used.\n");
391 exit(1);
392 }
393 type = optarg;
394 msopts = 1;
395 break;
396 case 'e':
397 if (using_switch_e ++ > 0) {
398 fprintf(stderr, "-e already used.\n");
399 exit(1);
400 }
401 subtype = optarg;
402 msopts = 1;
403 break;
404 case 'H':
405 machine_list_available_types_and_cpus();
406 exit(1);
407 case 'h':
408 usage(1);
409 exit(1);
410 case 'I':
411 m->emulated_hz = atoi(optarg);
412 msopts = 1;
413 break;
414 case 'i':
415 m->instruction_trace = 1;
416 msopts = 1;
417 break;
418 case 'J':
419 m->allow_instruction_combinations = 0;
420 msopts = 1;
421 break;
422 case 'j':
423 CHECK_ALLOCATION(m->boot_kernel_filename =
424 strdup(optarg));
425 msopts = 1;
426 break;
427 case 'k':
428 dyntrans_cache_size = atoi(optarg) * 1048576;
429 if (dyntrans_cache_size < 1) {
430 fprintf(stderr, "The dyntrans cache size must"
431 " be at least 1 MB.\n");
432 exit(1);
433 }
434 break;
435 case 'K':
436 force_debugger_at_exit = 1;
437 break;
438 case 'M':
439 m->physical_ram_in_mb = atoi(optarg);
440 msopts = 1;
441 break;
442 case 'N':
443 m->show_nr_of_instructions = 1;
444 msopts = 1;
445 break;
446 case 'n':
447 m->ncpus = atoi(optarg);
448 n_cpus_set = 1;
449 msopts = 1;
450 break;
451 case 'O':
452 m->force_netboot = 1;
453 msopts = 1;
454 break;
455 case 'o':
456 CHECK_ALLOCATION(m->boot_string_argument =
457 strdup(optarg));
458 msopts = 1;
459 break;
460 case 'p':
461 machine_add_breakpoint_string(m, optarg);
462 msopts = 1;
463 break;
464 case 'Q':
465 m->prom_emulation = 0;
466 msopts = 1;
467 break;
468 case 'q':
469 quiet_mode = 1;
470 break;
471 case 'R':
472 m->use_random_bootstrap_cpu = 1;
473 msopts = 1;
474 break;
475 case 'r':
476 m->register_dump = 1;
477 msopts = 1;
478 break;
479 case 'S':
480 m->random_mem_contents = 1;
481 msopts = 1;
482 break;
483 case 's':
484 machine_statistics_init(m, optarg);
485 msopts = 1;
486 break;
487 case 'T':
488 m->halt_on_nonexistant_memaccess = 1;
489 msopts = 1;
490 break;
491 case 't':
492 m->show_trace_tree = 1;
493 msopts = 1;
494 break;
495 case 'U':
496 m->slow_serial_interrupts_hack_for_linux = 1;
497 msopts = 1;
498 break;
499 case 'u':
500 CHECK_ALLOCATION(m->userland_emul = strdup(optarg));
501 m->machine_type = MACHINE_USERLAND;
502 msopts = 1;
503 break;
504 case 'V':
505 single_step = ENTER_SINGLE_STEPPING;
506 break;
507 case 'v':
508 verbose ++;
509 break;
510 case 'W':
511 internal_w(optarg);
512 exit(0);
513 case 'X':
514 m->x11_md.in_use = 1;
515 msopts = 1;
516 /* FALL-THROUGH */
517 case 'x':
518 console_allow_slaves(1);
519 break;
520 case 'Y':
521 m->x11_md.scaledown = atoi(optarg);
522 if (m->x11_md.scaledown < -1) {
523 m->x11_md.scaleup = - m->x11_md.scaledown;
524 m->x11_md.scaledown = 1;
525 }
526 if (m->x11_md.scaledown < 1) {
527 fprintf(stderr, "Invalid scaledown value.\n");
528 exit(1);
529 }
530 msopts = 1;
531 break;
532 case 'Z':
533 m->n_gfx_cards = atoi(optarg);
534 using_switch_Z = 1;
535 msopts = 1;
536 break;
537 case 'z':
538 m->x11_md.n_display_names ++;
539 CHECK_ALLOCATION(m->x11_md.display_names = realloc(
540 m->x11_md.display_names,
541 m->x11_md.n_display_names * sizeof(char *)));
542 CHECK_ALLOCATION(m->x11_md.display_names[
543 m->x11_md.n_display_names-1] = strdup(optarg));
544 msopts = 1;
545 break;
546 default:
547 fprintf(stderr, "Run %s -h for help on command "
548 "line options.\n", progname);
549 exit(1);
550 }
551 }
552
553 if (type != NULL || subtype != NULL) {
554 if (type == NULL)
555 type = "";
556 if (subtype == NULL)
557 subtype = "";
558 res = machine_name_to_type(type, subtype,
559 &m->machine_type, &m->machine_subtype, &m->arch);
560 if (!res)
561 exit(1);
562 }
563
564 argc -= optind;
565 argv += optind;
566
567 extra_argc = argc;
568 extra_argv = argv;
569
570
571 if (m->machine_type == MACHINE_NONE && msopts) {
572 fprintf(stderr, "Machine specific options used directly on "
573 "the command line, but no machine\nemulation specified?\n");
574 exit(1);
575 }
576
577
578 /* -i and -r are pretty verbose: */
579
580 if (m->instruction_trace && !verbose) {
581 fprintf(stderr, "Implicitly %sturning on -v, because"
582 " of -i\n", quiet_mode? "turning off -q and " : "");
583 verbose = 1;
584 quiet_mode = 0;
585 }
586
587 if (m->register_dump && !verbose) {
588 fprintf(stderr, "Implicitly %sturning on -v, because"
589 " of -r\n", quiet_mode? "turning off -q and " : "");
590 verbose = 1;
591 quiet_mode = 0;
592 }
593
594
595 /*
596 * Usually, an executable filename must be supplied.
597 *
598 * However, it is possible to boot directly from a harddisk image
599 * file. If no kernel is supplied, but a diskimage is being used,
600 * then try to boot from disk.
601 */
602 if (extra_argc == 0) {
603 if (using_switch_d) {
604 /* Booting directly from a disk image... */
605 } else {
606 usage(0);
607 fprintf(stderr, "\nNo filename given. Aborting.\n");
608 exit(1);
609 }
610 } else if (m->boot_kernel_filename[0] == '\0') {
611 /*
612 * Default boot_kernel_filename is "", which can be overriden
613 * by the -j command line option. If it is still "" here,
614 * and we're not booting directly from a disk image, then
615 * try to set it to the last part of the last file name
616 * given on the command line. (Last part = the stuff after
617 * the last slash.)
618 */
619 char *s = extra_argv[extra_argc - 1];
620 char *s2;
621
622 s2 = strrchr(s, '/');
623 if (s2 == NULL)
624 s2 = s;
625 else
626 s2 ++;
627
628 CHECK_ALLOCATION(m->boot_kernel_filename = strdup(s2));
629 }
630
631 if (m->n_gfx_cards < 0 || m->n_gfx_cards > 3) {
632 fprintf(stderr, "Bad number of gfx cards (-Z).\n");
633 exit(1);
634 }
635
636 if (!using_switch_Z && !m->x11_md.in_use)
637 m->n_gfx_cards = 0;
638
639 return 0;
640 }
641
642
643 /*
644 * main():
645 *
646 * Two kinds of emulations are started from here:
647 *
648 * o) Simple emulations, using command line arguments, compatible with
649 * earlier version of GXemul/mips64emul.
650 *
651 * o) Emulations set up by parsing special config files. (0 or more.)
652 */
653 int main(int argc, char *argv[])
654 {
655 /* Setting constants: */
656 const int constant_yes = 1;
657 const int constant_true = 1;
658 const int constant_no = 0;
659 const int constant_false = 0;
660
661 struct emul *emul;
662 int config_file = 0;
663
664 char **diskimages = NULL;
665 int n_diskimages = 0;
666 int i;
667
668
669 progname = argv[0];
670
671
672 /*
673 * Create the settings object, and add global settings to it:
674 *
675 * Read-only "constants": yes, no, true, false.
676 * Global emulator settings: verbose, single_step, ...
677 */
678 global_settings = settings_new();
679
680 settings_add(global_settings, "yes", 0, SETTINGS_TYPE_INT,
681 SETTINGS_FORMAT_YESNO, (void *)&constant_yes);
682 settings_add(global_settings, "no", 0, SETTINGS_TYPE_INT,
683 SETTINGS_FORMAT_YESNO, (void *)&constant_no);
684 settings_add(global_settings, "true", 0, SETTINGS_TYPE_INT,
685 SETTINGS_FORMAT_BOOL, (void *)&constant_true);
686 settings_add(global_settings, "false", 0, SETTINGS_TYPE_INT,
687 SETTINGS_FORMAT_BOOL, (void *)&constant_false);
688
689 /* Read-only settings: */
690 settings_add(global_settings, "single_step", 0,
691 SETTINGS_TYPE_INT, SETTINGS_FORMAT_YESNO, (void *)&single_step);
692
693 /* Read/write settings: */
694 settings_add(global_settings, "force_debugger_at_exit", 1,
695 SETTINGS_TYPE_INT, SETTINGS_FORMAT_YESNO,
696 (void *)&force_debugger_at_exit);
697 settings_add(global_settings, "verbose", 1,
698 SETTINGS_TYPE_INT, SETTINGS_FORMAT_YESNO, (void *)&verbose);
699 settings_add(global_settings, "quiet_mode", 1,
700 SETTINGS_TYPE_INT, SETTINGS_FORMAT_YESNO, (void *)&quiet_mode);
701
702 /* Initialize all emulator subsystems: */
703 console_init();
704 cpu_init();
705 device_init();
706 machine_init();
707 timer_init();
708 useremul_init();
709
710 /* Create a simple emulation setup: */
711 emul = emul_new(NULL);
712 settings_add(global_settings, "emul", 1,
713 SETTINGS_TYPE_SUBSETTINGS, 0, emul->settings);
714
715 get_cmd_args(argc, argv, emul, &diskimages, &n_diskimages);
716
717 if (!skip_srandom_call) {
718 struct timeval tv;
719 gettimeofday(&tv, NULL);
720 srandom(tv.tv_sec ^ getpid() ^ tv.tv_usec);
721 }
722
723 /* Print startup message: */
724 debug("GXemul "VERSION" Copyright (C) 2003-2007 Anders Gavare\n"
725 "Read the source code and/or documentation for other Copyright "
726 "messages.\n\n");
727
728 /* Simple initialization, from command line arguments: */
729 if (emul->machines[0]->machine_type != MACHINE_NONE) {
730 for (i=0; i<n_diskimages; i++)
731 diskimage_add(emul->machines[0], diskimages[i]);
732
733 /* Make sure that there are no configuration files as well: */
734 for (i=1; i<argc; i++)
735 if (argv[i][0] == '@') {
736 fprintf(stderr, "You can either start one "
737 "emulation with one machine directly from "
738 "the command\nline, or start one or more "
739 "emulations using configuration files."
740 " Not both.\n");
741 exit(1);
742 }
743
744 /* Initialize one emul: */
745 emul_simple_init(emul);
746 }
747
748 /* Initialize an emulation from a config file: */
749 for (i=1; i<argc; i++) {
750 if (argv[i][0] == '@') {
751 char *s = argv[i] + 1;
752
753 if (config_file) {
754 fprintf(stderr, "More than one configuration "
755 "file cannot be used.\n");
756 exit(1);
757 }
758
759 if (strlen(s) == 0 && i+1 < argc && *argv[i+1] != '@')
760 s = argv[++i];
761
762 /* Always allow slave xterms: */
763 console_allow_slaves(1);
764
765 /* Destroy the temporary emul, since it will
766 be overwritten: */
767 if (emul != NULL) {
768 emul_destroy(emul);
769 settings_remove(global_settings, "emul");
770 emul = NULL;
771 }
772
773 emul = emul_create_from_configfile(s);
774
775 settings_add(global_settings, "emul", 1,
776 SETTINGS_TYPE_SUBSETTINGS, 0, emul->settings);
777
778 config_file = 1;
779 }
780 }
781
782 if (emul->n_machines == 0) {
783 fprintf(stderr, "No emulations defined. Maybe you forgot to "
784 "use -E xx and/or -e yy, to specify\nthe machine type."
785 " For example:\n\n %s -e 3max -d disk.img\n\n"
786 "to boot an emulated DECstation 5000/200 with a disk "
787 "image.\n", progname);
788 exit(1);
789 }
790
791 device_set_exit_on_error(0);
792 console_warn_if_slaves_are_needed(1);
793
794
795 /* Run the emulation: */
796 emul_run(emul);
797
798
799 /*
800 * Deinitialize everything:
801 */
802
803 console_deinit();
804
805 emul_destroy(emul);
806
807 settings_remove_all(global_settings);
808 settings_destroy(global_settings);
809
810 return 0;
811 }
812

  ViewVC Help
Powered by ViewVC 1.1.26