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

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.26