/[gxemul]/upstream/0.4.4.1/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 /upstream/0.4.4.1/src/main.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 37 - (show annotations)
Mon Oct 8 16:21:43 2007 UTC (16 years, 7 months ago) by dpavlin
File MIME type: text/plain
File size: 25389 byte(s)
0.4.4.1
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.293 2007/02/05 16:49:05 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
49
50 extern volatile int single_step;
51 extern int force_debugger_at_exit;
52
53 extern int optind;
54 extern char *optarg;
55
56 struct settings *global_settings;
57
58 int extra_argc;
59 char **extra_argv;
60 char *progname;
61
62 size_t dyntrans_cache_size = DEFAULT_DYNTRANS_CACHE_SIZE;
63 int native_code_translation_enabled = 0;
64 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");
200 #ifdef VERSION
201 printf(" " VERSION);
202 #endif
203 printf(" Copyright (C) 2003-2007 Anders Gavare\n");
204 printf("Read the source code and/or documentation for "
205 "other Copyright messages.\n");
206
207 printf("\nusage: %s [machine, other, and general options] [file "
208 "[...]]\n", progname);
209 printf(" or %s [general options] @configfile\n", progname);
210 #ifdef UNSTABLE_DEVEL
211 printf(" or %s [userland, other, and general options] file "
212 "[args ...]\n", progname);
213 #endif
214
215 if (!longusage) {
216 printf("\nRun %s -h for help on command line options.\n",
217 progname);
218 return;
219 }
220
221 printf("\nMachine selection options:\n");
222 printf(" -E t try to emulate machine type t. (Use -H to get "
223 "a list of types.)\n");
224 printf(" -e st try to emulate machine subtype st. (Use this "
225 "with -E.)\n");
226
227 printf("\nOther options:\n");
228 printf(" -C x try to emulate a specific CPU. (Use -H to get a "
229 "list of types.)\n");
230 printf(" -d fname add fname as a disk image. You can add \"xxx:\""
231 " as a prefix\n");
232 printf(" where xxx is one or more of the following:\n");
233 printf(" b specifies that this is the boot"
234 " device\n");
235 printf(" c CD-ROM\n");
236 printf(" d DISK\n");
237 printf(" f FLOPPY\n");
238 printf(" gH;S; set geometry to H heads and S"
239 " sectors-per-track\n");
240 printf(" i IDE\n");
241 printf(" oOFS; set base offset to OFS (for ISO9660"
242 " filesystems)\n");
243 printf(" r read-only (don't allow changes to the"
244 " file)\n");
245 printf(" s SCSI\n");
246 printf(" t tape\n");
247 printf(" 0-7 force a specific ID\n");
248 printf(" -G port listen to gdb remote connections on this port\n");
249 printf(" -I hz set the main cpu frequency to hz (not used by "
250 "all combinations\n of machines and guest OSes)\n");
251 printf(" -i display each instruction as it is executed\n");
252 printf(" -J disable dyntrans instruction combinations\n");
253 printf(" -j name set the name of the kernel; for DECstation "
254 "emulation, this passes\n the name to the bootloader,"
255 " for example:\n");
256 printf(" -j netbsd (NetBSD/pmax) "
257 "-j bsd (OpenBSD/pmax)\n");
258 printf(" -j vmsprite (Sprite/pmax) "
259 "-j vmunix (Ultrix/RISC)\n");
260 printf(" For other emulation modes, if the boot disk is an"
261 " ISO9660\n filesystem, -j sets the name of the"
262 " kernel to load.\n");
263 printf(" -M m emulate m MBs of physical RAM\n");
264 printf(" -N display nr of instructions/second average, at"
265 " regular intervals\n");
266 printf(" -n nr set nr of CPUs (for SMP experiments)\n");
267 printf(" -O force netboot (tftp instead of disk), even when"
268 " a disk image is\n"
269 " present (for DECstation, SGI, and ARC emulation)\n");
270 printf(" -o arg set the boot argument, for DEC, ARC, or SGI"
271 " emulation\n");
272 printf(" (default arg for DEC is -a, for ARC/SGI -aN)\n");
273 printf(" -p pc add a breakpoint (remember to use the '0x' "
274 "prefix for hex!)\n");
275 printf(" -Q no built-in PROM emulation (use this for "
276 "running ROM images)\n");
277 printf(" -R use random bootstrap cpu, instead of nr 0\n");
278 printf(" -r register dumps before every instruction\n");
279 printf(" -S initialize emulated RAM to random bytes, "
280 "instead of zeroes\n");
281 printf(" -s f:name write statistics to file 'name', "
282 "f is one or more of the following:\n");
283 printf(" v virtual program counter\n");
284 printf(" p physical equivalent of program counter\n");
285 printf(" i internal ic->f representation of "
286 "the program counter\n");
287 printf(" and optionally:\n");
288 printf(" d disable statistics gathering at "
289 "startup\n");
290 printf(" o overwrite instead of append\n");
291 printf(" -T halt on non-existant memory accesses\n");
292 printf(" -t show function trace tree\n");
293 printf(" -U enable slow_serial_interrupts_hack_for_linux\n");
294 #ifdef WITH_X11
295 printf(" -X use X11\n");
296 printf(" -x open up new xterms for emulated serial ports "
297 "(default is on when\n using configuration files or"
298 " when X11 is used, off otherwise)\n");
299 printf(" -Y n scale down framebuffer windows by n x n times\n");
300 #endif /* WITH_X11 */
301 printf(" -Z n set nr of graphics cards, for emulating a "
302 "dual-head or tripple-head\n"
303 " environment (only for DECstation emulation)\n");
304 printf(" -z disp add disp as an X11 display to use for "
305 "framebuffers\n");
306
307 #ifdef UNSTABLE_DEVEL
308 printf("\nUserland options:\n");
309 printf(" -u emul userland-only (syscall) emulation (use -H to"
310 " get a list of\n available emulation modes)\n");
311 #endif
312
313 printf("\nGeneral options:\n");
314 #ifdef UNSTABLE_DEVEL
315 printf(" -b enable native code generation\n");
316 printf(" -B disable native code generation\n");
317 #endif
318 printf(" -c cmd add cmd as a command to run before starting "
319 "the simulation\n");
320 printf(" -D skip the srandom call at startup\n");
321 printf(" -H display a list of possible CPU and "
322 "machine types\n");
323 printf(" -h display this help message\n");
324 printf(" -k n set dyntrans translation caches to n MB (default"
325 " size is %i MB)\n", DEFAULT_DYNTRANS_CACHE_SIZE / 1048576);
326 printf(" -K force the debugger to be entered at the end "
327 "of a simulation\n");
328 printf(" -q quiet mode (don't print startup messages)\n");
329 printf(" -V start up in the single-step debugger, paused\n");
330 printf(" -v verbose debug messages\n");
331 printf("\n");
332 printf("If you are selecting a machine type to emulate directly "
333 "on the command line,\nthen you must specify one or more names"
334 " of files that you wish to load into\n"
335 "memory. Supported formats are: ELF a.out ecoff srec syms raw\n"
336 "where syms is the text produced by running 'nm' (or 'nm -S') "
337 "on a binary.\n"
338 "To load a raw binary into memory, add \"address:\" in front "
339 "of the filename,\n"
340 "or \"address:skiplen:\" or \"address:skiplen:initialpc:\".\n"
341 "Examples:\n"
342 " 0xbfc00000:rom.bin for a raw ROM image\n"
343 " 0xbfc00000:0x100:rom.bin for an image with "
344 "0x100 bytes header\n"
345 " 0xbfc00000:0x100:0xbfc00884:rom.bin "
346 "start with pc=0xbfc00884\n");
347 }
348
349
350 /*
351 * get_cmd_args():
352 *
353 * Reads command line arguments.
354 */
355 int get_cmd_args(int argc, char *argv[], struct emul *emul,
356 char ***diskimagesp, int *n_diskimagesp)
357 {
358 int ch, res, using_switch_d = 0, using_switch_Z = 0;
359 int using_switch_e = 0, using_switch_E = 0;
360 char *type = NULL, *subtype = NULL;
361 int n_cpus_set = 0;
362 int msopts = 0; /* Machine-specific options used */
363 struct machine *m = emul_add_machine(emul, "default");
364
365 char *opts =
366 #ifdef UNSTABLE_DEVEL
367 "bB"
368 #endif
369 "C:c:Dd:E:e:G:HhI:iJj:k:KM:Nn:Oo:p:QqRrSs:TtU"
370 #ifdef UNSTABLE_DEVEL
371 "u:"
372 #endif
373 "VvW:"
374 #ifdef WITH_X11
375 "XxY:"
376 #endif
377 "Z:z:";
378
379 while ((ch = getopt(argc, argv, opts)) != -1) {
380 switch (ch) {
381 #ifdef UNSTABLE_DEVEL
382 case 'b':
383 #ifndef NATIVE_CODE_GENERATION
384 printf("-b is not available on this host arch.\n");
385 exit(1);
386 #else
387 native_code_translation_enabled = 1;
388 break;
389 #endif
390 case 'B':
391 native_code_translation_enabled = 0;
392 break;
393 #endif /* UNSTABLE_DEVEL */
394 case 'C':
395 m->cpu_name = strdup(optarg);
396 msopts = 1;
397 break;
398 case 'c':
399 emul->n_debugger_cmds ++;
400 emul->debugger_cmds = realloc(emul->debugger_cmds,
401 emul->n_debugger_cmds * sizeof(char *));
402 if (emul->debugger_cmds == NULL) {
403 fatal("out of memory\n");
404 exit(1);
405 }
406 emul->debugger_cmds[emul->n_debugger_cmds-1] =
407 strdup(optarg);
408 break;
409 case 'D':
410 skip_srandom_call = 1;
411 break;
412 case 'd':
413 /* diskimage_add() is called further down */
414 (*n_diskimagesp) ++;
415 (*diskimagesp) = realloc(*diskimagesp,
416 sizeof(char *) * (*n_diskimagesp));
417 if (*diskimagesp == NULL) {
418 fprintf(stderr, "out of memory\n");
419 exit(1);
420 }
421 (*diskimagesp)[(*n_diskimagesp) - 1] = strdup(optarg);
422 using_switch_d = 1;
423 msopts = 1;
424 break;
425 case 'E':
426 if (using_switch_E ++ > 0) {
427 fprintf(stderr, "-E already used.\n");
428 exit(1);
429 }
430 type = optarg;
431 msopts = 1;
432 break;
433 case 'e':
434 if (using_switch_e ++ > 0) {
435 fprintf(stderr, "-e already used.\n");
436 exit(1);
437 }
438 subtype = optarg;
439 msopts = 1;
440 break;
441 case 'G':
442 m->gdb.port = atoi(optarg);
443 if (m->gdb.port < 1 || m->gdb.port > 65535) {
444 fprintf(stderr, "Invalid debugger port %i.\n",
445 m->gdb.port);
446 exit(1);
447 }
448 /* Note: implicit -V */
449 single_step = ENTER_SINGLE_STEPPING;
450 msopts = 1;
451 break;
452 case 'H':
453 machine_list_available_types_and_cpus();
454 exit(1);
455 case 'h':
456 usage(1);
457 exit(1);
458 case 'I':
459 m->emulated_hz = atoi(optarg);
460 msopts = 1;
461 break;
462 case 'i':
463 m->instruction_trace = 1;
464 msopts = 1;
465 break;
466 case 'J':
467 m->allow_instruction_combinations = 0;
468 msopts = 1;
469 break;
470 case 'j':
471 m->boot_kernel_filename = strdup(optarg);
472 if (m->boot_kernel_filename == NULL) {
473 fprintf(stderr, "out of memory\n");
474 exit(1);
475 }
476 msopts = 1;
477 break;
478 case 'k':
479 dyntrans_cache_size = atoi(optarg) * 1048576;
480 if (dyntrans_cache_size < 1) {
481 fprintf(stderr, "The dyntrans cache size must"
482 " be at least 1 MB.\n");
483 exit(1);
484 }
485 break;
486 case 'K':
487 force_debugger_at_exit = 1;
488 break;
489 case 'M':
490 m->physical_ram_in_mb = atoi(optarg);
491 msopts = 1;
492 break;
493 case 'N':
494 m->show_nr_of_instructions = 1;
495 msopts = 1;
496 break;
497 case 'n':
498 m->ncpus = atoi(optarg);
499 n_cpus_set = 1;
500 msopts = 1;
501 break;
502 case 'O':
503 m->force_netboot = 1;
504 msopts = 1;
505 break;
506 case 'o':
507 m->boot_string_argument = strdup(optarg);
508 if (m->boot_string_argument == NULL) {
509 fprintf(stderr, "out of memory\n");
510 exit(1);
511 }
512 msopts = 1;
513 break;
514 case 'p':
515 if (m->n_breakpoints >= MAX_BREAKPOINTS) {
516 fprintf(stderr, "too many breakpoints\n");
517 exit(1);
518 }
519 m->breakpoint_string[m->n_breakpoints] = strdup(optarg);
520 if (m->breakpoint_string[m->n_breakpoints] == NULL) {
521 fprintf(stderr, "out of memory\n");
522 exit(1);
523 }
524 m->breakpoint_flags[m->n_breakpoints] = 0;
525 m->n_breakpoints ++;
526 msopts = 1;
527 break;
528 case 'Q':
529 m->prom_emulation = 0;
530 msopts = 1;
531 break;
532 case 'q':
533 quiet_mode = 1;
534 break;
535 case 'R':
536 m->use_random_bootstrap_cpu = 1;
537 msopts = 1;
538 break;
539 case 'r':
540 m->register_dump = 1;
541 msopts = 1;
542 break;
543 case 'S':
544 m->random_mem_contents = 1;
545 msopts = 1;
546 break;
547 case 's':
548 machine_statistics_init(m, optarg);
549 native_code_translation_enabled = 0;
550 msopts = 1;
551 break;
552 case 'T':
553 m->halt_on_nonexistant_memaccess = 1;
554 msopts = 1;
555 break;
556 case 't':
557 m->show_trace_tree = 1;
558 msopts = 1;
559 break;
560 case 'U':
561 m->slow_serial_interrupts_hack_for_linux = 1;
562 msopts = 1;
563 break;
564 case 'u':
565 m->userland_emul = strdup(optarg);
566 if (m->userland_emul == NULL) {
567 fprintf(stderr, "out of memory\n");
568 exit(1);
569 }
570 m->machine_type = MACHINE_USERLAND;
571 msopts = 1;
572 break;
573 case 'V':
574 single_step = ENTER_SINGLE_STEPPING;
575 break;
576 case 'v':
577 verbose ++;
578 break;
579 case 'W':
580 internal_w(optarg);
581 exit(0);
582 case 'X':
583 m->use_x11 = 1;
584 msopts = 1;
585 /* FALL-THROUGH */
586 case 'x':
587 console_allow_slaves(1);
588 break;
589 case 'Y':
590 m->x11_scaledown = atoi(optarg);
591 if (m->x11_scaledown < -1) {
592 m->x11_scaleup = - m->x11_scaledown;
593 m->x11_scaledown = 1;
594 }
595 if (m->x11_scaledown < 1) {
596 fprintf(stderr, "Invalid scaledown value.\n");
597 exit(1);
598 }
599 msopts = 1;
600 break;
601 case 'Z':
602 m->n_gfx_cards = atoi(optarg);
603 using_switch_Z = 1;
604 msopts = 1;
605 break;
606 case 'z':
607 m->x11_n_display_names ++;
608 m->x11_display_names = realloc(
609 m->x11_display_names,
610 m->x11_n_display_names * sizeof(char *));
611 if (m->x11_display_names == NULL) {
612 fprintf(stderr, "out of memory\n");
613 exit(1);
614 }
615 m->x11_display_names[m->x11_n_display_names-1] =
616 strdup(optarg);
617 if (m->x11_display_names
618 [m->x11_n_display_names-1] == NULL) {
619 fprintf(stderr, "out of memory\n");
620 exit(1);
621 }
622 msopts = 1;
623 break;
624 default:
625 fprintf(stderr, "Run %s -h for help on command "
626 "line options.\n", progname);
627 exit(1);
628 }
629 }
630
631 if (type != NULL || subtype != NULL) {
632 if (type == NULL)
633 type = "";
634 if (subtype == NULL)
635 subtype = "";
636 res = machine_name_to_type(type, subtype,
637 &m->machine_type, &m->machine_subtype, &m->arch);
638 if (!res)
639 exit(1);
640 }
641
642 argc -= optind;
643 argv += optind;
644
645 extra_argc = argc;
646 extra_argv = argv;
647
648
649 if (m->machine_type == MACHINE_NONE && msopts) {
650 fprintf(stderr, "Machine specific options used directly on "
651 "the command line, but no machine\nemulation specified?\n");
652 exit(1);
653 }
654
655
656 /* -i and -r are pretty verbose: */
657
658 if (m->instruction_trace && !verbose) {
659 fprintf(stderr, "Implicitly %sturning on -v, because"
660 " of -i\n", quiet_mode? "turning off -q and " : "");
661 verbose = 1;
662 quiet_mode = 0;
663 }
664
665 if (m->register_dump && !verbose) {
666 fprintf(stderr, "Implicitly %sturning on -v, because"
667 " of -r\n", quiet_mode? "turning off -q and " : "");
668 verbose = 1;
669 quiet_mode = 0;
670 }
671
672
673 /*
674 * Usually, an executable filename must be supplied.
675 *
676 * However, it is possible to boot directly from a harddisk image
677 * file. If no kernel is supplied, but a diskimage is being used,
678 * then try to boot from disk.
679 */
680 if (extra_argc == 0) {
681 if (using_switch_d) {
682 /* Booting directly from a disk image... */
683 } else {
684 usage(0);
685 fprintf(stderr, "\nNo filename given. Aborting.\n");
686 exit(1);
687 }
688 } else if (m->boot_kernel_filename[0] == '\0') {
689 /*
690 * Default boot_kernel_filename is "", which can be overriden
691 * by the -j command line option. If it is still "" here,
692 * and we're not booting directly from a disk image, then
693 * try to set it to the last part of the last file name
694 * given on the command line. (Last part = the stuff after
695 * the last slash.)
696 */
697 char *s = extra_argv[extra_argc - 1];
698 char *s2;
699
700 s2 = strrchr(s, '/');
701 if (s2 == NULL)
702 s2 = s;
703 else
704 s2 ++;
705
706 m->boot_kernel_filename = strdup(s2);
707 if (m->boot_kernel_filename == NULL) {
708 fprintf(stderr, "out of memory\n");
709 exit(1);
710 }
711 }
712
713 if (m->n_gfx_cards < 0 || m->n_gfx_cards > 3) {
714 fprintf(stderr, "Bad number of gfx cards (-Z).\n");
715 exit(1);
716 }
717
718 if (!using_switch_Z && !m->use_x11)
719 m->n_gfx_cards = 0;
720
721 return 0;
722 }
723
724
725 /*
726 * main():
727 *
728 * Two kinds of emulations are started from here:
729 *
730 * o) Simple emulations, using command line arguments, compatible with
731 * earlier version of GXemul/mips64emul.
732 *
733 * o) Emulations set up by parsing special config files. (0 or more.)
734 */
735 int main(int argc, char *argv[])
736 {
737 /* Setting constants: */
738 const int constant_yes = 1;
739 const int constant_true = 1;
740 const int constant_no = 0;
741 const int constant_false = 0;
742
743 struct emul **emuls;
744 char **diskimages = NULL;
745 int n_diskimages = 0;
746 int n_emuls;
747 int i;
748
749
750 #ifdef USE_PROFIL
751 uint16_t samples[0x100000];
752 memset(samples, 0, sizeof(samples));
753 profil((char *)samples, sizeof(samples), (vm_offset_t) 0x400000, 8192);
754 #endif
755
756 #ifndef NATIVE_CODE_GENERATION
757 native_code_translation_enabled = 0;
758 #endif
759
760
761 progname = argv[0];
762
763
764 /*
765 * Create the settings object, and add global settings to it:
766 *
767 * Read-only "constants": yes, no, true, false.
768 * Global emulator settings: verbose, single_step, ...
769 */
770 global_settings = settings_new();
771
772 settings_add(global_settings, "yes", 0, SETTINGS_TYPE_INT,
773 SETTINGS_FORMAT_YESNO, (void *)&constant_yes);
774 settings_add(global_settings, "no", 0, SETTINGS_TYPE_INT,
775 SETTINGS_FORMAT_YESNO, (void *)&constant_no);
776 settings_add(global_settings, "true", 0, SETTINGS_TYPE_INT,
777 SETTINGS_FORMAT_BOOL, (void *)&constant_true);
778 settings_add(global_settings, "false", 0, SETTINGS_TYPE_INT,
779 SETTINGS_FORMAT_BOOL, (void *)&constant_false);
780
781 /* Read-only settings: */
782 settings_add(global_settings, "native_code_translation_enabled", 0,
783 SETTINGS_TYPE_INT, SETTINGS_FORMAT_YESNO,
784 (void *)&native_code_translation_enabled);
785 settings_add(global_settings, "single_step", 0,
786 SETTINGS_TYPE_INT, SETTINGS_FORMAT_YESNO, (void *)&single_step);
787
788 /* Read/write settings: */
789 settings_add(global_settings, "force_debugger_at_exit", 1,
790 SETTINGS_TYPE_INT, SETTINGS_FORMAT_YESNO,
791 (void *)&force_debugger_at_exit);
792 settings_add(global_settings, "verbose", 1,
793 SETTINGS_TYPE_INT, SETTINGS_FORMAT_YESNO, (void *)&verbose);
794 settings_add(global_settings, "quiet_mode", 1,
795 SETTINGS_TYPE_INT, SETTINGS_FORMAT_YESNO, (void *)&quiet_mode);
796
797 /* Initialize all emulator subsystems: */
798 console_init();
799 cpu_init();
800 device_init();
801 machine_init();
802 timer_init();
803 useremul_init();
804
805 emuls = malloc(sizeof(struct emul *));
806 if (emuls == NULL) {
807 fprintf(stderr, "out of memory\n");
808 exit(1);
809 }
810
811 /* Allocate space for a simple emul setup: */
812 n_emuls = 1;
813 emuls[0] = emul_new(NULL, 0);
814 if (emuls[0] == NULL) {
815 fprintf(stderr, "out of memory\n");
816 exit(1);
817 }
818 settings_add(global_settings, "emul[0]", 1,
819 SETTINGS_TYPE_SUBSETTINGS, 0, emuls[0]->settings);
820
821 get_cmd_args(argc, argv, emuls[0], &diskimages, &n_diskimages);
822
823 if (!skip_srandom_call) {
824 struct timeval tv;
825 gettimeofday(&tv, NULL);
826 srandom(tv.tv_sec ^ getpid() ^ tv.tv_usec);
827 }
828
829 /* Print startup message: */
830 debug("GXemul");
831 #ifdef VERSION
832 debug(" " VERSION);
833 #endif
834 debug(" Copyright (C) 2003-2007 Anders Gavare\n");
835 debug("Read the source code and/or documentation for "
836 "other Copyright messages.\n\n");
837
838 if (emuls[0]->machines[0]->machine_type == MACHINE_NONE) {
839 n_emuls --;
840 } else {
841 for (i=0; i<n_diskimages; i++)
842 diskimage_add(emuls[0]->machines[0], diskimages[i]);
843 }
844
845 /* Simple initialization, from command line arguments: */
846 if (n_emuls > 0) {
847 /* Make sure that there are no configuration files as well: */
848 for (i=1; i<argc; i++)
849 if (argv[i][0] == '@') {
850 fprintf(stderr, "You can either start one "
851 "emulation with one machine directly from "
852 "the command\nline, or start one or more "
853 "emulations using configuration files."
854 " Not both.\n");
855 exit(1);
856 }
857
858 /* Initialize one emul: */
859 emul_simple_init(emuls[0]);
860 }
861
862 /* Initialize emulations from config files: */
863 for (i=1; i<argc; i++) {
864 if (argv[i][0] == '@') {
865 char tmpstr[50];
866 char *s = argv[i] + 1;
867 if (strlen(s) == 0 && i+1 < argc &&
868 argv[i+1][0] != '@') {
869 i++;
870 s = argv[i];
871 }
872 n_emuls ++;
873 emuls = realloc(emuls, sizeof(struct emul *) * n_emuls);
874 if (emuls == NULL) {
875 fprintf(stderr, "out of memory\n");
876 exit(1);
877 }
878
879 /* Always allow slave xterms when using multiple
880 emulations: */
881 console_allow_slaves(1);
882
883 /* Destroy the temporary emuls[0], since it will
884 be overwritten: */
885 if (n_emuls == 1) {
886 emul_destroy(emuls[0]);
887 settings_remove(global_settings, "emul[0]");
888 }
889
890 emuls[n_emuls - 1] =
891 emul_create_from_configfile(s, n_emuls - 1);
892
893 snprintf(tmpstr, sizeof(tmpstr), "emul[%i]", n_emuls-1);
894 settings_add(global_settings, tmpstr, 1,
895 SETTINGS_TYPE_SUBSETTINGS, 0,
896 emuls[n_emuls-1]->settings);
897 }
898 }
899
900 if (n_emuls == 0) {
901 fprintf(stderr, "No emulations defined. Maybe you forgot to "
902 "use -E xx and/or -e yy, to specify\nthe machine type."
903 " For example:\n\n %s -e 3max -d disk.img\n\n"
904 "to boot an emulated DECstation 5000/200 with a disk "
905 "image.\n", progname);
906 exit(1);
907 }
908
909 device_set_exit_on_error(0);
910 console_warn_if_slaves_are_needed(1);
911
912
913 /* Run all emulations: */
914 emul_run(emuls, n_emuls);
915
916
917 /*
918 * Deinitialize everything:
919 */
920
921 console_deinit();
922
923 for (i=0; i<n_emuls; i++)
924 emul_destroy(emuls[i]);
925
926 settings_remove_all(global_settings);
927 settings_destroy(global_settings);
928
929 #ifdef USE_PROFIL
930 {
931 int i;
932 FILE *f = fopen("output.txt", "w");
933 for (i=0; i<sizeof(samples) / sizeof(uint16_t); ++i) {
934 if (samples[i] != 0)
935 fprintf(f, "%i %p\n", samples[i],
936 (void *) (size_t) (0x400000 + i * 16));
937 }
938 }
939 #endif
940
941 return 0;
942 }
943

  ViewVC Help
Powered by ViewVC 1.1.26